@nanahoshi/mona-ui 0.18.5 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/README.md +71 -13
  2. package/fesm2022/nanahoshi-mona-ui-auto-complete.mjs +11 -3
  3. package/fesm2022/nanahoshi-mona-ui-breadcrumb.mjs +17 -9
  4. package/fesm2022/nanahoshi-mona-ui-button-group.mjs +16 -7
  5. package/fesm2022/nanahoshi-mona-ui-calendar.mjs +122 -48
  6. package/fesm2022/nanahoshi-mona-ui-card.mjs +22 -14
  7. package/fesm2022/nanahoshi-mona-ui-chart.mjs +78 -18
  8. package/fesm2022/nanahoshi-mona-ui-check-box.mjs +1 -1
  9. package/fesm2022/nanahoshi-mona-ui-chip.mjs +199 -77
  10. package/fesm2022/nanahoshi-mona-ui-circular-progress-bar.mjs +1 -2
  11. package/fesm2022/nanahoshi-mona-ui-color-gradient.mjs +23 -5
  12. package/fesm2022/nanahoshi-mona-ui-color-palette.mjs +49 -28
  13. package/fesm2022/nanahoshi-mona-ui-color-picker.mjs +42 -26
  14. package/fesm2022/nanahoshi-mona-ui-combo-box.mjs +11 -3
  15. package/fesm2022/nanahoshi-mona-ui-date-picker.mjs +28 -16
  16. package/fesm2022/nanahoshi-mona-ui-datetime-picker.mjs +74 -51
  17. package/fesm2022/nanahoshi-mona-ui-dialog.mjs +57 -25
  18. package/fesm2022/nanahoshi-mona-ui-dropdown-list.mjs +13 -5
  19. package/fesm2022/nanahoshi-mona-ui-dropdowns.mjs +17 -6
  20. package/fesm2022/nanahoshi-mona-ui-editor.mjs +178 -59
  21. package/fesm2022/nanahoshi-mona-ui-filter.mjs +137 -54
  22. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-cell.component-WEDbZ5vy.mjs → nanahoshi-mona-ui-grid-grid-footer-cell.component-Bg7rckst.mjs} +2 -2
  23. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-table-cell.directive-ibH5osCg.mjs → nanahoshi-mona-ui-grid-grid-footer-table-cell.directive-BSSpaCLL.mjs} +2 -2
  24. package/fesm2022/nanahoshi-mona-ui-grid-grid-list.component-D9AwQFDV.mjs +145 -0
  25. package/fesm2022/{nanahoshi-mona-ui-grid-grid-toggle.component-hc-LeIb0.mjs → nanahoshi-mona-ui-grid-grid-toggle.component-Byb9iTes.mjs} +21 -17
  26. package/fesm2022/{nanahoshi-mona-ui-grid-grid-virtual-list.component-DYajpOb9.mjs → nanahoshi-mona-ui-grid-grid-virtual-list.component-CBmdtrXm.mjs} +5 -5
  27. package/fesm2022/{nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-Pm8Fbp6M.mjs → nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-DPmJmCap.mjs} +90 -42
  28. package/fesm2022/nanahoshi-mona-ui-grid.mjs +1 -1
  29. package/fesm2022/nanahoshi-mona-ui-i18n.mjs +1168 -0
  30. package/fesm2022/nanahoshi-mona-ui-internal-list.mjs +12 -4
  31. package/fesm2022/nanahoshi-mona-ui-internal-tree.mjs +48 -21
  32. package/fesm2022/nanahoshi-mona-ui-list-box.mjs +33 -18
  33. package/fesm2022/nanahoshi-mona-ui-list-view.mjs +10 -10
  34. package/fesm2022/nanahoshi-mona-ui-list.mjs +2 -0
  35. package/fesm2022/nanahoshi-mona-ui-menubar.mjs +29 -16
  36. package/fesm2022/nanahoshi-mona-ui-multi-select.mjs +12 -3
  37. package/fesm2022/nanahoshi-mona-ui-notification.mjs +23 -18
  38. package/fesm2022/nanahoshi-mona-ui-numeric-text-box.mjs +211 -106
  39. package/fesm2022/nanahoshi-mona-ui-otp-input.mjs +14 -6
  40. package/fesm2022/nanahoshi-mona-ui-pager.mjs +46 -19
  41. package/fesm2022/nanahoshi-mona-ui-popup-menu.mjs +57 -46
  42. package/fesm2022/nanahoshi-mona-ui-popup.mjs +35 -15
  43. package/fesm2022/nanahoshi-mona-ui-progress-bar.mjs +38 -17
  44. package/fesm2022/nanahoshi-mona-ui-rating.mjs +25 -7
  45. package/fesm2022/nanahoshi-mona-ui-scroll-view.mjs +431 -101
  46. package/fesm2022/nanahoshi-mona-ui-segmented.mjs +1 -1
  47. package/fesm2022/nanahoshi-mona-ui-sheet.mjs +26 -8
  48. package/fesm2022/nanahoshi-mona-ui-sidebar.mjs +222 -28
  49. package/fesm2022/nanahoshi-mona-ui-slider.mjs +91 -36
  50. package/fesm2022/nanahoshi-mona-ui-spinner.mjs +34 -15
  51. package/fesm2022/nanahoshi-mona-ui-split-button.mjs +39 -23
  52. package/fesm2022/nanahoshi-mona-ui-splitter.mjs +50 -25
  53. package/fesm2022/nanahoshi-mona-ui-stepper.mjs +32 -14
  54. package/fesm2022/nanahoshi-mona-ui-switch.mjs +9 -9
  55. package/fesm2022/nanahoshi-mona-ui-tabs.mjs +74 -56
  56. package/fesm2022/nanahoshi-mona-ui-text-box.mjs +16 -8
  57. package/fesm2022/nanahoshi-mona-ui-time-picker.mjs +33 -19
  58. package/fesm2022/nanahoshi-mona-ui-time-selector.mjs +66 -27
  59. package/fesm2022/nanahoshi-mona-ui-tree-view.mjs +23 -15
  60. package/fesm2022/nanahoshi-mona-ui-window.mjs +71 -40
  61. package/i18n/package.json +4 -0
  62. package/package.json +5 -1
  63. package/types/nanahoshi-mona-ui-auto-complete.d.ts +6 -1
  64. package/types/nanahoshi-mona-ui-breadcrumb.d.ts +9 -3
  65. package/types/nanahoshi-mona-ui-button-group.d.ts +9 -3
  66. package/types/nanahoshi-mona-ui-calendar.d.ts +13 -3
  67. package/types/nanahoshi-mona-ui-card.d.ts +8 -2
  68. package/types/nanahoshi-mona-ui-chart.d.ts +10 -1
  69. package/types/nanahoshi-mona-ui-chip.d.ts +14 -5
  70. package/types/nanahoshi-mona-ui-color-gradient.d.ts +6 -1
  71. package/types/nanahoshi-mona-ui-color-palette.d.ts +21 -10
  72. package/types/nanahoshi-mona-ui-color-picker.d.ts +30 -20
  73. package/types/nanahoshi-mona-ui-combo-box.d.ts +6 -1
  74. package/types/nanahoshi-mona-ui-date-picker.d.ts +7 -2
  75. package/types/nanahoshi-mona-ui-datetime-picker.d.ts +33 -8
  76. package/types/nanahoshi-mona-ui-dialog.d.ts +16 -7
  77. package/types/nanahoshi-mona-ui-dropdown-list.d.ts +6 -1
  78. package/types/nanahoshi-mona-ui-dropdowns.d.ts +4 -1
  79. package/types/nanahoshi-mona-ui-editor.d.ts +6 -1
  80. package/types/nanahoshi-mona-ui-filter.d.ts +16 -10
  81. package/types/nanahoshi-mona-ui-grid.d.ts +38 -1
  82. package/types/nanahoshi-mona-ui-i18n.d.ts +633 -0
  83. package/types/nanahoshi-mona-ui-internal-list.d.ts +7 -2
  84. package/types/nanahoshi-mona-ui-internal-tree.d.ts +7 -3
  85. package/types/nanahoshi-mona-ui-list-box.d.ts +9 -4
  86. package/types/nanahoshi-mona-ui-list-view.d.ts +6 -6
  87. package/types/nanahoshi-mona-ui-list.d.ts +1 -1
  88. package/types/nanahoshi-mona-ui-menubar.d.ts +59 -58
  89. package/types/nanahoshi-mona-ui-multi-select.d.ts +6 -1
  90. package/types/nanahoshi-mona-ui-notification.d.ts +11 -5
  91. package/types/nanahoshi-mona-ui-numeric-text-box.d.ts +24 -15
  92. package/types/nanahoshi-mona-ui-otp-input.d.ts +9 -3
  93. package/types/nanahoshi-mona-ui-pager.d.ts +19 -6
  94. package/types/nanahoshi-mona-ui-popup.d.ts +2 -1
  95. package/types/nanahoshi-mona-ui-progress-bar.d.ts +9 -7
  96. package/types/nanahoshi-mona-ui-rating.d.ts +19 -12
  97. package/types/nanahoshi-mona-ui-scroll-view.d.ts +34 -28
  98. package/types/nanahoshi-mona-ui-sheet.d.ts +8 -2
  99. package/types/nanahoshi-mona-ui-sidebar.d.ts +3 -0
  100. package/types/nanahoshi-mona-ui-slider.d.ts +44 -26
  101. package/types/nanahoshi-mona-ui-spinner.d.ts +13 -4
  102. package/types/nanahoshi-mona-ui-split-button.d.ts +62 -56
  103. package/types/nanahoshi-mona-ui-splitter.d.ts +9 -6
  104. package/types/nanahoshi-mona-ui-stepper.d.ts +9 -3
  105. package/types/nanahoshi-mona-ui-switch.d.ts +1 -1
  106. package/types/nanahoshi-mona-ui-tabs.d.ts +96 -35
  107. package/types/nanahoshi-mona-ui-text-box.d.ts +11 -5
  108. package/types/nanahoshi-mona-ui-time-picker.d.ts +7 -2
  109. package/types/nanahoshi-mona-ui-time-selector.d.ts +16 -5
  110. package/types/nanahoshi-mona-ui-tree-view.d.ts +15 -10
  111. package/types/nanahoshi-mona-ui-window.d.ts +26 -20
  112. package/fesm2022/nanahoshi-mona-ui-grid-grid-list.component-ZM3CneJ0.mjs +0 -145
