@yoozsoft/yoozsoft-ng 5.3.5 → 7.1.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 (113) hide show
  1. package/README.md +143 -24
  2. package/assets/js/UTIF.js-master/LICENSE +21 -21
  3. package/assets/js/UTIF.js-master/README.md +72 -72
  4. package/assets/js/UTIF.js-master/UTIF.js +1762 -1762
  5. package/assets/js/UTIF.js-master/package-lock.json +13 -13
  6. package/assets/js/UTIF.js-master/package.json +24 -0
  7. package/assets/styles/components/_ys-navbar.scss +22 -0
  8. package/assets/styles/components/_ys-pagination.scss +10 -0
  9. package/assets/styles/{ys-layout.scss → utilities/ys-layout.scss} +1 -1
  10. package/assets/styles/ys-styles.scss +2 -0
  11. package/autocomplete/package.json +4 -0
  12. package/date/package.json +4 -0
  13. package/datepicker/package.json +4 -0
  14. package/dropdown/package.json +4 -0
  15. package/fesm2022/yoozsoft-yoozsoft-ng-autocomplete.mjs +257 -197
  16. package/fesm2022/yoozsoft-yoozsoft-ng-autocomplete.mjs.map +1 -1
  17. package/fesm2022/yoozsoft-yoozsoft-ng-date.mjs +562 -0
  18. package/fesm2022/yoozsoft-yoozsoft-ng-date.mjs.map +1 -0
  19. package/fesm2022/yoozsoft-yoozsoft-ng-datepicker.mjs +600 -837
  20. package/fesm2022/yoozsoft-yoozsoft-ng-datepicker.mjs.map +1 -1
  21. package/fesm2022/yoozsoft-yoozsoft-ng-dropdown.mjs +161 -151
  22. package/fesm2022/yoozsoft-yoozsoft-ng-dropdown.mjs.map +1 -1
  23. package/fesm2022/yoozsoft-yoozsoft-ng-file-upload.mjs +93 -103
  24. package/fesm2022/yoozsoft-yoozsoft-ng-file-upload.mjs.map +1 -1
  25. package/fesm2022/yoozsoft-yoozsoft-ng-footer.mjs +16 -21
  26. package/fesm2022/yoozsoft-yoozsoft-ng-footer.mjs.map +1 -1
  27. package/fesm2022/yoozsoft-yoozsoft-ng-loading.mjs +20 -24
  28. package/fesm2022/yoozsoft-yoozsoft-ng-loading.mjs.map +1 -1
  29. package/fesm2022/yoozsoft-yoozsoft-ng-navbar.mjs +60 -76
  30. package/fesm2022/yoozsoft-yoozsoft-ng-navbar.mjs.map +1 -1
  31. package/fesm2022/yoozsoft-yoozsoft-ng-overlay.mjs +11 -15
  32. package/fesm2022/yoozsoft-yoozsoft-ng-overlay.mjs.map +1 -1
  33. package/fesm2022/yoozsoft-yoozsoft-ng-pagination.mjs +61 -55
  34. package/fesm2022/yoozsoft-yoozsoft-ng-pagination.mjs.map +1 -1
  35. package/fesm2022/yoozsoft-yoozsoft-ng-password-strength.mjs +142 -130
  36. package/fesm2022/yoozsoft-yoozsoft-ng-password-strength.mjs.map +1 -1
  37. package/fesm2022/yoozsoft-yoozsoft-ng-pipes.mjs +44 -0
  38. package/fesm2022/yoozsoft-yoozsoft-ng-pipes.mjs.map +1 -0
  39. package/fesm2022/yoozsoft-yoozsoft-ng-progress.mjs +51 -34
  40. package/fesm2022/yoozsoft-yoozsoft-ng-progress.mjs.map +1 -1
  41. package/fesm2022/yoozsoft-yoozsoft-ng-rating.mjs +155 -0
  42. package/fesm2022/yoozsoft-yoozsoft-ng-rating.mjs.map +1 -0
  43. package/fesm2022/yoozsoft-yoozsoft-ng-select.mjs +78 -80
  44. package/fesm2022/yoozsoft-yoozsoft-ng-select.mjs.map +1 -1
  45. package/fesm2022/yoozsoft-yoozsoft-ng-sidebar.mjs +99 -99
  46. package/fesm2022/yoozsoft-yoozsoft-ng-sidebar.mjs.map +1 -1
  47. package/fesm2022/yoozsoft-yoozsoft-ng-table.mjs +316 -0
  48. package/fesm2022/yoozsoft-yoozsoft-ng-table.mjs.map +1 -0
  49. package/fesm2022/yoozsoft-yoozsoft-ng-tiff-viewer.mjs +128 -114
  50. package/fesm2022/yoozsoft-yoozsoft-ng-tiff-viewer.mjs.map +1 -1
  51. package/fesm2022/yoozsoft-yoozsoft-ng-toast.mjs +112 -62
  52. package/fesm2022/yoozsoft-yoozsoft-ng-toast.mjs.map +1 -1
  53. package/fesm2022/yoozsoft-yoozsoft-ng-validators.mjs +37 -0
  54. package/fesm2022/yoozsoft-yoozsoft-ng-validators.mjs.map +1 -0
  55. package/fesm2022/yoozsoft-yoozsoft-ng.mjs.map +1 -1
  56. package/file-upload/package.json +4 -0
  57. package/footer/package.json +4 -0
  58. package/loading/package.json +4 -0
  59. package/navbar/package.json +4 -0
  60. package/overlay/package.json +4 -0
  61. package/package.json +61 -38
  62. package/pagination/package.json +4 -0
  63. package/password-strength/package.json +4 -0
  64. package/pipes/package.json +4 -0
  65. package/progress/package.json +4 -0
  66. package/rating/package.json +4 -0
  67. package/select/package.json +4 -0
  68. package/sidebar/package.json +4 -0
  69. package/table/package.json +4 -0
  70. package/tiff-viewer/package.json +4 -0
  71. package/toast/package.json +4 -0
  72. package/types/yoozsoft-yoozsoft-ng-autocomplete.d.ts +79 -0
  73. package/types/yoozsoft-yoozsoft-ng-date.d.ts +118 -0
  74. package/types/yoozsoft-yoozsoft-ng-datepicker.d.ts +120 -0
  75. package/types/yoozsoft-yoozsoft-ng-dropdown.d.ts +76 -0
  76. package/types/yoozsoft-yoozsoft-ng-file-upload.d.ts +75 -0
  77. package/types/yoozsoft-yoozsoft-ng-footer.d.ts +26 -0
  78. package/types/yoozsoft-yoozsoft-ng-loading.d.ts +14 -0
  79. package/types/yoozsoft-yoozsoft-ng-navbar.d.ts +60 -0
  80. package/types/yoozsoft-yoozsoft-ng-overlay.d.ts +10 -0
  81. package/types/yoozsoft-yoozsoft-ng-pagination.d.ts +31 -0
  82. package/types/yoozsoft-yoozsoft-ng-password-strength.d.ts +73 -0
  83. package/types/yoozsoft-yoozsoft-ng-pipes.d.ts +11 -0
  84. package/types/yoozsoft-yoozsoft-ng-progress.d.ts +31 -0
  85. package/types/yoozsoft-yoozsoft-ng-rating.d.ts +56 -0
  86. package/types/yoozsoft-yoozsoft-ng-select.d.ts +43 -0
  87. package/types/yoozsoft-yoozsoft-ng-sidebar.d.ts +69 -0
  88. package/types/yoozsoft-yoozsoft-ng-table.d.ts +137 -0
  89. package/types/yoozsoft-yoozsoft-ng-tiff-viewer.d.ts +53 -0
  90. package/types/yoozsoft-yoozsoft-ng-toast.d.ts +66 -0
  91. package/types/yoozsoft-yoozsoft-ng-validators.d.ts +5 -0
  92. package/validators/package.json +4 -0
  93. package/autocomplete/index.d.ts +0 -71
  94. package/datepicker/index.d.ts +0 -291
  95. package/directives/index.d.ts +0 -17
  96. package/dropdown/index.d.ts +0 -62
  97. package/fesm2022/yoozsoft-yoozsoft-ng-directives.mjs +0 -57
  98. package/fesm2022/yoozsoft-yoozsoft-ng-directives.mjs.map +0 -1
  99. package/file-upload/index.d.ts +0 -72
  100. package/footer/index.d.ts +0 -25
  101. package/loading/index.d.ts +0 -13
  102. package/navbar/index.d.ts +0 -56
  103. package/overlay/index.d.ts +0 -11
  104. package/pagination/index.d.ts +0 -29
  105. package/password-strength/index.d.ts +0 -84
  106. package/progress/index.d.ts +0 -28
  107. package/select/index.d.ts +0 -39
  108. package/sidebar/index.d.ts +0 -94
  109. package/tiff-viewer/index.d.ts +0 -52
  110. package/toast/index.d.ts +0 -53
  111. /package/assets/styles/{ys-preloader-9.scss → preloaders/ys-preloader-9.scss} +0 -0
  112. /package/assets/styles/{ys-preloader.scss → preloaders/ys-preloader.scss} +0 -0
  113. /package/{index.d.ts → types/yoozsoft-yoozsoft-ng.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"yoozsoft-yoozsoft-ng-autocomplete.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/src/ys-autocomplete/ys-autocomplete.component.ts","../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/src/ys-autocomplete/ys-autocomplete.component.html","../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/yoozsoft-yoozsoft-ng-autocomplete.ts"],"sourcesContent":["import { ScrollingModule } from '@angular/cdk/scrolling';\r\nimport { NgClass, NgTemplateOutlet } from '@angular/common';\r\nimport { Component, ContentChild, ElementRef, EventEmitter, forwardRef, HostListener, Input, Output, TemplateRef, ViewChild } from '@angular/core';\r\nimport { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';\r\nimport { catchError, debounceTime, distinctUntilChanged, Observable, of, Subject, switchMap } from 'rxjs';\r\n\r\n@Component({\r\n selector: 'ys-autocomplete',\r\n imports: [FormsModule, NgTemplateOutlet, NgClass, ScrollingModule],\r\n templateUrl: './ys-autocomplete.component.html',\r\n styleUrl: './ys-autocomplete.component.scss',\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => YsAutocompleteComponent),\r\n multi: true,\r\n },\r\n ],\r\n})\r\nexport class YsAutocompleteComponent implements ControlValueAccessor {\r\n\r\n searchTerm = '';\r\n filteredOptions: any[] = [];\r\n selectedOptions: any[] = [];\r\n showDropdown = false;\r\n activeIndex = -1;\r\n error: string | null = null;\r\n\r\n /** Array or async function */\r\n @Input() options?: any[] | ((term: string) => Observable<any[]>);\r\n\r\n /** Label display field */\r\n @Input() optionLabel = 'label';\r\n\r\n /** placeholder */\r\n @Input() placeholder: string = '';\r\n\r\n /** Multiple choice mode */\r\n @Input() multiple = false;\r\n\r\n /** Button to clear selection */\r\n @Input() showClear = false;\r\n\r\n @Input() disabled: boolean = false;\r\n\r\n /** Custom template */\r\n @ContentChild(TemplateRef) itemTemplate?: TemplateRef<any>;\r\n\r\n @Input() styleClass?: string;\r\n /** Badge style class on Multiple choice mode */\r\n @Input() badgeStyleClass: string = 'text-bg-light';\r\n @Input() loading: boolean = false;\r\n @Input() loadingMessage: string = 'Loading...';\r\n /** No results found message */\r\n @Input() noResultMessage: string = 'No results found.';\r\n\r\n /** Infinite scroll feature enabled */\r\n @Input() infiniteScroll = false;\r\n\r\n @Input() virtualScroll: boolean = true;\r\n @Input() virtualScrollItemSize: number = 36;\r\n // [virtualScrollOptions]=\"options\"\r\n\r\n /** Event to request more items */\r\n @Output() loadMore = new EventEmitter<string>();\r\n\r\n /** Output selection */\r\n @Output() selected = new EventEmitter<any>();\r\n /** Output selection after removed item */\r\n @Output() removed = new EventEmitter<any>();\r\n\r\n private search$ = new Subject<string>();\r\n private _onChange: (value: any) => void = () => { };\r\n private _onTouched: () => void = () => { };\r\n\r\n @ViewChild('inputRef') inputRef!: ElementRef<HTMLInputElement>;\r\n\r\n get isArrayItems(): boolean { return Array.isArray(this.options); }\r\n get isFunctionItems(): boolean { return typeof this.options === 'function'; }\r\n\r\n constructor(private elRef: ElementRef) { }\r\n\r\n ngOnInit() {\r\n if (Array.isArray(this.options)) {\r\n this.filteredOptions = this.options;\r\n }\r\n\r\n /** Only in async function mode */\r\n if (typeof this.options === 'function') {\r\n const fetchFn = this.options as (term: string) => Observable<any[]>;\r\n this.search$\r\n .pipe(\r\n debounceTime(300),\r\n distinctUntilChanged(),\r\n switchMap((term) => {\r\n this.loading = true;\r\n this.error = null;\r\n return fetchFn(term).pipe(\r\n catchError((err) => {\r\n this.error = 'Error receiving data!';\r\n console.error(err);\r\n return of([]);\r\n })\r\n );\r\n })\r\n )\r\n .subscribe((results) => {\r\n this.filteredOptions = results;\r\n this.loading = false;\r\n this.showDropdown = true;\r\n });\r\n }\r\n\r\n }\r\n\r\n /** For the initial value of FormControl */\r\n writeValue(value: any): void {\r\n if (this.multiple) {\r\n this.selectedOptions = value ? [...value] : [];\r\n } else {\r\n this.searchTerm = value ? this.getLabel(value) : '';\r\n }\r\n }\r\n\r\n registerOnChange(fn: any): void {\r\n this._onChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: any): void {\r\n this._onTouched = fn;\r\n }\r\n\r\n setDisabledState?(isDisabled: boolean): void {\r\n this.disabled = isDisabled;\r\n if (this.inputRef) {\r\n this.inputRef.nativeElement.disabled = isDisabled;\r\n }\r\n }\r\n\r\n onSearchChange() {\r\n const term = this.searchTerm.trim();\r\n\r\n if (Array.isArray(this.options)) {\r\n const lower = term.toLowerCase();\r\n this.filteredOptions = this.options.filter((item) =>\r\n this.getLabel(item).toLowerCase().includes(lower)\r\n );\r\n this.showDropdown = this.filteredOptions.length >= 0;\r\n } else if (typeof this.options === 'function') {\r\n this.search$.next(term);\r\n }\r\n\r\n if (!this.multiple && !term) {\r\n this.clearSelection();\r\n }\r\n }\r\n\r\n getLabel(item: any): string {\r\n if (!item) return '';\r\n if (typeof item === 'string') return item;\r\n if (item && this.optionLabel && item[this.optionLabel]) {\r\n return item[this.optionLabel];\r\n }\r\n return '';\r\n }\r\n\r\n onSelect(item: any) {\r\n if (this.multiple) {\r\n const exists = this.selectedOptions.some(\r\n (x) => this.getLabel(x) === this.getLabel(item)\r\n );\r\n if (!exists) {\r\n this.selectedOptions.push(item);\r\n this._onChange(this.selectedOptions);\r\n this._onTouched();\r\n this.selected.emit(this.selectedOptions);\r\n }\r\n this.searchTerm = '';\r\n this.showDropdown = true;\r\n this.onSearchChange();\r\n } else {\r\n this.searchTerm = this.getLabel(item);\r\n this._onChange(item);\r\n this._onTouched();\r\n this.selected.emit(item);\r\n this.showDropdown = false;\r\n }\r\n\r\n this.activeIndex = -1;\r\n }\r\n\r\n removeItem(item: any) {\r\n this.selectedOptions = this.selectedOptions.filter(\r\n (x) => this.getLabel(x) !== this.getLabel(item)\r\n );\r\n this._onChange(this.selectedOptions);\r\n this.removed.emit(this.selectedOptions);\r\n }\r\n\r\n onScroll(event: Event) {\r\n if (!this.infiniteScroll || this.loading) return;\r\n\r\n const target = event.target as HTMLElement;\r\n const nearBottom = target.scrollHeight - target.scrollTop <= target.clientHeight + 10;\r\n\r\n if (nearBottom) {\r\n // Request more items\r\n this.loadMore.emit(this.searchTerm);\r\n }\r\n }\r\n\r\n clearSelection() {\r\n if (this.multiple) {\r\n this.selectedOptions = [];\r\n this._onChange(this.selectedOptions);\r\n this.removed.emit(this.selectedOptions);\r\n } else {\r\n this.searchTerm = '';\r\n this._onChange(null);\r\n this.selected.emit(null);\r\n }\r\n\r\n this.showDropdown = false;\r\n }\r\n\r\n /** Keyboard control */\r\n @HostListener('keydown', ['$event'])\r\n handleKeyboard(event: KeyboardEvent) {\r\n if (!this.showDropdown || this.filteredOptions.length === 0) return;\r\n\r\n switch (event.key) {\r\n case 'ArrowDown':\r\n this.activeIndex = (this.activeIndex + 1) % this.filteredOptions.length;\r\n event.preventDefault();\r\n break;\r\n case 'ArrowUp':\r\n this.activeIndex =\r\n (this.activeIndex - 1 + this.filteredOptions.length) %\r\n this.filteredOptions.length;\r\n event.preventDefault();\r\n break;\r\n case 'Enter':\r\n if (this.activeIndex >= 0) {\r\n this.onSelect(this.filteredOptions[this.activeIndex]);\r\n event.preventDefault();\r\n }\r\n break;\r\n case 'Escape':\r\n this.showDropdown = false;\r\n break;\r\n }\r\n }\r\n\r\n /** Close by clicking outside */\r\n @HostListener('document:click', ['$event'])\r\n onClickOutside(event: MouseEvent) {\r\n const clickedInside = this.elRef.nativeElement.contains(event.target);\r\n if (!clickedInside) {\r\n this.showDropdown = false;\r\n }\r\n }\r\n\r\n}\r\n","<div class=\"ys-autocomplete position-relative\">\r\n <div class=\"input-group flex-wrap\">\r\n @if (multiple && selectedOptions.length > 0) {\r\n <div class=\"d-flex flex-wrap\">\r\n @for (item of selectedOptions; track item) {\r\n <span class=\"badge me-1 mb-1 p-2 d-flex align-items-center\" [ngClass]=\"badgeStyleClass\">\r\n {{ getLabel(item) }}\r\n <i class=\"fa fa-times ms-2 cursor-pointer\" (click)=\"removeItem(item)\"></i>\r\n </span>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"input-group w-100\">\r\n <input #inputRef type=\"text\" class=\"form-control\" [placeholder]=\"placeholder\" [(ngModel)]=\"searchTerm\"\r\n (input)=\"onSearchChange()\" (focus)=\"showDropdown = true\" [ngClass]=\"styleClass\" />\r\n\r\n @if (showClear) {\r\n @if ((multiple && selectedOptions.length > 0) || (!multiple && searchTerm)) {\r\n <button class=\"btn btn-outline-secondary btn-clear\" type=\"button\" id=\"btn-clear\" (click)=\"clearSelection()\"\r\n [disabled]=\"disabled\">\r\n <span class=\"fa fa-times\"></span>\r\n </button>\r\n }\r\n }\r\n <span class=\"input-group-text\" (click)=\"showDropdown = !showDropdown\">\r\n <i class=\"fa fa-search\"></i>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n @if (showDropdown) {\r\n <div class=\"dropdown-container position-absolute w-100 shadow-sm bg-white border rounded\">\r\n @if (loading) {\r\n <div class=\"list-group-item text-center\">\r\n <i class=\"fa fa-spinner fa-spin me-2\"></i>{{ loadingMessage }}\r\n </div>\r\n }\r\n @else if (error) {\r\n <div class=\"list-group-item text-danger text-center\">{{ error }}</div>\r\n }\r\n @else if (filteredOptions.length === 0) {\r\n <div class=\"list-group-item text-muted text-center\">\r\n {{ noResultMessage }}\r\n </div>\r\n }\r\n <!-- ✅ حالت Virtual Scroll برای لیست‌های بزرگ -->\r\n @else if (virtualScroll && filteredOptions.length > 100) {\r\n <cdk-virtual-scroll-viewport [itemSize]=\"virtualScrollItemSize\" class=\"list-group w-100 overflow-y-auto\">\r\n <ul class=\"list-group w-100\">\r\n @for (item of filteredOptions; track item; let i = $index) {\r\n <li class=\"list-group-item list-group-item-action\" [class.active]=\"i === activeIndex\"\r\n (click)=\"onSelect(item)\">\r\n @if (itemTemplate) {\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n } @else {\r\n {{ getLabel(item) }}\r\n }\r\n </li>\r\n }\r\n </ul>\r\n </cdk-virtual-scroll-viewport>\r\n }\r\n <!-- ✅ حالت معمولی برای لیست‌های کوچک -->\r\n @else {\r\n <ul class=\"list-group w-100 overflow-y-auto\" [class.scrollable]=\"infiniteScroll\" (scroll)=\"onScroll($event)\">\r\n @for (item of filteredOptions; track item; let i = $index) {\r\n <li class=\"list-group-item list-group-item-action\" [class.active]=\"i === activeIndex\"\r\n (click)=\"onSelect(item)\">\r\n @if (itemTemplate) {\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n } @else {\r\n {{ getLabel(item) }}\r\n }\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n\r\n</div>","/*\r\n * Public API Surface of ys-autocomplete\r\n */\r\n\r\nexport * from './src/ys-autocomplete/ys-autocomplete.component';\r\n\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"yoozsoft-yoozsoft-ng-autocomplete.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/src/ys-autocomplete/ys-autocomplete.ts","../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/src/ys-autocomplete/ys-autocomplete.html","../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/yoozsoft-yoozsoft-ng-autocomplete.ts"],"sourcesContent":["import { ScrollingModule } from '@angular/cdk/scrolling';\r\nimport { isPlatformBrowser, NgTemplateOutlet } from '@angular/common';\r\nimport { ChangeDetectionStrategy, Component, computed, ContentChild, DestroyRef, ElementRef, forwardRef, inject, input, output, PLATFORM_ID, signal, TemplateRef, viewChild } from '@angular/core';\r\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\r\nimport { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';\r\nimport { catchError, debounceTime, distinctUntilChanged, finalize, fromEvent, Observable, of, switchMap } from 'rxjs';\r\n\r\n@Component({\r\n selector: 'ys-autocomplete',\r\n imports: [\r\n FormsModule,\r\n NgTemplateOutlet,\r\n ScrollingModule\r\n ],\r\n templateUrl: './ys-autocomplete.html',\r\n styleUrl: './ys-autocomplete.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => YsAutocomplete),\r\n multi: true,\r\n },\r\n ],\r\n})\r\nexport class YsAutocomplete<T = any> implements ControlValueAccessor {\r\n\r\n /********************* Inputs */\r\n options = input<T[] | ((term: string) => Observable<T[]>)>([]);\r\n\r\n loading = input(false);\r\n loadingMessage = input('Loading...');\r\n noResultMessage = input('No results found.');\r\n\r\n optionLabel = input('label');\r\n placeholder = input('');\r\n\r\n multiple = input(false);\r\n showClear = input(false);\r\n disabled = input(false);\r\n\r\n styleClass = input<string>();\r\n selectionStyleClass = input('text-bg-light');\r\n clearIconClass = input('fa fa-times');\r\n searchIconClass = input('fa fa-search');\r\n loadingIconClass = input('fa fa-spinner fa-spin');\r\n multipleCheckIconClass = input('fa fa-check');\r\n\r\n infiniteScroll = input(false);\r\n virtualScroll = input(true);\r\n virtualScrollItemSize = input(36);\r\n virtualScrollThreshold = input(100);\r\n\r\n trackBy = input<(item: T) => unknown>();\r\n compareWith = input<(a: T, b: T) => boolean>();\r\n\r\n /********************* Outputs */\r\n /** Event to request more items */\r\n loadMore = output<string>();\r\n\r\n /** Return selected options */\r\n selectionChange = output<T | T[] | null>();\r\n\r\n\r\n /********************* Signals */\r\n searchTerm = signal('');\r\n filteredOptions = signal<T[]>([]);\r\n selectedOptions = signal<T[]>([]);\r\n showDropdown = signal(false);\r\n activeIndex = signal(-1);\r\n error = signal<string | null>(null);\r\n\r\n private readonly internalLoading = signal(false);\r\n readonly isLoading = computed(() => this.loading() || this.internalLoading());\r\n private disabledState = signal(false);\r\n readonly isDisabled = computed(() => this.disabled() || this.disabledState());\r\n\r\n private static nextId = 0;\r\n readonly componentId = `ys-autocomplete-${YsAutocomplete.nextId++}`;\r\n\r\n readonly activeOptionId = computed(() => {\r\n\r\n const index = this.activeIndex();\r\n\r\n return index >= 0\r\n ? `${this.componentId}-option-${index}`\r\n : null;\r\n\r\n });\r\n\r\n\r\n /********************* ViewChild */\r\n inputRef = viewChild<ElementRef<HTMLInputElement>>('inputRef');\r\n\r\n\r\n /********************* Inject */\r\n private readonly destroyRef = inject(DestroyRef);\r\n private readonly host = inject(ElementRef<HTMLElement>);\r\n private readonly platformId = inject(PLATFORM_ID);\r\n readonly isBrowser = isPlatformBrowser(this.platformId);\r\n\r\n /** Custom template */\r\n @ContentChild(TemplateRef) itemTemplate?: TemplateRef<any>;\r\n\r\n private onChange = (_: unknown) => { };\r\n private onTouched = () => { };\r\n\r\n constructor() {\r\n\r\n if (this.isBrowser) {\r\n\r\n fromEvent<MouseEvent>(\r\n document,\r\n 'click'\r\n )\r\n .pipe(\r\n takeUntilDestroyed(this.destroyRef)\r\n )\r\n .subscribe(event => {\r\n\r\n const target =\r\n event.target as Node;\r\n\r\n if (\r\n !this.host.nativeElement.contains(\r\n target\r\n )\r\n ) {\r\n this.showDropdown.set(false);\r\n }\r\n\r\n });\r\n }\r\n\r\n toObservable(this.searchTerm)\r\n .pipe(debounceTime(300), distinctUntilChanged(),\r\n\r\n switchMap(term => {\r\n\r\n const source = this.options();\r\n\r\n if (Array.isArray(source)) {\r\n\r\n const lower = term.toLowerCase();\r\n\r\n return of(\r\n source.filter(item =>\r\n this\r\n .getLabel(item)\r\n .toLowerCase()\r\n .includes(lower)\r\n )\r\n );\r\n }\r\n\r\n this.internalLoading.set(true);\r\n this.error.set(null);\r\n\r\n return source(term).pipe(\r\n catchError(error => {\r\n\r\n console.error(error);\r\n\r\n this.error.set('Error receiving data!');\r\n\r\n return of([]);\r\n\r\n }),\r\n\r\n finalize(() => {\r\n this.internalLoading.set(false);\r\n })\r\n );\r\n\r\n }),\r\n\r\n takeUntilDestroyed(this.destroyRef)\r\n )\r\n .subscribe(result => {\r\n\r\n this.filteredOptions.set(result);\r\n\r\n // this.showDropdown.set(\r\n // result.length > 0\r\n // );\r\n\r\n });\r\n\r\n }\r\n\r\n writeValue(value: T | T[]): void {\r\n\r\n if (this.multiple()) {\r\n\r\n this.selectedOptions.set(\r\n Array.isArray(value)\r\n ? [...value]\r\n : []\r\n );\r\n\r\n return;\r\n }\r\n\r\n this.searchTerm.set(\r\n value\r\n ? this.getLabel(value as T)\r\n : ''\r\n );\r\n\r\n }\r\n\r\n registerOnChange(fn: any): void {\r\n this.onChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: any): void {\r\n this.onTouched = fn;\r\n }\r\n\r\n setDisabledState?(isDisabled: boolean): void {\r\n this.disabledState.set(isDisabled);\r\n }\r\n\r\n onInput(event: Event): void {\r\n const value = (event.target as HTMLInputElement).value;\r\n this.onSearchChange(value);\r\n }\r\n\r\n private onSearchChange(term: string) {\r\n this.searchTerm.set(term.trim());\r\n\r\n if (Array.isArray(this.options())) {\r\n const lower = term.toLowerCase();\r\n this.filteredOptions.set(\r\n (this.options() as T[]).filter(item =>\r\n this.getLabel(item).toLowerCase().includes(lower)\r\n )\r\n );\r\n this.showDropdown.set(true);\r\n }\r\n\r\n if (!this.multiple && !term) {\r\n this.clearSelection();\r\n }\r\n }\r\n\r\n getLabel(item: T): string {\r\n\r\n if (item === null || item === undefined) {\r\n return '';\r\n }\r\n\r\n if (typeof item === 'string' || typeof item === 'number') {\r\n return String(item);\r\n }\r\n\r\n const key = this.optionLabel();\r\n const value = (item as any)?.[key];\r\n\r\n return value != null\r\n ? String(value)\r\n : '';\r\n\r\n }\r\n\r\n private isEqual(a: T, b: T): boolean {\r\n\r\n const comparer = this.compareWith();\r\n\r\n if (comparer) {\r\n return comparer(a, b);\r\n }\r\n\r\n return this.getLabel(a) === this.getLabel(b);\r\n }\r\n\r\n onSelect(item: any) {\r\n if (this.multiple()) {\r\n this.selectedOptions.update(list =>\r\n list.some(x => this.isEqual(x, item))\r\n ? list.filter(x => !this.isEqual(x, item)) // ✅ حذف\r\n : [...list, item] // ✅ اضافه\r\n );\r\n\r\n const value = this.selectedOptions();\r\n this.onChange(value);\r\n this.onTouched();\r\n this.selectionChange.emit(value);\r\n\r\n this.searchTerm.set('');\r\n this.showDropdown.set(true);\r\n this.onSearchChange(this.searchTerm());\r\n\r\n } else {\r\n this.searchTerm.set(this.getLabel(item));\r\n this.onChange(item);\r\n this.onTouched();\r\n this.selectionChange.emit(item);\r\n this.showDropdown.set(false);\r\n }\r\n\r\n this.activeIndex.set(-1);\r\n\r\n this.inputRef()?.nativeElement.focus();\r\n }\r\n\r\n removeItem(item: any) {\r\n const prev = this.selectedOptions();\r\n\r\n this.selectedOptions.update(list =>\r\n list.filter(x => !this.isEqual(x, item))\r\n );\r\n\r\n if (prev !== this.selectedOptions()) {\r\n const value = this.selectedOptions();\r\n this.onChange(value);\r\n this.selectionChange.emit(value);\r\n }\r\n }\r\n\r\n onScroll(event: Event) {\r\n if (!this.infiniteScroll || this.isLoading()) return;\r\n\r\n const target = event.target as HTMLElement;\r\n const nearBottom = target.scrollHeight - target.scrollTop <= target.clientHeight + 10;\r\n\r\n if (nearBottom) {\r\n // Request more items\r\n this.loadMore.emit(this.searchTerm());\r\n }\r\n }\r\n\r\n clearSelection() {\r\n if (this.multiple()) {\r\n this.selectedOptions.set([]);\r\n const value = this.selectedOptions();\r\n this.onChange(value);\r\n this.selectionChange.emit(value);\r\n } else {\r\n this.searchTerm.set('');\r\n this.onChange(null);\r\n this.selectionChange.emit(null);\r\n }\r\n\r\n // this.showDropdown.set(false);\r\n }\r\n\r\n handleKeyboard(event: KeyboardEvent) {\r\n const list = this.filteredOptions();\r\n if (list.length === 0) {\r\n return;\r\n }\r\n\r\n if (!this.showDropdown()) {\r\n this.showDropdown.set(true);\r\n }\r\n\r\n switch (event.key) {\r\n case 'ArrowDown':\r\n // برو به آیتم بعدی\r\n this.activeIndex.update(i => (i + 1) % list.length);\r\n event.preventDefault();\r\n break;\r\n case 'ArrowUp':\r\n // برو به آیتم قبلی\r\n this.activeIndex.update(i => (i - 1 + list.length) % list.length);\r\n event.preventDefault();\r\n break;\r\n case 'Enter':\r\n const index = this.activeIndex();\r\n if (index >= 0 && index < list.length) {\r\n this.onSelect(list[index]);\r\n }\r\n event.preventDefault();\r\n break;\r\n case 'Escape':\r\n this.showDropdown.set(false);\r\n break;\r\n case 'Home':\r\n this.activeIndex.set(0);\r\n event.preventDefault();\r\n break;\r\n case 'End':\r\n this.activeIndex.set(list.length - 1);\r\n event.preventDefault();\r\n break;\r\n case 'Tab':\r\n this.showDropdown.set(false);\r\n break;\r\n case 'PageUp':\r\n this.activeIndex.update(i =>\r\n Math.max(0, i - 10)\r\n );\r\n event.preventDefault();\r\n break;\r\n case 'PageDown':\r\n this.activeIndex.update(i =>\r\n Math.min(list.length - 1, i + 10)\r\n );\r\n event.preventDefault();\r\n break;\r\n }\r\n }\r\n\r\n isSelected(item: T): boolean {\r\n return this.selectedOptions()\r\n .some(x => this.isEqual(x, item));\r\n }\r\n\r\n trackItem(item: T) {\r\n return this.trackBy()?.(item)\r\n ?? this.getLabel(item);\r\n }\r\n\r\n}\r\n","<div class=\"ys-autocomplete position-relative\">\n <div class=\"input-group flex-wrap\">\n @if (multiple() && selectedOptions().length > 0) {\n <div class=\"d-flex flex-wrap\">\n @for (item of selectedOptions(); track trackItem(item)) {\n <span class=\"badge me-1 mb-1 p-2 d-flex align-items-center\" [class]=\"selectionStyleClass()\">\n {{ getLabel(item) }}\n <i class=\"ms-2 cursor-pointer\" [class]=\"clearIconClass()\" (click)=\"removeItem(item)\"></i>\n </span>\n }\n </div>\n }\n\n <div class=\"input-group w-100\">\n <input #inputRef type=\"text\" class=\"form-control\" [class]=\"styleClass()\" [placeholder]=\"placeholder()\"\n [value]=\"searchTerm()\" (input)=\"onInput($event)\" (keydown)=\"handleKeyboard($event)\"\n (focus)=\"showDropdown.set(true)\" (click)=\"showDropdown.set(true)\" role=\"combobox\"\n aria-autocomplete=\"list\" [attr.aria-expanded]=\"showDropdown()\" aria-haspopup=\"listbox\"\n [attr.aria-activedescendant]=\"activeOptionId()\" [disabled]=\"isDisabled()\" />\n\n @if (showClear()) {\n @if ((multiple() && selectedOptions().length > 0) || (!multiple() && searchTerm())) {\n <button class=\"btn btn-outline-secondary btn-clear\" type=\"button\" id=\"btn-clear\" (click)=\"clearSelection()\"\n [disabled]=\"isDisabled()\">\n <span [class]=\"clearIconClass()\"></span>\n </button>\n }\n }\n <span class=\"input-group-text\" (click)=\"showDropdown.set( !showDropdown())\">\n <i [class]=\"searchIconClass()\"></i>\n </span>\n </div>\n </div>\n\n @if (showDropdown()) {\n <div class=\"dropdown-container position-absolute w-100 shadow-sm bg-white border rounded\">\n @if (isLoading()) {\n <div class=\"list-group-item text-center\">\n <i class=\"me-2\" [class]=\"loadingIconClass()\"></i>{{ loadingMessage() }}\n </div>\n }\n @else if (error()) {\n <div class=\"list-group-item text-danger text-center\">{{ error() }}</div>\n }\n @else if (filteredOptions().length === 0) {\n <div class=\"list-group-item text-muted text-center\">\n {{ noResultMessage() }}\n </div>\n }\n <!-- ✅ حالت Virtual Scroll برای لیست‌های بزرگ -->\n @else if (virtualScroll() && filteredOptions().length > virtualScrollThreshold()) {\n <cdk-virtual-scroll-viewport [itemSize]=\"virtualScrollItemSize()\" class=\"list-group w-100\">\n\n <div [id]=\"componentId + '-option-' + i\" *cdkVirtualFor=\"let item of filteredOptions(); let i = index\"\n class=\"list-group-item list-group-item-action\" [class.active]=\"i === activeIndex()\"\n [class.selected]=\"isSelected(item)\" (click)=\"onSelect(item)\">\n\n @if (itemTemplate) {\n\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: {$implicit: item}\"> </ng-container>\n\n } @else {\n\n @if(multiple()){\n <i class=\"me-1 text-success\" [class]=\"multipleCheckIconClass()\" [class.invisible]=\"!isSelected(item)\">\n </i>\n }\n\n {{ getLabel(item) }}\n\n }\n\n </div>\n\n </cdk-virtual-scroll-viewport>\n\n }\n <!-- ✅ حالت معمولی برای لیست‌های کوچک -->\n @else {\n <ul class=\"list-group w-100 overflow-y-auto\" [class.scrollable]=\"infiniteScroll()\" (scroll)=\"onScroll($event)\"\n role=\"listbox\">\n @for (item of filteredOptions(); track trackItem(item); let i = $index) {\n <li [id]=\"componentId + '-option-' + i\" class=\"list-group-item list-group-item-action\"\n [class.active]=\"i === activeIndex()\" [class.selected]=\"isSelected(item)\" (click)=\"onSelect(item)\"\n role=\"option\" [attr.aria-selected]=\"isSelected(item)\">\n @if (itemTemplate) {\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\n } @else {\n @if(multiple()){\n <i class=\"me-1 text-success\" [class]=\"multipleCheckIconClass()\" [class.invisible]=\"!isSelected(item)\">\n </i>\n }\n {{ getLabel(item) }}\n }\n </li>\n }\n </ul>\n }\n </div>\n\n }\n\n</div>","/*\r\n * Public API Surface of ys-autocomplete\r\n */\r\n\r\nexport * from './src/ys-autocomplete/ys-autocomplete';\r\n\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,562 @@
1
+ const GREGORIAN_MONTHS = [
2
+ 'January',
3
+ 'February',
4
+ 'March',
5
+ 'April',
6
+ 'May',
7
+ 'June',
8
+ 'July',
9
+ 'August',
10
+ 'September',
11
+ 'October',
12
+ 'November',
13
+ 'December'
14
+ ];
15
+ const GREGORIAN_WEEKDAYS = [
16
+ 'Monday',
17
+ 'Tuesday',
18
+ 'Wednesday',
19
+ 'Thursday',
20
+ 'Friday',
21
+ 'Saturday',
22
+ 'Sunday',
23
+ ];
24
+ const PERSIAN_MONTHS = [
25
+ 'فروردین',
26
+ 'اردیبهشت',
27
+ 'خرداد',
28
+ 'تیر',
29
+ 'مرداد',
30
+ 'شهریور',
31
+ 'مهر',
32
+ 'آبان',
33
+ 'آذر',
34
+ 'دی',
35
+ 'بهمن',
36
+ 'اسفند'
37
+ ];
38
+ const PERSIAN_MONTH_SHORT = [
39
+ 'فرو',
40
+ 'ارد',
41
+ 'خرد',
42
+ 'تیر',
43
+ 'مرد',
44
+ 'شهر',
45
+ 'مهر',
46
+ 'آبا',
47
+ 'آذر',
48
+ 'دی',
49
+ 'بهم',
50
+ 'اسف'
51
+ ];
52
+ const PERSIAN_WEEKDAYS = [
53
+ 'دوشنبه',
54
+ 'سه‌شنبه',
55
+ 'چهارشنبه',
56
+ 'پنجشنبه',
57
+ 'جمعه',
58
+ 'شنبه',
59
+ 'یکشنبه'
60
+ ];
61
+ const PERSIAN_WEEKDAYS_SHORT = [
62
+ 'د',
63
+ 'س',
64
+ 'چ',
65
+ 'پ',
66
+ 'ج',
67
+ 'ش',
68
+ 'ی'
69
+ ];
70
+
71
+ class JalaliDate {
72
+ static calendarDaysInMonth = {
73
+ g_days_in_month: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
74
+ j_days_in_month: [31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29],
75
+ };
76
+ // private static readonly supportedTokens = [
77
+ // 'yyyy',
78
+ // 'yy',
79
+ // 'MMMM',
80
+ // 'MM',
81
+ // 'M',
82
+ // 'dd',
83
+ // 'd',
84
+ // 'HH',
85
+ // 'H',
86
+ // 'mm',
87
+ // 'm',
88
+ // 'ss',
89
+ // 's',
90
+ // 'EEEE'
91
+ // ];
92
+ static validateJalaliDate(year, month, day) {
93
+ if (year < 1) {
94
+ throw new Error('Invalid Jalali year');
95
+ }
96
+ if (month < 1 || month > 12) {
97
+ throw new Error('Invalid Jalali month');
98
+ }
99
+ const maxDay = this.daysInMonth(year, month);
100
+ if (day < 1 || day > maxDay) {
101
+ throw new Error('Invalid Jalali day');
102
+ }
103
+ }
104
+ static validateGregorianDate(year, month, day) {
105
+ if (year < 1) {
106
+ throw new Error('Invalid Gregorian year');
107
+ }
108
+ if (month < 1 || month > 12) {
109
+ throw new Error('Invalid Gregorian month');
110
+ }
111
+ let maxDay = this.calendarDaysInMonth.g_days_in_month[month - 1];
112
+ // Check leap year for February
113
+ if (month === 2 && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0)) {
114
+ maxDay = 29;
115
+ }
116
+ if (day < 1 || day > maxDay) {
117
+ throw new Error('Invalid Gregorian day');
118
+ }
119
+ }
120
+ // validation
121
+ static isValid(year, month, day) {
122
+ if (year < 1)
123
+ return false;
124
+ if (month < 1 || month > 12) {
125
+ return false;
126
+ }
127
+ return day >= 1 &&
128
+ day <= this.daysInMonth(year, month);
129
+ }
130
+ static isLeapYear(year) {
131
+ const mod = year % 33;
132
+ return [
133
+ 1, 5, 9, 13,
134
+ 17, 22, 26, 30
135
+ ].includes(mod);
136
+ }
137
+ // month
138
+ static daysInMonth(year, month) {
139
+ if (month <= 6) {
140
+ return 31;
141
+ }
142
+ if (month <= 11) {
143
+ return 30;
144
+ }
145
+ return this.isLeapYear(year)
146
+ ? 30
147
+ : 29;
148
+ }
149
+ static monthName(month) {
150
+ return PERSIAN_MONTHS[month - 1] ?? '';
151
+ }
152
+ static weekdayName(day) {
153
+ return PERSIAN_WEEKDAYS[day] ?? '';
154
+ }
155
+ // week
156
+ static dayOfWeek(year, month, day) {
157
+ const date = this.toDate({
158
+ year,
159
+ month,
160
+ day
161
+ });
162
+ const jsDay = date.getDay();
163
+ return jsDay === 0
164
+ ? 7
165
+ : jsDay;
166
+ }
167
+ static weekDayName(day) {
168
+ return PERSIAN_WEEKDAYS[day] ?? '';
169
+ }
170
+ // current
171
+ static today() {
172
+ return this.fromDate(new Date());
173
+ }
174
+ // compare
175
+ static compare(a, b) {
176
+ const d1 = this.toDate(a).getTime();
177
+ const d2 = this.toDate(b).getTime();
178
+ if (d1 === d2) {
179
+ return 0;
180
+ }
181
+ return d1 > d2 ? 1 : -1;
182
+ }
183
+ // parse
184
+ static parse(value) {
185
+ const match = value.match(/^(\d{4})[-\/](\d{1,2})[-\/](\d{1,2})$/);
186
+ if (!match) {
187
+ return null;
188
+ }
189
+ const date = {
190
+ year: +match[1],
191
+ month: +match[2],
192
+ day: +match[3]
193
+ };
194
+ return this.isValid(date.year, date.month, date.day)
195
+ ? date
196
+ : null;
197
+ }
198
+ // arithmetic
199
+ static addDays(date, days) {
200
+ const result = this.toDate(date);
201
+ result.setDate(result.getDate() + days);
202
+ return this.fromDate(result);
203
+ }
204
+ static addMonths(date, months) {
205
+ const result = this.toDate(date);
206
+ result.setMonth(result.getMonth() + months);
207
+ return this.fromDate(result);
208
+ }
209
+ static addYears(date, years) {
210
+ const result = this.toDate(date);
211
+ result.setFullYear(result.getFullYear() + years);
212
+ return this.fromDate(result);
213
+ }
214
+ // conversion helpers
215
+ static fromDate(date) {
216
+ const jDate = this.gregorianToJalali(date.getFullYear(), date.getMonth() + 1, date.getDate());
217
+ return {
218
+ year: jDate.year,
219
+ month: jDate.month,
220
+ day: jDate.day
221
+ };
222
+ }
223
+ static toDate(date) {
224
+ const gDate = this.jalaliToGregorian(date.year, date.month, date.day);
225
+ return new Date(gDate.year, gDate.month - 1, gDate.day);
226
+ }
227
+ // format
228
+ static format(value, format = 'yyyy/MM/dd') {
229
+ let date;
230
+ if (value instanceof Date) {
231
+ date = value;
232
+ }
233
+ else {
234
+ date = new Date(value);
235
+ }
236
+ if (isNaN(date.getTime())) {
237
+ return '';
238
+ }
239
+ const j = this.gregorianToJalali(date.getFullYear(), date.getMonth() + 1, date.getDate());
240
+ const pad = (v) => String(v).padStart(2, '0');
241
+ const weekdayIndex = (date.getDay() + 1) % 7;
242
+ const tokens = {
243
+ yyyy: String(j.year),
244
+ yy: String(j.year).slice(-2),
245
+ MM: pad(j.month),
246
+ M: String(j.month),
247
+ dd: pad(j.day),
248
+ d: String(j.day),
249
+ HH: pad(date.getHours()),
250
+ H: String(date.getHours()),
251
+ mm: pad(date.getMinutes()),
252
+ m: String(date.getMinutes()),
253
+ ss: pad(date.getSeconds()),
254
+ s: String(date.getSeconds()),
255
+ MMMM: PERSIAN_MONTHS[j.month - 1],
256
+ EEEE: PERSIAN_WEEKDAYS[weekdayIndex]
257
+ };
258
+ return format.replace(/yyyy|yy|MMMM|MM|M|dd|d|HH|H|mm|m|ss|s|EEEE/g, token => tokens[token]);
259
+ }
260
+ // conversion
261
+ static gregorianToJalali(year, month, day) {
262
+ // Floor inputs
263
+ year = Math.floor(year);
264
+ month = Math.floor(month);
265
+ day = Math.floor(day);
266
+ // Validate inputs
267
+ this.validateGregorianDate(year, month, day);
268
+ let gy = year - 1600;
269
+ let gm = month - 1;
270
+ let gd = day - 1;
271
+ // Calculate number of days passed since Gregorian epoch
272
+ let g_day_no = 365 * gy +
273
+ Math.floor((gy + 3) / 4) -
274
+ Math.floor((gy + 99) / 100) +
275
+ Math.floor((gy + 399) / 400);
276
+ for (let i = 0; i < gm; ++i)
277
+ g_day_no += this.calendarDaysInMonth.g_days_in_month[i];
278
+ if (gm > 1 &&
279
+ ((gy % 4 === 0 && gy % 100 !== 0) || gy % 400 === 0))
280
+ g_day_no++;
281
+ g_day_no += gd;
282
+ let j_day_no = g_day_no - 79;
283
+ let j_np = Math.floor(j_day_no / 12053);
284
+ j_day_no %= 12053;
285
+ let jy = 979 + 33 * j_np + 4 * Math.floor(j_day_no / 1461);
286
+ j_day_no %= 1461;
287
+ if (j_day_no >= 366) {
288
+ jy += Math.floor((j_day_no - 1) / 365);
289
+ j_day_no = (j_day_no - 1) % 365;
290
+ }
291
+ let jm = 0;
292
+ let jd = 0;
293
+ for (let i = 0; i < 11 && j_day_no >= this.calendarDaysInMonth.j_days_in_month[i]; ++i) {
294
+ j_day_no -= this.calendarDaysInMonth.j_days_in_month[i];
295
+ jm = i + 1;
296
+ }
297
+ jm++;
298
+ jd = j_day_no + 1;
299
+ return {
300
+ year: jy,
301
+ month: jm,
302
+ day: jd
303
+ };
304
+ }
305
+ static jalaliToGregorian(year, month, day) {
306
+ // Floor inputs to make sure they are integers
307
+ year = Math.floor(year);
308
+ month = Math.floor(month);
309
+ day = Math.floor(day);
310
+ // Validate inputs
311
+ this.validateJalaliDate(year, month, day);
312
+ let jy = year - 979;
313
+ let jm = month - 1;
314
+ let jd = day - 1;
315
+ // Calculate number of days passed since Jalali epoch
316
+ let j_day_no = 365 * jy + Math.floor(jy / 33) * 8 + Math.floor(((jy % 33) + 3) / 4);
317
+ for (let i = 0; i < jm; ++i)
318
+ j_day_no += this.calendarDaysInMonth.j_days_in_month[i];
319
+ j_day_no += jd;
320
+ // Convert to Gregorian day number
321
+ let g_day_no = j_day_no + 79;
322
+ // Calculate Gregorian year
323
+ let gy = 1600 + 400 * Math.floor(g_day_no / 146097);
324
+ g_day_no %= 146097;
325
+ let leap = true;
326
+ if (g_day_no >= 36525) {
327
+ g_day_no--;
328
+ gy += 100 * Math.floor(g_day_no / 36524);
329
+ g_day_no %= 36524;
330
+ if (g_day_no >= 365)
331
+ g_day_no++;
332
+ else
333
+ leap = false;
334
+ }
335
+ gy += 4 * Math.floor(g_day_no / 1461);
336
+ g_day_no %= 1461;
337
+ if (g_day_no >= 366) {
338
+ leap = false;
339
+ g_day_no--;
340
+ gy += Math.floor(g_day_no / 365);
341
+ g_day_no %= 365;
342
+ }
343
+ // Calculate Gregorian month and day
344
+ let gm = 0;
345
+ let gd = 0;
346
+ for (let i = 0; g_day_no >=
347
+ this.calendarDaysInMonth.g_days_in_month[i] + (i === 1 && leap ? 1 : 0); i++) {
348
+ g_day_no -= this.calendarDaysInMonth.g_days_in_month[i] + (i === 1 && leap ? 1 : 0);
349
+ gm = i + 1;
350
+ }
351
+ gm++;
352
+ gd = g_day_no + 1;
353
+ return {
354
+ year: gy,
355
+ month: gm,
356
+ day: gd
357
+ };
358
+ }
359
+ static toNgbDateStruct(date) {
360
+ return {
361
+ year: date.year,
362
+ month: date.month,
363
+ day: date.day
364
+ };
365
+ }
366
+ static fromNgbDateStruct(date) {
367
+ return {
368
+ year: date.year,
369
+ month: date.month,
370
+ day: date.day
371
+ };
372
+ }
373
+ static isBetween(value, start, end) {
374
+ return (this.compare(value, start) >= 0 &&
375
+ this.compare(value, end) <= 0);
376
+ }
377
+ }
378
+
379
+ class GregorianCalendarAdapter {
380
+ today() {
381
+ const now = new Date();
382
+ return {
383
+ year: now.getFullYear(),
384
+ month: now.getMonth() + 1,
385
+ day: now.getDate()
386
+ };
387
+ }
388
+ isValid(year, month, day) {
389
+ const date = new Date(year, month - 1, day);
390
+ return (date.getFullYear() === year &&
391
+ date.getMonth() === month - 1 &&
392
+ date.getDate() === day);
393
+ }
394
+ daysInMonth(year, month) {
395
+ return new Date(year, month, 0).getDate();
396
+ }
397
+ dayOfWeek(year, month, day) {
398
+ const jsDay = new Date(year, month - 1, day).getDay();
399
+ return jsDay === 0
400
+ ? 7
401
+ : jsDay;
402
+ }
403
+ monthName(month) {
404
+ return GREGORIAN_MONTHS[month - 1] ?? '';
405
+ }
406
+ weekdayName(day) {
407
+ return GREGORIAN_WEEKDAYS[day] ?? '';
408
+ }
409
+ compare(a, b) {
410
+ const t1 = this.toDate(a).getTime();
411
+ const t2 = this.toDate(b).getTime();
412
+ if (t1 === t2) {
413
+ return 0;
414
+ }
415
+ return t1 > t2 ? 1 : -1;
416
+ }
417
+ addDays(date, days) {
418
+ const d = this.toDate(date);
419
+ d.setDate(d.getDate() + days);
420
+ return this.fromDate(d);
421
+ }
422
+ addMonths(date, months) {
423
+ const d = this.toDate(date);
424
+ d.setMonth(d.getMonth() + months);
425
+ return this.fromDate(d);
426
+ }
427
+ addYears(date, years) {
428
+ const d = this.toDate(date);
429
+ d.setFullYear(d.getFullYear() + years);
430
+ return this.fromDate(d);
431
+ }
432
+ toDate(date) {
433
+ return new Date(date.year, date.month - 1, date.day);
434
+ }
435
+ fromDate(date) {
436
+ return {
437
+ year: date.getFullYear(),
438
+ month: date.getMonth() + 1,
439
+ day: date.getDate()
440
+ };
441
+ }
442
+ parse(value) {
443
+ const match = value.match(/^(\d{4})[-\/](\d{1,2})[-\/](\d{1,2})$/);
444
+ if (!match) {
445
+ return null;
446
+ }
447
+ const result = {
448
+ year: +match[1],
449
+ month: +match[2],
450
+ day: +match[3]
451
+ };
452
+ return this.isValid(result.year, result.month, result.day)
453
+ ? result
454
+ : null;
455
+ }
456
+ format(value, format = 'yyyy/MM/dd') {
457
+ const date = value instanceof Date
458
+ ? value
459
+ : new Date(value);
460
+ if (isNaN(date.getTime())) {
461
+ return '';
462
+ }
463
+ const pad = (v) => String(v).padStart(2, '0');
464
+ return format
465
+ .replace('yyyy', String(date.getFullYear()))
466
+ .replace('MM', pad(date.getMonth() + 1))
467
+ .replace('dd', pad(date.getDate()));
468
+ }
469
+ isBetween(value, start, end) {
470
+ return (this.compare(value, start) >= 0 &&
471
+ this.compare(value, end) <= 0);
472
+ }
473
+ }
474
+
475
+ class JalaliCalendarAdapter {
476
+ today() {
477
+ return JalaliDate.toNgbDateStruct(JalaliDate.today());
478
+ }
479
+ isValid(year, month, day) {
480
+ return JalaliDate.isValid(year, month, day);
481
+ }
482
+ daysInMonth(year, month) {
483
+ return JalaliDate.daysInMonth(year, month);
484
+ }
485
+ dayOfWeek(year, month, day) {
486
+ return JalaliDate.dayOfWeek(year, month, day);
487
+ }
488
+ monthName(month) {
489
+ return JalaliDate.monthName(month);
490
+ }
491
+ weekdayName(day) {
492
+ return JalaliDate.weekdayName(day);
493
+ }
494
+ compare(a, b) {
495
+ return JalaliDate.compare(JalaliDate.fromNgbDateStruct(a), JalaliDate.fromNgbDateStruct(b));
496
+ }
497
+ addDays(date, days) {
498
+ return JalaliDate.toNgbDateStruct(JalaliDate.addDays(JalaliDate.fromNgbDateStruct(date), days));
499
+ }
500
+ addMonths(date, months) {
501
+ return JalaliDate.toNgbDateStruct(JalaliDate.addMonths(JalaliDate.fromNgbDateStruct(date), months));
502
+ }
503
+ addYears(date, years) {
504
+ return JalaliDate.toNgbDateStruct(JalaliDate.addYears(JalaliDate.fromNgbDateStruct(date), years));
505
+ }
506
+ toDate(date) {
507
+ return JalaliDate.toDate(JalaliDate.fromNgbDateStruct(date));
508
+ }
509
+ fromDate(date) {
510
+ return JalaliDate.toNgbDateStruct(JalaliDate.fromDate(date));
511
+ }
512
+ parse(value) {
513
+ const result = JalaliDate.parse(value);
514
+ return result
515
+ ? JalaliDate.toNgbDateStruct(result)
516
+ : null;
517
+ }
518
+ format(value, format = 'yyyy/MM/dd') {
519
+ return JalaliDate.format(value, format);
520
+ }
521
+ isBetween(value, start, end) {
522
+ return JalaliDate.isBetween(JalaliDate.fromNgbDateStruct(value), JalaliDate.fromNgbDateStruct(start), JalaliDate.fromNgbDateStruct(end));
523
+ }
524
+ }
525
+
526
+ function createCalendarAdapter(type) {
527
+ return type === 'jalali'
528
+ ? new JalaliCalendarAdapter()
529
+ : new GregorianCalendarAdapter();
530
+ }
531
+
532
+ function compareDates(a, b) {
533
+ if (a.year !== b.year) {
534
+ return a.year - b.year;
535
+ }
536
+ if (a.month !== b.month) {
537
+ return a.month - b.month;
538
+ }
539
+ return a.day - b.day;
540
+ }
541
+ function dateToStruct(date) {
542
+ return {
543
+ year: date.getFullYear(),
544
+ month: date.getMonth() + 1,
545
+ day: date.getDate()
546
+ };
547
+ }
548
+ function structToDate(date) {
549
+ return new Date(date.year, date.month - 1, date.day, 12, // noon
550
+ 0, 0, 0);
551
+ }
552
+
553
+ /*
554
+ * Public API Surface of ys jalali date features
555
+ */
556
+
557
+ /**
558
+ * Generated bundle index. Do not edit.
559
+ */
560
+
561
+ export { GREGORIAN_MONTHS, GREGORIAN_WEEKDAYS, GregorianCalendarAdapter, JalaliCalendarAdapter, JalaliDate, PERSIAN_MONTHS, PERSIAN_MONTH_SHORT, PERSIAN_WEEKDAYS, PERSIAN_WEEKDAYS_SHORT, compareDates, createCalendarAdapter, dateToStruct, structToDate };
562
+ //# sourceMappingURL=yoozsoft-yoozsoft-ng-date.mjs.map