@ngneers/controls 0.0.1-pre1 → 0.0.1-pre2

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 (195) hide show
  1. package/LICENSE +21 -0
  2. package/fesm2022/ngneers-controls-accordion.mjs +194 -0
  3. package/fesm2022/ngneers-controls-accordion.mjs.map +1 -0
  4. package/fesm2022/ngneers-controls-api-ng.mjs +668 -0
  5. package/fesm2022/ngneers-controls-api-ng.mjs.map +1 -0
  6. package/fesm2022/ngneers-controls-api.mjs +256 -227
  7. package/fesm2022/ngneers-controls-api.mjs.map +1 -1
  8. package/fesm2022/ngneers-controls-avatar.mjs +70 -0
  9. package/fesm2022/ngneers-controls-avatar.mjs.map +1 -0
  10. package/fesm2022/ngneers-controls-base.mjs +397 -0
  11. package/fesm2022/ngneers-controls-base.mjs.map +1 -0
  12. package/fesm2022/ngneers-controls-breadcrumb.mjs +74 -0
  13. package/fesm2022/ngneers-controls-breadcrumb.mjs.map +1 -0
  14. package/fesm2022/ngneers-controls-button-group.mjs +51 -0
  15. package/fesm2022/ngneers-controls-button-group.mjs.map +1 -0
  16. package/fesm2022/ngneers-controls-button.mjs +62 -0
  17. package/fesm2022/ngneers-controls-button.mjs.map +1 -0
  18. package/fesm2022/ngneers-controls-calendar-time-C7UnIFzU.mjs +63 -0
  19. package/fesm2022/ngneers-controls-calendar-time-C7UnIFzU.mjs.map +1 -0
  20. package/fesm2022/ngneers-controls-calendar.mjs +468 -0
  21. package/fesm2022/ngneers-controls-calendar.mjs.map +1 -0
  22. package/fesm2022/ngneers-controls-checkbox.mjs +58 -0
  23. package/fesm2022/ngneers-controls-checkbox.mjs.map +1 -0
  24. package/fesm2022/ngneers-controls-chip.mjs +52 -0
  25. package/fesm2022/ngneers-controls-chip.mjs.map +1 -0
  26. package/fesm2022/ngneers-controls-defer.mjs +43 -0
  27. package/fesm2022/ngneers-controls-defer.mjs.map +1 -0
  28. package/fesm2022/ngneers-controls-dialog.mjs +329 -33
  29. package/fesm2022/ngneers-controls-dialog.mjs.map +1 -1
  30. package/fesm2022/ngneers-controls-directives.mjs +443 -0
  31. package/fesm2022/ngneers-controls-directives.mjs.map +1 -0
  32. package/fesm2022/ngneers-controls-drawer.mjs +232 -0
  33. package/fesm2022/ngneers-controls-drawer.mjs.map +1 -0
  34. package/fesm2022/ngneers-controls-edit-inplace.mjs +120 -0
  35. package/fesm2022/ngneers-controls-edit-inplace.mjs.map +1 -0
  36. package/fesm2022/ngneers-controls-filter.mjs +516 -0
  37. package/fesm2022/ngneers-controls-filter.mjs.map +1 -0
  38. package/fesm2022/ngneers-controls-i18n-de-CdTPeBiR.mjs +87 -0
  39. package/fesm2022/ngneers-controls-i18n-de-CdTPeBiR.mjs.map +1 -0
  40. package/fesm2022/ngneers-controls-i18n-en-Cfp2pOLY.mjs +87 -0
  41. package/fesm2022/ngneers-controls-i18n-en-Cfp2pOLY.mjs.map +1 -0
  42. package/fesm2022/ngneers-controls-i18n.mjs +57 -0
  43. package/fesm2022/ngneers-controls-i18n.mjs.map +1 -0
  44. package/fesm2022/ngneers-controls-icon-calendar-z5xA9wTT.mjs +4 -0
  45. package/fesm2022/ngneers-controls-icon-calendar-z5xA9wTT.mjs.map +1 -0
  46. package/fesm2022/ngneers-controls-icon-check-DdAQ9k-T.mjs +4 -0
  47. package/fesm2022/ngneers-controls-icon-check-DdAQ9k-T.mjs.map +1 -0
  48. package/fesm2022/ngneers-controls-icon-chevron_down-HO-z-xOr.mjs +4 -0
  49. package/fesm2022/ngneers-controls-icon-chevron_down-HO-z-xOr.mjs.map +1 -0
  50. package/fesm2022/ngneers-controls-icon-chevron_left-CC5psi16.mjs +4 -0
  51. package/fesm2022/ngneers-controls-icon-chevron_left-CC5psi16.mjs.map +1 -0
  52. package/fesm2022/ngneers-controls-icon-chevron_right-BRxlzx4G.mjs +4 -0
  53. package/fesm2022/ngneers-controls-icon-chevron_right-BRxlzx4G.mjs.map +1 -0
  54. package/fesm2022/ngneers-controls-icon-chevron_up-cqhPO7g2.mjs +4 -0
  55. package/fesm2022/ngneers-controls-icon-chevron_up-cqhPO7g2.mjs.map +1 -0
  56. package/fesm2022/ngneers-controls-icon-ellipsis-DXIGA1sk.mjs +4 -0
  57. package/fesm2022/ngneers-controls-icon-ellipsis-DXIGA1sk.mjs.map +1 -0
  58. package/fesm2022/ngneers-controls-icon-filter-oU7E6Xgr.mjs +4 -0
  59. package/fesm2022/ngneers-controls-icon-filter-oU7E6Xgr.mjs.map +1 -0
  60. package/fesm2022/ngneers-controls-icon-filter_solid-CqIKuR4N.mjs +4 -0
  61. package/fesm2022/ngneers-controls-icon-filter_solid-CqIKuR4N.mjs.map +1 -0
  62. package/fesm2022/ngneers-controls-icon-magnifying_glass-T4Hzbkig.mjs +4 -0
  63. package/fesm2022/ngneers-controls-icon-magnifying_glass-T4Hzbkig.mjs.map +1 -0
  64. package/fesm2022/ngneers-controls-icon-minus-oGDEFO4E.mjs +4 -0
  65. package/fesm2022/ngneers-controls-icon-minus-oGDEFO4E.mjs.map +1 -0
  66. package/fesm2022/ngneers-controls-icon-sort-CRD4tafz.mjs +4 -0
  67. package/fesm2022/ngneers-controls-icon-sort-CRD4tafz.mjs.map +1 -0
  68. package/fesm2022/ngneers-controls-icon-sort_down-DiFB1P6R.mjs +4 -0
  69. package/fesm2022/ngneers-controls-icon-sort_down-DiFB1P6R.mjs.map +1 -0
  70. package/fesm2022/ngneers-controls-icon-sort_up-Bq_q3hIi.mjs +4 -0
  71. package/fesm2022/ngneers-controls-icon-sort_up-Bq_q3hIi.mjs.map +1 -0
  72. package/fesm2022/ngneers-controls-icon-xmark-BZKZORiu.mjs +4 -0
  73. package/fesm2022/ngneers-controls-icon-xmark-BZKZORiu.mjs.map +1 -0
  74. package/fesm2022/ngneers-controls-icon.mjs +60 -18
  75. package/fesm2022/ngneers-controls-icon.mjs.map +1 -1
  76. package/fesm2022/ngneers-controls-inplace.mjs +107 -0
  77. package/fesm2022/ngneers-controls-inplace.mjs.map +1 -0
  78. package/fesm2022/ngneers-controls-input-field.mjs +141 -0
  79. package/fesm2022/ngneers-controls-input-field.mjs.map +1 -0
  80. package/fesm2022/ngneers-controls-input-mask.mjs +282 -0
  81. package/fesm2022/ngneers-controls-input-mask.mjs.map +1 -0
  82. package/fesm2022/ngneers-controls-input.mjs +69 -0
  83. package/fesm2022/ngneers-controls-input.mjs.map +1 -0
  84. package/fesm2022/ngneers-controls-item-view.mjs +441 -0
  85. package/fesm2022/ngneers-controls-item-view.mjs.map +1 -0
  86. package/fesm2022/ngneers-controls-list-box.mjs +157 -53
  87. package/fesm2022/ngneers-controls-list-box.mjs.map +1 -1
  88. package/fesm2022/ngneers-controls-menu.mjs +332 -0
  89. package/fesm2022/ngneers-controls-menu.mjs.map +1 -0
  90. package/fesm2022/ngneers-controls-message.mjs +29 -0
  91. package/fesm2022/ngneers-controls-message.mjs.map +1 -0
  92. package/fesm2022/ngneers-controls-paginator.mjs +111 -0
  93. package/fesm2022/ngneers-controls-paginator.mjs.map +1 -0
  94. package/fesm2022/ngneers-controls-popover.mjs +129 -40
  95. package/fesm2022/ngneers-controls-popover.mjs.map +1 -1
  96. package/fesm2022/ngneers-controls-progress.mjs +82 -0
  97. package/fesm2022/ngneers-controls-progress.mjs.map +1 -0
  98. package/fesm2022/ngneers-controls-scroller.mjs +155 -78
  99. package/fesm2022/ngneers-controls-scroller.mjs.map +1 -1
  100. package/fesm2022/ngneers-controls-select-button.mjs +55 -0
  101. package/fesm2022/ngneers-controls-select-button.mjs.map +1 -0
  102. package/fesm2022/ngneers-controls-select.mjs +313 -103
  103. package/fesm2022/ngneers-controls-select.mjs.map +1 -1
  104. package/fesm2022/ngneers-controls-slider.mjs +155 -0
  105. package/fesm2022/ngneers-controls-slider.mjs.map +1 -0
  106. package/fesm2022/ngneers-controls-spinner.mjs +169 -0
  107. package/fesm2022/ngneers-controls-spinner.mjs.map +1 -0
  108. package/fesm2022/ngneers-controls-splitter.mjs +717 -0
  109. package/fesm2022/ngneers-controls-splitter.mjs.map +1 -0
  110. package/fesm2022/ngneers-controls-switch.mjs +39 -0
  111. package/fesm2022/ngneers-controls-switch.mjs.map +1 -0
  112. package/fesm2022/ngneers-controls-table.mjs +379 -0
  113. package/fesm2022/ngneers-controls-table.mjs.map +1 -0
  114. package/fesm2022/ngneers-controls-tabs.mjs +287 -0
  115. package/fesm2022/ngneers-controls-tabs.mjs.map +1 -0
  116. package/fesm2022/ngneers-controls-tag.mjs +29 -0
  117. package/fesm2022/ngneers-controls-tag.mjs.map +1 -0
  118. package/fesm2022/ngneers-controls-toast.mjs +184 -0
  119. package/fesm2022/ngneers-controls-toast.mjs.map +1 -0
  120. package/fesm2022/ngneers-controls-toggle-button.mjs +65 -0
  121. package/fesm2022/ngneers-controls-toggle-button.mjs.map +1 -0
  122. package/fesm2022/ngneers-controls-tooltip.mjs +454 -0
  123. package/fesm2022/ngneers-controls-tooltip.mjs.map +1 -0
  124. package/fesm2022/ngneers-controls-utils-ng.mjs +227 -0
  125. package/fesm2022/ngneers-controls-utils-ng.mjs.map +1 -0
  126. package/fesm2022/ngneers-controls-utils.mjs +217 -60
  127. package/fesm2022/ngneers-controls-utils.mjs.map +1 -1
  128. package/fesm2022/ngneers-controls.mjs.map +1 -1
  129. package/package.json +167 -32
  130. package/types/ngneers-controls-accordion.d.ts +114 -0
  131. package/types/ngneers-controls-api-ng.d.ts +291 -0
  132. package/types/ngneers-controls-api.d.ts +99 -0
  133. package/types/ngneers-controls-avatar.d.ts +50 -0
  134. package/types/ngneers-controls-base.d.ts +166 -0
  135. package/types/ngneers-controls-breadcrumb.d.ts +86 -0
  136. package/types/ngneers-controls-button-group.d.ts +30 -0
  137. package/types/ngneers-controls-button.d.ts +34 -0
  138. package/types/ngneers-controls-calendar.d.ts +275 -0
  139. package/types/ngneers-controls-checkbox.d.ts +38 -0
  140. package/types/ngneers-controls-chip.d.ts +37 -0
  141. package/types/ngneers-controls-defer.d.ts +22 -0
  142. package/types/ngneers-controls-dialog.d.ts +218 -0
  143. package/types/ngneers-controls-directives.d.ts +146 -0
  144. package/types/ngneers-controls-drawer.d.ts +220 -0
  145. package/types/ngneers-controls-edit-inplace.d.ts +182 -0
  146. package/types/ngneers-controls-filter.d.ts +304 -0
  147. package/types/ngneers-controls-i18n.d.ts +108 -0
  148. package/types/ngneers-controls-icon.d.ts +74 -0
  149. package/types/ngneers-controls-inplace.d.ts +95 -0
  150. package/types/ngneers-controls-input-field.d.ts +159 -0
  151. package/types/ngneers-controls-input-mask.d.ts +83 -0
  152. package/types/ngneers-controls-input.d.ts +27 -0
  153. package/types/ngneers-controls-item-view.d.ts +211 -0
  154. package/types/ngneers-controls-list-box.d.ts +216 -0
  155. package/types/ngneers-controls-menu.d.ts +178 -0
  156. package/types/ngneers-controls-message.d.ts +19 -0
  157. package/types/ngneers-controls-paginator.d.ts +162 -0
  158. package/types/ngneers-controls-popover.d.ts +101 -0
  159. package/types/ngneers-controls-progress.d.ts +44 -0
  160. package/types/ngneers-controls-scroller.d.ts +137 -0
  161. package/types/ngneers-controls-select-button.d.ts +37 -0
  162. package/types/ngneers-controls-select.d.ts +314 -0
  163. package/types/ngneers-controls-slider.d.ts +53 -0
  164. package/types/ngneers-controls-spinner.d.ts +105 -0
  165. package/types/ngneers-controls-splitter.d.ts +391 -0
  166. package/types/ngneers-controls-switch.d.ts +18 -0
  167. package/types/ngneers-controls-table.d.ts +157 -0
  168. package/types/ngneers-controls-tabs.d.ts +106 -0
  169. package/types/ngneers-controls-tag.d.ts +19 -0
  170. package/types/ngneers-controls-toast.d.ts +70 -0
  171. package/types/ngneers-controls-toggle-button.d.ts +46 -0
  172. package/types/ngneers-controls-tooltip.d.ts +188 -0
  173. package/types/ngneers-controls-utils-ng.d.ts +57 -0
  174. package/types/ngneers-controls-utils.d.ts +130 -0
  175. package/api/index.d.ts +0 -134
  176. package/custom-types/index.d.ts +0 -7
  177. package/dialog/index.d.ts +0 -43
  178. package/fesm2022/ngneers-controls-custom-types.mjs +0 -4
  179. package/fesm2022/ngneers-controls-custom-types.mjs.map +0 -1
  180. package/fesm2022/ngneers-controls-form-field.mjs +0 -33
  181. package/fesm2022/ngneers-controls-form-field.mjs.map +0 -1
  182. package/fesm2022/ngneers-controls-lazy-cacher.mjs +0 -30
  183. package/fesm2022/ngneers-controls-lazy-cacher.mjs.map +0 -1
  184. package/fesm2022/ngneers-controls-text-field.mjs +0 -23
  185. package/fesm2022/ngneers-controls-text-field.mjs.map +0 -1
  186. package/form-field/index.d.ts +0 -19
  187. package/icon/index.d.ts +0 -30
  188. package/lazy-cacher/index.d.ts +0 -14
  189. package/list-box/index.d.ts +0 -58
  190. package/popover/index.d.ts +0 -41
  191. package/scroller/index.d.ts +0 -95
  192. package/select/index.d.ts +0 -86
  193. package/text-field/index.d.ts +0 -10
  194. package/utils/index.d.ts +0 -36
  195. /package/{index.d.ts → types/ngneers-controls.d.ts} +0 -0