@@ -9,6 +9,7 @@ import { Subject, take, tap, fromEvent, takeUntil, filter, switchMap } from 'rxj
9
9
  import { v4 } from 'uuid';
10
10
  import { NgTemplateOutlet } from '@angular/common';
11
11
  import { LucideChevronRight, LucideCheck } from '@lucide/angular';
12
+ import { injectComponentDirection, MonaI18nService } from '@nanahoshi/mona-ui/i18n';
12
13
  import { twMerge } from 'tailwind-merge';
13
14
  import { cva } from 'class-variance-authority';
14
15
 
@@ -166,9 +167,9 @@ const popupMenuGroupHeaderThemeVariants = cva(`inline-flex w-full select-none px
166
167
  }
167
168
  }
168
169
  });
169
- const popupMenuIconContainerThemeVariants = cva(`absolute left-2 flex items-center justify-center`);
170
+ const popupMenuIconContainerThemeVariants = cva(`absolute start-2 flex items-center justify-center`);
170
171
  const popupMenuItemThemeVariants = cva(`
171
- relative flex cursor-pointer select-none items-center gap-2 py-1 pr-2 pl-8
172
+ relative flex cursor-pointer select-none items-center gap-2 py-1 pe-2 ps-8
172
173
  text-foreground outline-none
173
174
  hover:bg-[var(--mona-menu-item-hover-background,var(--color-hover))] hover:text-foreground
174
175
  focus-within:bg-[var(--mona-menu-item-hover-background,var(--color-hover))]
@@ -200,7 +201,9 @@ class PopupMenuListComponent {
200
201
  #close$;
201
202
  #config;
202
203
  #destroyRef;
204
+ #direction;
203
205
  #host;
206
+ #i18n;
204
207
  #navigationItems;
205
208
  #parentConfig;
206
209
  #popupService;
@@ -241,7 +244,11 @@ class PopupMenuListComponent {
241
244
  }, /* @ts-ignore */
242
245
  ...(ngDevMode ? [{ debugName: "#config" }] : /* istanbul ignore next */ []));
243
246
  this.#destroyRef = inject(DestroyRef);
247
+ this.#direction = injectComponentDirection();
244
248
  this.#host = inject((ElementRef));
249
+ this.#i18n = inject(MonaI18nService);
250
+ this.isRtl = computed(() => this.#direction() === "rtl", /* @ts-ignore */
251
+ ...(ngDevMode ? [{ debugName: "isRtl" }] : /* istanbul ignore next */ []));
245
252
  this.#navigationItems = computed(() => {
246
253
  const items = this.#parentConfig.items;
247
254
  return selectMany(items, i => i.source)
@@ -268,10 +275,7 @@ class PopupMenuListComponent {
268
275
  ...(ngDevMode ? [{ debugName: "containerClasses" }] : /* istanbul ignore next */ []));
269
276
  this.groupHeaderClasses = computed(() => {
270
277
  const size = this.#parentConfig.size();
271
- const hasIcon = this.iconAreaVisible();
272
- const variantClasses = popupMenuGroupHeaderThemeVariants({ size });
273
- const iconClasses = ""; //hasIcon ? "pl-8" : "pl-2";
274
- return twMerge(variantClasses, iconClasses);
278
+ return popupMenuGroupHeaderThemeVariants({ size });
275
279
  }, /* @ts-ignore */
276
280
  ...(ngDevMode ? [{ debugName: "groupHeaderClasses" }] : /* istanbul ignore next */ []));
277
281
  this.iconAreaVisible = computed(() => {
@@ -295,7 +299,7 @@ class PopupMenuListComponent {
295
299
  const size = this.#parentConfig.size();
296
300
  const hasIcon = this.iconAreaVisible();
297
301
  const variantClasses = popupMenuItemThemeVariants({ rounded, size });
298
- const iconClasses = hasIcon ? "pl-8" : "pl-2";
302
+ const iconClasses = hasIcon ? "ps-8" : "ps-2";
299
303
  return twMerge(variantClasses, iconClasses);
300
304
  }, /* @ts-ignore */
301
305
  ...(ngDevMode ? [{ debugName: "menuItemClasses" }] : /* istanbul ignore next */ []));
@@ -317,7 +321,8 @@ class PopupMenuListComponent {
317
321
  this.#host.nativeElement.firstElementChild?.focus();
318
322
  if (!this.#parentConfig.isRoot && this.#parentConfig.viaKeyboardNavigation) {
319
323
  const item = this.focusFirstItem();
320
- this.notifyNavigation(item, "right");
324
+ const isRtl = this.isRtl();
325
+ this.notifyNavigation(item, isRtl ? "left" : "right");
321
326
  }
322
327
  }
323
328
  });
@@ -340,6 +345,9 @@ class PopupMenuListComponent {
340
345
  }
341
346
  this.#close$.next();
342
347
  }
348
+ closeSubmenu() {
349
+ this.#parentConfig.childCloseRequest$?.next();
350
+ }
343
351
  createSubmenu(target, viaKeyboard) {
344
352
  this.#viaKeyboardNavigation.set(viaKeyboard);
345
353
  const minWidth = this.#parentConfig.minWidth?.() ?? undefined;
@@ -410,24 +418,6 @@ class PopupMenuListComponent {
410
418
  }
411
419
  return firstItem;
412
420
  }
