@ngneers/controls 0.0.1-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/fesm2022/ngneers-controls-accordion.mjs +234 -0
  2. package/fesm2022/ngneers-controls-accordion.mjs.map +1 -0
  3. package/fesm2022/ngneers-controls-api-ng.mjs +959 -0
  4. package/fesm2022/ngneers-controls-api-ng.mjs.map +1 -0
  5. package/fesm2022/ngneers-controls-api-resize.mjs +712 -0
  6. package/fesm2022/ngneers-controls-api-resize.mjs.map +1 -0
  7. package/fesm2022/ngneers-controls-api.mjs +347 -0
  8. package/fesm2022/ngneers-controls-api.mjs.map +1 -0
  9. package/fesm2022/ngneers-controls-avatar.mjs +77 -0
  10. package/fesm2022/ngneers-controls-avatar.mjs.map +1 -0
  11. package/fesm2022/ngneers-controls-base.mjs +620 -0
  12. package/fesm2022/ngneers-controls-base.mjs.map +1 -0
  13. package/fesm2022/ngneers-controls-breadcrumb.mjs +100 -0
  14. package/fesm2022/ngneers-controls-breadcrumb.mjs.map +1 -0
  15. package/fesm2022/ngneers-controls-button-group.mjs +110 -0
  16. package/fesm2022/ngneers-controls-button-group.mjs.map +1 -0
  17. package/fesm2022/ngneers-controls-button.mjs +83 -0
  18. package/fesm2022/ngneers-controls-button.mjs.map +1 -0
  19. package/fesm2022/ngneers-controls-calendar-time-CJT5AFlA.mjs +74 -0
  20. package/fesm2022/ngneers-controls-calendar-time-CJT5AFlA.mjs.map +1 -0
  21. package/fesm2022/ngneers-controls-calendar.mjs +801 -0
  22. package/fesm2022/ngneers-controls-calendar.mjs.map +1 -0
  23. package/fesm2022/ngneers-controls-checkbox.mjs +63 -0
  24. package/fesm2022/ngneers-controls-checkbox.mjs.map +1 -0
  25. package/fesm2022/ngneers-controls-chip.mjs +55 -0
  26. package/fesm2022/ngneers-controls-chip.mjs.map +1 -0
  27. package/fesm2022/ngneers-controls-default-icons.mjs +82 -0
  28. package/fesm2022/ngneers-controls-default-icons.mjs.map +1 -0
  29. package/fesm2022/ngneers-controls-defer.mjs +72 -0
  30. package/fesm2022/ngneers-controls-defer.mjs.map +1 -0
  31. package/fesm2022/ngneers-controls-dialog.mjs +407 -0
  32. package/fesm2022/ngneers-controls-dialog.mjs.map +1 -0
  33. package/fesm2022/ngneers-controls-directives.mjs +498 -0
  34. package/fesm2022/ngneers-controls-directives.mjs.map +1 -0
  35. package/fesm2022/ngneers-controls-drawer.mjs +271 -0
  36. package/fesm2022/ngneers-controls-drawer.mjs.map +1 -0
  37. package/fesm2022/ngneers-controls-edit-inplace.mjs +127 -0
  38. package/fesm2022/ngneers-controls-edit-inplace.mjs.map +1 -0
  39. package/fesm2022/ngneers-controls-errors.mjs +329 -0
  40. package/fesm2022/ngneers-controls-errors.mjs.map +1 -0
  41. package/fesm2022/ngneers-controls-filter.mjs +708 -0
  42. package/fesm2022/ngneers-controls-filter.mjs.map +1 -0
  43. package/fesm2022/ngneers-controls-hint.mjs +153 -0
  44. package/fesm2022/ngneers-controls-hint.mjs.map +1 -0
  45. package/fesm2022/ngneers-controls-i18n-translations-de.mjs +170 -0
  46. package/fesm2022/ngneers-controls-i18n-translations-de.mjs.map +1 -0
  47. package/fesm2022/ngneers-controls-i18n-translations-en.mjs +170 -0
  48. package/fesm2022/ngneers-controls-i18n-translations-en.mjs.map +1 -0
  49. package/fesm2022/ngneers-controls-i18n.mjs +57 -0
  50. package/fesm2022/ngneers-controls-i18n.mjs.map +1 -0
  51. package/fesm2022/ngneers-controls-icon.mjs +195 -0
  52. package/fesm2022/ngneers-controls-icon.mjs.map +1 -0
  53. package/fesm2022/ngneers-controls-inplace.mjs +150 -0
  54. package/fesm2022/ngneers-controls-inplace.mjs.map +1 -0
  55. package/fesm2022/ngneers-controls-input-field.mjs +165 -0
  56. package/fesm2022/ngneers-controls-input-field.mjs.map +1 -0
  57. package/fesm2022/ngneers-controls-input.mjs +72 -0
  58. package/fesm2022/ngneers-controls-input.mjs.map +1 -0
  59. package/fesm2022/ngneers-controls-item-view.mjs +473 -0
  60. package/fesm2022/ngneers-controls-item-view.mjs.map +1 -0
  61. package/fesm2022/ngneers-controls-list-box.mjs +281 -0
  62. package/fesm2022/ngneers-controls-list-box.mjs.map +1 -0
  63. package/fesm2022/ngneers-controls-mask-input.mjs +888 -0
  64. package/fesm2022/ngneers-controls-mask-input.mjs.map +1 -0
  65. package/fesm2022/ngneers-controls-menu.mjs +371 -0
  66. package/fesm2022/ngneers-controls-menu.mjs.map +1 -0
  67. package/fesm2022/ngneers-controls-message.mjs +30 -0
  68. package/fesm2022/ngneers-controls-message.mjs.map +1 -0
  69. package/fesm2022/ngneers-controls-number-input.mjs +366 -0
  70. package/fesm2022/ngneers-controls-number-input.mjs.map +1 -0
  71. package/fesm2022/ngneers-controls-paginator.mjs +129 -0
  72. package/fesm2022/ngneers-controls-paginator.mjs.map +1 -0
  73. package/fesm2022/ngneers-controls-popover.mjs +215 -0
  74. package/fesm2022/ngneers-controls-popover.mjs.map +1 -0
  75. package/fesm2022/ngneers-controls-progress.mjs +98 -0
  76. package/fesm2022/ngneers-controls-progress.mjs.map +1 -0
  77. package/fesm2022/ngneers-controls-radio.mjs +152 -0
  78. package/fesm2022/ngneers-controls-radio.mjs.map +1 -0
  79. package/fesm2022/ngneers-controls-roving-focus.mjs +323 -0
  80. package/fesm2022/ngneers-controls-roving-focus.mjs.map +1 -0
  81. package/fesm2022/ngneers-controls-scroll-shadow.mjs +65 -0
  82. package/fesm2022/ngneers-controls-scroll-shadow.mjs.map +1 -0
  83. package/fesm2022/ngneers-controls-scroller.mjs +308 -0
  84. package/fesm2022/ngneers-controls-scroller.mjs.map +1 -0
  85. package/fesm2022/ngneers-controls-select-button.mjs +58 -0
  86. package/fesm2022/ngneers-controls-select-button.mjs.map +1 -0
  87. package/fesm2022/ngneers-controls-select.mjs +417 -0
  88. package/fesm2022/ngneers-controls-select.mjs.map +1 -0
  89. package/fesm2022/ngneers-controls-slider.mjs +167 -0
  90. package/fesm2022/ngneers-controls-slider.mjs.map +1 -0
  91. package/fesm2022/ngneers-controls-snackbar.mjs +414 -0
  92. package/fesm2022/ngneers-controls-snackbar.mjs.map +1 -0
  93. package/fesm2022/ngneers-controls-spin-buttons.mjs +126 -0
  94. package/fesm2022/ngneers-controls-spin-buttons.mjs.map +1 -0
  95. package/fesm2022/ngneers-controls-spinner.mjs +184 -0
  96. package/fesm2022/ngneers-controls-spinner.mjs.map +1 -0
  97. package/fesm2022/ngneers-controls-splitter.mjs +604 -0
  98. package/fesm2022/ngneers-controls-splitter.mjs.map +1 -0
  99. package/fesm2022/ngneers-controls-state.mjs +185 -0
  100. package/fesm2022/ngneers-controls-state.mjs.map +1 -0
  101. package/fesm2022/ngneers-controls-switch.mjs +39 -0
  102. package/fesm2022/ngneers-controls-switch.mjs.map +1 -0
  103. package/fesm2022/ngneers-controls-table.mjs +2634 -0
  104. package/fesm2022/ngneers-controls-table.mjs.map +1 -0
  105. package/fesm2022/ngneers-controls-tabs.mjs +336 -0
  106. package/fesm2022/ngneers-controls-tabs.mjs.map +1 -0
  107. package/fesm2022/ngneers-controls-tag.mjs +30 -0
  108. package/fesm2022/ngneers-controls-tag.mjs.map +1 -0
  109. package/fesm2022/ngneers-controls-toast.mjs +350 -0
  110. package/fesm2022/ngneers-controls-toast.mjs.map +1 -0
  111. package/fesm2022/ngneers-controls-toggle-button.mjs +70 -0
  112. package/fesm2022/ngneers-controls-toggle-button.mjs.map +1 -0
  113. package/fesm2022/ngneers-controls-tooltip.mjs +506 -0
  114. package/fesm2022/ngneers-controls-tooltip.mjs.map +1 -0
  115. package/fesm2022/ngneers-controls-tree.mjs +599 -0
  116. package/fesm2022/ngneers-controls-tree.mjs.map +1 -0
  117. package/fesm2022/ngneers-controls-upload.mjs +377 -0
  118. package/fesm2022/ngneers-controls-upload.mjs.map +1 -0
  119. package/fesm2022/ngneers-controls-utils-ng.mjs +411 -0
  120. package/fesm2022/ngneers-controls-utils-ng.mjs.map +1 -0
  121. package/fesm2022/ngneers-controls-utils.mjs +261 -0
  122. package/fesm2022/ngneers-controls-utils.mjs.map +1 -0
  123. package/fesm2022/ngneers-controls.mjs +6 -0
  124. package/fesm2022/ngneers-controls.mjs.map +1 -0
  125. package/package.json +302 -0
  126. package/types/ngneers-controls-accordion.d.ts +139 -0
  127. package/types/ngneers-controls-api-ng.d.ts +364 -0
  128. package/types/ngneers-controls-api-resize.d.ts +318 -0
  129. package/types/ngneers-controls-api.d.ts +145 -0
  130. package/types/ngneers-controls-avatar.d.ts +54 -0
  131. package/types/ngneers-controls-base.d.ts +277 -0
  132. package/types/ngneers-controls-breadcrumb.d.ts +272 -0
  133. package/types/ngneers-controls-button-group.d.ts +46 -0
  134. package/types/ngneers-controls-button.d.ts +48 -0
  135. package/types/ngneers-controls-calendar.d.ts +466 -0
  136. package/types/ngneers-controls-checkbox.d.ts +40 -0
  137. package/types/ngneers-controls-chip.d.ts +202 -0
  138. package/types/ngneers-controls-default-icons.d.ts +5 -0
  139. package/types/ngneers-controls-defer.d.ts +48 -0
  140. package/types/ngneers-controls-dialog.d.ts +399 -0
  141. package/types/ngneers-controls-directives.d.ts +171 -0
  142. package/types/ngneers-controls-drawer.d.ts +308 -0
  143. package/types/ngneers-controls-edit-inplace.d.ts +263 -0
  144. package/types/ngneers-controls-errors.d.ts +155 -0
  145. package/types/ngneers-controls-filter.d.ts +609 -0
  146. package/types/ngneers-controls-hint.d.ts +88 -0
  147. package/types/ngneers-controls-i18n-translations-de.d.ts +164 -0
  148. package/types/ngneers-controls-i18n-translations-en.d.ts +164 -0
  149. package/types/ngneers-controls-i18n.d.ts +186 -0
  150. package/types/ngneers-controls-icon.d.ts +68 -0
  151. package/types/ngneers-controls-inplace.d.ts +98 -0
  152. package/types/ngneers-controls-input-field.d.ts +248 -0
  153. package/types/ngneers-controls-input.d.ts +30 -0
  154. package/types/ngneers-controls-item-view.d.ts +215 -0
  155. package/types/ngneers-controls-list-box.d.ts +334 -0
  156. package/types/ngneers-controls-mask-input.d.ts +434 -0
  157. package/types/ngneers-controls-menu.d.ts +192 -0
  158. package/types/ngneers-controls-message.d.ts +21 -0
  159. package/types/ngneers-controls-number-input.d.ts +146 -0
  160. package/types/ngneers-controls-paginator.d.ts +255 -0
  161. package/types/ngneers-controls-popover.d.ts +116 -0
  162. package/types/ngneers-controls-progress.d.ts +49 -0
  163. package/types/ngneers-controls-radio.d.ts +91 -0
  164. package/types/ngneers-controls-roving-focus.d.ts +107 -0
  165. package/types/ngneers-controls-scroll-shadow.d.ts +25 -0
  166. package/types/ngneers-controls-scroller.d.ts +151 -0
  167. package/types/ngneers-controls-select-button.d.ts +51 -0
  168. package/types/ngneers-controls-select.d.ts +409 -0
  169. package/types/ngneers-controls-slider.d.ts +57 -0
  170. package/types/ngneers-controls-snackbar.d.ts +330 -0
  171. package/types/ngneers-controls-spin-buttons.d.ts +69 -0
  172. package/types/ngneers-controls-spinner.d.ts +117 -0
  173. package/types/ngneers-controls-splitter.d.ts +465 -0
  174. package/types/ngneers-controls-state.d.ts +102 -0
  175. package/types/ngneers-controls-switch.d.ts +18 -0
  176. package/types/ngneers-controls-table.d.ts +3127 -0
  177. package/types/ngneers-controls-tabs.d.ts +118 -0
  178. package/types/ngneers-controls-tag.d.ts +21 -0
  179. package/types/ngneers-controls-toast.d.ts +298 -0
  180. package/types/ngneers-controls-toggle-button.d.ts +48 -0
  181. package/types/ngneers-controls-tooltip.d.ts +189 -0
  182. package/types/ngneers-controls-tree.d.ts +409 -0
  183. package/types/ngneers-controls-upload.d.ts +347 -0
  184. package/types/ngneers-controls-utils-ng.d.ts +129 -0
  185. package/types/ngneers-controls-utils.d.ts +130 -0
  186. package/types/ngneers-controls.d.ts +2 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngneers-controls-mask-input.mjs","sources":["../../src/mask-input/masks.ts","../../src/mask-input/masks-date-time.ts","../../src/mask-input/helper.ts","../../src/mask-input/mask-input.ts","../../src/mask-input/mask-input.html","../../src/mask-input/ngneers-controls-mask-input.ts"],"sourcesContent":["import type { MaskInputCfg } from './types';\n\nconst phoneNumber = [\n '(',\n { kind: 'number', segment: 'areaCode', min: 0, max: 999, length: 3, placeholder: '000' },\n ')',\n ' ',\n { kind: 'number', segment: 'exchange', min: 0, max: 999, length: 3, placeholder: '000' },\n '-',\n { kind: 'number', segment: 'subscriber', min: 0, max: 9999, length: 4, placeholder: '0000' },\n] as const satisfies MaskInputCfg;\n\nconst creditCard = [\n { kind: 'number', segment: 'cardPart1', min: 0, max: 9999, length: 4, placeholder: '0000' },\n ' ',\n { kind: 'number', segment: 'cardPart2', min: 0, max: 9999, length: 4, placeholder: '0000' },\n ' ',\n { kind: 'number', segment: 'cardPart3', min: 0, max: 9999, length: 4, placeholder: '0000' },\n ' ',\n { kind: 'number', segment: 'cardPart4', min: 0, max: 9999, length: 4, placeholder: '0000' },\n] as const satisfies MaskInputCfg;\n\nconst ssn = [\n { kind: 'number', segment: 'areaNumber', min: 0, max: 999, length: 3, placeholder: '000' },\n '-',\n { kind: 'number', segment: 'groupNumber', min: 0, max: 99, length: 2, placeholder: '00' },\n '-',\n { kind: 'number', segment: 'serialNumber', min: 0, max: 9999, length: 4, placeholder: '0000' },\n] as const satisfies MaskInputCfg;\n\nconst zipCode = [\n { kind: 'number', segment: 'zipBase', min: 0, max: 99999, length: 5, placeholder: '00000' },\n '-',\n { kind: 'number', segment: 'zipPlus4', min: 0, max: 9999, length: 4, placeholder: '0000' },\n] as const satisfies MaskInputCfg;\n\nconst currency = [\n '$',\n {\n kind: 'number',\n segment: 'dollars',\n min: 0,\n max: 999999999,\n length: 9,\n placeholder: '000000000',\n },\n '.',\n { kind: 'number', segment: 'cents', min: 0, max: 99, length: 2, placeholder: '00' },\n] as const satisfies MaskInputCfg;\n\nconst percentage = [\n { kind: 'number', segment: 'percent', min: 0, max: 100, length: 3, placeholder: '000' },\n '%',\n] as const satisfies MaskInputCfg;\n\nexport const MASKS = {\n phoneNumber,\n creditCard,\n ssn,\n zipCode,\n currency,\n percentage,\n} as const satisfies Record<string, MaskInputCfg>;\n","import type { MaskInputCfg } from './types';\n\nconst formatSymbols = {\n d: 'day',\n M: 'month',\n y: 'year',\n H: 'hour24',\n h: 'hour12',\n m: 'minute',\n s: 'second',\n a: 'period',\n S: 'fractionalSecond',\n} as const;\n\ntype GroupedFormatSymbol = {\n symbol: (typeof formatSymbols)[keyof typeof formatSymbols];\n length: number;\n};\n\ntype Literal = {\n literal: string;\n};\n\ntype GroupedMaskSegment = GroupedFormatSymbol | Literal;\n\n/**\n * Returns the input mask configuration for a given date or time mask.\n * @param mask The mask string representing the date or time format.\n * For example, 'MM/dd/yyyy' for date, 'HH:mm:ss' for time, 'hh:mm:ss a' for 12-hour time with period.\n * @returns The input mask configuration that can be used with the input mask component.\n */\nexport function getDateOrTimeMask(mask: string): MaskInputCfg {\n const cfg: GroupedMaskSegment[] = [];\n let i = 0;\n while (i < mask.length) {\n const char = mask[i] as keyof typeof formatSymbols;\n const symbol = formatSymbols[char];\n if (symbol) {\n // Count how many times this symbol repeats\n let length = 1;\n while (i + length < mask.length && mask[i + length] === char) {\n length++;\n }\n cfg.push({ symbol, length });\n i += length;\n } else {\n cfg.push({ literal: char });\n i++;\n }\n }\n\n const result: MaskInputCfg = cfg.map(segment => {\n if ('literal' in segment) {\n return segment.literal;\n } else {\n const { symbol, length } = segment;\n // A single-letter token (length 1) yields a variable-length, non-padded field\n // (`length` omitted); a doubled token (length >= 2) yields a fixed, zero-padded field.\n const len = length >= 2 ? length : undefined;\n switch (symbol) {\n case 'day':\n return {\n segment: 'day',\n kind: 'number',\n min: 1,\n max: 31,\n length: len,\n placeholder: 'DD',\n } as const;\n case 'month':\n return {\n segment: 'month',\n kind: 'number',\n min: 1,\n max: 12,\n length: len,\n placeholder: 'MM',\n } as const;\n case 'year':\n return {\n segment: 'year',\n kind: 'number',\n min: 0,\n max: 9999,\n length: len,\n placeholder: 'YYYY',\n } as const;\n case 'hour24':\n return {\n segment: 'hour24',\n kind: 'number',\n min: 0,\n max: 23,\n length: len,\n placeholder: 'HH',\n } as const;\n case 'hour12':\n return {\n segment: 'hour12',\n kind: 'number',\n min: 1,\n max: 12,\n length: len,\n placeholder: 'HH',\n } as const;\n case 'minute':\n return {\n segment: 'minute',\n kind: 'number',\n min: 0,\n max: 59,\n length: len,\n placeholder: 'MM',\n } as const;\n case 'second':\n return {\n segment: 'second',\n kind: 'number',\n min: 0,\n max: 59,\n length: len,\n placeholder: 'SS',\n } as const;\n case 'period':\n return {\n segment: 'period',\n kind: 'enum',\n values: ['AM', 'PM'],\n } as const;\n case 'fractionalSecond':\n return {\n segment: 'fractionalSecond',\n kind: 'number',\n min: 0,\n max: 999,\n length: len,\n placeholder: 'SSS',\n } as const;\n }\n }\n });\n return result;\n}\n\nexport const DATE_TIME_MASKS = {\n date: getDateOrTimeMask('MM/dd/yyyy'),\n time: getDateOrTimeMask('HH:mm:ss'),\n timeShort: getDateOrTimeMask('HH:mm'),\n time12: getDateOrTimeMask('hh:mm:ss a'),\n};\n","import { MASKS } from './masks';\nimport { DATE_TIME_MASKS } from './masks-date-time';\n\nimport type { EnumField, Field, MaskInputCfg, NumberField, Part } from './types';\n\nexport type RenderToken =\n | { kind: 'sep'; text: string }\n | { kind: 'section'; ord: number; text: string; placeholder: boolean };\n\nexport function resolveMask(input: MaskInputCfg | string | null): Part[] | null {\n if (!input) return null;\n const cfg: MaskInputCfg | undefined =\n typeof input === 'string'\n ? ((MASKS as Record<string, MaskInputCfg>)[input] ??\n (DATE_TIME_MASKS as Record<string, MaskInputCfg>)[input])\n : input;\n if (!cfg) return null; // unknown raw string → unsupported\n\n return cfg.map<Part>(item => {\n if (typeof item === 'string') return { kind: 'sep', text: item };\n if (item.kind === 'number') {\n const maxLen = item.length ?? String(item.max).length;\n const field: NumberField = {\n kind: 'number',\n name: item.segment,\n min: item.min,\n max: item.max,\n maxLen,\n pad: item.length != null,\n placeholder: item.placeholder ?? '-'.repeat(maxLen),\n };\n return field;\n }\n // Guard an empty values array: Math.max(...[]) is -Infinity, which would\n // throw in '-'.repeat(maxLen). An empty enum is degenerate but must not crash.\n const maxLen = item.values.length === 0 ? 0 : Math.max(...item.values.map(v => v.length));\n const field: EnumField = {\n kind: 'enum',\n name: item.segment,\n values: [...item.values],\n maxLen,\n placeholder: item.placeholder ?? (maxLen > 0 ? '-'.repeat(maxLen) : ''),\n };\n return field;\n });\n}\n\nexport function fieldList(parts: Part[]): Field[] {\n return parts.filter((p): p is Field => p.kind !== 'sep');\n}\n\n/**\n * Index of the section whose horizontal box is nearest `clientX`.\n * - `clientX` left of the first section → 0\n * - `clientX` right of the last section → last index\n * - inside a section → that section\n * - in a gap/separator between two sections → the nearer one\n * Returns -1 for an empty list.\n */\nexport function nearestSectionIndex(\n rects: readonly { left: number; right: number }[],\n clientX: number\n): number {\n if (rects.length === 0) return -1;\n let best = 0;\n let bestDist = Infinity;\n for (let i = 0; i < rects.length; i++) {\n const r = rects[i];\n if (!r) continue;\n const dist = clientX < r.left ? r.left - clientX : clientX > r.right ? clientX - r.right : 0;\n if (dist < bestDist) {\n bestDist = dist;\n best = i;\n }\n if (dist === 0) break; // inside a section — exact hit\n }\n return best;\n}\n\n/**\n * Enforce the no-gaps invariant: scanning from index 0, once the first empty\n * field is seen, blank every field after it. A delete that empties an earlier\n * field therefore clears the now-orphaned later fields too.\n */\nexport function truncateGaps(values: string[]): string[] {\n let seenEmpty = false;\n return values.map(v => {\n if (seenEmpty) return '';\n if (!v) {\n seenEmpty = true;\n return '';\n }\n return v;\n });\n}\n\n// ---- New per-section pure functions ----\n\n/**\n * Type a char into ONE section. Returns the new section value + whether focus\n * should auto-advance to the next section, or null if the char is rejected.\n *\n * For number fields:\n * - Non-digit → null.\n * - If current is already complete (length===maxLen or value*10>max) a digit\n * starts a fresh value (replace).\n * - Otherwise appending is attempted. If the appended candidate exceeds max or\n * maxLen, restart with the bare digit instead.\n * - advance:true when the resulting value is isSectionComplete.\n *\n * For enum fields:\n * - Match by case-insensitive first char; on match returns {value, advance:true}.\n * - No match → null.\n *\n * NOTE: padding is NOT applied to the returned value — that is a display concern.\n */\nexport function typeIntoSection(\n field: Field,\n current: string,\n ch: string\n): { value: string; advance: boolean } | null {\n if (field.kind === 'enum') {\n const match = field.values.find(val => val[0]?.toLowerCase() === ch.toLowerCase());\n if (!match) return null;\n return { value: match, advance: true };\n }\n\n // number field — a single digit only (multi-char data is rejected outright).\n if (!/^\\d$/.test(ch)) return null;\n\n // If current section is already complete, start fresh\n const currentComplete = current !== '' && isSectionComplete(field, current);\n let candidate: string;\n if (currentComplete) {\n candidate = ch;\n } else {\n const appended = current + ch;\n // If appending would exceed max or length, restart with bare digit\n if (appended.length > field.maxLen || Number(appended) > field.max) {\n // A single digit that is itself out of range can never be a valid value\n // for this field (only possible for tiny fields with max < 10) → reject.\n if (Number(ch) > field.max) return null;\n candidate = ch;\n } else {\n candidate = appended;\n }\n }\n\n // A full-width candidate below the field minimum (e.g. '00' for a day/month\n // whose min is 1) is invalid — reject rather than letting it \"complete\".\n if (candidate.length === field.maxLen && Number(candidate) < field.min) return null;\n\n const advance = isSectionComplete(field, candidate);\n return { value: candidate, advance };\n}\n\n/**\n * Step/cycle a section value up (1) or down (-1). Empty defaults sensibly.\n *\n * For number fields:\n * - empty → field.min (no extra dir step on the empty→min transition).\n * - Non-empty: n = Number(current) + dir, wrap at >max → min, <min → max.\n * - Returns padded (padStart maxLen '0') iff field.pad.\n *\n * For enum fields:\n * - Find current (case-insensitive) in values; step by dir with wraparound.\n * - empty/not-found → first value (dir:1) or last value (dir:-1).\n */\nexport function stepSection(field: Field, current: string, dir: 1 | -1): string {\n if (field.kind === 'enum') {\n const i = field.values.findIndex(v => v.toLowerCase() === current.toLowerCase());\n if (i === -1) {\n return (dir === 1 ? field.values[0] : field.values[field.values.length - 1]) ?? '';\n }\n const next = (i + dir + field.values.length) % field.values.length;\n return field.values[next] ?? field.values[0] ?? '';\n }\n\n // number field\n if (current === '') {\n const min = field.min;\n return field.pad ? String(min).padStart(field.maxLen, '0') : String(min);\n }\n\n let n = Number(current) + dir;\n if (n > field.max) n = field.min;\n if (n < field.min) n = field.max;\n return field.pad ? String(n).padStart(field.maxLen, '0') : String(n);\n}\n\n/**\n * Whether a single section value is \"done\" (would auto-advance or is a fully\n * matched enum). Empty → always false.\n *\n * number: value.length===maxLen OR Number(value)*10 > max.\n * enum: value is literally in the values list (case-sensitive).\n */\nexport function isSectionComplete(field: Field, value: string): boolean {\n if (value === '') return false;\n if (field.kind === 'enum') return field.values.includes(value);\n if (!/^\\d+$/.test(value)) return false;\n const n = Number(value);\n // A complete number value must be within range AND either fill the width or be\n // unable to grow further (value*10 would exceed max).\n return n >= field.min && n <= field.max && (value.length === field.maxLen || n * 10 > field.max);\n}\n\n/**\n * Whether all fields in the mask have a complete value.\n * Empty field list → false.\n */\nexport function isComplete(parts: Part[], values: string[]): boolean {\n const fields = fieldList(parts);\n if (fields.length === 0) return false;\n return fields.every((field, i) => isSectionComplete(field, values[i] ?? ''));\n}\n\n/**\n * Render each part as a RenderToken for display. No offsets.\n *\n * Separator → {kind:'sep', text}.\n * Field → {kind:'section', ord, text, placeholder}:\n * - empty value → text=field.placeholder, placeholder=true\n * - filled → text=padded(number&&pad) or raw value, placeholder=false\n *\n * `ord` is the 0-based field ordinal (index among fields, not among all parts).\n *\n * When `activeOrd` is provided, a padded number field that is currently active\n * AND not yet complete renders its raw typed digits instead of zero-padded text.\n * This matches native date-field behaviour: padding is deferred until the section\n * is committed (complete or navigated away from).\n * When `activeOrd` is omitted, all non-empty padded fields are padded (preserving\n * the \"fully padded\" output for callers that don't track the active section).\n */\nexport function composeDisplay(parts: Part[], values: string[], activeOrd?: number): RenderToken[] {\n const tokens: RenderToken[] = [];\n let fieldOrd = 0;\n for (const part of parts) {\n if (part.kind === 'sep') {\n tokens.push({ kind: 'sep', text: part.text });\n } else {\n const o = fieldOrd;\n const value = values[o] ?? '';\n if (value === '') {\n tokens.push({ kind: 'section', ord: o, text: part.placeholder, placeholder: true });\n } else {\n const padded =\n part.kind === 'number' && part.pad && (o !== activeOrd || isSectionComplete(part, value));\n const text = padded ? value.padStart(part.maxLen, '0') : value;\n tokens.push({ kind: 'section', ord: o, text, placeholder: false });\n }\n fieldOrd++;\n }\n }\n return tokens;\n}\n\n/**\n * Compose the full serialized output string (padded per field definition).\n * Separators are appended verbatim. Number fields are padded iff field.pad.\n * Enum fields are verbatim. Empty values are included as-is (empty string).\n */\nexport function serialize(parts: Part[], values: string[]): string {\n let result = '';\n let fieldOrd = 0;\n for (const part of parts) {\n if (part.kind === 'sep') {\n result += part.text;\n } else {\n const value = values[fieldOrd] ?? '';\n if (part.kind === 'number' && part.pad) {\n result += value.padStart(part.maxLen, '0');\n } else {\n result += value;\n }\n fieldOrd++;\n }\n }\n return result;\n}\n\n// ---- Kept internals ----\n\n/**\n * Separator-aware string parser shared by `paste` and `deserialize`. Walks the\n * parts left→right with a cursor into `str`:\n * - **separator**: consume `sep.text` if present at the cursor; separators are\n * optional (so a no-separator paste like `'1234'` still works).\n * - **number field**: consume the maximal run of digits, capped at `maxLen`\n * (naturally stops at a non-digit such as a separator). Zero digits → leave\n * the field empty and stop. A chunk outside `[min,max]` → invalid.\n * - **enum field**: match a value (exact case-insensitive, else first char);\n * no match with chars remaining → invalid; no chars remaining → stop.\n *\n * The result is run through `truncateGaps` so a skipped middle field never\n * leaves a gap. `ok` is false when a field was outright invalid (out of range /\n * unmatched), in which case `values` holds the valid prefix parsed so far.\n */\n/** Per-field parse outcome: `stop` = nothing left to consume (partial input). */\ntype FieldParse = { value: string; cursor: number; ok: boolean; stop: boolean };\n\n/** Consume the maximal in-range digit run for a number field at `cursor`. */\nfunction takeNumberField(field: NumberField, str: string, cursor: number): FieldParse {\n let take = '';\n while (take.length < field.maxLen) {\n const c = str[cursor] ?? '';\n if (!/\\d/.test(c)) break;\n take += c;\n cursor++;\n }\n if (take === '') return { value: '', cursor, ok: true, stop: true };\n const n = Number(take);\n if (n < field.min || n > field.max) return { value: '', cursor, ok: false, stop: false };\n return { value: take, cursor, ok: true, stop: false };\n}\n\n/** Match an enum value (exact case-insensitive, else first char) at `cursor`. */\nfunction takeEnumField(field: EnumField, str: string, cursor: number): FieldParse {\n const rest = str.slice(cursor);\n if (rest === '') return { value: '', cursor, ok: true, stop: true };\n const exact = field.values.find(v => v.toUpperCase() === rest.slice(0, v.length).toUpperCase());\n const match = exact ?? field.values.find(v => v[0]?.toUpperCase() === rest[0]?.toUpperCase());\n if (!match) return { value: '', cursor, ok: false, stop: false };\n return { value: match, cursor: cursor + match.length, ok: true, stop: false };\n}\n\nfunction feedString(parts: Part[], str: string): { values: string[]; ok: boolean } {\n const fields = fieldList(parts);\n const values = fields.map(() => '');\n let cursor = 0;\n let o = 0; // field ordinal\n let ok = true;\n\n for (const part of parts) {\n if (part.kind === 'sep') {\n if (str.startsWith(part.text, cursor)) cursor += part.text.length;\n continue;\n }\n const res =\n part.kind === 'number'\n ? takeNumberField(part, str, cursor)\n : takeEnumField(part, str, cursor);\n if (!res.ok) {\n ok = false;\n break;\n }\n if (res.stop) break; // partial input — leave this and the rest empty\n values[o] = res.value;\n cursor = res.cursor;\n o++;\n }\n\n // Any unconsumed trailing input means the string didn't fully match the mask.\n // `paste` treats this as invalid (returns null); `deserialize` ignores `ok`\n // and keeps the best-effort prefix.\n if (cursor < str.length) ok = false;\n return { values: truncateGaps(values), ok };\n}\n\nexport function paste(parts: Part[], text: string): { values: string[]; offset: number } | null {\n const { values, ok } = feedString(parts, text);\n if (!ok) return null; // any invalid field rejects the whole paste\n // offset: count the committed characters in a simple left-to-right walk\n let offset = 0;\n let fieldOrd = 0;\n for (const part of parts) {\n if (part.kind === 'sep') {\n // include separator only if the next field has a value\n const nextValue = values[fieldOrd] ?? '';\n if (nextValue) offset += part.text.length;\n } else {\n const v = values[fieldOrd] ?? '';\n if (v) offset += v.length;\n fieldOrd++;\n }\n }\n return { values, offset };\n}\n\nexport function deserialize(parts: Part[], str: string): string[] {\n // Best-effort separator-aware parse. On an invalid/out-of-range field we keep\n // the valid prefix (feedString already stopped there, leaving the rest empty)\n // rather than producing garbage. Never throws.\n return feedString(parts, str).values;\n}\n","import {\n Component,\n computed,\n effect,\n ElementRef,\n inject,\n input,\n signal,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { domEventHandler } from '@ngneers/controls/api/ng';\nimport { NgnPt, provideSelf, ValueControlBase } from '@ngneers/controls/base';\nimport { I18n } from '@ngneers/controls/i18n';\nimport { NgnRovingGroup, NgnRovingItem } from '@ngneers/controls/roving-focus';\nimport { maskInputControlTemplate } from '@ngneers/controls-themes/templates/mask-input';\n\nimport {\n composeDisplay,\n deserialize,\n fieldList,\n isComplete,\n nearestSectionIndex,\n paste,\n resolveMask,\n serialize,\n stepSection,\n truncateGaps,\n typeIntoSection,\n} from './helper';\n\nimport type { MaskInputCfg } from './types';\n\n/**\n * @category control\n */\n@Component({\n selector: 'ngn-mask-input',\n templateUrl: './mask-input.html',\n imports: [NgnPt, NgnRovingGroup, NgnRovingItem],\n providers: [provideSelf(NgnMaskInput)],\n})\nexport class NgnMaskInput extends ValueControlBase<'maskInput', string | null> {\n public override readonly isFieldControl = true;\n protected readonly theme = this.injectThemeTemplate(maskInputControlTemplate, 'root');\n protected readonly i18n = inject(I18n).translations;\n\n /**\n * The mask to apply to the input. Can be a predefined mask key or a custom mask configuration.\n */\n public readonly mask = input<MaskInputCfg | string | null>(null);\n\n private readonly _parts = computed(() => resolveMask(this.mask()));\n\n private readonly _fields = computed(() => {\n const p = this._parts();\n return p ? fieldList(p) : [];\n });\n\n /**\n * Structural signature of the resolved mask — field kinds/names/widths and\n * separators, but deliberately NOT numeric min/max. The section values are\n * reset only when this changes, so a consumer narrowing a field's range (e.g.\n * a calendar shrinking the day field's max to the current month's length) does\n * not wipe what the user has already typed.\n */\n private readonly _structureSig = computed(() => {\n const parts = this._parts();\n if (!parts) return '';\n return parts\n .map(p =>\n p.kind === 'sep'\n ? `sep:${p.text}`\n : p.kind === 'number'\n ? `num:${p.name}:${p.maxLen}:${p.pad}`\n : `enum:${p.name}:${p.values.join('|')}`\n )\n .join(';');\n });\n\n /** Source of truth: one raw string per field ordinal. */\n protected readonly values = signal<string[]>([]);\n\n /** Whether the proxy input currently holds focus. The active-section\n * highlight and \"actively edited\" treatment only apply while focused. */\n protected readonly focused = signal(false);\n\n /** RenderTokens for template `@for` loop. While unfocused there is no active\n * section, so padded fields render in their resting (padded) form. */\n protected readonly tokens = computed(() => {\n const p = this._parts();\n if (!p) return [];\n return composeDisplay(p, this.values(), this.focused() ? this.activeOrd() : undefined);\n });\n\n /** The roving group on the proxy input element. */\n protected readonly rovingGroup = viewChild.required(NgnRovingGroup);\n\n /** The proxy input element reference. */\n private readonly _proxyRef = viewChild.required<ElementRef<HTMLInputElement>>('proxy');\n\n /** Active field ordinal (identity: item index === field ordinal). */\n protected readonly activeOrd = computed(() => this.rovingGroup().activeIndex());\n\n protected readonly proxyInputMode = computed(() => {\n const f = this._fields()[this.activeOrd()];\n return f?.kind === 'enum' ? 'text' : 'numeric';\n });\n\n protected readonly liveAnnouncement = signal<string>('');\n\n // ---- A11y helpers ----\n\n protected sectionValueNow(ord: number): number | null {\n const f = this._fields()[ord];\n const v = this.values()[ord] ?? '';\n if (!f || v === '') return null;\n if (f.kind === 'number') return Number(v);\n // enum: expose the option index so the spinbutton has a valid numeric value.\n const idx = f.values.indexOf(v);\n return idx >= 0 ? idx : null;\n }\n\n protected sectionMin(ord: number): number | null {\n const f = this._fields()[ord];\n if (!f) return null;\n return f.kind === 'number' ? f.min : 0;\n }\n\n protected sectionMax(ord: number): number | null {\n const f = this._fields()[ord];\n if (!f) return null;\n return f.kind === 'number' ? f.max : f.values.length - 1;\n }\n\n /** Accessible name for a section's `role=\"spinbutton\"` — the field's name. */\n protected sectionName(ord: number): string {\n return this._fields()[ord]?.name ?? '';\n }\n\n protected sectionValueText(ord: number): string {\n const f = this._fields()[ord];\n const v = this.values()[ord] ?? '';\n if (!f) return '';\n if (v === '') return f.placeholder;\n return v;\n }\n\n /**\n * Whether every section holds a finished value — i.e. the mask is fully\n * filled and a serialized output value has been emitted.\n */\n public readonly complete = computed(() => this.value() !== null);\n\n /** Whether no section holds any value (the whole field is blank). Lets a host\n * (e.g. calendar) distinguish a fully-cleared field from mid-typing, both of\n * which emit a `null` value. */\n public readonly empty = computed(() => this.values().every(v => v === ''));\n\n /**\n * Returns the resolved CSS class string for `section-active` from the theme,\n * used to highlight the currently active section span in the template.\n */\n protected readonly activeSectionClass = computed(() => this.theme.class('section-active'));\n\n // ---- Segment descriptions for sr ----\n\n protected readonly segmentDescriptions = computed(() => {\n const parts = this._parts();\n if (!parts) return [];\n return fieldList(parts).map(field => ({\n id: `seg-${field.name}-${this.inputId()}`,\n text:\n field.kind === 'number'\n ? this.i18n['maskInput_segmentRange']({\n name: field.name,\n min: field.min,\n max: field.max,\n })\n : field.values.join(this.i18n['maskInput_optionSeparator']()),\n }));\n });\n\n /** Returns the description span id for a given field ordinal, or null if none. */\n protected sectionDescId(ord: number): string | null {\n return this.segmentDescriptions()[ord]?.id ?? null;\n }\n\n constructor() {\n super();\n\n // Reset values only when the mask STRUCTURE changes (not a min/max-only\n // tweak), synchronously before the next render, so stale values from a\n // different mask are never composed against the new parts.\n let prevStructureSig: string | null = null;\n effect(() => {\n const sig = this._structureSig();\n if (prevStructureSig !== null && prevStructureSig !== sig) {\n this.values.set([]);\n }\n prevStructureSig = sig;\n });\n\n // External value → internal: guard against write-loop by comparing to serialized form.\n // Use untracked() when reading `values` so that internal typing changes do NOT re-trigger\n // this effect — it must only fire when the external `value` model (from the parent) changes.\n effect(() => {\n const parts = this._parts();\n if (!parts) return;\n const ext = this.value() ?? '';\n const current = untracked(() =>\n isComplete(parts, this.values()) ? serialize(parts, this.values()) : ''\n );\n if (ext !== current) {\n this.values.set(deserialize(parts, ext));\n }\n });\n\n // Internal values → external value model.\n effect(() => {\n const parts = this._parts();\n if (!parts) return;\n const vals = this.values();\n if (isComplete(parts, vals)) {\n this.value.set(serialize(parts, vals));\n } else {\n this.value.set(null);\n }\n });\n\n // Wire DOM events on the proxy input.\n domEventHandler(this._proxyRef, 'beforeinput', event => this._onBeforeInput(event));\n domEventHandler(this._proxyRef, 'keydown', event => this._onKeyDown(event));\n\n // Track focus so the active-section highlight only shows while focused.\n domEventHandler(this._proxyRef, 'focus', () => this.focused.set(true));\n domEventHandler(this._proxyRef, 'blur', () => this.focused.set(false));\n\n // Pointer down anywhere on the control: focus the proxy and select the\n // section nearest the pointer. Shared with field-delegated clicks via\n // `focusFromPointer`. Works standalone (no surrounding input-field).\n domEventHandler(this.element, 'pointerdown', event => {\n if (this.disabled()) return;\n event.preventDefault();\n this.focusFromPointer(event);\n });\n }\n\n /**\n * Places focus on the proxy input and selects the section nearest the\n * pointer's horizontal position. Invoked both by the control's own\n * `pointerdown` and by a surrounding `ngn-input-field` when its padding is\n * clicked (so a click \"above\" a section selects that section). Returns `true`\n * to signal the field it handled focus.\n */\n public override focusFromPointer(event: MouseEvent): boolean {\n if (this.disabled()) return false;\n this._proxyRef().nativeElement.focus();\n const ord = this._sectionIndexAt(event.clientX);\n if (ord >= 0) this.rovingGroup().setActive(ord);\n return true;\n }\n\n /** Clears every section (invoked by a surrounding field's clear button). */\n public override clearValue(): boolean {\n if (this.disabled() || this.readonly()) return false;\n this.values.set([]);\n return true;\n }\n\n /** Field ordinal of the section nearest `clientX`, or -1 when there are none. */\n private _sectionIndexAt(clientX: number): number {\n // Section spans carry role=\"spinbutton\" and appear in DOM order = field\n // ordinal order (matching the activeOrd identity mapping).\n const spans = this.element.nativeElement.querySelectorAll<HTMLElement>('[role=\"spinbutton\"]');\n const rects = Array.from(spans, el => el.getBoundingClientRect());\n return nearestSectionIndex(rects, clientX);\n }\n\n private _onBeforeInput(event: InputEvent): void {\n const parts = this._parts();\n if (!parts) return;\n if (this.disabled() || this.readonly()) return;\n\n event.preventDefault();\n\n if (event.inputType === 'insertFromPaste' || event.inputType === 'insertFromDrop') {\n const r = event.data ? paste(parts, event.data) : null;\n if (r) {\n this.values.set(r.values);\n // Advance to the next empty section or stay on last\n const fields = this._fields();\n const nextEmpty = r.values.findIndex(v => v === '');\n const targetOrd = nextEmpty >= 0 ? nextEmpty : fields.length - 1;\n this.rovingGroup().setActive(targetOrd);\n }\n return;\n }\n\n if (event.data) {\n const ord = this.activeOrd();\n const fields = this._fields();\n const f = fields[ord];\n if (!f) return;\n const current = this.values()[ord] ?? '';\n const r = typeIntoSection(f, current, event.data);\n if (r) {\n // Immutable update of the values array\n const newValues = [...this.values()];\n newValues[ord] = r.value;\n this.values.set(newValues);\n if (r.advance) {\n this.rovingGroup().next();\n }\n }\n }\n }\n\n private _onKeyDown(event: KeyboardEvent): void {\n const parts = this._parts();\n if (!parts || event.ctrlKey || event.metaKey || event.altKey) return;\n if (this.disabled() || this.readonly()) return;\n\n const ord = this.activeOrd();\n const fields = this._fields();\n const f = fields[ord];\n\n switch (event.key) {\n case 'Backspace':\n case 'Delete': {\n event.preventDefault();\n const currentVal = this.values()[ord] ?? '';\n if (currentVal === '') {\n // Already empty — step to previous section\n this.rovingGroup().prev();\n } else {\n // Clear the active section; then enforce no-gaps so any filled\n // fields after the newly-emptied one are also cleared.\n const newValues = [...this.values()];\n newValues[ord] = '';\n this.values.set(truncateGaps(newValues));\n }\n break;\n }\n case 'ArrowUp':\n case 'ArrowDown': {\n // The roving group is configured with horizontal orientation, so it\n // deliberately does NOT consume ArrowUp/ArrowDown — the mask owns them\n // for value stepping. This division is intentional, not coincidental:\n // Left/Right move between sections, Up/Down change the active value.\n event.preventDefault();\n if (!f) break;\n const dir: 1 | -1 = event.key === 'ArrowUp' ? 1 : -1;\n const newVal = stepSection(f, this.values()[ord] ?? '', dir);\n const newValues = [...this.values()];\n newValues[ord] = newVal;\n this.values.set(newValues);\n this.liveAnnouncement.set(`${f.name}: ${newVal}`);\n break;\n }\n // ArrowLeft/Right/Home/End are handled by the roving group — do not preventDefault\n }\n }\n}\n","<div [ptInt]=\"this\" [ptClass]=\"'root'\">\n <input\n #proxy\n #pg=\"ngnRovingGroup\"\n [ptInt]=\"this\"\n [ptClass]=\"'proxy'\"\n ngnRovingGroup\n rovingMode=\"activedescendant\"\n orientation=\"horizontal\"\n [attr.inputmode]=\"proxyInputMode()\"\n [attr.aria-roledescription]=\"i18n['maskInput_roleDescription']()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [disabled]=\"disabled()\"\n [attr.readonly]=\"readonly() || null\"\n tabindex=\"0\"\n />\n @for (tok of tokens(); track $index) {\n @if (tok.kind === 'sep') {\n <span [ptInt]=\"this\" [ptClass]=\"'separator'\" aria-hidden=\"true\">{{ tok.text }}</span>\n } @else {\n <span\n [ngnRovingItem]=\"pg\"\n role=\"spinbutton\"\n [attr.aria-label]=\"sectionName(tok.ord)\"\n [ptInt]=\"this\"\n [ptClass]=\"tok.placeholder ? 'section-placeholder' : 'section'\"\n [class]=\"focused() && activeOrd() === tok.ord ? activeSectionClass() : ''\"\n [attr.aria-valuenow]=\"sectionValueNow(tok.ord)\"\n [attr.aria-valuemin]=\"sectionMin(tok.ord)\"\n [attr.aria-valuemax]=\"sectionMax(tok.ord)\"\n [attr.aria-valuetext]=\"sectionValueText(tok.ord)\"\n [attr.aria-describedby]=\"sectionDescId(tok.ord)\"\n >{{ tok.text }}</span\n >\n }\n }\n @for (seg of segmentDescriptions(); track seg.id) {\n <span [id]=\"seg.id\" [ptInt]=\"this\" [ptClass]=\"'sr-only'\">{{ seg.text }}</span>\n }\n <span aria-live=\"polite\" [ptInt]=\"this\" [ptClass]=\"'sr-only'\">{{ liveAnnouncement() }}</span>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,371 @@
1
+ import * as i0 from '@angular/core';
2
+ import { viewChild, contentChild, input, computed, Directive, booleanAttribute, output, model, inject, viewChildren, signal, effect, Component, ElementRef, ViewContainerRef } from '@angular/core';
3
+ import { templateTypesFn, Platform, NgnTemplate, setComponentInput, domEventHandler } from '@ngneers/controls/api/ng';
4
+ import { NgTemplateOutlet } from '@angular/common';
5
+ import { RouterLink } from '@angular/router';
6
+ import { NgnBase, NgnPt, provideSelf } from '@ngneers/controls/base';
7
+ import { NgnAutofocus } from '@ngneers/controls/directives';
8
+ import { NgnIcon } from '@ngneers/controls/icon';
9
+ import { NgnPopover } from '@ngneers/controls/popover';
10
+ import { maybeCallback, NgnError } from '@ngneers/controls/utils';
11
+ import { generateElementId, effectWithPrevious, explicitEffect } from '@ngneers/controls/utils-ng';
12
+ import { menuControlTemplate } from '@ngneers/controls-themes/templates/menu';
13
+
14
+ class MenuTemplates extends NgnBase {
15
+ // Item template
16
+ _defaultItemTemplate = viewChild.required('defaultItemTemplate');
17
+ _userItemTemplate = contentChild('item', /* @ts-ignore */
18
+ ...(ngDevMode ? [{ debugName: "_userItemTemplate" }] : /* istanbul ignore next */ []));
19
+ /**
20
+ * Set a custom template for an item of the menu.
21
+ * Can also be set using an `<ng-template>` element with `#item` template reference variable.
22
+ */
23
+ templateItem = input(null, /* @ts-ignore */
24
+ ...(ngDevMode ? [{ debugName: "templateItem" }] : /* istanbul ignore next */ []));
25
+ itemTemplate = computed(() => this._userItemTemplate() ?? this.templateItem() ?? this._defaultItemTemplate(), /* @ts-ignore */
26
+ ...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
27
+ // Group template
28
+ _defaultGroupTemplate = viewChild.required('defaultGroupTemplate');
29
+ _userGroupTemplate = contentChild('group', /* @ts-ignore */
30
+ ...(ngDevMode ? [{ debugName: "_userGroupTemplate" }] : /* istanbul ignore next */ []));
31
+ /**
32
+ * Set a custom template for a group of items in the menu.
33
+ * Can also be set using an `<ng-template>` element with `#group` template reference variable.
34
+ */
35
+ templateGroup = input(null, /* @ts-ignore */
36
+ ...(ngDevMode ? [{ debugName: "templateGroup" }] : /* istanbul ignore next */ []));
37
+ groupTemplate = computed(() => this._userGroupTemplate() ?? this.templateGroup() ?? this._defaultGroupTemplate(), /* @ts-ignore */
38
+ ...(ngDevMode ? [{ debugName: "groupTemplate" }] : /* istanbul ignore next */ []));
39
+ /**
40
+ * Types for the dialog templates.
41
+ */
42
+ templateTypes = templateTypesFn();
43
+ internalTemplateTypes = templateTypesFn();
44
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: MenuTemplates, deps: null, target: i0.ɵɵFactoryTarget.Directive });
45
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.5", type: MenuTemplates, isStandalone: true, inputs: { templateItem: { classPropertyName: "templateItem", publicName: "templateItem", isSignal: true, isRequired: false, transformFunction: null }, templateGroup: { classPropertyName: "templateGroup", publicName: "templateGroup", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "_userItemTemplate", first: true, predicate: ["item"], descendants: true, isSignal: true }, { propertyName: "_userGroupTemplate", first: true, predicate: ["group"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_defaultItemTemplate", first: true, predicate: ["defaultItemTemplate"], descendants: true, isSignal: true }, { propertyName: "_defaultGroupTemplate", first: true, predicate: ["defaultGroupTemplate"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0 });
46
+ }
47
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: MenuTemplates, decorators: [{
48
+ type: Directive
49
+ }], propDecorators: { _defaultItemTemplate: [{ type: i0.ViewChild, args: ['defaultItemTemplate', { isSignal: true }] }], _userItemTemplate: [{ type: i0.ContentChild, args: ['item', { isSignal: true }] }], templateItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "templateItem", required: false }] }], _defaultGroupTemplate: [{ type: i0.ViewChild, args: ['defaultGroupTemplate', { isSignal: true }] }], _userGroupTemplate: [{ type: i0.ContentChild, args: ['group', { isSignal: true }] }], templateGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "templateGroup", required: false }] }] } });
50
+
51
+ /**
52
+ * @category control
53
+ */
54
+ class NgnMenu extends MenuTemplates {
55
+ theme = this.injectThemeTemplate(menuControlTemplate, {
56
+ submenu: () => this.isSubMenu(),
57
+ });
58
+ elementId = input(generateElementId(), /* @ts-ignore */
59
+ ...(ngDevMode ? [{ debugName: "elementId" }] : /* istanbul ignore next */ []));
60
+ /**
61
+ * The element to which the menu is anchored. Required if {@link popover} is `true`.
62
+ */
63
+ anchor = input(/* @ts-ignore */
64
+ ...(ngDevMode ? [undefined, { debugName: "anchor" }] : /* istanbul ignore next */ []));
65
+ /**
66
+ * The menu items to display.
67
+ */
68
+ items = input.required(/* @ts-ignore */
69
+ ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
70
+ /**
71
+ * Whether to automatically set ARIA attributes on the anchor element.
72
+ * @default true if anchor is an HTMLButtonElement, false otherwise.
73
+ */
74
+ autoAnchorAria = input(/* @ts-ignore */
75
+ ...(ngDevMode ? [undefined, { debugName: "autoAnchorAria" }] : /* istanbul ignore next */ []));
76
+ /**
77
+ * Whether the menu is a popover. Requires {@link anchor} to be set.
78
+ * @default false
79
+ */
80
+ popover = input(false, { ...(ngDevMode ? { debugName: "popover" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
81
+ /**
82
+ * The placement of the menu relative to the anchor element. Only used when {@link popover} is `true`.
83
+ * @default bottom-start
84
+ */
85
+ placement = input('bottom-start', /* @ts-ignore */
86
+ ...(ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []));
87
+ /**
88
+ * Icon type for children indicator (submenu indicator). If not set, a default icon will be used.
89
+ */
90
+ iconSubmenuIndicator = input(/* @ts-ignore */
91
+ ...(ngDevMode ? [undefined, { debugName: "iconSubmenuIndicator" }] : /* istanbul ignore next */ []));
92
+ /**
93
+ * Whether this menu is a submenu. Used internally.
94
+ * @internal
95
+ */
96
+ isSubMenu = input(false, { ...(ngDevMode ? { debugName: "isSubMenu" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
97
+ /**
98
+ * Whether to open submenus on hover. Defaults to true in popover mode.
99
+ * @default popover()
100
+ */
101
+ openSubmenuOnHover = input(false, { ...(ngDevMode ? { debugName: "openSubmenuOnHover" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
102
+ /**
103
+ * Emitted when the menu is fully closed.
104
+ */
105
+ closed = output();
106
+ /**
107
+ * Emitted when the menu is about to close.
108
+ */
109
+ closing = output();
110
+ /**
111
+ * Emitted when all menus should be closed (including parent menus). Used internally.
112
+ * @internal
113
+ */
114
+ closeAll = output();
115
+ /**
116
+ * Shows or hides the menu.
117
+ *
118
+ * You probably want to react to openChange events from outside to update your variable accordingly.
119
+ */
120
+ open = model(false, /* @ts-ignore */
121
+ ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
122
+ maybeCallback = maybeCallback;
123
+ _isTouchDevice = inject(Platform).isTouchDevice;
124
+ _popover = viewChild(NgnPopover, /* @ts-ignore */
125
+ ...(ngDevMode ? [{ debugName: "_popover" }] : /* istanbul ignore next */ []));
126
+ _menuItems = viewChildren('menuItem', /* @ts-ignore */
127
+ ...(ngDevMode ? [{ debugName: "_menuItems" }] : /* istanbul ignore next */ []));
128
+ _childMenus = viewChildren(NgnMenu, /* @ts-ignore */
129
+ ...(ngDevMode ? [{ debugName: "_childMenus" }] : /* istanbul ignore next */ []));
130
+ _openSubmenuOnHover = computed(() => this.openSubmenuOnHover() ?? this.popover(), /* @ts-ignore */
131
+ ...(ngDevMode ? [{ debugName: "_openSubmenuOnHover" }] : /* istanbul ignore next */ []));
132
+ autofocus = signal(false, /* @ts-ignore */
133
+ ...(ngDevMode ? [{ debugName: "autofocus" }] : /* istanbul ignore next */ []));
134
+ constructor() {
135
+ super();
136
+ effect(() => {
137
+ if (this.popover() && !this.anchor()) {
138
+ throw new NgnError('NgnMenu', 'When using popover mode, the anchor input must be provided.');
139
+ }
140
+ });
141
+ const autoAriaEnabled = computed(() => {
142
+ if (this.autoAnchorAria() !== undefined) {
143
+ return this.autoAnchorAria();
144
+ }
145
+ return this.anchor() instanceof HTMLButtonElement;
146
+ }, /* @ts-ignore */
147
+ ...(ngDevMode ? [{ debugName: "autoAriaEnabled" }] : /* istanbul ignore next */ []));
148
+ effectWithPrevious(this.anchor, (current, previous) => {
149
+ if (previous instanceof HTMLElement && autoAriaEnabled()) {
150
+ previous.removeAttribute('aria-controls');
151
+ previous.removeAttribute('aria-expanded');
152
+ previous.removeAttribute('aria-haspopup');
153
+ }
154
+ if (current instanceof HTMLElement && autoAriaEnabled()) {
155
+ current.setAttribute('aria-controls', `${this.elementId()}_menu`);
156
+ current.setAttribute('aria-haspopup', 'menu');
157
+ }
158
+ });
159
+ effect(() => {
160
+ const anchor = this.anchor();
161
+ if (anchor instanceof HTMLElement && autoAriaEnabled()) {
162
+ anchor.setAttribute('aria-expanded', this.open() ? 'true' : 'false');
163
+ }
164
+ });
165
+ explicitEffect([this.open], ([open]) => {
166
+ if (!open) {
167
+ if (this._popover()?.open()) {
168
+ this.hide();
169
+ }
170
+ }
171
+ if (open) {
172
+ if (!this._popover()?.open()) {
173
+ this.show(this.autofocus());
174
+ }
175
+ }
176
+ });
177
+ }
178
+ /**
179
+ * Shows the menu.
180
+ * @param focus Whether to focus the menu after showing it. Defaults to `true`.
181
+ */
182
+ show(focus = true) {
183
+ if (!this.popover()) {
184
+ throw new NgnError('NgnMenu', 'The show() method can only be used when popover mode is enabled.');
185
+ }
186
+ this._popover()?.show();
187
+ this.autofocus.set(focus);
188
+ }
189
+ /**
190
+ * Hides the menu.
191
+ * @param emitCloseEvent Whether to emit the close event. Defaults to `true`.
192
+ */
193
+ hide(emitCloseEvent = true) {
194
+ if (!this.popover()) {
195
+ throw new NgnError('NgnMenu', 'The hide() method can only be used when popover mode is enabled.');
196
+ }
197
+ this._popover()?.hide(emitCloseEvent);
198
+ }
199
+ /**
200
+ * Toggles the menu open or closed.
201
+ */
202
+ toggle() {
203
+ if (!this.popover()) {
204
+ throw new NgnError('NgnMenu', 'The toggle() method can only be used when popover mode is enabled.');
205
+ }
206
+ const popoverEl = this._popover();
207
+ if (!popoverEl) {
208
+ throw new NgnError('NgnMenu', 'Popover element is not available.');
209
+ }
210
+ if (popoverEl.open()) {
211
+ popoverEl.hide();
212
+ }
213
+ else {
214
+ popoverEl.open();
215
+ }
216
+ }
217
+ handleKeydown(event, subMenu) {
218
+ let currentIndex = this._menuItems()
219
+ .map(x => x.nativeElement)
220
+ .indexOf(event.target);
221
+ if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
222
+ event.preventDefault();
223
+ if (event.key === 'ArrowDown') {
224
+ currentIndex++;
225
+ }
226
+ else if (event.key === 'ArrowUp') {
227
+ currentIndex--;
228
+ }
229
+ if (currentIndex < 0) {
230
+ currentIndex = this._menuItems().length - 1;
231
+ }
232
+ else if (currentIndex >= this._menuItems().length) {
233
+ currentIndex = 0;
234
+ }
235
+ this._menuItems()[currentIndex]?.nativeElement.focus();
236
+ }
237
+ else if (event.key === 'ArrowRight' && subMenu) {
238
+ this.openChildMenu(subMenu, null, 'arrow');
239
+ }
240
+ else if (event.key === 'ArrowLeft' && this.isSubMenu()) {
241
+ this._popover()?.hide();
242
+ }
243
+ }
244
+ doCloseAll() {
245
+ this.hide();
246
+ // Delay the closing of the parents to ensure the children close first (for animation purposes)
247
+ requestAnimationFrame(() => {
248
+ this.closeAll.emit();
249
+ });
250
+ }
251
+ itemClicked(item) {
252
+ if (this.popover()) {
253
+ this.doCloseAll();
254
+ }
255
+ if ('callback' in item) {
256
+ item.callback?.();
257
+ }
258
+ }
259
+ closeChildMenus(closeBy, menuItem) {
260
+ if (closeBy === 'hover') {
261
+ if (this._isTouchDevice() || !this._openSubmenuOnHover()) {
262
+ return;
263
+ }
264
+ if (this._openSubmenuOnHover()) {
265
+ menuItem?.focus();
266
+ }
267
+ }
268
+ this._childMenus().forEach(menu => {
269
+ menu.hide(false);
270
+ });
271
+ }
272
+ openChildMenu(childMenu, menuItem, openBy) {
273
+ if (openBy === 'hover') {
274
+ if (this._isTouchDevice() || !this._openSubmenuOnHover()) {
275
+ return;
276
+ }
277
+ }
278
+ if (childMenu.open()) {
279
+ menuItem?.focus();
280
+ return;
281
+ }
282
+ this.closeChildMenus(openBy, menuItem);
283
+ setTimeout(() => {
284
+ childMenu.show(openBy === 'arrow');
285
+ });
286
+ }
287
+ popoverOpenChange(newState) {
288
+ this.open.set(newState);
289
+ }
290
+ popoverClosed() {
291
+ this.closed.emit();
292
+ }
293
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
294
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: NgnMenu, isStandalone: true, selector: "ngn-menu", inputs: { elementId: { classPropertyName: "elementId", publicName: "elementId", isSignal: true, isRequired: false, transformFunction: null }, anchor: { classPropertyName: "anchor", publicName: "anchor", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, autoAnchorAria: { classPropertyName: "autoAnchorAria", publicName: "autoAnchorAria", isSignal: true, isRequired: false, transformFunction: null }, popover: { classPropertyName: "popover", publicName: "popover", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, iconSubmenuIndicator: { classPropertyName: "iconSubmenuIndicator", publicName: "iconSubmenuIndicator", isSignal: true, isRequired: false, transformFunction: null }, isSubMenu: { classPropertyName: "isSubMenu", publicName: "isSubMenu", isSignal: true, isRequired: false, transformFunction: null }, openSubmenuOnHover: { classPropertyName: "openSubmenuOnHover", publicName: "openSubmenuOnHover", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", closing: "closing", closeAll: "closeAll", open: "openChange" }, providers: [provideSelf(NgnMenu)], viewQueries: [{ propertyName: "_popover", first: true, predicate: NgnPopover, descendants: true, isSignal: true }, { propertyName: "_menuItems", predicate: ["menuItem"], descendants: true, isSignal: true }, { propertyName: "_childMenus", predicate: NgnMenu, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (popover() && anchor(); as anchor) {\n <ngn-popover\n [ptInt]=\"this\"\n [ptDep]=\"'popover'\"\n [anchor]=\"anchor\"\n [options]=\"{ placement: placement(), padding: isSubMenu() ? 0 : undefined }\"\n (openChange)=\"popoverOpenChange($event)\"\n (closed)=\"popoverClosed()\"\n (closing)=\"closing.emit()\"\n >\n <ng-template #lazy>\n <ng-container *ngTemplateOutlet=\"menu\" />\n </ng-template>\n </ngn-popover>\n} @else {\n <ng-container *ngTemplateOutlet=\"menu\" />\n}\n\n<ng-template #menu>\n <div [ptInt]=\"this\" [ptClass]=\"'root'\" role=\"menu\" [tabIndex]=\"0\" [id]=\"elementId() + '_menu'\">\n @for (item of items(); track 'id' in item ? item.id : item) {\n @if ('separator' in item) {\n <ng-container *ngTemplateOutlet=\"separatorTemplate\" />\n } @else {\n <ng-container\n *ngTemplateOutlet=\"regularItemTemplate; context: { $implicit: item, index: $index }\"\n />\n }\n }\n </div>\n</ng-template>\n\n<ng-template #separatorTemplate>\n <hr [ptInt]=\"this\" [ptClass]=\"'separator'\" />\n</ng-template>\n\n<ng-template\n #regularItemTemplate\n [ngnTemplate]=\"internalTemplateTypes.regularItem\"\n let-item\n let-index=\"index\"\n>\n @if (item.children) {\n <button\n #menuItem\n role=\"menuitem\"\n aria-haspopup=\"menu\"\n [aria-expanded]=\"childMenu.open()\"\n [tabindex]=\"-1\"\n [ngnAutofocus]=\"open() && autofocus() && index === 0\"\n [ptInt]=\"this\"\n [ptClass]=\"{\n item: true,\n 'item-opened': childMenu.open(),\n }\"\n [disabled]=\"item.disabled\"\n (click)=\"openChildMenu(childMenu, menuItem, 'click')\"\n (mouseenter)=\"openChildMenu(childMenu, menuItem, 'hover')\"\n (keydown)=\"handleKeydown($event, childMenu)\"\n >\n <ng-container *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item }\" />\n </button>\n <ngn-menu\n #childMenu\n [anchor]=\"menuItem\"\n [items]=\"item.children\"\n [placement]=\"'right-start'\"\n [popover]=\"true\"\n [isSubMenu]=\"true\"\n (closing)=\"menuItem.focus()\"\n (closeAll)=\"doCloseAll()\"\n [elementId]=\"elementId() + '_submenu_' + item.id\"\n [openSubmenuOnHover]=\"openSubmenuOnHover()\"\n />\n } @else {\n <button\n #menuItem\n role=\"menuitem\"\n [tabindex]=\"-1\"\n [ngnAutofocus]=\"open() && autofocus() && index === 0\"\n [ptInt]=\"this\"\n [ptClass]=\"'item'\"\n [disabled]=\"item.disabled\"\n (keydown)=\"handleKeydown($event)\"\n (click)=\"itemClicked(item)\"\n (mouseenter)=\"closeChildMenus('hover', menuItem)\"\n [routerLink]=\"item.route\"\n >\n <ng-container *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item }\" />\n </button>\n }\n</ng-template>\n\n<ng-template #defaultItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\n {{ maybeCallback(item.label) }}\n @if (item.children) {\n <ngn-icon\n [ptInt]=\"this\"\n [ptClass]=\"'icon-children'\"\n defaultIcon=\"menu-submenu\"\n [icon]=\"iconSubmenuIndicator()\"\n />\n }\n</ng-template>\n\n<ng-template #defaultGroupTemplate></ng-template>\n", dependencies: [{ kind: "component", type: NgnMenu, selector: "ngn-menu", inputs: ["elementId", "anchor", "items", "autoAnchorAria", "popover", "placement", "iconSubmenuIndicator", "isSubMenu", "openSubmenuOnHover", "open"], outputs: ["closed", "closing", "closeAll", "openChange"] }, { kind: "directive", type: NgnPt, selector: "[ptInt]", inputs: ["ptInt", "ptClass", "ptDep"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgnTemplate, selector: "ng-template[ngnTemplate]", inputs: ["ngnTemplate"] }, { kind: "directive", type: NgnAutofocus, selector: "[ngnAutofocus]", inputs: ["ngnAutofocus"] }, { kind: "component", type: NgnPopover, selector: "ngn-popover", inputs: ["open", "anchor", "options", "hasShrinkableContent", "closeBy"], outputs: ["closed", "closing", "openChange"] }, { kind: "component", type: NgnIcon, selector: "ngn-icon", inputs: ["defaultIcon", "icon"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }] });
295
+ }
296
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnMenu, decorators: [{
297
+ type: Component,
298
+ args: [{ selector: 'ngn-menu', imports: [NgnPt, NgTemplateOutlet, NgnTemplate, NgnAutofocus, NgnPopover, NgnIcon, RouterLink], providers: [provideSelf(NgnMenu)], template: "@if (popover() && anchor(); as anchor) {\n <ngn-popover\n [ptInt]=\"this\"\n [ptDep]=\"'popover'\"\n [anchor]=\"anchor\"\n [options]=\"{ placement: placement(), padding: isSubMenu() ? 0 : undefined }\"\n (openChange)=\"popoverOpenChange($event)\"\n (closed)=\"popoverClosed()\"\n (closing)=\"closing.emit()\"\n >\n <ng-template #lazy>\n <ng-container *ngTemplateOutlet=\"menu\" />\n </ng-template>\n </ngn-popover>\n} @else {\n <ng-container *ngTemplateOutlet=\"menu\" />\n}\n\n<ng-template #menu>\n <div [ptInt]=\"this\" [ptClass]=\"'root'\" role=\"menu\" [tabIndex]=\"0\" [id]=\"elementId() + '_menu'\">\n @for (item of items(); track 'id' in item ? item.id : item) {\n @if ('separator' in item) {\n <ng-container *ngTemplateOutlet=\"separatorTemplate\" />\n } @else {\n <ng-container\n *ngTemplateOutlet=\"regularItemTemplate; context: { $implicit: item, index: $index }\"\n />\n }\n }\n </div>\n</ng-template>\n\n<ng-template #separatorTemplate>\n <hr [ptInt]=\"this\" [ptClass]=\"'separator'\" />\n</ng-template>\n\n<ng-template\n #regularItemTemplate\n [ngnTemplate]=\"internalTemplateTypes.regularItem\"\n let-item\n let-index=\"index\"\n>\n @if (item.children) {\n <button\n #menuItem\n role=\"menuitem\"\n aria-haspopup=\"menu\"\n [aria-expanded]=\"childMenu.open()\"\n [tabindex]=\"-1\"\n [ngnAutofocus]=\"open() && autofocus() && index === 0\"\n [ptInt]=\"this\"\n [ptClass]=\"{\n item: true,\n 'item-opened': childMenu.open(),\n }\"\n [disabled]=\"item.disabled\"\n (click)=\"openChildMenu(childMenu, menuItem, 'click')\"\n (mouseenter)=\"openChildMenu(childMenu, menuItem, 'hover')\"\n (keydown)=\"handleKeydown($event, childMenu)\"\n >\n <ng-container *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item }\" />\n </button>\n <ngn-menu\n #childMenu\n [anchor]=\"menuItem\"\n [items]=\"item.children\"\n [placement]=\"'right-start'\"\n [popover]=\"true\"\n [isSubMenu]=\"true\"\n (closing)=\"menuItem.focus()\"\n (closeAll)=\"doCloseAll()\"\n [elementId]=\"elementId() + '_submenu_' + item.id\"\n [openSubmenuOnHover]=\"openSubmenuOnHover()\"\n />\n } @else {\n <button\n #menuItem\n role=\"menuitem\"\n [tabindex]=\"-1\"\n [ngnAutofocus]=\"open() && autofocus() && index === 0\"\n [ptInt]=\"this\"\n [ptClass]=\"'item'\"\n [disabled]=\"item.disabled\"\n (keydown)=\"handleKeydown($event)\"\n (click)=\"itemClicked(item)\"\n (mouseenter)=\"closeChildMenus('hover', menuItem)\"\n [routerLink]=\"item.route\"\n >\n <ng-container *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item }\" />\n </button>\n }\n</ng-template>\n\n<ng-template #defaultItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\n {{ maybeCallback(item.label) }}\n @if (item.children) {\n <ngn-icon\n [ptInt]=\"this\"\n [ptClass]=\"'icon-children'\"\n defaultIcon=\"menu-submenu\"\n [icon]=\"iconSubmenuIndicator()\"\n />\n }\n</ng-template>\n\n<ng-template #defaultGroupTemplate></ng-template>\n" }]
299
+ }], ctorParameters: () => [], propDecorators: { elementId: [{ type: i0.Input, args: [{ isSignal: true, alias: "elementId", required: false }] }], anchor: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchor", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], autoAnchorAria: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoAnchorAria", required: false }] }], popover: [{ type: i0.Input, args: [{ isSignal: true, alias: "popover", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], iconSubmenuIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSubmenuIndicator", required: false }] }], isSubMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSubMenu", required: false }] }], openSubmenuOnHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "openSubmenuOnHover", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], closing: [{ type: i0.Output, args: ["closing"] }], closeAll: [{ type: i0.Output, args: ["closeAll"] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], _popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => NgnPopover), { isSignal: true }] }], _menuItems: [{ type: i0.ViewChildren, args: ['menuItem', { isSignal: true }] }], _childMenus: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => NgnMenu), { isSignal: true }] }] } });
300
+
301
+ /**
302
+ * Lazily creates (or reuses) an `NgnMenu` popover and shows it anchored either
303
+ * at a viewport point (context-menu style) or to an element. Returns the
304
+ * `ComponentRef` so callers can keep it for reuse and destroy it on teardown.
305
+ */
306
+ function openMenuAt(vcr, existing, items, anchor, placement) {
307
+ const menu = existing ?? vcr.createComponent(NgnMenu);
308
+ setComponentInput(menu, 'items', items);
309
+ setComponentInput(menu, 'anchor', anchor);
310
+ setComponentInput(menu, 'popover', true);
311
+ if (placement) {
312
+ setComponentInput(menu, 'placement', placement);
313
+ }
314
+ // Render the menu's own view synchronously so its `popover` viewChild
315
+ // resolves, then show it immediately. Deferring the show to a macrotask
316
+ // (setTimeout) makes the open latency depend on macrotask scheduling — under
317
+ // a busy host (e.g. a large table running frequent change detection) that
318
+ // callback is delayed noticeably, so the menu appears to open slowly. A
319
+ // synchronous change-detection + show opens deterministically regardless of
320
+ // host load. Guard against the host being torn down mid-call.
321
+ if (!menu.hostView.destroyed) {
322
+ menu.changeDetectorRef.detectChanges();
323
+ menu.instance.show();
324
+ }
325
+ return menu;
326
+ }
327
+
328
+ class NgnContextMenu {
329
+ _elementRef = inject(ElementRef);
330
+ _vcr = inject(ViewContainerRef);
331
+ _menu;
332
+ /**
333
+ * The menu items to display in the context menu opened on right-click.
334
+ */
335
+ ngnContextMenu = input.required(/* @ts-ignore */
336
+ ...(ngDevMode ? [{ debugName: "ngnContextMenu" }] : /* istanbul ignore next */ []));
337
+ constructor() {
338
+ domEventHandler(this._elementRef, 'contextmenu', this.handleClick.bind(this));
339
+ }
340
+ ngOnDestroy() {
341
+ this._menu?.destroy();
342
+ }
343
+ handleClick(event) {
344
+ if (event.button !== 2) {
345
+ return;
346
+ }
347
+ if (this._menu?.instance.open()) {
348
+ return;
349
+ }
350
+ event.preventDefault();
351
+ event.stopPropagation();
352
+ this._menu = openMenuAt(this._vcr, this._menu, this.ngnContextMenu(), {
353
+ x: event.clientX,
354
+ y: event.clientY,
355
+ });
356
+ return false;
357
+ }
358
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnContextMenu, deps: [], target: i0.ɵɵFactoryTarget.Directive });
359
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.5", type: NgnContextMenu, isStandalone: true, selector: "[ngnContextMenu]", inputs: { ngnContextMenu: { classPropertyName: "ngnContextMenu", publicName: "ngnContextMenu", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
360
+ }
361
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnContextMenu, decorators: [{
362
+ type: Directive,
363
+ args: [{ selector: '[ngnContextMenu]' }]
364
+ }], ctorParameters: () => [], propDecorators: { ngnContextMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngnContextMenu", required: true }] }] } });
365
+
366
+ /**
367
+ * Generated bundle index. Do not edit.
368
+ */
369
+
370
+ export { NgnContextMenu, NgnMenu, openMenuAt };
371
+ //# sourceMappingURL=ngneers-controls-menu.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngneers-controls-menu.mjs","sources":["../../src/menu/menu-templates.ts","../../src/menu/menu.ts","../../src/menu/menu.html","../../src/menu/open-menu-at.ts","../../src/menu/context-menu.ts","../../src/menu/ngneers-controls-menu.ts"],"sourcesContent":["import { computed, contentChild, Directive, input, TemplateRef, viewChild } from '@angular/core';\nimport { templateTypesFn } from '@ngneers/controls/api/ng';\nimport { NgnBase } from '@ngneers/controls/base';\n\nimport type { MenuItemDefault } from './types';\n\n@Directive()\nexport abstract class MenuTemplates extends NgnBase<'menu'> {\n // Item template\n private readonly _defaultItemTemplate =\n viewChild.required<TemplateRef<typeof this.templateTypes.item>>('defaultItemTemplate');\n private readonly _userItemTemplate =\n contentChild<TemplateRef<typeof this.templateTypes.item>>('item');\n /**\n * Set a custom template for an item of the menu.\n * Can also be set using an `<ng-template>` element with `#item` template reference variable.\n */\n public readonly templateItem = input<TemplateRef<typeof this.templateTypes.item> | null>(null);\n protected readonly itemTemplate = computed(\n () => this._userItemTemplate() ?? this.templateItem() ?? this._defaultItemTemplate()\n );\n\n // Group template\n private readonly _defaultGroupTemplate =\n viewChild.required<TemplateRef<unknown>>('defaultGroupTemplate');\n private readonly _userGroupTemplate = contentChild<TemplateRef<unknown>>('group');\n /**\n * Set a custom template for a group of items in the menu.\n * Can also be set using an `<ng-template>` element with `#group` template reference variable.\n */\n public readonly templateGroup = input<TemplateRef<unknown> | null>(null);\n protected readonly groupTemplate = computed(\n () => this._userGroupTemplate() ?? this.templateGroup() ?? this._defaultGroupTemplate()\n );\n\n /**\n * Types for the dialog templates.\n */\n public readonly templateTypes = templateTypesFn<{\n item: {\n $implicit: MenuItemDefault;\n };\n }>();\n\n protected readonly internalTemplateTypes = templateTypesFn<{\n regularItem: {\n $implicit: MenuItemDefault;\n index: number;\n };\n }>();\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n Component,\n computed,\n effect,\n ElementRef,\n inject,\n input,\n model,\n output,\n signal,\n viewChild,\n viewChildren,\n} from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { type Anchor, NgnTemplate, type Openable, Platform } from '@ngneers/controls/api/ng';\nimport { NgnPt, provideSelf } from '@ngneers/controls/base';\nimport { NgnAutofocus } from '@ngneers/controls/directives';\nimport { NgnIcon } from '@ngneers/controls/icon';\nimport { NgnPopover } from '@ngneers/controls/popover';\nimport { maybeCallback, NgnError } from '@ngneers/controls/utils';\nimport { effectWithPrevious, explicitEffect, generateElementId } from '@ngneers/controls/utils-ng';\nimport { menuControlTemplate } from '@ngneers/controls-themes/templates/menu';\n\nimport { MenuTemplates } from './menu-templates';\n\nimport type { MenuItem } from './types';\nimport type { Placement } from '@floating-ui/dom';\nimport type { IconType } from '@ngneers/controls-custom-types';\n\n/**\n * @category control\n */\n@Component({\n selector: 'ngn-menu',\n imports: [NgnPt, NgTemplateOutlet, NgnTemplate, NgnAutofocus, NgnPopover, NgnIcon, RouterLink],\n templateUrl: './menu.html',\n\n providers: [provideSelf(NgnMenu)],\n})\nexport class NgnMenu extends MenuTemplates implements Openable {\n protected readonly theme = this.injectThemeTemplate(menuControlTemplate, {\n submenu: () => this.isSubMenu(),\n });\n protected readonly elementId = input(generateElementId());\n /**\n * The element to which the menu is anchored. Required if {@link popover} is `true`.\n */\n public readonly anchor = input<Anchor>();\n /**\n * The menu items to display.\n */\n public readonly items = input.required<MenuItem[]>();\n /**\n * Whether to automatically set ARIA attributes on the anchor element.\n * @default true if anchor is an HTMLButtonElement, false otherwise.\n */\n public readonly autoAnchorAria = input<boolean>();\n /**\n * Whether the menu is a popover. Requires {@link anchor} to be set.\n * @default false\n */\n public readonly popover = input(false, { transform: booleanAttribute });\n /**\n * The placement of the menu relative to the anchor element. Only used when {@link popover} is `true`.\n * @default bottom-start\n */\n public readonly placement = input<Placement>('bottom-start');\n /**\n * Icon type for children indicator (submenu indicator). If not set, a default icon will be used.\n */\n public readonly iconSubmenuIndicator = input<IconType>();\n /**\n * Whether this menu is a submenu. Used internally.\n * @internal\n */\n public readonly isSubMenu = input(false, { transform: booleanAttribute });\n /**\n * Whether to open submenus on hover. Defaults to true in popover mode.\n * @default popover()\n */\n public readonly openSubmenuOnHover = input(false, { transform: booleanAttribute });\n\n /**\n * Emitted when the menu is fully closed.\n */\n public readonly closed = output<void>();\n /**\n * Emitted when the menu is about to close.\n */\n public readonly closing = output<void>();\n /**\n * Emitted when all menus should be closed (including parent menus). Used internally.\n * @internal\n */\n public readonly closeAll = output<void>();\n /**\n * Shows or hides the menu.\n *\n * You probably want to react to openChange events from outside to update your variable accordingly.\n */\n public readonly open = model(false);\n\n protected readonly maybeCallback = maybeCallback;\n\n private readonly _isTouchDevice = inject(Platform).isTouchDevice;\n private readonly _popover = viewChild(NgnPopover);\n private readonly _menuItems = viewChildren<ElementRef<HTMLElement>>('menuItem');\n private readonly _childMenus = viewChildren(NgnMenu);\n private readonly _openSubmenuOnHover = computed(\n () => this.openSubmenuOnHover() ?? this.popover()\n );\n protected readonly autofocus = signal(false);\n\n constructor() {\n super();\n effect(() => {\n if (this.popover() && !this.anchor()) {\n throw new NgnError(\n 'NgnMenu',\n 'When using popover mode, the anchor input must be provided.'\n );\n }\n });\n\n const autoAriaEnabled = computed(() => {\n if (this.autoAnchorAria() !== undefined) {\n return this.autoAnchorAria();\n }\n return this.anchor() instanceof HTMLButtonElement;\n });\n\n effectWithPrevious(this.anchor, (current, previous) => {\n if (previous instanceof HTMLElement && autoAriaEnabled()) {\n previous.removeAttribute('aria-controls');\n previous.removeAttribute('aria-expanded');\n previous.removeAttribute('aria-haspopup');\n }\n if (current instanceof HTMLElement && autoAriaEnabled()) {\n current.setAttribute('aria-controls', `${this.elementId()}_menu`);\n current.setAttribute('aria-haspopup', 'menu');\n }\n });\n\n effect(() => {\n const anchor = this.anchor();\n if (anchor instanceof HTMLElement && autoAriaEnabled()) {\n anchor.setAttribute('aria-expanded', this.open() ? 'true' : 'false');\n }\n });\n\n explicitEffect([this.open], ([open]) => {\n if (!open) {\n if (this._popover()?.open()) {\n this.hide();\n }\n }\n if (open) {\n if (!this._popover()?.open()) {\n this.show(this.autofocus());\n }\n }\n });\n }\n\n /**\n * Shows the menu.\n * @param focus Whether to focus the menu after showing it. Defaults to `true`.\n */\n public show(focus = true) {\n if (!this.popover()) {\n throw new NgnError(\n 'NgnMenu',\n 'The show() method can only be used when popover mode is enabled.'\n );\n }\n this._popover()?.show();\n this.autofocus.set(focus);\n }\n\n /**\n * Hides the menu.\n * @param emitCloseEvent Whether to emit the close event. Defaults to `true`.\n */\n public hide(emitCloseEvent = true) {\n if (!this.popover()) {\n throw new NgnError(\n 'NgnMenu',\n 'The hide() method can only be used when popover mode is enabled.'\n );\n }\n this._popover()?.hide(emitCloseEvent);\n }\n\n /**\n * Toggles the menu open or closed.\n */\n public toggle() {\n if (!this.popover()) {\n throw new NgnError(\n 'NgnMenu',\n 'The toggle() method can only be used when popover mode is enabled.'\n );\n }\n const popoverEl = this._popover();\n if (!popoverEl) {\n throw new NgnError('NgnMenu', 'Popover element is not available.');\n }\n if (popoverEl.open()) {\n popoverEl.hide();\n } else {\n popoverEl.open();\n }\n }\n\n protected handleKeydown(event: KeyboardEvent, subMenu?: NgnMenu) {\n let currentIndex = this._menuItems()\n .map(x => x.nativeElement)\n .indexOf(event.target as HTMLElement);\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n if (event.key === 'ArrowDown') {\n currentIndex++;\n } else if (event.key === 'ArrowUp') {\n currentIndex--;\n }\n if (currentIndex < 0) {\n currentIndex = this._menuItems().length - 1;\n } else if (currentIndex >= this._menuItems().length) {\n currentIndex = 0;\n }\n this._menuItems()[currentIndex]?.nativeElement.focus();\n } else if (event.key === 'ArrowRight' && subMenu) {\n this.openChildMenu(subMenu, null, 'arrow');\n } else if (event.key === 'ArrowLeft' && this.isSubMenu()) {\n this._popover()?.hide();\n }\n }\n\n protected doCloseAll() {\n this.hide();\n // Delay the closing of the parents to ensure the children close first (for animation purposes)\n requestAnimationFrame(() => {\n this.closeAll.emit();\n });\n }\n\n protected itemClicked(item: MenuItem) {\n if (this.popover()) {\n this.doCloseAll();\n }\n if ('callback' in item) {\n item.callback?.();\n }\n }\n\n protected closeChildMenus(\n closeBy: 'hover' | 'click' | 'arrow',\n menuItem: HTMLButtonElement | null\n ) {\n if (closeBy === 'hover') {\n if (this._isTouchDevice() || !this._openSubmenuOnHover()) {\n return;\n }\n if (this._openSubmenuOnHover()) {\n menuItem?.focus();\n }\n }\n this._childMenus().forEach(menu => {\n menu.hide(false);\n });\n }\n\n protected openChildMenu(\n childMenu: NgnMenu,\n menuItem: HTMLButtonElement | null,\n openBy: 'hover' | 'click' | 'arrow'\n ) {\n if (openBy === 'hover') {\n if (this._isTouchDevice() || !this._openSubmenuOnHover()) {\n return;\n }\n }\n if (childMenu.open()) {\n menuItem?.focus();\n return;\n }\n this.closeChildMenus(openBy, menuItem);\n setTimeout(() => {\n childMenu.show(openBy === 'arrow');\n });\n }\n\n protected popoverOpenChange(newState: boolean) {\n this.open.set(newState);\n }\n\n protected popoverClosed() {\n this.closed.emit();\n }\n}\n","@if (popover() && anchor(); as anchor) {\n <ngn-popover\n [ptInt]=\"this\"\n [ptDep]=\"'popover'\"\n [anchor]=\"anchor\"\n [options]=\"{ placement: placement(), padding: isSubMenu() ? 0 : undefined }\"\n (openChange)=\"popoverOpenChange($event)\"\n (closed)=\"popoverClosed()\"\n (closing)=\"closing.emit()\"\n >\n <ng-template #lazy>\n <ng-container *ngTemplateOutlet=\"menu\" />\n </ng-template>\n </ngn-popover>\n} @else {\n <ng-container *ngTemplateOutlet=\"menu\" />\n}\n\n<ng-template #menu>\n <div [ptInt]=\"this\" [ptClass]=\"'root'\" role=\"menu\" [tabIndex]=\"0\" [id]=\"elementId() + '_menu'\">\n @for (item of items(); track 'id' in item ? item.id : item) {\n @if ('separator' in item) {\n <ng-container *ngTemplateOutlet=\"separatorTemplate\" />\n } @else {\n <ng-container\n *ngTemplateOutlet=\"regularItemTemplate; context: { $implicit: item, index: $index }\"\n />\n }\n }\n </div>\n</ng-template>\n\n<ng-template #separatorTemplate>\n <hr [ptInt]=\"this\" [ptClass]=\"'separator'\" />\n</ng-template>\n\n<ng-template\n #regularItemTemplate\n [ngnTemplate]=\"internalTemplateTypes.regularItem\"\n let-item\n let-index=\"index\"\n>\n @if (item.children) {\n <button\n #menuItem\n role=\"menuitem\"\n aria-haspopup=\"menu\"\n [aria-expanded]=\"childMenu.open()\"\n [tabindex]=\"-1\"\n [ngnAutofocus]=\"open() && autofocus() && index === 0\"\n [ptInt]=\"this\"\n [ptClass]=\"{\n item: true,\n 'item-opened': childMenu.open(),\n }\"\n [disabled]=\"item.disabled\"\n (click)=\"openChildMenu(childMenu, menuItem, 'click')\"\n (mouseenter)=\"openChildMenu(childMenu, menuItem, 'hover')\"\n (keydown)=\"handleKeydown($event, childMenu)\"\n >\n <ng-container *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item }\" />\n </button>\n <ngn-menu\n #childMenu\n [anchor]=\"menuItem\"\n [items]=\"item.children\"\n [placement]=\"'right-start'\"\n [popover]=\"true\"\n [isSubMenu]=\"true\"\n (closing)=\"menuItem.focus()\"\n (closeAll)=\"doCloseAll()\"\n [elementId]=\"elementId() + '_submenu_' + item.id\"\n [openSubmenuOnHover]=\"openSubmenuOnHover()\"\n />\n } @else {\n <button\n #menuItem\n role=\"menuitem\"\n [tabindex]=\"-1\"\n [ngnAutofocus]=\"open() && autofocus() && index === 0\"\n [ptInt]=\"this\"\n [ptClass]=\"'item'\"\n [disabled]=\"item.disabled\"\n (keydown)=\"handleKeydown($event)\"\n (click)=\"itemClicked(item)\"\n (mouseenter)=\"closeChildMenus('hover', menuItem)\"\n [routerLink]=\"item.route\"\n >\n <ng-container *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item }\" />\n </button>\n }\n</ng-template>\n\n<ng-template #defaultItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\n {{ maybeCallback(item.label) }}\n @if (item.children) {\n <ngn-icon\n [ptInt]=\"this\"\n [ptClass]=\"'icon-children'\"\n defaultIcon=\"menu-submenu\"\n [icon]=\"iconSubmenuIndicator()\"\n />\n }\n</ng-template>\n\n<ng-template #defaultGroupTemplate></ng-template>\n","import { setComponentInput, type Anchor } from '@ngneers/controls/api/ng';\n\nimport { NgnMenu } from './menu';\n\nimport type { MenuItem } from './types';\nimport type { ComponentRef, ViewContainerRef } from '@angular/core';\nimport type { Placement } from '@floating-ui/dom';\n\n/**\n * Lazily creates (or reuses) an `NgnMenu` popover and shows it anchored either\n * at a viewport point (context-menu style) or to an element. Returns the\n * `ComponentRef` so callers can keep it for reuse and destroy it on teardown.\n */\nexport function openMenuAt(\n vcr: ViewContainerRef,\n existing: ComponentRef<NgnMenu> | undefined,\n items: MenuItem[],\n anchor: Anchor,\n placement?: Placement\n): ComponentRef<NgnMenu> {\n const menu = existing ?? vcr.createComponent(NgnMenu);\n setComponentInput(menu, 'items', items);\n setComponentInput(menu, 'anchor', anchor);\n setComponentInput(menu, 'popover', true);\n if (placement) {\n setComponentInput(menu, 'placement', placement);\n }\n // Render the menu's own view synchronously so its `popover` viewChild\n // resolves, then show it immediately. Deferring the show to a macrotask\n // (setTimeout) makes the open latency depend on macrotask scheduling — under\n // a busy host (e.g. a large table running frequent change detection) that\n // callback is delayed noticeably, so the menu appears to open slowly. A\n // synchronous change-detection + show opens deterministically regardless of\n // host load. Guard against the host being torn down mid-call.\n if (!menu.hostView.destroyed) {\n menu.changeDetectorRef.detectChanges();\n menu.instance.show();\n }\n return menu;\n}\n","import {\n ComponentRef,\n Directive,\n ElementRef,\n inject,\n input,\n type OnDestroy,\n ViewContainerRef,\n} from '@angular/core';\nimport { domEventHandler } from '@ngneers/controls/api/ng';\n\nimport { NgnMenu } from './menu';\nimport { openMenuAt } from './open-menu-at';\n\nimport type { MenuItem } from './types';\n\n@Directive({ selector: '[ngnContextMenu]' })\nexport class NgnContextMenu implements OnDestroy {\n private readonly _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly _vcr = inject(ViewContainerRef);\n private _menu?: ComponentRef<NgnMenu>;\n\n /**\n * The menu items to display in the context menu opened on right-click.\n */\n public readonly ngnContextMenu = input.required<MenuItem[]>();\n\n constructor() {\n domEventHandler(this._elementRef, 'contextmenu', this.handleClick.bind(this));\n }\n\n public ngOnDestroy(): void {\n this._menu?.destroy();\n }\n\n private handleClick(event: PointerEvent) {\n if (event.button !== 2) {\n return;\n }\n if (this._menu?.instance.open()) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n this._menu = openMenuAt(this._vcr, this._menu, this.ngnContextMenu(), {\n x: event.clientX,\n y: event.clientY,\n });\n return false;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}