@@ -0,0 +1,332 @@
1
+ import * as i0 from '@angular/core';
2
+ import { viewChild, contentChild, input, computed, Directive, booleanAttribute, output, model, inject, viewChildren, signal, effect, ChangeDetectionStrategy, Component, ElementRef, ViewContainerRef } from '@angular/core';
3
+ import { templateTypesFn, Platform, NgnTemplate, domEventHandler, setComponentInput } 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', ...(ngDevMode ? [{ debugName: "_userItemTemplate" }] : []));
18
+ /**
19
+ * Set a custom template for an item of the menu.
20
+ * Can also be set using an `<ng-template>` element with `#item` template reference variable.
21
+ */
22
+ templateItem = input(null, ...(ngDevMode ? [{ debugName: "templateItem" }] : []));
23
+ itemTemplate = computed(() => this._userItemTemplate() ?? this.templateItem() ?? this._defaultItemTemplate(), ...(ngDevMode ? [{ debugName: "itemTemplate" }] : []));
24
+ // Group template
25
+ _defaultGroupTemplate = viewChild.required('defaultGroupTemplate');
26
+ _userGroupTemplate = contentChild('group', ...(ngDevMode ? [{ debugName: "_userGroupTemplate" }] : []));
27
+ /**
28
+ * Set a custom template for a group of items in the menu.
29
+ * Can also be set using an `<ng-template>` element with `#group` template reference variable.
30
+ */
31
+ templateGroup = input(null, ...(ngDevMode ? [{ debugName: "templateGroup" }] : []));
32
+ groupTemplate = computed(() => this._userGroupTemplate() ?? this.templateGroup() ?? this._defaultGroupTemplate(), ...(ngDevMode ? [{ debugName: "groupTemplate" }] : []));
33
+ /**
34
+ * Types for the dialog templates.
35
+ */
36
+ templateTypes = templateTypesFn();
37
+ internalTemplateTypes = templateTypesFn();
38
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: MenuTemplates, deps: null, target: i0.ɵɵFactoryTarget.Directive });
39
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.1.0", 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 });
40
+ }
41
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: MenuTemplates, decorators: [{
42
+ type: Directive
43
+ }], 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 }] }] } });
44
+
45
+ /**
46
+ * @category control
47
+ */
48
+ class NgnMenu extends MenuTemplates {
49
+ theme = this.injectThemeTemplate(menuControlTemplate, {
50
+ submenu: () => this.isSubMenu(),
51
+ });
52
+ elementId = input(generateElementId(), ...(ngDevMode ? [{ debugName: "elementId" }] : []));
53
+ /**
54
+ * The element to which the menu is anchored. Required if `popover` is true.
55
+ */
56
+ anchor = input(...(ngDevMode ? [undefined, { debugName: "anchor" }] : []));
57
+ /**
58
+ * The menu items to display.
59
+ */
60
+ items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
61
+ /**
62
+ * Whether to automatically set ARIA attributes on the anchor element.
63
+ * @default true if anchor is an HTMLButtonElement, false otherwise.
64
+ */
65
+ autoAnchorAria = input(...(ngDevMode ? [undefined, { debugName: "autoAnchorAria" }] : []));
66
+ /**
67
+ * Whether the menu is a popover. Requires `anchor` to be set.
68
+ */
69
+ popover = input(false, { ...(ngDevMode ? { debugName: "popover" } : {}), transform: booleanAttribute });
70
+ /**
71
+ * The placement of the menu relative to the anchor element. Only used if `popover` is true.
72
+ * @default 'bottom-start'
73
+ */
74
+ placement = input('bottom-start', ...(ngDevMode ? [{ debugName: "placement" }] : []));
75
+ /**
76
+ * Icon type for children indicator (submenu indicator). If not set, a default icon will be used.
77
+ */
78
+ iconSubmenuIndicator = input(...(ngDevMode ? [undefined, { debugName: "iconSubmenuIndicator" }] : []));
79
+ /**
80
+ * Whether this menu is a submenu. Used internally.
81
+ * @internal
82
+ */
83
+ isSubMenu = input(false, { ...(ngDevMode ? { debugName: "isSubMenu" } : {}), transform: booleanAttribute });
84
+ /**
85
+ * Whether to open submenus on hover. Defaults to true in popover mode.
86
+ * @default popover()
87
+ */
88
+ openSubmenuOnHover = input(false, { ...(ngDevMode ? { debugName: "openSubmenuOnHover" } : {}), transform: booleanAttribute });
89
+ /**
90
+ * Emitted when the menu is fully closed.
91
+ */
92
+ closed = output();
93
+ /**
94
+ * Emitted when the menu is about to close.
95
+ */
96
+ closing = output();
97
+ /**
98
+ * Emitted when all menus should be closed (including parent menus). Used internally.
99
+ * @internal
100
+ */
101
+ closeAll = output();
102
+ /**
103
+ * Shows or hides the menu.
104
+ *
105
+ * You probably want to react to openChange events from outside to update your variable accordingly.
106
+ */
107
+ open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
108
+ maybeCallback = maybeCallback;
109
+ _isTouchDevice = inject(Platform).isTouchDevice;
110
+ _popover = viewChild(NgnPopover, ...(ngDevMode ? [{ debugName: "_popover" }] : []));
111
+ _menuItems = viewChildren('menuItem', ...(ngDevMode ? [{ debugName: "_menuItems" }] : []));
112
+ _childMenus = viewChildren(NgnMenu, ...(ngDevMode ? [{ debugName: "_childMenus" }] : []));
113
+ _openSubmenuOnHover = computed(() => this.openSubmenuOnHover() ?? this.popover(), ...(ngDevMode ? [{ debugName: "_openSubmenuOnHover" }] : []));
114
+ autofocus = signal(false, ...(ngDevMode ? [{ debugName: "autofocus" }] : []));
115
+ constructor() {
116
+ super();
117
+ effect(() => {
118
+ if (this.popover() && !this.anchor()) {
119
+ throw new NgnError('NgnMenu', 'When using popover mode, the anchor input must be provided.');
120
+ }
121
+ });
122
+ const autoAriaEnabled = computed(() => {
123
+ if (this.autoAnchorAria() !== undefined) {
124
+ return this.autoAnchorAria();
125
+ }
126
+ return this.anchor() instanceof HTMLButtonElement;
127
+ }, ...(ngDevMode ? [{ debugName: "autoAriaEnabled" }] : []));
128
+ effectWithPrevious(this.anchor, (current, previous) => {
129
+ if (previous instanceof HTMLElement && autoAriaEnabled()) {
130
+ previous.removeAttribute('aria-controls');
131
+ previous.removeAttribute('aria-expanded');
132
+ previous.removeAttribute('aria-haspopup');
133
+ }
134
+ if (current instanceof HTMLElement && autoAriaEnabled()) {
135
+ current.setAttribute('aria-controls', `${this.elementId()}_menu`);
136
+ current.setAttribute('aria-haspopup', 'menu');
137
+ }
138
+ });
139
+ effect(() => {
140
+ const anchor = this.anchor();
141
+ if (anchor instanceof HTMLElement && autoAriaEnabled()) {
142
+ anchor.setAttribute('aria-expanded', this.open() ? 'true' : 'false');
143
+ }
144
+ });
145
+ explicitEffect([this.open], ([open]) => {
146
+ if (!open) {
147
+ if (this._popover()?.open()) {
148
+ this.hide();
149
+ }
150
+ }
151
+ if (open) {
152
+ if (!this._popover()?.open()) {
153
+ this.show(this.autofocus());
154
+ }
155
+ }
156
+ });
157
+ }
158
+ /**
159
+ * Shows the menu.
160
+ * @param focus Whether to focus the menu after showing it. Defaults to `true`.
161
+ */
162
+ show(focus = true) {
163
+ if (!this.popover()) {
164
+ throw new NgnError('NgnMenu', 'The show() method can only be used when popover mode is enabled.');
165
+ }
166
+ this._popover()?.show();
167
+ this.autofocus.set(focus);
168
+ }
169
+ /**
170
+ * Hides the menu.
171
+ * @param emitCloseEvent Whether to emit the close event. Defaults to `true`.
172
+ */
173
+ hide(emitCloseEvent = true) {
174
+ if (!this.popover()) {
175
+ throw new NgnError('NgnMenu', 'The hide() method can only be used when popover mode is enabled.');
176
+ }
177
+ this._popover()?.hide(emitCloseEvent);
178
+ }
179
+ /**
180
+ * Toggles the menu open or closed.
181
+ */
182
+ toggle() {
183
+ if (!this.popover()) {
184
+ throw new NgnError('NgnMenu', 'The toggle() method can only be used when popover mode is enabled.');
185
+ }
186
+ const popoverEl = this._popover();
187
+ if (!popoverEl) {
188
+ throw new NgnError('NgnMenu', 'Popover element is not available.');
189
+ }
190
+ if (popoverEl.open()) {
191
+ popoverEl.hide();
192
+ }
193
+ else {
194
+ popoverEl.open();
195
+ }
196
+ }
197
+ handleKeydown(event, subMenu) {
198
+ let currentIndex = this._menuItems()
199
+ .map(x => x.nativeElement)
200
+ .indexOf(event.target);
201
+ if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
202
+ event.preventDefault();
203
+ if (event.key === 'ArrowDown') {
204
+ currentIndex++;
205
+ }
206
+ else if (event.key === 'ArrowUp') {
207
+ currentIndex--;
208
+ }
209
+ if (currentIndex < 0) {
210
+ currentIndex = this._menuItems().length - 1;
211
+ }
212
+ else if (currentIndex >= this._menuItems().length) {
213
+ currentIndex = 0;
214
+ }
215
+ this._menuItems()[currentIndex]?.nativeElement.focus();
216
+ }
217
+ else if (event.key === 'ArrowRight' && subMenu) {
218
+ this.openChildMenu(subMenu, null, 'arrow');
219
+ }
220
+ else if (event.key === 'ArrowLeft' && this.isSubMenu()) {
221
+ this._popover()?.hide();
222
+ }
223
+ }
224
+ doCloseAll() {
225
+ this.hide();
226
+ // Delay the closing of the parents to ensure the children close first (for animation purposes)
227
+ requestAnimationFrame(() => {
228
+ this.closeAll.emit();
229
+ });
230
+ }
231
+ itemClicked(item) {
232
+ if (this.popover()) {
233
+ this.doCloseAll();
234
+ }
235
+ if ('callback' in item) {
236
+ item.callback?.();
237
+ }
238
+ }
239
+ closeChildMenus(closeBy, menuItem) {
240
+ if (closeBy === 'hover') {
241
+ if (this._isTouchDevice() || !this._openSubmenuOnHover()) {
242
+ return;
243
+ }
244
+ if (this._openSubmenuOnHover()) {
245
+ menuItem?.focus();
246
+ }
247
+ }
248
+ this._childMenus().forEach(menu => {
249
+ menu.hide(false);
250
+ });
251
+ }
252
+ openChildMenu(childMenu, menuItem, openBy) {
253
+ if (openBy === 'hover') {
254
+ if (this._isTouchDevice() || !this._openSubmenuOnHover()) {
255
+ return;
256
+ }
257
+ }
258
+ if (childMenu.open()) {
259
+ menuItem?.focus();
260
+ return;
261
+ }
262
+ this.closeChildMenus(openBy, menuItem);
263
+ setTimeout(() => {
264
+ childMenu.show(openBy === 'arrow');
265
+ });
266
+ }
267
+ popoverOpenChange(newState) {
268
+ this.open.set(newState);
269
+ }
270
+ popoverClosed() {
271
+ this.closed.emit();
272
+ }
273
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
274
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", 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) {\r\n <ngn-popover\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'popover'\"\r\n [anchor]=\"anchor\"\r\n [options]=\"{ placement: placement(), padding: isSubMenu() ? 0 : undefined }\"\r\n (openChange)=\"popoverOpenChange($event)\"\r\n (closed)=\"popoverClosed()\"\r\n (closing)=\"closing.emit()\"\r\n >\r\n <ng-template #lazy>\r\n <ng-container *ngTemplateOutlet=\"menu\" />\r\n </ng-template>\r\n </ngn-popover>\r\n} @else {\r\n <ng-container *ngTemplateOutlet=\"menu\" />\r\n}\r\n\r\n<ng-template #menu>\r\n <div [ptInt]=\"this\" [ptClass]=\"'root'\" role=\"menu\" [tabIndex]=\"0\" [id]=\"elementId() + '_menu'\">\r\n @for (item of items(); track 'id' in item ? item.id : item) {\r\n @if ('separator' in item) {\r\n <ng-container *ngTemplateOutlet=\"separatorTemplate\" />\r\n } @else {\r\n <ng-container\r\n *ngTemplateOutlet=\"regularItemTemplate; context: { $implicit: item, index: $index }\"\r\n />\r\n }\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #separatorTemplate>\r\n <hr [ptInt]=\"this\" [ptClass]=\"'separator'\" />\r\n</ng-template>\r\n\r\n<ng-template\r\n #regularItemTemplate\r\n [ngnTemplate]=\"internalTemplateTypes.regularItem\"\r\n let-item\r\n let-index=\"index\"\r\n>\r\n @if (item.children) {\r\n <button\r\n #menuItem\r\n role=\"menuitem\"\r\n aria-haspopup=\"menu\"\r\n [aria-expanded]=\"childMenu.open()\"\r\n [tabindex]=\"-1\"\r\n [ngnAutofocus]=\"open() && autofocus() && index === 0\"\r\n [ptInt]=\"this\"\r\n [ptClass]=\"{\r\n item: true,\r\n 'item-opened': childMenu.open(),\r\n }\"\r\n [disabled]=\"item.disabled\"\r\n (click)=\"openChildMenu(childMenu, menuItem, 'click')\"\r\n (mouseenter)=\"openChildMenu(childMenu, menuItem, 'hover')\"\r\n (keydown)=\"handleKeydown($event, childMenu)\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item }\" />\r\n </button>\r\n <ngn-menu\r\n #childMenu\r\n [anchor]=\"menuItem\"\r\n [items]=\"item.children\"\r\n [placement]=\"'right-start'\"\r\n [popover]=\"true\"\r\n [isSubMenu]=\"true\"\r\n (closing)=\"menuItem.focus()\"\r\n (closeAll)=\"doCloseAll()\"\r\n [elementId]=\"elementId() + '_submenu_' + item.id\"\r\n [openSubmenuOnHover]=\"openSubmenuOnHover()\"\r\n />\r\n } @else {\r\n <button\r\n #menuItem\r\n role=\"menuitem\"\r\n [tabindex]=\"-1\"\r\n [ngnAutofocus]=\"open() && autofocus() && index === 0\"\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'item'\"\r\n [disabled]=\"item.disabled\"\r\n (keydown)=\"handleKeydown($event)\"\r\n (click)=\"itemClicked(item)\"\r\n (mouseenter)=\"closeChildMenus('hover', menuItem)\"\r\n [routerLink]=\"item.route\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item }\" />\r\n </button>\r\n }\r\n</ng-template>\r\n\r\n<ng-template #defaultItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\r\n {{ maybeCallback(item.label) }}\r\n @if (item.children) {\r\n <ngn-icon\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'icon-children'\"\r\n defaultIcon=\"chevron_right\"\r\n [icon]=\"iconSubmenuIndicator()\"\r\n />\r\n }\r\n</ng-template>\r\n\r\n<ng-template #defaultGroupTemplate></ng-template>\r\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"] }, { 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", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
275
+ }
276
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnMenu, decorators: [{
277
+ type: Component,
278
+ args: [{ selector: 'ngn-menu', imports: [NgnPt, NgTemplateOutlet, NgnTemplate, NgnAutofocus, NgnPopover, NgnIcon, RouterLink], changeDetection: ChangeDetectionStrategy.OnPush, providers: [provideSelf(NgnMenu)], template: "@if (popover() && anchor(); as anchor) {\r\n <ngn-popover\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'popover'\"\r\n [anchor]=\"anchor\"\r\n [options]=\"{ placement: placement(), padding: isSubMenu() ? 0 : undefined }\"\r\n (openChange)=\"popoverOpenChange($event)\"\r\n (closed)=\"popoverClosed()\"\r\n (closing)=\"closing.emit()\"\r\n >\r\n <ng-template #lazy>\r\n <ng-container *ngTemplateOutlet=\"menu\" />\r\n </ng-template>\r\n </ngn-popover>\r\n} @else {\r\n <ng-container *ngTemplateOutlet=\"menu\" />\r\n}\r\n\r\n<ng-template #menu>\r\n <div [ptInt]=\"this\" [ptClass]=\"'root'\" role=\"menu\" [tabIndex]=\"0\" [id]=\"elementId() + '_menu'\">\r\n @for (item of items(); track 'id' in item ? item.id : item) {\r\n @if ('separator' in item) {\r\n <ng-container *ngTemplateOutlet=\"separatorTemplate\" />\r\n } @else {\r\n <ng-container\r\n *ngTemplateOutlet=\"regularItemTemplate; context: { $implicit: item, index: $index }\"\r\n />\r\n }\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #separatorTemplate>\r\n <hr [ptInt]=\"this\" [ptClass]=\"'separator'\" />\r\n</ng-template>\r\n\r\n<ng-template\r\n #regularItemTemplate\r\n [ngnTemplate]=\"internalTemplateTypes.regularItem\"\r\n let-item\r\n let-index=\"index\"\r\n>\r\n @if (item.children) {\r\n <button\r\n #menuItem\r\n role=\"menuitem\"\r\n aria-haspopup=\"menu\"\r\n [aria-expanded]=\"childMenu.open()\"\r\n [tabindex]=\"-1\"\r\n [ngnAutofocus]=\"open() && autofocus() && index === 0\"\r\n [ptInt]=\"this\"\r\n [ptClass]=\"{\r\n item: true,\r\n 'item-opened': childMenu.open(),\r\n }\"\r\n [disabled]=\"item.disabled\"\r\n (click)=\"openChildMenu(childMenu, menuItem, 'click')\"\r\n (mouseenter)=\"openChildMenu(childMenu, menuItem, 'hover')\"\r\n (keydown)=\"handleKeydown($event, childMenu)\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item }\" />\r\n </button>\r\n <ngn-menu\r\n #childMenu\r\n [anchor]=\"menuItem\"\r\n [items]=\"item.children\"\r\n [placement]=\"'right-start'\"\r\n [popover]=\"true\"\r\n [isSubMenu]=\"true\"\r\n (closing)=\"menuItem.focus()\"\r\n (closeAll)=\"doCloseAll()\"\r\n [elementId]=\"elementId() + '_submenu_' + item.id\"\r\n [openSubmenuOnHover]=\"openSubmenuOnHover()\"\r\n />\r\n } @else {\r\n <button\r\n #menuItem\r\n role=\"menuitem\"\r\n [tabindex]=\"-1\"\r\n [ngnAutofocus]=\"open() && autofocus() && index === 0\"\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'item'\"\r\n [disabled]=\"item.disabled\"\r\n (keydown)=\"handleKeydown($event)\"\r\n (click)=\"itemClicked(item)\"\r\n (mouseenter)=\"closeChildMenus('hover', menuItem)\"\r\n [routerLink]=\"item.route\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item }\" />\r\n </button>\r\n }\r\n</ng-template>\r\n\r\n<ng-template #defaultItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\r\n {{ maybeCallback(item.label) }}\r\n @if (item.children) {\r\n <ngn-icon\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'icon-children'\"\r\n defaultIcon=\"chevron_right\"\r\n [icon]=\"iconSubmenuIndicator()\"\r\n />\r\n }\r\n</ng-template>\r\n\r\n<ng-template #defaultGroupTemplate></ng-template>\r\n" }]
279
+ }], 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 }] }] } });
280
+
281
+ class NgnContextMenu {
282
+ _elementRef = inject(ElementRef);
283
+ _vcr = inject(ViewContainerRef);
284
+ _menu;
285
+ ngnContextMenu = input.required(...(ngDevMode ? [{ debugName: "ngnContextMenu" }] : []));
286
+ constructor() {
287
+ domEventHandler(this._elementRef, 'contextmenu', this.handleClick.bind(this));
288
+ }
289
+ ngOnDestroy() {
290
+ this._menu?.destroy();
291
+ }
292
+ handleClick(event) {
293
+ if (event.button !== 2) {
294
+ return;
295
+ }
296
+ if (this._menu?.instance.open()) {
297
+ return;
298
+ }
299
+ event.preventDefault();
300
+ event.stopPropagation();
301
+ this.openMenu(event);
302
+ return false;
303
+ }
304
+ createMenu() {
305
+ if (!this._menu) {
306
+ this._menu = this._vcr.createComponent(NgnMenu);
307
+ }
308
+ return this._menu;
309
+ }
310
+ openMenu(event) {
311
+ const menu = this.createMenu();
312
+ setComponentInput(menu, 'items', this.ngnContextMenu());
313
+ setComponentInput(menu, 'anchor', { x: event.clientX, y: event.clientY });
314
+ setComponentInput(menu, 'popover', true);
315
+ setTimeout(() => {
316
+ menu.instance.show();
317
+ });
318
+ }
319
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnContextMenu, deps: [], target: i0.ɵɵFactoryTarget.Directive });
320
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: NgnContextMenu, isStandalone: true, selector: "[ngnContextMenu]", inputs: { ngnContextMenu: { classPropertyName: "ngnContextMenu", publicName: "ngnContextMenu", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
321
+ }
322
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnContextMenu, decorators: [{
323
+ type: Directive,
324
+ args: [{ selector: '[ngnContextMenu]' }]
325
+ }], ctorParameters: () => [], propDecorators: { ngnContextMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngnContextMenu", required: true }] }] } });
326
+
327
+ /**
328
+ * Generated bundle index. Do not edit.
329
+ */
330
+
331
+ export { NgnContextMenu, NgnMenu };
332
+ //# 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/context-menu.ts","../../src/menu/ngneers-controls-menu.ts"],"sourcesContent":["import { computed, contentChild, Directive, input, TemplateRef, viewChild } from '@angular/core';\r\nimport { templateTypesFn } from '@ngneers/controls/api/ng';\r\nimport { NgnBase } from '@ngneers/controls/base';\r\n\r\nimport type { MenuItemDefault } from './types';\r\n\r\n@Directive()\r\nexport abstract class MenuTemplates extends NgnBase<'menu'> {\r\n // Item template\r\n private readonly _defaultItemTemplate =\r\n viewChild.required<TemplateRef<typeof this.templateTypes.item>>('defaultItemTemplate');\r\n private readonly _userItemTemplate =\r\n contentChild<TemplateRef<typeof this.templateTypes.item>>('item');\r\n /**\r\n * Set a custom template for an item of the menu.\r\n * Can also be set using an `<ng-template>` element with `#item` template reference variable.\r\n */\r\n public readonly templateItem = input<TemplateRef<typeof this.templateTypes.item> | null>(null);\r\n protected readonly itemTemplate = computed(\r\n () => this._userItemTemplate() ?? this.templateItem() ?? this._defaultItemTemplate()\r\n );\r\n\r\n // Group template\r\n private readonly _defaultGroupTemplate =\r\n viewChild.required<TemplateRef<unknown>>('defaultGroupTemplate');\r\n private readonly _userGroupTemplate = contentChild<TemplateRef<unknown>>('group');\r\n /**\r\n * Set a custom template for a group of items in the menu.\r\n * Can also be set using an `<ng-template>` element with `#group` template reference variable.\r\n */\r\n public readonly templateGroup = input<TemplateRef<unknown> | null>(null);\r\n protected readonly groupTemplate = computed(\r\n () => this._userGroupTemplate() ?? this.templateGroup() ?? this._defaultGroupTemplate()\r\n );\r\n\r\n /**\r\n * Types for the dialog templates.\r\n */\r\n public readonly templateTypes = templateTypesFn<{\r\n item: {\r\n $implicit: MenuItemDefault;\r\n };\r\n }>();\r\n\r\n protected readonly internalTemplateTypes = templateTypesFn<{\r\n regularItem: {\r\n $implicit: MenuItemDefault;\r\n index: number;\r\n };\r\n }>();\r\n}\r\n","import { NgTemplateOutlet } from '@angular/common';\r\nimport {\r\n booleanAttribute,\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n effect,\r\n ElementRef,\r\n inject,\r\n input,\r\n model,\r\n output,\r\n signal,\r\n viewChild,\r\n viewChildren,\r\n} from '@angular/core';\r\nimport { RouterLink } from '@angular/router';\r\nimport { type Anchor, NgnTemplate, type Openable, Platform } from '@ngneers/controls/api/ng';\r\nimport { NgnPt, provideSelf } from '@ngneers/controls/base';\r\nimport { NgnAutofocus } from '@ngneers/controls/directives';\r\nimport { NgnIcon } from '@ngneers/controls/icon';\r\nimport { NgnPopover } from '@ngneers/controls/popover';\r\nimport { maybeCallback, NgnError } from '@ngneers/controls/utils';\r\nimport { effectWithPrevious, explicitEffect, generateElementId } from '@ngneers/controls/utils-ng';\r\nimport { menuControlTemplate } from '@ngneers/controls-themes/templates/menu';\r\n\r\nimport { MenuTemplates } from './menu-templates';\r\n\r\nimport type { MenuItem } from './types';\r\nimport type { Placement } from '@floating-ui/dom';\r\nimport type { IconType } from '@ngneers/controls-custom-types';\r\n\r\n/**\r\n * @category control\r\n */\r\n@Component({\r\n selector: 'ngn-menu',\r\n imports: [NgnPt, NgTemplateOutlet, NgnTemplate, NgnAutofocus, NgnPopover, NgnIcon, RouterLink],\r\n templateUrl: './menu.html',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n providers: [provideSelf(NgnMenu)],\r\n})\r\nexport class NgnMenu extends MenuTemplates implements Openable {\r\n protected readonly theme = this.injectThemeTemplate(menuControlTemplate, {\r\n submenu: () => this.isSubMenu(),\r\n });\r\n protected readonly elementId = input(generateElementId());\r\n /**\r\n * The element to which the menu is anchored. Required if `popover` is true.\r\n */\r\n public readonly anchor = input<Anchor>();\r\n /**\r\n * The menu items to display.\r\n */\r\n public readonly items = input.required<MenuItem[]>();\r\n /**\r\n * Whether to automatically set ARIA attributes on the anchor element.\r\n * @default true if anchor is an HTMLButtonElement, false otherwise.\r\n */\r\n public readonly autoAnchorAria = input<boolean>();\r\n /**\r\n * Whether the menu is a popover. Requires `anchor` to be set.\r\n */\r\n public readonly popover = input(false, { transform: booleanAttribute });\r\n /**\r\n * The placement of the menu relative to the anchor element. Only used if `popover` is true.\r\n * @default 'bottom-start'\r\n */\r\n public readonly placement = input<Placement>('bottom-start');\r\n /**\r\n * Icon type for children indicator (submenu indicator). If not set, a default icon will be used.\r\n */\r\n public readonly iconSubmenuIndicator = input<IconType>();\r\n /**\r\n * Whether this menu is a submenu. Used internally.\r\n * @internal\r\n */\r\n public readonly isSubMenu = input(false, { transform: booleanAttribute });\r\n /**\r\n * Whether to open submenus on hover. Defaults to true in popover mode.\r\n * @default popover()\r\n */\r\n public readonly openSubmenuOnHover = input(false, { transform: booleanAttribute });\r\n\r\n /**\r\n * Emitted when the menu is fully closed.\r\n */\r\n public readonly closed = output<void>();\r\n /**\r\n * Emitted when the menu is about to close.\r\n */\r\n public readonly closing = output<void>();\r\n /**\r\n * Emitted when all menus should be closed (including parent menus). Used internally.\r\n * @internal\r\n */\r\n public readonly closeAll = output<void>();\r\n /**\r\n * Shows or hides the menu.\r\n *\r\n * You probably want to react to openChange events from outside to update your variable accordingly.\r\n */\r\n public readonly open = model(false);\r\n\r\n protected readonly maybeCallback = maybeCallback;\r\n\r\n private readonly _isTouchDevice = inject(Platform).isTouchDevice;\r\n private readonly _popover = viewChild(NgnPopover);\r\n private readonly _menuItems = viewChildren<ElementRef<HTMLElement>>('menuItem');\r\n private readonly _childMenus = viewChildren(NgnMenu);\r\n private readonly _openSubmenuOnHover = computed(\r\n () => this.openSubmenuOnHover() ?? this.popover()\r\n );\r\n protected readonly autofocus = signal(false);\r\n\r\n constructor() {\r\n super();\r\n effect(() => {\r\n if (this.popover() && !this.anchor()) {\r\n throw new NgnError(\r\n 'NgnMenu',\r\n 'When using popover mode, the anchor input must be provided.'\r\n );\r\n }\r\n });\r\n\r\n const autoAriaEnabled = computed(() => {\r\n if (this.autoAnchorAria() !== undefined) {\r\n return this.autoAnchorAria();\r\n }\r\n return this.anchor() instanceof HTMLButtonElement;\r\n });\r\n\r\n effectWithPrevious(this.anchor, (current, previous) => {\r\n if (previous instanceof HTMLElement && autoAriaEnabled()) {\r\n previous.removeAttribute('aria-controls');\r\n previous.removeAttribute('aria-expanded');\r\n previous.removeAttribute('aria-haspopup');\r\n }\r\n if (current instanceof HTMLElement && autoAriaEnabled()) {\r\n current.setAttribute('aria-controls', `${this.elementId()}_menu`);\r\n current.setAttribute('aria-haspopup', 'menu');\r\n }\r\n });\r\n\r\n effect(() => {\r\n const anchor = this.anchor();\r\n if (anchor instanceof HTMLElement && autoAriaEnabled()) {\r\n anchor.setAttribute('aria-expanded', this.open() ? 'true' : 'false');\r\n }\r\n });\r\n\r\n explicitEffect([this.open], ([open]) => {\r\n if (!open) {\r\n if (this._popover()?.open()) {\r\n this.hide();\r\n }\r\n }\r\n if (open) {\r\n if (!this._popover()?.open()) {\r\n this.show(this.autofocus());\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Shows the menu.\r\n * @param focus Whether to focus the menu after showing it. Defaults to `true`.\r\n */\r\n public show(focus = true) {\r\n if (!this.popover()) {\r\n throw new NgnError(\r\n 'NgnMenu',\r\n 'The show() method can only be used when popover mode is enabled.'\r\n );\r\n }\r\n this._popover()?.show();\r\n this.autofocus.set(focus);\r\n }\r\n\r\n /**\r\n * Hides the menu.\r\n * @param emitCloseEvent Whether to emit the close event. Defaults to `true`.\r\n */\r\n public hide(emitCloseEvent = true) {\r\n if (!this.popover()) {\r\n throw new NgnError(\r\n 'NgnMenu',\r\n 'The hide() method can only be used when popover mode is enabled.'\r\n );\r\n }\r\n this._popover()?.hide(emitCloseEvent);\r\n }\r\n\r\n /**\r\n * Toggles the menu open or closed.\r\n */\r\n public toggle() {\r\n if (!this.popover()) {\r\n throw new NgnError(\r\n 'NgnMenu',\r\n 'The toggle() method can only be used when popover mode is enabled.'\r\n );\r\n }\r\n const popoverEl = this._popover();\r\n if (!popoverEl) {\r\n throw new NgnError('NgnMenu', 'Popover element is not available.');\r\n }\r\n if (popoverEl.open()) {\r\n popoverEl.hide();\r\n } else {\r\n popoverEl.open();\r\n }\r\n }\r\n\r\n protected handleKeydown(event: KeyboardEvent, subMenu?: NgnMenu) {\r\n let currentIndex = this._menuItems()\r\n .map(x => x.nativeElement)\r\n .indexOf(event.target as HTMLElement);\r\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\r\n event.preventDefault();\r\n if (event.key === 'ArrowDown') {\r\n currentIndex++;\r\n } else if (event.key === 'ArrowUp') {\r\n currentIndex--;\r\n }\r\n if (currentIndex < 0) {\r\n currentIndex = this._menuItems().length - 1;\r\n } else if (currentIndex >= this._menuItems().length) {\r\n currentIndex = 0;\r\n }\r\n this._menuItems()[currentIndex]?.nativeElement.focus();\r\n } else if (event.key === 'ArrowRight' && subMenu) {\r\n this.openChildMenu(subMenu, null, 'arrow');\r\n } else if (event.key === 'ArrowLeft' && this.isSubMenu()) {\r\n this._popover()?.hide();\r\n }\r\n }\r\n\r\n protected doCloseAll() {\r\n this.hide();\r\n // Delay the closing of the parents to ensure the children close first (for animation purposes)\r\n requestAnimationFrame(() => {\r\n this.closeAll.emit();\r\n });\r\n }\r\n\r\n protected itemClicked(item: MenuItem) {\r\n if (this.popover()) {\r\n this.doCloseAll();\r\n }\r\n if ('callback' in item) {\r\n item.callback?.();\r\n }\r\n }\r\n\r\n protected closeChildMenus(\r\n closeBy: 'hover' | 'click' | 'arrow',\r\n menuItem: HTMLButtonElement | null\r\n ) {\r\n if (closeBy === 'hover') {\r\n if (this._isTouchDevice() || !this._openSubmenuOnHover()) {\r\n return;\r\n }\r\n if (this._openSubmenuOnHover()) {\r\n menuItem?.focus();\r\n }\r\n }\r\n this._childMenus().forEach(menu => {\r\n menu.hide(false);\r\n });\r\n }\r\n\r\n protected openChildMenu(\r\n childMenu: NgnMenu,\r\n menuItem: HTMLButtonElement | null,\r\n openBy: 'hover' | 'click' | 'arrow'\r\n ) {\r\n if (openBy === 'hover') {\r\n if (this._isTouchDevice() || !this._openSubmenuOnHover()) {\r\n return;\r\n }\r\n }\r\n if (childMenu.open()) {\r\n menuItem?.focus();\r\n return;\r\n }\r\n this.closeChildMenus(openBy, menuItem);\r\n setTimeout(() => {\r\n childMenu.show(openBy === 'arrow');\r\n });\r\n }\r\n\r\n protected popoverOpenChange(newState: boolean) {\r\n this.open.set(newState);\r\n }\r\n\r\n protected popoverClosed() {\r\n this.closed.emit();\r\n }\r\n}\r\n","@if (popover() && anchor(); as anchor) {\r\n <ngn-popover\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'popover'\"\r\n [anchor]=\"anchor\"\r\n [options]=\"{ placement: placement(), padding: isSubMenu() ? 0 : undefined }\"\r\n (openChange)=\"popoverOpenChange($event)\"\r\n (closed)=\"popoverClosed()\"\r\n (closing)=\"closing.emit()\"\r\n >\r\n <ng-template #lazy>\r\n <ng-container *ngTemplateOutlet=\"menu\" />\r\n </ng-template>\r\n </ngn-popover>\r\n} @else {\r\n <ng-container *ngTemplateOutlet=\"menu\" />\r\n}\r\n\r\n<ng-template #menu>\r\n <div [ptInt]=\"this\" [ptClass]=\"'root'\" role=\"menu\" [tabIndex]=\"0\" [id]=\"elementId() + '_menu'\">\r\n @for (item of items(); track 'id' in item ? item.id : item) {\r\n @if ('separator' in item) {\r\n <ng-container *ngTemplateOutlet=\"separatorTemplate\" />\r\n } @else {\r\n <ng-container\r\n *ngTemplateOutlet=\"regularItemTemplate; context: { $implicit: item, index: $index }\"\r\n />\r\n }\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #separatorTemplate>\r\n <hr [ptInt]=\"this\" [ptClass]=\"'separator'\" />\r\n</ng-template>\r\n\r\n<ng-template\r\n #regularItemTemplate\r\n [ngnTemplate]=\"internalTemplateTypes.regularItem\"\r\n let-item\r\n let-index=\"index\"\r\n>\r\n @if (item.children) {\r\n <button\r\n #menuItem\r\n role=\"menuitem\"\r\n aria-haspopup=\"menu\"\r\n [aria-expanded]=\"childMenu.open()\"\r\n [tabindex]=\"-1\"\r\n [ngnAutofocus]=\"open() && autofocus() && index === 0\"\r\n [ptInt]=\"this\"\r\n [ptClass]=\"{\r\n item: true,\r\n 'item-opened': childMenu.open(),\r\n }\"\r\n [disabled]=\"item.disabled\"\r\n (click)=\"openChildMenu(childMenu, menuItem, 'click')\"\r\n (mouseenter)=\"openChildMenu(childMenu, menuItem, 'hover')\"\r\n (keydown)=\"handleKeydown($event, childMenu)\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item }\" />\r\n </button>\r\n <ngn-menu\r\n #childMenu\r\n [anchor]=\"menuItem\"\r\n [items]=\"item.children\"\r\n [placement]=\"'right-start'\"\r\n [popover]=\"true\"\r\n [isSubMenu]=\"true\"\r\n (closing)=\"menuItem.focus()\"\r\n (closeAll)=\"doCloseAll()\"\r\n [elementId]=\"elementId() + '_submenu_' + item.id\"\r\n [openSubmenuOnHover]=\"openSubmenuOnHover()\"\r\n />\r\n } @else {\r\n <button\r\n #menuItem\r\n role=\"menuitem\"\r\n [tabindex]=\"-1\"\r\n [ngnAutofocus]=\"open() && autofocus() && index === 0\"\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'item'\"\r\n [disabled]=\"item.disabled\"\r\n (keydown)=\"handleKeydown($event)\"\r\n (click)=\"itemClicked(item)\"\r\n (mouseenter)=\"closeChildMenus('hover', menuItem)\"\r\n [routerLink]=\"item.route\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item }\" />\r\n </button>\r\n }\r\n</ng-template>\r\n\r\n<ng-template #defaultItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\r\n {{ maybeCallback(item.label) }}\r\n @if (item.children) {\r\n <ngn-icon\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'icon-children'\"\r\n defaultIcon=\"chevron_right\"\r\n [icon]=\"iconSubmenuIndicator()\"\r\n />\r\n }\r\n</ng-template>\r\n\r\n<ng-template #defaultGroupTemplate></ng-template>\r\n","import {\r\n ComponentRef,\r\n Directive,\r\n ElementRef,\r\n inject,\r\n input,\r\n type OnDestroy,\r\n ViewContainerRef,\r\n} from '@angular/core';\r\nimport { domEventHandler, setComponentInput } from '@ngneers/controls/api/ng';\r\n\r\nimport { NgnMenu } from './menu';\r\n\r\nimport type { MenuItem } from './types';\r\n\r\n@Directive({ selector: '[ngnContextMenu]' })\r\nexport class NgnContextMenu implements OnDestroy {\r\n private readonly _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\r\n private readonly _vcr = inject(ViewContainerRef);\r\n private _menu?: ComponentRef<NgnMenu>;\r\n\r\n public readonly ngnContextMenu = input.required<MenuItem[]>();\r\n\r\n constructor() {\r\n domEventHandler(this._elementRef, 'contextmenu', this.handleClick.bind(this));\r\n }\r\n\r\n public ngOnDestroy(): void {\r\n this._menu?.destroy();\r\n }\r\n\r\n private handleClick(event: PointerEvent) {\r\n if (event.button !== 2) {\r\n return;\r\n }\r\n if (this._menu?.instance.open()) {\r\n return;\r\n }\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.openMenu(event);\r\n return false;\r\n }\r\n\r\n private createMenu() {\r\n if (!this._menu) {\r\n this._menu = this._vcr.createComponent(NgnMenu);\r\n }\r\n return this._menu;\r\n }\r\n\r\n private openMenu(event: PointerEvent) {\r\n const menu = this.createMenu();\r\n\r\n setComponentInput(menu, 'items', this.ngnContextMenu());\r\n setComponentInput(menu, 'anchor', { x: event.clientX, y: event.clientY });\r\n setComponentInput(menu, 'popover', true);\r\n setTimeout(() => {\r\n menu.instance.show();\r\n });\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { NgnBase, NgnPt, provideSelf } from '@ngneers/controls/base';
4
+ import { NgnIcon } from '@ngneers/controls/icon';
5
+ import { messageControlTemplate } from '@ngneers/controls-themes/templates/message';
6
+
7
+ /**
8
+ * @category control
9
+ */
10
+ class NgnMessage extends NgnBase {
11
+ theme = this.injectThemeTemplate(messageControlTemplate, 'root');
12
+ /**
13
+ * Set an icon to display before the text.
14
+ */
15
+ icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : []));
16
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnMessage, deps: null, target: i0.ɵɵFactoryTarget.Component });
17
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: NgnMessage, isStandalone: true, selector: "ngn-message", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideSelf(NgnMessage)], usesInheritance: true, ngImport: i0, template: "@if (icon()) {\r\n <ngn-icon [ptInt]=\"this\" [ptClass]=\"'icon'\" [icon]=\"icon()\" />\r\n}\r\n<div [ptInt]=\"this\" [ptClass]=\"'content'\">\r\n <ng-content />\r\n</div>\r\n", dependencies: [{ kind: "directive", type: NgnPt, selector: "[ptInt]", inputs: ["ptInt", "ptClass"] }, { kind: "component", type: NgnIcon, selector: "ngn-icon", inputs: ["defaultIcon", "icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
18
+ }
19
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnMessage, decorators: [{
20
+ type: Component,
21
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ngn-message', imports: [NgnPt, NgnIcon], providers: [provideSelf(NgnMessage)], template: "@if (icon()) {\r\n <ngn-icon [ptInt]=\"this\" [ptClass]=\"'icon'\" [icon]=\"icon()\" />\r\n}\r\n<div [ptInt]=\"this\" [ptClass]=\"'content'\">\r\n <ng-content />\r\n</div>\r\n" }]
22
+ }], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }] } });
23
+
24
+ /**
25
+ * Generated bundle index. Do not edit.
26
+ */
27
+
28
+ export { NgnMessage };
29
+ //# sourceMappingURL=ngneers-controls-message.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngneers-controls-message.mjs","sources":["../../src/message/message.ts","../../src/message/message.html","../../src/message/ngneers-controls-message.ts"],"sourcesContent":["import { Component, input, ChangeDetectionStrategy } from '@angular/core';\r\nimport { NgnBase, provideSelf, NgnPt } from '@ngneers/controls/base';\r\nimport { NgnIcon } from '@ngneers/controls/icon';\r\nimport { messageControlTemplate } from '@ngneers/controls-themes/templates/message';\r\n\r\nimport type { IconType } from '@ngneers/controls-custom-types';\r\n\r\n/**\r\n * @category control\r\n */\r\n@Component({\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n selector: 'ngn-message',\r\n templateUrl: './message.html',\r\n imports: [NgnPt, NgnIcon],\r\n providers: [provideSelf(NgnMessage)],\r\n})\r\nexport class NgnMessage extends NgnBase<'message'> {\r\n protected readonly theme = this.injectThemeTemplate(messageControlTemplate, 'root');\r\n\r\n /**\r\n * Set an icon to display before the text.\r\n */\r\n public readonly icon = input<IconType>();\r\n}\r\n","@if (icon()) {\r\n <ngn-icon [ptInt]=\"this\" [ptClass]=\"'icon'\" [icon]=\"icon()\" />\r\n}\r\n<div [ptInt]=\"this\" [ptClass]=\"'content'\">\r\n <ng-content />\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;AAOA;;AAEG;AAQG,MAAO,UAAW,SAAQ,OAAkB,CAAA;IAC7B,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,sBAAsB,EAAE,MAAM,CAAC;AAEnF;;AAEG;IACa,IAAI,GAAG,KAAK,CAAA,IAAA,SAAA,GAAA,CAAA,SAAA,EAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAY;uGAN7B,UAAU,EAAA,IAAA,EAAA,IAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAV,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAU,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,SAAA,EAFV,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,EAAA,eAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECftC,mLAMA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDQY,KAAK,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,OAAO,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,MAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAGb,UAAU,EAAA,UAAA,EAAA,CAAA;kBAPtB,SAAS;AACS,YAAA,IAAA,EAAA,CAAA,EAAA,eAAA,EAAA,uBAAuB,CAAC,MAAM,EAAA,QAAA,EACrC,aAAa,WAEd,CAAC,KAAK,EAAE,OAAO,CAAC,EAAA,SAAA,EACd,CAAC,WAAW,YAAY,CAAC,EAAA,QAAA,EAAA,mLAAA,EAAA;;;AEftC;;AAEG;;;;"}
@@ -0,0 +1,111 @@
1
+ import { NgStyle } from '@angular/common';
2
+ import * as i0 from '@angular/core';
3
+ import { inject, input, model, computed, output, effect, ChangeDetectionStrategy, Component } from '@angular/core';
4
+ import { NgnTemplate } from '@ngneers/controls/api/ng';
5
+ import { NgnBase, NgnPt, provideSelf } from '@ngneers/controls/base';
6
+ import { NgnButton } from '@ngneers/controls/button';
7
+ import { I18n } from '@ngneers/controls/i18n';
8
+ import { NgnIcon } from '@ngneers/controls/icon';
9
+ import { NgnItemView } from '@ngneers/controls/item-view';
10
+ import { NgnSelect } from '@ngneers/controls/select';
11
+ import { throwExp } from '@ngneers/controls/utils';
12
+ import { paginatorControlTemplate } from '@ngneers/controls-themes/templates/paginator';
13
+
14
+ /**
15
+ * @category control
16
+ */
17
+ class NgnPaginator extends NgnBase {
18
+ theme = this.injectThemeTemplate(paginatorControlTemplate, 'root');
19
+ i18n = inject(I18n).translations;
20
+ /**
21
+ * Total number of items to paginate.
22
+ */
23
+ totalItems = input.required(...(ngDevMode ? [{ debugName: "totalItems" }] : []));
24
+ /**
25
+ * Number of items per page. If not set, the first value from `possiblePageSizes` will be used.
26
+ */
27
+ pageSize = model(...(ngDevMode ? [undefined, { debugName: "pageSize" }] : []));
28
+ /**
29
+ * Possible page sizes to choose from.
30
+ * @default [5, 10, 25, 50]
31
+ */
32
+ possiblePageSizes = input([5, 10, 25, 50], { ...(ngDevMode ? { debugName: "possiblePageSizes" } : {}), transform: (sizes) => sizes.sort((a, b) => a - b) });
33
+ /**
34
+ * If set to `true`, the page size selector will be hidden and the page size cannot be changed by the user.
35
+ * @default false
36
+ */
37
+ fixedPageSize = input(false, ...(ngDevMode ? [{ debugName: "fixedPageSize" }] : []));
38
+ appliedPageSize = computed(() => this.pageSize() ||
39
+ this.possiblePageSizes()[0] ||
40
+ throwExp('NgnPaginator', 'At least one page size must be provided'), ...(ngDevMode ? [{ debugName: "appliedPageSize" }] : []));
41
+ pageCount = computed(() => Math.ceil(this.totalItems() / this.appliedPageSize()), ...(ngDevMode ? [{ debugName: "pageCount" }] : []));
42
+ pages = computed(() => Array.from({ length: this.pageCount() }, (_, i) => ({ page: i })), ...(ngDevMode ? [{ debugName: "pages" }] : []));
43
+ pageSizeOptions = computed(() => this.possiblePageSizes().map(size => ({
44
+ label: size.toString(),
45
+ value: size,
46
+ })), ...(ngDevMode ? [{ debugName: "pageSizeOptions" }] : []));
47
+ /**
48
+ * Emits the current pagination state whenever the page or page size changes.
49
+ */
50
+ value = output();
51
+ /**
52
+ * Current page index (zero-based).
53
+ * @default 0
54
+ */
55
+ page = model(0, ...(ngDevMode ? [{ debugName: "page" }] : []));
56
+ constructor() {
57
+ super();
58
+ effect(() => {
59
+ const page = this.page();
60
+ const pageSize = this.appliedPageSize();
61
+ this.value.emit({
62
+ page: {
63
+ current: page,
64
+ size: pageSize,
65
+ },
66
+ slice: {
67
+ skip: page * pageSize,
68
+ take: pageSize,
69
+ },
70
+ });
71
+ });
72
+ }
73
+ previousPage(event) {
74
+ const amount = event.shiftKey ? 10 : event.ctrlKey ? 100 : 1;
75
+ const newPage = Math.max(this.page() - amount, 0);
76
+ this.page.set(newPage);
77
+ }
78
+ nextPage(event) {
79
+ const amount = event.shiftKey ? 10 : event.ctrlKey ? 100 : 1;
80
+ const newPage = Math.min(this.page() + amount, this.pageCount() - 1);
81
+ this.page.set(newPage);
82
+ }
83
+ getButtonFontStyles(page) {
84
+ function getFontSizeMultiplier() {
85
+ const charCount = (page + 1).toString().length;
86
+ if (charCount <= 2) {
87
+ return 1;
88
+ }
89
+ return Math.pow(0.85, charCount - 2);
90
+ }
91
+ return {
92
+ fontSize: `${getFontSizeMultiplier()}em`,
93
+ width: 'calc(1rem + 2 * var(--padding))',
94
+ height: 'calc(1rem + 2 * var(--padding))',
95
+ lineHeight: '0',
96
+ };
97
+ }
98
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnPaginator, deps: [], target: i0.ɵɵFactoryTarget.Component });
99
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: NgnPaginator, isStandalone: true, selector: "ngn-paginator", inputs: { totalItems: { classPropertyName: "totalItems", publicName: "totalItems", isSignal: true, isRequired: true, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, possiblePageSizes: { classPropertyName: "possiblePageSizes", publicName: "possiblePageSizes", isSignal: true, isRequired: false, transformFunction: null }, fixedPageSize: { classPropertyName: "fixedPageSize", publicName: "fixedPageSize", isSignal: true, isRequired: false, transformFunction: null }, page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageSize: "pageSizeChange", value: "value", page: "pageChange" }, providers: [provideSelf(NgnPaginator)], usesInheritance: true, ngImport: i0, template: "<button ngnButton [kind]=\"'icon'\" (click)=\"previousPage($event)\">\r\n <ngn-icon [defaultIcon]=\"'chevron_left'\" />\r\n</button>\r\n\r\n<ngn-item-view\r\n #itemView\r\n [items]=\"pages()\"\r\n [idField]=\"'page'\"\r\n [overflowStrategy]=\"'aroundIndex'\"\r\n [overflowStrategyFreezeCount]=\"1\"\r\n [overflowStrategyIndex]=\"page()\"\r\n [sameWidthItems]=\"true\"\r\n>\r\n <ng-template #item let-item [ngnTemplate]=\"itemView.templateTypes.item\">\r\n @let buttonStyles = getButtonFontStyles(item.page);\r\n <button\r\n ngnButton\r\n [kind]=\"'icon'\"\r\n [ngStyle]=\"buttonStyles\"\r\n [style.background]=\"page() === item.page ? 'var(--ngn-color-secondary-500)' : null\"\r\n (click)=\"page.set(item.page)\"\r\n >\r\n {{ item.page + 1 }}\r\n </button>\r\n </ng-template>\r\n <ng-template #overflow let-item [ngnTemplate]=\"itemView.templateTypes.overflow\">\r\n <button ngnButton [kind]=\"'icon'\" style=\"opacity: 0.5\" disabled>...</button>\r\n </ng-template>\r\n</ngn-item-view>\r\n\r\n<button ngnButton [kind]=\"'icon'\" (click)=\"nextPage($event)\">\r\n <ngn-icon [defaultIcon]=\"'chevron_right'\" />\r\n</button>\r\n\r\n@if (!fixedPageSize()) {\r\n <ngn-select\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'page-size-options'\"\r\n [options]=\"pageSizeOptions()\"\r\n [value]=\"appliedPageSize()\"\r\n (valueChange)=\"pageSize.set($event)\"\r\n />\r\n}\r\n", dependencies: [{ kind: "directive", type: NgnButton, selector: "button[ngnButton], a[ngnButton]", inputs: ["inline"] }, { kind: "component", type: NgnIcon, selector: "ngn-icon", inputs: ["defaultIcon", "icon"] }, { kind: "component", type: NgnItemView, selector: "ngn-item-view", inputs: ["idField", "items", "separator", "iconItemSeparator", "overflowStrategy", "overflowStrategyFreezeCount", "overflowStrategyIndex", "sameWidthItems"] }, { kind: "component", type: NgnSelect, selector: "ngn-select", inputs: ["popoverOptions", "options", "filter", "filterText", "filterIcon", "dropdownIcon", "virtual", "itemHeight", "editable", "editableAutoFilter", "multiple", "scrollToSelectedItemOnOpen", "tabindex", "checkbox"] }, { kind: "directive", type: NgnTemplate, selector: "ng-template[ngnTemplate]", inputs: ["ngnTemplate"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgnPt, selector: "[ptInt]", inputs: ["ptInt", "ptClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
100
+ }
101
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnPaginator, decorators: [{
102
+ type: Component,
103
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ngn-paginator', imports: [NgnButton, NgnIcon, NgnItemView, NgnSelect, NgnTemplate, NgStyle, NgnPt], providers: [provideSelf(NgnPaginator)], template: "<button ngnButton [kind]=\"'icon'\" (click)=\"previousPage($event)\">\r\n <ngn-icon [defaultIcon]=\"'chevron_left'\" />\r\n</button>\r\n\r\n<ngn-item-view\r\n #itemView\r\n [items]=\"pages()\"\r\n [idField]=\"'page'\"\r\n [overflowStrategy]=\"'aroundIndex'\"\r\n [overflowStrategyFreezeCount]=\"1\"\r\n [overflowStrategyIndex]=\"page()\"\r\n [sameWidthItems]=\"true\"\r\n>\r\n <ng-template #item let-item [ngnTemplate]=\"itemView.templateTypes.item\">\r\n @let buttonStyles = getButtonFontStyles(item.page);\r\n <button\r\n ngnButton\r\n [kind]=\"'icon'\"\r\n [ngStyle]=\"buttonStyles\"\r\n [style.background]=\"page() === item.page ? 'var(--ngn-color-secondary-500)' : null\"\r\n (click)=\"page.set(item.page)\"\r\n >\r\n {{ item.page + 1 }}\r\n </button>\r\n </ng-template>\r\n <ng-template #overflow let-item [ngnTemplate]=\"itemView.templateTypes.overflow\">\r\n <button ngnButton [kind]=\"'icon'\" style=\"opacity: 0.5\" disabled>...</button>\r\n </ng-template>\r\n</ngn-item-view>\r\n\r\n<button ngnButton [kind]=\"'icon'\" (click)=\"nextPage($event)\">\r\n <ngn-icon [defaultIcon]=\"'chevron_right'\" />\r\n</button>\r\n\r\n@if (!fixedPageSize()) {\r\n <ngn-select\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'page-size-options'\"\r\n [options]=\"pageSizeOptions()\"\r\n [value]=\"appliedPageSize()\"\r\n (valueChange)=\"pageSize.set($event)\"\r\n />\r\n}\r\n" }]
104
+ }], ctorParameters: () => [], propDecorators: { totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }, { type: i0.Output, args: ["pageSizeChange"] }], possiblePageSizes: [{ type: i0.Input, args: [{ isSignal: true, alias: "possiblePageSizes", required: false }] }], fixedPageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "fixedPageSize", required: false }] }], value: [{ type: i0.Output, args: ["value"] }], page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }, { type: i0.Output, args: ["pageChange"] }] } });
105
+
106
+ /**
107
+ * Generated bundle index. Do not edit.
108
+ */
109
+
110
+ export { NgnPaginator };
111
+ //# sourceMappingURL=ngneers-controls-paginator.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngneers-controls-paginator.mjs","sources":["../../src/paginator/paginator.ts","../../src/paginator/paginator.html","../../src/paginator/ngneers-controls-paginator.ts"],"sourcesContent":["import { NgStyle } from '@angular/common';\r\nimport {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n model,\r\n output,\r\n} from '@angular/core';\r\nimport { NgnTemplate } from '@ngneers/controls/api/ng';\r\nimport { NgnBase, NgnPt, provideSelf } from '@ngneers/controls/base';\r\nimport { NgnButton } from '@ngneers/controls/button';\r\nimport { I18n } from '@ngneers/controls/i18n';\r\nimport { NgnIcon } from '@ngneers/controls/icon';\r\nimport { NgnItemView } from '@ngneers/controls/item-view';\r\nimport { NgnSelect } from '@ngneers/controls/select';\r\nimport { throwExp } from '@ngneers/controls/utils';\r\nimport { paginatorControlTemplate } from '@ngneers/controls-themes/templates/paginator';\r\n\r\nimport type { PaginationState } from './types';\r\nimport type { NgnItem } from '@ngneers/controls/api';\r\n\r\n/**\r\n * @category control\r\n */\r\n@Component({\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n selector: 'ngn-paginator',\r\n templateUrl: './paginator.html',\r\n imports: [NgnButton, NgnIcon, NgnItemView, NgnSelect, NgnTemplate, NgStyle, NgnPt],\r\n providers: [provideSelf(NgnPaginator)],\r\n})\r\nexport class NgnPaginator extends NgnBase<'paginator'> {\r\n protected readonly theme = this.injectThemeTemplate(paginatorControlTemplate, 'root');\r\n protected readonly i18n = inject(I18n).translations;\r\n\r\n /**\r\n * Total number of items to paginate.\r\n */\r\n public readonly totalItems = input.required<number>();\r\n /**\r\n * Number of items per page. If not set, the first value from `possiblePageSizes` will be used.\r\n */\r\n public readonly pageSize = model<number>();\r\n /**\r\n * Possible page sizes to choose from.\r\n * @default [5, 10, 25, 50]\r\n */\r\n public readonly possiblePageSizes = input([5, 10, 25, 50], {\r\n transform: (sizes: number[]) => sizes.sort((a, b) => a - b),\r\n });\r\n /**\r\n * If set to `true`, the page size selector will be hidden and the page size cannot be changed by the user.\r\n * @default false\r\n */\r\n public readonly fixedPageSize = input(false);\r\n\r\n protected readonly appliedPageSize = computed(\r\n () =>\r\n this.pageSize() ||\r\n this.possiblePageSizes()[0] ||\r\n throwExp('NgnPaginator', 'At least one page size must be provided')\r\n );\r\n protected readonly pageCount = computed(() =>\r\n Math.ceil(this.totalItems() / this.appliedPageSize())\r\n );\r\n protected readonly pages = computed(() =>\r\n Array.from({ length: this.pageCount() }, (_, i) => ({ page: i }))\r\n );\r\n protected readonly pageSizeOptions = computed<NgnItem[]>(() =>\r\n this.possiblePageSizes().map(size => ({\r\n label: size.toString(),\r\n value: size,\r\n }))\r\n );\r\n\r\n /**\r\n * Emits the current pagination state whenever the page or page size changes.\r\n */\r\n public readonly value = output<PaginationState>();\r\n /**\r\n * Current page index (zero-based).\r\n * @default 0\r\n */\r\n public readonly page = model(0);\r\n\r\n constructor() {\r\n super();\r\n effect(() => {\r\n const page = this.page();\r\n const pageSize = this.appliedPageSize();\r\n this.value.emit({\r\n page: {\r\n current: page,\r\n size: pageSize,\r\n },\r\n slice: {\r\n skip: page * pageSize,\r\n take: pageSize,\r\n },\r\n });\r\n });\r\n }\r\n\r\n protected previousPage(event: PointerEvent): void {\r\n const amount = event.shiftKey ? 10 : event.ctrlKey ? 100 : 1;\r\n const newPage = Math.max(this.page() - amount, 0);\r\n this.page.set(newPage);\r\n }\r\n\r\n protected nextPage(event: PointerEvent): void {\r\n const amount = event.shiftKey ? 10 : event.ctrlKey ? 100 : 1;\r\n const newPage = Math.min(this.page() + amount, this.pageCount() - 1);\r\n this.page.set(newPage);\r\n }\r\n\r\n protected getButtonFontStyles(page: number): {\r\n [klass: string]: string;\r\n } {\r\n function getFontSizeMultiplier() {\r\n const charCount = (page + 1).toString().length;\r\n if (charCount <= 2) {\r\n return 1;\r\n }\r\n return Math.pow(0.85, charCount - 2);\r\n }\r\n\r\n return {\r\n fontSize: `${getFontSizeMultiplier()}em`,\r\n width: 'calc(1rem + 2 * var(--padding))',\r\n height: 'calc(1rem + 2 * var(--padding))',\r\n lineHeight: '0',\r\n };\r\n }\r\n}\r\n","<button ngnButton [kind]=\"'icon'\" (click)=\"previousPage($event)\">\r\n <ngn-icon [defaultIcon]=\"'chevron_left'\" />\r\n</button>\r\n\r\n<ngn-item-view\r\n #itemView\r\n [items]=\"pages()\"\r\n [idField]=\"'page'\"\r\n [overflowStrategy]=\"'aroundIndex'\"\r\n [overflowStrategyFreezeCount]=\"1\"\r\n [overflowStrategyIndex]=\"page()\"\r\n [sameWidthItems]=\"true\"\r\n>\r\n <ng-template #item let-item [ngnTemplate]=\"itemView.templateTypes.item\">\r\n @let buttonStyles = getButtonFontStyles(item.page);\r\n <button\r\n ngnButton\r\n [kind]=\"'icon'\"\r\n [ngStyle]=\"buttonStyles\"\r\n [style.background]=\"page() === item.page ? 'var(--ngn-color-secondary-500)' : null\"\r\n (click)=\"page.set(item.page)\"\r\n >\r\n {{ item.page + 1 }}\r\n </button>\r\n </ng-template>\r\n <ng-template #overflow let-item [ngnTemplate]=\"itemView.templateTypes.overflow\">\r\n <button ngnButton [kind]=\"'icon'\" style=\"opacity: 0.5\" disabled>...</button>\r\n </ng-template>\r\n</ngn-item-view>\r\n\r\n<button ngnButton [kind]=\"'icon'\" (click)=\"nextPage($event)\">\r\n <ngn-icon [defaultIcon]=\"'chevron_right'\" />\r\n</button>\r\n\r\n@if (!fixedPageSize()) {\r\n <ngn-select\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'page-size-options'\"\r\n [options]=\"pageSizeOptions()\"\r\n [value]=\"appliedPageSize()\"\r\n (valueChange)=\"pageSize.set($event)\"\r\n />\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}