@ngneers/controls 0.0.1-next.0 → 0.0.1-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/fesm2022/ngneers-controls-api-ng.mjs +11 -18
  2. package/fesm2022/ngneers-controls-api-ng.mjs.map +1 -1
  3. package/fesm2022/ngneers-controls-api-resize.mjs +7 -0
  4. package/fesm2022/ngneers-controls-api-resize.mjs.map +1 -1
  5. package/fesm2022/ngneers-controls-badge.mjs +160 -0
  6. package/fesm2022/ngneers-controls-badge.mjs.map +1 -0
  7. package/fesm2022/ngneers-controls-base.mjs +85 -8
  8. package/fesm2022/ngneers-controls-base.mjs.map +1 -1
  9. package/fesm2022/{ngneers-controls-calendar-time-CJT5AFlA.mjs → ngneers-controls-calendar-time-paM6WVpV.mjs} +2 -2
  10. package/fesm2022/{ngneers-controls-calendar-time-CJT5AFlA.mjs.map → ngneers-controls-calendar-time-paM6WVpV.mjs.map} +1 -1
  11. package/fesm2022/ngneers-controls-calendar.mjs +13 -6
  12. package/fesm2022/ngneers-controls-calendar.mjs.map +1 -1
  13. package/fesm2022/ngneers-controls-checkbox.mjs +3 -3
  14. package/fesm2022/ngneers-controls-checkbox.mjs.map +1 -1
  15. package/fesm2022/ngneers-controls-color-picker.mjs +336 -0
  16. package/fesm2022/ngneers-controls-color-picker.mjs.map +1 -0
  17. package/fesm2022/ngneers-controls-default-icons.mjs +5 -0
  18. package/fesm2022/ngneers-controls-default-icons.mjs.map +1 -1
  19. package/fesm2022/ngneers-controls-directives.mjs +64 -7
  20. package/fesm2022/ngneers-controls-directives.mjs.map +1 -1
  21. package/fesm2022/ngneers-controls-edit-inplace.mjs +15 -5
  22. package/fesm2022/ngneers-controls-edit-inplace.mjs.map +1 -1
  23. package/fesm2022/ngneers-controls-errors.mjs +203 -148
  24. package/fesm2022/ngneers-controls-errors.mjs.map +1 -1
  25. package/fesm2022/ngneers-controls-filter.mjs +2 -2
  26. package/fesm2022/ngneers-controls-filter.mjs.map +1 -1
  27. package/fesm2022/ngneers-controls-hint.mjs +18 -1
  28. package/fesm2022/ngneers-controls-hint.mjs.map +1 -1
  29. package/fesm2022/ngneers-controls-i18n-translations-de.mjs +17 -0
  30. package/fesm2022/ngneers-controls-i18n-translations-de.mjs.map +1 -1
  31. package/fesm2022/ngneers-controls-i18n-translations-en.mjs +19 -0
  32. package/fesm2022/ngneers-controls-i18n-translations-en.mjs.map +1 -1
  33. package/fesm2022/ngneers-controls-icon.mjs +23 -6
  34. package/fesm2022/ngneers-controls-icon.mjs.map +1 -1
  35. package/fesm2022/ngneers-controls-input-field.mjs +18 -2
  36. package/fesm2022/ngneers-controls-input-field.mjs.map +1 -1
  37. package/fesm2022/ngneers-controls-input.mjs +49 -9
  38. package/fesm2022/ngneers-controls-input.mjs.map +1 -1
  39. package/fesm2022/ngneers-controls-list-box.mjs +2 -2
  40. package/fesm2022/ngneers-controls-list-box.mjs.map +1 -1
  41. package/fesm2022/ngneers-controls-mask-input.mjs +4 -1
  42. package/fesm2022/ngneers-controls-mask-input.mjs.map +1 -1
  43. package/fesm2022/ngneers-controls-number-input.mjs +4 -4
  44. package/fesm2022/ngneers-controls-number-input.mjs.map +1 -1
  45. package/fesm2022/ngneers-controls-otp.mjs +263 -0
  46. package/fesm2022/ngneers-controls-otp.mjs.map +1 -0
  47. package/fesm2022/ngneers-controls-paginator.mjs +36 -9
  48. package/fesm2022/ngneers-controls-paginator.mjs.map +1 -1
  49. package/fesm2022/ngneers-controls-radio.mjs +4 -4
  50. package/fesm2022/ngneers-controls-radio.mjs.map +1 -1
  51. package/fesm2022/ngneers-controls-rating.mjs +180 -0
  52. package/fesm2022/ngneers-controls-rating.mjs.map +1 -0
  53. package/fesm2022/ngneers-controls-scroll-shadow.mjs +33 -7
  54. package/fesm2022/ngneers-controls-scroll-shadow.mjs.map +1 -1
  55. package/fesm2022/ngneers-controls-scroller.mjs +4 -2
  56. package/fesm2022/ngneers-controls-scroller.mjs.map +1 -1
  57. package/fesm2022/ngneers-controls-select-button.mjs +2 -1
  58. package/fesm2022/ngneers-controls-select-button.mjs.map +1 -1
  59. package/fesm2022/ngneers-controls-select.mjs +24 -4
  60. package/fesm2022/ngneers-controls-select.mjs.map +1 -1
  61. package/fesm2022/ngneers-controls-slider.mjs +3 -3
  62. package/fesm2022/ngneers-controls-slider.mjs.map +1 -1
  63. package/fesm2022/ngneers-controls-splitter.mjs +43 -12
  64. package/fesm2022/ngneers-controls-splitter.mjs.map +1 -1
  65. package/fesm2022/ngneers-controls-stepper.mjs +142 -0
  66. package/fesm2022/ngneers-controls-stepper.mjs.map +1 -0
  67. package/fesm2022/ngneers-controls-switch.mjs +3 -3
  68. package/fesm2022/ngneers-controls-switch.mjs.map +1 -1
  69. package/fesm2022/ngneers-controls-table.mjs +282 -15
  70. package/fesm2022/ngneers-controls-table.mjs.map +1 -1
  71. package/fesm2022/ngneers-controls-tabs.mjs +2 -2
  72. package/fesm2022/ngneers-controls-tabs.mjs.map +1 -1
  73. package/fesm2022/ngneers-controls-toggle-button.mjs +3 -3
  74. package/fesm2022/ngneers-controls-toggle-button.mjs.map +1 -1
  75. package/fesm2022/ngneers-controls-tooltip.mjs +16 -28
  76. package/fesm2022/ngneers-controls-tooltip.mjs.map +1 -1
  77. package/fesm2022/ngneers-controls-tree.mjs +2 -2
  78. package/fesm2022/ngneers-controls-tree.mjs.map +1 -1
  79. package/fesm2022/ngneers-controls-utils.mjs +138 -1
  80. package/fesm2022/ngneers-controls-utils.mjs.map +1 -1
  81. package/package.json +22 -2
  82. package/types/ngneers-controls-api-ng.d.ts +12 -9
  83. package/types/ngneers-controls-badge.d.ts +67 -0
  84. package/types/ngneers-controls-base.d.ts +61 -4
  85. package/types/ngneers-controls-breadcrumb.d.ts +17 -0
  86. package/types/ngneers-controls-calendar.d.ts +24 -6
  87. package/types/ngneers-controls-chip.d.ts +17 -0
  88. package/types/ngneers-controls-color-picker.d.ts +119 -0
  89. package/types/ngneers-controls-dialog.d.ts +17 -0
  90. package/types/ngneers-controls-directives.d.ts +31 -2
  91. package/types/ngneers-controls-drawer.d.ts +17 -0
  92. package/types/ngneers-controls-edit-inplace.d.ts +23 -0
  93. package/types/ngneers-controls-errors.d.ts +105 -16
  94. package/types/ngneers-controls-filter.d.ts +30 -13
  95. package/types/ngneers-controls-hint.d.ts +8 -1
  96. package/types/ngneers-controls-i18n-translations-de.d.ts +17 -0
  97. package/types/ngneers-controls-i18n-translations-en.d.ts +17 -0
  98. package/types/ngneers-controls-i18n.d.ts +17 -0
  99. package/types/ngneers-controls-icon.d.ts +2 -2
  100. package/types/ngneers-controls-input-field.d.ts +28 -2
  101. package/types/ngneers-controls-input.d.ts +35 -3
  102. package/types/ngneers-controls-list-box.d.ts +17 -0
  103. package/types/ngneers-controls-mask-input.d.ts +17 -0
  104. package/types/ngneers-controls-otp.d.ts +262 -0
  105. package/types/ngneers-controls-paginator.d.ts +34 -3
  106. package/types/ngneers-controls-rating.d.ts +69 -0
  107. package/types/ngneers-controls-scroll-shadow.d.ts +11 -2
  108. package/types/ngneers-controls-scroller.d.ts +3 -1
  109. package/types/ngneers-controls-select.d.ts +30 -3
  110. package/types/ngneers-controls-snackbar.d.ts +17 -0
  111. package/types/ngneers-controls-splitter.d.ts +26 -2
  112. package/types/ngneers-controls-state.d.ts +2 -2
  113. package/types/ngneers-controls-stepper.d.ts +68 -0
  114. package/types/ngneers-controls-table.d.ts +276 -169
  115. package/types/ngneers-controls-toast.d.ts +17 -0
  116. package/types/ngneers-controls-tooltip.d.ts +0 -1
  117. package/types/ngneers-controls-tree.d.ts +17 -0
  118. package/types/ngneers-controls-upload.d.ts +17 -0
  119. package/types/ngneers-controls-utils.d.ts +27 -2
