codexly-ui 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4850,6 +4850,46 @@ const UPLOAD_SIZE_MAP = {
4850
4850
  md: { zone: 'py-9 px-8 gap-3', icon: 'lg', title: 'text-sm', hint: 'text-xs' },
4851
4851
  lg: { zone: 'py-12 px-10 gap-4', icon: 'xl', title: 'text-base', hint: 'text-sm' },
4852
4852
  };
4853
+ const FILE_TYPE_BY_MIME = {
4854
+ 'application/pdf': { icon: 'picture_as_pdf', color: 'red' },
4855
+ 'application/msword': { icon: 'description', color: 'blue' },
4856
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': { icon: 'description', color: 'blue' },
4857
+ 'application/vnd.ms-excel': { icon: 'table_chart', color: 'green' },
4858
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': { icon: 'table_chart', color: 'green' },
4859
+ 'text/csv': { icon: 'table_chart', color: 'green' },
4860
+ 'application/vnd.ms-powerpoint': { icon: 'slideshow', color: 'orange' },
4861
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation': { icon: 'slideshow', color: 'orange' },
4862
+ 'text/plain': { icon: 'article', color: 'slate' },
4863
+ 'application/zip': { icon: 'folder_zip', color: 'amber' },
4864
+ 'application/x-zip-compressed': { icon: 'folder_zip', color: 'amber' },
4865
+ 'application/x-rar-compressed': { icon: 'folder_zip', color: 'amber' },
4866
+ 'application/x-7z-compressed': { icon: 'folder_zip', color: 'amber' },
4867
+ };
4868
+ const FILE_TYPE_BY_EXTENSION = {
4869
+ pdf: { icon: 'picture_as_pdf', color: 'red' },
4870
+ doc: { icon: 'description', color: 'blue' },
4871
+ docx: { icon: 'description', color: 'blue' },
4872
+ xls: { icon: 'table_chart', color: 'green' },
4873
+ xlsx: { icon: 'table_chart', color: 'green' },
4874
+ csv: { icon: 'table_chart', color: 'green' },
4875
+ ppt: { icon: 'slideshow', color: 'orange' },
4876
+ pptx: { icon: 'slideshow', color: 'orange' },
4877
+ txt: { icon: 'article', color: 'slate' },
4878
+ zip: { icon: 'folder_zip', color: 'amber' },
4879
+ rar: { icon: 'folder_zip', color: 'amber' },
4880
+ '7z': { icon: 'folder_zip', color: 'amber' },
4881
+ };
4882
+ const FILE_TYPE_DEFAULT = { icon: 'draft', color: 'slate' };
4883
+ function resolveFileTypeVisual(name, mimeType) {
4884
+ if (mimeType?.startsWith('video/'))
4885
+ return { icon: 'movie', color: 'purple' };
4886
+ if (mimeType?.startsWith('audio/'))
4887
+ return { icon: 'audiotrack', color: 'pink' };
4888
+ if (mimeType && FILE_TYPE_BY_MIME[mimeType])
4889
+ return FILE_TYPE_BY_MIME[mimeType];
4890
+ const ext = name.split('.').pop()?.toLowerCase() ?? '';
4891
+ return FILE_TYPE_BY_EXTENSION[ext] ?? FILE_TYPE_DEFAULT;
4892
+ }
4853
4893
 
