@nordhealth/components 4.16.1 → 4.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/Input.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Input.js","sources":["../../icons/lib/assets/navigation-search.js","../src/common/controllers/ResizeController.ts","../src/input/Input.ts","../src/common/input.ts","../src/common/form.ts"],"sourcesContent":["export default '<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m16.03 14.61c1.23-1.54 1.97-3.49 1.97-5.61 0-4.97-4.03-9-9-9s-9 4.03-9 9 4.03 9 9 9c2.12 0 4.07-.74 5.61-1.97l3.97 3.97 1.41-1.41-3.97-3.97zm-7.03 1.39c-3.86 0-7-3.14-7-7s3.14-7 7-7 7 3.14 7 7-3.14 7-7 7z\" fill=\"currentColor\"/></svg>';\nexport const title = \"navigation-search\";\nexport const tags = \"nordicon navigation menu find search magnifying glass\";\n","import type { ReactiveController, ReactiveControllerHost } from 'lit'\nimport { isServer } from 'lit'\n\nexport class ResizeController implements ReactiveController {\n private observer?: ResizeObserver\n private hadFirstUpdate = false\n private borderBoxSize?: ResizeObserverSize\n\n constructor(\n host: ReactiveControllerHost,\n private target: () => HTMLElement,\n ) {\n host.addController(this)\n\n if (!isServer) {\n this.observer = new ResizeObserver(([entry]) => {\n const [borderBoxSize] = entry.borderBoxSize\n this.borderBoxSize = borderBoxSize\n host.requestUpdate()\n })\n }\n }\n\n get inlineSize() {\n return this.borderBoxSize?.inlineSize\n }\n\n get blockSize() {\n return this.borderBoxSize?.blockSize\n }\n\n hostUpdated() {\n if (!this.hadFirstUpdate && this.observer) {\n this.observer.observe(this.target())\n this.hadFirstUpdate = true\n }\n }\n\n hostConnected() {\n // in case the host has rendered, disconnected, and is now reconnected\n if (this.hadFirstUpdate && this.observer) {\n this.observer.observe(this.target())\n }\n }\n\n hostDisconnected() {\n if (this.observer) {\n this.observer.disconnect()\n }\n }\n}\n","import * as searchIcon from '@nordhealth/icons/lib/assets/navigation-search.js'\nimport { html, LitElement, nothing } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { ref } from 'lit/directives/ref.js'\n\nimport { styleMap } from 'lit/directives/style-map.js'\nimport { DirectionController } from '../common/controllers/DirectionController.js'\nimport { ResizeController } from '../common/controllers/ResizeController.js'\nimport { cond } from '../common/directives/cond.js'\nimport { NordEvent } from '../common/events.js'\nimport { getSubmitButton } from '../common/form.js'\nimport { cleanValue } from '../common/input.js'\nimport { AutocompleteMixin } from '../common/mixins/AutocompleteMixin.js'\n\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\nimport { ReadonlyMixin } from '../common/mixins/ReadonlyMixin.js'\nimport { SizeMixin } from '../common/mixins/SizeMixin.js'\nimport { TextSelectableMixin } from '../common/mixins/TextSelectableMixin.js'\nimport componentStyle from '../common/styles/Component.css'\nimport formFieldStyle from '../common/styles/FormField.css'\nimport textFieldStyle from '../common/styles/TextField.css'\nimport Icon from '../icon/Icon.js'\nimport style from './Input.css'\n\nIcon.registerIcon(searchIcon)\n\nconst px = (value?: number) => (value ? `${value}px` : undefined)\n\ntype InputMode = 'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search'\nconst defaultInputmodeMap: Record<string, InputMode> = {\n number: 'numeric',\n email: 'email',\n tel: 'tel',\n url: 'url',\n search: 'search',\n}\n\n/**\n * Inputs are used to allow users to provide text input when the expected input is short.\n * As well as plain text, Input supports various types of text, including passwords and numbers.\n *\n * @status ready\n * @category form\n * @slot label - Use when a label requires more than plain text.\n * @slot hint - Optional slot that holds hint text for the input.\n * @slot error - Optional slot that holds error text for the input.\n * @slot start - Optional slot used to place an icon or prefix at the start of the input.\n * @slot end - Optional slot used to place an icon or suffix at the end of the input.\n *\n * @cssprop [--n-input-inline-size=240px] - Controls the inline size, or width, of the input.\n * @cssprop [--n-input-background=var(--n-color-active)] - Controls the background of the input, using our [color tokens](/tokens/#color).\n * @cssprop [--n-input-color=var(--n-color-text)] - Controls the text color of the input, using our [color tokens](/tokens/#color).\n * @cssprop [--n-input-border-color=var(--n-color-border-strong)] - Controls the border color of the input, using our [color tokens](/tokens/#color).\n * @cssprop [--n-input-border-radius=var(--n-border-radius-s)] - Controls how rounded the corners are, using [border radius tokens](/tokens/#border-radius).\n * @cssprop [--n-input-text-align=start] - Controls the alignment of text within the input itself.\n * @cssprop [--n-label-color=var(--n-color-text)] - Controls the text color of the label, using our [color tokens](/tokens/#color).\n */\n@customElement('nord-input')\nexport default class Input extends SizeMixin(\n FormAssociatedMixin(AutocompleteMixin(ReadonlyMixin(TextSelectableMixin(InputMixin(FocusableMixin(LitElement)))))),\n) {\n static styles = [componentStyle, formFieldStyle, textFieldStyle, style]\n\n @query('slot[name=\\'start\\']') private startSlot!: HTMLSlotElement\n @query('slot[name=\\'end\\']') private endSlot!: HTMLSlotElement\n private startObserver = new ResizeController(this, () => this.startSlot)\n private endObserver = new ResizeController(this, () => this.endSlot)\n private direction = new DirectionController(this)\n\n /**\n * The type of the input.\n */\n @property({ reflect: true }) type:\n | 'text'\n | 'email'\n | 'password'\n | 'tel'\n | 'url'\n | 'search'\n | 'number'\n | 'unit'\n | 'button' = 'text'\n\n /**\n * Controls whether the input expands to fill the width of its container.\n */\n @property({ reflect: true, type: Boolean }) expand = false\n\n /**\n * Optionally disallow certain characters from being used inside the input, using a regex pattern.\n */\n @property({ reflect: true, attribute: 'disallow-pattern' }) disallowPattern?: string = undefined\n\n /**\n * The inputmode attribute provides a hint to the browser about what type of keyboard to open on mobile devices.\n * Valid values: none, text, decimal, numeric, tel, search, email, url\n * When not explicitly set, defaults based on input type:\n * - type=\"number\" → inputmode=\"numeric\"\n * - type=\"email\" → inputmode=\"email\"\n * - type=\"tel\" → inputmode=\"tel\"\n * - type=\"url\" → inputmode=\"url\"\n * - type=\"search\" → inputmode=\"search\"\n * Can be explicitly overridden for any type.\n */\n @property({ reflect: true }) inputmode?: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url' = undefined\n\n render() {\n const isNumber = this.type === 'number'\n\n const inputmodeValue = this.inputmode || defaultInputmodeMap[this.type]\n\n return html`\n ${this.renderLabel()}\n\n <div\n class=${classMap({\n 'n-input-container': true,\n 'is-rtl': this.direction.dir === 'rtl',\n })}\n style=${styleMap({\n '--_n-input-start-inline-size': px(this.startObserver.inlineSize),\n '--_n-input-end-inline-size': px(this.endObserver.inlineSize),\n })}\n >\n <slot name=\"start\">\n ${this.type === 'search' ? html`<nord-icon name=\"navigation-search\"></nord-icon>` : nothing}\n </slot>\n <input\n ${ref(this.textSelectableRef)}\n ${ref(this.focusableRef)}\n id=${this.inputId}\n class=\"n-input\"\n type=${isNumber || this.type === 'unit' ? 'text' : this.type}\n inputmode=${ifDefined(inputmodeValue)}\n pattern=${cond(isNumber, '[0-9]*')}\n ?disabled=${this.disabled}\n ?required=${this.required}\n ?readonly=${this.readonly}\n name=${ifDefined(this.name)}\n .value=${this.value ?? ''}\n placeholder=${ifDefined(this.placeholder)}\n @input=${this.handleInputChange}\n @change=${this.handleChange}\n @keydown=${this.handleKeydown}\n @select=${this.handleSelect}\n aria-describedby=${ifDefined(this.getDescribedBy())}\n aria-invalid=${ifDefined(this.getInvalid())}\n spellcheck=\"false\"\n autocomplete=${this.autocomplete as any}\n />\n <slot name=\"end\"></slot>\n </div>\n\n ${this.renderError()}\n `\n }\n\n private handleKeydown(e: KeyboardEvent) {\n if (e.key !== 'Enter') {\n return\n }\n\n const { form } = this\n\n if (form) {\n const button = getSubmitButton(form)\n setTimeout(() => button?.click(), 0)\n }\n }\n\n private handleInputChange = (e: Event) => {\n const target = e.target as HTMLInputElement\n\n // clean up any invalid characters\n if (this.disallowPattern) {\n cleanValue(target, new RegExp(this.disallowPattern, 'g'))\n }\n this.handleInput(e)\n }\n\n protected handleSelect(e: Event) {\n e.stopPropagation()\n\n /**\n * Fired when some text has been selected.\n */\n this.dispatchEvent(new NordEvent('select'))\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-input': Input\n }\n}\n","export function cleanValue(inputEl: HTMLInputElement, regex: RegExp): string {\n const { value } = inputEl\n const cursor = inputEl.selectionStart as number\n\n const beforeCursor = value.slice(0, cursor)\n const afterCursor = value.slice(cursor, value.length)\n\n const filteredBeforeCursor = beforeCursor.replace(regex, '')\n const filterAfterCursor = afterCursor.replace(regex, '')\n\n const newValue = filteredBeforeCursor + filterAfterCursor\n const newCursor = filteredBeforeCursor.length\n\n inputEl.value = newValue\n inputEl.selectionStart = newCursor\n inputEl.selectionEnd = newCursor\n\n return newValue\n}\n","/**\n * Finds a form's submit button. First looking for a button inside form,\n * and then looking for a button whose form attribute is equal to the ID of the form.\n */\nexport function getSubmitButton(form: HTMLFormElement): HTMLButtonElement | null {\n // we can get away with just looking for native <button> elements,\n // rather than our component, since our button component renders one to light dom.\n let button = form.querySelector<HTMLButtonElement>(`button[type=\"submit\"]`)\n\n if (!button && form.id) {\n const root = form.getRootNode() as ShadowRoot | Document\n button = root.querySelector<HTMLButtonElement>(`button[form=${form.id}]`)\n }\n\n return button\n}\n"],"names":["ResizeController","constructor","host","target","this","hadFirstUpdate","addController","isServer","observer","ResizeObserver","entry","borderBoxSize","requestUpdate","inlineSize","_a","blockSize","hostUpdated","observe","hostConnected","hostDisconnected","disconnect","Icon","registerIcon","searchIcon","px","value","undefined","defaultInputmodeMap","number","email","tel","url","search","Input","SizeMixin","FormAssociatedMixin","AutocompleteMixin","ReadonlyMixin","TextSelectableMixin","InputMixin","FocusableMixin","LitElement","startObserver","startSlot","endObserver","endSlot","direction","DirectionController","type","expand","disallowPattern","inputmode","handleInputChange","e","inputEl","regex","cursor","selectionStart","beforeCursor","slice","afterCursor","length","filteredBeforeCursor","replace","newValue","newCursor","selectionEnd","cleanValue","RegExp","handleInput","render","isNumber","inputmodeValue","html","renderLabel","classMap","dir","styleMap","nothing","ref","textSelectableRef","focusableRef","inputId","ifDefined","cond","disabled","required","readonly","name","placeholder","handleChange","handleKeydown","handleSelect","getDescribedBy","getInvalid","autocomplete","renderError","key","form","button","querySelector","id","getRootNode","getSubmitButton","setTimeout","click","stopPropagation","dispatchEvent","NordEvent","styles","componentStyle","formFieldStyle","textFieldStyle","style","__decorate","query","prototype","property","reflect","Boolean","attribute","customElement"],"mappings":"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"}
1
+ {"version":3,"file":"Input.js","sources":["../../icons/lib/assets/navigation-search.js","../src/common/controllers/ResizeController.ts","../src/input/Input.ts","../src/common/input.ts","../src/common/form.ts"],"sourcesContent":["export default '<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m16.03 14.61c1.23-1.54 1.97-3.49 1.97-5.61 0-4.97-4.03-9-9-9s-9 4.03-9 9 4.03 9 9 9c2.12 0 4.07-.74 5.61-1.97l3.97 3.97 1.41-1.41-3.97-3.97zm-7.03 1.39c-3.86 0-7-3.14-7-7s3.14-7 7-7 7 3.14 7 7-3.14 7-7 7z\" fill=\"currentColor\"/></svg>';\nexport const title = \"navigation-search\";\nexport const tags = \"nordicon navigation menu find search magnifying glass\";\n","import type { ReactiveController, ReactiveControllerHost } from 'lit'\nimport { isServer } from 'lit'\n\nexport class ResizeController implements ReactiveController {\n private observer?: ResizeObserver\n private hadFirstUpdate = false\n private borderBoxSize?: ResizeObserverSize\n\n constructor(\n host: ReactiveControllerHost,\n private target: () => HTMLElement,\n ) {\n host.addController(this)\n\n if (!isServer) {\n this.observer = new ResizeObserver(([entry]) => {\n const [borderBoxSize] = entry.borderBoxSize\n this.borderBoxSize = borderBoxSize\n host.requestUpdate()\n })\n }\n }\n\n get inlineSize() {\n return this.borderBoxSize?.inlineSize\n }\n\n get blockSize() {\n return this.borderBoxSize?.blockSize\n }\n\n hostUpdated() {\n if (!this.hadFirstUpdate && this.observer) {\n this.observer.observe(this.target())\n this.hadFirstUpdate = true\n }\n }\n\n hostConnected() {\n // in case the host has rendered, disconnected, and is now reconnected\n if (this.hadFirstUpdate && this.observer) {\n this.observer.observe(this.target())\n }\n }\n\n hostDisconnected() {\n if (this.observer) {\n this.observer.disconnect()\n }\n }\n}\n","import * as searchIcon from '@nordhealth/icons/lib/assets/navigation-search.js'\nimport { html, LitElement, nothing } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { ref } from 'lit/directives/ref.js'\n\nimport { styleMap } from 'lit/directives/style-map.js'\nimport { DirectionController } from '../common/controllers/DirectionController.js'\nimport { ResizeController } from '../common/controllers/ResizeController.js'\nimport { cond } from '../common/directives/cond.js'\nimport { NordEvent } from '../common/events.js'\nimport { getSubmitButton } from '../common/form.js'\nimport { cleanValue } from '../common/input.js'\nimport { AutocompleteMixin } from '../common/mixins/AutocompleteMixin.js'\n\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\nimport { ReadonlyMixin } from '../common/mixins/ReadonlyMixin.js'\nimport { SizeMixin } from '../common/mixins/SizeMixin.js'\nimport { TextSelectableMixin } from '../common/mixins/TextSelectableMixin.js'\nimport componentStyle from '../common/styles/Component.css'\nimport formFieldStyle from '../common/styles/FormField.css'\nimport textFieldStyle from '../common/styles/TextField.css'\nimport Icon from '../icon/Icon.js'\nimport style from './Input.css'\n\nIcon.registerIcon(searchIcon)\n\nconst px = (value?: number) => (value ? `${value}px` : undefined)\n\ntype InputMode = 'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search'\nconst defaultInputmodeMap: Record<string, InputMode> = {\n number: 'numeric',\n email: 'email',\n tel: 'tel',\n url: 'url',\n search: 'search',\n}\n\n/**\n * Inputs are used to allow users to provide text input when the expected input is short.\n * As well as plain text, Input supports various types of text, including passwords and numbers.\n *\n * @status ready\n * @category form\n * @slot label - Use when a label requires more than plain text.\n * @slot hint - Optional slot that holds hint text for the input.\n * @slot error - Optional slot that holds error text for the input.\n * @slot start - Optional slot used to place an icon or prefix at the start of the input.\n * @slot end - Optional slot used to place an icon or suffix at the end of the input.\n *\n * @cssprop [--n-input-inline-size=240px] - Controls the inline size, or width, of the input.\n * @cssprop [--n-input-background=var(--n-color-active)] - Controls the background of the input, using our [color tokens](/tokens/#color).\n * @cssprop [--n-input-color=var(--n-color-text)] - Controls the text color of the input, using our [color tokens](/tokens/#color).\n * @cssprop [--n-input-border-color=var(--n-color-border-strong)] - Controls the border color of the input, using our [color tokens](/tokens/#color).\n * @cssprop [--n-input-border-radius=var(--n-border-radius-s)] - Controls how rounded the corners are, using [border radius tokens](/tokens/#border-radius).\n * @cssprop [--n-input-text-align=start] - Controls the alignment of text within the input itself.\n * @cssprop [--n-label-color=var(--n-color-text)] - Controls the text color of the label, using our [color tokens](/tokens/#color).\n */\n@customElement('nord-input')\nexport default class Input extends SizeMixin(\n FormAssociatedMixin(AutocompleteMixin(ReadonlyMixin(TextSelectableMixin(InputMixin(FocusableMixin(LitElement)))))),\n) {\n static styles = [componentStyle, formFieldStyle, textFieldStyle, style]\n\n @query('slot[name=\\'start\\']') private startSlot!: HTMLSlotElement\n @query('slot[name=\\'end\\']') private endSlot!: HTMLSlotElement\n private startObserver = new ResizeController(this, () => this.startSlot)\n private endObserver = new ResizeController(this, () => this.endSlot)\n private direction = new DirectionController(this)\n\n /**\n * The type of the input.\n */\n @property({ reflect: true }) type:\n | 'text'\n | 'email'\n | 'password'\n | 'tel'\n | 'url'\n | 'search'\n | 'number'\n | 'unit'\n | 'button' = 'text'\n\n /**\n * Controls whether the input expands to fill the width of its container.\n */\n @property({ reflect: true, type: Boolean }) expand = false\n\n /**\n * Optionally disallow certain characters from being used inside the input, using a regex pattern.\n */\n @property({ reflect: true, attribute: 'disallow-pattern' }) disallowPattern?: string = undefined\n\n /**\n * The inputmode attribute provides a hint to the browser about what type of keyboard to open on mobile devices.\n * Valid values: none, text, decimal, numeric, tel, search, email, url\n * When not explicitly set, defaults based on input type:\n * - type=\"number\" → inputmode=\"numeric\"\n * - type=\"email\" → inputmode=\"email\"\n * - type=\"tel\" → inputmode=\"tel\"\n * - type=\"url\" → inputmode=\"url\"\n * - type=\"search\" → inputmode=\"search\"\n * Can be explicitly overridden for any type.\n */\n @property({ reflect: true }) inputmode?: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url' = undefined\n\n render() {\n const isNumber = this.type === 'number'\n\n const inputmodeValue = this.inputmode || defaultInputmodeMap[this.type]\n\n return html`\n ${this.renderLabel()}\n\n <div\n class=${classMap({\n 'n-input-container': true,\n 'is-rtl': this.direction.dir === 'rtl',\n })}\n style=${styleMap({\n '--_n-input-start-inline-size': px(this.startObserver.inlineSize),\n '--_n-input-end-inline-size': px(this.endObserver.inlineSize),\n })}\n >\n <slot name=\"start\">\n ${this.type === 'search' ? html`<nord-icon name=\"navigation-search\"></nord-icon>` : nothing}\n </slot>\n <input\n ${ref(this.textSelectableRef)}\n ${ref(this.focusableRef)}\n id=${this.inputId}\n class=\"n-input\"\n type=${isNumber || this.type === 'unit' ? 'text' : this.type}\n inputmode=${ifDefined(inputmodeValue)}\n pattern=${cond(isNumber, '[0-9]*')}\n ?disabled=${this.disabled}\n ?required=${this.required}\n ?readonly=${this.readonly}\n name=${ifDefined(this.name)}\n .value=${this.value ?? ''}\n placeholder=${ifDefined(this.placeholder)}\n @input=${this.handleInputChange}\n @change=${this.handleChange}\n @keydown=${this.handleKeydown}\n @select=${this.handleSelect}\n aria-describedby=${ifDefined(this.getDescribedBy())}\n aria-invalid=${ifDefined(this.getInvalid())}\n spellcheck=\"false\"\n autocomplete=${this.autocomplete as any}\n />\n <slot name=\"end\"></slot>\n </div>\n\n ${this.renderError()}\n ${this.isHintBelow ? this.renderHint() : nothing}\n `\n }\n\n private handleKeydown(e: KeyboardEvent) {\n if (e.key !== 'Enter') {\n return\n }\n\n const { form } = this\n\n if (form) {\n const button = getSubmitButton(form)\n setTimeout(() => button?.click(), 0)\n }\n }\n\n private handleInputChange = (e: Event) => {\n const target = e.target as HTMLInputElement\n\n // clean up any invalid characters\n if (this.disallowPattern) {\n cleanValue(target, new RegExp(this.disallowPattern, 'g'))\n }\n this.handleInput(e)\n }\n\n protected handleSelect(e: Event) {\n e.stopPropagation()\n\n /**\n * Fired when some text has been selected.\n */\n this.dispatchEvent(new NordEvent('select'))\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-input': Input\n }\n}\n","export function cleanValue(inputEl: HTMLInputElement, regex: RegExp): string {\n const { value } = inputEl\n const cursor = inputEl.selectionStart as number\n\n const beforeCursor = value.slice(0, cursor)\n const afterCursor = value.slice(cursor, value.length)\n\n const filteredBeforeCursor = beforeCursor.replace(regex, '')\n const filterAfterCursor = afterCursor.replace(regex, '')\n\n const newValue = filteredBeforeCursor + filterAfterCursor\n const newCursor = filteredBeforeCursor.length\n\n inputEl.value = newValue\n inputEl.selectionStart = newCursor\n inputEl.selectionEnd = newCursor\n\n return newValue\n}\n","/**\n * Finds a form's submit button. First looking for a button inside form,\n * and then looking for a button whose form attribute is equal to the ID of the form.\n */\nexport function getSubmitButton(form: HTMLFormElement): HTMLButtonElement | null {\n // we can get away with just looking for native <button> elements,\n // rather than our component, since our button component renders one to light dom.\n let button = form.querySelector<HTMLButtonElement>(`button[type=\"submit\"]`)\n\n if (!button && form.id) {\n const root = form.getRootNode() as ShadowRoot | Document\n button = root.querySelector<HTMLButtonElement>(`button[form=${form.id}]`)\n }\n\n return button\n}\n"],"names":["ResizeController","constructor","host","target","this","hadFirstUpdate","addController","isServer","observer","ResizeObserver","entry","borderBoxSize","requestUpdate","inlineSize","_a","blockSize","hostUpdated","observe","hostConnected","hostDisconnected","disconnect","Icon","registerIcon","searchIcon","px","value","undefined","defaultInputmodeMap","number","email","tel","url","search","Input","SizeMixin","FormAssociatedMixin","AutocompleteMixin","ReadonlyMixin","TextSelectableMixin","InputMixin","FocusableMixin","LitElement","startObserver","startSlot","endObserver","endSlot","direction","DirectionController","type","expand","disallowPattern","inputmode","handleInputChange","e","inputEl","regex","cursor","selectionStart","beforeCursor","slice","afterCursor","length","filteredBeforeCursor","replace","newValue","newCursor","selectionEnd","cleanValue","RegExp","handleInput","render","isNumber","inputmodeValue","html","renderLabel","classMap","dir","styleMap","nothing","ref","textSelectableRef","focusableRef","inputId","ifDefined","cond","disabled","required","readonly","name","placeholder","handleChange","handleKeydown","handleSelect","getDescribedBy","getInvalid","autocomplete","renderError","isHintBelow","renderHint","key","form","button","querySelector","id","getRootNode","getSubmitButton","setTimeout","click","stopPropagation","dispatchEvent","NordEvent","styles","componentStyle","formFieldStyle","textFieldStyle","style","__decorate","query","prototype","property","reflect","Boolean","attribute","customElement"],"mappings":"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"}
package/lib/Radio.js CHANGED
@@ -1,2 +1,2 @@
1
- import{_ as t}from"./tslib.es6-CmLYFWVC.js";import{css as i,html as e,nothing as o,LitElement as n}from"lit";import{property as r,customElement as a}from"lit/decorators.js";import{ref as s}from"lit/directives/ref.js";import{L as l}from"./LightDomController-DIwtVelV.js";import{L as d}from"./LightSlotController-Coyy4nqS.js";import{o as c}from"./observe-D0n0zOfU.js";import{c as h}from"./cond-CI1KbneT.js";import{F as p}from"./FocusableMixin-BlQLNPdJ.js";import{F as m}from"./FormAssociatedMixin-DFL7yabe.js";import{I as v}from"./InputMixin-LetXsCyv.js";import{S as u}from"./SizeMixin-CU9cLbLC.js";import{s as b}from"./Component-DSU3Qp0O.js";import{s as f}from"./FormField--eLuhPue.js";import"./SlotController-Z6eG7LSZ.js";import"./EventController-BBOmvfLa.js";import"./FormDataController-OUt5L5uC.js";import"./events-Bv6wNHwJ.js";import"./VisuallyHidden.js";const g=i`:host{--_n-radio-size:calc(var(--n-space-m) * 1.25);--_n-radio-dot-size:var(--n-space-s);--_n-radio-dot-inset:calc((var(--_n-radio-size) - var(--_n-radio-dot-size)) / 2);display:inline-block;line-height:var(--n-line-height)}.n-flex{display:flex}.n-expand{flex:1}.n-input-container{position:relative}::slotted(input){--_n-radio-accent-color:var(--n-color-accent);appearance:none;margin:0!important;padding:0!important;border:1px solid var(--_n-radio-border-color,var(--n-color-border-hover))!important;border-radius:var(--n-border-radius-circle)!important;transition:none!important;display:block!important;inline-size:var(--_n-radio-size)!important;block-size:var(--_n-radio-size)!important;cursor:pointer}::slotted(input:checked){--_n-radio-border-color:var(--n-color-accent);background:var(--_n-radio-accent-color)!important}::slotted(input[aria-invalid]){--_n-radio-accent-color:var(--n-color-status-danger);--_n-radio-border-color:var(--_n-radio-accent-color)}::slotted(input:active){opacity:.8}::slotted(input:focus-visible){outline:0!important}::slotted(input:focus){outline:0!important;box-shadow:0 0 0 1px var(--n-color-surface),0 0 0 3px var(--n-color-accent)!important}:host([disabled]) ::slotted(label){color:var(--n-color-text-weaker);cursor:default}:host([disabled]) ::slotted(input){background:var(--_n-radio-accent-color);cursor:default;opacity:1}:host([disabled]) ::slotted(input:not(:checked)){--_n-radio-accent-color:var(--n-color-active);--_n-radio-border-color:var(--n-color-border-neutral)}:host([disabled]) ::slotted(input:checked){opacity:.3}.n-dot{position:absolute;border-radius:var(--n-border-radius-circle);inline-size:var(--_n-radio-dot-size);block-size:var(--_n-radio-dot-size);background-color:var(--n-color-text-on-accent);inset-inline-start:var(--_n-radio-dot-inset);inset-block-start:var(--_n-radio-dot-inset);z-index:var(--n-index-default);pointer-events:none}.n-label-container{margin-block-end:0}::slotted(label){user-select:none;font-weight:var(--n-font-weight)!important;line-height:var(--n-line-height)!important;padding-inline-start:var(--n-space-s)!important;cursor:pointer}.n-hint{padding-inline-start:var(--n-space-s)}.n-error{margin-block-start:var(--n-space-xs);padding-inline-start:var(--n-space-s)}:host([size='s']){--_n-radio-size:var(--n-size-icon-m);--_n-radio-dot-size:calc(var(--n-size-icon-s) / 2)}:host([size='s']:not([hide-label])) .n-input-container{margin:calc(var(--n-space-s)/ 3) 0}:host([size='l']){--_n-radio-size:var(--n-size-icon-l);--_n-radio-dot-size:var(--n-size-icon-xs)}:host([size='l']:not([hide-label])) .n-label-container{margin:2px 0 0}`;let k=0;const $=t=>`nord-radio-${t}-${k++}`;let _=class extends(u(m(v(p(n))))){constructor(){super(...arguments),this.inputId=$("input"),this.hintId=$("hint"),this.errorId=$("error"),this.hintSlot=new d(this,{slotName:"hint",render:()=>this.hint?e`<div slot="hint-internal" id="${this.hintId}">${this.hint}</div>`:o,syncLightDom:t=>{t.id=this.hintId}}),this.labelSlot=new d(this,{slotName:"label",render:()=>this.label?e`<label slot="label-internal" for="${this.inputId}">${this.label}</label>`:o,syncLightDom:t=>{!function(t){return"label"===t.localName}(t)?console.warn('NORD: Only <label> elements should be placed in radio\'s "label" slot'):t.htmlFor=this.inputId}}),this.errorSlot=new d(this,{slotName:"error",render:()=>this.error?e`<div slot="error-internal" id="${this.errorId}">${this.error}</div>`:o,syncLightDom:t=>{t.id=this.hintId}}),this.inputSlot=new l(this,{render:()=>e`<input slot="input" @blur="${this.handleBlur}" @focus="${this.handleFocus}" ${s(this.focusableRef)} class="n-input" id="${this.inputId}" type="radio" name="${h(this.name)}" .value="${h(this.value)}" .checked="${this.checked}" ?disabled="${this.disabled}" ?required="${this.required}" aria-describedby="${h(this.getDescribedBy())}" aria-invalid="${h(this.getInvalid())}" form="${h(this._formId)}">`}),this.checked=!1,this.handleBlur=t=>{t.stopPropagation(),this.dispatchEvent(new Event("blur",{bubbles:!1,cancelable:!0}))},this.handleFocus=t=>{t.stopPropagation(),this.dispatchEvent(new Event("focus",{bubbles:!1,cancelable:!0}))}}get formValue(){}render(){return e`<div class="n-flex"><div class="n-input-container" @change="${this.handleChange}"><slot name="input"></slot>${this.checked?e`<div class="n-dot"></div>`:o}</div><div class="n-expand"><div class="n-label-container">${t=this.hideLabel,i=()=>e`<slot name="label"></slot><slot name="label-internal"></slot>`,n=t=>e`<nord-visually-hidden>${t}</nord-visually-hidden>`,t?n(i()):i()}<div class="n-caption n-hint" ?hidden="${!this.hasHint}"><slot name="hint"></slot><slot name="hint-internal"></slot></div></div><div class="n-caption n-error" role="alert" ?hidden="${!this.hasError}"><slot name="error"></slot><slot name="error-internal"></slot></div></div></div>`;var t,i,n}handleCheckedChange(t){!t&&this.checked&&this.uncheckSiblings()}uncheckSiblings(){this.getRootNode().querySelectorAll(`nord-radio[name="${this.name}"]`).forEach((t=>{t!==this&&t.checked&&(t.checked=!1,function(t){t.style.display="none",t.offsetHeight,t.style.display="inline-block"}(t))}))}handleChange(t){t.stopPropagation();const i=t.target;this.checked=i.checked,super.handleChange(t)}};_.styles=[b,f,g],t([r({type:Boolean,reflect:!0})],_.prototype,"checked",void 0),t([c("checked")],_.prototype,"handleCheckedChange",null),_=t([a("nord-radio")],_);var z=_;export{z as default};
1
+ import{_ as i}from"./tslib.es6-CmLYFWVC.js";import{css as t,html as e,nothing as o,LitElement as n}from"lit";import{property as r,customElement as a}from"lit/decorators.js";import{ref as s}from"lit/directives/ref.js";import{L as l}from"./LightDomController-DIwtVelV.js";import{L as d}from"./LightSlotController-Coyy4nqS.js";import{o as c}from"./observe-D0n0zOfU.js";import{c as h}from"./cond-CI1KbneT.js";import{F as p}from"./FocusableMixin-BlQLNPdJ.js";import{F as m}from"./FormAssociatedMixin-B4Qj-CQN.js";import{I as v}from"./InputMixin-LetXsCyv.js";import{S as u}from"./SizeMixin-CU9cLbLC.js";import{s as b}from"./Component-DSU3Qp0O.js";import{s as f}from"./FormField-BFaVzUjk.js";import"./SlotController-Z6eG7LSZ.js";import"./EventController-BBOmvfLa.js";import"./FormDataController-OUt5L5uC.js";import"./events-Bv6wNHwJ.js";import"./VisuallyHidden.js";const g=t`:host{--_n-radio-size:calc(var(--n-space-m) * 1.25);--_n-radio-dot-size:var(--n-space-s);--_n-radio-dot-inset:calc((var(--_n-radio-size) - var(--_n-radio-dot-size)) / 2);display:inline-block;line-height:var(--n-line-height)}.n-flex{display:flex}.n-expand{flex:1}.n-input-container{position:relative}::slotted(input){--_n-radio-accent-color:var(--n-color-accent);appearance:none;margin:0!important;padding:0!important;border:1px solid var(--_n-radio-border-color,var(--n-color-border-hover))!important;border-radius:var(--n-border-radius-circle)!important;transition:none!important;display:block!important;inline-size:var(--_n-radio-size)!important;block-size:var(--_n-radio-size)!important;cursor:pointer}::slotted(input:checked){--_n-radio-border-color:var(--n-color-accent);background:var(--_n-radio-accent-color)!important}::slotted(input[aria-invalid]){--_n-radio-accent-color:var(--n-color-status-danger);--_n-radio-border-color:var(--_n-radio-accent-color)}::slotted(input:active){opacity:.8}::slotted(input:focus-visible){outline:0!important}::slotted(input:focus){outline:0!important;box-shadow:0 0 0 1px var(--n-color-surface),0 0 0 3px var(--n-color-accent)!important}:host([disabled]) ::slotted(label){color:var(--n-color-text-weaker);cursor:default}:host([disabled]) ::slotted(input){background:var(--_n-radio-accent-color);cursor:default;opacity:1}:host([disabled]) ::slotted(input:not(:checked)){--_n-radio-accent-color:var(--n-color-active);--_n-radio-border-color:var(--n-color-border-neutral)}:host([disabled]) ::slotted(input:checked){opacity:.3}.n-dot{position:absolute;border-radius:var(--n-border-radius-circle);inline-size:var(--_n-radio-dot-size);block-size:var(--_n-radio-dot-size);background-color:var(--n-color-text-on-accent);inset-inline-start:var(--_n-radio-dot-inset);inset-block-start:var(--_n-radio-dot-inset);z-index:var(--n-index-default);pointer-events:none}.n-label-container{margin-block-end:0}::slotted(label){user-select:none;font-weight:var(--n-font-weight)!important;line-height:var(--n-line-height)!important;padding-inline-start:var(--n-space-s)!important;cursor:pointer}.n-hint{padding-inline-start:var(--n-space-s)}.n-error{margin-block-start:var(--n-space-xs);padding-inline-start:var(--n-space-s)}:host([hint-below]) :is(.n-hint, .n-error){padding-inline-start:0}:host([size='s']){--_n-radio-size:var(--n-size-icon-m);--_n-radio-dot-size:calc(var(--n-size-icon-s) / 2)}:host([size='s']:not([hide-label])) .n-input-container{margin:calc(var(--n-space-s)/ 3) 0}:host([size='l']){--_n-radio-size:var(--n-size-icon-l);--_n-radio-dot-size:var(--n-size-icon-xs)}:host([size='l']:not([hide-label])) .n-label-container{margin:2px 0 0}`;let $=0;const k=i=>`nord-radio-${i}-${$++}`;let _=class extends(u(m(v(p(n))))){constructor(){super(...arguments),this.inputId=k("input"),this.hintId=k("hint"),this.errorId=k("error"),this.hintSlot=new d(this,{slotName:"hint",render:()=>this.hint?e`<div slot="hint-internal" id="${this.hintId}">${this.hint}</div>`:o,syncLightDom:i=>{i.id=this.hintId}}),this.labelSlot=new d(this,{slotName:"label",render:()=>this.label?e`<label slot="label-internal" for="${this.inputId}">${this.label}</label>`:o,syncLightDom:i=>{!function(i){return"label"===i.localName}(i)?console.warn('NORD: Only <label> elements should be placed in radio\'s "label" slot'):i.htmlFor=this.inputId}}),this.errorSlot=new d(this,{slotName:"error",render:()=>this.error?e`<div slot="error-internal" id="${this.errorId}">${this.error}</div>`:o,syncLightDom:i=>{i.id=this.hintId}}),this.inputSlot=new l(this,{render:()=>e`<input slot="input" @blur="${this.handleBlur}" @focus="${this.handleFocus}" ${s(this.focusableRef)} class="n-input" id="${this.inputId}" type="radio" name="${h(this.name)}" .value="${h(this.value)}" .checked="${this.checked}" ?disabled="${this.disabled}" ?required="${this.required}" aria-describedby="${h(this.getDescribedBy())}" aria-invalid="${h(this.getInvalid())}" form="${h(this._formId)}">`}),this.checked=!1,this.handleBlur=i=>{i.stopPropagation(),this.dispatchEvent(new Event("blur",{bubbles:!1,cancelable:!0}))},this.handleFocus=i=>{i.stopPropagation(),this.dispatchEvent(new Event("focus",{bubbles:!1,cancelable:!0}))}}get formValue(){}render(){const i=e`<div class="n-caption n-hint" ?hidden="${!this.hasHint}"><slot name="hint"></slot><slot name="hint-internal"></slot></div>`,t=e`<div class="n-caption n-error" role="alert" ?hidden="${!this.hasError}"><slot name="error"></slot><slot name="error-internal"></slot></div>`;return e`<div class="n-flex"><div class="n-input-container" @change="${this.handleChange}"><slot name="input"></slot>${this.checked?e`<div class="n-dot"></div>`:o}</div><div class="n-expand"><div class="n-label-container">${n=this.hideLabel,r=()=>e`<slot name="label"></slot><slot name="label-internal"></slot>`,a=i=>e`<nord-visually-hidden>${i}</nord-visually-hidden>`,n?a(r()):r()} ${this.isHintBelow?o:i}</div>${this.isHintBelow?o:t}</div></div>${this.isHintBelow?t:o} ${this.isHintBelow?i:o}`;var n,r,a}handleCheckedChange(i){!i&&this.checked&&this.uncheckSiblings()}uncheckSiblings(){this.getRootNode().querySelectorAll(`nord-radio[name="${this.name}"]`).forEach((i=>{i!==this&&i.checked&&(i.checked=!1,function(i){i.style.display="none",i.offsetHeight,i.style.display="inline-block"}(i))}))}handleChange(i){i.stopPropagation();const t=i.target;this.checked=t.checked,super.handleChange(i)}};_.styles=[b,f,g],i([r({type:Boolean,reflect:!0})],_.prototype,"checked",void 0),i([c("checked")],_.prototype,"handleCheckedChange",null),_=i([a("nord-radio")],_);var z=_;export{z as default};
2
2
  //# sourceMappingURL=Radio.js.map
