@memberjunction/ng-ui-components 6.2.0-edge.0 → 6.2.0-edge.1

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 (81) hide show
  1. package/README.md +35 -9
  2. package/dist/lib/a11y/named-control.base.d.ts +91 -0
  3. package/dist/lib/a11y/named-control.base.d.ts.map +1 -0
  4. package/dist/lib/a11y/named-control.base.js +121 -0
  5. package/dist/lib/a11y/named-control.base.js.map +1 -0
  6. package/dist/lib/a11y/unnamed-control-guard.d.ts +52 -0
  7. package/dist/lib/a11y/unnamed-control-guard.d.ts.map +1 -0
  8. package/dist/lib/a11y/unnamed-control-guard.js +94 -0
  9. package/dist/lib/a11y/unnamed-control-guard.js.map +1 -0
  10. package/dist/lib/accordion/accordion.component.d.ts +16 -4
  11. package/dist/lib/accordion/accordion.component.d.ts.map +1 -1
  12. package/dist/lib/accordion/accordion.component.js +36 -12
  13. package/dist/lib/accordion/accordion.component.js.map +1 -1
  14. package/dist/lib/applied-filters/applied-filters.component.js.map +1 -1
  15. package/dist/lib/button/button.directive.d.ts +34 -6
  16. package/dist/lib/button/button.directive.d.ts.map +1 -1
  17. package/dist/lib/button/button.directive.js +85 -25
  18. package/dist/lib/button/button.directive.js.map +1 -1
  19. package/dist/lib/card-grid/card-grid.component.d.ts +3 -1
  20. package/dist/lib/card-grid/card-grid.component.d.ts.map +1 -1
  21. package/dist/lib/card-grid/card-grid.component.js +13 -9
  22. package/dist/lib/card-grid/card-grid.component.js.map +1 -1
  23. package/dist/lib/clickable/clickable.directive.d.ts +11 -3
  24. package/dist/lib/clickable/clickable.directive.d.ts.map +1 -1
  25. package/dist/lib/clickable/clickable.directive.js +25 -5
  26. package/dist/lib/clickable/clickable.directive.js.map +1 -1
  27. package/dist/lib/combobox/combobox.component.d.ts +44 -3
  28. package/dist/lib/combobox/combobox.component.d.ts.map +1 -1
  29. package/dist/lib/combobox/combobox.component.js +135 -51
  30. package/dist/lib/combobox/combobox.component.js.map +1 -1
  31. package/dist/lib/confirm-dialog/confirm-dialog.component.d.ts +6 -0
  32. package/dist/lib/confirm-dialog/confirm-dialog.component.d.ts.map +1 -1
  33. package/dist/lib/confirm-dialog/confirm-dialog.component.js +16 -4
  34. package/dist/lib/confirm-dialog/confirm-dialog.component.js.map +1 -1
  35. package/dist/lib/datepicker/datepicker.component.d.ts +25 -2
  36. package/dist/lib/datepicker/datepicker.component.d.ts.map +1 -1
  37. package/dist/lib/datepicker/datepicker.component.js +98 -42
  38. package/dist/lib/datepicker/datepicker.component.js.map +1 -1
  39. package/dist/lib/dialog/dialog.component.d.ts +4 -0
  40. package/dist/lib/dialog/dialog.component.d.ts.map +1 -1
  41. package/dist/lib/dialog/dialog.component.js +12 -4
  42. package/dist/lib/dialog/dialog.component.js.map +1 -1
  43. package/dist/lib/dialog/dialog.service.js.map +1 -1
  44. package/dist/lib/dropdown/dropdown.component.d.ts +19 -44
  45. package/dist/lib/dropdown/dropdown.component.d.ts.map +1 -1
  46. package/dist/lib/dropdown/dropdown.component.js +37 -76
  47. package/dist/lib/dropdown/dropdown.component.js.map +1 -1
  48. package/dist/lib/dropdown/dropdown.scss +0 -16
  49. package/dist/lib/filter-panel/filter-panel.component.d.ts +8 -0
  50. package/dist/lib/filter-panel/filter-panel.component.d.ts.map +1 -1
  51. package/dist/lib/filter-panel/filter-panel.component.js +25 -9
  52. package/dist/lib/filter-panel/filter-panel.component.js.map +1 -1
  53. package/dist/lib/numeric-input/numeric-input.component.d.ts +15 -1
  54. package/dist/lib/numeric-input/numeric-input.component.d.ts.map +1 -1
  55. package/dist/lib/numeric-input/numeric-input.component.js +36 -9
  56. package/dist/lib/numeric-input/numeric-input.component.js.map +1 -1
  57. package/dist/lib/page-search/page-search.component.d.ts +32 -3
  58. package/dist/lib/page-search/page-search.component.d.ts.map +1 -1
  59. package/dist/lib/page-search/page-search.component.js +68 -12
  60. package/dist/lib/page-search/page-search.component.js.map +1 -1
  61. package/dist/lib/switch/switch.component.d.ts +22 -1
  62. package/dist/lib/switch/switch.component.d.ts.map +1 -1
  63. package/dist/lib/switch/switch.component.js +50 -16
  64. package/dist/lib/switch/switch.component.js.map +1 -1
  65. package/dist/lib/tabs/tab-chrome-guard.d.ts +2 -0
  66. package/dist/lib/tabs/tab-chrome-guard.d.ts.map +1 -1
  67. package/dist/lib/tabs/tab-chrome-guard.js +5 -1
  68. package/dist/lib/tabs/tab-chrome-guard.js.map +1 -1
  69. package/dist/lib/window/window.component.d.ts +10 -0
  70. package/dist/lib/window/window.component.d.ts.map +1 -1
  71. package/dist/lib/window/window.component.js +27 -7
  72. package/dist/lib/window/window.component.js.map +1 -1
  73. package/dist/lib/workspace-tabs/workspace-tab-strip.component.d.ts +10 -0
  74. package/dist/lib/workspace-tabs/workspace-tab-strip.component.d.ts.map +1 -1
  75. package/dist/lib/workspace-tabs/workspace-tab-strip.component.js +27 -7
  76. package/dist/lib/workspace-tabs/workspace-tab-strip.component.js.map +1 -1
  77. package/dist/public-api.d.ts +2 -0
  78. package/dist/public-api.d.ts.map +1 -1
  79. package/dist/public-api.js +2 -0
  80. package/dist/public-api.js.map +1 -1
  81. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"confirm-dialog.component.js","sourceRoot":"","sources":["../../../src/lib/confirm-dialog/confirm-dialog.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, Output, booleanAttribute } from '@angular/core';\nimport { MJDialogComponent, MJDialogActionsComponent } from '../dialog/dialog.component';\nimport { MJButtonDirective } from '../button/button.directive';\n\n/**\n * Visual intent of an `<mj-confirm-dialog>`. Drives the header icon and the\n * confirm button's color, so callers rarely restate either.\n *\n * - `default` — a neutral question (e.g. \"Discard unsaved changes?\"). Blue confirm button.\n * - `danger` — a destructive / irreversible action (delete). Red confirm button.\n * - `warning` — a non-destructive but consequential action. Blue confirm button, caution icon.\n * - `info` — an informational confirmation. Blue confirm button, info icon.\n */\nexport type MJConfirmDialogType = 'default' | 'danger' | 'warning' | 'info';\n\nconst DEFAULT_ICONS: Record<MJConfirmDialogType, string> = {\n default: 'fa-solid fa-circle-question',\n danger: 'fa-solid fa-triangle-exclamation',\n warning: 'fa-solid fa-triangle-exclamation',\n info: 'fa-solid fa-circle-info',\n};\n\n/**\n * mj-confirm-dialog — Canonical confirmation prompt. The shared replacement for\n * native `window.confirm()` and the many hand-rolled \"Are you sure?\" modals\n * (`@if (showDeleteConfirm) { … backdrop + centered dialog }`) scattered across\n * the app, plus the duplicate local `mj-confirm-dialog` / `mj-ev-confirm-dialog`\n * components.\n *\n * Built on `<mj-dialog>` (so it inherits the backdrop, animations, mobile\n * full-screen behavior, and Esc/backdrop handling) and uses `role=\"alertdialog\"`\n * for screen readers. Buttons follow the MJ convention: the affirmative action\n * is **leftmost**, Cancel on the right.\n *\n * Visibility is two-way bindable. Cancelling (Cancel button, backdrop, Esc, or\n * the ✕) auto-closes and emits `Cancelled`. Confirming emits `Confirmed` and\n * **leaves the dialog open** so the handler can run async work — set `Visible`\n * to `false` (or update your bound property) when done. Bind `[Processing]` to a\n * loading flag during that async work to show a spinner, disable both buttons,\n * and block dismissal until it completes.\n *\n * Usage:\n * ```html\n * <!-- Simple destructive confirm -->\n * <mj-confirm-dialog\n * [(Visible)]=\"showDeleteConfirm\"\n * Type=\"danger\"\n * Title=\"Delete view\"\n * Message=\"Are you sure you want to delete this view?\"\n * DetailMessage=\"This action cannot be undone.\"\n * ConfirmText=\"Delete\"\n * (Confirmed)=\"onDeleteConfirmed()\">\n * </mj-confirm-dialog>\n *\n * <!-- Async confirm with a spinner while the work runs -->\n * <mj-confirm-dialog\n * [(Visible)]=\"confirmOpen\"\n * [Processing]=\"isDeleting\"\n * Type=\"danger\" Title=\"Delete user\" Message=\"Remove this user permanently?\"\n * ConfirmText=\"Delete\" (Confirmed)=\"deleteUser()\">\n * </mj-confirm-dialog>\n * ```\n */\n@Component({\n selector: 'mj-confirm-dialog',\n standalone: true,\n imports: [MJDialogComponent, MJDialogActionsComponent, MJButtonDirective],\n template: `\n <mj-dialog\n [Visible]=\"Visible\"\n [Title]=\"Title\"\n Size=\"sm\"\n Role=\"alertdialog\"\n [Closeable]=\"!Processing\"\n (Close)=\"onDismiss()\">\n\n <div class=\"mj-confirm\">\n @if (ResolvedIcon) {\n <i class=\"mj-confirm__icon mj-confirm__icon--{{ Type }} {{ ResolvedIcon }}\" aria-hidden=\"true\"></i>\n }\n <div class=\"mj-confirm__body\">\n @if (Message) {\n <p class=\"mj-confirm__message\">{{ Message }}</p>\n }\n @if (DetailMessage) {\n <p class=\"mj-confirm__detail\">{{ DetailMessage }}</p>\n }\n <ng-content></ng-content>\n </div>\n </div>\n\n <mj-dialog-actions>\n <button\n mjButton\n [variant]=\"ConfirmVariant\"\n [disabled]=\"Processing\"\n (click)=\"onConfirm()\">\n @if (Processing) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n }\n {{ ConfirmText }}\n </button>\n <button\n mjButton\n variant=\"secondary\"\n [disabled]=\"Processing\"\n (click)=\"onCancel()\">\n {{ CancelText }}\n </button>\n </mj-dialog-actions>\n </mj-dialog>\n `,\n styles: [`\n .mj-confirm {\n display: flex;\n align-items: flex-start;\n gap: var(--mj-space-3);\n }\n .mj-confirm__icon {\n flex-shrink: 0;\n font-size: 1.5rem;\n margin-top: 0.05em;\n color: var(--mj-text-muted);\n }\n .mj-confirm__icon--danger { color: var(--mj-status-error); }\n .mj-confirm__icon--warning { color: var(--mj-status-warning); }\n .mj-confirm__icon--info { color: var(--mj-status-info); }\n\n .mj-confirm__body { flex: 1; min-width: 0; }\n .mj-confirm__message {\n margin: 0;\n color: var(--mj-text-primary);\n line-height: 1.5;\n }\n .mj-confirm__detail {\n margin: var(--mj-space-2) 0 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n line-height: 1.45;\n }\n `]\n})\nexport class MJConfirmDialogComponent {\n /** Whether the dialog is shown. Two-way bindable: `[(Visible)]`. */\n @Input() Visible = false;\n /** Two-way `Visible` change channel — fires when the dialog auto-closes on cancel. */\n @Output() VisibleChange = new EventEmitter<boolean>();\n\n /** Heading shown in the dialog title bar. */\n @Input() Title = 'Confirm';\n\n /** Primary prompt text. For rich content, project default `<ng-content>` instead. */\n @Input() Message = 'Are you sure?';\n\n /** Optional secondary line, rendered smaller/muted beneath the message. */\n @Input() DetailMessage = '';\n\n /** Visual intent — drives the header icon + confirm button color. Defaults to 'default'. */\n @Input() Type: MJConfirmDialogType = 'default';\n\n /** Affirmative button label. */\n @Input() ConfirmText = 'Confirm';\n\n /** Dismiss button label. */\n @Input() CancelText = 'Cancel';\n\n /**\n * Font Awesome icon class (e.g. \"fa-solid fa-trash\") for the header. When\n * omitted, a sensible default is chosen from `Type`. Set to `''` for no icon.\n */\n @Input() Icon: string | null = null;\n\n /**\n * When true, shows a spinner on the confirm button, disables both buttons, and\n * blocks dismissal (Esc / backdrop / ✕) — bind this to your loading flag while\n * the `Confirmed` handler runs async work.\n */\n @Input({ transform: booleanAttribute }) Processing = false;\n\n /** Fired when the user confirms. The dialog stays open; close it when ready. */\n @Output() Confirmed = new EventEmitter<void>();\n\n /** Fired when the user cancels (button, backdrop, Esc, or ✕). The dialog auto-closes. */\n @Output() Cancelled = new EventEmitter<void>();\n\n /** mjButton variant for the confirm button — red for `danger`, blue otherwise. */\n get ConfirmVariant(): 'primary' | 'danger' {\n return this.Type === 'danger' ? 'danger' : 'primary';\n }\n\n /**\n * Icon actually rendered: the explicit `Icon` when provided (including `\"\"`\n * to suppress it), otherwise the per-type default.\n */\n get ResolvedIcon(): string {\n if (this.Icon != null) {\n return this.Icon;\n }\n return DEFAULT_ICONS[this.Type] ?? DEFAULT_ICONS.default;\n }\n\n onConfirm(): void {\n this.Confirmed.emit();\n }\n\n onCancel(): void {\n this.close();\n this.Cancelled.emit();\n }\n\n /** Backdrop / Esc / ✕ from the underlying dialog — ignored while Processing. */\n onDismiss(): void {\n if (this.Processing) {\n return;\n }\n this.onCancel();\n }\n\n private close(): void {\n this.Visible = false;\n this.VisibleChange.emit(false);\n }\n}\n"]}