413
- handleArrowLeftKey() {
414
- this.#parentConfig.childCloseRequest$?.next();
415
- }
416
- handleArrowRightKey() {
417
- const activeItem = this.activeMenuItem();
418
- if (!activeItem) {
419
- return { item: null, hasChild: false };
420
- }
421
- const target = this.#host.nativeElement.querySelector('[data-active="true"]');
422
- if (target && activeItem.items.length > 0) {
423
- this.createSubmenu(target, true).subscribe();
424
- return { item: activeItem, hasChild: true };
425
- }
426
- if (activeItem && activeItem.items.length > 0) {
427
- return { item: activeItem, hasChild: true };
428
- }
429
- return { item: null, hasChild: false };
430
- }
431
421
  handleArrowUpKey() {
432
422
  if (!this.activeMenuItem()) {
433
423
  const lastItem = this.#navigationItems().lastOrDefault();
@@ -481,21 +471,26 @@ class PopupMenuListComponent {
481
471
  }
482
472
  }
483
473
  handleNavigationKey(event) {
474
+ const isRtl = this.isRtl();
475
+ const openKey = isRtl ? "ArrowLeft" : "ArrowRight";
476
+ const closeKey = isRtl ? "ArrowRight" : "ArrowLeft";
477
+ const forwardDir = isRtl ? "left" : "right";
478
+ const backwardDir = isRtl ? "right" : "left";
484
479
  let item = null;
485
480
  if (event.key === "ArrowDown") {
486
481
  item = this.handleArrowDownKey();
487
482
  this.notifyNavigation(item, "down");
488
483
  }
489
- else if (event.key === "ArrowLeft") {
490
- this.handleArrowLeftKey();
484
+ else if (event.key === closeKey) {
485
+ this.closeSubmenu();
491
486
  if (this.#parentConfig.level === 0) {
492
- this.notifyNavigation(null, "left");
487
+ this.notifyNavigation(null, backwardDir);
493
488
  }
494
489
  }
495
- else if (event.key === "ArrowRight") {
496
- const result = this.handleArrowRightKey();
490
+ else if (event.key === openKey) {
491
+ const result = this.openSubmenu();
497
492
  if (!result.hasChild) {
498
- this.notifyNavigation(item, "right");
493
+ this.notifyNavigation(item, forwardDir);
499
494
  }
500
495
  }
501
496
  else if (event.key === "ArrowUp") {
@@ -526,6 +521,21 @@ class PopupMenuListComponent {
526
521
  level: this.#parentConfig.level
527
522
  });
528
523
  }
524
+ openSubmenu() {
525
+ const activeItem = this.activeMenuItem();
526
+ if (!activeItem) {
527
+ return { item: null, hasChild: false };
528
+ }
529
+ const target = this.#host.nativeElement.querySelector('[data-active="true"]');
530
+ if (target && activeItem.items.length > 0) {
531
+ this.createSubmenu(target, true).subscribe();
532
+ return { item: activeItem, hasChild: true };
533
+ }
534
+ if (activeItem && activeItem.items.length > 0) {
535
+ return { item: activeItem, hasChild: true };
536
+ }
537
+ return { item: null, hasChild: false };
538
+ }
529
539
  setKeyboardEvents() {
530
540
  const element = this.#host.nativeElement.firstElementChild;
531
541
  fromEvent(element, "keydown")
@@ -542,18 +552,6 @@ class PopupMenuListComponent {
542
552
  }))
543
553
  .subscribe();
544
554
  }
545
- setPopupCloseSubscription() {
546
- this.#parentConfig.parentClose$
547
- .pipe(takeUntilDestroyed(this.#destroyRef), tap(() => this.closePopup()))
548
- .subscribe();
549
- this.#childCloseRequest$
550
- .pipe(takeUntilDestroyed(this.#destroyRef), tap(() => {
551
- const activeItem = this.activeMenuItem();
552
- this.notifyNavigation(activeItem, "left");
553
- this.closePopup();
554
- }))
555
- .subscribe();
556
- }
557
555
  setPointerSubscriptions() {
558
556
  this.pointerEnter$
559
557
  .pipe(takeUntilDestroyed(this.#destroyRef), takeUntil(this.#parentConfig.parentClose$), filter(e => e.item !== this.activeMenuItem()), tap(e => {
@@ -570,6 +568,19 @@ class PopupMenuListComponent {
570
568
  .pipe(takeUntilDestroyed(this.#destroyRef), takeUntil(this.pointerEnter$))
571
569
  .subscribe(() => this.popupRef?.close());
572
570
  }
571
+ setPopupCloseSubscription() {
572
+ this.#parentConfig.parentClose$
573
+ .pipe(takeUntilDestroyed(this.#destroyRef), tap(() => this.closePopup()))
574
+ .subscribe();
575
+ this.#childCloseRequest$
576
+ .pipe(takeUntilDestroyed(this.#destroyRef), tap(() => {
577
+ const activeItem = this.activeMenuItem();
578
+ const isRtl = this.isRtl();
579
+ this.notifyNavigation(activeItem, isRtl ? "right" : "left");
580
+ this.closePopup();
581
+ }))
582
+ .subscribe();
583
+ }
573
584
  setSubscriptions() {
574
585
  this.setKeyboardEvents();
575
586
  this.setPointerSubscriptions();
@@ -582,13 +593,13 @@ class PopupMenuListComponent {
582
593
  .subscribe(buffer => this.cycleThroughMatchedItems(buffer));
583
594
  }
584
595
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: PopupMenuListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
585
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: PopupMenuListComponent, isStandalone: true, selector: "mona-popup-menu-list", host: { properties: { "class": "baseClasses()" } }, ngImport: i0, template: "<div\n role=\"menu\"\n [attr.tabindex]=\"0\"\n [attr.aria-orientation]=\"'vertical'\"\n [attr.aria-activedescendant]=\"activeMenuItem()?.uid\"\n [attr.id]=\"menuId()\"\n [class]=\"containerClasses()\">\n @for (group of menuItems(); track $index) {\n @if (typeof group.key === \"string\") {\n @let groupTemplate = group.first().groupTemplate?.() ?? popupGroupTemplate() ?? null;\n <div role=\"group\" [attr.aria-labelledby]=\"`${group.key}-${$index}`\" [class]=\"groupHeaderClasses()\">\n <div [id]=\"`${group.key}-${$index}`\" role=\"presentation\">\n @if (groupTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"groupTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: group.key }\"></ng-container>\n } @else {\n <span>{{ group.key }}</span>\n }\n </div>\n </div>\n }\n @for (item of group.source; track $index) {\n @if (item.separator) {\n <div role=\"separator\" class=\"bg-border my-1 h-px\"></div>\n } @else {\n @let iconTemplate = item.iconTemplate?.() ?? popupIconTemplate() ?? null;\n @let shortcutTemplate = item.shortcutTemplate?.() ?? popupShortcutTemplate() ?? null;\n @let textTemplate = item.textTemplate?.() ?? popupTextTemplate() ?? null;\n <div\n role=\"menuitem\"\n [id]=\"item.uid\"\n (pointerenter)=\"pointerEnter$.next({ event: $event, item: item })\"\n (pointerleave)=\"pointerLeave$.next({ event: $event, item: item })\"\n (click)=\"onItemClick($event, item)\"\n [attr.data-active]=\"item === activeMenuItem()\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.items.length > 0 && item === activeMenuItem() && !!popupRef\"\n [attr.aria-haspopup]=\"item.items.length > 0 ? 'menu' : null\"\n [attr.aria-label]=\"item.label || null\"\n [attr.data-disabled]=\"item.disabled\"\n [class]=\"menuItemClasses()\">\n @if (iconAreaVisible()) {\n <div [class]=\"iconContainerClasses()\">\n @if (!item.checkable && !item.radio) {\n <ng-container\n [ngTemplateOutlet]=\"iconTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n } @else if (item.checkable) {\n @if (item.checked?.()) {\n <svg lucideCheck [size]=\"14\"></svg>\n }\n } @else if (item.radio) {\n @if (item.selected?.()) {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n class=\"lucide lucide-circle size-2 fill-current\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n </svg>\n }\n }\n </div>\n }\n <div class=\"flex-1\">\n @if (textTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"textTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n } @else {\n {{ item.label }}\n }\n </div>\n @if (item.items.length > 0) {\n @if (!item.checkable) {\n <div [class]=\"linkContainerClasses()\">\n <svg lucideChevronRight [size]=\"16\"></svg>\n </div>\n }\n } @else if (shortcutTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"shortcutTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n }\n </div>\n }\n }\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: LucideChevronRight, selector: "svg[lucideChevronRight]" }, { kind: "component", type: LucideCheck, selector: "svg[lucideCheck]" }] }); }
596
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: PopupMenuListComponent, isStandalone: true, selector: "mona-popup-menu-list", host: { properties: { "class": "baseClasses()" } }, ngImport: i0, template: "<div\n role=\"menu\"\n [attr.tabindex]=\"0\"\n [attr.aria-orientation]=\"'vertical'\"\n [attr.aria-activedescendant]=\"activeMenuItem()?.uid\"\n [attr.id]=\"menuId()\"\n [class]=\"containerClasses()\">\n @for (group of menuItems(); track $index) {\n @if (typeof group.key === \"string\") {\n @let groupTemplate = group.first().groupTemplate?.() ?? popupGroupTemplate() ?? null;\n <div role=\"group\" [attr.aria-labelledby]=\"`${group.key}-${$index}`\" [class]=\"groupHeaderClasses()\">\n <div [id]=\"`${group.key}-${$index}`\" role=\"presentation\">\n @if (groupTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"groupTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: group.key }\"></ng-container>\n } @else {\n <span>{{ group.key }}</span>\n }\n </div>\n </div>\n }\n @for (item of group.source; track $index) {\n @if (item.separator) {\n <div role=\"separator\" class=\"bg-border my-1 h-px\"></div>\n } @else {\n @let iconTemplate = item.iconTemplate?.() ?? popupIconTemplate() ?? null;\n @let shortcutTemplate = item.shortcutTemplate?.() ?? popupShortcutTemplate() ?? null;\n @let textTemplate = item.textTemplate?.() ?? popupTextTemplate() ?? null;\n <div\n role=\"menuitem\"\n [id]=\"item.uid\"\n (pointerenter)=\"pointerEnter$.next({ event: $event, item: item })\"\n (pointerleave)=\"pointerLeave$.next({ event: $event, item: item })\"\n (click)=\"onItemClick($event, item)\"\n [attr.data-active]=\"item === activeMenuItem()\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.items.length > 0 && item === activeMenuItem() && !!popupRef\"\n [attr.aria-haspopup]=\"item.items.length > 0 ? 'menu' : null\"\n [attr.aria-label]=\"item.label || null\"\n [attr.data-disabled]=\"item.disabled\"\n [class]=\"menuItemClasses()\">\n @if (iconAreaVisible()) {\n <div [class]=\"iconContainerClasses()\">\n @if (!item.checkable && !item.radio) {\n <ng-container\n [ngTemplateOutlet]=\"iconTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n } @else if (item.checkable) {\n @if (item.checked?.()) {\n <svg lucideCheck [size]=\"14\"></svg>\n }\n } @else if (item.radio) {\n @if (item.selected?.()) {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n class=\"lucide lucide-circle size-2 fill-current\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n </svg>\n }\n }\n </div>\n }\n <div class=\"flex-1\">\n @if (textTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"textTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n } @else {\n {{ item.label }}\n }\n </div>\n @if (item.items.length > 0) {\n @if (!item.checkable) {\n <div [class]=\"linkContainerClasses()\">\n <svg lucideChevronRight [size]=\"16\" class=\"rtl:rotate-180\"></svg>\n </div>\n }\n } @else if (shortcutTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"shortcutTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n }\n </div>\n }\n }\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: LucideChevronRight, selector: "svg[lucideChevronRight]" }, { kind: "component", type: LucideCheck, selector: "svg[lucideCheck]" }] }); }
586
597
  }