4854
4894
  class ClxUploadComponent {
4855
4895
  _themeSvc = inject(ClxThemeService);
@@ -4863,13 +4903,20 @@ class ClxUploadComponent {
4863
4903
  size = input(undefined, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
4864
4904
  _size = computed(() => (this.size() ?? this._themeSvc.config().defaultSize), ...(ngDevMode ? [{ debugName: "_size" }] : /* istanbul ignore next */ []));
4865
4905
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
4906
+ /** Already-persisted files (e.g. previously uploaded to the backend). Rendered in the same
4907
+ * preview grid as newly-selected local files. The component never deletes these itself —
4908
+ * removing one only emits `existingFileRemove`, letting the caller decide (e.g. call the API). */
4909
+ existingFiles = input([], ...(ngDevMode ? [{ debugName: "existingFiles" }] : /* istanbul ignore next */ []));
4866
4910
  // ── Outputs ────────────────────────────────────────────────────────────────
4867
4911
  onUploadError = output();
4868
4912
  onUploadSuccess = output();
4913
+ existingFileRemove = output();
4869
4914
  // ── Internal state ─────────────────────────────────────────────────────────
4870
4915
  _files = signal([], ...(ngDevMode ? [{ debugName: "_files" }] : /* istanbul ignore next */ []));
4871
4916
  _isDragging = signal(false, ...(ngDevMode ? [{ debugName: "_isDragging" }] : /* istanbul ignore next */ []));
4872
4917
  _errorKey = signal(null, ...(ngDevMode ? [{ debugName: "_errorKey" }] : /* istanbul ignore next */ []));
4918
+ /** File → object URL cache, so we don't re-create (and leak) a new URL on every re-render. */
4919
+ _objectUrls = new Map();
4873
4920
  // ── CVA ────────────────────────────────────────────────────────────────────
4874
4921
  _ngControl = inject(NgControl, { optional: true, self: true });
4875
4922
  _cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_cvaDisabled" }] : /* istanbul ignore next */ []));
@@ -4886,11 +4933,37 @@ class ClxUploadComponent {
4886
4933
  _disabled = computed(() => this._cvaDisabled() || this.disabled(), ...(ngDevMode ? [{ debugName: "_disabled" }] : /* istanbul ignore next */ []));
4887
4934
  _sizeConfig = computed(() => UPLOAD_SIZE_MAP[this._size()], ...(ngDevMode ? [{ debugName: "_sizeConfig" }] : /* istanbul ignore next */ []));
4888
4935
  _isError = computed(() => this._errorKey() !== null, ...(ngDevMode ? [{ debugName: "_isError" }] : /* istanbul ignore next */ []));
4889
- _fileItemClass = computed(() => {
4890
- const t = resolveColor(this._color());
4891
- return `flex items-center gap-2 rounded-lg border px-3 py-2 transition-colors ${t.borderLight} ${t.bgSubtle}`;
4892
- }, ...(ngDevMode ? [{ debugName: "_fileItemClass" }] : /* istanbul ignore next */ []));
4893
- _fileIconClass = computed(() => resolveColor(this._color()).textSubtle, ...(ngDevMode ? [{ debugName: "_fileIconClass" }] : /* istanbul ignore next */ []));
4936
+ _thumbClass = computed(() => `relative group aspect-square ${resolveRadius(this._themeSvc.config().borderRadius)} overflow-hidden border border-clx-border bg-clx-surface-2`, ...(ngDevMode ? [{ debugName: "_thumbClass" }] : /* istanbul ignore next */ []));
4937
+ _fileCardClass = computed(() => `relative group aspect-square ${resolveRadius(this._themeSvc.config().borderRadius)} border border-clx-border bg-clx-surface-2 flex flex-col items-center justify-center gap-1 p-2`, ...(ngDevMode ? [{ debugName: "_fileCardClass" }] : /* istanbul ignore next */ []));
4938
+ _previewItems = computed(() => {
4939
+ const existing = this.existingFiles().map(f => ({
4940
+ kind: 'existing',
4941
+ key: `existing:${f.id}`,
4942
+ name: f.name ?? '',
4943
+ isImage: true,
4944
+ thumbUrl: f.url,
4945
+ fileIcon: '',
4946
+ fileColor: '',
4947
+ status: f.status,
4948
+ existing: f,
4949
+ }));
4950
+ const fresh = this._files().map(file => {
4951
+ const isImage = file.type.startsWith('image/');
4952
+ const visual = isImage ? null : resolveFileTypeVisual(file.name, file.type);
4953
+ return {
4954
+ kind: 'new',
4955
+ key: `new:${file.name}:${file.size}:${file.lastModified}`,
4956
+ name: file.name,
4957
+ size: file.size,
4958
+ isImage,
4959
+ thumbUrl: isImage ? this._getObjectUrl(file) : null,
4960
+ fileIcon: visual?.icon ?? '',
4961
+ fileColor: visual?.color ?? '',
4962
+ file,
4963
+ };
4964
+ });
4965
+ return [...existing, ...fresh];
4966
+ }, ...(ngDevMode ? [{ debugName: "_previewItems" }] : /* istanbul ignore next */ []));
4894
4967
  _zoneClass = computed(() => {
4895
4968
  const base = [
4896
4969
  'flex flex-col items-center justify-center text-center',
@@ -4957,15 +5030,13 @@ class ClxUploadComponent {
4957
5030
  // ── CVA implementation ─────────────────────────────────────────────────────
4958
5031
  writeValue(value) {
4959
5032
  this._cvaConnected = true;
4960
- if (!value) {
4961
- this._files.set([]);
4962
- }
4963
- else if (Array.isArray(value)) {
4964
- this._files.set(value);
4965
- }
4966
- else {
4967
- this._files.set([value]);
5033
+ const next = !value ? [] : Array.isArray(value) ? value : [value];
5034
+ const nextSet = new Set(next);
5035
+ for (const file of this._files()) {
5036
+ if (!nextSet.has(file))
5037
+ this._releaseObjectUrl(file);
4968
5038
  }
5039
+ this._files.set(next);
4969
5040
  }
4970
5041
  registerOnChange(fn) {
4971
5042
  this._onChange = fn;
@@ -5004,13 +5075,39 @@ class ClxUploadComponent {
5004
5075
  if (files?.length)
5005
5076
  this._addFiles(files);
5006
5077
  }
5007
- _removeFile(file) {
5078
+ _removeItem(item) {
5079
+ if (item.kind === 'existing') {
5080
+ this.existingFileRemove.emit(item.existing.id);
5081
+ return;
5082
+ }
5083
+ const file = item.file;
5008
5084
  this._files.update(current => current.filter(f => f !== file));
5085
+ this._releaseObjectUrl(file);
5009
5086
  this._errorKey.set(null);
5010
5087
  this._ngControl?.control?.setErrors(null);
5011
5088
  this._emit();
5012
5089
  this._onTouched();
5013
5090
  }
5091
+ _getObjectUrl(file) {
5092
+ let url = this._objectUrls.get(file);
5093
+ if (!url) {
5094
+ url = URL.createObjectURL(file);
5095
+ this._objectUrls.set(file, url);
5096
+ }
5097
+ return url;
5098
+ }
5099
+ _releaseObjectUrl(file) {
5100
+ const url = this._objectUrls.get(file);
5101
+ if (url) {
5102
+ URL.revokeObjectURL(url);
5103
+ this._objectUrls.delete(file);
5104
+ }
5105
+ }
5106
+ ngOnDestroy() {
5107
+ for (const url of this._objectUrls.values())
5108
+ URL.revokeObjectURL(url);
5109
+ this._objectUrls.clear();
5110
+ }
5014
5111
  // ── Helpers ────────────────────────────────────────────────────────────────
5015
5112
  _addFiles(rawFiles) {
5016
5113
  const files = Array.from(rawFiles);
@@ -5083,7 +5180,7 @@ class ClxUploadComponent {
5083
5180
  return `${(bytes / 1_048_576).toFixed(1)} MB`;
5084
5181
  }
5085
5182
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxUploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5086
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxUploadComponent, isStandalone: true, selector: "clx-upload", inputs: { multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, maxFileSize: { classPropertyName: "maxFileSize", publicName: "maxFileSize", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onUploadError: "onUploadError", onUploadSuccess: "onUploadSuccess" }, host: { classAttribute: "block w-full" }, viewQueries: [{ propertyName: "_fileInput", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }], ngImport: i0, template: `
5183
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxUploadComponent, isStandalone: true, selector: "clx-upload", inputs: { multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, maxFileSize: { classPropertyName: "maxFileSize", publicName: "maxFileSize", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, existingFiles: { classPropertyName: "existingFiles", publicName: "existingFiles", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onUploadError: "onUploadError", onUploadSuccess: "onUploadSuccess", existingFileRemove: "existingFileRemove" }, host: { classAttribute: "block w-full" }, viewQueries: [{ propertyName: "_fileInput", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }], ngImport: i0, template: `
5087
5184
  <!-- Hidden file input -->
5088
5185
  <input
5089
5186
  #fileInput
@@ -5127,25 +5224,48 @@ class ClxUploadComponent {
5127
5224
  </div>
5128
5225
  </div>
5129
5226
 
5130
- <!-- ── File list ─────────────────────────────────────────────────────────── -->
5131
- @if (_files().length) {
5132
- <div class="mt-3 space-y-2">
5133
- @for (file of _files(); track file.name + file.size) {
5134
- <div [class]="_fileItemClass()">
5135
- <span clx-icon name="description" size="sm" [class]="_fileIconClass() + ' shrink-0'"></span>
5136
- <span class="flex-1 text-sm text-clx-text-label font-medium truncate">{{ file.name }}</span>
5137
- <span class="text-xs text-clx-text-muted shrink-0">{{ _formatSize(file.size) }}</span>
5138
- <button
5139
- clx-button
5140
- variant="ghost"
5141
- [color]="_color()"
5142
- shape="circle"
5143
- size="sm"
5144
- icon="close"
5145
- [iconOnly]="true"
5146
- (click)="_removeFile(file); $event.stopPropagation()">
5147
- </button>
5148
- </div>
5227
+ <!-- ── Preview list (existing + new files, images get a real thumbnail) ───── -->
5228
+ @if (_previewItems().length) {
5229
+ <div class="mt-3 grid grid-cols-3 sm:grid-cols-4 gap-2">
5230
+ @for (item of _previewItems(); track item.key) {
5231
+ @if (item.isImage) {
5232
+ <div [class]="_thumbClass()">
5233
+ <img [src]="item.thumbUrl" [alt]="item.name" loading="lazy" class="w-full h-full object-cover" />
5234
+
5235
+ @if (item.status === 'PENDING' || item.status === 'PROCESSING') {
5236
+ <div class="absolute inset-0 bg-black/50 flex flex-col items-center justify-center gap-1">
5237
+ <span clx-icon name="progress_activity" size="md" class="text-white animate-spin"></span>
5238
+ </div>
5239
+ } @else if (item.status === 'FAILED') {
5240
+ <div class="absolute inset-0 bg-red-500/40 flex items-center justify-center">
5241
+ <span clx-icon name="error" size="md" class="text-white"></span>
5242
+ </div>
5243
+ }
5244
+
5245
+ <button
5246
+ type="button"
5247
+ class="absolute top-1 right-1 opacity-0 group-hover:opacity-100 hover:opacity-100 transition-opacity bg-black/60 hover:bg-red-600 text-white rounded-full w-6 h-6 flex items-center justify-center"
5248
+ [disabled]="_disabled()"
5249
+ (click)="_removeItem(item); $event.stopPropagation()">
5250
+ <span clx-icon name="close" size="xs"></span>
5251
+ </button>
5252
+ </div>
5253
+ } @else {
5254
+ <div [class]="_fileCardClass()">
5255
+ <span clx-icon [name]="item.fileIcon" size="lg" [class]="'text-' + item.fileColor + '-500'"></span>
5256
+ <span class="text-xs text-clx-text-label font-medium text-center truncate w-full px-1">{{ item.name }}</span>
5257
+ @if (item.size !== undefined) {
5258
+ <span class="text-[11px] text-clx-text-muted">{{ _formatSize(item.size) }}</span>
5259
+ }
5260
+ <button
5261
+ type="button"
5262
+ class="absolute top-1 right-1 opacity-0 group-hover:opacity-100 hover:opacity-100 transition-opacity bg-black/60 hover:bg-red-600 text-white rounded-full w-6 h-6 flex items-center justify-center"
5263
+ [disabled]="_disabled()"
5264
+ (click)="_removeItem(item); $event.stopPropagation()">
5265
+ <span clx-icon name="close" size="xs"></span>
5266
+ </button>
5267
+ </div>
5268
+ }
5149
5269
  }
5150
5270
  </div>
5151
5271
  }
@@ -5157,14 +5277,14 @@ class ClxUploadComponent {
5157
5277
  {{ _errorMessage() }}
5158
5278
  </p>
5159
5279
  }
5160
- `, isInline: true, dependencies: [{ kind: "component", type: ClxButtonComponent, selector: "button[clx-button], a[clx-button]", inputs: ["variant", "color", "size", "shape", "loading", "disabled", "block", "icon", "iconPosition", "iconOnly", "badge", "badgeColor"] }, { kind: "component", type: ClxIconComponent, selector: "span[clx-icon]", inputs: ["name", "size", "color", "fill"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5280
+ `, isInline: true, dependencies: [{ kind: "component", type: ClxIconComponent, selector: "span[clx-icon]", inputs: ["name", "size", "color", "fill"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5161
5281
  }
5162
5282
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxUploadComponent, decorators: [{
5163
5283
  type: Component,
5164
5284
  args: [{
5165
5285
  selector: 'clx-upload',
5166
5286
  standalone: true,
5167
- imports: [ClxButtonComponent, ClxIconComponent],
5287
+ imports: [ClxIconComponent],
5168
5288
  template: `
5169
5289
  <!-- Hidden file input -->
5170
5290
  <input
@@ -5209,25 +5329,48 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
5209
5329
  </div>
5210
5330
  </div>
5211
5331
 
5212
- <!-- ── File list ─────────────────────────────────────────────────────────── -->
5213
- @if (_files().length) {
5214
- <div class="mt-3 space-y-2">
5215
- @for (file of _files(); track file.name + file.size) {
5216
- <div [class]="_fileItemClass()">
5217
- <span clx-icon name="description" size="sm" [class]="_fileIconClass() + ' shrink-0'"></span>
5218
- <span class="flex-1 text-sm text-clx-text-label font-medium truncate">{{ file.name }}</span>
5219
- <span class="text-xs text-clx-text-muted shrink-0">{{ _formatSize(file.size) }}</span>
5220
- <button
5221
- clx-button
5222
- variant="ghost"
5223
- [color]="_color()"
5224
- shape="circle"
5225
- size="sm"
5226
- icon="close"
5227
- [iconOnly]="true"
5228
- (click)="_removeFile(file); $event.stopPropagation()">
5229
- </button>
5230
- </div>
5332
+ <!-- ── Preview list (existing + new files, images get a real thumbnail) ───── -->
5333
+ @if (_previewItems().length) {
5334
+ <div class="mt-3 grid grid-cols-3 sm:grid-cols-4 gap-2">
5335
+ @for (item of _previewItems(); track item.key) {
5336
+ @if (item.isImage) {
5337
+ <div [class]="_thumbClass()">
5338
+ <img [src]="item.thumbUrl" [alt]="item.name" loading="lazy" class="w-full h-full object-cover" />
5339
+
5340
+ @if (item.status === 'PENDING' || item.status === 'PROCESSING') {
5341
+ <div class="absolute inset-0 bg-black/50 flex flex-col items-center justify-center gap-1">
5342
+ <span clx-icon name="progress_activity" size="md" class="text-white animate-spin"></span>
5343
+ </div>
5344
+ } @else if (item.status === 'FAILED') {
5345
+ <div class="absolute inset-0 bg-red-500/40 flex items-center justify-center">
5346
+ <span clx-icon name="error" size="md" class="text-white"></span>
5347
+ </div>
5348
+ }
5349
+
5350
+ <button
5351
+ type="button"
5352
+ class="absolute top-1 right-1 opacity-0 group-hover:opacity-100 hover:opacity-100 transition-opacity bg-black/60 hover:bg-red-600 text-white rounded-full w-6 h-6 flex items-center justify-center"
5353
+ [disabled]="_disabled()"
5354
+ (click)="_removeItem(item); $event.stopPropagation()">
5355
+ <span clx-icon name="close" size="xs"></span>
5356
+ </button>
5357
+ </div>
5358
+ } @else {
5359
+ <div [class]="_fileCardClass()">
5360
+ <span clx-icon [name]="item.fileIcon" size="lg" [class]="'text-' + item.fileColor + '-500'"></span>
5361
+ <span class="text-xs text-clx-text-label font-medium text-center truncate w-full px-1">{{ item.name }}</span>
5362
+ @if (item.size !== undefined) {
5363
+ <span class="text-[11px] text-clx-text-muted">{{ _formatSize(item.size) }}</span>
5364
+ }
5365
+ <button
5366
+ type="button"
5367
+ class="absolute top-1 right-1 opacity-0 group-hover:opacity-100 hover:opacity-100 transition-opacity bg-black/60 hover:bg-red-600 text-white rounded-full w-6 h-6 flex items-center justify-center"
5368
+ [disabled]="_disabled()"
5369
+ (click)="_removeItem(item); $event.stopPropagation()">
5370
+ <span clx-icon name="close" size="xs"></span>
5371
+ </button>
5372
+ </div>
5373
+ }
5231
5374
  }
5232
5375
  </div>
5233
5376
  }
@@ -5246,7 +5389,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
5246
5389
  class: 'block w-full',
5247
5390
  },
5248
5391
  }]
5249
- }], ctorParameters: () => [], propDecorators: { multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], maxFileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFileSize", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], onUploadError: [{ type: i0.Output, args: ["onUploadError"] }], onUploadSuccess: [{ type: i0.Output, args: ["onUploadSuccess"] }], _fileInput: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }] } });
5392
+ }], ctorParameters: () => [], propDecorators: { multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], maxFileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFileSize", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], existingFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "existingFiles", required: false }] }], onUploadError: [{ type: i0.Output, args: ["onUploadError"] }], onUploadSuccess: [{ type: i0.Output, args: ["onUploadSuccess"] }], existingFileRemove: [{ type: i0.Output, args: ["existingFileRemove"] }], _fileInput: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }] } });
5250
5393
 
5251
5394
  const COLOR_PICKER_SIZE_MAP = {
5252
5395
  sm: { minH: 'min-h-8', text: 'text-sm', label: 'text-xs font-medium', hint: 'text-xs', px: 'px-2.5', swatchSz: 'w-4 h-4', btnSize: 'xs' },