@nordhealth/components 4.25.2 → 4.26.1
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 +15700 -13775
- package/lib/Aside.js +8 -0
- package/lib/Aside.js.map +1 -0
- package/lib/AsideDrawer.js +14 -0
- package/lib/AsideDrawer.js.map +1 -0
- package/lib/AsideTrigger.js +5 -0
- package/lib/AsideTrigger.js.map +1 -0
- package/lib/Button.js +1 -1
- package/lib/Button.js.map +1 -1
- package/lib/{Calendar-B5X2WKNb.js → Calendar-ChNZdVRO.js} +2 -2
- package/lib/{Calendar-B5X2WKNb.js.map → Calendar-ChNZdVRO.js.map} +1 -1
- package/lib/Calendar.js +1 -1
- package/lib/Checkbox.js +1 -1
- package/lib/CommandMenu.js +1 -1
- package/lib/CommandMenu.js.map +1 -1
- package/lib/DatePicker.js +1 -1
- package/lib/Drawer.js +1 -1
- package/lib/Drawer.js.map +1 -1
- package/lib/DropdownItem.js +1 -1
- package/lib/DropdownSubmenu.js.map +1 -1
- package/lib/Footer.js +1 -1
- package/lib/Footer.js.map +1 -1
- package/lib/Header.js +1 -1
- package/lib/Header.js.map +1 -1
- package/lib/Icon.js +1 -1
- package/lib/Input.js +1 -1
- package/lib/Layout.js +3 -1
- package/lib/Layout.js.map +1 -1
- package/lib/Modal.js +1 -1
- package/lib/NavToggle-DzKbd-El.js +2 -0
- package/lib/NavToggle-DzKbd-El.js.map +1 -0
- package/lib/NavToggle.js +1 -1
- package/lib/Navigation.js +1 -1
- package/lib/Navigation.js.map +1 -1
- package/lib/Select.js +1 -1
- package/lib/TagGroup.js +1 -1
- package/lib/Toggle.js +1 -1
- package/lib/Truncate.js.map +1 -1
- package/lib/bundle.js +56 -38
- package/lib/bundle.js.map +1 -1
- package/lib/focus-D8oSvIcN.js +2 -0
- package/lib/focus-D8oSvIcN.js.map +1 -0
- package/lib/index.js +1 -1
- package/lib/react.d.ts +45 -20
- package/lib/src/aside/Aside.d.ts +388 -0
- package/lib/src/aside-drawer/AsideDrawer.d.ts +153 -0
- package/lib/src/aside-trigger/AsideTrigger.d.ts +84 -0
- package/lib/src/button/Button.d.ts +6 -0
- package/lib/src/common/body-scroll-lock.d.ts +20 -0
- package/lib/src/drawer/Drawer.d.ts +2 -1
- package/lib/src/dropdown-submenu/DropdownSubmenu.d.ts +0 -6
- package/lib/src/header/Header.d.ts +1 -1
- package/lib/src/index.d.ts +3 -0
- package/lib/src/layout/Layout.d.ts +15 -1
- package/lib/src/nav-toggle/NavToggle.d.ts +1 -16
- package/lib/src/truncate/Truncate.d.ts +1 -10
- package/lib/storage-CGZ-YX4-.js +2 -0
- package/lib/storage-CGZ-YX4-.js.map +1 -0
- package/lib/vue.d.ts +40 -20
- package/package.json +7 -7
- package/lib/NavToggle-BQxuLW2X.js +0 -2
- package/lib/NavToggle-BQxuLW2X.js.map +0 -1
package/lib/Truncate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Truncate.js","sources":["../src/truncate/Truncate.ts"],"sourcesContent":["import type { PropertyValues } from 'lit'\nimport { html, isServer, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { createRef, ref } from 'lit/directives/ref.js'\nimport style from './Truncate.css'\nimport '../tooltip/Tooltip.js'\n\nlet counter = 0\n\nconst ELLIPSIS = '…'\n\n/**\n * Truncate is a text wrapper that applies single-line or multi-line ellipsis\n * truncation and automatically reveals a tooltip with the full text when the\n * content actually overflows its container.\n *\n * Truncation is performed in JS (the DOM text node is replaced with a\n * pre-truncated string + ellipsis), matching the approach used by Ant Design\n * Pro's `Ellipsis` component. This avoids the well-known CSS\n * `text-overflow: ellipsis` quirk where clicking inside the clipped text\n * shifts the line and loses the ellipsis — there is no overflow to scroll\n * because the visible text fits exactly.\n *\n * @status ready\n * @category text\n * @slot - The full text content. Plain text is recommended; rich markup is\n * not supported (only `textContent` is read for truncation).\n */\n@customElement('nord-truncate')\nexport default class Truncate extends LitElement {\n static styles = style\n\n private spanRef = createRef<HTMLSpanElement>()\n private observer?: ResizeObserver\n private contentObserver?: MutationObserver\n private tooltipId = `n-truncate-${++counter}`\n // The tooltip lives in document.body (not in shadow DOM) so its\n // root-level mouseover listener can see hovers on the trigger element,\n // and so aria-describedby can resolve across the same document tree.\n private tooltipElement?: HTMLElement\n // The element that actually receives pointer events (often this host, but\n // when slotted into nord-button — which sets `::slotted(*) { pointer-events:\n // none }` — it resolves to the nord-button itself). aria-describedby is set\n // on this element so the tooltip's `closest()` lookup succeeds.\n private currentTrigger: Element | null = null\n\n @state() private isTruncated = false\n @state() private text = ''\n\n /**\n * Position of the tooltip relative to the truncated text. Mirrors `nord-tooltip`.\n */\n @property({ reflect: true })\n position: 'block-end' | 'block-start' | 'inline-start' | 'inline-end' = 'block-start'\n\n /**\n * Delay in milliseconds before the tooltip opens.\n */\n @property({ reflect: true, type: Number })\n delay = 500\n\n /**\n * Maximum number of lines before truncating. Defaults to `1` (single line).\n * Values `>= 2` allow the text to wrap up to that many lines before the\n * ellipsis kicks in.\n */\n @property({ type: Number, attribute: 'line-clamp' })\n lineClamp = 1\n\n /**\n * When set, the component still truncates the text but does not render\n * a hover tooltip with the full content. The `truncated` attribute is\n * still reflected so consumers can style it.\n */\n @property({ type: Boolean, reflect: true, attribute: 'no-tooltip' })\n noTooltip = false\n\n connectedCallback() {\n super.connectedCallback()\n\n if (isServer)\n return\n\n this.observer = new ResizeObserver(() => {\n // Defer to next frame so the browser has finished the layout pass\n // triggered by the resize before we read geometry.\n requestAnimationFrame(() => this.measure())\n })\n // Catch content changes the ResizeObserver can't see: text-only mutations\n // via reactive bindings (Lit/Vue/React often mutate characterData), or\n // children being replaced. Without this, swapping the label to a\n // longer/shorter string after first render would never re-evaluate\n // truncation.\n this.contentObserver = new MutationObserver(() => {\n this.captureText()\n this.measure()\n })\n this.contentObserver.observe(this, {\n characterData: true,\n childList: true,\n subtree: true,\n })\n this.captureText()\n }\n\n protected firstUpdated() {\n const span = this.spanRef.value\n if (span && this.observer) {\n this.observer.observe(span)\n }\n }\n\n protected updated() {\n this.syncTooltip()\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.observer?.disconnect()\n this.observer = undefined\n this.contentObserver?.disconnect()\n this.contentObserver = undefined\n this.tooltipElement?.remove()\n this.tooltipElement = undefined\n this.clearTrigger()\n }\n\n private captureText() {\n const next = (this.textContent ?? '').trim()\n if (next !== this.text) {\n this.text = next\n }\n }\n\n /**\n * Measure overflow and, if needed, binary-search the longest prefix of the\n * full text that fits in the available space, then commit `<prefix>…` as\n * the visible text. Same algorithm as Ant Design Pro's `Ellipsis`.\n */\n private measure() {\n const span = this.spanRef.value\n if (!span)\n return\n\n const fullText = this.text\n if (!fullText) {\n span.textContent = ''\n this.isTruncated = false\n return\n }\n\n // Reset to full text and check whether it already fits.\n span.textContent = fullText\n if (this.fits(span)) {\n this.isTruncated = false\n return\n }\n\n // Binary search: largest prefix length such that `prefix + …` fits.\n let lo = 0\n let hi = fullText.length\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2)\n span.textContent = trimEnd(fullText.slice(0, mid)) + ELLIPSIS\n if (this.fits(span)) {\n lo = mid\n }\n else {\n hi = mid - 1\n }\n }\n\n span.textContent = trimEnd(fullText.slice(0, lo)) + ELLIPSIS\n this.isTruncated = true\n }\n\n private fits(span: HTMLElement): boolean {\n if (this.lineClamp > 1) {\n return span.scrollHeight <= span.clientHeight\n }\n return span.scrollWidth <= span.clientWidth\n }\n\n /**\n * Walk up the DOM until we find an ancestor that actually receives pointer\n * events. Needed because `nord-button` (and similar) set\n * `::slotted(*) { pointer-events: none }`, so this host can never see hover.\n * Falls back to this host if no such ancestor is found.\n */\n private findTriggerElement(): Element {\n // pointer-events walk from the host itself so a standalone truncate\n // (default pointer-events: auto) is correctly returned as the trigger.\n // eslint-disable-next-line ts/no-this-alias -- intentional: start the\n let element: Element | null = this\n while (element && element !== document.body && element !== document.documentElement) {\n if (getComputedStyle(element).pointerEvents !== 'none') {\n return element\n }\n element = element.parentElement\n }\n return this\n }\n\n private addDescribedById(element: Element, id: string) {\n const existing = element.getAttribute('aria-describedby')\n const ids = existing ? existing.split(/\\s+/).filter(Boolean) : []\n if (!ids.includes(id)) {\n ids.push(id)\n element.setAttribute('aria-describedby', ids.join(' '))\n }\n }\n\n private removeDescribedById(element: Element, id: string) {\n const existing = element.getAttribute('aria-describedby')\n if (!existing)\n return\n const ids = existing.split(/\\s+/).filter(Boolean).filter(x => x !== id)\n if (ids.length) {\n element.setAttribute('aria-describedby', ids.join(' '))\n }\n else {\n element.removeAttribute('aria-describedby')\n }\n }\n\n private clearTrigger() {\n if (this.currentTrigger) {\n this.removeDescribedById(this.currentTrigger, this.tooltipId)\n this.currentTrigger = null\n }\n }\n\n private syncTooltip() {\n if (!this.isTruncated || !this.text) {\n this.removeAttribute('truncated')\n this.tooltipElement?.remove()\n this.tooltipElement = undefined\n this.clearTrigger()\n return\n }\n\n this.setAttribute('truncated', '')\n\n if (this.noTooltip) {\n this.tooltipElement?.remove()\n this.tooltipElement = undefined\n this.clearTrigger()\n return\n }\n\n if (!this.tooltipElement) {\n this.tooltipElement = document.createElement('nord-tooltip')\n this.tooltipElement.id = this.tooltipId\n document.body.appendChild(this.tooltipElement)\n }\n this.tooltipElement.setAttribute('position', this.position)\n this.tooltipElement.setAttribute('delay', String(this.delay))\n this.tooltipElement.textContent = this.text\n\n const trigger = this.findTriggerElement()\n if (trigger !== this.currentTrigger) {\n if (this.currentTrigger) {\n this.removeDescribedById(this.currentTrigger, this.tooltipId)\n }\n this.currentTrigger = trigger\n }\n this.addDescribedById(trigger, this.tooltipId)\n }\n\n protected willUpdate(changed: PropertyValues) {\n if (changed.has('lineClamp')) {\n if (this.lineClamp > 1) {\n this.setAttribute('line-clamp', String(this.lineClamp))\n this.style.setProperty('--_n-truncate-line-clamp', String(this.lineClamp))\n }\n else {\n this.removeAttribute('line-clamp')\n this.style.removeProperty('--_n-truncate-line-clamp')\n }\n }\n }\n\n render() {\n // The visible truncated text lives in a dedicated shadow-DOM span whose\n // `textContent` is managed imperatively in `measure()` (binary-search\n // updates would otherwise destroy Lit's ChildPart markers). The slot,\n // hidden visually, keeps the full text in light DOM so that assistive\n // tech and copy/paste of the host element still see the complete content.\n return html`\n <span ${ref(this.spanRef)} class=\"n-truncate\"></span>\n <slot class=\"n-truncate-source\" aria-hidden=\"true\"></slot>\n `\n }\n}\n\nfunction trimEnd(input: string): string {\n return input.replace(/[\\s.,;:!?-]+$/u, '')\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-truncate': Truncate\n }\n}\n"],"names":["counter","Truncate","LitElement","constructor","this","spanRef","createRef","tooltipId","currentTrigger","isTruncated","text","position","delay","lineClamp","noTooltip","connectedCallback","super","isServer","observer","ResizeObserver","requestAnimationFrame","measure","contentObserver","MutationObserver","captureText","observe","characterData","childList","subtree","firstUpdated","span","value","updated","syncTooltip","disconnectedCallback","_a","disconnect","undefined","_b","_c","tooltipElement","remove","clearTrigger","next","textContent","trim","fullText","fits","lo","hi","length","mid","Math","ceil","trimEnd","slice","scrollHeight","clientHeight","scrollWidth","clientWidth","findTriggerElement","element","document","body","documentElement","getComputedStyle","pointerEvents","parentElement","addDescribedById","id","existing","getAttribute","ids","split","filter","Boolean","includes","push","setAttribute","join","removeDescribedById","x","removeAttribute","createElement","appendChild","String","trigger","willUpdate","changed","has","style","setProperty","removeProperty","render","html","ref","styles","__decorate","state","prototype","property","reflect","type","Number","attribute","customElement","input","replace"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Truncate.js","sources":["../src/truncate/Truncate.ts"],"sourcesContent":["import type { PropertyValues } from 'lit'\nimport { html, isServer, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { createRef, ref } from 'lit/directives/ref.js'\nimport style from './Truncate.css'\nimport '../tooltip/Tooltip.js'\n\nlet counter = 0\n\nconst ELLIPSIS = '…'\n\n/**\n * Truncate clips text with a single- or multi-line ellipsis and reveals a tooltip with the full text when the content overflows.\n *\n * @status ready\n * @category text\n * @slot - The full text content. Plain text is recommended; rich markup is\n * not supported (only `textContent` is read for truncation).\n */\n@customElement('nord-truncate')\nexport default class Truncate extends LitElement {\n static styles = style\n\n private spanRef = createRef<HTMLSpanElement>()\n private observer?: ResizeObserver\n private contentObserver?: MutationObserver\n private tooltipId = `n-truncate-${++counter}`\n // The tooltip lives in document.body (not in shadow DOM) so its\n // root-level mouseover listener can see hovers on the trigger element,\n // and so aria-describedby can resolve across the same document tree.\n private tooltipElement?: HTMLElement\n // The element that actually receives pointer events (often this host, but\n // when slotted into nord-button — which sets `::slotted(*) { pointer-events:\n // none }` — it resolves to the nord-button itself). aria-describedby is set\n // on this element so the tooltip's `closest()` lookup succeeds.\n private currentTrigger: Element | null = null\n\n @state() private isTruncated = false\n @state() private text = ''\n\n /**\n * Position of the tooltip relative to the truncated text. Mirrors `nord-tooltip`.\n */\n @property({ reflect: true })\n position: 'block-end' | 'block-start' | 'inline-start' | 'inline-end' = 'block-start'\n\n /**\n * Delay in milliseconds before the tooltip opens.\n */\n @property({ reflect: true, type: Number })\n delay = 500\n\n /**\n * Maximum number of lines before truncating. Defaults to `1` (single line).\n * Values `>= 2` allow the text to wrap up to that many lines before the\n * ellipsis kicks in.\n */\n @property({ type: Number, attribute: 'line-clamp' })\n lineClamp = 1\n\n /**\n * When set, the component still truncates the text but does not render\n * a hover tooltip with the full content. The `truncated` attribute is\n * still reflected so consumers can style it.\n */\n @property({ type: Boolean, reflect: true, attribute: 'no-tooltip' })\n noTooltip = false\n\n connectedCallback() {\n super.connectedCallback()\n\n if (isServer)\n return\n\n this.observer = new ResizeObserver(() => {\n // Defer to next frame so the browser has finished the layout pass\n // triggered by the resize before we read geometry.\n requestAnimationFrame(() => this.measure())\n })\n // Catch content changes the ResizeObserver can't see: text-only mutations\n // via reactive bindings (Lit/Vue/React often mutate characterData), or\n // children being replaced. Without this, swapping the label to a\n // longer/shorter string after first render would never re-evaluate\n // truncation.\n this.contentObserver = new MutationObserver(() => {\n this.captureText()\n this.measure()\n })\n this.contentObserver.observe(this, {\n characterData: true,\n childList: true,\n subtree: true,\n })\n this.captureText()\n }\n\n protected firstUpdated() {\n const span = this.spanRef.value\n if (span && this.observer) {\n this.observer.observe(span)\n }\n }\n\n protected updated() {\n this.syncTooltip()\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.observer?.disconnect()\n this.observer = undefined\n this.contentObserver?.disconnect()\n this.contentObserver = undefined\n this.tooltipElement?.remove()\n this.tooltipElement = undefined\n this.clearTrigger()\n }\n\n private captureText() {\n const next = (this.textContent ?? '').trim()\n if (next !== this.text) {\n this.text = next\n }\n }\n\n /**\n * Measure overflow and, if needed, binary-search the longest prefix of the\n * full text that fits in the available space, then commit `<prefix>…` as\n * the visible text. Same algorithm as Ant Design Pro's `Ellipsis`.\n */\n private measure() {\n const span = this.spanRef.value\n if (!span)\n return\n\n const fullText = this.text\n if (!fullText) {\n span.textContent = ''\n this.isTruncated = false\n return\n }\n\n // Reset to full text and check whether it already fits.\n span.textContent = fullText\n if (this.fits(span)) {\n this.isTruncated = false\n return\n }\n\n // Binary search: largest prefix length such that `prefix + …` fits.\n let lo = 0\n let hi = fullText.length\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2)\n span.textContent = trimEnd(fullText.slice(0, mid)) + ELLIPSIS\n if (this.fits(span)) {\n lo = mid\n }\n else {\n hi = mid - 1\n }\n }\n\n span.textContent = trimEnd(fullText.slice(0, lo)) + ELLIPSIS\n this.isTruncated = true\n }\n\n private fits(span: HTMLElement): boolean {\n if (this.lineClamp > 1) {\n return span.scrollHeight <= span.clientHeight\n }\n return span.scrollWidth <= span.clientWidth\n }\n\n /**\n * Walk up the DOM until we find an ancestor that actually receives pointer\n * events. Needed because `nord-button` (and similar) set\n * `::slotted(*) { pointer-events: none }`, so this host can never see hover.\n * Falls back to this host if no such ancestor is found.\n */\n private findTriggerElement(): Element {\n // pointer-events walk from the host itself so a standalone truncate\n // (default pointer-events: auto) is correctly returned as the trigger.\n // eslint-disable-next-line ts/no-this-alias -- intentional: start the\n let element: Element | null = this\n while (element && element !== document.body && element !== document.documentElement) {\n if (getComputedStyle(element).pointerEvents !== 'none') {\n return element\n }\n element = element.parentElement\n }\n return this\n }\n\n private addDescribedById(element: Element, id: string) {\n const existing = element.getAttribute('aria-describedby')\n const ids = existing ? existing.split(/\\s+/).filter(Boolean) : []\n if (!ids.includes(id)) {\n ids.push(id)\n element.setAttribute('aria-describedby', ids.join(' '))\n }\n }\n\n private removeDescribedById(element: Element, id: string) {\n const existing = element.getAttribute('aria-describedby')\n if (!existing)\n return\n const ids = existing.split(/\\s+/).filter(Boolean).filter(x => x !== id)\n if (ids.length) {\n element.setAttribute('aria-describedby', ids.join(' '))\n }\n else {\n element.removeAttribute('aria-describedby')\n }\n }\n\n private clearTrigger() {\n if (this.currentTrigger) {\n this.removeDescribedById(this.currentTrigger, this.tooltipId)\n this.currentTrigger = null\n }\n }\n\n private syncTooltip() {\n if (!this.isTruncated || !this.text) {\n this.removeAttribute('truncated')\n this.tooltipElement?.remove()\n this.tooltipElement = undefined\n this.clearTrigger()\n return\n }\n\n this.setAttribute('truncated', '')\n\n if (this.noTooltip) {\n this.tooltipElement?.remove()\n this.tooltipElement = undefined\n this.clearTrigger()\n return\n }\n\n if (!this.tooltipElement) {\n this.tooltipElement = document.createElement('nord-tooltip')\n this.tooltipElement.id = this.tooltipId\n document.body.appendChild(this.tooltipElement)\n }\n this.tooltipElement.setAttribute('position', this.position)\n this.tooltipElement.setAttribute('delay', String(this.delay))\n this.tooltipElement.textContent = this.text\n\n const trigger = this.findTriggerElement()\n if (trigger !== this.currentTrigger) {\n if (this.currentTrigger) {\n this.removeDescribedById(this.currentTrigger, this.tooltipId)\n }\n this.currentTrigger = trigger\n }\n this.addDescribedById(trigger, this.tooltipId)\n }\n\n protected willUpdate(changed: PropertyValues) {\n if (changed.has('lineClamp')) {\n if (this.lineClamp > 1) {\n this.setAttribute('line-clamp', String(this.lineClamp))\n this.style.setProperty('--_n-truncate-line-clamp', String(this.lineClamp))\n }\n else {\n this.removeAttribute('line-clamp')\n this.style.removeProperty('--_n-truncate-line-clamp')\n }\n }\n }\n\n render() {\n // The visible truncated text lives in a dedicated shadow-DOM span whose\n // `textContent` is managed imperatively in `measure()` (binary-search\n // updates would otherwise destroy Lit's ChildPart markers). The slot,\n // hidden visually, keeps the full text in light DOM so that assistive\n // tech and copy/paste of the host element still see the complete content.\n return html`\n <span ${ref(this.spanRef)} class=\"n-truncate\"></span>\n <slot class=\"n-truncate-source\" aria-hidden=\"true\"></slot>\n `\n }\n}\n\nfunction trimEnd(input: string): string {\n return input.replace(/[\\s.,;:!?-]+$/u, '')\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-truncate': Truncate\n }\n}\n"],"names":["counter","Truncate","LitElement","constructor","this","spanRef","createRef","tooltipId","currentTrigger","isTruncated","text","position","delay","lineClamp","noTooltip","connectedCallback","super","isServer","observer","ResizeObserver","requestAnimationFrame","measure","contentObserver","MutationObserver","captureText","observe","characterData","childList","subtree","firstUpdated","span","value","updated","syncTooltip","disconnectedCallback","_a","disconnect","undefined","_b","_c","tooltipElement","remove","clearTrigger","next","textContent","trim","fullText","fits","lo","hi","length","mid","Math","ceil","trimEnd","slice","scrollHeight","clientHeight","scrollWidth","clientWidth","findTriggerElement","element","document","body","documentElement","getComputedStyle","pointerEvents","parentElement","addDescribedById","id","existing","getAttribute","ids","split","filter","Boolean","includes","push","setAttribute","join","removeDescribedById","x","removeAttribute","createElement","appendChild","String","trigger","willUpdate","changed","has","style","setProperty","removeProperty","render","html","ref","styles","__decorate","state","prototype","property","reflect","type","Number","attribute","customElement","input","replace"],"mappings":"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"}
|