@ngstarter-ui/components 21.0.30 → 21.0.32

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 (40) hide show
  1. package/ai/component-registry.json +58 -14
  2. package/fesm2022/{ngstarter-ui-components-content-editor-code-block.component-CKrOhA7h.mjs → ngstarter-ui-components-content-editor-code-block.component-BZniTqu-.mjs} +2 -2
  3. package/fesm2022/{ngstarter-ui-components-content-editor-code-block.component-CKrOhA7h.mjs.map → ngstarter-ui-components-content-editor-code-block.component-BZniTqu-.mjs.map} +1 -1
  4. package/fesm2022/{ngstarter-ui-components-content-editor-embed-block-zSApBzF3.mjs → ngstarter-ui-components-content-editor-embed-block-QzDMzd3u.mjs} +2 -2
  5. package/fesm2022/{ngstarter-ui-components-content-editor-embed-block-zSApBzF3.mjs.map → ngstarter-ui-components-content-editor-embed-block-QzDMzd3u.mjs.map} +1 -1
  6. package/fesm2022/{ngstarter-ui-components-content-editor-heading-block.component-Dv8d0nCy.mjs → ngstarter-ui-components-content-editor-heading-block.component-CnYRnDBY.mjs} +2 -2
  7. package/fesm2022/{ngstarter-ui-components-content-editor-heading-block.component-Dv8d0nCy.mjs.map → ngstarter-ui-components-content-editor-heading-block.component-CnYRnDBY.mjs.map} +1 -1
  8. package/fesm2022/{ngstarter-ui-components-content-editor-image-block.component-g-H7a5Z_.mjs → ngstarter-ui-components-content-editor-image-block.component-IP_eRCQ2.mjs} +2 -2
  9. package/fesm2022/{ngstarter-ui-components-content-editor-image-block.component-g-H7a5Z_.mjs.map → ngstarter-ui-components-content-editor-image-block.component-IP_eRCQ2.mjs.map} +1 -1
  10. package/fesm2022/{ngstarter-ui-components-content-editor-list-block.component-PgqisgxY.mjs → ngstarter-ui-components-content-editor-list-block.component-amyfzXOW.mjs} +2 -2
  11. package/fesm2022/{ngstarter-ui-components-content-editor-list-block.component-PgqisgxY.mjs.map → ngstarter-ui-components-content-editor-list-block.component-amyfzXOW.mjs.map} +1 -1
  12. package/fesm2022/{ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-BuMm25ea.mjs → ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-DA-VnRa_.mjs} +453 -36
  13. package/fesm2022/ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-DA-VnRa_.mjs.map +1 -0
  14. package/fesm2022/{ngstarter-ui-components-content-editor-paragraph-block.component-DS_6CzuA.mjs → ngstarter-ui-components-content-editor-paragraph-block.component-DtophI4_.mjs} +2 -2
  15. package/fesm2022/{ngstarter-ui-components-content-editor-paragraph-block.component-DS_6CzuA.mjs.map → ngstarter-ui-components-content-editor-paragraph-block.component-DtophI4_.mjs.map} +1 -1
  16. package/fesm2022/{ngstarter-ui-components-content-editor-quote-block.component-Df92Nqvp.mjs → ngstarter-ui-components-content-editor-quote-block.component-B20eHQdw.mjs} +2 -2
  17. package/fesm2022/{ngstarter-ui-components-content-editor-quote-block.component-Df92Nqvp.mjs.map → ngstarter-ui-components-content-editor-quote-block.component-B20eHQdw.mjs.map} +1 -1
  18. package/fesm2022/{ngstarter-ui-components-content-editor-table-block.component-D4rdPkGz.mjs → ngstarter-ui-components-content-editor-table-block.component-hJ4OxKRX.mjs} +4 -4
  19. package/fesm2022/{ngstarter-ui-components-content-editor-table-block.component-D4rdPkGz.mjs.map → ngstarter-ui-components-content-editor-table-block.component-hJ4OxKRX.mjs.map} +1 -1
  20. package/fesm2022/{ngstarter-ui-components-content-editor-video-block.component-DqS9Lhp_.mjs → ngstarter-ui-components-content-editor-video-block.component-Cs7L1wwX.mjs} +2 -2
  21. package/fesm2022/{ngstarter-ui-components-content-editor-video-block.component-DqS9Lhp_.mjs.map → ngstarter-ui-components-content-editor-video-block.component-Cs7L1wwX.mjs.map} +1 -1
  22. package/fesm2022/ngstarter-ui-components-content-editor.mjs +1 -1
  23. package/fesm2022/ngstarter-ui-components-country-select.mjs +65 -4
  24. package/fesm2022/ngstarter-ui-components-country-select.mjs.map +1 -1
  25. package/fesm2022/ngstarter-ui-components-currency-select.mjs +65 -4
  26. package/fesm2022/ngstarter-ui-components-currency-select.mjs.map +1 -1
  27. package/fesm2022/ngstarter-ui-components-menu.mjs +10 -6
  28. package/fesm2022/ngstarter-ui-components-menu.mjs.map +1 -1
  29. package/fesm2022/ngstarter-ui-components-phone-input.mjs +113 -29
  30. package/fesm2022/ngstarter-ui-components-phone-input.mjs.map +1 -1
  31. package/fesm2022/ngstarter-ui-components-toolbar.mjs +2 -2
  32. package/fesm2022/ngstarter-ui-components-toolbar.mjs.map +1 -1
  33. package/package.json +1 -1
  34. package/styles/_global.scss +11 -0
  35. package/types/ngstarter-ui-components-content-editor.d.ts +226 -7
  36. package/types/ngstarter-ui-components-country-select.d.ts +12 -0
  37. package/types/ngstarter-ui-components-currency-select.d.ts +12 -0
  38. package/types/ngstarter-ui-components-menu.d.ts +3 -3
  39. package/types/ngstarter-ui-components-phone-input.d.ts +19 -2
  40. package/fesm2022/ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-BuMm25ea.mjs.map +0 -1
