@nordhealth/components 1.0.0-beta.10 → 1.0.0-beta.13

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/Button.js CHANGED
@@ -1,2 +1,2 @@
1
- import{_ as t,n as o}from"./query-assigned-elements-37b095c4.js";import{r as n,$ as e,w as r,s as a}from"./lit-element-9646ab7e.js";import{e as i}from"./property-03f59dce.js";import{l as s}from"./if-defined-2a4c6dbc.js";import{e as l,n as d}from"./ref-eb5cfa10.js";import{L as b}from"./LightDomController-f56fa1a4.js";import{F as c}from"./FocusableMixin-98e13999.js";import{I as u}from"./InputMixin-94d15730.js";import{s as v}from"./Component-6762b5eb.js";import"./directive-helpers-e7b6bf4b.js";import"./directive-de55b00a.js";const h=n`:host{display:inline-block}.n-button{-webkit-appearance:none;align-items:center;appearance:none;background:var(--n-button-background-color,var(--n-color-button));border-radius:var(--n-button-border-radius,var(--n-border-radius-s));border:1px var(--n-button-border-style,solid) var(--n-button-border-color,var(--n-color-border-strong));box-shadow:var(--n-button-box-shadow,var(--n-box-shadow));color:var(--n-button-color,var(--n-color-text));cursor:pointer;display:flex;gap:var(--n-button-gap,var(--n-space-s));font-family:var(--n-font-family);font-feature-settings:var(--n-font-features);font-size:var(--n-button-font-size,var(--n-font-size-m));font-weight:var(--n-button-font-weight,var(--n-font-weight));line-height:var(--n-line-height-form);margin:0;min-block-size:var(--n-button-min-height,var(--n-space-xl));padding:var(--n-button-padding-y,calc(var(--n-space-s)/ 1.6)) var(--n-button-padding-x,calc(var(--n-space-m)/ 1.2));text-align:var(--n-button-text-align,center);text-decoration:none;transition:all .1s ease;-webkit-user-select:none;user-select:none;position:relative;inline-size:var(--n-button-width,fit-content)}.n-button::after{content:"";position:absolute;background:0 0;background-image:var(--n-button-gradient,linear-gradient(to bottom,rgba(0,0,0,0) 50%,rgba(0,0,0,.013) 100%));background-repeat:repeat-x;inline-size:100%;inset-inline:0;block-size:100%;inset-block-start:0}:host([expand]){--n-button-width:100%;display:block}.n-content{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;position:relative}.n-button:hover{--n-button-background-color:var(--n-color-button-hover);--n-button-border-color:var(--n-color-border-hover)}.n-button:focus{--n-button-border-color:var(--n-color-primary);--n-button-border-style:solid;--n-button-box-shadow:0 0 0 1px var(--n-button-border-color);outline:0}.n-button:active{opacity:.8;transform:translateY(1px);transition:none}:host([variant=primary]){--n-button-background-color:var(--n-color-primary);--n-button-border-color:transparent;--n-button-box-shadow:none;--n-button-color:var(--n-color-text-inverse);--n-button-font-weight:var(--n-font-weight-active)}:host([variant=primary]) .n-button:focus{--n-button-box-shadow:0 0 0 1px var(--n-color-surface),0 0 0 3px var(--n-button-border-color)}:host([variant=primary]) .n-button:hover{--n-button-background-color:var(--n-color-primary-strong)}:host([variant=dashed]){--n-button-color:var(--n-color-text-weaker);--n-button-border-color:var(--n-color-border-hover);--n-button-border-style:dashed;--n-button-box-shadow:none}:host([variant=dashed]) .n-button:hover{--n-button-color:var(--n-color-text)}:host([variant=dashed]) .n-button::after{display:none}:host([variant=plain]){--n-button-border-color:transparent;--n-button-box-shadow:none}:host([variant=plain]) .n-button:hover{--n-button-border-color:transparent}:host([variant=plain]) .n-button:focus{--n-button-box-shadow:0 0 0 1px var(--n-button-border-color)}:host([variant=plain]) .n-button::after{display:none}:host([variant=danger]){--n-button-border-color:var(--n-color-status-danger);--n-button-color:var(--n-color-text-error);--n-button-font-weight:var(--n-font-weight-active)}:host([disabled]){--n-button-background-color:var(--n-color-border);--n-button-box-shadow:none;--n-button-border-color:var(--n-button-background-color);--n-button-color:var(--n-color-text-weaker);opacity:.5;pointer-events:none}:host([disabled]) .n-button::after{display:none}:host([size="s"]){--n-button-font-size:var(--n-font-size-s);--n-button-min-height:var(--n-space-l);--n-button-padding-y:calc(var(--n-space-s) / 1.5);--n-button-padding-x:var(--n-space-s);--n-button-gap:calc(var(--n-space-s) / 2)}:host([size="s"]) .n-button{line-height:var(--n-line-height-tight)}:host([size="l"]){--n-button-border-radius:var(--n-border-radius);--n-button-font-size:var(--n-font-size-l);--n-button-min-height:calc(var(--n-space-xxl) - var(--n-space-l));--n-button-padding-x:calc(var(--n-space-l) / 1.3);--n-button-font-weight:var(--n-font-weight-active)}::slotted(*){color:inherit;pointer-events:none}::slotted(svg){color:var(--n-color-icon)}::slotted(button[slot=proxy]){display:none}`;let p=class extends(u(c(a))){constructor(){super(...arguments),this.buttonRef=l(),this.lightDom=new b(this,{render:()=>this.renderLightDom()}),this.variant="default",this.type="submit",this.size="m",this.download=!1,this.target="_self",this.expand=!1,this.handleOuterClick=t=>{t.composedPath().some((t=>t===this.focusableRef.value))||t.stopPropagation()}}connectedCallback(){super.connectedCallback(),this.addEventListener("click",this.handleOuterClick,!0)}disconnectedCallback(){this.removeEventListener("click",this.handleOuterClick,!0)}render(){const t=e`<slot name="before"></slot><div class="n-content"><slot></slot></div><slot name="after"></slot>`;return this.href?this.renderLink(t):this.renderButton(t)}renderLink(t){return e`<a ${d(this.focusableRef)} class="n-button" target="${this.target}" ?download="${this.download}" href="${s(this.disabled?void 0:this.href)}" tabindex="${s(this.disabled?"-1":void 0)}" aria-disabled="${s(this.disabled?"true":void 0)}" role="${s(this.disabled?"link":void 0)}">${t}</a>`}renderButton(t){return e`<slot name="proxy"></slot><button ${d(this.focusableRef)} class="n-button" ?disabled="${this.disabled}" name="${s(this.name||void 0)}" value="${s(this.value||void 0)}" @click="${this.handleClick}">${t}</button>`}renderLightDom(){return this.href||!this.form?r:e`<button ${d(this.buttonRef)} slot="proxy" name="${s(this.name||void 0)}" value="${s(this.value||void 0)}" ?disabled="${this.disabled}" type="${this.type}"></button>`}handleClick(){var t;null===(t=this.buttonRef.value)||void 0===t||t.click()}};p.styles=[v,h],t([i({reflect:!0})],p.prototype,"variant",void 0),t([i({reflect:!0})],p.prototype,"type",void 0),t([i({reflect:!0})],p.prototype,"size",void 0),t([i({reflect:!0})],p.prototype,"href",void 0),t([i({type:Boolean})],p.prototype,"download",void 0),t([i({reflect:!0})],p.prototype,"target",void 0),t([i({reflect:!0,type:Boolean})],p.prototype,"expand",void 0),p=t([o("nord-button")],p);var f=p;export{f as default};
1
+ import{_ as t,n as o}from"./query-assigned-elements-37b095c4.js";import{r as n,$ as e,w as r,s as a}from"./lit-element-9646ab7e.js";import{e as i}from"./property-03f59dce.js";import{l as s}from"./if-defined-2a4c6dbc.js";import{e as l,n as b}from"./ref-eb5cfa10.js";import{L as d}from"./LightDomController-f56fa1a4.js";import{F as c}from"./FocusableMixin-98e13999.js";import{I as u}from"./InputMixin-94d15730.js";import{s as h}from"./Component-6762b5eb.js";import"./directive-helpers-e7b6bf4b.js";import"./directive-de55b00a.js";const v=n`:host{display:inline-block}.n-button{-webkit-appearance:none;align-items:center;appearance:none;background:var(--n-button-background-color,var(--n-color-button));border-radius:var(--n-button-border-radius,var(--n-border-radius-s));border:1px var(--n-button-border-style,solid) var(--n-button-border-color,var(--n-color-border-strong));box-shadow:var(--n-button-box-shadow,var(--n-box-shadow));color:var(--n-button-color,var(--n-color-text));cursor:pointer;display:flex;gap:var(--n-button-gap,var(--n-space-s));font-family:var(--n-font-family);font-feature-settings:var(--n-font-features);font-size:var(--n-button-font-size,var(--n-font-size-m));font-weight:var(--n-button-font-weight,var(--n-font-weight));line-height:var(--n-line-height-form);margin:0;min-block-size:var(--n-button-min-height,var(--n-space-xl));padding:var(--n-button-padding-y,calc(var(--n-space-s)/ 1.6)) var(--n-button-padding-x,calc(var(--n-space-m)/ 1.2));text-align:var(--n-button-text-align,center);text-decoration:none;transition:all .1s ease;-webkit-user-select:none;user-select:none;position:relative;inline-size:var(--n-button-width,fit-content)}.n-button::after{content:"";position:absolute;background:0 0;background-image:var(--n-button-gradient,linear-gradient(to bottom,rgba(0,0,0,0) 50%,rgba(0,0,0,.013) 100%));background-repeat:repeat-x;inline-size:100%;inset-inline:0;block-size:100%;inset-block-start:0}:host([expand]){--n-button-width:100%;display:block}.n-content{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;position:relative}.n-button:hover{--n-button-background-color:var(--n-color-button-hover);--n-button-border-color:var(--n-color-border-hover)}.n-button:focus{--n-button-border-color:var(--n-color-primary);--n-button-border-style:solid;--n-button-box-shadow:0 0 0 1px var(--n-button-border-color);outline:0}.n-button:active{opacity:.8;transform:translateY(1px);transition:none}:host([variant=primary]){--n-button-background-color:var(--n-color-primary);--n-button-border-color:transparent;--n-button-box-shadow:none;--n-button-color:var(--n-color-text-inverse);--n-button-font-weight:var(--n-font-weight-active)}:host([variant=primary]) .n-button:focus{--n-button-box-shadow:0 0 0 1px var(--n-color-surface),0 0 0 3px var(--n-button-border-color)}:host([variant=primary]) .n-button:hover{--n-button-border-color:transparent;--n-button-background-color:var(--n-color-primary);filter:brightness(93%)}:host([variant=dashed]){--n-button-color:var(--n-color-text-weaker);--n-button-border-color:var(--n-color-border-hover);--n-button-border-style:dashed;--n-button-box-shadow:none}:host([variant=dashed]) .n-button:hover{--n-button-color:var(--n-color-text)}:host([variant=dashed]) .n-button::after{display:none}:host([variant=plain]){--n-button-border-color:transparent;--n-button-box-shadow:none}:host([variant=plain]) .n-button:hover{--n-button-border-color:transparent}:host([variant=plain]) .n-button:focus{--n-button-box-shadow:0 0 0 1px var(--n-button-border-color)}:host([variant=plain]) .n-button::after{display:none}:host([variant=danger]){--n-button-border-color:var(--n-color-status-danger);--n-button-color:var(--n-color-text-error);--n-button-font-weight:var(--n-font-weight-active)}:host([variant=danger]) .n-button:hover{--n-button-border-color:var(--n-color-status-danger)}:host([disabled]){--n-button-background-color:var(--n-color-border);--n-button-box-shadow:none;--n-button-border-color:var(--n-button-background-color);--n-button-color:var(--n-color-text-weaker);opacity:.5;pointer-events:none}:host([disabled]) .n-button::after{display:none}:host([size="s"]){--n-button-font-size:var(--n-font-size-s);--n-button-min-height:var(--n-space-l);--n-button-padding-y:calc(var(--n-space-s) / 1.5);--n-button-padding-x:var(--n-space-s);--n-button-gap:calc(var(--n-space-s) / 2)}:host([size="s"]) .n-button{line-height:var(--n-line-height-tight)}:host([size="l"]){--n-button-border-radius:var(--n-border-radius);--n-button-font-size:var(--n-font-size-l);--n-button-min-height:calc(var(--n-space-xxl) - var(--n-space-l));--n-button-padding-x:calc(var(--n-space-l) / 1.3);--n-button-font-weight:var(--n-font-weight-active)}::slotted(*){color:inherit;pointer-events:none}::slotted(svg){color:var(--n-color-icon)}::slotted(button[slot=proxy]){display:none}`;let p=class extends(u(c(a))){constructor(){super(...arguments),this.buttonRef=l(),this.lightDom=new d(this,{render:()=>this.renderLightDom()}),this.variant="default",this.type="submit",this.size="m",this.download=!1,this.target="_self",this.expand=!1,this.handleOuterClick=t=>{t.composedPath().some((t=>t===this.focusableRef.value||t===this.buttonRef.value))||t.stopPropagation()}}connectedCallback(){super.connectedCallback(),this.addEventListener("click",this.handleOuterClick,!0)}disconnectedCallback(){this.removeEventListener("click",this.handleOuterClick,!0)}render(){const t=e`<slot name="before"></slot><div class="n-content"><slot></slot></div><slot name="after"></slot>`;return this.href?this.renderLink(t):this.renderButton(t)}renderLink(t){return e`<a ${b(this.focusableRef)} class="n-button" target="${this.target}" ?download="${this.download}" href="${s(this.disabled?void 0:this.href)}" tabindex="${s(this.disabled?"-1":void 0)}" aria-disabled="${s(this.disabled?"true":void 0)}" role="${s(this.disabled?"link":void 0)}">${t}</a>`}renderButton(t){return e`<slot name="proxy"></slot><button ${b(this.focusableRef)} class="n-button" ?disabled="${this.disabled}" name="${s(this.name||void 0)}" value="${s(this.value||void 0)}" @click="${this.handleClick}">${t}</button>`}renderLightDom(){return this.href||!this.form?r:e`<button ${b(this.buttonRef)} slot="proxy" name="${s(this.name||void 0)}" value="${s(this.value||void 0)}" ?disabled="${this.disabled}" type="${this.type}"></button>`}handleClick(t){this.buttonRef.value&&(t.stopPropagation(),this.buttonRef.value.click())}};p.styles=[h,v],t([i({reflect:!0})],p.prototype,"variant",void 0),t([i({reflect:!0})],p.prototype,"type",void 0),t([i({reflect:!0})],p.prototype,"size",void 0),t([i({reflect:!0})],p.prototype,"href",void 0),t([i({type:Boolean})],p.prototype,"download",void 0),t([i({reflect:!0})],p.prototype,"target",void 0),t([i({reflect:!0,type:Boolean})],p.prototype,"expand",void 0),p=t([o("nord-button")],p);var f=p;export{f as default};
2
2
  //# sourceMappingURL=Button.js.map