@@ -1 +1 @@
1
- {"version":3,"file":"ngneers-controls-i18n-translations-de.mjs","sources":["../../src/i18n/translations/de/index.ts","../../src/i18n/translations/de/ngneers-controls-i18n-translations-de.ts"],"sourcesContent":["export const de = {\n calendar: {\n today: 'Heute',\n input: 'Datum',\n selectYear: 'Jahr auswählen',\n selectMonth: 'Monat auswählen',\n previousMonth: 'Vorheriger Monat',\n nextMonth: 'Nächster Monat',\n weekdays: {\n monday: 'Montag',\n tuesday: 'Dienstag',\n wednesday: 'Mittwoch',\n thursday: 'Donnerstag',\n friday: 'Freitag',\n saturday: 'Samstag',\n sunday: 'Sonntag',\n },\n weekdaysShort: {\n monday: 'Mo',\n tuesday: 'Di',\n wednesday: 'Mi',\n thursday: 'Do',\n friday: 'Fr',\n saturday: 'Sa',\n sunday: 'So',\n },\n months: {\n january: 'Januar',\n february: 'Februar',\n march: 'März',\n april: 'April',\n may: 'Mai',\n june: 'Juni',\n july: 'Juli',\n august: 'August',\n september: 'September',\n october: 'Oktober',\n november: 'November',\n december: 'Dezember',\n },\n },\n editInplace: {\n placeholder: 'Klicken zum Bearbeiten',\n confirm: 'Bestätigen',\n },\n filter: {\n noFilter: 'Kein Filter',\n addCondition: 'Bedingung hinzufügen',\n removeCondition: 'Bedingung entfernen',\n operator: 'Operator',\n value: 'Wert',\n clear: 'Zurücksetzen',\n apply: 'Anwenden',\n cancel: 'Abbrechen',\n matchModeLabel: 'Match-Modus',\n match: {\n all: 'Alle Bedingungen',\n any: 'Beliebige Bedingung',\n and: 'und',\n or: 'oder',\n },\n selected: 'ausgewählt',\n conditions: 'Bedingungen',\n operators: {\n isEqual: 'Ist gleich',\n isNotEqual: 'Ist nicht gleich',\n contains: 'Enthält',\n startsWith: 'Beginnt mit',\n endsWith: 'Endet mit',\n in: 'Ist eines von',\n isEmpty: 'Ist leer',\n isNotEmpty: 'Ist nicht leer',\n greaterThan: 'Größer als',\n greaterThanOrEqual: 'Größer oder gleich',\n lessThan: 'Kleiner als',\n lessThanOrEqual: 'Kleiner oder gleich',\n after: 'Nach',\n onOrAfter: 'Am oder nach',\n before: 'Vor',\n onOrBefore: 'Am oder vor',\n isTrue: 'Ja',\n isFalse: 'Nein',\n custom: 'Benutzerdefiniert',\n },\n },\n splitter: {\n handleLabel: 'Ziehen zum Ändern der Größe',\n },\n inputField: {\n clearInput: 'Eingabe löschen',\n },\n maskInput: {\n roleDescription: 'formatierte Eingabe',\n segmentRange: '{{ name }}, {{ min }} bis {{ max }}',\n optionSeparator: ' oder ',\n },\n drawer: {\n close: 'Schließen',\n },\n dialog: {\n close: 'Schließen',\n },\n chip: {\n close: 'Entfernen',\n },\n breadcrumb: {\n overflow: 'Mehr anzeigen',\n },\n toast: {\n close: 'Schließen',\n region: 'Benachrichtigungen',\n },\n snackbar: {\n close: 'Schließen',\n region: 'Benachrichtigungen',\n severity: {\n error: 'Fehler:',\n warning: 'Warnung:',\n success: 'Erfolg:',\n info: 'Info:',\n },\n },\n upload: {\n upload: 'Hochladen',\n // Per-item action labels are parameterized so locales control word order.\n uploadNamed: '{{ name }} hochladen',\n retryNamed: '{{ name }} erneut versuchen',\n cancelNamed: '{{ name }} abbrechen',\n removeNamed: '{{ name }} entfernen',\n progressNamed: 'Upload-Fortschritt für {{ name }}',\n },\n select: {\n filterOptions: 'Optionen filtern',\n },\n paginator: {\n previousPage: 'Vorherige Seite',\n nextPage: 'Nächste Seite',\n },\n listBox: {\n noItemsFound: 'Keine Einträge gefunden',\n },\n tree: {\n noItemsFound: 'Keine Einträge gefunden',\n },\n table: {\n selectAllRows: 'Alle Zeilen auswählen',\n selectRow: 'Zeile auswählen',\n sortedBy: 'Sortiert nach {{ column }}, {{ direction }}',\n sortAscending: 'aufsteigend',\n sortDescending: 'absteigend',\n sortCleared: 'Sortierung aufgehoben',\n selectedCount: '{{ count }} von {{ total }} ausgewählt',\n page: 'Seite {{ page }} von {{ pages }}',\n resultCount: '{{ count }} Ergebnisse',\n },\n state: {\n loading: 'Wird geladen',\n success: 'Erfolg',\n warning: 'Warnung',\n error: 'Fehler',\n cancelled: 'Abgebrochen',\n },\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngneers-controls-i18n-translations-de.mjs","sources":["../../src/i18n/translations/de/index.ts","../../src/i18n/translations/de/ngneers-controls-i18n-translations-de.ts"],"sourcesContent":["export const de = {\n calendar: {\n today: 'Heute',\n input: 'Datum',\n selectYear: 'Jahr auswählen',\n selectMonth: 'Monat auswählen',\n previousMonth: 'Vorheriger Monat',\n nextMonth: 'Nächster Monat',\n weekdays: {\n monday: 'Montag',\n tuesday: 'Dienstag',\n wednesday: 'Mittwoch',\n thursday: 'Donnerstag',\n friday: 'Freitag',\n saturday: 'Samstag',\n sunday: 'Sonntag',\n },\n weekdaysShort: {\n monday: 'Mo',\n tuesday: 'Di',\n wednesday: 'Mi',\n thursday: 'Do',\n friday: 'Fr',\n saturday: 'Sa',\n sunday: 'So',\n },\n months: {\n january: 'Januar',\n february: 'Februar',\n march: 'März',\n april: 'April',\n may: 'Mai',\n june: 'Juni',\n july: 'Juli',\n august: 'August',\n september: 'September',\n october: 'Oktober',\n november: 'November',\n december: 'Dezember',\n },\n },\n editInplace: {\n placeholder: 'Klicken zum Bearbeiten',\n confirm: 'Bestätigen',\n },\n filter: {\n noFilter: 'Kein Filter',\n addCondition: 'Bedingung hinzufügen',\n removeCondition: 'Bedingung entfernen',\n operator: 'Operator',\n value: 'Wert',\n clear: 'Zurücksetzen',\n apply: 'Anwenden',\n cancel: 'Abbrechen',\n matchModeLabel: 'Match-Modus',\n match: {\n all: 'Alle Bedingungen',\n any: 'Beliebige Bedingung',\n and: 'und',\n or: 'oder',\n },\n selected: 'ausgewählt',\n conditions: 'Bedingungen',\n operators: {\n isEqual: 'Ist gleich',\n isNotEqual: 'Ist nicht gleich',\n contains: 'Enthält',\n startsWith: 'Beginnt mit',\n endsWith: 'Endet mit',\n in: 'Ist eines von',\n isEmpty: 'Ist leer',\n isNotEmpty: 'Ist nicht leer',\n greaterThan: 'Größer als',\n greaterThanOrEqual: 'Größer oder gleich',\n lessThan: 'Kleiner als',\n lessThanOrEqual: 'Kleiner oder gleich',\n after: 'Nach',\n onOrAfter: 'Am oder nach',\n before: 'Vor',\n onOrBefore: 'Am oder vor',\n isTrue: 'Ja',\n isFalse: 'Nein',\n custom: 'Benutzerdefiniert',\n },\n },\n splitter: {\n handleLabel: 'Ziehen zum Ändern der Größe',\n },\n inputField: {\n clearInput: 'Eingabe löschen',\n },\n maskInput: {\n roleDescription: 'formatierte Eingabe',\n segmentRange: '{{ name }}, {{ min }} bis {{ max }}',\n optionSeparator: ' oder ',\n },\n otp: {\n cellLabel: 'Zeichen {{ index }} von {{ total }}',\n },\n drawer: {\n close: 'Schließen',\n },\n dialog: {\n close: 'Schließen',\n },\n chip: {\n close: 'Entfernen',\n },\n breadcrumb: {\n overflow: 'Mehr anzeigen',\n },\n toast: {\n close: 'Schließen',\n region: 'Benachrichtigungen',\n },\n snackbar: {\n close: 'Schließen',\n region: 'Benachrichtigungen',\n severity: {\n error: 'Fehler:',\n warning: 'Warnung:',\n success: 'Erfolg:',\n info: 'Info:',\n },\n },\n upload: {\n upload: 'Hochladen',\n // Per-item action labels are parameterized so locales control word order.\n uploadNamed: '{{ name }} hochladen',\n retryNamed: '{{ name }} erneut versuchen',\n cancelNamed: '{{ name }} abbrechen',\n removeNamed: '{{ name }} entfernen',\n progressNamed: 'Upload-Fortschritt für {{ name }}',\n },\n select: {\n filterOptions: 'Optionen filtern',\n },\n paginator: {\n previousPage: 'Vorherige Seite',\n nextPage: 'Nächste Seite',\n },\n listBox: {\n noItemsFound: 'Keine Einträge gefunden',\n },\n tree: {\n noItemsFound: 'Keine Einträge gefunden',\n },\n table: {\n selectAllRows: 'Alle Zeilen auswählen',\n selectRow: 'Zeile auswählen',\n sortedBy: 'Sortiert nach {{ column }}, {{ direction }}',\n sortAscending: 'aufsteigend',\n sortDescending: 'absteigend',\n sortCleared: 'Sortierung aufgehoben',\n selectedCount: '{{ count }} von {{ total }} ausgewählt',\n page: 'Seite {{ page }} von {{ pages }}',\n resultCount: '{{ count }} Ergebnisse',\n retry: 'Erneut versuchen',\n loadError: 'Daten konnten nicht geladen werden',\n },\n state: {\n loading: 'Wird geladen',\n success: 'Erfolg',\n warning: 'Warnung',\n error: 'Fehler',\n cancelled: 'Abgebrochen',\n },\n errors: {\n pending: 'Wird geprüft...',\n required: 'Erforderlich',\n email: 'Gültige E-Mail-Adresse eingeben',\n minlength: 'Mindestens {{ requiredLength }} Zeichen verwenden',\n maxlength: 'Höchstens {{ requiredLength }} Zeichen verwenden',\n minLength: 'Mindestens {{ minLength }} Zeichen verwenden',\n maxLength: 'Höchstens {{ maxLength }} Zeichen verwenden',\n min: 'Mindestens {{ min }}',\n max: 'Höchstens {{ max }}',\n pattern: 'Ungültiges Format',\n },\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -94,6 +94,9 @@ const en = {
94
94
  segmentRange: '{{ name }}, {{ min }} to {{ max }}',
95
95
  optionSeparator: ' or ',
96
96
  },
97
+ otp: {
98
+ cellLabel: 'Character {{ index }} of {{ total }}',
99
+ },
97
100
  drawer: {
98
101
  close: 'Close',
99
102
  },
@@ -152,6 +155,8 @@ const en = {
152
155
  selectedCount: '{{ count }} of {{ total }} selected',
153
156
  page: 'Page {{ page }} of {{ pages }}',
154
157
  resultCount: '{{ count }} results',
158
+ retry: 'Retry',
159
+ loadError: 'Failed to load data',
155
160
  },
156
161
  state: {
157
162
  loading: 'Loading',
@@ -160,6 +165,20 @@ const en = {
160
165
  error: 'Error',
161
166
  cancelled: 'Cancelled',
162
167
  },
168
+ errors: {
169
+ pending: 'Validating...',
170
+ required: 'Required',
171
+ email: 'Enter a valid email address',
172
+ // classic Angular length errors expose `requiredLength`
173
+ minlength: 'Use at least {{ requiredLength }} characters',
174
+ maxlength: 'Use at most {{ requiredLength }} characters',
175
+ // signal-forms length errors expose the limit under its own name
176
+ minLength: 'Use at least {{ minLength }} characters',
177
+ maxLength: 'Use at most {{ maxLength }} characters',
178
+ min: 'Must be at least {{ min }}',
179
+ max: 'Must be at most {{ max }}',
180
+ pattern: 'Invalid format',
181
+ },
163
182
  };
164
183
 
165
184
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ngneers-controls-i18n-translations-en.mjs","sources":["../../src/i18n/translations/en/index.ts","../../src/i18n/translations/en/ngneers-controls-i18n-translations-en.ts"],"sourcesContent":["export const en = {\n calendar: {\n today: 'Today',\n input: 'Date',\n selectYear: 'Select year',\n selectMonth: 'Select month',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n weekdays: {\n monday: 'Monday',\n tuesday: 'Tuesday',\n wednesday: 'Wednesday',\n thursday: 'Thursday',\n friday: 'Friday',\n saturday: 'Saturday',\n sunday: 'Sunday',\n },\n weekdaysShort: {\n monday: 'Mo',\n tuesday: 'Tu',\n wednesday: 'We',\n thursday: 'Th',\n friday: 'Fr',\n saturday: 'Sa',\n sunday: 'Su',\n },\n months: {\n january: 'January',\n february: 'February',\n march: 'March',\n april: 'April',\n may: 'May',\n june: 'June',\n july: 'July',\n august: 'August',\n september: 'September',\n october: 'October',\n november: 'November',\n december: 'December',\n },\n },\n editInplace: {\n placeholder: 'Click to edit',\n confirm: 'Confirm',\n },\n filter: {\n noFilter: 'No filter',\n addCondition: 'Add condition',\n removeCondition: 'Remove condition',\n operator: 'Operator',\n value: 'Value',\n clear: 'Clear',\n apply: 'Apply',\n cancel: 'Cancel',\n matchModeLabel: 'Match mode',\n match: {\n all: 'Match all',\n any: 'Match any',\n and: 'and',\n or: 'or',\n },\n selected: 'selected',\n conditions: 'conditions',\n operators: {\n isEqual: 'Is equal',\n isNotEqual: 'Is not equal',\n contains: 'Contains',\n startsWith: 'Starts with',\n endsWith: 'Ends with',\n in: 'Is one of',\n isEmpty: 'Is empty',\n isNotEmpty: 'Is not empty',\n greaterThan: 'Greater than',\n greaterThanOrEqual: 'Greater than or equal',\n lessThan: 'Less than',\n lessThanOrEqual: 'Less than or equal',\n after: 'After',\n onOrAfter: 'On or after',\n before: 'Before',\n onOrBefore: 'On or before',\n isTrue: 'Yes',\n isFalse: 'No',\n custom: 'Custom',\n },\n },\n splitter: {\n handleLabel: 'Drag to resize',\n },\n inputField: {\n clearInput: 'Clear input',\n },\n maskInput: {\n roleDescription: 'formatted input',\n segmentRange: '{{ name }}, {{ min }} to {{ max }}',\n optionSeparator: ' or ',\n },\n drawer: {\n close: 'Close',\n },\n dialog: {\n close: 'Close',\n },\n chip: {\n close: 'Remove',\n },\n breadcrumb: {\n overflow: 'Show more',\n },\n toast: {\n close: 'Close',\n region: 'Notifications',\n },\n snackbar: {\n close: 'Close',\n region: 'Notifications',\n severity: {\n error: 'Error:',\n warning: 'Warning:',\n success: 'Success:',\n info: 'Info:',\n },\n },\n upload: {\n upload: 'Upload',\n // Per-item action labels are parameterized so locales control word order.\n uploadNamed: 'Upload {{ name }}',\n retryNamed: 'Retry {{ name }}',\n cancelNamed: 'Cancel {{ name }}',\n removeNamed: 'Remove {{ name }}',\n progressNamed: 'Upload progress for {{ name }}',\n },\n select: {\n filterOptions: 'Filter options',\n },\n paginator: {\n previousPage: 'Previous page',\n nextPage: 'Next page',\n },\n listBox: {\n noItemsFound: 'No items found',\n },\n tree: {\n noItemsFound: 'No items found',\n },\n table: {\n selectAllRows: 'Select all rows',\n selectRow: 'Select row',\n sortedBy: 'Sorted by {{ column }}, {{ direction }}',\n sortAscending: 'ascending',\n sortDescending: 'descending',\n sortCleared: 'Sorting cleared',\n selectedCount: '{{ count }} of {{ total }} selected',\n page: 'Page {{ page }} of {{ pages }}',\n resultCount: '{{ count }} results',\n },\n state: {\n loading: 'Loading',\n success: 'Success',\n warning: 'Warning',\n error: 'Error',\n cancelled: 'Cancelled',\n },\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngneers-controls-i18n-translations-en.mjs","sources":["../../src/i18n/translations/en/index.ts","../../src/i18n/translations/en/ngneers-controls-i18n-translations-en.ts"],"sourcesContent":["export const en = {\n calendar: {\n today: 'Today',\n input: 'Date',\n selectYear: 'Select year',\n selectMonth: 'Select month',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n weekdays: {\n monday: 'Monday',\n tuesday: 'Tuesday',\n wednesday: 'Wednesday',\n thursday: 'Thursday',\n friday: 'Friday',\n saturday: 'Saturday',\n sunday: 'Sunday',\n },\n weekdaysShort: {\n monday: 'Mo',\n tuesday: 'Tu',\n wednesday: 'We',\n thursday: 'Th',\n friday: 'Fr',\n saturday: 'Sa',\n sunday: 'Su',\n },\n months: {\n january: 'January',\n february: 'February',\n march: 'March',\n april: 'April',\n may: 'May',\n june: 'June',\n july: 'July',\n august: 'August',\n september: 'September',\n october: 'October',\n november: 'November',\n december: 'December',\n },\n },\n editInplace: {\n placeholder: 'Click to edit',\n confirm: 'Confirm',\n },\n filter: {\n noFilter: 'No filter',\n addCondition: 'Add condition',\n removeCondition: 'Remove condition',\n operator: 'Operator',\n value: 'Value',\n clear: 'Clear',\n apply: 'Apply',\n cancel: 'Cancel',\n matchModeLabel: 'Match mode',\n match: {\n all: 'Match all',\n any: 'Match any',\n and: 'and',\n or: 'or',\n },\n selected: 'selected',\n conditions: 'conditions',\n operators: {\n isEqual: 'Is equal',\n isNotEqual: 'Is not equal',\n contains: 'Contains',\n startsWith: 'Starts with',\n endsWith: 'Ends with',\n in: 'Is one of',\n isEmpty: 'Is empty',\n isNotEmpty: 'Is not empty',\n greaterThan: 'Greater than',\n greaterThanOrEqual: 'Greater than or equal',\n lessThan: 'Less than',\n lessThanOrEqual: 'Less than or equal',\n after: 'After',\n onOrAfter: 'On or after',\n before: 'Before',\n onOrBefore: 'On or before',\n isTrue: 'Yes',\n isFalse: 'No',\n custom: 'Custom',\n },\n },\n splitter: {\n handleLabel: 'Drag to resize',\n },\n inputField: {\n clearInput: 'Clear input',\n },\n maskInput: {\n roleDescription: 'formatted input',\n segmentRange: '{{ name }}, {{ min }} to {{ max }}',\n optionSeparator: ' or ',\n },\n otp: {\n cellLabel: 'Character {{ index }} of {{ total }}',\n },\n drawer: {\n close: 'Close',\n },\n dialog: {\n close: 'Close',\n },\n chip: {\n close: 'Remove',\n },\n breadcrumb: {\n overflow: 'Show more',\n },\n toast: {\n close: 'Close',\n region: 'Notifications',\n },\n snackbar: {\n close: 'Close',\n region: 'Notifications',\n severity: {\n error: 'Error:',\n warning: 'Warning:',\n success: 'Success:',\n info: 'Info:',\n },\n },\n upload: {\n upload: 'Upload',\n // Per-item action labels are parameterized so locales control word order.\n uploadNamed: 'Upload {{ name }}',\n retryNamed: 'Retry {{ name }}',\n cancelNamed: 'Cancel {{ name }}',\n removeNamed: 'Remove {{ name }}',\n progressNamed: 'Upload progress for {{ name }}',\n },\n select: {\n filterOptions: 'Filter options',\n },\n paginator: {\n previousPage: 'Previous page',\n nextPage: 'Next page',\n },\n listBox: {\n noItemsFound: 'No items found',\n },\n tree: {\n noItemsFound: 'No items found',\n },\n table: {\n selectAllRows: 'Select all rows',\n selectRow: 'Select row',\n sortedBy: 'Sorted by {{ column }}, {{ direction }}',\n sortAscending: 'ascending',\n sortDescending: 'descending',\n sortCleared: 'Sorting cleared',\n selectedCount: '{{ count }} of {{ total }} selected',\n page: 'Page {{ page }} of {{ pages }}',\n resultCount: '{{ count }} results',\n retry: 'Retry',\n loadError: 'Failed to load data',\n },\n state: {\n loading: 'Loading',\n success: 'Success',\n warning: 'Warning',\n error: 'Error',\n cancelled: 'Cancelled',\n },\n errors: {\n pending: 'Validating...',\n required: 'Required',\n email: 'Enter a valid email address',\n // classic Angular length errors expose `requiredLength`\n minlength: 'Use at least {{ requiredLength }} characters',\n maxlength: 'Use at most {{ requiredLength }} characters',\n // signal-forms length errors expose the limit under its own name\n minLength: 'Use at least {{ minLength }} characters',\n maxLength: 'Use at most {{ maxLength }} characters',\n min: 'Must be at least {{ min }}',\n max: 'Must be at most {{ max }}',\n pattern: 'Invalid format',\n },\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ import { signal, Service, InjectionToken, inject, input, computed, afterRenderEf
3
3
  import { NgTemplateOutlet } from '@angular/common';
4
4
  import { DomSanitizer } from '@angular/platform-browser';
5
5
  import { NgnBase, NgnPt, provideSelf } from '@ngneers/controls/base';
6
- import { NgnError } from '@ngneers/controls/utils';
6
+ import { Logger, NgnError } from '@ngneers/controls/utils';
7
7
  import { iconControlTemplate } from '@ngneers/controls-themes/templates/icon';
8
8
 
9
9
  class GlobalIconTemplate {
@@ -49,12 +49,15 @@ const NGN_ICON_KEYS = [
49
49
  'menu-submenu',
50
50
  'paginator-previous',
51
51
  'paginator-next',
52
+ 'rating-full',
53
+ 'rating-empty',
52
54
  'search',
53
55
  'sort-neutral',
54
56
  'sort-ascending',
55
57
  'sort-descending',
56
58
  'spin-decrement',
57
59
  'spin-increment',
60
+ 'stepper-completed',
58
61
  'table-group-toggle',
59
62
  'tabs-scroll-left',
60
63
  'tabs-scroll-right',
@@ -78,7 +81,19 @@ function withCustomIcons(registry) {
78
81
  };
79
82
  }
80
83
 
84
+ /**
85
+ * CJS icon modules (e.g. `@iconify/icons-tabler/*`) bind as `{ __esModule, default: <data> }`
86
+ * under Node ESM interop; unwrap to the real Iconify data so `.body` is readable.
87
+ */
88
+ function unwrapIcon(mod) {
89
+ return mod && typeof mod === 'object' && 'default' in mod ? mod.default : mod;
90
+ }
81
91
  function generateIconSvg(sanitizer, iconData, scale) {
92
+ iconData = unwrapIcon(iconData);
93
+ if (typeof iconData?.body !== 'string') {
94
+ Logger.error(new NgnError('icon', 'Icon data has no string "body". If importing from a CommonJS icon package, the module default may need unwrapping.', iconData));
95
+ return null;
96
+ }
82
97
  // Note: @iconify/types documents default as 16, but we default to 24 to match Tabler.
83
98
  // All Tabler icons provide explicit dimensions, so this fallback rarely triggers.
84
99
  const width = iconData.width ?? 24;
@@ -115,7 +130,7 @@ class NgnIcon extends NgnBase {
115
130
  icon = input(/* @ts-ignore */
116
131
  ...(ngDevMode ? [undefined, { debugName: "icon" }] : /* istanbul ignore next */ []));
117
132
  iconSvg = computed(() => {
118
- const value = this.icon();
133
+ const value = unwrapIcon(this.icon());
119
134
  if (!value || typeof value !== 'object')
120
135
  return null;
121
136
  let iconData;
@@ -123,9 +138,11 @@ class NgnIcon extends NgnBase {
123
138
  if ('body' in value) {
124
139
  iconData = value;
125
140
  }
126
- else if ('icon' in value && typeof value.icon === 'object' && 'body' in value.icon) {
141
+ else if ('icon' in value &&
142
+ typeof value.icon === 'object' &&
143
+ 'body' in unwrapIcon(value.icon)) {
127
144
  const entry = value;
128
- iconData = entry.icon;
145
+ iconData = unwrapIcon(entry.icon);
129
146
  scale = entry.scale ?? 1;
130
147
  }
131
148
  else {
@@ -138,9 +155,9 @@ class NgnIcon extends NgnBase {
138
155
  const key = this.defaultIcon();
139
156
  if (!key || this._isCustom || !this._registry)
140
157
  return null;
141
- const raw = this._registry[key];
158
+ const raw = unwrapIcon(this._registry[key]);
142
159
  const entry = 'body' in raw ? { icon: raw, scale: 1 } : raw;
143
- return generateIconSvg(this._sanitizer, entry.icon, entry.scale ?? 1);
160
+ return generateIconSvg(this._sanitizer, unwrapIcon(entry.icon), entry.scale ?? 1);
144
161
  }, /* @ts-ignore */
145
162
  ...(ngDevMode ? [{ debugName: "defaultIconSvg" }] : /* istanbul ignore next */ []));
146
163
  customDefaultIcon = computed(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"ngneers-controls-icon.mjs","sources":["../../src/icon/global-icon-template.ts","../../src/icon/icon-registry.ts","../../src/icon/icon.ts","../../src/icon/icon.html","../../src/icon/ngneers-controls-icon.ts"],"sourcesContent":["import { signal, TemplateRef, type OnDestroy, Service } from '@angular/core';\n\nimport type { IconTemplateContext } from './types';\n\nexport type IconTemplateType = TemplateRef<IconTemplateContext>;\n\n@Service()\nexport class GlobalIconTemplate implements OnDestroy {\n private readonly _globalIconTemplate = signal<IconTemplateType | null>(null);\n\n public readonly globalIconTemplate = this._globalIconTemplate.asReadonly();\n\n public setGlobalIconTemplate(template: IconTemplateType) {\n this._globalIconTemplate.set(template);\n }\n\n public ngOnDestroy() {\n this._globalIconTemplate.set(null);\n }\n}\n","import { InjectionToken } from '@angular/core';\n\nimport type { IconifyIcon } from '@iconify/types';\nimport type { NgnFeature } from '@ngneers/controls/api/ng';\nimport type { IconType, NgnIconEntry } from '@ngneers/controls-custom-types';\n\nexport type { NgnIconEntry } from '@ngneers/controls-custom-types';\n\nexport const NGN_ICON_KEYS = [\n 'accordion-collapse',\n 'accordion-expand',\n 'breadcrumb-separator',\n 'breadcrumb-overflow',\n 'calendar-trigger',\n 'calendar-previous-month',\n 'calendar-next-month',\n 'checkbox-checked',\n 'checkbox-indeterminate',\n 'chip-remove',\n 'dialog-close',\n 'drawer-close',\n 'dropdown-toggle',\n 'edit-confirm',\n 'filter-active',\n 'filter-inactive',\n 'filter-remove',\n 'hint-info',\n 'hint-success',\n 'hint-warning',\n 'hint-error',\n 'input-clear',\n 'menu-submenu',\n 'paginator-previous',\n 'paginator-next',\n 'search',\n 'sort-neutral',\n 'sort-ascending',\n 'sort-descending',\n 'spin-decrement',\n 'spin-increment',\n 'table-group-toggle',\n 'tabs-scroll-left',\n 'tabs-scroll-right',\n 'toast-close',\n 'snackbar-close',\n 'upload-trigger',\n 'upload-done',\n 'upload-failed',\n 'upload-retry',\n 'upload-cancel',\n 'upload-remove',\n] as const;\n\nexport type NgnIconKey = (typeof NGN_ICON_KEYS)[number];\n\nexport type NgnIconRegistry = Record<NgnIconKey, IconifyIcon | NgnIconEntry>;\n\nexport type NgnCustomIconRegistry = Record<NgnIconKey, IconType>;\n\nexport const NGN_ICON_REGISTRY = new InjectionToken<NgnIconRegistry | NgnCustomIconRegistry>(\n 'NGN_ICON_REGISTRY'\n);\n\nexport const NGN_CUSTOM_ICONS = new InjectionToken<boolean>('NGN_CUSTOM_ICONS');\n\nexport function withCustomIcons(registry: NgnCustomIconRegistry): NgnFeature {\n return {\n providers: [\n { provide: NGN_ICON_REGISTRY, useValue: registry },\n { provide: NGN_CUSTOM_ICONS, useValue: true },\n ],\n };\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport { afterRenderEffect, Component, computed, inject, input } from '@angular/core';\nimport { DomSanitizer, type SafeHtml } from '@angular/platform-browser';\nimport { NgnBase, provideSelf, NgnPt } from '@ngneers/controls/base';\nimport { NgnError } from '@ngneers/controls/utils';\nimport { iconControlTemplate } from '@ngneers/controls-themes/templates/icon';\n\nimport { GlobalIconTemplate } from './global-icon-template';\nimport { NGN_CUSTOM_ICONS, NGN_ICON_REGISTRY } from './icon-registry';\n\nimport type { NgnIconEntry, NgnIconKey, NgnIconRegistry } from './icon-registry';\nimport type { IconifyIcon } from '@iconify/types';\nimport type { IconType } from '@ngneers/controls-custom-types';\n\nfunction generateIconSvg(sanitizer: DomSanitizer, iconData: IconifyIcon, scale: number): SafeHtml {\n // Note: @iconify/types documents default as 16, but we default to 24 to match Tabler.\n // All Tabler icons provide explicit dimensions, so this fallback rarely triggers.\n const width = iconData.width ?? 24;\n const height = iconData.height ?? 24;\n\n const insetX = scale === 1 ? 0 : ((scale - 1) / scale) * (width / 2);\n const insetY = scale === 1 ? 0 : ((scale - 1) / scale) * (height / 2);\n const vbX = insetX;\n const vbY = insetY;\n const vbW = width - insetX * 2;\n const vbH = height - insetY * 2;\n\n return sanitizer.bypassSecurityTrustHtml(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\" viewBox=\"${vbX} ${vbY} ${vbW} ${vbH}\">${iconData.body}</svg>`\n );\n}\n\n/**\n * @category control\n */\n@Component({\n selector: 'ngn-icon',\n templateUrl: './icon.html',\n imports: [NgnPt, NgTemplateOutlet],\n providers: [provideSelf(NgnIcon)],\n host: {\n ngSkipHydration: 'true',\n },\n})\nexport class NgnIcon extends NgnBase<'icon'> {\n protected readonly theme = this.injectThemeTemplate(iconControlTemplate, 'root');\n private readonly _globalIconTemplate = inject(GlobalIconTemplate).globalIconTemplate;\n private readonly _sanitizer = inject(DomSanitizer);\n private readonly _registry = inject(NGN_ICON_REGISTRY, { optional: true });\n private readonly _isCustom = inject(NGN_CUSTOM_ICONS, { optional: true }) ?? false;\n\n /**\n * A key into the registered icon set (from `withDefaultIcons()` or `withCustomIcons()`).\n * Used as a fallback when {@link icon} is not provided; requires an icon registry.\n * @default undefined\n */\n public readonly defaultIcon = input<NgnIconKey>();\n /**\n * The icon to render. Accepts an Iconify data object, a registered icon entry, or a\n * custom value resolved via the {@link GlobalIconTemplate}. Takes precedence over {@link defaultIcon}.\n * @default undefined\n */\n public readonly icon = input<IconType>();\n\n protected readonly iconSvg = computed(() => {\n const value = this.icon();\n if (!value || typeof value !== 'object') return null;\n\n let iconData: IconifyIcon;\n let scale = 1;\n\n if ('body' in value) {\n iconData = value as IconifyIcon;\n } else if ('icon' in value && typeof value.icon === 'object' && 'body' in value.icon) {\n const entry = value as NgnIconEntry;\n iconData = entry.icon;\n scale = entry.scale ?? 1;\n } else {\n return null;\n }\n\n return generateIconSvg(this._sanitizer, iconData, scale);\n });\n\n protected readonly defaultIconSvg = computed(() => {\n const key = this.defaultIcon();\n if (!key || this._isCustom || !this._registry) return null;\n const raw = (this._registry as NgnIconRegistry)[key];\n const entry: NgnIconEntry =\n 'body' in raw ? { icon: raw as IconifyIcon, scale: 1 } : (raw as NgnIconEntry);\n\n return generateIconSvg(this._sanitizer, entry.icon, entry.scale ?? 1);\n });\n\n protected readonly customDefaultIcon = computed(() => {\n const key = this.defaultIcon();\n if (!key || !this._isCustom || !this._registry) return null;\n return this._registry[key] as IconType;\n });\n\n protected readonly iconTemplate = computed(() => this._globalIconTemplate());\n\n constructor() {\n super();\n // Invariant checks live here — NOT inside the computeds above.\n // Throwing inside a computed() is swallowed by Angular's reactive graph:\n // producerRecomputeValue caches the error and only re-throws on a direct\n // getter read, so a recompute during change-detection producer polling\n // runs the body (firing the NgnError constructor's fancy log) without ever\n // surfacing the error. afterRenderEffect throws surface reliably.\n afterRenderEffect(() => {\n const icon = this.icon();\n const defaultIcon = this.defaultIcon();\n\n if (!icon && !defaultIcon) {\n throw new NgnError(\n 'icon',\n 'Icon component requires either an icon or a default icon to be set.'\n );\n }\n\n if (defaultIcon && !this._registry) {\n throw new NgnError(\n 'icon',\n 'No icon registry provided. Add withDefaultIcons() or withCustomIcons() to your provideNgnControls() call.'\n );\n }\n\n // The template path is used for non-Iconify [icon] values and for custom\n // default icons; both require a registered GlobalIconTemplate.\n const needsTemplate = (!!icon && !this.iconSvg()) || !!this.customDefaultIcon();\n if (needsTemplate && !this._globalIconTemplate()) {\n throw new NgnError(\n 'icon',\n 'No GlobalIconTemplate registered. Required when using [icon] with non-Iconify values or withCustomIcons() with [defaultIcon]. If using Iconify, pass an IconifyIcon data object (e.g., import tablerUser from \"@iconify/icons-tabler/user\").'\n );\n }\n });\n }\n}\n","@if (iconSvg(); as svg) {\n <div [ptInt]=\"this\" [ptClass]=\"'default'\" [innerHtml]=\"svg\"></div>\n} @else if (icon()) {\n <ng-container\n *ngTemplateOutlet=\"\n iconTemplate();\n context: {\n $implicit: {\n icon: icon(),\n },\n }\n \"\n >\n </ng-container>\n} @else if (customDefaultIcon(); as customIcon) {\n <ng-container\n *ngTemplateOutlet=\"\n iconTemplate();\n context: {\n $implicit: {\n icon: customIcon,\n },\n }\n \"\n >\n </ng-container>\n} @else {\n @if (defaultIconSvg(); as defaultIcon) {\n <div [ptInt]=\"this\" [ptClass]=\"'default'\" [innerHtml]=\"defaultIcon\"></div>\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngneers-controls-icon.mjs","sources":["../../src/icon/global-icon-template.ts","../../src/icon/icon-registry.ts","../../src/icon/icon.ts","../../src/icon/icon.html","../../src/icon/ngneers-controls-icon.ts"],"sourcesContent":["import { signal, TemplateRef, type OnDestroy, Service } from '@angular/core';\n\nimport type { IconTemplateContext } from './types';\n\nexport type IconTemplateType = TemplateRef<IconTemplateContext>;\n\n@Service()\nexport class GlobalIconTemplate implements OnDestroy {\n private readonly _globalIconTemplate = signal<IconTemplateType | null>(null);\n\n public readonly globalIconTemplate = this._globalIconTemplate.asReadonly();\n\n public setGlobalIconTemplate(template: IconTemplateType) {\n this._globalIconTemplate.set(template);\n }\n\n public ngOnDestroy() {\n this._globalIconTemplate.set(null);\n }\n}\n","import { InjectionToken } from '@angular/core';\n\nimport type { IconifyIcon } from '@iconify/types';\nimport type { NgnFeature } from '@ngneers/controls/api/ng';\nimport type { IconType, NgnIconEntry } from '@ngneers/controls-custom-types';\n\nexport type { NgnIconEntry } from '@ngneers/controls-custom-types';\n\nexport const NGN_ICON_KEYS = [\n 'accordion-collapse',\n 'accordion-expand',\n 'breadcrumb-separator',\n 'breadcrumb-overflow',\n 'calendar-trigger',\n 'calendar-previous-month',\n 'calendar-next-month',\n 'checkbox-checked',\n 'checkbox-indeterminate',\n 'chip-remove',\n 'dialog-close',\n 'drawer-close',\n 'dropdown-toggle',\n 'edit-confirm',\n 'filter-active',\n 'filter-inactive',\n 'filter-remove',\n 'hint-info',\n 'hint-success',\n 'hint-warning',\n 'hint-error',\n 'input-clear',\n 'menu-submenu',\n 'paginator-previous',\n 'paginator-next',\n 'rating-full',\n 'rating-empty',\n 'search',\n 'sort-neutral',\n 'sort-ascending',\n 'sort-descending',\n 'spin-decrement',\n 'spin-increment',\n 'stepper-completed',\n 'table-group-toggle',\n 'tabs-scroll-left',\n 'tabs-scroll-right',\n 'toast-close',\n 'snackbar-close',\n 'upload-trigger',\n 'upload-done',\n 'upload-failed',\n 'upload-retry',\n 'upload-cancel',\n 'upload-remove',\n] as const;\n\nexport type NgnIconKey = (typeof NGN_ICON_KEYS)[number];\n\nexport type NgnIconRegistry = Record<NgnIconKey, IconifyIcon | NgnIconEntry>;\n\nexport type NgnCustomIconRegistry = Record<NgnIconKey, IconType>;\n\nexport const NGN_ICON_REGISTRY = new InjectionToken<NgnIconRegistry | NgnCustomIconRegistry>(\n 'NGN_ICON_REGISTRY'\n);\n\nexport const NGN_CUSTOM_ICONS = new InjectionToken<boolean>('NGN_CUSTOM_ICONS');\n\nexport function withCustomIcons(registry: NgnCustomIconRegistry): NgnFeature {\n return {\n providers: [\n { provide: NGN_ICON_REGISTRY, useValue: registry },\n { provide: NGN_CUSTOM_ICONS, useValue: true },\n ],\n };\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport { afterRenderEffect, Component, computed, inject, input } from '@angular/core';\nimport { DomSanitizer, type SafeHtml } from '@angular/platform-browser';\nimport { NgnBase, provideSelf, NgnPt } from '@ngneers/controls/base';\nimport { Logger, NgnError } from '@ngneers/controls/utils';\nimport { iconControlTemplate } from '@ngneers/controls-themes/templates/icon';\n\nimport { GlobalIconTemplate } from './global-icon-template';\nimport { NGN_CUSTOM_ICONS, NGN_ICON_REGISTRY } from './icon-registry';\n\nimport type { NgnIconEntry, NgnIconKey, NgnIconRegistry } from './icon-registry';\nimport type { IconifyIcon } from '@iconify/types';\nimport type { IconType } from '@ngneers/controls-custom-types';\n\n/**\n * CJS icon modules (e.g. `@iconify/icons-tabler/*`) bind as `{ __esModule, default: <data> }`\n * under Node ESM interop; unwrap to the real Iconify data so `.body` is readable.\n */\nfunction unwrapIcon<T>(mod: T): T {\n return mod && typeof mod === 'object' && 'default' in mod ? (mod as { default: T }).default : mod;\n}\n\nfunction generateIconSvg(\n sanitizer: DomSanitizer,\n iconData: IconifyIcon,\n scale: number\n): SafeHtml | null {\n iconData = unwrapIcon(iconData);\n if (typeof iconData?.body !== 'string') {\n Logger.error(\n new NgnError(\n 'icon',\n 'Icon data has no string \"body\". If importing from a CommonJS icon package, the module default may need unwrapping.',\n iconData\n )\n );\n return null;\n }\n\n // Note: @iconify/types documents default as 16, but we default to 24 to match Tabler.\n // All Tabler icons provide explicit dimensions, so this fallback rarely triggers.\n const width = iconData.width ?? 24;\n const height = iconData.height ?? 24;\n\n const insetX = scale === 1 ? 0 : ((scale - 1) / scale) * (width / 2);\n const insetY = scale === 1 ? 0 : ((scale - 1) / scale) * (height / 2);\n const vbX = insetX;\n const vbY = insetY;\n const vbW = width - insetX * 2;\n const vbH = height - insetY * 2;\n\n return sanitizer.bypassSecurityTrustHtml(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\" viewBox=\"${vbX} ${vbY} ${vbW} ${vbH}\">${iconData.body}</svg>`\n );\n}\n\n/**\n * @category control\n */\n@Component({\n selector: 'ngn-icon',\n templateUrl: './icon.html',\n imports: [NgnPt, NgTemplateOutlet],\n providers: [provideSelf(NgnIcon)],\n host: {\n ngSkipHydration: 'true',\n },\n})\nexport class NgnIcon extends NgnBase<'icon'> {\n protected readonly theme = this.injectThemeTemplate(iconControlTemplate, 'root');\n private readonly _globalIconTemplate = inject(GlobalIconTemplate).globalIconTemplate;\n private readonly _sanitizer = inject(DomSanitizer);\n private readonly _registry = inject(NGN_ICON_REGISTRY, { optional: true });\n private readonly _isCustom = inject(NGN_CUSTOM_ICONS, { optional: true }) ?? false;\n\n /**\n * A key into the registered icon set (from `withDefaultIcons()` or `withCustomIcons()`).\n * Used as a fallback when {@link icon} is not provided; requires an icon registry.\n * @default undefined\n */\n public readonly defaultIcon = input<NgnIconKey>();\n /**\n * The icon to render. Accepts an Iconify data object, a registered icon entry, or a\n * custom value resolved via the {@link GlobalIconTemplate}. Takes precedence over {@link defaultIcon}.\n * @default undefined\n */\n public readonly icon = input<IconType>();\n\n protected readonly iconSvg = computed(() => {\n const value = unwrapIcon(this.icon());\n if (!value || typeof value !== 'object') return null;\n\n let iconData: IconifyIcon;\n let scale = 1;\n\n if ('body' in value) {\n iconData = value as IconifyIcon;\n } else if (\n 'icon' in value &&\n typeof value.icon === 'object' &&\n 'body' in unwrapIcon(value.icon)\n ) {\n const entry = value as NgnIconEntry;\n iconData = unwrapIcon(entry.icon);\n scale = entry.scale ?? 1;\n } else {\n return null;\n }\n\n return generateIconSvg(this._sanitizer, iconData, scale);\n });\n\n protected readonly defaultIconSvg = computed(() => {\n const key = this.defaultIcon();\n if (!key || this._isCustom || !this._registry) return null;\n const raw = unwrapIcon((this._registry as NgnIconRegistry)[key]);\n const entry: NgnIconEntry =\n 'body' in raw ? { icon: raw as IconifyIcon, scale: 1 } : (raw as NgnIconEntry);\n\n return generateIconSvg(this._sanitizer, unwrapIcon(entry.icon), entry.scale ?? 1);\n });\n\n protected readonly customDefaultIcon = computed(() => {\n const key = this.defaultIcon();\n if (!key || !this._isCustom || !this._registry) return null;\n return this._registry[key] as IconType;\n });\n\n protected readonly iconTemplate = computed(() => this._globalIconTemplate());\n\n constructor() {\n super();\n // Invariant checks live here — NOT inside the computeds above.\n // Throwing inside a computed() is swallowed by Angular's reactive graph:\n // producerRecomputeValue caches the error and only re-throws on a direct\n // getter read, so a recompute during change-detection producer polling\n // runs the body (firing the NgnError constructor's fancy log) without ever\n // surfacing the error. afterRenderEffect throws surface reliably.\n afterRenderEffect(() => {\n const icon = this.icon();\n const defaultIcon = this.defaultIcon();\n\n if (!icon && !defaultIcon) {\n throw new NgnError(\n 'icon',\n 'Icon component requires either an icon or a default icon to be set.'\n );\n }\n\n if (defaultIcon && !this._registry) {\n throw new NgnError(\n 'icon',\n 'No icon registry provided. Add withDefaultIcons() or withCustomIcons() to your provideNgnControls() call.'\n );\n }\n\n // The template path is used for non-Iconify [icon] values and for custom\n // default icons; both require a registered GlobalIconTemplate.\n const needsTemplate = (!!icon && !this.iconSvg()) || !!this.customDefaultIcon();\n if (needsTemplate && !this._globalIconTemplate()) {\n throw new NgnError(\n 'icon',\n 'No GlobalIconTemplate registered. Required when using [icon] with non-Iconify values or withCustomIcons() with [defaultIcon]. If using Iconify, pass an IconifyIcon data object (e.g., import tablerUser from \"@iconify/icons-tabler/user\").'\n );\n }\n });\n }\n}\n","@if (iconSvg(); as svg) {\n <div [ptInt]=\"this\" [ptClass]=\"'default'\" [innerHtml]=\"svg\"></div>\n} @else if (icon()) {\n <ng-container\n *ngTemplateOutlet=\"\n iconTemplate();\n context: {\n $implicit: {\n icon: icon(),\n },\n }\n \"\n >\n </ng-container>\n} @else if (customDefaultIcon(); as customIcon) {\n <ng-container\n *ngTemplateOutlet=\"\n iconTemplate();\n context: {\n $implicit: {\n icon: customIcon,\n },\n }\n \"\n >\n </ng-container>\n} @else {\n @if (defaultIconSvg(); as defaultIcon) {\n <div [ptInt]=\"this\" [ptClass]=\"'default'\" [innerHtml]=\"defaultIcon\"></div>\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -11,7 +11,10 @@ import { inputFieldControlTemplate } from '@ngneers/controls-themes/templates/in
11
11
  * @category control
12
12
  */
13
13
  class NgnInputField extends NgnBase {
14
- theme = this.injectThemeTemplate(inputFieldControlTemplate, 'host');
14
+ theme = this.injectThemeTemplate(inputFieldControlTemplate, {
15
+ host: true,
16
+ filled: () => this.filled(),
17
+ });
15
18
  i18n = inject(I18n).translations;
16
19
  /**
17
20
  * Label for the input field
@@ -56,7 +59,10 @@ class NgnInputField extends NgnBase {
56
59
  tabindex = input(-1, /* @ts-ignore */
57
60
  ...(ngDevMode ? [{ debugName: "tabindex" }] : /* istanbul ignore next */ []));
58
61
  /**
59
- * Explicitly apply invalid state styling
62
+ * Explicitly apply invalid state styling on the field chrome. The field does
63
+ * not compute validity — it also reflects its projected control's own invalid
64
+ * state (the child's gated `aria-invalid`) via the theme. Set this only to
65
+ * force the invalid look regardless of the child.
60
66
  * @default false
61
67
  */
62
68
  invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
@@ -79,6 +85,16 @@ class NgnInputField extends NgnBase {
79
85
  */
80
86
  control = computed(() => this._projectedControls().find(c => c.isFieldControl), /* @ts-ignore */
81
87
  ...(ngDevMode ? [{ debugName: "control" }] : /* istanbul ignore next */ []));
88
+ /**
89
+ * Whether the projected control holds content. Drives float-label detection
90
+ * component-side (from the control's `empty` signal) so it works for every
91
+ * field control — select, calendar, mask-input — not just native inputs.
92
+ */
93
+ filled = computed(() => {
94
+ const control = this.control();
95
+ return !!control && !control.empty();
96
+ }, /* @ts-ignore */
97
+ ...(ngDevMode ? [{ debugName: "filled" }] : /* istanbul ignore next */ []));
82
98
  /** The primary control's element when it is a native input/textarea. */
83
99
  _inputElement = computed(() => {
84
100
  const el = this.control()?.element.nativeElement;
@@ -1 +1 @@
1
- {"version":3,"file":"ngneers-controls-input-field.mjs","sources":["../../src/input-field/input-field.ts","../../src/input-field/input-field.html","../../src/input-field/ngneers-controls-input-field.ts"],"sourcesContent":["import {\n booleanAttribute,\n Component,\n computed,\n contentChildren,\n effect,\n inject,\n input,\n} from '@angular/core';\nimport { NgnBase, NGN_CONTROL, provideSelf, NgnPt } from '@ngneers/controls/base';\nimport { NgnButton } from '@ngneers/controls/button';\nimport { I18n } from '@ngneers/controls/i18n';\nimport { NgnIcon } from '@ngneers/controls/icon';\nimport { generateElementId } from '@ngneers/controls/utils-ng';\nimport { inputFieldControlTemplate } from '@ngneers/controls-themes/templates/input-field';\n\nimport type { CustomKind, IconType } from '@ngneers/controls-custom-types';\n\n/**\n * @category control\n */\n@Component({\n imports: [NgnPt, NgnIcon, NgnButton],\n selector: 'ngn-input-field',\n templateUrl: './input-field.html',\n host: {\n '[inert]': 'disabled()',\n },\n providers: [provideSelf(NgnInputField)],\n})\nexport class NgnInputField extends NgnBase<'inputField'> {\n protected readonly theme = this.injectThemeTemplate(inputFieldControlTemplate, 'host');\n protected readonly i18n = inject(I18n).translations;\n\n /**\n * Label for the input field\n * @default null\n */\n public readonly label = input<string | null>(null);\n /**\n * Sets the `aria-labelledby` attribute on the input element\n * @default null\n */\n public readonly labelledBy = input<string | null>(null);\n /**\n * The kind of label presentation\n * @todo add link to custom kind documentation subsection label\n * @default undefined\n */\n public readonly labelKind = input<CustomKind<'inputFieldLabel'>>(undefined as never);\n /**\n * ID for the input element. Defaults to a generated id.\n */\n public readonly inputId = input<string>(generateElementId());\n /**\n * Show clear button\n * @default false\n */\n public readonly showClearButton = input(false, { transform: booleanAttribute });\n /**\n * Custom icon for the clear button. Use with {@link showClearButton}.\n * @default undefined\n */\n public readonly iconClearButton = input<IconType>();\n /**\n * Tabindex for the input field itself.\n * When another focusable (input) element is present inside the input field, this should be set to -1.\n * @default -1\n */\n public readonly tabindex = input<number>(-1);\n /**\n * Explicitly apply invalid state styling\n * @default false\n */\n public readonly invalid = input(false, { transform: booleanAttribute });\n /**\n * Explicitly apply readonly state styling\n * @default false\n */\n public readonly readonly = input(false, { transform: booleanAttribute });\n /**\n * Explicitly apply disabled state styling\n * @default false\n */\n public readonly disabled = input(false, { transform: booleanAttribute });\n\n private readonly _projectedControls = contentChildren(NGN_CONTROL, { descendants: true });\n /**\n * The projected primary control (input, mask, calendar, …), used to delegate\n * pointer focus, clearing and stepping. Auxiliary controls inside the field\n * (buttons, icons, spin buttons, …) are skipped via `isFieldControl`, so\n * their placement/order never shadows the actual input.\n */\n public readonly control = computed(() => this._projectedControls().find(c => c.isFieldControl));\n\n /** The primary control's element when it is a native input/textarea. */\n private readonly _inputElement = computed(() => {\n const el = this.control()?.element.nativeElement;\n return el && (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA')\n ? (el as HTMLInputElement | HTMLTextAreaElement)\n : undefined;\n });\n\n constructor() {\n super();\n this.initializeAutoThemeClasses('labelKind', this.labelKind);\n effect(() => {\n const inputElement = this._inputElement();\n if (!inputElement) {\n return;\n }\n inputElement.id = this.inputId();\n });\n effect(() => {\n const inputElement = this._inputElement();\n if (!inputElement) {\n return;\n }\n const labelledBy = this.labelledBy();\n inputElement.setAttribute('aria-labelledby', labelledBy ?? '');\n });\n }\n\n protected clicked(event: MouseEvent) {\n // Give the projected control a chance to place focus from the pointer\n // location (e.g. mask-input selects the section nearest the click). If it\n // handles the event, skip the primitive focusing below.\n if (this.control()?.focusFromPointer(event)) return;\n\n if (!(event.target instanceof Node)) return;\n\n const root = this.element.nativeElement;\n const targetElement = event.target instanceof Element ? event.target : null;\n\n // Controls that open/toggle on click (select combobox, calendar field) expose\n // their interactive host as the focusable element (tabindex=\"0\") -> redirect click there.\n const focusable = root.querySelector<HTMLElement>('[tabindex=\"0\"]');\n if (focusable && !focusable.contains(event.target)) {\n focusable.click();\n return;\n }\n\n // Keep real projected actions (buttons, links, explicit tab stops) in charge of their own click.\n const interactiveTarget = targetElement?.closest(\n 'button, a[href], select, [role=\"button\"], [tabindex]:not([tabindex=\"-1\"])'\n );\n if (interactiveTarget && root.contains(interactiveTarget)) {\n return;\n }\n\n // Plain input fields: clicking the field chrome or non-interactive adornments should focus\n // the actual input, even when the pointer target is SVG content inside an icon/state control.\n this._inputElement()?.focus();\n }\n\n protected clearButtonClicked(event: MouseEvent) {\n event.stopPropagation();\n // Controls that manage their own value (e.g. mask-input) clear via the hook;\n // the DOM fallback below only works for plain text inputs.\n if (this.control()?.clearValue()) {\n return;\n }\n const inputElement = this.element.nativeElement.querySelector('input, textarea');\n if (inputElement) {\n (inputElement as HTMLInputElement | HTMLTextAreaElement).value = '';\n inputElement.dispatchEvent(new Event('input', { bubbles: true }));\n inputElement.dispatchEvent(new Event('change', { bubbles: true }));\n (inputElement as HTMLInputElement | HTMLTextAreaElement).focus();\n }\n }\n}\n","@if (label(); as label) {\n <label [ptInt]=\"this\" [ptClass]=\"'label'\" [for]=\"inputId()\">{{ label }}</label>\n}\n<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n<div\n [ptInt]=\"this\"\n [ptClass]=\"{\n root: true,\n invalid: invalid(),\n readonly: readonly(),\n disabled: disabled(),\n }\"\n (click)=\"clicked($event)\"\n [tabindex]=\"tabindex()\"\n>\n <ng-content select=\"input, textarea\" />\n @if (showClearButton()) {\n <button\n tabindex=\"-1\"\n [ptInt]=\"this\"\n [ptClass]=\"'clear-button'\"\n ngnButton\n type=\"button\"\n [kind]=\"'icon'\"\n ngnButtonInline\n (click)=\"clearButtonClicked($event)\"\n [attr.aria-label]=\"i18n['inputField_clearInput']()\"\n >\n <ngn-icon defaultIcon=\"input-clear\" [icon]=\"iconClearButton()\" />\n </button>\n }\n <ng-content />\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngneers-controls-input-field.mjs","sources":["../../src/input-field/input-field.ts","../../src/input-field/input-field.html","../../src/input-field/ngneers-controls-input-field.ts"],"sourcesContent":["import {\n booleanAttribute,\n Component,\n computed,\n contentChildren,\n effect,\n inject,\n input,\n} from '@angular/core';\nimport { NgnBase, NGN_CONTROL, provideSelf, NgnPt } from '@ngneers/controls/base';\nimport { NgnButton } from '@ngneers/controls/button';\nimport { I18n } from '@ngneers/controls/i18n';\nimport { NgnIcon } from '@ngneers/controls/icon';\nimport { generateElementId } from '@ngneers/controls/utils-ng';\nimport { inputFieldControlTemplate } from '@ngneers/controls-themes/templates/input-field';\n\nimport type { CustomKind, IconType } from '@ngneers/controls-custom-types';\n\n/**\n * @category control\n */\n@Component({\n imports: [NgnPt, NgnIcon, NgnButton],\n selector: 'ngn-input-field',\n templateUrl: './input-field.html',\n host: {\n '[inert]': 'disabled()',\n },\n providers: [provideSelf(NgnInputField)],\n})\nexport class NgnInputField extends NgnBase<'inputField'> {\n protected readonly theme = this.injectThemeTemplate(inputFieldControlTemplate, {\n host: true,\n filled: () => this.filled(),\n });\n protected readonly i18n = inject(I18n).translations;\n\n /**\n * Label for the input field\n * @default null\n */\n public readonly label = input<string | null>(null);\n /**\n * Sets the `aria-labelledby` attribute on the input element\n * @default null\n */\n public readonly labelledBy = input<string | null>(null);\n /**\n * The kind of label presentation\n * @todo add link to custom kind documentation subsection label\n * @default undefined\n */\n public readonly labelKind = input<CustomKind<'inputFieldLabel'>>(undefined as never);\n /**\n * ID for the input element. Defaults to a generated id.\n */\n public readonly inputId = input<string>(generateElementId());\n /**\n * Show clear button\n * @default false\n */\n public readonly showClearButton = input(false, { transform: booleanAttribute });\n /**\n * Custom icon for the clear button. Use with {@link showClearButton}.\n * @default undefined\n */\n public readonly iconClearButton = input<IconType>();\n /**\n * Tabindex for the input field itself.\n * When another focusable (input) element is present inside the input field, this should be set to -1.\n * @default -1\n */\n public readonly tabindex = input<number>(-1);\n /**\n * Explicitly apply invalid state styling on the field chrome. The field does\n * not compute validity — it also reflects its projected control's own invalid\n * state (the child's gated `aria-invalid`) via the theme. Set this only to\n * force the invalid look regardless of the child.\n * @default false\n */\n public readonly invalid = input(false, { transform: booleanAttribute });\n /**\n * Explicitly apply readonly state styling\n * @default false\n */\n public readonly readonly = input(false, { transform: booleanAttribute });\n /**\n * Explicitly apply disabled state styling\n * @default false\n */\n public readonly disabled = input(false, { transform: booleanAttribute });\n\n private readonly _projectedControls = contentChildren(NGN_CONTROL, { descendants: true });\n /**\n * The projected primary control (input, mask, calendar, …), used to delegate\n * pointer focus, clearing and stepping. Auxiliary controls inside the field\n * (buttons, icons, spin buttons, …) are skipped via `isFieldControl`, so\n * their placement/order never shadows the actual input.\n */\n public readonly control = computed(() => this._projectedControls().find(c => c.isFieldControl));\n\n /**\n * Whether the projected control holds content. Drives float-label detection\n * component-side (from the control's `empty` signal) so it works for every\n * field control — select, calendar, mask-input — not just native inputs.\n */\n protected readonly filled = computed(() => {\n const control = this.control();\n return !!control && !control.empty();\n });\n\n /** The primary control's element when it is a native input/textarea. */\n private readonly _inputElement = computed(() => {\n const el = this.control()?.element.nativeElement;\n return el && (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA')\n ? (el as HTMLInputElement | HTMLTextAreaElement)\n : undefined;\n });\n\n constructor() {\n super();\n this.initializeAutoThemeClasses('labelKind', this.labelKind);\n effect(() => {\n const inputElement = this._inputElement();\n if (!inputElement) {\n return;\n }\n inputElement.id = this.inputId();\n });\n effect(() => {\n const inputElement = this._inputElement();\n if (!inputElement) {\n return;\n }\n const labelledBy = this.labelledBy();\n inputElement.setAttribute('aria-labelledby', labelledBy ?? '');\n });\n }\n\n protected clicked(event: MouseEvent) {\n // Give the projected control a chance to place focus from the pointer\n // location (e.g. mask-input selects the section nearest the click). If it\n // handles the event, skip the primitive focusing below.\n if (this.control()?.focusFromPointer(event)) return;\n\n if (!(event.target instanceof Node)) return;\n\n const root = this.element.nativeElement;\n const targetElement = event.target instanceof Element ? event.target : null;\n\n // Controls that open/toggle on click (select combobox, calendar field) expose\n // their interactive host as the focusable element (tabindex=\"0\") -> redirect click there.\n const focusable = root.querySelector<HTMLElement>('[tabindex=\"0\"]');\n if (focusable && !focusable.contains(event.target)) {\n focusable.click();\n return;\n }\n\n // Keep real projected actions (buttons, links, explicit tab stops) in charge of their own click.\n const interactiveTarget = targetElement?.closest(\n 'button, a[href], select, [role=\"button\"], [tabindex]:not([tabindex=\"-1\"])'\n );\n if (interactiveTarget && root.contains(interactiveTarget)) {\n return;\n }\n\n // Plain input fields: clicking the field chrome or non-interactive adornments should focus\n // the actual input, even when the pointer target is SVG content inside an icon/state control.\n this._inputElement()?.focus();\n }\n\n protected clearButtonClicked(event: MouseEvent) {\n event.stopPropagation();\n // Controls that manage their own value (e.g. mask-input) clear via the hook;\n // the DOM fallback below only works for plain text inputs.\n if (this.control()?.clearValue()) {\n return;\n }\n const inputElement = this.element.nativeElement.querySelector('input, textarea');\n if (inputElement) {\n (inputElement as HTMLInputElement | HTMLTextAreaElement).value = '';\n inputElement.dispatchEvent(new Event('input', { bubbles: true }));\n inputElement.dispatchEvent(new Event('change', { bubbles: true }));\n (inputElement as HTMLInputElement | HTMLTextAreaElement).focus();\n }\n }\n}\n","@if (label(); as label) {\n <label [ptInt]=\"this\" [ptClass]=\"'label'\" [for]=\"inputId()\">{{ label }}</label>\n}\n<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n<div\n [ptInt]=\"this\"\n [ptClass]=\"{\n root: true,\n invalid: invalid(),\n readonly: readonly(),\n disabled: disabled(),\n }\"\n (click)=\"clicked($event)\"\n [tabindex]=\"tabindex()\"\n>\n <ng-content select=\"input, textarea\" />\n @if (showClearButton()) {\n <button\n tabindex=\"-1\"\n [ptInt]=\"this\"\n [ptClass]=\"'clear-button'\"\n ngnButton\n type=\"button\"\n [kind]=\"'icon'\"\n ngnButtonInline\n (click)=\"clearButtonClicked($event)\"\n [attr.aria-label]=\"i18n['inputField_clearInput']()\"\n >\n <ngn-icon defaultIcon=\"input-clear\" [icon]=\"iconClearButton()\" />\n </button>\n }\n <ng-content />\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, booleanAttribute, model, runInInjectionContext, effect, Directive } from '@angular/core';
3
- import { domEventSignal } from '@ngneers/controls/api/ng';
4
- import { NgnBase, provideSelf } from '@ngneers/controls/base';
2
+ import { computed, input, booleanAttribute, model, output, runInInjectionContext, effect, Directive } from '@angular/core';
3
+ import { domEventSignal, domEventHandler } from '@ngneers/controls/api/ng';
4
+ import { NgnBase, resolveInvalidState, provideSelf } from '@ngneers/controls/base';
5
5
  import { inputControlTemplate } from '@ngneers/controls-themes/templates/input';
6
6
 
7
7
  /**
@@ -11,20 +11,49 @@ class NgnInput extends NgnBase {
11
11
  isFieldControl = true;
12
12
  theme = this.injectThemeTemplate(inputControlTemplate, {
13
13
  root: true,
14
- invalid: () => this.invalid(),
15
- empty: () => !this.value(),
14
+ invalid: () => this.invalidState(),
15
+ empty: () => this.empty(),
16
16
  });
17
+ empty = computed(() => !this.value(), /* @ts-ignore */
18
+ ...(ngDevMode ? [{ debugName: "empty" }] : /* istanbul ignore next */ []));
17
19
  /**
18
- * Explicitly apply invalid state styling
20
+ * The raw invalid flag (bound from a signal-forms field's validity, or set
21
+ * explicitly). Whether it *shows* is gated by {@link invalidOn} — read
22
+ * {@link invalidState}.
19
23
  * @default false
20
24
  */
21
25
  invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
26
+ /**
27
+ * When the input surfaces its invalid styling.
28
+ * @default touched
29
+ */
30
+ invalidOn = input('touched', /* @ts-ignore */
31
+ ...(ngDevMode ? [{ debugName: "invalidOn" }] : /* istanbul ignore next */ []));
32
+ /**
33
+ * Touched state. A bound signal-forms field writes it in (`FormUiControl`
34
+ * `touched` input); the input also sets it on blur, and reports blur out
35
+ * through {@link touch}.
36
+ */
37
+ touched = model(false, /* @ts-ignore */
38
+ ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
39
+ /**
40
+ * The invalid state the theme renders: {@link invalid} gated by
41
+ * {@link invalidOn}. (Dirty tracking isn't wired for the bare directive, so the
42
+ * `dirty` trigger behaves like `immediate` here.)
43
+ */
44
+ invalidState = computed(() => resolveInvalidState(this.invalid(), this.invalidOn(), this.touched(), true), /* @ts-ignore */
45
+ ...(ngDevMode ? [{ debugName: "invalidState" }] : /* istanbul ignore next */ []));
22
46
  /**
23
47
  * The current value of the input, kept in sync with the native element in both directions.
24
48
  * @default ''
25
49
  */
26
50
  value = model('', /* @ts-ignore */
27
51
  ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
52
+ /**
53
+ * Emits on blur so a bound signal-forms field is marked touched (the
54
+ * `FormUiControl` `touch` contract) — enables `ngnErrorsShowOn="touched"`.
55
+ */
56
+ touch = output();
28
57
  _input = this.element.nativeElement;
29
58
  ngAfterViewInit() {
30
59
  const changeEvent = domEventSignal(this.element.nativeElement, 'change', this.injector);
@@ -48,9 +77,20 @@ class NgnInput extends NgnBase {
48
77
  this._input.value = this.value() || '';
49
78
  }
50
79
  });
80
+ domEventHandler(this.element, 'blur', () => this.markTouched());
81
+ }
82
+ /**
83
+ * Marks the input touched on blur: flips {@link touched} for local consumers
84
+ * (e.g. `ngnErrors`) and emits {@link touch} so a bound signal-forms field is
85
+ * marked too. Mirrors `ValueControlBase.markTouched`, which this directive
86
+ * can't inherit (it extends {@link NgnBase} as a native-element directive).
87
+ */
88
+ markTouched() {
89
+ this.touched.set(true);
90
+ this.touch.emit();
51
91
  }
52
92
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnInput, deps: [], target: i0.ɵɵFactoryTarget.Directive });
53
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.5", type: NgnInput, isStandalone: true, selector: "input[ngnInput], textarea[ngnInput]", inputs: { invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "attr.aria-invalid": "invalid() ? \"true\" : null" } }, providers: [provideSelf(NgnInput)], exportAs: ["ngnInput"], usesInheritance: true, ngImport: i0 });
93
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.5", type: NgnInput, isStandalone: true, selector: "input[ngnInput], textarea[ngnInput]", inputs: { invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, invalidOn: { classPropertyName: "invalidOn", publicName: "invalidOn", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { touched: "touchedChange", value: "valueChange", touch: "touch" }, host: { properties: { "attr.aria-invalid": "invalidState() ? \"true\" : null" } }, providers: [provideSelf(NgnInput)], exportAs: ["ngnInput"], usesInheritance: true, ngImport: i0 });
54
94
  }
55
95
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnInput, decorators: [{
56
96
  type: Directive,
@@ -59,10 +99,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
59
99
  providers: [provideSelf(NgnInput)],
60
100
  exportAs: 'ngnInput',
61
101
  host: {
62
- '[attr.aria-invalid]': 'invalid() ? "true" : null',
102
+ '[attr.aria-invalid]': 'invalidState() ? "true" : null',
63
103
  },
64
104
  }]
65
- }], ctorParameters: () => [], propDecorators: { invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
105
+ }], ctorParameters: () => [], propDecorators: { invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], invalidOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalidOn", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], touch: [{ type: i0.Output, args: ["touch"] }] } });
66
106
 
67
107
  /**
68
108
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"ngneers-controls-input.mjs","sources":["../../src/input/input.ts","../../src/input/ngneers-controls-input.ts"],"sourcesContent":["import {\n type AfterViewInit,\n booleanAttribute,\n Directive,\n effect,\n input,\n model,\n runInInjectionContext,\n} from '@angular/core';\nimport { domEventSignal } from '@ngneers/controls/api/ng';\nimport { NgnBase, provideSelf } from '@ngneers/controls/base';\nimport { inputControlTemplate } from '@ngneers/controls-themes/templates/input';\n\n/**\n * @category control\n */\n@Directive({\n selector: 'input[ngnInput], textarea[ngnInput]',\n providers: [provideSelf(NgnInput)],\n exportAs: 'ngnInput',\n host: {\n '[attr.aria-invalid]': 'invalid() ? \"true\" : null',\n },\n})\nexport class NgnInput extends NgnBase<'input'> implements AfterViewInit {\n public override readonly isFieldControl = true;\n protected readonly theme = this.injectThemeTemplate(inputControlTemplate, {\n root: true,\n invalid: () => this.invalid(),\n empty: () => !this.value(),\n });\n /**\n * Explicitly apply invalid state styling\n * @default false\n */\n public readonly invalid = input(false, { transform: booleanAttribute });\n\n /**\n * The current value of the input, kept in sync with the native element in both directions.\n * @default ''\n */\n public readonly value = model<string | null>('');\n\n private readonly _input = this.element.nativeElement as HTMLInputElement;\n\n public ngAfterViewInit() {\n const changeEvent = domEventSignal(\n this.element.nativeElement as HTMLInputElement,\n 'change',\n this.injector\n );\n const inputEvent = domEventSignal(\n this.element.nativeElement as HTMLInputElement,\n 'input',\n this.injector\n );\n\n runInInjectionContext(this.injector, () => {\n effect(() => {\n const _changeEvent = changeEvent();\n const _inputEvent = inputEvent();\n if (!_changeEvent && !_inputEvent) {\n return;\n }\n const val = this._input.value;\n this.value.set(val ?? '');\n });\n });\n }\n\n constructor() {\n super();\n effect(() => {\n if (this._input.value !== this.value()) {\n this._input.value = this.value() || '';\n }\n });\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;AAaA;;AAEG;AASG,MAAO,QAAS,SAAQ,OAAgB,CAAA;IACnB,cAAc,GAAG,IAAI;AAC3B,IAAA,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,oBAAoB,EAAE;AACxE,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,OAAO,EAAE,MAAM,IAAI,CAAC,OAAO,EAAE;QAC7B,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE;AAC3B,KAAA,CAAC;AACF;;;AAGG;IACa,OAAO,GAAG,KAAK,CAAC,KAAK,+EAAI,SAAS,EAAE,gBAAgB,EAAA,CAAG;AAEvE;;;AAGG;IACa,KAAK,GAAG,KAAK,CAAgB,EAAE;8EAAC;AAE/B,IAAA,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,aAAiC;IAEjE,eAAe,GAAA;AACpB,QAAA,MAAM,WAAW,GAAG,cAAc,CAChC,IAAI,CAAC,OAAO,CAAC,aAAiC,EAC9C,QAAQ,EACR,IAAI,CAAC,QAAQ,CACd;AACD,QAAA,MAAM,UAAU,GAAG,cAAc,CAC/B,IAAI,CAAC,OAAO,CAAC,aAAiC,EAC9C,OAAO,EACP,IAAI,CAAC,QAAQ,CACd;AAED,QAAA,qBAAqB,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAK;YACxC,MAAM,CAAC,MAAK;AACV,gBAAA,MAAM,YAAY,GAAG,WAAW,EAAE;AAClC,gBAAA,MAAM,WAAW,GAAG,UAAU,EAAE;AAChC,gBAAA,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,EAAE;oBACjC;gBACF;AACA,gBAAA,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK;gBAC7B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC;AAC3B,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;IACJ;AAEA,IAAA,WAAA,GAAA;AACE,QAAA,KAAK,EAAE;QACP,MAAM,CAAC,MAAK;YACV,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE,EAAE;gBACtC,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE;YACxC;AACF,QAAA,CAAC,CAAC;IACJ;uGArDW,QAAQ,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAR,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,QAAQ,qcANR,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,EAAA,QAAA,EAAA,CAAA,UAAA,CAAA,EAAA,eAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAMvB,QAAQ,EAAA,UAAA,EAAA,CAAA;kBARpB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,qCAAqC;AAC/C,oBAAA,SAAS,EAAE,CAAC,WAAW,CAAA,QAAA,CAAU,CAAC;AAClC,oBAAA,QAAQ,EAAE,UAAU;AACpB,oBAAA,IAAI,EAAE;AACJ,wBAAA,qBAAqB,EAAE,2BAA2B;AACnD,qBAAA;AACF,iBAAA;;;ACvBD;;AAEG;;;;"}
1
+ {"version":3,"file":"ngneers-controls-input.mjs","sources":["../../src/input/input.ts","../../src/input/ngneers-controls-input.ts"],"sourcesContent":["import {\n type AfterViewInit,\n booleanAttribute,\n computed,\n Directive,\n effect,\n input,\n model,\n output,\n runInInjectionContext,\n} from '@angular/core';\nimport { domEventHandler, domEventSignal } from '@ngneers/controls/api/ng';\nimport {\n NgnBase,\n type NgnInvalidTrigger,\n provideSelf,\n resolveInvalidState,\n} from '@ngneers/controls/base';\nimport { inputControlTemplate } from '@ngneers/controls-themes/templates/input';\n\n/**\n * @category control\n */\n@Directive({\n selector: 'input[ngnInput], textarea[ngnInput]',\n providers: [provideSelf(NgnInput)],\n exportAs: 'ngnInput',\n host: {\n '[attr.aria-invalid]': 'invalidState() ? \"true\" : null',\n },\n})\nexport class NgnInput extends NgnBase<'input'> implements AfterViewInit {\n public override readonly isFieldControl = true;\n protected readonly theme = this.injectThemeTemplate(inputControlTemplate, {\n root: true,\n invalid: () => this.invalidState(),\n empty: () => this.empty(),\n });\n\n public override readonly empty = computed(() => !this.value());\n /**\n * The raw invalid flag (bound from a signal-forms field's validity, or set\n * explicitly). Whether it *shows* is gated by {@link invalidOn} — read\n * {@link invalidState}.\n * @default false\n */\n public readonly invalid = input(false, { transform: booleanAttribute });\n\n /**\n * When the input surfaces its invalid styling.\n * @default touched\n */\n public readonly invalidOn = input<NgnInvalidTrigger>('touched');\n\n /**\n * Touched state. A bound signal-forms field writes it in (`FormUiControl`\n * `touched` input); the input also sets it on blur, and reports blur out\n * through {@link touch}.\n */\n public readonly touched = model(false);\n\n /**\n * The invalid state the theme renders: {@link invalid} gated by\n * {@link invalidOn}. (Dirty tracking isn't wired for the bare directive, so the\n * `dirty` trigger behaves like `immediate` here.)\n */\n protected readonly invalidState = computed(() =>\n resolveInvalidState(this.invalid(), this.invalidOn(), this.touched(), true)\n );\n\n /**\n * The current value of the input, kept in sync with the native element in both directions.\n * @default ''\n */\n public readonly value = model<string | null>('');\n\n /**\n * Emits on blur so a bound signal-forms field is marked touched (the\n * `FormUiControl` `touch` contract) — enables `ngnErrorsShowOn=\"touched\"`.\n */\n public readonly touch = output<void>();\n\n private readonly _input = this.element.nativeElement as HTMLInputElement;\n\n public ngAfterViewInit() {\n const changeEvent = domEventSignal(\n this.element.nativeElement as HTMLInputElement,\n 'change',\n this.injector\n );\n const inputEvent = domEventSignal(\n this.element.nativeElement as HTMLInputElement,\n 'input',\n this.injector\n );\n\n runInInjectionContext(this.injector, () => {\n effect(() => {\n const _changeEvent = changeEvent();\n const _inputEvent = inputEvent();\n if (!_changeEvent && !_inputEvent) {\n return;\n }\n const val = this._input.value;\n this.value.set(val ?? '');\n });\n });\n }\n\n constructor() {\n super();\n effect(() => {\n if (this._input.value !== this.value()) {\n this._input.value = this.value() || '';\n }\n });\n domEventHandler(this.element, 'blur', () => this.markTouched());\n }\n\n /**\n * Marks the input touched on blur: flips {@link touched} for local consumers\n * (e.g. `ngnErrors`) and emits {@link touch} so a bound signal-forms field is\n * marked too. Mirrors `ValueControlBase.markTouched`, which this directive\n * can't inherit (it extends {@link NgnBase} as a native-element directive).\n */\n private markTouched(): void {\n this.touched.set(true);\n this.touch.emit();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -68,7 +68,7 @@ class NgnListBox extends ListBoxTemplates {
68
68
  i18n = inject(I18n).translations;
69
69
  theme = this.injectThemeTemplate(listBoxControlTemplate, {
70
70
  root: true,
71
- invalid: () => this.invalid(),
71
+ invalid: () => this.invalidState(),
72
72
  empty: () => !this.displayedItems().length,
73
73
  });
74
74
  _scroller = viewChild.required(NgnScroller);
@@ -253,7 +253,7 @@ class NgnListBox extends ListBoxTemplates {
253
253
  }
254
254
  }
255
255
  this.itemClicked.emit(value);
256
- this.touched.set(true);
256
+ this.markTouched();
257
257
  }
258
258
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnListBox, deps: [], target: i0.ɵɵFactoryTarget.Component });
259
259
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: NgnListBox, isStandalone: true, selector: "ngn-list-box", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, scrollToSelectedItemOnInit: { classPropertyName: "scrollToSelectedItemOnInit", publicName: "scrollToSelectedItemOnInit", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, selectOnHover: { classPropertyName: "selectOnHover", publicName: "selectOnHover", isSignal: true, isRequired: false, transformFunction: null }, focussable: { classPropertyName: "focussable", publicName: "focussable", isSignal: true, isRequired: false, transformFunction: null }, virtual: { classPropertyName: "virtual", publicName: "virtual", isSignal: true, isRequired: false, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, checkbox: { classPropertyName: "checkbox", publicName: "checkbox", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterText: { classPropertyName: "filterText", publicName: "filterText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClicked: "itemClicked" }, host: { attributes: { "role": "listbox" }, listeners: { "keydown": "onKeyDown($event)", "focusout": "currentHighlightedValue.set(null)" }, properties: { "attr.tabIndex": "focussable() ? 0 : null", "attr.aria-activedescendant": "currentHighlightedValue() ? inputId() + \"_option_\" + currentHighlightedValue() : null", "aria-multiselectable": "!!multiple()", "attr.aria-label": "label()", "attr.aria-labelledby": "labelledBy()", "id": "inputId()" } }, providers: [provideSelf(NgnListBox)], viewQueries: [{ propertyName: "_scroller", first: true, predicate: NgnScroller, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<ngn-scroller\n [ptInt]=\"this\"\n [ptDep]=\"'scroller'\"\n [virtual]=\"virtual()\"\n [itemHeight]=\"itemHeight()\"\n [items]=\"displayedItems()\"\n [templateItem]=\"usedItemTemplate\"\n [fieldSticky]=\"'items'\"\n #scroller\n/>\n\n@if (!displayedItems().length) {\n <div role=\"status\">\n <ng-container\n *ngTemplateOutlet=\"emptyTemplate() || defaultEmptyTemplate; context: {}\"\n ></ng-container>\n </div>\n}\n\n<ng-template #usedItemTemplate [ngnTemplate]=\"scroller.templateTypes.item\" let-itemOrGroup>\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n [ngnScrollerItem]=\"itemOrGroup\"\n [id]=\"inputId() + '_option_' + itemOrGroup.value\"\n [attr.role]=\"itemOrGroup.items ? 'group' : 'option'\"\n [attr.aria-label]=\"itemOrGroup.items ? maybeCallback(itemOrGroup.label) : null\"\n [aria-selected]=\"\n selectable() && !itemOrGroup.items ? valueArray().includes(itemOrGroup.value) : null\n \"\n [attr.aria-disabled]=\"itemOrGroup.disabled ? 'true' : null\"\n [ptInt]=\"this\"\n [ptClass]=\"{\n item: !itemOrGroup.items,\n group: !!itemOrGroup.items,\n 'item-selected': valueArray().includes(itemOrGroup.value),\n 'item-highlighted': itemOrGroup.value === currentHighlightedValue(),\n 'item-disabled': !!itemOrGroup.disabled,\n }\"\n (click)=\"\n !itemOrGroup.items && !itemOrGroup.disabled && selectable() && onSelect(itemOrGroup.value)\n \"\n (mouseenter)=\"\n !itemOrGroup.items &&\n !itemOrGroup.disabled &&\n selectable() &&\n selectOnHover() &&\n onSelect(itemOrGroup.value)\n \"\n >\n @if (showCheckboxes() && !itemOrGroup.items) {\n <ngn-checkbox\n [ptInt]=\"this\"\n [ptDep]=\"'checkbox'\"\n [value]=\"valueArray().includes(itemOrGroup.value)\"\n aria-hidden=\"true\"\n inert=\"true\"\n />\n }\n <ng-container\n *ngTemplateOutlet=\"\n itemOrGroup.items ? groupTemplate() : itemTemplate();\n context: { $implicit: itemOrGroup }\n \"\n ></ng-container>\n </div>\n</ng-template>\n\n<ng-template #defaultItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\n <span [attr.data-testid]=\"item?.testId\" [ptInt]=\"this\" [ptClass]=\"'default-item'\">\n @let label = item?.label;\n @if (label) {\n <span [attr.data-testid]=\"item?.testId\">{{ maybeCallback(label) }}</span>\n } @else {\n <span [attr.data-testid]=\"item?.testId\">&ZeroWidthSpace;</span>\n }\n </span>\n</ng-template>\n\n<ng-template #defaultGroupTemplate [ngnTemplate]=\"templateTypes.item\" let-group>\n <span [attr.data-testid]=\"group?.testId\" [ptInt]=\"this\" [ptClass]=\"'default-group'\">\n @let label = group?.label;\n @if (label) {\n <span [attr.data-testid]=\"group?.testId\">{{ maybeCallback(label) }}</span>\n } @else {\n <span [attr.data-testid]=\"group?.testId\">&ZeroWidthSpace;</span>\n }\n </span>\n</ng-template>\n\n<ng-template #defaultEmptyTemplate>\n <span [ptInt]=\"this\" [ptClass]=\"'empty'\" [attr.data-testid]=\"'empty'\">{{\n i18n['listBox_noItemsFound']()\n }}</span>\n</ng-template>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NgnScroller, selector: "ngn-scroller, [ngn-scroller]", inputs: ["items", "fieldId", "virtual", "itemHeight", "virtualPadding", "focusable", "fieldSticky"] }, { kind: "directive", type: NgnScrollerItem, selector: "[ngnScrollerItem]", inputs: ["ngnScrollerItem"] }, { kind: "component", type: NgnCheckbox, selector: "ngn-checkbox", inputs: ["iconChecked", "iconUnchecked", "iconIndeterminate", "allowIndeterminate"] }, { kind: "directive", type: NgnTemplate, selector: "ng-template[ngnTemplate]", inputs: ["ngnTemplate"] }, { kind: "directive", type: NgnPt, selector: "[ptInt]", inputs: ["ptInt", "ptClass", "ptDep"] }] });