package/lib/Radio.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Radio.js","sources":["../src/radio/Radio.ts","../src/common/directives/wrapIf.ts"],"sourcesContent":["import { html, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ref } from 'lit/directives/ref.js'\nimport { LightDomController } from '../common/controllers/LightDomController.js'\nimport { LightSlotController } from '../common/controllers/LightSlotController.js'\nimport { observe } from '../common/decorators/observe.js'\nimport { cond } from '../common/directives/cond.js'\nimport { wrapIf } from '../common/directives/wrapIf.js'\n\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\nimport { SizeMixin } from '../common/mixins/SizeMixin.js'\n\nimport componentStyle from '../common/styles/Component.css'\nimport formFieldStyle from '../common/styles/FormField.css'\nimport style from './Radio.css'\n\nlet id = 0\nconst createId = (suffix: string) => `nord-radio-${suffix}-${id++}`\n\nfunction isLabel(element: Element): element is HTMLLabelElement {\n return element.localName === 'label'\n}\n\n/**\n * Force reflow (and with it a repaint) of a radio button because of a macOS Safari rendering bug\n *\n * @see https://bugs.webkit.org/show_bug.cgi?id=249706\n */\nfunction forceReflow(radio: Radio) {\n radio.style.display = 'none'\n // eslint-disable-next-line ts/no-unused-expressions\n radio.offsetHeight // no need to store this anywhere, the reference is enough\n radio.style.display = 'inline-block'\n}\n\n/**\n * Radio buttons are graphical user interface elements that allow user to choose only one option from\n * a predefined set of mutually exclusive options.\n *\n * @status ready\n * @category form\n * @slot label - Use when a label requires more than plain text.\n * @slot hint - Optional slot that holds hint text for the input.\n * @slot error - Optional slot that holds error text for the input.\n *\n * @cssprop [--n-label-color=var(--n-color-text)] - Controls the text color of the label, using our [color tokens](/tokens/#color).\n */\n@customElement('nord-radio')\nexport default class Radio extends SizeMixin(FormAssociatedMixin(InputMixin(FocusableMixin(LitElement)))) {\n static styles = [componentStyle, formFieldStyle, style]\n\n protected override inputId = createId('input')\n protected override hintId = createId('hint')\n protected override errorId = createId('error')\n\n /**\n * For accessibility reasons, we render some parts of the component to the light DOM.\n */\n protected override hintSlot = new LightSlotController(this, {\n slotName: 'hint',\n render: () => (this.hint ? html`<div slot=\"hint-internal\" id=${this.hintId}>${this.hint}</div>` : nothing),\n syncLightDom: (element) => {\n element.id = this.hintId\n },\n })\n\n protected override labelSlot = new LightSlotController(this, {\n slotName: 'label',\n render: () => (this.label ? html`<label slot=\"label-internal\" for=${this.inputId}>${this.label}</label>` : nothing),\n syncLightDom: (element) => {\n if (!isLabel(element)) {\n console.warn(`NORD: Only <label> elements should be placed in radio's \"label\" slot`)\n }\n else {\n element.htmlFor = this.inputId\n }\n },\n })\n\n protected override errorSlot = new LightSlotController(this, {\n slotName: 'error',\n render: () => (this.error ? html`<div slot=\"error-internal\" id=${this.errorId}>${this.error}</div>` : nothing),\n syncLightDom: (element) => {\n element.id = this.hintId\n },\n })\n\n protected inputSlot = new LightDomController(this, {\n render: () => html`\n <input\n slot=\"input\"\n @blur=${this.handleBlur}\n @focus=${this.handleFocus}\n ${ref(this.focusableRef)}\n class=\"n-input\"\n id=${this.inputId}\n type=\"radio\"\n name=${cond(this.name)}\n .value=${cond(this.value)}\n .checked=${this.checked}\n ?disabled=${this.disabled}\n ?required=${this.required}\n aria-describedby=${cond(this.getDescribedBy())}\n aria-invalid=${cond(this.getInvalid())}\n form=${cond(this._formId)}\n />\n `,\n })\n\n protected override get formValue() {\n // opt out of formdata event, since radio button is in light dom\n return undefined\n }\n\n /**\n * Controls whether the checkbox is checked or not.\n */\n @property({ type: Boolean, reflect: true }) checked: boolean = false\n\n render() {\n return html`\n <div class=\"n-flex\">\n <div class=\"n-input-container\" @change=${this.handleChange}>\n <slot name=\"input\"></slot>\n ${this.checked ? html`<div class=\"n-dot\"></div>` : nothing}\n </div>\n <div class=\"n-expand\">\n <div class=\"n-label-container\">\n ${wrapIf(\n this.hideLabel,\n () => html`\n <slot name=\"label\"></slot>\n <slot name=\"label-internal\"></slot>\n `,\n content => html`<nord-visually-hidden>${content}</nord-visually-hidden>`,\n )}\n <div class=\"n-caption n-hint\" ?hidden=${!this.hasHint}>\n <slot name=\"hint\"></slot>\n <slot name=\"hint-internal\"></slot>\n </div>\n </div>\n <div class=\"n-caption n-error\" role=\"alert\" ?hidden=${!this.hasError}>\n <slot name=\"error\"></slot>\n <slot name=\"error-internal\"></slot>\n </div>\n </div>\n </div>\n `\n }\n\n @observe('checked')\n protected handleCheckedChange(previousChecked: boolean) {\n // if this component was previous unchecked but is now checked,\n // then we need to uncheck any radios in the same group\n if (!previousChecked && this.checked) {\n this.uncheckSiblings()\n }\n }\n\n private uncheckSiblings() {\n const root = this.getRootNode() as Document | ShadowRoot\n\n root.querySelectorAll<Radio>(`nord-radio[name=\"${this.name}\"]`).forEach((radio) => {\n if (radio !== this && radio.checked) {\n radio.checked = false\n forceReflow(radio)\n }\n })\n }\n\n protected handleChange(e: Event): void {\n e.stopPropagation()\n const target = e.target as HTMLInputElement\n\n this.checked = target.checked\n super.handleChange(e)\n }\n\n private handleBlur = (e: Event) => {\n e.stopPropagation()\n this.dispatchEvent(new Event('blur', { bubbles: false, cancelable: true }))\n }\n\n private handleFocus = (e: Event) => {\n e.stopPropagation()\n this.dispatchEvent(new Event('focus', { bubbles: false, cancelable: true }))\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-radio': Radio\n }\n}\n","// some clever typing so that TS knows what happens if you pass true/false values\nexport function wrapIf<TInner, TWrapper>(\n condition: false,\n inner: () => TInner,\n wrapper: (inner: TInner) => TWrapper,\n): TInner\nexport function wrapIf<TInner, TWrapper>(\n condition: true,\n inner: () => TInner,\n wrapper: (inner: TInner) => TWrapper,\n): TWrapper\nexport function wrapIf<TInner, TWrapper>(\n condition: unknown,\n inner: () => TInner,\n wrapper: (inner: TInner) => TWrapper,\n): TInner | TWrapper\n\n/**\n * @returns if condition is truthy, return result of wrapper, passing result of inner as arg. if falsy, return result of inner\n */\nexport function wrapIf<TInner, TWrapper>(condition: any, inner: () => TInner, wrapper: (innards: TInner) => TWrapper) {\n return condition ? wrapper(inner()) : inner()\n}\n"],"names":["id","createId","suffix","Radio","SizeMixin","FormAssociatedMixin","InputMixin","FocusableMixin","LitElement","constructor","this","inputId","hintId","errorId","hintSlot","LightSlotController","slotName","render","hint","html","nothing","syncLightDom","element","labelSlot","label","localName","isLabel","console","warn","htmlFor","errorSlot","error","inputSlot","LightDomController","handleBlur","handleFocus","ref","focusableRef","cond","name","value","checked","disabled","required","getDescribedBy","getInvalid","_formId","e","stopPropagation","dispatchEvent","Event","bubbles","cancelable","formValue","handleChange","condition","hideLabel","inner","wrapper","content","hasHint","hasError","handleCheckedChange","previousChecked","uncheckSiblings","getRootNode","querySelectorAll","forEach","radio","style","display","offsetHeight","forceReflow","target","super","styles","componentStyle","formFieldStyle","__decorate","property","type","Boolean","reflect","prototype","observe","customElement"],"mappings":"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"}
1
+ {"version":3,"file":"Radio.js","sources":["../src/radio/Radio.ts","../src/common/directives/wrapIf.ts"],"sourcesContent":["import { html, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ref } from 'lit/directives/ref.js'\nimport { LightDomController } from '../common/controllers/LightDomController.js'\nimport { LightSlotController } from '../common/controllers/LightSlotController.js'\nimport { observe } from '../common/decorators/observe.js'\nimport { cond } from '../common/directives/cond.js'\nimport { wrapIf } from '../common/directives/wrapIf.js'\n\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\nimport { SizeMixin } from '../common/mixins/SizeMixin.js'\n\nimport componentStyle from '../common/styles/Component.css'\nimport formFieldStyle from '../common/styles/FormField.css'\nimport style from './Radio.css'\n\nlet id = 0\nconst createId = (suffix: string) => `nord-radio-${suffix}-${id++}`\n\nfunction isLabel(element: Element): element is HTMLLabelElement {\n return element.localName === 'label'\n}\n\n/**\n * Force reflow (and with it a repaint) of a radio button because of a macOS Safari rendering bug\n *\n * @see https://bugs.webkit.org/show_bug.cgi?id=249706\n */\nfunction forceReflow(radio: Radio) {\n radio.style.display = 'none'\n // eslint-disable-next-line ts/no-unused-expressions\n radio.offsetHeight // no need to store this anywhere, the reference is enough\n radio.style.display = 'inline-block'\n}\n\n/**\n * Radio buttons are graphical user interface elements that allow user to choose only one option from\n * a predefined set of mutually exclusive options.\n *\n * @status ready\n * @category form\n * @slot label - Use when a label requires more than plain text.\n * @slot hint - Optional slot that holds hint text for the input.\n * @slot error - Optional slot that holds error text for the input.\n *\n * @cssprop [--n-label-color=var(--n-color-text)] - Controls the text color of the label, using our [color tokens](/tokens/#color).\n */\n@customElement('nord-radio')\nexport default class Radio extends SizeMixin(FormAssociatedMixin(InputMixin(FocusableMixin(LitElement)))) {\n static styles = [componentStyle, formFieldStyle, style]\n\n protected override inputId = createId('input')\n protected override hintId = createId('hint')\n protected override errorId = createId('error')\n\n /**\n * For accessibility reasons, we render some parts of the component to the light DOM.\n */\n protected override hintSlot = new LightSlotController(this, {\n slotName: 'hint',\n render: () => (this.hint ? html`<div slot=\"hint-internal\" id=${this.hintId}>${this.hint}</div>` : nothing),\n syncLightDom: (element) => {\n element.id = this.hintId\n },\n })\n\n protected override labelSlot = new LightSlotController(this, {\n slotName: 'label',\n render: () => (this.label ? html`<label slot=\"label-internal\" for=${this.inputId}>${this.label}</label>` : nothing),\n syncLightDom: (element) => {\n if (!isLabel(element)) {\n console.warn(`NORD: Only <label> elements should be placed in radio's \"label\" slot`)\n }\n else {\n element.htmlFor = this.inputId\n }\n },\n })\n\n protected override errorSlot = new LightSlotController(this, {\n slotName: 'error',\n render: () => (this.error ? html`<div slot=\"error-internal\" id=${this.errorId}>${this.error}</div>` : nothing),\n syncLightDom: (element) => {\n element.id = this.hintId\n },\n })\n\n protected inputSlot = new LightDomController(this, {\n render: () => html`\n <input\n slot=\"input\"\n @blur=${this.handleBlur}\n @focus=${this.handleFocus}\n ${ref(this.focusableRef)}\n class=\"n-input\"\n id=${this.inputId}\n type=\"radio\"\n name=${cond(this.name)}\n .value=${cond(this.value)}\n .checked=${this.checked}\n ?disabled=${this.disabled}\n ?required=${this.required}\n aria-describedby=${cond(this.getDescribedBy())}\n aria-invalid=${cond(this.getInvalid())}\n form=${cond(this._formId)}\n />\n `,\n })\n\n protected override get formValue() {\n // opt out of formdata event, since radio button is in light dom\n return undefined\n }\n\n /**\n * Controls whether the checkbox is checked or not.\n */\n @property({ type: Boolean, reflect: true }) checked: boolean = false\n\n render() {\n const hint = html`\n <div class=\"n-caption n-hint\" ?hidden=${!this.hasHint}>\n <slot name=\"hint\"></slot>\n <slot name=\"hint-internal\"></slot>\n </div>\n `\n const error = html`\n <div class=\"n-caption n-error\" role=\"alert\" ?hidden=${!this.hasError}>\n <slot name=\"error\"></slot>\n <slot name=\"error-internal\"></slot>\n </div>\n `\n\n return html`\n <div class=\"n-flex\">\n <div class=\"n-input-container\" @change=${this.handleChange}>\n <slot name=\"input\"></slot>\n ${this.checked ? html`<div class=\"n-dot\"></div>` : nothing}\n </div>\n <div class=\"n-expand\">\n <div class=\"n-label-container\">\n ${wrapIf(\n this.hideLabel,\n () => html`\n <slot name=\"label\"></slot>\n <slot name=\"label-internal\"></slot>\n `,\n content => html`<nord-visually-hidden>${content}</nord-visually-hidden>`,\n )}\n ${this.isHintBelow ? nothing : hint}\n </div>\n ${this.isHintBelow ? nothing : error}\n </div>\n </div>\n ${this.isHintBelow ? error : nothing}\n ${this.isHintBelow ? hint : nothing}\n `\n }\n\n @observe('checked')\n protected handleCheckedChange(previousChecked: boolean) {\n // if this component was previous unchecked but is now checked,\n // then we need to uncheck any radios in the same group\n if (!previousChecked && this.checked) {\n this.uncheckSiblings()\n }\n }\n\n private uncheckSiblings() {\n const root = this.getRootNode() as Document | ShadowRoot\n\n root.querySelectorAll<Radio>(`nord-radio[name=\"${this.name}\"]`).forEach((radio) => {\n if (radio !== this && radio.checked) {\n radio.checked = false\n forceReflow(radio)\n }\n })\n }\n\n protected handleChange(e: Event): void {\n e.stopPropagation()\n const target = e.target as HTMLInputElement\n\n this.checked = target.checked\n super.handleChange(e)\n }\n\n private handleBlur = (e: Event) => {\n e.stopPropagation()\n this.dispatchEvent(new Event('blur', { bubbles: false, cancelable: true }))\n }\n\n private handleFocus = (e: Event) => {\n e.stopPropagation()\n this.dispatchEvent(new Event('focus', { bubbles: false, cancelable: true }))\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-radio': Radio\n }\n}\n","// some clever typing so that TS knows what happens if you pass true/false values\nexport function wrapIf<TInner, TWrapper>(\n condition: false,\n inner: () => TInner,\n wrapper: (inner: TInner) => TWrapper,\n): TInner\nexport function wrapIf<TInner, TWrapper>(\n condition: true,\n inner: () => TInner,\n wrapper: (inner: TInner) => TWrapper,\n): TWrapper\nexport function wrapIf<TInner, TWrapper>(\n condition: unknown,\n inner: () => TInner,\n wrapper: (inner: TInner) => TWrapper,\n): TInner | TWrapper\n\n/**\n * @returns if condition is truthy, return result of wrapper, passing result of inner as arg. if falsy, return result of inner\n */\nexport function wrapIf<TInner, TWrapper>(condition: any, inner: () => TInner, wrapper: (innards: TInner) => TWrapper) {\n return condition ? wrapper(inner()) : inner()\n}\n"],"names":["id","createId","suffix","Radio","SizeMixin","FormAssociatedMixin","InputMixin","FocusableMixin","LitElement","constructor","this","inputId","hintId","errorId","hintSlot","LightSlotController","slotName","render","hint","html","nothing","syncLightDom","element","labelSlot","label","localName","isLabel","console","warn","htmlFor","errorSlot","error","inputSlot","LightDomController","handleBlur","handleFocus","ref","focusableRef","cond","name","value","checked","disabled","required","getDescribedBy","getInvalid","_formId","e","stopPropagation","dispatchEvent","Event","bubbles","cancelable","formValue","hasHint","hasError","handleChange","condition","hideLabel","inner","wrapper","content","isHintBelow","handleCheckedChange","previousChecked","uncheckSiblings","getRootNode","querySelectorAll","forEach","radio","style","display","offsetHeight","forceReflow","target","super","styles","componentStyle","formFieldStyle","__decorate","property","type","Boolean","reflect","prototype","observe","customElement"],"mappings":"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"}
package/lib/Range.js CHANGED
@@ -1,2 +1,2 @@
1
- import{_ as r}from"./tslib.es6-CmLYFWVC.js";import{css as e,html as n,LitElement as a}from"lit";import{property as o,customElement as t}from"lit/decorators.js";import{classMap as i}from"lit/directives/class-map.js";import{ifDefined as s}from"lit/directives/if-defined.js";import{ref as l}from"lit/directives/ref.js";import{D as c}from"./DirectionController-ChvNGESZ.js";import{N as d}from"./events-Bv6wNHwJ.js";import{A as b}from"./AutocompleteMixin-D8eiOxvO.js";import{F as m}from"./FocusableMixin-BlQLNPdJ.js";import{F as g}from"./FormAssociatedMixin-DFL7yabe.js";import{I as u}from"./InputMixin-LetXsCyv.js";import{R as h,s as v}from"./TextField-BdEdZ0_b.js";import{s as p}from"./Component-DSU3Qp0O.js";import{s as _}from"./FormField--eLuhPue.js";import"./FormDataController-OUt5L5uC.js";import"./SlotController-Z6eG7LSZ.js";import"./EventController-BBOmvfLa.js";import"./VisuallyHidden.js";const f=e`:host{--_n-range-progress:0%;--_n-range-thumb-focus-ring:0 0 0 1px var(--n-color-accent);--_n-range-thumb-color:var(--n-color-text-on-accent);--_n-range-thumb-border-size:1px;--_n-range-thumb-border-color:var(--n-color-border-strong);--_n-range-gradient-direction:right;--_n-range-thumb-size:var(--n-range-thumb-size, 20px);--_n-range-track-color-active:var(--n-range-track-color-active, var(--n-color-accent));--_n-range-track-color-inactive:var(--n-range-track-color-inactive, var(--n-color-border-strong));--_n-range-track-size:var(--n-range-track-size, 3px)}.n-range{appearance:none;inline-size:100%;background:linear-gradient(to var(--_n-range-gradient-direction),var(--_n-range-track-color-active) 0,var(--_n-range-track-color-active) var(--_n-range-progress),var(--_n-range-track-color-inactive) var(--_n-range-progress));border-radius:var(--n-border-radius-s)}.n-range.is-rtl{--_n-range-gradient-direction:left}.n-range::-webkit-slider-runnable-track{inline-size:100%;block-size:var(--_n-range-track-size)}.n-range::-webkit-slider-thumb{block-size:var(--_n-range-thumb-size);inline-size:var(--_n-range-thumb-size);box-shadow:var(--n-box-shadow),var(--n-box-shadow);border-radius:var(--n-border-radius-circle);background:var(--_n-range-thumb-color);border:var(--_n-range-thumb-border-size) solid var(--_n-range-thumb-border-color);cursor:pointer;appearance:none;margin-block-start:calc(calc(var(--_n-range-thumb-size) - var(--_n-range-track-size))/ 2 * -1)}.n-range::-moz-range-track{border:var(--n-space-s) solid var(--n-color-surface);inline-size:100%;block-size:var(--_n-range-track-size)}.n-range::-moz-range-thumb{block-size:var(--_n-range-thumb-size);inline-size:var(--_n-range-thumb-size);box-shadow:var(--n-box-shadow);border-radius:var(--n-border-radius-circle);background:var(--_n-range-thumb-color);border:var(--_n-range-thumb-border-size) solid var(--_n-range-thumb-border-color);cursor:pointer;appearance:none;margin-block-start:calc(calc(var(--_n-range-thumb-size) - var(--_n-range-track-size))/ 2 * -1)}.n-label-container{margin-block-end:0;inline-size:100%}label{display:flex!important}.n-range-output{font-weight:var(--n-font-weight);color:var(--n-color-text-weaker);font-size:var(--n-font-size-m);margin-inline-start:auto}.n-range:focus{outline:0}.n-label-container:hover+.n-input-container .n-input:disabled,.n-range:disabled{opacity:.5}.n-range:disabled::-webkit-slider-thumb,.n-range[readonly]::-webkit-slider-thumb{--_n-range-thumb-color:var(--n-color-border);--_n-range-thumb-border-color:var(--n-color-border);box-shadow:none;cursor:default}.n-range:disabled::-moz-range-thumb,.n-range[readonly]::-moz-range-thumb{--_n-range-thumb-color:var(--n-color-border);--_n-range-thumb-border-color:var(--n-color-border);box-shadow:none;cursor:default}.n-range:focus::-webkit-slider-thumb{--_n-range-thumb-border-color:var(--n-color-accent);box-shadow:var(--_n-range-thumb-focus-ring)}.n-range:focus::-moz-range-thumb{--_n-range-thumb-border-color:var(--n-color-accent);box-shadow:var(--_n-range-thumb-focus-ring)}`;let z=class extends(g(b(h(u(m(a)))))){constructor(){super(...arguments),this.direction=new c(this),this.min=0,this.max=10,this.step=1,this.expand=!1}render(){const r=Number(this.value)||0,e=Math.max(0,(r-this.min)/(this.max-this.min));return n`<div class="n-input-container">${this.renderLabel(n`<span class="n-range-output" aria-hidden="true">${r}</span>`)} <input ${l(this.focusableRef)} id="${this.inputId}" type="range" class="${i({"n-range":!0,"is-rtl":this.direction.isRTL})}" name="${s(this.name)}" min="${this.min}" step="${this.step}" max="${this.max}" style="${`--_n-range-progress: ${100*e}%`}" ?disabled="${this.disabled}" ?required="${this.required}" ?readonly="${this.readonly}" .value="${this.value?this.value:"0"}" @input="${this.handleInput}" @change="${this.handleChange}" aria-describedby="${s(this.getDescribedBy())}" aria-invalid="${s(this.getInvalid())}"></div>${this.renderError()}`}handleInput(r){r.stopPropagation();const e=r.target;if(this.readonly)return r.preventDefault(),void(e.value=this.value);this.value=e.value,this.dispatchEvent(new d("input"))}};z.styles=[p,_,v,f],r([o({reflect:!0,type:Number})],z.prototype,"min",void 0),r([o({reflect:!0,type:Number})],z.prototype,"max",void 0),r([o({reflect:!0,type:Number})],z.prototype,"step",void 0),r([o({reflect:!0,type:Boolean})],z.prototype,"expand",void 0),z=r([t("nord-range")],z);var k=z;export{k as default};
1
+ import{_ as r}from"./tslib.es6-CmLYFWVC.js";import{css as e,html as n,nothing as a,LitElement as o}from"lit";import{property as t,customElement as i}from"lit/decorators.js";import{classMap as s}from"lit/directives/class-map.js";import{ifDefined as l}from"lit/directives/if-defined.js";import{ref as c}from"lit/directives/ref.js";import{D as d}from"./DirectionController-ChvNGESZ.js";import{N as b}from"./events-Bv6wNHwJ.js";import{A as m}from"./AutocompleteMixin-D8eiOxvO.js";import{F as g}from"./FocusableMixin-BlQLNPdJ.js";import{F as u}from"./FormAssociatedMixin-B4Qj-CQN.js";import{I as h}from"./InputMixin-LetXsCyv.js";import{R as v,s as p}from"./TextField-BdEdZ0_b.js";import{s as _}from"./Component-DSU3Qp0O.js";import{s as f}from"./FormField-BFaVzUjk.js";import"./FormDataController-OUt5L5uC.js";import"./SlotController-Z6eG7LSZ.js";import"./EventController-BBOmvfLa.js";import"./VisuallyHidden.js";const z=e`:host{--_n-range-progress:0%;--_n-range-thumb-focus-ring:0 0 0 1px var(--n-color-accent);--_n-range-thumb-color:var(--n-color-text-on-accent);--_n-range-thumb-border-size:1px;--_n-range-thumb-border-color:var(--n-color-border-strong);--_n-range-gradient-direction:right;--_n-range-thumb-size:var(--n-range-thumb-size, 20px);--_n-range-track-color-active:var(--n-range-track-color-active, var(--n-color-accent));--_n-range-track-color-inactive:var(--n-range-track-color-inactive, var(--n-color-border-strong));--_n-range-track-size:var(--n-range-track-size, 3px)}.n-range{appearance:none;inline-size:100%;background:linear-gradient(to var(--_n-range-gradient-direction),var(--_n-range-track-color-active) 0,var(--_n-range-track-color-active) var(--_n-range-progress),var(--_n-range-track-color-inactive) var(--_n-range-progress));border-radius:var(--n-border-radius-s)}.n-range.is-rtl{--_n-range-gradient-direction:left}.n-range::-webkit-slider-runnable-track{inline-size:100%;block-size:var(--_n-range-track-size)}.n-range::-webkit-slider-thumb{block-size:var(--_n-range-thumb-size);inline-size:var(--_n-range-thumb-size);box-shadow:var(--n-box-shadow),var(--n-box-shadow);border-radius:var(--n-border-radius-circle);background:var(--_n-range-thumb-color);border:var(--_n-range-thumb-border-size) solid var(--_n-range-thumb-border-color);cursor:pointer;appearance:none;margin-block-start:calc(calc(var(--_n-range-thumb-size) - var(--_n-range-track-size))/ 2 * -1)}.n-range::-moz-range-track{border:var(--n-space-s) solid var(--n-color-surface);inline-size:100%;block-size:var(--_n-range-track-size)}.n-range::-moz-range-thumb{block-size:var(--_n-range-thumb-size);inline-size:var(--_n-range-thumb-size);box-shadow:var(--n-box-shadow);border-radius:var(--n-border-radius-circle);background:var(--_n-range-thumb-color);border:var(--_n-range-thumb-border-size) solid var(--_n-range-thumb-border-color);cursor:pointer;appearance:none;margin-block-start:calc(calc(var(--_n-range-thumb-size) - var(--_n-range-track-size))/ 2 * -1)}.n-label-container{margin-block-end:0;inline-size:100%}label{display:flex!important}.n-range-output{font-weight:var(--n-font-weight);color:var(--n-color-text-weaker);font-size:var(--n-font-size-m);margin-inline-start:auto}.n-range:focus{outline:0}.n-label-container:hover+.n-input-container .n-input:disabled,.n-range:disabled{opacity:.5}.n-range:disabled::-webkit-slider-thumb,.n-range[readonly]::-webkit-slider-thumb{--_n-range-thumb-color:var(--n-color-border);--_n-range-thumb-border-color:var(--n-color-border);box-shadow:none;cursor:default}.n-range:disabled::-moz-range-thumb,.n-range[readonly]::-moz-range-thumb{--_n-range-thumb-color:var(--n-color-border);--_n-range-thumb-border-color:var(--n-color-border);box-shadow:none;cursor:default}.n-range:focus::-webkit-slider-thumb{--_n-range-thumb-border-color:var(--n-color-accent);box-shadow:var(--_n-range-thumb-focus-ring)}.n-range:focus::-moz-range-thumb{--_n-range-thumb-border-color:var(--n-color-accent);box-shadow:var(--_n-range-thumb-focus-ring)}`;let k=class extends(u(m(v(h(g(o)))))){constructor(){super(...arguments),this.direction=new d(this),this.min=0,this.max=10,this.step=1,this.expand=!1}render(){const r=Number(this.value)||0,e=Math.max(0,(r-this.min)/(this.max-this.min));return n`<div class="n-input-container">${this.renderLabel(n`<span class="n-range-output" aria-hidden="true">${r}</span>`)} <input ${c(this.focusableRef)} id="${this.inputId}" type="range" class="${s({"n-range":!0,"is-rtl":this.direction.isRTL})}" name="${l(this.name)}" min="${this.min}" step="${this.step}" max="${this.max}" style="${`--_n-range-progress: ${100*e}%`}" ?disabled="${this.disabled}" ?required="${this.required}" ?readonly="${this.readonly}" .value="${this.value?this.value:"0"}" @input="${this.handleInput}" @change="${this.handleChange}" aria-describedby="${l(this.getDescribedBy())}" aria-invalid="${l(this.getInvalid())}"></div>${this.renderError()} ${this.isHintBelow?this.renderHint():a}`}handleInput(r){r.stopPropagation();const e=r.target;if(this.readonly)return r.preventDefault(),void(e.value=this.value);this.value=e.value,this.dispatchEvent(new b("input"))}};k.styles=[_,f,p,z],r([t({reflect:!0,type:Number})],k.prototype,"min",void 0),r([t({reflect:!0,type:Number})],k.prototype,"max",void 0),r([t({reflect:!0,type:Number})],k.prototype,"step",void 0),r([t({reflect:!0,type:Boolean})],k.prototype,"expand",void 0),k=r([i("nord-range")],k);var x=k;export{x as default};
2
2
  //# sourceMappingURL=Range.js.map
package/lib/Range.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Range.js","sources":["../src/range/Range.ts"],"sourcesContent":["import { html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { ref } from 'lit/directives/ref.js'\nimport { DirectionController } from '../common/controllers/DirectionController.js'\n\nimport { NordEvent } from '../common/events.js'\nimport { AutocompleteMixin } from '../common/mixins/AutocompleteMixin.js'\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\nimport { ReadonlyMixin } from '../common/mixins/ReadonlyMixin.js'\n\nimport componentStyle from '../common/styles/Component.css'\nimport formFieldStyle from '../common/styles/FormField.css'\nimport textFieldStyle from '../common/styles/TextField.css'\nimport style from './Range.css'\n\n/**\n * Range input lets user specify a numeric value using a slider which\n * must be no less than a given value, and no more than another given value.\n *\n * @status ready\n * @category form\n * @slot label - Use when a label requires more than plain text.\n * @slot hint - Optional slot that holds hint text for the input.\n * @slot error - Optional slot that holds error text for the input.\n *\n * @cssprop [--n-range-thumb-size=20px] - Controls the size of the thumb.\n * @cssprop [--n-range-track-color-active=var(--n-color-accent)] - Controls the color of the portion of the track that represents the current value.\n * @cssprop [--n-range-track-color-inactive=var(--n-color-border-strong)] - Controls the color of the portion of the track that represents the remaining value.\n * @cssprop [--n-range-track-size=3px] - Controls the height of the track.\n */\n@customElement('nord-range')\nexport default class Range extends FormAssociatedMixin(\n AutocompleteMixin(ReadonlyMixin(InputMixin(FocusableMixin(LitElement)))),\n) {\n static styles = [componentStyle, formFieldStyle, textFieldStyle, style]\n\n private direction = new DirectionController(this)\n\n /**\n * Minimum value for the range slider.\n */\n @property({ reflect: true, type: Number }) min: number = 0\n\n /**\n * Maximum value for the range slider.\n */\n @property({ reflect: true, type: Number }) max: number = 10\n\n /**\n * Step amount for the range slider.\n */\n @property({ reflect: true, type: Number }) step: number = 1\n\n /**\n * Controls whether the input expands to fill the width of its container.\n */\n @property({ reflect: true, type: Boolean }) expand = false\n\n render() {\n const value = Number(this.value) || 0\n const percent = Math.max(0, (value - this.min) / (this.max - this.min))\n\n return html`\n <div class=\"n-input-container\">\n ${this.renderLabel(html`<span class=\"n-range-output\" aria-hidden=\"true\">${value}</span>`)}\n\n <input\n ${ref(this.focusableRef)}\n id=${this.inputId}\n type=\"range\"\n class=${classMap({\n 'n-range': true,\n 'is-rtl': this.direction.isRTL,\n })}\n name=${ifDefined(this.name)}\n min=${this.min}\n step=${this.step}\n max=${this.max}\n style=${`--_n-range-progress: ${percent * 100}%`}\n ?disabled=${this.disabled}\n ?required=${this.required}\n ?readonly=${this.readonly}\n .value=${this.value ? this.value : '0'}\n @input=${this.handleInput}\n @change=${this.handleChange}\n aria-describedby=${ifDefined(this.getDescribedBy())}\n aria-invalid=${ifDefined(this.getInvalid())}\n />\n </div>\n\n ${this.renderError()}\n `\n }\n\n protected handleInput(e: Event) {\n e.stopPropagation()\n const target = e.target as HTMLInputElement\n\n if (this.readonly) {\n e.preventDefault()\n target.value = this.value\n return\n }\n\n this.value = target.value\n\n /**\n * Fired as the user types into the input.\n */\n this.dispatchEvent(new NordEvent('input'))\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-range': Range\n }\n}\n"],"names":["Range","FormAssociatedMixin","AutocompleteMixin","ReadonlyMixin","InputMixin","FocusableMixin","LitElement","constructor","this","direction","DirectionController","min","max","step","expand","render","value","Number","percent","Math","html","renderLabel","ref","focusableRef","inputId","classMap","isRTL","ifDefined","name","disabled","required","readonly","handleInput","handleChange","getDescribedBy","getInvalid","renderError","e","stopPropagation","target","preventDefault","dispatchEvent","NordEvent","styles","componentStyle","formFieldStyle","textFieldStyle","style","__decorate","property","reflect","type","prototype","Boolean","customElement"],"mappings":"q2HAmCe,IAAMA,EAAN,cAAoBC,EACjCC,EAAkBC,EAAcC,EAAWC,EAAeC,QAD7C,WAAAC,uBAKLC,KAAAC,UAAY,IAAIC,EAAoBF,MAKDA,KAAGG,IAAW,EAKdH,KAAGI,IAAW,GAKdJ,KAAIK,KAAW,EAKdL,KAAMM,QAAG,CAuDtD,CArDC,MAAAC,GACE,MAAMC,EAAQC,OAAOT,KAAKQ,QAAU,EAC9BE,EAAUC,KAAKP,IAAI,GAAII,EAAQR,KAAKG,MAAQH,KAAKI,IAAMJ,KAAKG,MAElE,OAAOS,CAAI,kCAELZ,KAAKa,YAAYD,CAAI,mDAAmDJ,sBAGtEM,EAAId,KAAKe,qBACNf,KAAKgB,gCAEFC,EAAS,CACf,WAAW,EACX,SAAUjB,KAAKC,UAAUiB,kBAEpBC,EAAUnB,KAAKoB,eAChBpB,KAAKG,cACJH,KAAKK,cACNL,KAAKI,eACH,wBAAkC,IAAVM,oBACpBV,KAAKqB,wBACLrB,KAAKsB,wBACLtB,KAAKuB,qBACRvB,KAAKQ,MAAQR,KAAKQ,MAAQ,gBAC1BR,KAAKwB,yBACJxB,KAAKyB,mCACIN,EAAUnB,KAAK0B,oCACnBP,EAAUnB,KAAK2B,wBAIhC3B,KAAK4B,eAEV,CAES,WAAAJ,CAAYK,GACpBA,EAAEC,kBACF,MAAMC,EAASF,EAAEE,OAEjB,GAAI/B,KAAKuB,SAGP,OAFAM,EAAEG,sBACFD,EAAOvB,MAAQR,KAAKQ,OAItBR,KAAKQ,MAAQuB,EAAOvB,MAKpBR,KAAKiC,cAAc,IAAIC,EAAU,SAClC,GA5EM1C,EAAM2C,OAAG,CAACC,EAAgBC,EAAgBC,EAAgBC,GAOtBC,EAAA,CAA1CC,EAAS,CAAEC,SAAS,EAAMC,KAAMlC,UAAyBjB,EAAAoD,UAAA,WAAA,GAKfJ,EAAA,CAA1CC,EAAS,CAAEC,SAAS,EAAMC,KAAMlC,UAA0BjB,EAAAoD,UAAA,WAAA,GAKhBJ,EAAA,CAA1CC,EAAS,CAAEC,SAAS,EAAMC,KAAMlC,UAA0BjB,EAAAoD,UAAA,YAAA,GAKfJ,EAAA,CAA3CC,EAAS,CAAEC,SAAS,EAAMC,KAAME,WAAyBrD,EAAAoD,UAAA,cAAA,GAzBvCpD,EAAKgD,EAAA,CADzBM,EAAc,eACMtD,SAAAA"}
1
+ {"version":3,"file":"Range.js","sources":["../src/range/Range.ts"],"sourcesContent":["import { html, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { ref } from 'lit/directives/ref.js'\nimport { DirectionController } from '../common/controllers/DirectionController.js'\n\nimport { NordEvent } from '../common/events.js'\nimport { AutocompleteMixin } from '../common/mixins/AutocompleteMixin.js'\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\nimport { ReadonlyMixin } from '../common/mixins/ReadonlyMixin.js'\n\nimport componentStyle from '../common/styles/Component.css'\nimport formFieldStyle from '../common/styles/FormField.css'\nimport textFieldStyle from '../common/styles/TextField.css'\nimport style from './Range.css'\n\n/**\n * Range input lets user specify a numeric value using a slider which\n * must be no less than a given value, and no more than another given value.\n *\n * @status ready\n * @category form\n * @slot label - Use when a label requires more than plain text.\n * @slot hint - Optional slot that holds hint text for the input.\n * @slot error - Optional slot that holds error text for the input.\n *\n * @cssprop [--n-range-thumb-size=20px] - Controls the size of the thumb.\n * @cssprop [--n-range-track-color-active=var(--n-color-accent)] - Controls the color of the portion of the track that represents the current value.\n * @cssprop [--n-range-track-color-inactive=var(--n-color-border-strong)] - Controls the color of the portion of the track that represents the remaining value.\n * @cssprop [--n-range-track-size=3px] - Controls the height of the track.\n */\n@customElement('nord-range')\nexport default class Range extends FormAssociatedMixin(\n AutocompleteMixin(ReadonlyMixin(InputMixin(FocusableMixin(LitElement)))),\n) {\n static styles = [componentStyle, formFieldStyle, textFieldStyle, style]\n\n private direction = new DirectionController(this)\n\n /**\n * Minimum value for the range slider.\n */\n @property({ reflect: true, type: Number }) min: number = 0\n\n /**\n * Maximum value for the range slider.\n */\n @property({ reflect: true, type: Number }) max: number = 10\n\n /**\n * Step amount for the range slider.\n */\n @property({ reflect: true, type: Number }) step: number = 1\n\n /**\n * Controls whether the input expands to fill the width of its container.\n */\n @property({ reflect: true, type: Boolean }) expand = false\n\n render() {\n const value = Number(this.value) || 0\n const percent = Math.max(0, (value - this.min) / (this.max - this.min))\n\n return html`\n <div class=\"n-input-container\">\n ${this.renderLabel(html`<span class=\"n-range-output\" aria-hidden=\"true\">${value}</span>`)}\n\n <input\n ${ref(this.focusableRef)}\n id=${this.inputId}\n type=\"range\"\n class=${classMap({\n 'n-range': true,\n 'is-rtl': this.direction.isRTL,\n })}\n name=${ifDefined(this.name)}\n min=${this.min}\n step=${this.step}\n max=${this.max}\n style=${`--_n-range-progress: ${percent * 100}%`}\n ?disabled=${this.disabled}\n ?required=${this.required}\n ?readonly=${this.readonly}\n .value=${this.value ? this.value : '0'}\n @input=${this.handleInput}\n @change=${this.handleChange}\n aria-describedby=${ifDefined(this.getDescribedBy())}\n aria-invalid=${ifDefined(this.getInvalid())}\n />\n </div>\n\n ${this.renderError()}\n ${this.isHintBelow ? this.renderHint() : nothing}\n `\n }\n\n protected handleInput(e: Event) {\n e.stopPropagation()\n const target = e.target as HTMLInputElement\n\n if (this.readonly) {\n e.preventDefault()\n target.value = this.value\n return\n }\n\n this.value = target.value\n\n /**\n * Fired as the user types into the input.\n */\n this.dispatchEvent(new NordEvent('input'))\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-range': Range\n }\n}\n"],"names":["Range","FormAssociatedMixin","AutocompleteMixin","ReadonlyMixin","InputMixin","FocusableMixin","LitElement","constructor","this","direction","DirectionController","min","max","step","expand","render","value","Number","percent","Math","html","renderLabel","ref","focusableRef","inputId","classMap","isRTL","ifDefined","name","disabled","required","readonly","handleInput","handleChange","getDescribedBy","getInvalid","renderError","isHintBelow","renderHint","nothing","e","stopPropagation","target","preventDefault","dispatchEvent","NordEvent","styles","componentStyle","formFieldStyle","textFieldStyle","style","__decorate","property","reflect","type","prototype","Boolean","customElement"],"mappings":"k3HAmCe,IAAMA,EAAN,cAAoBC,EACjCC,EAAkBC,EAAcC,EAAWC,EAAeC,QAD7C,WAAAC,uBAKLC,KAAAC,UAAY,IAAIC,EAAoBF,MAKDA,KAAGG,IAAW,EAKdH,KAAGI,IAAW,GAKdJ,KAAIK,KAAW,EAKdL,KAAMM,QAAG,CAwDtD,CAtDC,MAAAC,GACE,MAAMC,EAAQC,OAAOT,KAAKQ,QAAU,EAC9BE,EAAUC,KAAKP,IAAI,GAAII,EAAQR,KAAKG,MAAQH,KAAKI,IAAMJ,KAAKG,MAElE,OAAOS,CAAI,kCAELZ,KAAKa,YAAYD,CAAI,mDAAmDJ,sBAGtEM,EAAId,KAAKe,qBACNf,KAAKgB,gCAEFC,EAAS,CACf,WAAW,EACX,SAAUjB,KAAKC,UAAUiB,kBAEpBC,EAAUnB,KAAKoB,eAChBpB,KAAKG,cACJH,KAAKK,cACNL,KAAKI,eACH,wBAAkC,IAAVM,oBACpBV,KAAKqB,wBACLrB,KAAKsB,wBACLtB,KAAKuB,qBACRvB,KAAKQ,MAAQR,KAAKQ,MAAQ,gBAC1BR,KAAKwB,yBACJxB,KAAKyB,mCACIN,EAAUnB,KAAK0B,oCACnBP,EAAUnB,KAAK2B,wBAIhC3B,KAAK4B,iBACL5B,KAAK6B,YAAc7B,KAAK8B,aAAeC,GAE5C,CAES,WAAAP,CAAYQ,GACpBA,EAAEC,kBACF,MAAMC,EAASF,EAAEE,OAEjB,GAAIlC,KAAKuB,SAGP,OAFAS,EAAEG,sBACFD,EAAO1B,MAAQR,KAAKQ,OAItBR,KAAKQ,MAAQ0B,EAAO1B,MAKpBR,KAAKoC,cAAc,IAAIC,EAAU,SAClC,GA7EM7C,EAAM8C,OAAG,CAACC,EAAgBC,EAAgBC,EAAgBC,GAOtBC,EAAA,CAA1CC,EAAS,CAAEC,SAAS,EAAMC,KAAMrC,UAAyBjB,EAAAuD,UAAA,WAAA,GAKfJ,EAAA,CAA1CC,EAAS,CAAEC,SAAS,EAAMC,KAAMrC,UAA0BjB,EAAAuD,UAAA,WAAA,GAKhBJ,EAAA,CAA1CC,EAAS,CAAEC,SAAS,EAAMC,KAAMrC,UAA0BjB,EAAAuD,UAAA,YAAA,GAKfJ,EAAA,CAA3CC,EAAS,CAAEC,SAAS,EAAMC,KAAME,WAAyBxD,EAAAuD,UAAA,cAAA,GAzBvCvD,EAAKmD,EAAA,CADzBM,EAAc,eACMzD,SAAAA"}
package/lib/Select.js CHANGED
@@ -1,2 +1,2 @@
1
- import{_ as t}from"./tslib.es6-CmLYFWVC.js";import{css as e,html as o,isServer as n,LitElement as r}from"lit";import{property as i,customElement as s}from"lit/decorators.js";import{ifDefined as l}from"lit/directives/if-defined.js";import{ref as a}from"lit/directives/ref.js";import{S as c}from"./SlotController-Z6eG7LSZ.js";import{A as d}from"./AutocompleteMixin-D8eiOxvO.js";import{F as p}from"./FocusableMixin-BlQLNPdJ.js";import{F as u}from"./FormAssociatedMixin-DFL7yabe.js";import{I as b}from"./InputMixin-LetXsCyv.js";import{S as v}from"./SizeMixin-CU9cLbLC.js";import{s as h}from"./Component-DSU3Qp0O.js";import{s as m}from"./FormField--eLuhPue.js";import f from"./Icon.js";import"./Button.js";import"./EventController-BBOmvfLa.js";import"./FormDataController-OUt5L5uC.js";import"./events-Bv6wNHwJ.js";import"./VisuallyHidden.js";import"lit/directives/unsafe-html.js";import"./observe-D0n0zOfU.js";import"./cond-CI1KbneT.js";import"./IconManager.js";import"./LightDomController-DIwtVelV.js";import"./Spinner.js";var x=Object.freeze({__proto__:null,default:'<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="m14.0864 12.0402 1.8138 1.8137-4.7724 4.7724c-.2573.2573-.5789.373-.9133.373-.33447 0-.65606-.1286-.91333-.373l-4.77238-4.7724 1.81377-1.8137 3.85904 3.859 3.8591-3.859zm-3.859-7.93687 3.859 3.85907 1.8138-1.81376-4.7724-4.77238c-.5017-.50168-1.31208-.50168-1.81376 0l-4.77238 4.77238 1.81376 1.81376 3.85908-3.85907z" fill="currentColor"/></svg>',tags:"nordicon small interface dropdown select arrow up down caret triangle chevron",title:"interface-dropdown-small"});const j=e`:host{--_n-select-inline-size:var(--n-select-inline-size, fit-content);--_n-select-block-size:var(--n-select-block-size, var(--n-space-xl))}.n-select-container{position:relative;inline-size:fit-content}:host([expand]){inline-size:100%}:host([expand]) .n-select-container{inline-size:100%}select{appearance:none;position:absolute;font-size:var(--n-font-size-m);font-family:var(--n-font-family);color:var(--n-color-text);inline-size:100%;opacity:.0001;cursor:pointer;background:0 0;border:0;block-size:var(--_n-select-block-size);inset-block-end:0;inset-inline-start:0;z-index:var(--n-index-default)}option{color:initial}nord-button{--n-button-text-align:start}nord-button:not([expand]){--_n-button-inline-size:var(--_n-select-inline-size)}nord-icon{color:var(--n-color-icon)}.n-label-container:hover+.n-select-container nord-button,select:hover+nord-button{--_n-button-border-color:var(--n-button-border-color, var(--n-color-border-hover));--_n-button-background-color:var(--n-button-background-color, var(--n-color-button-hover))}select:focus+nord-button{--n-button-border-color:var(--n-color-accent);--n-button-box-shadow:0 0 0 1px var(--n-button-border-color)}:host([disabled]){cursor:auto;pointer-events:none}:host([disabled]) nord-button{--n-input-border-color:var(--n-color-active);--_n-button-color:var(--n-color-text-weakest);--_n-button-background-color:var(--n-color-active);--_n-button-opacity:1}:host([disabled]) nord-icon{color:var(--n-color-text-weakest)}::slotted(:not([slot])){display:none}select[aria-invalid=true]+nord-button{--n-button-border-color:var(--n-color-status-danger)}`;f.registerIcon(x);let g=class extends(v(u(d(b(p(r)))))){constructor(){super(...arguments),this.defaultSlot=new c(this),this.inputId="select",this.expand=!1}get formValue(){return this.value||void 0}firstUpdated(){this.setupOptionObserver()}connectedCallback(){super.connectedCallback(),this.hasUpdated&&!this.optionObserver&&this.setupOptionObserver()}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this.optionObserver)||void 0===t||t.disconnect(),this.optionObserver=void 0}setupOptionObserver(){this.optionObserver||(this.optionObserver=new MutationObserver((()=>this.requestUpdate())),this.optionObserver.observe(this,{subtree:!0,childList:!0,characterData:!0}))}render(){const t=this.options,e=this.getButtonText(t);return o`<slot></slot>${this.renderLabel()}<div class="n-select-container"><select ${a(this.focusableRef)} id="${this.inputId}" ?disabled="${this.disabled}" ?required="${this.required}" name="${l(this.name)}" @change="${this.handleChange}" @input="${this.handleInput}" aria-describedby="${l(this.getDescribedBy())}" aria-invalid="${l(this.getInvalid())}" autocomplete="${this.autocomplete}">${this.placeholder&&o`<option value="" disabled="disabled" ?selected="${!this.value}">${this.placeholder}</option>`} ${t.map((t=>this.renderOption(t)))}</select><nord-button size="${this.size}" ?disabled="${this.disabled}" ?expand="${this.expand}" type="button" inert><slot slot="start" name="icon"></slot>${e}<nord-icon slot="end" name="interface-dropdown-small"></nord-icon></nord-button></div>${this.renderError()}`}get options(){return n?[]:Array.from(this.querySelectorAll("option"))}getButtonText(t){const e=t.find((t=>t.value===this.value.toString()));return e?e.text:this.placeholder?this.placeholder:t[0]?t[0].text:""}renderOption(t){return o`<option value="${l(t.value)}" ?disabled="${t.disabled}" .selected="${t.value===this.value.toString()}">${t.text}</option>`}};g.styles=[h,m,j],t([i({reflect:!0,type:Boolean})],g.prototype,"expand",void 0),g=t([s("nord-select")],g);var $=g;export{$ as default};
1
+ import{_ as t}from"./tslib.es6-CmLYFWVC.js";import{css as e,html as o,nothing as n,isServer as r,LitElement as i}from"lit";import{property as s,customElement as l}from"lit/decorators.js";import{ifDefined as a}from"lit/directives/if-defined.js";import{ref as c}from"lit/directives/ref.js";import{S as d}from"./SlotController-Z6eG7LSZ.js";import{A as p}from"./AutocompleteMixin-D8eiOxvO.js";import{F as u}from"./FocusableMixin-BlQLNPdJ.js";import{F as b}from"./FormAssociatedMixin-B4Qj-CQN.js";import{I as v}from"./InputMixin-LetXsCyv.js";import{S as h}from"./SizeMixin-CU9cLbLC.js";import{s as m}from"./Component-DSU3Qp0O.js";import{s as f}from"./FormField-BFaVzUjk.js";import x from"./Icon.js";import"./Button.js";import"./EventController-BBOmvfLa.js";import"./FormDataController-OUt5L5uC.js";import"./events-Bv6wNHwJ.js";import"./VisuallyHidden.js";import"lit/directives/unsafe-html.js";import"./observe-D0n0zOfU.js";import"./cond-CI1KbneT.js";import"./IconManager.js";import"./LightDomController-DIwtVelV.js";import"./Spinner.js";var j=Object.freeze({__proto__:null,default:'<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="m14.0864 12.0402 1.8138 1.8137-4.7724 4.7724c-.2573.2573-.5789.373-.9133.373-.33447 0-.65606-.1286-.91333-.373l-4.77238-4.7724 1.81377-1.8137 3.85904 3.859 3.8591-3.859zm-3.859-7.93687 3.859 3.85907 1.8138-1.81376-4.7724-4.77238c-.5017-.50168-1.31208-.50168-1.81376 0l-4.77238 4.77238 1.81376 1.81376 3.85908-3.85907z" fill="currentColor"/></svg>',tags:"nordicon small interface dropdown select arrow up down caret triangle chevron",title:"interface-dropdown-small"});const g=e`:host{--_n-select-inline-size:var(--n-select-inline-size, fit-content);--_n-select-block-size:var(--n-select-block-size, var(--n-space-xl))}.n-select-container{position:relative;inline-size:fit-content}:host([expand]){inline-size:100%}:host([expand]) .n-select-container{inline-size:100%}select{appearance:none;position:absolute;font-size:var(--n-font-size-m);font-family:var(--n-font-family);color:var(--n-color-text);inline-size:100%;opacity:.0001;cursor:pointer;background:0 0;border:0;block-size:var(--_n-select-block-size);inset-block-end:0;inset-inline-start:0;z-index:var(--n-index-default)}option{color:initial}nord-button{--n-button-text-align:start}nord-button:not([expand]){--_n-button-inline-size:var(--_n-select-inline-size)}nord-icon{color:var(--n-color-icon)}.n-label-container:hover+.n-select-container nord-button,select:hover+nord-button{--_n-button-border-color:var(--n-button-border-color, var(--n-color-border-hover));--_n-button-background-color:var(--n-button-background-color, var(--n-color-button-hover))}select:focus+nord-button{--n-button-border-color:var(--n-color-accent);--n-button-box-shadow:0 0 0 1px var(--n-button-border-color)}:host([disabled]){cursor:auto;pointer-events:none}:host([disabled]) nord-button{--n-input-border-color:var(--n-color-active);--_n-button-color:var(--n-color-text-weakest);--_n-button-background-color:var(--n-color-active);--_n-button-opacity:1}:host([disabled]) nord-icon{color:var(--n-color-text-weakest)}::slotted(:not([slot])){display:none}select[aria-invalid=true]+nord-button{--n-button-border-color:var(--n-color-status-danger)}`;x.registerIcon(j);let $=class extends(h(b(p(v(u(i)))))){constructor(){super(...arguments),this.defaultSlot=new d(this),this.inputId="select",this.expand=!1}get formValue(){return this.value||void 0}firstUpdated(){this.setupOptionObserver()}connectedCallback(){super.connectedCallback(),this.hasUpdated&&!this.optionObserver&&this.setupOptionObserver()}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this.optionObserver)||void 0===t||t.disconnect(),this.optionObserver=void 0}setupOptionObserver(){this.optionObserver||(this.optionObserver=new MutationObserver((()=>this.requestUpdate())),this.optionObserver.observe(this,{subtree:!0,childList:!0,characterData:!0}))}render(){const t=this.options,e=this.getButtonText(t);return o`<slot></slot>${this.renderLabel()}<div class="n-select-container"><select ${c(this.focusableRef)} id="${this.inputId}" ?disabled="${this.disabled}" ?required="${this.required}" name="${a(this.name)}" @change="${this.handleChange}" @input="${this.handleInput}" aria-describedby="${a(this.getDescribedBy())}" aria-invalid="${a(this.getInvalid())}" autocomplete="${this.autocomplete}">${this.placeholder&&o`<option value="" disabled="disabled" ?selected="${!this.value}">${this.placeholder}</option>`} ${t.map((t=>this.renderOption(t)))}</select><nord-button size="${this.size}" ?disabled="${this.disabled}" ?expand="${this.expand}" type="button" inert><slot slot="start" name="icon"></slot>${e}<nord-icon slot="end" name="interface-dropdown-small"></nord-icon></nord-button></div>${this.renderError()} ${this.isHintBelow?this.renderHint():n}`}get options(){return r?[]:Array.from(this.querySelectorAll("option"))}getButtonText(t){const e=t.find((t=>t.value===this.value.toString()));return e?e.text:this.placeholder?this.placeholder:t[0]?t[0].text:""}renderOption(t){return o`<option value="${a(t.value)}" ?disabled="${t.disabled}" .selected="${t.value===this.value.toString()}">${t.text}</option>`}};$.styles=[m,f,g],t([s({reflect:!0,type:Boolean})],$.prototype,"expand",void 0),$=t([l("nord-select")],$);var z=$;export{z as default};
2
2
  //# sourceMappingURL=Select.js.map