@@ -4,7 +4,7 @@ import { UploadArea, UploadTriggerDirective } from '@ngstarter-ui/components/upl
4
4
  import { ProgressBar } from '@ngstarter-ui/components/progress-bar';
5
5
  import { Button } from '@ngstarter-ui/components/button';
6
6
  import { Icon } from '@ngstarter-ui/components/icon';
7
- import { C as ContentBuilderStore, a as CONTENT_BUILDER, b as CONTENT_EDITOR_BLOCK } from './ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-BuMm25ea.mjs';
7
+ import { C as ContentBuilderStore, a as CONTENT_BUILDER, b as CONTENT_EDITOR_BLOCK } from './ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-DA-VnRa_.mjs';
8
8
  import { FormField, Label } from '@ngstarter-ui/components/form-field';
9
9
  import { Input } from '@ngstarter-ui/components/input';
10
10
  import * as i1 from '@angular/forms';
@@ -172,4 +172,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
172
172
  }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: true }] }], settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: true }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: true }] }], _caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "_caption", required: false }] }, { type: i0.Output, args: ["_captionChange"] }], _settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "_settings", required: false }] }, { type: i0.Output, args: ["_settingsChange"] }], videoElement: [{ type: i0.ViewChild, args: ['videoPlayer', { isSignal: true }] }] } });
173
173
 
174
174
  export { VideoBlockComponent };
