@ajuarezso/sui-design-system 0.12.0 → 0.13.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.
|
@@ -9176,6 +9176,17 @@ const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
|
|
|
9176
9176
|
* - errorEvent: mensaje de error de validación
|
|
9177
9177
|
*/
|
|
9178
9178
|
class SuiImageUpload {
|
|
9179
|
+
/**
|
|
9180
|
+
* Ocupa el ancho del contenedor en vez del cuadrado fijo de `size`.
|
|
9181
|
+
*
|
|
9182
|
+
* Por defecto el componente es un cuadrado de lado `size` —pensado para
|
|
9183
|
+
* avatares y logos, donde eso es lo correcto—. Pero para subir un documento
|
|
9184
|
+
* (un comprobante de pago, una licencia) el cuadrado desperdicia el ancho
|
|
9185
|
+
* disponible y recorta imágenes verticales, que es la forma natural de una
|
|
9186
|
+
* captura de celular. En fluido el alto lo da el contenido, así que el botón
|
|
9187
|
+
* de quitar deja de desbordarse.
|
|
9188
|
+
*/
|
|
9189
|
+
fluid = input(false, ...(ngDevMode ? [{ debugName: "fluid" }] : /* istanbul ignore next */ []));
|
|
9179
9190
|
shape = input('circle', ...(ngDevMode ? [{ debugName: "shape" }] : /* istanbul ignore next */ []));
|
|
9180
9191
|
size = input('lg', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
9181
9192
|
src = model(null, ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
|
|
@@ -9232,6 +9243,20 @@ class SuiImageUpload {
|
|
|
9232
9243
|
return;
|
|
9233
9244
|
this.inputRef()?.nativeElement.click();
|
|
9234
9245
|
}
|
|
9246
|
+
/**
|
|
9247
|
+
* Reabre el selector de archivo.
|
|
9248
|
+
*
|
|
9249
|
+
* Público a propósito: en modo editable el lápiz emite `editRequested` para
|
|
9250
|
+
* que el consumer abra su recortador, pero no todo caso tiene uno. Para subir
|
|
9251
|
+
* un documento —un comprobante, una licencia— lo que se espera del lápiz es
|
|
9252
|
+
* simplemente elegir otro archivo, y sin esto el consumer no tenía forma de
|
|
9253
|
+
* llegar al input, que es interno.
|
|
9254
|
+
*/
|
|
9255
|
+
abrirSelector() {
|
|
9256
|
+
if (this.disabled())
|
|
9257
|
+
return;
|
|
9258
|
+
this.inputRef()?.nativeElement.click();
|
|
9259
|
+
}
|
|
9235
9260
|
/** Modo editable: pide al consumer que abra su editor (recortador). */
|
|
9236
9261
|
onEditClick(e) {
|
|
9237
9262
|
e.stopPropagation();
|
|
@@ -9303,7 +9328,7 @@ class SuiImageUpload {
|
|
|
9303
9328
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
9304
9329
|
}
|
|
9305
9330
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiImageUpload, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9306
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiImageUpload, isStandalone: true, selector: "sui-image-upload", inputs: { shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, maxSize: { classPropertyName: "maxSize", publicName: "maxSize", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { src: "srcChange", imageSelected: "imageSelected", removed: "removed", editRequested: "editRequested", errorEvent: "errorEvent" }, host: { listeners: { "touchstart": "$event.currentTarget", "touchend": "$any($event.currentTarget).blur()", "click": "onHostClick()", "keydown.enter": "onHostClick()", "keydown.space": "onHostClick(); $event.preventDefault()", "dragover": "onDragOver($event)", "dragleave": "onDragLeave($event)", "drop": "onDrop($event)" }, properties: { "attr.title": "null", "attr.data-sui-shape": "shape()", "attr.data-sui-size": "size()", "attr.data-sui-state": "state()", "attr.data-sui-disabled": "disabled() ? \"\" : null", "attr.role": "\"button\"", "attr.tabindex": "disabled() ? -1 : 0", "style.width.px": "sizePx()", "style.height.px": "sizePx()" } }, viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["imgInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Estado: sin imagen (empty / dragover) -->\n@if (!hasSrc()) {\n <div class=\"sui-image-upload__empty\">\n <!-- Icono c\u00E1mara \u2014 sui-icon (DS), no SVG inline -->\n <div class=\"sui-image-upload__icon\">\n <sui-icon name=\"image-add-line\" [size]=\"iconSize()\" aria-hidden=\"true\" />\n </div>\n\n <div class=\"sui-image-upload__text\">\n <p class=\"sui-image-upload__title\">{{ resolvedTitle() }}</p>\n <p class=\"sui-image-upload__subtitle\">{{ resolvedSubtitle() }}</p>\n </div>\n\n @if (internalError()) {\n <p class=\"sui-image-upload__error\">{{ internalError() }}</p>\n }\n </div>\n}\n\n<!-- Estado: con imagen (filled) -->\n@if (hasSrc()) {\n <div class=\"sui-image-upload__preview\" [class.sui-image-upload__preview--editable]=\"editable()\">\n <img\n class=\"sui-image-upload__img\"\n [src]=\"src()\"\n alt=\"Preview\"\n draggable=\"false\" />\n\n @if (editable()) {\n <!-- Modo editable: controles de \u00EDcono en esquina (editar + tacho). -->\n <div class=\"sui-image-upload__controls\">\n <button\n type=\"button\"\n class=\"sui-image-upload__ctrl\"\n aria-label=\"Editar imagen\"\n [disabled]=\"disabled()\"\n (click)=\"onEditClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\">\n <sui-icon name=\"pencil-line\" [size]=\"16\" aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n class=\"sui-image-upload__ctrl sui-image-upload__ctrl--danger\"\n aria-label=\"Quitar imagen\"\n [disabled]=\"disabled()\"\n (click)=\"onRemoveClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\">\n <sui-icon name=\"delete-bin-line\" [size]=\"16\" aria-hidden=\"true\" />\n </button>\n </div>\n } @else {\n <!-- Overlay hover con icono lapiz (re-subir) -->\n <div class=\"sui-image-upload__overlay\" (click)=\"onChangeClick($event)\">\n <div class=\"sui-image-upload__overlay-icon\">\n <sui-icon name=\"pencil-line\" [size]=\"16\" aria-hidden=\"true\" />\n </div>\n </div>\n }\n </div>\n\n @if (!editable()) {\n <!-- Bot\u00F3n Quitar debajo del preview \u2014 sui-button stroke (DS), no <button> custom.\n Figma node 452:699 \"Remove\" = stroke error; aqu\u00ED usamos color=error para\n que el affordance de borrado sea consistente con el DS. -->\n <sui-button\n class=\"sui-image-upload__remove\"\n variant=\"stroke\"\n color=\"error\"\n size=\"2xsmall\"\n [disabled]=\"disabled()\"\n (click)=\"onRemoveClick($event)\">\n Quitar\n </sui-button>\n }\n}\n\n<!-- Input file oculto (siempre presente para el click) -->\n<input\n #imgInput\n type=\"file\"\n class=\"sui-image-upload__input\"\n accept=\"image/jpeg,image/png,image/webp,image/gif\"\n [disabled]=\"disabled()\"\n (change)=\"onInputChange($event)\" />\n", styles: ["@charset \"UTF-8\";:host{position:relative;display:inline-flex;flex-direction:column;align-items:center;gap:8px;font-family:var(--sui-font-sans, var(--font-sans, sans-serif));cursor:pointer;flex-shrink:0}:host([data-sui-disabled]){cursor:not-allowed;opacity:.5}.sui-image-upload__empty{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;border:1px dashed var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #fff);box-shadow:var(--sui-shadow-x-small, 0 1px 2px 0 rgba(0, 0, 0, .06));text-align:center;padding:12px 8px;box-sizing:border-box;transition:border-color var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1)),background var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1))}:host([data-sui-shape=circle]) .sui-image-upload__empty{border-radius:999px}:host([data-sui-shape=rect]) .sui-image-upload__empty{border-radius:var(--sui-radius-12, 12px)}:host(:hover:not([data-sui-disabled])) .sui-image-upload__empty{border-color:var(--sui-stroke-sub-300, #d1d1d1);background:var(--sui-bg-weak-50, #f7f7f7)}:host([data-sui-state=dragover]) .sui-image-upload__empty{border-color:var(--sui-primary-base, #fa7319);background:var(--sui-primary-alpha-10, rgba(250, 115, 25, .1019607843))}.sui-image-upload__icon{width:32px;height:32px;border-radius:999px;background:var(--sui-bg-weak-50, #f7f7f7);display:flex;align-items:center;justify-content:center;color:var(--sui-icon-sub-600, #5c5c5c);flex-shrink:0}:host([data-sui-size=xl]) .sui-image-upload__icon{width:40px;height:40px}:host([data-sui-state=dragover]) .sui-image-upload__icon{background:var(--sui-primary-alpha-16, rgba(250, 115, 25, .1607843137));color:var(--sui-primary-base, #fa7319)}.sui-image-upload__text{display:flex;flex-direction:column;gap:2px;align-items:center}.sui-image-upload__title{margin:0;font-size:12px;font-weight:500;line-height:16px;color:var(--sui-text-strong-950, #171717)}:host([data-sui-size=xl]) .sui-image-upload__title{font-size:13px;line-height:18px}.sui-image-upload__subtitle{margin:0;font-size:11px;font-weight:400;line-height:15px;color:var(--sui-text-sub-600, #5c5c5c)}:host([data-sui-size=sm]) .sui-image-upload__subtitle{display:none}:host([data-sui-size=xl]) .sui-image-upload__subtitle{font-size:12px;line-height:16px}.sui-image-upload__error{margin:2px 0 0;font-size:10px;line-height:14px;color:var(--sui-state-error-base, #fb3748);text-align:center}.sui-image-upload__preview{position:relative;width:100%;height:100%;overflow:hidden;box-shadow:var(--sui-shadow-x-small, 0 1px 2px 0 rgba(0, 0, 0, .06));flex-shrink:0}:host([data-sui-shape=circle]) .sui-image-upload__preview{border-radius:999px}:host([data-sui-shape=rect]) .sui-image-upload__preview{border-radius:var(--sui-radius-12, 12px)}.sui-image-upload__img{width:100%;height:100%;object-fit:cover;display:block;pointer-events:none;-webkit-user-select:none;user-select:none}.sui-image-upload__overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#0006;opacity:0;transition:opacity var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1));cursor:pointer}:host(:hover:not([data-sui-disabled])) .sui-image-upload__overlay{opacity:1}.sui-image-upload__overlay-icon{width:32px;height:32px;border-radius:999px;background:#fff3;display:flex;align-items:center;justify-content:center;color:var(--sui-static-white, #fff)}.sui-image-upload__preview--editable{cursor:default}.sui-image-upload__controls{position:absolute;top:8px;right:8px;display:flex;gap:6px;z-index:2}.sui-image-upload__ctrl{width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;border:none;background:#0000008c;color:var(--sui-static-white, #fff);cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background-color .15s ease,transform .12s ease}.sui-image-upload__ctrl:active{transform:scale(.92)}.sui-image-upload__ctrl:disabled{opacity:.5;cursor:not-allowed}.sui-image-upload__ctrl--danger:active{background:var(--sui-state-error-base, #fb3748)}.sui-image-upload__remove{flex-shrink:0}.sui-image-upload__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: SuiButton, selector: "sui-button", inputs: ["variant", "color", "size", "onlyIcon", "disabled", "leftIcon", "rightIcon", "type"] }, { kind: "component", type: SuiIcon, selector: "sui-icon", inputs: ["name", "size", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9331
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiImageUpload, isStandalone: true, selector: "sui-image-upload", inputs: { fluid: { classPropertyName: "fluid", publicName: "fluid", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, maxSize: { classPropertyName: "maxSize", publicName: "maxSize", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { src: "srcChange", imageSelected: "imageSelected", removed: "removed", editRequested: "editRequested", errorEvent: "errorEvent" }, host: { listeners: { "touchstart": "$event.currentTarget", "touchend": "$any($event.currentTarget).blur()", "click": "onHostClick()", "keydown.enter": "onHostClick()", "keydown.space": "onHostClick(); $event.preventDefault()", "dragover": "onDragOver($event)", "dragleave": "onDragLeave($event)", "drop": "onDrop($event)" }, properties: { "attr.title": "null", "attr.data-sui-shape": "shape()", "attr.data-sui-size": "size()", "attr.data-sui-state": "state()", "attr.data-sui-disabled": "disabled() ? \"\" : null", "attr.role": "\"button\"", "attr.tabindex": "disabled() ? -1 : 0", "attr.data-sui-fluid": "fluid() ? \"\" : null", "style.width.px": "fluid() ? null : sizePx()", "style.height.px": "fluid() ? null : sizePx()" } }, viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["imgInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Estado: sin imagen (empty / dragover) -->\n@if (!hasSrc()) {\n <div class=\"sui-image-upload__empty\">\n <!-- Icono c\u00E1mara \u2014 sui-icon (DS), no SVG inline -->\n <div class=\"sui-image-upload__icon\">\n <sui-icon name=\"image-add-line\" [size]=\"iconSize()\" aria-hidden=\"true\" />\n </div>\n\n <div class=\"sui-image-upload__text\">\n <p class=\"sui-image-upload__title\">{{ resolvedTitle() }}</p>\n <p class=\"sui-image-upload__subtitle\">{{ resolvedSubtitle() }}</p>\n </div>\n\n @if (internalError()) {\n <p class=\"sui-image-upload__error\">{{ internalError() }}</p>\n }\n </div>\n}\n\n<!-- Estado: con imagen (filled) -->\n@if (hasSrc()) {\n <div class=\"sui-image-upload__preview\" [class.sui-image-upload__preview--editable]=\"editable()\">\n <img\n class=\"sui-image-upload__img\"\n [src]=\"src()\"\n alt=\"Preview\"\n draggable=\"false\" />\n\n @if (editable()) {\n <!-- Modo editable: controles de \u00EDcono en esquina (editar + tacho). -->\n <div class=\"sui-image-upload__controls\">\n <button\n type=\"button\"\n class=\"sui-image-upload__ctrl\"\n aria-label=\"Editar imagen\"\n [disabled]=\"disabled()\"\n (click)=\"onEditClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\">\n <sui-icon name=\"pencil-line\" [size]=\"16\" aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n class=\"sui-image-upload__ctrl sui-image-upload__ctrl--danger\"\n aria-label=\"Quitar imagen\"\n [disabled]=\"disabled()\"\n (click)=\"onRemoveClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\">\n <sui-icon name=\"delete-bin-line\" [size]=\"16\" aria-hidden=\"true\" />\n </button>\n </div>\n } @else {\n <!-- Overlay hover con icono lapiz (re-subir) -->\n <div class=\"sui-image-upload__overlay\" (click)=\"onChangeClick($event)\">\n <div class=\"sui-image-upload__overlay-icon\">\n <sui-icon name=\"pencil-line\" [size]=\"16\" aria-hidden=\"true\" />\n </div>\n </div>\n }\n </div>\n\n @if (!editable()) {\n <!-- Bot\u00F3n Quitar debajo del preview \u2014 sui-button stroke (DS), no <button> custom.\n Figma node 452:699 \"Remove\" = stroke error; aqu\u00ED usamos color=error para\n que el affordance de borrado sea consistente con el DS. -->\n <sui-button\n class=\"sui-image-upload__remove\"\n variant=\"stroke\"\n color=\"error\"\n size=\"2xsmall\"\n [disabled]=\"disabled()\"\n (click)=\"onRemoveClick($event)\">\n Quitar\n </sui-button>\n }\n}\n\n<!-- Input file oculto (siempre presente para el click) -->\n<input\n #imgInput\n type=\"file\"\n class=\"sui-image-upload__input\"\n accept=\"image/jpeg,image/png,image/webp,image/gif\"\n [disabled]=\"disabled()\"\n (change)=\"onInputChange($event)\" />\n", styles: ["@charset \"UTF-8\";:host{position:relative;display:inline-flex;flex-direction:column;align-items:center;gap:8px;font-family:var(--sui-font-sans, var(--font-sans, sans-serif));cursor:pointer;flex-shrink:0}:host([data-sui-fluid]){display:block;width:100%}:host([data-sui-fluid]) .sui-image-upload__empty{height:auto;min-height:132px;padding:20px 16px}:host([data-sui-fluid]) .sui-image-upload__preview{height:auto;max-height:320px}:host([data-sui-fluid]) .sui-image-upload__img{height:auto;max-height:320px;object-fit:contain;background:var(--sui-bg-weak-50, #f7f7f7)}:host([data-sui-fluid]) .sui-image-upload__remove{margin-top:8px}:host([data-sui-disabled]){cursor:not-allowed;opacity:.5}.sui-image-upload__empty{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;border:1px dashed var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #fff);box-shadow:var(--sui-shadow-x-small, 0 1px 2px 0 rgba(0, 0, 0, .06));text-align:center;padding:12px 8px;box-sizing:border-box;transition:border-color var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1)),background var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1))}:host([data-sui-shape=circle]) .sui-image-upload__empty{border-radius:999px}:host([data-sui-shape=rect]) .sui-image-upload__empty{border-radius:var(--sui-radius-12, 12px)}:host(:hover:not([data-sui-disabled])) .sui-image-upload__empty{border-color:var(--sui-stroke-sub-300, #d1d1d1);background:var(--sui-bg-weak-50, #f7f7f7)}:host([data-sui-state=dragover]) .sui-image-upload__empty{border-color:var(--sui-primary-base, #fa7319);background:var(--sui-primary-alpha-10, rgba(250, 115, 25, .1019607843))}.sui-image-upload__icon{width:32px;height:32px;border-radius:999px;background:var(--sui-bg-weak-50, #f7f7f7);display:flex;align-items:center;justify-content:center;color:var(--sui-icon-sub-600, #5c5c5c);flex-shrink:0}:host([data-sui-size=xl]) .sui-image-upload__icon{width:40px;height:40px}:host([data-sui-state=dragover]) .sui-image-upload__icon{background:var(--sui-primary-alpha-16, rgba(250, 115, 25, .1607843137));color:var(--sui-primary-base, #fa7319)}.sui-image-upload__text{display:flex;flex-direction:column;gap:2px;align-items:center}.sui-image-upload__title{margin:0;font-size:12px;font-weight:500;line-height:16px;color:var(--sui-text-strong-950, #171717)}:host([data-sui-size=xl]) .sui-image-upload__title{font-size:13px;line-height:18px}.sui-image-upload__subtitle{margin:0;font-size:11px;font-weight:400;line-height:15px;color:var(--sui-text-sub-600, #5c5c5c)}:host([data-sui-size=sm]) .sui-image-upload__subtitle{display:none}:host([data-sui-size=xl]) .sui-image-upload__subtitle{font-size:12px;line-height:16px}.sui-image-upload__error{margin:2px 0 0;font-size:10px;line-height:14px;color:var(--sui-state-error-base, #fb3748);text-align:center}.sui-image-upload__preview{position:relative;width:100%;height:100%;overflow:hidden;box-shadow:var(--sui-shadow-x-small, 0 1px 2px 0 rgba(0, 0, 0, .06));flex-shrink:0}:host([data-sui-shape=circle]) .sui-image-upload__preview{border-radius:999px}:host([data-sui-shape=rect]) .sui-image-upload__preview{border-radius:var(--sui-radius-12, 12px)}.sui-image-upload__img{width:100%;height:100%;object-fit:cover;display:block;pointer-events:none;-webkit-user-select:none;user-select:none}.sui-image-upload__overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#0006;opacity:0;transition:opacity var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1));cursor:pointer}:host(:hover:not([data-sui-disabled])) .sui-image-upload__overlay{opacity:1}.sui-image-upload__overlay-icon{width:32px;height:32px;border-radius:999px;background:#fff3;display:flex;align-items:center;justify-content:center;color:var(--sui-static-white, #fff)}.sui-image-upload__preview--editable{cursor:default}.sui-image-upload__controls{position:absolute;top:8px;right:8px;display:flex;gap:6px;z-index:2}.sui-image-upload__ctrl{width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;border:none;background:#0000008c;color:var(--sui-static-white, #fff);cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background-color .15s ease,transform .12s ease}.sui-image-upload__ctrl:active{transform:scale(.92)}.sui-image-upload__ctrl:disabled{opacity:.5;cursor:not-allowed}.sui-image-upload__ctrl--danger:active{background:var(--sui-state-error-base, #fb3748)}.sui-image-upload__remove{flex-shrink:0}.sui-image-upload__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: SuiButton, selector: "sui-button", inputs: ["variant", "color", "size", "onlyIcon", "disabled", "leftIcon", "rightIcon", "type"] }, { kind: "component", type: SuiIcon, selector: "sui-icon", inputs: ["name", "size", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9307
9332
|
}
|
|
9308
9333
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiImageUpload, decorators: [{
|
|
9309
9334
|
type: Component,
|
|
@@ -9316,8 +9341,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
9316
9341
|
'[attr.data-sui-disabled]': 'disabled() ? "" : null',
|
|
9317
9342
|
'[attr.role]': '"button"',
|
|
9318
9343
|
'[attr.tabindex]': 'disabled() ? -1 : 0',
|
|
9319
|
-
'[
|
|
9320
|
-
|
|
9344
|
+
'[attr.data-sui-fluid]': 'fluid() ? "" : null',
|
|
9345
|
+
/* En modo fluido el tamaño lo pone el contenedor, no el `size`. */
|
|
9346
|
+
'[style.width.px]': 'fluid() ? null : sizePx()',
|
|
9347
|
+
'[style.height.px]': 'fluid() ? null : sizePx()',
|
|
9321
9348
|
/* iOS WKWebView :active fix — CRITICO para pages standalone */
|
|
9322
9349
|
'(touchstart)': '$event.currentTarget',
|
|
9323
9350
|
'(touchend)': '$any($event.currentTarget).blur()',
|
|
@@ -9327,8 +9354,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
9327
9354
|
'(dragover)': 'onDragOver($event)',
|
|
9328
9355
|
'(dragleave)': 'onDragLeave($event)',
|
|
9329
9356
|
'(drop)': 'onDrop($event)',
|
|
9330
|
-
}, template: "<!-- Estado: sin imagen (empty / dragover) -->\n@if (!hasSrc()) {\n <div class=\"sui-image-upload__empty\">\n <!-- Icono c\u00E1mara \u2014 sui-icon (DS), no SVG inline -->\n <div class=\"sui-image-upload__icon\">\n <sui-icon name=\"image-add-line\" [size]=\"iconSize()\" aria-hidden=\"true\" />\n </div>\n\n <div class=\"sui-image-upload__text\">\n <p class=\"sui-image-upload__title\">{{ resolvedTitle() }}</p>\n <p class=\"sui-image-upload__subtitle\">{{ resolvedSubtitle() }}</p>\n </div>\n\n @if (internalError()) {\n <p class=\"sui-image-upload__error\">{{ internalError() }}</p>\n }\n </div>\n}\n\n<!-- Estado: con imagen (filled) -->\n@if (hasSrc()) {\n <div class=\"sui-image-upload__preview\" [class.sui-image-upload__preview--editable]=\"editable()\">\n <img\n class=\"sui-image-upload__img\"\n [src]=\"src()\"\n alt=\"Preview\"\n draggable=\"false\" />\n\n @if (editable()) {\n <!-- Modo editable: controles de \u00EDcono en esquina (editar + tacho). -->\n <div class=\"sui-image-upload__controls\">\n <button\n type=\"button\"\n class=\"sui-image-upload__ctrl\"\n aria-label=\"Editar imagen\"\n [disabled]=\"disabled()\"\n (click)=\"onEditClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\">\n <sui-icon name=\"pencil-line\" [size]=\"16\" aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n class=\"sui-image-upload__ctrl sui-image-upload__ctrl--danger\"\n aria-label=\"Quitar imagen\"\n [disabled]=\"disabled()\"\n (click)=\"onRemoveClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\">\n <sui-icon name=\"delete-bin-line\" [size]=\"16\" aria-hidden=\"true\" />\n </button>\n </div>\n } @else {\n <!-- Overlay hover con icono lapiz (re-subir) -->\n <div class=\"sui-image-upload__overlay\" (click)=\"onChangeClick($event)\">\n <div class=\"sui-image-upload__overlay-icon\">\n <sui-icon name=\"pencil-line\" [size]=\"16\" aria-hidden=\"true\" />\n </div>\n </div>\n }\n </div>\n\n @if (!editable()) {\n <!-- Bot\u00F3n Quitar debajo del preview \u2014 sui-button stroke (DS), no <button> custom.\n Figma node 452:699 \"Remove\" = stroke error; aqu\u00ED usamos color=error para\n que el affordance de borrado sea consistente con el DS. -->\n <sui-button\n class=\"sui-image-upload__remove\"\n variant=\"stroke\"\n color=\"error\"\n size=\"2xsmall\"\n [disabled]=\"disabled()\"\n (click)=\"onRemoveClick($event)\">\n Quitar\n </sui-button>\n }\n}\n\n<!-- Input file oculto (siempre presente para el click) -->\n<input\n #imgInput\n type=\"file\"\n class=\"sui-image-upload__input\"\n accept=\"image/jpeg,image/png,image/webp,image/gif\"\n [disabled]=\"disabled()\"\n (change)=\"onInputChange($event)\" />\n", styles: ["@charset \"UTF-8\";:host{position:relative;display:inline-flex;flex-direction:column;align-items:center;gap:8px;font-family:var(--sui-font-sans, var(--font-sans, sans-serif));cursor:pointer;flex-shrink:0}:host([data-sui-disabled]){cursor:not-allowed;opacity:.5}.sui-image-upload__empty{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;border:1px dashed var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #fff);box-shadow:var(--sui-shadow-x-small, 0 1px 2px 0 rgba(0, 0, 0, .06));text-align:center;padding:12px 8px;box-sizing:border-box;transition:border-color var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1)),background var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1))}:host([data-sui-shape=circle]) .sui-image-upload__empty{border-radius:999px}:host([data-sui-shape=rect]) .sui-image-upload__empty{border-radius:var(--sui-radius-12, 12px)}:host(:hover:not([data-sui-disabled])) .sui-image-upload__empty{border-color:var(--sui-stroke-sub-300, #d1d1d1);background:var(--sui-bg-weak-50, #f7f7f7)}:host([data-sui-state=dragover]) .sui-image-upload__empty{border-color:var(--sui-primary-base, #fa7319);background:var(--sui-primary-alpha-10, rgba(250, 115, 25, .1019607843))}.sui-image-upload__icon{width:32px;height:32px;border-radius:999px;background:var(--sui-bg-weak-50, #f7f7f7);display:flex;align-items:center;justify-content:center;color:var(--sui-icon-sub-600, #5c5c5c);flex-shrink:0}:host([data-sui-size=xl]) .sui-image-upload__icon{width:40px;height:40px}:host([data-sui-state=dragover]) .sui-image-upload__icon{background:var(--sui-primary-alpha-16, rgba(250, 115, 25, .1607843137));color:var(--sui-primary-base, #fa7319)}.sui-image-upload__text{display:flex;flex-direction:column;gap:2px;align-items:center}.sui-image-upload__title{margin:0;font-size:12px;font-weight:500;line-height:16px;color:var(--sui-text-strong-950, #171717)}:host([data-sui-size=xl]) .sui-image-upload__title{font-size:13px;line-height:18px}.sui-image-upload__subtitle{margin:0;font-size:11px;font-weight:400;line-height:15px;color:var(--sui-text-sub-600, #5c5c5c)}:host([data-sui-size=sm]) .sui-image-upload__subtitle{display:none}:host([data-sui-size=xl]) .sui-image-upload__subtitle{font-size:12px;line-height:16px}.sui-image-upload__error{margin:2px 0 0;font-size:10px;line-height:14px;color:var(--sui-state-error-base, #fb3748);text-align:center}.sui-image-upload__preview{position:relative;width:100%;height:100%;overflow:hidden;box-shadow:var(--sui-shadow-x-small, 0 1px 2px 0 rgba(0, 0, 0, .06));flex-shrink:0}:host([data-sui-shape=circle]) .sui-image-upload__preview{border-radius:999px}:host([data-sui-shape=rect]) .sui-image-upload__preview{border-radius:var(--sui-radius-12, 12px)}.sui-image-upload__img{width:100%;height:100%;object-fit:cover;display:block;pointer-events:none;-webkit-user-select:none;user-select:none}.sui-image-upload__overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#0006;opacity:0;transition:opacity var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1));cursor:pointer}:host(:hover:not([data-sui-disabled])) .sui-image-upload__overlay{opacity:1}.sui-image-upload__overlay-icon{width:32px;height:32px;border-radius:999px;background:#fff3;display:flex;align-items:center;justify-content:center;color:var(--sui-static-white, #fff)}.sui-image-upload__preview--editable{cursor:default}.sui-image-upload__controls{position:absolute;top:8px;right:8px;display:flex;gap:6px;z-index:2}.sui-image-upload__ctrl{width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;border:none;background:#0000008c;color:var(--sui-static-white, #fff);cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background-color .15s ease,transform .12s ease}.sui-image-upload__ctrl:active{transform:scale(.92)}.sui-image-upload__ctrl:disabled{opacity:.5;cursor:not-allowed}.sui-image-upload__ctrl--danger:active{background:var(--sui-state-error-base, #fb3748)}.sui-image-upload__remove{flex-shrink:0}.sui-image-upload__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
|
|
9331
|
-
}], propDecorators: { shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }, { type: i0.Output, args: ["srcChange"] }], maxSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSize", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], imageSelected: [{ type: i0.Output, args: ["imageSelected"] }], removed: [{ type: i0.Output, args: ["removed"] }], editRequested: [{ type: i0.Output, args: ["editRequested"] }], errorEvent: [{ type: i0.Output, args: ["errorEvent"] }], inputRef: [{ type: i0.ViewChild, args: ['imgInput', { isSignal: true }] }] } });
|
|
9357
|
+
}, template: "<!-- Estado: sin imagen (empty / dragover) -->\n@if (!hasSrc()) {\n <div class=\"sui-image-upload__empty\">\n <!-- Icono c\u00E1mara \u2014 sui-icon (DS), no SVG inline -->\n <div class=\"sui-image-upload__icon\">\n <sui-icon name=\"image-add-line\" [size]=\"iconSize()\" aria-hidden=\"true\" />\n </div>\n\n <div class=\"sui-image-upload__text\">\n <p class=\"sui-image-upload__title\">{{ resolvedTitle() }}</p>\n <p class=\"sui-image-upload__subtitle\">{{ resolvedSubtitle() }}</p>\n </div>\n\n @if (internalError()) {\n <p class=\"sui-image-upload__error\">{{ internalError() }}</p>\n }\n </div>\n}\n\n<!-- Estado: con imagen (filled) -->\n@if (hasSrc()) {\n <div class=\"sui-image-upload__preview\" [class.sui-image-upload__preview--editable]=\"editable()\">\n <img\n class=\"sui-image-upload__img\"\n [src]=\"src()\"\n alt=\"Preview\"\n draggable=\"false\" />\n\n @if (editable()) {\n <!-- Modo editable: controles de \u00EDcono en esquina (editar + tacho). -->\n <div class=\"sui-image-upload__controls\">\n <button\n type=\"button\"\n class=\"sui-image-upload__ctrl\"\n aria-label=\"Editar imagen\"\n [disabled]=\"disabled()\"\n (click)=\"onEditClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\">\n <sui-icon name=\"pencil-line\" [size]=\"16\" aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n class=\"sui-image-upload__ctrl sui-image-upload__ctrl--danger\"\n aria-label=\"Quitar imagen\"\n [disabled]=\"disabled()\"\n (click)=\"onRemoveClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\">\n <sui-icon name=\"delete-bin-line\" [size]=\"16\" aria-hidden=\"true\" />\n </button>\n </div>\n } @else {\n <!-- Overlay hover con icono lapiz (re-subir) -->\n <div class=\"sui-image-upload__overlay\" (click)=\"onChangeClick($event)\">\n <div class=\"sui-image-upload__overlay-icon\">\n <sui-icon name=\"pencil-line\" [size]=\"16\" aria-hidden=\"true\" />\n </div>\n </div>\n }\n </div>\n\n @if (!editable()) {\n <!-- Bot\u00F3n Quitar debajo del preview \u2014 sui-button stroke (DS), no <button> custom.\n Figma node 452:699 \"Remove\" = stroke error; aqu\u00ED usamos color=error para\n que el affordance de borrado sea consistente con el DS. -->\n <sui-button\n class=\"sui-image-upload__remove\"\n variant=\"stroke\"\n color=\"error\"\n size=\"2xsmall\"\n [disabled]=\"disabled()\"\n (click)=\"onRemoveClick($event)\">\n Quitar\n </sui-button>\n }\n}\n\n<!-- Input file oculto (siempre presente para el click) -->\n<input\n #imgInput\n type=\"file\"\n class=\"sui-image-upload__input\"\n accept=\"image/jpeg,image/png,image/webp,image/gif\"\n [disabled]=\"disabled()\"\n (change)=\"onInputChange($event)\" />\n", styles: ["@charset \"UTF-8\";:host{position:relative;display:inline-flex;flex-direction:column;align-items:center;gap:8px;font-family:var(--sui-font-sans, var(--font-sans, sans-serif));cursor:pointer;flex-shrink:0}:host([data-sui-fluid]){display:block;width:100%}:host([data-sui-fluid]) .sui-image-upload__empty{height:auto;min-height:132px;padding:20px 16px}:host([data-sui-fluid]) .sui-image-upload__preview{height:auto;max-height:320px}:host([data-sui-fluid]) .sui-image-upload__img{height:auto;max-height:320px;object-fit:contain;background:var(--sui-bg-weak-50, #f7f7f7)}:host([data-sui-fluid]) .sui-image-upload__remove{margin-top:8px}:host([data-sui-disabled]){cursor:not-allowed;opacity:.5}.sui-image-upload__empty{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;border:1px dashed var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #fff);box-shadow:var(--sui-shadow-x-small, 0 1px 2px 0 rgba(0, 0, 0, .06));text-align:center;padding:12px 8px;box-sizing:border-box;transition:border-color var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1)),background var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1))}:host([data-sui-shape=circle]) .sui-image-upload__empty{border-radius:999px}:host([data-sui-shape=rect]) .sui-image-upload__empty{border-radius:var(--sui-radius-12, 12px)}:host(:hover:not([data-sui-disabled])) .sui-image-upload__empty{border-color:var(--sui-stroke-sub-300, #d1d1d1);background:var(--sui-bg-weak-50, #f7f7f7)}:host([data-sui-state=dragover]) .sui-image-upload__empty{border-color:var(--sui-primary-base, #fa7319);background:var(--sui-primary-alpha-10, rgba(250, 115, 25, .1019607843))}.sui-image-upload__icon{width:32px;height:32px;border-radius:999px;background:var(--sui-bg-weak-50, #f7f7f7);display:flex;align-items:center;justify-content:center;color:var(--sui-icon-sub-600, #5c5c5c);flex-shrink:0}:host([data-sui-size=xl]) .sui-image-upload__icon{width:40px;height:40px}:host([data-sui-state=dragover]) .sui-image-upload__icon{background:var(--sui-primary-alpha-16, rgba(250, 115, 25, .1607843137));color:var(--sui-primary-base, #fa7319)}.sui-image-upload__text{display:flex;flex-direction:column;gap:2px;align-items:center}.sui-image-upload__title{margin:0;font-size:12px;font-weight:500;line-height:16px;color:var(--sui-text-strong-950, #171717)}:host([data-sui-size=xl]) .sui-image-upload__title{font-size:13px;line-height:18px}.sui-image-upload__subtitle{margin:0;font-size:11px;font-weight:400;line-height:15px;color:var(--sui-text-sub-600, #5c5c5c)}:host([data-sui-size=sm]) .sui-image-upload__subtitle{display:none}:host([data-sui-size=xl]) .sui-image-upload__subtitle{font-size:12px;line-height:16px}.sui-image-upload__error{margin:2px 0 0;font-size:10px;line-height:14px;color:var(--sui-state-error-base, #fb3748);text-align:center}.sui-image-upload__preview{position:relative;width:100%;height:100%;overflow:hidden;box-shadow:var(--sui-shadow-x-small, 0 1px 2px 0 rgba(0, 0, 0, .06));flex-shrink:0}:host([data-sui-shape=circle]) .sui-image-upload__preview{border-radius:999px}:host([data-sui-shape=rect]) .sui-image-upload__preview{border-radius:var(--sui-radius-12, 12px)}.sui-image-upload__img{width:100%;height:100%;object-fit:cover;display:block;pointer-events:none;-webkit-user-select:none;user-select:none}.sui-image-upload__overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#0006;opacity:0;transition:opacity var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1));cursor:pointer}:host(:hover:not([data-sui-disabled])) .sui-image-upload__overlay{opacity:1}.sui-image-upload__overlay-icon{width:32px;height:32px;border-radius:999px;background:#fff3;display:flex;align-items:center;justify-content:center;color:var(--sui-static-white, #fff)}.sui-image-upload__preview--editable{cursor:default}.sui-image-upload__controls{position:absolute;top:8px;right:8px;display:flex;gap:6px;z-index:2}.sui-image-upload__ctrl{width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;border:none;background:#0000008c;color:var(--sui-static-white, #fff);cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background-color .15s ease,transform .12s ease}.sui-image-upload__ctrl:active{transform:scale(.92)}.sui-image-upload__ctrl:disabled{opacity:.5;cursor:not-allowed}.sui-image-upload__ctrl--danger:active{background:var(--sui-state-error-base, #fb3748)}.sui-image-upload__remove{flex-shrink:0}.sui-image-upload__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
|
|
9358
|
+
}], propDecorators: { fluid: [{ type: i0.Input, args: [{ isSignal: true, alias: "fluid", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }, { type: i0.Output, args: ["srcChange"] }], maxSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSize", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], imageSelected: [{ type: i0.Output, args: ["imageSelected"] }], removed: [{ type: i0.Output, args: ["removed"] }], editRequested: [{ type: i0.Output, args: ["editRequested"] }], errorEvent: [{ type: i0.Output, args: ["errorEvent"] }], inputRef: [{ type: i0.ViewChild, args: ['imgInput', { isSignal: true }] }] } });
|
|
9332
9359
|
|
|
9333
9360
|
/**
|
|
9334
9361
|
* SUI Inline Input — SUI Design System 2.0
|