@nordhealth/components 5.0.1 → 5.0.2
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/custom-elements.json +15645 -15496
- package/lib/AsideDrawer.js +2 -2
- package/lib/AsideDrawer.js.map +1 -1
- package/lib/AsideTrigger.js +2 -2
- package/lib/AsideTrigger.js.map +1 -1
- package/lib/Button.js +2 -2
- package/lib/Button.js.map +1 -1
- package/lib/DatePicker.js +1 -1
- package/lib/DateRangePicker.js +1 -1
- package/lib/FilterDateRange.js +1 -1
- package/lib/FilterDropdown.js +1 -1
- package/lib/Header.js +1 -1
- package/lib/Header.js.map +1 -1
- package/lib/IconManager.js +1 -1
- package/lib/Input.js +1 -1
- package/lib/NavItem.js +1 -1
- package/lib/NavItem.js.map +1 -1
- package/lib/Navigation.js +1 -1
- package/lib/Navigation.js.map +1 -1
- package/lib/Range.js +1 -1
- package/lib/SegmentedControlItem.js +1 -1
- package/lib/TextField-BYSciLeB.js +2 -0
- package/lib/TextField-BYSciLeB.js.map +1 -0
- package/lib/Textarea.js +1 -1
- package/lib/TimePicker.js +1 -1
- package/lib/bundle.js +12 -12
- package/lib/bundle.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/src/aside-trigger/AsideTrigger.d.ts +28 -2
- package/lib/src/button/Button.d.ts +6 -0
- package/lib/src/nav-item/NavItem.d.ts +22 -0
- package/lib/src/navigation/Navigation.d.ts +18 -0
- package/package.json +8 -8
- package/lib/TextField-CSKvieoG.js +0 -2
- package/lib/TextField-CSKvieoG.js.map +0 -1
package/lib/AsideDrawer.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{_ as e}from"./tslib.es6-CmLYFWVC.js";import{css as i,LitElement as
|
|
1
|
+
import{_ as e}from"./tslib.es6-CmLYFWVC.js";import{css as i,LitElement as t,html as r,isServer as n}from"lit";import{property as a,state as d,customElement as s}from"lit/decorators.js";import{o as l}from"./observe-D0n0zOfU.js";import{N as o}from"./events-Bv6wNHwJ.js";import{c as h}from"./number-Dg2vCfGd.js";import{s as u}from"./storage-CGZ-YX4-.js";import{s as c}from"./Component-BJ5O5n8k.js";const m=i`:host{--_n-aside-drawer-inline-size:var(--n-aside-drawer-inline-size,420px);--_n-aside-drawer-min-inline-size:var(--n-aside-drawer-min-inline-size,280px);--_n-aside-drawer-max-inline-size:var(--n-aside-drawer-max-inline-size,none);--_n-aside-drawer-background-color:var(--n-aside-drawer-background-color,var(--n-color-surface));--_n-aside-drawer-border-color:var(--n-aside-drawer-border-color,var(--n-color-border));--_n-aside-drawer-border-width:var(--n-aside-drawer-border-width,0);--_n-aside-drawer-border-inline-end-width:var(
|
|
2
2
|
--n-aside-drawer-border-inline-end-width,var(--_n-aside-drawer-border-width)
|
|
3
3
|
);--_n-aside-drawer-border-block-start-width:var(
|
|
4
4
|
--n-aside-drawer-border-block-start-width,var(--_n-aside-drawer-border-width)
|
|
@@ -6,5 +6,5 @@ import{_ as e}from"./tslib.es6-CmLYFWVC.js";import{css as i,LitElement as r,html
|
|
|
6
6
|
--n-aside-drawer-border-block-end-width,var(--_n-aside-drawer-border-width)
|
|
7
7
|
);--_n-aside-drawer-border-radius:var(--n-aside-drawer-border-radius,0);--_n-aside-drawer-box-shadow:var(--n-aside-drawer-box-shadow,var(--n-box-shadow-card));--_n-aside-drawer-margin-block:var(--n-aside-drawer-margin-block,0);--_n-aside-drawer-margin-inline-start:var(--n-aside-drawer-margin-inline-start,0);--_n-aside-drawer-margin-inline-end:var(--n-aside-drawer-margin-inline-end,0);--_n-aside-drawer-fullscreen-inset-block-start:var(
|
|
8
8
|
--n-aside-drawer-fullscreen-inset-block-start,var(--n-layout-header-size,0)
|
|
9
|
-
);--_n-aside-drawer-z-index:var(--n-aside-z-index,var(--n-index-nav));--_n-aside-drawer-fullscreen-z-index:var(--n-aside-z-index-fullscreen,var(--n-index-top-bar,1000));background:var(--_n-aside-drawer-background-color);box-shadow:var(--_n-aside-drawer-box-shadow);box-sizing:border-box;display:block;inline-size:var(--_n-aside-drawer-inline-size);margin-block-end:var(--_n-aside-drawer-margin-block);margin-block-start:var(--_n-aside-drawer-margin-block);margin-inline-end:var(--_n-aside-drawer-margin-inline-end);margin-inline-start:var(--_n-aside-drawer-margin-inline-start);max-inline-size:var(--_n-aside-drawer-max-inline-size);min-inline-size:var(--_n-aside-drawer-min-inline-size);position:relative;z-index:var(--_n-aside-drawer-z-index)}.n-aside-drawer{block-size:100%;inline-size:100%}::slotted(*){block-size:100%}::slotted(nord-drawer){--n-drawer-border-color:var(--_n-aside-drawer-border-color);--n-drawer-border-radius:var(--_n-aside-drawer-border-radius);--n-drawer-border-inline-start-width:var(--_n-aside-drawer-border-width);--n-drawer-border-inline-end-width:var(--_n-aside-drawer-border-inline-end-width);--n-drawer-border-block-start-width:var(--_n-aside-drawer-border-block-start-width);--n-drawer-border-block-end-width:var(--_n-aside-drawer-border-block-end-width)}@media (min-width:768px){:host([data-animating-fullscreen]),:host([fullscreen]){inset-block-end:var(--n-layout-footer-block-size,0);inset-block-start:var(--_n-aside-drawer-fullscreen-inset-block-start);inset-inline-end:calc(var(--n-aside-rail-width, 48px) + var(--_n-aside-rail-gap, 0px));margin-inline:0;position:fixed;z-index:var(--_n-aside-drawer-fullscreen-z-index)}:host([fullscreen]){inline-size:min(var(--_n-aside-drawer-fullscreen-max,100vw),var(--_n-aside-drawer-fullscreen-available,100vw));max-inline-size:min(var(--_n-aside-drawer-fullscreen-max,100vw),var(--_n-aside-drawer-fullscreen-available,100vw));min-inline-size:0}}`;class
|
|
9
|
+
);--_n-aside-drawer-z-index:var(--n-aside-z-index,var(--n-index-nav));--_n-aside-drawer-fullscreen-z-index:var(--n-aside-z-index-fullscreen,var(--n-index-top-bar,1000));background:var(--_n-aside-drawer-background-color);box-shadow:var(--_n-aside-drawer-box-shadow);box-sizing:border-box;display:block;inline-size:var(--_n-aside-drawer-inline-size);margin-block-end:var(--_n-aside-drawer-margin-block);margin-block-start:var(--_n-aside-drawer-margin-block);margin-inline-end:var(--_n-aside-drawer-margin-inline-end);margin-inline-start:var(--_n-aside-drawer-margin-inline-start);max-inline-size:var(--_n-aside-drawer-max-inline-size);min-inline-size:var(--_n-aside-drawer-min-inline-size);position:relative;z-index:var(--_n-aside-drawer-z-index)}.n-aside-drawer{block-size:100%;inline-size:100%}::slotted(*){block-size:100%}::slotted(nord-drawer){--n-drawer-border-color:var(--_n-aside-drawer-border-color);--n-drawer-border-radius:var(--_n-aside-drawer-border-radius);--n-drawer-border-inline-start-width:var(--_n-aside-drawer-border-width);--n-drawer-border-inline-end-width:var(--_n-aside-drawer-border-inline-end-width);--n-drawer-border-block-start-width:var(--_n-aside-drawer-border-block-start-width);--n-drawer-border-block-end-width:var(--_n-aside-drawer-border-block-end-width)}@media (min-width:768px){:host([data-animating-fullscreen]),:host([fullscreen]){inset-block-end:var(--n-layout-footer-block-size,0);inset-block-start:var(--_n-aside-drawer-fullscreen-inset-block-start);inset-inline-end:calc(var(--n-aside-rail-width, 48px) + var(--_n-aside-rail-gap, 0px));margin-inline:0;position:fixed;z-index:var(--_n-aside-drawer-fullscreen-z-index)}:host([fullscreen]){inline-size:min(var(--_n-aside-drawer-fullscreen-max,100vw),var(--_n-aside-drawer-fullscreen-available,100vw));max-inline-size:min(var(--_n-aside-drawer-fullscreen-max,100vw),var(--_n-aside-drawer-fullscreen-available,100vw));min-inline-size:0}}`;class w extends o{constructor(e,i){super("width-change"),Object.defineProperty(this,"width",{value:e,enumerable:!0,writable:!1}),Object.defineProperty(this,"source",{value:i,enumerable:!0,writable:!1})}}const b="nord-aside.";function v(e){return`${b}${e}.width`}let p=class extends t{constructor(){super(...arguments),this.defaultWidth=420,this.minWidth=280,this.maxWidth=Number.MAX_SAFE_INTEGER,this.maxFullscreenWidth=Number.MAX_SAFE_INTEGER,this.disabled=!1,this.fullscreen=!1,this.floating=!1,this.width=420,this.widthSeeded=!1,this.fullscreenSeeded=!1,this.observedWidth=0}render(){return r`<div class="n-aside-drawer" part="drawer"><slot></slot></div>`}connectedCallback(){super.connectedCallback(),this.applyFloatingRole(),this.applyAriaLabelledby(),n||(this.observedWidth=this.getBoundingClientRect().width,"undefined"!=typeof ResizeObserver&&(this.fullscreenResizeObserver=new ResizeObserver((e=>{var i,t,r;if(this.hasAttribute("data-animating-fullscreen"))return;const n=e[0];if(!n)return;const a=null!==(r=null===(t=null===(i=n.borderBoxSize)||void 0===i?void 0:i[0])||void 0===t?void 0:t.inlineSize)&&void 0!==r?r:n.contentRect.width;this.observedWidth=a})),this.fullscreenResizeObserver.observe(this)))}disconnectedCallback(){var e,i;super.disconnectedCallback(),null===(e=this.fullscreenResizeObserver)||void 0===e||e.disconnect(),this.fullscreenResizeObserver=void 0,null===(i=this.fullscreenAnimation)||void 0===i||i.cancel(),this.fullscreenAnimation=void 0,this.fullscreenAnimationCleanup=void 0,this.removeAttribute("data-animating-fullscreen"),this.style.removeProperty("inline-size"),this.style.removeProperty("max-inline-size"),this.style.removeProperty("min-inline-size")}willUpdate(){this.widthSeeded||(this.seedWidth(),this.widthSeeded=!0)}handleFullscreenChange(e,i){if(n)return;if(!this.fullscreenSeeded)return this.fullscreenSeeded=!0,void(this.observedWidth=this.getBoundingClientRect().width);if("undefined"!=typeof matchMedia&&!matchMedia("(min-width: 768px)").matches)return;this.fullscreenAnimation&&(this.observedWidth=this.getBoundingClientRect().width,this.fullscreenAnimation.cancel(),this.fullscreenAnimation=void 0,this.fullscreenAnimationCleanup=void 0);const t=this.observedWidth;this.setAttribute("data-animating-fullscreen",""),i||this.setWidth(this.defaultWidth,"attribute"),this.style.setProperty("inline-size",`${t}px`),this.style.setProperty("max-inline-size",`${t}px`),this.style.setProperty("min-inline-size",`${t}px`),requestAnimationFrame((()=>requestAnimationFrame((()=>{this.style.removeProperty("inline-size"),this.style.removeProperty("max-inline-size"),this.style.removeProperty("min-inline-size");const e=this.getBoundingClientRect().width;if(Math.abs(t-e)<1)return this.removeAttribute("data-animating-fullscreen"),this.observedWidth=e,void(this.fullscreenAnimationCleanup=void 0);const i=this.animate([{inlineSize:`${t}px`,maxInlineSize:`${t}px`,minInlineSize:`${t}px`},{inlineSize:`${e}px`,maxInlineSize:`${e}px`,minInlineSize:`${e}px`}],{duration:300,easing:"cubic-bezier(0.4, 0, 0.2, 1)",fill:"none"});this.fullscreenAnimation=i;const r=()=>{this.fullscreenAnimation===i&&(this.fullscreenAnimation=void 0,this.fullscreenAnimationCleanup=void 0,this.removeAttribute("data-animating-fullscreen"),this.observedWidth=this.getBoundingClientRect().width)};this.fullscreenAnimationCleanup=r,i.onfinish=r,i.oncancel=r}))))}handleBoundsChange(){if(!this.widthSeeded)return;const e=h(this.width,this.minWidth,this.maxWidth);e!==this.width?this.setWidth(e,"attribute"):this.applyWidthVars()}handleFloatingChange(){this.applyFloatingRole()}applyFloatingRole(){this.floating?(this.setAttribute("role","dialog"),this.setAttribute("aria-modal","true")):(this.setAttribute("role","region"),this.removeAttribute("aria-modal"))}applyWidthVars(){this.style.setProperty("--_n-aside-drawer-inline-size",`${this.width}px`),this.style.setProperty("--_n-aside-drawer-min-inline-size",`${this.minWidth}px`);const e=this.maxWidth>=Number.MAX_SAFE_INTEGER;this.style.setProperty("--_n-aside-drawer-max-inline-size",e?"none":`${this.maxWidth}px`);const i=this.maxFullscreenWidth>=Number.MAX_SAFE_INTEGER;this.style.setProperty("--_n-aside-drawer-fullscreen-max",i?"100vw":`max(${this.minWidth}px, ${this.maxFullscreenWidth}px)`)}setWidth(e,i){const t=h(Math.round(e),this.minWidth,this.maxWidth);t!==this.width&&(this.width=t,!n&&this.id&&(u(v(this.id),this.defaultWidth).value=this.width),this.dispatchEvent(new w(this.width,i)))}get isPinned(){return this.minWidth===this.maxWidth}seedWidth(){if(n||!this.id)return this.width=h(this.defaultWidth,this.minWidth,this.maxWidth),void this.applyWidthVars();const e=u(v(this.id),this.defaultWidth),i=u((t=this.id,`${b}${t}.defaultWidth`),this.defaultWidth);var t;let r,a;i.value!==this.defaultWidth?(r=this.defaultWidth,e.value=r,i.value=this.defaultWidth,a="attribute"):(r=e.value,a="storage"),this.width=h(Math.round(r),this.minWidth,this.maxWidth),this.applyWidthVars(),this.dispatchEvent(new w(this.width,a))}applyAriaLabelledby(){if(!this.id)return void this.removeAttribute("aria-labelledby");const e=this.closest("nord-aside");if(!e)return;const i=e.querySelector(`nord-aside-trigger[drawer="${this.id}"]`);i&&(i.id||(i.id=`${this.id}-trigger`),this.setAttribute("aria-labelledby",i.id))}};p.styles=[c,m],e([a({reflect:!0,type:Number,attribute:"default-width"})],p.prototype,"defaultWidth",void 0),e([a({reflect:!0,type:Number,attribute:"min-width"})],p.prototype,"minWidth",void 0),e([a({reflect:!1,type:Number,attribute:"max-width"})],p.prototype,"maxWidth",void 0),e([a({reflect:!1,type:Number,attribute:"max-fullscreen-width"})],p.prototype,"maxFullscreenWidth",void 0),e([a({type:Boolean,reflect:!0})],p.prototype,"disabled",void 0),e([a({type:Boolean,reflect:!0})],p.prototype,"fullscreen",void 0),e([a({type:Boolean,reflect:!1})],p.prototype,"floating",void 0),e([d()],p.prototype,"width",void 0),e([l("fullscreen")],p.prototype,"handleFullscreenChange",null),e([l("defaultWidth"),l("minWidth"),l("maxWidth"),l("maxFullscreenWidth")],p.prototype,"handleBoundsChange",null),e([l("floating")],p.prototype,"handleFloatingChange",null),e([l("width")],p.prototype,"applyWidthVars",null),p=e([s("nord-aside-drawer")],p);var f=p;export{w as AsideDrawerWidthChangeEvent,f as default};
|
|
10
10
|
//# sourceMappingURL=AsideDrawer.js.map
|
package/lib/AsideDrawer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AsideDrawer.js","sources":["../src/aside-drawer/AsideDrawer.ts"],"sourcesContent":["import { html, isServer, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { observe } from '../common/decorators/observe.js'\nimport { NordEvent } from '../common/events.js'\nimport { clamp } from '../common/number.js'\nimport { storage } from '../common/storage.js'\n\nimport componentStyle from '../common/styles/Component.css'\nimport style from './AsideDrawer.css'\n\nexport type AsideDrawerWidthSource = 'drag' | 'keyboard' | 'attribute' | 'storage'\n\n/**\n * Event dispatched when the drawer's width changes. The `width` property is\n * the new applied inline-size in px, and `source` is the cause of the change.\n */\nexport class AsideDrawerWidthChangeEvent extends NordEvent {\n declare width: number\n declare source: AsideDrawerWidthSource\n\n constructor(width: number, source: AsideDrawerWidthSource) {\n super('width-change')\n Object.defineProperty(this, 'width', {\n value: width,\n enumerable: true,\n writable: false,\n })\n Object.defineProperty(this, 'source', {\n value: source,\n enumerable: true,\n writable: false,\n })\n }\n}\n\nconst STORAGE_KEY_PREFIX = 'nord-aside.'\n\nfunction widthKey(id: string) {\n return `${STORAGE_KEY_PREFIX}${id}.width`\n}\n\nfunction defaultWidthKey(id: string) {\n return `${STORAGE_KEY_PREFIX}${id}.defaultWidth`\n}\n\n/**\n * A drawer panel inside `<nord-aside>`.\n *\n * @status new\n * @category layout\n * @slot - Default slot. Place arbitrary drawer content here.\n *\n * @fires {AsideDrawerWidthChangeEvent} width-change - Dispatched when the\n * drawer's width changes. The event exposes `width` (the new applied\n * inline-size in px) and `source` (`'drag' | 'keyboard' | 'attribute' | 'storage'`).\n *\n * @parent Aside\n */\n@customElement('nord-aside-drawer')\nexport default class AsideDrawer extends LitElement {\n static styles = [componentStyle, style]\n\n /**\n * Initial width in px. The persisted value overrides this on load; if\n * `default-width` changes between sessions, the persisted value is\n * re-seeded to the new default.\n */\n @property({ reflect: true, type: Number, attribute: 'default-width' }) defaultWidth: number = 420\n\n /**\n * Resize clamp lower bound in px.\n */\n @property({ reflect: true, type: Number, attribute: 'min-width' }) minWidth: number = 280\n\n /**\n * Resize clamp upper bound in px. Defaults to `Number.MAX_SAFE_INTEGER`\n * so an unset `max-width` doesn't constrain the drawer — the consumer's\n * layout (or the rail / nav anchoring) determines the practical ceiling.\n * Set an explicit value to clamp.\n *\n * Not reflected: an unset cap is the `Number.MAX_SAFE_INTEGER` sentinel,\n * which must never render into the DOM as `max-width=\"9007199254740991\"`.\n */\n @property({ reflect: false, type: Number, attribute: 'max-width' }) maxWidth: number = Number.MAX_SAFE_INTEGER\n\n /**\n * Maximum inline-size in px the drawer can reach when `[fullscreen]`\n * is active. Independent of `max-width` (which only caps the docked\n * drag / keyboard resize) — fullscreen typically wants to grow\n * larger than the docked maximum. Defaults to `Number.MAX_SAFE_INTEGER`\n * so an unset value lets fullscreen fill all available room (bounded\n * by the layout's left-cap rule in `<nord-aside>`).\n *\n * Not reflected: an unset cap is the `Number.MAX_SAFE_INTEGER` sentinel,\n * which must never render into the DOM.\n */\n @property({ reflect: false, type: Number, attribute: 'max-fullscreen-width' }) maxFullscreenWidth: number = Number.MAX_SAFE_INTEGER\n\n /**\n * When set, the drawer cannot be opened. Programmatic opens are silently\n * ignored; if the drawer is already open and this flips on, the drawer\n * stays open until closed normally.\n */\n @property({ type: Boolean, reflect: true }) disabled: boolean = false\n\n /**\n * Reflected. Phase 3 wires the overlay sizing internally.\n */\n @property({ type: Boolean, reflect: true }) fullscreen: boolean = false\n\n /**\n * Set by the parent `<nord-aside>` when the drawer renders as a narrow\n * floating overlay (rather than a docked region). When `true` the host\n * becomes an accessible modal dialog (`role=\"dialog\"` + `aria-modal`);\n * when `false` the host is a `role=\"region\"` landmark. Drive this only\n * through the parent — it owns the floating-vs-docked decision.\n */\n @property({ type: Boolean, reflect: false }) floating: boolean = false\n\n /**\n * Currently-applied width in px. Public read-only-ish; use `setWidth()`\n * (or drive via `default-width` + min/max attrs) rather than poking\n * this directly.\n * @internal\n */\n @state() width = 420\n\n private widthSeeded = false\n private fullscreenSeeded = false\n private fullscreenAnimationCleanup?: () => void\n private fullscreenAnimation?: Animation\n // Last painted inline-size, kept up to date by ResizeObserver. Used as\n // the animation's `fromWidth` on toggle — read from this cache instead\n // of `getBoundingClientRect()` (which would force sync layout against\n // the already-mutated `fullscreen` attribute).\n private observedWidth = 0\n private fullscreenResizeObserver?: ResizeObserver\n\n render() {\n return html`\n <div class=\"n-aside-drawer\" part=\"drawer\">\n <slot></slot>\n </div>\n `\n }\n\n connectedCallback() {\n super.connectedCallback()\n this.applyFloatingRole()\n this.applyAriaLabelledby()\n if (isServer) {\n return\n }\n // Seed observedWidth synchronously so the first toggle has a valid\n // fromWidth even before ResizeObserver has fired.\n this.observedWidth = this.getBoundingClientRect().width\n if (typeof ResizeObserver !== 'undefined') {\n this.fullscreenResizeObserver = new ResizeObserver((entries) => {\n // Don't overwrite while an animation is running — intermediate\n // frames aren't valid `fromWidth` candidates for the NEXT toggle.\n if (this.hasAttribute('data-animating-fullscreen'))\n return\n const entry = entries[0]\n if (!entry)\n return\n const size = entry.borderBoxSize?.[0]?.inlineSize ?? entry.contentRect.width\n this.observedWidth = size\n })\n this.fullscreenResizeObserver.observe(this)\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.fullscreenResizeObserver?.disconnect()\n this.fullscreenResizeObserver = undefined\n this.fullscreenAnimation?.cancel()\n this.fullscreenAnimation = undefined\n this.fullscreenAnimationCleanup = undefined\n }\n\n willUpdate() {\n if (!this.widthSeeded) {\n this.seedWidth()\n this.widthSeeded = true\n }\n }\n\n /**\n * Animate the fullscreen toggle ONLY when the user flips the attribute.\n * Not on initial mount, not on drag-resize, not on show/hide, not on\n * nav-state-driven size changes.\n *\n * Uses Web Animations API with explicit `from`/`to` keyframes because\n * the drawer's `position` flips between `relative` (docked, in flex\n * flow) and `fixed` (fullscreen, overlay). CSS transitions don't\n * reliably interpolate `inline-size` across a position-type change.\n *\n * `fromWidth` comes from `observedWidth` — the last size painted by\n * the browser, captured by ResizeObserver BEFORE the consumer flipped\n * the attribute. Reading `getBoundingClientRect()` here would return\n * the post-toggle size (Lit has already reflected the attribute), so\n * the cached value is the only reliable pre-toggle width.\n *\n * `toWidth` is measured inside rAF, after Lit has committed the new\n * attribute and Aside has updated `--_n-aside-drawer-fullscreen-size`.\n *\n * Exiting also resets the drawer's docked width to its declared\n * `default-width` so the user lands at a predictable size after\n * collapsing.\n */\n @observe('fullscreen')\n protected handleFullscreenChange(_oldValue: boolean | undefined, newValue: boolean) {\n if (isServer) {\n return\n }\n if (!this.fullscreenSeeded) {\n this.fullscreenSeeded = true\n this.observedWidth = this.getBoundingClientRect().width\n return\n }\n // At narrow viewports the `fullscreen` attribute has no visual effect\n // (the parent <nord-aside> renders the drawer as a floating overlay\n // regardless). The CSS rules for [fullscreen] are gated behind\n // `@media (min-width: 768px)` — skip the animation here too so we\n // don't run a no-op WAAPI animation against zero size delta.\n if (typeof matchMedia !== 'undefined' && !matchMedia('(min-width: 768px)').matches) {\n return\n }\n\n // Reverse-mid-flight: snapshot the current visible width BEFORE\n // cancelling, because `animation.cancel()` synchronously reverts\n // the element to its CSS layout — measuring after cancel would\n // give us the underlying CSS width, not what the user is seeing.\n // oncancel fires synchronously on cancel(), so cleanup runs from there —\n // do NOT call cleanupFn manually here or it will run twice.\n if (this.fullscreenAnimation) {\n this.observedWidth = this.getBoundingClientRect().width\n this.fullscreenAnimation.cancel()\n }\n\n const fromWidth = this.observedWidth\n\n // Pin `position: fixed` for the entire animation in both directions\n // via `:host([data-animating-fullscreen])`. Setting this here also\n // tells the ResizeObserver to stop updating `observedWidth`.\n this.setAttribute('data-animating-fullscreen', '')\n\n if (!newValue) {\n this.setWidth(this.defaultWidth, 'attribute')\n }\n\n // Double-rAF: the first frame lets Aside's scheduleLeftCapReconcile rAF\n // (queued synchronously above via syncFullscreenAttr) write\n // `--_n-aside-drawer-fullscreen-available`. The second frame then reads\n // the post-reconcile toWidth so the animation end-state is correct.\n requestAnimationFrame(() => requestAnimationFrame(() => {\n const toWidth = this.getBoundingClientRect().width\n\n if (Math.abs(fromWidth - toWidth) < 1) {\n this.removeAttribute('data-animating-fullscreen')\n this.observedWidth = toWidth\n this.fullscreenAnimationCleanup = undefined\n return\n }\n\n const animation = this.animate(\n [\n {\n inlineSize: `${fromWidth}px`,\n maxInlineSize: `${fromWidth}px`,\n minInlineSize: `${fromWidth}px`,\n },\n {\n inlineSize: `${toWidth}px`,\n maxInlineSize: `${toWidth}px`,\n minInlineSize: `${toWidth}px`,\n },\n ],\n {\n duration: 300,\n easing: 'cubic-bezier(0.4, 0, 0.2, 1)',\n fill: 'none',\n },\n )\n\n this.fullscreenAnimation = animation\n\n const cleanup = () => {\n if (this.fullscreenAnimation !== animation)\n return\n this.fullscreenAnimation = undefined\n this.fullscreenAnimationCleanup = undefined\n this.removeAttribute('data-animating-fullscreen')\n this.observedWidth = this.getBoundingClientRect().width\n }\n this.fullscreenAnimationCleanup = cleanup\n animation.onfinish = cleanup\n animation.oncancel = cleanup\n }))\n }\n\n @observe('defaultWidth')\n @observe('minWidth')\n @observe('maxWidth')\n @observe('maxFullscreenWidth')\n protected handleBoundsChange() {\n // Re-seeding happens once on willUpdate; subsequent bound changes\n // just re-clamp the current width.\n if (!this.widthSeeded) {\n return\n }\n const clamped = clamp(this.width, this.minWidth, this.maxWidth)\n if (clamped !== this.width) {\n this.setWidth(clamped, 'attribute')\n }\n else {\n this.applyWidthVars()\n }\n }\n\n @observe('floating')\n protected handleFloatingChange() {\n this.applyFloatingRole()\n }\n\n /**\n * Single writer for the host's landmark/dialog role. A floating overlay\n * is an accessible modal (`role=\"dialog\"` + `aria-modal=\"true\"`); a docked\n * drawer is a `role=\"region\"` landmark with no aria-modal.\n */\n private applyFloatingRole() {\n if (this.floating) {\n this.setAttribute('role', 'dialog')\n this.setAttribute('aria-modal', 'true')\n }\n else {\n this.setAttribute('role', 'region')\n this.removeAttribute('aria-modal')\n }\n }\n\n @observe('width')\n protected applyWidthVars() {\n this.style.setProperty('--_n-aside-drawer-inline-size', `${this.width}px`)\n this.style.setProperty('--_n-aside-drawer-min-inline-size', `${this.minWidth}px`)\n // An unset `max-width` defaults to MAX_SAFE_INTEGER — too large for\n // CSS to handle reliably. Translate to `none` so the drawer has no\n // CSS-side cap; the clamp in `setWidth` still runs against the\n // numeric value so drag/keyboard don't escape JS-side bounds.\n const isMaxUnbounded = this.maxWidth >= Number.MAX_SAFE_INTEGER\n this.style.setProperty('--_n-aside-drawer-max-inline-size', isMaxUnbounded ? 'none' : `${this.maxWidth}px`)\n // Fullscreen rendered inline-size is the CSS-time `min()` of two vars:\n // - `--_n-aside-drawer-fullscreen-max` (this var, drawer-owned)\n // - `--_n-aside-drawer-fullscreen-available` (written by <nord-aside>\n // to the layout's left-cap; absent when there's no aside parent)\n // The drawer's own var floors at `minWidth` so a tiny consumer value\n // can never drop the drawer below its declared minimum. Unset\n // `max-fullscreen-width` resolves to `100vw` — a sensible standalone\n // fallback when there's no aside to publish the available width.\n const isFullscreenUnbounded = this.maxFullscreenWidth >= Number.MAX_SAFE_INTEGER\n this.style.setProperty(\n '--_n-aside-drawer-fullscreen-max',\n isFullscreenUnbounded\n ? '100vw'\n : `max(${this.minWidth}px, ${this.maxFullscreenWidth}px)`,\n )\n }\n\n /**\n * Update the drawer width, clamped to `[min-width, max-width]`. Persists\n * to localStorage and dispatches `width-change` with the given source.\n */\n setWidth(width: number, source: AsideDrawerWidthSource) {\n const next = clamp(Math.round(width), this.minWidth, this.maxWidth)\n if (next === this.width) {\n return\n }\n this.width = next\n if (!isServer && this.id) {\n storage(widthKey(this.id), this.defaultWidth).value = this.width\n }\n this.dispatchEvent(new AsideDrawerWidthChangeEvent(this.width, source))\n }\n\n /**\n * Whether the drawer is pinned — `min === max === default`. A pinned\n * drawer's resize handle is a drag no-op.\n */\n get isPinned(): boolean {\n return this.minWidth === this.maxWidth\n }\n\n /**\n * Lift Layout.ts's re-seed pattern: if the consumer-provided\n * `default-width` differs from the last default we wrote for this id,\n * the persisted width is reset to the new default.\n */\n private seedWidth() {\n // On the server there's no localStorage and no layout to paint; clamp\n // the declared default and skip both the storage read/write and the\n // `width-change` dispatch.\n if (isServer || !this.id) {\n this.width = clamp(this.defaultWidth, this.minWidth, this.maxWidth)\n this.applyWidthVars()\n return\n }\n const widthStore = storage(widthKey(this.id), this.defaultWidth)\n const defaultStore = storage(defaultWidthKey(this.id), this.defaultWidth)\n let next: number\n let source: AsideDrawerWidthSource\n if (defaultStore.value !== this.defaultWidth) {\n next = this.defaultWidth\n widthStore.value = next\n defaultStore.value = this.defaultWidth\n source = 'attribute'\n }\n else {\n next = widthStore.value\n source = 'storage'\n }\n this.width = clamp(Math.round(next), this.minWidth, this.maxWidth)\n this.applyWidthVars()\n this.dispatchEvent(new AsideDrawerWidthChangeEvent(this.width, source))\n }\n\n /**\n * Resolve the matching `<nord-aside-trigger drawer=\"<this.id>\">` inside\n * the ancestor `<nord-aside>` and use it as the drawer's aria-labelledby\n * target. Falls back to no label when no matching trigger exists.\n */\n private applyAriaLabelledby() {\n if (!this.id) {\n this.removeAttribute('aria-labelledby')\n return\n }\n const aside = this.closest('nord-aside')\n if (!aside) {\n return\n }\n const trigger = aside.querySelector<HTMLElement>(\n `nord-aside-trigger[drawer=\"${this.id}\"]`,\n )\n if (!trigger) {\n return\n }\n if (!trigger.id) {\n trigger.id = `${this.id}-trigger`\n }\n this.setAttribute('aria-labelledby', trigger.id)\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-aside-drawer': AsideDrawer\n }\n}\n"],"names":["AsideDrawerWidthChangeEvent","NordEvent","constructor","width","source","super","Object","defineProperty","this","value","enumerable","writable","STORAGE_KEY_PREFIX","widthKey","id","AsideDrawer","LitElement","defaultWidth","minWidth","maxWidth","Number","MAX_SAFE_INTEGER","maxFullscreenWidth","disabled","fullscreen","floating","widthSeeded","fullscreenSeeded","observedWidth","render","html","connectedCallback","applyFloatingRole","applyAriaLabelledby","isServer","getBoundingClientRect","ResizeObserver","fullscreenResizeObserver","entries","hasAttribute","entry","size","_c","_a","borderBoxSize","_b","inlineSize","contentRect","observe","disconnectedCallback","disconnect","undefined","fullscreenAnimation","cancel","fullscreenAnimationCleanup","willUpdate","seedWidth","handleFullscreenChange","_oldValue","newValue","matchMedia","matches","fromWidth","setAttribute","setWidth","requestAnimationFrame","toWidth","Math","abs","removeAttribute","animation","animate","maxInlineSize","minInlineSize","duration","easing","fill","cleanup","onfinish","oncancel","handleBoundsChange","clamped","clamp","applyWidthVars","handleFloatingChange","style","setProperty","isMaxUnbounded","isFullscreenUnbounded","next","round","storage","dispatchEvent","isPinned","widthStore","defaultStore","aside","closest","trigger","querySelector","styles","componentStyle","__decorate","property","reflect","type","attribute","prototype","Boolean","state","customElement"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AsideDrawer.js","sources":["../src/aside-drawer/AsideDrawer.ts"],"sourcesContent":["import { html, isServer, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { observe } from '../common/decorators/observe.js'\nimport { NordEvent } from '../common/events.js'\nimport { clamp } from '../common/number.js'\nimport { storage } from '../common/storage.js'\n\nimport componentStyle from '../common/styles/Component.css'\nimport style from './AsideDrawer.css'\n\nexport type AsideDrawerWidthSource = 'drag' | 'keyboard' | 'attribute' | 'storage'\n\n/**\n * Event dispatched when the drawer's width changes. The `width` property is\n * the new applied inline-size in px, and `source` is the cause of the change.\n */\nexport class AsideDrawerWidthChangeEvent extends NordEvent {\n declare width: number\n declare source: AsideDrawerWidthSource\n\n constructor(width: number, source: AsideDrawerWidthSource) {\n super('width-change')\n Object.defineProperty(this, 'width', {\n value: width,\n enumerable: true,\n writable: false,\n })\n Object.defineProperty(this, 'source', {\n value: source,\n enumerable: true,\n writable: false,\n })\n }\n}\n\nconst STORAGE_KEY_PREFIX = 'nord-aside.'\n\nfunction widthKey(id: string) {\n return `${STORAGE_KEY_PREFIX}${id}.width`\n}\n\nfunction defaultWidthKey(id: string) {\n return `${STORAGE_KEY_PREFIX}${id}.defaultWidth`\n}\n\n/**\n * A drawer panel inside `<nord-aside>`.\n *\n * @status new\n * @category layout\n * @slot - Default slot. Place arbitrary drawer content here.\n *\n * @fires {AsideDrawerWidthChangeEvent} width-change - Dispatched when the\n * drawer's width changes. The event exposes `width` (the new applied\n * inline-size in px) and `source` (`'drag' | 'keyboard' | 'attribute' | 'storage'`).\n *\n * @parent Aside\n */\n@customElement('nord-aside-drawer')\nexport default class AsideDrawer extends LitElement {\n static styles = [componentStyle, style]\n\n /**\n * Initial width in px. The persisted value overrides this on load; if\n * `default-width` changes between sessions, the persisted value is\n * re-seeded to the new default.\n */\n @property({ reflect: true, type: Number, attribute: 'default-width' }) defaultWidth: number = 420\n\n /**\n * Resize clamp lower bound in px.\n */\n @property({ reflect: true, type: Number, attribute: 'min-width' }) minWidth: number = 280\n\n /**\n * Resize clamp upper bound in px. Defaults to `Number.MAX_SAFE_INTEGER`\n * so an unset `max-width` doesn't constrain the drawer — the consumer's\n * layout (or the rail / nav anchoring) determines the practical ceiling.\n * Set an explicit value to clamp.\n *\n * Not reflected: an unset cap is the `Number.MAX_SAFE_INTEGER` sentinel,\n * which must never render into the DOM as `max-width=\"9007199254740991\"`.\n */\n @property({ reflect: false, type: Number, attribute: 'max-width' }) maxWidth: number = Number.MAX_SAFE_INTEGER\n\n /**\n * Maximum inline-size in px the drawer can reach when `[fullscreen]`\n * is active. Independent of `max-width` (which only caps the docked\n * drag / keyboard resize) — fullscreen typically wants to grow\n * larger than the docked maximum. Defaults to `Number.MAX_SAFE_INTEGER`\n * so an unset value lets fullscreen fill all available room (bounded\n * by the layout's left-cap rule in `<nord-aside>`).\n *\n * Not reflected: an unset cap is the `Number.MAX_SAFE_INTEGER` sentinel,\n * which must never render into the DOM.\n */\n @property({ reflect: false, type: Number, attribute: 'max-fullscreen-width' }) maxFullscreenWidth: number = Number.MAX_SAFE_INTEGER\n\n /**\n * When set, the drawer cannot be opened. Programmatic opens are silently\n * ignored; if the drawer is already open and this flips on, the drawer\n * stays open until closed normally.\n */\n @property({ type: Boolean, reflect: true }) disabled: boolean = false\n\n /**\n * Reflected. Phase 3 wires the overlay sizing internally.\n */\n @property({ type: Boolean, reflect: true }) fullscreen: boolean = false\n\n /**\n * Set by the parent `<nord-aside>` when the drawer renders as a narrow\n * floating overlay (rather than a docked region). When `true` the host\n * becomes an accessible modal dialog (`role=\"dialog\"` + `aria-modal`);\n * when `false` the host is a `role=\"region\"` landmark. Drive this only\n * through the parent — it owns the floating-vs-docked decision.\n */\n @property({ type: Boolean, reflect: false }) floating: boolean = false\n\n /**\n * Currently-applied width in px. Public read-only-ish; use `setWidth()`\n * (or drive via `default-width` + min/max attrs) rather than poking\n * this directly.\n * @internal\n */\n @state() width = 420\n\n private widthSeeded = false\n private fullscreenSeeded = false\n private fullscreenAnimationCleanup?: () => void\n private fullscreenAnimation?: Animation\n // Last painted inline-size, kept up to date by ResizeObserver. Used as\n // the animation's `fromWidth` on toggle — read from this cache instead\n // of `getBoundingClientRect()` (which would force sync layout against\n // the already-mutated `fullscreen` attribute).\n private observedWidth = 0\n private fullscreenResizeObserver?: ResizeObserver\n\n render() {\n return html`\n <div class=\"n-aside-drawer\" part=\"drawer\">\n <slot></slot>\n </div>\n `\n }\n\n connectedCallback() {\n super.connectedCallback()\n this.applyFloatingRole()\n this.applyAriaLabelledby()\n if (isServer) {\n return\n }\n // Seed observedWidth synchronously so the first toggle has a valid\n // fromWidth even before ResizeObserver has fired.\n this.observedWidth = this.getBoundingClientRect().width\n if (typeof ResizeObserver !== 'undefined') {\n this.fullscreenResizeObserver = new ResizeObserver((entries) => {\n // Don't overwrite while an animation is running — intermediate\n // frames aren't valid `fromWidth` candidates for the NEXT toggle.\n if (this.hasAttribute('data-animating-fullscreen'))\n return\n const entry = entries[0]\n if (!entry)\n return\n const size = entry.borderBoxSize?.[0]?.inlineSize ?? entry.contentRect.width\n this.observedWidth = size\n })\n this.fullscreenResizeObserver.observe(this)\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.fullscreenResizeObserver?.disconnect()\n this.fullscreenResizeObserver = undefined\n this.fullscreenAnimation?.cancel()\n this.fullscreenAnimation = undefined\n this.fullscreenAnimationCleanup = undefined\n // The cancel EVENT is queued, not synchronous, and its cleanup no-ops\n // once `fullscreenAnimation` is cleared — so remove the animation\n // state directly. Without this, a drawer disconnected mid-toggle\n // (or while the tab is hidden and rAFs are paused) reconnects with a\n // stale width pin and a stuck `position: fixed`.\n this.removeAttribute('data-animating-fullscreen')\n this.style.removeProperty('inline-size')\n this.style.removeProperty('max-inline-size')\n this.style.removeProperty('min-inline-size')\n }\n\n willUpdate() {\n if (!this.widthSeeded) {\n this.seedWidth()\n this.widthSeeded = true\n }\n }\n\n /**\n * Animate the fullscreen toggle ONLY when the user flips the attribute.\n * Not on initial mount, not on drag-resize, not on show/hide, not on\n * nav-state-driven size changes.\n *\n * Uses Web Animations API with explicit `from`/`to` keyframes because\n * the drawer's `position` flips between `relative` (docked, in flex\n * flow) and `fixed` (fullscreen, overlay). CSS transitions don't\n * reliably interpolate `inline-size` across a position-type change.\n *\n * `fromWidth` comes from `observedWidth` — the last size painted by\n * the browser, captured by ResizeObserver BEFORE the consumer flipped\n * the attribute. Reading `getBoundingClientRect()` here would return\n * the post-toggle size (Lit has already reflected the attribute), so\n * the cached value is the only reliable pre-toggle width.\n *\n * `toWidth` is measured inside rAF, after Lit has committed the new\n * attribute and Aside has updated `--_n-aside-drawer-fullscreen-size`.\n *\n * Exiting also resets the drawer's docked width to its declared\n * `default-width` so the user lands at a predictable size after\n * collapsing.\n */\n @observe('fullscreen')\n protected handleFullscreenChange(_oldValue: boolean | undefined, newValue: boolean) {\n if (isServer) {\n return\n }\n if (!this.fullscreenSeeded) {\n this.fullscreenSeeded = true\n this.observedWidth = this.getBoundingClientRect().width\n return\n }\n // At narrow viewports the `fullscreen` attribute has no visual effect\n // (the parent <nord-aside> renders the drawer as a floating overlay\n // regardless). The CSS rules for [fullscreen] are gated behind\n // `@media (min-width: 768px)` — skip the animation here too so we\n // don't run a no-op WAAPI animation against zero size delta.\n if (typeof matchMedia !== 'undefined' && !matchMedia('(min-width: 768px)').matches) {\n return\n }\n\n // Reverse-mid-flight: snapshot the current visible width BEFORE\n // cancelling, because `animation.cancel()` synchronously reverts\n // the element to its CSS layout — measuring after cancel would\n // give us the underlying CSS width, not what the user is seeing.\n // The cancel EVENT however is queued, firing in the next rendering\n // update — AFTER this handler has re-set `data-animating-fullscreen`\n // below. Clear `fullscreenAnimation` here so the stale animation's\n // cleanup fails its identity guard and can't strip the attribute\n // this new toggle now owns (which would drop `position: fixed`\n // mid-animation and push the drawer back into flex flow).\n if (this.fullscreenAnimation) {\n this.observedWidth = this.getBoundingClientRect().width\n this.fullscreenAnimation.cancel()\n this.fullscreenAnimation = undefined\n this.fullscreenAnimationCleanup = undefined\n }\n\n const fromWidth = this.observedWidth\n\n // Pin `position: fixed` for the entire animation in both directions\n // via `:host([data-animating-fullscreen])`. Setting this here also\n // tells the ResizeObserver to stop updating `observedWidth`.\n this.setAttribute('data-animating-fullscreen', '')\n\n if (!newValue) {\n this.setWidth(this.defaultWidth, 'attribute')\n }\n\n // Pin the pre-toggle width inline for the frame(s) between the\n // attribute flip and the animation start below — without this the\n // browser paints the CSS end-state (fullscreen or re-docked) for a\n // frame, flashing the final size before the animation snaps back to\n // `fromWidth`. The pin is removed just before measuring the animation\n // target; once running, the animation's keyframes outrank inline\n // styles anyway.\n this.style.setProperty('inline-size', `${fromWidth}px`)\n this.style.setProperty('max-inline-size', `${fromWidth}px`)\n this.style.setProperty('min-inline-size', `${fromWidth}px`)\n\n // Double-rAF: the first frame lets Aside's scheduleLeftCapReconcile rAF\n // (queued synchronously above via syncFullscreenAttr) write\n // `--_n-aside-drawer-fullscreen-available`. The second frame then reads\n // the post-reconcile toWidth so the animation end-state is correct.\n requestAnimationFrame(() => requestAnimationFrame(() => {\n this.style.removeProperty('inline-size')\n this.style.removeProperty('max-inline-size')\n this.style.removeProperty('min-inline-size')\n\n const toWidth = this.getBoundingClientRect().width\n\n if (Math.abs(fromWidth - toWidth) < 1) {\n this.removeAttribute('data-animating-fullscreen')\n this.observedWidth = toWidth\n this.fullscreenAnimationCleanup = undefined\n return\n }\n\n const animation = this.animate(\n [\n {\n inlineSize: `${fromWidth}px`,\n maxInlineSize: `${fromWidth}px`,\n minInlineSize: `${fromWidth}px`,\n },\n {\n inlineSize: `${toWidth}px`,\n maxInlineSize: `${toWidth}px`,\n minInlineSize: `${toWidth}px`,\n },\n ],\n {\n duration: 300,\n easing: 'cubic-bezier(0.4, 0, 0.2, 1)',\n fill: 'none',\n },\n )\n\n this.fullscreenAnimation = animation\n\n const cleanup = () => {\n if (this.fullscreenAnimation !== animation)\n return\n this.fullscreenAnimation = undefined\n this.fullscreenAnimationCleanup = undefined\n this.removeAttribute('data-animating-fullscreen')\n this.observedWidth = this.getBoundingClientRect().width\n }\n this.fullscreenAnimationCleanup = cleanup\n animation.onfinish = cleanup\n animation.oncancel = cleanup\n }))\n }\n\n @observe('defaultWidth')\n @observe('minWidth')\n @observe('maxWidth')\n @observe('maxFullscreenWidth')\n protected handleBoundsChange() {\n // Re-seeding happens once on willUpdate; subsequent bound changes\n // just re-clamp the current width.\n if (!this.widthSeeded) {\n return\n }\n const clamped = clamp(this.width, this.minWidth, this.maxWidth)\n if (clamped !== this.width) {\n this.setWidth(clamped, 'attribute')\n }\n else {\n this.applyWidthVars()\n }\n }\n\n @observe('floating')\n protected handleFloatingChange() {\n this.applyFloatingRole()\n }\n\n /**\n * Single writer for the host's landmark/dialog role. A floating overlay\n * is an accessible modal (`role=\"dialog\"` + `aria-modal=\"true\"`); a docked\n * drawer is a `role=\"region\"` landmark with no aria-modal.\n */\n private applyFloatingRole() {\n if (this.floating) {\n this.setAttribute('role', 'dialog')\n this.setAttribute('aria-modal', 'true')\n }\n else {\n this.setAttribute('role', 'region')\n this.removeAttribute('aria-modal')\n }\n }\n\n @observe('width')\n protected applyWidthVars() {\n this.style.setProperty('--_n-aside-drawer-inline-size', `${this.width}px`)\n this.style.setProperty('--_n-aside-drawer-min-inline-size', `${this.minWidth}px`)\n // An unset `max-width` defaults to MAX_SAFE_INTEGER — too large for\n // CSS to handle reliably. Translate to `none` so the drawer has no\n // CSS-side cap; the clamp in `setWidth` still runs against the\n // numeric value so drag/keyboard don't escape JS-side bounds.\n const isMaxUnbounded = this.maxWidth >= Number.MAX_SAFE_INTEGER\n this.style.setProperty('--_n-aside-drawer-max-inline-size', isMaxUnbounded ? 'none' : `${this.maxWidth}px`)\n // Fullscreen rendered inline-size is the CSS-time `min()` of two vars:\n // - `--_n-aside-drawer-fullscreen-max` (this var, drawer-owned)\n // - `--_n-aside-drawer-fullscreen-available` (written by <nord-aside>\n // to the layout's left-cap; absent when there's no aside parent)\n // The drawer's own var floors at `minWidth` so a tiny consumer value\n // can never drop the drawer below its declared minimum. Unset\n // `max-fullscreen-width` resolves to `100vw` — a sensible standalone\n // fallback when there's no aside to publish the available width.\n const isFullscreenUnbounded = this.maxFullscreenWidth >= Number.MAX_SAFE_INTEGER\n this.style.setProperty(\n '--_n-aside-drawer-fullscreen-max',\n isFullscreenUnbounded\n ? '100vw'\n : `max(${this.minWidth}px, ${this.maxFullscreenWidth}px)`,\n )\n }\n\n /**\n * Update the drawer width, clamped to `[min-width, max-width]`. Persists\n * to localStorage and dispatches `width-change` with the given source.\n */\n setWidth(width: number, source: AsideDrawerWidthSource) {\n const next = clamp(Math.round(width), this.minWidth, this.maxWidth)\n if (next === this.width) {\n return\n }\n this.width = next\n if (!isServer && this.id) {\n storage(widthKey(this.id), this.defaultWidth).value = this.width\n }\n this.dispatchEvent(new AsideDrawerWidthChangeEvent(this.width, source))\n }\n\n /**\n * Whether the drawer is pinned — `min === max === default`. A pinned\n * drawer's resize handle is a drag no-op.\n */\n get isPinned(): boolean {\n return this.minWidth === this.maxWidth\n }\n\n /**\n * Lift Layout.ts's re-seed pattern: if the consumer-provided\n * `default-width` differs from the last default we wrote for this id,\n * the persisted width is reset to the new default.\n */\n private seedWidth() {\n // On the server there's no localStorage and no layout to paint; clamp\n // the declared default and skip both the storage read/write and the\n // `width-change` dispatch.\n if (isServer || !this.id) {\n this.width = clamp(this.defaultWidth, this.minWidth, this.maxWidth)\n this.applyWidthVars()\n return\n }\n const widthStore = storage(widthKey(this.id), this.defaultWidth)\n const defaultStore = storage(defaultWidthKey(this.id), this.defaultWidth)\n let next: number\n let source: AsideDrawerWidthSource\n if (defaultStore.value !== this.defaultWidth) {\n next = this.defaultWidth\n widthStore.value = next\n defaultStore.value = this.defaultWidth\n source = 'attribute'\n }\n else {\n next = widthStore.value\n source = 'storage'\n }\n this.width = clamp(Math.round(next), this.minWidth, this.maxWidth)\n this.applyWidthVars()\n this.dispatchEvent(new AsideDrawerWidthChangeEvent(this.width, source))\n }\n\n /**\n * Resolve the matching `<nord-aside-trigger drawer=\"<this.id>\">` inside\n * the ancestor `<nord-aside>` and use it as the drawer's aria-labelledby\n * target. Falls back to no label when no matching trigger exists.\n */\n private applyAriaLabelledby() {\n if (!this.id) {\n this.removeAttribute('aria-labelledby')\n return\n }\n const aside = this.closest('nord-aside')\n if (!aside) {\n return\n }\n const trigger = aside.querySelector<HTMLElement>(\n `nord-aside-trigger[drawer=\"${this.id}\"]`,\n )\n if (!trigger) {\n return\n }\n if (!trigger.id) {\n trigger.id = `${this.id}-trigger`\n }\n this.setAttribute('aria-labelledby', trigger.id)\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-aside-drawer': AsideDrawer\n }\n}\n"],"names":["AsideDrawerWidthChangeEvent","NordEvent","constructor","width","source","super","Object","defineProperty","this","value","enumerable","writable","STORAGE_KEY_PREFIX","widthKey","id","AsideDrawer","LitElement","defaultWidth","minWidth","maxWidth","Number","MAX_SAFE_INTEGER","maxFullscreenWidth","disabled","fullscreen","floating","widthSeeded","fullscreenSeeded","observedWidth","render","html","connectedCallback","applyFloatingRole","applyAriaLabelledby","isServer","getBoundingClientRect","ResizeObserver","fullscreenResizeObserver","entries","hasAttribute","entry","size","_c","_a","borderBoxSize","_b","inlineSize","contentRect","observe","disconnectedCallback","disconnect","undefined","fullscreenAnimation","cancel","fullscreenAnimationCleanup","removeAttribute","style","removeProperty","willUpdate","seedWidth","handleFullscreenChange","_oldValue","newValue","matchMedia","matches","fromWidth","setAttribute","setWidth","setProperty","requestAnimationFrame","toWidth","Math","abs","animation","animate","maxInlineSize","minInlineSize","duration","easing","fill","cleanup","onfinish","oncancel","handleBoundsChange","clamped","clamp","applyWidthVars","handleFloatingChange","isMaxUnbounded","isFullscreenUnbounded","next","round","storage","dispatchEvent","isPinned","widthStore","defaultStore","aside","closest","trigger","querySelector","styles","componentStyle","__decorate","property","reflect","type","attribute","prototype","Boolean","state","customElement"],"mappings":"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"}
|
package/lib/AsideTrigger.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{_ as t}from"./tslib.es6-CmLYFWVC.js";import{css as i,LitElement as e,html as r,nothing as s}from"lit";import{property as o,state as a,customElement as n}from"lit/decorators.js";import{S as d}from"./SlotController-Z6eG7LSZ.js";import{o as l}from"./observe-D0n0zOfU.js";import{s as
|
|
1
|
+
import{_ as t}from"./tslib.es6-CmLYFWVC.js";import{css as i,LitElement as e,html as r,nothing as s}from"lit";import{property as o,state as a,customElement as n}from"lit/decorators.js";import{S as d}from"./SlotController-Z6eG7LSZ.js";import{o as l}from"./observe-D0n0zOfU.js";import{s as h}from"./Component-BJ5O5n8k.js";import"./Button.js";import"./Icon.js";import"./Tooltip.js";import"./EventController-BBOmvfLa.js";import"lit/directives/ref.js";import"./LightDomController-DIwtVelV.js";import"./cond-CI1KbneT.js";import"./FocusableMixin-BlQLNPdJ.js";import"./InputMixin-LetXsCyv.js";import"./Spinner.js";import"lit/directives/if-defined.js";import"lit/directives/unsafe-html.js";import"./IconManager.js";import"./positioning-D-K8Mueq.js";import"./events-Bv6wNHwJ.js";import"./fsm-Bq5jMQrK.js";const c=i`:host{--_n-aside-trigger-size:var(--n-aside-trigger-size,32px);--_n-aside-trigger-background-color:var(--n-aside-trigger-background-color,#0000);--_n-aside-trigger-background-color-active:var(
|
|
2
2
|
--n-aside-trigger-background-color-active,var(--n-color-button-hover)
|
|
3
|
-
);display:block;inline-size:100%}.n-aside-trigger{display:block;inline-size:100%;position:relative;text-align:center}.n-aside-trigger nord-button{--n-button-min-block-size:var(--_n-aside-trigger-size);--n-button-min-inline-size:var(--_n-aside-trigger-size);--n-button-background-color:var(--_n-aside-trigger-background-color)}:host([aria-expanded=true]){--_n-aside-trigger-background-color:var(--_n-aside-trigger-background-color-active)}:host(:hover),:host([aria-expanded=true]){--n-button-color:var(--n-color-text);--n-color-icon:var(--n-color-text)}.n-aside-trigger-dot{background:var(--n-color-status-notification);block-size:5px;border-radius:var(--n-border-radius-circle);inline-size:5px;inset-block-start:3px;inset-inline-end:2px;pointer-events:none;position:absolute}`;let p=0,v=class extends e{constructor(){super(...arguments),this.defaultSlot=new d(this),this.tooltipSlot=new d(this,"tooltip"),this.drawer="",this.label="",this.disabled=!1,this.tooltip=!0,this.active=!1,this.targetDisabled=!1,this.tooltipId="n-aside-trigger-tip-"+ ++p,this.handleActiveDrawerChange=()=>{this.syncFromAside()},this.handleClick=t=>{var i;if(this.disabled||this.targetDisabled)return t.stopPropagation(),void t.preventDefault();const e=this.aside;if(
|
|
3
|
+
);display:block;inline-size:100%}.n-aside-trigger{display:block;inline-size:100%;position:relative;text-align:center}.n-aside-trigger nord-button{--n-button-min-block-size:var(--_n-aside-trigger-size);--n-button-min-inline-size:var(--_n-aside-trigger-size);--n-button-background-color:var(--_n-aside-trigger-background-color)}:host([aria-expanded=true]){--_n-aside-trigger-background-color:var(--_n-aside-trigger-background-color-active)}:host(:hover),:host([aria-expanded=true]){--n-button-color:var(--n-color-text);--n-color-icon:var(--n-color-text)}.n-aside-trigger-dot{background:var(--n-color-status-notification);block-size:5px;border-radius:var(--n-border-radius-circle);inline-size:5px;inset-block-start:3px;inset-inline-end:2px;pointer-events:none;position:absolute}`;let p=0,v=class extends e{constructor(){super(...arguments),this.defaultSlot=new d(this),this.tooltipSlot=new d(this,"tooltip"),this.drawer="",this.label="",this.disabled=!1,this.tooltip=!0,this.active=!1,this.targetDisabled=!1,this.tooltipId="n-aside-trigger-tip-"+ ++p,this.handleActiveDrawerChange=()=>{this.syncFromAside()},this.handleClick=t=>{var i;if(this.disabled||this.targetDisabled)return t.stopPropagation(),void t.preventDefault();const e=this.aside;if(this.isLink||!e||!this.drawer)return;const r=null!==(i=e.getAttribute("active-drawer"))&&void 0!==i?i:"";e.activeDrawer=r===this.drawer?"":this.drawer}}render(){const t=!this.defaultSlot.isEmpty,i=!t&&!!this.icon,e=void 0!==this.badge&&null!==this.badge&&""!==this.badge,o=!this.tooltipSlot.isEmpty,a=this.tooltip&&(!!this.label||o);return r`<div class="n-aside-trigger"><nord-button square size="s" variant="plain" type="button" href="${this.href||s}" target="${this.isLink&&this.target||s}" rel="${this.isLink&&this.rel||s}" aria-label="${this.label||s}" aria-describedby="${a?this.tooltipId:s}" ?disabled="${this.disabled}" @click="${this.handleClick}">${t?r`<slot></slot>`:s} ${i?r`<nord-icon name="${this.icon}" size="m"></nord-icon>`:s}</nord-button>${e?r`<span class="n-aside-trigger-dot" aria-hidden="true"></span>`:s} ${a?r`<nord-tooltip id="${this.tooltipId}" position="inline-start"><slot name="tooltip">${this.label}</slot></nord-tooltip>`:s}</div>`}connectedCallback(){super.connectedCallback(),this.startObservingAside()}disconnectedCallback(){super.disconnectedCallback(),this.stopObservingAside()}handleDrawerChange(){this.syncFromAside()}handleHrefChange(){this.syncFromAside()}handleDisabledChange(){this.syncAria()}get aside(){return this.closest("nord-aside")}get isLink(){return!!this.href}startObservingAside(){var t;this.observedAside=null!==(t=this.aside)&&void 0!==t?t:void 0,this.observedAside&&(this.observedAside.addEventListener("active-drawer-change",this.handleActiveDrawerChange),this.syncFromAside())}stopObservingAside(){var t;null===(t=this.observedAside)||void 0===t||t.removeEventListener("active-drawer-change",this.handleActiveDrawerChange),this.observedAside=void 0}syncFromAside(){var t,i,e;const r=null!==(t=this.observedAside)&&void 0!==t?t:this.aside;if(this.isLink||!r)return this.active=!1,this.targetDisabled=!1,void this.syncAria();const s=null!==(e=null!==(i=r.activeDrawer)&&void 0!==i?i:r.getAttribute("active-drawer"))&&void 0!==e?e:"";this.active=!!this.drawer&&s===this.drawer;const o=this.drawer?r.querySelector(`:scope > nord-aside-drawer#${CSS.escape(this.drawer)}`):null;this.targetDisabled=!o||o.hasAttribute("disabled"),this.syncAria()}syncAria(){this.drawer&&!this.isLink?this.setAttribute("aria-controls",this.drawer):this.removeAttribute("aria-controls"),this.isLink?this.removeAttribute("aria-expanded"):this.setAttribute("aria-expanded",this.active?"true":"false"),this.disabled||this.targetDisabled?this.setAttribute("aria-disabled","true"):this.removeAttribute("aria-disabled")}};v.styles=[h,c],t([o({reflect:!0})],v.prototype,"drawer",void 0),t([o({reflect:!0})],v.prototype,"href",void 0),t([o()],v.prototype,"target",void 0),t([o()],v.prototype,"rel",void 0),t([o({reflect:!0})],v.prototype,"icon",void 0),t([o({reflect:!0})],v.prototype,"label",void 0),t([o({reflect:!0})],v.prototype,"badge",void 0),t([o({type:Boolean,reflect:!0})],v.prototype,"disabled",void 0),t([o({type:Boolean,reflect:!0})],v.prototype,"tooltip",void 0),t([a()],v.prototype,"active",void 0),t([a()],v.prototype,"targetDisabled",void 0),t([l("drawer")],v.prototype,"handleDrawerChange",null),t([l("href")],v.prototype,"handleHrefChange",null),t([l("disabled")],v.prototype,"handleDisabledChange",null),v=t([n("nord-aside-trigger")],v);var g=v;export{g as default};
|
|
4
4
|
//# sourceMappingURL=AsideTrigger.js.map
|
package/lib/AsideTrigger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AsideTrigger.js","sources":["../src/aside-trigger/AsideTrigger.ts"],"sourcesContent":["import { html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { SlotController } from '../common/controllers/SlotController.js'\nimport { observe } from '../common/decorators/observe.js'\n\nimport componentStyle from '../common/styles/Component.css'\nimport style from './AsideTrigger.css'\nimport '../button/Button.js'\nimport '../icon/Icon.js'\nimport '../tooltip/Tooltip.js'\n\nlet asideTriggerTooltipIdCounter = 0\n\n/**\n * Rail button that toggles a `<nord-aside-drawer>` inside `<nord-aside>`.\n *\n * @status new\n * @category action\n * @slot - Overrides the `icon` attribute for custom leading content.\n * @slot tooltip - Overrides the tooltip body (falls back to `label`).\n * Lets consumers add icons, shortcut hints, etc. — anything beyond the\n * plain string label.\n *\n * @parent Aside\n */\n@customElement('nord-aside-trigger')\nexport default class AsideTrigger extends LitElement {\n static styles = [componentStyle, style]\n\n private defaultSlot = new SlotController(this)\n private tooltipSlot = new SlotController(this, 'tooltip')\n\n /**\n * The id of the `<nord-aside-drawer>` this trigger toggles.\n * Required.\n */\n @property({ reflect: true }) drawer: string = ''\n\n /**\n * Nord icon name. Shortcut for the common case; equivalent to placing\n * `<nord-icon name=\"…\">` in the default slot.\n */\n @property({ reflect: true }) icon?: string\n\n /**\n * Accessible label (used for `aria-label` on the host).\n */\n @property({ reflect: true }) label: string = ''\n\n /**\n * Optional badge content (forwarded to inner `<nord-badge>`).\n */\n @property({ reflect: true }) badge?: string | number\n\n /**\n * Makes the trigger disabled. Takes precedence over the target\n * drawer's `disabled` state.\n */\n @property({ type: Boolean, reflect: true }) disabled: boolean = false\n\n /**\n * Whether to render a `<nord-tooltip>` showing `label` on hover/focus.\n * Defaults to `true` — set `tooltip=\"false\"` (or omit `label`) to opt out.\n */\n @property({ type: Boolean, reflect: true }) tooltip: boolean = true\n\n /**\n * Whether the ancestor `<nord-aside>`'s `active-drawer` currently\n * matches this trigger's `drawer` id.\n * @internal\n */\n @state() private active: boolean = false\n\n /**\n * Whether the target drawer exists and is not disabled. Drives\n * `aria-disabled` on the host.\n * @internal\n */\n @state() private targetDisabled: boolean = false\n\n private observedAside?: HTMLElement\n private readonly tooltipId = `n-aside-trigger-tip-${++asideTriggerTooltipIdCounter}`\n\n render() {\n const showCustomLeading = !this.defaultSlot.isEmpty\n const showIcon = !showCustomLeading && !!this.icon\n const showBadge = this.badge !== undefined && this.badge !== null && this.badge !== ''\n\n // Tooltip is rendered when explicitly enabled AND there's something to\n // show — either the `label` attr (default body) or a custom `tooltip`\n // slot.\n const hasTooltipSlot = !this.tooltipSlot.isEmpty\n const showTooltip = this.tooltip && (!!this.label || hasTooltipSlot)\n return html`\n <div class=\"n-aside-trigger\">\n <nord-button\n square\n size=\"s\"\n variant=\"plain\"\n type=\"button\"\n aria-label=${this.label || nothing}\n aria-describedby=${showTooltip ? this.tooltipId : nothing}\n ?disabled=${this.disabled}\n @click=${this.handleClick}\n >\n ${showCustomLeading ? html`<slot></slot>` : nothing}\n ${showIcon ? html`<nord-icon name=${this.icon!} size=\"m\"></nord-icon>` : nothing}\n </nord-button>\n ${showBadge ? html`<span class=\"n-aside-trigger-dot\" aria-hidden=\"true\"></span>` : nothing}\n ${showTooltip\n ? html`\n <nord-tooltip id=${this.tooltipId} position=\"inline-start\">\n <slot name=\"tooltip\">${this.label}</slot>\n </nord-tooltip>\n `\n : nothing}\n </div>\n `\n }\n\n connectedCallback() {\n super.connectedCallback()\n this.startObservingAside()\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.stopObservingAside()\n }\n\n @observe('drawer')\n protected handleDrawerChange() {\n this.syncFromAside()\n }\n\n @observe('disabled')\n protected handleDisabledChange() {\n this.syncAria()\n }\n\n private get aside(): HTMLElement | null {\n return this.closest('nord-aside')\n }\n\n private readonly handleActiveDrawerChange = () => {\n this.syncFromAside()\n }\n\n /**\n * Listen to the aside's own `active-drawer-change` event instead of each\n * trigger installing its own subtree MutationObserver on the whole aside.\n * One shared event covers open / switch / close, so N triggers no longer\n * mean N observers waking on every aside DOM mutation.\n */\n private startObservingAside() {\n this.observedAside = this.aside ?? undefined\n if (!this.observedAside) {\n return\n }\n this.observedAside.addEventListener('active-drawer-change', this.handleActiveDrawerChange)\n this.syncFromAside()\n }\n\n private stopObservingAside() {\n this.observedAside?.removeEventListener('active-drawer-change', this.handleActiveDrawerChange)\n this.observedAside = undefined\n }\n\n private syncFromAside() {\n const aside = this.observedAside ?? this.aside\n if (!aside) {\n this.active = false\n this.targetDisabled = false\n this.syncAria()\n return\n }\n\n // Prefer the live `activeDrawer` property over the reflected attribute:\n // the `active-drawer-change` event fires during the aside's update cycle,\n // before Lit reflects the property to the `active-drawer` attribute, so\n // reading the attribute here would lag one tick behind. Fall back to the\n // attribute only while the aside element has not upgraded yet.\n const activeDrawer\n = (aside as HTMLElement & { activeDrawer?: string }).activeDrawer\n ?? aside.getAttribute('active-drawer')\n ?? ''\n this.active = !!this.drawer && activeDrawer === this.drawer\n\n const target = this.drawer\n ? aside.querySelector(`:scope > nord-aside-drawer#${CSS.escape(this.drawer)}`)\n : null\n this.targetDisabled = !target || target.hasAttribute('disabled')\n\n this.syncAria()\n }\n\n private syncAria() {\n if (this.drawer) {\n this.setAttribute('aria-controls', this.drawer)\n }\n else {\n this.removeAttribute('aria-controls')\n }\n this.setAttribute('aria-expanded', this.active ? 'true' : 'false')\n if (this.disabled || this.targetDisabled) {\n this.setAttribute('aria-disabled', 'true')\n }\n else {\n this.removeAttribute('aria-disabled')\n }\n }\n\n private handleClick = (event: Event) => {\n if (this.disabled || this.targetDisabled) {\n event.stopPropagation()\n event.preventDefault()\n return\n }\n const aside = this.aside\n if (!aside || !this.drawer) {\n return\n }\n const current = aside.getAttribute('active-drawer') ?? ''\n ;(aside as HTMLElement & { activeDrawer?: string }).activeDrawer\n = current === this.drawer ? '' : this.drawer\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-aside-trigger': AsideTrigger\n }\n}\n"],"names":["asideTriggerTooltipIdCounter","AsideTrigger","LitElement","constructor","this","defaultSlot","SlotController","tooltipSlot","drawer","label","disabled","tooltip","active","targetDisabled","tooltipId","handleActiveDrawerChange","syncFromAside","handleClick","event","stopPropagation","preventDefault","aside","current","_a","getAttribute","activeDrawer","render","showCustomLeading","isEmpty","showIcon","icon","showBadge","undefined","badge","hasTooltipSlot","showTooltip","html","nothing","connectedCallback","super","startObservingAside","disconnectedCallback","stopObservingAside","handleDrawerChange","handleDisabledChange","syncAria","closest","observedAside","addEventListener","removeEventListener","_c","_b","target","querySelector","CSS","escape","hasAttribute","setAttribute","removeAttribute","styles","componentStyle","style","__decorate","property","reflect","prototype","type","Boolean","state","observe","customElement"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AsideTrigger.js","sources":["../src/aside-trigger/AsideTrigger.ts"],"sourcesContent":["import { html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { SlotController } from '../common/controllers/SlotController.js'\nimport { observe } from '../common/decorators/observe.js'\n\nimport componentStyle from '../common/styles/Component.css'\nimport style from './AsideTrigger.css'\nimport '../button/Button.js'\nimport '../icon/Icon.js'\nimport '../tooltip/Tooltip.js'\n\nlet asideTriggerTooltipIdCounter = 0\n\n/**\n * Rail button that toggles a `<nord-aside-drawer>` inside `<nord-aside>`,\n * or navigates like a link when `href` is set.\n *\n * @status new\n * @category action\n * @slot - Overrides the `icon` attribute for custom leading content.\n * @slot tooltip - Overrides the tooltip body (falls back to `label`).\n * Lets consumers add icons, shortcut hints, etc. — anything beyond the\n * plain string label.\n *\n * @parent Aside\n */\n@customElement('nord-aside-trigger')\nexport default class AsideTrigger extends LitElement {\n static styles = [componentStyle, style]\n\n private defaultSlot = new SlotController(this)\n private tooltipSlot = new SlotController(this, 'tooltip')\n\n /**\n * The id of the `<nord-aside-drawer>` this trigger toggles.\n * Mutually exclusive with `href` — when both are set, `href` wins and\n * the trigger acts as a link instead of a drawer toggle.\n */\n @property({ reflect: true }) drawer: string = ''\n\n /**\n * When provided, renders the trigger as a link that navigates to the\n * given URL instead of toggling a drawer. Mutually exclusive with\n * `drawer`. Mirrors `nord-button`'s link mode, so middle-click,\n * cmd/ctrl-click and right-click behave like a real anchor.\n */\n @property({ reflect: true }) href?: string\n\n /**\n * When provided together with a href property, determines where to open\n * the linked URL. Forwarded to the underlying anchor.\n */\n @property() target?: '_self' | '_blank' | '_parent' | '_top'\n\n /**\n * When provided together with a href property, sets the relationship\n * between the linked URL and the current document, e.g. “noopener\n * noreferrer” when linking to untrusted content in a new tab.\n */\n @property() rel?: string\n\n /**\n * Nord icon name. Shortcut for the common case; equivalent to placing\n * `<nord-icon name=\"…\">` in the default slot.\n */\n @property({ reflect: true }) icon?: string\n\n /**\n * Accessible label (used for `aria-label` on the host).\n */\n @property({ reflect: true }) label: string = ''\n\n /**\n * Optional badge content (forwarded to inner `<nord-badge>`).\n */\n @property({ reflect: true }) badge?: string | number\n\n /**\n * Makes the trigger disabled. Takes precedence over the target\n * drawer's `disabled` state.\n */\n @property({ type: Boolean, reflect: true }) disabled: boolean = false\n\n /**\n * Whether to render a `<nord-tooltip>` showing `label` on hover/focus.\n * Defaults to `true` — set `tooltip=\"false\"` (or omit `label`) to opt out.\n */\n @property({ type: Boolean, reflect: true }) tooltip: boolean = true\n\n /**\n * Whether the ancestor `<nord-aside>`'s `active-drawer` currently\n * matches this trigger's `drawer` id.\n * @internal\n */\n @state() private active: boolean = false\n\n /**\n * Whether the target drawer exists and is not disabled. Drives\n * `aria-disabled` on the host.\n * @internal\n */\n @state() private targetDisabled: boolean = false\n\n private observedAside?: HTMLElement\n private readonly tooltipId = `n-aside-trigger-tip-${++asideTriggerTooltipIdCounter}`\n\n render() {\n const showCustomLeading = !this.defaultSlot.isEmpty\n const showIcon = !showCustomLeading && !!this.icon\n const showBadge = this.badge !== undefined && this.badge !== null && this.badge !== ''\n\n // Tooltip is rendered when explicitly enabled AND there's something to\n // show — either the `label` attr (default body) or a custom `tooltip`\n // slot.\n const hasTooltipSlot = !this.tooltipSlot.isEmpty\n const showTooltip = this.tooltip && (!!this.label || hasTooltipSlot)\n return html`\n <div class=\"n-aside-trigger\">\n <nord-button\n square\n size=\"s\"\n variant=\"plain\"\n type=\"button\"\n href=${this.href || nothing}\n target=${(this.isLink && this.target) || nothing}\n rel=${(this.isLink && this.rel) || nothing}\n aria-label=${this.label || nothing}\n aria-describedby=${showTooltip ? this.tooltipId : nothing}\n ?disabled=${this.disabled}\n @click=${this.handleClick}\n >\n ${showCustomLeading ? html`<slot></slot>` : nothing}\n ${showIcon ? html`<nord-icon name=${this.icon!} size=\"m\"></nord-icon>` : nothing}\n </nord-button>\n ${showBadge ? html`<span class=\"n-aside-trigger-dot\" aria-hidden=\"true\"></span>` : nothing}\n ${showTooltip\n ? html`\n <nord-tooltip id=${this.tooltipId} position=\"inline-start\">\n <slot name=\"tooltip\">${this.label}</slot>\n </nord-tooltip>\n `\n : nothing}\n </div>\n `\n }\n\n connectedCallback() {\n super.connectedCallback()\n this.startObservingAside()\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.stopObservingAside()\n }\n\n @observe('drawer')\n protected handleDrawerChange() {\n this.syncFromAside()\n }\n\n @observe('href')\n protected handleHrefChange() {\n this.syncFromAside()\n }\n\n @observe('disabled')\n protected handleDisabledChange() {\n this.syncAria()\n }\n\n private get aside(): HTMLElement | null {\n return this.closest('nord-aside')\n }\n\n /**\n * `href` takes precedence over `drawer`: a trigger with both acts as a\n * link and never toggles a drawer.\n */\n private get isLink(): boolean {\n return !!this.href\n }\n\n private readonly handleActiveDrawerChange = () => {\n this.syncFromAside()\n }\n\n /**\n * Listen to the aside's own `active-drawer-change` event instead of each\n * trigger installing its own subtree MutationObserver on the whole aside.\n * One shared event covers open / switch / close, so N triggers no longer\n * mean N observers waking on every aside DOM mutation.\n */\n private startObservingAside() {\n this.observedAside = this.aside ?? undefined\n if (!this.observedAside) {\n return\n }\n this.observedAside.addEventListener('active-drawer-change', this.handleActiveDrawerChange)\n this.syncFromAside()\n }\n\n private stopObservingAside() {\n this.observedAside?.removeEventListener('active-drawer-change', this.handleActiveDrawerChange)\n this.observedAside = undefined\n }\n\n private syncFromAside() {\n const aside = this.observedAside ?? this.aside\n if (this.isLink || !aside) {\n this.active = false\n this.targetDisabled = false\n this.syncAria()\n return\n }\n\n // Prefer the live `activeDrawer` property over the reflected attribute:\n // the `active-drawer-change` event fires during the aside's update cycle,\n // before Lit reflects the property to the `active-drawer` attribute, so\n // reading the attribute here would lag one tick behind. Fall back to the\n // attribute only while the aside element has not upgraded yet.\n const activeDrawer\n = (aside as HTMLElement & { activeDrawer?: string }).activeDrawer\n ?? aside.getAttribute('active-drawer')\n ?? ''\n this.active = !!this.drawer && activeDrawer === this.drawer\n\n const target = this.drawer\n ? aside.querySelector(`:scope > nord-aside-drawer#${CSS.escape(this.drawer)}`)\n : null\n this.targetDisabled = !target || target.hasAttribute('disabled')\n\n this.syncAria()\n }\n\n private syncAria() {\n // Link mode has no expand/collapse semantics — no aria-controls or\n // aria-expanded, and the inner nord-button anchor handles disabled\n // link semantics itself.\n if (this.drawer && !this.isLink) {\n this.setAttribute('aria-controls', this.drawer)\n }\n else {\n this.removeAttribute('aria-controls')\n }\n if (this.isLink) {\n this.removeAttribute('aria-expanded')\n }\n else {\n this.setAttribute('aria-expanded', this.active ? 'true' : 'false')\n }\n if (this.disabled || this.targetDisabled) {\n this.setAttribute('aria-disabled', 'true')\n }\n else {\n this.removeAttribute('aria-disabled')\n }\n }\n\n private handleClick = (event: Event) => {\n if (this.disabled || this.targetDisabled) {\n event.stopPropagation()\n event.preventDefault()\n return\n }\n const aside = this.aside\n if (this.isLink || !aside || !this.drawer) {\n return\n }\n const current = aside.getAttribute('active-drawer') ?? ''\n ;(aside as HTMLElement & { activeDrawer?: string }).activeDrawer\n = current === this.drawer ? '' : this.drawer\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-aside-trigger': AsideTrigger\n }\n}\n"],"names":["asideTriggerTooltipIdCounter","AsideTrigger","LitElement","constructor","this","defaultSlot","SlotController","tooltipSlot","drawer","label","disabled","tooltip","active","targetDisabled","tooltipId","handleActiveDrawerChange","syncFromAside","handleClick","event","stopPropagation","preventDefault","aside","isLink","current","_a","getAttribute","activeDrawer","render","showCustomLeading","isEmpty","showIcon","icon","showBadge","undefined","badge","hasTooltipSlot","showTooltip","html","href","nothing","target","rel","connectedCallback","super","startObservingAside","disconnectedCallback","stopObservingAside","handleDrawerChange","handleHrefChange","handleDisabledChange","syncAria","closest","observedAside","addEventListener","removeEventListener","_c","_b","querySelector","CSS","escape","hasAttribute","setAttribute","removeAttribute","styles","componentStyle","style","__decorate","property","reflect","prototype","type","Boolean","state","observe","customElement"],"mappings":"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"}
|
package/lib/Button.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import{_ as t}from"./tslib.es6-CmLYFWVC.js";import{css as o,html as n,nothing as r,LitElement as e}from"lit";import{property as a,customElement as i}from"lit/decorators.js";import{createRef as s,ref as l}from"lit/directives/ref.js";import{E as b}from"./EventController-BBOmvfLa.js";import{L as d}from"./LightDomController-DIwtVelV.js";import{S as c}from"./SlotController-Z6eG7LSZ.js";import{c as u}from"./cond-CI1KbneT.js";import{F as v}from"./FocusableMixin-BlQLNPdJ.js";import{I as h}from"./InputMixin-LetXsCyv.js";import{s as p}from"./Component-BJ5O5n8k.js";import"./Spinner.js";import"lit/directives/if-defined.js";const g=o`:host{--_n-button-border-radius:var(--n-button-border-radius,var(--n-border-radius-s));--_n-button-gap:var(--n-button-gap,var(--n-space-s));--_n-button-gradient:var(
|
|
2
2
|
--n-button-gradient,linear-gradient(to bottom,#0000 50%,rgba(0,0,0,.013) 100%)
|
|
3
|
-
);--_n-button-background-color:var(--n-button-background-color,var(--n-color-button));--_n-button-border-color:var(--n-button-border-color,var(--n-color-border-strong));--_n-button-text-align:var(--n-button-text-align,center);--_n-button-box-shadow:var(--n-button-box-shadow,var(--n-box-shadow));--_n-button-color:var(--n-button-color,var(--n-color-text));--_n-button-padding-inline:var(--n-button-padding-inline,calc(var(--n-space-m)/1.2));--_n-button-font-size:var(--n-button-font-size,var(--n-font-size-m));--_n-button-font-weight:var(--n-button-font-weight,var(--n-font-weight));--_n-button-min-block-size:var(--n-button-min-block-size,var(--n-space-xl));--_n-button-toggle-icon-color:var(--n-button-toggle-icon-color,var(--n-color-icon));--_n-button-overflow:var(--n-button-overflow,hidden);--_n-button-user-select:var(--n-button-user-select,none);--_n-button-opacity:1;--_n-button-border-style:solid;--_n-button-inline-size:fit-content;--_n-button-padding-block:calc(var(--n-space-s)/1.6);--_n-button-icon-size:var(--n-size-icon-s);display:inline-block}.n-button{align-items:center;appearance:none;background:var(--_n-button-background-color);border:1px var(--_n-button-border-style) var(--_n-button-border-color);border-radius:var(--_n-button-border-radius);box-shadow:var(--_n-button-box-shadow);color:var(--_n-button-color);cursor:pointer;display:flex;font-family:var(--n-font-family);font-feature-settings:var(--n-font-features);font-size:var(--_n-button-font-size);font-weight:var(--_n-button-font-weight);gap:var(--_n-button-gap);inline-size:var(--_n-button-inline-size);justify-content:var(--n-button-justify-content,flex-start);line-height:var(--n-line-height-form);margin:0;min-block-size:var(--_n-button-min-block-size);opacity:var(--_n-button-opacity);padding:var(--_n-button-padding-block)
|
|
3
|
+
);--_n-button-background-color:var(--n-button-background-color,var(--n-color-button));--_n-button-border-color:var(--n-button-border-color,var(--n-color-border-strong));--_n-button-text-align:var(--n-button-text-align,center);--_n-button-box-shadow:var(--n-button-box-shadow,var(--n-box-shadow));--_n-button-color:var(--n-button-color,var(--n-color-text));--_n-button-padding-inline:var(--n-button-padding-inline,calc(var(--n-space-m)/1.2));--_n-button-font-size:var(--n-button-font-size,var(--n-font-size-m));--_n-button-font-weight:var(--n-button-font-weight,var(--n-font-weight));--_n-button-min-block-size:var(--n-button-min-block-size,var(--n-space-xl));--_n-button-toggle-icon-color:var(--n-button-toggle-icon-color,var(--n-color-icon));--_n-button-overflow:var(--n-button-overflow,hidden);--_n-button-user-select:var(--n-button-user-select,none);--_n-button-opacity:1;--_n-button-border-style:solid;--_n-button-inline-size:fit-content;--_n-button-padding-block:calc(var(--n-space-s)/1.6);--_n-button-icon-size:var(--n-size-icon-s);display:inline-block}.n-button{align-items:center;appearance:none;background:var(--_n-button-background-color);border:1px var(--_n-button-border-style) var(--_n-button-border-color);border-radius:var(--_n-button-border-radius);box-shadow:var(--_n-button-box-shadow);color:var(--_n-button-color);cursor:pointer;display:flex;font-family:var(--n-font-family);font-feature-settings:var(--n-font-features);font-size:var(--_n-button-font-size);font-weight:var(--_n-button-font-weight);gap:var(--_n-button-gap);inline-size:var(--_n-button-inline-size);justify-content:var(--n-button-justify-content,flex-start);line-height:var(--n-line-height-form);margin:0;min-block-size:var(--_n-button-min-block-size);opacity:var(--_n-button-opacity);padding-block:var(--_n-button-padding-block);padding-inline:var(--_n-button-padding-inline);position:relative;text-align:var(--_n-button-text-align);text-decoration:none;transition:var(--n-transition-quickly);transition-property:background-color,opacity,color,box-shadow,border-color;-webkit-user-select:var(--_n-button-user-select);user-select:var(--_n-button-user-select)}.n-button:after{background:#0000;background-image:var(--_n-button-gradient);background-repeat:repeat-x;block-size:100%;border-radius:var(--_n-button-border-radius);content:"";inline-size:100%;inset-block-start:0;inset-inline:0;position:absolute}:host([expand]){--_n-button-inline-size:100%;display:block}.n-content{display:var(--n-button-content-display,block);flex:1;overflow:var(--_n-button-overflow);position:relative;text-overflow:ellipsis;white-space:nowrap}.n-button:hover{--_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))}.n-button:focus{outline:none}.n-button:focus-visible{--_n-button-border-color:var(--n-button-border-color,var(--n-color-accent));--_n-button-box-shadow:var(--n-button-box-shadow,0 0 0 1px var(--n-color-accent),var(--n-box-shadow));--_n-button-border-style:solid}.n-button:active{opacity:.8;transform:translateY(1px);transition:none}:host([variant=primary]){--_n-button-box-shadow:var(--n-button-box-shadow,none);--_n-button-color:var(--n-button-color,var(--n-color-text-on-accent));--_n-button-font-weight:var(--n-button-font-weight,var(--n-font-weight-active))}:host([variant=primary]),:host([variant=primary]) .n-button:hover{--_n-button-border-color:var(--n-button-border-color,#0000);--_n-button-background-color:var(--n-button-background-color,var(--n-color-accent))}:host([variant=primary]) .n-button:hover{filter:brightness(93%)}:host([variant=primary]) .n-button:focus{--_n-button-box-shadow:var(
|
|
4
4
|
--n-button-box-shadow,0 0 0 1px var(--n-color-surface),0 0 0 3px var(--_n-button-border-color)
|
|
5
5
|
)}:host([variant=dashed]){--_n-button-border-color:var(--n-button-border-color,var(--n-color-border-hover));--_n-button-box-shadow:var(--n-button-box-shadow,none);--_n-button-color:var(--n-button-color,var(--n-color-text-weaker));--_n-button-border-style:dashed}:host([variant=dashed]) .n-button:hover{--_n-button-color:var(--n-button-color,var(--n-color-text))}:host([variant=dashed]) .n-button:after{display:none}:host([variant=plain]){--_n-button-box-shadow:var(--n-button-box-shadow,none)}:host([variant=plain]),:host([variant=plain]) .n-button:hover{--_n-button-border-color:var(--n-button-border-color,#0000)}:host([variant=plain]) .n-button:after{display:none}:host([variant=danger]){--_n-button-box-shadow:var(--n-button-box-shadow,none);--_n-button-color:var(--n-button-color,var(--n-color-text-on-accent));--_n-button-font-weight:var(--n-button-font-weight,var(--n-font-weight-active))}:host([variant=danger]),:host([variant=danger]) .n-button:hover{--_n-button-border-color:var(--n-button-border-color,#0000);--_n-button-background-color:var(--n-button-background-color,var(--n-color-status-danger))}:host([variant=danger]) .n-button:hover{filter:brightness(93%)}:host([variant=danger]) .n-button:focus{--_n-button-border-color:var(--n-button-border-color,var(--n-color-status-danger));--_n-button-box-shadow:var(
|
|
6
6
|
--n-button-box-shadow,0 0 0 1px var(--n-color-surface),0 0 0 3px var(--n-color-status-danger)
|
|
7
|
-
)}:host([disabled]){--_n-button-border-color:var(--n-button-border-color,var(--_n-button-background-color));--_n-button-background-color:var(--n-button-background-color,var(--n-color-border));--_n-button-box-shadow:var(--n-button-box-shadow,none);--_n-button-color:var(--n-button-color,var(--n-color-text-weak));--_n-button-opacity:0.5;pointer-events:none}:host([disabled]) .n-button:after{display:none}.n-button-spinner{inset-block-start:50%;inset-inline-start:50%;position:absolute;transform:translateX(-50%) translateY(-50%)}:host([loading]:not([href])){pointer-events:none}:host([loading]:not([href])) .n-content,:host([loading]:not([href])) ::slotted([slot=end]),:host([loading]:not([href])) ::slotted([slot=start]){opacity:0}:host([size=s]){--_n-button-gap:var(--n-button-gap,var(--n-space-xs));--_n-button-padding-inline:var(--n-button-padding-inline,calc(var(--n-space-s) + 1px));--_n-button-font-size:var(--n-button-font-size,var(--n-font-size-s));--_n-button-min-block-size:var(--n-button-min-block-size,calc(var(--n-space-l) + var(--n-space-xs)));--_n-button-padding-block:calc(var(--n-space-xs) - 1px);--_n-button-icon-size:var(--n-size-icon-xs)}:host([size=l]){--_n-button-border-radius:var(--n-button-border-radius,var(--n-border-radius));--_n-button-padding-inline:var(--n-button-padding-inline,calc(var(--n-space-l)/1.3));--_n-button-font-size:var(--n-button-font-size,var(--n-font-size-l));--_n-button-font-weight:var(--n-button-font-weight,var(--n-font-weight-active));--_n-button-min-block-size:var(--n-button-min-block-size,calc(var(--n-space-xxl) - var(--n-space-l)));--_n-button-icon-size:var(--n-size-icon-m)}:host([square]){--_n-button-inline-size:var(--_n-button-min-block-size);--_n-button-padding-block:0;--_n-button-padding-inline:0}:host([square]) .n-content{align-items:center;display:flex;justify-content:center}::slotted(*){color:inherit;pointer-events:none}::slotted(svg){color:var(--n-color-icon)}::slotted(button[slot=proxy]){display:none}:host(:not([variant=primary],[variant=danger])) ::slotted(nord-icon){color:var(--n-color-icon)}:host(:not([variant=primary],[variant=danger])) .n-toggle-icon{color:var(--_n-button-toggle-icon-color)}:host(:not([square])) slot:not([name])::slotted(nord-icon){transform:translateY(1px)}::slotted(nord-icon:not([size])),nord-icon{--_n-icon-size:var(--_n-button-icon-size)}`;let f=class extends(h(v(e))){constructor(){super(...arguments),this.defaultSlot=new c(this),this.buttonRef=s(),this.events=new b(this),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.square=!1,this.loading=!1,this.hideDropdownIcon=!1,this.handleOuterClick=t=>{t.composedPath().some((t=>t===this.focusableRef.value||t===this.buttonRef.value))||t.stopPropagation()}}connectedCallback(){super.connectedCallback(),this.events.listen(this,"click",this.handleOuterClick,!0)}render(){var t;const o="toggle"===(null===(t=this.assignedSlot)||void 0===t?void 0:t.name),e=this.defaultSlot.assigned.some((t=>"nord-icon"===t.localName)),a=o&&!this.hideDropdownIcon&&!e&&!this.href,i=n`<slot name="start"></slot><div class="n-content"><slot></slot></div><nord-spinner class="n-button-spinner" color="currentColor" ?hidden="${!this.loading||Boolean(this.href)}"></nord-spinner><slot name="end">${a?n`<nord-icon name="interface-dropdown-small" class="n-toggle-icon"></nord-icon>`:r}</slot>`;return this.href?this.renderLink(i):this.renderButton(i)}get isHostNonFocusable(){return"-1"===this.getAttribute("tabindex")}renderLink(t){return n`<a ${l(this.focusableRef)} class="n-button" target="${this.target}" ?download="${this.download}" href="${u(this.disabled,r,this.href)}" tabindex="${u(this.disabled||this.isHostNonFocusable,"-1")}" aria-disabled="${u(this.disabled,"true")}" role="${u(this.disabled,"link")}">${t}</a>`}renderButton(t){return n`<slot name="proxy" @slotchange="${this.handleProxyChange}"></slot><button ${l(this.focusableRef)} class="n-button" ?disabled="${this.disabled}" name="${u(this.name)}" value="${u(this.value)}" tabindex="${u(this.isHostNonFocusable,"-1")}" @click="${this.handleClick}" aria-disabled="${u(this.loading,"true")}" aria-expanded="${u(this.accessibleExpanded)}" aria-haspopup="${u(this.accessibleHasPopup)}">${t}</button>`}renderLightDom(){return this.href||!this.form?r:n`<button ${l(this.buttonRef)} slot="proxy" name="${u(this.name)}" value="${u(this.value)}" ?disabled="${this.disabled}" form="${u(this._formId)}" type="${this.type}"></button>`}handleClick(t){this.buttonRef.value&&(t.stopPropagation(),this.buttonRef.value.click())}handleProxyChange(t){const o=t.target,n=this.buttonRef.value;n&&n.assignedSlot!==o&&this.appendChild(n)}};f.shadowRootOptions={...e.shadowRootOptions,delegatesFocus:!0},f.styles=[p,g],t([a({reflect:!0})],f.prototype,"variant",void 0),t([a({reflect:!0})],f.prototype,"type",void 0),t([a({reflect:!0})],f.prototype,"size",void 0),t([a({attribute:"aria-expanded"})],f.prototype,"accessibleExpanded",void 0),t([a({attribute:"aria-haspopup"})],f.prototype,"accessibleHasPopup",void 0),t([a({reflect:!0})],f.prototype,"href",void 0),t([a({reflect:!0,type:Boolean})],f.prototype,"download",void 0),t([a()],f.prototype,"target",void 0),t([a({reflect:!0,type:Boolean})],f.prototype,"expand",void 0),t([a({reflect:!0,type:Boolean})],f.prototype,"square",void 0),t([a({reflect:!0,type:Boolean})],f.prototype,"loading",void 0),t([a({reflect:!0,type:Boolean,attribute:"hide-dropdown-icon"})],f.prototype,"hideDropdownIcon",void 0),f=t([i("nord-button")],f);var _=f;export{_ as default};
|
|
7
|
+
)}:host([disabled]){--_n-button-border-color:var(--n-button-border-color,var(--_n-button-background-color));--_n-button-background-color:var(--n-button-background-color,var(--n-color-border));--_n-button-box-shadow:var(--n-button-box-shadow,none);--_n-button-color:var(--n-button-color,var(--n-color-text-weak));--_n-button-opacity:0.5;pointer-events:none}:host([disabled]) .n-button:after{display:none}.n-button-spinner{inset-block-start:50%;inset-inline-start:50%;position:absolute;transform:translateX(-50%) translateY(-50%)}:host([loading]:not([href])){pointer-events:none}:host([loading]:not([href])) .n-content,:host([loading]:not([href])) ::slotted([slot=end]),:host([loading]:not([href])) ::slotted([slot=start]){opacity:0}:host([size=s]){--_n-button-gap:var(--n-button-gap,var(--n-space-xs));--_n-button-padding-inline:var(--n-button-padding-inline,calc(var(--n-space-s) + 1px));--_n-button-font-size:var(--n-button-font-size,var(--n-font-size-s));--_n-button-min-block-size:var(--n-button-min-block-size,calc(var(--n-space-l) + var(--n-space-xs)));--_n-button-padding-block:calc(var(--n-space-xs) - 1px);--_n-button-icon-size:var(--n-size-icon-xs)}:host([size=l]){--_n-button-border-radius:var(--n-button-border-radius,var(--n-border-radius));--_n-button-padding-inline:var(--n-button-padding-inline,calc(var(--n-space-l)/1.3));--_n-button-font-size:var(--n-button-font-size,var(--n-font-size-l));--_n-button-font-weight:var(--n-button-font-weight,var(--n-font-weight-active));--_n-button-min-block-size:var(--n-button-min-block-size,calc(var(--n-space-xxl) - var(--n-space-l)));--_n-button-icon-size:var(--n-size-icon-m)}:host([square]){--_n-button-inline-size:var(--_n-button-min-block-size);--_n-button-padding-block:0;--_n-button-padding-inline:0}:host([square]) .n-content{align-items:center;display:flex;justify-content:center}::slotted(*){color:inherit;pointer-events:none}::slotted(svg){color:var(--n-color-icon)}::slotted(button[slot=proxy]){display:none}:host(:not([variant=primary],[variant=danger])) ::slotted(nord-icon){color:var(--n-color-icon)}:host(:not([variant=primary],[variant=danger])) .n-toggle-icon{color:var(--_n-button-toggle-icon-color)}:host(:not([square])) slot:not([name])::slotted(nord-icon){transform:translateY(1px)}::slotted(nord-icon:not([size])),nord-icon{--_n-icon-size:var(--_n-button-icon-size)}`;let f=class extends(h(v(e))){constructor(){super(...arguments),this.defaultSlot=new c(this),this.buttonRef=s(),this.events=new b(this),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.square=!1,this.loading=!1,this.hideDropdownIcon=!1,this.handleOuterClick=t=>{t.composedPath().some((t=>t===this.focusableRef.value||t===this.buttonRef.value))||t.stopPropagation()}}connectedCallback(){super.connectedCallback(),this.events.listen(this,"click",this.handleOuterClick,!0)}render(){var t;const o="toggle"===(null===(t=this.assignedSlot)||void 0===t?void 0:t.name),e=this.defaultSlot.assigned.some((t=>"nord-icon"===t.localName)),a=o&&!this.hideDropdownIcon&&!e&&!this.href,i=n`<slot name="start"></slot><div class="n-content"><slot></slot></div><nord-spinner class="n-button-spinner" color="currentColor" ?hidden="${!this.loading||Boolean(this.href)}"></nord-spinner><slot name="end">${a?n`<nord-icon name="interface-dropdown-small" class="n-toggle-icon"></nord-icon>`:r}</slot>`;return this.href?this.renderLink(i):this.renderButton(i)}get isHostNonFocusable(){return"-1"===this.getAttribute("tabindex")}renderLink(t){return n`<a ${l(this.focusableRef)} class="n-button" target="${this.target}" rel="${u(this.rel)}" ?download="${this.download}" href="${u(this.disabled,r,this.href)}" tabindex="${u(this.disabled||this.isHostNonFocusable,"-1")}" aria-disabled="${u(this.disabled,"true")}" role="${u(this.disabled,"link")}">${t}</a>`}renderButton(t){return n`<slot name="proxy" @slotchange="${this.handleProxyChange}"></slot><button ${l(this.focusableRef)} class="n-button" ?disabled="${this.disabled}" name="${u(this.name)}" value="${u(this.value)}" tabindex="${u(this.isHostNonFocusable,"-1")}" @click="${this.handleClick}" aria-disabled="${u(this.loading,"true")}" aria-expanded="${u(this.accessibleExpanded)}" aria-haspopup="${u(this.accessibleHasPopup)}">${t}</button>`}renderLightDom(){return this.href||!this.form?r:n`<button ${l(this.buttonRef)} slot="proxy" name="${u(this.name)}" value="${u(this.value)}" ?disabled="${this.disabled}" form="${u(this._formId)}" type="${this.type}"></button>`}handleClick(t){this.buttonRef.value&&(t.stopPropagation(),this.buttonRef.value.click())}handleProxyChange(t){const o=t.target,n=this.buttonRef.value;n&&n.assignedSlot!==o&&this.appendChild(n)}};f.shadowRootOptions={...e.shadowRootOptions,delegatesFocus:!0},f.styles=[p,g],t([a({reflect:!0})],f.prototype,"variant",void 0),t([a({reflect:!0})],f.prototype,"type",void 0),t([a({reflect:!0})],f.prototype,"size",void 0),t([a({attribute:"aria-expanded"})],f.prototype,"accessibleExpanded",void 0),t([a({attribute:"aria-haspopup"})],f.prototype,"accessibleHasPopup",void 0),t([a({reflect:!0})],f.prototype,"href",void 0),t([a({reflect:!0,type:Boolean})],f.prototype,"download",void 0),t([a()],f.prototype,"target",void 0),t([a()],f.prototype,"rel",void 0),t([a({reflect:!0,type:Boolean})],f.prototype,"expand",void 0),t([a({reflect:!0,type:Boolean})],f.prototype,"square",void 0),t([a({reflect:!0,type:Boolean})],f.prototype,"loading",void 0),t([a({reflect:!0,type:Boolean,attribute:"hide-dropdown-icon"})],f.prototype,"hideDropdownIcon",void 0),f=t([i("nord-button")],f);var _=f;export{_ as default};
|
|
8
8
|
//# sourceMappingURL=Button.js.map
|
package/lib/Button.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.js","sources":["../src/button/Button.ts"],"sourcesContent":["/* eslint-disable lit-a11y/accessible-name */\nimport type { TemplateResult } from 'lit'\nimport { html, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { createRef, ref } from 'lit/directives/ref.js'\nimport { EventController } from '../common/controllers/EventController.js'\nimport { LightDomController } from '../common/controllers/LightDomController.js'\nimport { SlotController } from '../common/controllers/SlotController.js'\n\nimport { cond } from '../common/directives/cond.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'\nimport '../spinner/Spinner.js'\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 start - Used to place content at the start of button text. Typically used for icons.\n * @slot end - Used to place content at the end of button text. Typically used for icons.\n *\n * @cssprop [--n-button-border-radius=var(--n-border-radius-s)] - Controls the rounded corners of the button, using [border radius tokens](/tokens/#border-radius).\n * @cssprop [--n-button-gap=var(--n-space-s)] - Controls the spacing between items within the button, using our [spacing tokens](/tokens/#space).\n * @cssprop [--n-button-gradient=linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0.013) 100%))] - Controls the overlayed gradient background on the button.\n * @cssprop [--n-button-background-color=var(--n-color-button)] - Controls the background color of the button, using our [color tokens](/tokens/#color).\n * @cssprop [--n-button-border-color=var(--n-color-border-strong)] - Controls the border color of the button, using our [color tokens](/tokens/#color).\n * @cssprop [--n-button-text-align=center] - Controls the text alignment for the text in the button.\n * @cssprop [--n-button-box-shadow=var(--n-box-shadow)] - Controls the surrounding shadow, using our [box shadow tokens](/tokens/#box-shadow).\n * @cssprop [--n-button-color=var(--n-color-text)] - Controls the color of the text within the button, using our [color tokens](/tokens/#color).\n * @cssprop [--n-button-padding-inline=calc(var(--n-space-m) / 1.2)] - Controls the inline, or left and right, padding of the button.\n * @cssprop [--n-button-font-size=var(--n-font-size-m)] - Controls the size of the text within the button, using our [font tokens](/tokens/#font).\n * @cssprop [--n-button-font-weight=var(--n-font-weight)] - Controls the weight of the text within the button, using our [font tokens](/tokens/#font).\n * @cssprop [--n-button-min-block-size=var(--n-space-xl)] - Controls the minimum block size, or height, of the button using our [spacing tokens](/tokens/#space).\n * @cssprop [--n-button-toggle-icon-color=var(--n-color-icon)] - Controls the color of toggle icon that gets rendered when the button is used as a [Dropdown](/components/dropdown/) toggle.\n * @cssprop [--n-button-user-select=none] - Controls the text selection behavior of the button text.\n */\n@customElement('nord-button')\nexport default class Button extends InputMixin(FocusableMixin(LitElement)) {\n static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true }\n\n static styles = [componentStyle, style]\n\n private defaultSlot = new SlotController(this)\n private buttonRef = createRef<HTMLButtonElement>()\n private events = new EventController(this)\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 * This does not need to be documented,\n * since it is only for forwarding the aria-expanded attribute\n * to the internal button element.\n * @private\n */\n @property({ attribute: 'aria-expanded' }) accessibleExpanded?: 'true' | 'false'\n\n /**\n * This does not need to be documented,\n * since it is only for forwarding the aria-haspopup attribute\n * to the internal button element.\n * @private\n */\n @property({ attribute: 'aria-haspopup' }) accessibleHasPopup?:\n | 'false'\n | 'true'\n | 'menu'\n | 'listbox'\n | 'tree'\n | 'grid'\n | 'dialog'\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({ reflect: true, 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() 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 /**\n * When provided, the button is rendered as a square button. Use this for icon only buttons.\n */\n @property({ reflect: true, type: Boolean }) square = false\n\n /**\n * Controls whether the button is in loading state. Please note that the spinner\n * is hidden from assistive technologies, so you need to make sure to announce\n * the loading state to e.g. screen reader users. We also recommend disabling\n * all user interactions on the button itself while in loading state.\n */\n @property({ reflect: true, type: Boolean }) loading = false\n\n /**\n * Controls whether the `interface-dropdown-small` icon from Nordicons is hidden\n * in the `end` slot when used as a dropdown toggle.\n */\n @property({ reflect: true, type: Boolean, attribute: 'hide-dropdown-icon' }) hideDropdownIcon = false\n\n connectedCallback() {\n super.connectedCallback()\n this.events.listen(this, 'click', this.handleOuterClick, true)\n }\n\n render() {\n const isDropdownToggle = this.assignedSlot?.name === 'toggle'\n const isIconButton = this.defaultSlot.assigned.some(node => node.localName === 'nord-icon')\n const shouldShowDropdownIcon = isDropdownToggle && !this.hideDropdownIcon && !isIconButton && !this.href\n\n const innards = html`\n <slot name=\"start\"></slot>\n <div class=\"n-content\">\n <slot></slot>\n </div>\n <nord-spinner\n class=\"n-button-spinner\"\n color=\"currentColor\"\n ?hidden=${!this.loading || Boolean(this.href)}\n ></nord-spinner>\n <slot name=\"end\">\n ${shouldShowDropdownIcon\n ? html`<nord-icon name=\"interface-dropdown-small\" class=\"n-toggle-icon\"></nord-icon>`\n : nothing}\n </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 // When the host is explicitly removed from the tab order (`tabindex=\"-1\"`,\n // e.g. a decorative/`aria-hidden` button), forward that to the internal\n // control. `delegatesFocus` otherwise keeps the shadow button focusable, which\n // fails the `aria-hidden-focus` a11y rule (focusable descendant of a hidden\n // element). Only `-1` is forwarded — positive/zero values are left to\n // `delegatesFocus`.\n private get isHostNonFocusable(): boolean {\n return this.getAttribute('tabindex') === '-1'\n }\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=${cond(this.disabled, nothing, this.href)}\n tabindex=${cond(this.disabled || this.isHostNonFocusable, '-1')}\n aria-disabled=${cond(this.disabled, 'true')}\n role=${cond(this.disabled, 'link')}\n >${innards}\n </a>\n `\n }\n\n private renderButton(innards: TemplateResult) {\n return html`\n <slot name=\"proxy\" @slotchange=${this.handleProxyChange}></slot>\n <button\n ${ref(this.focusableRef)}\n class=\"n-button\"\n ?disabled=${this.disabled}\n name=${cond(this.name)}\n value=${cond(this.value)}\n tabindex=${cond(this.isHostNonFocusable, '-1')}\n @click=${this.handleClick}\n aria-disabled=${cond(this.loading, 'true')}\n aria-expanded=${cond(this.accessibleExpanded)}\n aria-haspopup=${cond(this.accessibleHasPopup)}\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=${cond(this.name)}\n value=${cond(this.value)}\n ?disabled=${this.disabled}\n form=${cond(this._formId)}\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 /**\n * React/Vue etc may remove our proxy button when updating button text, since they are unaware of its existence.\n * So we listen for a slotchange event, and if the element is no longer connected to the DOM we add it back in.\n */\n private handleProxyChange(e: Event) {\n const slot = e.target as HTMLSlotElement\n const proxyButton = this.buttonRef.value\n\n if (proxyButton && proxyButton.assignedSlot !== slot) {\n this.appendChild(proxyButton)\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-button': Button\n }\n}\n"],"names":["Button","InputMixin","FocusableMixin","LitElement","constructor","this","defaultSlot","SlotController","buttonRef","createRef","events","EventController","lightDom","LightDomController","render","renderLightDom","variant","type","size","download","target","expand","square","loading","hideDropdownIcon","handleOuterClick","e","composedPath","some","node","focusableRef","value","stopPropagation","connectedCallback","super","listen","isDropdownToggle","_a","assignedSlot","name","isIconButton","assigned","localName","shouldShowDropdownIcon","href","innards","html","Boolean","nothing","renderLink","renderButton","isHostNonFocusable","getAttribute","ref","cond","disabled","handleProxyChange","handleClick","accessibleExpanded","accessibleHasPopup","form","_formId","click","slot","proxyButton","appendChild","shadowRootOptions","delegatesFocus","styles","componentStyle","style","__decorate","property","reflect","prototype","attribute","customElement"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Button.js","sources":["../src/button/Button.ts"],"sourcesContent":["/* eslint-disable lit-a11y/accessible-name */\nimport type { TemplateResult } from 'lit'\nimport { html, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { createRef, ref } from 'lit/directives/ref.js'\nimport { EventController } from '../common/controllers/EventController.js'\nimport { LightDomController } from '../common/controllers/LightDomController.js'\nimport { SlotController } from '../common/controllers/SlotController.js'\n\nimport { cond } from '../common/directives/cond.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'\nimport '../spinner/Spinner.js'\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 start - Used to place content at the start of button text. Typically used for icons.\n * @slot end - Used to place content at the end of button text. Typically used for icons.\n *\n * @cssprop [--n-button-border-radius=var(--n-border-radius-s)] - Controls the rounded corners of the button, using [border radius tokens](/tokens/#border-radius).\n * @cssprop [--n-button-gap=var(--n-space-s)] - Controls the spacing between items within the button, using our [spacing tokens](/tokens/#space).\n * @cssprop [--n-button-gradient=linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0.013) 100%))] - Controls the overlayed gradient background on the button.\n * @cssprop [--n-button-background-color=var(--n-color-button)] - Controls the background color of the button, using our [color tokens](/tokens/#color).\n * @cssprop [--n-button-border-color=var(--n-color-border-strong)] - Controls the border color of the button, using our [color tokens](/tokens/#color).\n * @cssprop [--n-button-text-align=center] - Controls the text alignment for the text in the button.\n * @cssprop [--n-button-box-shadow=var(--n-box-shadow)] - Controls the surrounding shadow, using our [box shadow tokens](/tokens/#box-shadow).\n * @cssprop [--n-button-color=var(--n-color-text)] - Controls the color of the text within the button, using our [color tokens](/tokens/#color).\n * @cssprop [--n-button-padding-inline=calc(var(--n-space-m) / 1.2)] - Controls the inline, or left and right, padding of the button.\n * @cssprop [--n-button-font-size=var(--n-font-size-m)] - Controls the size of the text within the button, using our [font tokens](/tokens/#font).\n * @cssprop [--n-button-font-weight=var(--n-font-weight)] - Controls the weight of the text within the button, using our [font tokens](/tokens/#font).\n * @cssprop [--n-button-min-block-size=var(--n-space-xl)] - Controls the minimum block size, or height, of the button using our [spacing tokens](/tokens/#space).\n * @cssprop [--n-button-toggle-icon-color=var(--n-color-icon)] - Controls the color of toggle icon that gets rendered when the button is used as a [Dropdown](/components/dropdown/) toggle.\n * @cssprop [--n-button-user-select=none] - Controls the text selection behavior of the button text.\n */\n@customElement('nord-button')\nexport default class Button extends InputMixin(FocusableMixin(LitElement)) {\n static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true }\n\n static styles = [componentStyle, style]\n\n private defaultSlot = new SlotController(this)\n private buttonRef = createRef<HTMLButtonElement>()\n private events = new EventController(this)\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 * This does not need to be documented,\n * since it is only for forwarding the aria-expanded attribute\n * to the internal button element.\n * @private\n */\n @property({ attribute: 'aria-expanded' }) accessibleExpanded?: 'true' | 'false'\n\n /**\n * This does not need to be documented,\n * since it is only for forwarding the aria-haspopup attribute\n * to the internal button element.\n * @private\n */\n @property({ attribute: 'aria-haspopup' }) accessibleHasPopup?:\n | 'false'\n | 'true'\n | 'menu'\n | 'listbox'\n | 'tree'\n | 'grid'\n | 'dialog'\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({ reflect: true, 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() target: '_self' | '_blank' | '_parent' | '_top' = '_self'\n\n /**\n * When provided together with a href property, sets the relationship\n * between the linked URL and the current document, e.g. “noopener\n * noreferrer” when linking to untrusted content in a new tab.\n */\n @property() rel?: string\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 /**\n * When provided, the button is rendered as a square button. Use this for icon only buttons.\n */\n @property({ reflect: true, type: Boolean }) square = false\n\n /**\n * Controls whether the button is in loading state. Please note that the spinner\n * is hidden from assistive technologies, so you need to make sure to announce\n * the loading state to e.g. screen reader users. We also recommend disabling\n * all user interactions on the button itself while in loading state.\n */\n @property({ reflect: true, type: Boolean }) loading = false\n\n /**\n * Controls whether the `interface-dropdown-small` icon from Nordicons is hidden\n * in the `end` slot when used as a dropdown toggle.\n */\n @property({ reflect: true, type: Boolean, attribute: 'hide-dropdown-icon' }) hideDropdownIcon = false\n\n connectedCallback() {\n super.connectedCallback()\n this.events.listen(this, 'click', this.handleOuterClick, true)\n }\n\n render() {\n const isDropdownToggle = this.assignedSlot?.name === 'toggle'\n const isIconButton = this.defaultSlot.assigned.some(node => node.localName === 'nord-icon')\n const shouldShowDropdownIcon = isDropdownToggle && !this.hideDropdownIcon && !isIconButton && !this.href\n\n const innards = html`\n <slot name=\"start\"></slot>\n <div class=\"n-content\">\n <slot></slot>\n </div>\n <nord-spinner\n class=\"n-button-spinner\"\n color=\"currentColor\"\n ?hidden=${!this.loading || Boolean(this.href)}\n ></nord-spinner>\n <slot name=\"end\">\n ${shouldShowDropdownIcon\n ? html`<nord-icon name=\"interface-dropdown-small\" class=\"n-toggle-icon\"></nord-icon>`\n : nothing}\n </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 // When the host is explicitly removed from the tab order (`tabindex=\"-1\"`,\n // e.g. a decorative/`aria-hidden` button), forward that to the internal\n // control. `delegatesFocus` otherwise keeps the shadow button focusable, which\n // fails the `aria-hidden-focus` a11y rule (focusable descendant of a hidden\n // element). Only `-1` is forwarded — positive/zero values are left to\n // `delegatesFocus`.\n private get isHostNonFocusable(): boolean {\n return this.getAttribute('tabindex') === '-1'\n }\n\n private renderLink(innards: TemplateResult) {\n return html`\n <a\n ${ref(this.focusableRef)}\n class=\"n-button\"\n target=${this.target}\n rel=${cond(this.rel)}\n ?download=${this.download}\n href=${cond(this.disabled, nothing, this.href)}\n tabindex=${cond(this.disabled || this.isHostNonFocusable, '-1')}\n aria-disabled=${cond(this.disabled, 'true')}\n role=${cond(this.disabled, 'link')}\n >${innards}\n </a>\n `\n }\n\n private renderButton(innards: TemplateResult) {\n return html`\n <slot name=\"proxy\" @slotchange=${this.handleProxyChange}></slot>\n <button\n ${ref(this.focusableRef)}\n class=\"n-button\"\n ?disabled=${this.disabled}\n name=${cond(this.name)}\n value=${cond(this.value)}\n tabindex=${cond(this.isHostNonFocusable, '-1')}\n @click=${this.handleClick}\n aria-disabled=${cond(this.loading, 'true')}\n aria-expanded=${cond(this.accessibleExpanded)}\n aria-haspopup=${cond(this.accessibleHasPopup)}\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=${cond(this.name)}\n value=${cond(this.value)}\n ?disabled=${this.disabled}\n form=${cond(this._formId)}\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 /**\n * React/Vue etc may remove our proxy button when updating button text, since they are unaware of its existence.\n * So we listen for a slotchange event, and if the element is no longer connected to the DOM we add it back in.\n */\n private handleProxyChange(e: Event) {\n const slot = e.target as HTMLSlotElement\n const proxyButton = this.buttonRef.value\n\n if (proxyButton && proxyButton.assignedSlot !== slot) {\n this.appendChild(proxyButton)\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-button': Button\n }\n}\n"],"names":["Button","InputMixin","FocusableMixin","LitElement","constructor","this","defaultSlot","SlotController","buttonRef","createRef","events","EventController","lightDom","LightDomController","render","renderLightDom","variant","type","size","download","target","expand","square","loading","hideDropdownIcon","handleOuterClick","e","composedPath","some","node","focusableRef","value","stopPropagation","connectedCallback","super","listen","isDropdownToggle","_a","assignedSlot","name","isIconButton","assigned","localName","shouldShowDropdownIcon","href","innards","html","Boolean","nothing","renderLink","renderButton","isHostNonFocusable","getAttribute","ref","cond","rel","disabled","handleProxyChange","handleClick","accessibleExpanded","accessibleHasPopup","form","_formId","click","slot","proxyButton","appendChild","shadowRootOptions","delegatesFocus","styles","componentStyle","style","__decorate","property","reflect","prototype","attribute","customElement"],"mappings":"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"}
|
package/lib/DatePicker.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{_ as t}from"./tslib.es6-CmLYFWVC.js";import{i}from"./context-provider-D8lrPLVi.js";import{c as e}from"./interface-calendar-Cw2bJfbS.js";import{c as o}from"./interface-close-small-CnpAFMO3.js";import{css as a,html as s,nothing as r,LitElement as n}from"lit";import{query as l,property as d,customElement as p}from"lit/decorators.js";import{ifDefined as c}from"lit/directives/if-defined.js";import{ref as h}from"lit/directives/ref.js";import{S as m,i as u}from"./Calendar-D47b20IT.js";import{D as v,c as j,p as f,a as b}from"./dates-C-ZvzXaC.js";import{c as y}from"./cond-CI1KbneT.js";import{N as g}from"./events-Bv6wNHwJ.js";import{F as $}from"./FocusableMixin-BlQLNPdJ.js";import{F as z}from"./FormAssociatedMixin-D9aPREgv.js";import{I as D}from"./InputMixin-LetXsCyv.js";import{R as x}from"./ReadonlyMixin-BdJPGtQ3.js";import{S as k}from"./SizeMixin-CU9cLbLC.js";import{s as w}from"./Component-BJ5O5n8k.js";import{s as F}from"./FormField-CMgEFZCK.js";import{s as C}from"./TextField-
|
|
1
|
+
import{_ as t}from"./tslib.es6-CmLYFWVC.js";import{i}from"./context-provider-D8lrPLVi.js";import{c as e}from"./interface-calendar-Cw2bJfbS.js";import{c as o}from"./interface-close-small-CnpAFMO3.js";import{css as a,html as s,nothing as r,LitElement as n}from"lit";import{query as l,property as d,customElement as p}from"lit/decorators.js";import{ifDefined as c}from"lit/directives/if-defined.js";import{ref as h}from"lit/directives/ref.js";import{S as m,i as u}from"./Calendar-D47b20IT.js";import{D as v,c as j,p as f,a as b}from"./dates-C-ZvzXaC.js";import{c as y}from"./cond-CI1KbneT.js";import{N as g}from"./events-Bv6wNHwJ.js";import{F as $}from"./FocusableMixin-BlQLNPdJ.js";import{F as z}from"./FormAssociatedMixin-D9aPREgv.js";import{I as D}from"./InputMixin-LetXsCyv.js";import{R as x}from"./ReadonlyMixin-BdJPGtQ3.js";import{S as k}from"./SizeMixin-CU9cLbLC.js";import{s as w}from"./Component-BJ5O5n8k.js";import{s as F}from"./FormField-CMgEFZCK.js";import{s as C}from"./TextField-BYSciLeB.js";import{fieldContext as A}from"./field-context.js";import I from"./Icon.js";import{LocalizeController as S}from"./LocalizeController.js";import{isoAdapter as B}from"./date-adapter.js";import"./Input.js";import"./Button.js";import"./VisuallyHidden.js";import"./Popout-B6Hirj3y.js";import"./Stack.js";import"./context-request-event-CCRlXoeR.js";import"lit/directives/class-map.js";import"lit/directives/repeat.js";import"./tinykeys-DwvDXsEb.js";import"./collection-Dvg2XbxV.js";import"./DirectionController-ChvNGESZ.js";import"./EventController-BBOmvfLa.js";import"./observe-D0n0zOfU.js";import"./number-Dg2vCfGd.js";import"./DateRangeSelectEvent.js";import"./DateSelectEvent.js";import"./FormDataController-OUt5L5uC.js";import"./FieldControlMixin-BXNZJXu9.js";import"./context-consumer-BJVUulGf.js";import"./SlotController-Z6eG7LSZ.js";import"./light-dom-styles-DXsbiKU9.js";import"./create-context-CJ69ntlY.js";import"lit/directives/unsafe-html.js";import"./IconManager.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";import"./localization10.js";import"./localization11.js";import"./localization12.js";import"./localization13.js";import"./localization14.js";import"./localization15.js";import"./localization16.js";import"./localization17.js";import"./localization18.js";import"./localization19.js";import"./localization20.js";import"./localization21.js";import"./localization22.js";import"./localization23.js";import"./localization24.js";import"./navigation-search-CBbIGzo2.js";import"lit/directives/style-map.js";import"./ResizeController-14PUwRQy.js";import"./AutocompleteMixin-D8eiOxvO.js";import"./TextSelectableMixin-Cfv__lHS.js";import"./LightDomController-DIwtVelV.js";import"./Spinner.js";import"./positioning-D-K8Mueq.js";import"./LightDismissController-wcL1ziJa.js";import"./ShortcutController-CV5b0BZl.js";import"./ScrollbarController-BFC67Y2x.js";const E=a`:host{color:var(--n-color-text);position:relative}:host(:not([expand])) .n-date-picker-input{max-inline-size:max-content}.n-date-picker-calendar{--n-calendar-box-shadow:none}@media (max-width:35.9375em){.n-date-picker-header{border-block-end:1px solid var(--n-color-border);padding:calc(var(--n-space-s)*1.5) var(--n-space-m)}.n-date-picker-calendar{--_n-calendar-padding:var(--n-space-l)}}.n-date-picker-close-button{--n-button-border-radius:var(--n-border-radius-circle);--_n-button-padding-inline:calc(var(--n-space-s)/1.3);--_n-button-padding-block:0;inset-block-start:calc(var(--n-space-s)*-1);inset-inline-end:calc(var(--n-space-s)*-1);opacity:0;position:absolute}.n-date-picker-close-button:focus{opacity:1}.n-date-picker-heading{display:none;font-weight:var(--n-font-weight-active)}@media (max-width:35.9375em){.n-date-picker-close-button{inset:auto;opacity:1;position:relative}.n-date-picker-heading{display:initial}}`;I.registerIcon(e),I.registerIcon(o);const L=()=>!1,M=()=>!1;let O=class extends(k(z(x(D($(n)))))){constructor(){super(...arguments),this.fieldBarrier=new i(this,{context:A,initialValue:void 0}),this.swipe=new m(this,{target:()=>this.popout,matchesGesture:u,onSwipeEnd:()=>this.hide()}),this.localize=new S(this,{onLangChange:()=>this.createDateFormatters()}),this.value="",this.open=!1,this.firstDayOfWeek=v.Monday,this.dateAdapter=B,this.isDateDisabled=L,this.isDateHighlighted=M,this.expand=!1,this.handleDaySelect=t=>{t.stopPropagation(),this.setValue(t.date),this.hide()},this.handleBlur=t=>{t.stopPropagation(),this.internalError=this.validateDateBounds(this.valueAsDate),this.dispatchEvent(new g("blur"))},this.handleFocus=t=>{t.stopPropagation(),this.dispatchEvent(new g("focus"))},this.handleInputChange=t=>{var i;const e=t.target,o=this.dateAdapter.parse(e.value,j);this.rawValue=null===(i=this.focusableRef.value)||void 0===i?void 0:i.value,(o||""===e.value)&&this.setValue(o)}}get valueAsDate(){return f(this.value)}set valueAsDate(t){this.value=t?b(t):""}get valueAsNumber(){var t,i;return null!==(i=null===(t=this.valueAsDate)||void 0===t?void 0:t.getTime())&&void 0!==i?i:Number.NaN}set valueAsNumber(t){this.value=t?b(new Date(t)):""}get ownInvalid(){return Boolean(this.error||this.internalError)||super.ownInvalid}firstUpdated(){var t;this.rawValue=null===(t=this.focusableRef.value)||void 0===t?void 0:t.value}render(){const{valueAsDate:t}=this,i=t?this.dateAdapter.format(t):"";return s`<nord-input class="n-date-picker-input" value="${i}" label="${this.insideField?r:c(this.label)}" hint="${this.insideField?r:c(this.hint)}" error="${this.insideField?r:y(this.error||this.internalError,this.error||this.internalError)}" placeholder="${c(this.placeholder)}" id="${this.inputId}" size="${this.size}" ?expand="${this.expand}" ?disabled="${this.effectiveDisabled}" ?required="${this.required}" ?readonly="${this.readonly}" ?hint-below="${this.hintBelow}" ?hide-label="${this.insideField||this.hideLabel}" ?hide-required="${this.hideRequired}" disallow-pattern="[^0-9./-]" @focus="${this.handleFocus}" @blur="${this.handleBlur}" @input="${this.handleInputChange}" ${h(this.focusableRef)} aria-label="${c(this.controlAriaLabel)}" aria-invalid="${c(this.controlAriaInvalid)}" aria-describedby="${c(this.controlAriaDescribedby)}">${this.insideField||this.hintSlot.isEmpty?r:s`<slot name="hint" slot="hint"></slot>`} ${this.insideField||this.labelSlot.isEmpty?r:s`<slot name="label" slot="label"></slot>`}<nord-button size="${this.size}" ?disabled="${this.disabled||this.readonly}" slot="end" class="n-date-picker-toggle" aria-controls="popout" type="button"><nord-icon name="interface-calendar"></nord-icon><nord-visually-hidden>${this.localize.term("buttonLabel")} ${t?s`<span>, ${this.localize.term("selectedDateMessage")} ${this.dateFormatLong.format(t)}</span>`:r}</nord-visually-hidden></nord-button></nord-input><nord-popout id="popout" anchor="${this.inputId}" align="end" position="block-end" role="dialog" aria-modal="true" ?open="${this.open}" @open="${this.handleOpen}" @close="${this.handleClose}" aria-labelledby="header"><div aria-hidden="true" tabindex="0" @focus="${this.focusLast}"></div><nord-stack class="n-date-picker-header" direction="horizontal" justify-content="space-between"><div class="n-date-picker-heading" id="header">${this.localize.term("modalHeading")}</div><nord-button class="n-date-picker-close-button" type="button" size="s" variant="plain" @click="${this.handleClose}"><nord-visually-hidden>${this.localize.term("closeLabel")}</nord-visually-hidden><nord-icon name="interface-close-small"></nord-icon></nord-button></nord-stack><nord-calendar class="n-date-picker-calendar" expand value="${this.value}" min="${c(this.min)}" max="${c(this.max)}" today="${c(this.today)}" .firstDayOfWeek="${this.firstDayOfWeek}" .isDateDisabled="${this.isDateDisabled}" .isDateHighlighted="${this.isDateHighlighted}" @change="${this.handleDaySelect}"></nord-calendar><div aria-hidden="true" tabindex="0" @focus="${this.focusFirst}"></div></nord-popout>`}createDateFormatters(){this.dateFormatLong=new Intl.DateTimeFormat(this.localize.resolvedLang,{day:"numeric",month:"long",year:"numeric"})}focusFirst(){this.closeButton.focus()}focusLast(){this.calendar.focus({target:"day"})}handleOpen(){this.open=!0,this.calendar.focus({target:"month"})}handleClose(){this.open=!1}setValue(t){this.value=t?b(t):"";const{valueAsDate:i}=this,e=i?this.dateAdapter.format(i):"";this.rawValue=e,this.dispatchEvent(new g("change"))}validateDateBounds(t){if(!t)return;const i=f(this.min||""),e=f(this.max||"");return i&&t<i?this.localize.term("dateOutOfMinBound",this.min):e&&t>e?this.localize.term("dateOutOfMaxBound",this.max):void 0}hide(t){this.popout.hide(t)}show(){this.popout.show()}};O.styles=[w,F,C,E],t([l(".n-date-picker-toggle",!0)],O.prototype,"toggleButton",void 0),t([l(".n-date-picker-close-button",!0)],O.prototype,"closeButton",void 0),t([l("nord-calendar",!0)],O.prototype,"calendar",void 0),t([l('[role="dialog"]',!0)],O.prototype,"popout",void 0),t([d()],O.prototype,"value",void 0),t([d({attribute:!1})],O.prototype,"internalError",void 0),t([d({attribute:!1})],O.prototype,"rawValue",void 0),t([d({type:Boolean,reflect:!0})],O.prototype,"open",void 0),t([d({reflect:!0})],O.prototype,"min",void 0),t([d({reflect:!0})],O.prototype,"max",void 0),t([d({reflect:!0})],O.prototype,"today",void 0),t([d({reflect:!0,attribute:"first-day-of-week",type:Number})],O.prototype,"firstDayOfWeek",void 0),t([d({attribute:!1})],O.prototype,"dateAdapter",void 0),t([d({attribute:!1})],O.prototype,"isDateDisabled",void 0),t([d({attribute:!1})],O.prototype,"isDateHighlighted",void 0),t([d({reflect:!0,type:Boolean})],O.prototype,"expand",void 0),O=t([p("nord-date-picker")],O);var R=O;export{R as default};
|
|
2
2
|
//# sourceMappingURL=DatePicker.js.map
|