package/lib/Button.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Button.js","sources":["../src/button/Button.ts"],"sourcesContent":["import { LitElement, html, nothing, TemplateResult } from \"lit\"\nimport { customElement, property } from \"lit/decorators.js\"\nimport { ifDefined } from \"lit/directives/if-defined.js\"\nimport { createRef, ref } from \"lit/directives/ref.js\"\nimport { LightDomController } from \"../common/controllers/LightDomController.js\"\n\nimport { FocusableMixin } from \"../common/mixins/FocusableMixin.js\"\nimport { InputMixin } from \"../common/mixins/InputMixin.js\"\nimport componentStyle from \"../common/styles/Component.css\"\nimport style from \"./Button.css\"\n\n/**\n * Buttons are used for interface actions. Primary style should be\n * used only once per section for main call-to-action, while other\n * styles can appear more frequently.\n *\n * @status ready\n * @category action\n * @slot - The button content\n * @slot before - Used to place content before button text. Typically used for icons.\n * @slot after - Used to place content after button text. Typically used for icons.\n */\n@customElement(\"nord-button\")\nexport default class Button extends InputMixin(FocusableMixin(LitElement)) {\n static styles = [componentStyle, style]\n\n private buttonRef = createRef<HTMLButtonElement>()\n private lightDom = new LightDomController(this, {\n render: () => this.renderLightDom(),\n })\n\n /**\n * The style variant of the button.\n */\n @property({ reflect: true }) variant: \"default\" | \"primary\" | \"dashed\" | \"plain\" | \"danger\" = \"default\"\n\n /**\n * The type of the button.\n */\n @property({ reflect: true }) type: \"button\" | \"submit\" | \"reset\" = \"submit\"\n\n /**\n * The size of the button.\n * This affects font-size and padding.\n */\n @property({ reflect: true }) size: \"s\" | \"m\" | \"l\" = \"m\"\n\n /**\n * When provided, renders the button as a link,\n * with its href attribute set to the given value.\n */\n @property({ reflect: true }) href?: string\n\n /**\n * When provided together with a href property, the button will\n * trigger a file download instead of a page visit.\n */\n @property({ type: Boolean }) download = false\n\n /**\n * When provided together with a href property, determines where\n * to open the linked URL. The keywords have special meanings for\n * where to load the URL: “_self” means the current browsing context,\n * “_blank” usually a new tab but users can configure browsers this to\n * open a new window instead, “_parent” means the parent browsing\n * context of the current one, but if no parent exists, behaves as\n * _self, and finally “top” means the topmost browsing context.\n */\n @property({ reflect: true }) target: \"_self\" | \"_blank\" | \"_parent\" | \"_top\" = \"_self\"\n\n /**\n * Controls whether the button expands to fill the width of its container.\n */\n @property({ reflect: true, type: Boolean }) expand = false\n\n connectedCallback() {\n super.connectedCallback()\n this.addEventListener(\"click\", this.handleOuterClick, true)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"click\", this.handleOuterClick, true)\n }\n\n render() {\n const innards = html`\n <slot name=\"before\"></slot>\n <div class=\"n-content\">\n <slot></slot>\n </div>\n <slot name=\"after\"></slot>\n `\n\n return this.href ? this.renderLink(innards) : this.renderButton(innards)\n }\n\n /**\n * We jump through some hoops here to ensure the link is treated correctly when \"disabled\".\n * Links cannot be disabled natively, so we need to rely on some aria magic to get the correct semantics.\n * Along with the advice in the article below, we also set tabindex to \"-1\", so it is taken out of tab order.\n *\n * @see https://www.scottohara.me/blog/2021/05/28/disabled-links.html\n */\n private renderLink(innards: TemplateResult) {\n return html`\n <a\n ${ref(this.focusableRef)}\n class=\"n-button\"\n target=${this.target}\n ?download=${this.download}\n href=${ifDefined(this.disabled ? undefined : this.href)}\n tabindex=${ifDefined(this.disabled ? \"-1\" : undefined)}\n aria-disabled=${ifDefined(this.disabled ? \"true\" : undefined)}\n role=${ifDefined(this.disabled ? \"link\" : undefined)}\n >${innards}\n </a>\n `\n }\n\n private renderButton(innards: TemplateResult) {\n return html`\n <slot name=\"proxy\"></slot>\n <button\n ${ref(this.focusableRef)}\n class=\"n-button\"\n ?disabled=${this.disabled}\n name=${ifDefined(this.name || undefined)}\n value=${ifDefined(this.value || undefined)}\n @click=${this.handleClick}\n >\n ${innards}\n </button>\n `\n }\n\n private renderLightDom() {\n if (this.href || !this.form) {\n return nothing\n }\n\n return html`\n <button\n ${ref(this.buttonRef)}\n slot=\"proxy\"\n name=${ifDefined(this.name || undefined)}\n value=${ifDefined(this.value || undefined)}\n ?disabled=${this.disabled}\n type=${this.type}\n ></button>\n `\n }\n\n private handleOuterClick = (e: MouseEvent) => {\n const isInternalButton = e.composedPath().some(node => node === this.focusableRef.value)\n\n if (!isInternalButton) {\n e.stopPropagation()\n }\n }\n\n private handleClick() {\n this.buttonRef.value?.click()\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"nord-button\": Button\n }\n}\n"],"names":["Button","InputMixin","FocusableMixin","LitElement","constructor","this","createRef","LightDomController","render","renderLightDom","e","composedPath","some","node","focusableRef","value","stopPropagation","connectedCallback","super","addEventListener","handleOuterClick","disconnectedCallback","removeEventListener","innards","html","href","renderLink","renderButton","ref","target","download","ifDefined","disabled","undefined","name","handleClick","form","nothing","buttonRef","type","click","componentStyle","style","__decorate","property","reflect","Boolean","customElement"],"mappings":"kkJAuBA,IAAqBA,EAArB,cAAoCC,EAAWC,EAAeC,KAA9DC,kCAGUC,eAAYC,IACZD,cAAW,IAAIE,EAAmBF,KAAM,CAC9CG,OAAQ,IAAMH,KAAKI,mBAMQJ,aAAiE,UAKjEA,UAAsC,SAMtCA,UAAwB,IAYxBA,eAAW,EAWXA,YAAkD,QAKnCA,aAAS,EA+E7CA,sBAAoBK,IACDA,EAAEC,eAAeC,MAAKC,GAAQA,IAASR,KAAKS,aAAaC,SAGhFL,EAAEM,mBAjFNC,oBACEC,MAAMD,oBACNZ,KAAKc,iBAAiB,QAASd,KAAKe,kBAAkB,GAGxDC,uBACEhB,KAAKiB,oBAAoB,QAASjB,KAAKe,kBAAkB,GAG3DZ,SACE,MAAMe,EAAUC,CAAI,kGAQpB,OAAOnB,KAAKoB,KAAOpB,KAAKqB,WAAWH,GAAWlB,KAAKsB,aAAaJ,GAU1DG,WAAWH,GACjB,OAAOC,CAAI,MAELI,EAAIvB,KAAKS,0CAEFT,KAAKwB,sBACFxB,KAAKyB,mBACVC,EAAU1B,KAAK2B,cAAWC,EAAY5B,KAAKoB,oBACvCM,EAAU1B,KAAK2B,SAAW,UAAOC,sBAC5BF,EAAU1B,KAAK2B,SAAW,YAASC,aAC5CF,EAAU1B,KAAK2B,SAAW,YAASC,OACvCV,QAKDI,aAAaJ,GACnB,OAAOC,CAAI,qCAGLI,EAAIvB,KAAKS,6CAECT,KAAK2B,mBACVD,EAAU1B,KAAK6B,WAAQD,cACtBF,EAAU1B,KAAKU,YAASkB,eACvB5B,KAAK8B,gBAEZZ,aAKAd,iBACN,OAAIJ,KAAKoB,OAASpB,KAAK+B,KACdC,EAGFb,CAAI,WAELI,EAAIvB,KAAKiC,iCAEJP,EAAU1B,KAAK6B,WAAQD,cACtBF,EAAU1B,KAAKU,YAASkB,kBACpB5B,KAAK2B,mBACV3B,KAAKkC,kBAaVJ,8BACN9B,KAAKiC,UAAUvB,sBAAOyB,UAzIjBxC,SAAS,CAACyC,EAAgBC,GAUJC,GAA5BC,EAAS,CAAEC,SAAS,mCAKQF,GAA5BC,EAAS,CAAEC,SAAS,gCAMQF,GAA5BC,EAAS,CAAEC,SAAS,gCAMQF,GAA5BC,EAAS,CAAEC,SAAS,gCAMQF,GAA5BC,EAAS,CAAEL,KAAMO,0CAWWH,GAA5BC,EAAS,CAAEC,SAAS,kCAKuBF,GAA3CC,EAAS,CAAEC,SAAS,EAAMN,KAAMO,wCAlDd9C,KADpB+C,EAAc,gBACM/C,SAAAA"}
1
+ {"version":3,"file":"Button.js","sources":["../src/button/Button.ts"],"sourcesContent":["import { LitElement, html, nothing, TemplateResult } from \"lit\"\nimport { customElement, property } from \"lit/decorators.js\"\nimport { ifDefined } from \"lit/directives/if-defined.js\"\nimport { createRef, ref } from \"lit/directives/ref.js\"\nimport { LightDomController } from \"../common/controllers/LightDomController.js\"\n\nimport { FocusableMixin } from \"../common/mixins/FocusableMixin.js\"\nimport { InputMixin } from \"../common/mixins/InputMixin.js\"\nimport componentStyle from \"../common/styles/Component.css\"\nimport style from \"./Button.css\"\n\n/**\n * Buttons are used for interface actions. Primary style should be\n * used only once per section for main call-to-action, while other\n * styles can appear more frequently.\n *\n * @status ready\n * @category action\n * @slot - The button content\n * @slot before - Used to place content before button text. Typically used for icons.\n * @slot after - Used to place content after button text. Typically used for icons.\n */\n@customElement(\"nord-button\")\nexport default class Button extends InputMixin(FocusableMixin(LitElement)) {\n static styles = [componentStyle, style]\n\n private buttonRef = createRef<HTMLButtonElement>()\n private lightDom = new LightDomController(this, {\n render: () => this.renderLightDom(),\n })\n\n /**\n * The style variant of the button.\n */\n @property({ reflect: true }) variant: \"default\" | \"primary\" | \"dashed\" | \"plain\" | \"danger\" = \"default\"\n\n /**\n * The type of the button.\n */\n @property({ reflect: true }) type: \"button\" | \"submit\" | \"reset\" = \"submit\"\n\n /**\n * The size of the button.\n * This affects font-size and padding.\n */\n @property({ reflect: true }) size: \"s\" | \"m\" | \"l\" = \"m\"\n\n /**\n * When provided, renders the button as a link,\n * with its href attribute set to the given value.\n */\n @property({ reflect: true }) href?: string\n\n /**\n * When provided together with a href property, the button will\n * trigger a file download instead of a page visit.\n */\n @property({ type: Boolean }) download = false\n\n /**\n * When provided together with a href property, determines where\n * to open the linked URL. The keywords have special meanings for\n * where to load the URL: “_self” means the current browsing context,\n * “_blank” usually a new tab but users can configure browsers this to\n * open a new window instead, “_parent” means the parent browsing\n * context of the current one, but if no parent exists, behaves as\n * _self, and finally “top” means the topmost browsing context.\n */\n @property({ reflect: true }) target: \"_self\" | \"_blank\" | \"_parent\" | \"_top\" = \"_self\"\n\n /**\n * Controls whether the button expands to fill the width of its container.\n */\n @property({ reflect: true, type: Boolean }) expand = false\n\n connectedCallback() {\n super.connectedCallback()\n this.addEventListener(\"click\", this.handleOuterClick, true)\n }\n\n disconnectedCallback() {\n this.removeEventListener(\"click\", this.handleOuterClick, true)\n }\n\n render() {\n const innards = html`\n <slot name=\"before\"></slot>\n <div class=\"n-content\">\n <slot></slot>\n </div>\n <slot name=\"after\"></slot>\n `\n\n return this.href ? this.renderLink(innards) : this.renderButton(innards)\n }\n\n /**\n * We jump through some hoops here to ensure the link is treated correctly when \"disabled\".\n * Links cannot be disabled natively, so we need to rely on some aria magic to get the correct semantics.\n * Along with the advice in the article below, we also set tabindex to \"-1\", so it is taken out of tab order.\n *\n * @see https://www.scottohara.me/blog/2021/05/28/disabled-links.html\n */\n private renderLink(innards: TemplateResult) {\n return html`\n <a\n ${ref(this.focusableRef)}\n class=\"n-button\"\n target=${this.target}\n ?download=${this.download}\n href=${ifDefined(this.disabled ? undefined : this.href)}\n tabindex=${ifDefined(this.disabled ? \"-1\" : undefined)}\n aria-disabled=${ifDefined(this.disabled ? \"true\" : undefined)}\n role=${ifDefined(this.disabled ? \"link\" : undefined)}\n >${innards}\n </a>\n `\n }\n\n private renderButton(innards: TemplateResult) {\n return html`\n <slot name=\"proxy\"></slot>\n <button\n ${ref(this.focusableRef)}\n class=\"n-button\"\n ?disabled=${this.disabled}\n name=${ifDefined(this.name || undefined)}\n value=${ifDefined(this.value || undefined)}\n @click=${this.handleClick}\n >\n ${innards}\n </button>\n `\n }\n\n private renderLightDom() {\n if (this.href || !this.form) {\n return nothing\n }\n\n return html`\n <button\n ${ref(this.buttonRef)}\n slot=\"proxy\"\n name=${ifDefined(this.name || undefined)}\n value=${ifDefined(this.value || undefined)}\n ?disabled=${this.disabled}\n type=${this.type}\n ></button>\n `\n }\n\n private handleOuterClick = (e: MouseEvent) => {\n // we want to avoid emitting click events when a click\n // happens in blank space in the host, but not on the button\n // so we stop propagation of any events if click didn't happen on the internal or proxy button\n const isInternalButton = e\n .composedPath()\n .some(node => node === this.focusableRef.value || node === this.buttonRef.value)\n\n if (!isInternalButton) {\n e.stopPropagation()\n }\n }\n\n private handleClick(e: Event) {\n if (this.buttonRef.value) {\n // prevents two events: one from internal button, one from proxy button\n e.stopPropagation()\n this.buttonRef.value.click()\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"nord-button\": Button\n }\n}\n"],"names":["Button","InputMixin","FocusableMixin","LitElement","constructor","this","createRef","LightDomController","render","renderLightDom","e","composedPath","some","node","focusableRef","value","buttonRef","stopPropagation","connectedCallback","super","addEventListener","handleOuterClick","disconnectedCallback","removeEventListener","innards","html","href","renderLink","renderButton","ref","target","download","ifDefined","disabled","undefined","name","handleClick","form","nothing","type","click","componentStyle","style","__decorate","property","reflect","Boolean","customElement"],"mappings":"mtJAuBA,IAAqBA,EAArB,cAAoCC,EAAWC,EAAeC,KAA9DC,kCAGUC,eAAYC,IACZD,cAAW,IAAIE,EAAmBF,KAAM,CAC9CG,OAAQ,IAAMH,KAAKI,mBAMQJ,aAAiE,UAKjEA,UAAsC,SAMtCA,UAAwB,IAYxBA,eAAW,EAWXA,YAAkD,QAKnCA,aAAS,EA+E7CA,sBAAoBK,IAIDA,EACtBC,eACAC,MAAKC,GAAQA,IAASR,KAAKS,aAAaC,OAASF,IAASR,KAAKW,UAAUD,SAG1EL,EAAEO,mBAtFNC,oBACEC,MAAMD,oBACNb,KAAKe,iBAAiB,QAASf,KAAKgB,kBAAkB,GAGxDC,uBACEjB,KAAKkB,oBAAoB,QAASlB,KAAKgB,kBAAkB,GAG3Db,SACE,MAAMgB,EAAUC,CAAI,kGAQpB,OAAOpB,KAAKqB,KAAOrB,KAAKsB,WAAWH,GAAWnB,KAAKuB,aAAaJ,GAU1DG,WAAWH,GACjB,OAAOC,CAAI,MAELI,EAAIxB,KAAKS,0CAEFT,KAAKyB,sBACFzB,KAAK0B,mBACVC,EAAU3B,KAAK4B,cAAWC,EAAY7B,KAAKqB,oBACvCM,EAAU3B,KAAK4B,SAAW,UAAOC,sBAC5BF,EAAU3B,KAAK4B,SAAW,YAASC,aAC5CF,EAAU3B,KAAK4B,SAAW,YAASC,OACvCV,QAKDI,aAAaJ,GACnB,OAAOC,CAAI,qCAGLI,EAAIxB,KAAKS,6CAECT,KAAK4B,mBACVD,EAAU3B,KAAK8B,WAAQD,cACtBF,EAAU3B,KAAKU,YAASmB,eACvB7B,KAAK+B,gBAEZZ,aAKAf,iBACN,OAAIJ,KAAKqB,OAASrB,KAAKgC,KACdC,EAGFb,CAAI,WAELI,EAAIxB,KAAKW,iCAEJgB,EAAU3B,KAAK8B,WAAQD,cACtBF,EAAU3B,KAAKU,YAASmB,kBACpB7B,KAAK4B,mBACV5B,KAAKkC,kBAkBVH,YAAY1B,GACdL,KAAKW,UAAUD,QAEjBL,EAAEO,kBACFZ,KAAKW,UAAUD,MAAMyB,WAjJlBxC,SAAS,CAACyC,EAAgBC,GAUJC,GAA5BC,EAAS,CAAEC,SAAS,mCAKQF,GAA5BC,EAAS,CAAEC,SAAS,gCAMQF,GAA5BC,EAAS,CAAEC,SAAS,gCAMQF,GAA5BC,EAAS,CAAEC,SAAS,gCAMQF,GAA5BC,EAAS,CAAEL,KAAMO,0CAWWH,GAA5BC,EAAS,CAAEC,SAAS,kCAKuBF,GAA3CC,EAAS,CAAEC,SAAS,EAAMN,KAAMO,wCAlDd9C,KADpB+C,EAAc,gBACM/C,SAAAA"}
@@ -1,2 +1,2 @@
1
- import{_ as e,n as o}from"./query-assigned-elements-37b095c4.js";import{r as t,s as n,$ as s,w as r}from"./lit-element-9646ab7e.js";import{e as i}from"./property-03f59dce.js";import{t as a}from"./state-70f38ceb.js";import{c as l,w as d}from"./number-e7cd246c.js";import{e as c,n as p}from"./ref-eb5cfa10.js";import{o as m}from"./class-map-61e9e8c1.js";import{l as h}from"./if-defined-2a4c6dbc.js";import{g as v}from"./collection-f3631dc8.js";import{N as u}from"./events-731d0007.js";import{L as f}from"./LightDismissController-cc5b4bf2.js";import{KeyboardController as b}from"./KeyboardController.js";import g from"./Icon.js";import"./VisuallyHidden.js";import"./CommandMenuAction.js";import{SelectEvent as x}from"./SelectEvent.js";import{s as y}from"./Component-6762b5eb.js";import"./directive-de55b00a.js";import"./directive-helpers-e7b6bf4b.js";import"./ShortcutController-93173ff4.js";import"./tinykeys.module-84e6cc41.js";import"./unsafe-html-4da54dd2.js";const w="keyboard-arrow-up-down";var k=Object.freeze({__proto__:null,default:'<svg viewBox="0 0 140 140" xmlns="http://www.w3.org/2000/svg"><path d="M105.833 24v93m0-93L80 49.833M105.833 24l25.834 25.833M34.167 117V24m0 93L60 91.167M34.167 117 8.333 91.167" fill="none" stroke="currentColor" stroke-width="14" stroke-linecap="round" stroke-linejoin="round"/></svg>',title:w,tags:"nordicon keyboard keys arrow up down shortcut"});var z=Object.freeze({__proto__:null,default:'<svg viewBox="0 0 140 140" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="14"><path d="M35 133 7 105l28-28"/><path d="M7 105h112a14 14 0 0 0 14-14V21a14 14 0 0 0-14-14H77"/></g></svg>',title:"keyboard-return",tags:"nordicon keyboard return key shortcut"});const $="keyboard-backspace";var j=Object.freeze({__proto__:null,default:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="currentColor" fill-rule="evenodd" d="M6.707 4.879A3 3 0 0 1 8.828 4H15a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H8.828a3 3 0 0 1-2.12-.879l-4.415-4.414a1 1 0 0 1 0-1.414l4.414-4.414zm4 2.414a1 1 0 0 0-1.414 1.414L10.586 10l-1.293 1.293a1 1 0 1 0 1.414 1.414L12 11.414l1.293 1.293a1 1 0 0 0 1.414-1.414L13.414 10l1.293-1.293a1 1 0 0 0-1.414-1.414L12 8.586l-1.293-1.293z" clip-rule="evenodd"/></svg>',title:$,tags:"nordicon keyboard backspace back delete key shortcut"});function C(e){var o;return(null===(o=e.activeElement)||void 0===o?void 0:o.shadowRoot)?C(e.activeElement.shadowRoot):e.activeElement||void 0}const I=t`:host{--n-command-menu-width:640px;--n-command-menu-top:16%;--n-command-menu-height:290px}.n-modal{display:none;position:fixed;pointer-events:none;z-index:var(--n-index-modal);inset-inline-start:0;inset-block-start:0;inline-size:100%;block-size:100%;overflow:auto}.n-modal.n-visible{display:block}.n-modal-content{position:relative;pointer-events:all;inset-block-start:var(--n-command-menu-top);margin:auto;display:flex;flex-direction:column;min-inline-size:0;background:var(--n-color-surface);border-radius:var(--n-border-radius);box-shadow:var(--n-box-shadow-modal);max-inline-size:var(--n-command-menu-width);overflow:hidden}.n-bump{animation:zoom-in-zoom-out var(--n-transition-slowly)}@keyframes zoom-in-zoom-out{0%{transform:translateY(-10px) scale(.97);opacity:0}100%{transform:translateY(0) scale(1.0001);opacity:1}}.n-modal-footer{display:flex;gap:var(--n-space-s);padding:var(--n-space-s) var(--n-space-m);font-size:calc(var(--n-font-size-s) - 1px);color:var(--n-color-text-weaker)}.n-help{display:flex;align-items:center;gap:2px}.n-help+.n-help{padding-inline-start:var(--n-space-s);border-inline-start:1px solid var(--n-color-border-strong)}.n-help nord-icon{--n-icon-size:10px;color:currentColor;margin:3px 4px}.n-help.n-backspace nord-icon{--n-icon-size:12px}.n-search-wrapper{display:flex;border-block-end:1px solid var(--n-color-border)}[role=combobox]{flex:1;font-size:var(--n-font-size-l);font-weight:var(--n-font-weight);font-family:inherit;background:0 0;color:var(--n-color-text);border:none;border-radius:0;appearance:none;outline:0;margin:0;padding:var(--n-space-m)}[role=combobox]::-webkit-input-placeholder{color:var(--n-color-text-weaker);opacity:.6!important}[role=combobox]::-moz-placeholder{color:var(--n-color-text-weaker);opacity:.6!important}[role=combobox]::-ms-input-placeholder{color:var(--n-color-text-weaker);opacity:.6!important}[role=listbox]{max-block-size:var(--n-command-menu-height);overflow:auto;margin:0;padding:0}.n-group-header{line-height:var(--n-line-height);border-block-end:1px solid var(--n-color-border);padding:calc(var(--n-space-s)/ 1.4) var(--n-space-m);text-overflow:ellipsis;white-space:nowrap;overflow:hidden;font-size:var(--n-font-size-s);background:var(--n-color-surface-raised);font-weight:var(--n-font-weight-active);color:var(--n-color-text-weaker)}.n-command-empty{display:flex;flex:1;flex-direction:column;border-inline-start:2px solid transparent;align-items:flex-start;color:var(--n-color-text);border-block-end:1px solid var(--n-color-border);padding:calc(var(--n-space-m)/ 1.5) var(--n-space-m)}.n-command-empty .n-title{flex:1;margin-block-start:var(--n-space-s);margin-inline-end:calc(var(--n-space-s)/ 2);max-inline-size:100%;font-size:var(--n-font-size-m);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.n-command-empty .n-tip{flex:1;margin-block-start:var(--n-space-s);margin-block-end:var(--n-space-m);font-size:var(--n-font-size-s);color:var(--n-color-text-weaker)}`;g.registerIcon(k),g.registerIcon(z),g.registerIcon(j);let E=class extends n{constructor(){super(...arguments),this.inputRef=c(),this.listRef=c(),this.dismissController=new f(this,{isOpen:()=>this.open,onDismiss:()=>this.close()}),this.keyboardController=new b(this,{trigger:()=>this.select(),goBack:()=>this.goBack(),end:()=>this.end(),start:()=>this.start(),next:()=>this.next(),previous:()=>this.previous(),toggleOpen:()=>this.toggleOpen()}),this.open=!1,this.placeholder="Type a command or search...",this.commands=[],this.search="",this.bump=!0,this.selectedIndex=0,this.filteredCommands=[]}get selected(){return this.filteredCommands[this.selectedIndex]}show(e={}){this.open=!0,this.setParent(e.parent),this.dispatchEvent(new u("open"))}close(){var e;this.open=!1,null===(e=this.previousFocus)||void 0===e||e.focus(),this.previousFocus=void 0,this.dispatchEvent(new u("close"))}toggleOpen(){this.open?this.close():this.show()}focus(){var e;null===(e=this.inputRef.value)||void 0===e||e.focus()}willUpdate(e){e.has("commands")&&this.keyboardController.registerCommandShortcuts(),e.has("open")&&this.open&&(this.bump=!0),(e.has("search")||e.has("parent")||e.has("commands"))&&this.filterCommands()}updated(e){e.has("open")&&this.open&&(this.previousFocus=C(document),this.focus(),this.listRef.value&&(this.listRef.value.scrollTop=0))}render(){var e;const o=v(this.filteredCommands,"section"),t=0===this.filteredCommands.length?"no-results":null===(e=this.selected)||void 0===e?void 0:e.id;return s`<div class="${m({"n-visible":this.open,"n-modal":!0})}"><div @animationend="${this.handleAnimationEnd}" class="${m({"n-bump":this.bump,"n-modal-content":!0})}"><div class="n-search-wrapper"><nord-visually-hidden id="instructions">Press 'Enter' to confirm your input or 'Escape' to cancel</nord-visually-hidden><input type="text" id="search" @input="${this.handleInput}" @blur="${this.handleBlur}" ${p(this.inputRef)} placeholder="${this.placeholder}" .value="${this.search}" spellcheck="false" autocomplete="off" autocapitalize="off" aria-label="Type the name of a command to run." aria-autocomplete="list" aria-haspopup="listbox" role="combobox" aria-controls="list" aria-expanded="true" aria-activedescendant="${h(t)}" aria-describedby="instructions"></div><div class="n-modal-body"><div id="list" ${p(this.listRef)} role="listbox">${0===this.filteredCommands.length?this.renderNoResults():Array.from(o,(([e,o])=>this.renderSection(e,o)))}</div></div><slot name="footer"><div class="n-modal-footer" slot="footer"><span class="n-help"><nord-icon label="Arrow keys" name="${w}"></nord-icon>Navigate</span> <span class="n-help"><nord-icon label="Enter key" name="${"keyboard-return"}"></nord-icon>Select</span> <span class="n-help">Esc to dismiss</span> <span class="n-help n-backspace"><nord-icon label="Backspace key" name="${$}"></nord-icon>Move to parent</span></div></slot></div></div>`}renderNoResults(){return s`<div id="no-results" class="n-command-empty" role="option" aria-selected="true"><div class="n-title">No results for “${this.search}”</div><div class="n-tip">Search tips: some search terms require exact match. Try typing the entire command name, or use a different word or phrase.</div></div>`}renderSection(e,o){const t=`section-${e}`;return s`<div role="group" aria-labelledby="${h(e?t:void 0)}">${e?s`<div class="n-group-header" role="presentation" id="${h(t)}">${e}</div>`:r} ${l(o,(e=>e.id),(e=>{var o,t;return s`<nord-command-menu-action id="${e.id}" .command="${e}" ?selected="${e.id===(null===(o=this.selected)||void 0===o?void 0:o.id)}" @click="${()=>this.select(e)}" role="option" aria-selected="${h(e.id===(null===(t=this.selected)||void 0===t?void 0:t.id)||void 0)}"></nord-command-menu-action>`}))}</div>`}handleAnimationEnd(){this.bump=!1}handleBlur(){this.open&&this.focus()}handleInput(e){const o=e.target;this.setSearch(o.value)}select(e=this.selected){var o;this.commands.some((o=>o.parent===e.id))?(this.setParent(e.id),this.bump=!0,this.focus()):this.close(),this.setSearch(""),null===(o=e.handler)||void 0===o||o.call(e,this);const t=new x(e);this.dispatchEvent(t)}start(){this.selectedIndex=0}end(){this.selectedIndex=this.filteredCommands.length-1}next(){this.selectedIndex=d(this.selectedIndex+1,0,this.filteredCommands.length-1)}previous(){this.selectedIndex=d(this.selectedIndex-1,0,this.filteredCommands.length-1)}goBack(){if(!this.search&&this.parent){const e=this.commands.find((e=>e.id===this.parent));this.setParent(null==e?void 0:e.parent)}}setParent(e){this.parent=e,this.setSearch("")}setSearch(e){this.search=e,this.selectedIndex=0}filterCommands(){const e=this.search.toLocaleLowerCase().split(/\s+/);this.filteredCommands=this.commands.filter((({title:o,keywords:t="",parent:n})=>{const s=`${o} ${t}`.toLocaleLowerCase(),r=e.every((e=>s.includes(e)));return(!this.parent&&this.search||n===this.parent)&&r}))}};E.styles=[y,I],e([i({type:Boolean})],E.prototype,"open",void 0),e([i({type:String})],E.prototype,"placeholder",void 0),e([i({type:Array,attribute:!1})],E.prototype,"commands",void 0),e([a()],E.prototype,"parent",void 0),e([a()],E.prototype,"search",void 0),e([a()],E.prototype,"bump",void 0),e([a()],E.prototype,"selectedIndex",void 0),e([a()],E.prototype,"filteredCommands",void 0),E=e([o("nord-command-menu")],E);var _=E;export{_ as default};
1
+ import{_ as e,n as o}from"./query-assigned-elements-37b095c4.js";import{r as t,s as n,$ as s,w as r}from"./lit-element-9646ab7e.js";import{e as i}from"./property-03f59dce.js";import{t as a}from"./state-70f38ceb.js";import{c as l,w as d}from"./number-e7cd246c.js";import{e as c,n as p}from"./ref-eb5cfa10.js";import{o as m}from"./class-map-61e9e8c1.js";import{l as h}from"./if-defined-2a4c6dbc.js";import{g as v}from"./collection-f3631dc8.js";import{N as u}from"./events-731d0007.js";import{L as f}from"./LightDismissController-cc5b4bf2.js";import{KeyboardController as b}from"./KeyboardController.js";import g from"./Icon.js";import"./VisuallyHidden.js";import"./CommandMenuAction.js";import{SelectEvent as x}from"./SelectEvent.js";import{s as y}from"./Component-6762b5eb.js";import"./directive-de55b00a.js";import"./directive-helpers-e7b6bf4b.js";import"./ShortcutController-93173ff4.js";import"./tinykeys.module-84e6cc41.js";import"./unsafe-html-4da54dd2.js";const w="keyboard-arrow-up-down";var k=Object.freeze({__proto__:null,default:'<svg viewBox="0 0 140 140" xmlns="http://www.w3.org/2000/svg"><path d="M105.833 24v93m0-93L80 49.833M105.833 24l25.834 25.833M34.167 117V24m0 93L60 91.167M34.167 117 8.333 91.167" fill="none" stroke="currentColor" stroke-width="14" stroke-linecap="round" stroke-linejoin="round"/></svg>',title:w,tags:"nordicon keyboard keys arrow up down shortcut"});var z=Object.freeze({__proto__:null,default:'<svg viewBox="0 0 140 140" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="14"><path d="M35 133 7 105l28-28"/><path d="M7 105h112a14 14 0 0 0 14-14V21a14 14 0 0 0-14-14H77"/></g></svg>',title:"keyboard-return",tags:"nordicon keyboard return key shortcut"});const $="keyboard-backspace";var j=Object.freeze({__proto__:null,default:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="currentColor" fill-rule="evenodd" d="M6.707 4.879A3 3 0 0 1 8.828 4H15a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H8.828a3 3 0 0 1-2.12-.879l-4.415-4.414a1 1 0 0 1 0-1.414l4.414-4.414zm4 2.414a1 1 0 0 0-1.414 1.414L10.586 10l-1.293 1.293a1 1 0 1 0 1.414 1.414L12 11.414l1.293 1.293a1 1 0 0 0 1.414-1.414L13.414 10l1.293-1.293a1 1 0 0 0-1.414-1.414L12 8.586l-1.293-1.293z" clip-rule="evenodd"/></svg>',title:$,tags:"nordicon keyboard backspace back delete key shortcut"});function C(e){var o;return(null===(o=e.activeElement)||void 0===o?void 0:o.shadowRoot)?C(e.activeElement.shadowRoot):e.activeElement||void 0}const I=t`:host{--n-command-menu-width:640px;--n-command-menu-top:16%;--n-command-menu-height:290px}.n-modal{display:none;position:fixed;pointer-events:none;z-index:var(--n-index-modal);inset-inline-start:0;inset-block-start:0;inline-size:100%;block-size:100%;overflow:auto}.n-modal.n-visible{display:block}.n-modal-content{position:relative;pointer-events:all;inset-block-start:var(--n-command-menu-top);margin:auto;display:flex;flex-direction:column;min-inline-size:0;background:var(--n-color-surface);border-radius:var(--n-border-radius);box-shadow:var(--n-box-shadow-modal);max-inline-size:var(--n-command-menu-width);overflow:hidden}.n-bump{animation:zoom-in-zoom-out var(--n-transition-slowly)}@keyframes zoom-in-zoom-out{0%{transform:translateY(-10px) scale(.97);opacity:0}100%{transform:translateY(0) scale(1.0001);opacity:1}}.n-modal-footer{display:flex;gap:var(--n-space-s);padding:var(--n-space-s) var(--n-space-m);font-size:calc(var(--n-font-size-s) - 1px);color:var(--n-color-text-weaker)}.n-help{display:flex;align-items:center;gap:2px}.n-help+.n-help{padding-inline-start:var(--n-space-s);border-inline-start:1px solid var(--n-color-border-strong)}.n-help nord-icon{--n-icon-size:10px;color:currentColor;margin:3px 4px}.n-help.n-backspace nord-icon{--n-icon-size:12px}.n-search-wrapper{display:flex;border-block-end:1px solid var(--n-color-border)}[role=combobox]{flex:1;font-size:var(--n-font-size-l);font-weight:var(--n-font-weight);font-family:inherit;background:0 0;color:var(--n-color-text);border:none;border-radius:0;appearance:none;outline:0;margin:0;padding:var(--n-space-m)}[role=combobox]::-webkit-input-placeholder{color:var(--n-color-text-weaker);opacity:.6!important}[role=combobox]::-moz-placeholder{color:var(--n-color-text-weaker);opacity:.6!important}[role=combobox]::-ms-input-placeholder{color:var(--n-color-text-weaker);opacity:.6!important}[role=listbox]{max-block-size:var(--n-command-menu-height);overflow:auto;margin:0;padding:0}.n-group-header{line-height:var(--n-line-height);border-block-end:1px solid var(--n-color-border);padding:calc(var(--n-space-s)/ 1.4) var(--n-space-m);text-overflow:ellipsis;white-space:nowrap;overflow:hidden;font-size:var(--n-font-size-s);background:var(--n-color-surface-raised);font-weight:var(--n-font-weight-active);color:var(--n-color-text-weaker)}.n-command-empty{display:flex;flex:1;flex-direction:column;border-inline-start:2px solid transparent;align-items:flex-start;color:var(--n-color-text);border-block-end:1px solid var(--n-color-border);padding:calc(var(--n-space-m)/ 1.5) var(--n-space-m)}.n-command-empty .n-title{flex:1;margin-block-start:var(--n-space-s);margin-inline-end:calc(var(--n-space-s)/ 2);max-inline-size:100%;font-size:var(--n-font-size-m);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.n-command-empty .n-tip{flex:1;margin-block-start:var(--n-space-s);margin-block-end:var(--n-space-m);font-size:var(--n-font-size-s);color:var(--n-color-text-weaker)}`;g.registerIcon(k),g.registerIcon(z),g.registerIcon(j);let E=class extends n{constructor(){super(...arguments),this.inputRef=c(),this.listRef=c(),this.dismissController=new f(this,{isOpen:()=>this.open,onDismiss:()=>this.close()}),this.keyboardController=new b(this,{trigger:()=>this.select(),goBack:()=>this.goBack(),end:()=>this.end(),start:()=>this.start(),next:()=>this.next(),previous:()=>this.previous(),toggleOpen:()=>this.toggleOpen()}),this.open=!1,this.placeholder="Type a command or search...",this.commands=[],this.search="",this.bump=!0,this.selectedIndex=0,this.filteredCommands=[]}get selected(){return this.filteredCommands[this.selectedIndex]}show(e={}){this.dispatchEvent(new u("open",{cancelable:!0}))&&(this.open=!0,this.setParent(e.parent))}close(){var e;this.open=!1,null===(e=this.previousFocus)||void 0===e||e.focus(),this.previousFocus=void 0,this.dispatchEvent(new u("close"))}toggleOpen(){this.open?this.close():this.show()}focus(){var e;null===(e=this.inputRef.value)||void 0===e||e.focus()}willUpdate(e){e.has("commands")&&this.keyboardController.registerCommandShortcuts(),e.has("open")&&this.open&&(this.bump=!0),(e.has("search")||e.has("parent")||e.has("commands"))&&this.filterCommands()}updated(e){e.has("open")&&this.open&&(this.previousFocus=C(document),this.focus(),this.listRef.value&&(this.listRef.value.scrollTop=0))}render(){var e;const o=v(this.filteredCommands,"section"),t=0===this.filteredCommands.length?"no-results":null===(e=this.selected)||void 0===e?void 0:e.id;return s`<div class="${m({"n-visible":this.open,"n-modal":!0})}"><div @animationend="${this.handleAnimationEnd}" class="${m({"n-bump":this.bump,"n-modal-content":!0})}"><div class="n-search-wrapper"><nord-visually-hidden id="instructions">Press 'Enter' to confirm your input or 'Escape' to cancel</nord-visually-hidden><input type="text" id="search" @input="${this.handleInput}" @blur="${this.handleBlur}" ${p(this.inputRef)} placeholder="${this.placeholder}" .value="${this.search}" spellcheck="false" autocomplete="off" autocapitalize="off" aria-label="Type the name of a command to run." aria-autocomplete="list" aria-haspopup="listbox" role="combobox" aria-controls="list" aria-expanded="true" aria-activedescendant="${h(t)}" aria-describedby="instructions"></div><div class="n-modal-body"><div id="list" ${p(this.listRef)} role="listbox">${0===this.filteredCommands.length?this.renderNoResults():Array.from(o,(([e,o])=>this.renderSection(e,o)))}</div></div><slot name="footer"><div class="n-modal-footer" slot="footer"><span class="n-help"><nord-icon label="Arrow keys" name="${w}"></nord-icon>Navigate</span> <span class="n-help"><nord-icon label="Enter key" name="${"keyboard-return"}"></nord-icon>Select</span> <span class="n-help">Esc to dismiss</span> <span class="n-help n-backspace"><nord-icon label="Backspace key" name="${$}"></nord-icon>Move to parent</span></div></slot></div></div>`}renderNoResults(){return s`<div id="no-results" class="n-command-empty" role="option" aria-selected="true"><div class="n-title">No results for “${this.search}”</div><div class="n-tip">Search tips: some search terms require exact match. Try typing the entire command name, or use a different word or phrase.</div></div>`}renderSection(e,o){const t=`section-${e}`;return s`<div role="group" aria-labelledby="${h(e?t:void 0)}">${e?s`<div class="n-group-header" role="presentation" id="${h(t)}">${e}</div>`:r} ${l(o,(e=>e.id),(e=>{var o,t;return s`<nord-command-menu-action id="${e.id}" .command="${e}" ?selected="${e.id===(null===(o=this.selected)||void 0===o?void 0:o.id)}" @click="${()=>this.select(e)}" role="option" aria-selected="${h(e.id===(null===(t=this.selected)||void 0===t?void 0:t.id)||void 0)}"></nord-command-menu-action>`}))}</div>`}handleAnimationEnd(){this.bump=!1}handleBlur(){this.open&&this.focus()}handleInput(e){const o=e.target;this.setSearch(o.value)}select(e=this.selected){var o;this.commands.some((o=>o.parent===e.id))?(this.setParent(e.id),this.bump=!0,this.focus()):this.close(),this.setSearch(""),null===(o=e.handler)||void 0===o||o.call(e,this);const t=new x(e);this.dispatchEvent(t)}start(){this.selectedIndex=0}end(){this.selectedIndex=this.filteredCommands.length-1}next(){this.selectedIndex=d(this.selectedIndex+1,0,this.filteredCommands.length-1)}previous(){this.selectedIndex=d(this.selectedIndex-1,0,this.filteredCommands.length-1)}goBack(){if(!this.search&&this.parent){const e=this.commands.find((e=>e.id===this.parent));this.setParent(null==e?void 0:e.parent)}}setParent(e){this.parent=e,this.setSearch("")}setSearch(e){this.search=e,this.selectedIndex=0}filterCommands(){const e=this.search.toLocaleLowerCase().split(/\s+/);this.filteredCommands=this.commands.filter((({title:o,keywords:t="",parent:n})=>{const s=`${o} ${t}`.toLocaleLowerCase(),r=e.every((e=>s.includes(e)));return(!this.parent&&this.search||n===this.parent)&&r}))}};E.styles=[y,I],e([i({type:Boolean})],E.prototype,"open",void 0),e([i({type:String})],E.prototype,"placeholder",void 0),e([i({type:Array,attribute:!1})],E.prototype,"commands",void 0),e([a()],E.prototype,"parent",void 0),e([a()],E.prototype,"search",void 0),e([a()],E.prototype,"bump",void 0),e([a()],E.prototype,"selectedIndex",void 0),e([a()],E.prototype,"filteredCommands",void 0),E=e([o("nord-command-menu")],E);var _=E;export{_ as default};
2
2
  //# sourceMappingURL=CommandMenu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CommandMenu.js","sources":["../../icons/lib/assets/keyboard-arrow-up-down.js","../../icons/lib/assets/keyboard-return.js","../../icons/lib/assets/keyboard-backspace.js","../src/common/focus.ts","../src/command-menu/CommandMenu.ts"],"sourcesContent":["export default '<svg viewBox=\"0 0 140 140\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M105.833 24v93m0-93L80 49.833M105.833 24l25.834 25.833M34.167 117V24m0 93L60 91.167M34.167 117 8.333 91.167\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"14\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>'\nexport const title = \"keyboard-arrow-up-down\"\nexport const tags = \"nordicon keyboard keys arrow up down shortcut\"\n","export default '<svg viewBox=\"0 0 140 140\" xmlns=\"http://www.w3.org/2000/svg\"><g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"14\"><path d=\"M35 133 7 105l28-28\"/><path d=\"M7 105h112a14 14 0 0 0 14-14V21a14 14 0 0 0-14-14H77\"/></g></svg>'\nexport const title = \"keyboard-return\"\nexport const tags = \"nordicon keyboard return key shortcut\"\n","export default '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\"><path fill=\"currentColor\" fill-rule=\"evenodd\" d=\"M6.707 4.879A3 3 0 0 1 8.828 4H15a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H8.828a3 3 0 0 1-2.12-.879l-4.415-4.414a1 1 0 0 1 0-1.414l4.414-4.414zm4 2.414a1 1 0 0 0-1.414 1.414L10.586 10l-1.293 1.293a1 1 0 1 0 1.414 1.414L12 11.414l1.293 1.293a1 1 0 0 0 1.414-1.414L13.414 10l1.293-1.293a1 1 0 0 0-1.414-1.414L12 8.586l-1.293-1.293z\" clip-rule=\"evenodd\"/></svg>'\nexport const title = \"keyboard-backspace\"\nexport const tags = \"nordicon keyboard backspace back delete key shortcut\"\n","/**\n * Gets the currently focused element, taking shadow roots into account.\n */\nexport function getFocusedElement(root: Document | ShadowRoot): Element | undefined {\n if (root.activeElement?.shadowRoot) {\n return getFocusedElement(root.activeElement.shadowRoot)\n }\n\n return root.activeElement || undefined\n}\n","import { LitElement, html, PropertyValues, nothing } from \"lit\"\nimport { customElement, property, state } from \"lit/decorators.js\"\nimport { repeat } from \"lit/directives/repeat.js\"\nimport { createRef, ref } from \"lit/directives/ref.js\"\nimport { classMap } from \"lit/directives/class-map.js\"\nimport { ifDefined } from \"lit/directives/if-defined.js\"\n\nimport * as navigateIcon from \"@nordhealth/icons/lib/assets/keyboard-arrow-up-down.js\"\nimport * as enterIcon from \"@nordhealth/icons/lib/assets/keyboard-return.js\"\nimport * as backspaceIcon from \"@nordhealth/icons/lib/assets/keyboard-backspace.js\"\n\nimport { groupBy } from \"../common/collection.js\"\nimport { wrap } from \"../common/number.js\"\nimport { NordEvent } from \"../common/events.js\"\nimport { getFocusedElement } from \"../common/focus.js\"\nimport { LightDismissController } from \"../common/controllers/LightDismissController.js\"\nimport { KeyboardController } from \"./KeyboardController.js\"\n\nimport Icon from \"../icon/Icon.js\"\nimport \"../visually-hidden/VisuallyHidden.js\"\nimport \"./CommandMenuAction.js\"\nimport { ICommandMenuAction } from \"./ICommandMenuAction.js\"\nimport { SelectEvent } from \"./SelectEvent.js\"\nimport componentStyle from \"../common/styles/Component.css\"\nimport style from \"./CommandMenu.css\"\n\nIcon.registerIcon(navigateIcon)\nIcon.registerIcon(enterIcon)\nIcon.registerIcon(backspaceIcon)\n\n/**\n * Command Menu allows users to navigate and use an app without\n * touching the mouse and helps them transform into “power users”\n * who can harness more advanced features far faster.\n *\n * @status ready\n * @category action\n * @slot footer - Used to replace the default footer contents.\n * @fires open - The command menu was opened.\n * @fires close - The command menu was closed.\n * @fires {SelectEvent} nord-select - User selected a command from the menu.\n */\n@customElement(\"nord-command-menu\")\nexport default class CommandMenu extends LitElement {\n static styles = [componentStyle, style]\n\n private inputRef = createRef<HTMLInputElement>()\n private listRef = createRef<HTMLElement>()\n private previousFocus?: HTMLElement\n\n private dismissController = new LightDismissController(this, {\n isOpen: () => this.open,\n onDismiss: () => this.close(),\n })\n\n private keyboardController = new KeyboardController(this, {\n trigger: () => this.select(),\n goBack: () => this.goBack(),\n end: () => this.end(),\n start: () => this.start(),\n next: () => this.next(),\n previous: () => this.previous(),\n toggleOpen: () => this.toggleOpen(),\n })\n\n /**\n * Show or hide the command menu.\n */\n @property({ type: Boolean }) open = false\n\n /**\n * Hint text to display in the Command Menu search field.\n */\n @property({ type: String }) placeholder = \"Type a command or search...\"\n\n /**\n * Array of commands to be included in the menu.\n * Please see “Commands data” section for more documentation.\n */\n @property({ type: Array, attribute: false }) commands: Array<ICommandMenuAction> = []\n\n @state() private parent?: string\n @state() private search: string = \"\"\n @state() private bump = true\n @state() private selectedIndex = 0\n @state() private filteredCommands: Array<ICommandMenuAction> = []\n\n private get selected(): ICommandMenuAction {\n return this.filteredCommands[this.selectedIndex]\n }\n\n /**\n * Show the command menu programmatically.\n * @param options allows you to open the menu filtered to a specific parent command.\n */\n show(options: { parent?: string } = {}) {\n this.open = true\n this.setParent(options.parent)\n\n this.dispatchEvent(new NordEvent(\"open\"))\n }\n\n /**\n * Close the command menu programmatically.\n */\n close() {\n this.open = false\n this.previousFocus?.focus()\n this.previousFocus = undefined\n\n this.dispatchEvent(new NordEvent(\"close\"))\n }\n\n /**\n * Toggle the open state programmatically.\n */\n toggleOpen() {\n if (this.open) {\n this.close()\n } else {\n this.show()\n }\n }\n\n /**\n * Focus the command menu's input.\n */\n focus() {\n this.inputRef.value?.focus()\n }\n\n override willUpdate(changedProperties: PropertyValues<this>) {\n if (changedProperties.has(\"commands\")) {\n this.keyboardController.registerCommandShortcuts()\n }\n\n if (changedProperties.has(\"open\") && this.open) {\n this.bump = true\n }\n\n if (\n // @ts-expect-error this is a private property so it errors, but it's fine here\n changedProperties.has(\"search\") ||\n // @ts-expect-error this is a private property so it errors, but it's fine here\n changedProperties.has(\"parent\") ||\n changedProperties.has(\"commands\")\n ) {\n this.filterCommands()\n }\n }\n\n override updated(changedProperties: PropertyValues<this>) {\n if (changedProperties.has(\"open\") && this.open) {\n this.previousFocus = getFocusedElement(document) as HTMLElement\n this.focus()\n\n if (this.listRef.value) {\n this.listRef.value.scrollTop = 0\n }\n }\n }\n\n override render() {\n const sections = groupBy(this.filteredCommands, \"section\")\n const activeDescendant = this.filteredCommands.length === 0 ? \"no-results\" : this.selected?.id\n\n return html`\n <div\n class=${classMap({\n \"n-visible\": this.open,\n \"n-modal\": true,\n })}\n >\n <div\n @animationend=${this.handleAnimationEnd}\n class=${classMap({\n \"n-bump\": this.bump,\n \"n-modal-content\": true,\n })}\n >\n <div class=\"n-search-wrapper\">\n <nord-visually-hidden id=\"instructions\">\n Press 'Enter' to confirm your input or 'Escape' to cancel\n </nord-visually-hidden>\n <input\n type=\"text\"\n id=\"search\"\n @input=${this.handleInput}\n @blur=${this.handleBlur}\n ${ref(this.inputRef)}\n placeholder=${this.placeholder}\n .value=${this.search}\n spellcheck=\"false\"\n autocomplete=\"off\"\n autocapitalize=\"off\"\n aria-label=\"Type the name of a command to run.\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n role=\"combobox\"\n aria-controls=\"list\"\n aria-expanded=\"true\"\n aria-activedescendant=${ifDefined(activeDescendant)}\n aria-describedby=\"instructions\"\n />\n </div>\n\n <div class=\"n-modal-body\">\n <div id=\"list\" ${ref(this.listRef)} role=\"listbox\">\n ${this.filteredCommands.length === 0\n ? this.renderNoResults()\n : Array.from(sections, ([section, commands]) => this.renderSection(section, commands))}\n </div>\n </div>\n <slot name=\"footer\">\n <div class=\"n-modal-footer\" slot=\"footer\">\n <span class=\"n-help\"><nord-icon label=\"Arrow keys\" name=${navigateIcon.title}></nord-icon> Navigate</span>\n <span class=\"n-help\"><nord-icon label=\"Enter key\" name=${enterIcon.title}></nord-icon> Select</span>\n <span class=\"n-help\">Esc to dismiss</span>\n <span class=\"n-help n-backspace\"\n ><nord-icon label=\"Backspace key\" name=${backspaceIcon.title}></nord-icon> Move to parent</span\n >\n </div>\n </slot>\n </div>\n </div>\n `\n }\n\n private renderNoResults() {\n return html`\n <div id=\"no-results\" class=\"n-command-empty\" role=\"option\" aria-selected=\"true\">\n <div class=\"n-title\">No results for “${this.search}”</div>\n <div class=\"n-tip\">\n Search tips: some search terms require exact match. Try typing the entire command name, or use\n a&nbsp;different word or phrase.\n </div>\n </div>\n `\n }\n\n private renderSection(section: string | undefined, commands: ICommandMenuAction[]) {\n const sectionId = `section-${section}`\n\n // TODO: test on latest safari, since it seems to have issues with grouped options\n return html`\n <div role=\"group\" aria-labelledby=${ifDefined(section ? sectionId : undefined)}>\n ${section\n ? html`<div class=\"n-group-header\" role=\"presentation\" id=${ifDefined(sectionId)}>${section}</div>`\n : nothing}\n ${repeat(\n commands,\n command => command.id,\n command => html`\n <nord-command-menu-action\n id=${command.id}\n .command=${command}\n ?selected=${command.id === this.selected?.id}\n @click=${() => this.select(command)}\n role=\"option\"\n aria-selected=${ifDefined(command.id === this.selected?.id || undefined)}\n ></nord-command-menu-action>\n `\n )}\n </div>\n `\n }\n\n private handleAnimationEnd() {\n this.bump = false\n }\n\n private handleBlur() {\n if (this.open) {\n this.focus()\n }\n }\n\n private handleInput(event: KeyboardEvent) {\n const input = event.target as HTMLInputElement\n this.setSearch(input.value)\n }\n\n private select(command: ICommandMenuAction = this.selected) {\n const isParent = this.commands.some(item => item.parent === command.id)\n\n if (isParent) {\n this.setParent(command.id)\n this.bump = true\n this.focus()\n } else {\n this.close()\n }\n\n this.setSearch(\"\")\n command.handler?.(this)\n\n // this is separated into two parts because of a bug in Custom Elements Analyzer, where it gets the event name wrong.\n // TODO: cleanup when bug is fixed.\n const event = new SelectEvent(command)\n this.dispatchEvent(event)\n }\n\n private start() {\n this.selectedIndex = 0\n }\n\n private end() {\n this.selectedIndex = this.filteredCommands.length - 1\n }\n\n private next() {\n this.selectedIndex = wrap(this.selectedIndex + 1, 0, this.filteredCommands.length - 1)\n }\n\n private previous() {\n this.selectedIndex = wrap(this.selectedIndex - 1, 0, this.filteredCommands.length - 1)\n }\n\n private goBack() {\n if (this.search) {\n return\n }\n\n if (this.parent) {\n const parentCommand = this.commands.find(command => command.id === this.parent)\n this.setParent(parentCommand?.parent)\n }\n }\n\n private setParent(parent?: string) {\n this.parent = parent\n this.setSearch(\"\")\n }\n\n private setSearch(str: string) {\n this.search = str\n this.selectedIndex = 0\n }\n\n private filterCommands() {\n const searchTerms = this.search.toLocaleLowerCase().split(/\\s+/)\n\n this.filteredCommands = this.commands.filter(({ title, keywords = \"\", parent }) => {\n const searchSpace = `${title} ${keywords}`.toLocaleLowerCase()\n const matcher = searchTerms.every(term => searchSpace.includes(term))\n\n if (!this.parent && this.search) {\n // global search for items on root\n return matcher\n }\n\n return parent === this.parent && matcher\n })\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"nord-command-menu\": CommandMenu\n }\n}\n"],"names":["title","getFocusedElement","root","activeElement","shadowRoot","undefined","Icon","registerIcon","navigateIcon","enterIcon","backspaceIcon","CommandMenu","LitElement","constructor","this","createRef","LightDismissController","isOpen","open","onDismiss","close","KeyboardController","trigger","select","goBack","end","start","next","previous","toggleOpen","selected","filteredCommands","selectedIndex","show","options","setParent","parent","dispatchEvent","NordEvent","previousFocus","focus","inputRef","value","willUpdate","changedProperties","has","keyboardController","registerCommandShortcuts","bump","filterCommands","updated","document","listRef","scrollTop","render","sections","groupBy","activeDescendant","length","id","html","classMap","handleAnimationEnd","handleInput","handleBlur","ref","placeholder","search","ifDefined","renderNoResults","Array","from","section","commands","renderSection","navigateIcon.title","backspaceIcon.title","sectionId","nothing","repeat","command","event","input","target","setSearch","some","item","handler","SelectEvent","wrap","parentCommand","find","str","searchTerms","toLocaleLowerCase","split","filter","keywords","searchSpace","matcher","every","term","includes","componentStyle","style","__decorate","property","type","Boolean","String","attribute","state","customElement"],"mappings":"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"}
1
+ {"version":3,"file":"CommandMenu.js","sources":["../../icons/lib/assets/keyboard-arrow-up-down.js","../../icons/lib/assets/keyboard-return.js","../../icons/lib/assets/keyboard-backspace.js","../src/common/focus.ts","../src/command-menu/CommandMenu.ts"],"sourcesContent":["export default '<svg viewBox=\"0 0 140 140\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M105.833 24v93m0-93L80 49.833M105.833 24l25.834 25.833M34.167 117V24m0 93L60 91.167M34.167 117 8.333 91.167\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"14\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>'\nexport const title = \"keyboard-arrow-up-down\"\nexport const tags = \"nordicon keyboard keys arrow up down shortcut\"\n","export default '<svg viewBox=\"0 0 140 140\" xmlns=\"http://www.w3.org/2000/svg\"><g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"14\"><path d=\"M35 133 7 105l28-28\"/><path d=\"M7 105h112a14 14 0 0 0 14-14V21a14 14 0 0 0-14-14H77\"/></g></svg>'\nexport const title = \"keyboard-return\"\nexport const tags = \"nordicon keyboard return key shortcut\"\n","export default '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\"><path fill=\"currentColor\" fill-rule=\"evenodd\" d=\"M6.707 4.879A3 3 0 0 1 8.828 4H15a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H8.828a3 3 0 0 1-2.12-.879l-4.415-4.414a1 1 0 0 1 0-1.414l4.414-4.414zm4 2.414a1 1 0 0 0-1.414 1.414L10.586 10l-1.293 1.293a1 1 0 1 0 1.414 1.414L12 11.414l1.293 1.293a1 1 0 0 0 1.414-1.414L13.414 10l1.293-1.293a1 1 0 0 0-1.414-1.414L12 8.586l-1.293-1.293z\" clip-rule=\"evenodd\"/></svg>'\nexport const title = \"keyboard-backspace\"\nexport const tags = \"nordicon keyboard backspace back delete key shortcut\"\n","/**\n * Gets the currently focused element, taking shadow roots into account.\n */\nexport function getFocusedElement(root: Document | ShadowRoot): Element | undefined {\n if (root.activeElement?.shadowRoot) {\n return getFocusedElement(root.activeElement.shadowRoot)\n }\n\n return root.activeElement || undefined\n}\n","import { LitElement, html, PropertyValues, nothing } from \"lit\"\nimport { customElement, property, state } from \"lit/decorators.js\"\nimport { repeat } from \"lit/directives/repeat.js\"\nimport { createRef, ref } from \"lit/directives/ref.js\"\nimport { classMap } from \"lit/directives/class-map.js\"\nimport { ifDefined } from \"lit/directives/if-defined.js\"\n\nimport * as navigateIcon from \"@nordhealth/icons/lib/assets/keyboard-arrow-up-down.js\"\nimport * as enterIcon from \"@nordhealth/icons/lib/assets/keyboard-return.js\"\nimport * as backspaceIcon from \"@nordhealth/icons/lib/assets/keyboard-backspace.js\"\n\nimport { groupBy } from \"../common/collection.js\"\nimport { wrap } from \"../common/number.js\"\nimport { NordEvent } from \"../common/events.js\"\nimport { getFocusedElement } from \"../common/focus.js\"\nimport { LightDismissController } from \"../common/controllers/LightDismissController.js\"\nimport { KeyboardController } from \"./KeyboardController.js\"\n\nimport Icon from \"../icon/Icon.js\"\nimport \"../visually-hidden/VisuallyHidden.js\"\nimport \"./CommandMenuAction.js\"\nimport { ICommandMenuAction } from \"./ICommandMenuAction.js\"\nimport { SelectEvent } from \"./SelectEvent.js\"\nimport componentStyle from \"../common/styles/Component.css\"\nimport style from \"./CommandMenu.css\"\n\nIcon.registerIcon(navigateIcon)\nIcon.registerIcon(enterIcon)\nIcon.registerIcon(backspaceIcon)\n\n/**\n * Command Menu allows users to navigate and use an app without\n * touching the mouse and helps them transform into “power users”\n * who can harness more advanced features far faster.\n *\n * @status ready\n * @category action\n * @slot footer - Used to replace the default footer contents.\n * @fires open - The command menu was opened.\n * @fires close - The command menu was closed.\n * @fires {SelectEvent} nord-select - User selected a command from the menu.\n */\n@customElement(\"nord-command-menu\")\nexport default class CommandMenu extends LitElement {\n static styles = [componentStyle, style]\n\n private inputRef = createRef<HTMLInputElement>()\n private listRef = createRef<HTMLElement>()\n private previousFocus?: HTMLElement\n\n private dismissController = new LightDismissController(this, {\n isOpen: () => this.open,\n onDismiss: () => this.close(),\n })\n\n private keyboardController = new KeyboardController(this, {\n trigger: () => this.select(),\n goBack: () => this.goBack(),\n end: () => this.end(),\n start: () => this.start(),\n next: () => this.next(),\n previous: () => this.previous(),\n toggleOpen: () => this.toggleOpen(),\n })\n\n /**\n * Show or hide the command menu.\n */\n @property({ type: Boolean }) open = false\n\n /**\n * Hint text to display in the Command Menu search field.\n */\n @property({ type: String }) placeholder = \"Type a command or search...\"\n\n /**\n * Array of commands to be included in the menu.\n * Please see “Commands data” section for more documentation.\n */\n @property({ type: Array, attribute: false }) commands: Array<ICommandMenuAction> = []\n\n @state() private parent?: string\n @state() private search: string = \"\"\n @state() private bump = true\n @state() private selectedIndex = 0\n @state() private filteredCommands: Array<ICommandMenuAction> = []\n\n private get selected(): ICommandMenuAction {\n return this.filteredCommands[this.selectedIndex]\n }\n\n /**\n * Show the command menu programmatically.\n * @param options allows you to open the menu filtered to a specific parent command.\n */\n show(options: { parent?: string } = {}) {\n const notCancelled = this.dispatchEvent(new NordEvent(\"open\", { cancelable: true }))\n\n if (notCancelled) {\n this.open = true\n this.setParent(options.parent)\n }\n }\n\n /**\n * Close the command menu programmatically.\n */\n close() {\n this.open = false\n this.previousFocus?.focus()\n this.previousFocus = undefined\n\n this.dispatchEvent(new NordEvent(\"close\"))\n }\n\n /**\n * Toggle the open state programmatically.\n */\n toggleOpen() {\n if (this.open) {\n this.close()\n } else {\n this.show()\n }\n }\n\n /**\n * Focus the command menu's input.\n */\n focus() {\n this.inputRef.value?.focus()\n }\n\n override willUpdate(changedProperties: PropertyValues<this>) {\n if (changedProperties.has(\"commands\")) {\n this.keyboardController.registerCommandShortcuts()\n }\n\n if (changedProperties.has(\"open\") && this.open) {\n this.bump = true\n }\n\n if (\n // @ts-expect-error this is a private property so it errors, but it's fine here\n changedProperties.has(\"search\") ||\n // @ts-expect-error this is a private property so it errors, but it's fine here\n changedProperties.has(\"parent\") ||\n changedProperties.has(\"commands\")\n ) {\n this.filterCommands()\n }\n }\n\n override updated(changedProperties: PropertyValues<this>) {\n if (changedProperties.has(\"open\") && this.open) {\n this.previousFocus = getFocusedElement(document) as HTMLElement\n this.focus()\n\n if (this.listRef.value) {\n this.listRef.value.scrollTop = 0\n }\n }\n }\n\n override render() {\n const sections = groupBy(this.filteredCommands, \"section\")\n const activeDescendant = this.filteredCommands.length === 0 ? \"no-results\" : this.selected?.id\n\n return html`\n <div\n class=${classMap({\n \"n-visible\": this.open,\n \"n-modal\": true,\n })}\n >\n <div\n @animationend=${this.handleAnimationEnd}\n class=${classMap({\n \"n-bump\": this.bump,\n \"n-modal-content\": true,\n })}\n >\n <div class=\"n-search-wrapper\">\n <nord-visually-hidden id=\"instructions\">\n Press 'Enter' to confirm your input or 'Escape' to cancel\n </nord-visually-hidden>\n <input\n type=\"text\"\n id=\"search\"\n @input=${this.handleInput}\n @blur=${this.handleBlur}\n ${ref(this.inputRef)}\n placeholder=${this.placeholder}\n .value=${this.search}\n spellcheck=\"false\"\n autocomplete=\"off\"\n autocapitalize=\"off\"\n aria-label=\"Type the name of a command to run.\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n role=\"combobox\"\n aria-controls=\"list\"\n aria-expanded=\"true\"\n aria-activedescendant=${ifDefined(activeDescendant)}\n aria-describedby=\"instructions\"\n />\n </div>\n\n <div class=\"n-modal-body\">\n <div id=\"list\" ${ref(this.listRef)} role=\"listbox\">\n ${this.filteredCommands.length === 0\n ? this.renderNoResults()\n : Array.from(sections, ([section, commands]) => this.renderSection(section, commands))}\n </div>\n </div>\n <slot name=\"footer\">\n <div class=\"n-modal-footer\" slot=\"footer\">\n <span class=\"n-help\"><nord-icon label=\"Arrow keys\" name=${navigateIcon.title}></nord-icon> Navigate</span>\n <span class=\"n-help\"><nord-icon label=\"Enter key\" name=${enterIcon.title}></nord-icon> Select</span>\n <span class=\"n-help\">Esc to dismiss</span>\n <span class=\"n-help n-backspace\"\n ><nord-icon label=\"Backspace key\" name=${backspaceIcon.title}></nord-icon> Move to parent</span\n >\n </div>\n </slot>\n </div>\n </div>\n `\n }\n\n private renderNoResults() {\n return html`\n <div id=\"no-results\" class=\"n-command-empty\" role=\"option\" aria-selected=\"true\">\n <div class=\"n-title\">No results for “${this.search}”</div>\n <div class=\"n-tip\">\n Search tips: some search terms require exact match. Try typing the entire command name, or use\n a&nbsp;different word or phrase.\n </div>\n </div>\n `\n }\n\n private renderSection(section: string | undefined, commands: ICommandMenuAction[]) {\n const sectionId = `section-${section}`\n\n // TODO: test on latest safari, since it seems to have issues with grouped options\n return html`\n <div role=\"group\" aria-labelledby=${ifDefined(section ? sectionId : undefined)}>\n ${section\n ? html`<div class=\"n-group-header\" role=\"presentation\" id=${ifDefined(sectionId)}>${section}</div>`\n : nothing}\n ${repeat(\n commands,\n command => command.id,\n command => html`\n <nord-command-menu-action\n id=${command.id}\n .command=${command}\n ?selected=${command.id === this.selected?.id}\n @click=${() => this.select(command)}\n role=\"option\"\n aria-selected=${ifDefined(command.id === this.selected?.id || undefined)}\n ></nord-command-menu-action>\n `\n )}\n </div>\n `\n }\n\n private handleAnimationEnd() {\n this.bump = false\n }\n\n private handleBlur() {\n if (this.open) {\n this.focus()\n }\n }\n\n private handleInput(event: KeyboardEvent) {\n const input = event.target as HTMLInputElement\n this.setSearch(input.value)\n }\n\n private select(command: ICommandMenuAction = this.selected) {\n const isParent = this.commands.some(item => item.parent === command.id)\n\n if (isParent) {\n this.setParent(command.id)\n this.bump = true\n this.focus()\n } else {\n this.close()\n }\n\n this.setSearch(\"\")\n command.handler?.(this)\n\n // this is separated into two parts because of a bug in Custom Elements Analyzer, where it gets the event name wrong.\n // TODO: cleanup when bug is fixed.\n const event = new SelectEvent(command)\n this.dispatchEvent(event)\n }\n\n private start() {\n this.selectedIndex = 0\n }\n\n private end() {\n this.selectedIndex = this.filteredCommands.length - 1\n }\n\n private next() {\n this.selectedIndex = wrap(this.selectedIndex + 1, 0, this.filteredCommands.length - 1)\n }\n\n private previous() {\n this.selectedIndex = wrap(this.selectedIndex - 1, 0, this.filteredCommands.length - 1)\n }\n\n private goBack() {\n if (this.search) {\n return\n }\n\n if (this.parent) {\n const parentCommand = this.commands.find(command => command.id === this.parent)\n this.setParent(parentCommand?.parent)\n }\n }\n\n private setParent(parent?: string) {\n this.parent = parent\n this.setSearch(\"\")\n }\n\n private setSearch(str: string) {\n this.search = str\n this.selectedIndex = 0\n }\n\n private filterCommands() {\n const searchTerms = this.search.toLocaleLowerCase().split(/\\s+/)\n\n this.filteredCommands = this.commands.filter(({ title, keywords = \"\", parent }) => {\n const searchSpace = `${title} ${keywords}`.toLocaleLowerCase()\n const matcher = searchTerms.every(term => searchSpace.includes(term))\n\n if (!this.parent && this.search) {\n // global search for items on root\n return matcher\n }\n\n return parent === this.parent && matcher\n })\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"nord-command-menu\": CommandMenu\n }\n}\n"],"names":["title","getFocusedElement","root","activeElement","shadowRoot","undefined","Icon","registerIcon","navigateIcon","enterIcon","backspaceIcon","CommandMenu","LitElement","constructor","this","createRef","LightDismissController","isOpen","open","onDismiss","close","KeyboardController","trigger","select","goBack","end","start","next","previous","toggleOpen","selected","filteredCommands","selectedIndex","show","options","dispatchEvent","NordEvent","cancelable","setParent","parent","previousFocus","focus","inputRef","value","willUpdate","changedProperties","has","keyboardController","registerCommandShortcuts","bump","filterCommands","updated","document","listRef","scrollTop","render","sections","groupBy","activeDescendant","length","id","html","classMap","handleAnimationEnd","handleInput","handleBlur","ref","placeholder","search","ifDefined","renderNoResults","Array","from","section","commands","renderSection","navigateIcon.title","backspaceIcon.title","sectionId","nothing","repeat","command","event","input","target","setSearch","some","item","handler","SelectEvent","wrap","parentCommand","find","str","searchTerms","toLocaleLowerCase","split","filter","keywords","searchSpace","matcher","every","term","includes","componentStyle","style","__decorate","property","type","Boolean","String","attribute","state","customElement"],"mappings":"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"}