@ziadshalaby/ngx-zs-component 3.0.2 → 3.0.4

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.
@@ -2361,11 +2361,11 @@ class FileInput {
2361
2361
  });
2362
2362
  }
2363
2363
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: FileInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
2364
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: FileInput, isStandalone: true, selector: "ZS-file", inputs: { Id: { classPropertyName: "Id", publicName: "Id", isSignal: true, isRequired: false, transformFunction: null }, iName: { classPropertyName: "iName", publicName: "iName", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, inputStyle: { classPropertyName: "inputStyle", publicName: "inputStyle", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, isReadonly: { classPropertyName: "isReadonly", publicName: "isReadonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, validateFns: { classPropertyName: "validateFns", publicName: "validateFns", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, maxSize: { classPropertyName: "maxSize", publicName: "maxSize", isSignal: true, isRequired: false, transformFunction: null }, allowPreview: { classPropertyName: "allowPreview", publicName: "allowPreview", isSignal: true, isRequired: false, transformFunction: null }, maxFiles: { classPropertyName: "maxFiles", publicName: "maxFiles", isSignal: true, isRequired: false, transformFunction: null }, files: { classPropertyName: "files", publicName: "files", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changeEv: "changeEv", files: "filesChange", touched: "touchedChange" }, viewQueries: [{ propertyName: "fileInputRef", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"zs:flex zs:flex-col zs:gap-2 zs:w-full\"\n [ngClass]=\"disabled() ? 'zs:opacity-60' : ''\"\n role=\"group\"\n [attr.aria-labelledby]=\"Id() + '-label'\"\n [attr.aria-describedby]=\"Id() + '-hint ' + Id() + '-error'\"\n>\n <!-- ========================= Label & Hint ========================= -->\n <ZS-label [class]=\"(label() || hint()) ? 'zs:mb-1' : ''\"\n [label]=\"label()\"\n [hint]=\"hint()\"\n [required]=\"required()\"\n [hintId]=\"Id() + '-hint'\"\n [for]=\"Id()\"\n [id]=\"Id() + '-label'\"\n >\n </ZS-label>\n\n <!-- ================= Input ================= -->\n <div\n [class]=\"[\n 'zs:relative zs:rounded-xl zs:flex zs:flex-col zs:justify-center zs:items-center zs:gap-2 zs:border-2 zs:border-dashed zs:transition-all zs:duration-200',\n palette().inputPalette.border,\n palette().ringPalette.ring,\n palette().inputPalette.borderHover,\n palette().inputPalette.inputBg\n ].join(' ')\"\n [ngClass]=\"disabledOrReadonly() ? 'cursor-not-allowed' : 'cursor-pointer'\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-disabled]=\"disabledOrReadonly()\"\n [attr.aria-label]=\"placeholder() || 'Upload file'\"\n (keydown.enter)=\"!disabledOrReadonly() && fileInput.click()\"\n (keydown.space)=\"!disabledOrReadonly() && fileInput.click()\"\n >\n <input\n #fileInput\n type=\"file\"\n [id]=\"Id()\"\n [name]=\"iName()\"\n [attr.accept]=\"accept()\"\n [attr.multiple]=\"multiple() ? '' : null\"\n [attr.autofocus]=\"autofocus() ? true : null\"\n class=\"zs:absolute zs:inset-0 zs:opacity-0 zs:cursor-pointer\"\n [disabled]=\"disabledOrReadonly()\"\n (change)=\"handleFileChange($event)\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"!!error().length\"\n [attr.aria-describedby]=\"Id() + '-hint ' + Id() + '-error'\"\n />\n\n <div class=\"zs:flex zs:flex-col zs:items-center zs:justify-center zs:text-center zs:py-6 zs:pointer-events-none zs:select-none\">\n <i class=\"fa-solid fa-upload text-3xl mb-2\" [ngClass]=\"palette().inputPalette.text\" aria-hidden=\"true\"></i>\n <p class=\"zs:text-sm zs:text-gray-500 zs:dark:text-gray-400\">\n {{ placeholder() }}\n </p>\n </div>\n </div>\n\n <!-- ================= Files Preview ================= -->\n @if (hasFiles()) {\n <div\n class=\"zs:flex zs:flex-col zs:gap-2 zs:mt-3\"\n role=\"list\"\n aria-label=\"Uploaded files\"\n >\n @for (entry of files().entries(); track entry[0]) {\n <div\n class=\"zs:flex zs:flex-col zs:gap-1 zs:p-2 zs:rounded-lg zs:border zs:focus:outline-hidden zs:focus:ring-2 zs:focus:ring-offset-2\"\n [ngClass]=\"[palette().inputPalette.border, palette().inputPalette.inputBg]\"\n role=\"listitem\"\n tabindex=\"0\"\n >\n <span class=\"zs:block zs:text-sm zs:font-medium zs:truncate\">\n {{ entry[1].name }}\n </span>\n\n <div class=\"zs:flex zs:items-center zs:justify-between zs:gap-4\">\n <div class=\"zs:flex zs:items-center zs:gap-1\">\n <i class=\"text-lg fa-solid fa-file\" [ngClass]=\"palette().inputPalette.text\" aria-hidden=\"true\"></i>\n <span class=\"zs:text-xs zs:text-gray-500\">\n {{ formatSize(entry[1].size) }}\n </span>\n </div>\n\n <div class=\"zs:flex zs:gap-2\">\n @if (allowPreview() && entry[1].url?.startsWith('blob:')) {\n <ZS-button\n type=\"button\"\n (clickedEv)=\"preview(entry[1].url)\"\n [btnStyle]=\"inputStyle()\"\n size=\"sm\"\n aria-label=\"Preview {{ entry[1].name }}\"\n >\n Preview\n </ZS-button>\n }\n\n @if (!disabledOrReadonly()) {\n <ZS-button\n type=\"button\"\n variant=\"outline\"\n btnStyle=\"danger\"\n (clickedEv)=\"removeFile(entry[0])\"\n icon=\"fa-solid fa-trash\"\n aria-label=\"Remove {{ entry[1].name }}\"\n >\n </ZS-button>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- ========================= Error Messages ========================= -->\n <ZS-input-errors\n [Id]=\"Id() + '-error'\"\n [errors]=\"[error()]\"\n aria-live=\"assertive\"\n role=\"alert\"\n >\n </ZS-input-errors>\n</div>\n", styles: [":host{@apply block w-full;}input[type=file]:disabled{@apply cursor-not-allowed opacity-60;}\n"], dependencies: [{ kind: "component", type: Label, selector: "ZS-label", inputs: ["label", "hint", "hintId", "size", "required", "for"] }, { kind: "component", type: InputErrors, selector: "ZS-input-errors", inputs: ["Id", "errors"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: Button, selector: "ZS-button", inputs: ["Id", "btnStyle", "variant", "size", "disabled", "icon", "type"], outputs: ["clickedEv"] }] });
2364
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: FileInput, isStandalone: true, selector: "ZS-file", inputs: { Id: { classPropertyName: "Id", publicName: "Id", isSignal: true, isRequired: false, transformFunction: null }, iName: { classPropertyName: "iName", publicName: "iName", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, inputStyle: { classPropertyName: "inputStyle", publicName: "inputStyle", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, isReadonly: { classPropertyName: "isReadonly", publicName: "isReadonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, validateFns: { classPropertyName: "validateFns", publicName: "validateFns", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, maxSize: { classPropertyName: "maxSize", publicName: "maxSize", isSignal: true, isRequired: false, transformFunction: null }, allowPreview: { classPropertyName: "allowPreview", publicName: "allowPreview", isSignal: true, isRequired: false, transformFunction: null }, maxFiles: { classPropertyName: "maxFiles", publicName: "maxFiles", isSignal: true, isRequired: false, transformFunction: null }, files: { classPropertyName: "files", publicName: "files", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changeEv: "changeEv", files: "filesChange", touched: "touchedChange" }, viewQueries: [{ propertyName: "fileInputRef", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"zs:flex zs:flex-col zs:gap-2 zs:w-full\"\n [ngClass]=\"disabled() ? 'zs:opacity-60' : ''\"\n role=\"group\"\n [attr.aria-labelledby]=\"Id() + '-label'\"\n [attr.aria-describedby]=\"Id() + '-hint ' + Id() + '-error'\"\n>\n <!-- ========================= Label & Hint ========================= -->\n <ZS-label [class]=\"(label() || hint()) ? 'zs:mb-1' : ''\"\n [label]=\"label()\"\n [hint]=\"hint()\"\n [required]=\"required()\"\n [hintId]=\"Id() + '-hint'\"\n [for]=\"Id()\"\n [id]=\"Id() + '-label'\"\n >\n </ZS-label>\n\n <!-- ================= Input ================= -->\n <div\n [class]=\"[\n 'zs:relative zs:rounded-xl zs:flex zs:flex-col zs:justify-center zs:items-center zs:gap-2 zs:border-2 zs:border-dashed zs:transition-all zs:duration-200',\n palette().inputPalette.border,\n palette().ringPalette.ring,\n palette().inputPalette.borderHover,\n palette().inputPalette.inputBg\n ].join(' ')\"\n [ngClass]=\"disabledOrReadonly() ? 'cursor-not-allowed' : 'cursor-pointer'\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-disabled]=\"disabledOrReadonly()\"\n [attr.aria-label]=\"placeholder() || 'Upload file'\"\n (keydown.enter)=\"!disabledOrReadonly() && fileInput.click()\"\n (keydown.space)=\"!disabledOrReadonly() && fileInput.click()\"\n >\n <input\n #fileInput\n type=\"file\"\n [id]=\"Id()\"\n [name]=\"iName()\"\n [attr.accept]=\"accept()\"\n [attr.multiple]=\"multiple() ? '' : null\"\n [attr.autofocus]=\"autofocus() ? true : null\"\n class=\"zs:absolute zs:inset-0 zs:opacity-0 zs:cursor-pointer\"\n [disabled]=\"disabledOrReadonly()\"\n (change)=\"handleFileChange($event)\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"!!error().length\"\n [attr.aria-describedby]=\"Id() + '-hint ' + Id() + '-error'\"\n />\n\n <div class=\"zs:flex zs:flex-col zs:items-center zs:justify-center zs:text-center zs:p-6 zs:pointer-events-none zs:select-none\">\n <i class=\"fa-solid fa-upload text-3xl mb-2\" [ngClass]=\"palette().inputPalette.text\" aria-hidden=\"true\"></i>\n <p class=\"zs:text-sm zs:text-gray-500 zs:dark:text-gray-400\">\n {{ placeholder() }}\n </p>\n </div>\n </div>\n\n <!-- ================= Files Preview ================= -->\n @if (hasFiles()) {\n <div\n class=\"zs:flex zs:flex-col zs:gap-2 zs:mt-3\"\n role=\"list\"\n aria-label=\"Uploaded files\"\n >\n @for (entry of files().entries(); track entry[0]) {\n <div\n class=\"zs:flex zs:flex-col zs:gap-1 zs:p-2 zs:rounded-lg zs:border zs:focus:outline-hidden zs:focus:ring-2 zs:focus:ring-offset-2\"\n [ngClass]=\"[palette().inputPalette.border, palette().inputPalette.inputBg]\"\n role=\"listitem\"\n tabindex=\"0\"\n >\n <span class=\"zs:block zs:text-sm zs:font-medium zs:truncate\">\n {{ entry[1].name }}\n </span>\n\n <div class=\"zs:flex zs:items-center zs:justify-between zs:gap-4\">\n <div class=\"zs:flex zs:items-center zs:gap-1\">\n <i class=\"text-lg fa-solid fa-file\" [ngClass]=\"palette().inputPalette.text\" aria-hidden=\"true\"></i>\n <span class=\"zs:text-xs zs:text-gray-500\">\n {{ formatSize(entry[1].size) }}\n </span>\n </div>\n\n <div class=\"zs:flex zs:gap-2\">\n @if (allowPreview() && entry[1].url?.startsWith('blob:')) {\n <ZS-button\n type=\"button\"\n (clickedEv)=\"preview(entry[1].url)\"\n [btnStyle]=\"inputStyle()\"\n size=\"sm\"\n aria-label=\"Preview {{ entry[1].name }}\"\n >\n Preview\n </ZS-button>\n }\n\n @if (!disabledOrReadonly()) {\n <ZS-button\n type=\"button\"\n variant=\"outline\"\n btnStyle=\"danger\"\n (clickedEv)=\"removeFile(entry[0])\"\n icon=\"fa-solid fa-trash\"\n aria-label=\"Remove {{ entry[1].name }}\"\n >\n </ZS-button>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- ========================= Error Messages ========================= -->\n <ZS-input-errors\n [Id]=\"Id() + '-error'\"\n [errors]=\"[error()]\"\n aria-live=\"assertive\"\n role=\"alert\"\n >\n </ZS-input-errors>\n</div>\n", styles: [":host{@apply block w-full;}input[type=file]:disabled{@apply cursor-not-allowed opacity-60;}\n"], dependencies: [{ kind: "component", type: Label, selector: "ZS-label", inputs: ["label", "hint", "hintId", "size", "required", "for"] }, { kind: "component", type: InputErrors, selector: "ZS-input-errors", inputs: ["Id", "errors"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: Button, selector: "ZS-button", inputs: ["Id", "btnStyle", "variant", "size", "disabled", "icon", "type"], outputs: ["clickedEv"] }] });
2365
2365
  }
2366
2366
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: FileInput, decorators: [{
2367
2367
  type: Component,
2368
- args: [{ selector: 'ZS-file', imports: [Label, InputErrors, CommonModule, Button], template: "<div\n class=\"zs:flex zs:flex-col zs:gap-2 zs:w-full\"\n [ngClass]=\"disabled() ? 'zs:opacity-60' : ''\"\n role=\"group\"\n [attr.aria-labelledby]=\"Id() + '-label'\"\n [attr.aria-describedby]=\"Id() + '-hint ' + Id() + '-error'\"\n>\n <!-- ========================= Label & Hint ========================= -->\n <ZS-label [class]=\"(label() || hint()) ? 'zs:mb-1' : ''\"\n [label]=\"label()\"\n [hint]=\"hint()\"\n [required]=\"required()\"\n [hintId]=\"Id() + '-hint'\"\n [for]=\"Id()\"\n [id]=\"Id() + '-label'\"\n >\n </ZS-label>\n\n <!-- ================= Input ================= -->\n <div\n [class]=\"[\n 'zs:relative zs:rounded-xl zs:flex zs:flex-col zs:justify-center zs:items-center zs:gap-2 zs:border-2 zs:border-dashed zs:transition-all zs:duration-200',\n palette().inputPalette.border,\n palette().ringPalette.ring,\n palette().inputPalette.borderHover,\n palette().inputPalette.inputBg\n ].join(' ')\"\n [ngClass]=\"disabledOrReadonly() ? 'cursor-not-allowed' : 'cursor-pointer'\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-disabled]=\"disabledOrReadonly()\"\n [attr.aria-label]=\"placeholder() || 'Upload file'\"\n (keydown.enter)=\"!disabledOrReadonly() && fileInput.click()\"\n (keydown.space)=\"!disabledOrReadonly() && fileInput.click()\"\n >\n <input\n #fileInput\n type=\"file\"\n [id]=\"Id()\"\n [name]=\"iName()\"\n [attr.accept]=\"accept()\"\n [attr.multiple]=\"multiple() ? '' : null\"\n [attr.autofocus]=\"autofocus() ? true : null\"\n class=\"zs:absolute zs:inset-0 zs:opacity-0 zs:cursor-pointer\"\n [disabled]=\"disabledOrReadonly()\"\n (change)=\"handleFileChange($event)\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"!!error().length\"\n [attr.aria-describedby]=\"Id() + '-hint ' + Id() + '-error'\"\n />\n\n <div class=\"zs:flex zs:flex-col zs:items-center zs:justify-center zs:text-center zs:py-6 zs:pointer-events-none zs:select-none\">\n <i class=\"fa-solid fa-upload text-3xl mb-2\" [ngClass]=\"palette().inputPalette.text\" aria-hidden=\"true\"></i>\n <p class=\"zs:text-sm zs:text-gray-500 zs:dark:text-gray-400\">\n {{ placeholder() }}\n </p>\n </div>\n </div>\n\n <!-- ================= Files Preview ================= -->\n @if (hasFiles()) {\n <div\n class=\"zs:flex zs:flex-col zs:gap-2 zs:mt-3\"\n role=\"list\"\n aria-label=\"Uploaded files\"\n >\n @for (entry of files().entries(); track entry[0]) {\n <div\n class=\"zs:flex zs:flex-col zs:gap-1 zs:p-2 zs:rounded-lg zs:border zs:focus:outline-hidden zs:focus:ring-2 zs:focus:ring-offset-2\"\n [ngClass]=\"[palette().inputPalette.border, palette().inputPalette.inputBg]\"\n role=\"listitem\"\n tabindex=\"0\"\n >\n <span class=\"zs:block zs:text-sm zs:font-medium zs:truncate\">\n {{ entry[1].name }}\n </span>\n\n <div class=\"zs:flex zs:items-center zs:justify-between zs:gap-4\">\n <div class=\"zs:flex zs:items-center zs:gap-1\">\n <i class=\"text-lg fa-solid fa-file\" [ngClass]=\"palette().inputPalette.text\" aria-hidden=\"true\"></i>\n <span class=\"zs:text-xs zs:text-gray-500\">\n {{ formatSize(entry[1].size) }}\n </span>\n </div>\n\n <div class=\"zs:flex zs:gap-2\">\n @if (allowPreview() && entry[1].url?.startsWith('blob:')) {\n <ZS-button\n type=\"button\"\n (clickedEv)=\"preview(entry[1].url)\"\n [btnStyle]=\"inputStyle()\"\n size=\"sm\"\n aria-label=\"Preview {{ entry[1].name }}\"\n >\n Preview\n </ZS-button>\n }\n\n @if (!disabledOrReadonly()) {\n <ZS-button\n type=\"button\"\n variant=\"outline\"\n btnStyle=\"danger\"\n (clickedEv)=\"removeFile(entry[0])\"\n icon=\"fa-solid fa-trash\"\n aria-label=\"Remove {{ entry[1].name }}\"\n >\n </ZS-button>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- ========================= Error Messages ========================= -->\n <ZS-input-errors\n [Id]=\"Id() + '-error'\"\n [errors]=\"[error()]\"\n aria-live=\"assertive\"\n role=\"alert\"\n >\n </ZS-input-errors>\n</div>\n", styles: [":host{@apply block w-full;}input[type=file]:disabled{@apply cursor-not-allowed opacity-60;}\n"] }]
2368
+ args: [{ selector: 'ZS-file', imports: [Label, InputErrors, CommonModule, Button], template: "<div\n class=\"zs:flex zs:flex-col zs:gap-2 zs:w-full\"\n [ngClass]=\"disabled() ? 'zs:opacity-60' : ''\"\n role=\"group\"\n [attr.aria-labelledby]=\"Id() + '-label'\"\n [attr.aria-describedby]=\"Id() + '-hint ' + Id() + '-error'\"\n>\n <!-- ========================= Label & Hint ========================= -->\n <ZS-label [class]=\"(label() || hint()) ? 'zs:mb-1' : ''\"\n [label]=\"label()\"\n [hint]=\"hint()\"\n [required]=\"required()\"\n [hintId]=\"Id() + '-hint'\"\n [for]=\"Id()\"\n [id]=\"Id() + '-label'\"\n >\n </ZS-label>\n\n <!-- ================= Input ================= -->\n <div\n [class]=\"[\n 'zs:relative zs:rounded-xl zs:flex zs:flex-col zs:justify-center zs:items-center zs:gap-2 zs:border-2 zs:border-dashed zs:transition-all zs:duration-200',\n palette().inputPalette.border,\n palette().ringPalette.ring,\n palette().inputPalette.borderHover,\n palette().inputPalette.inputBg\n ].join(' ')\"\n [ngClass]=\"disabledOrReadonly() ? 'cursor-not-allowed' : 'cursor-pointer'\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-disabled]=\"disabledOrReadonly()\"\n [attr.aria-label]=\"placeholder() || 'Upload file'\"\n (keydown.enter)=\"!disabledOrReadonly() && fileInput.click()\"\n (keydown.space)=\"!disabledOrReadonly() && fileInput.click()\"\n >\n <input\n #fileInput\n type=\"file\"\n [id]=\"Id()\"\n [name]=\"iName()\"\n [attr.accept]=\"accept()\"\n [attr.multiple]=\"multiple() ? '' : null\"\n [attr.autofocus]=\"autofocus() ? true : null\"\n class=\"zs:absolute zs:inset-0 zs:opacity-0 zs:cursor-pointer\"\n [disabled]=\"disabledOrReadonly()\"\n (change)=\"handleFileChange($event)\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"!!error().length\"\n [attr.aria-describedby]=\"Id() + '-hint ' + Id() + '-error'\"\n />\n\n <div class=\"zs:flex zs:flex-col zs:items-center zs:justify-center zs:text-center zs:p-6 zs:pointer-events-none zs:select-none\">\n <i class=\"fa-solid fa-upload text-3xl mb-2\" [ngClass]=\"palette().inputPalette.text\" aria-hidden=\"true\"></i>\n <p class=\"zs:text-sm zs:text-gray-500 zs:dark:text-gray-400\">\n {{ placeholder() }}\n </p>\n </div>\n </div>\n\n <!-- ================= Files Preview ================= -->\n @if (hasFiles()) {\n <div\n class=\"zs:flex zs:flex-col zs:gap-2 zs:mt-3\"\n role=\"list\"\n aria-label=\"Uploaded files\"\n >\n @for (entry of files().entries(); track entry[0]) {\n <div\n class=\"zs:flex zs:flex-col zs:gap-1 zs:p-2 zs:rounded-lg zs:border zs:focus:outline-hidden zs:focus:ring-2 zs:focus:ring-offset-2\"\n [ngClass]=\"[palette().inputPalette.border, palette().inputPalette.inputBg]\"\n role=\"listitem\"\n tabindex=\"0\"\n >\n <span class=\"zs:block zs:text-sm zs:font-medium zs:truncate\">\n {{ entry[1].name }}\n </span>\n\n <div class=\"zs:flex zs:items-center zs:justify-between zs:gap-4\">\n <div class=\"zs:flex zs:items-center zs:gap-1\">\n <i class=\"text-lg fa-solid fa-file\" [ngClass]=\"palette().inputPalette.text\" aria-hidden=\"true\"></i>\n <span class=\"zs:text-xs zs:text-gray-500\">\n {{ formatSize(entry[1].size) }}\n </span>\n </div>\n\n <div class=\"zs:flex zs:gap-2\">\n @if (allowPreview() && entry[1].url?.startsWith('blob:')) {\n <ZS-button\n type=\"button\"\n (clickedEv)=\"preview(entry[1].url)\"\n [btnStyle]=\"inputStyle()\"\n size=\"sm\"\n aria-label=\"Preview {{ entry[1].name }}\"\n >\n Preview\n </ZS-button>\n }\n\n @if (!disabledOrReadonly()) {\n <ZS-button\n type=\"button\"\n variant=\"outline\"\n btnStyle=\"danger\"\n (clickedEv)=\"removeFile(entry[0])\"\n icon=\"fa-solid fa-trash\"\n aria-label=\"Remove {{ entry[1].name }}\"\n >\n </ZS-button>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- ========================= Error Messages ========================= -->\n <ZS-input-errors\n [Id]=\"Id() + '-error'\"\n [errors]=\"[error()]\"\n aria-live=\"assertive\"\n role=\"alert\"\n >\n </ZS-input-errors>\n</div>\n", styles: [":host{@apply block w-full;}input[type=file]:disabled{@apply cursor-not-allowed opacity-60;}\n"] }]
2369
2369
  }], propDecorators: { Id: [{ type: i0.Input, args: [{ isSignal: true, alias: "Id", required: false }] }], iName: [{ type: i0.Input, args: [{ isSignal: true, alias: "iName", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], inputStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputStyle", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], isReadonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "isReadonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], validateFns: [{ type: i0.Input, args: [{ isSignal: true, alias: "validateFns", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], maxSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSize", required: false }] }], allowPreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowPreview", required: false }] }], maxFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFiles", required: false }] }], changeEv: [{ type: i0.Output, args: ["changeEv"] }], files: [{ type: i0.Input, args: [{ isSignal: true, alias: "files", required: false }] }, { type: i0.Output, args: ["filesChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], fileInputRef: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }] } });
2370
2370
 
2371
2371
  // ==============================================================================
@@ -2483,9 +2483,10 @@ class Input {
2483
2483
  const baseClasses = 'zs:border zs:transition-all zs:duration-150 zs:focus-within:ring-2';
2484
2484
  const hasError = this.error().length;
2485
2485
  let styleConfig = inputPaletteMap.get(this.inputStyle());
2486
- const ringConfig = ringPaletteMap.get(this.inputStyle());
2486
+ let ringConfig = ringPaletteMap.get(this.inputStyle());
2487
2487
  if (hasError) {
2488
2488
  styleConfig = inputPaletteMap.get('danger');
2489
+ ringConfig = ringPaletteMap.get('danger');
2489
2490
  }
2490
2491
  const disabledClass = this.disabled() ? 'zs:opacity-60' : '';
2491
2492
  const interactionClass = this.disabledOrReadonly()
@@ -3178,11 +3179,11 @@ class Footer {
3178
3179
  showDefultContent = input(true, ...(ngDevMode ? [{ debugName: "showDefultContent" }] : []));
3179
3180
  pages = input([], ...(ngDevMode ? [{ debugName: "pages" }] : []));
3180
3181
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: Footer, deps: [], target: i0.ɵɵFactoryTarget.Component });
3181
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: Footer, isStandalone: true, selector: "ZS-footer", inputs: { showDefultContent: { classPropertyName: "showDefultContent", publicName: "showDefultContent", isSignal: true, isRequired: false, transformFunction: null }, pages: { classPropertyName: "pages", publicName: "pages", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<footer class=\"zs:bg-gray-700 zs:dark:bg-gray-950 zs:dark:text-gray-300 zs:text-white zs:py-8\">\n <div class=\"zs:text-center zs:flex zs:flex-col zs:gap-8\">\n <p class=\"zs:text-xs zs:sm:text-sm zs:px-6\">\n <ng-content select=\"[rights]\"></ng-content>\n\n @if(showDefultContent()) {\n &copy;\n <span class=\"zs:font-semibold\">2026 Ziad Ahmed Shalaby</span>.\n All rights reserved.\n }\n </p>\n\n @if(pages().length) {\n <nav class=\"zs:flex zs:flex-wrap zs:justify-center zs:items-center\n zs:gap-y-6 zs:gap-x-4 zs:sm:gap-x-6 zs:md:gap-x-8 zs:lg:gap-x-10 zs:w-full\">\n @for (page of pages(); track $index) {\n <a class=\"zs:text-[10px] zs:sm:text-xs \n zs:hover:underline zs:text-center zs:min-w-30\" \n [routerLink]=\"page.routerLink\">\n {{ page.label }}\n </a>\n }\n </nav>\n }\n </div>\n</footer>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
3182
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: Footer, isStandalone: true, selector: "ZS-footer", inputs: { showDefultContent: { classPropertyName: "showDefultContent", publicName: "showDefultContent", isSignal: true, isRequired: false, transformFunction: null }, pages: { classPropertyName: "pages", publicName: "pages", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<footer class=\"zs:bg-gray-700 zs:dark:bg-gray-950 \nzs:dark:text-gray-300 zs:text-white zs:py-6\">\n <div class=\"zs:text-center zs:flex zs:flex-col zs:gap-8\">\n <p class=\"zs:text-xs zs:sm:text-sm zs:px-6\">\n <ng-content select=\"[rights]\"></ng-content>\n\n @if(showDefultContent()) {\n &copy;\n <span class=\"zs:font-semibold\">2026 Ziad Ahmed Shalaby</span>.\n All rights reserved.\n }\n </p>\n\n @if(pages().length) {\n <nav class=\"zs:flex zs:flex-wrap zs:justify-center zs:items-center\n zs:gap-y-6 zs:gap-x-4 zs:sm:gap-x-6 zs:md:gap-x-8 zs:lg:gap-x-10 zs:w-full\">\n @for (page of pages(); track $index) {\n <a class=\"zs:text-[10px] zs:sm:text-xs \n zs:hover:underline zs:text-center zs:min-w-30\" \n [routerLink]=\"page.routerLink\">\n {{ page.label }}\n </a>\n }\n </nav>\n }\n </div>\n</footer>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
3182
3183
  }
3183
3184
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: Footer, decorators: [{
3184
3185
  type: Component,
3185
- args: [{ selector: 'ZS-footer', imports: [RouterModule], template: "<footer class=\"zs:bg-gray-700 zs:dark:bg-gray-950 zs:dark:text-gray-300 zs:text-white zs:py-8\">\n <div class=\"zs:text-center zs:flex zs:flex-col zs:gap-8\">\n <p class=\"zs:text-xs zs:sm:text-sm zs:px-6\">\n <ng-content select=\"[rights]\"></ng-content>\n\n @if(showDefultContent()) {\n &copy;\n <span class=\"zs:font-semibold\">2026 Ziad Ahmed Shalaby</span>.\n All rights reserved.\n }\n </p>\n\n @if(pages().length) {\n <nav class=\"zs:flex zs:flex-wrap zs:justify-center zs:items-center\n zs:gap-y-6 zs:gap-x-4 zs:sm:gap-x-6 zs:md:gap-x-8 zs:lg:gap-x-10 zs:w-full\">\n @for (page of pages(); track $index) {\n <a class=\"zs:text-[10px] zs:sm:text-xs \n zs:hover:underline zs:text-center zs:min-w-30\" \n [routerLink]=\"page.routerLink\">\n {{ page.label }}\n </a>\n }\n </nav>\n }\n </div>\n</footer>\n" }]
3186
+ args: [{ selector: 'ZS-footer', imports: [RouterModule], template: "<footer class=\"zs:bg-gray-700 zs:dark:bg-gray-950 \nzs:dark:text-gray-300 zs:text-white zs:py-6\">\n <div class=\"zs:text-center zs:flex zs:flex-col zs:gap-8\">\n <p class=\"zs:text-xs zs:sm:text-sm zs:px-6\">\n <ng-content select=\"[rights]\"></ng-content>\n\n @if(showDefultContent()) {\n &copy;\n <span class=\"zs:font-semibold\">2026 Ziad Ahmed Shalaby</span>.\n All rights reserved.\n }\n </p>\n\n @if(pages().length) {\n <nav class=\"zs:flex zs:flex-wrap zs:justify-center zs:items-center\n zs:gap-y-6 zs:gap-x-4 zs:sm:gap-x-6 zs:md:gap-x-8 zs:lg:gap-x-10 zs:w-full\">\n @for (page of pages(); track $index) {\n <a class=\"zs:text-[10px] zs:sm:text-xs \n zs:hover:underline zs:text-center zs:min-w-30\" \n [routerLink]=\"page.routerLink\">\n {{ page.label }}\n </a>\n }\n </nav>\n }\n </div>\n</footer>\n" }]
3186
3187
  }], propDecorators: { showDefultContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDefultContent", required: false }] }], pages: [{ type: i0.Input, args: [{ isSignal: true, alias: "pages", required: false }] }] } });
3187
3188
 
3188
3189
  /*