1
+ {"version":3,"file":"confirm-dialog.component.js","sourceRoot":"","sources":["../../../src/lib/confirm-dialog/confirm-dialog.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, Output, booleanAttribute } from '@angular/core';\nimport { MJDialogComponent, MJDialogActionsComponent } from '../dialog/dialog.component';\nimport { MJButtonDirective } from '../button/button.directive';\n\n/**\n * Visual intent of an `<mj-confirm-dialog>`. Drives the header icon and the\n * confirm button's color, so callers rarely restate either.\n *\n * - `default` — a neutral question (e.g. \"Discard unsaved changes?\"). Blue confirm button.\n * - `danger` — a destructive / irreversible action (delete). Red confirm button.\n * - `warning` — a non-destructive but consequential action. Blue confirm button, caution icon.\n * - `info` — an informational confirmation. Blue confirm button, info icon.\n */\nexport type MJConfirmDialogType = 'default' | 'danger' | 'warning' | 'info';\n\nconst DEFAULT_ICONS: Record<MJConfirmDialogType, string> = {\n default: 'fa-solid fa-circle-question',\n danger: 'fa-solid fa-triangle-exclamation',\n warning: 'fa-solid fa-triangle-exclamation',\n info: 'fa-solid fa-circle-info',\n};\n\n/**\n * mj-confirm-dialog — Canonical confirmation prompt. The shared replacement for\n * native `window.confirm()` and the many hand-rolled \"Are you sure?\" modals\n * (`@if (showDeleteConfirm) { … backdrop + centered dialog }`) scattered across\n * the app, plus the duplicate local `mj-confirm-dialog` / `mj-ev-confirm-dialog`\n * components.\n *\n * Built on `<mj-dialog>` (so it inherits the backdrop, animations, mobile\n * full-screen behavior, and Esc/backdrop handling) and uses `role=\"alertdialog\"`\n * for screen readers. Buttons follow the MJ convention: the affirmative action\n * is **leftmost**, Cancel on the right.\n *\n * Visibility is two-way bindable. Cancelling (Cancel button, backdrop, Esc, or\n * the ✕) auto-closes and emits `Cancelled`. Confirming emits `Confirmed` and\n * **leaves the dialog open** so the handler can run async work — set `Visible`\n * to `false` (or update your bound property) when done. Bind `[Processing]` to a\n * loading flag during that async work to show a spinner, disable both buttons,\n * and block dismissal until it completes.\n *\n * Usage:\n * ```html\n * <!-- Simple destructive confirm -->\n * <mj-confirm-dialog\n * [(Visible)]=\"showDeleteConfirm\"\n * Type=\"danger\"\n * Title=\"Delete view\"\n * Message=\"Are you sure you want to delete this view?\"\n * DetailMessage=\"This action cannot be undone.\"\n * ConfirmText=\"Delete\"\n * (Confirmed)=\"onDeleteConfirmed()\">\n * </mj-confirm-dialog>\n *\n * <!-- Async confirm with a spinner while the work runs -->\n * <mj-confirm-dialog\n * [(Visible)]=\"confirmOpen\"\n * [Processing]=\"isDeleting\"\n * Type=\"danger\" Title=\"Delete user\" Message=\"Remove this user permanently?\"\n * ConfirmText=\"Delete\" (Confirmed)=\"deleteUser()\">\n * </mj-confirm-dialog>\n * ```\n */\n@Component({\n selector: 'mj-confirm-dialog',\n standalone: true,\n imports: [MJDialogComponent, MJDialogActionsComponent, MJButtonDirective],\n template: `\n <mj-dialog\n [Visible]=\"Visible\"\n [Title]=\"Title\"\n Size=\"sm\"\n Role=\"alertdialog\"\n [Closeable]=\"!Processing\"\n (Close)=\"onDismiss()\">\n\n <div class=\"mj-confirm\">\n @if (ResolvedIcon) {\n <i class=\"mj-confirm__icon mj-confirm__icon--{{ Type }} {{ ResolvedIcon }}\" aria-hidden=\"true\"></i>\n }\n <div class=\"mj-confirm__body\">\n @if (Message) {\n <p class=\"mj-confirm__message\">{{ Message }}</p>\n }\n @if (DetailMessage) {\n <p class=\"mj-confirm__detail\">{{ DetailMessage }}</p>\n }\n <ng-content></ng-content>\n </div>\n </div>\n\n <mj-dialog-actions>\n <button\n mjButton\n [variant]=\"ConfirmVariant\"\n [disabled]=\"Processing\"\n (click)=\"onConfirm()\">\n @if (Processing) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n }\n {{ ConfirmText }}\n </button>\n <button\n mjButton\n variant=\"secondary\"\n [disabled]=\"Processing\"\n (click)=\"onCancel()\">\n {{ CancelText }}\n </button>\n </mj-dialog-actions>\n </mj-dialog>\n `,\n styles: [`\n .mj-confirm {\n display: flex;\n align-items: flex-start;\n gap: var(--mj-space-3);\n }\n .mj-confirm__icon {\n flex-shrink: 0;\n font-size: 1.5rem;\n margin-top: 0.05em;\n color: var(--mj-text-muted);\n }\n .mj-confirm__icon--danger { color: var(--mj-status-error); }\n .mj-confirm__icon--warning { color: var(--mj-status-warning); }\n .mj-confirm__icon--info { color: var(--mj-status-info); }\n\n .mj-confirm__body { flex: 1; min-width: 0; }\n .mj-confirm__message {\n margin: 0;\n color: var(--mj-text-primary);\n line-height: 1.5;\n }\n .mj-confirm__detail {\n margin: var(--mj-space-2) 0 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n line-height: 1.45;\n }\n `]\n})\nexport class MJConfirmDialogComponent {\n /** Whether the dialog is shown. Two-way bindable: `[(Visible)]`. */\n @Input() Visible = false;\n /** Two-way `Visible` change channel — fires when the dialog auto-closes on cancel. */\n @Output() VisibleChange = new EventEmitter<boolean>();\n\n /** Heading shown in the dialog title bar. */\n @Input() Title = 'Confirm';\n\n /** Primary prompt text. For rich content, project default `<ng-content>` instead. */\n @Input() Message = 'Are you sure?';\n\n /** Optional secondary line, rendered smaller/muted beneath the message. */\n @Input() DetailMessage = '';\n\n /** Visual intent — drives the header icon + confirm button color. Defaults to 'default'. */\n @Input() Type: MJConfirmDialogType = 'default';\n\n /** Affirmative button label. */\n @Input() ConfirmText = 'Confirm';\n\n /** Dismiss button label. */\n @Input() CancelText = 'Cancel';\n\n /**\n * Font Awesome icon class (e.g. \"fa-solid fa-trash\") for the header. When\n * omitted, a sensible default is chosen from `Type`. Set to `''` for no icon.\n */\n @Input() Icon: string | null = null;\n\n /**\n * When true, shows a spinner on the confirm button, disables both buttons, and\n * blocks dismissal (Esc / backdrop / ✕) — bind this to your loading flag while\n * the `Confirmed` handler runs async work.\n */\n @Input({ transform: booleanAttribute }) Processing = false;\n\n /** Fired when the user confirms. The dialog stays open; close it when ready. */\n @Output() Confirmed = new EventEmitter<void>();\n\n /** Fired when the user cancels (button, backdrop, Esc, or ✕). The dialog auto-closes. */\n @Output() Cancelled = new EventEmitter<void>();\n\n /** mjButton variant for the confirm button — red for `danger`, blue otherwise. */\n get ConfirmVariant(): 'primary' | 'danger' {\n return this.Type === 'danger' ? 'danger' : 'primary';\n }\n\n /**\n * Icon actually rendered: the explicit `Icon` when provided (including `\"\"`\n * to suppress it), otherwise the per-type default.\n */\n get ResolvedIcon(): string {\n if (this.Icon != null) {\n return this.Icon;\n }\n return DEFAULT_ICONS[this.Type] ?? DEFAULT_ICONS.default;\n }\n\n OnConfirm(): void {\n this.Confirmed.emit();\n }\n\n /** @deprecated Use {@link OnConfirm}. */\n onConfirm(): void {\n return this.OnConfirm();\n }\n\n OnCancel(): void {\n this.close();\n this.Cancelled.emit();\n }\n\n /** @deprecated Use {@link OnCancel}. */\n onCancel(): void {\n return this.OnCancel();\n }\n\n /** Backdrop / Esc / ✕ from the underlying dialog — ignored while Processing. */\n OnDismiss(): void {\n if (this.Processing) {\n return;\n }\n this.OnCancel();\n }\n\n /** @deprecated Use {@link OnDismiss}. */\n onDismiss(): void {\n return this.OnDismiss();\n }\n\n private close(): void {\n this.Visible = false;\n this.VisibleChange.emit(false);\n }\n}\n"]}
@@ -1,12 +1,25 @@
1
- import { EventEmitter, OnDestroy } from '@angular/core';
1
+ import { AfterViewInit, EventEmitter, OnDestroy } from '@angular/core';
2
2
  import { ControlValueAccessor } from '@angular/forms';
3
3
  import { ConnectedPosition } from '@angular/cdk/overlay';
4
4
  import { CalendarDay } from '../calendar/calendar-utils';
5
+ import { MJNamedControlBase } from '../a11y/named-control.base';
5
6
  import * as i0 from "@angular/core";
6
7
  /**
7
8
  * mj-datepicker — Date picker with calendar popup. Replaces `<kendo-datepicker>`.
9
+ *
10
+ * Without an accessible name the date field announces as "edit, blank" and its calendar popup as a
11
+ * generic "Calendar" — so a form with a start date and an end date presents two identical grids
12
+ * (WCAG 2.1 4.1.2). Use {@link MJNamedControlBase.AriaLabelledBy} when a visible label exists,
13
+ * {@link MJNamedControlBase.AriaLabel} when none does; the toggle button and the calendar take
14
+ * their names from the same source. The field is a real `<input>`, so
15
+ * {@link MJNamedControlBase.InputId} IS a valid `<label for>` target.
16
+ *
17
+ * @example
18
+ * ```html
19
+ * <mj-datepicker AriaLabel="Due date" [(ngModel)]="dueDate" [Min]="minDate" />
20
+ * ```
8
21
  */