587
598
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: PopupMenuListComponent, decorators: [{
588
599
  type: Component,
589
600
  args: [{ selector: "mona-popup-menu-list", imports: [NgTemplateOutlet, LucideChevronRight, LucideCheck], host: {
590
601
  "[class]": "baseClasses()"
591
- }, template: "<div\n role=\"menu\"\n [attr.tabindex]=\"0\"\n [attr.aria-orientation]=\"'vertical'\"\n [attr.aria-activedescendant]=\"activeMenuItem()?.uid\"\n [attr.id]=\"menuId()\"\n [class]=\"containerClasses()\">\n @for (group of menuItems(); track $index) {\n @if (typeof group.key === \"string\") {\n @let groupTemplate = group.first().groupTemplate?.() ?? popupGroupTemplate() ?? null;\n <div role=\"group\" [attr.aria-labelledby]=\"`${group.key}-${$index}`\" [class]=\"groupHeaderClasses()\">\n <div [id]=\"`${group.key}-${$index}`\" role=\"presentation\">\n @if (groupTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"groupTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: group.key }\"></ng-container>\n } @else {\n <span>{{ group.key }}</span>\n }\n </div>\n </div>\n }\n @for (item of group.source; track $index) {\n @if (item.separator) {\n <div role=\"separator\" class=\"bg-border my-1 h-px\"></div>\n } @else {\n @let iconTemplate = item.iconTemplate?.() ?? popupIconTemplate() ?? null;\n @let shortcutTemplate = item.shortcutTemplate?.() ?? popupShortcutTemplate() ?? null;\n @let textTemplate = item.textTemplate?.() ?? popupTextTemplate() ?? null;\n <div\n role=\"menuitem\"\n [id]=\"item.uid\"\n (pointerenter)=\"pointerEnter$.next({ event: $event, item: item })\"\n (pointerleave)=\"pointerLeave$.next({ event: $event, item: item })\"\n (click)=\"onItemClick($event, item)\"\n [attr.data-active]=\"item === activeMenuItem()\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.items.length > 0 && item === activeMenuItem() && !!popupRef\"\n [attr.aria-haspopup]=\"item.items.length > 0 ? 'menu' : null\"\n [attr.aria-label]=\"item.label || null\"\n [attr.data-disabled]=\"item.disabled\"\n [class]=\"menuItemClasses()\">\n @if (iconAreaVisible()) {\n <div [class]=\"iconContainerClasses()\">\n @if (!item.checkable && !item.radio) {\n <ng-container\n [ngTemplateOutlet]=\"iconTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n } @else if (item.checkable) {\n @if (item.checked?.()) {\n <svg lucideCheck [size]=\"14\"></svg>\n }\n } @else if (item.radio) {\n @if (item.selected?.()) {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n class=\"lucide lucide-circle size-2 fill-current\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n </svg>\n }\n }\n </div>\n }\n <div class=\"flex-1\">\n @if (textTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"textTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n } @else {\n {{ item.label }}\n }\n </div>\n @if (item.items.length > 0) {\n @if (!item.checkable) {\n <div [class]=\"linkContainerClasses()\">\n <svg lucideChevronRight [size]=\"16\"></svg>\n </div>\n }\n } @else if (shortcutTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"shortcutTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n }\n </div>\n }\n }\n }\n</div>\n" }]
602
+ }, template: "<div\n role=\"menu\"\n [attr.tabindex]=\"0\"\n [attr.aria-orientation]=\"'vertical'\"\n [attr.aria-activedescendant]=\"activeMenuItem()?.uid\"\n [attr.id]=\"menuId()\"\n [class]=\"containerClasses()\">\n @for (group of menuItems(); track $index) {\n @if (typeof group.key === \"string\") {\n @let groupTemplate = group.first().groupTemplate?.() ?? popupGroupTemplate() ?? null;\n <div role=\"group\" [attr.aria-labelledby]=\"`${group.key}-${$index}`\" [class]=\"groupHeaderClasses()\">\n <div [id]=\"`${group.key}-${$index}`\" role=\"presentation\">\n @if (groupTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"groupTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: group.key }\"></ng-container>\n } @else {\n <span>{{ group.key }}</span>\n }\n </div>\n </div>\n }\n @for (item of group.source; track $index) {\n @if (item.separator) {\n <div role=\"separator\" class=\"bg-border my-1 h-px\"></div>\n } @else {\n @let iconTemplate = item.iconTemplate?.() ?? popupIconTemplate() ?? null;\n @let shortcutTemplate = item.shortcutTemplate?.() ?? popupShortcutTemplate() ?? null;\n @let textTemplate = item.textTemplate?.() ?? popupTextTemplate() ?? null;\n <div\n role=\"menuitem\"\n [id]=\"item.uid\"\n (pointerenter)=\"pointerEnter$.next({ event: $event, item: item })\"\n (pointerleave)=\"pointerLeave$.next({ event: $event, item: item })\"\n (click)=\"onItemClick($event, item)\"\n [attr.data-active]=\"item === activeMenuItem()\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.items.length > 0 && item === activeMenuItem() && !!popupRef\"\n [attr.aria-haspopup]=\"item.items.length > 0 ? 'menu' : null\"\n [attr.aria-label]=\"item.label || null\"\n [attr.data-disabled]=\"item.disabled\"\n [class]=\"menuItemClasses()\">\n @if (iconAreaVisible()) {\n <div [class]=\"iconContainerClasses()\">\n @if (!item.checkable && !item.radio) {\n <ng-container\n [ngTemplateOutlet]=\"iconTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n } @else if (item.checkable) {\n @if (item.checked?.()) {\n <svg lucideCheck [size]=\"14\"></svg>\n }\n } @else if (item.radio) {\n @if (item.selected?.()) {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n class=\"lucide lucide-circle size-2 fill-current\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n </svg>\n }\n }\n </div>\n }\n <div class=\"flex-1\">\n @if (textTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"textTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n } @else {\n {{ item.label }}\n }\n </div>\n @if (item.items.length > 0) {\n @if (!item.checkable) {\n <div [class]=\"linkContainerClasses()\">\n <svg lucideChevronRight [size]=\"16\" class=\"rtl:rotate-180\"></svg>\n </div>\n }\n } @else if (shortcutTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"shortcutTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n }\n </div>\n }\n }\n }\n</div>\n" }]
592
603
  }], ctorParameters: () => [] });
