codexly-ui 0.3.0 → 0.4.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.
@@ -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,36 @@ 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 flex flex-col ${resolveRadius(this._themeSvc.config().borderRadius)} overflow-hidden border border-clx-border bg-clx-surface-2`, ...(ngDevMode ? [{ debugName: "_thumbClass" }] : /* istanbul ignore next */ []));
4937
+ _previewItems = computed(() => {
4938
+ const existing = this.existingFiles().map(f => ({
4939
+ kind: 'existing',
4940
+ key: `existing:${f.id}`,
4941
+ name: f.name ?? '',
4942
+ isImage: true,
4943
+ thumbUrl: f.url,
4944
+ fileIcon: '',
4945
+ fileColor: '',
4946
+ status: f.status,
4947
+ existing: f,
4948
+ }));
4949
+ const fresh = this._files().map(file => {
4950
+ const isImage = file.type.startsWith('image/');
4951
+ const visual = isImage ? null : resolveFileTypeVisual(file.name, file.type);
4952
+ return {
4953
+ kind: 'new',
4954
+ key: `new:${file.name}:${file.size}:${file.lastModified}`,
4955
+ name: file.name,
4956
+ size: file.size,
4957
+ isImage,
4958
+ thumbUrl: isImage ? this._getObjectUrl(file) : null,
4959
+ fileIcon: visual?.icon ?? '',
4960
+ fileColor: visual?.color ?? '',
4961
+ file,
4962
+ };
4963
+ });
4964
+ return [...existing, ...fresh];
4965
+ }, ...(ngDevMode ? [{ debugName: "_previewItems" }] : /* istanbul ignore next */ []));
4894
4966
  _zoneClass = computed(() => {
4895
4967
  const base = [
4896
4968
  'flex flex-col items-center justify-center text-center',
@@ -4957,15 +5029,13 @@ class ClxUploadComponent {
4957
5029
  // ── CVA implementation ─────────────────────────────────────────────────────
4958
5030
  writeValue(value) {
4959
5031
  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]);
5032
+ const next = !value ? [] : Array.isArray(value) ? value : [value];
5033
+ const nextSet = new Set(next);
5034
+ for (const file of this._files()) {
5035
+ if (!nextSet.has(file))
5036
+ this._releaseObjectUrl(file);
4968
5037
  }
5038
+ this._files.set(next);
4969
5039
  }
4970
5040
  registerOnChange(fn) {
4971
5041
  this._onChange = fn;
@@ -5004,13 +5074,39 @@ class ClxUploadComponent {
5004
5074
  if (files?.length)
5005
5075
  this._addFiles(files);
5006
5076
  }
5007
- _removeFile(file) {
5077
+ _removeItem(item) {
5078
+ if (item.kind === 'existing') {
5079
+ this.existingFileRemove.emit(item.existing.id);
5080
+ return;
5081
+ }
5082
+ const file = item.file;
5008
5083
  this._files.update(current => current.filter(f => f !== file));
5084
+ this._releaseObjectUrl(file);
5009
5085
  this._errorKey.set(null);
5010
5086
  this._ngControl?.control?.setErrors(null);
5011
5087
  this._emit();
5012
5088
  this._onTouched();
5013
5089
  }
5090
+ _getObjectUrl(file) {
5091
+ let url = this._objectUrls.get(file);
5092
+ if (!url) {
5093
+ url = URL.createObjectURL(file);
5094
+ this._objectUrls.set(file, url);
5095
+ }
5096
+ return url;
5097
+ }
5098
+ _releaseObjectUrl(file) {
5099
+ const url = this._objectUrls.get(file);
5100
+ if (url) {
5101
+ URL.revokeObjectURL(url);
5102
+ this._objectUrls.delete(file);
5103
+ }
5104
+ }
5105
+ ngOnDestroy() {
5106
+ for (const url of this._objectUrls.values())
5107
+ URL.revokeObjectURL(url);
5108
+ this._objectUrls.clear();
5109
+ }
5014
5110
  // ── Helpers ────────────────────────────────────────────────────────────────
5015
5111
  _addFiles(rawFiles) {
5016
5112
  const files = Array.from(rawFiles);
@@ -5083,7 +5179,7 @@ class ClxUploadComponent {
5083
5179
  return `${(bytes / 1_048_576).toFixed(1)} MB`;
5084
5180
  }
5085
5181
  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: `
5182
+ 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
5183
  <!-- Hidden file input -->
5088
5184
  <input
5089
5185
  #fileInput