9
- export declare class MJDatepickerComponent implements ControlValueAccessor, OnDestroy {
22
+ export declare class MJDatepickerComponent extends MJNamedControlBase implements ControlValueAccessor, AfterViewInit, OnDestroy {
10
23
  Min: Date | null;
11
24
  Max: Date | null;
12
25
  Format: string;
@@ -21,6 +34,7 @@ export declare class MJDatepickerComponent implements ControlValueAccessor, OnDe
21
34
  get Disabled(): boolean;
22
35
  ValueChange: EventEmitter<Date | null>;
23
36
  private triggerEl;
37
+ private dateInputEl;
24
38
  readonly hostClass = true;
25
39
  private cdr;
26
40
  IsOpen: boolean;
@@ -34,6 +48,15 @@ export declare class MJDatepickerComponent implements ControlValueAccessor, OnDe
34
48
  private onChange;
35
49
  private onTouched;
36
50
  get MonthYearLabel(): string;
51
+ /** `aria-labelledby` id list for the toggle button when a VISIBLE label names the field. */
52
+ get ToggleLabelledBy(): string;
53
+ /** `aria-label` for the toggle button in the no-visible-label case. */
54
+ get ToggleLabel(): string;
55
+ /** `aria-labelledby` id list for the calendar grid when a VISIBLE label names the field. */
56
+ get CalendarLabelledBy(): string;
57
+ /** `aria-label` for the calendar grid in the no-visible-label case. */
58
+ get CalendarLabel(): string;
59
+ ngAfterViewInit(): void;
37
60
  Toggle(): void;
38
61
  Open(): void;
39
62
  Close(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"datepicker.component.d.ts","sourceRoot":"","sources":["../../../src/lib/datepicker/datepicker.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAkD,SAAS,EAA6B,MAAM,eAAe,CAAC;AAC7J,OAAO,EAAqB,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAiB,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAgE,MAAM,4BAA4B,CAAC;;AAEvH;;GAEG;AACH,qBAkDa,qBAAsB,YAAW,oBAAoB,EAAE,SAAS;IAClE,GAAG,EAAE,IAAI,GAAG,IAAI,CAAQ;IACxB,GAAG,EAAE,IAAI,GAAG,IAAI,CAAQ;IACxB,MAAM,SAAgB;IACtB,WAAW,SAAM;IAC1B;;;;;OAKG;IACH,IACI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAsD;IACjF,IAAI,QAAQ,IAAI,OAAO,CAA+B;IAC5C,WAAW,4BAAmC;IAClC,OAAO,CAAC,SAAS,CAA2B;IACzB,QAAQ,CAAC,SAAS,QAAQ;IACnE,OAAO,CAAC,GAAG,CAA6B;IAExC,MAAM,UAAS;IAAC,UAAU,UAAS;IAAC,YAAY,SAAM;IACtD,KAAK,EAAE,WAAW,EAAE,EAAE,CAAM;IAAC,QAAQ,WAAa;IAClD,SAAS,EAAE,iBAAiB,EAAE,CAG5B;IACF,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAA0C;IAC1D,OAAO,CAAC,SAAS,CAAwB;IAEzC,IAAI,cAAc,IAAI,MAAM,CAA6C;IAEzE,MAAM,IAAI,IAAI;IACd,IAAI,IAAI,IAAI;IAKZ,KAAK,IAAI,IAAI;IAEb,8CAA8C;IAC9C,OAAO,CAAC,aAAa,CAAS;IAC9B,4FAA4F;IAC5F,OAAO,CAAC,YAAY,CAAS;IAE7B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,YAAY;IAOpB,aAAa,IAAI,IAAI;IACrB,SAAS,IAAI,IAAI;IAEjB,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI;IAKlC,WAAW,IAAI,IAAI;IAKnB,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO;IAIxC,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO;IAKvC,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAKjC,MAAM,IAAI,IAAI;IACd,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAIrC,UAAU,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI;IAI7C,gBAAgB,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI;IACxD,iBAAiB,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI;IACvC,gBAAgB,CAAC,UAAU,EAAE,OAAO,GAAG,IAAI;IAC3C,WAAW,IAAI,IAAI;yCAvGR,qBAAqB;2CAArB,qBAAqB;CAwGjC"}
1
+ {"version":3,"file":"datepicker.component.d.ts","sourceRoot":"","sources":["../../../src/lib/datepicker/datepicker.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA4B,YAAY,EAAkD,SAAS,EAA6B,MAAM,eAAe,CAAC;AAC5K,OAAO,EAAqB,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAiB,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAgE,MAAM,4BAA4B,CAAC;AACvH,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;;AAGhE;;;;;;;;;;;;;;GAcG;AACH,qBA4Fa,qBAAsB,SAAQ,kBAAmB,YAAW,oBAAoB,EAAE,aAAa,EAAE,SAAS;IAC5G,GAAG,EAAE,IAAI,GAAG,IAAI,CAAQ;IACxB,GAAG,EAAE,IAAI,GAAG,IAAI,CAAQ;IACxB,MAAM,SAAgB;IACtB,WAAW,SAAM;IAC1B;;;;;OAKG;IACH,IACI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAsD;IACjF,IAAI,QAAQ,IAAI,OAAO,CAA+B;IAC5C,WAAW,4BAAmC;IAClC,OAAO,CAAC,SAAS,CAA2B;IAC1C,OAAO,CAAC,WAAW,CAA2C;IAC7C,QAAQ,CAAC,SAAS,QAAQ;IACnE,OAAO,CAAC,GAAG,CAA6B;IAExC,MAAM,UAAS;IAAC,UAAU,UAAS;IAAC,YAAY,SAAM;IACtD,KAAK,EAAE,WAAW,EAAE,EAAE,CAAM;IAAC,QAAQ,WAAa;IAClD,SAAS,EAAE,iBAAiB,EAAE,CAG5B;IACF,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAA0C;IAC1D,OAAO,CAAC,SAAS,CAAwB;IAEzC,IAAI,cAAc,IAAI,MAAM,CAA6C;IAEzE,4FAA4F;IAC5F,IAAI,gBAAgB,IAAI,MAAM,CAAoD;IAElF,uEAAuE;IACvE,IAAI,WAAW,IAAI,MAAM,CAAsE;IAE/F,4FAA4F;IAC5F,IAAI,kBAAkB,IAAI,MAAM,CAAsD;IAEtF,uEAAuE;IACvE,IAAI,aAAa,IAAI,MAAM,CAA4D;IAEvF,eAAe,IAAI,IAAI;IAEvB,MAAM,IAAI,IAAI;IACd,IAAI,IAAI,IAAI;IAKZ,KAAK,IAAI,IAAI;IAEb,8CAA8C;IAC9C,OAAO,CAAC,aAAa,CAAS;IAC9B,4FAA4F;IAC5F,OAAO,CAAC,YAAY,CAAS;IAE7B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,YAAY;IAOpB,aAAa,IAAI,IAAI;IACrB,SAAS,IAAI,IAAI;IAEjB,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI;IAKlC,WAAW,IAAI,IAAI;IAKnB,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO;IAIxC,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO;IAKvC,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAKjC,MAAM,IAAI,IAAI;IACd,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAIrC,UAAU,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI;IAI7C,gBAAgB,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI;IACxD,iBAAiB,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI;IACvC,gBAAgB,CAAC,UAAU,EAAE,OAAO,GAAG,IAAI;IAC3C,WAAW,IAAI,IAAI;yCAtHR,qBAAqB;2CAArB,qBAAqB;CAuHjC"}
@@ -2,12 +2,15 @@ import { Component, Input, Output, EventEmitter, forwardRef, HostBinding, ViewCh
2
2
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
3
3
  import { OverlayModule } from '@angular/cdk/overlay';
4
4
  import { WEEK_DAYS, BuildCalendarWeeks, FormatDate, GetMonthYearLabel } from '../calendar/calendar-utils';
5
+ import { MJNamedControlBase } from '../a11y/named-control.base';
6
+ import { WarnIfUnnamed } from '../a11y/unnamed-control-guard';
5
7
  import * as i0 from "@angular/core";
6
8
  import * as i1 from "@angular/cdk/overlay";
7
9
  const _c0 = ["trigger"];
10
+ const _c1 = ["dateInput"];
8
11
  const _forTrack0 = ($index, $item) => $item.date.getTime();
9
- function MJDatepickerComponent_ng_template_7_For_10_Template(rf, ctx) { if (rf & 1) {
10
- i0.ɵɵelementStart(0, "span", 15);
12
+ function MJDatepickerComponent_ng_template_11_For_10_Template(rf, ctx) { if (rf & 1) {
13
+ i0.ɵɵelementStart(0, "span", 16);
11
14
  i0.ɵɵtext(1);
12
15
  i0.ɵɵelementEnd();
13
16
  } if (rf & 2) {
@@ -15,10 +18,10 @@ function MJDatepickerComponent_ng_template_7_For_10_Template(rf, ctx) { if (rf &
15
18
  i0.ɵɵadvance();
16
19
  i0.ɵɵtextInterpolate(day_r3);
17
20
  } }
18
- function MJDatepickerComponent_ng_template_7_For_12_For_2_Template(rf, ctx) { if (rf & 1) {
21
+ function MJDatepickerComponent_ng_template_11_For_12_For_2_Template(rf, ctx) { if (rf & 1) {
19
22
  const _r4 = i0.ɵɵgetCurrentView();
20
- i0.ɵɵelementStart(0, "button", 20);
21
- i0.ɵɵlistener("click", function MJDatepickerComponent_ng_template_7_For_12_For_2_Template_button_click_0_listener() { const day_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.SelectDate(day_r5)); });
23
+ i0.ɵɵelementStart(0, "button", 21);
24
+ i0.ɵɵlistener("click", function MJDatepickerComponent_ng_template_11_For_12_For_2_Template_button_click_0_listener() { const day_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.SelectDate(day_r5)); });
22
25
  i0.ɵɵtext(1);
23
26
  i0.ɵɵelementEnd();
24
27
  } if (rf & 2) {
@@ -30,38 +33,39 @@ function MJDatepickerComponent_ng_template_7_For_12_For_2_Template(rf, ctx) { if
30
33
  i0.ɵɵadvance();
31
34
  i0.ɵɵtextInterpolate(day_r5.dayNumber);
32
35
  } }
33
- function MJDatepickerComponent_ng_template_7_For_12_Template(rf, ctx) { if (rf & 1) {
34
- i0.ɵɵelementStart(0, "div", 16);
35
- i0.ɵɵrepeaterCreate(1, MJDatepickerComponent_ng_template_7_For_12_For_2_Template, 2, 9, "button", 19, _forTrack0);
36
+ function MJDatepickerComponent_ng_template_11_For_12_Template(rf, ctx) { if (rf & 1) {
37
+ i0.ɵɵelementStart(0, "div", 17);
38
+ i0.ɵɵrepeaterCreate(1, MJDatepickerComponent_ng_template_11_For_12_For_2_Template, 2, 9, "button", 20, _forTrack0);
36
39
  i0.ɵɵelementEnd();
37
40
  } if (rf & 2) {
38
41
  const week_r6 = ctx.$implicit;
39
42
  i0.ɵɵadvance();
40
43
  i0.ɵɵrepeater(week_r6);
41
44
  } }
42
- function MJDatepickerComponent_ng_template_7_Template(rf, ctx) { if (rf & 1) {
45
+ function MJDatepickerComponent_ng_template_11_Template(rf, ctx) { if (rf & 1) {
43
46
  const _r1 = i0.ɵɵgetCurrentView();
44
- i0.ɵɵelementStart(0, "div", 7)(1, "div", 8)(2, "button", 9);
45
- i0.ɵɵlistener("click", function MJDatepickerComponent_ng_template_7_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.PreviousMonth()); });
46
- i0.ɵɵelement(3, "i", 10);
47
+ i0.ɵɵelementStart(0, "div", 8)(1, "div", 9)(2, "button", 10);
48
+ i0.ɵɵlistener("click", function MJDatepickerComponent_ng_template_11_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.PreviousMonth()); });
49
+ i0.ɵɵelement(3, "i", 11);
47
50
  i0.ɵɵelementEnd();
48
- i0.ɵɵelementStart(4, "span", 11);
51
+ i0.ɵɵelementStart(4, "span", 12);
49
52
  i0.ɵɵtext(5);
50
53
  i0.ɵɵelementEnd();
51
- i0.ɵɵelementStart(6, "button", 12);
52
- i0.ɵɵlistener("click", function MJDatepickerComponent_ng_template_7_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.NextMonth()); });
53
- i0.ɵɵelement(7, "i", 13);
54
+ i0.ɵɵelementStart(6, "button", 13);
55
+ i0.ɵɵlistener("click", function MJDatepickerComponent_ng_template_11_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.NextMonth()); });
56
+ i0.ɵɵelement(7, "i", 14);
54
57
  i0.ɵɵelementEnd()();
55
- i0.ɵɵelementStart(8, "div", 14);
56
- i0.ɵɵrepeaterCreate(9, MJDatepickerComponent_ng_template_7_For_10_Template, 2, 1, "span", 15, i0.ɵɵrepeaterTrackByIdentity);
58
+ i0.ɵɵelementStart(8, "div", 15);
59
+ i0.ɵɵrepeaterCreate(9, MJDatepickerComponent_ng_template_11_For_10_Template, 2, 1, "span", 16, i0.ɵɵrepeaterTrackByIdentity);
57
60
  i0.ɵɵelementEnd();
58
- i0.ɵɵrepeaterCreate(11, MJDatepickerComponent_ng_template_7_For_12_Template, 3, 0, "div", 16, i0.ɵɵrepeaterTrackByIndex);
59
- i0.ɵɵelementStart(13, "div", 17)(14, "button", 18);
60
- i0.ɵɵlistener("click", function MJDatepickerComponent_ng_template_7_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SelectToday()); });
61
+ i0.ɵɵrepeaterCreate(11, MJDatepickerComponent_ng_template_11_For_12_Template, 3, 0, "div", 17, i0.ɵɵrepeaterTrackByIndex);
62
+ i0.ɵɵelementStart(13, "div", 18)(14, "button", 19);
63
+ i0.ɵɵlistener("click", function MJDatepickerComponent_ng_template_11_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SelectToday()); });
61
64
  i0.ɵɵtext(15, "Today");
62
65
  i0.ɵɵelementEnd()()();
63
66
  } if (rf & 2) {
64
67
  const ctx_r1 = i0.ɵɵnextContext();
68
+ i0.ɵɵattribute("aria-labelledby", ctx_r1.CalendarLabelledBy || null)("aria-label", ctx_r1.CalendarLabelledBy ? null : ctx_r1.CalendarLabel);
65
69
  i0.ɵɵadvance(5);
66
70
  i0.ɵɵtextInterpolate(ctx_r1.MonthYearLabel);
67
71
  i0.ɵɵadvance(4);
@@ -71,8 +75,20 @@ function MJDatepickerComponent_ng_template_7_Template(rf, ctx) { if (rf & 1) {
71
75
  } }
72
76
  /**
73
77
  * mj-datepicker — Date picker with calendar popup. Replaces `<kendo-datepicker>`.
78
+ *
79
+ * Without an accessible name the date field announces as "edit, blank" and its calendar popup as a
80
+ * generic "Calendar" — so a form with a start date and an end date presents two identical grids
81
+ * (WCAG 2.1 4.1.2). Use {@link MJNamedControlBase.AriaLabelledBy} when a visible label exists,
82
+ * {@link MJNamedControlBase.AriaLabel} when none does; the toggle button and the calendar take
83
+ * their names from the same source. The field is a real `<input>`, so
84
+ * {@link MJNamedControlBase.InputId} IS a valid `<label for>` target.
85
+ *
86
+ * @example
87
+ * ```html
88
+ * <mj-datepicker AriaLabel="Due date" [(ngModel)]="dueDate" [Min]="minDate" />
89
+ * ```
74
90
  */
75
- export class MJDatepickerComponent {
91
+ export class MJDatepickerComponent extends MJNamedControlBase {
76
92
  Min = null;
77
93
  Max = null;
78
94
  Format = 'MM/dd/yyyy';
@@ -87,6 +103,7 @@ export class MJDatepickerComponent {
87
103
  get Disabled() { return this.disabledInput; }
88
104
  ValueChange = new EventEmitter();
89
105
  triggerEl;
106
+ dateInputEl;
90
107
  hostClass = true;
91
108
  cdr = inject(ChangeDetectorRef);
92
109
  IsOpen = false;
@@ -103,6 +120,15 @@ export class MJDatepickerComponent {
103
120
  onChange = () => { };
104
121
  onTouched = () => { };
105
122
  get MonthYearLabel() { return GetMonthYearLabel(this.viewDate); }
123
+ /** `aria-labelledby` id list for the toggle button when a VISIBLE label names the field. */
124
+ get ToggleLabelledBy() { return this.SecondaryLabelledBy('toggle-word'); }
125
+ /** `aria-label` for the toggle button in the no-visible-label case. */
126
+ get ToggleLabel() { return this.SecondaryLabel('Open calendar for', 'Open calendar'); }
127
+ /** `aria-labelledby` id list for the calendar grid when a VISIBLE label names the field. */
128
+ get CalendarLabelledBy() { return this.SecondaryLabelledBy('calendar-word'); }
129
+ /** `aria-label` for the calendar grid in the no-visible-label case. */
130
+ get CalendarLabel() { return this.SecondaryLabel('Calendar for', 'Calendar'); }
131
+ ngAfterViewInit() { WarnIfUnnamed(this.dateInputEl?.nativeElement, 'mj-datepicker'); }
106
132
  Toggle() { if (this.IsDisabled)
107
133
  return; this.IsOpen ? this.Close() : this.Open(); }
108
134
  Open() {
@@ -206,49 +232,76 @@ export class MJDatepickerComponent {
206
232
  registerOnTouched(fn) { this.onTouched = fn; }
207
233
  setDisabledState(isDisabled) { this.formDisabled = isDisabled; this.syncDisabled(); }
208
234
  ngOnDestroy() { this.Close(); }
209
- static ɵfac = function MJDatepickerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJDatepickerComponent)(); };
235
+ static ɵfac = /*@__PURE__*/ (() => { let ɵMJDatepickerComponent_BaseFactory; return function MJDatepickerComponent_Factory(__ngFactoryType__) { return (ɵMJDatepickerComponent_BaseFactory || (ɵMJDatepickerComponent_BaseFactory = i0.ɵɵgetInheritedFactory(MJDatepickerComponent)))(__ngFactoryType__ || MJDatepickerComponent); }; })();
210
236
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJDatepickerComponent, selectors: [["mj-datepicker"]], viewQuery: function MJDatepickerComponent_Query(rf, ctx) { if (rf & 1) {
211
- i0.ɵɵviewQuery(_c0, 5);
237
+ i0.ɵɵviewQuery(_c0, 5)(_c1, 5);
212
238
  } if (rf & 2) {
213
239
  let _t;
214
240
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.triggerEl = _t.first);
241
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.dateInputEl = _t.first);
215
242
  } }, hostVars: 2, hostBindings: function MJDatepickerComponent_HostBindings(rf, ctx) { if (rf & 2) {
216
243
  i0.ɵɵclassProp("mj-datepicker-host", ctx.hostClass);
217
- } }, inputs: { Min: "Min", Max: "Max", Format: "Format", Placeholder: "Placeholder", Disabled: "Disabled" }, outputs: { ValueChange: "ValueChange" }, features: [i0.ɵɵProvidersFeature([{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MJDatepickerComponent), multi: true }])], decls: 8, vars: 10, consts: [["trigger", "", "overlayOrigin", "cdkOverlayOrigin"], ["dateInput", ""], ["cdkOverlayOrigin", "", 1, "mj-datepicker"], ["type", "text", 1, "mj-input", "mj-datepicker-input", 3, "input", "blur", "keydown", "placeholder", "disabled", "value"], ["type", "button", "tabindex", "-1", "aria-label", "Open calendar", 1, "mj-datepicker-toggle", 3, "click", "disabled"], [1, "fa-solid", "fa-calendar"], ["cdkConnectedOverlay", "", "cdkConnectedOverlayBackdropClass", "mj-dropdown-backdrop", 3, "backdropClick", "detach", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayPositions", "cdkConnectedOverlayHasBackdrop"], ["role", "grid", "aria-label", "Calendar", 1, "mj-calendar"], [1, "mj-calendar-header"], ["type", "button", "aria-label", "Previous month", 1, "mj-calendar-nav", 3, "click"], [1, "fa-solid", "fa-chevron-left"], [1, "mj-calendar-title"], ["type", "button", "aria-label", "Next month", 1, "mj-calendar-nav", 3, "click"], [1, "fa-solid", "fa-chevron-right"], ["role", "row", 1, "mj-calendar-weekdays"], ["role", "columnheader", 1, "mj-calendar-weekday"], ["role", "row", 1, "mj-calendar-row"], [1, "mj-calendar-footer"], ["type", "button", 1, "mj-calendar-today", 3, "click"], ["type", "button", "role", "gridcell", 1, "mj-calendar-day", 3, "mj-calendar-day--selected", "mj-calendar-day--today", "mj-calendar-day--other-month", "disabled"], ["type", "button", "role", "gridcell", 1, "mj-calendar-day", 3, "click", "disabled"]], template: function MJDatepickerComponent_Template(rf, ctx) { if (rf & 1) {
244
+ } }, inputs: { Min: "Min", Max: "Max", Format: "Format", Placeholder: "Placeholder", Disabled: "Disabled" }, outputs: { ValueChange: "ValueChange" }, features: [i0.ɵɵProvidersFeature([{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MJDatepickerComponent), multi: true }]), i0.ɵɵInheritDefinitionFeature], decls: 12, vars: 18, consts: [["trigger", "", "overlayOrigin", "cdkOverlayOrigin"], ["dateInput", ""], ["cdkOverlayOrigin", "", 1, "mj-datepicker"], ["type", "text", 1, "mj-input", "mj-datepicker-input", 3, "input", "blur", "keydown", "placeholder", "disabled", "value"], ["aria-hidden", "true", 1, "mj-datepicker-sr-only"], ["type", "button", "tabindex", "-1", 1, "mj-datepicker-toggle", 3, "click", "disabled"], [1, "fa-solid", "fa-calendar"], ["cdkConnectedOverlay", "", "cdkConnectedOverlayBackdropClass", "mj-dropdown-backdrop", 3, "backdropClick", "detach", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayPositions", "cdkConnectedOverlayHasBackdrop"], ["role", "grid", 1, "mj-calendar"], [1, "mj-calendar-header"], ["type", "button", "aria-label", "Previous month", 1, "mj-calendar-nav", 3, "click"], [1, "fa-solid", "fa-chevron-left"], [1, "mj-calendar-title"], ["type", "button", "aria-label", "Next month", 1, "mj-calendar-nav", 3, "click"], [1, "fa-solid", "fa-chevron-right"], ["role", "row", 1, "mj-calendar-weekdays"], ["role", "columnheader", 1, "mj-calendar-weekday"], ["role", "row", 1, "mj-calendar-row"], [1, "mj-calendar-footer"], ["type", "button", 1, "mj-calendar-today", 3, "click"], ["type", "button", "role", "gridcell", 1, "mj-calendar-day", 3, "mj-calendar-day--selected", "mj-calendar-day--today", "mj-calendar-day--other-month", "disabled"], ["type", "button", "role", "gridcell", 1, "mj-calendar-day", 3, "click", "disabled"]], template: function MJDatepickerComponent_Template(rf, ctx) { if (rf & 1) {
218
245
  i0.ɵɵelementStart(0, "div", 2, 0)(3, "input", 3, 1);
219
246
  i0.ɵɵlistener("input", function MJDatepickerComponent_Template_input_input_3_listener($event) { return ctx.OnInputChange($event); })("blur", function MJDatepickerComponent_Template_input_blur_3_listener() { return ctx.OnBlur(); })("keydown", function MJDatepickerComponent_Template_input_keydown_3_listener($event) { return ctx.OnKeyDown($event); });
220
247
  i0.ɵɵelementEnd();
221
- i0.ɵɵelementStart(5, "button", 4);
222
- i0.ɵɵlistener("click", function MJDatepickerComponent_Template_button_click_5_listener() { return ctx.Toggle(); });
223
- i0.ɵɵelement(6, "i", 5);
248
+ i0.ɵɵelementStart(5, "span", 4);
249
+ i0.ɵɵtext(6, "Open calendar for");
250
+ i0.ɵɵelementEnd();
251
+ i0.ɵɵelementStart(7, "span", 4);
252
+ i0.ɵɵtext(8, "Calendar for");
253
+ i0.ɵɵelementEnd();
254
+ i0.ɵɵelementStart(9, "button", 5);
255
+ i0.ɵɵlistener("click", function MJDatepickerComponent_Template_button_click_9_listener() { return ctx.Toggle(); });
256
+ i0.ɵɵelement(10, "i", 6);
224
257
  i0.ɵɵelementEnd()();
225
- i0.ɵɵtemplate(7, MJDatepickerComponent_ng_template_7_Template, 16, 1, "ng-template", 6);
226
- i0.ɵɵlistener("backdropClick", function MJDatepickerComponent_Template_ng_template_backdropClick_7_listener() { return ctx.Close(); })("detach", function MJDatepickerComponent_Template_ng_template_detach_7_listener() { return ctx.Close(); });
258
+ i0.ɵɵtemplate(11, MJDatepickerComponent_ng_template_11_Template, 16, 3, "ng-template", 7);
259
+ i0.ɵɵlistener("backdropClick", function MJDatepickerComponent_Template_ng_template_backdropClick_11_listener() { return ctx.Close(); })("detach", function MJDatepickerComponent_Template_ng_template_detach_11_listener() { return ctx.Close(); });
227
260
  } if (rf & 2) {
228
261
  const overlayOrigin_r7 = i0.ɵɵreference(2);
229
262
  i0.ɵɵclassProp("mj-datepicker--disabled", ctx.IsDisabled);
230
263
  i0.ɵɵadvance(3);
231
264
  i0.ɵɵproperty("placeholder", ctx.Placeholder)("disabled", ctx.IsDisabled)("value", ctx.DisplayValue);
265
+ i0.ɵɵattribute("id", ctx.InputId || null)("aria-label", ctx.AriaLabel || null)("aria-labelledby", ctx.AriaLabelledBy || null)("aria-describedby", ctx.AriaDescribedBy || null);
266
+ i0.ɵɵadvance(2);
267
+ i0.ɵɵattribute("id", ctx.SecondaryWordId("toggle-word"));
268
+ i0.ɵɵadvance(2);
269
+ i0.ɵɵattribute("id", ctx.SecondaryWordId("calendar-word"));
232
270
  i0.ɵɵadvance(2);
233
271
  i0.ɵɵproperty("disabled", ctx.IsDisabled);
272
+ i0.ɵɵattribute("aria-labelledby", ctx.ToggleLabelledBy || null)("aria-label", ctx.ToggleLabelledBy ? null : ctx.ToggleLabel);
234
273
  i0.ɵɵadvance(2);
235
274
  i0.ɵɵproperty("cdkConnectedOverlayOrigin", overlayOrigin_r7)("cdkConnectedOverlayOpen", ctx.IsOpen)("cdkConnectedOverlayPositions", ctx.Positions)("cdkConnectedOverlayHasBackdrop", true);
236
- } }, dependencies: [OverlayModule, i1.CdkConnectedOverlay, i1.CdkOverlayOrigin], encapsulation: 2 });
275
+ } }, dependencies: [OverlayModule, i1.CdkConnectedOverlay, i1.CdkOverlayOrigin], styles: ["\n\n\n\n\n\n\n\n\n .mj-datepicker-sr-only[_ngcontent-%COMP%] {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }"] });
237
276
  }
