@libs-ui/components-image-editor 0.2.306 → 0.2.307-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { NgTemplateOutlet } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { EventEmitter, Component, Input, Output, signal, input, model, viewChild, output, inject, DestroyRef, ChangeDetectionStrategy, Optional, Inject, ViewChild } from '@angular/core';
3
+ import { EventEmitter, Output, Input, Component, signal, input, model, viewChild, output, inject, DestroyRef, Optional, Inject, ChangeDetectionStrategy, ViewChild } from '@angular/core';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
5
  import { LibsUiComponentsButtonsButtonComponent } from '@libs-ui/components-buttons-button';
6
6
  import { LibsUiComponentsInputsValidComponent } from '@libs-ui/components-inputs-valid';
@@ -18,43 +18,43 @@ const cropRationItems = () => {
18
18
  return [
19
19
  {
20
20
  key: 'free',
21
- icon: 'libs-ui-icon-customize-image-outline'
21
+ icon: 'libs-ui-icon-customize-image-outline',
22
22
  },
23
23
  {
24
24
  key: '1:1',
25
25
  value: 1,
26
- icon: 'libs-ui-icon-ratio-1-1'
26
+ icon: 'libs-ui-icon-ratio-1-1',
27
27
  },
28
28
  {
29
29
  key: '2:3',
30
30
  value: 2 / 3,
31
- icon: 'libs-ui-icon-ratio-2-3'
31
+ icon: 'libs-ui-icon-ratio-2-3',
32
32
  },
33
33
  {
34
34
  key: '3:2',
35
35
  value: 3 / 2,
36
- icon: 'libs-ui-icon-ratio-3-2'
36
+ icon: 'libs-ui-icon-ratio-3-2',
37
37
  },
38
38
  {
39
39
  key: '3:4',
40
40
  value: 3 / 4,
41
- icon: 'libs-ui-icon-ratio-3-4'
41
+ icon: 'libs-ui-icon-ratio-3-4',
42
42
  },
43
43
  {
44
44
  key: '4:3',
45
45
  value: 4 / 3,
46
- icon: 'libs-ui-icon-ratio-4-3'
46
+ icon: 'libs-ui-icon-ratio-4-3',
47
47
  },
48
48
  {
49
49
  key: '9:16',
50
50
  value: 9 / 16,
51
- icon: 'libs-ui-icon-ratio-9-16'
51
+ icon: 'libs-ui-icon-ratio-9-16',
52
52
  },
53
53
  {
54
54
  key: '16:9',
55
55
  value: 16 / 9,
56
- icon: 'libs-ui-icon-ratio-16-9'
57
- }
56
+ icon: 'libs-ui-icon-ratio-16-9',
57
+ },
58
58
  ];
59
59
  };
60
60
  const getMimeTypeFromSrc = (src) => {
@@ -67,7 +67,7 @@ const getMimeTypeFromSrc = (src) => {
67
67
  }
68
68
  const srcSplit = src.split('.');
69
69
  const mineType = srcSplit[srcSplit.length - 1];
70
- return `image/${(mineType.toLowerCase()) === 'jpg' ? 'jpeg' : mineType}`;
70
+ return `image/${mineType.toLowerCase() === 'jpg' ? 'jpeg' : mineType}`;
71
71
  };
72
72
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
73
  const getDataUrl = (canvas, mimetype, src) => {
@@ -95,11 +95,11 @@ const getCropRectImage = (rectClip, imgWidth, imgHeight, scale) => {
95
95
  left: Math.max(rectClip.left * scale, 0),
96
96
  top: Math.max(rectClip.top * scale, 0),
97
97
  width: rectClip.width * scale,
98
- height: rectClip.height * scale
98
+ height: rectClip.height * scale,
99
99
  };
100
100
  };
101
101
  const getStylesOfElement = (element, fields) => {
102
- return fields?.map(field => parseFloat(get(element, field) || '0'));
102
+ return fields?.map((field) => parseFloat(get(element, field) || '0'));
103
103
  };
104
104
 
105
105
  class LibsUiComponentsImageEditorResizeComponent {
@@ -117,17 +117,20 @@ class LibsUiComponentsImageEditorResizeComponent {
117
117
  outClose = new EventEmitter();
118
118
  outSave = new EventEmitter();
119
119
  constructor() {
120
- this.buttonsFooter = [{
120
+ this.buttonsFooter = [
121
+ {
121
122
  type: 'button-third',
122
123
  label: 'i18n_cancel',
123
- action: async () => this.outClose.emit()
124
- }, {
124
+ action: async () => this.outClose.emit(),
125
+ },
126
+ {
125
127
  label: 'i18n_save',
126
128
  action: async () => {
127
129
  this.outSave.emit(this.resizeData);
128
130
  this.outClose.emit();
129
- }
130
- }];
131
+ },
132
+ },
133
+ ];
131
134
  this.inputValidFunctionControl = [];
132
135
  }
133
136
  async ngOnInit() {
@@ -144,8 +147,8 @@ class LibsUiComponentsImageEditorResizeComponent {
144
147
  ratio = 100;
145
148
  this.resizeData.ratio = ratio;
146
149
  }
147
- this.resizeData.width = Math.max(parseInt(`${this.originWidth * ratio / 100}`), 1);
148
- this.resizeData.height = Math.max(parseInt(`${this.originHeight * ratio / 100}`), 1);
150
+ this.resizeData.width = Math.max(parseInt(`${(this.originWidth * ratio) / 100}`), 1);
151
+ this.resizeData.height = Math.max(parseInt(`${(this.originHeight * ratio) / 100}`), 1);
149
152
  // this.inputValidFunctionControl.forEach(item => item.detectChanges());
150
153
  this.currentFileSize = await this.getFileSize();
151
154
  }
@@ -177,8 +180,8 @@ class LibsUiComponentsImageEditorResizeComponent {
177
180
  if (!value || value > originByValue) {
178
181
  return;
179
182
  }
180
- this.resizeData[fieldResize] = Math.max(parseInt(`${originOtherValue * value / originByValue}`), 1);
181
- this.resizeData.ratio = Math.max(parseInt(`${100 * value / originByValue}`), 1);
183
+ this.resizeData[fieldResize] = Math.max(parseInt(`${(originOtherValue * value) / originByValue}`), 1);
184
+ this.resizeData.ratio = Math.max(parseInt(`${(100 * value) / originByValue}`), 1);
182
185
  this.currentFileSize = await this.getFileSize();
183
186
  }
184
187
  handlerInputValidFunctionControl(event) {
@@ -190,13 +193,11 @@ class LibsUiComponentsImageEditorResizeComponent {
190
193
  }
191
194
  }
192
195
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsImageEditorResizeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
193
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: LibsUiComponentsImageEditorResizeComponent, isStandalone: true, selector: "libs-ui-components-image_editor-resize", inputs: { resizeData: "resizeData", originWidth: "originWidth", originHeight: "originHeight", src: "src", zIndex: "zIndex", mimetype: "mimetype" }, outputs: { outClose: "outClose", outSave: "outSave" }, ngImport: i0, template: "<libs_ui-components-modal [headerConfig]=\"{ignoreHeaderTheme: true}\"\n [mode]=\"'center'\"\n [width]=\"'500px'\"\n [height]=\"'auto'\"\n [title]=\"'i18n_resize' | translate\"\n [zIndex]=\"zIndex\"\n [buttonsFooter]=\"buttonsFooter\"\n (outEvent)=\"handlerEvent($event)\">\n <div class=\"libs-ui-modal-body-custom w-full h-full\">\n <div class=\"flex items-center\">\n <div class=\"libs-ui-font-h7r mr-[4px] text-[#6a7383] w-[100px] shrink-0\">\n {{ 'i18n_ratio_size' | translate }} (%)\n </div>\n <libs_ui-components-inputs-valid [ignoreWidthInput100]=\"true\"\n [classIncludeInput]=\"'w-[132px]'\"\n [dataType]=\"'int'\"\n [fieldNameBind]=\"'ratio'\"\n [(item)]=\"resizeData\"\n [minValueNumber]=\"1\"\n [maxValueNumber]=\"100\"\n [valueUpDownNumber]=\"1\"\n [validRequired]=\"{isRequired: true}\"\n [ignoreShowError]=\"true\"\n (outValueChange)=\"handlerResizeRatio()\"\n (outFunctionsControl)=\"handlerInputValidFunctionControl($event)\" />\n </div>\n <div class=\"mt-[16px] relative\">\n <div class=\"flex items-center\">\n <div class=\"libs-ui-font-h7r mr-[4px] text-[#6a7383] w-[100px] shrink-0\">\n {{ 'i18n_width' | translate }}\n </div>\n <libs_ui-components-inputs-valid [ignoreWidthInput100]=\"true\"\n [classIncludeInput]=\"'w-[102px]'\"\n [dataType]=\"'int'\"\n [maxValueNumber]=\"originWidth\"\n [minValueNumber]=\"1\"\n [fieldNameBind]=\"'width'\"\n [(item)]=\"resizeData\"\n [unitsRight]=\"[{id: 'px', label: 'px'}]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n (outValueChange)=\"handlerResizeWidth()\"\n (outFunctionsControl)=\"handlerInputValidFunctionControl($event)\" />\n </div>\n <div class=\"flex items-center mt-[8px]\">\n <div class=\"libs-ui-font-h7r mr-[4px] text-[#6a7383] w-[100px] shrink-0\">\n {{ 'i18n_length' | translate }}\n </div>\n <libs_ui-components-inputs-valid [ignoreWidthInput100]=\"true\"\n [classIncludeInput]=\"'w-[102px]'\"\n [dataType]=\"'int'\"\n [minValueNumber]=\"1\"\n [maxValueNumber]=\"originHeight\"\n [fieldNameBind]=\"'height'\"\n [(item)]=\"resizeData\"\n [unitsRight]=\"[{id: 'px', label: 'px'}]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n (outValueChange)=\"handlerResizeHeight()\"\n (outFunctionsControl)=\"handlerInputValidFunctionControl($event)\" />\n </div>\n <div class=\"absolute flex items-center left-[236px] top-[14px]\">\n <div\n class=\"w-[20px] h-[44px] libs-ui-border-top-general libs-ui-border-right-general libs-ui-border-bottom-general\">\n </div>\n <div class=\"ml-[6px] text-[#9ca2ad] libs-ui-icon-lock\"></div>\n </div>\n </div>\n <div class=\"mt-[16px]\">\n <div class=\"libs-ui-font-h6m text-[#6a7383] mb-[8px]\">{{ 'i18n_size_photo' | translate }}</div>\n <div class=\"libs-ui-font-h5r rounded-[4px] py-[8px] px-[16px] bg-[#f8f9fa] text-[#9ca2ad]\">\n {{ 'i18n_file_size_compare_when_resize' | translate:{current_size: currentFileSize, original_size: originFileSize} }}\n </div>\n </div>\n </div>\n</libs_ui-components-modal>\n", dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "component", type: LibsUiComponentsModalComponent, selector: "libs_ui-components-modal", inputs: ["show", "mode", "isBackdropTransparent", "isBackgroundTransparentModal", "isSizeBackdropByWidthHeightInput", "hasShadowBoxWhenHiddenBackDropTransparent", "classIncludeModalWrapper", "zIndex", "width", "height", "maxWidth", "maxHeight", "minWidth", "isFullScreen", "disable", "ignoreCommunicateMicroEvent", "headerConfig", "bodyConfig", "footerConfig", "buttonsFooter", "title", "titleUseXssFilter", "titleUseTooltip", "titleUseInnerText"], outputs: ["showChange", "widthChange", "heightChange", "maxWidthChange", "maxHeightChange", "minWidthChange", "disableChange", "buttonsFooterChange", "outScrollContent", "outEvent", "outFunctionControl"] }, { kind: "component", type: LibsUiComponentsInputsValidComponent, selector: "libs_ui-components-inputs-valid", inputs: ["item", "labelConfig", "emitEmptyInDataTypeNumber", "ignoreBlockInputMaxValue", "fieldNameBind", "showCount", "typeComponentSelectItem", "valueComponentSelectItem", "disableComponentSelectItem", "tagInput", "dataType", "typeInput", "modeInput", "resetAutoCompletePassword", "textAreaEnterNotNewLine", "fixedFloat", "acceptNegativeValue", "valueUpDownNumber", "ignoreWidthInput100", "classIncludeInput", "classContainerInput", "readonly", "disable", "noBorder", "backgroundNone", "useColorModeExist", "placeholder", "keepPlaceholderOnly", "classContainerBottomInput", "autoRemoveEmoji", "defaultHeight", "maxHeightTextArea", "minHeightTextArea", "ignoreShowError", "borderError", "iconLeftClass", "popoverContentIconLeft", "iconRightClass", "popoverContentIconRight", "zIndexPopoverContent", "unitsLeft", "configUnitLeft", "keySelectedUnitLeft", "unitsRight", "configUnitRight", "keySelectedUnitRight", "maxValueNumber", "minValueNumber", "ignoreContentLeft", "ignoreContentRight", "isBaselineStyle", "valuePatternShowError", "validPattern", "validRequired", "validMinLength", "validMinValue", "validMaxValue", "validMaxLength", "functionValid", "maxLength", "positionMessageErrorStartInput", "classInclude", "resize", "templateLeftBottomInput", "templateRightBottomInput", "onlyAcceptNegativeValue", "autoAddZeroLessThan10InTypeInt", "maxLengthNumberCount", "classMessageErrorInclude", "ignoreStopPropagationEvent", "ignoreUnitRightClassReadOnly", "paddingRightCustomSpecific", "focusTimeOut", "debounceTimeValidate"], outputs: ["itemChange", "outValueChange", "outSelect", "outIconLeft", "outIconRight", "outClickButtonLabel", "outSwitchEventLabel", "outLabelRightClick", "outEnterInputEvent", "outHeightAreaChange", "outFunctionsControl", "outFocusAndBlur", "outChangeValueByButtonUpDown"] }] });
196
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: LibsUiComponentsImageEditorResizeComponent, isStandalone: true, selector: "libs-ui-components-image_editor-resize", inputs: { resizeData: "resizeData", originWidth: "originWidth", originHeight: "originHeight", src: "src", zIndex: "zIndex", mimetype: "mimetype" }, outputs: { outClose: "outClose", outSave: "outSave" }, ngImport: i0, template: "<libs_ui-components-modal\n [headerConfig]=\"{ ignoreHeaderTheme: true }\"\n [mode]=\"'center'\"\n [width]=\"'500px'\"\n [height]=\"'auto'\"\n [title]=\"'i18n_resize' | translate\"\n [zIndex]=\"zIndex\"\n [buttonsFooter]=\"buttonsFooter\"\n (outEvent)=\"handlerEvent($event)\">\n <div class=\"libs-ui-modal-body-custom w-full h-full\">\n <div class=\"flex items-center\">\n <div class=\"libs-ui-font-h7r mr-[4px] text-[#6a7383] w-[100px] shrink-0\">{{ 'i18n_ratio_size' | translate }} (%)</div>\n <libs_ui-components-inputs-valid\n [ignoreWidthInput100]=\"true\"\n [classIncludeInput]=\"'w-[132px]'\"\n [dataType]=\"'int'\"\n [fieldNameBind]=\"'ratio'\"\n [(item)]=\"resizeData\"\n [minValueNumber]=\"1\"\n [maxValueNumber]=\"100\"\n [valueUpDownNumber]=\"1\"\n [validRequired]=\"{ isRequired: true }\"\n [ignoreShowError]=\"true\"\n (outValueChange)=\"handlerResizeRatio()\"\n (outFunctionsControl)=\"handlerInputValidFunctionControl($event)\" />\n </div>\n <div class=\"mt-[16px] relative\">\n <div class=\"flex items-center\">\n <div class=\"libs-ui-font-h7r mr-[4px] text-[#6a7383] w-[100px] shrink-0\">\n {{ 'i18n_width' | translate }}\n </div>\n <libs_ui-components-inputs-valid\n [ignoreWidthInput100]=\"true\"\n [classIncludeInput]=\"'w-[102px]'\"\n [dataType]=\"'int'\"\n [maxValueNumber]=\"originWidth\"\n [minValueNumber]=\"1\"\n [fieldNameBind]=\"'width'\"\n [(item)]=\"resizeData\"\n [unitsRight]=\"[{ id: 'px', label: 'px' }]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n (outValueChange)=\"handlerResizeWidth()\"\n (outFunctionsControl)=\"handlerInputValidFunctionControl($event)\" />\n </div>\n <div class=\"flex items-center mt-[8px]\">\n <div class=\"libs-ui-font-h7r mr-[4px] text-[#6a7383] w-[100px] shrink-0\">\n {{ 'i18n_length' | translate }}\n </div>\n <libs_ui-components-inputs-valid\n [ignoreWidthInput100]=\"true\"\n [classIncludeInput]=\"'w-[102px]'\"\n [dataType]=\"'int'\"\n [minValueNumber]=\"1\"\n [maxValueNumber]=\"originHeight\"\n [fieldNameBind]=\"'height'\"\n [(item)]=\"resizeData\"\n [unitsRight]=\"[{ id: 'px', label: 'px' }]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n (outValueChange)=\"handlerResizeHeight()\"\n (outFunctionsControl)=\"handlerInputValidFunctionControl($event)\" />\n </div>\n <div class=\"absolute flex items-center left-[236px] top-[14px]\">\n <div class=\"w-[20px] h-[44px] libs-ui-border-top-general libs-ui-border-right-general libs-ui-border-bottom-general\"></div>\n <div class=\"ml-[6px] text-[#9ca2ad] libs-ui-icon-lock\"></div>\n </div>\n </div>\n <div class=\"mt-[16px]\">\n <div class=\"libs-ui-font-h6m text-[#6a7383] mb-[8px]\">{{ 'i18n_size_photo' | translate }}</div>\n <div class=\"libs-ui-font-h5r rounded-[4px] py-[8px] px-[16px] bg-[#f8f9fa] text-[#9ca2ad]\">\n {{ 'i18n_file_size_compare_when_resize' | translate: { current_size: currentFileSize, original_size: originFileSize } }}\n </div>\n </div>\n </div>\n</libs_ui-components-modal>\n", dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "component", type: LibsUiComponentsModalComponent, selector: "libs_ui-components-modal", inputs: ["show", "mode", "isBackdropTransparent", "isBackgroundTransparentModal", "isSizeBackdropByWidthHeightInput", "hasShadowBoxWhenHiddenBackDropTransparent", "classIncludeModalWrapper", "zIndex", "width", "height", "maxWidth", "maxHeight", "minWidth", "isFullScreen", "disable", "ignoreCommunicateMicroEvent", "headerConfig", "bodyConfig", "footerConfig", "buttonsFooter", "title", "titleUseXssFilter", "titleUseTooltip", "titleUseInnerText"], outputs: ["showChange", "widthChange", "heightChange", "maxWidthChange", "maxHeightChange", "minWidthChange", "disableChange", "buttonsFooterChange", "outScrollContent", "outEvent", "outFunctionControl"] }, { kind: "component", type: LibsUiComponentsInputsValidComponent, selector: "libs_ui-components-inputs-valid", inputs: ["item", "labelConfig", "emitEmptyInDataTypeNumber", "ignoreBlockInputMaxValue", "fieldNameBind", "showCount", "typeComponentSelectItem", "valueComponentSelectItem", "disableComponentSelectItem", "tagInput", "dataType", "typeInput", "modeInput", "resetAutoCompletePassword", "textAreaEnterNotNewLine", "fixedFloat", "acceptNegativeValue", "valueUpDownNumber", "ignoreWidthInput100", "classIncludeInput", "classContainerInput", "readonly", "disable", "noBorder", "backgroundNone", "useColorModeExist", "placeholder", "keepPlaceholderOnly", "classContainerBottomInput", "autoRemoveEmoji", "defaultHeight", "maxHeightTextArea", "minHeightTextArea", "ignoreShowError", "borderError", "iconLeftClass", "popoverContentIconLeft", "iconRightClass", "popoverContentIconRight", "zIndexPopoverContent", "unitsLeft", "configUnitLeft", "keySelectedUnitLeft", "unitsRight", "configUnitRight", "keySelectedUnitRight", "maxValueNumber", "minValueNumber", "ignoreContentLeft", "ignoreContentRight", "isBaselineStyle", "valuePatternShowError", "validPattern", "validRequired", "validMinLength", "validMinValue", "validMaxValue", "validMaxLength", "functionValid", "maxLength", "positionMessageErrorStartInput", "classInclude", "resize", "templateLeftBottomInput", "templateRightBottomInput", "onlyAcceptNegativeValue", "autoAddZeroLessThan10InTypeInt", "maxLengthNumberCount", "classMessageErrorInclude", "ignoreStopPropagationEvent", "ignoreUnitRightClassReadOnly", "paddingRightCustomSpecific", "focusTimeOut", "debounceTimeValidate"], outputs: ["itemChange", "outValueChange", "outSelect", "outIconLeft", "outIconRight", "outClickButtonLabel", "outSwitchEventLabel", "outLabelRightClick", "outEnterInputEvent", "outHeightAreaChange", "outFunctionsControl", "outFocusAndBlur", "outChangeValueByButtonUpDown"] }] });
194
197
  }