package/lib/Select.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Select.js","sources":["../../icons/lib/assets/interface-dropdown-small.js","../src/select/Select.ts"],"sourcesContent":["export default '<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m14.0864 12.0402 1.8138 1.8137-4.7724 4.7724c-.2573.2573-.5789.373-.9133.373-.33447 0-.65606-.1286-.91333-.373l-4.77238-4.7724 1.81377-1.8137 3.85904 3.859 3.8591-3.859zm-3.859-7.93687 3.859 3.85907 1.8138-1.81376-4.7724-4.77238c-.5017-.50168-1.31208-.50168-1.81376 0l-4.77238 4.77238 1.81376 1.81376 3.85908-3.85907z\" fill=\"currentColor\"/></svg>';\nexport const title = \"interface-dropdown-small\";\nexport const tags =\n \"nordicon small interface dropdown select arrow up down caret triangle chevron\";\n","import * as dropdownIcon from '@nordhealth/icons/lib/assets/interface-dropdown-small.js'\nimport { html, isServer, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { ref } from 'lit/directives/ref.js'\n\nimport { SlotController } from '../common/controllers/SlotController.js'\nimport { AutocompleteMixin } from '../common/mixins/AutocompleteMixin.js'\n\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\nimport { SizeMixin } from '../common/mixins/SizeMixin.js'\nimport componentStyle from '../common/styles/Component.css'\n\nimport formFieldStyle from '../common/styles/FormField.css'\nimport Icon from '../icon/Icon.js'\nimport style from './Select.css'\nimport '../button/Button.js'\n\nIcon.registerIcon(dropdownIcon)\n\n/**\n * Select lets users choose one option from an options menu.\n * Consider using select when you have 5 or more options to choose from.\n *\n * @status ready\n * @category form\n * @slot - Default slot for holding <option> elements.\n * @slot label - Use when a label requires more than plain text.\n * @slot hint - Use when a hint requires more than plain text.\n * @slot error - Optional slot that holds error text for the input.\n * @slot icon - Used to place an icon at the start of select.\n *\n * @cssprop [--n-select-block-size=var(--n-space-xl)] - Controls the block size, or height, of the select using our [spacing tokens](/tokens/#space).\n * @cssprop [--n-select-inline-size=fit-content] - Controls the inline size, or width, of the select.\n * @cssprop [--n-label-color=var(--n-color-text)] - Controls the text color of the label, using our [color tokens](/tokens/#color).\n */\n@customElement('nord-select')\nexport default class Select extends SizeMixin(\n FormAssociatedMixin(AutocompleteMixin(InputMixin(FocusableMixin(LitElement)))),\n) {\n static styles = [componentStyle, formFieldStyle, style]\n\n protected override get formValue() {\n return this.value || undefined\n }\n\n private defaultSlot = new SlotController(this)\n private optionObserver?: MutationObserver\n\n protected inputId = 'select'\n\n firstUpdated() {\n this.setupOptionObserver()\n }\n\n connectedCallback() {\n super.connectedCallback()\n // Re-setup observer after reconnection (firstUpdated only runs once per instance)\n if (this.hasUpdated && !this.optionObserver) {\n this.setupOptionObserver()\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n // Clean up observer to prevent memory leaks\n this.optionObserver?.disconnect()\n this.optionObserver = undefined\n }\n\n private setupOptionObserver() {\n // Avoid creating multiple observers\n if (this.optionObserver) {\n return\n }\n\n // Set up observer to watch for changes to slotted option content\n this.optionObserver = new MutationObserver(() => this.requestUpdate())\n this.optionObserver.observe(this, {\n subtree: true,\n childList: true,\n characterData: true,\n })\n }\n\n /**\n * Controls whether the select expands to fill the width of its container.\n */\n @property({ reflect: true, type: Boolean }) expand = false\n\n render() {\n const slottedOptions = this.options\n const buttonText = this.getButtonText(slottedOptions)\n\n return html`\n <slot></slot>\n ${this.renderLabel()}\n\n <div class=\"n-select-container\">\n <select\n ${ref(this.focusableRef)}\n id=${this.inputId}\n ?disabled=${this.disabled}\n ?required=${this.required}\n name=${ifDefined(this.name)}\n @change=${this.handleChange}\n @input=${this.handleInput}\n aria-describedby=${ifDefined(this.getDescribedBy())}\n aria-invalid=${ifDefined(this.getInvalid())}\n autocomplete=${this.autocomplete as any}\n >\n ${this.placeholder && html`<option value=\"\" disabled ?selected=${!this.value}>${this.placeholder}</option>`}\n ${slottedOptions.map(option => this.renderOption(option))}\n </select>\n\n <nord-button size=${this.size} ?disabled=${this.disabled} ?expand=${this.expand} type=\"button\" inert>\n <slot slot=\"start\" name=\"icon\"></slot>\n ${buttonText}\n <nord-icon slot=\"end\" name=\"interface-dropdown-small\"></nord-icon>\n </nord-button>\n </div>\n\n ${this.renderError()}\n `\n }\n\n private get options() {\n if (isServer) {\n return []\n }\n\n return Array.from(this.querySelectorAll('option'))\n }\n\n private getButtonText(options: HTMLOptionElement[]): string {\n const selected = options.find(option => option.value === this.value.toString())\n\n if (selected) {\n return selected.text\n }\n\n if (this.placeholder) {\n return this.placeholder\n }\n\n if (options[0]) {\n return options[0].text\n }\n\n return ''\n }\n\n private renderOption(option: HTMLOptionElement) {\n return html`\n <option\n value=${ifDefined(option.value)}\n ?disabled=${option.disabled}\n .selected=${option.value === this.value.toString()}\n >\n ${option.text}\n </option>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-select': Select\n }\n}\n"],"names":["Icon","registerIcon","dropdownIcon","Select","SizeMixin","FormAssociatedMixin","AutocompleteMixin","InputMixin","FocusableMixin","LitElement","constructor","this","defaultSlot","SlotController","inputId","expand","formValue","value","undefined","firstUpdated","setupOptionObserver","connectedCallback","super","hasUpdated","optionObserver","disconnectedCallback","_a","disconnect","MutationObserver","requestUpdate","observe","subtree","childList","characterData","render","slottedOptions","options","buttonText","getButtonText","html","renderLabel","ref","focusableRef","disabled","required","ifDefined","name","handleChange","handleInput","getDescribedBy","getInvalid","autocomplete","placeholder","map","option","renderOption","size","renderError","isServer","Array","from","querySelectorAll","selected","find","toString","text","styles","componentStyle","formFieldStyle","style","__decorate","property","reflect","type","Boolean","prototype","customElement"],"mappings":"uiCAAe,uaAGb,sFAFmB,qmDCmBrBA,EAAKC,aAAaC,GAmBH,IAAMC,EAAN,cAAqBC,EAClCC,EAAoBC,EAAkBC,EAAWC,EAAeC,QADnD,WAAAC,uBASLC,KAAAC,YAAc,IAAIC,EAAeF,MAG/BA,KAAOG,QAAG,SAuCwBH,KAAMI,QAAG,CA2EtD,CAzHC,aAAuBC,GACrB,OAAOL,KAAKM,YAASC,CACtB,CAOD,YAAAC,GACER,KAAKS,qBACN,CAED,iBAAAC,GACEC,MAAMD,oBAEFV,KAAKY,aAAeZ,KAAKa,gBAC3Bb,KAAKS,qBAER,CAED,oBAAAK,SACEH,MAAMG,uBAEe,QAArBC,EAAAf,KAAKa,sBAAgB,IAAAE,GAAAA,EAAAC,aACrBhB,KAAKa,oBAAiBN,CACvB,CAEO,mBAAAE,GAEFT,KAAKa,iBAKTb,KAAKa,eAAiB,IAAII,kBAAiB,IAAMjB,KAAKkB,kBACtDlB,KAAKa,eAAeM,QAAQnB,KAAM,CAChCoB,SAAS,EACTC,WAAW,EACXC,eAAe,IAElB,CAOD,MAAAC,GACE,MAAMC,EAAiBxB,KAAKyB,QACtBC,EAAa1B,KAAK2B,cAAcH,GAEtC,OAAOI,CAAI,gBAEP5B,KAAK6B,wDAIDC,EAAI9B,KAAK+B,qBACN/B,KAAKG,uBACEH,KAAKgC,wBACLhC,KAAKiC,mBACVC,EAAUlC,KAAKmC,mBACZnC,KAAKoC,yBACNpC,KAAKqC,kCACKH,EAAUlC,KAAKsC,oCACnBJ,EAAUlC,KAAKuC,gCACfvC,KAAKwC,iBAElBxC,KAAKyC,aAAeb,CAAI,oDAAwC5B,KAAKM,UAASN,KAAKyC,0BACnFjB,EAAekB,KAAIC,GAAU3C,KAAK4C,aAAaD,mCAG/B3C,KAAK6C,oBAAkB7C,KAAKgC,sBAAoBhC,KAAKI,qEAErEsB,0FAKJ1B,KAAK8C,eAEV,CAED,WAAYrB,GACV,OAAIsB,EACK,GAGFC,MAAMC,KAAKjD,KAAKkD,iBAAiB,UACzC,CAEO,aAAAvB,CAAcF,GACpB,MAAM0B,EAAW1B,EAAQ2B,MAAKT,GAAUA,EAAOrC,QAAUN,KAAKM,MAAM+C,aAEpE,OAAIF,EACKA,EAASG,KAGdtD,KAAKyC,YACAzC,KAAKyC,YAGVhB,EAAQ,GACHA,EAAQ,GAAG6B,KAGb,EACR,CAEO,YAAAV,CAAaD,GACnB,OAAOf,CAAI,kBAECM,EAAUS,EAAOrC,sBACbqC,EAAOX,wBACPW,EAAOrC,QAAUN,KAAKM,MAAM+C,eAEtCV,EAAOW,eAGd,GA1HM9D,EAAM+D,OAAG,CAACC,EAAgBC,EAAgBC,GAgDLC,EAAA,CAA3CC,EAAS,CAAEC,SAAS,EAAMC,KAAMC,WAAyBvE,EAAAwE,UAAA,cAAA,GAnDvCxE,EAAMmE,EAAA,CAD1BM,EAAc,gBACMzE,SAAAA"}
1
+ {"version":3,"file":"Select.js","sources":["../../icons/lib/assets/interface-dropdown-small.js","../src/select/Select.ts"],"sourcesContent":["export default '<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m14.0864 12.0402 1.8138 1.8137-4.7724 4.7724c-.2573.2573-.5789.373-.9133.373-.33447 0-.65606-.1286-.91333-.373l-4.77238-4.7724 1.81377-1.8137 3.85904 3.859 3.8591-3.859zm-3.859-7.93687 3.859 3.85907 1.8138-1.81376-4.7724-4.77238c-.5017-.50168-1.31208-.50168-1.81376 0l-4.77238 4.77238 1.81376 1.81376 3.85908-3.85907z\" fill=\"currentColor\"/></svg>';\nexport const title = \"interface-dropdown-small\";\nexport const tags =\n \"nordicon small interface dropdown select arrow up down caret triangle chevron\";\n","import * as dropdownIcon from '@nordhealth/icons/lib/assets/interface-dropdown-small.js'\nimport { html, isServer, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { ref } from 'lit/directives/ref.js'\n\nimport { SlotController } from '../common/controllers/SlotController.js'\nimport { AutocompleteMixin } from '../common/mixins/AutocompleteMixin.js'\n\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\nimport { SizeMixin } from '../common/mixins/SizeMixin.js'\nimport componentStyle from '../common/styles/Component.css'\n\nimport formFieldStyle from '../common/styles/FormField.css'\nimport Icon from '../icon/Icon.js'\nimport style from './Select.css'\nimport '../button/Button.js'\n\nIcon.registerIcon(dropdownIcon)\n\n/**\n * Select lets users choose one option from an options menu.\n * Consider using select when you have 5 or more options to choose from.\n *\n * @status ready\n * @category form\n * @slot - Default slot for holding <option> elements.\n * @slot label - Use when a label requires more than plain text.\n * @slot hint - Use when a hint requires more than plain text.\n * @slot error - Optional slot that holds error text for the input.\n * @slot icon - Used to place an icon at the start of select.\n *\n * @cssprop [--n-select-block-size=var(--n-space-xl)] - Controls the block size, or height, of the select using our [spacing tokens](/tokens/#space).\n * @cssprop [--n-select-inline-size=fit-content] - Controls the inline size, or width, of the select.\n * @cssprop [--n-label-color=var(--n-color-text)] - Controls the text color of the label, using our [color tokens](/tokens/#color).\n */\n@customElement('nord-select')\nexport default class Select extends SizeMixin(\n FormAssociatedMixin(AutocompleteMixin(InputMixin(FocusableMixin(LitElement)))),\n) {\n static styles = [componentStyle, formFieldStyle, style]\n\n protected override get formValue() {\n return this.value || undefined\n }\n\n private defaultSlot = new SlotController(this)\n private optionObserver?: MutationObserver\n\n protected inputId = 'select'\n\n firstUpdated() {\n this.setupOptionObserver()\n }\n\n connectedCallback() {\n super.connectedCallback()\n // Re-setup observer after reconnection (firstUpdated only runs once per instance)\n if (this.hasUpdated && !this.optionObserver) {\n this.setupOptionObserver()\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n // Clean up observer to prevent memory leaks\n this.optionObserver?.disconnect()\n this.optionObserver = undefined\n }\n\n private setupOptionObserver() {\n // Avoid creating multiple observers\n if (this.optionObserver) {\n return\n }\n\n // Set up observer to watch for changes to slotted option content\n this.optionObserver = new MutationObserver(() => this.requestUpdate())\n this.optionObserver.observe(this, {\n subtree: true,\n childList: true,\n characterData: true,\n })\n }\n\n /**\n * Controls whether the select expands to fill the width of its container.\n */\n @property({ reflect: true, type: Boolean }) expand = false\n\n render() {\n const slottedOptions = this.options\n const buttonText = this.getButtonText(slottedOptions)\n\n return html`\n <slot></slot>\n ${this.renderLabel()}\n\n <div class=\"n-select-container\">\n <select\n ${ref(this.focusableRef)}\n id=${this.inputId}\n ?disabled=${this.disabled}\n ?required=${this.required}\n name=${ifDefined(this.name)}\n @change=${this.handleChange}\n @input=${this.handleInput}\n aria-describedby=${ifDefined(this.getDescribedBy())}\n aria-invalid=${ifDefined(this.getInvalid())}\n autocomplete=${this.autocomplete as any}\n >\n ${this.placeholder && html`<option value=\"\" disabled ?selected=${!this.value}>${this.placeholder}</option>`}\n ${slottedOptions.map(option => this.renderOption(option))}\n </select>\n\n <nord-button size=${this.size} ?disabled=${this.disabled} ?expand=${this.expand} type=\"button\" inert>\n <slot slot=\"start\" name=\"icon\"></slot>\n ${buttonText}\n <nord-icon slot=\"end\" name=\"interface-dropdown-small\"></nord-icon>\n </nord-button>\n </div>\n\n ${this.renderError()}\n ${this.isHintBelow ? this.renderHint() : nothing}\n `\n }\n\n private get options() {\n if (isServer) {\n return []\n }\n\n return Array.from(this.querySelectorAll('option'))\n }\n\n private getButtonText(options: HTMLOptionElement[]): string {\n const selected = options.find(option => option.value === this.value.toString())\n\n if (selected) {\n return selected.text\n }\n\n if (this.placeholder) {\n return this.placeholder\n }\n\n if (options[0]) {\n return options[0].text\n }\n\n return ''\n }\n\n private renderOption(option: HTMLOptionElement) {\n return html`\n <option\n value=${ifDefined(option.value)}\n ?disabled=${option.disabled}\n .selected=${option.value === this.value.toString()}\n >\n ${option.text}\n </option>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-select': Select\n }\n}\n"],"names":["Icon","registerIcon","dropdownIcon","Select","SizeMixin","FormAssociatedMixin","AutocompleteMixin","InputMixin","FocusableMixin","LitElement","constructor","this","defaultSlot","SlotController","inputId","expand","formValue","value","undefined","firstUpdated","setupOptionObserver","connectedCallback","super","hasUpdated","optionObserver","disconnectedCallback","_a","disconnect","MutationObserver","requestUpdate","observe","subtree","childList","characterData","render","slottedOptions","options","buttonText","getButtonText","html","renderLabel","ref","focusableRef","disabled","required","ifDefined","name","handleChange","handleInput","getDescribedBy","getInvalid","autocomplete","placeholder","map","option","renderOption","size","renderError","isHintBelow","renderHint","nothing","isServer","Array","from","querySelectorAll","selected","find","toString","text","styles","componentStyle","formFieldStyle","style","__decorate","property","reflect","type","Boolean","prototype","customElement"],"mappings":"ojCAAe,uaAGb,sFAFmB,qmDCmBrBA,EAAKC,aAAaC,GAmBH,IAAMC,EAAN,cAAqBC,EAClCC,EAAoBC,EAAkBC,EAAWC,EAAeC,QADnD,WAAAC,uBASLC,KAAAC,YAAc,IAAIC,EAAeF,MAG/BA,KAAOG,QAAG,SAuCwBH,KAAMI,QAAG,CA4EtD,CA1HC,aAAuBC,GACrB,OAAOL,KAAKM,YAASC,CACtB,CAOD,YAAAC,GACER,KAAKS,qBACN,CAED,iBAAAC,GACEC,MAAMD,oBAEFV,KAAKY,aAAeZ,KAAKa,gBAC3Bb,KAAKS,qBAER,CAED,oBAAAK,SACEH,MAAMG,uBAEe,QAArBC,EAAAf,KAAKa,sBAAgB,IAAAE,GAAAA,EAAAC,aACrBhB,KAAKa,oBAAiBN,CACvB,CAEO,mBAAAE,GAEFT,KAAKa,iBAKTb,KAAKa,eAAiB,IAAII,kBAAiB,IAAMjB,KAAKkB,kBACtDlB,KAAKa,eAAeM,QAAQnB,KAAM,CAChCoB,SAAS,EACTC,WAAW,EACXC,eAAe,IAElB,CAOD,MAAAC,GACE,MAAMC,EAAiBxB,KAAKyB,QACtBC,EAAa1B,KAAK2B,cAAcH,GAEtC,OAAOI,CAAI,gBAEP5B,KAAK6B,wDAIDC,EAAI9B,KAAK+B,qBACN/B,KAAKG,uBACEH,KAAKgC,wBACLhC,KAAKiC,mBACVC,EAAUlC,KAAKmC,mBACZnC,KAAKoC,yBACNpC,KAAKqC,kCACKH,EAAUlC,KAAKsC,oCACnBJ,EAAUlC,KAAKuC,gCACfvC,KAAKwC,iBAElBxC,KAAKyC,aAAeb,CAAI,oDAAwC5B,KAAKM,UAASN,KAAKyC,0BACnFjB,EAAekB,KAAIC,GAAU3C,KAAK4C,aAAaD,mCAG/B3C,KAAK6C,oBAAkB7C,KAAKgC,sBAAoBhC,KAAKI,qEAErEsB,0FAKJ1B,KAAK8C,iBACL9C,KAAK+C,YAAc/C,KAAKgD,aAAeC,GAE5C,CAED,WAAYxB,GACV,OAAIyB,EACK,GAGFC,MAAMC,KAAKpD,KAAKqD,iBAAiB,UACzC,CAEO,aAAA1B,CAAcF,GACpB,MAAM6B,EAAW7B,EAAQ8B,MAAKZ,GAAUA,EAAOrC,QAAUN,KAAKM,MAAMkD,aAEpE,OAAIF,EACKA,EAASG,KAGdzD,KAAKyC,YACAzC,KAAKyC,YAGVhB,EAAQ,GACHA,EAAQ,GAAGgC,KAGb,EACR,CAEO,YAAAb,CAAaD,GACnB,OAAOf,CAAI,kBAECM,EAAUS,EAAOrC,sBACbqC,EAAOX,wBACPW,EAAOrC,QAAUN,KAAKM,MAAMkD,eAEtCb,EAAOc,eAGd,GA3HMjE,EAAMkE,OAAG,CAACC,EAAgBC,EAAgBC,GAgDLC,EAAA,CAA3CC,EAAS,CAAEC,SAAS,EAAMC,KAAMC,WAAyB1E,EAAA2E,UAAA,cAAA,GAnDvC3E,EAAMsE,EAAA,CAD1BM,EAAc,gBACM5E,SAAAA"}
package/lib/Textarea.js CHANGED
@@ -1,2 +1,2 @@
1
- import{_ as e}from"./tslib.es6-CmLYFWVC.js";import{css as t,html as r,nothing as o,LitElement as n}from"lit";import{property as a,customElement as i}from"lit/decorators.js";import{ifDefined as l}from"lit/directives/if-defined.js";import{ref as s}from"lit/directives/ref.js";import{o as c}from"./observe-D0n0zOfU.js";import{N as d}from"./events-Bv6wNHwJ.js";import{A as p}from"./AutocompleteMixin-D8eiOxvO.js";import{F as u}from"./FocusableMixin-BlQLNPdJ.js";import{F as h}from"./FormAssociatedMixin-DFL7yabe.js";import{I as v}from"./InputMixin-LetXsCyv.js";import{R as m,s as b}from"./TextField-BdEdZ0_b.js";import{S as x}from"./SizeMixin-CU9cLbLC.js";import{T as f}from"./TextSelectableMixin-Cfv__lHS.js";import{s as g}from"./Component-DSU3Qp0O.js";import{s as z}from"./FormField--eLuhPue.js";import{LocalizeController as j}from"./LocalizeController.js";import"./FormDataController-OUt5L5uC.js";import"./SlotController-Z6eG7LSZ.js";import"./EventController-BBOmvfLa.js";import"./VisuallyHidden.js";import"./translation.js";import"./en-us.js";import"./localization.js";import"./localization2.js";import"./localization3.js";import"./localization4.js";import"./localization5.js";import"./localization6.js";import"./localization7.js";import"./localization8.js";import"./localization9.js";const y=t`:host{--_n-textarea-inline-size:var(--n-textarea-inline-size, 240px);--_n-textarea-block-size:var(--n-textarea-block-size, 76px);--_n-input-background:var(--n-textarea-background, var(--n-color-active));--_n-input-color:var(--n-textarea-color, var(--n-color-text));--_n-input-border-color:var(--n-textarea-border-color, var(--n-color-border-strong));--_n-input-border-radius:var(--n-textarea-border-radius, var(--n-border-radius-s))}.n-input-container{position:relative;inline-size:var(--_n-textarea-inline-size)}.n-input{min-block-size:var(--_n-textarea-block-size);transition:border var(--n-transition-slowly),box-shadow var(--n-transition-slowly),background var(--n-transition-slowly);display:block;resize:vertical}:host([resize=auto]) .n-input{resize:none;overflow:hidden}:host([expand]){--_n-textarea-inline-size:100%}.n-character-counter{margin-block-start:var(--n-space-xs);font-size:var(--n-font-size-s);color:var(--n-color-text-weaker)}.n-input:hover,.n-label-container:hover+.n-input-container .n-input{--_n-input-border-color:var(--n-textarea-border-color, var(--n-color-border-hover))}.n-input:focus{--_n-input-border-color:var(--n-textarea-border-color, var(--n-color-accent));--_n-input-background:var(--n-textarea-background, var(--n-color-surface))}.n-input[aria-invalid=true]{--_n-input-border-color:var(--n-textarea-border-color, var(--n-color-status-danger))!important}.n-input:disabled,.n-input[readonly],.n-label-container:hover+.n-input-container .n-input:disabled,.n-label-container:hover+.n-input-container .n-input[readonly]{--_n-input-border-color:var(--n-textarea-border-color, var(--n-color-active));--_n-input-color:var(--n-textarea-color, var(--n-color-text-weakest))}.n-input[readonly],.n-label-container:hover+.n-input-container .n-input[readonly]{--_n-input-color:var(--n-textarea-color, var(--n-color-text-weak))}.n-input[readonly]:focus{--_n-input-border-color:var(--n-textarea-border-color, var(--n-color-accent))}`;let $=class extends(x(h(p(m(f(v(u(n)))))))){constructor(){super(...arguments),this.inputId="textarea",this.localize=new j(this,{onLangChange:()=>this.handleLangChange()}),this.resize="vertical",this.expand=!1,this.characterCounter=!1}render(){var e;return r`${this.renderLabel()}<div class="n-input-container"><textarea ${s(this.textSelectableRef)} ${s(this.focusableRef)} id="${this.inputId}" class="n-input" ?disabled="${this.disabled}" ?readonly="${this.readonly}" ?required="${this.required}" name="${l(this.name)}" maxlength="${l(this.maxLength)}" .value="${null!==(e=this.value)&&void 0!==e?e:""}" placeholder="${l(this.placeholder)}" @change="${this.handleChange}" @input="${this.handleInput}" @select="${this.handleSelect}" aria-describedby="${l(this.getDescribedBy())}" aria-invalid="${l(this.getInvalid())}" autocomplete="${this.autocomplete}"></textarea> ${this.characterCounter?this.renderCharacterCounter():o}</div>${this.renderError()}`}handleSelect(e){e.stopPropagation(),this.dispatchEvent(new d("select"))}renderCharacterCounter(){const{value:e,maxLength:t}=this,o="string"==typeof e?this.lengthMeasurer(e):0,n=t?t-o:null,a=t?`${o}/${t}`:o;return r`<nord-visually-hidden aria-live="polite" aria-atomic="true">${null!=n&&n<=10?this.localize.term("remainingCharacters",n):""}</nord-visually-hidden><div class="n-character-counter">${a}</div>`}handleLangChange(){const e=this.localize.resolvedLang;this.lengthMeasurer=function(e){if(Intl.Segmenter){const t=new Intl.Segmenter(e);return e=>[...t.segment(e)].length}return e=>e.length}(e)}resizeToFitContent(){const e=this.focusableRef.value;e&&("auto"===this.resize?(e.style.height="auto",e.style.height=`${e.scrollHeight}px`):e.style.height="")}};$.styles=[g,z,b,y],e([a({reflect:!0})],$.prototype,"resize",void 0),e([a({reflect:!0,type:Boolean})],$.prototype,"expand",void 0),e([a({reflect:!0,attribute:"maxlength",type:Number})],$.prototype,"maxLength",void 0),e([a({reflect:!0,type:Boolean,attribute:"character-counter"})],$.prototype,"characterCounter",void 0),e([c("resize","updated"),c("value","updated")],$.prototype,"resizeToFitContent",null),$=e([i("nord-textarea")],$);var C=$;export{C as default};
1
+ import{_ as e}from"./tslib.es6-CmLYFWVC.js";import{css as t,html as r,nothing as o,LitElement as n}from"lit";import{property as a,customElement as i}from"lit/decorators.js";import{ifDefined as l}from"lit/directives/if-defined.js";import{ref as s}from"lit/directives/ref.js";import{o as c}from"./observe-D0n0zOfU.js";import{N as d}from"./events-Bv6wNHwJ.js";import{A as p}from"./AutocompleteMixin-D8eiOxvO.js";import{F as u}from"./FocusableMixin-BlQLNPdJ.js";import{F as h}from"./FormAssociatedMixin-B4Qj-CQN.js";import{I as v}from"./InputMixin-LetXsCyv.js";import{R as m,s as b}from"./TextField-BdEdZ0_b.js";import{S as x}from"./SizeMixin-CU9cLbLC.js";import{T as f}from"./TextSelectableMixin-Cfv__lHS.js";import{s as g}from"./Component-DSU3Qp0O.js";import{s as z}from"./FormField-BFaVzUjk.js";import{LocalizeController as j}from"./LocalizeController.js";import"./FormDataController-OUt5L5uC.js";import"./SlotController-Z6eG7LSZ.js";import"./EventController-BBOmvfLa.js";import"./VisuallyHidden.js";import"./translation.js";import"./en-us.js";import"./localization.js";import"./localization2.js";import"./localization3.js";import"./localization4.js";import"./localization5.js";import"./localization6.js";import"./localization7.js";import"./localization8.js";import"./localization9.js";const y=t`:host{--_n-textarea-inline-size:var(--n-textarea-inline-size, 240px);--_n-textarea-block-size:var(--n-textarea-block-size, 76px);--_n-input-background:var(--n-textarea-background, var(--n-color-active));--_n-input-color:var(--n-textarea-color, var(--n-color-text));--_n-input-border-color:var(--n-textarea-border-color, var(--n-color-border-strong));--_n-input-border-radius:var(--n-textarea-border-radius, var(--n-border-radius-s))}.n-input-container{position:relative;inline-size:var(--_n-textarea-inline-size)}.n-input{min-block-size:var(--_n-textarea-block-size);transition:border var(--n-transition-slowly),box-shadow var(--n-transition-slowly),background var(--n-transition-slowly);display:block;resize:vertical}:host([resize=auto]) .n-input{resize:none;overflow:hidden}:host([expand]){--_n-textarea-inline-size:100%}.n-character-counter{margin-block-start:var(--n-space-xs);font-size:var(--n-font-size-s);color:var(--n-color-text-weaker)}.n-input:hover,.n-label-container:hover+.n-input-container .n-input{--_n-input-border-color:var(--n-textarea-border-color, var(--n-color-border-hover))}.n-input:focus{--_n-input-border-color:var(--n-textarea-border-color, var(--n-color-accent));--_n-input-background:var(--n-textarea-background, var(--n-color-surface))}.n-input[aria-invalid=true]{--_n-input-border-color:var(--n-textarea-border-color, var(--n-color-status-danger))!important}.n-input:disabled,.n-input[readonly],.n-label-container:hover+.n-input-container .n-input:disabled,.n-label-container:hover+.n-input-container .n-input[readonly]{--_n-input-border-color:var(--n-textarea-border-color, var(--n-color-active));--_n-input-color:var(--n-textarea-color, var(--n-color-text-weakest))}.n-input[readonly],.n-label-container:hover+.n-input-container .n-input[readonly]{--_n-input-color:var(--n-textarea-color, var(--n-color-text-weak))}.n-input[readonly]:focus{--_n-input-border-color:var(--n-textarea-border-color, var(--n-color-accent))}`;let $=class extends(x(h(p(m(f(v(u(n)))))))){constructor(){super(...arguments),this.inputId="textarea",this.localize=new j(this,{onLangChange:()=>this.handleLangChange()}),this.resize="vertical",this.expand=!1,this.characterCounter=!1}render(){var e;return r`${this.renderLabel()}<div class="n-input-container"><textarea ${s(this.textSelectableRef)} ${s(this.focusableRef)} id="${this.inputId}" class="n-input" ?disabled="${this.disabled}" ?readonly="${this.readonly}" ?required="${this.required}" name="${l(this.name)}" maxlength="${l(this.maxLength)}" .value="${null!==(e=this.value)&&void 0!==e?e:""}" placeholder="${l(this.placeholder)}" @change="${this.handleChange}" @input="${this.handleInput}" @select="${this.handleSelect}" aria-describedby="${l(this.getDescribedBy())}" aria-invalid="${l(this.getInvalid())}" autocomplete="${this.autocomplete}"></textarea> ${this.characterCounter?this.renderCharacterCounter():o}</div>${this.renderError()} ${this.isHintBelow?this.renderHint():o}`}handleSelect(e){e.stopPropagation(),this.dispatchEvent(new d("select"))}renderCharacterCounter(){const{value:e,maxLength:t}=this,o="string"==typeof e?this.lengthMeasurer(e):0,n=t?t-o:null,a=t?`${o}/${t}`:o;return r`<nord-visually-hidden aria-live="polite" aria-atomic="true">${null!=n&&n<=10?this.localize.term("remainingCharacters",n):""}</nord-visually-hidden><div class="n-character-counter">${a}</div>`}handleLangChange(){const e=this.localize.resolvedLang;this.lengthMeasurer=function(e){if(Intl.Segmenter){const t=new Intl.Segmenter(e);return e=>[...t.segment(e)].length}return e=>e.length}(e)}resizeToFitContent(){const e=this.focusableRef.value;e&&("auto"===this.resize?(e.style.height="auto",e.style.height=`${e.scrollHeight}px`):e.style.height="")}};$.styles=[g,z,b,y],e([a({reflect:!0})],$.prototype,"resize",void 0),e([a({reflect:!0,type:Boolean})],$.prototype,"expand",void 0),e([a({reflect:!0,attribute:"maxlength",type:Number})],$.prototype,"maxLength",void 0),e([a({reflect:!0,type:Boolean,attribute:"character-counter"})],$.prototype,"characterCounter",void 0),e([c("resize","updated"),c("value","updated")],$.prototype,"resizeToFitContent",null),$=e([i("nord-textarea")],$);var C=$;export{C as default};
2
2
  //# sourceMappingURL=Textarea.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Textarea.js","sources":["../src/textarea/Textarea.ts"],"sourcesContent":["import { html, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { ref } from 'lit/directives/ref.js'\nimport { observe } from '../common/decorators/observe.js'\n\nimport { NordEvent } from '../common/events.js'\nimport { AutocompleteMixin } from '../common/mixins/AutocompleteMixin.js'\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\nimport { ReadonlyMixin } from '../common/mixins/ReadonlyMixin.js'\nimport { SizeMixin } from '../common/mixins/SizeMixin.js'\n\nimport { TextSelectableMixin } from '../common/mixins/TextSelectableMixin.js'\nimport componentStyle from '../common/styles/Component.css'\nimport formFieldStyle from '../common/styles/FormField.css'\nimport textFieldStyle from '../common/styles/TextField.css'\nimport { LocalizeController } from '../localization/LocalizeController.js'\nimport style from './Textarea.css'\n\nfunction createLengthMeasurer(locale: string) {\n if (Intl.Segmenter) {\n const segmenter = new Intl.Segmenter(locale)\n return (value: string) => [...segmenter.segment(value)].length\n }\n\n return (value: string) => value.length\n}\n\n/**\n * Textarea is a component that allows user to write text over\n * multiple rows. Used when the expected user input is long.\n * For shorter input, use the Input component.\n *\n * @status ready\n * @category form\n * @slot label - Use when a label requires more than plain text.\n * @slot hint - Optional slot that holds hint text for the textarea.\n * @slot error - Optional slot that holds error text for the textarea.\n *\n * @cssprop [--n-textarea-inline-size=240px] - Controls the inline size, or width, of the textarea.\n * @cssprop [--n-textarea-block-size=76px] - Controls the block size, or height, of the textarea.\n * @cssprop [--n-textarea-background=var(--n-color-active)] - Controls the background of the textarea, using our [color tokens](/tokens/#color).\n * @cssprop [--n-textarea-color=var(--n-color-text)] - Controls the text color of the textarea, using our [color tokens](/tokens/#color).\n * @cssprop [--n-textarea-border-color=var(--n-color-border-strong)] - Controls the border color of the textarea, using our [color tokens](/tokens/#color).\n * @cssprop [--n-textarea-border-radius=var(--n-border-radius-s)] - Controls how rounded the corners are, using [border radius tokens](/tokens/#border-radius).\n * @cssprop [--n-label-color=var(--n-color-text)] - Controls the text color of the label, using our [color tokens](/tokens/#color).\n *\n * @localization remainingCharacters - A function which receives the number of remaining characters and returns a string to be used as the aria-live message.\n */\n@customElement('nord-textarea')\nexport default class Textarea extends SizeMixin(\n FormAssociatedMixin(AutocompleteMixin(ReadonlyMixin(TextSelectableMixin(InputMixin(FocusableMixin(LitElement)))))),\n) {\n static styles = [componentStyle, formFieldStyle, textFieldStyle, style]\n\n protected inputId = 'textarea'\n\n private lengthMeasurer!: (value: string) => number\n private localize = new LocalizeController<'nord-textarea'>(this, {\n onLangChange: () => this.handleLangChange(),\n })\n\n /**\n * Controls whether the textarea is resizable.\n * By default is manually resizable vertically.\n * Set to \"auto\" to enable auto-resizing as content grows.\n */\n @property({ reflect: true }) resize: 'vertical' | 'auto' = 'vertical'\n\n /**\n * Controls whether the textarea expands to fill the width of its container.\n */\n @property({ reflect: true, type: Boolean }) expand = false\n\n /**\n * Controls the max allowed length for the textarea.\n */\n @property({ reflect: true, attribute: 'maxlength', type: Number }) maxLength?: number\n\n /**\n * Controls whether to show a count of the number of characters in the textarea.\n * When combined with `maxlength`, both the count and the max length are shown.\n */\n @property({ reflect: true, type: Boolean, attribute: 'character-counter' }) characterCounter = false\n\n render() {\n return html`\n ${this.renderLabel()}\n\n <div class=\"n-input-container\">\n <textarea\n ${ref(this.textSelectableRef)}\n ${ref(this.focusableRef)}\n id=${this.inputId}\n class=\"n-input\"\n ?disabled=${this.disabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\n name=${ifDefined(this.name)}\n maxlength=${ifDefined(this.maxLength)}\n .value=${this.value ?? ''}\n placeholder=${ifDefined(this.placeholder)}\n @change=${this.handleChange}\n @input=${this.handleInput}\n @select=${this.handleSelect}\n aria-describedby=${ifDefined(this.getDescribedBy())}\n aria-invalid=${ifDefined(this.getInvalid())}\n autocomplete=${this.autocomplete as any}\n ></textarea>\n\n ${this.characterCounter ? this.renderCharacterCounter() : nothing}\n </div>\n\n ${this.renderError()}\n `\n }\n\n protected handleSelect(e: Event) {\n e.stopPropagation()\n\n /**\n * Fired when some text has been selected.\n */\n this.dispatchEvent(new NordEvent('select'))\n }\n\n private renderCharacterCounter() {\n const { value, maxLength } = this\n const length = typeof value === 'string' ? this.lengthMeasurer(value) : 0\n\n const remainder = maxLength ? maxLength - length : null\n const counter = maxLength ? `${length}/${maxLength}` : length\n\n return html`\n <nord-visually-hidden aria-live=\"polite\" aria-atomic=\"true\">\n ${remainder != null && remainder <= 10 ? this.localize.term('remainingCharacters', remainder) : ''}\n </nord-visually-hidden>\n <div class=\"n-character-counter\">${counter}</div>\n `\n }\n\n private handleLangChange() {\n const lang = this.localize.resolvedLang\n this.lengthMeasurer = createLengthMeasurer(lang)\n }\n\n @observe('resize', 'updated')\n @observe('value', 'updated')\n protected resizeToFitContent() {\n const textarea = this.focusableRef.value\n\n if (!textarea) {\n return\n }\n\n if (this.resize === 'auto') {\n textarea.style.height = 'auto'\n textarea.style.height = `${textarea.scrollHeight}px`\n }\n else {\n textarea.style.height = ''\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-textarea': Textarea\n }\n}\n"],"names":["Textarea","SizeMixin","FormAssociatedMixin","AutocompleteMixin","ReadonlyMixin","TextSelectableMixin","InputMixin","FocusableMixin","LitElement","constructor","this","inputId","localize","LocalizeController","onLangChange","handleLangChange","resize","expand","characterCounter","render","html","renderLabel","ref","textSelectableRef","focusableRef","disabled","readonly","required","ifDefined","name","maxLength","_a","value","placeholder","handleChange","handleInput","handleSelect","getDescribedBy","getInvalid","autocomplete","renderCharacterCounter","nothing","renderError","e","stopPropagation","dispatchEvent","NordEvent","length","lengthMeasurer","remainder","counter","term","lang","resolvedLang","locale","Intl","Segmenter","segmenter","segment","createLengthMeasurer","resizeToFitContent","textarea","style","height","scrollHeight","styles","componentStyle","formFieldStyle","textFieldStyle","__decorate","property","reflect","prototype","type","Boolean","attribute","Number","observe","customElement"],"mappings":"+qGAoDe,IAAMA,EAAN,cAAuBC,EACpCC,EAAoBC,EAAkBC,EAAcC,EAAoBC,EAAWC,EAAeC,UADrF,WAAAC,uBAKHC,KAAOC,QAAG,WAGZD,KAAAE,SAAW,IAAIC,EAAoCH,KAAM,CAC/DI,aAAc,IAAMJ,KAAKK,qBAQEL,KAAMM,OAAwB,WAKfN,KAAMO,QAAG,EAWuBP,KAAgBQ,kBAAG,CAgFhG,CA9EC,MAAAC,SACE,OAAOC,CAAI,GACPV,KAAKW,yDAIDC,EAAIZ,KAAKa,sBACTD,EAAIZ,KAAKc,qBACNd,KAAKC,uCAEED,KAAKe,wBACLf,KAAKgB,wBACLhB,KAAKiB,mBACVC,EAAUlB,KAAKmB,qBACVD,EAAUlB,KAAKoB,uBACR,QAAVC,EAAArB,KAAKsB,aAAK,IAAAD,EAAAA,EAAI,oBACTH,EAAUlB,KAAKuB,0BACnBvB,KAAKwB,yBACNxB,KAAKyB,yBACJzB,KAAK0B,mCACIR,EAAUlB,KAAK2B,oCACnBT,EAAUlB,KAAK4B,gCACf5B,KAAK6B,6BAGpB7B,KAAKQ,iBAAmBR,KAAK8B,yBAA2BC,UAG1D/B,KAAKgC,eAEV,CAES,YAAAN,CAAaO,GACrBA,EAAEC,kBAKFlC,KAAKmC,cAAc,IAAIC,EAAU,UAClC,CAEO,sBAAAN,GACN,MAAMR,MAAEA,EAAKF,UAAEA,GAAcpB,KACvBqC,EAA0B,iBAAVf,EAAqBtB,KAAKsC,eAAehB,GAAS,EAElEiB,EAAYnB,EAAYA,EAAYiB,EAAS,KAC7CG,EAAUpB,EAAY,GAAGiB,KAAUjB,IAAciB,EAEvD,OAAO3B,CAAI,+DAEQ,MAAb6B,GAAqBA,GAAa,GAAKvC,KAAKE,SAASuC,KAAK,sBAAuBF,GAAa,6DAE/DC,SAEtC,CAEO,gBAAAnC,GACN,MAAMqC,EAAO1C,KAAKE,SAASyC,aAC3B3C,KAAKsC,eA5HT,SAA8BM,GAC5B,GAAIC,KAAKC,UAAW,CAClB,MAAMC,EAAY,IAAIF,KAAKC,UAAUF,GACrC,OAAQtB,GAAkB,IAAIyB,EAAUC,QAAQ1B,IAAQe,MACzD,CAED,OAAQf,GAAkBA,EAAMe,MAClC,CAqH0BY,CAAqBP,EAC5C,CAIS,kBAAAQ,GACR,MAAMC,EAAWnD,KAAKc,aAAaQ,MAE9B6B,IAIe,SAAhBnD,KAAKM,QACP6C,EAASC,MAAMC,OAAS,OACxBF,EAASC,MAAMC,OAAS,GAAGF,EAASG,kBAGpCH,EAASC,MAAMC,OAAS,GAE3B,GA7GM/D,EAAMiE,OAAG,CAACC,EAAgBC,EAAgBC,EAAgBN,GAcpCO,EAAA,CAA5BC,EAAS,CAAEC,SAAS,KAAgDvE,EAAAwE,UAAA,cAAA,GAKzBH,EAAA,CAA3CC,EAAS,CAAEC,SAAS,EAAME,KAAMC,WAAyB1E,EAAAwE,UAAA,cAAA,GAKSH,EAAA,CAAlEC,EAAS,CAAEC,SAAS,EAAMI,UAAW,YAAaF,KAAMG,UAA4B5E,EAAAwE,UAAA,iBAAA,GAMTH,EAAA,CAA3EC,EAAS,CAAEC,SAAS,EAAME,KAAMC,QAASC,UAAW,uBAA+C3E,EAAAwE,UAAA,wBAAA,GAiE1FH,EAAA,CAFTQ,EAAQ,SAAU,WAClBA,EAAQ,QAAS,YAejB7E,EAAAwE,UAAA,qBAAA,MAhHkBxE,EAAQqE,EAAA,CAD5BS,EAAc,kBACM9E,SAAAA"}