238
277
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJDatepickerComponent, [{
239
278
  type: Component,
240
- args: [{
241
- selector: 'mj-datepicker',
242
- standalone: true,
243
- imports: [OverlayModule],
244
- template: `
279
+ args: [{ selector: 'mj-datepicker', standalone: true, imports: [OverlayModule], template: `
245
280
  <div class="mj-datepicker" #trigger cdkOverlayOrigin #overlayOrigin="cdkOverlayOrigin"
246
281
  [class.mj-datepicker--disabled]="IsDisabled">
247
282
  <input #dateInput class="mj-input mj-datepicker-input" type="text"
283
+ [attr.id]="InputId || null"
284
+ [attr.aria-label]="AriaLabel || null"
285
+ [attr.aria-labelledby]="AriaLabelledBy || null"
286
+ [attr.aria-describedby]="AriaDescribedBy || null"
248
287
  [placeholder]="Placeholder" [disabled]="IsDisabled" [value]="DisplayValue"
249
288
  (input)="OnInputChange($event)" (blur)="OnBlur()" (keydown)="OnKeyDown($event)" />
289
+ <!--
290
+ The fixed words live in hidden spans rather than in concatenated strings so the
291
+ AriaLabelledBy path can name the toggle and the calendar from the same visible label that
292
+ names the field: aria-labelledby takes an ID LIST, so the word plus the label's own text is
293
+ composed by the accessibility tree without this component ever seeing that text. The
294
+ calendar's word sits here, outside the overlay, because ids resolve document-wide.
295
+ A hidden node that is DIRECTLY referenced by aria-labelledby is still included in the name
296
+ (accname §4.1), so aria-hidden keeps the word out of the reading order without costing the
297
+ composed name.
298
+ -->
299
+ <span class="mj-datepicker-sr-only" aria-hidden="true" [attr.id]="SecondaryWordId('toggle-word')">Open calendar for</span>
300
+ <span class="mj-datepicker-sr-only" aria-hidden="true" [attr.id]="SecondaryWordId('calendar-word')">Calendar for</span>
250
301
  <button type="button" class="mj-datepicker-toggle" tabindex="-1" [disabled]="IsDisabled"
251
- (click)="Toggle()" aria-label="Open calendar">
302
+ (click)="Toggle()"
303
+ [attr.aria-labelledby]="ToggleLabelledBy || null"
304
+ [attr.aria-label]="ToggleLabelledBy ? null : ToggleLabel">
252
305
  <i class="fa-solid fa-calendar"></i>
253
306
  </button>
254
307
  </div>
@@ -256,7 +309,9 @@ export class MJDatepickerComponent {
256
309
  [cdkConnectedOverlayOpen]="IsOpen" [cdkConnectedOverlayPositions]="Positions"
257
310
  [cdkConnectedOverlayHasBackdrop]="true" cdkConnectedOverlayBackdropClass="mj-dropdown-backdrop"
258
311
  (backdropClick)="Close()" (detach)="Close()">
259
- <div class="mj-calendar" role="grid" aria-label="Calendar">
312
+ <div class="mj-calendar" role="grid"
313
+ [attr.aria-labelledby]="CalendarLabelledBy || null"
314
+ [attr.aria-label]="CalendarLabelledBy ? null : CalendarLabel">
260
315
  <div class="mj-calendar-header">
261
316
  <button type="button" (click)="PreviousMonth()" aria-label="Previous month" class="mj-calendar-nav">
262
317
  <i class="fa-solid fa-chevron-left"></i></button>
@@ -284,9 +339,7 @@ export class MJDatepickerComponent {
284
339
  </div>
285
340
  </div>
286
341
  </ng-template>
287
- `,
288
- providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MJDatepickerComponent), multi: true }]
289
- }]
342
+ `, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MJDatepickerComponent), multi: true }], styles: ["\n /*\n * Component-scoped ON PURPOSE, unlike the rest of this control's styling, which ships as a global\n * stylesheet the host application imports. A host that skips that import gets unstyled chrome \u2014\n * survivable \u2014 but a hidden-word span that is not hidden renders its word as literal text in the\n * middle of the field. The rule that hides it therefore has to travel with the component.\n *\n * Not display:none or visibility:hidden \u2014 both remove the element from the accessibility tree,\n * which is the one thing this element exists to be in.\n */\n .mj-datepicker-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n "] }]
290
343
  }], null, { Min: [{
291
344
  type: Input
292
345
  }], Max: [{
@@ -302,9 +355,12 @@ export class MJDatepickerComponent {
302
355
  }], triggerEl: [{
303
356
  type: ViewChild,
304
357
  args: ['trigger']
358
+ }], dateInputEl: [{
359
+ type: ViewChild,
360
+ args: ['dateInput']
305
361
  }], hostClass: [{
306
362
  type: HostBinding,
307
363
  args: ['class.mj-datepicker-host']
308
364
  }] }); })();