195
198
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsImageEditorResizeComponent, decorators: [{
196
199
  type: Component,
197
- args: [{ selector: 'libs-ui-components-image_editor-resize', standalone: true, imports: [
198
- TranslateModule, LibsUiComponentsModalComponent, LibsUiComponentsInputsValidComponent
199
- ], template: "<libs_ui-components-modal [headerConfig]=\"{ignoreHeaderTheme: true}\"\n [mode]=\"'center'\"\n [width]=\"'500px'\"\n [height]=\"'auto'\"\n [title]=\"'i18n_resize' | translate\"\n [zIndex]=\"zIndex\"\n [buttonsFooter]=\"buttonsFooter\"\n (outEvent)=\"handlerEvent($event)\">\n <div class=\"libs-ui-modal-body-custom w-full h-full\">\n <div class=\"flex items-center\">\n <div class=\"libs-ui-font-h7r mr-[4px] text-[#6a7383] w-[100px] shrink-0\">\n {{ 'i18n_ratio_size' | translate }} (%)\n </div>\n <libs_ui-components-inputs-valid [ignoreWidthInput100]=\"true\"\n [classIncludeInput]=\"'w-[132px]'\"\n [dataType]=\"'int'\"\n [fieldNameBind]=\"'ratio'\"\n [(item)]=\"resizeData\"\n [minValueNumber]=\"1\"\n [maxValueNumber]=\"100\"\n [valueUpDownNumber]=\"1\"\n [validRequired]=\"{isRequired: true}\"\n [ignoreShowError]=\"true\"\n (outValueChange)=\"handlerResizeRatio()\"\n (outFunctionsControl)=\"handlerInputValidFunctionControl($event)\" />\n </div>\n <div class=\"mt-[16px] relative\">\n <div class=\"flex items-center\">\n <div class=\"libs-ui-font-h7r mr-[4px] text-[#6a7383] w-[100px] shrink-0\">\n {{ 'i18n_width' | translate }}\n </div>\n <libs_ui-components-inputs-valid [ignoreWidthInput100]=\"true\"\n [classIncludeInput]=\"'w-[102px]'\"\n [dataType]=\"'int'\"\n [maxValueNumber]=\"originWidth\"\n [minValueNumber]=\"1\"\n [fieldNameBind]=\"'width'\"\n [(item)]=\"resizeData\"\n [unitsRight]=\"[{id: 'px', label: 'px'}]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n (outValueChange)=\"handlerResizeWidth()\"\n (outFunctionsControl)=\"handlerInputValidFunctionControl($event)\" />\n </div>\n <div class=\"flex items-center mt-[8px]\">\n <div class=\"libs-ui-font-h7r mr-[4px] text-[#6a7383] w-[100px] shrink-0\">\n {{ 'i18n_length' | translate }}\n </div>\n <libs_ui-components-inputs-valid [ignoreWidthInput100]=\"true\"\n [classIncludeInput]=\"'w-[102px]'\"\n [dataType]=\"'int'\"\n [minValueNumber]=\"1\"\n [maxValueNumber]=\"originHeight\"\n [fieldNameBind]=\"'height'\"\n [(item)]=\"resizeData\"\n [unitsRight]=\"[{id: 'px', label: 'px'}]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n (outValueChange)=\"handlerResizeHeight()\"\n (outFunctionsControl)=\"handlerInputValidFunctionControl($event)\" />\n </div>\n <div class=\"absolute flex items-center left-[236px] top-[14px]\">\n <div\n class=\"w-[20px] h-[44px] libs-ui-border-top-general libs-ui-border-right-general libs-ui-border-bottom-general\">\n </div>\n <div class=\"ml-[6px] text-[#9ca2ad] libs-ui-icon-lock\"></div>\n </div>\n </div>\n <div class=\"mt-[16px]\">\n <div class=\"libs-ui-font-h6m text-[#6a7383] mb-[8px]\">{{ 'i18n_size_photo' | translate }}</div>\n <div class=\"libs-ui-font-h5r rounded-[4px] py-[8px] px-[16px] bg-[#f8f9fa] text-[#9ca2ad]\">\n {{ 'i18n_file_size_compare_when_resize' | translate:{current_size: currentFileSize, original_size: originFileSize} }}\n </div>\n </div>\n </div>\n</libs_ui-components-modal>\n" }]
200
+ args: [{ selector: 'libs-ui-components-image_editor-resize', standalone: true, imports: [TranslateModule, LibsUiComponentsModalComponent, LibsUiComponentsInputsValidComponent], template: "<libs_ui-components-modal\n [headerConfig]=\"{ ignoreHeaderTheme: true }\"\n [mode]=\"'center'\"\n [width]=\"'500px'\"\n [height]=\"'auto'\"\n [title]=\"'i18n_resize' | translate\"\n [zIndex]=\"zIndex\"\n [buttonsFooter]=\"buttonsFooter\"\n (outEvent)=\"handlerEvent($event)\">\n <div class=\"libs-ui-modal-body-custom w-full h-full\">\n <div class=\"flex items-center\">\n <div class=\"libs-ui-font-h7r mr-[4px] text-[#6a7383] w-[100px] shrink-0\">{{ 'i18n_ratio_size' | translate }} (%)</div>\n <libs_ui-components-inputs-valid\n [ignoreWidthInput100]=\"true\"\n [classIncludeInput]=\"'w-[132px]'\"\n [dataType]=\"'int'\"\n [fieldNameBind]=\"'ratio'\"\n [(item)]=\"resizeData\"\n [minValueNumber]=\"1\"\n [maxValueNumber]=\"100\"\n [valueUpDownNumber]=\"1\"\n [validRequired]=\"{ isRequired: true }\"\n [ignoreShowError]=\"true\"\n (outValueChange)=\"handlerResizeRatio()\"\n (outFunctionsControl)=\"handlerInputValidFunctionControl($event)\" />\n </div>\n <div class=\"mt-[16px] relative\">\n <div class=\"flex items-center\">\n <div class=\"libs-ui-font-h7r mr-[4px] text-[#6a7383] w-[100px] shrink-0\">\n {{ 'i18n_width' | translate }}\n </div>\n <libs_ui-components-inputs-valid\n [ignoreWidthInput100]=\"true\"\n [classIncludeInput]=\"'w-[102px]'\"\n [dataType]=\"'int'\"\n [maxValueNumber]=\"originWidth\"\n [minValueNumber]=\"1\"\n [fieldNameBind]=\"'width'\"\n [(item)]=\"resizeData\"\n [unitsRight]=\"[{ id: 'px', label: 'px' }]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n (outValueChange)=\"handlerResizeWidth()\"\n (outFunctionsControl)=\"handlerInputValidFunctionControl($event)\" />\n </div>\n <div class=\"flex items-center mt-[8px]\">\n <div class=\"libs-ui-font-h7r mr-[4px] text-[#6a7383] w-[100px] shrink-0\">\n {{ 'i18n_length' | translate }}\n </div>\n <libs_ui-components-inputs-valid\n [ignoreWidthInput100]=\"true\"\n [classIncludeInput]=\"'w-[102px]'\"\n [dataType]=\"'int'\"\n [minValueNumber]=\"1\"\n [maxValueNumber]=\"originHeight\"\n [fieldNameBind]=\"'height'\"\n [(item)]=\"resizeData\"\n [unitsRight]=\"[{ id: 'px', label: 'px' }]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n (outValueChange)=\"handlerResizeHeight()\"\n (outFunctionsControl)=\"handlerInputValidFunctionControl($event)\" />\n </div>\n <div class=\"absolute flex items-center left-[236px] top-[14px]\">\n <div class=\"w-[20px] h-[44px] libs-ui-border-top-general libs-ui-border-right-general libs-ui-border-bottom-general\"></div>\n <div class=\"ml-[6px] text-[#9ca2ad] libs-ui-icon-lock\"></div>\n </div>\n </div>\n <div class=\"mt-[16px]\">\n <div class=\"libs-ui-font-h6m text-[#6a7383] mb-[8px]\">{{ 'i18n_size_photo' | translate }}</div>\n <div class=\"libs-ui-font-h5r rounded-[4px] py-[8px] px-[16px] bg-[#f8f9fa] text-[#9ca2ad]\">\n {{ 'i18n_file_size_compare_when_resize' | translate: { current_size: currentFileSize, original_size: originFileSize } }}\n </div>\n </div>\n </div>\n</libs_ui-components-modal>\n" }]
200
201
  }], ctorParameters: () => [], propDecorators: { resizeData: [{
201
202
  type: Input,
202
203
  args: [{ required: true }]
@@ -281,7 +282,7 @@ class LibsUiComponentsImageEditorComponent {
281
282
  this.linkImageError = linkImageError;
282
283
  }
283
284
  ngAfterViewInit() {
284
- const aspectRatioFound = this.aspectRatio()?.key ? this.cropRatioItems().find(item => item.key === this.aspectRatio()?.key) : this.cropRatioItems()[0];
285
+ const aspectRatioFound = this.aspectRatio()?.key ? this.cropRatioItems().find((item) => item.key === this.aspectRatio()?.key) : this.cropRatioItems()[0];
285
286
  if (aspectRatioFound) {
286
287
  this.dragGridCrop.set(true);
287
288
  this.cropRatioItemSelected.set(aspectRatioFound?.key);
@@ -291,10 +292,13 @@ class LibsUiComponentsImageEditorComponent {
291
292
  this.updateModalSize();
292
293
  this.initData();
293
294
  this.initMouseEvent();
294
- this.outFunctionsControl.emit({
295
+ this.outFunctionsControl.emit(this.FunctionsControl);
296
+ }
297
+ get FunctionsControl() {
298
+ return {
295
299
  cropImage: this.cropImage.bind(this),
296
- setLoadingState: (loading) => this.loading.set(loading)
297
- });
300
+ setLoadingState: (loading) => this.loading.set(loading),
301
+ };
298
302
  }
299
303
  handlerImageLoaded() {
300
304
  setTimeout(() => {
@@ -335,14 +339,30 @@ class LibsUiComponentsImageEditorComponent {
335
339
  this.initEvent(this.imageEditorContainer(), 'wheel', { callStopPropagation: true }, undefined, (e) => this.handlerMousewheel(e)).subscribe();
336
340
  this.initEvent({ nativeElement: window }, 'resize', {}, undefined, () => this.updateModalSize()).subscribe();
337
341
  this.initEvent(this.imageContainer(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => this.handlerImageContainerMousedown(e)).subscribe((e) => this.handlerMousemove(e));
338
- this.initEvent(this.cropTL(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => { this.handlerCropResize(e, 'TL'); }).subscribe((e) => this.handlerMousemove(e));
339
- this.initEvent(this.cropBL(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => { this.handlerCropResize(e, 'BL'); }).subscribe((e) => this.handlerMousemove(e));
340
- this.initEvent(this.cropBR(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => { this.handlerCropResize(e, 'BR'); }).subscribe((e) => this.handlerMousemove(e));
341
- this.initEvent(this.cropTR(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => { this.handlerCropResize(e, 'TR'); }).subscribe((e) => this.handlerMousemove(e));
342
- this.initEvent(this.cropLineVL(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => { this.handlerCropResize(e, 'VL'); }).subscribe((e) => this.handlerMousemove(e));
343
- this.initEvent(this.cropLineVR(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => { this.handlerCropResize(e, 'VR'); }).subscribe((e) => this.handlerMousemove(e));
344
- this.initEvent(this.cropLineHT(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => { this.handlerCropResize(e, 'HT'); }).subscribe((e) => this.handlerMousemove(e));
345
- this.initEvent(this.cropLineHB(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => { this.handlerCropResize(e, 'HB'); }).subscribe((e) => this.handlerMousemove(e));
342
+ this.initEvent(this.cropTL(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => {
343
+ this.handlerCropResize(e, 'TL');
344
+ }).subscribe((e) => this.handlerMousemove(e));
345
+ this.initEvent(this.cropBL(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => {
346
+ this.handlerCropResize(e, 'BL');
347
+ }).subscribe((e) => this.handlerMousemove(e));
348
+ this.initEvent(this.cropBR(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => {
349
+ this.handlerCropResize(e, 'BR');
350
+ }).subscribe((e) => this.handlerMousemove(e));
351
+ this.initEvent(this.cropTR(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => {
352
+ this.handlerCropResize(e, 'TR');
353
+ }).subscribe((e) => this.handlerMousemove(e));
354
+ this.initEvent(this.cropLineVL(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => {
355
+ this.handlerCropResize(e, 'VL');
356
+ }).subscribe((e) => this.handlerMousemove(e));
357
+ this.initEvent(this.cropLineVR(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => {
358
+ this.handlerCropResize(e, 'VR');
359
+ }).subscribe((e) => this.handlerMousemove(e));
360
+ this.initEvent(this.cropLineHT(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => {
361
+ this.handlerCropResize(e, 'HT');
362
+ }).subscribe((e) => this.handlerMousemove(e));
363
+ this.initEvent(this.cropLineHB(), 'mousedown', { callStopPropagation: true, callPreventDefault: true }, mouseMove, (e) => {
364
+ this.handlerCropResize(e, 'HB');
365
+ }).subscribe((e) => this.handlerMousemove(e));
346
366
  this.initEvent(this.cropArea(), 'mousedown', {}, undefined, (e) => this.handlerMousedownCropArea(e)).subscribe((e) => this.handlerMousemove(e));
347
367
  }
348
368
  initEvent(element, eventName, flag, obsMerge, callback) {
@@ -358,11 +378,10 @@ class LibsUiComponentsImageEditorComponent {
358
378
  }
359
379
  }), takeUntilDestroyed(this.destroyRef));
360
380
  if (obsMerge) {
361
- return obs.pipe(mergeMap(() => obsMerge), (takeUntilDestroyed(this.destroyRef)));
381
+ return obs.pipe(mergeMap(() => obsMerge), takeUntilDestroyed(this.destroyRef));
362
382
  }
363
383
  return obs;
364
384
  }
365
- ;
366
385
  updateOriginImageSize() {
367
386
  let width = this.originWidth();
368
387
  let height = this.originHeight();
@@ -400,7 +419,7 @@ class LibsUiComponentsImageEditorComponent {
400
419
  top: Math.max(0, imgTop),
401
420
  left: Math.max(0, imgLeft),
402
421
  width: imgWidth,
403
- height: imgHeight
422
+ height: imgHeight,
404
423
  };
405
424
  rectImg.width = Math.min(imgWidth, this.containerWidth() - imgLeft);
406
425
  if (imgLeft < 0) {
@@ -426,9 +445,9 @@ class LibsUiComponentsImageEditorComponent {
426
445
  this.setStylesElements(this.cropArea(), { width, height, top, left });
427
446
  }
428
447
  getCropRatioValue() {
429
- const cropRatio = this.cropRatioItems().find(item => item.key === this.cropRatioItemSelected());
448
+ const cropRatio = this.cropRatioItems().find((item) => item.key === this.cropRatioItemSelected());
430
449
  if (!cropRatio?.value) {
431
- return this.aspectRatio()?.value || (this.originWidth() / this.originHeight());
450
+ return this.aspectRatio()?.value || this.originWidth() / this.originHeight();
432
451
  }
433
452
  return cropRatio.value;
434
453
  }
@@ -451,8 +470,8 @@ class LibsUiComponentsImageEditorComponent {
451
470
  const ratio = this.originWidth() / imageRect.width;
452
471
  this.rectClip.set({ left, top, right, bottom, width, height });
453
472
  this.cropSize.set({
454
- height: top >= 0 ? (Math.round((bottom - top) * ratio)) : (Math.floor((bottom - top) * ratio)),
455
- width: top >= 0 ? (Math.round(((right - left) * (this.ratioValue() ?? 1)) * ratio)) : (Math.floor(((right - left) * (this.ratioValue() ?? 1)) * ratio))
473
+ height: top >= 0 ? Math.round((bottom - top) * ratio) : Math.floor((bottom - top) * ratio),
474
+ width: top >= 0 ? Math.round((right - left) * (this.ratioValue() ?? 1) * ratio) : Math.floor((right - left) * (this.ratioValue() ?? 1) * ratio),
456
475
  });
457
476
  return this.rectClip();
458
477
  }
@@ -619,7 +638,7 @@ class LibsUiComponentsImageEditorComponent {
619
638
  imageTop: imageTop,
620
639
  imageLeft: imageLeft,
621
640
  imageWidth: imageWidth,
622
- imageHeight: imageHeight
641
+ imageHeight: imageHeight,
623
642
  });
624
643
  this.ratioValue.set(this.getCropRatioValue());
625
644
  }
@@ -649,7 +668,7 @@ class LibsUiComponentsImageEditorComponent {
649
668
  zoomImage(scale) {
650
669
  const [currWidth, currHeight, currTop, currLeft] = getStylesOfElement(this.imageOrigin().nativeElement, ['offsetWidth', 'offsetHeight', 'style.top', 'style.left']);
651
670
  const width = Math.max(currWidth * scale, 50);
652
- const height = this.imageOrigin().nativeElement.offsetHeight * width / this.imageOrigin().nativeElement.offsetWidth;
671
+ const height = (this.imageOrigin().nativeElement.offsetHeight * width) / this.imageOrigin().nativeElement.offsetWidth;
653
672
  // Calculate the center point of the current view
654
673
  const centerX = currLeft + currWidth / 2;
655
674
  const centerY = currTop + currHeight / 2;
@@ -682,7 +701,7 @@ class LibsUiComponentsImageEditorComponent {
682
701
  cropWidth = cropHeight * this.ratioValue();
683
702
  }
684
703
  // Update clipping rectangle
685
- this.rectClip.update(rect => {
704
+ this.rectClip.update((rect) => {
686
705
  const rectTop = cropTopNew - top;
687
706
  const rectLeft = cropLeftNew - left;
688
707
  return {
@@ -690,7 +709,7 @@ class LibsUiComponentsImageEditorComponent {
690
709
  top: rectTop,
691
710
  left: rectLeft,
692
711
  right: rectLeft + cropWidth,
693
- bottom: rectTop + cropHeight
712
+ bottom: rectTop + cropHeight,
694
713
  };
695
714
  });
696
715
  const clip = `rect(${this.rectClip().top}px, ${this.rectClip().right}px, ${this.rectClip().bottom}px, ${this.rectClip().left}px)`;
@@ -706,7 +725,7 @@ class LibsUiComponentsImageEditorComponent {
706
725
  this.image.src = this.imgSrc();
707
726
  this.image.onload = () => {
708
727
  const canvas = document.createElement('canvas');
709
- const ctx = canvas.getContext("2d");
728
+ const ctx = canvas.getContext('2d');
710
729
  const [width, height] = getStylesOfElement(this.imageOrigin().nativeElement, ['offsetWidth', 'offsetHeight']);
711
730
  const originWidth = this.image.width;
712
731
  const originHeight = this.image.height;
@@ -758,7 +777,7 @@ class LibsUiComponentsImageEditorComponent {
758
777
  this.image.src = this.imgSrc();
759
778
  this.image.onload = () => {
760
779
  const canvas = document.createElement('canvas');
761
- const ctx = canvas.getContext("2d");
780
+ const ctx = canvas.getContext('2d');
762
781
  const width = this.image.width;
763
782
  const height = this.image.height;
764
783
  canvas.height = height;
@@ -812,7 +831,7 @@ class LibsUiComponentsImageEditorComponent {
812
831
  canvas.width = cropRect.width;
813
832
  this.originHeight.set(canvas.height);
814
833
  this.originWidth.set(canvas.width);
815
- const ctx = canvas.getContext("2d");
834
+ const ctx = canvas.getContext('2d');
816
835
  if (ctx) {
817
836
  ctx.drawImage(this.image, cropRect.left, cropRect.top, cropRect.width, cropRect.height, 0, 0, cropRect.width, cropRect.height);
818
837
  }
@@ -854,7 +873,7 @@ class LibsUiComponentsImageEditorComponent {
854
873
  instance.src = this.imgSrc();
855
874
  instance.mimetype = this.mimetype();
856
875
  instance.zIndex = this.zIndex();
857
- subs.add(instance.outSave.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(event => {
876
+ subs.add(instance.outSave.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((event) => {
858
877
  this.resizeData.set(event);
859
878
  this.saveResize();
860
879
  }));
@@ -885,7 +904,7 @@ class LibsUiComponentsImageEditorComponent {
885
904
  const left = currLeft + (currWidth - newWidth) / 2;
886
905
  const movementY = currTop - top;
887
906
  const movementX = currLeft - left;
888
- this.rectClip.update(rect => {
907
+ this.rectClip.update((rect) => {
889
908
  const rectTop = rect.top + movementY;
890
909
  const rectLeft = rect.left + movementX;
891
910
  return {
@@ -893,7 +912,7 @@ class LibsUiComponentsImageEditorComponent {
893
912
  top: rectTop,
894
913
  left: rectLeft,
895
914
  right: rectLeft + newWidth,
896
- bottom: rectTop + newHeight
915
+ bottom: rectTop + newHeight,
897
916
  };
898
917
  });
899
918
  const clip = `rect(${this.rectClip().top}px, ${this.rectClip().right}px, ${this.rectClip().bottom}px, ${this.rectClip().left}px)`;
@@ -930,18 +949,18 @@ class LibsUiComponentsImageEditorComponent {
930
949
  cropHeight = cropValue / this.ratioValue();
931
950
  cropHeight = Math.min(cropHeight, maxCropHeight);
932
951
  cropValue = cropHeight * this.ratioValue();
933
- this.cropSize.update(cropSize => ({ ...cropSize, height: Math.round(cropHeight * ratio) }));
952
+ this.cropSize.update((cropSize) => ({ ...cropSize, height: Math.round(cropHeight * ratio) }));
934
953
  this.cropArea().nativeElement.style.height = `${cropHeight}px`;
935
954
  }
936
955
  if (cropBy === 'height') {
937
956
  cropWidth = cropValue * this.ratioValue();
938
957
  cropWidth = Math.min(cropWidth, maxCropWidth);
939
958
  cropValue = cropWidth / this.ratioValue();
940
- this.cropSize.update(cropSize => ({ ...cropSize, width: Math.round(cropWidth * ratio) }));
959
+ this.cropSize.update((cropSize) => ({ ...cropSize, width: Math.round(cropWidth * ratio) }));
941
960
  this.cropArea().nativeElement.style.width = `${cropWidth}px`;
942
961
  }
943
962
  }
944
- this.cropSize.update(cropSize => ({ ...cropSize, [cropBy]: Math.round(cropValue * ratio) }));
963
+ this.cropSize.update((cropSize) => ({ ...cropSize, [cropBy]: Math.round(cropValue * ratio) }));
945
964
  this.cropArea().nativeElement.style[cropBy] = `${cropValue}px`;
946
965
  const imageRect = this.imageClip().nativeElement.getBoundingClientRect();
947
966
  const cropRect = this.cropArea().nativeElement.getBoundingClientRect();
@@ -953,7 +972,7 @@ class LibsUiComponentsImageEditorComponent {
953
972
  this.imageClip().nativeElement.style.clip = `rect(${top}px, ${right}px, ${bottom}px, ${left}px)`;
954
973
  }
955
974
  setStylesElements(element, styles, isUpdateRectClipPos) {
956
- Object.keys(styles).forEach(key => {
975
+ Object.keys(styles).forEach((key) => {
957
976
  const value = get(styles, key);
958
977
  if (isNil(value)) {
959
978
  return;
@@ -968,14 +987,11 @@ class LibsUiComponentsImageEditorComponent {
968
987
  this.dynamicComponentService.remove(this.resizeComponentRef);
969
988
  }
970
989
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsImageEditorComponent, deps: [{ token: LINK_IMAGE_ERROR_TOKEN_INJECT, optional: true }], target: i0.ɵɵFactoryTarget.Component });
971
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: LibsUiComponentsImageEditorComponent, isStandalone: true, selector: "libs_ui-components-image_editor", inputs: { modeShowButton: { classPropertyName: "modeShowButton", publicName: "modeShowButton", isSignal: true, isRequired: false, transformFunction: null }, mimetype: { classPropertyName: "mimetype", publicName: "mimetype", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, imgSrc: { classPropertyName: "imgSrc", publicName: "imgSrc", isSignal: true, isRequired: true, transformFunction: null }, originUrl: { classPropertyName: "originUrl", publicName: "originUrl", isSignal: true, isRequired: false, transformFunction: null }, nameFile: { classPropertyName: "nameFile", publicName: "nameFile", isSignal: true, isRequired: false, transformFunction: null }, hasZoom: { classPropertyName: "hasZoom", publicName: "hasZoom", isSignal: true, isRequired: false, transformFunction: null }, aspectRatio: { classPropertyName: "aspectRatio", publicName: "aspectRatio", isSignal: true, isRequired: false, transformFunction: null }, requiredCropFollowRatio: { classPropertyName: "requiredCropFollowRatio", publicName: "requiredCropFollowRatio", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { imgSrc: "imgSrcChange", outClose: "outClose", outSaveFile: "outSaveFile", outFunctionsControl: "outFunctionsControl" }, viewQueries: [{ propertyName: "imageOrigin", first: true, predicate: ["imageOrigin"], descendants: true, isSignal: true }, { propertyName: "imageClip", first: true, predicate: ["imageClip"], descendants: true, isSignal: true }, { propertyName: "imageEditorContainer", first: true, predicate: ["imageEditorContainer"], descendants: true, isSignal: true }, { propertyName: "imageContainer", first: true, predicate: ["imageContainer"], descendants: true, isSignal: true }, { propertyName: "cropArea", first: true, predicate: ["cropArea"], descendants: true, isSignal: true }, { propertyName: "cropTL", first: true, predicate: ["cropTL"], descendants: true, isSignal: true }, { propertyName: "cropBL", first: true, predicate: ["cropBL"], descendants: true, isSignal: true }, { propertyName: "cropBR", first: true, predicate: ["cropBR"], descendants: true, isSignal: true }, { propertyName: "cropTR", first: true, predicate: ["cropTR"], descendants: true, isSignal: true }, { propertyName: "cropLineVL", first: true, predicate: ["cropLineVL"], descendants: true, isSignal: true }, { propertyName: "cropLineVR", first: true, predicate: ["cropLineVR"], descendants: true, isSignal: true }, { propertyName: "cropLineHT", first: true, predicate: ["cropLineHT"], descendants: true, isSignal: true }, { propertyName: "cropLineHB", first: true, predicate: ["cropLineHB"], descendants: true, isSignal: true }, { propertyName: "circleTL", first: true, predicate: ["circleTL"], descendants: true, isSignal: true }, { propertyName: "circleTR", first: true, predicate: ["circleTR"], descendants: true, isSignal: true }, { propertyName: "circleBL", first: true, predicate: ["circleBL"], descendants: true, isSignal: true }, { propertyName: "circleBR", first: true, predicate: ["circleBR"], descendants: true, isSignal: true }], ngImport: i0, template: "<libs_ui-components-modal [width]=\"'calc(100vw - 400px)'\"\n [height]=\"'calc(100vh - 100px)'\"\n [minWidth]=\"'1200px'\"\n [headerConfig]=\"{ignoreHeaderTheme: true, removeButtonClose: true}\"\n [bodyConfig]=\"{classInclude: '!p-0', scrollOverlayOptions: {scrollX: 'hidden', scrollY: 'hidden'}}\"\n [footerConfig]=\"{hidden: true}\"\n [zIndex]=\"zIndex()\"\n [buttonsFooter]=\"[]\"\n [mode]=\"'center'\">\n <div class=\"libs-ui-modal-header-custom w-full flex items-center justify-between\">\n <div class=\"w-full relative mx-[24px] h-[16px]\">\n <div class=\"flex w-full libs-ui-font-h4s absolute\">\n <libs_ui-components-popover [type]=\"'text'\"\n [config]=\"{zIndex: zIndex()}\">\n {{ 'i18n_edit_file_name' | translate:{file_name: nameFile()} }}\n </libs_ui-components-popover>\n </div>\n </div>\n <div class=\"flex items-center\">\n @if (modeShowButton() === 'save-file') {\n <libs_ui-components-buttons-button [type]=\"'button-third'\"\n [label]=\"'i18n_cancel'\"\n [disable]=\"loading() || loadingImage()\"\n [classInclude]=\"'py-[6px] px-[12px] mr-[16px]'\"\n (outClick)=\"handlerClose($event)\" />\n\n <libs_ui-components-buttons-button class=\"mr-[24px]\"\n [label]=\"'i18n_save'\"\n [disable]=\"loading() || loadingImage()\"\n [classInclude]=\"'py-[6px] px-[12px]'\"\n (outClick)=\"handlerSaveFile($event,'save-file')\" />\n }\n @else {\n <libs_ui-components-buttons-button [label]=\"'i18n_save_to_new_file'\"\n [type]=\"'button-outline'\"\n [classInclude]=\"'mx-[16px] py-[6px] px-[12px]'\"\n [disable]=\"loading() || loadingImage() || !changed()\"\n (outClick)=\"handlerSaveFile($event,'save-api-as-new-file')\" />\n <libs_ui-components-buttons-button [type]=\"'button-secondary'\"\n [label]=\"'i18n_save'\"\n [classInclude]=\"'py-[6px] px-[12px]'\"\n [disable]=\"loading() || loadingImage() || !changed()\"\n (outClick)=\"handlerSaveFile($event,'save-api')\" />\n <div class=\"h-[12px] libs-ui-border-left-general mx-[16px]\"></div>\n <libs_ui-components-buttons-button class=\"mr-[24px]\"\n [classInclude]=\"'p-[6px]'\"\n [type]=\"'button-third-hover-danger'\"\n [iconOnlyType]=\"true\"\n [disable]=\"loading()\"\n [popover]=\"{config: {content: 'i18n_exit_edit_mode', zIndex: zIndex()}}\"\n [classIconLeft]=\"'libs-ui-icon-close'\"\n (outClick)=\"handlerClose($event)\" />\n }\n </div>\n </div>\n <div class=\"libs-ui-modal-body-custom h-full w-full flex\">\n <div #imageEditorContainer\n class=\"relative w-full h-full bg-[#e6e7ea] border-radius-bottom-left-8px p-[32px] libs-ui-input-image-editor-container-left\">\n @if (loadingImage()) {\n <div class=\"absolute h-full w-full bg-[#e6e7ea] top-0 left-0 z-[5]\">\n <libs_ui-components-spinner [size]=\"'medium'\" />\n </div>\n }\n <div class=\"absolute h-[32px] w-[calc(100%-64px)] bg-[#e6e7eab8] top-0 left-[32px] z-[1]\">\n </div>\n <div class=\"absolute w-[32px] h-full bg-[#e6e7eab8] left-0 top-0 z-[1] rounded-bl-[8px]\">\n </div>\n <div class=\"absolute w-[32px] h-full bg-[#e6e7eab8] right-0 top-0 z-[1]\">\n </div>\n <div class=\"absolute h-[32px] w-[calc(100%-64px)] bg-[#e6e7eab8] bottom-0 left-[32px] z-[1]\">\n </div>\n <div #imageContainer\n class=\"relative w-full h-full rounded-bl-[8px] min-h-0\">\n <div #circleTL\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <div #circleTR\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <div #circleBL\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <div #circleBR\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <img #imageOrigin\n class=\"absolute border-[4px] border-[#8e61ee] rounded-[4px] top-[-1000px] left-[-1000px]\"\n loading=\"lazy\"\n [src]=\"imgSrc()\"\n (load)=\"handlerImageLoaded()\"\n (error)=\"handlerImageError($event)\" />\n <img #imageClip\n class=\"absolute z-[1] top-[-1000px] left-[-1000px]\"\n loading=\"lazy\"\n [src]=\"imgSrc()\"\n (error)=\"handlerImageError($event)\" />\n <div class=\"absolute top-0 left-0 right-0 bottom-0 bg-[#e6e7eab8]\">\n </div>\n <div #cropArea\n class=\"absolute z-[2] border-[4px] border-[#8e61ee] rounded-[4px]\">\n <div class=\"relative w-full h-full\">\n <div #cropTL\n class=\"absolute z-[2] left-[-18px] top-[-17px] cursor-nwse-resize\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div #cropBL\n class=\"absolute z-[2] left-[-17px] bottom-[-18px] cursor-nesw-resize rotate-[270deg]\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div #cropTR\n class=\"absolute z-[2] right-[-17px] top-[-17px] cursor-nesw-resize rotate-[90deg]\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div #cropBR\n class=\"absolute z-[2] right-[-18px] bottom-[-17px] cursor-nwse-resize rotate-[180deg]\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div #cropLineVL\n class=\"absolute z-[1] w-[12px] left-[-6px] top-0 bottom-0 cursor-ew-resize\">\n </div>\n <div #cropLineVR\n class=\"absolute z-[1] w-[12px] right-[-6px] top-0 bottom-0 cursor-ew-resize\">\n </div>\n <div #cropLineHT\n class=\"absolute z-[1] h-[12px] left-0 top-[-6px] right-0 cursor-ns-resize\">\n </div>\n <div #cropLineHB\n class=\"absolute z-[1] h-[12px] left-0 right-0 bottom-[-6px] cursor-ns-resize\">\n </div>\n\n <div class=\"bg-white absolute h-[1px] top-0 left-0 right-0\"></div>\n <div class=\"bg-white absolute h-[1px] bottom-0 left-0 right-0\"></div>\n <div class=\"bg-white absolute w-[1px] top-0 left-0 bottom-0\"></div>\n <div class=\"bg-white absolute w-[1px] top-0 bottom-0 right-0\"></div>\n <div class=\"bg-white absolute h-[2px] top-[33%] left-0 right-0\"></div>\n <div class=\"bg-white absolute h-[2px] top-[66%] left-0 right-0\"></div>\n <div class=\"bg-white absolute w-[2px] top-0 bottom-0 left-[33%]\"></div>\n <div class=\"bg-white absolute w-[2px] top-0 bottom-0 left-[66%]\"></div>\n </div>\n </div>\n </div>\n @if (loading()) {\n <libs_ui-components-spinner [size]=\"'medium'\" />\n }\n </div>\n <div class=\"w-[320px] shrink-0 p-[16px] bg-[#ffffff] rounded-br-[8px] z-[2] libs-ui-input-image-editor-container-right\">\n <div class=\"flex items-center justify-between mb-[16px]\">\n <div class=\"libs-ui-font-h4m\">{{ 'i18n_cutting_ratio' | translate }}</div>\n <libs_ui-components-buttons-button [iconOnlyType]=\"true\"\n [type]=\"'button-third'\"\n [classIconLeft]=\"'libs-ui-icon-refresh'\"\n [classInclude]=\"'p-[6px] mr-[8px]'\"\n [popover]=\"{config: {content: 'i18n_restore_the_original_state', zIndex: zIndex()}}\"\n [disable]=\"loading() || loadingImage() || !changed()\"\n (outClick)=\"handlerRestoreImage($event)\" />\n </div>\n <div class=\"mb-[16px] libs-ui-image-editor-edit-display-grid-gap-16\">\n @for (item of cropRatioItems(); track item.key) {\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage() || requiredCropFollowRatio()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"item.icon+' !text-[20px]'\"\n [isActive]=\"item.key === cropRatioItemSelected()\"\n (outClick)=\"handlerSelectCropRatioItem($event, item.key)\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ (item.key === 'free' ? 'i18n_custom' : item.key) | translate }}\n </div>\n </div>\n }\n </div>\n <div class=\"mb-[16px] flex\">\n <libs_ui-components-inputs-valid class=\"mr-[16px]\"\n [dataType]=\"'int'\"\n [labelConfig]=\"{labelLeft: 'i18n_width', classInclude: 'mb-[4px]', labelLeftClass: 'libs-ui-font-h7r'}\"\n [fieldNameBind]=\"'width'\"\n [(item)]=\"cropSize\"\n [unitsRight]=\"[{id: 'px', label: 'px'}]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n [maxValueNumber]=\"originWidth()\"\n [disable]=\"loading() || loadingImage()\"\n (outValueChange)=\"handlerCropWidth()\" />\n <libs_ui-components-inputs-valid [dataType]=\"'int'\"\n [labelConfig]=\"{labelLeft: 'i18n_length', classInclude: 'mb-[4px]', labelLeftClass: 'libs-ui-font-h7r'}\"\n [fieldNameBind]=\"'height'\"\n [(item)]=\"cropSize\"\n [unitsRight]=\"[{id: 'px', label: 'px'}]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n [maxValueNumber]=\"originHeight()\"\n [disable]=\"loading() || loadingImage()\"\n (outValueChange)=\"handlerCropHeight()\" />\n </div>\n <div class=\"libs-ui-font-h4m mb-[16px]\">{{ 'i18n_rotate_photos' | translate }}</div>\n <div class=\"flex libs-ui-image-editor-edit-display-grid-gap-16\">\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-rotate-image-outline !text-[20px]'\"\n (outClick)=\"handlerRotateImage($event)\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_rotate_ninety_degrees' | translate }}\n </div>\n </div>\n\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-flip-vertical !text-[20px]'\"\n (outClick)=\"handlerFlipImage($event, 'vertical')\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_vertical_flip' | translate }}\n </div>\n </div>\n\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-flip-horizontal !text-[20px]'\"\n (outClick)=\"handlerFlipImage($event, 'horizontal')\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_horizontal_flip' | translate }}\n </div>\n </div>\n\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-scale !text-[20px]'\"\n (outClick)=\"handlerResize($event)\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_resize' | translate }}\n </div>\n </div>\n </div>\n </div>\n </div>\n</libs_ui-components-modal>\n\n<ng-template #svgArrow>\n <svg xmlns=\"http://www.w3.org/2000/svg\"\n width=\"40\"\n height=\"40\"\n viewBox=\"0 0 40 40\"\n fill=\"none\">\n <path d=\"M33.6987 14.6969L18.3309 14.6969C16.516 14.6969 15.0311 16.1818 15.0311 17.9967L15.0311 33.3645\"\n stroke=\"white\"\n stroke-width=\"5.83333\"\n stroke-miterlimit=\"10\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n</ng-template>\n\n<ng-template #svgCircle>\n <svg xmlns=\"http://www.w3.org/2000/svg\"\n width=\"15\"\n height=\"15\"\n viewBox=\"0 0 15 15\"\n fill=\"none\">\n <circle cx=\"7.5\"\n cy=\"7.5\"\n r=\"7.5\"\n fill=\"white\" />\n </svg>\n</ng-template>\n", styles: [".libs-ui-image-editor-edit-display-grid-gap-16{display:grid;gap:16px;grid-template-columns:1fr 1fr 1fr 1fr}.libs-ui-image-editor-edit-top-33{top:33.33%}.libs-ui-image-editor-edit-top-66{top:66.66%}.libs-ui-image-editor-edit-left-33{left:33.33%}.libs-ui-image-editor-edit-left-66{left:66.66%}.libs-ui-image-editor-edit-action-item{display:flex;flex-direction:column;align-items:center;width:60px;cursor:pointer}.libs-ui-image-editor-edit-action-item-icon{padding:12px;border-radius:8px;width:max-content;border:1px solid #e6e7ea}.libs-ui-image-editor-edit-action-item-icon:before{font-size:20px}.libs-ui-image-editor-edit-action-item:hover .libs-ui-image-editor-edit-action-item-icon{border:1px solid var(--mo-global-color-primary-border-hover)}.libs-ui-image-editor-edit-action-item:hover .libs-ui-image-editor-edit-action-item-icon:before{color:var(--mo-global-color-primary-text-bright-20)!important}.libs-ui-image-editor-edit-action-item[active=true] .libs-ui-image-editor-edit-action-item-icon{border:1px solid var(--mo-global-color-primary-border-active)!important;background-color:var(--mo-global-color-primary-background-95)!important}.libs-ui-image-editor-edit-action-item[active=true] .libs-ui-image-editor-edit-action-item-icon:before{color:var(--mo-global-color-primary-text-active)!important}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "component", type: LibsUiComponentsPopoverComponent, selector: "libs_ui-components-popover,[LibsUiComponentsPopoverDirective]", inputs: ["debugId", "flagMouse", "type", "mode", "config", "ignoreShowPopover", "elementRefCustom", "initEventInElementRefCustom", "classInclude", "ignoreHiddenPopoverContentWhenMouseLeave", "ignoreStopPropagationEvent", "ignoreCursorPointerModeLikeClick", "isAddContentToParentDocument", "ignoreClickOutside"], outputs: ["outEvent", "outChangStageFlagMouse", "outEventPopoverContent", "outFunctionsControl"] }, { kind: "component", type: LibsUiComponentsModalComponent, selector: "libs_ui-components-modal", inputs: ["show", "mode", "isBackdropTransparent", "isBackgroundTransparentModal", "isSizeBackdropByWidthHeightInput", "hasShadowBoxWhenHiddenBackDropTransparent", "classIncludeModalWrapper", "zIndex", "width", "height", "maxWidth", "maxHeight", "minWidth", "isFullScreen", "disable", "ignoreCommunicateMicroEvent", "headerConfig", "bodyConfig", "footerConfig", "buttonsFooter", "title", "titleUseXssFilter", "titleUseTooltip", "titleUseInnerText"], outputs: ["showChange", "widthChange", "heightChange", "maxWidthChange", "maxHeightChange", "minWidthChange", "disableChange", "buttonsFooterChange", "outScrollContent", "outEvent", "outFunctionControl"] }, { kind: "component", type: LibsUiComponentsInputsValidComponent, selector: "libs_ui-components-inputs-valid", inputs: ["item", "labelConfig", "emitEmptyInDataTypeNumber", "ignoreBlockInputMaxValue", "fieldNameBind", "showCount", "typeComponentSelectItem", "valueComponentSelectItem", "disableComponentSelectItem", "tagInput", "dataType", "typeInput", "modeInput", "resetAutoCompletePassword", "textAreaEnterNotNewLine", "fixedFloat", "acceptNegativeValue", "valueUpDownNumber", "ignoreWidthInput100", "classIncludeInput", "classContainerInput", "readonly", "disable", "noBorder", "backgroundNone", "useColorModeExist", "placeholder", "keepPlaceholderOnly", "classContainerBottomInput", "autoRemoveEmoji", "defaultHeight", "maxHeightTextArea", "minHeightTextArea", "ignoreShowError", "borderError", "iconLeftClass", "popoverContentIconLeft", "iconRightClass", "popoverContentIconRight", "zIndexPopoverContent", "unitsLeft", "configUnitLeft", "keySelectedUnitLeft", "unitsRight", "configUnitRight", "keySelectedUnitRight", "maxValueNumber", "minValueNumber", "ignoreContentLeft", "ignoreContentRight", "isBaselineStyle", "valuePatternShowError", "validPattern", "validRequired", "validMinLength", "validMinValue", "validMaxValue", "validMaxLength", "functionValid", "maxLength", "positionMessageErrorStartInput", "classInclude", "resize", "templateLeftBottomInput", "templateRightBottomInput", "onlyAcceptNegativeValue", "autoAddZeroLessThan10InTypeInt", "maxLengthNumberCount", "classMessageErrorInclude", "ignoreStopPropagationEvent", "ignoreUnitRightClassReadOnly", "paddingRightCustomSpecific", "focusTimeOut", "debounceTimeValidate"], outputs: ["itemChange", "outValueChange", "outSelect", "outIconLeft", "outIconRight", "outClickButtonLabel", "outSwitchEventLabel", "outLabelRightClick", "outEnterInputEvent", "outHeightAreaChange", "outFunctionsControl", "outFocusAndBlur", "outChangeValueByButtonUpDown"] }, { kind: "component", type: LibsUiComponentsButtonsButtonComponent, selector: "libs_ui-components-buttons-button", inputs: ["flagMouse", "type", "buttonCustom", "sizeButton", "label", "disable", "isPending", "imageLeft", "classInclude", "classIconLeft", "classIconRight", "classLabel", "iconOnlyType", "popover", "ignoreStopPropagationEvent", "zIndex", "widthLabelPopover", "styleIconLeft", "styleButton", "ignoreFocusWhenInputTab", "ignoreSetClickWhenShowPopover", "ignorePointerEvent", "isActive", "isHandlerEnterDocumentClickButton"], outputs: ["outClick", "outPopoverEvent", "outFunctionsControl"] }, { kind: "component", type: LibsUiComponentsSpinnerComponent, selector: "libs_ui-components-spinner", inputs: ["type", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
990
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: LibsUiComponentsImageEditorComponent, isStandalone: true, selector: "libs_ui-components-image_editor", inputs: { modeShowButton: { classPropertyName: "modeShowButton", publicName: "modeShowButton", isSignal: true, isRequired: false, transformFunction: null }, mimetype: { classPropertyName: "mimetype", publicName: "mimetype", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, imgSrc: { classPropertyName: "imgSrc", publicName: "imgSrc", isSignal: true, isRequired: true, transformFunction: null }, originUrl: { classPropertyName: "originUrl", publicName: "originUrl", isSignal: true, isRequired: false, transformFunction: null }, nameFile: { classPropertyName: "nameFile", publicName: "nameFile", isSignal: true, isRequired: false, transformFunction: null }, hasZoom: { classPropertyName: "hasZoom", publicName: "hasZoom", isSignal: true, isRequired: false, transformFunction: null }, aspectRatio: { classPropertyName: "aspectRatio", publicName: "aspectRatio", isSignal: true, isRequired: false, transformFunction: null }, requiredCropFollowRatio: { classPropertyName: "requiredCropFollowRatio", publicName: "requiredCropFollowRatio", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { imgSrc: "imgSrcChange", outClose: "outClose", outSaveFile: "outSaveFile", outFunctionsControl: "outFunctionsControl" }, viewQueries: [{ propertyName: "imageOrigin", first: true, predicate: ["imageOrigin"], descendants: true, isSignal: true }, { propertyName: "imageClip", first: true, predicate: ["imageClip"], descendants: true, isSignal: true }, { propertyName: "imageEditorContainer", first: true, predicate: ["imageEditorContainer"], descendants: true, isSignal: true }, { propertyName: "imageContainer", first: true, predicate: ["imageContainer"], descendants: true, isSignal: true }, { propertyName: "cropArea", first: true, predicate: ["cropArea"], descendants: true, isSignal: true }, { propertyName: "cropTL", first: true, predicate: ["cropTL"], descendants: true, isSignal: true }, { propertyName: "cropBL", first: true, predicate: ["cropBL"], descendants: true, isSignal: true }, { propertyName: "cropBR", first: true, predicate: ["cropBR"], descendants: true, isSignal: true }, { propertyName: "cropTR", first: true, predicate: ["cropTR"], descendants: true, isSignal: true }, { propertyName: "cropLineVL", first: true, predicate: ["cropLineVL"], descendants: true, isSignal: true }, { propertyName: "cropLineVR", first: true, predicate: ["cropLineVR"], descendants: true, isSignal: true }, { propertyName: "cropLineHT", first: true, predicate: ["cropLineHT"], descendants: true, isSignal: true }, { propertyName: "cropLineHB", first: true, predicate: ["cropLineHB"], descendants: true, isSignal: true }, { propertyName: "circleTL", first: true, predicate: ["circleTL"], descendants: true, isSignal: true }, { propertyName: "circleTR", first: true, predicate: ["circleTR"], descendants: true, isSignal: true }, { propertyName: "circleBL", first: true, predicate: ["circleBL"], descendants: true, isSignal: true }, { propertyName: "circleBR", first: true, predicate: ["circleBR"], descendants: true, isSignal: true }], ngImport: i0, template: "<libs_ui-components-modal\n [width]=\"'calc(100vw - 400px)'\"\n [height]=\"'calc(100vh - 100px)'\"\n [minWidth]=\"'1200px'\"\n [headerConfig]=\"{ ignoreHeaderTheme: true, removeButtonClose: true }\"\n [bodyConfig]=\"{ classInclude: '!p-0', scrollOverlayOptions: { scrollX: 'hidden', scrollY: 'hidden' } }\"\n [footerConfig]=\"{ hidden: true }\"\n [zIndex]=\"zIndex()\"\n [buttonsFooter]=\"[]\"\n [mode]=\"'center'\">\n <div class=\"libs-ui-modal-header-custom w-full flex items-center justify-between\">\n <div class=\"w-full relative mx-[24px] h-[16px]\">\n <div class=\"flex w-full libs-ui-font-h4s absolute\">\n <libs_ui-components-popover\n [type]=\"'text'\"\n [config]=\"{ zIndex: zIndex() }\">\n {{ 'i18n_edit_file_name' | translate: { file_name: nameFile() } }}\n </libs_ui-components-popover>\n </div>\n </div>\n <div class=\"flex items-center\">\n @if (modeShowButton() === 'save-file') {\n <libs_ui-components-buttons-button\n [type]=\"'button-third'\"\n [label]=\"'i18n_cancel'\"\n [disable]=\"loading() || loadingImage()\"\n [classInclude]=\"'py-[6px] px-[12px] mr-[16px]'\"\n (outClick)=\"handlerClose($event)\" />\n\n <libs_ui-components-buttons-button\n class=\"mr-[24px]\"\n [label]=\"'i18n_save'\"\n [disable]=\"loading() || loadingImage()\"\n [classInclude]=\"'py-[6px] px-[12px]'\"\n (outClick)=\"handlerSaveFile($event, 'save-file')\" />\n } @else {\n <libs_ui-components-buttons-button\n [label]=\"'i18n_save_to_new_file'\"\n [type]=\"'button-outline'\"\n [classInclude]=\"'mx-[16px] py-[6px] px-[12px]'\"\n [disable]=\"loading() || loadingImage() || !changed()\"\n (outClick)=\"handlerSaveFile($event, 'save-api-as-new-file')\" />\n <libs_ui-components-buttons-button\n [type]=\"'button-secondary'\"\n [label]=\"'i18n_save'\"\n [classInclude]=\"'py-[6px] px-[12px]'\"\n [disable]=\"loading() || loadingImage() || !changed()\"\n (outClick)=\"handlerSaveFile($event, 'save-api')\" />\n <div class=\"h-[12px] libs-ui-border-left-general mx-[16px]\"></div>\n <libs_ui-components-buttons-button\n class=\"mr-[24px]\"\n [classInclude]=\"'p-[6px]'\"\n [type]=\"'button-third-hover-danger'\"\n [iconOnlyType]=\"true\"\n [disable]=\"loading()\"\n [popover]=\"{ config: { content: 'i18n_exit_edit_mode', zIndex: zIndex() } }\"\n [classIconLeft]=\"'libs-ui-icon-close'\"\n (outClick)=\"handlerClose($event)\" />\n }\n </div>\n </div>\n <div class=\"libs-ui-modal-body-custom h-full w-full flex\">\n <div\n #imageEditorContainer\n class=\"relative w-full h-full bg-[#e6e7ea] border-radius-bottom-left-8px p-[32px] libs-ui-input-image-editor-container-left\">\n @if (loadingImage()) {\n <div class=\"absolute h-full w-full bg-[#e6e7ea] top-0 left-0 z-[5]\">\n <libs_ui-components-spinner [size]=\"'medium'\" />\n </div>\n }\n <div class=\"absolute h-[32px] w-[calc(100%-64px)] bg-[#e6e7eab8] top-0 left-[32px] z-[1]\"></div>\n <div class=\"absolute w-[32px] h-full bg-[#e6e7eab8] left-0 top-0 z-[1] rounded-bl-[8px]\"></div>\n <div class=\"absolute w-[32px] h-full bg-[#e6e7eab8] right-0 top-0 z-[1]\"></div>\n <div class=\"absolute h-[32px] w-[calc(100%-64px)] bg-[#e6e7eab8] bottom-0 left-[32px] z-[1]\"></div>\n <div\n #imageContainer\n class=\"relative w-full h-full rounded-bl-[8px] min-h-0\">\n <div\n #circleTL\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <div\n #circleTR\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <div\n #circleBL\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <div\n #circleBR\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <img\n #imageOrigin\n class=\"absolute border-[4px] border-[#8e61ee] rounded-[4px] top-[-1000px] left-[-1000px]\"\n loading=\"lazy\"\n [src]=\"imgSrc()\"\n (load)=\"handlerImageLoaded()\"\n (error)=\"handlerImageError($event)\" />\n <img\n #imageClip\n class=\"absolute z-[1] top-[-1000px] left-[-1000px]\"\n loading=\"lazy\"\n [src]=\"imgSrc()\"\n (error)=\"handlerImageError($event)\" />\n <div class=\"absolute top-0 left-0 right-0 bottom-0 bg-[#e6e7eab8]\"></div>\n <div\n #cropArea\n class=\"absolute z-[2] border-[4px] border-[#8e61ee] rounded-[4px]\">\n <div class=\"relative w-full h-full\">\n <div\n #cropTL\n class=\"absolute z-[2] left-[-18px] top-[-17px] cursor-nwse-resize\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div\n #cropBL\n class=\"absolute z-[2] left-[-17px] bottom-[-18px] cursor-nesw-resize rotate-[270deg]\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div\n #cropTR\n class=\"absolute z-[2] right-[-17px] top-[-17px] cursor-nesw-resize rotate-[90deg]\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div\n #cropBR\n class=\"absolute z-[2] right-[-18px] bottom-[-17px] cursor-nwse-resize rotate-[180deg]\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div\n #cropLineVL\n class=\"absolute z-[1] w-[12px] left-[-6px] top-0 bottom-0 cursor-ew-resize\"></div>\n <div\n #cropLineVR\n class=\"absolute z-[1] w-[12px] right-[-6px] top-0 bottom-0 cursor-ew-resize\"></div>\n <div\n #cropLineHT\n class=\"absolute z-[1] h-[12px] left-0 top-[-6px] right-0 cursor-ns-resize\"></div>\n <div\n #cropLineHB\n class=\"absolute z-[1] h-[12px] left-0 right-0 bottom-[-6px] cursor-ns-resize\"></div>\n\n <div class=\"bg-white absolute h-[1px] top-0 left-0 right-0\"></div>\n <div class=\"bg-white absolute h-[1px] bottom-0 left-0 right-0\"></div>\n <div class=\"bg-white absolute w-[1px] top-0 left-0 bottom-0\"></div>\n <div class=\"bg-white absolute w-[1px] top-0 bottom-0 right-0\"></div>\n <div class=\"bg-white absolute h-[2px] top-[33%] left-0 right-0\"></div>\n <div class=\"bg-white absolute h-[2px] top-[66%] left-0 right-0\"></div>\n <div class=\"bg-white absolute w-[2px] top-0 bottom-0 left-[33%]\"></div>\n <div class=\"bg-white absolute w-[2px] top-0 bottom-0 left-[66%]\"></div>\n </div>\n </div>\n </div>\n @if (loading()) {\n <libs_ui-components-spinner [size]=\"'medium'\" />\n }\n </div>\n <div class=\"w-[320px] shrink-0 p-[16px] bg-[#ffffff] rounded-br-[8px] z-[2] libs-ui-input-image-editor-container-right\">\n <div class=\"flex items-center justify-between mb-[16px]\">\n <div class=\"libs-ui-font-h4m\">{{ 'i18n_cutting_ratio' | translate }}</div>\n <libs_ui-components-buttons-button\n [iconOnlyType]=\"true\"\n [type]=\"'button-third'\"\n [classIconLeft]=\"'libs-ui-icon-refresh'\"\n [classInclude]=\"'p-[6px] mr-[8px]'\"\n [popover]=\"{ config: { content: 'i18n_restore_the_original_state', zIndex: zIndex() } }\"\n [disable]=\"loading() || loadingImage() || !changed()\"\n (outClick)=\"handlerRestoreImage($event)\" />\n </div>\n <div class=\"mb-[16px] libs-ui-image-editor-edit-display-grid-gap-16\">\n @for (item of cropRatioItems(); track item.key) {\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage() || requiredCropFollowRatio()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"item.icon + ' !text-[20px]'\"\n [isActive]=\"item.key === cropRatioItemSelected()\"\n (outClick)=\"handlerSelectCropRatioItem($event, item.key)\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ (item.key === 'free' ? 'i18n_custom' : item.key) | translate }}\n </div>\n </div>\n }\n </div>\n <div class=\"mb-[16px] flex\">\n <libs_ui-components-inputs-valid\n class=\"mr-[16px]\"\n [dataType]=\"'int'\"\n [labelConfig]=\"{ labelLeft: 'i18n_width', classInclude: 'mb-[4px]', labelLeftClass: 'libs-ui-font-h7r' }\"\n [fieldNameBind]=\"'width'\"\n [(item)]=\"cropSize\"\n [unitsRight]=\"[{ id: 'px', label: 'px' }]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n [maxValueNumber]=\"originWidth()\"\n [disable]=\"loading() || loadingImage()\"\n (outValueChange)=\"handlerCropWidth()\" />\n <libs_ui-components-inputs-valid\n [dataType]=\"'int'\"\n [labelConfig]=\"{ labelLeft: 'i18n_length', classInclude: 'mb-[4px]', labelLeftClass: 'libs-ui-font-h7r' }\"\n [fieldNameBind]=\"'height'\"\n [(item)]=\"cropSize\"\n [unitsRight]=\"[{ id: 'px', label: 'px' }]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n [maxValueNumber]=\"originHeight()\"\n [disable]=\"loading() || loadingImage()\"\n (outValueChange)=\"handlerCropHeight()\" />\n </div>\n <div class=\"libs-ui-font-h4m mb-[16px]\">{{ 'i18n_rotate_photos' | translate }}</div>\n <div class=\"flex libs-ui-image-editor-edit-display-grid-gap-16\">\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-rotate-image-outline !text-[20px]'\"\n (outClick)=\"handlerRotateImage($event)\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_rotate_ninety_degrees' | translate }}\n </div>\n </div>\n\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-flip-vertical !text-[20px]'\"\n (outClick)=\"handlerFlipImage($event, 'vertical')\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_vertical_flip' | translate }}\n </div>\n </div>\n\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-flip-horizontal !text-[20px]'\"\n (outClick)=\"handlerFlipImage($event, 'horizontal')\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_horizontal_flip' | translate }}\n </div>\n </div>\n\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-scale !text-[20px]'\"\n (outClick)=\"handlerResize($event)\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_resize' | translate }}\n </div>\n </div>\n </div>\n </div>\n </div>\n</libs_ui-components-modal>\n\n<ng-template #svgArrow>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"40\"\n height=\"40\"\n viewBox=\"0 0 40 40\"\n fill=\"none\">\n <path\n d=\"M33.6987 14.6969L18.3309 14.6969C16.516 14.6969 15.0311 16.1818 15.0311 17.9967L15.0311 33.3645\"\n stroke=\"white\"\n stroke-width=\"5.83333\"\n stroke-miterlimit=\"10\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n</ng-template>\n\n<ng-template #svgCircle>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"15\"\n height=\"15\"\n viewBox=\"0 0 15 15\"\n fill=\"none\">\n <circle\n cx=\"7.5\"\n cy=\"7.5\"\n r=\"7.5\"\n fill=\"white\" />\n </svg>\n</ng-template>\n", styles: [".libs-ui-image-editor-edit-display-grid-gap-16{display:grid;gap:16px;grid-template-columns:1fr 1fr 1fr 1fr}.libs-ui-image-editor-edit-top-33{top:33.33%}.libs-ui-image-editor-edit-top-66{top:66.66%}.libs-ui-image-editor-edit-left-33{left:33.33%}.libs-ui-image-editor-edit-left-66{left:66.66%}.libs-ui-image-editor-edit-action-item{display:flex;flex-direction:column;align-items:center;width:60px;cursor:pointer}.libs-ui-image-editor-edit-action-item-icon{padding:12px;border-radius:8px;width:max-content;border:1px solid #e6e7ea}.libs-ui-image-editor-edit-action-item-icon:before{font-size:20px}.libs-ui-image-editor-edit-action-item:hover .libs-ui-image-editor-edit-action-item-icon{border:1px solid var(--mo-global-color-primary-border-hover)}.libs-ui-image-editor-edit-action-item:hover .libs-ui-image-editor-edit-action-item-icon:before{color:var(--mo-global-color-primary-text-bright-20)!important}.libs-ui-image-editor-edit-action-item[active=true] .libs-ui-image-editor-edit-action-item-icon{border:1px solid var(--mo-global-color-primary-border-active)!important;background-color:var(--mo-global-color-primary-background-95)!important}.libs-ui-image-editor-edit-action-item[active=true] .libs-ui-image-editor-edit-action-item-icon:before{color:var(--mo-global-color-primary-text-active)!important}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "component", type: LibsUiComponentsPopoverComponent, selector: "libs_ui-components-popover,[LibsUiComponentsPopoverDirective]", inputs: ["debugId", "flagMouse", "type", "mode", "config", "ignoreShowPopover", "elementRefCustom", "initEventInElementRefCustom", "classInclude", "ignoreHiddenPopoverContentWhenMouseLeave", "ignoreStopPropagationEvent", "ignoreCursorPointerModeLikeClick", "isAddContentToParentDocument", "ignoreClickOutside"], outputs: ["outEvent", "outChangStageFlagMouse", "outEventPopoverContent", "outFunctionsControl"] }, { kind: "component", type: LibsUiComponentsModalComponent, selector: "libs_ui-components-modal", inputs: ["show", "mode", "isBackdropTransparent", "isBackgroundTransparentModal", "isSizeBackdropByWidthHeightInput", "hasShadowBoxWhenHiddenBackDropTransparent", "classIncludeModalWrapper", "zIndex", "width", "height", "maxWidth", "maxHeight", "minWidth", "isFullScreen", "disable", "ignoreCommunicateMicroEvent", "headerConfig", "bodyConfig", "footerConfig", "buttonsFooter", "title", "titleUseXssFilter", "titleUseTooltip", "titleUseInnerText"], outputs: ["showChange", "widthChange", "heightChange", "maxWidthChange", "maxHeightChange", "minWidthChange", "disableChange", "buttonsFooterChange", "outScrollContent", "outEvent", "outFunctionControl"] }, { kind: "component", type: LibsUiComponentsInputsValidComponent, selector: "libs_ui-components-inputs-valid", inputs: ["item", "labelConfig", "emitEmptyInDataTypeNumber", "ignoreBlockInputMaxValue", "fieldNameBind", "showCount", "typeComponentSelectItem", "valueComponentSelectItem", "disableComponentSelectItem", "tagInput", "dataType", "typeInput", "modeInput", "resetAutoCompletePassword", "textAreaEnterNotNewLine", "fixedFloat", "acceptNegativeValue", "valueUpDownNumber", "ignoreWidthInput100", "classIncludeInput", "classContainerInput", "readonly", "disable", "noBorder", "backgroundNone", "useColorModeExist", "placeholder", "keepPlaceholderOnly", "classContainerBottomInput", "autoRemoveEmoji", "defaultHeight", "maxHeightTextArea", "minHeightTextArea", "ignoreShowError", "borderError", "iconLeftClass", "popoverContentIconLeft", "iconRightClass", "popoverContentIconRight", "zIndexPopoverContent", "unitsLeft", "configUnitLeft", "keySelectedUnitLeft", "unitsRight", "configUnitRight", "keySelectedUnitRight", "maxValueNumber", "minValueNumber", "ignoreContentLeft", "ignoreContentRight", "isBaselineStyle", "valuePatternShowError", "validPattern", "validRequired", "validMinLength", "validMinValue", "validMaxValue", "validMaxLength", "functionValid", "maxLength", "positionMessageErrorStartInput", "classInclude", "resize", "templateLeftBottomInput", "templateRightBottomInput", "onlyAcceptNegativeValue", "autoAddZeroLessThan10InTypeInt", "maxLengthNumberCount", "classMessageErrorInclude", "ignoreStopPropagationEvent", "ignoreUnitRightClassReadOnly", "paddingRightCustomSpecific", "focusTimeOut", "debounceTimeValidate"], outputs: ["itemChange", "outValueChange", "outSelect", "outIconLeft", "outIconRight", "outClickButtonLabel", "outSwitchEventLabel", "outLabelRightClick", "outEnterInputEvent", "outHeightAreaChange", "outFunctionsControl", "outFocusAndBlur", "outChangeValueByButtonUpDown"] }, { kind: "component", type: LibsUiComponentsButtonsButtonComponent, selector: "libs_ui-components-buttons-button", inputs: ["flagMouse", "type", "buttonCustom", "sizeButton", "label", "disable", "isPending", "imageLeft", "classInclude", "classIconLeft", "classIconRight", "classLabel", "iconOnlyType", "popover", "ignoreStopPropagationEvent", "zIndex", "widthLabelPopover", "styleIconLeft", "styleButton", "ignoreFocusWhenInputTab", "ignoreSetClickWhenShowPopover", "ignorePointerEvent", "isActive", "isHandlerEnterDocumentClickButton"], outputs: ["outClick", "outPopoverEvent", "outFunctionsControl"] }, { kind: "component", type: LibsUiComponentsSpinnerComponent, selector: "libs_ui-components-spinner", inputs: ["type", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
972
991
  }
973
992
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsImageEditorComponent, decorators: [{
974
993
  type: Component,
975
- args: [{ selector: 'libs_ui-components-image_editor', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
976
- NgTemplateOutlet, TranslateModule, LibsUiComponentsPopoverComponent, LibsUiComponentsModalComponent,
977
- LibsUiComponentsInputsValidComponent, LibsUiComponentsButtonsButtonComponent, LibsUiComponentsSpinnerComponent,
978
- ], template: "<libs_ui-components-modal [width]=\"'calc(100vw - 400px)'\"\n [height]=\"'calc(100vh - 100px)'\"\n [minWidth]=\"'1200px'\"\n [headerConfig]=\"{ignoreHeaderTheme: true, removeButtonClose: true}\"\n [bodyConfig]=\"{classInclude: '!p-0', scrollOverlayOptions: {scrollX: 'hidden', scrollY: 'hidden'}}\"\n [footerConfig]=\"{hidden: true}\"\n [zIndex]=\"zIndex()\"\n [buttonsFooter]=\"[]\"\n [mode]=\"'center'\">\n <div class=\"libs-ui-modal-header-custom w-full flex items-center justify-between\">\n <div class=\"w-full relative mx-[24px] h-[16px]\">\n <div class=\"flex w-full libs-ui-font-h4s absolute\">\n <libs_ui-components-popover [type]=\"'text'\"\n [config]=\"{zIndex: zIndex()}\">\n {{ 'i18n_edit_file_name' | translate:{file_name: nameFile()} }}\n </libs_ui-components-popover>\n </div>\n </div>\n <div class=\"flex items-center\">\n @if (modeShowButton() === 'save-file') {\n <libs_ui-components-buttons-button [type]=\"'button-third'\"\n [label]=\"'i18n_cancel'\"\n [disable]=\"loading() || loadingImage()\"\n [classInclude]=\"'py-[6px] px-[12px] mr-[16px]'\"\n (outClick)=\"handlerClose($event)\" />\n\n <libs_ui-components-buttons-button class=\"mr-[24px]\"\n [label]=\"'i18n_save'\"\n [disable]=\"loading() || loadingImage()\"\n [classInclude]=\"'py-[6px] px-[12px]'\"\n (outClick)=\"handlerSaveFile($event,'save-file')\" />\n }\n @else {\n <libs_ui-components-buttons-button [label]=\"'i18n_save_to_new_file'\"\n [type]=\"'button-outline'\"\n [classInclude]=\"'mx-[16px] py-[6px] px-[12px]'\"\n [disable]=\"loading() || loadingImage() || !changed()\"\n (outClick)=\"handlerSaveFile($event,'save-api-as-new-file')\" />\n <libs_ui-components-buttons-button [type]=\"'button-secondary'\"\n [label]=\"'i18n_save'\"\n [classInclude]=\"'py-[6px] px-[12px]'\"\n [disable]=\"loading() || loadingImage() || !changed()\"\n (outClick)=\"handlerSaveFile($event,'save-api')\" />\n <div class=\"h-[12px] libs-ui-border-left-general mx-[16px]\"></div>\n <libs_ui-components-buttons-button class=\"mr-[24px]\"\n [classInclude]=\"'p-[6px]'\"\n [type]=\"'button-third-hover-danger'\"\n [iconOnlyType]=\"true\"\n [disable]=\"loading()\"\n [popover]=\"{config: {content: 'i18n_exit_edit_mode', zIndex: zIndex()}}\"\n [classIconLeft]=\"'libs-ui-icon-close'\"\n (outClick)=\"handlerClose($event)\" />\n }\n </div>\n </div>\n <div class=\"libs-ui-modal-body-custom h-full w-full flex\">\n <div #imageEditorContainer\n class=\"relative w-full h-full bg-[#e6e7ea] border-radius-bottom-left-8px p-[32px] libs-ui-input-image-editor-container-left\">\n @if (loadingImage()) {\n <div class=\"absolute h-full w-full bg-[#e6e7ea] top-0 left-0 z-[5]\">\n <libs_ui-components-spinner [size]=\"'medium'\" />\n </div>\n }\n <div class=\"absolute h-[32px] w-[calc(100%-64px)] bg-[#e6e7eab8] top-0 left-[32px] z-[1]\">\n </div>\n <div class=\"absolute w-[32px] h-full bg-[#e6e7eab8] left-0 top-0 z-[1] rounded-bl-[8px]\">\n </div>\n <div class=\"absolute w-[32px] h-full bg-[#e6e7eab8] right-0 top-0 z-[1]\">\n </div>\n <div class=\"absolute h-[32px] w-[calc(100%-64px)] bg-[#e6e7eab8] bottom-0 left-[32px] z-[1]\">\n </div>\n <div #imageContainer\n class=\"relative w-full h-full rounded-bl-[8px] min-h-0\">\n <div #circleTL\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <div #circleTR\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <div #circleBL\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <div #circleBR\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <img #imageOrigin\n class=\"absolute border-[4px] border-[#8e61ee] rounded-[4px] top-[-1000px] left-[-1000px]\"\n loading=\"lazy\"\n [src]=\"imgSrc()\"\n (load)=\"handlerImageLoaded()\"\n (error)=\"handlerImageError($event)\" />\n <img #imageClip\n class=\"absolute z-[1] top-[-1000px] left-[-1000px]\"\n loading=\"lazy\"\n [src]=\"imgSrc()\"\n (error)=\"handlerImageError($event)\" />\n <div class=\"absolute top-0 left-0 right-0 bottom-0 bg-[#e6e7eab8]\">\n </div>\n <div #cropArea\n class=\"absolute z-[2] border-[4px] border-[#8e61ee] rounded-[4px]\">\n <div class=\"relative w-full h-full\">\n <div #cropTL\n class=\"absolute z-[2] left-[-18px] top-[-17px] cursor-nwse-resize\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div #cropBL\n class=\"absolute z-[2] left-[-17px] bottom-[-18px] cursor-nesw-resize rotate-[270deg]\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div #cropTR\n class=\"absolute z-[2] right-[-17px] top-[-17px] cursor-nesw-resize rotate-[90deg]\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div #cropBR\n class=\"absolute z-[2] right-[-18px] bottom-[-17px] cursor-nwse-resize rotate-[180deg]\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div #cropLineVL\n class=\"absolute z-[1] w-[12px] left-[-6px] top-0 bottom-0 cursor-ew-resize\">\n </div>\n <div #cropLineVR\n class=\"absolute z-[1] w-[12px] right-[-6px] top-0 bottom-0 cursor-ew-resize\">\n </div>\n <div #cropLineHT\n class=\"absolute z-[1] h-[12px] left-0 top-[-6px] right-0 cursor-ns-resize\">\n </div>\n <div #cropLineHB\n class=\"absolute z-[1] h-[12px] left-0 right-0 bottom-[-6px] cursor-ns-resize\">\n </div>\n\n <div class=\"bg-white absolute h-[1px] top-0 left-0 right-0\"></div>\n <div class=\"bg-white absolute h-[1px] bottom-0 left-0 right-0\"></div>\n <div class=\"bg-white absolute w-[1px] top-0 left-0 bottom-0\"></div>\n <div class=\"bg-white absolute w-[1px] top-0 bottom-0 right-0\"></div>\n <div class=\"bg-white absolute h-[2px] top-[33%] left-0 right-0\"></div>\n <div class=\"bg-white absolute h-[2px] top-[66%] left-0 right-0\"></div>\n <div class=\"bg-white absolute w-[2px] top-0 bottom-0 left-[33%]\"></div>\n <div class=\"bg-white absolute w-[2px] top-0 bottom-0 left-[66%]\"></div>\n </div>\n </div>\n </div>\n @if (loading()) {\n <libs_ui-components-spinner [size]=\"'medium'\" />\n }\n </div>\n <div class=\"w-[320px] shrink-0 p-[16px] bg-[#ffffff] rounded-br-[8px] z-[2] libs-ui-input-image-editor-container-right\">\n <div class=\"flex items-center justify-between mb-[16px]\">\n <div class=\"libs-ui-font-h4m\">{{ 'i18n_cutting_ratio' | translate }}</div>\n <libs_ui-components-buttons-button [iconOnlyType]=\"true\"\n [type]=\"'button-third'\"\n [classIconLeft]=\"'libs-ui-icon-refresh'\"\n [classInclude]=\"'p-[6px] mr-[8px]'\"\n [popover]=\"{config: {content: 'i18n_restore_the_original_state', zIndex: zIndex()}}\"\n [disable]=\"loading() || loadingImage() || !changed()\"\n (outClick)=\"handlerRestoreImage($event)\" />\n </div>\n <div class=\"mb-[16px] libs-ui-image-editor-edit-display-grid-gap-16\">\n @for (item of cropRatioItems(); track item.key) {\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage() || requiredCropFollowRatio()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"item.icon+' !text-[20px]'\"\n [isActive]=\"item.key === cropRatioItemSelected()\"\n (outClick)=\"handlerSelectCropRatioItem($event, item.key)\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ (item.key === 'free' ? 'i18n_custom' : item.key) | translate }}\n </div>\n </div>\n }\n </div>\n <div class=\"mb-[16px] flex\">\n <libs_ui-components-inputs-valid class=\"mr-[16px]\"\n [dataType]=\"'int'\"\n [labelConfig]=\"{labelLeft: 'i18n_width', classInclude: 'mb-[4px]', labelLeftClass: 'libs-ui-font-h7r'}\"\n [fieldNameBind]=\"'width'\"\n [(item)]=\"cropSize\"\n [unitsRight]=\"[{id: 'px', label: 'px'}]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n [maxValueNumber]=\"originWidth()\"\n [disable]=\"loading() || loadingImage()\"\n (outValueChange)=\"handlerCropWidth()\" />\n <libs_ui-components-inputs-valid [dataType]=\"'int'\"\n [labelConfig]=\"{labelLeft: 'i18n_length', classInclude: 'mb-[4px]', labelLeftClass: 'libs-ui-font-h7r'}\"\n [fieldNameBind]=\"'height'\"\n [(item)]=\"cropSize\"\n [unitsRight]=\"[{id: 'px', label: 'px'}]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n [maxValueNumber]=\"originHeight()\"\n [disable]=\"loading() || loadingImage()\"\n (outValueChange)=\"handlerCropHeight()\" />\n </div>\n <div class=\"libs-ui-font-h4m mb-[16px]\">{{ 'i18n_rotate_photos' | translate }}</div>\n <div class=\"flex libs-ui-image-editor-edit-display-grid-gap-16\">\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-rotate-image-outline !text-[20px]'\"\n (outClick)=\"handlerRotateImage($event)\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_rotate_ninety_degrees' | translate }}\n </div>\n </div>\n\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-flip-vertical !text-[20px]'\"\n (outClick)=\"handlerFlipImage($event, 'vertical')\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_vertical_flip' | translate }}\n </div>\n </div>\n\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-flip-horizontal !text-[20px]'\"\n (outClick)=\"handlerFlipImage($event, 'horizontal')\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_horizontal_flip' | translate }}\n </div>\n </div>\n\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-scale !text-[20px]'\"\n (outClick)=\"handlerResize($event)\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_resize' | translate }}\n </div>\n </div>\n </div>\n </div>\n </div>\n</libs_ui-components-modal>\n\n<ng-template #svgArrow>\n <svg xmlns=\"http://www.w3.org/2000/svg\"\n width=\"40\"\n height=\"40\"\n viewBox=\"0 0 40 40\"\n fill=\"none\">\n <path d=\"M33.6987 14.6969L18.3309 14.6969C16.516 14.6969 15.0311 16.1818 15.0311 17.9967L15.0311 33.3645\"\n stroke=\"white\"\n stroke-width=\"5.83333\"\n stroke-miterlimit=\"10\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n</ng-template>\n\n<ng-template #svgCircle>\n <svg xmlns=\"http://www.w3.org/2000/svg\"\n width=\"15\"\n height=\"15\"\n viewBox=\"0 0 15 15\"\n fill=\"none\">\n <circle cx=\"7.5\"\n cy=\"7.5\"\n r=\"7.5\"\n fill=\"white\" />\n </svg>\n</ng-template>\n", styles: [".libs-ui-image-editor-edit-display-grid-gap-16{display:grid;gap:16px;grid-template-columns:1fr 1fr 1fr 1fr}.libs-ui-image-editor-edit-top-33{top:33.33%}.libs-ui-image-editor-edit-top-66{top:66.66%}.libs-ui-image-editor-edit-left-33{left:33.33%}.libs-ui-image-editor-edit-left-66{left:66.66%}.libs-ui-image-editor-edit-action-item{display:flex;flex-direction:column;align-items:center;width:60px;cursor:pointer}.libs-ui-image-editor-edit-action-item-icon{padding:12px;border-radius:8px;width:max-content;border:1px solid #e6e7ea}.libs-ui-image-editor-edit-action-item-icon:before{font-size:20px}.libs-ui-image-editor-edit-action-item:hover .libs-ui-image-editor-edit-action-item-icon{border:1px solid var(--mo-global-color-primary-border-hover)}.libs-ui-image-editor-edit-action-item:hover .libs-ui-image-editor-edit-action-item-icon:before{color:var(--mo-global-color-primary-text-bright-20)!important}.libs-ui-image-editor-edit-action-item[active=true] .libs-ui-image-editor-edit-action-item-icon{border:1px solid var(--mo-global-color-primary-border-active)!important;background-color:var(--mo-global-color-primary-background-95)!important}.libs-ui-image-editor-edit-action-item[active=true] .libs-ui-image-editor-edit-action-item-icon:before{color:var(--mo-global-color-primary-text-active)!important}\n"] }]
994
+ args: [{ selector: 'libs_ui-components-image_editor', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [NgTemplateOutlet, TranslateModule, LibsUiComponentsPopoverComponent, LibsUiComponentsModalComponent, LibsUiComponentsInputsValidComponent, LibsUiComponentsButtonsButtonComponent, LibsUiComponentsSpinnerComponent], template: "<libs_ui-components-modal\n [width]=\"'calc(100vw - 400px)'\"\n [height]=\"'calc(100vh - 100px)'\"\n [minWidth]=\"'1200px'\"\n [headerConfig]=\"{ ignoreHeaderTheme: true, removeButtonClose: true }\"\n [bodyConfig]=\"{ classInclude: '!p-0', scrollOverlayOptions: { scrollX: 'hidden', scrollY: 'hidden' } }\"\n [footerConfig]=\"{ hidden: true }\"\n [zIndex]=\"zIndex()\"\n [buttonsFooter]=\"[]\"\n [mode]=\"'center'\">\n <div class=\"libs-ui-modal-header-custom w-full flex items-center justify-between\">\n <div class=\"w-full relative mx-[24px] h-[16px]\">\n <div class=\"flex w-full libs-ui-font-h4s absolute\">\n <libs_ui-components-popover\n [type]=\"'text'\"\n [config]=\"{ zIndex: zIndex() }\">\n {{ 'i18n_edit_file_name' | translate: { file_name: nameFile() } }}\n </libs_ui-components-popover>\n </div>\n </div>\n <div class=\"flex items-center\">\n @if (modeShowButton() === 'save-file') {\n <libs_ui-components-buttons-button\n [type]=\"'button-third'\"\n [label]=\"'i18n_cancel'\"\n [disable]=\"loading() || loadingImage()\"\n [classInclude]=\"'py-[6px] px-[12px] mr-[16px]'\"\n (outClick)=\"handlerClose($event)\" />\n\n <libs_ui-components-buttons-button\n class=\"mr-[24px]\"\n [label]=\"'i18n_save'\"\n [disable]=\"loading() || loadingImage()\"\n [classInclude]=\"'py-[6px] px-[12px]'\"\n (outClick)=\"handlerSaveFile($event, 'save-file')\" />\n } @else {\n <libs_ui-components-buttons-button\n [label]=\"'i18n_save_to_new_file'\"\n [type]=\"'button-outline'\"\n [classInclude]=\"'mx-[16px] py-[6px] px-[12px]'\"\n [disable]=\"loading() || loadingImage() || !changed()\"\n (outClick)=\"handlerSaveFile($event, 'save-api-as-new-file')\" />\n <libs_ui-components-buttons-button\n [type]=\"'button-secondary'\"\n [label]=\"'i18n_save'\"\n [classInclude]=\"'py-[6px] px-[12px]'\"\n [disable]=\"loading() || loadingImage() || !changed()\"\n (outClick)=\"handlerSaveFile($event, 'save-api')\" />\n <div class=\"h-[12px] libs-ui-border-left-general mx-[16px]\"></div>\n <libs_ui-components-buttons-button\n class=\"mr-[24px]\"\n [classInclude]=\"'p-[6px]'\"\n [type]=\"'button-third-hover-danger'\"\n [iconOnlyType]=\"true\"\n [disable]=\"loading()\"\n [popover]=\"{ config: { content: 'i18n_exit_edit_mode', zIndex: zIndex() } }\"\n [classIconLeft]=\"'libs-ui-icon-close'\"\n (outClick)=\"handlerClose($event)\" />\n }\n </div>\n </div>\n <div class=\"libs-ui-modal-body-custom h-full w-full flex\">\n <div\n #imageEditorContainer\n class=\"relative w-full h-full bg-[#e6e7ea] border-radius-bottom-left-8px p-[32px] libs-ui-input-image-editor-container-left\">\n @if (loadingImage()) {\n <div class=\"absolute h-full w-full bg-[#e6e7ea] top-0 left-0 z-[5]\">\n <libs_ui-components-spinner [size]=\"'medium'\" />\n </div>\n }\n <div class=\"absolute h-[32px] w-[calc(100%-64px)] bg-[#e6e7eab8] top-0 left-[32px] z-[1]\"></div>\n <div class=\"absolute w-[32px] h-full bg-[#e6e7eab8] left-0 top-0 z-[1] rounded-bl-[8px]\"></div>\n <div class=\"absolute w-[32px] h-full bg-[#e6e7eab8] right-0 top-0 z-[1]\"></div>\n <div class=\"absolute h-[32px] w-[calc(100%-64px)] bg-[#e6e7eab8] bottom-0 left-[32px] z-[1]\"></div>\n <div\n #imageContainer\n class=\"relative w-full h-full rounded-bl-[8px] min-h-0\">\n <div\n #circleTL\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <div\n #circleTR\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <div\n #circleBL\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <div\n #circleBR\n class=\"absolute z-[1]\"\n [class.hidden]=\"!dragGridCrop()\"\n [class.flex]=\"dragGridCrop()\">\n <ng-template *ngTemplateOutlet=\"svgCircle\" />\n </div>\n <img\n #imageOrigin\n class=\"absolute border-[4px] border-[#8e61ee] rounded-[4px] top-[-1000px] left-[-1000px]\"\n loading=\"lazy\"\n [src]=\"imgSrc()\"\n (load)=\"handlerImageLoaded()\"\n (error)=\"handlerImageError($event)\" />\n <img\n #imageClip\n class=\"absolute z-[1] top-[-1000px] left-[-1000px]\"\n loading=\"lazy\"\n [src]=\"imgSrc()\"\n (error)=\"handlerImageError($event)\" />\n <div class=\"absolute top-0 left-0 right-0 bottom-0 bg-[#e6e7eab8]\"></div>\n <div\n #cropArea\n class=\"absolute z-[2] border-[4px] border-[#8e61ee] rounded-[4px]\">\n <div class=\"relative w-full h-full\">\n <div\n #cropTL\n class=\"absolute z-[2] left-[-18px] top-[-17px] cursor-nwse-resize\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div\n #cropBL\n class=\"absolute z-[2] left-[-17px] bottom-[-18px] cursor-nesw-resize rotate-[270deg]\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div\n #cropTR\n class=\"absolute z-[2] right-[-17px] top-[-17px] cursor-nesw-resize rotate-[90deg]\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div\n #cropBR\n class=\"absolute z-[2] right-[-18px] bottom-[-17px] cursor-nwse-resize rotate-[180deg]\">\n <ng-template *ngTemplateOutlet=\"svgArrow\" />\n </div>\n <div\n #cropLineVL\n class=\"absolute z-[1] w-[12px] left-[-6px] top-0 bottom-0 cursor-ew-resize\"></div>\n <div\n #cropLineVR\n class=\"absolute z-[1] w-[12px] right-[-6px] top-0 bottom-0 cursor-ew-resize\"></div>\n <div\n #cropLineHT\n class=\"absolute z-[1] h-[12px] left-0 top-[-6px] right-0 cursor-ns-resize\"></div>\n <div\n #cropLineHB\n class=\"absolute z-[1] h-[12px] left-0 right-0 bottom-[-6px] cursor-ns-resize\"></div>\n\n <div class=\"bg-white absolute h-[1px] top-0 left-0 right-0\"></div>\n <div class=\"bg-white absolute h-[1px] bottom-0 left-0 right-0\"></div>\n <div class=\"bg-white absolute w-[1px] top-0 left-0 bottom-0\"></div>\n <div class=\"bg-white absolute w-[1px] top-0 bottom-0 right-0\"></div>\n <div class=\"bg-white absolute h-[2px] top-[33%] left-0 right-0\"></div>\n <div class=\"bg-white absolute h-[2px] top-[66%] left-0 right-0\"></div>\n <div class=\"bg-white absolute w-[2px] top-0 bottom-0 left-[33%]\"></div>\n <div class=\"bg-white absolute w-[2px] top-0 bottom-0 left-[66%]\"></div>\n </div>\n </div>\n </div>\n @if (loading()) {\n <libs_ui-components-spinner [size]=\"'medium'\" />\n }\n </div>\n <div class=\"w-[320px] shrink-0 p-[16px] bg-[#ffffff] rounded-br-[8px] z-[2] libs-ui-input-image-editor-container-right\">\n <div class=\"flex items-center justify-between mb-[16px]\">\n <div class=\"libs-ui-font-h4m\">{{ 'i18n_cutting_ratio' | translate }}</div>\n <libs_ui-components-buttons-button\n [iconOnlyType]=\"true\"\n [type]=\"'button-third'\"\n [classIconLeft]=\"'libs-ui-icon-refresh'\"\n [classInclude]=\"'p-[6px] mr-[8px]'\"\n [popover]=\"{ config: { content: 'i18n_restore_the_original_state', zIndex: zIndex() } }\"\n [disable]=\"loading() || loadingImage() || !changed()\"\n (outClick)=\"handlerRestoreImage($event)\" />\n </div>\n <div class=\"mb-[16px] libs-ui-image-editor-edit-display-grid-gap-16\">\n @for (item of cropRatioItems(); track item.key) {\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage() || requiredCropFollowRatio()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"item.icon + ' !text-[20px]'\"\n [isActive]=\"item.key === cropRatioItemSelected()\"\n (outClick)=\"handlerSelectCropRatioItem($event, item.key)\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ (item.key === 'free' ? 'i18n_custom' : item.key) | translate }}\n </div>\n </div>\n }\n </div>\n <div class=\"mb-[16px] flex\">\n <libs_ui-components-inputs-valid\n class=\"mr-[16px]\"\n [dataType]=\"'int'\"\n [labelConfig]=\"{ labelLeft: 'i18n_width', classInclude: 'mb-[4px]', labelLeftClass: 'libs-ui-font-h7r' }\"\n [fieldNameBind]=\"'width'\"\n [(item)]=\"cropSize\"\n [unitsRight]=\"[{ id: 'px', label: 'px' }]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n [maxValueNumber]=\"originWidth()\"\n [disable]=\"loading() || loadingImage()\"\n (outValueChange)=\"handlerCropWidth()\" />\n <libs_ui-components-inputs-valid\n [dataType]=\"'int'\"\n [labelConfig]=\"{ labelLeft: 'i18n_length', classInclude: 'mb-[4px]', labelLeftClass: 'libs-ui-font-h7r' }\"\n [fieldNameBind]=\"'height'\"\n [(item)]=\"cropSize\"\n [unitsRight]=\"[{ id: 'px', label: 'px' }]\"\n [keySelectedUnitRight]=\"'px'\"\n [valueUpDownNumber]=\"1\"\n [maxValueNumber]=\"originHeight()\"\n [disable]=\"loading() || loadingImage()\"\n (outValueChange)=\"handlerCropHeight()\" />\n </div>\n <div class=\"libs-ui-font-h4m mb-[16px]\">{{ 'i18n_rotate_photos' | translate }}</div>\n <div class=\"flex libs-ui-image-editor-edit-display-grid-gap-16\">\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-rotate-image-outline !text-[20px]'\"\n (outClick)=\"handlerRotateImage($event)\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_rotate_ninety_degrees' | translate }}\n </div>\n </div>\n\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-flip-vertical !text-[20px]'\"\n (outClick)=\"handlerFlipImage($event, 'vertical')\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_vertical_flip' | translate }}\n </div>\n </div>\n\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-flip-horizontal !text-[20px]'\"\n (outClick)=\"handlerFlipImage($event, 'horizontal')\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_horizontal_flip' | translate }}\n </div>\n </div>\n\n <div class=\"flex flex-col items-center\">\n <libs_ui-components-buttons-button\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'large'\"\n [disable]=\"loading() || loadingImage()\"\n [type]=\"'button-outline'\"\n [classIconLeft]=\"'libs-ui-icon-scale !text-[20px]'\"\n (outClick)=\"handlerResize($event)\" />\n <div class=\"libs-ui-font-h6r text-[#6a7383] mt-[4px]\">\n {{ 'i18n_resize' | translate }}\n </div>\n </div>\n </div>\n </div>\n </div>\n</libs_ui-components-modal>\n\n<ng-template #svgArrow>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"40\"\n height=\"40\"\n viewBox=\"0 0 40 40\"\n fill=\"none\">\n <path\n d=\"M33.6987 14.6969L18.3309 14.6969C16.516 14.6969 15.0311 16.1818 15.0311 17.9967L15.0311 33.3645\"\n stroke=\"white\"\n stroke-width=\"5.83333\"\n stroke-miterlimit=\"10\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n</ng-template>\n\n<ng-template #svgCircle>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"15\"\n height=\"15\"\n viewBox=\"0 0 15 15\"\n fill=\"none\">\n <circle\n cx=\"7.5\"\n cy=\"7.5\"\n r=\"7.5\"\n fill=\"white\" />\n </svg>\n</ng-template>\n", styles: [".libs-ui-image-editor-edit-display-grid-gap-16{display:grid;gap:16px;grid-template-columns:1fr 1fr 1fr 1fr}.libs-ui-image-editor-edit-top-33{top:33.33%}.libs-ui-image-editor-edit-top-66{top:66.66%}.libs-ui-image-editor-edit-left-33{left:33.33%}.libs-ui-image-editor-edit-left-66{left:66.66%}.libs-ui-image-editor-edit-action-item{display:flex;flex-direction:column;align-items:center;width:60px;cursor:pointer}.libs-ui-image-editor-edit-action-item-icon{padding:12px;border-radius:8px;width:max-content;border:1px solid #e6e7ea}.libs-ui-image-editor-edit-action-item-icon:before{font-size:20px}.libs-ui-image-editor-edit-action-item:hover .libs-ui-image-editor-edit-action-item-icon{border:1px solid var(--mo-global-color-primary-border-hover)}.libs-ui-image-editor-edit-action-item:hover .libs-ui-image-editor-edit-action-item-icon:before{color:var(--mo-global-color-primary-text-bright-20)!important}.libs-ui-image-editor-edit-action-item[active=true] .libs-ui-image-editor-edit-action-item-icon{border:1px solid var(--mo-global-color-primary-border-active)!important;background-color:var(--mo-global-color-primary-background-95)!important}.libs-ui-image-editor-edit-action-item[active=true] .libs-ui-image-editor-edit-action-item-icon:before{color:var(--mo-global-color-primary-text-active)!important}\n"] }]
979
995
  }], ctorParameters: () => [{ type: undefined, decorators: [{
980
996
  type: Optional
981
997
  }, {
@@ -995,88 +1011,91 @@ class LibsUiComponentsImageEditorDemoComponent {
995
1011
  { name: 'imgSrc', type: 'string', default: 'Bắt buộc', description: 'Đường dẫn hoặc base64 của hình ảnh cần chỉnh sửa' },
996
1012
  { name: 'originUrl', type: 'string', default: '-', description: 'URL gốc của hình ảnh' },
997
1013
  { name: 'nameFile', type: 'string', default: '-', description: 'Tên file khi lưu' },
998
- { name: 'modeShowButton', type: '\'save-file\' | \'save-api\'', default: '\'save-file\'', description: 'Chế độ nút lưu' },
1014
+ { name: 'modeShowButton', type: "'save-file' | 'save-api'", default: "'save-file'", description: 'Chế độ nút lưu' },
999
1015
  { name: 'mimetype', type: 'string', default: '-', description: 'Định dạng của hình ảnh' },
1000
1016
  { name: 'zIndex', type: 'number', default: '1200', description: 'z-index của component' },
1001
1017
  { name: 'hasZoom', type: 'boolean', default: 'false', description: 'Cho phép phóng to/thu nhỏ hình ảnh' },
1002
1018
  { name: 'aspectRatio', type: 'IAspectRatio', default: '-', description: 'Tỷ lệ khung hình mặc định' },
1003
- { name: 'requiredCropFollowRatio', type: 'boolean', default: 'false', description: 'Bắt buộc cắt theo tỷ lệ đã chọn' }
1019
+ { name: 'requiredCropFollowRatio', type: 'boolean', default: 'false', description: 'Bắt buộc cắt theo tỷ lệ đã chọn' },
1004
1020
  ];
1005
1021
  outputsDoc = [
1006
1022
  { name: 'outClose', type: '{isClickButtonClose: boolean}', description: 'Sự kiện khi đóng trình chỉnh sửa' },
1007
1023
  { name: 'outSaveFile', type: 'ISaveFile', description: 'Sự kiện khi lưu file' },
1008
- { name: 'outFunctionsControl', type: 'IImageEditorFunctionControlEvent', description: 'Sự kiện để kiểm soát các chức năng' }
1024
+ { name: 'outFunctionsControl', type: 'IImageEditorFunctionControlEvent', description: 'Sự kiện để kiểm soát các chức năng' },
1009
1025
  ];
1010
1026
  interfacesDoc = [
1011
1027
  {
1012
1028
  name: 'ISaveFile',
1013
- code: 'export interface ISaveFile {\n file: Blob;\n url: string;\n mode: \'save-file\' | \'save-api\' | \'save-api-as-new-file\';\n}',
1014
- description: 'Interface định nghĩa dữ liệu khi lưu file.'
1029
+ code: "export interface ISaveFile {\n file: Blob;\n url: string;\n mode: 'save-file' | 'save-api' | 'save-api-as-new-file';\n}",
1030
+ description: 'Interface định nghĩa dữ liệu khi lưu file.',
1015
1031
  },
1016
1032
  {
1017
1033
  name: 'IImageEditorFunctionControlEvent',
1018
1034
  code: 'export interface IImageEditorFunctionControlEvent {\n cropImage: () => Promise<string>;\n setLoadingState: (loading: boolean) => void;\n}',
1019
- description: 'Interface định nghĩa các hàm điều khiển có thể được gọi từ bên ngoài component.'
1035
+ description: 'Interface định nghĩa các hàm điều khiển có thể được gọi từ bên ngoài component.',
1020
1036
  },
1021
1037
  {
1022
1038
  name: 'IAspectRatio',
1023
1039
  code: 'export interface IAspectRatio {\n key: string;\n value: number;\n}',
1024
- description: 'Interface định nghĩa tỷ lệ khung hình.'
1025
- }
1040
+ description: 'Interface định nghĩa tỷ lệ khung hình.',
1041
+ },
1026
1042
  ];
1027
1043
  features = [
1028
1044
  {
1029
1045
  id: 1,
1030
1046
  icon: '✂️',
1031
1047
  title: 'Cắt ảnh',
1032
- description: 'Cắt hình ảnh theo khu vực tùy chỉnh hoặc dựa trên tỷ lệ định trước (1:1, 4:3, 16:9, v.v.).'
1048
+ description: 'Cắt hình ảnh theo khu vực tùy chỉnh hoặc dựa trên tỷ lệ định trước (1:1, 4:3, 16:9, v.v.).',
1033
1049
  },
1034
1050
  {
1035
1051
  id: 2,
1036
1052
  icon: '🔄',
1037
1053
  title: 'Xoay và lật',
1038
- description: 'Xoay hình ảnh theo các góc khác nhau hoặc lật theo chiều ngang/dọc.'
1054
+ description: 'Xoay hình ảnh theo các góc khác nhau hoặc lật theo chiều ngang/dọc.',
1039
1055
  },
1040
1056
  {
1041
1057
  id: 3,
1042
1058
  icon: '📏',
1043
1059
  title: 'Thay đổi kích thước',
1044
- description: 'Thay đổi kích thước hình ảnh theo tỷ lệ phần trăm hoặc kích thước cụ thể.'
1060
+ description: 'Thay đổi kích thước hình ảnh theo tỷ lệ phần trăm hoặc kích thước cụ thể.',
1045
1061
  },
1046
1062
  {
1047
1063
  id: 4,
1048
1064
  icon: '💾',
1049
1065
  title: 'Nhiều chế độ lưu',
1050
- description: 'Hỗ trợ nhiều chế độ lưu: tải xuống trực tiếp hoặc gửi đến API.'
1066
+ description: 'Hỗ trợ nhiều chế độ lưu: tải xuống trực tiếp hoặc gửi đến API.',
1051
1067
  },
1052
1068
  {
1053
1069
  id: 5,
1054
1070
  icon: '🔍',
1055
1071
  title: 'Phóng to/thu nhỏ',
1056
- description: 'Tính năng phóng to/thu nhỏ để xem chi tiết hình ảnh khi cần thiết.'
1057
- }
1072
+ description: 'Tính năng phóng to/thu nhỏ để xem chi tiết hình ảnh khi cần thiết.',
1073
+ },
1058
1074
  ];
1059
1075
  codeExamples = [
1060
1076
  {
1061
1077
  id: 1,
1062
1078
  title: 'Sử dụng cơ bản',
1063
- code: `import { Component } from '@angular/core';\nimport { LibsUiComponentsImageEditorComponent } from '@libs-ui/components-image-editor';\n\n@Component({\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n template: \`\n <libs_ui-components-image_editor\n [(imgSrc)]="imageSource"\n [modeShowButton]="'save-file'"\n [nameFile]="'image.jpg'"\n (outSaveFile)="onSaveFile($event)"\n (outClose)="onClose($event)">\n </libs_ui-components-image_editor>\n \`\n})\nexport class ExampleComponent {\n imageSource = 'https://example.com/path/to/image.jpg';\n\n onSaveFile(data: {file: Blob, url: string, mode: string}) {\n console.log('File đã được lưu:', data);\n }\n\n onClose(data: {isClickButtonClose: boolean}) {\n console.log('Đã đóng trình chỉnh sửa ảnh');\n }\n}`
1079
+ code: `import { Component } from '@angular/core';\nimport { LibsUiComponentsImageEditorComponent } from '@libs-ui/components-image-editor';\n\n@Component({\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n template: \`\n <libs_ui-components-image_editor\n [(imgSrc)]="imageSource"\n [modeShowButton]="'save-file'"\n [nameFile]="'image.jpg'"\n (outSaveFile)="onSaveFile($event)"\n (outClose)="onClose($event)">\n </libs_ui-components-image_editor>\n \`\n})\nexport class ExampleComponent {\n imageSource = 'https://example.com/path/to/image.jpg';\n\n onSaveFile(data: {file: Blob, url: string, mode: string}) {\n console.log('File đã được lưu:', data);\n }\n\n onClose(data: {isClickButtonClose: boolean}) {\n console.log('Đã đóng trình chỉnh sửa ảnh');\n }\n}`,
1064
1080
  },
1065
1081
  {
1066
1082
  id: 2,
1067
1083
  title: 'Sử dụng với tỷ lệ cố định',
1068
- code: `import { Component } from '@angular/core';\nimport { LibsUiComponentsImageEditorComponent } from '@libs-ui/components-image-editor';\nimport { IAspectRatio } from '@libs-ui/interfaces-types';\n\n@Component({\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n template: \`\n <libs_ui-components-image_editor\n [(imgSrc)]="imageSource"\n [aspectRatio]="aspectRatio"\n [requiredCropFollowRatio]="true"\n (outSaveFile)="onSaveFile($event)">\n </libs_ui-components-image_editor>\n \`\n})\nexport class ExampleComponent {\n imageSource = 'https://example.com/path/to/image.jpg';\n aspectRatio: IAspectRatio = {\n key: '1:1',\n value: 1\n };\n\n onSaveFile(data: any) {\n console.log('Đã lưu hình ảnh với tỷ lệ 1:1');\n }\n}`
1084
+ code: `import { Component } from '@angular/core';\nimport { LibsUiComponentsImageEditorComponent } from '@libs-ui/components-image-editor';\nimport { IAspectRatio } from '@libs-ui/interfaces-types';\n\n@Component({\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n template: \`\n <libs_ui-components-image_editor\n [(imgSrc)]="imageSource"\n [aspectRatio]="aspectRatio"\n [requiredCropFollowRatio]="true"\n (outSaveFile)="onSaveFile($event)">\n </libs_ui-components-image_editor>\n \`\n})\nexport class ExampleComponent {\n imageSource = 'https://example.com/path/to/image.jpg';\n aspectRatio: IAspectRatio = {\n key: '1:1',\n value: 1\n };\n\n onSaveFile(data: any) {\n console.log('Đã lưu hình ảnh với tỷ lệ 1:1');\n }\n}`,
1069
1085
  },
1070
1086
  {
1071
1087
  id: 3,
1072
1088
  title: 'Sử dụng với phần điều khiển bên ngoài',
1073
- code: `import { Component, ViewChild } from '@angular/core';\nimport { LibsUiComponentsImageEditorComponent, IImageEditorFunctionControlEvent } from '@libs-ui/components-image-editor';\n\n@Component({\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n template: \`\n <button (click)="cropAndSave()">Cắt và lưu ngay</button>\n <libs_ui-components-image_editor\n [(imgSrc)]="imageSource"\n (outFunctionsControl)="onFunctionsControl($event)">\n </libs_ui-components-image_editor>\n \`\n})\nexport class ExampleComponent {\n imageSource = 'https://example.com/path/to/image.jpg';\n editorFunctions!: IImageEditorFunctionControlEvent;\n\n onFunctionsControl(event: IImageEditorFunctionControlEvent) {\n this.editorFunctions = event;\n }\n\n async cropAndSave() {\n if (this.editorFunctions) {\n this.editorFunctions.setLoadingState(true);\n try {\n const dataUrl = await this.editorFunctions.cropImage();\n console.log('Hình ảnh đã được cắt:', dataUrl);\n } finally {\n this.editorFunctions.setLoadingState(false);\n }\n }\n }\n}`
1074
- }
1089
+ code: `import { Component, ViewChild } from '@angular/core';\nimport { LibsUiComponentsImageEditorComponent, IImageEditorFunctionControlEvent } from '@libs-ui/components-image-editor';\n\n@Component({\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n template: \`\n <button (click)="cropAndSave()">Cắt và lưu ngay</button>\n <libs_ui-components-image_editor\n [(imgSrc)]="imageSource"\n (outFunctionsControl)="onFunctionsControl($event)">\n </libs_ui-components-image_editor>\n \`\n})\nexport class ExampleComponent {\n imageSource = 'https://example.com/path/to/image.jpg';\n editorFunctions!: IImageEditorFunctionControlEvent;\n\n onFunctionsControl(event: IImageEditorFunctionControlEvent) {\n this.editorFunctions = event;\n }\n\n async cropAndSave() {\n if (this.editorFunctions) {\n this.editorFunctions.setLoadingState(true);\n try {\n const dataUrl = await this.editorFunctions.cropImage();\n console.log('Hình ảnh đã được cắt:', dataUrl);\n } finally {\n this.editorFunctions.setLoadingState(false);\n }\n }\n }\n}`,
1090
+ },
1075
1091
  ];
1076
1092
  copyToClipboard(text) {
1077
- navigator.clipboard.writeText(text).then(() => {
1093
+ navigator.clipboard
1094
+ .writeText(text)
1095
+ .then(() => {
1078
1096
  alert('Đã sao chép vào clipboard');
1079
- }).catch(err => {
1097
+ })
1098
+ .catch((err) => {
1080
1099
  console.error('Không thể sao chép: ', err);
1081
1100
  });
1082
1101
  }
@@ -1119,15 +1138,15 @@ class LibsUiComponentsImageEditorDemoComponent {
1119
1138
  link.click();
1120
1139
  }
1121
1140
  }
1141
+ handleFunctionControl(event) {
1142
+ console.log(event);
1143
+ }
1122
1144
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsImageEditorDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1123
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: LibsUiComponentsImageEditorDemoComponent, isStandalone: true, selector: "lib-image-editor-demo", viewQueries: [{ propertyName: "imageFileInput", first: true, predicate: ["imageFileInput"], descendants: true }], ngImport: i0, template: "<div class=\"max-w-6xl mx-auto p-5 font-sans text-gray-800\">\n <header class=\"text-center py-10 bg-white rounded-lg mb-8 shadow-sm\">\n <h1 class=\"text-4xl font-bold text-gray-800 mb-2\">Demo Tr\u00ECnh Ch\u1EC9nh S\u1EEDa H\u00ECnh \u1EA2nh</h1>\n <p class=\"text-xl text-gray-500\">Th\u01B0 vi\u1EC7n component cho Angular \u0111\u1EC3 ch\u1EC9nh s\u1EEDa h\u00ECnh \u1EA3nh</p>\n </header>\n\n <main>\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Gi\u1EDBi thi\u1EC7u</h2>\n <p>\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">&#64;libs-ui/components-image-editor</code> l\u00E0 m\u1ED9t\n component Angular m\u1EA1nh m\u1EBD cho ph\u00E9p ng\u01B0\u1EDDi d\u00F9ng th\u1EF1c hi\u1EC7n c\u00E1c thao t\u00E1c ch\u1EC9nh s\u1EEDa h\u00ECnh \u1EA3nh nh\u01B0 c\u1EAFt, thay \u0111\u1ED5i k\u00EDch\n th\u01B0\u1EDBc, xoay, l\u1EADt v\u00E0 \u00E1p d\u1EE5ng t\u1EF7 l\u1EC7 c\u1ED1 \u0111\u1ECBnh.\n </p>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E0i \u0111\u1EB7t</h2>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Y\u00EAu c\u1EA7u</h3>\n <ul class=\"list-disc pl-5 space-y-2 text-gray-600\">\n <li><span class=\"font-semibold\">Angular</span>: 18.0.0 tr\u1EDF l\u00EAn</li>\n <li><span class=\"font-semibold\">Tailwind CSS</span>: 3.3.0 tr\u1EDF l\u00EAn</li>\n </ul>\n </div>\n\n <p class=\"mb-4\">\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>npm install &#64;libs-ui/components-image-editor</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('npm install @libs-ui/components-image-editor')\">\n Sao ch\u00E9p\n </button>\n </div>\n\n <p class=\"mb-4\">Ho\u1EB7c v\u1EDBi yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>yarn add &#64;libs-ui/components-image-editor</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('yarn add @libs-ui/components-image-editor')\">\n Sao ch\u00E9p\n </button>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Demo tr\u1EF1c ti\u1EBFp</h2>\n <div>\n <p class=\"mb-4\">T\u1EA3i l\u00EAn h\u00ECnh \u1EA3nh v\u00E0 ch\u1EC9nh s\u1EEDa ngay tr\u00EAn tr\u00ECnh duy\u1EC7t:</p>\n <div class=\"flex flex-wrap items-center gap-4 mb-8\">\n <input type=\"file\"\n #imageFileInput\n accept=\"image/*\"\n class=\"border border-gray-300 rounded px-3 py-2\"\n (change)=\"onFileSelected($event)\" />\n <libs_ui-components-buttons-button label=\"T\u1EA3i l\u00EAn v\u00E0 ch\u1EC9nh s\u1EEDa\"\n (click)=\"uploadAndEdit()\">\n </libs_ui-components-buttons-button>\n </div>\n\n @if (editedImageUrl) {\n <div class=\"mt-8 p-6 bg-gray-50 rounded-lg\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">K\u1EBFt qu\u1EA3</h3>\n <div class=\"max-w-xl mx-auto mb-4 border border-gray-200 rounded-lg overflow-hidden shadow-md\">\n <img [src]=\"editedImageUrl\"\n alt=\"H\u00ECnh \u1EA3nh \u0111\u00E3 ch\u1EC9nh s\u1EEDa\"\n class=\"w-full h-auto\" />\n </div>\n <div class=\"flex justify-center\">\n <libs_ui-components-buttons-button label=\"T\u1EA3i xu\u1ED1ng h\u00ECnh \u1EA3nh\"\n (click)=\"downloadImage()\">\n </libs_ui-components-buttons-button>\n </div>\n </div>\n }\n </div>\n </section>\n\n @if (showEditor) {\n <div class=\"fixed inset-0 z-50\">\n <libs_ui-components-image_editor [(imgSrc)]=\"imageSource\"\n [nameFile]=\"imageName || 'demo-image.jpg'\"\n [modeShowButton]=\"'save-file'\"\n [hasZoom]=\"true\"\n (outSaveFile)=\"onSaveImage($event)\"\n (outClose)=\"onCloseEditor($event)\" />\n </div>\n }\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E1ch s\u1EED d\u1EE5ng</h2>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 1: S\u1EED d\u1EE5ng file HTML ri\u00EAng bi\u1EC7t</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (example.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>&lt;libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [nameFile]=\"'image.jpg'\"\n [modeShowButton]=\"'save-file'\"\n (outSaveFile)=\"onSaveFile($event)\"\n (outClose)=\"onClose($event)\"&gt;\n&lt;/libs_ui-components-image_editor&gt;</code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (example.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import &#123; Component &#125; from '&#64;angular/core';\nimport &#123; LibsUiComponentsImageEditorComponent &#125; from '&#64;libs-ui/components-image-editor';\n\n&#64;Component(&#123;\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n templateUrl: './example.component.html'\n&#125;)\nexport class ExampleComponent &#123;\n imageSource = 'https://example.com/path/to/image.jpg';\n\n onSaveFile(data: &#123;file: Blob, url: string, mode: string&#125;) &#123;\n console.log('File \u0111\u00E3 \u0111\u01B0\u1EE3c l\u01B0u:', data);\n &#125;\n\n onClose(data: &#123;isClickButtonClose: boolean&#125;) &#123;\n console.log('\u0110\u00E3 \u0111\u00F3ng tr\u00ECnh ch\u1EC9nh s\u1EEDa \u1EA3nh');\n &#125;\n&#125;</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 2: V\u1EDBi tr\u00ECnh ch\u1EC9nh s\u1EEDa c\u00F3 th\u1EC3 \u0111\u00F3ng/m\u1EDF</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (toggle-editor.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>&lt;button (click)=\"openEditor()\" class=\"px-4 py-2 bg-blue-500 text-white rounded\"&gt;\n M\u1EDF tr\u00ECnh ch\u1EC9nh s\u1EEDa \u1EA3nh\n&lt;/button&gt;\n\n&#64;if (showEditor) &#123;\n &lt;libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [nameFile]=\"'my-image.jpg'\"\n (outSaveFile)=\"onSaveFile($event)\"\n (outClose)=\"onCloseEditor($event)\"&gt;\n &lt;/libs_ui-components-image_editor&gt;\n&#125;\n\n&#64;if (editedImageUrl) &#123;\n &lt;div class=\"mt-4\"&gt;\n &lt;h3 class=\"text-lg font-semibold\"&gt;H\u00ECnh \u1EA3nh \u0111\u00E3 ch\u1EC9nh s\u1EEDa:&lt;/h3&gt;\n &lt;img [src]=\"editedImageUrl\" alt=\"H\u00ECnh \u1EA3nh \u0111\u00E3 ch\u1EC9nh s\u1EEDa\" class=\"mt-2 max-w-full h-auto\" /&gt;\n &lt;/div&gt;\n&#125;</code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (toggle-editor.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import &#123; Component &#125; from '&#64;angular/core';\nimport &#123; LibsUiComponentsImageEditorComponent &#125; from '&#64;libs-ui/components-image-editor';\nimport &#123; ISaveFile &#125; from '&#64;libs-ui/components-image-editor';\n\n&#64;Component(&#123;\n selector: 'app-toggle-editor',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n templateUrl: './toggle-editor.component.html'\n&#125;)\nexport class ToggleEditorComponent &#123;\n imageSource = 'https://example.com/path/to/image.jpg';\n showEditor = false;\n editedImageUrl = '';\n\n openEditor() &#123;\n this.showEditor = true;\n &#125;\n\n onSaveFile(data: ISaveFile) &#123;\n this.editedImageUrl = data.url;\n this.showEditor = false;\n console.log('\u0110\u00E3 l\u01B0u file:', data.file);\n &#125;\n\n onCloseEditor(data: &#123;isClickButtonClose: boolean&#125;) &#123;\n this.showEditor = false;\n &#125;\n&#125;</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 3: V\u1EDBi t\u1EF7 l\u1EC7 khung h\u00ECnh c\u1ED1 \u0111\u1ECBnh</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (fixed-ratio.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>&lt;libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [aspectRatio]=\"aspectRatio\"\n [requiredCropFollowRatio]=\"true\"\n (outSaveFile)=\"onSaveFile($event)\"&gt;\n&lt;/libs_ui-components-image_editor&gt;</code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (fixed-ratio.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import &#123; Component &#125; from '&#64;angular/core';\nimport &#123; LibsUiComponentsImageEditorComponent &#125; from '&#64;libs-ui/components-image-editor';\nimport &#123; IAspectRatio &#125; from '&#64;libs-ui/interfaces-types';\n\n&#64;Component(&#123;\n selector: 'app-fixed-ratio',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n templateUrl: './fixed-ratio.component.html'\n&#125;)\nexport class FixedRatioComponent &#123;\n imageSource = 'https://example.com/path/to/image.jpg';\n aspectRatio: IAspectRatio = &#123;\n key: '1:1',\n value: 1\n &#125;;\n\n onSaveFile(data: any) &#123;\n console.log('\u0110\u00E3 l\u01B0u h\u00ECnh \u1EA3nh v\u1EDBi t\u1EF7 l\u1EC7 1:1');\n &#125;\n&#125;</code></pre>\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">T\u00E0i li\u1EC7u API</h2>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Inputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF\n li\u1EC7u\n </th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u1EB7c \u0111\u1ECBnh\n </th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3\n </th>\n </tr>\n </thead>\n <tbody>\n @for (input of inputsDoc; track input.name) {\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ input.name }}</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ input.type }}</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">{{ input.default }}</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">{{ input.description }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Outputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF\n li\u1EC7u\n </th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3\n </th>\n </tr>\n </thead>\n <tbody>\n @for (output of outputsDoc; track output.name) {\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ output.name }}</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ output.type }}</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">{{ output.description }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Interfaces</h3>\n <div class=\"space-y-6\">\n @for (interfaceItem of interfacesDoc; track interfaceItem.name) {\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <h4 class=\"text-lg font-semibold text-gray-700 mb-3\">{{ interfaceItem.name }}</h4>\n <pre\n class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm mb-3\"><code>{{ interfaceItem.code }}</code></pre>\n <p class=\"text-gray-600\">{{ interfaceItem.description }}</p>\n </div>\n }\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">T\u00EDnh n\u0103ng</h2>\n <ul class=\"space-y-6\">\n @for (feature of features; track feature.id) {\n <li class=\"flex items-start\">\n <span class=\"text-2xl text-blue-500\">{{ feature.icon }}</span>\n <div>\n <h3 class=\"text-lg font-semibold text-gray-700 mb-1\">{{ feature.title }}</h3>\n <p class=\"text-gray-600\">{{ feature.description }}</p>\n </div>\n </li>\n }\n </ul>\n </section>\n </main>\n</div>\n", styles: ["pre code{@apply font-mono;}.hover\\:bg-blue-600{transition:background-color .2s ease-in-out}.overflow-x-auto{-webkit-overflow-scrolling:touch}pre::-webkit-scrollbar{@apply h-1.5 bg-gray-100;}pre::-webkit-scrollbar-thumb{@apply bg-gray-300 rounded;}button:focus,input:focus{@apply outline-none ring-2 ring-blue-400 ring-opacity-50;}input[type=file]{@apply text-sm text-gray-600;}\n"], dependencies: [{ kind: "component", type: LibsUiComponentsButtonsButtonComponent, selector: "libs_ui-components-buttons-button", inputs: ["flagMouse", "type", "buttonCustom", "sizeButton", "label", "disable", "isPending", "imageLeft", "classInclude", "classIconLeft", "classIconRight", "classLabel", "iconOnlyType", "popover", "ignoreStopPropagationEvent", "zIndex", "widthLabelPopover", "styleIconLeft", "styleButton", "ignoreFocusWhenInputTab", "ignoreSetClickWhenShowPopover", "ignorePointerEvent", "isActive", "isHandlerEnterDocumentClickButton"], outputs: ["outClick", "outPopoverEvent", "outFunctionsControl"] }, { kind: "component", type: LibsUiComponentsImageEditorComponent, selector: "libs_ui-components-image_editor", inputs: ["modeShowButton", "mimetype", "zIndex", "imgSrc", "originUrl", "nameFile", "hasZoom", "aspectRatio", "requiredCropFollowRatio"], outputs: ["imgSrcChange", "outClose", "outSaveFile", "outFunctionsControl"] }] });
1145
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: LibsUiComponentsImageEditorDemoComponent, isStandalone: true, selector: "lib-image-editor-demo", viewQueries: [{ propertyName: "imageFileInput", first: true, predicate: ["imageFileInput"], descendants: true }], ngImport: i0, template: "<div class=\"max-w-6xl mx-auto p-5 font-sans text-gray-800\">\n <header class=\"text-center py-10 bg-white rounded-lg mb-8 shadow-sm\">\n <h1 class=\"text-4xl font-bold text-gray-800 mb-2\">Demo Tr\u00ECnh Ch\u1EC9nh S\u1EEDa H\u00ECnh \u1EA2nh</h1>\n <p class=\"text-xl text-gray-500\">Th\u01B0 vi\u1EC7n component cho Angular \u0111\u1EC3 ch\u1EC9nh s\u1EEDa h\u00ECnh \u1EA3nh</p>\n </header>\n\n <main>\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Gi\u1EDBi thi\u1EC7u</h2>\n <p>\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">&#64;libs-ui/components-image-editor</code>\n l\u00E0 m\u1ED9t component Angular m\u1EA1nh m\u1EBD cho ph\u00E9p ng\u01B0\u1EDDi d\u00F9ng th\u1EF1c hi\u1EC7n c\u00E1c thao t\u00E1c ch\u1EC9nh s\u1EEDa h\u00ECnh \u1EA3nh nh\u01B0 c\u1EAFt, thay \u0111\u1ED5i k\u00EDch th\u01B0\u1EDBc, xoay, l\u1EADt v\u00E0 \u00E1p d\u1EE5ng t\u1EF7 l\u1EC7 c\u1ED1 \u0111\u1ECBnh.\n </p>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E0i \u0111\u1EB7t</h2>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Y\u00EAu c\u1EA7u</h3>\n <ul class=\"list-disc pl-5 space-y-2 text-gray-600\">\n <li>\n <span class=\"font-semibold\">Angular</span>\n : 18.0.0 tr\u1EDF l\u00EAn\n </li>\n <li>\n <span class=\"font-semibold\">Tailwind CSS</span>\n : 3.3.0 tr\u1EDF l\u00EAn\n </li>\n </ul>\n </div>\n\n <p class=\"mb-4\">\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>npm install &#64;libs-ui/components-image-editor</code></pre>\n <button\n class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('npm install @libs-ui/components-image-editor')\">\n Sao ch\u00E9p\n </button>\n </div>\n\n <p class=\"mb-4\">Ho\u1EB7c v\u1EDBi yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>yarn add &#64;libs-ui/components-image-editor</code></pre>\n <button\n class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('yarn add @libs-ui/components-image-editor')\">\n Sao ch\u00E9p\n </button>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Demo tr\u1EF1c ti\u1EBFp</h2>\n <div>\n <p class=\"mb-4\">T\u1EA3i l\u00EAn h\u00ECnh \u1EA3nh v\u00E0 ch\u1EC9nh s\u1EEDa ngay tr\u00EAn tr\u00ECnh duy\u1EC7t:</p>\n <div class=\"flex flex-wrap items-center gap-4 mb-8\">\n <input\n type=\"file\"\n #imageFileInput\n accept=\"image/*\"\n class=\"border border-gray-300 rounded px-3 py-2\"\n (change)=\"onFileSelected($event)\" />\n <libs_ui-components-buttons-button\n label=\"T\u1EA3i l\u00EAn v\u00E0 ch\u1EC9nh s\u1EEDa\"\n (click)=\"uploadAndEdit()\"></libs_ui-components-buttons-button>\n </div>\n\n @if (editedImageUrl) {\n <div class=\"mt-8 p-6 bg-gray-50 rounded-lg\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">K\u1EBFt qu\u1EA3</h3>\n <div class=\"max-w-xl mx-auto mb-4 border border-gray-200 rounded-lg overflow-hidden shadow-md\">\n <img\n [src]=\"editedImageUrl\"\n alt=\"H\u00ECnh \u1EA3nh \u0111\u00E3 ch\u1EC9nh s\u1EEDa\"\n class=\"w-full h-auto\" />\n </div>\n <div class=\"flex justify-center\">\n <libs_ui-components-buttons-button\n label=\"T\u1EA3i xu\u1ED1ng h\u00ECnh \u1EA3nh\"\n (click)=\"downloadImage()\"></libs_ui-components-buttons-button>\n </div>\n </div>\n }\n </div>\n </section>\n\n @if (showEditor) {\n <div class=\"fixed inset-0 z-50\">\n <libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [nameFile]=\"imageName || 'demo-image.jpg'\"\n [modeShowButton]=\"'save-file'\"\n [hasZoom]=\"true\"\n (outSaveFile)=\"onSaveImage($event)\"\n (outClose)=\"onCloseEditor($event)\"\n (outFunctionsControl)=\"handleFunctionControl($event)\" />\n </div>\n }\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E1ch s\u1EED d\u1EE5ng</h2>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 1: S\u1EED d\u1EE5ng file HTML ri\u00EAng bi\u1EC7t</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (example.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>&lt;libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [nameFile]=\"'image.jpg'\"\n [modeShowButton]=\"'save-file'\"\n (outSaveFile)=\"onSaveFile($event)\"\n (outClose)=\"onClose($event)\"&gt;\n&lt;/libs_ui-components-image_editor&gt;</code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (example.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import &#123; Component &#125; from '&#64;angular/core';\nimport &#123; LibsUiComponentsImageEditorComponent &#125; from '&#64;libs-ui/components-image-editor';\n\n&#64;Component(&#123;\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n templateUrl: './example.component.html'\n&#125;)\nexport class ExampleComponent &#123;\n imageSource = 'https://example.com/path/to/image.jpg';\n\n onSaveFile(data: &#123;file: Blob, url: string, mode: string&#125;) &#123;\n console.log('File \u0111\u00E3 \u0111\u01B0\u1EE3c l\u01B0u:', data);\n &#125;\n\n onClose(data: &#123;isClickButtonClose: boolean&#125;) &#123;\n console.log('\u0110\u00E3 \u0111\u00F3ng tr\u00ECnh ch\u1EC9nh s\u1EEDa \u1EA3nh');\n &#125;\n&#125;</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 2: V\u1EDBi tr\u00ECnh ch\u1EC9nh s\u1EEDa c\u00F3 th\u1EC3 \u0111\u00F3ng/m\u1EDF</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (toggle-editor.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>&lt;button (click)=\"openEditor()\" class=\"px-4 py-2 bg-blue-500 text-white rounded\"&gt;\n M\u1EDF tr\u00ECnh ch\u1EC9nh s\u1EEDa \u1EA3nh\n&lt;/button&gt;\n\n&#64;if (showEditor) &#123;\n &lt;libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [nameFile]=\"'my-image.jpg'\"\n (outSaveFile)=\"onSaveFile($event)\"\n (outClose)=\"onCloseEditor($event)\"&gt;\n &lt;/libs_ui-components-image_editor&gt;\n&#125;\n\n&#64;if (editedImageUrl) &#123;\n &lt;div class=\"mt-4\"&gt;\n &lt;h3 class=\"text-lg font-semibold\"&gt;H\u00ECnh \u1EA3nh \u0111\u00E3 ch\u1EC9nh s\u1EEDa:&lt;/h3&gt;\n &lt;img [src]=\"editedImageUrl\" alt=\"H\u00ECnh \u1EA3nh \u0111\u00E3 ch\u1EC9nh s\u1EEDa\" class=\"mt-2 max-w-full h-auto\" /&gt;\n &lt;/div&gt;\n&#125;</code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (toggle-editor.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import &#123; Component &#125; from '&#64;angular/core';\nimport &#123; LibsUiComponentsImageEditorComponent &#125; from '&#64;libs-ui/components-image-editor';\nimport &#123; ISaveFile &#125; from '&#64;libs-ui/components-image-editor';\n\n&#64;Component(&#123;\n selector: 'app-toggle-editor',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n templateUrl: './toggle-editor.component.html'\n&#125;)\nexport class ToggleEditorComponent &#123;\n imageSource = 'https://example.com/path/to/image.jpg';\n showEditor = false;\n editedImageUrl = '';\n\n openEditor() &#123;\n this.showEditor = true;\n &#125;\n\n onSaveFile(data: ISaveFile) &#123;\n this.editedImageUrl = data.url;\n this.showEditor = false;\n console.log('\u0110\u00E3 l\u01B0u file:', data.file);\n &#125;\n\n onCloseEditor(data: &#123;isClickButtonClose: boolean&#125;) &#123;\n this.showEditor = false;\n &#125;\n&#125;</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 3: V\u1EDBi t\u1EF7 l\u1EC7 khung h\u00ECnh c\u1ED1 \u0111\u1ECBnh</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (fixed-ratio.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>&lt;libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [aspectRatio]=\"aspectRatio\"\n [requiredCropFollowRatio]=\"true\"\n (outSaveFile)=\"onSaveFile($event)\"&gt;\n&lt;/libs_ui-components-image_editor&gt;</code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (fixed-ratio.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import &#123; Component &#125; from '&#64;angular/core';\nimport &#123; LibsUiComponentsImageEditorComponent &#125; from '&#64;libs-ui/components-image-editor';\nimport &#123; IAspectRatio &#125; from '&#64;libs-ui/interfaces-types';\n\n&#64;Component(&#123;\n selector: 'app-fixed-ratio',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n templateUrl: './fixed-ratio.component.html'\n&#125;)\nexport class FixedRatioComponent &#123;\n imageSource = 'https://example.com/path/to/image.jpg';\n aspectRatio: IAspectRatio = &#123;\n key: '1:1',\n value: 1\n &#125;;\n\n onSaveFile(data: any) &#123;\n console.log('\u0110\u00E3 l\u01B0u h\u00ECnh \u1EA3nh v\u1EDBi t\u1EF7 l\u1EC7 1:1');\n &#125;\n&#125;</code></pre>\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">T\u00E0i li\u1EC7u API</h2>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Inputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u1EB7c \u0111\u1ECBnh</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3</th>\n </tr>\n </thead>\n <tbody>\n @for (input of inputsDoc; track input.name) {\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\">\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ input.name }}</code>\n </td>\n <td class=\"py-2 px-4 border-b border-gray-200\">\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ input.type }}</code>\n </td>\n <td class=\"py-2 px-4 border-b border-gray-200\">{{ input.default }}</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">{{ input.description }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Outputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3</th>\n </tr>\n </thead>\n <tbody>\n @for (output of outputsDoc; track output.name) {\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\">\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ output.name }}</code>\n </td>\n <td class=\"py-2 px-4 border-b border-gray-200\">\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ output.type }}</code>\n </td>\n <td class=\"py-2 px-4 border-b border-gray-200\">{{ output.description }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Interfaces</h3>\n <div class=\"space-y-6\">\n @for (interfaceItem of interfacesDoc; track interfaceItem.name) {\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <h4 class=\"text-lg font-semibold text-gray-700 mb-3\">{{ interfaceItem.name }}</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm mb-3\"><code>{{ interfaceItem.code }}</code></pre>\n <p class=\"text-gray-600\">{{ interfaceItem.description }}</p>\n </div>\n }\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">T\u00EDnh n\u0103ng</h2>\n <ul class=\"space-y-6\">\n @for (feature of features; track feature.id) {\n <li class=\"flex items-start\">\n <span class=\"text-2xl text-blue-500\">{{ feature.icon }}</span>\n <div>\n <h3 class=\"text-lg font-semibold text-gray-700 mb-1\">{{ feature.title }}</h3>\n <p class=\"text-gray-600\">{{ feature.description }}</p>\n </div>\n </li>\n }\n </ul>\n </section>\n </main>\n</div>\n", styles: ["pre code{@apply font-mono;}.hover\\:bg-blue-600{transition:background-color .2s ease-in-out}.overflow-x-auto{-webkit-overflow-scrolling:touch}pre::-webkit-scrollbar{@apply h-1.5 bg-gray-100;}pre::-webkit-scrollbar-thumb{@apply bg-gray-300 rounded;}button:focus,input:focus{@apply outline-none ring-2 ring-blue-400 ring-opacity-50;}input[type=file]{@apply text-sm text-gray-600;}\n"], dependencies: [{ kind: "component", type: LibsUiComponentsButtonsButtonComponent, selector: "libs_ui-components-buttons-button", inputs: ["flagMouse", "type", "buttonCustom", "sizeButton", "label", "disable", "isPending", "imageLeft", "classInclude", "classIconLeft", "classIconRight", "classLabel", "iconOnlyType", "popover", "ignoreStopPropagationEvent", "zIndex", "widthLabelPopover", "styleIconLeft", "styleButton", "ignoreFocusWhenInputTab", "ignoreSetClickWhenShowPopover", "ignorePointerEvent", "isActive", "isHandlerEnterDocumentClickButton"], outputs: ["outClick", "outPopoverEvent", "outFunctionsControl"] }, { kind: "component", type: LibsUiComponentsImageEditorComponent, selector: "libs_ui-components-image_editor", inputs: ["modeShowButton", "mimetype", "zIndex", "imgSrc", "originUrl", "nameFile", "hasZoom", "aspectRatio", "requiredCropFollowRatio"], outputs: ["imgSrcChange", "outClose", "outSaveFile", "outFunctionsControl"] }] });
1124
1146
  }
1125
1147
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsImageEditorDemoComponent, decorators: [{
1126
1148
  type: Component,
1127
- args: [{ selector: 'lib-image-editor-demo', standalone: true, imports: [
1128
- LibsUiComponentsButtonsButtonComponent,
1129
- LibsUiComponentsImageEditorComponent
1130
- ], template: "<div class=\"max-w-6xl mx-auto p-5 font-sans text-gray-800\">\n <header class=\"text-center py-10 bg-white rounded-lg mb-8 shadow-sm\">\n <h1 class=\"text-4xl font-bold text-gray-800 mb-2\">Demo Tr\u00ECnh Ch\u1EC9nh S\u1EEDa H\u00ECnh \u1EA2nh</h1>\n <p class=\"text-xl text-gray-500\">Th\u01B0 vi\u1EC7n component cho Angular \u0111\u1EC3 ch\u1EC9nh s\u1EEDa h\u00ECnh \u1EA3nh</p>\n </header>\n\n <main>\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Gi\u1EDBi thi\u1EC7u</h2>\n <p>\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">&#64;libs-ui/components-image-editor</code> l\u00E0 m\u1ED9t\n component Angular m\u1EA1nh m\u1EBD cho ph\u00E9p ng\u01B0\u1EDDi d\u00F9ng th\u1EF1c hi\u1EC7n c\u00E1c thao t\u00E1c ch\u1EC9nh s\u1EEDa h\u00ECnh \u1EA3nh nh\u01B0 c\u1EAFt, thay \u0111\u1ED5i k\u00EDch\n th\u01B0\u1EDBc, xoay, l\u1EADt v\u00E0 \u00E1p d\u1EE5ng t\u1EF7 l\u1EC7 c\u1ED1 \u0111\u1ECBnh.\n </p>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E0i \u0111\u1EB7t</h2>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Y\u00EAu c\u1EA7u</h3>\n <ul class=\"list-disc pl-5 space-y-2 text-gray-600\">\n <li><span class=\"font-semibold\">Angular</span>: 18.0.0 tr\u1EDF l\u00EAn</li>\n <li><span class=\"font-semibold\">Tailwind CSS</span>: 3.3.0 tr\u1EDF l\u00EAn</li>\n </ul>\n </div>\n\n <p class=\"mb-4\">\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>npm install &#64;libs-ui/components-image-editor</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('npm install @libs-ui/components-image-editor')\">\n Sao ch\u00E9p\n </button>\n </div>\n\n <p class=\"mb-4\">Ho\u1EB7c v\u1EDBi yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>yarn add &#64;libs-ui/components-image-editor</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('yarn add @libs-ui/components-image-editor')\">\n Sao ch\u00E9p\n </button>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Demo tr\u1EF1c ti\u1EBFp</h2>\n <div>\n <p class=\"mb-4\">T\u1EA3i l\u00EAn h\u00ECnh \u1EA3nh v\u00E0 ch\u1EC9nh s\u1EEDa ngay tr\u00EAn tr\u00ECnh duy\u1EC7t:</p>\n <div class=\"flex flex-wrap items-center gap-4 mb-8\">\n <input type=\"file\"\n #imageFileInput\n accept=\"image/*\"\n class=\"border border-gray-300 rounded px-3 py-2\"\n (change)=\"onFileSelected($event)\" />\n <libs_ui-components-buttons-button label=\"T\u1EA3i l\u00EAn v\u00E0 ch\u1EC9nh s\u1EEDa\"\n (click)=\"uploadAndEdit()\">\n </libs_ui-components-buttons-button>\n </div>\n\n @if (editedImageUrl) {\n <div class=\"mt-8 p-6 bg-gray-50 rounded-lg\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">K\u1EBFt qu\u1EA3</h3>\n <div class=\"max-w-xl mx-auto mb-4 border border-gray-200 rounded-lg overflow-hidden shadow-md\">\n <img [src]=\"editedImageUrl\"\n alt=\"H\u00ECnh \u1EA3nh \u0111\u00E3 ch\u1EC9nh s\u1EEDa\"\n class=\"w-full h-auto\" />\n </div>\n <div class=\"flex justify-center\">\n <libs_ui-components-buttons-button label=\"T\u1EA3i xu\u1ED1ng h\u00ECnh \u1EA3nh\"\n (click)=\"downloadImage()\">\n </libs_ui-components-buttons-button>\n </div>\n </div>\n }\n </div>\n </section>\n\n @if (showEditor) {\n <div class=\"fixed inset-0 z-50\">\n <libs_ui-components-image_editor [(imgSrc)]=\"imageSource\"\n [nameFile]=\"imageName || 'demo-image.jpg'\"\n [modeShowButton]=\"'save-file'\"\n [hasZoom]=\"true\"\n (outSaveFile)=\"onSaveImage($event)\"\n (outClose)=\"onCloseEditor($event)\" />\n </div>\n }\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E1ch s\u1EED d\u1EE5ng</h2>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 1: S\u1EED d\u1EE5ng file HTML ri\u00EAng bi\u1EC7t</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (example.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>&lt;libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [nameFile]=\"'image.jpg'\"\n [modeShowButton]=\"'save-file'\"\n (outSaveFile)=\"onSaveFile($event)\"\n (outClose)=\"onClose($event)\"&gt;\n&lt;/libs_ui-components-image_editor&gt;</code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (example.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import &#123; Component &#125; from '&#64;angular/core';\nimport &#123; LibsUiComponentsImageEditorComponent &#125; from '&#64;libs-ui/components-image-editor';\n\n&#64;Component(&#123;\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n templateUrl: './example.component.html'\n&#125;)\nexport class ExampleComponent &#123;\n imageSource = 'https://example.com/path/to/image.jpg';\n\n onSaveFile(data: &#123;file: Blob, url: string, mode: string&#125;) &#123;\n console.log('File \u0111\u00E3 \u0111\u01B0\u1EE3c l\u01B0u:', data);\n &#125;\n\n onClose(data: &#123;isClickButtonClose: boolean&#125;) &#123;\n console.log('\u0110\u00E3 \u0111\u00F3ng tr\u00ECnh ch\u1EC9nh s\u1EEDa \u1EA3nh');\n &#125;\n&#125;</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 2: V\u1EDBi tr\u00ECnh ch\u1EC9nh s\u1EEDa c\u00F3 th\u1EC3 \u0111\u00F3ng/m\u1EDF</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (toggle-editor.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>&lt;button (click)=\"openEditor()\" class=\"px-4 py-2 bg-blue-500 text-white rounded\"&gt;\n M\u1EDF tr\u00ECnh ch\u1EC9nh s\u1EEDa \u1EA3nh\n&lt;/button&gt;\n\n&#64;if (showEditor) &#123;\n &lt;libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [nameFile]=\"'my-image.jpg'\"\n (outSaveFile)=\"onSaveFile($event)\"\n (outClose)=\"onCloseEditor($event)\"&gt;\n &lt;/libs_ui-components-image_editor&gt;\n&#125;\n\n&#64;if (editedImageUrl) &#123;\n &lt;div class=\"mt-4\"&gt;\n &lt;h3 class=\"text-lg font-semibold\"&gt;H\u00ECnh \u1EA3nh \u0111\u00E3 ch\u1EC9nh s\u1EEDa:&lt;/h3&gt;\n &lt;img [src]=\"editedImageUrl\" alt=\"H\u00ECnh \u1EA3nh \u0111\u00E3 ch\u1EC9nh s\u1EEDa\" class=\"mt-2 max-w-full h-auto\" /&gt;\n &lt;/div&gt;\n&#125;</code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (toggle-editor.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import &#123; Component &#125; from '&#64;angular/core';\nimport &#123; LibsUiComponentsImageEditorComponent &#125; from '&#64;libs-ui/components-image-editor';\nimport &#123; ISaveFile &#125; from '&#64;libs-ui/components-image-editor';\n\n&#64;Component(&#123;\n selector: 'app-toggle-editor',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n templateUrl: './toggle-editor.component.html'\n&#125;)\nexport class ToggleEditorComponent &#123;\n imageSource = 'https://example.com/path/to/image.jpg';\n showEditor = false;\n editedImageUrl = '';\n\n openEditor() &#123;\n this.showEditor = true;\n &#125;\n\n onSaveFile(data: ISaveFile) &#123;\n this.editedImageUrl = data.url;\n this.showEditor = false;\n console.log('\u0110\u00E3 l\u01B0u file:', data.file);\n &#125;\n\n onCloseEditor(data: &#123;isClickButtonClose: boolean&#125;) &#123;\n this.showEditor = false;\n &#125;\n&#125;</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 3: V\u1EDBi t\u1EF7 l\u1EC7 khung h\u00ECnh c\u1ED1 \u0111\u1ECBnh</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (fixed-ratio.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>&lt;libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [aspectRatio]=\"aspectRatio\"\n [requiredCropFollowRatio]=\"true\"\n (outSaveFile)=\"onSaveFile($event)\"&gt;\n&lt;/libs_ui-components-image_editor&gt;</code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (fixed-ratio.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import &#123; Component &#125; from '&#64;angular/core';\nimport &#123; LibsUiComponentsImageEditorComponent &#125; from '&#64;libs-ui/components-image-editor';\nimport &#123; IAspectRatio &#125; from '&#64;libs-ui/interfaces-types';\n\n&#64;Component(&#123;\n selector: 'app-fixed-ratio',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n templateUrl: './fixed-ratio.component.html'\n&#125;)\nexport class FixedRatioComponent &#123;\n imageSource = 'https://example.com/path/to/image.jpg';\n aspectRatio: IAspectRatio = &#123;\n key: '1:1',\n value: 1\n &#125;;\n\n onSaveFile(data: any) &#123;\n console.log('\u0110\u00E3 l\u01B0u h\u00ECnh \u1EA3nh v\u1EDBi t\u1EF7 l\u1EC7 1:1');\n &#125;\n&#125;</code></pre>\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">T\u00E0i li\u1EC7u API</h2>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Inputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF\n li\u1EC7u\n </th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u1EB7c \u0111\u1ECBnh\n </th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3\n </th>\n </tr>\n </thead>\n <tbody>\n @for (input of inputsDoc; track input.name) {\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ input.name }}</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ input.type }}</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">{{ input.default }}</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">{{ input.description }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Outputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF\n li\u1EC7u\n </th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3\n </th>\n </tr>\n </thead>\n <tbody>\n @for (output of outputsDoc; track output.name) {\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ output.name }}</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ output.type }}</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">{{ output.description }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Interfaces</h3>\n <div class=\"space-y-6\">\n @for (interfaceItem of interfacesDoc; track interfaceItem.name) {\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <h4 class=\"text-lg font-semibold text-gray-700 mb-3\">{{ interfaceItem.name }}</h4>\n <pre\n class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm mb-3\"><code>{{ interfaceItem.code }}</code></pre>\n <p class=\"text-gray-600\">{{ interfaceItem.description }}</p>\n </div>\n }\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">T\u00EDnh n\u0103ng</h2>\n <ul class=\"space-y-6\">\n @for (feature of features; track feature.id) {\n <li class=\"flex items-start\">\n <span class=\"text-2xl text-blue-500\">{{ feature.icon }}</span>\n <div>\n <h3 class=\"text-lg font-semibold text-gray-700 mb-1\">{{ feature.title }}</h3>\n <p class=\"text-gray-600\">{{ feature.description }}</p>\n </div>\n </li>\n }\n </ul>\n </section>\n </main>\n</div>\n", styles: ["pre code{@apply font-mono;}.hover\\:bg-blue-600{transition:background-color .2s ease-in-out}.overflow-x-auto{-webkit-overflow-scrolling:touch}pre::-webkit-scrollbar{@apply h-1.5 bg-gray-100;}pre::-webkit-scrollbar-thumb{@apply bg-gray-300 rounded;}button:focus,input:focus{@apply outline-none ring-2 ring-blue-400 ring-opacity-50;}input[type=file]{@apply text-sm text-gray-600;}\n"] }]
1149
+ args: [{ selector: 'lib-image-editor-demo', standalone: true, imports: [LibsUiComponentsButtonsButtonComponent, LibsUiComponentsImageEditorComponent], template: "<div class=\"max-w-6xl mx-auto p-5 font-sans text-gray-800\">\n <header class=\"text-center py-10 bg-white rounded-lg mb-8 shadow-sm\">\n <h1 class=\"text-4xl font-bold text-gray-800 mb-2\">Demo Tr\u00ECnh Ch\u1EC9nh S\u1EEDa H\u00ECnh \u1EA2nh</h1>\n <p class=\"text-xl text-gray-500\">Th\u01B0 vi\u1EC7n component cho Angular \u0111\u1EC3 ch\u1EC9nh s\u1EEDa h\u00ECnh \u1EA3nh</p>\n </header>\n\n <main>\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Gi\u1EDBi thi\u1EC7u</h2>\n <p>\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">&#64;libs-ui/components-image-editor</code>\n l\u00E0 m\u1ED9t component Angular m\u1EA1nh m\u1EBD cho ph\u00E9p ng\u01B0\u1EDDi d\u00F9ng th\u1EF1c hi\u1EC7n c\u00E1c thao t\u00E1c ch\u1EC9nh s\u1EEDa h\u00ECnh \u1EA3nh nh\u01B0 c\u1EAFt, thay \u0111\u1ED5i k\u00EDch th\u01B0\u1EDBc, xoay, l\u1EADt v\u00E0 \u00E1p d\u1EE5ng t\u1EF7 l\u1EC7 c\u1ED1 \u0111\u1ECBnh.\n </p>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E0i \u0111\u1EB7t</h2>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Y\u00EAu c\u1EA7u</h3>\n <ul class=\"list-disc pl-5 space-y-2 text-gray-600\">\n <li>\n <span class=\"font-semibold\">Angular</span>\n : 18.0.0 tr\u1EDF l\u00EAn\n </li>\n <li>\n <span class=\"font-semibold\">Tailwind CSS</span>\n : 3.3.0 tr\u1EDF l\u00EAn\n </li>\n </ul>\n </div>\n\n <p class=\"mb-4\">\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>npm install &#64;libs-ui/components-image-editor</code></pre>\n <button\n class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('npm install @libs-ui/components-image-editor')\">\n Sao ch\u00E9p\n </button>\n </div>\n\n <p class=\"mb-4\">Ho\u1EB7c v\u1EDBi yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>yarn add &#64;libs-ui/components-image-editor</code></pre>\n <button\n class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('yarn add @libs-ui/components-image-editor')\">\n Sao ch\u00E9p\n </button>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Demo tr\u1EF1c ti\u1EBFp</h2>\n <div>\n <p class=\"mb-4\">T\u1EA3i l\u00EAn h\u00ECnh \u1EA3nh v\u00E0 ch\u1EC9nh s\u1EEDa ngay tr\u00EAn tr\u00ECnh duy\u1EC7t:</p>\n <div class=\"flex flex-wrap items-center gap-4 mb-8\">\n <input\n type=\"file\"\n #imageFileInput\n accept=\"image/*\"\n class=\"border border-gray-300 rounded px-3 py-2\"\n (change)=\"onFileSelected($event)\" />\n <libs_ui-components-buttons-button\n label=\"T\u1EA3i l\u00EAn v\u00E0 ch\u1EC9nh s\u1EEDa\"\n (click)=\"uploadAndEdit()\"></libs_ui-components-buttons-button>\n </div>\n\n @if (editedImageUrl) {\n <div class=\"mt-8 p-6 bg-gray-50 rounded-lg\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">K\u1EBFt qu\u1EA3</h3>\n <div class=\"max-w-xl mx-auto mb-4 border border-gray-200 rounded-lg overflow-hidden shadow-md\">\n <img\n [src]=\"editedImageUrl\"\n alt=\"H\u00ECnh \u1EA3nh \u0111\u00E3 ch\u1EC9nh s\u1EEDa\"\n class=\"w-full h-auto\" />\n </div>\n <div class=\"flex justify-center\">\n <libs_ui-components-buttons-button\n label=\"T\u1EA3i xu\u1ED1ng h\u00ECnh \u1EA3nh\"\n (click)=\"downloadImage()\"></libs_ui-components-buttons-button>\n </div>\n </div>\n }\n </div>\n </section>\n\n @if (showEditor) {\n <div class=\"fixed inset-0 z-50\">\n <libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [nameFile]=\"imageName || 'demo-image.jpg'\"\n [modeShowButton]=\"'save-file'\"\n [hasZoom]=\"true\"\n (outSaveFile)=\"onSaveImage($event)\"\n (outClose)=\"onCloseEditor($event)\"\n (outFunctionsControl)=\"handleFunctionControl($event)\" />\n </div>\n }\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E1ch s\u1EED d\u1EE5ng</h2>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 1: S\u1EED d\u1EE5ng file HTML ri\u00EAng bi\u1EC7t</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (example.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>&lt;libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [nameFile]=\"'image.jpg'\"\n [modeShowButton]=\"'save-file'\"\n (outSaveFile)=\"onSaveFile($event)\"\n (outClose)=\"onClose($event)\"&gt;\n&lt;/libs_ui-components-image_editor&gt;</code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (example.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import &#123; Component &#125; from '&#64;angular/core';\nimport &#123; LibsUiComponentsImageEditorComponent &#125; from '&#64;libs-ui/components-image-editor';\n\n&#64;Component(&#123;\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n templateUrl: './example.component.html'\n&#125;)\nexport class ExampleComponent &#123;\n imageSource = 'https://example.com/path/to/image.jpg';\n\n onSaveFile(data: &#123;file: Blob, url: string, mode: string&#125;) &#123;\n console.log('File \u0111\u00E3 \u0111\u01B0\u1EE3c l\u01B0u:', data);\n &#125;\n\n onClose(data: &#123;isClickButtonClose: boolean&#125;) &#123;\n console.log('\u0110\u00E3 \u0111\u00F3ng tr\u00ECnh ch\u1EC9nh s\u1EEDa \u1EA3nh');\n &#125;\n&#125;</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 2: V\u1EDBi tr\u00ECnh ch\u1EC9nh s\u1EEDa c\u00F3 th\u1EC3 \u0111\u00F3ng/m\u1EDF</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (toggle-editor.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>&lt;button (click)=\"openEditor()\" class=\"px-4 py-2 bg-blue-500 text-white rounded\"&gt;\n M\u1EDF tr\u00ECnh ch\u1EC9nh s\u1EEDa \u1EA3nh\n&lt;/button&gt;\n\n&#64;if (showEditor) &#123;\n &lt;libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [nameFile]=\"'my-image.jpg'\"\n (outSaveFile)=\"onSaveFile($event)\"\n (outClose)=\"onCloseEditor($event)\"&gt;\n &lt;/libs_ui-components-image_editor&gt;\n&#125;\n\n&#64;if (editedImageUrl) &#123;\n &lt;div class=\"mt-4\"&gt;\n &lt;h3 class=\"text-lg font-semibold\"&gt;H\u00ECnh \u1EA3nh \u0111\u00E3 ch\u1EC9nh s\u1EEDa:&lt;/h3&gt;\n &lt;img [src]=\"editedImageUrl\" alt=\"H\u00ECnh \u1EA3nh \u0111\u00E3 ch\u1EC9nh s\u1EEDa\" class=\"mt-2 max-w-full h-auto\" /&gt;\n &lt;/div&gt;\n&#125;</code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (toggle-editor.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import &#123; Component &#125; from '&#64;angular/core';\nimport &#123; LibsUiComponentsImageEditorComponent &#125; from '&#64;libs-ui/components-image-editor';\nimport &#123; ISaveFile &#125; from '&#64;libs-ui/components-image-editor';\n\n&#64;Component(&#123;\n selector: 'app-toggle-editor',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n templateUrl: './toggle-editor.component.html'\n&#125;)\nexport class ToggleEditorComponent &#123;\n imageSource = 'https://example.com/path/to/image.jpg';\n showEditor = false;\n editedImageUrl = '';\n\n openEditor() &#123;\n this.showEditor = true;\n &#125;\n\n onSaveFile(data: ISaveFile) &#123;\n this.editedImageUrl = data.url;\n this.showEditor = false;\n console.log('\u0110\u00E3 l\u01B0u file:', data.file);\n &#125;\n\n onCloseEditor(data: &#123;isClickButtonClose: boolean&#125;) &#123;\n this.showEditor = false;\n &#125;\n&#125;</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 3: V\u1EDBi t\u1EF7 l\u1EC7 khung h\u00ECnh c\u1ED1 \u0111\u1ECBnh</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (fixed-ratio.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>&lt;libs_ui-components-image_editor\n [(imgSrc)]=\"imageSource\"\n [aspectRatio]=\"aspectRatio\"\n [requiredCropFollowRatio]=\"true\"\n (outSaveFile)=\"onSaveFile($event)\"&gt;\n&lt;/libs_ui-components-image_editor&gt;</code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (fixed-ratio.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import &#123; Component &#125; from '&#64;angular/core';\nimport &#123; LibsUiComponentsImageEditorComponent &#125; from '&#64;libs-ui/components-image-editor';\nimport &#123; IAspectRatio &#125; from '&#64;libs-ui/interfaces-types';\n\n&#64;Component(&#123;\n selector: 'app-fixed-ratio',\n standalone: true,\n imports: [LibsUiComponentsImageEditorComponent],\n templateUrl: './fixed-ratio.component.html'\n&#125;)\nexport class FixedRatioComponent &#123;\n imageSource = 'https://example.com/path/to/image.jpg';\n aspectRatio: IAspectRatio = &#123;\n key: '1:1',\n value: 1\n &#125;;\n\n onSaveFile(data: any) &#123;\n console.log('\u0110\u00E3 l\u01B0u h\u00ECnh \u1EA3nh v\u1EDBi t\u1EF7 l\u1EC7 1:1');\n &#125;\n&#125;</code></pre>\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">T\u00E0i li\u1EC7u API</h2>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Inputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u1EB7c \u0111\u1ECBnh</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3</th>\n </tr>\n </thead>\n <tbody>\n @for (input of inputsDoc; track input.name) {\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\">\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ input.name }}</code>\n </td>\n <td class=\"py-2 px-4 border-b border-gray-200\">\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ input.type }}</code>\n </td>\n <td class=\"py-2 px-4 border-b border-gray-200\">{{ input.default }}</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">{{ input.description }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Outputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF li\u1EC7u</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3</th>\n </tr>\n </thead>\n <tbody>\n @for (output of outputsDoc; track output.name) {\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\">\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ output.name }}</code>\n </td>\n <td class=\"py-2 px-4 border-b border-gray-200\">\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">{{ output.type }}</code>\n </td>\n <td class=\"py-2 px-4 border-b border-gray-200\">{{ output.description }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Interfaces</h3>\n <div class=\"space-y-6\">\n @for (interfaceItem of interfacesDoc; track interfaceItem.name) {\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <h4 class=\"text-lg font-semibold text-gray-700 mb-3\">{{ interfaceItem.name }}</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm mb-3\"><code>{{ interfaceItem.code }}</code></pre>\n <p class=\"text-gray-600\">{{ interfaceItem.description }}</p>\n </div>\n }\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">T\u00EDnh n\u0103ng</h2>\n <ul class=\"space-y-6\">\n @for (feature of features; track feature.id) {\n <li class=\"flex items-start\">\n <span class=\"text-2xl text-blue-500\">{{ feature.icon }}</span>\n <div>\n <h3 class=\"text-lg font-semibold text-gray-700 mb-1\">{{ feature.title }}</h3>\n <p class=\"text-gray-600\">{{ feature.description }}</p>\n </div>\n </li>\n }\n </ul>\n </section>\n </main>\n</div>\n", styles: ["pre code{@apply font-mono;}.hover\\:bg-blue-600{transition:background-color .2s ease-in-out}.overflow-x-auto{-webkit-overflow-scrolling:touch}pre::-webkit-scrollbar{@apply h-1.5 bg-gray-100;}pre::-webkit-scrollbar-thumb{@apply bg-gray-300 rounded;}button:focus,input:focus{@apply outline-none ring-2 ring-blue-400 ring-opacity-50;}input[type=file]{@apply text-sm text-gray-600;}\n"] }]
1131
1150
  }], propDecorators: { imageFileInput: [{
1132
1151
  type: ViewChild,
1133
1152
  args: ['imageFileInput']