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.
- package/fesm2022/codexly-ui.mjs +204 -54
- package/fesm2022/codexly-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/codexly-ui.d.ts +40 -7
package/fesm2022/codexly-ui.mjs
CHANGED
|
@@ -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
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
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
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
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
|
-
|
|
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
|
-
<!-- ──
|
|
5131
|
-
@if (
|
|
5132
|
-
<div class="mt-3
|
|
5133
|
-
@for (
|
|
5134
|
-
<div [class]="
|
|
5135
|
-
<
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
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:
|
|
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: [
|
|
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
|
-
<!-- ──
|
|
5213
|
-
@if (
|
|
5214
|
-
<div class="mt-3
|
|
5215
|
-
@for (
|
|
5216
|
-
<div [class]="
|
|
5217
|
-
<
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
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' },
|