@nordhealth/components 5.0.0 → 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.
Files changed (132) hide show
  1. package/custom-elements.json +26062 -25769
  2. package/lib/AsideDrawer.js +2 -2
  3. package/lib/AsideDrawer.js.map +1 -1
  4. package/lib/AsideTrigger.js +2 -2
  5. package/lib/AsideTrigger.js.map +1 -1
  6. package/lib/Autocomplete.js +1 -1
  7. package/lib/Autocomplete.js.map +1 -1
  8. package/lib/Button.js +2 -2
  9. package/lib/Button.js.map +1 -1
  10. package/lib/Calendar.js +1 -1
  11. package/lib/Combobox.js +1 -1
  12. package/lib/Combobox.js.map +1 -1
  13. package/lib/ComboboxBase.js +1 -1
  14. package/lib/ComboboxBase.js.map +1 -1
  15. package/lib/CommandMenu.js +1 -1
  16. package/lib/CommandMenu.js.map +1 -1
  17. package/lib/DatePicker.js +1 -1
  18. package/lib/DatePicker.js.map +1 -1
  19. package/lib/DateRangePicker.js +1 -1
  20. package/lib/DateRangePicker.js.map +1 -1
  21. package/lib/Dropdown.js +1 -1
  22. package/lib/Dropdown.js.map +1 -1
  23. package/lib/DropdownSubmenu.js +1 -1
  24. package/lib/FilterAddButton.js +1 -1
  25. package/lib/FilterAddButton.js.map +1 -1
  26. package/lib/FilterDateRange.js +1 -1
  27. package/lib/FilterDateRange.js.map +1 -1
  28. package/lib/FilterDropdown.js +1 -1
  29. package/lib/FilterDropdown.js.map +1 -1
  30. package/lib/FilterField.js +1 -1
  31. package/lib/FilterField.js.map +1 -1
  32. package/lib/FilterInput.js +1 -1
  33. package/lib/FilterInput.js.map +1 -1
  34. package/lib/FilterResetButton.js +1 -1
  35. package/lib/FilterResetButton.js.map +1 -1
  36. package/lib/Header.js +1 -1
  37. package/lib/Header.js.map +1 -1
  38. package/lib/IconManager.js +1 -1
  39. package/lib/Input.js +1 -1
  40. package/lib/Item.js +1 -1
  41. package/lib/Item.js.map +1 -1
  42. package/lib/Layout.js +1 -1
  43. package/lib/Layout.js.map +1 -1
  44. package/lib/LocalizeController.js +1 -1
  45. package/lib/LocalizeController.js.map +1 -1
  46. package/lib/Message.js +1 -1
  47. package/lib/Message.js.map +1 -1
  48. package/lib/Modal.js +1 -1
  49. package/lib/Modal.js.map +1 -1
  50. package/lib/NavGroup.js +1 -1
  51. package/lib/NavGroup.js.map +1 -1
  52. package/lib/NavItem.js +1 -1
  53. package/lib/NavItem.js.map +1 -1
  54. package/lib/NavToggle-ROsuaJkW.js +2 -0
  55. package/lib/{NavToggle-BY83xpx0.js.map → NavToggle-ROsuaJkW.js.map} +1 -1
  56. package/lib/NavToggle.js +1 -1
  57. package/lib/Navigation.js +1 -1
  58. package/lib/Navigation.js.map +1 -1
  59. package/lib/Notification.js +1 -1
  60. package/lib/Notification.js.map +1 -1
  61. package/lib/NumberField.js +1 -1
  62. package/lib/NumberField.js.map +1 -1
  63. package/lib/OtpField.js +1 -1
  64. package/lib/OtpField.js.map +1 -1
  65. package/lib/Outline.js +1 -1
  66. package/lib/Outline.js.map +1 -1
  67. package/lib/Pagination.js +1 -1
  68. package/lib/Pagination.js.map +1 -1
  69. package/lib/Popout-B6Hirj3y.js +2 -0
  70. package/lib/{Popout-CFtFoCaA.js.map → Popout-B6Hirj3y.js.map} +1 -1
  71. package/lib/Popout.js +1 -1
  72. package/lib/Range.js +1 -1
  73. package/lib/SegmentedControlItem.js +1 -1
  74. package/lib/Tag.js +1 -1
  75. package/lib/Tag.js.map +1 -1
  76. package/lib/TextField-BYSciLeB.js +2 -0
  77. package/lib/TextField-BYSciLeB.js.map +1 -0
  78. package/lib/Textarea.js +1 -1
  79. package/lib/Textarea.js.map +1 -1
  80. package/lib/TimePicker.js +1 -1
  81. package/lib/TimePicker.js.map +1 -1
  82. package/lib/bundle.js +13 -13
  83. package/lib/bundle.js.map +1 -1
  84. package/lib/en-us.js +1 -1
  85. package/lib/en-us.js.map +1 -1
  86. package/lib/fi-fi.js +1 -1
  87. package/lib/fi-fi.js.map +1 -1
  88. package/lib/index.js +1 -1
  89. package/lib/localization13.js +1 -1
  90. package/lib/localization13.js.map +1 -1
  91. package/lib/localization14.js +1 -1
  92. package/lib/localization14.js.map +1 -1
  93. package/lib/localization15.js +1 -1
  94. package/lib/localization15.js.map +1 -1
  95. package/lib/localization16.js +1 -1
  96. package/lib/localization16.js.map +1 -1
  97. package/lib/localization17.js +1 -1
  98. package/lib/localization17.js.map +1 -1
  99. package/lib/localization18.js +1 -1
  100. package/lib/localization18.js.map +1 -1
  101. package/lib/localization19.js +1 -1
  102. package/lib/localization19.js.map +1 -1
  103. package/lib/localization20.js +1 -1
  104. package/lib/localization20.js.map +1 -1
  105. package/lib/localization21.js +1 -1
  106. package/lib/localization21.js.map +1 -1
  107. package/lib/localization22.js +1 -1
  108. package/lib/localization22.js.map +1 -1
  109. package/lib/localization23.js +1 -1
  110. package/lib/localization23.js.map +1 -1
  111. package/lib/localization24.js +2 -0
  112. package/lib/localization24.js.map +1 -0
  113. package/lib/nav-context.js +2 -0
  114. package/lib/nav-context.js.map +1 -0
  115. package/lib/src/aside-trigger/AsideTrigger.d.ts +28 -2
  116. package/lib/src/button/Button.d.ts +7 -0
  117. package/lib/src/dropdown/Dropdown.d.ts +3 -0
  118. package/lib/src/layout/Layout.d.ts +12 -0
  119. package/lib/src/layout/localization.d.ts +5 -0
  120. package/lib/src/localization/en-us.d.ts +4 -0
  121. package/lib/src/localization/translation.d.ts +4 -0
  122. package/lib/src/nav-group/NavGroup.d.ts +1 -0
  123. package/lib/src/nav-group/nav-context.d.ts +11 -0
  124. package/lib/src/nav-item/NavItem.d.ts +45 -0
  125. package/lib/src/navigation/Navigation.d.ts +18 -0
  126. package/lib/translation.js +1 -1
  127. package/lib/translation.js.map +1 -1
  128. package/package.json +8 -8
  129. package/lib/NavToggle-BY83xpx0.js +0 -2
  130. package/lib/Popout-CFtFoCaA.js +0 -2
  131. package/lib/TextField-CSKvieoG.js +0 -2
  132. package/lib/TextField-CSKvieoG.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DateRangePicker.js","sources":["../src/date-range-picker/DateRangePicker.ts"],"sourcesContent":["import type { PropertyValues } from 'lit'\nimport type Calendar from '../calendar/Calendar.js'\nimport type { DatePredicate } from '../calendar/Calendar.js'\nimport type { DateRangeSelectEvent } from '../calendar/DateRangeSelectEvent.js'\n\nimport * as calendarIcon from '@nordhealth/icons/lib/assets/interface-calendar.js'\nimport * as closeIcon from '@nordhealth/icons/lib/assets/interface-close-small.js'\nimport * as dropdownIcon from '@nordhealth/icons/lib/assets/interface-dropdown-small.js'\nimport { html, LitElement, nothing } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { ref } from 'lit/directives/ref.js'\n\nimport { OpenStateController } from '../common/controllers/OpenStateController.js'\nimport { addDays, addMonths, DaysOfWeek, getQuarterRange, isQuarterCompleted, parseISODate, printISODate, setYear, startOfMonth, startOfQuarter, startOfWeek, startOfYear } from '../common/dates.js'\nimport { observe } from '../common/decorators/observe.js'\nimport { cond } from '../common/directives/cond.js'\nimport { NordEvent } from '../common/events.js'\nimport { injectLightDomStyles } from '../common/light-dom-styles.js'\nimport { DraftComponentMixin } from '../common/mixins/DraftComponentMixin.js'\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\nimport { ReadonlyMixin } from '../common/mixins/ReadonlyMixin.js'\nimport { SizeMixin } from '../common/mixins/SizeMixin.js'\nimport Icon from '../icon/Icon.js'\nimport { LocalizeController } from '../localization/LocalizeController.js'\nimport { DateRangeChangeEvent } from './DateRangeChangeEvent.js'\nimport style from './DateRangePicker.css'\nimport '../button/Button.js'\nimport '../input/Input.js'\nimport '../calendar/Calendar.js'\nimport '../popout/Popout.js'\nimport '../stack/Stack.js'\nimport '../visually-hidden/VisuallyHidden.js'\n\nIcon.registerIcon(calendarIcon)\nIcon.registerIcon(closeIcon)\nIcon.registerIcon(dropdownIcon)\n\n/** Per-instance counter so light-DOM ids stay unique across instances. */\nlet dateRangePickerCount = 1\n\n/** Default calendar predicates: nothing disabled, nothing highlighted. */\nconst isDateDisabled: DatePredicate = () => false\nconst isDateHighlighted = () => false\n\n/** A built-in preset row, resolved against \"today\" each time the popout opens. */\ninterface Preset {\n /** Stable key for tracking the active preset, and for the `presets` subset. */\n id: string\n /** Which divider group this preset belongs to (presets are grouped in order). */\n group: string\n /** Localized, human-readable label. */\n label: string\n /** Resolves the preset to an inclusive `[start, end]` relative to `today`. */\n resolve: (today: Date) => [Date, Date]\n /**\n * Optional gate (e.g. hide a current-year quarter that hasn't finished yet).\n * When omitted the preset is always available.\n */\n available?: (today: Date) => boolean\n}\n\n/** Order of the divider groups in the rendered preset list. */\nconst PRESET_GROUP_ORDER = ['today', 'lastDays', 'lastPeriod', 'currentPeriod', 'quarters'] as const\n\n/** Splits an interval string `YYYY-MM-DD/YYYY-MM-DD` into its two ISO parts. */\nfunction splitInterval(value: string): [string, string] {\n if (!value) {\n return ['', '']\n }\n const [start = '', end = ''] = value.split('/')\n return [start, end]\n}\n\n/** Joins two ISO parts into an interval string; returns `\"\"` if either is missing. */\nfunction joinInterval(start: string, end: string): string {\n return start && end ? `${start}/${end}` : ''\n}\n\n/**\n * Date Range Picker lets people choose a start and end date as a single range,\n * either from a built-in list of presets (Today, Last 7 days, This month, …) or\n * from a range calendar. It is a control only — compose it inside a\n * [Field](/components/field/) for a label, hint or error, like a native input.\n *\n * The committed value is an ISO-8601 interval string `YYYY-MM-DD/YYYY-MM-DD`;\n * the convenience `start-date` / `end-date` props and the `valueAsDateRange`\n * getter/setter stay in sync with it. Selecting in the popout builds a *pending*\n * range; **Apply** commits it (firing `change`), **Cancel** reverts to the last\n * committed value, and **Clear** empties it.\n *\n * @status draft\n * @category form\n * @lightDom true\n *\n * @fires {DateRangeChangeEvent} change - Dispatched when the committed range changes (Apply or Clear).\n * @fires {DateRangeChangeEvent} input - Dispatched live as the pending range changes inside the popout.\n * @fires {NordEvent} open - Dispatched when the popout is opened.\n * @fires {NordEvent} close - Dispatched when the popout is closed.\n *\n * @slot trigger - Optional custom trigger element (e.g. a filter chip or a `nord-button`) that opens the picker. Replaces the built-in trigger button when provided.\n *\n * @localization buttonLabel - Accessible label for the trigger button.\n * @localization placeholder - Placeholder shown in the trigger when no range is selected.\n * @localization modalHeading - Heading shown above the calendar in the popout.\n * @localization closeLabel - Accessible label for the close button.\n * @localization applyLabel - Label for the Apply button.\n * @localization cancelLabel - Label for the Cancel button.\n * @localization clearLabel - Label for the Clear button.\n * @localization presetsLabel - Accessible label for the preset list.\n * @localization presetsCollapsedLabel - Label for the collapsed preset dropdown (narrow widths).\n * @localization rangeSeparator - Character shown between the start and end dates in the trigger.\n * @localization dateOutOfMinBound - Error message shown when the range starts before the minimum date.\n * @localization dateOutOfMaxBound - Error message shown when the range ends after the maximum date.\n * @localization presetToday - Label for the \"Today\" preset.\n * @localization presetYesterday - Label for the \"Yesterday\" preset.\n * @localization presetLastDays - Label for the \"Last X days\" presets.\n * @localization presetLastMonths - Label for the \"Last X months\" presets.\n * @localization presetThisMonth - Label for the \"This month\" preset.\n * @localization presetLastWeek - Label for the \"Last week\" preset.\n * @localization presetLastMonth - Label for the \"Last month\" preset.\n * @localization presetLastQuarter - Label for the \"Last quarter\" preset.\n * @localization presetLastYear - Label for the \"Last year\" preset.\n * @localization presetCurrentWeek - Label for the \"Current week\" preset.\n * @localization presetCurrentMonth - Label for the \"Current month\" preset.\n * @localization presetCurrentQuarter - Label for the \"Current quarter\" preset.\n * @localization presetCurrentYear - Label for the \"Current year\" preset.\n * @localization presetQuarter - Label for a specific calendar quarter, e.g. \"Q3 2025\".\n *\n * @cssprop [--n-date-range-picker-trigger-min-inline-size=14rem] - Controls the minimum inline size of the trigger.\n * @cssprop [--n-date-range-picker-popout-inline-size] - Controls the inline size of the popout content.\n */\n@customElement('nord-date-range-picker')\nexport default class DateRangePicker extends DraftComponentMixin(\n SizeMixin(FormAssociatedMixin(ReadonlyMixin(InputMixin(FocusableMixin(LitElement))))),\n) {\n /** Stable, unique id base for the light-DOM ARIA wiring of this instance. */\n private dateRangePickerId = `nord-date-range-picker-${dateRangePickerCount++}`\n\n // The built-in `<label for>` (from FieldControlMixin) must point at the real\n // focusable trigger, so override the mixin's default id with the trigger's id.\n protected override inputId = `${this.dateRangePickerId}-input`\n\n // The trigger is a button that opens the popup on click, so a label click\n // should focus it (with the ring) rather than open it — keyboard opens it.\n protected override get labelFocusOnly() {\n return true\n }\n\n @query('nord-calendar', true) private calendar?: Calendar\n @query('.n-drp-toggle', true) private toggle?: HTMLElement\n @query('nord-popout', true) private popout?: HTMLElement & {\n show: () => Promise<unknown>\n hide: (moveFocusToButton?: boolean) => Promise<unknown>\n }\n\n private localize = new LocalizeController<'nord-date-range-picker'>(this, {\n onLangChange: () => this.createDateFormatters(),\n })\n\n // Coordinates `open` with the popout: `open` is the source of truth (it drives\n // popout.show()/hide()), the popout's own events sync `open` back, and one\n // canonical open/close is emitted. Opening is rejected while disabled/read-only.\n private openState = new OpenStateController(this, {\n isOpen: () => this.open,\n setOpen: (open) => { this.open = open },\n popout: () => this.popout,\n isInert: () => this.disabled || this.readonly,\n onOpen: () => {\n // Seed the pending selection from the committed value on every open, so an\n // abandoned (cancelled) pending range never leaks across opens, then move\n // focus into the calendar.\n this.pendingStart = this.startDate\n this.pendingEnd = this.endDate\n void this.calendar?.updateComplete.then(() => this.calendar?.focus({ target: 'day' }))\n },\n })\n\n private dateFormat!: Intl.DateTimeFormat\n\n /**\n * The committed value as an ISO-8601 interval string `YYYY-MM-DD/YYYY-MM-DD`.\n * An empty string means no range is committed.\n */\n @property() value = ''\n\n /**\n * Convenience accessor for the committed start date, in ISO-8601 format. Kept\n * in sync with `value` and `end-date`.\n */\n @property({ reflect: true, attribute: 'start-date' }) startDate = ''\n\n /**\n * Convenience accessor for the committed end date, in ISO-8601 format. Kept in\n * sync with `value` and `start-date`.\n */\n @property({ reflect: true, attribute: 'end-date' }) endDate = ''\n\n /**\n * Controls whether the popout is open.\n */\n @property({ type: Boolean, reflect: true }) open = false\n\n /**\n * Minimum date allowed to be picked, in ISO-8601 format: YYYY-MM-DD.\n */\n @property({ reflect: true }) min?: string\n\n /**\n * Maximum date allowed to be picked, in ISO-8601 format: YYYY-MM-DD.\n */\n @property({ reflect: true }) max?: string\n\n /**\n * The date that is considered today, in ISO-8601 format. Presets resolve\n * relative to this; if unset, the user's current local date is used.\n */\n @property({ reflect: true }) today?: string\n\n /**\n * Which day is considered the first day of the week. `0` for Sunday, `1` for\n * Monday, etc. Default is Monday.\n */\n @property({ reflect: true, attribute: 'first-day-of-week', type: Number }) firstDayOfWeek: DaysOfWeek\n = DaysOfWeek.Monday\n\n /**\n * Controls which days are disabled and therefore disallowed.\n * For example, this can be used to disallow selection of weekends.\n */\n @property({ attribute: false }) isDateDisabled: DatePredicate = isDateDisabled\n\n /**\n * Controls which days are highlighted with a small indicator.\n * Returning `false` will not show an indicator.\n * Returning `true` will show the indicator, but without an accessible label. Therefore\n * Returning a string will show the indicator, and use the string as accessible label.\n * It is recommended to return a string rather than `true` whenever possible.\n */\n @property({ attribute: false }) isDateHighlighted: (date: Date) => string | boolean = isDateHighlighted\n\n /**\n * Hides the built-in list of preset ranges, leaving only the calendar.\n */\n @property({ reflect: true, type: Boolean, attribute: 'hide-presets' }) hidePresets = false\n\n /**\n * Restricts the preset list to this subset of preset ids (in their natural\n * group order). When unset, the full catalogue is shown. Ids:\n * `today`, `yesterday`, `last-7`/`last-30`/`last-60`/`last-90`/`last-365`,\n * `last-week`, `last-month`, `last-6-months`, `last-quarter`, `last-year`,\n * `last-12-months`, `current-week`/`current-month`/`current-quarter`/`current-year`,\n * and quarter ids `q-<year>-<1-4>`.\n */\n @property({ attribute: false }) presets?: string[]\n\n /**\n * Render the picker inline — the presets, calendar and Apply/Cancel/Clear are\n * always visible, with no trigger button or popout. Use it when the picker\n * lives directly on the page (e.g. in a form) rather than behind a trigger.\n */\n @property({ reflect: true, type: Boolean }) inline = false\n\n /**\n * The name used to submit the **start** date as its own form field. When both\n * `start-name` and `end-name` are set, the picker submits two fields\n * (`start-name`=startDate, `end-name`=endDate) instead of the single `name`.\n */\n @property({ reflect: true, attribute: 'start-name' }) startName?: string\n\n /**\n * The name used to submit the **end** date as its own form field. See\n * `start-name`.\n */\n @property({ reflect: true, attribute: 'end-name' }) endName?: string\n\n /**\n * Validation error message, set automatically when the committed range falls\n * outside min/max.\n */\n @property({ attribute: false }) internalError?: string\n\n /** The pending range inside the popout, before Apply commits it. */\n @state() private pendingStart = ''\n @state() private pendingEnd = ''\n\n /** Whether the popout shows a single month (narrow) rather than two. */\n @state() private isNarrow = false\n\n /** Whether the collapsed preset dropdown (narrow layout) is open. */\n @state() private presetsOpen = false\n\n /**\n * Below this viewport width (in `rem`) the picker collapses to a single month\n * with stacked presets. Measured against the viewport — NOT the host — because\n * the popout floats (`position: fixed`) and is free to be as wide as the\n * viewport allows, regardless of the trigger's own width. A `resize` listener\n * is required (rather than a CSS media query) because the month count is a\n * `nord-calendar` prop in shadow DOM that CSS cannot reach.\n *\n * Two months + presets need ~900px to render without overflowing, so the\n * threshold sits a little above that. Expressed in `rem` (resolved against the\n * root font size on each measurement) so it scales with zoom / font size, the\n * same way the calendar's own `rem`-based sizing does.\n */\n private static readonly narrowThresholdRem = 57.5\n\n // Keeps the collapsed-presets popout width in sync with the trigger as the host\n // resizes; the narrow/wide decision itself tracks the viewport (see below).\n private resizeObserver = new ResizeObserver(() => {\n this.measureNarrow()\n this.syncPresetsInlineSize()\n })\n\n private handleViewportResize = () => {\n this.measureNarrow()\n }\n\n /**\n * Sets `isNarrow` from the viewport width. The `resize` listener drives this for\n * live changes, but it fires asynchronously, so it's also called synchronously\n * before opening the popout so the first render already shows the right number\n * of months. Ignores 0-width measurements (detached/hidden).\n */\n private measureNarrow(width: number = window.innerWidth) {\n if (width > 0) {\n const rootFontSize = Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 16\n this.isNarrow = width < DateRangePicker.narrowThresholdRem * rootFontSize\n }\n }\n\n /**\n * Mirror the collapsed-presets trigger width into a custom property so the\n * presets popout matches it (the popout floats `position: fixed`, so a `%`\n * width can't reference the trigger). Mirrors the combobox dropdown approach.\n */\n private syncPresetsInlineSize() {\n const collapsed = this.renderRoot.querySelector('.n-drp-presets-collapsed')\n if (collapsed) {\n this.style.setProperty('--_n-drp-presets-inline-size', `${collapsed.clientWidth}px`)\n }\n }\n\n /**\n * A user-supplied trigger element (`slot=\"trigger\"`), captured from the light\n * DOM before the first render so it can be re-inserted into the rendered\n * structure. When present it replaces the built-in button; `null` uses the\n * default trigger.\n */\n private customTrigger: HTMLElement | null = null\n\n /** The interval string was the source of the most recent sync (avoids loops). */\n private syncingFromValue = false\n\n get valueAsDateRange(): [Date, Date] | undefined {\n const start = parseISODate(this.startDate)\n const end = parseISODate(this.endDate)\n return start && end ? [start, end] : undefined\n }\n\n /**\n * Get/set the committed range as a `[Date, Date]` tuple. Setting `undefined`\n * clears the range.\n */\n set valueAsDateRange(range: [Date, Date] | undefined) {\n if (!range) {\n this.value = ''\n return\n }\n const [start, end] = range\n this.value = joinInterval(printISODate(start), printISODate(end))\n }\n\n /** The form the `formdata` listener is currently attached to, if any. */\n private boundForm: HTMLFormElement | null = null\n\n connectedCallback() {\n super.connectedCallback()\n injectLightDomStyles(this, style)\n this.syncFormListener()\n this.resizeObserver.observe(this)\n window.addEventListener('resize', this.handleViewportResize)\n // Capture a custom trigger (`slot=\"trigger\"`) before the first render owns\n // the light DOM; it is re-inserted into the rendered structure by `render`.\n this.customTrigger = this.querySelector<HTMLElement>(':scope > [slot=\"trigger\"]')\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.boundForm?.removeEventListener('formdata', this.handleFormData)\n this.boundForm = null\n this.resizeObserver.disconnect()\n window.removeEventListener('resize', this.handleViewportResize)\n }\n\n // Render in the light DOM so the control participates in the document tree.\n protected createRenderRoot() {\n return this\n }\n\n // The control's own invalid state for the field context: a built-in/internal error.\n protected override get ownInvalid() {\n return Boolean(this.error || this.internalError) || super.ownInvalid\n }\n\n protected firstUpdated(changed: PropertyValues) {\n super.firstUpdated(changed)\n // Seed the inline pending selection from an initial value.\n if (this.inline) {\n this.pendingStart = this.startDate\n this.pendingEnd = this.endDate\n }\n }\n\n protected updated(changed: PropertyValues) {\n super.updated(changed)\n // The associated form can change after `form` is set or on reconnection.\n this.syncFormListener()\n this.wireCustomTrigger()\n // Keep the presets popout matched to the (re-rendered) collapsed trigger.\n this.syncPresetsInlineSize()\n }\n\n /**\n * Give a slotted custom trigger the same ARIA wiring the built-in button has,\n * so `nord-popout` auto-attaches its open/close click via `aria-controls` and\n * assistive tech sees the dialog relationship and expanded state.\n */\n private wireCustomTrigger() {\n const trigger = this.customTrigger\n if (!trigger) {\n return\n }\n const popoutId = `${this.dateRangePickerId}-popout`\n trigger.setAttribute('aria-controls', popoutId)\n trigger.setAttribute('aria-haspopup', 'dialog')\n trigger.setAttribute('aria-expanded', this.open ? 'true' : 'false')\n // Drive `open` (the source of truth) from the trigger click, like the\n // built-in button's `@click`. `nord-popout` also auto-wires a click via\n // `aria-controls`, but show()/hide() are idempotent so the two coincide\n // harmlessly. The listener is added once (it's a no-op if already bound).\n trigger.removeEventListener('click', this.handleTriggerClick)\n trigger.addEventListener('click', this.handleTriggerClick)\n }\n\n /**\n * The control submits one OR two form fields (single interval, or separate\n * start/end), which `FormAssociatedMixin`'s single `FormDataController` can't\n * express, so listen for `formdata` directly and (re)bind to the active form.\n */\n private syncFormListener() {\n const form = this.form\n if (form === this.boundForm) {\n return\n }\n this.boundForm?.removeEventListener('formdata', this.handleFormData)\n this.boundForm = form\n this.boundForm?.addEventListener('formdata', this.handleFormData)\n }\n\n /**\n * Keep `value`, `start-date` and `end-date` consistent. The interval string is\n * the source of truth; whichever changed last drives the others.\n */\n @observe('value')\n protected handleValueObserve() {\n if (this.syncingFromValue) {\n return\n }\n this.syncingFromValue = true\n const [start, end] = splitInterval(this.value)\n this.startDate = start\n this.endDate = end\n this.internalError = this.validateBounds(start, end)\n this.syncingFromValue = false\n\n // Inline has no popout-open to seed the pending selection, so mirror the\n // committed value into it whenever it changes.\n if (this.inline) {\n this.pendingStart = start\n this.pendingEnd = end\n }\n }\n\n @observe('startDate')\n @observe('endDate')\n protected handlePartObserve() {\n if (this.syncingFromValue) {\n return\n }\n this.syncingFromValue = true\n this.value = joinInterval(this.startDate, this.endDate)\n this.internalError = this.validateBounds(this.startDate, this.endDate)\n this.syncingFromValue = false\n }\n\n /**\n * Suppress the inherited `FormDataController`. This control submits one OR two\n * fields depending on `start-name`/`end-name`, which a single controller can't\n * express, so `handleFormData` owns the entire submission instead. Returning\n * `undefined` here keeps the base controller from also appending `name`.\n */\n protected get formValue(): string | undefined {\n return undefined\n }\n\n private handleFormData = (e: FormDataEvent) => {\n if (this.disabled) {\n return\n }\n\n // Two-field mode: submit start and end under their own names.\n if (this.startName && this.endName) {\n if (this.startDate) {\n e.formData.append(this.startName, this.startDate)\n }\n if (this.endDate) {\n e.formData.append(this.endName, this.endDate)\n }\n return\n }\n\n // Single-field mode: submit the interval string under `name`.\n if (this.name && this.value) {\n e.formData.append(this.name, this.value)\n }\n }\n\n /**\n * The full catalogue of presets, resolved against the configured (or current)\n * \"today\". Date arithmetic mirrors NFE's `getPredefinedDateRange`: \"last N\n * days\" counts back `N` days from today; \"last N months\" are full calendar\n * months ending at the previous month-end; period/quarter presets use calendar\n * boundaries (first-day-of-week aware for weeks).\n */\n private get presetCatalogue(): Preset[] {\n const t = this.localize\n const fdow = this.firstDayOfWeek\n const currentYear = this.getToday().getFullYear()\n const lastYear = currentYear - 1\n\n const presets: Preset[] = [\n // today / yesterday\n { id: 'today', group: 'today', label: t.term('presetToday'), resolve: today => [today, today] },\n { id: 'yesterday', group: 'today', label: t.term('presetYesterday'), resolve: (today) => {\n const y = addDays(today, -1)\n return [y, y]\n } },\n\n // last N days (start = today − N, mirroring NFE)\n { id: 'last-7', group: 'lastDays', label: t.term('presetLastDays', 7), resolve: today => [addDays(today, -7), today] },\n { id: 'last-30', group: 'lastDays', label: t.term('presetLastDays', 30), resolve: today => [addDays(today, -30), today] },\n { id: 'last-60', group: 'lastDays', label: t.term('presetLastDays', 60), resolve: today => [addDays(today, -60), today] },\n { id: 'last-90', group: 'lastDays', label: t.term('presetLastDays', 90), resolve: today => [addDays(today, -90), today] },\n { id: 'last-365', group: 'lastDays', label: t.term('presetLastDays', 365), resolve: today => [addDays(today, -365), today] },\n\n // last calendar periods\n { id: 'last-week', group: 'lastPeriod', label: t.term('presetLastWeek'), resolve: (today) => {\n const thisWeekStart = startOfWeek(today, fdow)\n return [addDays(thisWeekStart, -7), addDays(thisWeekStart, -1)]\n } },\n { id: 'last-month', group: 'lastPeriod', label: t.term('presetLastMonth'), resolve: (today) => {\n const lastMonthEnd = addDays(startOfMonth(today), -1)\n return [startOfMonth(lastMonthEnd), lastMonthEnd]\n } },\n { id: 'last-6-months', group: 'lastPeriod', label: t.term('presetLastMonths', 6), resolve: (today) => {\n const end = addDays(startOfMonth(today), -1)\n return [startOfMonth(addMonths(end, -5)), end]\n } },\n { id: 'last-quarter', group: 'lastPeriod', label: t.term('presetLastQuarter'), resolve: (today) => {\n const lastQuarterEnd = addDays(startOfQuarter(today), -1)\n return [startOfQuarter(lastQuarterEnd), lastQuarterEnd]\n } },\n { id: 'last-year', group: 'lastPeriod', label: t.term('presetLastYear'), resolve: (today) => {\n const prev = setYear(today, today.getFullYear() - 1)\n return [startOfYear(prev), addDays(startOfYear(today), -1)]\n } },\n { id: 'last-12-months', group: 'lastPeriod', label: t.term('presetLastMonths', 12), resolve: (today) => {\n const end = addDays(startOfMonth(today), -1)\n return [startOfMonth(addMonths(end, -11)), end]\n } },\n\n // current calendar periods (start of period → today)\n { id: 'current-week', group: 'currentPeriod', label: t.term('presetCurrentWeek'), resolve: today => [startOfWeek(today, fdow), today] },\n { id: 'current-month', group: 'currentPeriod', label: t.term('presetCurrentMonth'), resolve: today => [startOfMonth(today), today] },\n { id: 'current-quarter', group: 'currentPeriod', label: t.term('presetCurrentQuarter'), resolve: today => [startOfQuarter(today), today] },\n { id: 'current-year', group: 'currentPeriod', label: t.term('presetCurrentYear'), resolve: today => [startOfYear(today), today] },\n ]\n\n // Explicit calendar quarters: Q4→Q1 of the current year (only those already\n // completed), then Q4→Q1 of last year.\n for (const year of [currentYear, lastYear]) {\n for (const quarter of [4, 3, 2, 1]) {\n presets.push({\n id: `q-${year}-${quarter}`,\n group: 'quarters',\n label: t.term('presetQuarter', quarter, year),\n resolve: () => getQuarterRange(quarter, year),\n available: year === currentYear ? today => isQuarterCompleted(quarter, today) : undefined,\n })\n }\n }\n\n return presets\n }\n\n /** The presets that should be shown, after subset/availability/min-max filters. */\n private get visiblePresets(): Preset[] {\n const today = this.getToday()\n const min = parseISODate(this.min || '')\n const max = parseISODate(this.max || '')\n\n let presets = this.presetCatalogue\n\n // Optional consumer-chosen subset, preserving catalogue order.\n if (this.presets) {\n const allowed = new Set(this.presets)\n presets = presets.filter(preset => allowed.has(preset.id))\n }\n\n return presets.filter((preset) => {\n if (preset.available && !preset.available(today)) {\n return false\n }\n // Drop presets whose resolved range falls outside min/max.\n const [start, end] = preset.resolve(today)\n if (min && start.getTime() < min.getTime()) {\n return false\n }\n if (max && end.getTime() > max.getTime()) {\n return false\n }\n return true\n })\n }\n\n /** The visible presets bucketed into their divider groups, in group order. */\n private get presetGroups(): Preset[][] {\n const visible = this.visiblePresets\n return PRESET_GROUP_ORDER\n .map(group => visible.filter(preset => preset.group === group))\n .filter(group => group.length > 0)\n }\n\n private getToday(): Date {\n return parseISODate(this.today || '') || new Date()\n }\n\n /** Which preset (if any) the pending selection currently matches. */\n private get activePresetId(): string | undefined {\n if (!this.pendingStart || !this.pendingEnd) {\n return undefined\n }\n const today = this.getToday()\n for (const preset of this.visiblePresets) {\n const [start, end] = preset.resolve(today)\n if (printISODate(start) === this.pendingStart && printISODate(end) === this.pendingEnd) {\n return preset.id\n }\n }\n return undefined\n }\n\n private createDateFormatters() {\n this.dateFormat = new Intl.DateTimeFormat(this.localize.resolvedLang, {\n day: 'numeric',\n month: 'short',\n year: 'numeric',\n })\n }\n\n /** The text shown in the trigger: the formatted range, or the placeholder. */\n private get displayValue(): string {\n const range = this.valueAsDateRange\n if (!range) {\n return ''\n }\n const [start, end] = range\n const sep = this.localize.term('rangeSeparator')\n return `${this.dateFormat.format(start)} ${sep} ${this.dateFormat.format(end)}`\n }\n\n /** The in-progress (pending) range formatted for the footer, or '' while empty. */\n private get pendingRangeLabel(): string {\n const start = parseISODate(this.pendingStart)\n if (!start) {\n return ''\n }\n const end = parseISODate(this.pendingEnd)\n const sep = this.localize.term('rangeSeparator')\n return end ? `${this.dateFormat.format(start)} ${sep} ${this.dateFormat.format(end)}` : this.dateFormat.format(start)\n }\n\n private validateBounds(start: string, end: string): string | undefined {\n const minDate = parseISODate(this.min || '')\n const maxDate = parseISODate(this.max || '')\n const startDate = parseISODate(start)\n const endDate = parseISODate(end)\n\n if (minDate && startDate && startDate < minDate) {\n return this.localize.term('dateOutOfMinBound', this.min!)\n }\n if (maxDate && endDate && endDate > maxDate) {\n return this.localize.term('dateOutOfMaxBound', this.max!)\n }\n return undefined\n }\n\n render() {\n const display = this.displayValue\n const placeholder = this.placeholder || this.localize.term('placeholder')\n const anchorId = `${this.dateRangePickerId}-anchor`\n const popoutId = `${this.dateRangePickerId}-popout`\n const headerId = `${this.dateRangePickerId}-header`\n // Naming resolved by the FieldControlMixin getters (field context in a field,\n // built-in label standalone, or host aria-* fallback). Light DOM, so the\n // aria-labelledby IDREF resolves.\n const ariaLabel = this.controlAriaLabel\n const ariaLabelledby = this.controlAriaLabelledby\n const ariaDescribedby = this.controlAriaDescribedby\n const activePreset = this.activePresetId\n\n // Inline: render the presets + calendar + actions directly, with no trigger\n // or popout.\n if (this.inline) {\n return html`\n ${this.renderLabel()}\n <div\n class=\"n-drp\"\n id=${anchorId}\n aria-label=${ifDefined(ariaLabel)}\n aria-labelledby=${ifDefined(ariaLabelledby)}\n aria-describedby=${ifDefined(ariaDescribedby)}\n ?inert=${this.effectiveDisabled || this.readonly}\n aria-disabled=${this.effectiveDisabled ? 'true' : nothing}\n >\n ${this.renderBody(activePreset)}\n </div>\n ${this.renderError()}\n ${this.isHintBelow ? this.renderHint() : nothing}\n `\n }\n\n return html`\n <div class=\"n-drp\" id=${anchorId}>\n ${this.customTrigger\n ? this.customTrigger\n : html`\n <nord-input\n class=${classMap({ 'n-drp-toggle': true, 'is-placeholder': !display })}\n type=\"button\"\n size=${this.size}\n id=${`${this.dateRangePickerId}-input`}\n value=${display || placeholder}\n label=${this.insideField ? nothing : ifDefined(this.label)}\n hint=${this.insideField ? nothing : ifDefined(this.hint)}\n error=${this.insideField ? nothing : cond(this.error || this.internalError, this.error || this.internalError)}\n placeholder=${ifDefined(placeholder)}\n ?disabled=${this.effectiveDisabled}\n ?required=${this.required}\n ?readonly=${this.readonly}\n ?hint-below=${this.hintBelow}\n ?hide-label=${this.insideField || this.hideLabel}\n aria-haspopup=\"dialog\"\n aria-controls=${popoutId}\n aria-expanded=${this.open ? 'true' : 'false'}\n aria-label=${ifDefined(ariaLabel)}\n aria-describedby=${ifDefined(ariaDescribedby)}\n aria-invalid=${ifDefined(this.controlAriaInvalid)}\n @click=${this.handleTriggerClick}\n @focus=${this.handleFocus}\n @blur=${this.handleBlur}\n ${ref(this.focusableRef)}\n >\n ${this.insideField || this.hintSlot.isEmpty ? nothing : html`<slot name=\"hint\" slot=\"hint\"></slot>`}\n ${this.insideField || this.labelSlot.isEmpty ? nothing : html`<slot name=\"label\" slot=\"label\"></slot>`}\n <nord-button\n slot=\"end\"\n class=\"n-drp-toggle-button\"\n size=${this.size}\n ?disabled=${this.effectiveDisabled || this.readonly}\n aria-controls=${popoutId}\n type=\"button\"\n >\n <nord-icon name=\"interface-calendar\"></nord-icon>\n <nord-visually-hidden>${this.localize.term('buttonLabel')}</nord-visually-hidden>\n </nord-button>\n </nord-input>\n `}\n\n <nord-popout\n id=${popoutId}\n controlled\n anchor=${anchorId}\n align=\"start\"\n position=\"block-end\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=${headerId}\n @open=${this.openState.onPopoutOpen}\n @close=${this.openState.onPopoutClose}\n >\n <div class=\"n-drp-popout\">\n <div class=\"n-drp-popout-header\">\n <span class=\"n-drp-heading\" id=${headerId}>${this.localize.term('modalHeading')}</span>\n <button\n type=\"button\"\n class=\"n-drp-close\"\n aria-label=${this.localize.term('closeLabel')}\n @click=${() => this.hide(true)}\n >\n <nord-icon name=\"interface-close-small\"></nord-icon>\n </button>\n </div>\n\n ${this.renderBody(activePreset)}\n </div>\n </nord-popout>\n </div>\n `\n }\n\n /** The presets + calendar + actions shared by the popout and inline layouts. */\n private renderBody(activePreset: string | undefined) {\n const actionSize = this.isNarrow ? 's' : 'm'\n\n return html`\n <div class=${classMap({ 'n-drp-body': true, 'is-narrow': this.isNarrow })}>\n ${this.hidePresets || this.presetGroups.length === 0\n ? nothing\n : this.isNarrow\n ? this.renderPresetsCollapsed(activePreset)\n : this.renderPresetsList(activePreset)}\n\n <div class=\"n-drp-calendar\">\n <nord-calendar\n range\n expand\n months=${this.isNarrow ? 1 : 2}\n range-start=${this.pendingStart}\n range-end=${this.pendingEnd}\n min=${ifDefined(this.min)}\n max=${ifDefined(this.max)}\n today=${ifDefined(this.today)}\n .firstDayOfWeek=${this.firstDayOfWeek}\n .isDateDisabled=${this.isDateDisabled}\n .isDateHighlighted=${this.isDateHighlighted}\n @range-change=${this.handleRangeChange}\n ></nord-calendar>\n </div>\n </div>\n\n <div class=\"n-drp-footer\">\n <nord-button type=\"button\" size=${actionSize} variant=\"plain\" @click=${this.handleClear}>\n ${this.localize.term('clearLabel')}\n </nord-button>\n <div class=\"n-drp-footer-end\">\n ${this.pendingRangeLabel ? html`<span class=\"n-drp-period\">${this.pendingRangeLabel}</span>` : nothing}\n ${this.inline\n ? nothing\n : html`\n <nord-button type=\"button\" size=${actionSize} @click=${() => this.hide(true)}>\n ${this.localize.term('cancelLabel')}\n </nord-button>\n `}\n <nord-button\n type=\"button\"\n size=${actionSize}\n variant=\"primary\"\n ?disabled=${!this.pendingStart || !this.pendingEnd}\n @click=${this.handleApply}\n >\n ${this.localize.term('applyLabel')}\n </nord-button>\n </div>\n </div>\n `\n }\n\n /** A single preset row. */\n private renderPreset(preset: Preset, activePreset: string | undefined) {\n return html`\n <li>\n <button\n type=\"button\"\n class=${classMap({ 'n-drp-preset': true, 'is-active': preset.id === activePreset })}\n aria-pressed=${preset.id === activePreset ? 'true' : 'false'}\n @click=${() => this.handlePresetClick(preset)}\n >\n ${preset.label}\n </button>\n </li>\n `\n }\n\n /** The presets bucketed into one `<ul>` per divider group. */\n private renderPresetGroups(activePreset: string | undefined) {\n return this.presetGroups.map(\n group => html`\n <ul class=\"n-drp-preset-group\">\n ${group.map(preset => this.renderPreset(preset, activePreset))}\n </ul>\n `,\n )\n }\n\n /** Wide layout: the grouped presets shown as a list beside the calendar. */\n private renderPresetsList(activePreset: string | undefined) {\n return html`\n <div class=\"n-drp-presets\" role=\"group\" aria-label=${this.localize.term('presetsLabel')}>\n ${this.renderPresetGroups(activePreset)}\n </div>\n `\n }\n\n /** Narrow layout: the presets collapse into a dropdown button + popout. */\n private renderPresetsCollapsed(activePreset: string | undefined) {\n const popoutId = `${this.dateRangePickerId}-presets`\n const activeLabel = this.visiblePresets.find(preset => preset.id === activePreset)?.label\n\n return html`\n <div class=\"n-drp-presets-collapsed\">\n <nord-button\n type=\"button\"\n size=\"s\"\n expand\n aria-haspopup=\"true\"\n aria-controls=${popoutId}\n aria-expanded=${this.presetsOpen ? 'true' : 'false'}\n >\n ${activeLabel ?? this.localize.term('presetsCollapsedLabel')}\n <nord-icon slot=\"end\" name=\"interface-dropdown-small\"></nord-icon>\n </nord-button>\n\n <nord-popout\n id=${popoutId}\n always-floating\n expand\n position=\"block-end\"\n ?open=${this.presetsOpen}\n @open=${() => (this.presetsOpen = true)}\n @close=${() => (this.presetsOpen = false)}\n >\n <div class=\"n-drp-presets-menu\" role=\"group\" aria-label=${this.localize.term('presetsLabel')}>\n ${this.renderPresetGroups(activePreset)}\n </div>\n </nord-popout>\n </div>\n `\n }\n\n private handleFocus = () => {\n this.dispatchEvent(new NordEvent('focus'))\n }\n\n private handleBlur = () => {\n this.dispatchEvent(new NordEvent('blur'))\n }\n\n private handlePresetClick(preset: Preset) {\n if (this.disabled || this.readonly) {\n return\n }\n const [start, end] = preset.resolve(this.getToday())\n this.pendingStart = printISODate(start)\n this.pendingEnd = printISODate(end)\n this.emitInput()\n // In the collapsed (narrow) layout the presets live in their own popout;\n // close it once a choice is made.\n this.presetsOpen = false\n }\n\n // The calendar owns the two-click range selection and hover preview across its\n // months; it fires `range-change` once a complete range is picked.\n private handleRangeChange = (e: DateRangeSelectEvent) => {\n e.stopPropagation()\n if (this.disabled || this.readonly) {\n return\n }\n this.pendingStart = printISODate(e.start)\n this.pendingEnd = printISODate(e.end)\n this.emitInput()\n }\n\n private emitInput() {\n this.dispatchEvent(\n new DateRangeChangeEvent('input', {\n value: joinInterval(this.pendingStart, this.pendingEnd),\n startDate: this.pendingStart,\n endDate: this.pendingEnd,\n }),\n )\n }\n\n private handleApply = () => {\n if (this.disabled || this.readonly || !this.pendingStart || !this.pendingEnd) {\n return\n }\n this.commit(this.pendingStart, this.pendingEnd)\n this.hide(true)\n }\n\n private handleClear = () => {\n if (this.disabled || this.readonly) {\n return\n }\n this.pendingStart = ''\n this.pendingEnd = ''\n this.commit('', '')\n this.hide(true)\n }\n\n /** Commits a range to `value`, syncs the parts, and fires `change`. */\n private commit(start: string, end: string) {\n this.value = joinInterval(start, end)\n this.dispatchEvent(\n new DateRangeChangeEvent('change', {\n value: this.value,\n startDate: start,\n endDate: end,\n }),\n )\n }\n\n // The trigger drives `open` (the source of truth); the OpenStateController then\n // drives the popout's show()/hide(), syncs `open` back from the popout's own\n // events, emits the single canonical open/close, and rejects opening while the\n // picker is disabled/read-only (including via the popout's auto-wired click on\n // a slotted custom trigger, which onPopoutOpen rejects when inert).\n private handleTriggerClick = () => {\n // Resolve narrow/wide synchronously so the popout opens with the right\n // number of months (the ResizeObserver fires too late for the first open).\n this.measureNarrow()\n this.openState.toggle()\n }\n\n /**\n * Open the picker programmatically.\n */\n show() {\n this.measureNarrow()\n this.openState.show()\n }\n\n /**\n * Close the picker programmatically.\n * @param moveFocusToToggle Move focus back to the trigger after closing.\n */\n hide(moveFocusToToggle = false) {\n // The controller always closes the popout with `hide(false)` (no focus\n // restore), so move focus back to the trigger here when asked — covering\n // both the built-in button and a slotted custom trigger.\n if (moveFocusToToggle) {\n (this.customTrigger ?? this.toggle)?.focus()\n }\n this.openState.hide()\n }\n\n /**\n * Move focus to the picker's trigger.\n */\n focus(options?: FocusOptions) {\n this.toggle?.focus(options)\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-date-range-picker': DateRangePicker\n }\n}\n"],"names":["Icon","registerIcon","calendarIcon","closeIcon","dropdownIcon","dateRangePickerCount","isDateDisabled","isDateHighlighted","PRESET_GROUP_ORDER","joinInterval","start","end","DateRangePicker","DraftComponentMixin","SizeMixin","FormAssociatedMixin","ReadonlyMixin","InputMixin","FocusableMixin","LitElement","constructor","this","dateRangePickerId","inputId","localize","LocalizeController","onLangChange","createDateFormatters","openState","OpenStateController","isOpen","open","setOpen","popout","isInert","disabled","readonly","onOpen","pendingStart","startDate","pendingEnd","endDate","_a","calendar","updateComplete","then","focus","target","value","firstDayOfWeek","DaysOfWeek","Monday","hidePresets","inline","isNarrow","presetsOpen","resizeObserver","ResizeObserver","measureNarrow","syncPresetsInlineSize","handleViewportResize","customTrigger","syncingFromValue","boundForm","handleFormData","e","startName","endName","formData","append","name","handleFocus","dispatchEvent","NordEvent","handleBlur","handleRangeChange","stopPropagation","printISODate","emitInput","handleApply","commit","hide","handleClear","handleTriggerClick","toggle","labelFocusOnly","width","window","innerWidth","rootFontSize","Number","parseFloat","getComputedStyle","document","documentElement","fontSize","DateRangePicker_1","narrowThresholdRem","collapsed","renderRoot","querySelector","style","setProperty","clientWidth","valueAsDateRange","parseISODate","undefined","range","connectedCallback","super","injectLightDomStyles","syncFormListener","observe","addEventListener","disconnectedCallback","removeEventListener","disconnect","createRenderRoot","ownInvalid","Boolean","error","internalError","firstUpdated","changed","updated","wireCustomTrigger","trigger","popoutId","setAttribute","form","_b","handleValueObserve","split","splitInterval","validateBounds","handlePartObserve","formValue","presetCatalogue","t","fdow","currentYear","getToday","getFullYear","lastYear","presets","id","group","label","term","resolve","today","y","addDays","thisWeekStart","startOfWeek","lastMonthEnd","startOfMonth","addMonths","lastQuarterEnd","startOfQuarter","prev","setYear","startOfYear","year","quarter","push","getQuarterRange","available","isQuarterCompleted","visiblePresets","min","max","allowed","Set","filter","preset","has","getTime","presetGroups","visible","map","length","Date","activePresetId","dateFormat","Intl","DateTimeFormat","resolvedLang","day","month","displayValue","sep","format","pendingRangeLabel","minDate","maxDate","render","display","placeholder","anchorId","headerId","ariaLabel","controlAriaLabel","ariaLabelledby","controlAriaLabelledby","ariaDescribedby","controlAriaDescribedby","activePreset","html","renderLabel","ifDefined","effectiveDisabled","nothing","renderBody","renderError","isHintBelow","renderHint","classMap","size","insideField","hint","cond","required","hintBelow","hideLabel","controlAriaInvalid","ref","focusableRef","hintSlot","isEmpty","labelSlot","onPopoutOpen","onPopoutClose","actionSize","renderPresetsCollapsed","renderPresetsList","renderPreset","handlePresetClick","renderPresetGroups","activeLabel","find","DateRangeChangeEvent","show","moveFocusToToggle","options","__decorate","query","prototype","property","reflect","attribute","type","state","customElement"],"mappings":"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"}
1
+ {"version":3,"file":"DateRangePicker.js","sources":["../src/date-range-picker/DateRangePicker.ts"],"sourcesContent":["import type { PropertyValues } from 'lit'\nimport type Calendar from '../calendar/Calendar.js'\nimport type { DatePredicate } from '../calendar/Calendar.js'\nimport type { DateRangeSelectEvent } from '../calendar/DateRangeSelectEvent.js'\n\nimport * as calendarIcon from '@nordhealth/icons/lib/assets/interface-calendar.js'\nimport * as closeIcon from '@nordhealth/icons/lib/assets/interface-close-small.js'\nimport * as dropdownIcon from '@nordhealth/icons/lib/assets/interface-dropdown-small.js'\nimport { html, LitElement, nothing } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { ref } from 'lit/directives/ref.js'\n\nimport { OpenStateController } from '../common/controllers/OpenStateController.js'\nimport { addDays, addMonths, DaysOfWeek, getQuarterRange, isQuarterCompleted, parseISODate, printISODate, setYear, startOfMonth, startOfQuarter, startOfWeek, startOfYear } from '../common/dates.js'\nimport { observe } from '../common/decorators/observe.js'\nimport { cond } from '../common/directives/cond.js'\nimport { NordEvent } from '../common/events.js'\nimport { injectLightDomStyles } from '../common/light-dom-styles.js'\nimport { DraftComponentMixin } from '../common/mixins/DraftComponentMixin.js'\nimport { FocusableMixin } from '../common/mixins/FocusableMixin.js'\nimport { FormAssociatedMixin } from '../common/mixins/FormAssociatedMixin.js'\nimport { InputMixin } from '../common/mixins/InputMixin.js'\nimport { ReadonlyMixin } from '../common/mixins/ReadonlyMixin.js'\nimport { SizeMixin } from '../common/mixins/SizeMixin.js'\nimport Icon from '../icon/Icon.js'\nimport { LocalizeController } from '../localization/LocalizeController.js'\nimport { DateRangeChangeEvent } from './DateRangeChangeEvent.js'\nimport style from './DateRangePicker.css'\nimport '../button/Button.js'\nimport '../input/Input.js'\nimport '../calendar/Calendar.js'\nimport '../popout/Popout.js'\nimport '../stack/Stack.js'\nimport '../visually-hidden/VisuallyHidden.js'\n\nIcon.registerIcon(calendarIcon)\nIcon.registerIcon(closeIcon)\nIcon.registerIcon(dropdownIcon)\n\n/** Per-instance counter so light-DOM ids stay unique across instances. */\nlet dateRangePickerCount = 1\n\n/** Default calendar predicates: nothing disabled, nothing highlighted. */\nconst isDateDisabled: DatePredicate = () => false\nconst isDateHighlighted = () => false\n\n/** A built-in preset row, resolved against \"today\" each time the popout opens. */\ninterface Preset {\n /** Stable key for tracking the active preset, and for the `presets` subset. */\n id: string\n /** Which divider group this preset belongs to (presets are grouped in order). */\n group: string\n /** Localized, human-readable label. */\n label: string\n /** Resolves the preset to an inclusive `[start, end]` relative to `today`. */\n resolve: (today: Date) => [Date, Date]\n /**\n * Optional gate (e.g. hide a current-year quarter that hasn't finished yet).\n * When omitted the preset is always available.\n */\n available?: (today: Date) => boolean\n}\n\n/** Order of the divider groups in the rendered preset list. */\nconst PRESET_GROUP_ORDER = ['today', 'lastDays', 'lastPeriod', 'currentPeriod', 'quarters'] as const\n\n/** Splits an interval string `YYYY-MM-DD/YYYY-MM-DD` into its two ISO parts. */\nfunction splitInterval(value: string): [string, string] {\n if (!value) {\n return ['', '']\n }\n const [start = '', end = ''] = value.split('/')\n return [start, end]\n}\n\n/** Joins two ISO parts into an interval string; returns `\"\"` if either is missing. */\nfunction joinInterval(start: string, end: string): string {\n return start && end ? `${start}/${end}` : ''\n}\n\n/**\n * Date Range Picker lets people choose a start and end date as a single range,\n * either from a built-in list of presets (Today, Last 7 days, This month, …) or\n * from a range calendar. It is a control only — compose it inside a\n * [Field](/components/field/) for a label, hint or error, like a native input.\n *\n * The committed value is an ISO-8601 interval string `YYYY-MM-DD/YYYY-MM-DD`;\n * the convenience `start-date` / `end-date` props and the `valueAsDateRange`\n * getter/setter stay in sync with it. Selecting in the popout builds a *pending*\n * range; **Apply** commits it (firing `change`), **Cancel** reverts to the last\n * committed value, and **Clear** empties it.\n *\n * @status draft\n * @category form\n * @lightDom true\n *\n * @fires {DateRangeChangeEvent} change - Dispatched when the committed range changes (Apply or Clear).\n * @fires {DateRangeChangeEvent} input - Dispatched live as the pending range changes inside the popout.\n * @fires {NordEvent} open - Dispatched when the popout is opened.\n * @fires {NordEvent} close - Dispatched when the popout is closed.\n *\n * @slot trigger - Optional custom trigger element (e.g. a filter chip or a `nord-button`) that opens the picker. Replaces the built-in trigger button when provided.\n *\n * @localization buttonLabel - Accessible label for the trigger button.\n * @localization placeholder - Placeholder shown in the trigger when no range is selected.\n * @localization modalHeading - Heading shown above the calendar in the popout.\n * @localization closeLabel - Accessible label for the close button.\n * @localization applyLabel - Label for the Apply button.\n * @localization cancelLabel - Label for the Cancel button.\n * @localization clearLabel - Label for the Clear button.\n * @localization presetsLabel - Accessible label for the preset list.\n * @localization presetsCollapsedLabel - Label for the collapsed preset dropdown (narrow widths).\n * @localization rangeSeparator - Character shown between the start and end dates in the trigger.\n * @localization dateOutOfMinBound - Error message shown when the range starts before the minimum date.\n * @localization dateOutOfMaxBound - Error message shown when the range ends after the maximum date.\n * @localization presetToday - Label for the \"Today\" preset.\n * @localization presetYesterday - Label for the \"Yesterday\" preset.\n * @localization presetLastDays - Label for the \"Last X days\" presets.\n * @localization presetLastMonths - Label for the \"Last X months\" presets.\n * @localization presetThisMonth - Label for the \"This month\" preset.\n * @localization presetLastWeek - Label for the \"Last week\" preset.\n * @localization presetLastMonth - Label for the \"Last month\" preset.\n * @localization presetLastQuarter - Label for the \"Last quarter\" preset.\n * @localization presetLastYear - Label for the \"Last year\" preset.\n * @localization presetCurrentWeek - Label for the \"Current week\" preset.\n * @localization presetCurrentMonth - Label for the \"Current month\" preset.\n * @localization presetCurrentQuarter - Label for the \"Current quarter\" preset.\n * @localization presetCurrentYear - Label for the \"Current year\" preset.\n * @localization presetQuarter - Label for a specific calendar quarter, e.g. \"Q3 2025\".\n *\n * @cssprop [--n-date-range-picker-trigger-min-inline-size=14rem] - Controls the minimum inline size of the trigger.\n * @cssprop [--n-date-range-picker-popout-inline-size] - Controls the inline size of the popout content.\n */\n@customElement('nord-date-range-picker')\nexport default class DateRangePicker extends DraftComponentMixin(\n SizeMixin(FormAssociatedMixin(ReadonlyMixin(InputMixin(FocusableMixin(LitElement))))),\n) {\n /** Stable, unique id base for the light-DOM ARIA wiring of this instance. */\n private dateRangePickerId = `nord-date-range-picker-${dateRangePickerCount++}`\n\n // The built-in `<label for>` (from FieldControlMixin) must point at the real\n // focusable trigger, so override the mixin's default id with the trigger's id.\n protected override inputId = `${this.dateRangePickerId}-input`\n\n // The trigger is a button that opens the popup on click, so a label click\n // should focus it (with the ring) rather than open it — keyboard opens it.\n protected override get labelFocusOnly() {\n return true\n }\n\n @query('nord-calendar', true) private calendar?: Calendar\n @query('.n-drp-toggle', true) private toggle?: HTMLElement\n @query('nord-popout', true) private popout?: HTMLElement & {\n show: () => Promise<unknown>\n hide: (moveFocusToButton?: boolean) => Promise<unknown>\n }\n\n private localize = new LocalizeController<'nord-date-range-picker'>(this, {\n onLangChange: () => this.createDateFormatters(),\n })\n\n // Coordinates `open` with the popout: `open` is the source of truth (it drives\n // popout.show()/hide()), the popout's own events sync `open` back, and one\n // canonical open/close is emitted. Opening is rejected while disabled/read-only.\n private openState = new OpenStateController(this, {\n isOpen: () => this.open,\n setOpen: (open) => { this.open = open },\n popout: () => this.popout,\n isInert: () => this.disabled || this.readonly,\n onOpen: () => {\n // Seed the pending selection from the committed value on every open, so an\n // abandoned (cancelled) pending range never leaks across opens, then move\n // focus into the calendar.\n this.pendingStart = this.startDate\n this.pendingEnd = this.endDate\n void this.calendar?.updateComplete.then(() => this.calendar?.focus({ target: 'day' }))\n },\n })\n\n private dateFormat!: Intl.DateTimeFormat\n\n /**\n * The committed value as an ISO-8601 interval string `YYYY-MM-DD/YYYY-MM-DD`.\n * An empty string means no range is committed.\n */\n @property() value = ''\n\n /**\n * Convenience accessor for the committed start date, in ISO-8601 format. Kept\n * in sync with `value` and `end-date`.\n */\n @property({ reflect: true, attribute: 'start-date' }) startDate = ''\n\n /**\n * Convenience accessor for the committed end date, in ISO-8601 format. Kept in\n * sync with `value` and `start-date`.\n */\n @property({ reflect: true, attribute: 'end-date' }) endDate = ''\n\n /**\n * Controls whether the popout is open.\n */\n @property({ type: Boolean, reflect: true }) open = false\n\n /**\n * Minimum date allowed to be picked, in ISO-8601 format: YYYY-MM-DD.\n */\n @property({ reflect: true }) min?: string\n\n /**\n * Maximum date allowed to be picked, in ISO-8601 format: YYYY-MM-DD.\n */\n @property({ reflect: true }) max?: string\n\n /**\n * The date that is considered today, in ISO-8601 format. Presets resolve\n * relative to this; if unset, the user's current local date is used.\n */\n @property({ reflect: true }) today?: string\n\n /**\n * Which day is considered the first day of the week. `0` for Sunday, `1` for\n * Monday, etc. Default is Monday.\n */\n @property({ reflect: true, attribute: 'first-day-of-week', type: Number }) firstDayOfWeek: DaysOfWeek\n = DaysOfWeek.Monday\n\n /**\n * Controls which days are disabled and therefore disallowed.\n * For example, this can be used to disallow selection of weekends.\n */\n @property({ attribute: false }) isDateDisabled: DatePredicate = isDateDisabled\n\n /**\n * Controls which days are highlighted with a small indicator.\n * Returning `false` will not show an indicator.\n * Returning `true` will show the indicator, but without an accessible label. Therefore\n * Returning a string will show the indicator, and use the string as accessible label.\n * It is recommended to return a string rather than `true` whenever possible.\n */\n @property({ attribute: false }) isDateHighlighted: (date: Date) => string | boolean = isDateHighlighted\n\n /**\n * Hides the built-in list of preset ranges, leaving only the calendar.\n */\n @property({ reflect: true, type: Boolean, attribute: 'hide-presets' }) hidePresets = false\n\n /**\n * Restricts the preset list to this subset of preset ids (in their natural\n * group order). When unset, the full catalogue is shown. Ids:\n * `today`, `yesterday`, `last-7`/`last-30`/`last-60`/`last-90`/`last-365`,\n * `last-week`, `last-month`, `last-6-months`, `last-quarter`, `last-year`,\n * `last-12-months`, `current-week`/`current-month`/`current-quarter`/`current-year`,\n * and quarter ids `q-<year>-<1-4>`.\n */\n @property({ attribute: false }) presets?: string[]\n\n /**\n * Render the picker inline — the presets, calendar and Apply/Cancel/Clear are\n * always visible, with no trigger button or popout. Use it when the picker\n * lives directly on the page (e.g. in a form) rather than behind a trigger.\n */\n @property({ reflect: true, type: Boolean }) inline = false\n\n /**\n * The name used to submit the **start** date as its own form field. When both\n * `start-name` and `end-name` are set, the picker submits two fields\n * (`start-name`=startDate, `end-name`=endDate) instead of the single `name`.\n */\n @property({ reflect: true, attribute: 'start-name' }) startName?: string\n\n /**\n * The name used to submit the **end** date as its own form field. See\n * `start-name`.\n */\n @property({ reflect: true, attribute: 'end-name' }) endName?: string\n\n /**\n * Validation error message, set automatically when the committed range falls\n * outside min/max.\n */\n @property({ attribute: false }) internalError?: string\n\n /** The pending range inside the popout, before Apply commits it. */\n @state() private pendingStart = ''\n @state() private pendingEnd = ''\n\n /** Whether the popout shows a single month (narrow) rather than two. */\n @state() private isNarrow = false\n\n /** Whether the collapsed preset dropdown (narrow layout) is open. */\n @state() private presetsOpen = false\n\n /**\n * Below this viewport width (in `rem`) the picker collapses to a single month\n * with stacked presets. Measured against the viewport — NOT the host — because\n * the popout floats (`position: fixed`) and is free to be as wide as the\n * viewport allows, regardless of the trigger's own width. A `resize` listener\n * is required (rather than a CSS media query) because the month count is a\n * `nord-calendar` prop in shadow DOM that CSS cannot reach.\n *\n * Two months + presets need ~900px to render without overflowing, so the\n * threshold sits a little above that. Expressed in `rem` (resolved against the\n * root font size on each measurement) so it scales with zoom / font size, the\n * same way the calendar's own `rem`-based sizing does.\n */\n private static readonly narrowThresholdRem = 57.5\n\n // Keeps the collapsed-presets popout width in sync with the trigger as the host\n // resizes; the narrow/wide decision itself tracks the viewport (see below).\n private resizeObserver = new ResizeObserver(() => {\n this.measureNarrow()\n this.syncPresetsInlineSize()\n })\n\n private handleViewportResize = () => {\n this.measureNarrow()\n }\n\n /**\n * Sets `isNarrow` from the viewport width. The `resize` listener drives this for\n * live changes, but it fires asynchronously, so it's also called synchronously\n * before opening the popout so the first render already shows the right number\n * of months. Ignores 0-width measurements (detached/hidden).\n */\n private measureNarrow(width: number = window.innerWidth) {\n if (width > 0) {\n const rootFontSize = Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 16\n this.isNarrow = width < DateRangePicker.narrowThresholdRem * rootFontSize\n }\n }\n\n /**\n * Mirror the collapsed-presets trigger width into a custom property so the\n * presets popout matches it (the popout floats `position: fixed`, so a `%`\n * width can't reference the trigger). Mirrors the combobox dropdown approach.\n */\n private syncPresetsInlineSize() {\n const collapsed = this.renderRoot.querySelector('.n-drp-presets-collapsed')\n if (collapsed) {\n this.style.setProperty('--_n-drp-presets-inline-size', `${collapsed.clientWidth}px`)\n }\n }\n\n /**\n * A user-supplied trigger element (`slot=\"trigger\"`), captured from the light\n * DOM before the first render so it can be re-inserted into the rendered\n * structure. When present it replaces the built-in button; `null` uses the\n * default trigger.\n */\n private customTrigger: HTMLElement | null = null\n\n /** The interval string was the source of the most recent sync (avoids loops). */\n private syncingFromValue = false\n\n get valueAsDateRange(): [Date, Date] | undefined {\n const start = parseISODate(this.startDate)\n const end = parseISODate(this.endDate)\n return start && end ? [start, end] : undefined\n }\n\n /**\n * Get/set the committed range as a `[Date, Date]` tuple. Setting `undefined`\n * clears the range.\n */\n set valueAsDateRange(range: [Date, Date] | undefined) {\n if (!range) {\n this.value = ''\n return\n }\n const [start, end] = range\n this.value = joinInterval(printISODate(start), printISODate(end))\n }\n\n /** The form the `formdata` listener is currently attached to, if any. */\n private boundForm: HTMLFormElement | null = null\n\n connectedCallback() {\n super.connectedCallback()\n injectLightDomStyles(this, style)\n this.syncFormListener()\n this.resizeObserver.observe(this)\n window.addEventListener('resize', this.handleViewportResize)\n // Capture a custom trigger (`slot=\"trigger\"`) before the first render owns\n // the light DOM; it is re-inserted into the rendered structure by `render`.\n this.customTrigger = this.querySelector<HTMLElement>(':scope > [slot=\"trigger\"]')\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.boundForm?.removeEventListener('formdata', this.handleFormData)\n this.boundForm = null\n this.resizeObserver.disconnect()\n window.removeEventListener('resize', this.handleViewportResize)\n }\n\n // Render in the light DOM so the control participates in the document tree.\n protected createRenderRoot() {\n return this\n }\n\n // The control's own invalid state for the field context: a built-in/internal error.\n protected override get ownInvalid() {\n return Boolean(this.error || this.internalError) || super.ownInvalid\n }\n\n protected firstUpdated(changed: PropertyValues) {\n super.firstUpdated(changed)\n // Seed the inline pending selection from an initial value.\n if (this.inline) {\n this.pendingStart = this.startDate\n this.pendingEnd = this.endDate\n }\n }\n\n protected updated(changed: PropertyValues) {\n super.updated(changed)\n // The associated form can change after `form` is set or on reconnection.\n this.syncFormListener()\n this.wireCustomTrigger()\n // Keep the presets popout matched to the (re-rendered) collapsed trigger.\n this.syncPresetsInlineSize()\n }\n\n /**\n * Give a slotted custom trigger the same ARIA wiring the built-in button has,\n * so `nord-popout` auto-attaches its open/close click via `aria-controls` and\n * assistive tech sees the dialog relationship and expanded state.\n */\n private wireCustomTrigger() {\n const trigger = this.customTrigger\n if (!trigger) {\n return\n }\n const popoutId = `${this.dateRangePickerId}-popout`\n trigger.setAttribute('aria-controls', popoutId)\n trigger.setAttribute('aria-haspopup', 'dialog')\n trigger.setAttribute('aria-expanded', this.open ? 'true' : 'false')\n // Drive `open` (the source of truth) from the trigger click, like the\n // built-in button's `@click`. `nord-popout` also auto-wires a click via\n // `aria-controls`, but show()/hide() are idempotent so the two coincide\n // harmlessly. The listener is added once (it's a no-op if already bound).\n trigger.removeEventListener('click', this.handleTriggerClick)\n trigger.addEventListener('click', this.handleTriggerClick)\n }\n\n /**\n * The control submits one OR two form fields (single interval, or separate\n * start/end), which `FormAssociatedMixin`'s single `FormDataController` can't\n * express, so listen for `formdata` directly and (re)bind to the active form.\n */\n private syncFormListener() {\n const form = this.form\n if (form === this.boundForm) {\n return\n }\n this.boundForm?.removeEventListener('formdata', this.handleFormData)\n this.boundForm = form\n this.boundForm?.addEventListener('formdata', this.handleFormData)\n }\n\n /**\n * Keep `value`, `start-date` and `end-date` consistent. The interval string is\n * the source of truth; whichever changed last drives the others.\n */\n @observe('value')\n protected handleValueObserve() {\n if (this.syncingFromValue) {\n return\n }\n this.syncingFromValue = true\n const [start, end] = splitInterval(this.value)\n this.startDate = start\n this.endDate = end\n this.internalError = this.validateBounds(start, end)\n this.syncingFromValue = false\n\n // Inline has no popout-open to seed the pending selection, so mirror the\n // committed value into it whenever it changes.\n if (this.inline) {\n this.pendingStart = start\n this.pendingEnd = end\n }\n }\n\n @observe('startDate')\n @observe('endDate')\n protected handlePartObserve() {\n if (this.syncingFromValue) {\n return\n }\n this.syncingFromValue = true\n this.value = joinInterval(this.startDate, this.endDate)\n this.internalError = this.validateBounds(this.startDate, this.endDate)\n this.syncingFromValue = false\n }\n\n /**\n * Suppress the inherited `FormDataController`. This control submits one OR two\n * fields depending on `start-name`/`end-name`, which a single controller can't\n * express, so `handleFormData` owns the entire submission instead. Returning\n * `undefined` here keeps the base controller from also appending `name`.\n */\n protected get formValue(): string | undefined {\n return undefined\n }\n\n private handleFormData = (e: FormDataEvent) => {\n if (this.disabled) {\n return\n }\n\n // Two-field mode: submit start and end under their own names.\n if (this.startName && this.endName) {\n if (this.startDate) {\n e.formData.append(this.startName, this.startDate)\n }\n if (this.endDate) {\n e.formData.append(this.endName, this.endDate)\n }\n return\n }\n\n // Single-field mode: submit the interval string under `name`.\n if (this.name && this.value) {\n e.formData.append(this.name, this.value)\n }\n }\n\n /**\n * The full catalogue of presets, resolved against the configured (or current)\n * \"today\". Date arithmetic mirrors NFE's `getPredefinedDateRange`: \"last N\n * days\" counts back `N` days from today; \"last N months\" are full calendar\n * months ending at the previous month-end; period/quarter presets use calendar\n * boundaries (first-day-of-week aware for weeks).\n */\n private get presetCatalogue(): Preset[] {\n const t = this.localize\n const fdow = this.firstDayOfWeek\n const currentYear = this.getToday().getFullYear()\n const lastYear = currentYear - 1\n\n const presets: Preset[] = [\n // today / yesterday\n { id: 'today', group: 'today', label: t.term('presetToday'), resolve: today => [today, today] },\n { id: 'yesterday', group: 'today', label: t.term('presetYesterday'), resolve: (today) => {\n const y = addDays(today, -1)\n return [y, y]\n } },\n\n // last N days (start = today − N, mirroring NFE)\n { id: 'last-7', group: 'lastDays', label: t.term('presetLastDays', 7), resolve: today => [addDays(today, -7), today] },\n { id: 'last-30', group: 'lastDays', label: t.term('presetLastDays', 30), resolve: today => [addDays(today, -30), today] },\n { id: 'last-60', group: 'lastDays', label: t.term('presetLastDays', 60), resolve: today => [addDays(today, -60), today] },\n { id: 'last-90', group: 'lastDays', label: t.term('presetLastDays', 90), resolve: today => [addDays(today, -90), today] },\n { id: 'last-365', group: 'lastDays', label: t.term('presetLastDays', 365), resolve: today => [addDays(today, -365), today] },\n\n // last calendar periods\n { id: 'last-week', group: 'lastPeriod', label: t.term('presetLastWeek'), resolve: (today) => {\n const thisWeekStart = startOfWeek(today, fdow)\n return [addDays(thisWeekStart, -7), addDays(thisWeekStart, -1)]\n } },\n { id: 'last-month', group: 'lastPeriod', label: t.term('presetLastMonth'), resolve: (today) => {\n const lastMonthEnd = addDays(startOfMonth(today), -1)\n return [startOfMonth(lastMonthEnd), lastMonthEnd]\n } },\n { id: 'last-6-months', group: 'lastPeriod', label: t.term('presetLastMonths', 6), resolve: (today) => {\n const end = addDays(startOfMonth(today), -1)\n return [startOfMonth(addMonths(end, -5)), end]\n } },\n { id: 'last-quarter', group: 'lastPeriod', label: t.term('presetLastQuarter'), resolve: (today) => {\n const lastQuarterEnd = addDays(startOfQuarter(today), -1)\n return [startOfQuarter(lastQuarterEnd), lastQuarterEnd]\n } },\n { id: 'last-year', group: 'lastPeriod', label: t.term('presetLastYear'), resolve: (today) => {\n const prev = setYear(today, today.getFullYear() - 1)\n return [startOfYear(prev), addDays(startOfYear(today), -1)]\n } },\n { id: 'last-12-months', group: 'lastPeriod', label: t.term('presetLastMonths', 12), resolve: (today) => {\n const end = addDays(startOfMonth(today), -1)\n return [startOfMonth(addMonths(end, -11)), end]\n } },\n\n // current calendar periods (start of period → today)\n { id: 'current-week', group: 'currentPeriod', label: t.term('presetCurrentWeek'), resolve: today => [startOfWeek(today, fdow), today] },\n { id: 'current-month', group: 'currentPeriod', label: t.term('presetCurrentMonth'), resolve: today => [startOfMonth(today), today] },\n { id: 'current-quarter', group: 'currentPeriod', label: t.term('presetCurrentQuarter'), resolve: today => [startOfQuarter(today), today] },\n { id: 'current-year', group: 'currentPeriod', label: t.term('presetCurrentYear'), resolve: today => [startOfYear(today), today] },\n ]\n\n // Explicit calendar quarters: Q4→Q1 of the current year (only those already\n // completed), then Q4→Q1 of last year.\n for (const year of [currentYear, lastYear]) {\n for (const quarter of [4, 3, 2, 1]) {\n presets.push({\n id: `q-${year}-${quarter}`,\n group: 'quarters',\n label: t.term('presetQuarter', quarter, year),\n resolve: () => getQuarterRange(quarter, year),\n available: year === currentYear ? today => isQuarterCompleted(quarter, today) : undefined,\n })\n }\n }\n\n return presets\n }\n\n /** The presets that should be shown, after subset/availability/min-max filters. */\n private get visiblePresets(): Preset[] {\n const today = this.getToday()\n const min = parseISODate(this.min || '')\n const max = parseISODate(this.max || '')\n\n let presets = this.presetCatalogue\n\n // Optional consumer-chosen subset, preserving catalogue order.\n if (this.presets) {\n const allowed = new Set(this.presets)\n presets = presets.filter(preset => allowed.has(preset.id))\n }\n\n return presets.filter((preset) => {\n if (preset.available && !preset.available(today)) {\n return false\n }\n // Drop presets whose resolved range falls outside min/max.\n const [start, end] = preset.resolve(today)\n if (min && start.getTime() < min.getTime()) {\n return false\n }\n if (max && end.getTime() > max.getTime()) {\n return false\n }\n return true\n })\n }\n\n /** The visible presets bucketed into their divider groups, in group order. */\n private get presetGroups(): Preset[][] {\n const visible = this.visiblePresets\n return PRESET_GROUP_ORDER\n .map(group => visible.filter(preset => preset.group === group))\n .filter(group => group.length > 0)\n }\n\n private getToday(): Date {\n return parseISODate(this.today || '') || new Date()\n }\n\n /** Which preset (if any) the pending selection currently matches. */\n private get activePresetId(): string | undefined {\n if (!this.pendingStart || !this.pendingEnd) {\n return undefined\n }\n const today = this.getToday()\n for (const preset of this.visiblePresets) {\n const [start, end] = preset.resolve(today)\n if (printISODate(start) === this.pendingStart && printISODate(end) === this.pendingEnd) {\n return preset.id\n }\n }\n return undefined\n }\n\n private createDateFormatters() {\n this.dateFormat = new Intl.DateTimeFormat(this.localize.resolvedLang, {\n day: 'numeric',\n month: 'short',\n year: 'numeric',\n })\n }\n\n /** The text shown in the trigger: the formatted range, or the placeholder. */\n private get displayValue(): string {\n const range = this.valueAsDateRange\n if (!range) {\n return ''\n }\n const [start, end] = range\n const sep = this.localize.term('rangeSeparator')\n return `${this.dateFormat.format(start)} ${sep} ${this.dateFormat.format(end)}`\n }\n\n /** The in-progress (pending) range formatted for the footer, or '' while empty. */\n private get pendingRangeLabel(): string {\n const start = parseISODate(this.pendingStart)\n if (!start) {\n return ''\n }\n const end = parseISODate(this.pendingEnd)\n const sep = this.localize.term('rangeSeparator')\n return end ? `${this.dateFormat.format(start)} ${sep} ${this.dateFormat.format(end)}` : this.dateFormat.format(start)\n }\n\n private validateBounds(start: string, end: string): string | undefined {\n const minDate = parseISODate(this.min || '')\n const maxDate = parseISODate(this.max || '')\n const startDate = parseISODate(start)\n const endDate = parseISODate(end)\n\n if (minDate && startDate && startDate < minDate) {\n return this.localize.term('dateOutOfMinBound', this.min!)\n }\n if (maxDate && endDate && endDate > maxDate) {\n return this.localize.term('dateOutOfMaxBound', this.max!)\n }\n return undefined\n }\n\n render() {\n const display = this.displayValue\n const placeholder = this.placeholder || this.localize.term('placeholder')\n const anchorId = `${this.dateRangePickerId}-anchor`\n const popoutId = `${this.dateRangePickerId}-popout`\n const headerId = `${this.dateRangePickerId}-header`\n // Naming resolved by the FieldControlMixin getters (field context in a field,\n // built-in label standalone, or host aria-* fallback). Light DOM, so the\n // aria-labelledby IDREF resolves.\n const ariaLabel = this.controlAriaLabel\n const ariaLabelledby = this.controlAriaLabelledby\n const ariaDescribedby = this.controlAriaDescribedby\n const activePreset = this.activePresetId\n\n // Inline: render the presets + calendar + actions directly, with no trigger\n // or popout.\n if (this.inline) {\n return html`\n ${this.renderLabel()}\n <div\n class=\"n-drp\"\n id=${anchorId}\n aria-label=${ifDefined(ariaLabel)}\n aria-labelledby=${ifDefined(ariaLabelledby)}\n aria-describedby=${ifDefined(ariaDescribedby)}\n ?inert=${this.effectiveDisabled || this.readonly}\n aria-disabled=${this.effectiveDisabled ? 'true' : nothing}\n >\n ${this.renderBody(activePreset)}\n </div>\n ${this.renderError()}\n ${this.isHintBelow ? this.renderHint() : nothing}\n `\n }\n\n return html`\n <div class=\"n-drp\" id=${anchorId}>\n ${this.customTrigger\n ? this.customTrigger\n : html`\n <nord-input\n class=${classMap({ 'n-drp-toggle': true, 'is-placeholder': !display })}\n type=\"button\"\n size=${this.size}\n id=${`${this.dateRangePickerId}-input`}\n value=${display || placeholder}\n label=${this.insideField ? nothing : ifDefined(this.label)}\n hint=${this.insideField ? nothing : ifDefined(this.hint)}\n error=${this.insideField ? nothing : cond(this.error || this.internalError, this.error || this.internalError)}\n placeholder=${ifDefined(placeholder)}\n ?disabled=${this.effectiveDisabled}\n ?required=${this.required}\n ?readonly=${this.readonly}\n ?hint-below=${this.hintBelow}\n ?hide-label=${this.insideField || this.hideLabel}\n aria-haspopup=\"dialog\"\n aria-controls=${popoutId}\n aria-expanded=${this.open ? 'true' : 'false'}\n aria-label=${ifDefined(ariaLabel)}\n aria-describedby=${ifDefined(ariaDescribedby)}\n aria-invalid=${ifDefined(this.controlAriaInvalid)}\n @click=${this.handleTriggerClick}\n @focus=${this.handleFocus}\n @blur=${this.handleBlur}\n ${ref(this.focusableRef)}\n >\n ${this.insideField || this.hintSlot.isEmpty ? nothing : html`<slot name=\"hint\" slot=\"hint\"></slot>`}\n ${this.insideField || this.labelSlot.isEmpty ? nothing : html`<slot name=\"label\" slot=\"label\"></slot>`}\n <nord-button\n slot=\"end\"\n class=\"n-drp-toggle-button\"\n size=${this.size}\n ?disabled=${this.effectiveDisabled || this.readonly}\n aria-controls=${popoutId}\n type=\"button\"\n >\n <nord-icon name=\"interface-calendar\"></nord-icon>\n <nord-visually-hidden>${this.localize.term('buttonLabel')}</nord-visually-hidden>\n </nord-button>\n </nord-input>\n `}\n\n <nord-popout\n id=${popoutId}\n controlled\n anchor=${anchorId}\n align=\"start\"\n position=\"block-end\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=${headerId}\n @open=${this.openState.onPopoutOpen}\n @close=${this.openState.onPopoutClose}\n >\n <div class=\"n-drp-popout\">\n <div class=\"n-drp-popout-header\">\n <span class=\"n-drp-heading\" id=${headerId}>${this.localize.term('modalHeading')}</span>\n <button\n type=\"button\"\n class=\"n-drp-close\"\n aria-label=${this.localize.term('closeLabel')}\n @click=${() => this.hide(true)}\n >\n <nord-icon name=\"interface-close-small\"></nord-icon>\n </button>\n </div>\n\n ${this.renderBody(activePreset)}\n </div>\n </nord-popout>\n </div>\n `\n }\n\n /** The presets + calendar + actions shared by the popout and inline layouts. */\n private renderBody(activePreset: string | undefined) {\n const actionSize = this.isNarrow ? 's' : 'm'\n\n return html`\n <div class=${classMap({ 'n-drp-body': true, 'is-narrow': this.isNarrow })}>\n ${this.hidePresets || this.presetGroups.length === 0\n ? nothing\n : this.isNarrow\n ? this.renderPresetsCollapsed(activePreset)\n : this.renderPresetsList(activePreset)}\n\n <div class=\"n-drp-calendar\">\n <nord-calendar\n range\n expand\n months=${this.isNarrow ? 1 : 2}\n range-start=${this.pendingStart}\n range-end=${this.pendingEnd}\n min=${ifDefined(this.min)}\n max=${ifDefined(this.max)}\n today=${ifDefined(this.today)}\n .firstDayOfWeek=${this.firstDayOfWeek}\n .isDateDisabled=${this.isDateDisabled}\n .isDateHighlighted=${this.isDateHighlighted}\n @range-change=${this.handleRangeChange}\n ></nord-calendar>\n </div>\n </div>\n\n <div class=\"n-drp-footer\">\n <nord-button type=\"button\" size=${actionSize} variant=\"plain\" @click=${this.handleClear}>\n ${this.localize.term('clearLabel')}\n </nord-button>\n <div class=\"n-drp-footer-end\">\n ${this.pendingRangeLabel ? html`<span class=\"n-drp-period\">${this.pendingRangeLabel}</span>` : nothing}\n ${this.inline\n ? nothing\n : html`\n <nord-button type=\"button\" size=${actionSize} @click=${() => this.hide(true)}>\n ${this.localize.term('cancelLabel')}\n </nord-button>\n `}\n <nord-button\n type=\"button\"\n size=${actionSize}\n variant=\"primary\"\n ?disabled=${!this.pendingStart || !this.pendingEnd}\n @click=${this.handleApply}\n >\n ${this.localize.term('applyLabel')}\n </nord-button>\n </div>\n </div>\n `\n }\n\n /** A single preset row. */\n private renderPreset(preset: Preset, activePreset: string | undefined) {\n return html`\n <li>\n <button\n type=\"button\"\n class=${classMap({ 'n-drp-preset': true, 'is-active': preset.id === activePreset })}\n aria-pressed=${preset.id === activePreset ? 'true' : 'false'}\n @click=${() => this.handlePresetClick(preset)}\n >\n ${preset.label}\n </button>\n </li>\n `\n }\n\n /** The presets bucketed into one `<ul>` per divider group. */\n private renderPresetGroups(activePreset: string | undefined) {\n return this.presetGroups.map(\n group => html`\n <ul class=\"n-drp-preset-group\">\n ${group.map(preset => this.renderPreset(preset, activePreset))}\n </ul>\n `,\n )\n }\n\n /** Wide layout: the grouped presets shown as a list beside the calendar. */\n private renderPresetsList(activePreset: string | undefined) {\n return html`\n <div class=\"n-drp-presets\" role=\"group\" aria-label=${this.localize.term('presetsLabel')}>\n ${this.renderPresetGroups(activePreset)}\n </div>\n `\n }\n\n /** Narrow layout: the presets collapse into a dropdown button + popout. */\n private renderPresetsCollapsed(activePreset: string | undefined) {\n const popoutId = `${this.dateRangePickerId}-presets`\n const activeLabel = this.visiblePresets.find(preset => preset.id === activePreset)?.label\n\n return html`\n <div class=\"n-drp-presets-collapsed\">\n <nord-button\n type=\"button\"\n size=\"s\"\n expand\n aria-haspopup=\"true\"\n aria-controls=${popoutId}\n aria-expanded=${this.presetsOpen ? 'true' : 'false'}\n >\n ${activeLabel ?? this.localize.term('presetsCollapsedLabel')}\n <nord-icon slot=\"end\" name=\"interface-dropdown-small\"></nord-icon>\n </nord-button>\n\n <nord-popout\n id=${popoutId}\n always-floating\n expand\n position=\"block-end\"\n ?open=${this.presetsOpen}\n @open=${() => (this.presetsOpen = true)}\n @close=${() => (this.presetsOpen = false)}\n >\n <div class=\"n-drp-presets-menu\" role=\"group\" aria-label=${this.localize.term('presetsLabel')}>\n ${this.renderPresetGroups(activePreset)}\n </div>\n </nord-popout>\n </div>\n `\n }\n\n private handleFocus = () => {\n this.dispatchEvent(new NordEvent('focus'))\n }\n\n private handleBlur = () => {\n this.dispatchEvent(new NordEvent('blur'))\n }\n\n private handlePresetClick(preset: Preset) {\n if (this.disabled || this.readonly) {\n return\n }\n const [start, end] = preset.resolve(this.getToday())\n this.pendingStart = printISODate(start)\n this.pendingEnd = printISODate(end)\n this.emitInput()\n // In the collapsed (narrow) layout the presets live in their own popout;\n // close it once a choice is made.\n this.presetsOpen = false\n }\n\n // The calendar owns the two-click range selection and hover preview across its\n // months; it fires `range-change` once a complete range is picked.\n private handleRangeChange = (e: DateRangeSelectEvent) => {\n e.stopPropagation()\n if (this.disabled || this.readonly) {\n return\n }\n this.pendingStart = printISODate(e.start)\n this.pendingEnd = printISODate(e.end)\n this.emitInput()\n }\n\n private emitInput() {\n this.dispatchEvent(\n new DateRangeChangeEvent('input', {\n value: joinInterval(this.pendingStart, this.pendingEnd),\n startDate: this.pendingStart,\n endDate: this.pendingEnd,\n }),\n )\n }\n\n private handleApply = () => {\n if (this.disabled || this.readonly || !this.pendingStart || !this.pendingEnd) {\n return\n }\n this.commit(this.pendingStart, this.pendingEnd)\n this.hide(true)\n }\n\n private handleClear = () => {\n if (this.disabled || this.readonly) {\n return\n }\n this.pendingStart = ''\n this.pendingEnd = ''\n this.commit('', '')\n this.hide(true)\n }\n\n /** Commits a range to `value`, syncs the parts, and fires `change`. */\n private commit(start: string, end: string) {\n this.value = joinInterval(start, end)\n this.dispatchEvent(\n new DateRangeChangeEvent('change', {\n value: this.value,\n startDate: start,\n endDate: end,\n }),\n )\n }\n\n // The trigger drives `open` (the source of truth); the OpenStateController then\n // drives the popout's show()/hide(), syncs `open` back from the popout's own\n // events, emits the single canonical open/close, and rejects opening while the\n // picker is disabled/read-only (including via the popout's auto-wired click on\n // a slotted custom trigger, which onPopoutOpen rejects when inert).\n private handleTriggerClick = () => {\n // Resolve narrow/wide synchronously so the popout opens with the right\n // number of months (the ResizeObserver fires too late for the first open).\n this.measureNarrow()\n this.openState.toggle()\n }\n\n /**\n * Open the picker programmatically.\n */\n show() {\n this.measureNarrow()\n this.openState.show()\n }\n\n /**\n * Close the picker programmatically.\n * @param moveFocusToToggle Move focus back to the trigger after closing.\n */\n hide(moveFocusToToggle = false) {\n // The controller always closes the popout with `hide(false)` (no focus\n // restore), so move focus back to the trigger here when asked — covering\n // both the built-in button and a slotted custom trigger.\n if (moveFocusToToggle) {\n (this.customTrigger ?? this.toggle)?.focus()\n }\n this.openState.hide()\n }\n\n /**\n * Move focus to the picker's trigger.\n */\n focus(options?: FocusOptions) {\n this.toggle?.focus(options)\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-date-range-picker': DateRangePicker\n }\n}\n"],"names":["Icon","registerIcon","calendarIcon","closeIcon","dropdownIcon","dateRangePickerCount","isDateDisabled","isDateHighlighted","PRESET_GROUP_ORDER","joinInterval","start","end","DateRangePicker","DraftComponentMixin","SizeMixin","FormAssociatedMixin","ReadonlyMixin","InputMixin","FocusableMixin","LitElement","constructor","this","dateRangePickerId","inputId","localize","LocalizeController","onLangChange","createDateFormatters","openState","OpenStateController","isOpen","open","setOpen","popout","isInert","disabled","readonly","onOpen","pendingStart","startDate","pendingEnd","endDate","_a","calendar","updateComplete","then","focus","target","value","firstDayOfWeek","DaysOfWeek","Monday","hidePresets","inline","isNarrow","presetsOpen","resizeObserver","ResizeObserver","measureNarrow","syncPresetsInlineSize","handleViewportResize","customTrigger","syncingFromValue","boundForm","handleFormData","e","startName","endName","formData","append","name","handleFocus","dispatchEvent","NordEvent","handleBlur","handleRangeChange","stopPropagation","printISODate","emitInput","handleApply","commit","hide","handleClear","handleTriggerClick","toggle","labelFocusOnly","width","window","innerWidth","rootFontSize","Number","parseFloat","getComputedStyle","document","documentElement","fontSize","DateRangePicker_1","narrowThresholdRem","collapsed","renderRoot","querySelector","style","setProperty","clientWidth","valueAsDateRange","parseISODate","undefined","range","connectedCallback","super","injectLightDomStyles","syncFormListener","observe","addEventListener","disconnectedCallback","removeEventListener","disconnect","createRenderRoot","ownInvalid","Boolean","error","internalError","firstUpdated","changed","updated","wireCustomTrigger","trigger","popoutId","setAttribute","form","_b","handleValueObserve","split","splitInterval","validateBounds","handlePartObserve","formValue","presetCatalogue","t","fdow","currentYear","getToday","getFullYear","lastYear","presets","id","group","label","term","resolve","today","y","addDays","thisWeekStart","startOfWeek","lastMonthEnd","startOfMonth","addMonths","lastQuarterEnd","startOfQuarter","prev","setYear","startOfYear","year","quarter","push","getQuarterRange","available","isQuarterCompleted","visiblePresets","min","max","allowed","Set","filter","preset","has","getTime","presetGroups","visible","map","length","Date","activePresetId","dateFormat","Intl","DateTimeFormat","resolvedLang","day","month","displayValue","sep","format","pendingRangeLabel","minDate","maxDate","render","display","placeholder","anchorId","headerId","ariaLabel","controlAriaLabel","ariaLabelledby","controlAriaLabelledby","ariaDescribedby","controlAriaDescribedby","activePreset","html","renderLabel","ifDefined","effectiveDisabled","nothing","renderBody","renderError","isHintBelow","renderHint","classMap","size","insideField","hint","cond","required","hintBelow","hideLabel","controlAriaInvalid","ref","focusableRef","hintSlot","isEmpty","labelSlot","onPopoutOpen","onPopoutClose","actionSize","renderPresetsCollapsed","renderPresetsList","renderPreset","handlePresetClick","renderPresetGroups","activeLabel","find","DateRangeChangeEvent","show","moveFocusToToggle","options","__decorate","query","prototype","property","reflect","attribute","type","state","customElement"],"mappings":"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"}
package/lib/Dropdown.js CHANGED
@@ -1,2 +1,2 @@
1
- import{_ as t}from"./tslib.es6-CmLYFWVC.js";import{css as e,html as o,LitElement as n}from"lit";import{query as s,state as i,property as a,customElement as r}from"lit/decorators.js";import{ifDefined as d}from"lit/directives/if-defined.js";import{S as l}from"./SlotController-Z6eG7LSZ.js";import{o as p}from"./observe-D0n0zOfU.js";import{F as c}from"./Popout-CFtFoCaA.js";import{s as u}from"./Component-BJ5O5n8k.js";import"./Icon.js";import"./DropdownItem.js";import"./EventController-BBOmvfLa.js";import"./positioning-D-K8Mueq.js";import"./DirectionController-ChvNGESZ.js";import"./LightDismissController-wcL1ziJa.js";import"./ShortcutController-CV5b0BZl.js";import"./tinykeys-DwvDXsEb.js";import"./ScrollbarController-BFC67Y2x.js";import"./events-Bv6wNHwJ.js";import"lit/directives/unsafe-html.js";import"./cond-CI1KbneT.js";import"./IconManager.js";import"lit/directives/ref.js";import"./FocusableMixin-BlQLNPdJ.js";import"./DropdownItem-BYbOLth6.js";const h=e`:host{--_n-dropdown-size:var(--n-dropdown-size,250px);--_n-dropdown-max-block-size:var(--n-dropdown-max-block-size,460px)}.n-dropdown-content{max-block-size:var(--_n-dropdown-max-block-size);max-inline-size:calc(var(--_n-dropdown-size)*1.5);min-inline-size:var(--_n-dropdown-size);overflow-y:auto;padding:var(--n-space-s) 0}@media (max-width:35.9375em){.n-dropdown-content{max-block-size:70vh;max-inline-size:none}.n-dropdown-header.is-navigation-header{padding:var(--n-space-s) 0}.n-dropdown-back-item{inline-size:100%;padding-inline-end:var(--n-space-s);padding-inline-start:var(--n-space-s)}.n-dropdown-content.is-submenu-active ::slotted(nord-dropdown-group),.n-dropdown-content.is-submenu-active ::slotted(nord-dropdown-item),.n-dropdown-content.is-submenu-active ::slotted(nord-dropdown-submenu:not([mobile-active])){display:none}}::slotted(nord-dropdown-group),::slotted(nord-dropdown-item){padding-inline-end:var(--n-space-s);padding-inline-start:var(--n-space-s)}::slotted(nord-dropdown-group){border-block-end:1px solid var(--n-color-border);margin-block-end:var(--n-space-s);padding-block-end:var(--n-space-s)}::slotted(nord-dropdown-group:last-child){border-block-end:0;margin-block-end:0;padding-block-end:0}::slotted(nord-message:first-of-type){padding-block-start:0}::slotted(nord-message:last-of-type){margin-block-end:var(--n-space-s)}slot[name=toggle]{display:inline-block}:host([expand]) slot[name=toggle]{inline-size:100%}:host([size=s]){--_n-dropdown-size:var(--n-dropdown-size,150px)}:host([size=l]){--_n-dropdown-size:var(--n-dropdown-size,300px)}.n-dropdown-header{align-items:center;background-color:var(--n-color-surface-raised);border-block-end:1px solid var(--n-color-border);border-start-end-radius:var(--n-border-radius);border-start-start-radius:var(--n-border-radius);display:flex;flex-wrap:wrap;font-weight:var(--n-font-weight);gap:var(--n-space-s);padding:calc(var(--n-space-m) + 2px) var(--n-space-m)}.n-dropdown-header ::slotted(nord-button){--n-button-gap:var(--n-space-xs);--n-button-background-color:var(--n-color-surface)}.n-dropdown-header ::slotted(nord-button:hover){--n-button-background-color:var(--n-color-button-hover)}::slotted([slot=header-end]){align-items:center;display:flex;flex-wrap:wrap;gap:var(--n-space-s);margin-inline-start:auto}::slotted(:is(h1,h2,h3,h4,h5,h6,p)){margin:0!important}`;let m=class extends(c(n)){constructor(){super(...arguments),this.headerSlot=new l(this,"header"),this.headerEndSlot=new l(this,"header-end"),this.submenuStack=[],this.isNavigating=!1,this.expand=!1,this.size="m",this.alwaysFloating=!1}get isShowingSubmenu(){return this.submenuStack.length>0}get submenuStackRef(){return this.submenuStack}get deepestSubmenu(){return this.submenuStack[this.submenuStack.length-1]}handleAlwaysFloatingChange(){this.open&&(this.open=!1,this.updateComplete.then((()=>{this.open=!0})))}connectedCallback(){super.connectedCallback();const t=this.querySelector('[slot="toggle"]');null==t||t.setAttribute("aria-haspopup","true")}render(){var t;const e=this.submenuStack[this.submenuStack.length-1];return o`<div class="n-dropdown" @nord-submenu-navigate="${this.handleSubmenuNavigate}" @focusout="${this.handleBlur}"><slot name="toggle" aria-controls="popout"></slot><nord-popout id="popout" align="${d(this.align)}" position="${d(this.position)}" side-offset="${this.sideOffset}" align-offset="${this.alignOffset}" ?open="${this.open}" ?always-floating="${this.alwaysFloating}" @open="${this.handleOpen}" @close="${this.handleClose}">${this.isShowingSubmenu?o`<div class="n-dropdown-header is-navigation-header"><nord-dropdown-item @click="${this.handleBackClick}" class="n-dropdown-back-item"><nord-icon slot="start" name="arrow-left" size="s"></nord-icon>${null!==(t=null==e?void 0:e.label)&&void 0!==t?t:""}</nord-dropdown-item></div>`:o`<div class="n-dropdown-header" ?hidden="${this.headerSlot.isEmpty&&this.headerEndSlot.isEmpty}"><slot name="${this.headerSlot.slotName}"></slot><slot name="${this.headerEndSlot.slotName}"></slot></div>`}<div class="n-dropdown-content ${this.isShowingSubmenu?"is-submenu-active":""}"><slot></slot></div></nord-popout></div>`}handleBlur(t){const e=t.relatedTarget;this.isNavigating||this.isShowingSubmenu||e&&(this.contains(e)||this.popout.hide(!1))}handleOpen(){this.open=!0}handleBackClick(t){t.preventDefault(),t.stopPropagation(),this.isNavigating=!0,this.navigateBack(),this.updateComplete.then((()=>{this.isNavigating=!1;const t=this.submenuStack[this.submenuStack.length-1],e=t?t.querySelector('[slot="trigger"]'):this.querySelector("nord-dropdown-item");null==e||e.focus()}))}handleClose(t){if(this.isNavigating)return;this.clearSubmenuStack();const e=t.target;"NORD-POPOUT"===(null==e?void 0:e.tagName)&&this.contains(e)||(this.open=!1)}handleOpenChange(){var t;if(this.open){const e=null!==(t=this.querySelector("[autofocus]"))&&void 0!==t?t:this.querySelector("nord-dropdown-item, nord-message");null==e||e.focus(),this.list.scrollTop=0}else this.isNavigating||this.clearSubmenuStack()}navigateBack(){if(0===this.submenuStack.length)return;const t=this.submenuStack[this.submenuStack.length-1];t.deactivateMobile(),t.requestUpdate();const e=this.submenuStack[this.submenuStack.length-2];e&&(e.removeAttribute("has-active-child"),e.requestUpdate()),this.submenuStack=this.submenuStack.slice(0,-1)}clearSubmenuStack(){for(const t of this.submenuStack)t.deactivateMobile(),t.removeAttribute("has-active-child");this.submenuStack=[]}handleSubmenuNavigate(t){const e=t;e.stopPropagation();const o=this.submenuStack[this.submenuStack.length-1];o&&(o.setAttribute("has-active-child",""),o.requestUpdate());const n=e.detail.submenu;this.submenuStack=[...this.submenuStack,n],this.updateComplete.then((()=>{n.requestUpdate()}))}hide(t){return this.popout.hide(t)}show(){return this.popout.show()}};m.styles=[u,h],m.shadowRootOptions={...n.shadowRootOptions,delegatesFocus:!0},t([s(".n-dropdown-content")],m.prototype,"list",void 0),t([s("nord-popout",!0)],m.prototype,"popout",void 0),t([i()],m.prototype,"submenuStack",void 0),t([a({reflect:!0,type:Boolean})],m.prototype,"expand",void 0),t([a({reflect:!0})],m.prototype,"size",void 0),t([a({reflect:!0,type:Boolean,attribute:"always-floating"})],m.prototype,"alwaysFloating",void 0),t([p("alwaysFloating")],m.prototype,"handleAlwaysFloatingChange",null),t([p("open","updated")],m.prototype,"handleOpenChange",null),m=t([r("nord-dropdown")],m);var g=m;export{g as default};
1
+ import{_ as t}from"./tslib.es6-CmLYFWVC.js";import{css as e,html as o,LitElement as n}from"lit";import{query as s,state as i,property as a,customElement as r}from"lit/decorators.js";import{ifDefined as d}from"lit/directives/if-defined.js";import{S as l}from"./SlotController-Z6eG7LSZ.js";import{o as p}from"./observe-D0n0zOfU.js";import{F as c}from"./Popout-B6Hirj3y.js";import{s as u}from"./Component-BJ5O5n8k.js";import"./Icon.js";import"./DropdownItem.js";import"./EventController-BBOmvfLa.js";import"./positioning-D-K8Mueq.js";import"./DirectionController-ChvNGESZ.js";import"./LightDismissController-wcL1ziJa.js";import"./ShortcutController-CV5b0BZl.js";import"./tinykeys-DwvDXsEb.js";import"./ScrollbarController-BFC67Y2x.js";import"./events-Bv6wNHwJ.js";import"lit/directives/unsafe-html.js";import"./cond-CI1KbneT.js";import"./IconManager.js";import"lit/directives/ref.js";import"./FocusableMixin-BlQLNPdJ.js";import"./DropdownItem-BYbOLth6.js";const h=e`:host{--_n-dropdown-size:var(--n-dropdown-size,250px);--_n-dropdown-max-block-size:var(--n-dropdown-max-block-size,460px)}.n-dropdown-content{max-block-size:var(--_n-dropdown-max-block-size);max-inline-size:calc(var(--_n-dropdown-size)*1.5);min-inline-size:var(--_n-dropdown-size);overflow-y:auto;padding:var(--n-space-s) 0}@media (max-width:35.9375em){.n-dropdown-content{max-block-size:70vh;max-inline-size:none}.n-dropdown-header.is-navigation-header{padding:var(--n-space-s) 0}.n-dropdown-back-item{inline-size:100%;padding-inline-end:var(--n-space-s);padding-inline-start:var(--n-space-s)}.n-dropdown-content.is-submenu-active ::slotted(nord-dropdown-group),.n-dropdown-content.is-submenu-active ::slotted(nord-dropdown-item),.n-dropdown-content.is-submenu-active ::slotted(nord-dropdown-submenu:not([mobile-active])){display:none}}::slotted(nord-dropdown-group),::slotted(nord-dropdown-item){padding-inline-end:var(--n-space-s);padding-inline-start:var(--n-space-s)}::slotted(nord-dropdown-group){border-block-end:1px solid var(--n-color-border);margin-block-end:var(--n-space-s);padding-block-end:var(--n-space-s)}::slotted(nord-dropdown-group:last-child){border-block-end:0;margin-block-end:0;padding-block-end:0}::slotted(nord-message:first-of-type){padding-block-start:0}::slotted(nord-message:last-of-type){margin-block-end:var(--n-space-s)}slot[name=toggle]{display:inline-block}:host([expand]) slot[name=toggle]{inline-size:100%}:host([size=s]){--_n-dropdown-size:var(--n-dropdown-size,150px)}:host([size=l]){--_n-dropdown-size:var(--n-dropdown-size,300px)}.n-dropdown-header{align-items:center;background-color:var(--n-color-surface-raised);border-block-end:1px solid var(--n-color-border);border-start-end-radius:var(--n-border-radius);border-start-start-radius:var(--n-border-radius);display:flex;flex-wrap:wrap;font-weight:var(--n-font-weight);gap:var(--n-space-s);padding:calc(var(--n-space-m) + 2px) var(--n-space-m)}.n-dropdown-header ::slotted(nord-button){--n-button-gap:var(--n-space-xs);--n-button-background-color:var(--n-color-surface)}.n-dropdown-header ::slotted(nord-button:hover){--n-button-background-color:var(--n-color-button-hover)}::slotted([slot=header-end]){align-items:center;display:flex;flex-wrap:wrap;gap:var(--n-space-s);margin-inline-start:auto}::slotted(:is(h1,h2,h3,h4,h5,h6,p)){margin:0!important}`;let m=class extends(c(n)){constructor(){super(...arguments),this.headerSlot=new l(this,"header"),this.headerEndSlot=new l(this,"header-end"),this.submenuStack=[],this.isNavigating=!1,this.expand=!1,this.size="m",this.alwaysFloating=!1}get isShowingSubmenu(){return this.submenuStack.length>0}get submenuStackRef(){return this.submenuStack}get deepestSubmenu(){return this.submenuStack[this.submenuStack.length-1]}handleAlwaysFloatingChange(){this.open&&(this.open=!1,this.updateComplete.then((()=>{this.open=!0})))}connectedCallback(){super.connectedCallback();const t=this.querySelector('[slot="toggle"]');null==t||t.setAttribute("aria-haspopup","true")}render(){var t;const e=this.submenuStack[this.submenuStack.length-1];return o`<div class="n-dropdown" @nord-submenu-navigate="${this.handleSubmenuNavigate}" @focusout="${this.handleBlur}"><slot name="toggle" aria-controls="popout"></slot><nord-popout id="popout" align="${d(this.align)}" position="${d(this.position)}" side-offset="${this.sideOffset}" align-offset="${this.alignOffset}" ?open="${this.open}" ?always-floating="${this.alwaysFloating}" @open="${this.handleOpen}" @close="${this.handleClose}">${this.isShowingSubmenu?o`<div class="n-dropdown-header is-navigation-header"><nord-dropdown-item @click="${this.handleBackClick}" class="n-dropdown-back-item"><nord-icon slot="start" name="arrow-left" size="s"></nord-icon>${null!==(t=null==e?void 0:e.label)&&void 0!==t?t:""}</nord-dropdown-item></div>`:o`<div class="n-dropdown-header" ?hidden="${this.headerSlot.isEmpty&&this.headerEndSlot.isEmpty}"><slot name="${this.headerSlot.slotName}"></slot><slot name="${this.headerEndSlot.slotName}"></slot></div>`}<div class="n-dropdown-content ${this.isShowingSubmenu?"is-submenu-active":""}"><slot></slot></div></nord-popout></div>`}handleBlur(t){const e=t.relatedTarget;this.isNavigating||this.isShowingSubmenu||e&&(this.contains(e)||this.popout.hide(!1))}handleOpen(){this.open=!0}handleBackClick(t){t.preventDefault(),t.stopPropagation(),this.isNavigating=!0,this.navigateBack(),this.updateComplete.then((()=>{this.isNavigating=!1;const t=this.submenuStack[this.submenuStack.length-1],e=t?t.querySelector('[slot="trigger"]'):this.querySelector("nord-dropdown-item");null==e||e.focus()}))}handleClose(t){if(this.isNavigating)return;this.clearSubmenuStack();const e=t.target;"NORD-POPOUT"===(null==e?void 0:e.tagName)&&this.contains(e)||(this.open=!1)}handleOpenChange(){var t;if(this.open){const e=null!==(t=this.querySelector("[autofocus]"))&&void 0!==t?t:this.querySelector("nord-dropdown-item, nord-message");null==e||e.focus(),this.list.scrollTop=0}else this.isNavigating||this.clearSubmenuStack()}navigateBack(){if(0===this.submenuStack.length)return;const t=this.submenuStack[this.submenuStack.length-1];t.deactivateMobile(),t.requestUpdate();const e=this.submenuStack[this.submenuStack.length-2];e&&(e.removeAttribute("has-active-child"),e.requestUpdate()),this.submenuStack=this.submenuStack.slice(0,-1)}clearSubmenuStack(){for(const t of this.submenuStack)t.deactivateMobile(),t.removeAttribute("has-active-child");this.submenuStack=[]}handleSubmenuNavigate(t){const e=t;e.stopPropagation();const o=this.submenuStack[this.submenuStack.length-1];o&&(o.setAttribute("has-active-child",""),o.requestUpdate());const n=e.detail.submenu;this.submenuStack=[...this.submenuStack,n],this.updateComplete.then((()=>{n.requestUpdate()}))}hide(t){return this.popout.hide(t)}show(){return this.popout.show()}};m.styles=[u,h],m.shadowRootOptions={...n.shadowRootOptions,delegatesFocus:!0},t([s(".n-dropdown-content")],m.prototype,"list",void 0),t([s("nord-popout",!0)],m.prototype,"popout",void 0),t([i()],m.prototype,"submenuStack",void 0),t([a({reflect:!0,type:Boolean})],m.prototype,"expand",void 0),t([a({reflect:!0})],m.prototype,"size",void 0),t([a({reflect:!0,type:Boolean,attribute:"always-floating"})],m.prototype,"alwaysFloating",void 0),t([p("alwaysFloating")],m.prototype,"handleAlwaysFloatingChange",null),t([p("open","updated")],m.prototype,"handleOpenChange",null),m=t([r("nord-dropdown")],m);var g=m;export{g as default};
2
2
  //# sourceMappingURL=Dropdown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.js","sources":["../src/dropdown/Dropdown.ts"],"sourcesContent":["import type DropdownSubmenu from '../dropdown-submenu/DropdownSubmenu.js'\nimport type Popout from '../popout/Popout.js'\nimport { html, LitElement } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { SlotController } from '../common/controllers/SlotController.js'\nimport { observe } from '../common/decorators/observe.js'\n\nimport { FloatingMixin } from '../common/mixins/FloatingComponentMixin.js'\nimport componentStyle from '../common/styles/Component.css'\n\nimport style from './Dropdown.css'\nimport '../popout/Popout.js'\nimport '../icon/Icon.js'\nimport '../dropdown-item/DropdownItem.js'\n\n/**\n * Dropdown menu displays a list of actions or selectable options for\n * a user. Dropdown uses popout component internally to create\n * the overlay functionality.\n *\n * @status ready\n * @category overlay\n *\n * @slot - The dropdown content.\n * @slot toggle - Used to place the toggle for dropdown.\n * @slot header - Optional slot that holds a header for the dropdown.\n * @slot header-end - Optional slot that positions content at the end of the header. Useful for actions or additional info.\n *\n * @fires {NordEvent} open - Dispatched when the popout is opened.\n * @fires {NordEvent} close - Dispatched when the popout is closed.\n *\n * @cssprop [--n-dropdown-size=250px] - Controls the inline size, or width, of the dropdown. Will resize up to 1.5 times to account for larger content.\n * @cssprop [--n-dropdown-max-block-size=460px] - Controls the maximum block size, or height, of the dropdown. Larger content will get a scrollbar.\n */\n@customElement('nord-dropdown')\nexport default class Dropdown extends FloatingMixin(LitElement) {\n static styles = [componentStyle, style]\n\n /**\n * we delegate focus, to ensure focus does not move to body if you click\n * some whitespace or a dropdown-group heading, as this would close the dropdown\n * @internal\n */\n static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true }\n\n private headerSlot = new SlotController(this, 'header')\n private headerEndSlot = new SlotController(this, 'header-end')\n\n @query('.n-dropdown-content') private list!: HTMLElement\n @query('nord-popout', true) private popout!: Popout\n\n @state() private submenuStack: DropdownSubmenu[] = []\n private isNavigating = false\n\n private get isShowingSubmenu(): boolean {\n return this.submenuStack.length > 0\n }\n\n /**\n * @internal\n */\n get submenuStackRef(): readonly DropdownSubmenu[] {\n return this.submenuStack\n }\n\n /**\n * @internal\n */\n get deepestSubmenu(): DropdownSubmenu | undefined {\n return this.submenuStack[this.submenuStack.length - 1]\n }\n\n /**\n * Controls whether the toggle slot expands to fill the width of its container.\n */\n @property({ reflect: true, type: Boolean }) expand = false\n\n /**\n * The size of the dropdown. This affects the minimum and maximum inline-size\n * of the dropdown.\n */\n @property({ reflect: true }) size: 's' | 'm' | 'l' = 'm'\n\n /**\n * Set to true to always display the dropdown as a floating overlay, even on smaller viewports.\n */\n @property({ reflect: true, type: Boolean, attribute: 'always-floating' })\n alwaysFloating: boolean = false\n\n @observe('alwaysFloating')\n protected handleAlwaysFloatingChange() {\n if (this.open) {\n this.open = false\n this.updateComplete.then(() => {\n this.open = true\n })\n }\n }\n\n connectedCallback() {\n super.connectedCallback()\n\n const toggle = this.querySelector(`[slot=\"toggle\"]`)\n toggle?.setAttribute('aria-haspopup', 'true')\n }\n\n render() {\n const activeSubmenu = this.submenuStack[this.submenuStack.length - 1]\n\n return html`\n <div class=\"n-dropdown\" @nord-submenu-navigate=${this.handleSubmenuNavigate} @focusout=${this.handleBlur}>\n <slot name=\"toggle\" aria-controls=\"popout\"></slot>\n <nord-popout\n id=\"popout\"\n align=${ifDefined(this.align)}\n position=${ifDefined(this.position)}\n side-offset=${this.sideOffset}\n align-offset=${this.alignOffset}\n ?open=${this.open}\n ?always-floating=${this.alwaysFloating}\n @open=${this.handleOpen}\n @close=${this.handleClose}\n >\n ${\n this.isShowingSubmenu\n ? html`\n <div class=\"n-dropdown-header is-navigation-header\">\n <nord-dropdown-item @click=${this.handleBackClick} class=\"n-dropdown-back-item\">\n <nord-icon slot=\"start\" name=\"arrow-left\" size=\"s\"></nord-icon>\n ${activeSubmenu?.label ?? ''}\n </nord-dropdown-item>\n </div>\n `\n : html`\n <div class=\"n-dropdown-header\" ?hidden=${this.headerSlot.isEmpty && this.headerEndSlot.isEmpty}>\n <slot name=${this.headerSlot.slotName}></slot>\n <slot name=${this.headerEndSlot.slotName}></slot>\n </div>\n `\n }\n <div class=\"n-dropdown-content ${this.isShowingSubmenu ? 'is-submenu-active' : ''}\">\n <slot></slot>\n </div>\n </nord-popout>\n </div>\n `\n }\n\n private handleBlur(e: FocusEvent) {\n const relatedTarget = e.relatedTarget as HTMLElement\n\n // Don't close during navigation or if we're still showing a submenu\n // (the blur event fires after back button is removed from DOM, but we're still in submenu mode)\n if (this.isNavigating || this.isShowingSubmenu)\n return\n\n // Safari will set relatedTarget to null when clicking on the trigger button\n // because it doesn't focus buttons on click.\n // this caused weird behavior where the dropdown closed _and_ opened with a single click.\n // so we only run this logic if relatedTarget is set, which sidesteps this issue\n if (!relatedTarget) {\n return\n }\n\n // Close dropdown if focus moved outside\n if (!this.contains(relatedTarget)) {\n this.popout.hide(false)\n }\n }\n\n private handleOpen() {\n this.open = true\n }\n\n private handleBackClick(event: MouseEvent) {\n event.preventDefault()\n event.stopPropagation()\n\n this.isNavigating = true\n this.navigateBack()\n\n // Reset navigation flag after updates complete\n this.updateComplete.then(() => {\n this.isNavigating = false\n // Focus the trigger of the submenu we're returning to, or the first item\n const newTop = this.submenuStack[this.submenuStack.length - 1]\n const focusTarget = newTop\n ? newTop.querySelector<HTMLElement>('[slot=\"trigger\"]')\n : this.querySelector<HTMLElement>('nord-dropdown-item')\n focusTarget?.focus()\n })\n }\n\n private handleClose(e: Event) {\n // Don't close during navigation\n if (this.isNavigating)\n return\n\n // Clear submenu stack on close\n this.clearSubmenuStack()\n\n // Ignore close events from child popouts (submenus)\n // The event target will be a nord-popout element that is a child of this dropdown\n const eventTarget = e.target as HTMLElement\n const isChildPopout = eventTarget?.tagName === 'NORD-POPOUT' && this.contains(eventTarget)\n\n if (isChildPopout) {\n return\n }\n\n this.open = false\n }\n\n @observe('open', 'updated')\n protected handleOpenChange() {\n if (this.open) {\n const focusTarget\n = this.querySelector<HTMLElement>('[autofocus]')\n ?? this.querySelector<HTMLElement>('nord-dropdown-item, nord-message')\n\n focusTarget?.focus()\n this.list.scrollTop = 0\n }\n else if (!this.isNavigating) {\n // Clear submenu stack when dropdown closes (but not during navigation)\n this.clearSubmenuStack()\n }\n }\n\n /**\n * Navigate back one level in the submenu stack.\n * @internal\n */\n navigateBack() {\n if (this.submenuStack.length === 0)\n return\n\n const topSubmenu = this.submenuStack[this.submenuStack.length - 1]\n topSubmenu.deactivateMobile()\n // Trigger re-render so it loses active and is-deepest-active classes\n topSubmenu.requestUpdate()\n\n const newTop = this.submenuStack[this.submenuStack.length - 2]\n if (newTop) {\n newTop.removeAttribute('has-active-child')\n // Trigger re-render so it gains is-deepest-active class back\n newTop.requestUpdate()\n }\n\n this.submenuStack = this.submenuStack.slice(0, -1)\n }\n\n /**\n * Clear the entire submenu stack.\n * @internal\n */\n private clearSubmenuStack() {\n for (const submenu of this.submenuStack) {\n submenu.deactivateMobile()\n submenu.removeAttribute('has-active-child')\n }\n this.submenuStack = []\n }\n\n /**\n * Handle submenu navigation event.\n * @internal\n */\n private handleSubmenuNavigate(event: Event) {\n const customEvent = event as CustomEvent<{ submenu: DropdownSubmenu }>\n customEvent.stopPropagation()\n\n const previousDeepest = this.submenuStack[this.submenuStack.length - 1]\n if (previousDeepest) {\n previousDeepest.setAttribute('has-active-child', '')\n // Trigger re-render so it loses is-deepest-active class\n previousDeepest.requestUpdate()\n }\n\n const newSubmenu = customEvent.detail.submenu\n this.submenuStack = [...this.submenuStack, newSubmenu]\n\n // Trigger re-render of new deepest so it gains is-deepest-active class\n this.updateComplete.then(() => {\n newSubmenu.requestUpdate()\n })\n }\n\n /**\n * Hide the dropdown programmatically.\n * This method delegates to the Dropdown's internal Popout component.\n * See [Popout's hide() method](/components/popout#methods-hide) for more details.\n * @param moveFocusToButton A boolean option to move the focus to the original button that opens the dropdown.\n */\n hide(moveFocusToButton?: boolean): Promise<TransitionEvent | void> {\n return this.popout.hide(moveFocusToButton)\n }\n\n /**\n * Show the dropdown programmatically.\n * This method delegates to the Dropdown's internal Popout component.\n * See [Popout's show() method](/components/popout#methods-hide) for more details.\n */\n show(): Promise<TransitionEvent | void> {\n return this.popout.show()\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-dropdown': Dropdown\n }\n}\n"],"names":["Dropdown","FloatingMixin","LitElement","constructor","this","headerSlot","SlotController","headerEndSlot","submenuStack","isNavigating","expand","size","alwaysFloating","isShowingSubmenu","length","submenuStackRef","deepestSubmenu","handleAlwaysFloatingChange","open","updateComplete","then","connectedCallback","super","toggle","querySelector","setAttribute","render","activeSubmenu","html","handleSubmenuNavigate","handleBlur","ifDefined","align","position","sideOffset","alignOffset","handleOpen","handleClose","handleBackClick","_a","label","isEmpty","slotName","e","relatedTarget","contains","popout","hide","event","preventDefault","stopPropagation","navigateBack","newTop","focusTarget","focus","clearSubmenuStack","eventTarget","target","tagName","handleOpenChange","list","scrollTop","topSubmenu","deactivateMobile","requestUpdate","removeAttribute","slice","submenu","customEvent","previousDeepest","newSubmenu","detail","moveFocusToButton","show","styles","componentStyle","style","shadowRootOptions","delegatesFocus","__decorate","query","prototype","state","property","reflect","type","Boolean","attribute","observe","customElement"],"mappings":"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"}
1
+ {"version":3,"file":"Dropdown.js","sources":["../src/dropdown/Dropdown.ts"],"sourcesContent":["import type DropdownSubmenu from '../dropdown-submenu/DropdownSubmenu.js'\nimport type Popout from '../popout/Popout.js'\nimport { html, LitElement } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { SlotController } from '../common/controllers/SlotController.js'\nimport { observe } from '../common/decorators/observe.js'\n\nimport { FloatingMixin } from '../common/mixins/FloatingComponentMixin.js'\nimport componentStyle from '../common/styles/Component.css'\n\nimport style from './Dropdown.css'\nimport '../popout/Popout.js'\nimport '../icon/Icon.js'\nimport '../dropdown-item/DropdownItem.js'\n\n/**\n * Dropdown menu displays a list of actions or selectable options for\n * a user. Dropdown uses popout component internally to create\n * the overlay functionality.\n *\n * @status ready\n * @category overlay\n *\n * @slot - The dropdown content.\n * @slot toggle - Used to place the toggle for dropdown.\n * @slot header - Optional slot that holds a header for the dropdown.\n * @slot header-end - Optional slot that positions content at the end of the header. Useful for actions or additional info.\n *\n * @fires {NordEvent} open - Dispatched when the popout is opened.\n * @fires {NordEvent} close - Dispatched when the popout is closed.\n *\n * @cssprop [--n-dropdown-size=250px] - Controls the inline size, or width, of the dropdown. Will resize up to 1.5 times to account for larger content.\n * @cssprop [--n-dropdown-max-block-size=460px] - Controls the maximum block size, or height, of the dropdown. Larger content will get a scrollbar.\n */\n@customElement('nord-dropdown')\nexport default class Dropdown extends FloatingMixin(LitElement) {\n static styles = [componentStyle, style]\n\n /**\n * we delegate focus, to ensure focus does not move to body if you click\n * some whitespace or a dropdown-group heading, as this would close the dropdown\n * @internal\n */\n static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true }\n\n private headerSlot = new SlotController(this, 'header')\n private headerEndSlot = new SlotController(this, 'header-end')\n\n @query('.n-dropdown-content') private list!: HTMLElement\n @query('nord-popout', true) private popout!: Popout\n\n @state() private submenuStack: DropdownSubmenu[] = []\n private isNavigating = false\n\n private get isShowingSubmenu(): boolean {\n return this.submenuStack.length > 0\n }\n\n /**\n * @internal\n */\n get submenuStackRef(): readonly DropdownSubmenu[] {\n return this.submenuStack\n }\n\n /**\n * @internal\n */\n get deepestSubmenu(): DropdownSubmenu | undefined {\n return this.submenuStack[this.submenuStack.length - 1]\n }\n\n /**\n * Controls whether the toggle slot expands to fill the width of its container.\n * Note that this only stretches the slot itself — the slotted toggle must\n * also expand to fill it, e.g. a `<nord-button slot=\"toggle\">` needs its own\n * `expand` attribute as well.\n */\n @property({ reflect: true, type: Boolean }) expand = false\n\n /**\n * The size of the dropdown. This affects the minimum and maximum inline-size\n * of the dropdown.\n */\n @property({ reflect: true }) size: 's' | 'm' | 'l' = 'm'\n\n /**\n * Set to true to always display the dropdown as a floating overlay, even on smaller viewports.\n */\n @property({ reflect: true, type: Boolean, attribute: 'always-floating' })\n alwaysFloating: boolean = false\n\n @observe('alwaysFloating')\n protected handleAlwaysFloatingChange() {\n if (this.open) {\n this.open = false\n this.updateComplete.then(() => {\n this.open = true\n })\n }\n }\n\n connectedCallback() {\n super.connectedCallback()\n\n const toggle = this.querySelector(`[slot=\"toggle\"]`)\n toggle?.setAttribute('aria-haspopup', 'true')\n }\n\n render() {\n const activeSubmenu = this.submenuStack[this.submenuStack.length - 1]\n\n return html`\n <div class=\"n-dropdown\" @nord-submenu-navigate=${this.handleSubmenuNavigate} @focusout=${this.handleBlur}>\n <slot name=\"toggle\" aria-controls=\"popout\"></slot>\n <nord-popout\n id=\"popout\"\n align=${ifDefined(this.align)}\n position=${ifDefined(this.position)}\n side-offset=${this.sideOffset}\n align-offset=${this.alignOffset}\n ?open=${this.open}\n ?always-floating=${this.alwaysFloating}\n @open=${this.handleOpen}\n @close=${this.handleClose}\n >\n ${\n this.isShowingSubmenu\n ? html`\n <div class=\"n-dropdown-header is-navigation-header\">\n <nord-dropdown-item @click=${this.handleBackClick} class=\"n-dropdown-back-item\">\n <nord-icon slot=\"start\" name=\"arrow-left\" size=\"s\"></nord-icon>\n ${activeSubmenu?.label ?? ''}\n </nord-dropdown-item>\n </div>\n `\n : html`\n <div class=\"n-dropdown-header\" ?hidden=${this.headerSlot.isEmpty && this.headerEndSlot.isEmpty}>\n <slot name=${this.headerSlot.slotName}></slot>\n <slot name=${this.headerEndSlot.slotName}></slot>\n </div>\n `\n }\n <div class=\"n-dropdown-content ${this.isShowingSubmenu ? 'is-submenu-active' : ''}\">\n <slot></slot>\n </div>\n </nord-popout>\n </div>\n `\n }\n\n private handleBlur(e: FocusEvent) {\n const relatedTarget = e.relatedTarget as HTMLElement\n\n // Don't close during navigation or if we're still showing a submenu\n // (the blur event fires after back button is removed from DOM, but we're still in submenu mode)\n if (this.isNavigating || this.isShowingSubmenu)\n return\n\n // Safari will set relatedTarget to null when clicking on the trigger button\n // because it doesn't focus buttons on click.\n // this caused weird behavior where the dropdown closed _and_ opened with a single click.\n // so we only run this logic if relatedTarget is set, which sidesteps this issue\n if (!relatedTarget) {\n return\n }\n\n // Close dropdown if focus moved outside\n if (!this.contains(relatedTarget)) {\n this.popout.hide(false)\n }\n }\n\n private handleOpen() {\n this.open = true\n }\n\n private handleBackClick(event: MouseEvent) {\n event.preventDefault()\n event.stopPropagation()\n\n this.isNavigating = true\n this.navigateBack()\n\n // Reset navigation flag after updates complete\n this.updateComplete.then(() => {\n this.isNavigating = false\n // Focus the trigger of the submenu we're returning to, or the first item\n const newTop = this.submenuStack[this.submenuStack.length - 1]\n const focusTarget = newTop\n ? newTop.querySelector<HTMLElement>('[slot=\"trigger\"]')\n : this.querySelector<HTMLElement>('nord-dropdown-item')\n focusTarget?.focus()\n })\n }\n\n private handleClose(e: Event) {\n // Don't close during navigation\n if (this.isNavigating)\n return\n\n // Clear submenu stack on close\n this.clearSubmenuStack()\n\n // Ignore close events from child popouts (submenus)\n // The event target will be a nord-popout element that is a child of this dropdown\n const eventTarget = e.target as HTMLElement\n const isChildPopout = eventTarget?.tagName === 'NORD-POPOUT' && this.contains(eventTarget)\n\n if (isChildPopout) {\n return\n }\n\n this.open = false\n }\n\n @observe('open', 'updated')\n protected handleOpenChange() {\n if (this.open) {\n const focusTarget\n = this.querySelector<HTMLElement>('[autofocus]')\n ?? this.querySelector<HTMLElement>('nord-dropdown-item, nord-message')\n\n focusTarget?.focus()\n this.list.scrollTop = 0\n }\n else if (!this.isNavigating) {\n // Clear submenu stack when dropdown closes (but not during navigation)\n this.clearSubmenuStack()\n }\n }\n\n /**\n * Navigate back one level in the submenu stack.\n * @internal\n */\n navigateBack() {\n if (this.submenuStack.length === 0)\n return\n\n const topSubmenu = this.submenuStack[this.submenuStack.length - 1]\n topSubmenu.deactivateMobile()\n // Trigger re-render so it loses active and is-deepest-active classes\n topSubmenu.requestUpdate()\n\n const newTop = this.submenuStack[this.submenuStack.length - 2]\n if (newTop) {\n newTop.removeAttribute('has-active-child')\n // Trigger re-render so it gains is-deepest-active class back\n newTop.requestUpdate()\n }\n\n this.submenuStack = this.submenuStack.slice(0, -1)\n }\n\n /**\n * Clear the entire submenu stack.\n * @internal\n */\n private clearSubmenuStack() {\n for (const submenu of this.submenuStack) {\n submenu.deactivateMobile()\n submenu.removeAttribute('has-active-child')\n }\n this.submenuStack = []\n }\n\n /**\n * Handle submenu navigation event.\n * @internal\n */\n private handleSubmenuNavigate(event: Event) {\n const customEvent = event as CustomEvent<{ submenu: DropdownSubmenu }>\n customEvent.stopPropagation()\n\n const previousDeepest = this.submenuStack[this.submenuStack.length - 1]\n if (previousDeepest) {\n previousDeepest.setAttribute('has-active-child', '')\n // Trigger re-render so it loses is-deepest-active class\n previousDeepest.requestUpdate()\n }\n\n const newSubmenu = customEvent.detail.submenu\n this.submenuStack = [...this.submenuStack, newSubmenu]\n\n // Trigger re-render of new deepest so it gains is-deepest-active class\n this.updateComplete.then(() => {\n newSubmenu.requestUpdate()\n })\n }\n\n /**\n * Hide the dropdown programmatically.\n * This method delegates to the Dropdown's internal Popout component.\n * See [Popout's hide() method](/components/popout#methods-hide) for more details.\n * @param moveFocusToButton A boolean option to move the focus to the original button that opens the dropdown.\n */\n hide(moveFocusToButton?: boolean): Promise<TransitionEvent | void> {\n return this.popout.hide(moveFocusToButton)\n }\n\n /**\n * Show the dropdown programmatically.\n * This method delegates to the Dropdown's internal Popout component.\n * See [Popout's show() method](/components/popout#methods-hide) for more details.\n */\n show(): Promise<TransitionEvent | void> {\n return this.popout.show()\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-dropdown': Dropdown\n }\n}\n"],"names":["Dropdown","FloatingMixin","LitElement","constructor","this","headerSlot","SlotController","headerEndSlot","submenuStack","isNavigating","expand","size","alwaysFloating","isShowingSubmenu","length","submenuStackRef","deepestSubmenu","handleAlwaysFloatingChange","open","updateComplete","then","connectedCallback","super","toggle","querySelector","setAttribute","render","activeSubmenu","html","handleSubmenuNavigate","handleBlur","ifDefined","align","position","sideOffset","alignOffset","handleOpen","handleClose","handleBackClick","_a","label","isEmpty","slotName","e","relatedTarget","contains","popout","hide","event","preventDefault","stopPropagation","navigateBack","newTop","focusTarget","focus","clearSubmenuStack","eventTarget","target","tagName","handleOpenChange","list","scrollTop","topSubmenu","deactivateMobile","requestUpdate","removeAttribute","slice","submenu","customEvent","previousDeepest","newSubmenu","detail","moveFocusToButton","show","styles","componentStyle","style","shadowRootOptions","delegatesFocus","__decorate","query","prototype","state","property","reflect","type","Boolean","attribute","observe","customElement"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{_ as e}from"./tslib.es6-CmLYFWVC.js";import{css as t,LitElement as o,html as n}from"lit";import{query as i,state as s,customElement as r}from"lit/decorators.js";import{classMap as l}from"lit/directives/class-map.js";import{E as a}from"./EventController-BBOmvfLa.js";import{s as d}from"./Component-BJ5O5n8k.js";import"./Popout-CFtFoCaA.js";import"./positioning-D-K8Mueq.js";import"./DirectionController-ChvNGESZ.js";import"./LightDismissController-wcL1ziJa.js";import"./ShortcutController-CV5b0BZl.js";import"./tinykeys-DwvDXsEb.js";import"./ScrollbarController-BFC67Y2x.js";import"./observe-D0n0zOfU.js";import"./events-Bv6wNHwJ.js";const u=t`:host{display:block;--_n-submenu-focus-padding:2px}.n-dropdown-submenu-content{max-block-size:var(--_n-dropdown-max-block-size);max-inline-size:calc(var(--_n-dropdown-size)*1.5);min-inline-size:var(--_n-dropdown-size);overflow-y:auto;padding-block-end:var(--_n-submenu-content-padding-block,var(--n-space-s));padding-block-start:var(--_n-submenu-content-padding-block,var(--n-space-s))}:host([mobile-active]){--_n-submenu-content-padding-block:0}@media (max-width:35.9375em){.n-dropdown-submenu-content{max-block-size:70vh;max-inline-size:none}.n-dropdown-submenu-content.is-deepest-active{padding-block-end:var(--_n-submenu-focus-padding);padding-block-start:var(--_n-submenu-focus-padding)}:host([mobile-active]) ::slotted([slot=trigger]){display:none}:host([mobile-active][has-active-child]) ::slotted(nord-dropdown-group),:host([mobile-active][has-active-child]) ::slotted(nord-dropdown-item),:host([mobile-active][has-active-child]) ::slotted(nord-dropdown-submenu:not([mobile-active])){display:none}}::slotted(nord-dropdown-item){padding-inline-end:var(--n-space-s);padding-inline-start:var(--n-space-s)}::slotted(nord-dropdown-group){border-block-end:1px solid var(--n-color-border);margin-block-end:var(--n-space-s);padding-block-end:var(--n-space-s);padding-inline-end:var(--n-space-s);padding-inline-start:var(--n-space-s)}::slotted(nord-dropdown-group:last-child){border-block-end:0;margin-block-end:0;padding-block-end:0}`;let p=0,h=class extends o{constructor(){super(...arguments),this.mobileActive=!1,this.popoutId="nord-dropdown-submenu-popout-"+ ++p,this.events=new a(this),this.currentTriggerElement=null,this.popoutOpen=!1,this.mobileMediaQuery=window.matchMedia("(max-width: 35.9375em)"),this.isSmallScreen=this.mobileMediaQuery.matches,this.parentDropdownAlwaysFloating=!1,this.handleTriggerMouseEnter=()=>{var e;this.shouldUseMobileStack||(this.closeOtherSubmenus(),null===(e=this.popout)||void 0===e||e.show())},this.handleTriggerClick=e=>{var t;e.preventDefault(),e.stopImmediatePropagation(),this.shouldUseMobileStack?this.navigateIntoSubmenu():(this.closeOtherSubmenus(),null===(t=this.popout)||void 0===t||t.show())},this.handleTriggerKeydown=e=>{var t;if("ArrowRight"===e.key||"Enter"===e.key){if(e.preventDefault(),this.shouldUseMobileStack)return void this.navigateIntoSubmenu();this.closeOtherSubmenus(),null===(t=this.popout)||void 0===t||t.show(),this.updateComplete.then((()=>{var e;null===(e=this.querySelector("nord-dropdown-item"))||void 0===e||e.focus()}))}},this.handleContentKeydown=e=>{var t,o;if("ArrowLeft"===e.key){if(e.preventDefault(),e.stopPropagation(),this.shouldUseMobileStack&&this.mobileActive)return void(null===(t=this.closest("nord-dropdown"))||void 0===t||t.navigateBack());null===(o=this.popout)||void 0===o||o.hide(!0)}},this.handlePopoutOpen=()=>{this.popoutOpen=!0,this.closeOtherSubmenus()},this.handlePopoutClose=e=>{e.stopPropagation(),this.popoutOpen=!1},this.handleParentDropdownMouseOver=e=>{var t;if(this.shouldUseMobileStack)return;const o=e.target;"NORD-DROPDOWN-ITEM"===o.tagName&&!this.contains(o)&&this.popoutOpen&&(e.stopImmediatePropagation(),null===(t=this.popout)||void 0===t||t.hide())}}get shouldUseMobileStack(){return this.isSmallScreen&&!this.parentDropdownAlwaysFloating}get parentDropdown(){return this.closest("nord-dropdown")}get isInSubmenuStack(){const e=this.parentDropdown;return!!e&&e.submenuStackRef.includes(this)}get isDeepestInStack(){const e=this.parentDropdown;return!!e&&e.deepestSubmenu===this}connectedCallback(){super.connectedCallback();const e=this.querySelector('[slot="trigger"]');null==e||e.setAttribute("aria-haspopup","menu");const t=this.closest("nord-dropdown");t&&(this.parentDropdownAlwaysFloating=t.alwaysFloating,this.events.listen(t,"mouseover",this.handleParentDropdownMouseOver),this.parentObserver=new MutationObserver((e=>{for(const o of e)"always-floating"===o.attributeName&&(this.parentDropdownAlwaysFloating=t.alwaysFloating)})),this.parentObserver.observe(t,{attributes:!0,attributeFilter:["always-floating"]})),this.events.listen(this.mobileMediaQuery,"change",(e=>{this.isSmallScreen=e.matches,this.requestUpdate()}))}disconnectedCallback(){var e;super.disconnectedCallback(),null===(e=this.parentObserver)||void 0===e||e.disconnect()}render(){return this.shouldUseMobileStack&&this.mobileActive?n`<slot name="trigger"></slot><div class="${l({"n-dropdown-submenu-content":!0,active:this.isInSubmenuStack,"is-deepest-active":this.isDeepestInStack})}" @keydown="${this.handleContentKeydown}"><slot></slot></div>`:n`<slot name="trigger" aria-controls="${this.popoutId}" @slotchange="${this.handleTriggerSlotChange}"></slot><nord-popout id="${this.popoutId}" position="inline-end" always-floating @open="${this.handlePopoutOpen}" @close="${this.handlePopoutClose}"><div class="n-dropdown-submenu-content" @keydown="${this.handleContentKeydown}"><slot></slot></div></nord-popout>`}handleTriggerSlotChange(){var e;const t=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector('slot[name="trigger"]'),o=null==t?void 0:t.assignedElements()[0];if(this.currentTriggerElement&&this.currentTriggerElement!==o&&(this.currentTriggerElement.removeEventListener("mouseenter",this.handleTriggerMouseEnter),this.currentTriggerElement.removeEventListener("click",this.handleTriggerClick),this.currentTriggerElement.removeEventListener("keydown",this.handleTriggerKeydown)),this.currentTriggerElement=null!=o?o:null,!o)return;o.setAttribute("aria-haspopup","menu");const n=!window.matchMedia("(hover: hover)").matches;this.events.listen(o,"mouseenter",this.handleTriggerMouseEnter),n&&!this.isSmallScreen||this.events.listen(o,"click",this.handleTriggerClick),this.events.listen(o,"keydown",this.handleTriggerKeydown)}closeOtherSubmenus(){var e;if(this.shouldUseMobileStack)return;const t=null===(e=this.parentElement)||void 0===e?void 0:e.closest("nord-dropdown, nord-dropdown-submenu");t&&Array.from(t.querySelectorAll(":scope > nord-dropdown-submenu")).forEach((e=>{e!==this&&e.close()}))}deactivateMobile(){var e;this.mobileActive=!1,this.removeAttribute("mobile-active");const t=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector('slot[name="trigger"]'),o=null==t?void 0:t.assignedElements()[0];null==o||o.removeAttribute("aria-expanded")}get label(){var e,t,o,n;const i=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector('slot[name="trigger"]');return null!==(n=null===(o=null===(t=null==i?void 0:i.assignedElements()[0])||void 0===t?void 0:t.textContent)||void 0===o?void 0:o.trim())&&void 0!==n?n:""}close(){return this.mobileActive?(this.deactivateMobile(),Promise.resolve()):this.popout?this.popout.hide():Promise.reject(new Error("DropdownSubmenu: popout component not found or not ready"))}navigateIntoSubmenu(){this.mobileActive=!0,this.setAttribute("mobile-active",""),this.dispatchEvent(new CustomEvent("nord-submenu-navigate",{bubbles:!0,detail:{submenu:this}})),this.updateComplete.then((()=>{const e=this.querySelector(".n-dropdown-submenu-content"),t=null==e?void 0:e.querySelector("nord-dropdown-item");null==t||t.focus()}))}};h.styles=[d,u],e([i("nord-popout")],h.prototype,"popout",void 0),e([s()],h.prototype,"mobileActive",void 0),e([s()],h.prototype,"isSmallScreen",void 0),e([s()],h.prototype,"parentDropdownAlwaysFloating",void 0),h=e([r("nord-dropdown-submenu")],h);var c=h;export{c as default};
1
+ import{_ as e}from"./tslib.es6-CmLYFWVC.js";import{css as t,LitElement as o,html as n}from"lit";import{query as i,state as s,customElement as r}from"lit/decorators.js";import{classMap as l}from"lit/directives/class-map.js";import{E as a}from"./EventController-BBOmvfLa.js";import{s as d}from"./Component-BJ5O5n8k.js";import"./Popout-B6Hirj3y.js";import"./positioning-D-K8Mueq.js";import"./DirectionController-ChvNGESZ.js";import"./LightDismissController-wcL1ziJa.js";import"./ShortcutController-CV5b0BZl.js";import"./tinykeys-DwvDXsEb.js";import"./ScrollbarController-BFC67Y2x.js";import"./observe-D0n0zOfU.js";import"./events-Bv6wNHwJ.js";const u=t`:host{display:block;--_n-submenu-focus-padding:2px}.n-dropdown-submenu-content{max-block-size:var(--_n-dropdown-max-block-size);max-inline-size:calc(var(--_n-dropdown-size)*1.5);min-inline-size:var(--_n-dropdown-size);overflow-y:auto;padding-block-end:var(--_n-submenu-content-padding-block,var(--n-space-s));padding-block-start:var(--_n-submenu-content-padding-block,var(--n-space-s))}:host([mobile-active]){--_n-submenu-content-padding-block:0}@media (max-width:35.9375em){.n-dropdown-submenu-content{max-block-size:70vh;max-inline-size:none}.n-dropdown-submenu-content.is-deepest-active{padding-block-end:var(--_n-submenu-focus-padding);padding-block-start:var(--_n-submenu-focus-padding)}:host([mobile-active]) ::slotted([slot=trigger]){display:none}:host([mobile-active][has-active-child]) ::slotted(nord-dropdown-group),:host([mobile-active][has-active-child]) ::slotted(nord-dropdown-item),:host([mobile-active][has-active-child]) ::slotted(nord-dropdown-submenu:not([mobile-active])){display:none}}::slotted(nord-dropdown-item){padding-inline-end:var(--n-space-s);padding-inline-start:var(--n-space-s)}::slotted(nord-dropdown-group){border-block-end:1px solid var(--n-color-border);margin-block-end:var(--n-space-s);padding-block-end:var(--n-space-s);padding-inline-end:var(--n-space-s);padding-inline-start:var(--n-space-s)}::slotted(nord-dropdown-group:last-child){border-block-end:0;margin-block-end:0;padding-block-end:0}`;let p=0,h=class extends o{constructor(){super(...arguments),this.mobileActive=!1,this.popoutId="nord-dropdown-submenu-popout-"+ ++p,this.events=new a(this),this.currentTriggerElement=null,this.popoutOpen=!1,this.mobileMediaQuery=window.matchMedia("(max-width: 35.9375em)"),this.isSmallScreen=this.mobileMediaQuery.matches,this.parentDropdownAlwaysFloating=!1,this.handleTriggerMouseEnter=()=>{var e;this.shouldUseMobileStack||(this.closeOtherSubmenus(),null===(e=this.popout)||void 0===e||e.show())},this.handleTriggerClick=e=>{var t;e.preventDefault(),e.stopImmediatePropagation(),this.shouldUseMobileStack?this.navigateIntoSubmenu():(this.closeOtherSubmenus(),null===(t=this.popout)||void 0===t||t.show())},this.handleTriggerKeydown=e=>{var t;if("ArrowRight"===e.key||"Enter"===e.key){if(e.preventDefault(),this.shouldUseMobileStack)return void this.navigateIntoSubmenu();this.closeOtherSubmenus(),null===(t=this.popout)||void 0===t||t.show(),this.updateComplete.then((()=>{var e;null===(e=this.querySelector("nord-dropdown-item"))||void 0===e||e.focus()}))}},this.handleContentKeydown=e=>{var t,o;if("ArrowLeft"===e.key){if(e.preventDefault(),e.stopPropagation(),this.shouldUseMobileStack&&this.mobileActive)return void(null===(t=this.closest("nord-dropdown"))||void 0===t||t.navigateBack());null===(o=this.popout)||void 0===o||o.hide(!0)}},this.handlePopoutOpen=()=>{this.popoutOpen=!0,this.closeOtherSubmenus()},this.handlePopoutClose=e=>{e.stopPropagation(),this.popoutOpen=!1},this.handleParentDropdownMouseOver=e=>{var t;if(this.shouldUseMobileStack)return;const o=e.target;"NORD-DROPDOWN-ITEM"===o.tagName&&!this.contains(o)&&this.popoutOpen&&(e.stopImmediatePropagation(),null===(t=this.popout)||void 0===t||t.hide())}}get shouldUseMobileStack(){return this.isSmallScreen&&!this.parentDropdownAlwaysFloating}get parentDropdown(){return this.closest("nord-dropdown")}get isInSubmenuStack(){const e=this.parentDropdown;return!!e&&e.submenuStackRef.includes(this)}get isDeepestInStack(){const e=this.parentDropdown;return!!e&&e.deepestSubmenu===this}connectedCallback(){super.connectedCallback();const e=this.querySelector('[slot="trigger"]');null==e||e.setAttribute("aria-haspopup","menu");const t=this.closest("nord-dropdown");t&&(this.parentDropdownAlwaysFloating=t.alwaysFloating,this.events.listen(t,"mouseover",this.handleParentDropdownMouseOver),this.parentObserver=new MutationObserver((e=>{for(const o of e)"always-floating"===o.attributeName&&(this.parentDropdownAlwaysFloating=t.alwaysFloating)})),this.parentObserver.observe(t,{attributes:!0,attributeFilter:["always-floating"]})),this.events.listen(this.mobileMediaQuery,"change",(e=>{this.isSmallScreen=e.matches,this.requestUpdate()}))}disconnectedCallback(){var e;super.disconnectedCallback(),null===(e=this.parentObserver)||void 0===e||e.disconnect()}render(){return this.shouldUseMobileStack&&this.mobileActive?n`<slot name="trigger"></slot><div class="${l({"n-dropdown-submenu-content":!0,active:this.isInSubmenuStack,"is-deepest-active":this.isDeepestInStack})}" @keydown="${this.handleContentKeydown}"><slot></slot></div>`:n`<slot name="trigger" aria-controls="${this.popoutId}" @slotchange="${this.handleTriggerSlotChange}"></slot><nord-popout id="${this.popoutId}" position="inline-end" always-floating @open="${this.handlePopoutOpen}" @close="${this.handlePopoutClose}"><div class="n-dropdown-submenu-content" @keydown="${this.handleContentKeydown}"><slot></slot></div></nord-popout>`}handleTriggerSlotChange(){var e;const t=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector('slot[name="trigger"]'),o=null==t?void 0:t.assignedElements()[0];if(this.currentTriggerElement&&this.currentTriggerElement!==o&&(this.currentTriggerElement.removeEventListener("mouseenter",this.handleTriggerMouseEnter),this.currentTriggerElement.removeEventListener("click",this.handleTriggerClick),this.currentTriggerElement.removeEventListener("keydown",this.handleTriggerKeydown)),this.currentTriggerElement=null!=o?o:null,!o)return;o.setAttribute("aria-haspopup","menu");const n=!window.matchMedia("(hover: hover)").matches;this.events.listen(o,"mouseenter",this.handleTriggerMouseEnter),n&&!this.isSmallScreen||this.events.listen(o,"click",this.handleTriggerClick),this.events.listen(o,"keydown",this.handleTriggerKeydown)}closeOtherSubmenus(){var e;if(this.shouldUseMobileStack)return;const t=null===(e=this.parentElement)||void 0===e?void 0:e.closest("nord-dropdown, nord-dropdown-submenu");t&&Array.from(t.querySelectorAll(":scope > nord-dropdown-submenu")).forEach((e=>{e!==this&&e.close()}))}deactivateMobile(){var e;this.mobileActive=!1,this.removeAttribute("mobile-active");const t=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector('slot[name="trigger"]'),o=null==t?void 0:t.assignedElements()[0];null==o||o.removeAttribute("aria-expanded")}get label(){var e,t,o,n;const i=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector('slot[name="trigger"]');return null!==(n=null===(o=null===(t=null==i?void 0:i.assignedElements()[0])||void 0===t?void 0:t.textContent)||void 0===o?void 0:o.trim())&&void 0!==n?n:""}close(){return this.mobileActive?(this.deactivateMobile(),Promise.resolve()):this.popout?this.popout.hide():Promise.reject(new Error("DropdownSubmenu: popout component not found or not ready"))}navigateIntoSubmenu(){this.mobileActive=!0,this.setAttribute("mobile-active",""),this.dispatchEvent(new CustomEvent("nord-submenu-navigate",{bubbles:!0,detail:{submenu:this}})),this.updateComplete.then((()=>{const e=this.querySelector(".n-dropdown-submenu-content"),t=null==e?void 0:e.querySelector("nord-dropdown-item");null==t||t.focus()}))}};h.styles=[d,u],e([i("nord-popout")],h.prototype,"popout",void 0),e([s()],h.prototype,"mobileActive",void 0),e([s()],h.prototype,"isSmallScreen",void 0),e([s()],h.prototype,"parentDropdownAlwaysFloating",void 0),h=e([r("nord-dropdown-submenu")],h);var c=h;export{c as default};
2
2
  //# sourceMappingURL=DropdownSubmenu.js.map
@@ -1,2 +1,2 @@
1
- import{_ as o}from"./tslib.es6-CmLYFWVC.js";import{css as t,html as i,nothing as r,LitElement as e}from"lit";import{query as n,property as s,customElement as l}from"lit/decorators.js";import{repeat as a}from"lit/directives/repeat.js";import{L as d}from"./LightDismissController-wcL1ziJa.js";import{O as p}from"./OpenStateController-CCnZ7up6.js";import{i as c}from"./light-dom-styles-DXsbiKU9.js";import{D as m}from"./DraftComponentMixin-4qug5Rky.js";import h from"./Icon.js";import{LocalizeController as u}from"./LocalizeController.js";import{FilterAddButtonSelectEvent as j}from"./FilterAddButtonEvents.js";import"./Button.js";import"./DropdownGroup.js";import"./DropdownItem.js";import"./Popout-CFtFoCaA.js";import"./EventController-BBOmvfLa.js";import"./ShortcutController-CV5b0BZl.js";import"./tinykeys-DwvDXsEb.js";import"./events-Bv6wNHwJ.js";import"lit/directives/if-defined.js";import"lit/directives/unsafe-html.js";import"./observe-D0n0zOfU.js";import"./cond-CI1KbneT.js";import"./Component-BJ5O5n8k.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"lit/directives/ref.js";import"./LightDomController-DIwtVelV.js";import"./SlotController-Z6eG7LSZ.js";import"./FocusableMixin-BlQLNPdJ.js";import"./InputMixin-LetXsCyv.js";import"./Spinner.js";import"./DropdownItem-BYbOLth6.js";import"./positioning-D-K8Mueq.js";import"./DirectionController-ChvNGESZ.js";import"./ScrollbarController-BFC67Y2x.js";var f=Object.freeze({__proto__:null,default:'<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="m20 11h-9v9h-2v-9h-9v-2h9v-9h2v9h9z" fill="currentColor"/></svg>',tags:"nordicon interface add plus adding more",title:"interface-add"});const b=t`nord-filter-add-button{--_n-filter-add-button-list-inline-size:var(--n-filter-add-button-list-inline-size,250px);display:inline-flex}nord-filter-add-button .n-filter-add-list{max-block-size:330px;max-inline-size:calc(var(--_n-filter-add-button-list-inline-size)*1.5);min-inline-size:var(--_n-filter-add-button-list-inline-size);overflow-y:auto;padding-block-end:var(--n-space-s);padding-block-start:var(--n-space-s);padding-inline-end:var(--n-space-s);padding-inline-start:var(--n-space-s)}nord-filter-add-button .n-filter-add-list nord-dropdown-group{border-block-end:1px solid var(--n-color-border);display:block;margin-block-end:var(--n-space-s);padding-block-end:var(--n-space-s)}nord-filter-add-button .n-filter-add-list nord-dropdown-group:last-child{border-block-end:0;margin-block-end:0;padding-block-end:0}nord-filter-add-button .n-filter-add-list nord-dropdown-item:hover{--n-dropdown-item-background-color:var(--n-color-active);--n-dropdown-item-color:var(--n-color-text)}@media (width <= 35.9375em){nord-filter-add-button .n-filter-add-list{max-block-size:70vh;max-inline-size:none}}`;h.registerIcon(f);let v=1,z=class extends(m(e)){constructor(){super(...arguments),this.filterAddButtonId="nord-filter-add-button-"+v++,this.localize=new u(this),this.dismiss=new d(this,{isOpen:()=>this.open,onDismiss:()=>this.hide(),isDismissible:o=>o!==this}),this.openState=new p(this,{isOpen:()=>this.open,setOpen:o=>{this.open=o},popout:()=>this.popout,isInert:()=>this.disabled}),this.options=[],this.disabled=!1,this.open=!1,this.size="s",this.handleTriggerClick=()=>{this.openState.toggle()}}connectedCallback(){super.connectedCallback(),c(this,b)}createRenderRoot(){return this}get groups(){const o=this.options;if(0===o.length)return[];return o.some((o=>!("id"in o)))?o:[{options:o}]}show(){this.openState.show()}hide(){this.openState.hide()}handleSelect(o){this.disabled||o.disabled||(this.dispatchEvent(new j(o.id)),this.hide())}render(){const o=`${this.filterAddButtonId}-popout`;return i`<nord-button class="n-filter-add-button" type="button" variant="dashed" size="${this.size}" aria-controls="${o}" aria-haspopup="menu" aria-expanded="${this.open?"true":"false"}" ?disabled="${this.disabled}" @click="${this.handleTriggerClick}"><nord-icon slot="start" name="interface-add" size="xs"></nord-icon>${this.localize.term("label")}</nord-button><nord-popout id="${o}" controlled always-floating @open="${this.openState.onPopoutOpen}" @close="${this.openState.onPopoutClose}"><div class="n-filter-add-list">${0===this.groups.length?r:a(this.groups,((o,t)=>t),(o=>{var t;return i`<nord-dropdown-group heading="${null!==(t=o.heading)&&void 0!==t?t:r}">${a(o.options,(o=>o.id),(o=>i`<nord-dropdown-item ?disabled="${o.disabled}" @click="${()=>this.handleSelect(o)}">${o.label}</nord-dropdown-item>`))}</nord-dropdown-group>`}))}</div></nord-popout>`}};o([n("nord-popout",!0)],z.prototype,"popout",void 0),o([s({attribute:!1})],z.prototype,"options",void 0),o([s({reflect:!0,type:Boolean})],z.prototype,"disabled",void 0),o([s({reflect:!0,type:Boolean})],z.prototype,"open",void 0),o([s({reflect:!0})],z.prototype,"size",void 0),z=o([l("nord-filter-add-button")],z);var g=z;export{j as FilterAddButtonSelectEvent,g as default};
1
+ import{_ as o}from"./tslib.es6-CmLYFWVC.js";import{css as t,html as i,nothing as r,LitElement as n}from"lit";import{query as e,property as s,customElement as l}from"lit/decorators.js";import{repeat as a}from"lit/directives/repeat.js";import{L as d}from"./LightDismissController-wcL1ziJa.js";import{O as p}from"./OpenStateController-CCnZ7up6.js";import{i as c}from"./light-dom-styles-DXsbiKU9.js";import{D as m}from"./DraftComponentMixin-4qug5Rky.js";import h from"./Icon.js";import{LocalizeController as u}from"./LocalizeController.js";import{FilterAddButtonSelectEvent as j}from"./FilterAddButtonEvents.js";import"./Button.js";import"./DropdownGroup.js";import"./DropdownItem.js";import"./Popout-B6Hirj3y.js";import"./EventController-BBOmvfLa.js";import"./ShortcutController-CV5b0BZl.js";import"./tinykeys-DwvDXsEb.js";import"./events-Bv6wNHwJ.js";import"lit/directives/if-defined.js";import"lit/directives/unsafe-html.js";import"./observe-D0n0zOfU.js";import"./cond-CI1KbneT.js";import"./Component-BJ5O5n8k.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"lit/directives/ref.js";import"./LightDomController-DIwtVelV.js";import"./SlotController-Z6eG7LSZ.js";import"./FocusableMixin-BlQLNPdJ.js";import"./InputMixin-LetXsCyv.js";import"./Spinner.js";import"./DropdownItem-BYbOLth6.js";import"./positioning-D-K8Mueq.js";import"./DirectionController-ChvNGESZ.js";import"./ScrollbarController-BFC67Y2x.js";var f=Object.freeze({__proto__:null,default:'<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="m20 11h-9v9h-2v-9h-9v-2h9v-9h2v9h9z" fill="currentColor"/></svg>',tags:"nordicon interface add plus adding more",title:"interface-add"});const b=t`nord-filter-add-button{--_n-filter-add-button-list-inline-size:var(--n-filter-add-button-list-inline-size,250px);display:inline-flex}nord-filter-add-button .n-filter-add-list{max-block-size:330px;max-inline-size:calc(var(--_n-filter-add-button-list-inline-size)*1.5);min-inline-size:var(--_n-filter-add-button-list-inline-size);overflow-y:auto;padding-block-end:var(--n-space-s);padding-block-start:var(--n-space-s);padding-inline-end:var(--n-space-s);padding-inline-start:var(--n-space-s)}nord-filter-add-button .n-filter-add-list nord-dropdown-group{border-block-end:1px solid var(--n-color-border);display:block;margin-block-end:var(--n-space-s);padding-block-end:var(--n-space-s)}nord-filter-add-button .n-filter-add-list nord-dropdown-group:last-child{border-block-end:0;margin-block-end:0;padding-block-end:0}nord-filter-add-button .n-filter-add-list nord-dropdown-item:hover{--n-dropdown-item-background-color:var(--n-color-active);--n-dropdown-item-color:var(--n-color-text)}@media (width <= 35.9375em){nord-filter-add-button .n-filter-add-list{max-block-size:70vh;max-inline-size:none}}`;h.registerIcon(f);let v=1,z=class extends(m(n)){constructor(){super(...arguments),this.filterAddButtonId="nord-filter-add-button-"+v++,this.localize=new u(this),this.dismiss=new d(this,{isOpen:()=>this.open,onDismiss:()=>this.hide(),isDismissible:o=>o!==this}),this.openState=new p(this,{isOpen:()=>this.open,setOpen:o=>{this.open=o},popout:()=>this.popout,isInert:()=>this.disabled}),this.options=[],this.disabled=!1,this.open=!1,this.size="s",this.handleTriggerClick=()=>{this.openState.toggle()}}connectedCallback(){super.connectedCallback(),c(this,b)}createRenderRoot(){return this}get groups(){const o=this.options;if(0===o.length)return[];return o.some((o=>!("id"in o)))?o:[{options:o}]}show(){this.openState.show()}hide(){this.openState.hide()}handleSelect(o){this.disabled||o.disabled||(this.dispatchEvent(new j(o.id)),this.hide())}render(){const o=`${this.filterAddButtonId}-popout`;return i`<nord-button class="n-filter-add-button" type="button" variant="dashed" size="${this.size}" aria-controls="${o}" aria-haspopup="menu" aria-expanded="${this.open?"true":"false"}" ?disabled="${this.disabled}" @click="${this.handleTriggerClick}"><nord-icon slot="start" name="interface-add" size="xs"></nord-icon>${this.localize.term("label")}</nord-button><nord-popout id="${o}" controlled always-floating @open="${this.openState.onPopoutOpen}" @close="${this.openState.onPopoutClose}"><div class="n-filter-add-list">${0===this.groups.length?r:a(this.groups,((o,t)=>t),(o=>{var t;return i`<nord-dropdown-group heading="${null!==(t=o.heading)&&void 0!==t?t:r}">${a(o.options,(o=>o.id),(o=>i`<nord-dropdown-item ?disabled="${o.disabled}" @click="${()=>this.handleSelect(o)}">${o.label}</nord-dropdown-item>`))}</nord-dropdown-group>`}))}</div></nord-popout>`}};o([e("nord-popout",!0)],z.prototype,"popout",void 0),o([s({attribute:!1})],z.prototype,"options",void 0),o([s({reflect:!0,type:Boolean})],z.prototype,"disabled",void 0),o([s({reflect:!0,type:Boolean})],z.prototype,"open",void 0),o([s({reflect:!0})],z.prototype,"size",void 0),z=o([l("nord-filter-add-button")],z);var g=z;export{j as FilterAddButtonSelectEvent,g as default};
2
2
  //# sourceMappingURL=FilterAddButton.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FilterAddButton.js","sources":["../../icons/lib/assets/interface-add.js","../src/filter-add-button/FilterAddButton.ts"],"sourcesContent":["export default '<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m20 11h-9v9h-2v-9h-9v-2h9v-9h2v9h9z\" fill=\"currentColor\"/></svg>';\nexport const title = \"interface-add\";\nexport const tags = \"nordicon interface add plus adding more\";\n","import * as addIcon from '@nordhealth/icons/lib/assets/interface-add.js'\nimport { html, LitElement, nothing } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { repeat } from 'lit/directives/repeat.js'\n\nimport { LightDismissController } from '../common/controllers/LightDismissController.js'\nimport { OpenStateController } from '../common/controllers/OpenStateController.js'\nimport { injectLightDomStyles } from '../common/light-dom-styles.js'\nimport { DraftComponentMixin } from '../common/mixins/DraftComponentMixin.js'\nimport Icon from '../icon/Icon.js'\nimport { LocalizeController } from '../localization/LocalizeController.js'\nimport style from './FilterAddButton.css'\nimport { FilterAddButtonSelectEvent } from './FilterAddButtonEvents.js'\nimport '../button/Button.js'\nimport '../dropdown-group/DropdownGroup.js'\nimport '../dropdown-item/DropdownItem.js'\nimport '../popout/Popout.js'\n\nIcon.registerIcon(addIcon)\n\nexport { FilterAddButtonSelectEvent } from './FilterAddButtonEvents.js'\n\n/** Per-instance counter so the popout/trigger ids stay unique in the light DOM. */\nlet filterAddButtonCount = 1\n\n/** A single, selectable option offered by the add-filter popout. */\nexport interface FilterAddOption {\n /** Identifies the option; sent in the `select` event when chosen. */\n id: string\n /** The human-readable label shown in the list. */\n label: string\n /** When `true`, the option cannot be selected. */\n disabled?: boolean\n}\n\n/** A heading-labelled cluster of options. */\nexport interface FilterAddGroup {\n /** Optional heading shown above the group's options. */\n heading?: string\n /** The options within the group. */\n options: FilterAddOption[]\n}\n\n/**\n * Filter Add Button opens a popout of available filters and emits the chosen one\n * so your app can add it to the bar. Pass a flat list of options, or group them\n * under headings; selecting one fires a `select` event with the option's `id`\n * and closes the popout.\n *\n * Like the other filter primitives it is intent-only: it does not track which\n * filters are active. Your app owns the active filters and decides what to do on\n * `select` (typically render a new [Filter Field](/components/filter-field/)).\n * Mirrors the Provet Cloud filter add button.\n *\n * @status draft\n * @category form\n * @lightDom true\n *\n * @fires {FilterAddButtonSelectEvent} select - Dispatched with the chosen option's `id` when an option is selected.\n * @fires {NordEvent} open - Dispatched when the popout is opened.\n * @fires {NordEvent} close - Dispatched when the popout is closed.\n *\n * @localization label - The text label for the add-filter button.\n *\n * @cssprop [--n-filter-add-button-list-inline-size=250px] - Controls the inline size, or width, of the popout list.\n *\n * @parent FilterBar\n */\n@customElement('nord-filter-add-button')\nexport default class FilterAddButton extends DraftComponentMixin(LitElement) {\n private filterAddButtonId = `nord-filter-add-button-${filterAddButtonCount++}`\n\n private localize = new LocalizeController<'nord-filter-add-button'>(this)\n\n @query('nord-popout', true) private popout?: HTMLElement & {\n show: () => Promise<unknown>\n hide: (moveFocusToButton?: boolean) => Promise<unknown>\n }\n\n private dismiss = new LightDismissController(this, {\n isOpen: () => this.open,\n onDismiss: () => this.hide(),\n isDismissible: node => node !== this,\n })\n\n // Coordinates `open` with the popout (drive show/hide, sync from its events,\n // emit one canonical open/close, reject opening while disabled).\n private openState = new OpenStateController(this, {\n isOpen: () => this.open,\n setOpen: (open) => { this.open = open },\n popout: () => this.popout,\n isInert: () => this.disabled,\n })\n\n /**\n * The options to offer in the popout. Either a flat list of options, or an\n * array of groups (each with an optional `heading` and its own `options`),\n * which renders dividers between the groups.\n */\n @property({ attribute: false }) options: FilterAddOption[] | FilterAddGroup[] = []\n\n /**\n * Makes the component disabled. This prevents users from being able to\n * interact with it and conveys its inactive state to assistive technologies.\n */\n @property({ reflect: true, type: Boolean }) disabled = false\n\n /**\n * Whether the popout is open. Set it to open or close the popout\n * programmatically.\n */\n @property({ reflect: true, type: Boolean }) open = false\n\n /**\n * The size of the button.\n */\n @property({ reflect: true }) size: 's' | 'm' | 'l' = 's'\n\n connectedCallback() {\n super.connectedCallback()\n injectLightDomStyles(this, style)\n }\n\n protected createRenderRoot() {\n return this\n }\n\n /** Normalises the options into groups, wrapping a flat list in a single group. */\n private get groups(): FilterAddGroup[] {\n const options = this.options\n if (options.length === 0) {\n return []\n }\n\n const isGrouped = options.some(option => !('id' in option))\n if (isGrouped) {\n return options as FilterAddGroup[]\n }\n\n return [{ options: options as FilterAddOption[] }]\n }\n\n /** Open the popout. */\n show() {\n this.openState.show()\n }\n\n /** Close the popout. */\n hide() {\n this.openState.hide()\n }\n\n private handleTriggerClick = () => {\n this.openState.toggle()\n }\n\n private handleSelect(option: FilterAddOption) {\n if (this.disabled || option.disabled) {\n return\n }\n\n /**\n * Dispatched with the chosen option's `id`. The consumer adds the\n * corresponding filter; the button does not mutate `options`.\n */\n this.dispatchEvent(new FilterAddButtonSelectEvent(option.id))\n this.hide()\n }\n\n render() {\n const popoutId = `${this.filterAddButtonId}-popout`\n\n return html`\n <nord-button\n class=\"n-filter-add-button\"\n type=\"button\"\n variant=\"dashed\"\n size=${this.size}\n aria-controls=${popoutId}\n aria-haspopup=\"menu\"\n aria-expanded=${this.open ? 'true' : 'false'}\n ?disabled=${this.disabled}\n @click=${this.handleTriggerClick}\n >\n <nord-icon slot=\"start\" name=\"interface-add\" size=\"xs\"></nord-icon>\n ${this.localize.term('label')}\n </nord-button>\n\n <nord-popout\n id=${popoutId}\n controlled\n always-floating\n @open=${this.openState.onPopoutOpen}\n @close=${this.openState.onPopoutClose}\n >\n <div class=\"n-filter-add-list\">\n ${this.groups.length === 0\n ? nothing\n : repeat(\n this.groups,\n (_group, index) => index,\n group => html`\n <nord-dropdown-group heading=${group.heading ?? nothing}>\n ${repeat(\n group.options,\n option => option.id,\n option => html`\n <nord-dropdown-item\n ?disabled=${option.disabled}\n @click=${() => this.handleSelect(option)}\n >\n ${option.label}\n </nord-dropdown-item>\n `,\n )}\n </nord-dropdown-group>\n `,\n )}\n </div>\n </nord-popout>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-filter-add-button': FilterAddButton\n }\n}\n"],"names":["Icon","registerIcon","addIcon","filterAddButtonCount","FilterAddButton","DraftComponentMixin","LitElement","constructor","this","filterAddButtonId","localize","LocalizeController","dismiss","LightDismissController","isOpen","open","onDismiss","hide","isDismissible","node","openState","OpenStateController","setOpen","popout","isInert","disabled","options","size","handleTriggerClick","toggle","connectedCallback","super","injectLightDomStyles","style","createRenderRoot","groups","length","some","option","show","handleSelect","dispatchEvent","FilterAddButtonSelectEvent","id","render","popoutId","html","term","onPopoutOpen","onPopoutClose","nothing","repeat","_group","index","group","_a","heading","label","__decorate","query","prototype","property","attribute","reflect","type","Boolean","customElement"],"mappings":"gkEAAe,6IAEK,gDADC,qmCCiBrBA,EAAKC,aAAaC,GAKlB,IAAIC,EAAuB,EA8CNC,EAAN,cAA8BC,EAAoBC,IAAlD,WAAAC,uBACLC,KAAAC,kBAAoB,0BAA0BN,IAE9CK,KAAAE,SAAW,IAAIC,EAA6CH,MAO5DA,KAAAI,QAAU,IAAIC,EAAuBL,KAAM,CACjDM,OAAQ,IAAMN,KAAKO,KACnBC,UAAW,IAAMR,KAAKS,OACtBC,cAAeC,GAAQA,IAASX,OAK1BA,KAAAY,UAAY,IAAIC,EAAoBb,KAAM,CAChDM,OAAQ,IAAMN,KAAKO,KACnBO,QAAUP,IAAWP,KAAKO,KAAOA,CAAI,EACrCQ,OAAQ,IAAMf,KAAKe,OACnBC,QAAS,IAAMhB,KAAKiB,WAQUjB,KAAOkB,QAAyC,GAMpClB,KAAQiB,UAAG,EAMXjB,KAAIO,MAAG,EAKtBP,KAAImB,KAAoB,IAoC7CnB,KAAkBoB,mBAAG,KAC3BpB,KAAKY,UAAUS,QAAQ,CAqE1B,CAxGC,iBAAAC,GACEC,MAAMD,oBACNE,EAAqBxB,KAAMyB,EAC5B,CAES,gBAAAC,GACR,OAAO1B,IACR,CAGD,UAAY2B,GACV,MAAMT,EAAUlB,KAAKkB,QACrB,GAAuB,IAAnBA,EAAQU,OACV,MAAO,GAIT,OADkBV,EAAQW,MAAKC,KAAY,OAAQA,KAE1CZ,EAGF,CAAC,CAAEA,QAASA,GACpB,CAGD,IAAAa,GACE/B,KAAKY,UAAUmB,MAChB,CAGD,IAAAtB,GACET,KAAKY,UAAUH,MAChB,CAMO,YAAAuB,CAAaF,GACf9B,KAAKiB,UAAYa,EAAOb,WAQ5BjB,KAAKiC,cAAc,IAAIC,EAA2BJ,EAAOK,KACzDnC,KAAKS,OACN,CAED,MAAA2B,GACE,MAAMC,EAAW,GAAGrC,KAAKC,2BAEzB,OAAOqC,CAAI,iFAKAtC,KAAKmB,wBACIkB,0CAEArC,KAAKO,KAAO,OAAS,uBACzBP,KAAKiB,qBACRjB,KAAKoB,0FAGZpB,KAAKE,SAASqC,KAAK,0CAIhBF,wCAGGrC,KAAKY,UAAU4B,yBACdxC,KAAKY,UAAU6B,iDAGG,IAAvBzC,KAAK2B,OAAOC,OACVc,EACAC,EACE3C,KAAK2B,QACL,CAACiB,EAAQC,IAAUA,IACnBC,UAAS,OAAAR,CAAI,iCACiC,QAAbS,EAAAD,EAAME,eAAO,IAAAD,EAAAA,EAAIL,MAC5CC,EACAG,EAAM5B,SACNY,GAAUA,EAAOK,KACjBL,GAAUQ,CAAI,kCAEER,EAAOb,qBACV,IAAMjB,KAAKgC,aAAaF,OAE/BA,EAAOmB,sDAKlB,yBAKd,GAnJmCC,EAAA,CAAnCC,EAAM,eAAe,IAGrBvD,EAAAwD,UAAA,cAAA,GAsB+BF,EAAA,CAA/BG,EAAS,CAAEC,WAAW,KAA2D1D,EAAAwD,UAAA,eAAA,GAMtCF,EAAA,CAA3CG,EAAS,CAAEE,SAAS,EAAMC,KAAMC,WAA2B7D,EAAAwD,UAAA,gBAAA,GAMhBF,EAAA,CAA3CG,EAAS,CAAEE,SAAS,EAAMC,KAAMC,WAAuB7D,EAAAwD,UAAA,YAAA,GAK3BF,EAAA,CAA5BG,EAAS,CAAEE,SAAS,KAAmC3D,EAAAwD,UAAA,YAAA,GA/CrCxD,EAAesD,EAAA,CADnCQ,EAAc,2BACM9D,SAAAA"}
1
+ {"version":3,"file":"FilterAddButton.js","sources":["../../icons/lib/assets/interface-add.js","../src/filter-add-button/FilterAddButton.ts"],"sourcesContent":["export default '<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m20 11h-9v9h-2v-9h-9v-2h9v-9h2v9h9z\" fill=\"currentColor\"/></svg>';\nexport const title = \"interface-add\";\nexport const tags = \"nordicon interface add plus adding more\";\n","import * as addIcon from '@nordhealth/icons/lib/assets/interface-add.js'\nimport { html, LitElement, nothing } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { repeat } from 'lit/directives/repeat.js'\n\nimport { LightDismissController } from '../common/controllers/LightDismissController.js'\nimport { OpenStateController } from '../common/controllers/OpenStateController.js'\nimport { injectLightDomStyles } from '../common/light-dom-styles.js'\nimport { DraftComponentMixin } from '../common/mixins/DraftComponentMixin.js'\nimport Icon from '../icon/Icon.js'\nimport { LocalizeController } from '../localization/LocalizeController.js'\nimport style from './FilterAddButton.css'\nimport { FilterAddButtonSelectEvent } from './FilterAddButtonEvents.js'\nimport '../button/Button.js'\nimport '../dropdown-group/DropdownGroup.js'\nimport '../dropdown-item/DropdownItem.js'\nimport '../popout/Popout.js'\n\nIcon.registerIcon(addIcon)\n\nexport { FilterAddButtonSelectEvent } from './FilterAddButtonEvents.js'\n\n/** Per-instance counter so the popout/trigger ids stay unique in the light DOM. */\nlet filterAddButtonCount = 1\n\n/** A single, selectable option offered by the add-filter popout. */\nexport interface FilterAddOption {\n /** Identifies the option; sent in the `select` event when chosen. */\n id: string\n /** The human-readable label shown in the list. */\n label: string\n /** When `true`, the option cannot be selected. */\n disabled?: boolean\n}\n\n/** A heading-labelled cluster of options. */\nexport interface FilterAddGroup {\n /** Optional heading shown above the group's options. */\n heading?: string\n /** The options within the group. */\n options: FilterAddOption[]\n}\n\n/**\n * Filter Add Button opens a popout of available filters and emits the chosen one\n * so your app can add it to the bar. Pass a flat list of options, or group them\n * under headings; selecting one fires a `select` event with the option's `id`\n * and closes the popout.\n *\n * Like the other filter primitives it is intent-only: it does not track which\n * filters are active. Your app owns the active filters and decides what to do on\n * `select` (typically render a new [Filter Field](/components/filter-field/)).\n * Mirrors the Provet Cloud filter add button.\n *\n * @status draft\n * @category form\n * @lightDom true\n *\n * @fires {FilterAddButtonSelectEvent} select - Dispatched with the chosen option's `id` when an option is selected.\n * @fires {NordEvent} open - Dispatched when the popout is opened.\n * @fires {NordEvent} close - Dispatched when the popout is closed.\n *\n * @localization label - The text label for the add-filter button.\n *\n * @cssprop [--n-filter-add-button-list-inline-size=250px] - Controls the inline size, or width, of the popout list.\n *\n * @parent FilterBar\n */\n@customElement('nord-filter-add-button')\nexport default class FilterAddButton extends DraftComponentMixin(LitElement) {\n private filterAddButtonId = `nord-filter-add-button-${filterAddButtonCount++}`\n\n private localize = new LocalizeController<'nord-filter-add-button'>(this)\n\n @query('nord-popout', true) private popout?: HTMLElement & {\n show: () => Promise<unknown>\n hide: (moveFocusToButton?: boolean) => Promise<unknown>\n }\n\n private dismiss = new LightDismissController(this, {\n isOpen: () => this.open,\n onDismiss: () => this.hide(),\n isDismissible: node => node !== this,\n })\n\n // Coordinates `open` with the popout (drive show/hide, sync from its events,\n // emit one canonical open/close, reject opening while disabled).\n private openState = new OpenStateController(this, {\n isOpen: () => this.open,\n setOpen: (open) => { this.open = open },\n popout: () => this.popout,\n isInert: () => this.disabled,\n })\n\n /**\n * The options to offer in the popout. Either a flat list of options, or an\n * array of groups (each with an optional `heading` and its own `options`),\n * which renders dividers between the groups.\n */\n @property({ attribute: false }) options: FilterAddOption[] | FilterAddGroup[] = []\n\n /**\n * Makes the component disabled. This prevents users from being able to\n * interact with it and conveys its inactive state to assistive technologies.\n */\n @property({ reflect: true, type: Boolean }) disabled = false\n\n /**\n * Whether the popout is open. Set it to open or close the popout\n * programmatically.\n */\n @property({ reflect: true, type: Boolean }) open = false\n\n /**\n * The size of the button.\n */\n @property({ reflect: true }) size: 's' | 'm' | 'l' = 's'\n\n connectedCallback() {\n super.connectedCallback()\n injectLightDomStyles(this, style)\n }\n\n protected createRenderRoot() {\n return this\n }\n\n /** Normalises the options into groups, wrapping a flat list in a single group. */\n private get groups(): FilterAddGroup[] {\n const options = this.options\n if (options.length === 0) {\n return []\n }\n\n const isGrouped = options.some(option => !('id' in option))\n if (isGrouped) {\n return options as FilterAddGroup[]\n }\n\n return [{ options: options as FilterAddOption[] }]\n }\n\n /** Open the popout. */\n show() {\n this.openState.show()\n }\n\n /** Close the popout. */\n hide() {\n this.openState.hide()\n }\n\n private handleTriggerClick = () => {\n this.openState.toggle()\n }\n\n private handleSelect(option: FilterAddOption) {\n if (this.disabled || option.disabled) {\n return\n }\n\n /**\n * Dispatched with the chosen option's `id`. The consumer adds the\n * corresponding filter; the button does not mutate `options`.\n */\n this.dispatchEvent(new FilterAddButtonSelectEvent(option.id))\n this.hide()\n }\n\n render() {\n const popoutId = `${this.filterAddButtonId}-popout`\n\n return html`\n <nord-button\n class=\"n-filter-add-button\"\n type=\"button\"\n variant=\"dashed\"\n size=${this.size}\n aria-controls=${popoutId}\n aria-haspopup=\"menu\"\n aria-expanded=${this.open ? 'true' : 'false'}\n ?disabled=${this.disabled}\n @click=${this.handleTriggerClick}\n >\n <nord-icon slot=\"start\" name=\"interface-add\" size=\"xs\"></nord-icon>\n ${this.localize.term('label')}\n </nord-button>\n\n <nord-popout\n id=${popoutId}\n controlled\n always-floating\n @open=${this.openState.onPopoutOpen}\n @close=${this.openState.onPopoutClose}\n >\n <div class=\"n-filter-add-list\">\n ${this.groups.length === 0\n ? nothing\n : repeat(\n this.groups,\n (_group, index) => index,\n group => html`\n <nord-dropdown-group heading=${group.heading ?? nothing}>\n ${repeat(\n group.options,\n option => option.id,\n option => html`\n <nord-dropdown-item\n ?disabled=${option.disabled}\n @click=${() => this.handleSelect(option)}\n >\n ${option.label}\n </nord-dropdown-item>\n `,\n )}\n </nord-dropdown-group>\n `,\n )}\n </div>\n </nord-popout>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nord-filter-add-button': FilterAddButton\n }\n}\n"],"names":["Icon","registerIcon","addIcon","filterAddButtonCount","FilterAddButton","DraftComponentMixin","LitElement","constructor","this","filterAddButtonId","localize","LocalizeController","dismiss","LightDismissController","isOpen","open","onDismiss","hide","isDismissible","node","openState","OpenStateController","setOpen","popout","isInert","disabled","options","size","handleTriggerClick","toggle","connectedCallback","super","injectLightDomStyles","style","createRenderRoot","groups","length","some","option","show","handleSelect","dispatchEvent","FilterAddButtonSelectEvent","id","render","popoutId","html","term","onPopoutOpen","onPopoutClose","nothing","repeat","_group","index","group","_a","heading","label","__decorate","query","prototype","property","attribute","reflect","type","Boolean","customElement"],"mappings":"4lEAAe,6IAEK,gDADC,qmCCiBrBA,EAAKC,aAAaC,GAKlB,IAAIC,EAAuB,EA8CNC,EAAN,cAA8BC,EAAoBC,IAAlD,WAAAC,uBACLC,KAAAC,kBAAoB,0BAA0BN,IAE9CK,KAAAE,SAAW,IAAIC,EAA6CH,MAO5DA,KAAAI,QAAU,IAAIC,EAAuBL,KAAM,CACjDM,OAAQ,IAAMN,KAAKO,KACnBC,UAAW,IAAMR,KAAKS,OACtBC,cAAeC,GAAQA,IAASX,OAK1BA,KAAAY,UAAY,IAAIC,EAAoBb,KAAM,CAChDM,OAAQ,IAAMN,KAAKO,KACnBO,QAAUP,IAAWP,KAAKO,KAAOA,CAAI,EACrCQ,OAAQ,IAAMf,KAAKe,OACnBC,QAAS,IAAMhB,KAAKiB,WAQUjB,KAAOkB,QAAyC,GAMpClB,KAAQiB,UAAG,EAMXjB,KAAIO,MAAG,EAKtBP,KAAImB,KAAoB,IAoC7CnB,KAAkBoB,mBAAG,KAC3BpB,KAAKY,UAAUS,QAAQ,CAqE1B,CAxGC,iBAAAC,GACEC,MAAMD,oBACNE,EAAqBxB,KAAMyB,EAC5B,CAES,gBAAAC,GACR,OAAO1B,IACR,CAGD,UAAY2B,GACV,MAAMT,EAAUlB,KAAKkB,QACrB,GAAuB,IAAnBA,EAAQU,OACV,MAAO,GAIT,OADkBV,EAAQW,MAAKC,KAAY,OAAQA,KAE1CZ,EAGF,CAAC,CAAEA,QAASA,GACpB,CAGD,IAAAa,GACE/B,KAAKY,UAAUmB,MAChB,CAGD,IAAAtB,GACET,KAAKY,UAAUH,MAChB,CAMO,YAAAuB,CAAaF,GACf9B,KAAKiB,UAAYa,EAAOb,WAQ5BjB,KAAKiC,cAAc,IAAIC,EAA2BJ,EAAOK,KACzDnC,KAAKS,OACN,CAED,MAAA2B,GACE,MAAMC,EAAW,GAAGrC,KAAKC,2BAEzB,OAAOqC,CAAI,iFAKAtC,KAAKmB,wBACIkB,0CAEArC,KAAKO,KAAO,OAAS,uBACzBP,KAAKiB,qBACRjB,KAAKoB,0FAGZpB,KAAKE,SAASqC,KAAK,0CAIhBF,wCAGGrC,KAAKY,UAAU4B,yBACdxC,KAAKY,UAAU6B,iDAGG,IAAvBzC,KAAK2B,OAAOC,OACVc,EACAC,EACE3C,KAAK2B,QACL,CAACiB,EAAQC,IAAUA,IACnBC,UAAS,OAAAR,CAAI,iCACiC,QAAbS,EAAAD,EAAME,eAAO,IAAAD,EAAAA,EAAIL,MAC5CC,EACAG,EAAM5B,SACNY,GAAUA,EAAOK,KACjBL,GAAUQ,CAAI,kCAEER,EAAOb,qBACV,IAAMjB,KAAKgC,aAAaF,OAE/BA,EAAOmB,sDAKlB,yBAKd,GAnJmCC,EAAA,CAAnCC,EAAM,eAAe,IAGrBvD,EAAAwD,UAAA,cAAA,GAsB+BF,EAAA,CAA/BG,EAAS,CAAEC,WAAW,KAA2D1D,EAAAwD,UAAA,eAAA,GAMtCF,EAAA,CAA3CG,EAAS,CAAEE,SAAS,EAAMC,KAAMC,WAA2B7D,EAAAwD,UAAA,gBAAA,GAMhBF,EAAA,CAA3CG,EAAS,CAAEE,SAAS,EAAMC,KAAMC,WAAuB7D,EAAAwD,UAAA,YAAA,GAK3BF,EAAA,CAA5BG,EAAS,CAAEE,SAAS,KAAmC3D,EAAAwD,UAAA,YAAA,GA/CrCxD,EAAesD,EAAA,CADnCQ,EAAc,2BACM9D,SAAAA"}