@@ -5127,24 +5223,51 @@ class ClxUploadComponent {
5127
5223
  </div>
5128
5224
  </div>
5129
5225
 
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>
5226
+ <!-- ── Preview list (existing + new files, images get a real thumbnail) ───── -->
5227
+ @if (_previewItems().length) {
5228
+ <div class="mt-3 grid grid-cols-4 sm:grid-cols-6 gap-2">
5229
+ @for (item of _previewItems(); track item.key) {
5230
+ <div [class]="_thumbClass()">
5231
+ <div class="relative aspect-square w-full overflow-hidden">
5232
+ @if (item.isImage) {
5233
+ <img [src]="item.thumbUrl" [alt]="item.name" loading="lazy" class="w-full h-full object-cover" />
5234
+ } @else {
5235
+ <div class="w-full h-full flex items-center justify-center bg-clx-surface-3">
5236
+ <span clx-icon [name]="item.fileIcon" size="lg" [class]="'text-' + item.fileColor + '-500'"></span>
5237
+ </div>
5238
+ }
5239
+
5240
+ @if (item.status === 'PENDING' || item.status === 'PROCESSING') {
5241
+ <div class="absolute inset-0 bg-black/50 flex flex-col items-center justify-center gap-1">
5242
+ <span clx-icon name="progress_activity" size="md" class="text-white animate-spin"></span>
5243
+ </div>
5244
+ } @else if (item.status === 'FAILED') {
5245
+ <div class="absolute inset-0 bg-red-500/40 flex items-center justify-center">
5246
+ <span clx-icon name="error" size="md" class="text-white"></span>
5247
+ </div>
5248
+ }
5249
+
5250
+ <button
5251
+ clx-button
5252
+ type="button"
5253
+ variant="solid"
5254
+ color="red"
5255
+ shape="circle"
5256
+ size="xs"
5257
+ icon="close"
5258
+ [iconOnly]="true"
5259
+ class="absolute top-1 right-1 opacity-0 group-hover:opacity-100 focus-visible:opacity-100 transition-opacity shadow-md"
5260
+ [disabled]="_disabled()"
5261
+ (click)="_removeItem(item); $event.stopPropagation()">
5262
+ </button>
5263
+ </div>
5264
+
5265
+ <div class="px-1.5 py-1 w-full min-w-0">
5266
+ <p class="text-[11px] leading-tight text-clx-text-label font-medium truncate" [title]="item.name">{{ item.name }}</p>
5267
+ @if (item.size !== undefined) {
5268
+ <p class="text-[10px] leading-tight text-clx-text-muted">{{ _formatSize(item.size) }}</p>
5269
+ }
5270
+ </div>
5148
5271
  </div>
5149
5272
  }
5150
5273
  </div>
@@ -5157,14 +5280,14 @@ class ClxUploadComponent {
5157
5280
  {{ _errorMessage() }}
5158
5281
  </p>
5159
5282
  }
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 });
5283
+ `, isInline: true, dependencies: [{ kind: "component", type: ClxIconComponent, selector: "span[clx-icon]", inputs: ["name", "size", "color", "fill"] }, { kind: "component", type: ClxButtonComponent, selector: "button[clx-button], a[clx-button]", inputs: ["variant", "color", "size", "shape", "loading", "disabled", "block", "icon", "iconPosition", "iconOnly", "badge", "badgeColor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5161
5284
  }
5162
5285
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxUploadComponent, decorators: [{
5163
5286
  type: Component,
5164
5287
  args: [{
5165
5288
  selector: 'clx-upload',
5166
5289
  standalone: true,
5167
- imports: [ClxButtonComponent, ClxIconComponent],
5290
+ imports: [ClxIconComponent, ClxButtonComponent],
5168
5291
  template: `
5169
5292
  <!-- Hidden file input -->
5170
5293
  <input
@@ -5209,24 +5332,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
5209
5332
  </div>
5210
5333
  </div>
5211
5334
 
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>
5335
+ <!-- ── Preview list (existing + new files, images get a real thumbnail) ───── -->
5336
+ @if (_previewItems().length) {
5337
+ <div class="mt-3 grid grid-cols-4 sm:grid-cols-6 gap-2">
5338
+ @for (item of _previewItems(); track item.key) {
5339
+ <div [class]="_thumbClass()">
5340
+ <div class="relative aspect-square w-full overflow-hidden">
5341
+ @if (item.isImage) {
5342
+ <img [src]="item.thumbUrl" [alt]="item.name" loading="lazy" class="w-full h-full object-cover" />
5343
+ } @else {
5344
+ <div class="w-full h-full flex items-center justify-center bg-clx-surface-3">
5345
+ <span clx-icon [name]="item.fileIcon" size="lg" [class]="'text-' + item.fileColor + '-500'"></span>
5346
+ </div>
5347
+ }
5348
+
5349
+ @if (item.status === 'PENDING' || item.status === 'PROCESSING') {
5350
+ <div class="absolute inset-0 bg-black/50 flex flex-col items-center justify-center gap-1">
5351
+ <span clx-icon name="progress_activity" size="md" class="text-white animate-spin"></span>
5352
+ </div>
5353
+ } @else if (item.status === 'FAILED') {
5354
+ <div class="absolute inset-0 bg-red-500/40 flex items-center justify-center">
5355
+ <span clx-icon name="error" size="md" class="text-white"></span>
5356
+ </div>
5357
+ }
5358
+
5359
+ <button
5360
+ clx-button
5361
+ type="button"
5362
+ variant="solid"
5363
+ color="red"
5364
+ shape="circle"
5365
+ size="xs"
5366
+ icon="close"
5367
+ [iconOnly]="true"
5368
+ class="absolute top-1 right-1 opacity-0 group-hover:opacity-100 focus-visible:opacity-100 transition-opacity shadow-md"
5369
+ [disabled]="_disabled()"
5370
+ (click)="_removeItem(item); $event.stopPropagation()">
5371
+ </button>
5372
+ </div>
5373
+
5374
+ <div class="px-1.5 py-1 w-full min-w-0">
5375
+ <p class="text-[11px] leading-tight text-clx-text-label font-medium truncate" [title]="item.name">{{ item.name }}</p>
5376
+ @if (item.size !== undefined) {
5377
+ <p class="text-[10px] leading-tight text-clx-text-muted">{{ _formatSize(item.size) }}</p>
5378
+ }
5379
+ </div>
5230
5380
  </div>
5231
5381
  }
5232
5382
  </div>
@@ -5246,7 +5396,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
5246
5396
  class: 'block w-full',
5247
5397
  },
5248
5398
  }]
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 }] }] } });
5399
+ }], 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
5400
 
5251
5401
  const COLOR_PICKER_SIZE_MAP = {
5252
5402
  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' },