593
604
 
594
605
  class PopupMenuComponent {
@@ -8,6 +8,7 @@ import { Directionality } from '@angular/cdk/bidi';
8
8
  import { Overlay, OverlayConfig } from '@angular/cdk/overlay';
9
9
  import { ComponentPortal } from '@angular/cdk/portal';
10
10
  import { ScrollDispatcher } from '@angular/cdk/scrolling';
11
+ import { MonaI18nService, resolveComponentDirection, observeComponentDirection } from '@nanahoshi/mona-ui/i18n';
11
12
  import { NgTemplateOutlet } from '@angular/common';
12
13
 
13
14
  class PopupCloseEvent extends PreventableEvent {
@@ -552,11 +553,12 @@ class PopupService {
552
553
  #destroyRef = inject(DestroyRef);
553
554
  #directionality = inject(Directionality, { optional: true });
554
555
  #document = inject(DOCUMENT);
556
+ #i18n = inject(MonaI18nService, { optional: true });
555
557
  #injector = inject(Injector);
556
558
  #outsideEventsToClose = ["click", "mousedown", "dblclick", "contextmenu", "auxclick"];
557
559
  #overlay = inject(Overlay);
558
- #selectorSubscriptions = new Map();
559
560
  #scrollDispatcher = inject(ScrollDispatcher);
561
+ #selectorSubscriptions = new Map();
560
562
  create(settings) {
561
563
  if (typeof settings.anchor === "string") {
562
564
  return this.createMultiElementPopup(settings);
@@ -628,7 +630,12 @@ class PopupService {
628
630
  createOverlay(settings) {
629
631
  const positionStrategy = this.createPositionStrategy(settings);
630
632
  const panelClass = this.buildPanelClass(settings.popupClass);
631
- const direction = this.#directionality?.value;
633
+ const anchorElement = settings.anchor instanceof ElementRef
634
+ ? settings.anchor.nativeElement
635
+ : settings.anchor instanceof HTMLElement
636
+ ? settings.anchor
637
+ : null;
638
+ const direction = resolveComponentDirection(anchorElement, this.#directionality);
632
639
  return this.#overlay.create(new OverlayConfig({
633
640
  positionStrategy,
634
641
  hasBackdrop: settings.hasBackdrop ?? false,
@@ -688,6 +695,7 @@ class PopupService {
688
695
  this.setupScrollTracking(settings, overlayRef, popupReference);
689
696
  this.setupEscapeKeyListener(settings, popupReference);
690
697
  this.setupPositionChangeTracking(settings, overlayRef, popupReference);
698
+ this.setupDirectionTracking(settings, overlayRef, popupReference);
691
699
  return popupReference.popupRef;
692
700
  }
693
701
  getAnchorElement(anchor) {
@@ -732,6 +740,19 @@ class PopupService {
732
740
  .forEach(scrollable => addScrollable(scrollable));
733
741
  return Array.from(scrollablesByElement.values());
734
742
  }
743
+ handleFocusRestoration(settings, originallyFocusedElement) {
744
+ const restoreFocus = settings.restoreFocus ?? "auto";
745
+ if (restoreFocus === false) {
746
+ return;
747
+ }
748
+ if (restoreFocus === "auto") {
749
+ if (originallyFocusedElement) {
750
+ originallyFocusedElement.focus();
751
+ }
752
+ return;
753
+ }
754
+ this.restoreFocusToAnchor(settings.anchor);
755
+ }
735
756
  isScrollableElement(element) {
736
757
  const defaultView = this.#document.defaultView;
737
758
  if (!defaultView) {
@@ -747,19 +768,6 @@ class PopupService {
747
768
  isScrollableOverflow(value) {
748
769
  return value === "auto" || value === "scroll" || value === "overlay";
749
770
  }
750
- handleFocusRestoration(settings, originallyFocusedElement) {
751
- const restoreFocus = settings.restoreFocus ?? "auto";
752
- if (restoreFocus === false) {
753
- return;
754
- }
755
- if (restoreFocus === "auto") {
756
- if (originallyFocusedElement) {
757
- originallyFocusedElement.focus();
758
- }
759
- return;
760
- }
761
- this.restoreFocusToAnchor(settings.anchor);
762
- }
763
771
  /**
764
772
  * Resolves a PopupAnchor to a FlexibleConnectedPositionStrategyOrigin.
765
773
  * This method should only receive actual elements or ElementRefs, not CSS selector strings.
@@ -936,6 +944,18 @@ class PopupService {
936
944
  .subscribe(change => popupReference.positionChanges$.next(change.connectionPair));
937
945
  }
938
946
  }
947
+ setupDirectionTracking(settings, overlayRef, popupReference) {
948
+ const resolvedAnchor = this.resolveAnchor(settings.anchor);
949
+ const anchorElement = this.getAnchorElement(resolvedAnchor);
950
+ const cleanup = observeComponentDirection(anchorElement, this.#directionality, nextDir => {
951
+ overlayRef.setDirection(nextDir);
952
+ overlayRef.updatePosition();
953
+ popupReference.componentRef?.changeDetectorRef.markForCheck();
954
+ });
955
+ popupReference.closed.pipe(take(1)).subscribe(() => {
956
+ cleanup();
957
+ });
958
+ }
939
959
  setupScrollClosing(settings, popupReference, overlayRef) {
940
960
  if (!settings.closeOnScroll) {
941
961
  return;
@@ -1,7 +1,8 @@
1
- import { NgTemplateOutlet, DecimalPipe } from '@angular/common';
1
+ import { NgTemplateOutlet } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
3
  import { inject, TemplateRef, Directive, computed, contentChild, input, Component } from '@angular/core';
4
4
  import { getPercentage } from '@nanahoshi/mona-ui/common';
5
+ import { injectComponentDirection, MonaI18nService, formatNumber } from '@nanahoshi/mona-ui/i18n';
5
6
  import { twMerge } from 'tailwind-merge';
6
7
  import { cva } from 'class-variance-authority';
7
8
 
@@ -62,8 +63,8 @@ const progressBarTrackThemeVariants = cva(`
62
63
  data-[next='true']:duration-(--mona-motion-fast)
63
64
  data-[next='true']:ease-in
64
65
  data-[value='0']:bg-transparent
65
- data-[left='true']:justify-start
66
- data-[right='true']:justify-end
66
+ data-[start='true']:justify-start
67
+ data-[end='true']:justify-end
67
68
  `, {
68
69
  variants: {
69
70
  rounded: {
@@ -84,6 +85,18 @@ class ProgressBarComponent {
84
85
  return typeof color === "string" ? color : color?.(progress);
85
86
  }, /* @ts-ignore */
86
87
  ...(ngDevMode ? [{ debugName: "#color" }] : /* istanbul ignore next */ []));
88
+ this.#direction = injectComponentDirection();
89
+ this.#i18n = inject(MonaI18nService);
90
+ this.isRtl = computed(() => this.#direction() === "rtl", /* @ts-ignore */
91
+ ...(ngDevMode ? [{ debugName: "isRtl" }] : /* istanbul ignore next */ []));
92
+ this.formattedProgress = computed(() => {
93
+ return formatNumber(this.progress(), this.#i18n.localeId(), {
94
+ minimumFractionDigits: 0,
95
+ maximumFractionDigits: 2,
96
+ useGrouping: false
97
+ });
98
+ }, /* @ts-ignore */
99
+ ...(ngDevMode ? [{ debugName: "formattedProgress" }] : /* istanbul ignore next */ []));
87
100
  this.baseClasses = computed(() => {
88
101
  const rounded = this.rounded();
89
102
  const classes = progressBarBaseThemeVariants({ rounded });
@@ -103,7 +116,10 @@ class ProgressBarComponent {
103
116
  ...(ngDevMode ? [{ debugName: "labelTemplate" }] : /* istanbul ignore next */ []));
104
117
  this.nextTrackClipPath = computed(() => {
105
118
  const progress = this.progress();
106
- return `inset(-1px -1px -1px ${progress}%)`;
119
+ const isRtl = this.isRtl();
120
+ return isRtl
121
+ ? `inset(-1px ${progress}% -1px -1px)`
122
+ : `inset(-1px -1px -1px ${progress}%)`;
107
123
  }, /* @ts-ignore */
108
124
  ...(ngDevMode ? [{ debugName: "nextTrackClipPath" }] : /* istanbul ignore next */ []));
109
125
  this.prevTrackClipPath = computed(() => {
@@ -112,8 +128,11 @@ class ProgressBarComponent {
112
128
  if (indeterminate) {
113
129
  return `inset(-1px -1px -1px -1px)`;
114
130
  }
115
- const right = progress < 100 ? 8 : 0;
116
- return `inset(-1px ${right}px -1px 0px)`;
131
+ const offset = progress < 100 ? 8 : 0;
132
+ const isRtl = this.isRtl();
133
+ return isRtl
134
+ ? `inset(-1px 0px -1px ${offset}px)`
135
+ : `inset(-1px ${offset}px -1px 0px)`;
117
136
  }, /* @ts-ignore */
118
137
  ...(ngDevMode ? [{ debugName: "prevTrackClipPath" }] : /* istanbul ignore next */ []));
119
138
  this.progress = computed(() => getPercentage(this.value(), this.min(), this.max()), /* @ts-ignore */
@@ -127,6 +146,13 @@ class ProgressBarComponent {
127
146
  }, /* @ts-ignore */
128
147
  ...(ngDevMode ? [{ debugName: "trackClasses" }] : /* istanbul ignore next */ []));
129
148
  this.trackColor = this.#color;
149
+ /**
150
+ * @description Enables CSS transitions on fill and color changes.
151
+ * Set to `false` when updating `value` at high frequency (e.g., a real-time byte counter).
152
+ * @default true
153
+ */
154
+ this.animate = input(true, /* @ts-ignore */
155
+ ...(ngDevMode ? [{ debugName: "animate" }] : /* istanbul ignore next */ []));
130
156
  /**
131
157
  * @description Accessible label for the progress bar host element.
132
158
  * Use to describe what is being measured (e.g., "Upload progress").
@@ -142,13 +168,6 @@ class ProgressBarComponent {
142
168
  * @default ""
143
169
  */
144
170
  this.ariaValueText = input("", { ...(ngDevMode ? { debugName: "ariaValueText" } : /* istanbul ignore next */ {}), alias: "aria-valuetext" });
145
- /**
146
- * @description Enables CSS transitions on fill and color changes.
147
- * Set to `false` when updating `value` at high frequency (e.g., a real-time byte counter).
148
- * @default true
149
- */
150
- this.animate = input(true, /* @ts-ignore */
151
- ...(ngDevMode ? [{ debugName: "animate" }] : /* istanbul ignore next */ []));
152
171
  /**
153
172
  * @description Fill color of the progress track.
154
173
  * Pass a CSS color string, or a function that receives the current percentage (0–100) and returns a color string.
@@ -222,12 +241,14 @@ class ProgressBarComponent {
222
241
  ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
223
242
  }
224
243
  #color;
244
+ #direction;
245
+ #i18n;
225
246
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ProgressBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
226
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: ProgressBarComponent, isStandalone: true, selector: "mona-progress-bar", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaValueText: { classPropertyName: "ariaValueText", publicName: "aria-valuetext", isSignal: true, isRequired: false, transformFunction: null }, animate: { classPropertyName: "animate", publicName: "animate", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null }, labelPosition: { classPropertyName: "labelPosition", publicName: "labelPosition", isSignal: true, isRequired: false, transformFunction: null }, labelStyles: { classPropertyName: "labelStyles", publicName: "labelStyles", isSignal: true, isRequired: false, transformFunction: null }, labelVisible: { classPropertyName: "labelVisible", publicName: "labelVisible", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "progressbar" }, properties: { "class": "baseClasses()", "attr.aria-busy": "indeterminate() || null", "attr.aria-label": "ariaLabel() || null", "attr.aria-valuemin": "indeterminate() ? null : min()", "attr.aria-valuemax": "indeterminate() ? null : max()", "attr.aria-valuenow": "indeterminate() ? null : value()", "attr.aria-valuetext": "ariaValueText() || null", "attr.aria-disabled": "disabled() || null", "attr.data-disabled": "disabled()" } }, queries: [{ propertyName: "labelTemplate", first: true, predicate: ProgressBarLabelTemplateDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<div\n [class]=\"trackClasses()\"\n [style.background-color]=\"trackColor()\"\n [attr.data-prev]=\"true\"\n [attr.data-left]=\"labelPosition() === 'start'\"\n [attr.data-right]=\"labelPosition() === 'end'\"\n [attr.data-indeterminate]=\"indeterminate()\"\n [attr.data-value]=\"progress()\"\n [style.clip-path]=\"prevTrackClipPath()\">\n @if (indeterminate()) {\n <div [class]=\"indeterminateClasses()\" class=\"indeterminate\"></div>\n } @else if (labelVisible()) {\n @if (labelTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), min: min(), max: max(), percent: progress() }\">\n </ng-container>\n } @else {\n <span [class]=\"labelClasses()\" [style]=\"labelStyles()\">{{ progress() | number: \"1.0-2\" }}</span>\n }\n }\n</div>\n\n@if (!indeterminate()) {\n <div\n [class]=\"trackClasses()\"\n [attr.data-next]=\"true\"\n [attr.data-left]=\"labelPosition() === 'start'\"\n [attr.data-right]=\"labelPosition() === 'end'\"\n [style.clip-path]=\"nextTrackClipPath()\">\n @if (labelVisible()) {\n @if (labelTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), min: min(), max: max(), percent: progress() }\">\n </ng-container>\n } @else {\n <span [class]=\"labelClasses()\" [style]=\"labelStyles()\">{{ progress() | number: \"1.0-2\" }}</span>\n }\n }\n </div>\n}\n", styles: [".indeterminate{animation:indeterminate 16s linear infinite}@keyframes indeterminate{0%{background-position:0 0}to{background-position:100% 0}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: DecimalPipe, name: "number" }] }); }
247
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: ProgressBarComponent, isStandalone: true, selector: "mona-progress-bar", inputs: { animate: { classPropertyName: "animate", publicName: "animate", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaValueText: { classPropertyName: "ariaValueText", publicName: "aria-valuetext", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null }, labelPosition: { classPropertyName: "labelPosition", publicName: "labelPosition", isSignal: true, isRequired: false, transformFunction: null }, labelStyles: { classPropertyName: "labelStyles", publicName: "labelStyles", isSignal: true, isRequired: false, transformFunction: null }, labelVisible: { classPropertyName: "labelVisible", publicName: "labelVisible", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "progressbar" }, properties: { "class": "baseClasses()", "attr.aria-busy": "indeterminate() || null", "attr.aria-label": "ariaLabel() || null", "attr.aria-valuemin": "indeterminate() ? null : min()", "attr.aria-valuemax": "indeterminate() ? null : max()", "attr.aria-valuenow": "indeterminate() ? null : value()", "attr.aria-valuetext": "ariaValueText() || null", "attr.aria-disabled": "disabled() || null", "attr.data-disabled": "disabled()" } }, queries: [{ propertyName: "labelTemplate", first: true, predicate: ProgressBarLabelTemplateDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<div\n [class]=\"trackClasses()\"\n [style.background-color]=\"trackColor()\"\n [attr.data-prev]=\"true\"\n [attr.data-start]=\"labelPosition() === 'start'\"\n [attr.data-end]=\"labelPosition() === 'end'\"\n [attr.data-indeterminate]=\"indeterminate()\"\n [attr.data-value]=\"progress()\"\n [style.clip-path]=\"prevTrackClipPath()\">\n @if (indeterminate()) {\n <div [class]=\"indeterminateClasses()\" class=\"indeterminate\"></div>\n } @else if (labelVisible()) {\n @if (labelTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), min: min(), max: max(), percent: progress() }\">\n </ng-container>\n } @else {\n <span [class]=\"labelClasses()\" [style]=\"labelStyles()\">{{ formattedProgress() }}</span>\n }\n }\n</div>\n\n@if (!indeterminate()) {\n <div\n [class]=\"trackClasses()\"\n [attr.data-next]=\"true\"\n [attr.data-start]=\"labelPosition() === 'start'\"\n [attr.data-end]=\"labelPosition() === 'end'\"\n [style.clip-path]=\"nextTrackClipPath()\">\n @if (labelVisible()) {\n @if (labelTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), min: min(), max: max(), percent: progress() }\">\n </ng-container>\n } @else {\n <span [class]=\"labelClasses()\" [style]=\"labelStyles()\">{{ formattedProgress() }}</span>\n }\n }\n </div>\n}\n", styles: [".indeterminate{animation:indeterminate 16s linear infinite}@keyframes indeterminate{0%{background-position:0 0}to{background-position:100% 0}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
227
248
  }
228
249
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ProgressBarComponent, decorators: [{
229
250
  type: Component,
230
- args: [{ selector: "mona-progress-bar", imports: [DecimalPipe, NgTemplateOutlet], host: {
251
+ args: [{ selector: "mona-progress-bar", imports: [NgTemplateOutlet], host: {
231
252
  "[class]": "baseClasses()",
232
253
  "[attr.aria-busy]": "indeterminate() || null",
233
254
  "[attr.aria-label]": "ariaLabel() || null",
@@ -238,8 +259,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
238
259
  "[attr.aria-disabled]": "disabled() || null",
239
260
  "[attr.data-disabled]": "disabled()",
240
261
  role: "progressbar"
241
- }, template: "<div\n [class]=\"trackClasses()\"\n [style.background-color]=\"trackColor()\"\n [attr.data-prev]=\"true\"\n [attr.data-left]=\"labelPosition() === 'start'\"\n [attr.data-right]=\"labelPosition() === 'end'\"\n [attr.data-indeterminate]=\"indeterminate()\"\n [attr.data-value]=\"progress()\"\n [style.clip-path]=\"prevTrackClipPath()\">\n @if (indeterminate()) {\n <div [class]=\"indeterminateClasses()\" class=\"indeterminate\"></div>\n } @else if (labelVisible()) {\n @if (labelTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), min: min(), max: max(), percent: progress() }\">\n </ng-container>\n } @else {\n <span [class]=\"labelClasses()\" [style]=\"labelStyles()\">{{ progress() | number: \"1.0-2\" }}</span>\n }\n }\n</div>\n\n@if (!indeterminate()) {\n <div\n [class]=\"trackClasses()\"\n [attr.data-next]=\"true\"\n [attr.data-left]=\"labelPosition() === 'start'\"\n [attr.data-right]=\"labelPosition() === 'end'\"\n [style.clip-path]=\"nextTrackClipPath()\">\n @if (labelVisible()) {\n @if (labelTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), min: min(), max: max(), percent: progress() }\">\n </ng-container>\n } @else {\n <span [class]=\"labelClasses()\" [style]=\"labelStyles()\">{{ progress() | number: \"1.0-2\" }}</span>\n }\n }\n </div>\n}\n", styles: [".indeterminate{animation:indeterminate 16s linear infinite}@keyframes indeterminate{0%{background-position:0 0}to{background-position:100% 0}}\n"] }]
242
- }], propDecorators: { labelTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ProgressBarLabelTemplateDirective), { isSignal: true }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], ariaValueText: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-valuetext", required: false }] }], animate: [{ type: i0.Input, args: [{ isSignal: true, alias: "animate", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], labelPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelPosition", required: false }] }], labelStyles: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelStyles", required: false }] }], labelVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelVisible", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }] } });
262
+ }, template: "<div\n [class]=\"trackClasses()\"\n [style.background-color]=\"trackColor()\"\n [attr.data-prev]=\"true\"\n [attr.data-start]=\"labelPosition() === 'start'\"\n [attr.data-end]=\"labelPosition() === 'end'\"\n [attr.data-indeterminate]=\"indeterminate()\"\n [attr.data-value]=\"progress()\"\n [style.clip-path]=\"prevTrackClipPath()\">\n @if (indeterminate()) {\n <div [class]=\"indeterminateClasses()\" class=\"indeterminate\"></div>\n } @else if (labelVisible()) {\n @if (labelTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), min: min(), max: max(), percent: progress() }\">\n </ng-container>\n } @else {\n <span [class]=\"labelClasses()\" [style]=\"labelStyles()\">{{ formattedProgress() }}</span>\n }\n }\n</div>\n\n@if (!indeterminate()) {\n <div\n [class]=\"trackClasses()\"\n [attr.data-next]=\"true\"\n [attr.data-start]=\"labelPosition() === 'start'\"\n [attr.data-end]=\"labelPosition() === 'end'\"\n [style.clip-path]=\"nextTrackClipPath()\">\n @if (labelVisible()) {\n @if (labelTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"labelTemplate()?.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), min: min(), max: max(), percent: progress() }\">\n </ng-container>\n } @else {\n <span [class]=\"labelClasses()\" [style]=\"labelStyles()\">{{ formattedProgress() }}</span>\n }\n }\n </div>\n}\n", styles: [".indeterminate{animation:indeterminate 16s linear infinite}@keyframes indeterminate{0%{background-position:0 0}to{background-position:100% 0}}\n"] }]
263
+ }], propDecorators: { labelTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ProgressBarLabelTemplateDirective), { isSignal: true }] }], animate: [{ type: i0.Input, args: [{ isSignal: true, alias: "animate", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], ariaValueText: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-valuetext", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], labelPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelPosition", required: false }] }], labelStyles: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelStyles", required: false }] }], labelVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelVisible", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }] } });
243
264
 
244
265
  /*
245
266
  * Public API Surface of @nanahoshi/mona-ui/progress-bar
@@ -4,9 +4,15 @@ import { inject, TemplateRef, Directive, computed, viewChild, contentChild, sign
4
4
  import { LucideStar, LucideHeart, LucideFlame, LucideDiamond, LucideCircle, LucideDynamicIcon } from '@lucide/angular';
5
5
  import { createElementControlId } from '@nanahoshi/mona-ui/internal';
6
6
  import { range } from '@mirei/ts-collections';
7
+ import { injectComponentDirection, MonaI18nService } from '@nanahoshi/mona-ui/i18n';
7
8
  import { twMerge } from 'tailwind-merge';
8
9
  import { cva } from 'class-variance-authority';
9
10
 
11
+ const RATING_DEFAULT_MESSAGES = {
12
+ notRated: "Not rated",
13
+ valueText: (value, max) => `${value} out of ${max}`
14
+ };
15
+
10
16
  /**
11
17
  * @description Renders the pointer-preview visual for rating items. Overrides the default preset
12
18
  * overlay whenever the visible state comes from pointer preview.
@@ -15,7 +21,7 @@ class RatingHoveredItemTemplateDirective {
15
21
  constructor() {
16
22
  this.templateRef = inject(TemplateRef);
17
23
  }
18
- static ngTemplateContextGuard(_directive, context) {
24
+ static ngTemplateContextGuard(_directive, _context) {
19
25
  return true;
20
26
  }
21
27
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingHoveredItemTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
@@ -36,7 +42,7 @@ class RatingItemTemplateDirective {
36
42
  constructor() {
37
43
  this.templateRef = inject(TemplateRef);
38
44
  }
39
- static ngTemplateContextGuard(_directive, context) {
45
+ static ngTemplateContextGuard(_directive, _context) {
40
46
  return true;
41
47
  }
42
48
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingItemTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
@@ -57,7 +63,7 @@ class RatingSelectedItemTemplateDirective {
57
63
  constructor() {
58
64
  this.templateRef = inject(TemplateRef);
59
65
  }
60
- static ngTemplateContextGuard(_directive, context) {
66
+ static ngTemplateContextGuard(_directive, _context) {
61
67
  return true;
62
68
  }
63
69
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: RatingSelectedItemTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
@@ -263,6 +269,8 @@ const ratingIcons = {
263
269
  };
264
270
  class RatingComponent {
265
271
  constructor() {
272
+ this.#direction = injectComponentDirection();
273
+ this.#i18n = inject(MonaI18nService);
266
274
  this.activeState = computed(() => this.previewActive() ? "hovered" : "selected", /* @ts-ignore */
267
275
  ...(ngDevMode ? [{ debugName: "activeState" }] : /* istanbul ignore next */ []));
268
276
  this.containerClasses = computed(() => twMerge(ratingContainerThemeVariants(), this.userClass()), /* @ts-ignore */
@@ -288,7 +296,9 @@ class RatingComponent {
288
296
  if (custom) {
289
297
  return custom(this.normalizedValue(), this.itemsCount());
290
298
  }
291
- return this.normalizedValue() === 0 ? "Not rated" : `${this.normalizedValue()} out of ${this.itemsCount()}`;
299
+ return this.normalizedValue() === 0
300
+ ? this.messages().notRated
301
+ : this.messages().valueText(this.normalizedValue(), this.itemsCount());
292
302
  }, /* @ts-ignore */
293
303
  ...(ngDevMode ? [{ debugName: "effectiveAriaValueText" }] : /* istanbul ignore next */ []));
294
304
  this.effectiveTabIndex = computed(() => (this.disabled() ? -1 : this.tabindex()), /* @ts-ignore */
@@ -304,6 +314,8 @@ class RatingComponent {
304
314
  ...(ngDevMode ? [{ debugName: "interactionStep" }] : /* istanbul ignore next */ []));
305
315
  this.invalidState = computed(() => this.touched() && this.invalid(), /* @ts-ignore */
306
316
  ...(ngDevMode ? [{ debugName: "invalidState" }] : /* istanbul ignore next */ []));
317
+ this.isRtl = computed(() => this.#direction() === "rtl", /* @ts-ignore */
318
+ ...(ngDevMode ? [{ debugName: "isRtl" }] : /* istanbul ignore next */ []));
307
319
  this.itemClasses = computed(() => ratingItemThemeVariants({ size: this.size() }), /* @ts-ignore */
308
320
  ...(ngDevMode ? [{ debugName: "itemClasses" }] : /* istanbul ignore next */ []));
309
321
  this.itemTemplate = contentChild(RatingItemTemplateDirective, { ...(ngDevMode ? { debugName: "itemTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
@@ -314,6 +326,7 @@ class RatingComponent {
314
326
  this.labelClasses = computed(() => ratingLabelThemeVariants({ size: this.size() }), /* @ts-ignore */
315
327
  ...(ngDevMode ? [{ debugName: "labelClasses" }] : /* istanbul ignore next */ []));
316
328
  this.labelId = createElementControlId();
329
+ this.messages = this.#i18n.componentMessages("rating", RATING_DEFAULT_MESSAGES);
317
330
  this.normalizedValue = computed(() => normalizeRatingValue(this.value(), this.itemsCount(), this.precision()), /* @ts-ignore */
318
331
  ...(ngDevMode ? [{ debugName: "normalizedValue" }] : /* istanbul ignore next */ []));
319
332
  this.overlayClipClasses = computed(() => ratingOverlayClipThemeVariants(), /* @ts-ignore */
@@ -459,6 +472,8 @@ class RatingComponent {
459
472
  this.value = model(0, /* @ts-ignore */
460
473
  ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
461
474
  }
475
+ #direction;
476
+ #i18n;
462
477
  blur() {
463
478
  this.controlElement().nativeElement.blur();
464
479
  }
@@ -564,11 +579,14 @@ class RatingComponent {
564
579
  });
565
580
  }
566
581
  getKeyAction(key) {
582
+ const isRtl = this.isRtl();
583
+ const decreaseKey = isRtl ? "ArrowRight" : "ArrowLeft";
584
+ const increaseKey = isRtl ? "ArrowLeft" : "ArrowRight";
567
585
  switch (key) {
568
- case "ArrowRight":
586
+ case increaseKey:
569
587
  case "ArrowUp":
570
588
  return "increase";
571
- case "ArrowLeft":
589
+ case decreaseKey:
572
590
  case "ArrowDown":
573
591
  return "decrease";
574
592
  case "Home":
@@ -602,5 +620,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
602
620
  * Generated bundle index. Do not edit.
603
621
  */
604
622
 
605
- export { RatingComponent, RatingHoveredItemTemplateDirective, RatingItemTemplateDirective, RatingSelectedItemTemplateDirective };
623
+ export { RATING_DEFAULT_MESSAGES, RatingComponent, RatingHoveredItemTemplateDirective, RatingItemTemplateDirective, RatingSelectedItemTemplateDirective };
606
624
  //# sourceMappingURL=nanahoshi-mona-ui-rating.mjs.map