1
+ {"version":3,"file":"Textarea.js","sources":["../src/textarea/Textarea.ts"],"sourcesContent":["import { html, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { ref } from 'lit/directives/ref.js'\nimport { observe } from '../common/decorators/observe.js'\n\nimport { NordEvent } from '../common/events.js'\nimport { AutocompleteMixin } from '../common/mixins/AutocompleteMixin.js'\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\nimport { ReadonlyMixin } from '../common/mixins/ReadonlyMixin.js'\nimport { SizeMixin } from '../common/mixins/SizeMixin.js'\n\nimport { TextSelectableMixin } from '../common/mixins/TextSelectableMixin.js'\nimport componentStyle from '../common/styles/Component.css'\nimport formFieldStyle from '../common/styles/FormField.css'\nimport textFieldStyle from '../common/styles/TextField.css'\nimport { LocalizeController } from '../localization/LocalizeController.js'\nimport style from './Textarea.css'\n\nfunction createLengthMeasurer(locale: string) {\n if (Intl.Segmenter) {\n const segmenter = new Intl.Segmenter(locale)\n return (value: string) => [...segmenter.segment(value)].length\n }\n\n return (value: string) => value.length\n}\n\n/**\n * Textarea is a component that allows user to write text over\n * multiple rows. Used when the expected user input is long.\n * For shorter input, use the Input component.\n *\n * @status ready\n * @category form\n * @slot label - Use when a label requires more than plain text.\n * @slot hint - Optional slot that holds hint text for the textarea.\n * @slot error - Optional slot that holds error text for the textarea.\n *\n * @cssprop [--n-textarea-inline-size=240px] - Controls the inline size, or width, of the textarea.\n * @cssprop [--n-textarea-block-size=76px] - Controls the block size, or height, of the textarea.\n * @cssprop [--n-textarea-background=var(--n-color-active)] - Controls the background of the textarea, using our [color tokens](/tokens/#color).\n * @cssprop [--n-textarea-color=var(--n-color-text)] - Controls the text color of the textarea, using our [color tokens](/tokens/#color).\n * @cssprop [--n-textarea-border-color=var(--n-color-border-strong)] - Controls the border color of the textarea, using our [color tokens](/tokens/#color).\n * @cssprop [--n-textarea-border-radius=var(--n-border-radius-s)] - Controls how rounded the corners are, using [border radius tokens](/tokens/#border-radius).\n * @cssprop [--n-label-color=var(--n-color-text)] - Controls the text color of the label, using our [color tokens](/tokens/#color).\n *\n * @localization remainingCharacters - A function which receives the number of remaining characters and returns a string to be used as the aria-live message.\n */\n@customElement('nord-textarea')\nexport default class Textarea extends SizeMixin(\n FormAssociatedMixin(AutocompleteMixin(ReadonlyMixin(TextSelectableMixin(InputMixin(FocusableMixin(LitElement)))))),\n) {\n static styles = [componentStyle, formFieldStyle, textFieldStyle, style]\n\n protected inputId = 'textarea'\n\n private lengthMeasurer!: (value: string) => number\n private localize = new LocalizeController<'nord-textarea'>(this, {\n onLangChange: () => this.handleLangChange(),\n })\n\n /**\n * Controls whether the textarea is resizable.\n * By default is manually resizable vertically.\n * Set to \"auto\" to enable auto-resizing as content grows.\n */\n @property({ reflect: true }) resize: 'vertical' | 'auto' = 'vertical'\n\n /**\n * Controls whether the textarea expands to fill the width of its container.\n */\n @property({ reflect: true, type: Boolean }) expand = false\n\n /**\n * Controls the max allowed length for the textarea.\n */\n @property({ reflect: true, attribute: 'maxlength', type: Number }) maxLength?: number\n\n /**\n * Controls whether to show a count of the number of characters in the textarea.\n * When combined with `maxlength`, both the count and the max length are shown.\n */\n @property({ reflect: true, type: Boolean, attribute: 'character-counter' }) characterCounter = false\n\n render() {\n return html`\n ${this.renderLabel()}\n\n <div class=\"n-input-container\">\n <textarea\n ${ref(this.textSelectableRef)}\n ${ref(this.focusableRef)}\n id=${this.inputId}\n class=\"n-input\"\n ?disabled=${this.disabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\n name=${ifDefined(this.name)}\n maxlength=${ifDefined(this.maxLength)}\n .value=${this.value ?? ''}\n placeholder=${ifDefined(this.placeholder)}\n @change=${this.handleChange}\n @input=${this.handleInput}\n @select=${this.handleSelect}\n aria-describedby=${ifDefined(this.getDescribedBy())}\n aria-invalid=${ifDefined(this.getInvalid())}\n autocomplete=${this.autocomplete as any}\n ></textarea>\n\n ${this.characterCounter ? this.renderCharacterCounter() : nothing}\n </div>\n\n ${this.renderError()}\n ${this.isHintBelow ? this.renderHint() : nothing}\n `\n }\n\n protected handleSelect(e: Event) {\n e.stopPropagation()\n\n /**\n * Fired when some text has been selected.\n */\n this.dispatchEvent(new NordEvent('select'))\n }\n\n private renderCharacterCounter() {\n const { value, maxLength } = this\n const length = typeof value === 'string' ? this.lengthMeasurer(value) : 0\n\n const remainder = maxLength ? maxLength - length : null\n const counter = maxLength ? `${length}/${maxLength}` : length\n\n return html`\n <nord-visually-hidden aria-live=\"polite\" aria-atomic=\"true\">\n ${remainder != null && remainder <= 10 ? this.localize.term('remainingCharacters', remainder) : ''}\n </nord-visually-hidden>\n <div class=\"n-character-counter\">${counter}</div>\n `\n }\n\n private handleLangChange() {\n const lang = this.localize.resolvedLang\n this.lengthMeasurer = createLengthMeasurer(lang)\n }\n\n @observe('resize', 'updated')\n @observe('value', 'updated')\n protected resizeToFitContent() {\n const textarea = this.focusableRef.value\n\n if (!textarea) {\n return\n }\n\n if (this.resize === 'auto') {\n textarea.style.height = 'auto'\n textarea.style.height = `${textarea.scrollHeight}px`\n }\n else {\n textarea.style.height = ''\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-textarea': Textarea\n }\n}\n"],"names":["Textarea","SizeMixin","FormAssociatedMixin","AutocompleteMixin","ReadonlyMixin","TextSelectableMixin","InputMixin","FocusableMixin","LitElement","constructor","this","inputId","localize","LocalizeController","onLangChange","handleLangChange","resize","expand","characterCounter","render","html","renderLabel","ref","textSelectableRef","focusableRef","disabled","readonly","required","ifDefined","name","maxLength","_a","value","placeholder","handleChange","handleInput","handleSelect","getDescribedBy","getInvalid","autocomplete","renderCharacterCounter","nothing","renderError","isHintBelow","renderHint","e","stopPropagation","dispatchEvent","NordEvent","length","lengthMeasurer","remainder","counter","term","lang","resolvedLang","locale","Intl","Segmenter","segmenter","segment","createLengthMeasurer","resizeToFitContent","textarea","style","height","scrollHeight","styles","componentStyle","formFieldStyle","textFieldStyle","__decorate","property","reflect","prototype","type","Boolean","attribute","Number","observe","customElement"],"mappings":"+qGAoDe,IAAMA,EAAN,cAAuBC,EACpCC,EAAoBC,EAAkBC,EAAcC,EAAoBC,EAAWC,EAAeC,UADrF,WAAAC,uBAKHC,KAAOC,QAAG,WAGZD,KAAAE,SAAW,IAAIC,EAAoCH,KAAM,CAC/DI,aAAc,IAAMJ,KAAKK,qBAQEL,KAAMM,OAAwB,WAKfN,KAAMO,QAAG,EAWuBP,KAAgBQ,kBAAG,CAiFhG,CA/EC,MAAAC,SACE,OAAOC,CAAI,GACPV,KAAKW,yDAIDC,EAAIZ,KAAKa,sBACTD,EAAIZ,KAAKc,qBACNd,KAAKC,uCAEED,KAAKe,wBACLf,KAAKgB,wBACLhB,KAAKiB,mBACVC,EAAUlB,KAAKmB,qBACVD,EAAUlB,KAAKoB,uBACR,QAAVC,EAAArB,KAAKsB,aAAK,IAAAD,EAAAA,EAAI,oBACTH,EAAUlB,KAAKuB,0BACnBvB,KAAKwB,yBACNxB,KAAKyB,yBACJzB,KAAK0B,mCACIR,EAAUlB,KAAK2B,oCACnBT,EAAUlB,KAAK4B,gCACf5B,KAAK6B,6BAGpB7B,KAAKQ,iBAAmBR,KAAK8B,yBAA2BC,UAG1D/B,KAAKgC,iBACLhC,KAAKiC,YAAcjC,KAAKkC,aAAeH,GAE5C,CAES,YAAAL,CAAaS,GACrBA,EAAEC,kBAKFpC,KAAKqC,cAAc,IAAIC,EAAU,UAClC,CAEO,sBAAAR,GACN,MAAMR,MAAEA,EAAKF,UAAEA,GAAcpB,KACvBuC,EAA0B,iBAAVjB,EAAqBtB,KAAKwC,eAAelB,GAAS,EAElEmB,EAAYrB,EAAYA,EAAYmB,EAAS,KAC7CG,EAAUtB,EAAY,GAAGmB,KAAUnB,IAAcmB,EAEvD,OAAO7B,CAAI,+DAEQ,MAAb+B,GAAqBA,GAAa,GAAKzC,KAAKE,SAASyC,KAAK,sBAAuBF,GAAa,6DAE/DC,SAEtC,CAEO,gBAAArC,GACN,MAAMuC,EAAO5C,KAAKE,SAAS2C,aAC3B7C,KAAKwC,eA7HT,SAA8BM,GAC5B,GAAIC,KAAKC,UAAW,CAClB,MAAMC,EAAY,IAAIF,KAAKC,UAAUF,GACrC,OAAQxB,GAAkB,IAAI2B,EAAUC,QAAQ5B,IAAQiB,MACzD,CAED,OAAQjB,GAAkBA,EAAMiB,MAClC,CAsH0BY,CAAqBP,EAC5C,CAIS,kBAAAQ,GACR,MAAMC,EAAWrD,KAAKc,aAAaQ,MAE9B+B,IAIe,SAAhBrD,KAAKM,QACP+C,EAASC,MAAMC,OAAS,OACxBF,EAASC,MAAMC,OAAS,GAAGF,EAASG,kBAGpCH,EAASC,MAAMC,OAAS,GAE3B,GA9GMjE,EAAMmE,OAAG,CAACC,EAAgBC,EAAgBC,EAAgBN,GAcpCO,EAAA,CAA5BC,EAAS,CAAEC,SAAS,KAAgDzE,EAAA0E,UAAA,cAAA,GAKzBH,EAAA,CAA3CC,EAAS,CAAEC,SAAS,EAAME,KAAMC,WAAyB5E,EAAA0E,UAAA,cAAA,GAKSH,EAAA,CAAlEC,EAAS,CAAEC,SAAS,EAAMI,UAAW,YAAaF,KAAMG,UAA4B9E,EAAA0E,UAAA,iBAAA,GAMTH,EAAA,CAA3EC,EAAS,CAAEC,SAAS,EAAME,KAAMC,QAASC,UAAW,uBAA+C7E,EAAA0E,UAAA,wBAAA,GAkE1FH,EAAA,CAFTQ,EAAQ,SAAU,WAClBA,EAAQ,QAAS,YAejB/E,EAAA0E,UAAA,qBAAA,MAjHkB1E,EAAQuE,EAAA,CAD5BS,EAAc,kBACMhF,SAAAA"}
package/lib/Toggle.js CHANGED
@@ -1,2 +1,2 @@
1
- import{_ as e}from"./tslib.es6-CmLYFWVC.js";import{css as n,html as i,LitElement as r}from"lit";import{property as t,customElement as o}from"lit/decorators.js";import{ifDefined as s}from"lit/directives/if-defined.js";import{ref as a}from"lit/directives/ref.js";import{F as l}from"./FocusableMixin-BlQLNPdJ.js";import{F as c}from"./FormAssociatedMixin-DFL7yabe.js";import{I as d}from"./InputMixin-LetXsCyv.js";import{s as g}from"./Component-DSU3Qp0O.js";import{s as p}from"./FormField--eLuhPue.js";import"./FormDataController-OUt5L5uC.js";import"./SlotController-Z6eG7LSZ.js";import"./EventController-BBOmvfLa.js";import"./events-Bv6wNHwJ.js";import"./VisuallyHidden.js";const h=n`:host{--_n-toggle-block-size:calc(var(--_n-toggle-inline-size) / 1.6);--_n-toggle-inline-size:3.2143em;--_n-toggle-thumb-margin:0.35em;display:inline-block;font-size:var(--n-font-size-m)}.n-flex{display:flex}.n-expand{flex:1;display:flex;justify-content:center;align-items:flex-start;flex-direction:column;min-block-size:100%}.n-input-container{position:relative}.n-toggle{appearance:none;display:inline-flex;align-items:center;inline-size:var(--_n-toggle-inline-size);block-size:var(--_n-toggle-block-size);border-radius:var(--n-border-radius-pill);background:var(--_n-toggle-background,var(--n-color-border-strong));cursor:pointer;transition:background var(--n-transition-slowly);font-size:var(--_n-toggle-size,var(--n-font-size-m))}.n-toggle::before{content:'';display:block;aspect-ratio:1/1;block-size:calc(100% - 2 * var(--_n-toggle-thumb-margin));background:var(--n-color-text-on-accent);border-radius:var(--n-border-radius-circle);transition:margin;transition-duration:inherit;margin-inline-start:var(--_n-toggle-thumb-margin);box-shadow:var(--n-box-shadow)}input:checked{--_n-toggle-background:var(--n-color-accent)}input:checked::before{margin-inline-start:calc(var(--_n-toggle-inline-size) - var(--_n-toggle-block-size) + var(--_n-toggle-thumb-margin))}input:checked[aria-invalid]{--_n-toggle-background:var(--n-color-status-danger)}input:focus{outline:0;box-shadow:0 0 0 1px var(--n-color-surface),0 0 0 3px var(--n-color-accent)}:host([disabled]) label{color:var(--n-color-text-weaker);cursor:default}:host([disabled]) input{cursor:default}:host([disabled]) input:not(:checked){--_n-toggle-background:var(--n-color-border-neutral)}:host([disabled]) input:checked{opacity:.3}.n-label-container{margin-block-end:0}label{user-select:none;font-weight:var(--n-font-weight)!important;line-height:var(--n-line-height);padding-inline-start:var(--n-space-s);cursor:pointer}.n-hint{padding-inline-start:var(--n-space-s)}.n-error{margin-block-start:var(--n-space-xs);padding-inline-start:var(--n-space-s)}:host([reverse]) .n-error,:host([reverse]) .n-hint,:host([reverse]) label{padding-inline-start:0;padding-inline-end:var(--n-space-s)}:host([size='s']) .n-toggle{--_n-toggle-size:var(--n-font-size-xs)}:host([size='l']) .n-toggle{--_n-toggle-size:var(--n-font-size-xl)}`;let v=class extends(c(d(l(r)))){constructor(){super(...arguments),this.checked=!1,this.reverse=!1,this.size="m"}get formValue(){return this.checked?this.value||"on":void 0}render(){const e=i`<div class="n-expand">${this.renderLabel()} ${this.renderError()}</div>`,n=i`<div class="n-input-container"><input ${a(this.focusableRef)} class="n-toggle" id="${this.inputId}" type="checkbox" role="switch" name="${s(this.name)}" .value="${this.value}" .checked="${this.checked}" ?disabled="${this.disabled}" ?required="${this.required}" aria-describedby="${s(this.getDescribedBy())}" aria-invalid="${s(this.getInvalid())}" @change="${this.handleChange}"></div>`;return i`<div class="n-flex">${this.reverse?[e,n]:[n,e]}</div>`}handleChange(e){const n=e.target;this.checked=n.checked,super.handleChange(e)}};v.styles=[g,p,h],e([t({reflect:!0,type:Boolean})],v.prototype,"checked",void 0),e([t({reflect:!0,type:Boolean})],v.prototype,"reverse",void 0),e([t({reflect:!0})],v.prototype,"size",void 0),v=e([o("nord-toggle")],v);var u=v;export{u as default};
1
+ import{_ as e}from"./tslib.es6-CmLYFWVC.js";import{css as n,html as i,nothing as r,LitElement as t}from"lit";import{property as o,customElement as s}from"lit/decorators.js";import{ifDefined as a}from"lit/directives/if-defined.js";import{ref as l}from"lit/directives/ref.js";import{F as d}from"./FocusableMixin-BlQLNPdJ.js";import{F as c}from"./FormAssociatedMixin-B4Qj-CQN.js";import{I as g}from"./InputMixin-LetXsCyv.js";import{s as h}from"./Component-DSU3Qp0O.js";import{s as p}from"./FormField-BFaVzUjk.js";import"./FormDataController-OUt5L5uC.js";import"./SlotController-Z6eG7LSZ.js";import"./EventController-BBOmvfLa.js";import"./events-Bv6wNHwJ.js";import"./VisuallyHidden.js";const v=n`:host{--_n-toggle-block-size:calc(var(--_n-toggle-inline-size) / 1.6);--_n-toggle-inline-size:3.2143em;--_n-toggle-thumb-margin:0.35em;display:inline-block;font-size:var(--n-font-size-m)}.n-flex{display:flex}.n-expand{flex:1;display:flex;justify-content:center;align-items:flex-start;flex-direction:column;min-block-size:100%}.n-input-container{position:relative}.n-toggle{appearance:none;display:inline-flex;align-items:center;inline-size:var(--_n-toggle-inline-size);block-size:var(--_n-toggle-block-size);border-radius:var(--n-border-radius-pill);background:var(--_n-toggle-background,var(--n-color-border-strong));cursor:pointer;transition:background var(--n-transition-slowly);font-size:var(--_n-toggle-size,var(--n-font-size-m))}.n-toggle::before{content:'';display:block;aspect-ratio:1/1;block-size:calc(100% - 2 * var(--_n-toggle-thumb-margin));background:var(--n-color-text-on-accent);border-radius:var(--n-border-radius-circle);transition:margin;transition-duration:inherit;margin-inline-start:var(--_n-toggle-thumb-margin);box-shadow:var(--n-box-shadow)}input:checked{--_n-toggle-background:var(--n-color-accent)}input:checked::before{margin-inline-start:calc(var(--_n-toggle-inline-size) - var(--_n-toggle-block-size) + var(--_n-toggle-thumb-margin))}input:checked[aria-invalid]{--_n-toggle-background:var(--n-color-status-danger)}input:focus{outline:0;box-shadow:0 0 0 1px var(--n-color-surface),0 0 0 3px var(--n-color-accent)}:host([disabled]) label{color:var(--n-color-text-weaker);cursor:default}:host([disabled]) input{cursor:default}:host([disabled]) input:not(:checked){--_n-toggle-background:var(--n-color-border-neutral)}:host([disabled]) input:checked{opacity:.3}.n-label-container{margin-block-end:0}label{user-select:none;font-weight:var(--n-font-weight)!important;line-height:var(--n-line-height);padding-inline-start:var(--n-space-s);cursor:pointer}.n-hint{padding-inline-start:var(--n-space-s)}.n-error{margin-block-start:var(--n-space-xs);padding-inline-start:var(--n-space-s)}:host([hint-below]) :is(.n-hint, .n-error){padding-inline-start:0}:host([reverse]) .n-error,:host([reverse]) .n-hint,:host([reverse]) label{padding-inline-start:0;padding-inline-end:var(--n-space-s)}:host([reverse][hint-below]) :is(.n-hint, .n-error){padding-inline-end:0}:host([size='s']) .n-toggle{--_n-toggle-size:var(--n-font-size-xs)}:host([size='l']) .n-toggle{--_n-toggle-size:var(--n-font-size-xl)}`;let u=class extends(c(g(d(t)))){constructor(){super(...arguments),this.checked=!1,this.reverse=!1,this.size="m"}get formValue(){return this.checked?this.value||"on":void 0}render(){const e=i`<div class="n-expand">${this.renderLabel()} ${this.isHintBelow?r:this.renderError()}</div>`,n=i`<div class="n-input-container"><input ${l(this.focusableRef)} class="n-toggle" id="${this.inputId}" type="checkbox" role="switch" name="${a(this.name)}" .value="${this.value}" .checked="${this.checked}" ?disabled="${this.disabled}" ?required="${this.required}" aria-describedby="${a(this.getDescribedBy())}" aria-invalid="${a(this.getInvalid())}" @change="${this.handleChange}"></div>`;return i`<div class="n-flex">${this.reverse?[e,n]:[n,e]}</div>${this.isHintBelow?this.renderError():r} ${this.isHintBelow?this.renderHint():r}`}handleChange(e){const n=e.target;this.checked=n.checked,super.handleChange(e)}};u.styles=[h,p,v],e([o({reflect:!0,type:Boolean})],u.prototype,"checked",void 0),e([o({reflect:!0,type:Boolean})],u.prototype,"reverse",void 0),e([o({reflect:!0})],u.prototype,"size",void 0),u=e([s("nord-toggle")],u);var m=u;export{m as default};
2
2
  //# sourceMappingURL=Toggle.js.map