309
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJDatepickerComponent, { className: "MJDatepickerComponent", filePath: "lib/datepicker/datepicker.component.ts", lineNumber: 59 }); })();
365
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJDatepickerComponent, { className: "MJDatepickerComponent", filePath: "lib/datepicker/datepicker.component.ts", lineNumber: 115 }); })();
310
366
  //# sourceMappingURL=datepicker.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"datepicker.component.js","sourceRoot":"","sources":["../../../src/lib/datepicker/datepicker.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, forwardRef, HostBinding, ElementRef, ViewChild, OnDestroy, inject, ChangeDetectorRef } from '@angular/core';\nimport { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';\nimport { OverlayModule, ConnectedPosition } from '@angular/cdk/overlay';\nimport { CalendarDay, WEEK_DAYS, BuildCalendarWeeks, FormatDate, GetMonthYearLabel } from '../calendar/calendar-utils';\n\n/**\n * mj-datepicker — Date picker with calendar popup. Replaces `<kendo-datepicker>`.\n */\n@Component({\n selector: 'mj-datepicker',\n standalone: true,\n imports: [OverlayModule],\n template: `\n <div class=\"mj-datepicker\" #trigger cdkOverlayOrigin #overlayOrigin=\"cdkOverlayOrigin\"\n [class.mj-datepicker--disabled]=\"IsDisabled\">\n <input #dateInput class=\"mj-input mj-datepicker-input\" type=\"text\"\n [placeholder]=\"Placeholder\" [disabled]=\"IsDisabled\" [value]=\"DisplayValue\"\n (input)=\"OnInputChange($event)\" (blur)=\"OnBlur()\" (keydown)=\"OnKeyDown($event)\" />\n <button type=\"button\" class=\"mj-datepicker-toggle\" tabindex=\"-1\" [disabled]=\"IsDisabled\"\n (click)=\"Toggle()\" aria-label=\"Open calendar\">\n <i class=\"fa-solid fa-calendar\"></i>\n </button>\n </div>\n <ng-template cdkConnectedOverlay [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"IsOpen\" [cdkConnectedOverlayPositions]=\"Positions\"\n [cdkConnectedOverlayHasBackdrop]=\"true\" cdkConnectedOverlayBackdropClass=\"mj-dropdown-backdrop\"\n (backdropClick)=\"Close()\" (detach)=\"Close()\">\n <div class=\"mj-calendar\" role=\"grid\" aria-label=\"Calendar\">\n <div class=\"mj-calendar-header\">\n <button type=\"button\" (click)=\"PreviousMonth()\" aria-label=\"Previous month\" class=\"mj-calendar-nav\">\n <i class=\"fa-solid fa-chevron-left\"></i></button>\n <span class=\"mj-calendar-title\">{{ MonthYearLabel }}</span>\n <button type=\"button\" (click)=\"NextMonth()\" aria-label=\"Next month\" class=\"mj-calendar-nav\">\n <i class=\"fa-solid fa-chevron-right\"></i></button>\n </div>\n <div class=\"mj-calendar-weekdays\" role=\"row\">\n @for (day of WeekDays; track day) { <span class=\"mj-calendar-weekday\" role=\"columnheader\">{{ day }}</span> }\n </div>\n @for (week of Weeks; track $index) {\n <div class=\"mj-calendar-row\" role=\"row\">\n @for (day of week; track day.date.getTime()) {\n <button type=\"button\" class=\"mj-calendar-day\" role=\"gridcell\"\n [class.mj-calendar-day--selected]=\"IsSelectedDay(day)\"\n [class.mj-calendar-day--today]=\"day.isToday\"\n [class.mj-calendar-day--other-month]=\"!day.isCurrentMonth\"\n [disabled]=\"IsOutOfRange(day)\" [attr.aria-selected]=\"IsSelectedDay(day)\"\n (click)=\"SelectDate(day)\">{{ day.dayNumber }}</button>\n }\n </div>\n }\n <div class=\"mj-calendar-footer\">\n <button type=\"button\" class=\"mj-calendar-today\" (click)=\"SelectToday()\">Today</button>\n </div>\n </div>\n </ng-template>\n `,\n providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MJDatepickerComponent), multi: true }]\n})\nexport class MJDatepickerComponent implements ControlValueAccessor, OnDestroy {\n @Input() Min: Date | null = null;\n @Input() Max: Date | null = null;\n @Input() Format = 'MM/dd/yyyy';\n @Input() Placeholder = '';\n /**\n * Host-driven disable. Composed with Angular Forms' `setDisabledState()` into `IsDisabled`\n * (the actual gate) — see `syncDisabled`. A setter, not a bare field, because this input is\n * routinely bound to an expression that changes over the control's lifetime, and the gate has\n * to follow it every time.\n */\n @Input()\n set Disabled(value: boolean) { this.disabledInput = value; this.syncDisabled(); }\n get Disabled(): boolean { return this.disabledInput; }\n @Output() ValueChange = new EventEmitter<Date | null>();\n @ViewChild('trigger') private triggerEl!: ElementRef<HTMLElement>;\n @HostBinding('class.mj-datepicker-host') readonly hostClass = true;\n private cdr = inject(ChangeDetectorRef);\n\n IsOpen = false; IsDisabled = false; DisplayValue = '';\n Weeks: CalendarDay[][] = []; WeekDays = WEEK_DAYS;\n Positions: ConnectedPosition[] = [\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' }\n ];\n private viewDate = new Date();\n private selectedDate: Date | null = null;\n private onChange: (value: Date | null) => void = () => {};\n private onTouched: () => void = () => {};\n\n get MonthYearLabel(): string { return GetMonthYearLabel(this.viewDate); }\n\n Toggle(): void { if (this.IsDisabled) return; this.IsOpen ? this.Close() : this.Open(); }\n Open(): void {\n if (this.IsDisabled || this.IsOpen) return;\n this.viewDate = this.selectedDate ? new Date(this.selectedDate) : new Date();\n this.Weeks = BuildCalendarWeeks(this.viewDate); this.IsOpen = true; this.cdr.detectChanges();\n }\n Close(): void { if (!this.IsOpen) return; this.IsOpen = false; this.cdr.detectChanges(); }\n\n /** Backing field for the `Disabled` input. */\n private disabledInput = false;\n /** The forms-driven disabled state, kept SEPARATE so neither source can stomp the other. */\n private formDisabled = false;\n\n /**\n * Recompute the gate from both of its sources. Called whenever either changes.\n *\n * `IsDisabled` is derived state, and the only thing that assigned it was `setDisabledState()`.\n * The forms-driven half was in fact fine — `setUpControl` also wires `registerOnDisabledChange`,\n * so that hook fires on every `control.disable()`/`enable()`, not just at registration. What had\n * no recompute path at all was the `Disabled` @Input: a plain field, so the gate froze at\n * whatever the first compose produced and every later change to the input was dropped.\n *\n * Closes the calendar directly rather than via `Close()`: this can run from an @Input setter,\n * i.e. DURING the parent's CD pass, where a nested `detectChanges()` trips NG0100.\n */\n private syncDisabled(): void {\n const disabled = this.disabledInput || this.formDisabled;\n if (disabled === this.IsDisabled) return;\n this.IsDisabled = disabled;\n if (disabled) this.IsOpen = false;\n this.cdr.markForCheck();\n }\n PreviousMonth(): void { this.viewDate = new Date(this.viewDate.getFullYear(), this.viewDate.getMonth() - 1, 1); this.Weeks = BuildCalendarWeeks(this.viewDate); }\n NextMonth(): void { this.viewDate = new Date(this.viewDate.getFullYear(), this.viewDate.getMonth() + 1, 1); this.Weeks = BuildCalendarWeeks(this.viewDate); }\n\n SelectDate(day: CalendarDay): void {\n if (this.IsOutOfRange(day)) return;\n this.selectedDate = day.date; this.DisplayValue = FormatDate(day.date);\n this.onChange(day.date); this.ValueChange.emit(day.date); this.Close();\n }\n SelectToday(): void {\n const today = new Date(); today.setHours(0, 0, 0, 0);\n this.selectedDate = today; this.DisplayValue = FormatDate(today);\n this.onChange(today); this.ValueChange.emit(today); this.Close();\n }\n IsSelectedDay(day: CalendarDay): boolean {\n if (!this.selectedDate) return false;\n return day.date.getFullYear() === this.selectedDate.getFullYear() && day.date.getMonth() === this.selectedDate.getMonth() && day.date.getDate() === this.selectedDate.getDate();\n }\n IsOutOfRange(day: CalendarDay): boolean {\n if (this.Min && day.date < this.Min) return true;\n if (this.Max && day.date > this.Max) return true;\n return false;\n }\n OnInputChange(event: Event): void {\n const value = (event.target as HTMLInputElement).value; this.DisplayValue = value;\n const parsed = new Date(value);\n if (!isNaN(parsed.getTime())) { this.selectedDate = parsed; this.onChange(parsed); this.ValueChange.emit(parsed); }\n }\n OnBlur(): void { this.onTouched(); }\n OnKeyDown(event: KeyboardEvent): void {\n if (event.key === 'Escape') this.Close();\n else if (event.key === 'Enter' && !this.IsOpen) this.Open();\n }\n writeValue(value: Date | string | null): void {\n if (value == null) { this.selectedDate = null; this.DisplayValue = ''; }\n else { const d = typeof value === 'string' ? new Date(value) : value; if (!isNaN(d.getTime())) { this.selectedDate = d; this.DisplayValue = FormatDate(d); } }\n }\n registerOnChange(fn: (value: Date | null) => void): void { this.onChange = fn; }\n registerOnTouched(fn: () => void): void { this.onTouched = fn; }\n setDisabledState(isDisabled: boolean): void { this.formDisabled = isDisabled; this.syncDisabled(); }\n ngOnDestroy(): void { this.Close(); }\n}\n"]}