175
- //# sourceMappingURL=ngstarter-ui-components-content-editor-video-block.component-DqS9Lhp_.mjs.map
175
+ //# sourceMappingURL=ngstarter-ui-components-content-editor-video-block.component-Cs7L1wwX.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ngstarter-ui-components-content-editor-video-block.component-DqS9Lhp_.mjs","sources":["../../../projects/components/content-editor/src/_builder/video-block/video-block.component.ts","../../../projects/components/content-editor/src/_builder/video-block/video-block.component.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component, forwardRef, inject, input, model, OnInit, signal, viewChild, ElementRef } from '@angular/core';\nimport { UploadArea, UploadFileSelectedEvent, UploadTriggerDirective } from '@ngstarter-ui/components/upload';\nimport { ProgressBar } from '@ngstarter-ui/components/progress-bar';\nimport { Button } from '@ngstarter-ui/components/button';\nimport { Icon } from '@ngstarter-ui/components/icon';\nimport {\n CONTENT_BUILDER,\n CONTENT_EDITOR_BLOCK, ContentEditorDataBlock,\n ContentEditorVideoBlockSettings,\n ContentEditorVideoContent\n} from '../../types';\nimport { FormField, Label } from '@ngstarter-ui/components/form-field';\nimport { Input } from '@ngstarter-ui/components/input';\nimport { FormsModule } from '@angular/forms';\nimport { ContentBuilderStore } from '../../content-builder.store';\nimport { ContentBuilderComponent } from '../../content-builder/content-builder.component';\nimport { ResizableContainer } from '@ngstarter-ui/components/resizable-container';\n\n@Component({\n selector: 'ngs-video-block',\n imports: [\n UploadArea,\n UploadTriggerDirective,\n ProgressBar,\n Button,\n Icon,\n FormField,\n Input,\n FormsModule,\n Label,\n ResizableContainer\n ],\n providers: [\n {\n provide: CONTENT_EDITOR_BLOCK,\n useExisting: forwardRef(() => VideoBlockComponent),\n multi: true\n }\n ],\n templateUrl: './video-block.component.html',\n styleUrl: './video-block.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '(keypress)': 'handleKeyPress($event)',\n 'class': 'block'\n }\n})\nexport class VideoBlockComponent implements OnInit, ContentEditorDataBlock {\n private _store = inject(ContentBuilderStore);\n private _contentBuilder = inject<ContentBuilderComponent>(CONTENT_BUILDER);\n\n id = input.required<string>();\n content = input.required<ContentEditorVideoContent>();\n settings = input.required<ContentEditorVideoBlockSettings>();\n index = input.required<number>();\n\n uploading = signal(false);\n selectedVideo = signal<string>('');\n\n protected _src = signal<string>('');\n protected _caption = model<string>('');\n protected _orientation = signal<'portrait' | 'landscape'>('landscape');\n protected _settings = model<ContentEditorVideoBlockSettings>({});\n readonly initialized = signal(false);\n\n readonly videoElement = viewChild<ElementRef<HTMLVideoElement>>('videoPlayer');\n\n private _aspectRatio = 16 / 9;\n\n ngOnInit() {\n this._src.set(this.content().src);\n this._caption.set(this.content().caption);\n this._orientation.set(this.content().orientation || 'landscape');\n this._settings.set(this.settings() || {});\n this.initialized.set(true);\n }\n\n focus() {\n if (this._src()) {\n this._contentBuilder.focusBlock(this.id());\n }\n }\n\n getData(): any {\n return {\n content: {\n src: this._src(),\n caption: this._caption(),\n orientation: this._orientation()\n },\n settings: {\n ...this._settings(),\n }\n };\n }\n\n isEmpty(): boolean {\n const src = this.getData().content.src;\n return typeof src === 'string' ? src.trim().length === 0 : !src;\n }\n\n protected cancelUploading() {\n this.uploading.set(false);\n }\n\n protected onFileSelected(event: UploadFileSelectedEvent): void {\n this.uploading.set(true);\n const reader = new FileReader();\n reader.addEventListener('load', () => {\n this.selectedVideo.set(reader.result as string);\n\n const video = document.createElement('video');\n video.preload = 'metadata';\n video.onloadedmetadata = () => {\n window.URL.revokeObjectURL(video.src);\n const orientation = video.videoWidth > video.videoHeight ? 'landscape' : 'portrait';\n this._orientation.set(orientation);\n this._aspectRatio = video.videoWidth / video.videoHeight;\n\n let width = video.videoWidth;\n let height = video.videoHeight;\n\n if (width > 704) {\n width = 704;\n height = Math.round(width / this._aspectRatio);\n }\n\n if (height > 1000) {\n width = Math.round(width / 2);\n height = Math.round(height / 2);\n }\n\n // Initial settings based on video metadata\n this._settings.update(s => ({\n ...s,\n actualWidth: video.videoWidth,\n actualHeight: video.videoHeight,\n width,\n height\n }));\n };\n video.src = URL.createObjectURL(event.files[0]);\n\n const uploadFn = this._contentBuilder.getBlockDefOption('video', 'uploadFn');\n uploadFn(event.files[0], reader.result)\n .then((url: string) => {\n if (!this.uploading()) {\n this.selectedVideo.set('');\n return;\n }\n\n this._src.set(url);\n this.selectedVideo.set('');\n this.uploading.set(false);\n this.update();\n this.focus();\n });\n }, false);\n reader.readAsDataURL(event.files[0]);\n }\n\n protected _onCaptionChange() {\n this.update();\n }\n\n protected _onVideoResized(event: { width: number }) {\n let width = event.width;\n if (width > 704) {\n width = 704;\n }\n const height = Math.round(width / this._aspectRatio);\n\n this._settings.update(s => ({\n ...s,\n width,\n height\n }));\n\n this.update();\n }\n\n protected _onVideoLoaded(event: any) {\n const video = event.target as HTMLVideoElement;\n this._aspectRatio = video.videoWidth / video.videoHeight;\n }\n\n protected handleKeyPress(event: KeyboardEvent) {\n if (event.key === 'Enter') {\n event.preventDefault();\n event.stopPropagation();\n this._contentBuilder.insertEmptyBlock(this.index());\n }\n }\n\n private update() {\n this._store.updateBlock(this.id(), {...this.getData(), isEmpty: this.isEmpty()});\n this._contentBuilder.emitContentChangeEvent();\n }\n}\n","@if (uploading()) {\n <div class=\"relative flex items-center justify-center overflow-hidden\">\n <div class=\"absolute inset-0 z-10 flex items-center justify-center bg-white/80\">\n <div class=\"absolute top-0 start-0 end-0 z-20\">\n <ngs-progress-bar mode=\"indeterminate\"/>\n </div>\n <div class=\"absolute end-2 top-4 w-max z-30\">\n <button ngsButton (click)=\"cancelUploading()\">\n <ngs-icon name=\"fluent:delete-24-regular\"/>\n </button>\n </div>\n <div class=\"bg-white px-3 text-sm py-1.5 rounded-lg border border-border\">Loading...</div>\n </div>\n <div [style.width.px]=\"_settings().width || null\"\n [style.height.px]=\"_settings().height || null\"\n [class.max-w-full]=\"!_settings().width\">\n <video [src]=\"selectedVideo()\" muted class=\"w-full h-auto block\"></video>\n </div>\n </div>\n} @else if (_src()) {\n <div class=\"flex items-center justify-center overflow-hidden\">\n <ngs-resizable-container (resized)=\"_onVideoResized($event)\"\n [style.width.px]=\"_settings().width || null\"\n [style.height.px]=\"_settings().height || null\"\n [class.max-w-full]=\"!_settings().width\">\n <video #videoPlayer\n [src]=\"_src()\"\n class=\"w-full h-auto block\"\n (loadedmetadata)=\"_onVideoLoaded($event)\"\n controls></video>\n </ngs-resizable-container>\n </div>\n <ngs-form-field class=\"w-full mt-5\">\n <ngs-label>Caption</ngs-label>\n <input ngsInput [(ngModel)]=\"_caption\" (ngModelChange)=\"_onCaptionChange()\">\n </ngs-form-field>\n} @else {\n <ngs-upload-area #uploadArea=\"ngsUploadArea\"\n ngsUploadTrigger accept=\"video/*\"\n (fileSelected)=\"onFileSelected($event)\" multiple=\"false\"\n class=\"cursor-pointer hover:outline-2 hover:outline-[var(--color-primary)]\">\n @if (!uploadArea.api.isDropActive) {\n Drag & drop video here or click to upload\n } @else {\n <div class=\"font-medium\">Drop video here</div>\n }\n </ngs-upload-area>\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngstarter-ui-components-content-editor-video-block.component-Cs7L1wwX.mjs","sources":["../../../projects/components/content-editor/src/_builder/video-block/video-block.component.ts","../../../projects/components/content-editor/src/_builder/video-block/video-block.component.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component, forwardRef, inject, input, model, OnInit, signal, viewChild, ElementRef } from '@angular/core';\nimport { UploadArea, UploadFileSelectedEvent, UploadTriggerDirective } from '@ngstarter-ui/components/upload';\nimport { ProgressBar } from '@ngstarter-ui/components/progress-bar';\nimport { Button } from '@ngstarter-ui/components/button';\nimport { Icon } from '@ngstarter-ui/components/icon';\nimport {\n CONTENT_BUILDER,\n CONTENT_EDITOR_BLOCK, ContentEditorDataBlock,\n ContentEditorVideoBlockSettings,\n ContentEditorVideoContent\n} from '../../types';\nimport { FormField, Label } from '@ngstarter-ui/components/form-field';\nimport { Input } from '@ngstarter-ui/components/input';\nimport { FormsModule } from '@angular/forms';\nimport { ContentBuilderStore } from '../../content-builder.store';\nimport { ContentBuilderComponent } from '../../content-builder/content-builder.component';\nimport { ResizableContainer } from '@ngstarter-ui/components/resizable-container';\n\n@Component({\n selector: 'ngs-video-block',\n imports: [\n UploadArea,\n UploadTriggerDirective,\n ProgressBar,\n Button,\n Icon,\n FormField,\n Input,\n FormsModule,\n Label,\n ResizableContainer\n ],\n providers: [\n {\n provide: CONTENT_EDITOR_BLOCK,\n useExisting: forwardRef(() => VideoBlockComponent),\n multi: true\n }\n ],\n templateUrl: './video-block.component.html',\n styleUrl: './video-block.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '(keypress)': 'handleKeyPress($event)',\n 'class': 'block'\n }\n})\nexport class VideoBlockComponent implements OnInit, ContentEditorDataBlock {\n private _store = inject(ContentBuilderStore);\n private _contentBuilder = inject<ContentBuilderComponent>(CONTENT_BUILDER);\n\n id = input.required<string>();\n content = input.required<ContentEditorVideoContent>();\n settings = input.required<ContentEditorVideoBlockSettings>();\n index = input.required<number>();\n\n uploading = signal(false);\n selectedVideo = signal<string>('');\n\n protected _src = signal<string>('');\n protected _caption = model<string>('');\n protected _orientation = signal<'portrait' | 'landscape'>('landscape');\n protected _settings = model<ContentEditorVideoBlockSettings>({});\n readonly initialized = signal(false);\n\n readonly videoElement = viewChild<ElementRef<HTMLVideoElement>>('videoPlayer');\n\n private _aspectRatio = 16 / 9;\n\n ngOnInit() {\n this._src.set(this.content().src);\n this._caption.set(this.content().caption);\n this._orientation.set(this.content().orientation || 'landscape');\n this._settings.set(this.settings() || {});\n this.initialized.set(true);\n }\n\n focus() {\n if (this._src()) {\n this._contentBuilder.focusBlock(this.id());\n }\n }\n\n getData(): any {\n return {\n content: {\n src: this._src(),\n caption: this._caption(),\n orientation: this._orientation()\n },\n settings: {\n ...this._settings(),\n }\n };\n }\n\n isEmpty(): boolean {\n const src = this.getData().content.src;\n return typeof src === 'string' ? src.trim().length === 0 : !src;\n }\n\n protected cancelUploading() {\n this.uploading.set(false);\n }\n\n protected onFileSelected(event: UploadFileSelectedEvent): void {\n this.uploading.set(true);\n const reader = new FileReader();\n reader.addEventListener('load', () => {\n this.selectedVideo.set(reader.result as string);\n\n const video = document.createElement('video');\n video.preload = 'metadata';\n video.onloadedmetadata = () => {\n window.URL.revokeObjectURL(video.src);\n const orientation = video.videoWidth > video.videoHeight ? 'landscape' : 'portrait';\n this._orientation.set(orientation);\n this._aspectRatio = video.videoWidth / video.videoHeight;\n\n let width = video.videoWidth;\n let height = video.videoHeight;\n\n if (width > 704) {\n width = 704;\n height = Math.round(width / this._aspectRatio);\n }\n\n if (height > 1000) {\n width = Math.round(width / 2);\n height = Math.round(height / 2);\n }\n\n // Initial settings based on video metadata\n this._settings.update(s => ({\n ...s,\n actualWidth: video.videoWidth,\n actualHeight: video.videoHeight,\n width,\n height\n }));\n };\n video.src = URL.createObjectURL(event.files[0]);\n\n const uploadFn = this._contentBuilder.getBlockDefOption('video', 'uploadFn');\n uploadFn(event.files[0], reader.result)\n .then((url: string) => {\n if (!this.uploading()) {\n this.selectedVideo.set('');\n return;\n }\n\n this._src.set(url);\n this.selectedVideo.set('');\n this.uploading.set(false);\n this.update();\n this.focus();\n });\n }, false);\n reader.readAsDataURL(event.files[0]);\n }\n\n protected _onCaptionChange() {\n this.update();\n }\n\n protected _onVideoResized(event: { width: number }) {\n let width = event.width;\n if (width > 704) {\n width = 704;\n }\n const height = Math.round(width / this._aspectRatio);\n\n this._settings.update(s => ({\n ...s,\n width,\n height\n }));\n\n this.update();\n }\n\n protected _onVideoLoaded(event: any) {\n const video = event.target as HTMLVideoElement;\n this._aspectRatio = video.videoWidth / video.videoHeight;\n }\n\n protected handleKeyPress(event: KeyboardEvent) {\n if (event.key === 'Enter') {\n event.preventDefault();\n event.stopPropagation();\n this._contentBuilder.insertEmptyBlock(this.index());\n }\n }\n\n private update() {\n this._store.updateBlock(this.id(), {...this.getData(), isEmpty: this.isEmpty()});\n this._contentBuilder.emitContentChangeEvent();\n }\n}\n","@if (uploading()) {\n <div class=\"relative flex items-center justify-center overflow-hidden\">\n <div class=\"absolute inset-0 z-10 flex items-center justify-center bg-white/80\">\n <div class=\"absolute top-0 start-0 end-0 z-20\">\n <ngs-progress-bar mode=\"indeterminate\"/>\n </div>\n <div class=\"absolute end-2 top-4 w-max z-30\">\n <button ngsButton (click)=\"cancelUploading()\">\n <ngs-icon name=\"fluent:delete-24-regular\"/>\n </button>\n </div>\n <div class=\"bg-white px-3 text-sm py-1.5 rounded-lg border border-border\">Loading...</div>\n </div>\n <div [style.width.px]=\"_settings().width || null\"\n [style.height.px]=\"_settings().height || null\"\n [class.max-w-full]=\"!_settings().width\">\n <video [src]=\"selectedVideo()\" muted class=\"w-full h-auto block\"></video>\n </div>\n </div>\n} @else if (_src()) {\n <div class=\"flex items-center justify-center overflow-hidden\">\n <ngs-resizable-container (resized)=\"_onVideoResized($event)\"\n [style.width.px]=\"_settings().width || null\"\n [style.height.px]=\"_settings().height || null\"\n [class.max-w-full]=\"!_settings().width\">\n <video #videoPlayer\n [src]=\"_src()\"\n class=\"w-full h-auto block\"\n (loadedmetadata)=\"_onVideoLoaded($event)\"\n controls></video>\n </ngs-resizable-container>\n </div>\n <ngs-form-field class=\"w-full mt-5\">\n <ngs-label>Caption</ngs-label>\n <input ngsInput [(ngModel)]=\"_caption\" (ngModelChange)=\"_onCaptionChange()\">\n </ngs-form-field>\n} @else {\n <ngs-upload-area #uploadArea=\"ngsUploadArea\"\n ngsUploadTrigger accept=\"video/*\"\n (fileSelected)=\"onFileSelected($event)\" multiple=\"false\"\n class=\"cursor-pointer hover:outline-2 hover:outline-[var(--color-primary)]\">\n @if (!uploadArea.api.isDropActive) {\n Drag & drop video here or click to upload\n } @else {\n <div class=\"font-medium\">Drop video here</div>\n }\n </ngs-upload-area>\n}\n"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export { B as BlockSelectionDirective, a as CONTENT_BUILDER, b as CONTENT_EDITOR_BLOCK, c as CommandBarComponent, d as ContentBuilderComponent, e as ContentViewerComponent, T as TextSelectionPopupDirective } from './ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-BuMm25ea.mjs';
1
+ export { B as BlockSelectionDirective, a as CONTENT_BUILDER, b as CONTENT_EDITOR_BLOCK, c as CONTENT_EDITOR_BLOCK_RENDERERS, d as CONTENT_EDITOR_DEFAULT_RENDERERS, e as CommandBarComponent, f as ContentBuilderComponent, g as ContentEditorCodeRenderer, h as ContentEditorDividerRenderer, i as ContentEditorEmbedRenderer, j as ContentEditorHeadingRenderer, k as ContentEditorImageRenderer, l as ContentEditorListRenderer, m as ContentEditorParagraphRenderer, n as ContentEditorQuoteRenderer, o as ContentEditorRenderer, p as ContentEditorTableRenderer, q as ContentEditorVideoRenderer, T as TextSelectionPopupDirective, r as provideContentEditorRenderer, s as provideContentEditorRenderers } from './ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-DA-VnRa_.mjs';
2
2
  //# sourceMappingURL=ngstarter-ui-components-content-editor.mjs.map