package/lib/Toggle.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Toggle.js","sources":["../src/toggle/Toggle.ts"],"sourcesContent":["/* eslint-disable lit-a11y/role-has-required-aria-attrs */\nimport { html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { ref } from 'lit/directives/ref.js'\n\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\n\nimport componentStyle from '../common/styles/Component.css'\nimport formFieldStyle from '../common/styles/FormField.css'\nimport style from './Toggle.css'\n\n/**\n * Toggle switch gives control over a feature or option that can be\n * turned on or off. If a physical switch would work for the action, a\n * toggle is probably the best component to use.\n *\n * @status ready\n * @category form\n * @slot label - Use when a label requires more than plain text.\n * @slot hint - Optional slot that holds hint text for the input.\n * @slot error - Optional slot that holds error text for the input.\n *\n * @cssprop [--n-label-color=var(--n-color-text)] - Controls the text color of the label, using our [color tokens](/tokens/#color).\n */\n@customElement('nord-toggle')\nexport default class Toggle extends FormAssociatedMixin(InputMixin(FocusableMixin(LitElement))) {\n static styles = [componentStyle, formFieldStyle, style]\n\n protected override get formValue() {\n return this.checked ? this.value || 'on' : undefined\n }\n\n /**\n * Controls whether the toggle is checked or not.\n */\n @property({ reflect: true, type: Boolean }) checked: boolean = false\n\n /**\n * Controls whether the contents are displayed in reverse order,\n * putting the label before the toggle.\n */\n @property({ reflect: true, type: Boolean }) reverse: boolean = false\n\n /**\n * The size of the toggle switch.\n */\n @property({ reflect: true }) size: 's' | 'm' | 'l' = 'm'\n\n render() {\n const label = html`<div class=\"n-expand\">${this.renderLabel()} ${this.renderError()}</div>`\n const input = html`<div class=\"n-input-container\">\n <input\n ${ref(this.focusableRef)}\n class=\"n-toggle\"\n id=${this.inputId}\n type=\"checkbox\"\n role=\"switch\"\n name=${ifDefined(this.name)}\n .value=${this.value}\n .checked=${this.checked}\n ?disabled=${this.disabled}\n ?required=${this.required}\n aria-describedby=${ifDefined(this.getDescribedBy())}\n aria-invalid=${ifDefined(this.getInvalid())}\n @change=${this.handleChange}\n />\n </div>`\n\n return html`<div class=\"n-flex\">${this.reverse ? [label, input] : [input, label]}</div>`\n }\n\n protected handleChange(e: Event): void {\n const target = e.target as HTMLInputElement\n this.checked = target.checked\n super.handleChange(e)\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-toggle': Toggle\n }\n}\n"],"names":["Toggle","FormAssociatedMixin","InputMixin","FocusableMixin","LitElement","constructor","this","checked","reverse","size","formValue","value","undefined","render","label","html","renderLabel","renderError","input","ref","focusableRef","inputId","ifDefined","name","disabled","required","getDescribedBy","getInvalid","handleChange","e","target","super","styles","componentStyle","formFieldStyle","style","__decorate","property","reflect","type","Boolean","prototype","customElement"],"mappings":"24FA4Be,IAAMA,EAAN,cAAqBC,EAAoBC,EAAWC,EAAeC,MAAnE,WAAAC,uBAU+BC,KAAOC,SAAY,EAMnBD,KAAOE,SAAY,EAKlCF,KAAIG,KAAoB,GA8BtD,CAhDC,aAAuBC,GACrB,OAAOJ,KAAKC,QAAUD,KAAKK,OAAS,UAAOC,CAC5C,CAkBD,MAAAC,GACE,MAAMC,EAAQC,CAAI,yBAAyBT,KAAKU,iBAAiBV,KAAKW,sBAChEC,EAAQH,CAAI,yCAEZI,EAAIb,KAAKc,sCAENd,KAAKe,gDAGHC,EAAUhB,KAAKiB,kBACbjB,KAAKK,oBACHL,KAAKC,uBACJD,KAAKkB,wBACLlB,KAAKmB,+BACEH,EAAUhB,KAAKoB,oCACnBJ,EAAUhB,KAAKqB,2BACpBrB,KAAKsB,uBAInB,OAAOb,CAAI,uBAAuBT,KAAKE,QAAU,CAACM,EAAOI,GAAS,CAACA,EAAOJ,UAC3E,CAES,YAAAc,CAAaC,GACrB,MAAMC,EAASD,EAAEC,OACjBxB,KAAKC,QAAUuB,EAAOvB,QACtBwB,MAAMH,aAAaC,EACpB,GAjDM7B,EAAMgC,OAAG,CAACC,EAAgBC,EAAgBC,GASLC,EAAA,CAA3CC,EAAS,CAAEC,SAAS,EAAMC,KAAMC,WAAmCxC,EAAAyC,UAAA,eAAA,GAMxBL,EAAA,CAA3CC,EAAS,CAAEC,SAAS,EAAMC,KAAMC,WAAmCxC,EAAAyC,UAAA,eAAA,GAKvCL,EAAA,CAA5BC,EAAS,CAAEC,SAAS,KAAmCtC,EAAAyC,UAAA,YAAA,GArBrCzC,EAAMoC,EAAA,CAD1BM,EAAc,gBACM1C,SAAAA"}
1
+ {"version":3,"file":"Toggle.js","sources":["../src/toggle/Toggle.ts"],"sourcesContent":["/* eslint-disable lit-a11y/role-has-required-aria-attrs */\nimport { html, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { ref } from 'lit/directives/ref.js'\n\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\n\nimport componentStyle from '../common/styles/Component.css'\nimport formFieldStyle from '../common/styles/FormField.css'\nimport style from './Toggle.css'\n\n/**\n * Toggle switch gives control over a feature or option that can be\n * turned on or off. If a physical switch would work for the action, a\n * toggle is probably the best component to use.\n *\n * @status ready\n * @category form\n * @slot label - Use when a label requires more than plain text.\n * @slot hint - Optional slot that holds hint text for the input.\n * @slot error - Optional slot that holds error text for the input.\n *\n * @cssprop [--n-label-color=var(--n-color-text)] - Controls the text color of the label, using our [color tokens](/tokens/#color).\n */\n@customElement('nord-toggle')\nexport default class Toggle extends FormAssociatedMixin(InputMixin(FocusableMixin(LitElement))) {\n static styles = [componentStyle, formFieldStyle, style]\n\n protected override get formValue() {\n return this.checked ? this.value || 'on' : undefined\n }\n\n /**\n * Controls whether the toggle is checked or not.\n */\n @property({ reflect: true, type: Boolean }) checked: boolean = false\n\n /**\n * Controls whether the contents are displayed in reverse order,\n * putting the label before the toggle.\n */\n @property({ reflect: true, type: Boolean }) reverse: boolean = false\n\n /**\n * The size of the toggle switch.\n */\n @property({ reflect: true }) size: 's' | 'm' | 'l' = 'm'\n\n render() {\n const label = html`\n <div class=\"n-expand\">\n ${this.renderLabel()}\n ${this.isHintBelow ? nothing : this.renderError()}\n </div>\n `\n const input = html`<div class=\"n-input-container\">\n <input\n ${ref(this.focusableRef)}\n class=\"n-toggle\"\n id=${this.inputId}\n type=\"checkbox\"\n role=\"switch\"\n name=${ifDefined(this.name)}\n .value=${this.value}\n .checked=${this.checked}\n ?disabled=${this.disabled}\n ?required=${this.required}\n aria-describedby=${ifDefined(this.getDescribedBy())}\n aria-invalid=${ifDefined(this.getInvalid())}\n @change=${this.handleChange}\n />\n </div>`\n\n return html`\n <div class=\"n-flex\">${this.reverse ? [label, input] : [input, label]}</div>\n ${this.isHintBelow ? this.renderError() : nothing}\n ${this.isHintBelow ? this.renderHint() : nothing}\n `\n }\n\n protected handleChange(e: Event): void {\n const target = e.target as HTMLInputElement\n this.checked = target.checked\n super.handleChange(e)\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-toggle': Toggle\n }\n}\n"],"names":["Toggle","FormAssociatedMixin","InputMixin","FocusableMixin","LitElement","constructor","this","checked","reverse","size","formValue","value","undefined","render","label","html","renderLabel","isHintBelow","nothing","renderError","input","ref","focusableRef","inputId","ifDefined","name","disabled","required","getDescribedBy","getInvalid","handleChange","renderHint","e","target","super","styles","componentStyle","formFieldStyle","style","__decorate","property","reflect","type","Boolean","prototype","customElement"],"mappings":"miGA4Be,IAAMA,EAAN,cAAqBC,EAAoBC,EAAWC,EAAeC,MAAnE,WAAAC,uBAU+BC,KAAOC,SAAY,EAMnBD,KAAOE,SAAY,EAKlCF,KAAIG,KAAoB,GAuCtD,CAzDC,aAAuBC,GACrB,OAAOJ,KAAKC,QAAUD,KAAKK,OAAS,UAAOC,CAC5C,CAkBD,MAAAC,GACE,MAAMC,EAAQC,CAAI,yBAEZT,KAAKU,iBACLV,KAAKW,YAAcC,EAAUZ,KAAKa,sBAGlCC,EAAQL,CAAI,yCAEZM,EAAIf,KAAKgB,sCAENhB,KAAKiB,gDAGHC,EAAUlB,KAAKmB,kBACbnB,KAAKK,oBACHL,KAAKC,uBACJD,KAAKoB,wBACLpB,KAAKqB,+BACEH,EAAUlB,KAAKsB,oCACnBJ,EAAUlB,KAAKuB,2BACpBvB,KAAKwB,uBAInB,OAAOf,CAAI,uBACaT,KAAKE,QAAU,CAACM,EAAOM,GAAS,CAACA,EAAON,WAC5DR,KAAKW,YAAcX,KAAKa,cAAgBD,KACxCZ,KAAKW,YAAcX,KAAKyB,aAAeb,GAE5C,CAES,YAAAY,CAAaE,GACrB,MAAMC,EAASD,EAAEC,OACjB3B,KAAKC,QAAU0B,EAAO1B,QACtB2B,MAAMJ,aAAaE,EACpB,GA1DMhC,EAAMmC,OAAG,CAACC,EAAgBC,EAAgBC,GASLC,EAAA,CAA3CC,EAAS,CAAEC,SAAS,EAAMC,KAAMC,WAAmC3C,EAAA4C,UAAA,eAAA,GAMxBL,EAAA,CAA3CC,EAAS,CAAEC,SAAS,EAAMC,KAAMC,WAAmC3C,EAAA4C,UAAA,eAAA,GAKvCL,EAAA,CAA5BC,EAAS,CAAEC,SAAS,KAAmCzC,EAAA4C,UAAA,YAAA,GArBrC5C,EAAMuC,EAAA,CAD1BM,EAAc,gBACM7C,SAAAA"}