1
+ {"version":3,"file":"datepicker.component.js","sourceRoot":"","sources":["../../../src/lib/datepicker/datepicker.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAc,SAAS,EAAa,MAAM,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC5K,OAAO,EAAE,iBAAiB,EAAwB,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAqB,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAe,SAAS,EAAE,kBAAkB,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACvH,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;;;;;sCAqElD,oBAAkB;;IAJgB,gCAAsD;IAAA,YAAS;IAAA,iBAAO;;;IAAhB,cAAS;IAAT,4BAAS;;;;IAK/F,kCAK4B;IAA1B,iOAAS,yBAAe,KAAC;IAAC,YAAmB;IAAA,iBAAS;;;;IAFtD,AADA,AADA,yEAAsD,0CACV,wDACc;IAC1D,sDAA8B;;IACJ,cAAmB;IAAnB,sCAAmB;;;IAPnD,+BAAwC;IACtC,kHAOC;IACH,iBAAM;;;IARJ,cAOC;IAPD,sBAOC;;;;IAlBH,AADF,AAHF,8BAEgE,aAC9B,iBACsE;IAA9E,0LAAS,sBAAe,KAAC;IAC7C,wBAAwC;IAAA,iBAAS;IACnD,gCAAgC;IAAA,YAAoB;IAAA,iBAAO;IAC3D,kCAA4F;IAAtE,0LAAS,kBAAW,KAAC;IACzC,wBAAyC;IAC7C,AAD6C,iBAAS,EAChD;IACN,+BAA6C;IAC3C,4HAA4G;IAC9G,iBAAM;IACN,yHAWC;IAEC,AADF,gCAAgC,kBAC0C;IAAxB,2LAAS,oBAAa,KAAC;IAAC,sBAAK;IAEjF,AADE,AAD+E,iBAAS,EAClF,EACF;;;;IAtB8B,eAAoB;IAApB,2CAAoB;IAKpD,eAA4G;IAA5G,8BAA4G;IAE9G,eAWC;IAXD,2BAWC;;AA5ET;;;;;;;;;;;;;;GAcG;AA6FH,MAAM,OAAO,qBAAsB,SAAQ,kBAAkB;IAClD,GAAG,GAAgB,IAAI,CAAC;IACxB,GAAG,GAAgB,IAAI,CAAC;IACxB,MAAM,GAAG,YAAY,CAAC;IACtB,WAAW,GAAG,EAAE,CAAC;IAC1B;;;;;OAKG;IACH,IACI,QAAQ,CAAC,KAAc,IAAI,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;IACjF,IAAI,QAAQ,KAAc,OAAO,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;IAC5C,WAAW,GAAG,IAAI,YAAY,EAAe,CAAC;IAC1B,SAAS,CAA2B;IAClC,WAAW,CAA2C;IACpC,SAAS,GAAG,IAAI,CAAC;IAC3D,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAExC,MAAM,GAAG,KAAK,CAAC;IAAC,UAAU,GAAG,KAAK,CAAC;IAAC,YAAY,GAAG,EAAE,CAAC;IACtD,KAAK,GAAoB,EAAE,CAAC;IAAC,QAAQ,GAAG,SAAS,CAAC;IAClD,SAAS,GAAwB;QAC/B,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC3E,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE;KAC5E,CAAC;IACM,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC;IACtB,YAAY,GAAgB,IAAI,CAAC;IACjC,QAAQ,GAAiC,GAAG,EAAE,GAAE,CAAC,CAAC;IAClD,SAAS,GAAe,GAAG,EAAE,GAAE,CAAC,CAAC;IAEzC,IAAI,cAAc,KAAa,OAAO,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEzE,4FAA4F;IAC5F,IAAI,gBAAgB,KAAa,OAAO,IAAI,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAElF,uEAAuE;IACvE,IAAI,WAAW,KAAa,OAAO,IAAI,CAAC,cAAc,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IAE/F,4FAA4F;IAC5F,IAAI,kBAAkB,KAAa,OAAO,IAAI,CAAC,mBAAmB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAEtF,uEAAuE;IACvE,IAAI,aAAa,KAAa,OAAO,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IAEvF,eAAe,KAAW,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IAE5F,MAAM,KAAW,IAAI,IAAI,CAAC,UAAU;QAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACzF,IAAI;QACF,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QAC3C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QAC7E,IAAI,CAAC,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC/F,CAAC;IACD,KAAK,KAAW,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IAE1F,8CAA8C;IACtC,aAAa,GAAG,KAAK,CAAC;IAC9B,4FAA4F;IACpF,YAAY,GAAG,KAAK,CAAC;IAE7B;;;;;;;;;;;OAWG;IACK,YAAY;QAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,YAAY,CAAC;QACzD,IAAI,QAAQ,KAAK,IAAI,CAAC,UAAU;YAAE,OAAO;QACzC,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC;QAC3B,IAAI,QAAQ;YAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC1B,CAAC;IACD,aAAa,KAAW,IAAI,CAAC,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACjK,SAAS,KAAW,IAAI,CAAC,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAE7J,UAAU,CAAC,GAAgB;QACzB,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC;YAAE,OAAO;QACnC,IAAI,CAAC,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC;QAAC,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACzE,CAAC;IACD,WAAW;QACT,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAAC,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACjE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACnE,CAAC;IACD,aAAa,CAAC,GAAgB;QAC5B,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,OAAO,KAAK,CAAC;QACrC,OAAO,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;IAClL,CAAC;IACD,YAAY,CAAC,GAAgB;QAC3B,IAAI,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACjD,IAAI,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACjD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,aAAa,CAAC,KAAY;QACxB,MAAM,KAAK,GAAI,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;QAAC,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAClF,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;YAAC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC;YAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAAC,CAAC;IACrH,CAAC;IACD,MAAM,KAAW,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IACpC,SAAS,CAAC,KAAoB;QAC5B,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ;YAAE,IAAI,CAAC,KAAK,EAAE,CAAC;aACpC,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAC9D,CAAC;IACD,UAAU,CAAC,KAA2B;QACpC,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAAC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YAAC,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QAAC,CAAC;aACnE,CAAC;YAAC,MAAM,CAAC,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;gBAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;gBAAC,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;QAAC,CAAC;IAChK,CAAC;IACD,gBAAgB,CAAC,EAAgC,IAAU,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC;IAChF,iBAAiB,CAAC,EAAc,IAAU,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC,CAAC;IAChE,gBAAgB,CAAC,UAAmB,IAAU,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;IACpG,WAAW,KAAW,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;iQAtH1B,qBAAqB,yBAArB,qBAAqB;6DAArB,qBAAqB;;;;;;;YAArB,mDAAqB;+LAFrB,CAAC,EAAE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;YAnF1G,AAFF,iCAC+C,kBAOuC;YAAhC,AAAlB,AAAhC,uGAAS,yBAAqB,IAAC,kFAAS,YAAQ,IAAC,8FAAY,qBAAiB,IAAC;YANjF,iBAMoF;YAWpF,+BAAkG;YAAA,iCAAiB;YAAA,iBAAO;YAC1H,+BAAoG;YAAA,4BAAY;YAAA,iBAAO;YACvH,iCAG4D;YAF1D,kGAAS,YAAQ,IAAC;YAGlB,wBAAoC;YAExC,AADE,iBAAS,EACL;YACN,yFAG+C;YAAnB,AAA1B,wHAAiB,WAAO,IAAC,6FAAW,WAAO,IAAC;;;YA9B5C,yDAA4C;YAM1C,eAA2B;YAAyB,AAAxB,AAA5B,6CAA2B,4BAAwB,2BAAuB;;YAYrB,eAA0C;;YAC1C,eAA4C;;YAClC,eAAuB;YAAvB,yCAAuB;;YAOzD,eAA2C;YAE1E,AADmC,AAAnC,AAD+B,4DAA2C,uCACxC,+CAA2C,wCACtC;4BAhCjC,aAAa;;iFAyFZ,qBAAqB;cA5FjC,SAAS;2BACE,eAAe,cACb,IAAI,WACP,CAAC,aAAa,CAAC,YACd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DT,aAuBU,CAAC,EAAE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,CAAC,GAAG,EAAE,sBAAsB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;;kBAG7G,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBAOL,KAAK;;kBAGL,MAAM;;kBACN,SAAS;mBAAC,SAAS;;kBACnB,SAAS;mBAAC,WAAW;;kBACrB,WAAW;mBAAC,0BAA0B;;kFAjB5B,qBAAqB","sourcesContent":["import { AfterViewInit, Component, Input, Output, EventEmitter, forwardRef, HostBinding, ElementRef, ViewChild, OnDestroy, inject, ChangeDetectorRef } from '@angular/core';\nimport { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';\nimport { OverlayModule, ConnectedPosition } from '@angular/cdk/overlay';\nimport { CalendarDay, WEEK_DAYS, BuildCalendarWeeks, FormatDate, GetMonthYearLabel } from '../calendar/calendar-utils';\nimport { MJNamedControlBase } from '../a11y/named-control.base';\nimport { WarnIfUnnamed } from '../a11y/unnamed-control-guard';\n\n/**\n * mj-datepicker — Date picker with calendar popup. Replaces `<kendo-datepicker>`.\n *\n * Without an accessible name the date field announces as \"edit, blank\" and its calendar popup as a\n * generic \"Calendar\" — so a form with a start date and an end date presents two identical grids\n * (WCAG 2.1 4.1.2). Use {@link MJNamedControlBase.AriaLabelledBy} when a visible label exists,\n * {@link MJNamedControlBase.AriaLabel} when none does; the toggle button and the calendar take\n * their names from the same source. The field is a real `<input>`, so\n * {@link MJNamedControlBase.InputId} IS a valid `<label for>` target.\n *\n * @example\n * ```html\n * <mj-datepicker AriaLabel=\"Due date\" [(ngModel)]=\"dueDate\" [Min]=\"minDate\" />\n * ```\n */\n@Component({\n selector: 'mj-datepicker',\n standalone: true,\n imports: [OverlayModule],\n template: `\n <div class=\"mj-datepicker\" #trigger cdkOverlayOrigin #overlayOrigin=\"cdkOverlayOrigin\"\n [class.mj-datepicker--disabled]=\"IsDisabled\">\n <input #dateInput class=\"mj-input mj-datepicker-input\" type=\"text\"\n [attr.id]=\"InputId || null\"\n [attr.aria-label]=\"AriaLabel || null\"\n [attr.aria-labelledby]=\"AriaLabelledBy || null\"\n [attr.aria-describedby]=\"AriaDescribedBy || null\"\n [placeholder]=\"Placeholder\" [disabled]=\"IsDisabled\" [value]=\"DisplayValue\"\n (input)=\"OnInputChange($event)\" (blur)=\"OnBlur()\" (keydown)=\"OnKeyDown($event)\" />\n <!--\n The fixed words live in hidden spans rather than in concatenated strings so the\n AriaLabelledBy path can name the toggle and the calendar from the same visible label that\n names the field: aria-labelledby takes an ID LIST, so the word plus the label's own text is\n composed by the accessibility tree without this component ever seeing that text. The\n calendar's word sits here, outside the overlay, because ids resolve document-wide.\n A hidden node that is DIRECTLY referenced by aria-labelledby is still included in the name\n (accname §4.1), so aria-hidden keeps the word out of the reading order without costing the\n composed name.\n -->\n <span class=\"mj-datepicker-sr-only\" aria-hidden=\"true\" [attr.id]=\"SecondaryWordId('toggle-word')\">Open calendar for</span>\n <span class=\"mj-datepicker-sr-only\" aria-hidden=\"true\" [attr.id]=\"SecondaryWordId('calendar-word')\">Calendar for</span>\n <button type=\"button\" class=\"mj-datepicker-toggle\" tabindex=\"-1\" [disabled]=\"IsDisabled\"\n (click)=\"Toggle()\"\n [attr.aria-labelledby]=\"ToggleLabelledBy || null\"\n [attr.aria-label]=\"ToggleLabelledBy ? null : ToggleLabel\">\n <i class=\"fa-solid fa-calendar\"></i>\n </button>\n </div>\n <ng-template cdkConnectedOverlay [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"IsOpen\" [cdkConnectedOverlayPositions]=\"Positions\"\n [cdkConnectedOverlayHasBackdrop]=\"true\" cdkConnectedOverlayBackdropClass=\"mj-dropdown-backdrop\"\n (backdropClick)=\"Close()\" (detach)=\"Close()\">\n <div class=\"mj-calendar\" role=\"grid\"\n [attr.aria-labelledby]=\"CalendarLabelledBy || null\"\n [attr.aria-label]=\"CalendarLabelledBy ? null : CalendarLabel\">\n <div class=\"mj-calendar-header\">\n <button type=\"button\" (click)=\"PreviousMonth()\" aria-label=\"Previous month\" class=\"mj-calendar-nav\">\n <i class=\"fa-solid fa-chevron-left\"></i></button>\n <span class=\"mj-calendar-title\">{{ MonthYearLabel }}</span>\n <button type=\"button\" (click)=\"NextMonth()\" aria-label=\"Next month\" class=\"mj-calendar-nav\">\n <i class=\"fa-solid fa-chevron-right\"></i></button>\n </div>\n <div class=\"mj-calendar-weekdays\" role=\"row\">\n @for (day of WeekDays; track day) { <span class=\"mj-calendar-weekday\" role=\"columnheader\">{{ day }}</span> }\n </div>\n @for (week of Weeks; track $index) {\n <div class=\"mj-calendar-row\" role=\"row\">\n @for (day of week; track day.date.getTime()) {\n <button type=\"button\" class=\"mj-calendar-day\" role=\"gridcell\"\n [class.mj-calendar-day--selected]=\"IsSelectedDay(day)\"\n [class.mj-calendar-day--today]=\"day.isToday\"\n [class.mj-calendar-day--other-month]=\"!day.isCurrentMonth\"\n [disabled]=\"IsOutOfRange(day)\" [attr.aria-selected]=\"IsSelectedDay(day)\"\n (click)=\"SelectDate(day)\">{{ day.dayNumber }}</button>\n }\n </div>\n }\n <div class=\"mj-calendar-footer\">\n <button type=\"button\" class=\"mj-calendar-today\" (click)=\"SelectToday()\">Today</button>\n </div>\n </div>\n </ng-template>\n `,\n styles: [`\n /*\n * Component-scoped ON PURPOSE, unlike the rest of this control's styling, which ships as a global\n * stylesheet the host application imports. A host that skips that import gets unstyled chrome —\n * survivable — but a hidden-word span that is not hidden renders its word as literal text in the\n * middle of the field. The rule that hides it therefore has to travel with the component.\n *\n * Not display:none or visibility:hidden — both remove the element from the accessibility tree,\n * which is the one thing this element exists to be in.\n */\n .mj-datepicker-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n `],\n providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MJDatepickerComponent), multi: true }]\n})\nexport class MJDatepickerComponent extends MJNamedControlBase implements ControlValueAccessor, AfterViewInit, OnDestroy {\n @Input() Min: Date | null = null;\n @Input() Max: Date | null = null;\n @Input() Format = 'MM/dd/yyyy';\n @Input() Placeholder = '';\n /**\n * Host-driven disable. Composed with Angular Forms' `setDisabledState()` into `IsDisabled`\n * (the actual gate) — see `syncDisabled`. A setter, not a bare field, because this input is\n * routinely bound to an expression that changes over the control's lifetime, and the gate has\n * to follow it every time.\n */\n @Input()\n set Disabled(value: boolean) { this.disabledInput = value; this.syncDisabled(); }\n get Disabled(): boolean { return this.disabledInput; }\n @Output() ValueChange = new EventEmitter<Date | null>();\n @ViewChild('trigger') private triggerEl!: ElementRef<HTMLElement>;\n @ViewChild('dateInput') private dateInputEl: ElementRef<HTMLInputElement> | undefined;\n @HostBinding('class.mj-datepicker-host') readonly hostClass = true;\n private cdr = inject(ChangeDetectorRef);\n\n IsOpen = false; IsDisabled = false; DisplayValue = '';\n Weeks: CalendarDay[][] = []; WeekDays = WEEK_DAYS;\n Positions: ConnectedPosition[] = [\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' }\n ];\n private viewDate = new Date();\n private selectedDate: Date | null = null;\n private onChange: (value: Date | null) => void = () => {};\n private onTouched: () => void = () => {};\n\n get MonthYearLabel(): string { return GetMonthYearLabel(this.viewDate); }\n\n /** `aria-labelledby` id list for the toggle button when a VISIBLE label names the field. */\n get ToggleLabelledBy(): string { return this.SecondaryLabelledBy('toggle-word'); }\n\n /** `aria-label` for the toggle button in the no-visible-label case. */\n get ToggleLabel(): string { return this.SecondaryLabel('Open calendar for', 'Open calendar'); }\n\n /** `aria-labelledby` id list for the calendar grid when a VISIBLE label names the field. */\n get CalendarLabelledBy(): string { return this.SecondaryLabelledBy('calendar-word'); }\n\n /** `aria-label` for the calendar grid in the no-visible-label case. */\n get CalendarLabel(): string { return this.SecondaryLabel('Calendar for', 'Calendar'); }\n\n ngAfterViewInit(): void { WarnIfUnnamed(this.dateInputEl?.nativeElement, 'mj-datepicker'); }\n\n Toggle(): void { if (this.IsDisabled) return; this.IsOpen ? this.Close() : this.Open(); }\n Open(): void {\n if (this.IsDisabled || this.IsOpen) return;\n this.viewDate = this.selectedDate ? new Date(this.selectedDate) : new Date();\n this.Weeks = BuildCalendarWeeks(this.viewDate); this.IsOpen = true; this.cdr.detectChanges();\n }\n Close(): void { if (!this.IsOpen) return; this.IsOpen = false; this.cdr.detectChanges(); }\n\n /** Backing field for the `Disabled` input. */\n private disabledInput = false;\n /** The forms-driven disabled state, kept SEPARATE so neither source can stomp the other. */\n private formDisabled = false;\n\n /**\n * Recompute the gate from both of its sources. Called whenever either changes.\n *\n * `IsDisabled` is derived state, and the only thing that assigned it was `setDisabledState()`.\n * The forms-driven half was in fact fine — `setUpControl` also wires `registerOnDisabledChange`,\n * so that hook fires on every `control.disable()`/`enable()`, not just at registration. What had\n * no recompute path at all was the `Disabled` @Input: a plain field, so the gate froze at\n * whatever the first compose produced and every later change to the input was dropped.\n *\n * Closes the calendar directly rather than via `Close()`: this can run from an @Input setter,\n * i.e. DURING the parent's CD pass, where a nested `detectChanges()` trips NG0100.\n */\n private syncDisabled(): void {\n const disabled = this.disabledInput || this.formDisabled;\n if (disabled === this.IsDisabled) return;\n this.IsDisabled = disabled;\n if (disabled) this.IsOpen = false;\n this.cdr.markForCheck();\n }\n PreviousMonth(): void { this.viewDate = new Date(this.viewDate.getFullYear(), this.viewDate.getMonth() - 1, 1); this.Weeks = BuildCalendarWeeks(this.viewDate); }\n NextMonth(): void { this.viewDate = new Date(this.viewDate.getFullYear(), this.viewDate.getMonth() + 1, 1); this.Weeks = BuildCalendarWeeks(this.viewDate); }\n\n SelectDate(day: CalendarDay): void {\n if (this.IsOutOfRange(day)) return;\n this.selectedDate = day.date; this.DisplayValue = FormatDate(day.date);\n this.onChange(day.date); this.ValueChange.emit(day.date); this.Close();\n }\n SelectToday(): void {\n const today = new Date(); today.setHours(0, 0, 0, 0);\n this.selectedDate = today; this.DisplayValue = FormatDate(today);\n this.onChange(today); this.ValueChange.emit(today); this.Close();\n }\n IsSelectedDay(day: CalendarDay): boolean {\n if (!this.selectedDate) return false;\n return day.date.getFullYear() === this.selectedDate.getFullYear() && day.date.getMonth() === this.selectedDate.getMonth() && day.date.getDate() === this.selectedDate.getDate();\n }\n IsOutOfRange(day: CalendarDay): boolean {\n if (this.Min && day.date < this.Min) return true;\n if (this.Max && day.date > this.Max) return true;\n return false;\n }\n OnInputChange(event: Event): void {\n const value = (event.target as HTMLInputElement).value; this.DisplayValue = value;\n const parsed = new Date(value);\n if (!isNaN(parsed.getTime())) { this.selectedDate = parsed; this.onChange(parsed); this.ValueChange.emit(parsed); }\n }\n OnBlur(): void { this.onTouched(); }\n OnKeyDown(event: KeyboardEvent): void {\n if (event.key === 'Escape') this.Close();\n else if (event.key === 'Enter' && !this.IsOpen) this.Open();\n }\n writeValue(value: Date | string | null): void {\n if (value == null) { this.selectedDate = null; this.DisplayValue = ''; }\n else { const d = typeof value === 'string' ? new Date(value) : value; if (!isNaN(d.getTime())) { this.selectedDate = d; this.DisplayValue = FormatDate(d); } }\n }\n registerOnChange(fn: (value: Date | null) => void): void { this.onChange = fn; }\n registerOnTouched(fn: () => void): void { this.onTouched = fn; }\n setDisabledState(isDisabled: boolean): void { this.formDisabled = isDisabled; this.syncDisabled(); }\n ngOnDestroy(): void { this.Close(); }\n}\n"]}
@@ -41,7 +41,11 @@ export declare class MJDialogComponent implements OnDestroy {
41
41
  Close: EventEmitter<void>;
42
42
  DialogId: number;
43
43
  get dialogId(): number;
44
+ get ResolvedWidth(): string;
45
+ /** @deprecated Use {@link ResolvedWidth}. */
44
46
  get resolvedWidth(): string;
47
+ get ResolvedHeight(): string;
48
+ /** @deprecated Use {@link ResolvedHeight}. */
45
49
  get resolvedHeight(): string;
46
50
  OnEscapeKey(): void;
47
51
  OnBackdropClick(event: Event): void;
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.component.d.ts","sourceRoot":"","sources":["../../../src/lib/dialog/dialog.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,YAAY,EAKZ,SAAS,EAEV,MAAM,eAAe,CAAC;;AAEvB,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAU9D;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBA2Ca,iBAAkB,YAAW,SAAS;IACjD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAK;IAE1B,IACI,OAAO,CAAC,KAAK,EAAE,OAAO,EASzB;IACD,IAAI,OAAO,IAAI,OAAO,CAErB;IAEQ,KAAK,SAAM;IACX,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAQ;IACrC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAQ;IACtC,IAAI,EAAE,YAAY,CAAU;IAC5B,SAAS,UAAQ;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAExC;;;;;OAKG;IACM,IAAI,EAAE,QAAQ,GAAG,aAAa,CAAY;IAEzC,KAAK,qBAA4B;IAE3C,QAAQ,SAA8B;IAEtC,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,aAAa,IAAI,MAAM,CAK1B;IAED,IAAI,cAAc,IAAI,MAAM,CAK3B;IAGD,WAAW,IAAI,IAAI;IAMnB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAMnC,YAAY,IAAI,IAAI;IAIpB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,eAAe;IAIvB,WAAW,IAAI,IAAI;yCAjFR,iBAAiB;2CAAjB,iBAAiB;CAoF7B;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAKa,yBAAyB;yCAAzB,yBAAyB;2CAAzB,yBAAyB;CAAG;AAEzC;;;;;;;;;;;;GAYG;AACH,qBASa,wBAAwB;yCAAxB,wBAAwB;2CAAxB,wBAAwB;CAAG"}
1
+ {"version":3,"file":"dialog.component.d.ts","sourceRoot":"","sources":["../../../src/lib/dialog/dialog.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,YAAY,EAKZ,SAAS,EAEV,MAAM,eAAe,CAAC;;AAEvB,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAU9D;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBA2Ca,iBAAkB,YAAW,SAAS;IACjD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAK;IAE1B,IACI,OAAO,CAAC,KAAK,EAAE,OAAO,EASzB;IACD,IAAI,OAAO,IAAI,OAAO,CAErB;IAEQ,KAAK,SAAM;IACX,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAQ;IACrC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAQ;IACtC,IAAI,EAAE,YAAY,CAAU;IAC5B,SAAS,UAAQ;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAExC;;;;;OAKG;IACM,IAAI,EAAE,QAAQ,GAAG,aAAa,CAAY;IAEzC,KAAK,qBAA4B;IAE3C,QAAQ,SAA8B;IAEtC,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,aAAa,IAAI,MAAM,CAK1B;IAED,6CAA6C;IAC7C,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,IAAI,cAAc,IAAI,MAAM,CAK3B;IAED,8CAA8C;IAC9C,IAAI,cAAc,IAAI,MAAM,CAE3B;IAGD,WAAW,IAAI,IAAI;IAMnB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAMnC,YAAY,IAAI,IAAI;IAIpB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,eAAe;IAIvB,WAAW,IAAI,IAAI;yCA3FR,iBAAiB;2CAAjB,iBAAiB;CA8F7B;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAKa,yBAAyB;yCAAzB,yBAAyB;2CAAzB,yBAAyB;CAAG;AAEzC;;;;;;;;;;;;GAYG;AACH,qBASa,wBAAwB;yCAAxB,wBAAwB;2CAAxB,wBAAwB;CAAG"}
@@ -113,18 +113,26 @@ export class MJDialogComponent {
113
113
  get dialogId() {
114
114
  return this.DialogId;
115
115
  }
116
- get resolvedWidth() {
116
+ get ResolvedWidth() {
117
117
  if (this.Width) {
118
118
  return typeof this.Width === 'number' ? `${this.Width}px` : this.Width;
119
119
  }
120
120
  return SIZE_MAP[this.Size] ?? 'auto';
121
121
  }
122
- get resolvedHeight() {
122
+ /** @deprecated Use {@link ResolvedWidth}. */
123
+ get resolvedWidth() {
124
+ return this.ResolvedWidth;
125
+ }
126
+ get ResolvedHeight() {
123
127
  if (this.Height) {
124
128
  return typeof this.Height === 'number' ? `${this.Height}px` : this.Height;
125
129
  }
126
130
  return 'auto';
127
131
  }
132
+ /** @deprecated Use {@link ResolvedHeight}. */
133
+ get resolvedHeight() {
134
+ return this.ResolvedHeight;
135
+ }
128
136
  OnEscapeKey() {
129
137
  if (this.Visible && this.Closeable) {
130
138
  this.OnCloseClick();
@@ -255,7 +263,7 @@ export class MJDialogTitlebarComponent {
255
263
  template: `<ng-content></ng-content>`
256
264
  }]
257
265
  }], null, null); })();
258
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJDialogTitlebarComponent, { className: "MJDialogTitlebarComponent", filePath: "lib/dialog/dialog.component.ts", lineNumber: 192 }); })();
266
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJDialogTitlebarComponent, { className: "MJDialogTitlebarComponent", filePath: "lib/dialog/dialog.component.ts", lineNumber: 202 }); })();
259
267
  /**
260
268
  * mj-dialog-actions — Footer action bar for mj-dialog.
261
269
  *
@@ -290,5 +298,5 @@ export class MJDialogActionsComponent {
290
298
  `
291
299
  }]
292
300
  }], null, null); })();
293
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJDialogActionsComponent, { className: "MJDialogActionsComponent", filePath: "lib/dialog/dialog.component.ts", lineNumber: 216 }); })();
301
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJDialogActionsComponent, { className: "MJDialogActionsComponent", filePath: "lib/dialog/dialog.component.ts", lineNumber: 226 }); })();
294
302
  //# sourceMappingURL=dialog.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.component.js","sourceRoot":"","sources":["../../../src/lib/dialog/dialog.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,YAAY,EACZ,YAAY,EAMb,MAAM,eAAe,CAAC;;;;;IAmDP,gCAAiE;IAAA,YAAW;IAAA,oBAAK;;;IAArD,4DAAoC;IAAC,cAAW;IAAX,kCAAW;;;;IAI5E,oCAAmF;IAAnD,qNAAS,qBAAc,KAAC;IACtD,0BAAiC;IACnC,oBAAS;;;IARb,iCAAgC;IAC9B,8GAAa;IAGb,qBAAqD;IACrD,kHAAiB;IAKnB,oBAAM;;;IATJ,cAEC;IAFD,uCAEC;IAED,eAIC;IAJD,2CAIC;;;;IAtBT,iCAAkE;IAAlC,2LAAS,8BAAuB,KAAC;IAC/D,iCAQqC;IAAnC,kHAAS,wBAAwB,IAAC;IAGlC,iGAA0B;IAe1B,iCAA4B;IAC1B,kBAAyB;IAC3B,oBAAM;IAGN,qBAAoD;IAExD,AADE,oBAAM,EACF;;;IA7BF,cAA6B;IAG7B,AADA,AADA,AADA,6CAA6B,iCACE,qBACL,sBACC;;IAI3B,cAYC;IAZD,2DAYC;;;AAxDX,MAAM,QAAQ,GAAiC;IAC7C,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,QAAQ;IACZ,IAAI,EAAE,MAAM;CACb,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AA4CH,MAAM,OAAO,iBAAiB;IACpB,QAAQ,GAAG,KAAK,CAAC;IACjB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAE1B,IACI,OAAO,CAAC,KAAc;QACxB,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC;QACD,IAAI,CAAC,KAAK,IAAI,UAAU,EAAE,CAAC;YACzB,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IACD,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAEQ,KAAK,GAAG,EAAE,CAAC;IACX,KAAK,GAA2B,IAAI,CAAC;IACrC,MAAM,GAA2B,IAAI,CAAC;IACtC,IAAI,GAAiB,MAAM,CAAC;IAC5B,SAAS,GAAG,IAAI,CAAC;IACjB,QAAQ,GAAkB,IAAI,CAAC;IAExC;;;;;OAKG;IACM,IAAI,GAA6B,QAAQ,CAAC;IAEzC,KAAK,GAAG,IAAI,YAAY,EAAQ,CAAC;IAE3C,QAAQ,GAAG,iBAAiB,CAAC,MAAM,EAAE,CAAC;IAEtC,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,IAAI,aAAa;QACf,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;QACzE,CAAC;QACD,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;IACvC,CAAC;IAED,IAAI,cAAc;QAChB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QAC5E,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAGD,WAAW;QACT,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED,eAAe,CAAC,KAAY;QAC1B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED,YAAY;QACV,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAEO,MAAM;QACZ,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1C,CAAC;IAEO,eAAe;QACrB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC;IACpC,CAAC;IAED,WAAW;QACT,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC;IACpC,CAAC;2GAnFU,iBAAiB;6DAAjB,iBAAiB;YAAjB,wGAAA,iBAAa,0BAAI;;;YAvC1B,oFAAe;;YAAf,sCAoCC;;;iFAGQ,iBAAiB;cA3C7B,SAAS;eAAC;gBACT,QAAQ,EAAE,WAAW;gBACrB,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCT;aACF;;kBAKE,KAAK;;kBAeL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBAQL,KAAK;;kBAEL,MAAM;;kBAsBN,YAAY;mBAAC,yBAAyB;;kFAxD5B,iBAAiB;AAsF9B;;;;;;;;;;;;;;GAcG;AAMH,MAAM,OAAO,yBAAyB;mHAAzB,yBAAyB;6DAAzB,yBAAyB;;YAFzB,kBAAyB;;;iFAEzB,yBAAyB;cALrC,SAAS;eAAC;gBACT,QAAQ,EAAE,oBAAoB;gBAC9B,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE,2BAA2B;aACtC;;kFACY,yBAAyB;AAEtC;;;;;;;;;;;;GAYG;AAUH,MAAM,OAAO,wBAAwB;kHAAxB,wBAAwB;6DAAxB,wBAAwB;;YALjC,iCAA+B;YAC7B,kBAAyB;YAC3B,oBAAM;;;iFAGG,wBAAwB;cATpC,SAAS;eAAC;gBACT,QAAQ,EAAE,mBAAmB;gBAC7B,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE;;;;GAIT;aACF;;kFACY,wBAAwB","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n HostListener,\n ElementRef,\n ViewChild,\n AfterViewInit,\n OnDestroy,\n inject\n} from '@angular/core';\n\nexport type MjDialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'auto';\n\nconst SIZE_MAP: Record<MjDialogSize, string> = {\n sm: '400px',\n md: '600px',\n lg: '800px',\n xl: '1000px',\n auto: 'auto'\n};\n\n/**\n * mj-dialog — Modal dialog component using native `<dialog>` element.\n *\n * Replaces `<kendo-dialog>`.\n *\n * Supports both explicit width/height and size presets.\n * Content is projected, with an optional `<mj-dialog-actions>` for the footer.\n *\n * @example\n * ```html\n * <mj-dialog [Visible]=\"showDialog\" Title=\"Confirm\" (Close)=\"onClose()\">\n * <p>Are you sure?</p>\n * <mj-dialog-actions>\n * <button mjButton variant=\"primary\" (click)=\"onConfirm()\">Yes</button>\n * <button mjButton (click)=\"onClose()\">No</button>\n * </mj-dialog-actions>\n * </mj-dialog>\n * ```\n */\n@Component({\n selector: 'mj-dialog',\n standalone: true,\n template: `\n @if (Visible) {\n <div class=\"mj-dialog-backdrop\" (click)=\"OnBackdropClick($event)\">\n <div class=\"mj-dialog-container\"\n [attr.role]=\"Role\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"Title ? 'mj-dialog-title-' + dialogId : null\"\n [style.width]=\"resolvedWidth\"\n [style.height]=\"resolvedHeight\"\n [style.max-width]=\"'90vw'\"\n [style.max-height]=\"'90vh'\"\n (click)=\"$event.stopPropagation()\">\n\n <!-- Title bar -->\n @if (Title || Closeable) {\n <div class=\"mj-dialog-titlebar\">\n @if (Title) {\n <h2 class=\"mj-dialog-title\" [id]=\"'mj-dialog-title-' + dialogId\">{{ Title }}</h2>\n }\n <ng-content select=\"mj-dialog-titlebar\"></ng-content>\n @if (Closeable) {\n <button class=\"mj-dialog-close\" (click)=\"OnCloseClick()\" aria-label=\"Close dialog\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n }\n\n <!-- Body -->\n <div class=\"mj-dialog-body\">\n <ng-content></ng-content>\n </div>\n\n <!-- Actions (projected) -->\n <ng-content select=\"mj-dialog-actions\"></ng-content>\n </div>\n </div>\n }\n `\n})\nexport class MJDialogComponent implements OnDestroy {\n private _visible = false;\n private static nextId = 0;\n\n @Input()\n set Visible(value: boolean) {\n const wasVisible = this._visible;\n this._visible = value;\n if (value && !wasVisible) {\n this.onOpen();\n }\n if (!value && wasVisible) {\n this.onCloseInternal();\n }\n }\n get Visible(): boolean {\n return this._visible;\n }\n\n @Input() Title = '';\n @Input() Width: number | string | null = null;\n @Input() Height: number | string | null = null;\n @Input() Size: MjDialogSize = 'auto';\n @Input() Closeable = true;\n @Input() MinWidth: number | null = null;\n\n /**\n * ARIA role for the dialog container. Defaults to `'dialog'`; pass\n * `'alertdialog'` for confirmation / destructive prompts that interrupt the\n * user (per WAI-ARIA, an alertdialog conveys an urgent message requiring a\n * response). Backward compatible — existing callers keep `'dialog'`.\n */\n @Input() Role: 'dialog' | 'alertdialog' = 'dialog';\n\n @Output() Close = new EventEmitter<void>();\n\n DialogId = MJDialogComponent.nextId++;\n\n get dialogId(): number {\n return this.DialogId;\n }\n\n get resolvedWidth(): string {\n if (this.Width) {\n return typeof this.Width === 'number' ? `${this.Width}px` : this.Width;\n }\n return SIZE_MAP[this.Size] ?? 'auto';\n }\n\n get resolvedHeight(): string {\n if (this.Height) {\n return typeof this.Height === 'number' ? `${this.Height}px` : this.Height;\n }\n return 'auto';\n }\n\n @HostListener('document:keydown.escape')\n OnEscapeKey(): void {\n if (this.Visible && this.Closeable) {\n this.OnCloseClick();\n }\n }\n\n OnBackdropClick(event: Event): void {\n if (this.Closeable) {\n this.OnCloseClick();\n }\n }\n\n OnCloseClick(): void {\n this.Close.emit();\n }\n\n private onOpen(): void {\n document.body.style.overflow = 'hidden';\n }\n\n private onCloseInternal(): void {\n document.body.style.overflow = '';\n }\n\n ngOnDestroy(): void {\n document.body.style.overflow = '';\n }\n}\n\n/**\n * mj-dialog-titlebar — Custom titlebar content for mj-dialog.\n *\n * Replaces `<kendo-dialog-titlebar>`.\n *\n * @example\n * ```html\n * <mj-dialog [Visible]=\"show\" (Close)=\"onClose()\">\n * <mj-dialog-titlebar>\n * <i class=\"fa-solid fa-save\"></i> Custom Title\n * </mj-dialog-titlebar>\n * <p>Dialog content</p>\n * </mj-dialog>\n * ```\n */\n@Component({\n selector: 'mj-dialog-titlebar',\n standalone: true,\n template: `<ng-content></ng-content>`\n})\nexport class MJDialogTitlebarComponent {}\n\n/**\n * mj-dialog-actions — Footer action bar for mj-dialog.\n *\n * Replaces `<kendo-dialog-actions>`.\n *\n * @example\n * ```html\n * <mj-dialog-actions>\n * <button mjButton variant=\"primary\">Save</button>\n * <button mjButton>Cancel</button>\n * </mj-dialog-actions>\n * ```\n */\n@Component({\n selector: 'mj-dialog-actions',\n standalone: true,\n template: `\n <div class=\"mj-dialog-actions\">\n <ng-content></ng-content>\n </div>\n `\n})\nexport class MJDialogActionsComponent {}\n"]}