@@ -263,6 +263,8 @@ const countries = [
263
263
  ];
264
264
 
265
265
  class CountrySelect {
266
+ static COUNTRY_RENDER_CHUNK_SIZE = 32;
267
+ static COUNTRY_RENDER_CHUNK_DELAY = 50;
266
268
  _elementRef = inject(ElementRef);
267
269
  _renderer = inject(Renderer2);
268
270
  _formField = inject(FORM_FIELD, { optional: true });
@@ -270,6 +272,7 @@ class CountrySelect {
270
272
  id = `ngs-country-select-${CountrySelect.nextId++}`;
271
273
  stateChanges = new Subject();
272
274
  searchTerm = model('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : /* istanbul ignore next */ []));
275
+ visibleCountryCount = signal(CountrySelect.COUNTRY_RENDER_CHUNK_SIZE, ...(ngDevMode ? [{ debugName: "visibleCountryCount" }] : /* istanbul ignore next */ []));
273
276
  _valueSignal = signal(null, ...(ngDevMode ? [{ debugName: "_valueSignal" }] : /* istanbul ignore next */ []));
274
277
  _focusedSignal = signal(false, ...(ngDevMode ? [{ debugName: "_focusedSignal" }] : /* istanbul ignore next */ []));
275
278
  _touched = false;
@@ -288,6 +291,9 @@ class CountrySelect {
288
291
  return countries.filter(country => country.name.toLowerCase().includes(filterValue) ||
289
292
  country.code.toLowerCase().includes(filterValue));
290
293
  }, ...(ngDevMode ? [{ debugName: "filteredCountries" }] : /* istanbul ignore next */ []));
294
+ visibleCountries = computed(() => {
295
+ return this.filteredCountries().slice(0, this.visibleCountryCount());
296
+ }, ...(ngDevMode ? [{ debugName: "visibleCountries" }] : /* istanbul ignore next */ []));
291
297
  selectedCountryDisplay = computed(() => {
292
298
  return this.internalCountries.find(c => c.code === this._valueSignal());
293
299
  }, ...(ngDevMode ? [{ debugName: "selectedCountryDisplay" }] : /* istanbul ignore next */ []));
@@ -301,11 +307,14 @@ class CountrySelect {
301
307
  closed = output();
302
308
  onChangeFn = () => { };
303
309
  onTouchedFn = () => { };
310
+ _countryRenderTimeout;
311
+ _countrySearchFocusTimeout;
304
312
  constructor() {
305
313
  if (this.ngControl) {
306
314
  this.ngControl.valueAccessor = this;
307
315
  }
308
316
  this.destroyRef.onDestroy(() => {
317
+ this.clearCountrySelectTimeouts();
309
318
  this.fm.stopMonitoring(this.elRef.nativeElement);
310
319
  this.stateChanges.complete();
311
320
  });
@@ -338,6 +347,7 @@ class CountrySelect {
338
347
  }
339
348
  }
340
349
  ngOnDestroy() {
350
+ this.clearCountrySelectTimeouts();
341
351
  }
342
352
  get value() {
343
353
  return this._valueSignal();
@@ -427,18 +437,27 @@ class CountrySelect {
427
437
  }
428
438
  clearSearch(event) {
429
439
  event.stopPropagation();
430
- this.searchTerm.set('');
440
+ this.onCountrySearch('');
431
441
  this.searchInput().nativeElement.focus();
432
442
  }
443
+ onCountrySearch(searchTerm) {
444
+ this.searchTerm.set(searchTerm);
445
+ this.visibleCountryCount.set(CountrySelect.COUNTRY_RENDER_CHUNK_SIZE);
446
+ this.scheduleCountryRendering();
447
+ }
433
448
  onSelectOpened() {
434
- setTimeout(() => {
449
+ this.visibleCountryCount.set(this.getInitialVisibleCountryCount());
450
+ this.scheduleCountryRendering();
451
+ this._countrySearchFocusTimeout = setTimeout(() => {
435
452
  this.searchInput().nativeElement.focus();
436
453
  });
437
454
  this.opened.emit();
438
455
  }
439
456
  onSelectClosed() {
457
+ this.clearCountrySelectTimeouts();
440
458
  this._focusedSignal.set(false);
441
459
  this.searchTerm.set('');
460
+ this.visibleCountryCount.set(CountrySelect.COUNTRY_RENDER_CHUNK_SIZE);
442
461
  if (!this._touched) {
443
462
  this.onTouchedFn();
444
463
  }
@@ -447,13 +466,55 @@ class CountrySelect {
447
466
  focus() {
448
467
  this.ngsSelect()?.focus();
449
468
  }
469
+ getInitialVisibleCountryCount() {
470
+ const countries = this.filteredCountries();
471
+ const selectedCountryCode = this._valueSignal();
472
+ if (!selectedCountryCode) {
473
+ return CountrySelect.COUNTRY_RENDER_CHUNK_SIZE;
474
+ }
475
+ const selectedCountryIndex = countries.findIndex((country) => country.code === selectedCountryCode);
476
+ if (selectedCountryIndex === -1) {
477
+ return CountrySelect.COUNTRY_RENDER_CHUNK_SIZE;
478
+ }
479
+ return Math.min(Math.max(selectedCountryIndex + 1, CountrySelect.COUNTRY_RENDER_CHUNK_SIZE), countries.length);
480
+ }
481
+ scheduleCountryRendering() {
482
+ this.clearCountryRenderTimeout();
483
+ if (this.visibleCountryCount() >= this.filteredCountries().length) {
484
+ return;
485
+ }
486
+ this._countryRenderTimeout = setTimeout(() => {
487
+ this.visibleCountryCount.update((count) => {
488
+ return Math.min(count + CountrySelect.COUNTRY_RENDER_CHUNK_SIZE, this.filteredCountries().length);
489
+ });
490
+ this.scheduleCountryRendering();
491
+ }, CountrySelect.COUNTRY_RENDER_CHUNK_DELAY);
492
+ }
493
+ clearCountrySelectTimeouts() {
494
+ this.clearCountryRenderTimeout();
495
+ this.clearCountrySearchFocusTimeout();
496
+ }
497
+ clearCountryRenderTimeout() {
498
+ if (!this._countryRenderTimeout) {
499
+ return;
500
+ }
501
+ clearTimeout(this._countryRenderTimeout);
502
+ this._countryRenderTimeout = undefined;
503
+ }
504
+ clearCountrySearchFocusTimeout() {
505
+ if (!this._countrySearchFocusTimeout) {
506
+ return;
507
+ }
508
+ clearTimeout(this._countrySearchFocusTimeout);
509
+ this._countrySearchFocusTimeout = undefined;
510
+ }
450
511
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CountrySelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
451
512
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: CountrySelect, isStandalone: true, selector: "ngs-country-select", inputs: { searchTerm: { classPropertyName: "searchTerm", publicName: "searchTerm", isSignal: true, isRequired: false, transformFunction: null }, placeholderInputSignal: { classPropertyName: "placeholderInputSignal", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, isRequiredSignal: { classPropertyName: "isRequiredSignal", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, isDisabledSignal: { classPropertyName: "isDisabledSignal", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showCountryCode: { classPropertyName: "showCountryCode", publicName: "showCountryCode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchTerm: "searchTermChange", isRequiredSignal: "requiredChange", isDisabledSignal: "disabledChange", opened: "opened", closed: "closed" }, host: { listeners: { "focus": "onFocusIn()", "blur": "onFocusOut($event)" }, properties: { "class.floating": "shouldLabelFloat", "id": "id", "attr.tabindex": "disabled ? -1 : 0" }, classAttribute: "ngs-country-select" }, providers: [
452
513
  {
453
514
  provide: FormFieldControl,
454
515
  useExisting: forwardRef(() => CountrySelect),
455
516
  },
456
- ], viewQueries: [{ propertyName: "ngsSelect", first: true, predicate: ["ngsSelect"], descendants: true, isSignal: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], exportAs: ["ngsCountrySelect"], ngImport: i0, template: "<ngs-select\n #ngsSelect\n [value]=\"value\"\n (selectionChange)=\"onSelectionChange($event)\"\n (opened)=\"onSelectOpened()\"\n (closed)=\"onSelectClosed()\"\n [placeholder]=\"placeholder\"\n [required]=\"isRequiredSignal()\"\n [disabled]=\"isDisabledSignal()\">\n <ngs-select-trigger class=\"select-trigger\">\n @let selectedCountry = selectedCountryDisplay();\n @if (selectedCountry) {\n <span class=\"ngs-select-trigger-content\">\n <span class=\"ngs-select-trigger-icon\">{{ selectedCountry.flag }}</span>\n <span class=\"ngs-select-trigger-text\">\n {{ selectedCountry.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ selectedCountry.code }})</span>\n }\n </span>\n </span>\n }\n\n @if (!selectedCountryDisplay() && placeholder) {\n <span class=\"ngs-select-trigger-text placeholder-text\">\n {{ placeholder }}\n </span>\n }\n </ngs-select-trigger>\n\n <ngs-select-header>\n <div class=\"sticky top-0 z-1 bg-surface-container-lowest\">\n <input #searchInput\n type=\"text\"\n placeholder=\"Search...\"\n autocomplete=\"off\"\n [(ngModel)]=\"searchTerm\"\n class=\"w-full text-sm focus:outline-none border-b border-surface-container-high focus:border-b-primary h-14 px-3\">\n @if (searchTerm().trim()) {\n <div class=\"absolute end-1 top-1/2 -translate-y-1/2\">\n <button\n ngsIconButton\n (click)=\"clearSearch($event)\"\n class=\"clear-button\"\n type=\"button\"\n aria-label=\"Clear search\">\n <ngs-icon name=\"fluent:dismiss-24-regular\"/>\n </button>\n </div>\n }\n </div>\n </ngs-select-header>\n\n @for (country of filteredCountries(); track country.code) {\n <ngs-option [value]=\"country.code\">\n <span class=\"select-option-content\">\n <span class=\"select-option-icon\">{{ country.flag }}</span>\n <span class=\"select-option-text\">\n {{ country.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ country.code }})</span>\n }\n </span>\n </span>\n </ngs-option>\n } @empty {\n @if (searchTerm()) {\n <div class=\"text-sm px-4 py-3\">\n <span i18n>Country not found</span>.\n </div>\n }\n }\n</ngs-select>\n", styles: [":host{display:block}:host .ngs-select-trigger-icon,:host .select-option-icon{font-size:1.25rem}:host .select-option-content{display:flex;align-items:center;gap:var(--ngs-dropdown-item-gap, calc(var(--spacing, .25rem) * 2));min-width:0;width:100%;height:100%;overflow:hidden;white-space:nowrap}:host .select-option-icon{flex:none;line-height:0}:host .select-option-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .code{text-transform:uppercase;color:var(--ngs-color-neutral-500)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: Option, selector: "ngs-option", inputs: ["value", "data", "disabled", "selected"], outputs: ["onSelectionChange"], exportAs: ["ngsOption"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "component", type: Select, selector: "ngs-select", inputs: ["id", "placeholder", "disabled", "required", "multiple", "hideCheckIcon", "clearable", "aria-label", "tabIndex", "aria-describedby", "value"], outputs: ["selectionChange", "opened", "closed", "valueChange"], exportAs: ["ngsSelect"] }, { kind: "directive", type: SelectTrigger, selector: "ngs-select-trigger" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "component", type: SelectHeader, selector: "ngs-select-header" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
517
+ ], viewQueries: [{ propertyName: "ngsSelect", first: true, predicate: ["ngsSelect"], descendants: true, isSignal: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], exportAs: ["ngsCountrySelect"], ngImport: i0, template: "<ngs-select\n #ngsSelect\n [value]=\"value\"\n (selectionChange)=\"onSelectionChange($event)\"\n (opened)=\"onSelectOpened()\"\n (closed)=\"onSelectClosed()\"\n [placeholder]=\"placeholder\"\n [required]=\"isRequiredSignal()\"\n [disabled]=\"isDisabledSignal()\">\n <ngs-select-trigger class=\"select-trigger\">\n @let selectedCountry = selectedCountryDisplay();\n @if (selectedCountry) {\n <span class=\"ngs-select-trigger-content\">\n <span class=\"flag-icon\" aria-hidden=\"true\">{{ selectedCountry.flag }}</span>\n <span class=\"ngs-select-trigger-text\">\n {{ selectedCountry.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ selectedCountry.code }})</span>\n }\n </span>\n </span>\n }\n\n @if (!selectedCountryDisplay() && placeholder) {\n <span class=\"ngs-select-trigger-text placeholder-text\">\n {{ placeholder }}\n </span>\n }\n </ngs-select-trigger>\n\n <ngs-select-header>\n <div class=\"sticky top-0 z-1 bg-surface-container-lowest\">\n <input #searchInput\n type=\"text\"\n placeholder=\"Search...\"\n autocomplete=\"off\"\n [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"onCountrySearch($event)\"\n class=\"w-full text-sm focus:outline-none border-b border-surface-container-high focus:border-b-primary h-14 px-3\">\n @if (searchTerm().trim()) {\n <div class=\"absolute end-1 top-1/2 -translate-y-1/2\">\n <button\n ngsIconButton\n (click)=\"clearSearch($event)\"\n class=\"clear-button\"\n type=\"button\"\n aria-label=\"Clear search\">\n <ngs-icon name=\"fluent:dismiss-24-regular\"/>\n </button>\n </div>\n }\n </div>\n </ngs-select-header>\n\n @for (country of visibleCountries(); track country.code) {\n <ngs-option [value]=\"country.code\">\n <div class=\"flex items-center gap-2\">\n <span class=\"select-option-icon text-2xl\" aria-hidden=\"true\">{{ country.flag }}</span>\n <span class=\"select-option-text\">\n {{ country.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ country.code }})</span>\n }\n </span>\n </div>\n </ngs-option>\n } @empty {\n @if (searchTerm()) {\n <div class=\"text-sm px-4 py-3\">\n <span i18n>Country not found</span>.\n </div>\n }\n }\n\n @if (visibleCountryCount() < filteredCountries().length) {\n <div class=\"select-loading\">\n Loading more countries...\n </div>\n }\n</ngs-select>\n", styles: [":host{display:block}:host .flag-icon{display:inline-flex;align-items:center;justify-content:center;width:22px;font-size:22px;line-height:1}:host .select-option-content{display:flex;align-items:center;gap:var(--ngs-dropdown-item-gap);min-width:0;width:100%;height:100%;overflow:hidden;white-space:nowrap}:host .select-option-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .code{text-transform:uppercase;color:var(--ngs-color-neutral-500)}:host .select-loading{padding:calc(var(--spacing, .25rem) * 2) calc(var(--spacing, .25rem) * 4);color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-sm)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: Option, selector: "ngs-option", inputs: ["value", "data", "disabled", "selected"], outputs: ["onSelectionChange"], exportAs: ["ngsOption"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "component", type: Select, selector: "ngs-select", inputs: ["id", "placeholder", "disabled", "required", "multiple", "hideCheckIcon", "clearable", "aria-label", "tabIndex", "aria-describedby", "value"], outputs: ["selectionChange", "opened", "closed", "valueChange"], exportAs: ["ngsSelect"] }, { kind: "directive", type: SelectTrigger, selector: "ngs-select-trigger" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "component", type: SelectHeader, selector: "ngs-select-header" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
457
518
  }
458
519
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CountrySelect, decorators: [{
459
520
  type: Component,
@@ -478,7 +539,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
478
539
  '[attr.tabindex]': 'disabled ? -1 : 0',
479
540
  '(focus)': 'onFocusIn()',
480
541
  '(blur)': 'onFocusOut($event)',
481
- }, template: "<ngs-select\n #ngsSelect\n [value]=\"value\"\n (selectionChange)=\"onSelectionChange($event)\"\n (opened)=\"onSelectOpened()\"\n (closed)=\"onSelectClosed()\"\n [placeholder]=\"placeholder\"\n [required]=\"isRequiredSignal()\"\n [disabled]=\"isDisabledSignal()\">\n <ngs-select-trigger class=\"select-trigger\">\n @let selectedCountry = selectedCountryDisplay();\n @if (selectedCountry) {\n <span class=\"ngs-select-trigger-content\">\n <span class=\"ngs-select-trigger-icon\">{{ selectedCountry.flag }}</span>\n <span class=\"ngs-select-trigger-text\">\n {{ selectedCountry.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ selectedCountry.code }})</span>\n }\n </span>\n </span>\n }\n\n @if (!selectedCountryDisplay() && placeholder) {\n <span class=\"ngs-select-trigger-text placeholder-text\">\n {{ placeholder }}\n </span>\n }\n </ngs-select-trigger>\n\n <ngs-select-header>\n <div class=\"sticky top-0 z-1 bg-surface-container-lowest\">\n <input #searchInput\n type=\"text\"\n placeholder=\"Search...\"\n autocomplete=\"off\"\n [(ngModel)]=\"searchTerm\"\n class=\"w-full text-sm focus:outline-none border-b border-surface-container-high focus:border-b-primary h-14 px-3\">\n @if (searchTerm().trim()) {\n <div class=\"absolute end-1 top-1/2 -translate-y-1/2\">\n <button\n ngsIconButton\n (click)=\"clearSearch($event)\"\n class=\"clear-button\"\n type=\"button\"\n aria-label=\"Clear search\">\n <ngs-icon name=\"fluent:dismiss-24-regular\"/>\n </button>\n </div>\n }\n </div>\n </ngs-select-header>\n\n @for (country of filteredCountries(); track country.code) {\n <ngs-option [value]=\"country.code\">\n <span class=\"select-option-content\">\n <span class=\"select-option-icon\">{{ country.flag }}</span>\n <span class=\"select-option-text\">\n {{ country.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ country.code }})</span>\n }\n </span>\n </span>\n </ngs-option>\n } @empty {\n @if (searchTerm()) {\n <div class=\"text-sm px-4 py-3\">\n <span i18n>Country not found</span>.\n </div>\n }\n }\n</ngs-select>\n", styles: [":host{display:block}:host .ngs-select-trigger-icon,:host .select-option-icon{font-size:1.25rem}:host .select-option-content{display:flex;align-items:center;gap:var(--ngs-dropdown-item-gap, calc(var(--spacing, .25rem) * 2));min-width:0;width:100%;height:100%;overflow:hidden;white-space:nowrap}:host .select-option-icon{flex:none;line-height:0}:host .select-option-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .code{text-transform:uppercase;color:var(--ngs-color-neutral-500)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
542
+ }, template: "<ngs-select\n #ngsSelect\n [value]=\"value\"\n (selectionChange)=\"onSelectionChange($event)\"\n (opened)=\"onSelectOpened()\"\n (closed)=\"onSelectClosed()\"\n [placeholder]=\"placeholder\"\n [required]=\"isRequiredSignal()\"\n [disabled]=\"isDisabledSignal()\">\n <ngs-select-trigger class=\"select-trigger\">\n @let selectedCountry = selectedCountryDisplay();\n @if (selectedCountry) {\n <span class=\"ngs-select-trigger-content\">\n <span class=\"flag-icon\" aria-hidden=\"true\">{{ selectedCountry.flag }}</span>\n <span class=\"ngs-select-trigger-text\">\n {{ selectedCountry.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ selectedCountry.code }})</span>\n }\n </span>\n </span>\n }\n\n @if (!selectedCountryDisplay() && placeholder) {\n <span class=\"ngs-select-trigger-text placeholder-text\">\n {{ placeholder }}\n </span>\n }\n </ngs-select-trigger>\n\n <ngs-select-header>\n <div class=\"sticky top-0 z-1 bg-surface-container-lowest\">\n <input #searchInput\n type=\"text\"\n placeholder=\"Search...\"\n autocomplete=\"off\"\n [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"onCountrySearch($event)\"\n class=\"w-full text-sm focus:outline-none border-b border-surface-container-high focus:border-b-primary h-14 px-3\">\n @if (searchTerm().trim()) {\n <div class=\"absolute end-1 top-1/2 -translate-y-1/2\">\n <button\n ngsIconButton\n (click)=\"clearSearch($event)\"\n class=\"clear-button\"\n type=\"button\"\n aria-label=\"Clear search\">\n <ngs-icon name=\"fluent:dismiss-24-regular\"/>\n </button>\n </div>\n }\n </div>\n </ngs-select-header>\n\n @for (country of visibleCountries(); track country.code) {\n <ngs-option [value]=\"country.code\">\n <div class=\"flex items-center gap-2\">\n <span class=\"select-option-icon text-2xl\" aria-hidden=\"true\">{{ country.flag }}</span>\n <span class=\"select-option-text\">\n {{ country.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ country.code }})</span>\n }\n </span>\n </div>\n </ngs-option>\n } @empty {\n @if (searchTerm()) {\n <div class=\"text-sm px-4 py-3\">\n <span i18n>Country not found</span>.\n </div>\n }\n }\n\n @if (visibleCountryCount() < filteredCountries().length) {\n <div class=\"select-loading\">\n Loading more countries...\n </div>\n }\n</ngs-select>\n", styles: [":host{display:block}:host .flag-icon{display:inline-flex;align-items:center;justify-content:center;width:22px;font-size:22px;line-height:1}:host .select-option-content{display:flex;align-items:center;gap:var(--ngs-dropdown-item-gap);min-width:0;width:100%;height:100%;overflow:hidden;white-space:nowrap}:host .select-option-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .code{text-transform:uppercase;color:var(--ngs-color-neutral-500)}:host .select-loading{padding:calc(var(--spacing, .25rem) * 2) calc(var(--spacing, .25rem) * 4);color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-sm)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
482
543
  }], ctorParameters: () => [], propDecorators: { searchTerm: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchTerm", required: false }] }, { type: i0.Output, args: ["searchTermChange"] }], placeholderInputSignal: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], isRequiredSignal: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }, { type: i0.Output, args: ["requiredChange"] }], isDisabledSignal: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], showCountryCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCountryCode", required: false }] }], ngsSelect: [{ type: i0.ViewChild, args: ['ngsSelect', { isSignal: true }] }], searchInput: [{ type: i0.ViewChild, args: ['searchInput', { isSignal: true }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
483
544
 
484
545
  /**