1
+ {"version":3,"file":"dialog.component.js","sourceRoot":"","sources":["../../../src/lib/dialog/dialog.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n HostListener,\n ElementRef,\n ViewChild,\n AfterViewInit,\n OnDestroy,\n inject\n} from '@angular/core';\n\nexport type MjDialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'auto';\n\nconst SIZE_MAP: Record<MjDialogSize, string> = {\n sm: '400px',\n md: '600px',\n lg: '800px',\n xl: '1000px',\n auto: 'auto'\n};\n\n/**\n * mj-dialog — Modal dialog component using native `<dialog>` element.\n *\n * Replaces `<kendo-dialog>`.\n *\n * Supports both explicit width/height and size presets.\n * Content is projected, with an optional `<mj-dialog-actions>` for the footer.\n *\n * @example\n * ```html\n * <mj-dialog [Visible]=\"showDialog\" Title=\"Confirm\" (Close)=\"onClose()\">\n * <p>Are you sure?</p>\n * <mj-dialog-actions>\n * <button mjButton variant=\"primary\" (click)=\"onConfirm()\">Yes</button>\n * <button mjButton (click)=\"onClose()\">No</button>\n * </mj-dialog-actions>\n * </mj-dialog>\n * ```\n */\n@Component({\n selector: 'mj-dialog',\n standalone: true,\n template: `\n @if (Visible) {\n <div class=\"mj-dialog-backdrop\" (click)=\"OnBackdropClick($event)\">\n <div class=\"mj-dialog-container\"\n [attr.role]=\"Role\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"Title ? 'mj-dialog-title-' + dialogId : null\"\n [style.width]=\"resolvedWidth\"\n [style.height]=\"resolvedHeight\"\n [style.max-width]=\"'90vw'\"\n [style.max-height]=\"'90vh'\"\n (click)=\"$event.stopPropagation()\">\n\n <!-- Title bar -->\n @if (Title || Closeable) {\n <div class=\"mj-dialog-titlebar\">\n @if (Title) {\n <h2 class=\"mj-dialog-title\" [id]=\"'mj-dialog-title-' + dialogId\">{{ Title }}</h2>\n }\n <ng-content select=\"mj-dialog-titlebar\"></ng-content>\n @if (Closeable) {\n <button class=\"mj-dialog-close\" (click)=\"OnCloseClick()\" aria-label=\"Close dialog\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n }\n\n <!-- Body -->\n <div class=\"mj-dialog-body\">\n <ng-content></ng-content>\n </div>\n\n <!-- Actions (projected) -->\n <ng-content select=\"mj-dialog-actions\"></ng-content>\n </div>\n </div>\n }\n `\n})\nexport class MJDialogComponent implements OnDestroy {\n private _visible = false;\n private static nextId = 0;\n\n @Input()\n set Visible(value: boolean) {\n const wasVisible = this._visible;\n this._visible = value;\n if (value && !wasVisible) {\n this.onOpen();\n }\n if (!value && wasVisible) {\n this.onCloseInternal();\n }\n }\n get Visible(): boolean {\n return this._visible;\n }\n\n @Input() Title = '';\n @Input() Width: number | string | null = null;\n @Input() Height: number | string | null = null;\n @Input() Size: MjDialogSize = 'auto';\n @Input() Closeable = true;\n @Input() MinWidth: number | null = null;\n\n /**\n * ARIA role for the dialog container. Defaults to `'dialog'`; pass\n * `'alertdialog'` for confirmation / destructive prompts that interrupt the\n * user (per WAI-ARIA, an alertdialog conveys an urgent message requiring a\n * response). Backward compatible — existing callers keep `'dialog'`.\n */\n @Input() Role: 'dialog' | 'alertdialog' = 'dialog';\n\n @Output() Close = new EventEmitter<void>();\n\n DialogId = MJDialogComponent.nextId++;\n\n get dialogId(): number { // case-violation-ok-legacy-back-compat: the PascalCase name is already taken in this scope\n return this.DialogId;\n }\n\n get ResolvedWidth(): string {\n if (this.Width) {\n return typeof this.Width === 'number' ? `${this.Width}px` : this.Width;\n }\n return SIZE_MAP[this.Size] ?? 'auto';\n }\n\n /** @deprecated Use {@link ResolvedWidth}. */\n get resolvedWidth(): string {\n return this.ResolvedWidth;\n }\n\n get ResolvedHeight(): string {\n if (this.Height) {\n return typeof this.Height === 'number' ? `${this.Height}px` : this.Height;\n }\n return 'auto';\n }\n\n /** @deprecated Use {@link ResolvedHeight}. */\n get resolvedHeight(): string {\n return this.ResolvedHeight;\n }\n\n @HostListener('document:keydown.escape')\n OnEscapeKey(): void {\n if (this.Visible && this.Closeable) {\n this.OnCloseClick();\n }\n }\n\n OnBackdropClick(event: Event): void {\n if (this.Closeable) {\n this.OnCloseClick();\n }\n }\n\n OnCloseClick(): void {\n this.Close.emit();\n }\n\n private onOpen(): void {\n document.body.style.overflow = 'hidden';\n }\n\n private onCloseInternal(): void {\n document.body.style.overflow = '';\n }\n\n ngOnDestroy(): void {\n document.body.style.overflow = '';\n }\n}\n\n/**\n * mj-dialog-titlebar — Custom titlebar content for mj-dialog.\n *\n * Replaces `<kendo-dialog-titlebar>`.\n *\n * @example\n * ```html\n * <mj-dialog [Visible]=\"show\" (Close)=\"onClose()\">\n * <mj-dialog-titlebar>\n * <i class=\"fa-solid fa-save\"></i> Custom Title\n * </mj-dialog-titlebar>\n * <p>Dialog content</p>\n * </mj-dialog>\n * ```\n */\n@Component({\n selector: 'mj-dialog-titlebar',\n standalone: true,\n template: `<ng-content></ng-content>`\n})\nexport class MJDialogTitlebarComponent {}\n\n/**\n * mj-dialog-actions — Footer action bar for mj-dialog.\n *\n * Replaces `<kendo-dialog-actions>`.\n *\n * @example\n * ```html\n * <mj-dialog-actions>\n * <button mjButton variant=\"primary\">Save</button>\n * <button mjButton>Cancel</button>\n * </mj-dialog-actions>\n * ```\n */\n@Component({\n selector: 'mj-dialog-actions',\n standalone: true,\n template: `\n <div class=\"mj-dialog-actions\">\n <ng-content></ng-content>\n </div>\n `\n})\nexport class MJDialogActionsComponent {}\n"]}