@libs-ui/components-image-editor 0.2.227 → 0.2.228

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.
@@ -139,16 +139,16 @@ export class LibsUiComponentsImageEditorDemoComponent {
139
139
  }
140
140
  }
141
141
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsImageEditorDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
142
- 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 mr-4\">{{ 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"] }] });
142
+ 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"] }] });
143
143
  }
144
144
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsImageEditorDemoComponent, decorators: [{
145
145
  type: Component,
146
146
  args: [{ selector: 'lib-image-editor-demo', standalone: true, imports: [
147
147
  LibsUiComponentsButtonsButtonComponent,
148
148
  LibsUiComponentsImageEditorComponent
149
- ], 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 mr-4\">{{ 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"] }]
149
+ ], 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"] }]
150
150
  }], propDecorators: { imageFileInput: [{
151
151
  type: ViewChild,
152
152
  args: ['imageFileInput']
153
153
  }] } });
154
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2UtZWRpdG9yLWRlbW8uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vbGlicy11aS9jb21wb25lbnRzL2ltYWdlLWVkaXRvci9zcmMvZGVtby9pbWFnZS1lZGl0b3ItZGVtby5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvaW1hZ2UtZWRpdG9yL3NyYy9kZW1vL2ltYWdlLWVkaXRvci1kZW1vLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNqRSxPQUFPLEVBQUUsc0NBQXNDLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUM1RixPQUFPLEVBQUUsb0NBQW9DLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQzs7QUFhakYsTUFBTSxPQUFPLHdDQUF3QztJQUN0QixjQUFjLENBQWdDO0lBRTNFLFdBQVcsR0FBRyxFQUFFLENBQUM7SUFDakIsVUFBVSxHQUFHLEtBQUssQ0FBQztJQUNuQixjQUFjLEdBQUcsRUFBRSxDQUFDO0lBQ3BCLFlBQVksR0FBZ0IsSUFBSSxDQUFDO0lBQ2pDLFNBQVMsR0FBRyxFQUFFLENBQUM7SUFFZiwyQ0FBMkM7SUFDM0MsU0FBUyxHQUFHO1FBQ1YsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsa0RBQWtELEVBQUU7UUFDeEgsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsc0JBQXNCLEVBQUU7UUFDeEYsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsa0JBQWtCLEVBQUU7UUFDbkYsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsSUFBSSxFQUFFLDhCQUE4QixFQUFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsV0FBVyxFQUFFLGdCQUFnQixFQUFFO1FBQ3pILEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsV0FBVyxFQUFFLHdCQUF3QixFQUFFO1FBQ3pGLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLHVCQUF1QixFQUFFO1FBQ3pGLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsV0FBVyxFQUFFLG9DQUFvQyxFQUFFO1FBQ3pHLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsV0FBVyxFQUFFLDJCQUEyQixFQUFFO1FBQ3JHLEVBQUUsSUFBSSxFQUFFLHlCQUF5QixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsaUNBQWlDLEVBQUU7S0FDdkgsQ0FBQztJQUVGLFVBQVUsR0FBRztRQUNYLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsK0JBQStCLEVBQUUsV0FBVyxFQUFFLGtDQUFrQyxFQUFFO1FBQzVHLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxzQkFBc0IsRUFBRTtRQUMvRSxFQUFFLElBQUksRUFBRSxxQkFBcUIsRUFBRSxJQUFJLEVBQUUsa0NBQWtDLEVBQUUsV0FBVyxFQUFFLG9DQUFvQyxFQUFFO0tBQzdILENBQUM7SUFFRixhQUFhLEdBQUc7UUFDZDtZQUNFLElBQUksRUFBRSxXQUFXO1lBQ2pCLElBQUksRUFBRSxrSUFBa0k7WUFDeEksV0FBVyxFQUFFLDRDQUE0QztTQUMxRDtRQUNEO1lBQ0UsSUFBSSxFQUFFLGtDQUFrQztZQUN4QyxJQUFJLEVBQUUsNklBQTZJO1lBQ25KLFdBQVcsRUFBRSxpRkFBaUY7U0FDL0Y7UUFDRDtZQUNFLElBQUksRUFBRSxjQUFjO1lBQ3BCLElBQUksRUFBRSxzRUFBc0U7WUFDNUUsV0FBVyxFQUFFLHdDQUF3QztTQUN0RDtLQUNGLENBQUM7SUFFRixRQUFRLEdBQUc7UUFDVDtZQUNFLEVBQUUsRUFBRSxDQUFDO1lBQ0wsSUFBSSxFQUFFLElBQUk7WUFDVixLQUFLLEVBQUUsU0FBUztZQUNoQixXQUFXLEVBQUUsNEZBQTRGO1NBQzFHO1FBQ0Q7WUFDRSxFQUFFLEVBQUUsQ0FBQztZQUNMLElBQUksRUFBRSxJQUFJO1lBQ1YsS0FBSyxFQUFFLGFBQWE7WUFDcEIsV0FBVyxFQUFFLHFFQUFxRTtTQUNuRjtRQUNEO1lBQ0UsRUFBRSxFQUFFLENBQUM7WUFDTCxJQUFJLEVBQUUsSUFBSTtZQUNWLEtBQUssRUFBRSxxQkFBcUI7WUFDNUIsV0FBVyxFQUFFLDJFQUEyRTtTQUN6RjtRQUNEO1lBQ0UsRUFBRSxFQUFFLENBQUM7WUFDTCxJQUFJLEVBQUUsSUFBSTtZQUNWLEtBQUssRUFBRSxrQkFBa0I7WUFDekIsV0FBVyxFQUFFLGdFQUFnRTtTQUM5RTtRQUNEO1lBQ0UsRUFBRSxFQUFFLENBQUM7WUFDTCxJQUFJLEVBQUUsSUFBSTtZQUNWLEtBQUssRUFBRSxrQkFBa0I7WUFDekIsV0FBVyxFQUFFLG9FQUFvRTtTQUNsRjtLQUNGLENBQUM7SUFFRixZQUFZLEdBQUc7UUFDYjtZQUNFLEVBQUUsRUFBRSxDQUFDO1lBQ0wsS0FBSyxFQUFFLGdCQUFnQjtZQUN2QixJQUFJLEVBQUUsbTFCQUFtMUI7U0FDMTFCO1FBQ0Q7WUFDRSxFQUFFLEVBQUUsQ0FBQztZQUNMLEtBQUssRUFBRSwyQkFBMkI7WUFDbEMsSUFBSSxFQUFFLDZ5QkFBNnlCO1NBQ3B6QjtRQUNEO1lBQ0UsRUFBRSxFQUFFLENBQUM7WUFDTCxLQUFLLEVBQUUsdUNBQXVDO1lBQzlDLElBQUksRUFBRSw0bkNBQTRuQztTQUNub0M7S0FDRixDQUFDO0lBRUYsZUFBZSxDQUFDLElBQVk7UUFDMUIsU0FBUyxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUM1QyxLQUFLLENBQUMsMkJBQTJCLENBQUMsQ0FBQztRQUNyQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDYixPQUFPLENBQUMsS0FBSyxDQUFDLHNCQUFzQixFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQzdDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGNBQWMsQ0FBQyxLQUFZO1FBQ3pCLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUEwQixDQUFDO1FBQy9DLElBQUksS0FBSyxDQUFDLEtBQUssSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUMxQyxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDbkMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQztZQUN4QyxPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDeEQsQ0FBQztJQUNILENBQUM7SUFFRCxhQUFhO1FBQ1gsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN2QixLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztZQUMvQyxPQUFPO1FBQ1QsQ0FBQztRQUVELE1BQU0sTUFBTSxHQUFHLElBQUksVUFBVSxFQUFFLENBQUM7UUFDaEMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQTRCLEVBQUUsRUFBRTtZQUMvQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUM7Z0JBQ3JCLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFnQixDQUFDO2dCQUM3QyxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztZQUN6QixDQUFDO1FBQ0gsQ0FBQyxDQUFDO1FBQ0YsTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVELFdBQVcsQ0FBQyxJQUFlO1FBQ3pCLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2xDLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQztRQUMvQixJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztJQUMxQixDQUFDO0lBRUQsYUFBYSxDQUFDLElBQXFDO1FBQ2pELE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDcEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7SUFDMUIsQ0FBQztJQUVELGFBQWE7UUFDWCxJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN4QixNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3pDLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQztZQUNoQyxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxTQUFTLElBQUksa0JBQWtCLENBQUM7WUFDckQsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2YsQ0FBQztJQUNILENBQUM7d0dBcEpVLHdDQUF3Qzs0RkFBeEMsd0NBQXdDLG1NQ2ZyRCxzL2RBeVVBLHNiRGhVSSxzQ0FBc0Msc2pCQUN0QyxvQ0FBb0M7OzRGQUszQix3Q0FBd0M7a0JBVnBELFNBQVM7K0JBQ0UsdUJBQXVCLGNBQ3JCLElBQUksV0FDUDt3QkFDUCxzQ0FBc0M7d0JBQ3RDLG9DQUFvQztxQkFDckM7OEJBSzRCLGNBQWM7c0JBQTFDLFNBQVM7dUJBQUMsZ0JBQWdCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IExpYnNVaUNvbXBvbmVudHNCdXR0b25zQnV0dG9uQ29tcG9uZW50IH0gZnJvbSAnQGxpYnMtdWkvY29tcG9uZW50cy1idXR0b25zLWJ1dHRvbic7XG5pbXBvcnQgeyBMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnQgfSBmcm9tICcuLi9pbWFnZS1lZGl0b3IuY29tcG9uZW50JztcbmltcG9ydCB7IElTYXZlRmlsZSB9IGZyb20gJy4uL2ludGVyZmFjZXMvaW1hZ2UtZWRpdG9yLmludGVyZmFjZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2xpYi1pbWFnZS1lZGl0b3ItZGVtbycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBMaWJzVWlDb21wb25lbnRzQnV0dG9uc0J1dHRvbkNvbXBvbmVudCxcbiAgICBMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnRcbiAgXSxcbiAgdGVtcGxhdGVVcmw6ICcuL2ltYWdlLWVkaXRvci1kZW1vLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL2ltYWdlLWVkaXRvci1kZW1vLmNvbXBvbmVudC5zY3NzJ1xufSlcbmV4cG9ydCBjbGFzcyBMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JEZW1vQ29tcG9uZW50IHtcbiAgQFZpZXdDaGlsZCgnaW1hZ2VGaWxlSW5wdXQnKSBpbWFnZUZpbGVJbnB1dCE6IEVsZW1lbnRSZWY8SFRNTElucHV0RWxlbWVudD47XG5cbiAgaW1hZ2VTb3VyY2UgPSAnJztcbiAgc2hvd0VkaXRvciA9IGZhbHNlO1xuICBlZGl0ZWRJbWFnZVVybCA9ICcnO1xuICBzZWxlY3RlZEZpbGU6IEZpbGUgfCBudWxsID0gbnVsbDtcbiAgaW1hZ2VOYW1lID0gJyc7XG5cbiAgLy8gRG9jdW1lbnRhdGlvbiBkYXRhIGFzIHJlZ3VsYXIgcHJvcGVydGllc1xuICBpbnB1dHNEb2MgPSBbXG4gICAgeyBuYW1lOiAnaW1nU3JjJywgdHlwZTogJ3N0cmluZycsIGRlZmF1bHQ6ICdC4bqvdCBideG7mWMnLCBkZXNjcmlwdGlvbjogJ8SQxrDhu51uZyBk4bqrbiBob+G6t2MgYmFzZTY0IGPhu6dhIGjDrG5oIOG6o25oIGPhuqduIGNo4buJbmggc+G7rWEnIH0sXG4gICAgeyBuYW1lOiAnb3JpZ2luVXJsJywgdHlwZTogJ3N0cmluZycsIGRlZmF1bHQ6ICctJywgZGVzY3JpcHRpb246ICdVUkwgZ+G7kWMgY+G7p2EgaMOsbmgg4bqjbmgnIH0sXG4gICAgeyBuYW1lOiAnbmFtZUZpbGUnLCB0eXBlOiAnc3RyaW5nJywgZGVmYXVsdDogJy0nLCBkZXNjcmlwdGlvbjogJ1TDqm4gZmlsZSBraGkgbMawdScgfSxcbiAgICB7IG5hbWU6ICdtb2RlU2hvd0J1dHRvbicsIHR5cGU6ICdcXCdzYXZlLWZpbGVcXCcgfCBcXCdzYXZlLWFwaVxcJycsIGRlZmF1bHQ6ICdcXCdzYXZlLWZpbGVcXCcnLCBkZXNjcmlwdGlvbjogJ0No4bq/IMSR4buZIG7DunQgbMawdScgfSxcbiAgICB7IG5hbWU6ICdtaW1ldHlwZScsIHR5cGU6ICdzdHJpbmcnLCBkZWZhdWx0OiAnLScsIGRlc2NyaXB0aW9uOiAnxJDhu4tuaCBk4bqhbmcgY+G7p2EgaMOsbmgg4bqjbmgnIH0sXG4gICAgeyBuYW1lOiAnekluZGV4JywgdHlwZTogJ251bWJlcicsIGRlZmF1bHQ6ICcxMjAwJywgZGVzY3JpcHRpb246ICd6LWluZGV4IGPhu6dhIGNvbXBvbmVudCcgfSxcbiAgICB7IG5hbWU6ICdoYXNab29tJywgdHlwZTogJ2Jvb2xlYW4nLCBkZWZhdWx0OiAnZmFsc2UnLCBkZXNjcmlwdGlvbjogJ0NobyBwaMOpcCBwaMOzbmcgdG8vdGh1IG5o4buPIGjDrG5oIOG6o25oJyB9LFxuICAgIHsgbmFtZTogJ2FzcGVjdFJhdGlvJywgdHlwZTogJ0lBc3BlY3RSYXRpbycsIGRlZmF1bHQ6ICctJywgZGVzY3JpcHRpb246ICdU4bu3IGzhu4cga2h1bmcgaMOsbmggbeG6t2MgxJHhu4tuaCcgfSxcbiAgICB7IG5hbWU6ICdyZXF1aXJlZENyb3BGb2xsb3dSYXRpbycsIHR5cGU6ICdib29sZWFuJywgZGVmYXVsdDogJ2ZhbHNlJywgZGVzY3JpcHRpb246ICdC4bqvdCBideG7mWMgY+G6r3QgdGhlbyB04bu3IGzhu4cgxJHDoyBjaOG7jW4nIH1cbiAgXTtcblxuICBvdXRwdXRzRG9jID0gW1xuICAgIHsgbmFtZTogJ291dENsb3NlJywgdHlwZTogJ3tpc0NsaWNrQnV0dG9uQ2xvc2U6IGJvb2xlYW59JywgZGVzY3JpcHRpb246ICdT4buxIGtp4buHbiBraGkgxJHDs25nIHRyw6xuaCBjaOG7iW5oIHPhu61hJyB9LFxuICAgIHsgbmFtZTogJ291dFNhdmVGaWxlJywgdHlwZTogJ0lTYXZlRmlsZScsIGRlc2NyaXB0aW9uOiAnU+G7sSBraeG7h24ga2hpIGzGsHUgZmlsZScgfSxcbiAgICB7IG5hbWU6ICdvdXRGdW5jdGlvbnNDb250cm9sJywgdHlwZTogJ0lJbWFnZUVkaXRvckZ1bmN0aW9uQ29udHJvbEV2ZW50JywgZGVzY3JpcHRpb246ICdT4buxIGtp4buHbiDEkeG7gyBraeG7g20gc2/DoXQgY8OhYyBjaOG7qWMgbsSDbmcnIH1cbiAgXTtcblxuICBpbnRlcmZhY2VzRG9jID0gW1xuICAgIHtcbiAgICAgIG5hbWU6ICdJU2F2ZUZpbGUnLFxuICAgICAgY29kZTogJ2V4cG9ydCBpbnRlcmZhY2UgSVNhdmVGaWxlIHtcXG4gIGZpbGU6IEJsb2I7XFxuICB1cmw6IHN0cmluZztcXG4gIG1vZGU6IFxcJ3NhdmUtZmlsZVxcJyB8IFxcJ3NhdmUtYXBpXFwnIHwgXFwnc2F2ZS1hcGktYXMtbmV3LWZpbGVcXCc7XFxufScsXG4gICAgICBkZXNjcmlwdGlvbjogJ0ludGVyZmFjZSDEkeG7i25oIG5naMSpYSBk4buvIGxp4buHdSBraGkgbMawdSBmaWxlLidcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdJSW1hZ2VFZGl0b3JGdW5jdGlvbkNvbnRyb2xFdmVudCcsXG4gICAgICBjb2RlOiAnZXhwb3J0IGludGVyZmFjZSBJSW1hZ2VFZGl0b3JGdW5jdGlvbkNvbnRyb2xFdmVudCB7XFxuICBjcm9wSW1hZ2U6ICgpID0+IFByb21pc2U8c3RyaW5nPjtcXG4gIHNldExvYWRpbmdTdGF0ZTogKGxvYWRpbmc6IGJvb2xlYW4pID0+IHZvaWQ7XFxufScsXG4gICAgICBkZXNjcmlwdGlvbjogJ0ludGVyZmFjZSDEkeG7i25oIG5naMSpYSBjw6FjIGjDoG0gxJFp4buBdSBraGnhu4NuIGPDsyB0aOG7gyDEkcaw4bujYyBn4buNaSB04burIGLDqm4gbmdvw6BpIGNvbXBvbmVudC4nXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiAnSUFzcGVjdFJhdGlvJyxcbiAgICAgIGNvZGU6ICdleHBvcnQgaW50ZXJmYWNlIElBc3BlY3RSYXRpbyB7XFxuICBrZXk6IHN0cmluZztcXG4gIHZhbHVlOiBudW1iZXI7XFxufScsXG4gICAgICBkZXNjcmlwdGlvbjogJ0ludGVyZmFjZSDEkeG7i25oIG5naMSpYSB04bu3IGzhu4cga2h1bmcgaMOsbmguJ1xuICAgIH1cbiAgXTtcblxuICBmZWF0dXJlcyA9IFtcbiAgICB7XG4gICAgICBpZDogMSxcbiAgICAgIGljb246ICfinILvuI8nLFxuICAgICAgdGl0bGU6ICdD4bqvdCDhuqNuaCcsXG4gICAgICBkZXNjcmlwdGlvbjogJ0Phuq90IGjDrG5oIOG6o25oIHRoZW8ga2h1IHbhu7FjIHTDuXkgY2jhu4luaCBob+G6t2MgZOG7sWEgdHLDqm4gdOG7tyBs4buHIMSR4buLbmggdHLGsOG7m2MgKDE6MSwgNDozLCAxNjo5LCB2LnYuKS4nXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogMixcbiAgICAgIGljb246ICfwn5SEJyxcbiAgICAgIHRpdGxlOiAnWG9heSB2w6AgbOG6rXQnLFxuICAgICAgZGVzY3JpcHRpb246ICdYb2F5IGjDrG5oIOG6o25oIHRoZW8gY8OhYyBnw7NjIGtow6FjIG5oYXUgaG/hurdjIGzhuq10IHRoZW8gY2hp4buBdSBuZ2FuZy9k4buNYy4nXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogMyxcbiAgICAgIGljb246ICfwn5OPJyxcbiAgICAgIHRpdGxlOiAnVGhheSDEkeG7lWkga8OtY2ggdGjGsOG7m2MnLFxuICAgICAgZGVzY3JpcHRpb246ICdUaGF5IMSR4buVaSBrw61jaCB0aMaw4bubYyBow6xuaCDhuqNuaCB0aGVvIHThu7cgbOG7hyBwaOG6p24gdHLEg20gaG/hurdjIGvDrWNoIHRoxrDhu5tjIGPhu6UgdGjhu4MuJ1xuICAgIH0sXG4gICAge1xuICAgICAgaWQ6IDQsXG4gICAgICBpY29uOiAn8J+SvicsXG4gICAgICB0aXRsZTogJ05oaeG7gXUgY2jhur8gxJHhu5kgbMawdScsXG4gICAgICBkZXNjcmlwdGlvbjogJ0jhu5cgdHLhu6Mgbmhp4buBdSBjaOG6vyDEkeG7mSBsxrB1OiB04bqjaSB4deG7kW5nIHRy4buxYyB0aeG6v3AgaG/hurdjIGfhu61pIMSR4bq/biBBUEkuJ1xuICAgIH0sXG4gICAge1xuICAgICAgaWQ6IDUsXG4gICAgICBpY29uOiAn8J+UjScsXG4gICAgICB0aXRsZTogJ1Bow7NuZyB0by90aHUgbmjhu48nLFxuICAgICAgZGVzY3JpcHRpb246ICdUw61uaCBuxINuZyBwaMOzbmcgdG8vdGh1IG5o4buPIMSR4buDIHhlbSBjaGkgdGnhur90IGjDrG5oIOG6o25oIGtoaSBj4bqnbiB0aGnhur90LidcbiAgICB9XG4gIF07XG5cbiAgY29kZUV4YW1wbGVzID0gW1xuICAgIHtcbiAgICAgIGlkOiAxLFxuICAgICAgdGl0bGU6ICdT4butIGThu6VuZyBjxqEgYuG6o24nLFxuICAgICAgY29kZTogYGltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xcbmltcG9ydCB7IExpYnNVaUNvbXBvbmVudHNJbWFnZUVkaXRvckNvbXBvbmVudCB9IGZyb20gJ0BsaWJzLXVpL2NvbXBvbmVudHMtaW1hZ2UtZWRpdG9yJztcXG5cXG5AQ29tcG9uZW50KHtcXG4gIHNlbGVjdG9yOiAnYXBwLWV4YW1wbGUnLFxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcXG4gIGltcG9ydHM6IFtMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnRdLFxcbiAgdGVtcGxhdGU6IFxcYFxcbiAgICA8bGlic191aS1jb21wb25lbnRzLWltYWdlX2VkaXRvclxcbiAgICAgIFsoaW1nU3JjKV09XCJpbWFnZVNvdXJjZVwiXFxuICAgICAgW21vZGVTaG93QnV0dG9uXT1cIidzYXZlLWZpbGUnXCJcXG4gICAgICBbbmFtZUZpbGVdPVwiJ2ltYWdlLmpwZydcIlxcbiAgICAgIChvdXRTYXZlRmlsZSk9XCJvblNhdmVGaWxlKCRldmVudClcIlxcbiAgICAgIChvdXRDbG9zZSk9XCJvbkNsb3NlKCRldmVudClcIj5cXG4gICAgPC9saWJzX3VpLWNvbXBvbmVudHMtaW1hZ2VfZWRpdG9yPlxcbiAgXFxgXFxufSlcXG5leHBvcnQgY2xhc3MgRXhhbXBsZUNvbXBvbmVudCB7XFxuICBpbWFnZVNvdXJjZSA9ICdodHRwczovL2V4YW1wbGUuY29tL3BhdGgvdG8vaW1hZ2UuanBnJztcXG5cXG4gIG9uU2F2ZUZpbGUoZGF0YToge2ZpbGU6IEJsb2IsIHVybDogc3RyaW5nLCBtb2RlOiBzdHJpbmd9KSB7XFxuICAgIGNvbnNvbGUubG9nKCdGaWxlIMSRw6MgxJHGsOG7o2MgbMawdTonLCBkYXRhKTtcXG4gIH1cXG5cXG4gIG9uQ2xvc2UoZGF0YToge2lzQ2xpY2tCdXR0b25DbG9zZTogYm9vbGVhbn0pIHtcXG4gICAgY29uc29sZS5sb2coJ8SQw6MgxJHDs25nIHRyw6xuaCBjaOG7iW5oIHPhu61hIOG6o25oJyk7XFxuICB9XFxufWBcbiAgICB9LFxuICAgIHtcbiAgICAgIGlkOiAyLFxuICAgICAgdGl0bGU6ICdT4butIGThu6VuZyB24bubaSB04bu3IGzhu4cgY+G7kSDEkeG7i25oJyxcbiAgICAgIGNvZGU6IGBpbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcXG5pbXBvcnQgeyBMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnQgfSBmcm9tICdAbGlicy11aS9jb21wb25lbnRzLWltYWdlLWVkaXRvcic7XFxuaW1wb3J0IHsgSUFzcGVjdFJhdGlvIH0gZnJvbSAnQGxpYnMtdWkvaW50ZXJmYWNlcy10eXBlcyc7XFxuXFxuQENvbXBvbmVudCh7XFxuICBzZWxlY3RvcjogJ2FwcC1leGFtcGxlJyxcXG4gIHN0YW5kYWxvbmU6IHRydWUsXFxuICBpbXBvcnRzOiBbTGlic1VpQ29tcG9uZW50c0ltYWdlRWRpdG9yQ29tcG9uZW50XSxcXG4gIHRlbXBsYXRlOiBcXGBcXG4gICAgPGxpYnNfdWktY29tcG9uZW50cy1pbWFnZV9lZGl0b3JcXG4gICAgICBbKGltZ1NyYyldPVwiaW1hZ2VTb3VyY2VcIlxcbiAgICAgIFthc3BlY3RSYXRpb109XCJhc3BlY3RSYXRpb1wiXFxuICAgICAgW3JlcXVpcmVkQ3JvcEZvbGxvd1JhdGlvXT1cInRydWVcIlxcbiAgICAgIChvdXRTYXZlRmlsZSk9XCJvblNhdmVGaWxlKCRldmVudClcIj5cXG4gICAgPC9saWJzX3VpLWNvbXBvbmVudHMtaW1hZ2VfZWRpdG9yPlxcbiAgXFxgXFxufSlcXG5leHBvcnQgY2xhc3MgRXhhbXBsZUNvbXBvbmVudCB7XFxuICBpbWFnZVNvdXJjZSA9ICdodHRwczovL2V4YW1wbGUuY29tL3BhdGgvdG8vaW1hZ2UuanBnJztcXG4gIGFzcGVjdFJhdGlvOiBJQXNwZWN0UmF0aW8gPSB7XFxuICAgIGtleTogJzE6MScsXFxuICAgIHZhbHVlOiAxXFxuICB9O1xcblxcbiAgb25TYXZlRmlsZShkYXRhOiBhbnkpIHtcXG4gICAgY29uc29sZS5sb2coJ8SQw6MgbMawdSBow6xuaCDhuqNuaCB24bubaSB04bu3IGzhu4cgMToxJyk7XFxuICB9XFxufWBcbiAgICB9LFxuICAgIHtcbiAgICAgIGlkOiAzLFxuICAgICAgdGl0bGU6ICdT4butIGThu6VuZyB24bubaSBwaOG6p24gxJFp4buBdSBraGnhu4NuIGLDqm4gbmdvw6BpJyxcbiAgICAgIGNvZGU6IGBpbXBvcnQgeyBDb21wb25lbnQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xcbmltcG9ydCB7IExpYnNVaUNvbXBvbmVudHNJbWFnZUVkaXRvckNvbXBvbmVudCwgSUltYWdlRWRpdG9yRnVuY3Rpb25Db250cm9sRXZlbnQgfSBmcm9tICdAbGlicy11aS9jb21wb25lbnRzLWltYWdlLWVkaXRvcic7XFxuXFxuQENvbXBvbmVudCh7XFxuICBzZWxlY3RvcjogJ2FwcC1leGFtcGxlJyxcXG4gIHN0YW5kYWxvbmU6IHRydWUsXFxuICBpbXBvcnRzOiBbTGlic1VpQ29tcG9uZW50c0ltYWdlRWRpdG9yQ29tcG9uZW50XSxcXG4gIHRlbXBsYXRlOiBcXGBcXG4gICAgPGJ1dHRvbiAoY2xpY2spPVwiY3JvcEFuZFNhdmUoKVwiPkPhuq90IHbDoCBsxrB1IG5nYXk8L2J1dHRvbj5cXG4gICAgPGxpYnNfdWktY29tcG9uZW50cy1pbWFnZV9lZGl0b3JcXG4gICAgICBbKGltZ1NyYyldPVwiaW1hZ2VTb3VyY2VcIlxcbiAgICAgIChvdXRGdW5jdGlvbnNDb250cm9sKT1cIm9uRnVuY3Rpb25zQ29udHJvbCgkZXZlbnQpXCI+XFxuICAgIDwvbGlic191aS1jb21wb25lbnRzLWltYWdlX2VkaXRvcj5cXG4gIFxcYFxcbn0pXFxuZXhwb3J0IGNsYXNzIEV4YW1wbGVDb21wb25lbnQge1xcbiAgaW1hZ2VTb3VyY2UgPSAnaHR0cHM6Ly9leGFtcGxlLmNvbS9wYXRoL3RvL2ltYWdlLmpwZyc7XFxuICBlZGl0b3JGdW5jdGlvbnMhOiBJSW1hZ2VFZGl0b3JGdW5jdGlvbkNvbnRyb2xFdmVudDtcXG5cXG4gIG9uRnVuY3Rpb25zQ29udHJvbChldmVudDogSUltYWdlRWRpdG9yRnVuY3Rpb25Db250cm9sRXZlbnQpIHtcXG4gICAgdGhpcy5lZGl0b3JGdW5jdGlvbnMgPSBldmVudDtcXG4gIH1cXG5cXG4gIGFzeW5jIGNyb3BBbmRTYXZlKCkge1xcbiAgICBpZiAodGhpcy5lZGl0b3JGdW5jdGlvbnMpIHtcXG4gICAgICB0aGlzLmVkaXRvckZ1bmN0aW9ucy5zZXRMb2FkaW5nU3RhdGUodHJ1ZSk7XFxuICAgICAgdHJ5IHtcXG4gICAgICAgIGNvbnN0IGRhdGFVcmwgPSBhd2FpdCB0aGlzLmVkaXRvckZ1bmN0aW9ucy5jcm9wSW1hZ2UoKTtcXG4gICAgICAgIGNvbnNvbGUubG9nKCdIw6xuaCDhuqNuaCDEkcOjIMSRxrDhu6NjIGPhuq90OicsIGRhdGFVcmwpO1xcbiAgICAgIH0gZmluYWxseSB7XFxuICAgICAgICB0aGlzLmVkaXRvckZ1bmN0aW9ucy5zZXRMb2FkaW5nU3RhdGUoZmFsc2UpO1xcbiAgICAgIH1cXG4gICAgfVxcbiAgfVxcbn1gXG4gICAgfVxuICBdO1xuXG4gIGNvcHlUb0NsaXBib2FyZCh0ZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dCh0ZXh0KS50aGVuKCgpID0+IHtcbiAgICAgIGFsZXJ0KCfEkMOjIHNhbyBjaMOpcCB2w6BvIGNsaXBib2FyZCcpO1xuICAgIH0pLmNhdGNoKGVyciA9PiB7XG4gICAgICBjb25zb2xlLmVycm9yKCdLaMO0bmcgdGjhu4Mgc2FvIGNow6lwOiAnLCBlcnIpO1xuICAgIH0pO1xuICB9XG5cbiAgb25GaWxlU2VsZWN0ZWQoZXZlbnQ6IEV2ZW50KSB7XG4gICAgY29uc3QgaW5wdXQgPSBldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICBpZiAoaW5wdXQuZmlsZXMgJiYgaW5wdXQuZmlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5zZWxlY3RlZEZpbGUgPSBpbnB1dC5maWxlc1swXTtcbiAgICAgIHRoaXMuaW1hZ2VOYW1lID0gdGhpcy5zZWxlY3RlZEZpbGUubmFtZTtcbiAgICAgIGNvbnNvbGUubG9nKCdGaWxlIHNlbGVjdGVkOicsIHRoaXMuc2VsZWN0ZWRGaWxlLm5hbWUpO1xuICAgIH1cbiAgfVxuXG4gIHVwbG9hZEFuZEVkaXQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNlbGVjdGVkRmlsZSkge1xuICAgICAgYWxlcnQoJ1Z1aSBsw7JuZyBjaOG7jW4gbeG7mXQgZmlsZSBow6xuaCDhuqNuaCB0csaw4bubYycpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG4gICAgcmVhZGVyLm9ubG9hZCA9IChlOiBQcm9ncmVzc0V2ZW50PEZpbGVSZWFkZXI+KSA9PiB7XG4gICAgICBpZiAoZS50YXJnZXQ/LnJlc3VsdCkge1xuICAgICAgICB0aGlzLmltYWdlU291cmNlID0gZS50YXJnZXQucmVzdWx0IGFzIHN0cmluZztcbiAgICAgICAgdGhpcy5zaG93RWRpdG9yID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKHRoaXMuc2VsZWN0ZWRGaWxlKTtcbiAgfVxuXG4gIG9uU2F2ZUltYWdlKGRhdGE6IElTYXZlRmlsZSk6IHZvaWQge1xuICAgIGNvbnNvbGUubG9nKCdJbWFnZSBzYXZlZDonLCBkYXRhKTtcbiAgICB0aGlzLmVkaXRlZEltYWdlVXJsID0gZGF0YS51cmw7XG4gICAgdGhpcy5zaG93RWRpdG9yID0gZmFsc2U7XG4gIH1cblxuICBvbkNsb3NlRWRpdG9yKGRhdGE6IHsgaXNDbGlja0J1dHRvbkNsb3NlOiBib29sZWFuIH0pOiB2b2lkIHtcbiAgICBjb25zb2xlLmxvZygnRWRpdG9yIGNsb3NlZDonLCBkYXRhKTtcbiAgICB0aGlzLnNob3dFZGl0b3IgPSBmYWxzZTtcbiAgfVxuXG4gIGRvd25sb2FkSW1hZ2UoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZWRpdGVkSW1hZ2VVcmwpIHtcbiAgICAgIGNvbnN0IGxpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgICBsaW5rLmhyZWYgPSB0aGlzLmVkaXRlZEltYWdlVXJsO1xuICAgICAgbGluay5kb3dubG9hZCA9IHRoaXMuaW1hZ2VOYW1lIHx8ICdlZGl0ZWQtaW1hZ2UuanBnJztcbiAgICAgIGxpbmsuY2xpY2soKTtcbiAgICB9XG4gIH1cbn0gIiwiPGRpdiBjbGFzcz1cIm1heC13LTZ4bCBteC1hdXRvIHAtNSBmb250LXNhbnMgdGV4dC1ncmF5LTgwMFwiPlxuICA8aGVhZGVyIGNsYXNzPVwidGV4dC1jZW50ZXIgcHktMTAgYmctd2hpdGUgcm91bmRlZC1sZyBtYi04IHNoYWRvdy1zbVwiPlxuICAgIDxoMSBjbGFzcz1cInRleHQtNHhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTJcIj5EZW1vIFRyw6xuaCBDaOG7iW5oIFPhu61hIEjDrG5oIOG6om5oPC9oMT5cbiAgICA8cCBjbGFzcz1cInRleHQteGwgdGV4dC1ncmF5LTUwMFwiPlRoxrAgdmnhu4duIGNvbXBvbmVudCBjaG8gQW5ndWxhciDEkeG7gyBjaOG7iW5oIHPhu61hIGjDrG5oIOG6o25oPC9wPlxuICA8L2hlYWRlcj5cblxuICA8bWFpbj5cbiAgICA8c2VjdGlvbiBjbGFzcz1cImJnLXdoaXRlIHJvdW5kZWQtbGcgcC04IG1iLTggc2hhZG93LXNtXCI+XG4gICAgICA8aDIgY2xhc3M9XCJ0ZXh0LTJ4bCBmb250LWJvbGQgdGV4dC1ncmF5LTgwMCBtYi01IHBiLTMgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+R2nhu5tpIHRoaeG7h3U8L2gyPlxuICAgICAgPHA+XG4gICAgICAgIDxjb2RlIGNsYXNzPVwidGV4dC1zbSBiZy1ncmF5LTEwMCBweC0xLjUgcHktMC41IHJvdW5kZWRcIj4mIzY0O2xpYnMtdWkvY29tcG9uZW50cy1pbWFnZS1lZGl0b3I8L2NvZGU+IGzDoCBt4buZdFxuICAgICAgICBjb21wb25lbnQgQW5ndWxhciBt4bqhbmggbeG6vSBjaG8gcGjDqXAgbmfGsOG7nWkgZMO5bmcgdGjhu7FjIGhp4buHbiBjw6FjIHRoYW8gdMOhYyBjaOG7iW5oIHPhu61hIGjDrG5oIOG6o25oIG5oxrAgY+G6r3QsIHRoYXkgxJHhu5VpIGvDrWNoXG4gICAgICAgIHRoxrDhu5tjLCB4b2F5LCBs4bqtdCB2w6Agw6FwIGThu6VuZyB04bu3IGzhu4cgY+G7kSDEkeG7i25oLlxuICAgICAgPC9wPlxuICAgIDwvc2VjdGlvbj5cblxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBwLTggbWItOCBzaGFkb3ctc21cIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTUgcGItMyBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5Dw6BpIMSR4bq3dDwvaDI+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJtYi02XCI+XG4gICAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTNcIj5Zw6p1IGPhuqd1PC9oMz5cbiAgICAgICAgPHVsIGNsYXNzPVwibGlzdC1kaXNjIHBsLTUgc3BhY2UteS0yIHRleHQtZ3JheS02MDBcIj5cbiAgICAgICAgICA8bGk+PHNwYW4gY2xhc3M9XCJmb250LXNlbWlib2xkXCI+QW5ndWxhcjwvc3Bhbj46IDE4LjAuMCB0cuG7nyBsw6puPC9saT5cbiAgICAgICAgICA8bGk+PHNwYW4gY2xhc3M9XCJmb250LXNlbWlib2xkXCI+VGFpbHdpbmQgQ1NTPC9zcGFuPjogMy4zLjAgdHLhu58gbMOqbjwvbGk+XG4gICAgICAgIDwvdWw+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPHAgY2xhc3M9XCJtYi00XCI+xJDhu4MgY8OgaSDEkeG6t3QgdGjGsCB2aeG7h24sIHPhu60gZOG7pW5nIG5wbSBob+G6t2MgeWFybjo8L3A+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBiZy1ncmF5LTEwMCBwLTQgcm91bmRlZC1sZyBtYi02XCI+XG4gICAgICAgIDxwcmUgY2xhc3M9XCJmbGV4LTEgdGV4dC1zbSBvdmVyZmxvdy14LWF1dG9cIj48Y29kZT5ucG0gaW5zdGFsbCAmIzY0O2xpYnMtdWkvY29tcG9uZW50cy1pbWFnZS1lZGl0b3I8L2NvZGU+PC9wcmU+XG4gICAgICAgIDxidXR0b24gY2xhc3M9XCJtbC00IHB4LTMgcHktMSBiZy1ibHVlLTUwMCB0ZXh0LXdoaXRlIHJvdW5kZWQgaG92ZXI6YmctYmx1ZS02MDAgdHJhbnNpdGlvbi1jb2xvcnNcIlxuICAgICAgICAgIChjbGljayk9XCJjb3B5VG9DbGlwYm9hcmQoJ25wbSBpbnN0YWxsIEBsaWJzLXVpL2NvbXBvbmVudHMtaW1hZ2UtZWRpdG9yJylcIj5cbiAgICAgICAgICBTYW8gY2jDqXBcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPHAgY2xhc3M9XCJtYi00XCI+SG/hurdjIHbhu5tpIHlhcm46PC9wPlxuXG4gICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgYmctZ3JheS0xMDAgcC00IHJvdW5kZWQtbGcgbWItNlwiPlxuICAgICAgICA8cHJlIGNsYXNzPVwiZmxleC0xIHRleHQtc20gb3ZlcmZsb3cteC1hdXRvXCI+PGNvZGU+eWFybiBhZGQgJiM2NDtsaWJzLXVpL2NvbXBvbmVudHMtaW1hZ2UtZWRpdG9yPC9jb2RlPjwvcHJlPlxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwibWwtNCBweC0zIHB5LTEgYmctYmx1ZS01MDAgdGV4dC13aGl0ZSByb3VuZGVkIGhvdmVyOmJnLWJsdWUtNjAwIHRyYW5zaXRpb24tY29sb3JzXCJcbiAgICAgICAgICAoY2xpY2spPVwiY29weVRvQ2xpcGJvYXJkKCd5YXJuIGFkZCBAbGlicy11aS9jb21wb25lbnRzLWltYWdlLWVkaXRvcicpXCI+XG4gICAgICAgICAgU2FvIGNow6lwXG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgPC9zZWN0aW9uPlxuXG4gICAgPHNlY3Rpb24gY2xhc3M9XCJiZy13aGl0ZSByb3VuZGVkLWxnIHAtOCBtYi04IHNoYWRvdy1zbVwiPlxuICAgICAgPGgyIGNsYXNzPVwidGV4dC0yeGwgZm9udC1ib2xkIHRleHQtZ3JheS04MDAgbWItNSBwYi0zIGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPkRlbW8gdHLhu7FjIHRp4bq/cDwvaDI+XG4gICAgICA8ZGl2PlxuICAgICAgICA8cCBjbGFzcz1cIm1iLTRcIj5U4bqjaSBsw6puIGjDrG5oIOG6o25oIHbDoCBjaOG7iW5oIHPhu61hIG5nYXkgdHLDqm4gdHLDrG5oIGR1eeG7h3Q6PC9wPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LXdyYXAgaXRlbXMtY2VudGVyIGdhcC00IG1iLThcIj5cbiAgICAgICAgICA8aW5wdXQgdHlwZT1cImZpbGVcIlxuICAgICAgICAgICAgI2ltYWdlRmlsZUlucHV0XG4gICAgICAgICAgICBhY2NlcHQ9XCJpbWFnZS8qXCJcbiAgICAgICAgICAgIGNsYXNzPVwiYm9yZGVyIGJvcmRlci1ncmF5LTMwMCByb3VuZGVkIHB4LTMgcHktMlwiXG4gICAgICAgICAgICAoY2hhbmdlKT1cIm9uRmlsZVNlbGVjdGVkKCRldmVudClcIiAvPlxuICAgICAgICAgIDxsaWJzX3VpLWNvbXBvbmVudHMtYnV0dG9ucy1idXR0b24gbGFiZWw9XCJU4bqjaSBsw6puIHbDoCBjaOG7iW5oIHPhu61hXCJcbiAgICAgICAgICAgIChjbGljayk9XCJ1cGxvYWRBbmRFZGl0KClcIj5cbiAgICAgICAgICA8L2xpYnNfdWktY29tcG9uZW50cy1idXR0b25zLWJ1dHRvbj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgQGlmIChlZGl0ZWRJbWFnZVVybCkge1xuICAgICAgICAgIDxkaXYgY2xhc3M9XCJtdC04IHAtNiBiZy1ncmF5LTUwIHJvdW5kZWQtbGdcIj5cbiAgICAgICAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTRcIj5L4bq/dCBxdeG6ozwvaDM+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWF4LXcteGwgbXgtYXV0byBtYi00IGJvcmRlciBib3JkZXItZ3JheS0yMDAgcm91bmRlZC1sZyBvdmVyZmxvdy1oaWRkZW4gc2hhZG93LW1kXCI+XG4gICAgICAgICAgICAgIDxpbWcgW3NyY109XCJlZGl0ZWRJbWFnZVVybFwiXG4gICAgICAgICAgICAgICAgYWx0PVwiSMOsbmgg4bqjbmggxJHDoyBjaOG7iW5oIHPhu61hXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cInctZnVsbCBoLWF1dG9cIiAvPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBqdXN0aWZ5LWNlbnRlclwiPlxuICAgICAgICAgICAgICA8bGlic191aS1jb21wb25lbnRzLWJ1dHRvbnMtYnV0dG9uIGxhYmVsPVwiVOG6o2kgeHXhu5FuZyBow6xuaCDhuqNuaFwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImRvd25sb2FkSW1hZ2UoKVwiPlxuICAgICAgICAgICAgICA8L2xpYnNfdWktY29tcG9uZW50cy1idXR0b25zLWJ1dHRvbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICA8L3NlY3Rpb24+XG5cbiAgICBAaWYgKHNob3dFZGl0b3IpIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJmaXhlZCBpbnNldC0wIHotNTBcIj5cbiAgICAgICAgPGxpYnNfdWktY29tcG9uZW50cy1pbWFnZV9lZGl0b3IgWyhpbWdTcmMpXT1cImltYWdlU291cmNlXCJcbiAgICAgICAgICBbbmFtZUZpbGVdPVwiaW1hZ2VOYW1lIHx8ICdkZW1vLWltYWdlLmpwZydcIlxuICAgICAgICAgIFttb2RlU2hvd0J1dHRvbl09XCInc2F2ZS1maWxlJ1wiXG4gICAgICAgICAgW2hhc1pvb21dPVwidHJ1ZVwiXG4gICAgICAgICAgKG91dFNhdmVGaWxlKT1cIm9uU2F2ZUltYWdlKCRldmVudClcIlxuICAgICAgICAgIChvdXRDbG9zZSk9XCJvbkNsb3NlRWRpdG9yKCRldmVudClcIiAvPlxuICAgICAgPC9kaXY+XG4gICAgfVxuXG4gICAgPHNlY3Rpb24gY2xhc3M9XCJiZy13aGl0ZSByb3VuZGVkLWxnIHAtOCBtYi04IHNoYWRvdy1zbVwiPlxuICAgICAgPGgyIGNsYXNzPVwidGV4dC0yeGwgZm9udC1ib2xkIHRleHQtZ3JheS04MDAgbWItNSBwYi0zIGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPkPDoWNoIHPhu60gZOG7pW5nPC9oMj5cblxuICAgICAgPGRpdiBjbGFzcz1cIm1iLThcIj5cbiAgICAgICAgPGgzIGNsYXNzPVwidGV4dC14bCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDAgbWItNFwiPkPDoWNoIDE6IFPhu60gZOG7pW5nIGZpbGUgSFRNTCByacOqbmcgYmnhu4d0PC9oMz5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiZ3JpZCBncmlkLWNvbHMtMSBtZDpncmlkLWNvbHMtMiBnYXAtNiBtYi00XCI+XG4gICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgIDxoNCBjbGFzcz1cImZvbnQtc2VtaWJvbGQgbWItMiB0ZXh0LWdyYXktNzAwXCI+SFRNTCAoZXhhbXBsZS5jb21wb25lbnQuaHRtbCk8L2g0PlxuICAgICAgICAgICAgPHByZSBjbGFzcz1cImJnLWdyYXktMTAwIHAtNCByb3VuZGVkLWxnIG92ZXJmbG93LXgtYXV0byB0ZXh0LXNtXCI+PGNvZGU+Jmx0O2xpYnNfdWktY29tcG9uZW50cy1pbWFnZV9lZGl0b3JcbiAgWyhpbWdTcmMpXT1cImltYWdlU291cmNlXCJcbiAgW25hbWVGaWxlXT1cIidpbWFnZS5qcGcnXCJcbiAgW21vZGVTaG93QnV0dG9uXT1cIidzYXZlLWZpbGUnXCJcbiAgKG91dFNhdmVGaWxlKT1cIm9uU2F2ZUZpbGUoJGV2ZW50KVwiXG4gIChvdXRDbG9zZSk9XCJvbkNsb3NlKCRldmVudClcIiZndDtcbiZsdDsvbGlic191aS1jb21wb25lbnRzLWltYWdlX2VkaXRvciZndDs8L2NvZGU+PC9wcmU+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgPGg0IGNsYXNzPVwiZm9udC1zZW1pYm9sZCBtYi0yIHRleHQtZ3JheS03MDBcIj5UeXBlU2NyaXB0IChleGFtcGxlLmNvbXBvbmVudC50cyk8L2g0PlxuICAgICAgICAgICAgPHByZSBjbGFzcz1cImJnLWdyYXktMTAwIHAtNCByb3VuZGVkLWxnIG92ZXJmbG93LXgtYXV0byB0ZXh0LXNtXCI+PGNvZGU+aW1wb3J0ICYjMTIzOyBDb21wb25lbnQgJiMxMjU7IGZyb20gJyYjNjQ7YW5ndWxhci9jb3JlJztcbmltcG9ydCAmIzEyMzsgTGlic1VpQ29tcG9uZW50c0ltYWdlRWRpdG9yQ29tcG9uZW50ICYjMTI1OyBmcm9tICcmIzY0O2xpYnMtdWkvY29tcG9uZW50cy1pbWFnZS1lZGl0b3InO1xuXG4mIzY0O0NvbXBvbmVudCgmIzEyMztcbiAgc2VsZWN0b3I6ICdhcHAtZXhhbXBsZScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnRdLFxuICB0ZW1wbGF0ZVVybDogJy4vZXhhbXBsZS5jb21wb25lbnQuaHRtbCdcbiYjMTI1OylcbmV4cG9ydCBjbGFzcyBFeGFtcGxlQ29tcG9uZW50ICYjMTIzO1xuICBpbWFnZVNvdXJjZSA9ICdodHRwczovL2V4YW1wbGUuY29tL3BhdGgvdG8vaW1hZ2UuanBnJztcblxuICBvblNhdmVGaWxlKGRhdGE6ICYjMTIzO2ZpbGU6IEJsb2IsIHVybDogc3RyaW5nLCBtb2RlOiBzdHJpbmcmIzEyNTspICYjMTIzO1xuICAgIGNvbnNvbGUubG9nKCdGaWxlIMSRw6MgxJHGsOG7o2MgbMawdTonLCBkYXRhKTtcbiAgJiMxMjU7XG5cbiAgb25DbG9zZShkYXRhOiAmIzEyMztpc0NsaWNrQnV0dG9uQ2xvc2U6IGJvb2xlYW4mIzEyNTspICYjMTIzO1xuICAgIGNvbnNvbGUubG9nKCfEkMOjIMSRw7NuZyB0csOsbmggY2jhu4luaCBz4butYSDhuqNuaCcpO1xuICAmIzEyNTtcbiYjMTI1OzwvY29kZT48L3ByZT5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGRpdiBjbGFzcz1cIm1iLThcIj5cbiAgICAgICAgPGgzIGNsYXNzPVwidGV4dC14bCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDAgbWItNFwiPkPDoWNoIDI6IFbhu5tpIHRyw6xuaCBjaOG7iW5oIHPhu61hIGPDsyB0aOG7gyDEkcOzbmcvbeG7nzwvaDM+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cImdyaWQgZ3JpZC1jb2xzLTEgbWQ6Z3JpZC1jb2xzLTIgZ2FwLTYgbWItNFwiPlxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8aDQgY2xhc3M9XCJmb250LXNlbWlib2xkIG1iLTIgdGV4dC1ncmF5LTcwMFwiPkhUTUwgKHRvZ2dsZS1lZGl0b3IuY29tcG9uZW50Lmh0bWwpPC9oND5cbiAgICAgICAgICAgIDxwcmUgY2xhc3M9XCJiZy1ncmF5LTEwMCBwLTQgcm91bmRlZC1sZyBvdmVyZmxvdy14LWF1dG8gdGV4dC1zbVwiPjxjb2RlPiZsdDtidXR0b24gKGNsaWNrKT1cIm9wZW5FZGl0b3IoKVwiIGNsYXNzPVwicHgtNCBweS0yIGJnLWJsdWUtNTAwIHRleHQtd2hpdGUgcm91bmRlZFwiJmd0O1xuICBN4bufIHRyw6xuaCBjaOG7iW5oIHPhu61hIOG6o25oXG4mbHQ7L2J1dHRvbiZndDtcblxuJiM2NDtpZiAoc2hvd0VkaXRvcikgJiMxMjM7XG4gICZsdDtsaWJzX3VpLWNvbXBvbmVudHMtaW1hZ2VfZWRpdG9yXG4gICAgWyhpbWdTcmMpXT1cImltYWdlU291cmNlXCJcbiAgICBbbmFtZUZpbGVdPVwiJ215LWltYWdlLmpwZydcIlxuICAgIChvdXRTYXZlRmlsZSk9XCJvblNhdmVGaWxlKCRldmVudClcIlxuICAgIChvdXRDbG9zZSk9XCJvbkNsb3NlRWRpdG9yKCRldmVudClcIiZndDtcbiAgJmx0Oy9saWJzX3VpLWNvbXBvbmVudHMtaW1hZ2VfZWRpdG9yJmd0O1xuJiMxMjU7XG5cbiYjNjQ7aWYgKGVkaXRlZEltYWdlVXJsKSAmIzEyMztcbiAgJmx0O2RpdiBjbGFzcz1cIm10LTRcIiZndDtcbiAgICAmbHQ7aDMgY2xhc3M9XCJ0ZXh0LWxnIGZvbnQtc2VtaWJvbGRcIiZndDtIw6xuaCDhuqNuaCDEkcOjIGNo4buJbmggc+G7rWE6Jmx0Oy9oMyZndDtcbiAgICAmbHQ7aW1nIFtzcmNdPVwiZWRpdGVkSW1hZ2VVcmxcIiBhbHQ9XCJIw6xuaCDhuqNuaCDEkcOjIGNo4buJbmggc+G7rWFcIiBjbGFzcz1cIm10LTIgbWF4LXctZnVsbCBoLWF1dG9cIiAvJmd0O1xuICAmbHQ7L2RpdiZndDtcbiYjMTI1OzwvY29kZT48L3ByZT5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8aDQgY2xhc3M9XCJmb250LXNlbWlib2xkIG1iLTIgdGV4dC1ncmF5LTcwMFwiPlR5cGVTY3JpcHQgKHRvZ2dsZS1lZGl0b3IuY29tcG9uZW50LnRzKTwvaDQ+XG4gICAgICAgICAgICA8cHJlIGNsYXNzPVwiYmctZ3JheS0xMDAgcC00IHJvdW5kZWQtbGcgb3ZlcmZsb3cteC1hdXRvIHRleHQtc21cIj48Y29kZT5pbXBvcnQgJiMxMjM7IENvbXBvbmVudCAmIzEyNTsgZnJvbSAnJiM2NDthbmd1bGFyL2NvcmUnO1xuaW1wb3J0ICYjMTIzOyBMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnQgJiMxMjU7IGZyb20gJyYjNjQ7bGlicy11aS9jb21wb25lbnRzLWltYWdlLWVkaXRvcic7XG5pbXBvcnQgJiMxMjM7IElTYXZlRmlsZSAmIzEyNTsgZnJvbSAnJiM2NDtsaWJzLXVpL2NvbXBvbmVudHMtaW1hZ2UtZWRpdG9yJztcblxuJiM2NDtDb21wb25lbnQoJiMxMjM7XG4gIHNlbGVjdG9yOiAnYXBwLXRvZ2dsZS1lZGl0b3InLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbTGlic1VpQ29tcG9uZW50c0ltYWdlRWRpdG9yQ29tcG9uZW50XSxcbiAgdGVtcGxhdGVVcmw6ICcuL3RvZ2dsZS1lZGl0b3IuY29tcG9uZW50Lmh0bWwnXG4mIzEyNTspXG5leHBvcnQgY2xhc3MgVG9nZ2xlRWRpdG9yQ29tcG9uZW50ICYjMTIzO1xuICBpbWFnZVNvdXJjZSA9ICdodHRwczovL2V4YW1wbGUuY29tL3BhdGgvdG8vaW1hZ2UuanBnJztcbiAgc2hvd0VkaXRvciA9IGZhbHNlO1xuICBlZGl0ZWRJbWFnZVVybCA9ICcnO1xuXG4gIG9wZW5FZGl0b3IoKSAmIzEyMztcbiAgICB0aGlzLnNob3dFZGl0b3IgPSB0cnVlO1xuICAmIzEyNTtcblxuICBvblNhdmVGaWxlKGRhdGE6IElTYXZlRmlsZSkgJiMxMjM7XG4gICAgdGhpcy5lZGl0ZWRJbWFnZVVybCA9IGRhdGEudXJsO1xuICAgIHRoaXMuc2hvd0VkaXRvciA9IGZhbHNlO1xuICAgIGNvbnNvbGUubG9nKCfEkMOjIGzGsHUgZmlsZTonLCBkYXRhLmZpbGUpO1xuICAmIzEyNTtcblxuICBvbkNsb3NlRWRpdG9yKGRhdGE6ICYjMTIzO2lzQ2xpY2tCdXR0b25DbG9zZTogYm9vbGVhbiYjMTI1OykgJiMxMjM7XG4gICAgdGhpcy5zaG93RWRpdG9yID0gZmFsc2U7XG4gICYjMTI1O1xuJiMxMjU7PC9jb2RlPjwvcHJlPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2IGNsYXNzPVwibWItOFwiPlxuICAgICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi00XCI+Q8OhY2ggMzogVuG7m2kgdOG7tyBs4buHIGtodW5nIGjDrG5oIGPhu5EgxJHhu4tuaDwvaDM+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cImdyaWQgZ3JpZC1jb2xzLTEgbWQ6Z3JpZC1jb2xzLTIgZ2FwLTYgbWItNFwiPlxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8aDQgY2xhc3M9XCJmb250LXNlbWlib2xkIG1iLTIgdGV4dC1ncmF5LTcwMFwiPkhUTUwgKGZpeGVkLXJhdGlvLmNvbXBvbmVudC5odG1sKTwvaDQ+XG4gICAgICAgICAgICA8cHJlIGNsYXNzPVwiYmctZ3JheS0xMDAgcC00IHJvdW5kZWQtbGcgb3ZlcmZsb3cteC1hdXRvIHRleHQtc21cIj48Y29kZT4mbHQ7bGlic191aS1jb21wb25lbnRzLWltYWdlX2VkaXRvclxuICBbKGltZ1NyYyldPVwiaW1hZ2VTb3VyY2VcIlxuICBbYXNwZWN0UmF0aW9dPVwiYXNwZWN0UmF0aW9cIlxuICBbcmVxdWlyZWRDcm9wRm9sbG93UmF0aW9dPVwidHJ1ZVwiXG4gIChvdXRTYXZlRmlsZSk9XCJvblNhdmVGaWxlKCRldmVudClcIiZndDtcbiZsdDsvbGlic191aS1jb21wb25lbnRzLWltYWdlX2VkaXRvciZndDs8L2NvZGU+PC9wcmU+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgPGg0IGNsYXNzPVwiZm9udC1zZW1pYm9sZCBtYi0yIHRleHQtZ3JheS03MDBcIj5UeXBlU2NyaXB0IChmaXhlZC1yYXRpby5jb21wb25lbnQudHMpPC9oND5cbiAgICAgICAgICAgIDxwcmUgY2xhc3M9XCJiZy1ncmF5LTEwMCBwLTQgcm91bmRlZC1sZyBvdmVyZmxvdy14LWF1dG8gdGV4dC1zbVwiPjxjb2RlPmltcG9ydCAmIzEyMzsgQ29tcG9uZW50ICYjMTI1OyBmcm9tICcmIzY0O2FuZ3VsYXIvY29yZSc7XG5pbXBvcnQgJiMxMjM7IExpYnNVaUNvbXBvbmVudHNJbWFnZUVkaXRvckNvbXBvbmVudCAmIzEyNTsgZnJvbSAnJiM2NDtsaWJzLXVpL2NvbXBvbmVudHMtaW1hZ2UtZWRpdG9yJztcbmltcG9ydCAmIzEyMzsgSUFzcGVjdFJhdGlvICYjMTI1OyBmcm9tICcmIzY0O2xpYnMtdWkvaW50ZXJmYWNlcy10eXBlcyc7XG5cbiYjNjQ7Q29tcG9uZW50KCYjMTIzO1xuICBzZWxlY3RvcjogJ2FwcC1maXhlZC1yYXRpbycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnRdLFxuICB0ZW1wbGF0ZVVybDogJy4vZml4ZWQtcmF0aW8uY29tcG9uZW50Lmh0bWwnXG4mIzEyNTspXG5leHBvcnQgY2xhc3MgRml4ZWRSYXRpb0NvbXBvbmVudCAmIzEyMztcbiAgaW1hZ2VTb3VyY2UgPSAnaHR0cHM6Ly9leGFtcGxlLmNvbS9wYXRoL3RvL2ltYWdlLmpwZyc7XG4gIGFzcGVjdFJhdGlvOiBJQXNwZWN0UmF0aW8gPSAmIzEyMztcbiAgICBrZXk6ICcxOjEnLFxuICAgIHZhbHVlOiAxXG4gICYjMTI1OztcblxuICBvblNhdmVGaWxlKGRhdGE6IGFueSkgJiMxMjM7XG4gICAgY29uc29sZS5sb2coJ8SQw6MgbMawdSBow6xuaCDhuqNuaCB24bubaSB04bu3IGzhu4cgMToxJyk7XG4gICYjMTI1O1xuJiMxMjU7PC9jb2RlPjwvcHJlPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvc2VjdGlvbj5cblxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBwLTggbWItOCBzaGFkb3ctc21cIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTUgcGItMyBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5Uw6BpIGxp4buHdSBBUEk8L2gyPlxuXG4gICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi00XCI+SW5wdXRzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJvdmVyZmxvdy14LWF1dG8gbWItOFwiPlxuICAgICAgICA8dGFibGUgY2xhc3M9XCJtaW4tdy1mdWxsIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDBcIj5cbiAgICAgICAgICA8dGhlYWQ+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0aCBjbGFzcz1cInB5LTMgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDAgYmctZ3JheS0xMDAgdGV4dC1sZWZ0IGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMFwiPlTDqm48L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwIGJnLWdyYXktMTAwIHRleHQtbGVmdCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDBcIj5LaeG7g3UgZOG7r1xuICAgICAgICAgICAgICAgIGxp4buHdVxuICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwIGJnLWdyYXktMTAwIHRleHQtbGVmdCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDBcIj5N4bq3YyDEkeG7i25oXG4gICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICAgIDx0aCBjbGFzcz1cInB5LTMgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDAgYmctZ3JheS0xMDAgdGV4dC1sZWZ0IGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMFwiPk3DtCB04bqjXG4gICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICA8L3RyPlxuICAgICAgICAgIDwvdGhlYWQ+XG4gICAgICAgICAgPHRib2R5PlxuICAgICAgICAgICAgQGZvciAoaW5wdXQgb2YgaW5wdXRzRG9jOyB0cmFjayBpbnB1dC5uYW1lKSB7XG4gICAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIGJnLWdyYXktMTAwIHB4LTEuNSBweS0wLjUgcm91bmRlZFwiPnt7IGlucHV0Lm5hbWUgfX08L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIGJnLWdyYXktMTAwIHB4LTEuNSBweS0wLjUgcm91bmRlZFwiPnt7IGlucHV0LnR5cGUgfX08L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+e3sgaW5wdXQuZGVmYXVsdCB9fTwvdGQ+XG4gICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPnt7IGlucHV0LmRlc2NyaXB0aW9uIH19PC90ZD5cbiAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L3Rib2R5PlxuICAgICAgICA8L3RhYmxlPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTRcIj5PdXRwdXRzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJvdmVyZmxvdy14LWF1dG8gbWItOFwiPlxuICAgICAgICA8dGFibGUgY2xhc3M9XCJtaW4tdy1mdWxsIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDBcIj5cbiAgICAgICAgICA8dGhlYWQ+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0aCBjbGFzcz1cInB5LTMgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDAgYmctZ3JheS0xMDAgdGV4dC1sZWZ0IGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMFwiPlTDqm48L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwIGJnLWdyYXktMTAwIHRleHQtbGVmdCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDBcIj5LaeG7g3UgZOG7r1xuICAgICAgICAgICAgICAgIGxp4buHdVxuICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwIGJnLWdyYXktMTAwIHRleHQtbGVmdCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDBcIj5Nw7QgdOG6o1xuICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L3RoZWFkPlxuICAgICAgICAgIDx0Ym9keT5cbiAgICAgICAgICAgIEBmb3IgKG91dHB1dCBvZiBvdXRwdXRzRG9jOyB0cmFjayBvdXRwdXQubmFtZSkge1xuICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPjxjb2RlXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1zbSBiZy1ncmF5LTEwMCBweC0xLjUgcHktMC41IHJvdW5kZWRcIj57eyBvdXRwdXQubmFtZSB9fTwvY29kZT48L3RkPlxuICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtc20gYmctZ3JheS0xMDAgcHgtMS41IHB5LTAuNSByb3VuZGVkXCI+e3sgb3V0cHV0LnR5cGUgfX08L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+e3sgb3V0cHV0LmRlc2NyaXB0aW9uIH19PC90ZD5cbiAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L3Rib2R5PlxuICAgICAgICA8L3RhYmxlPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTRcIj5JbnRlcmZhY2VzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJzcGFjZS15LTZcIj5cbiAgICAgICAgQGZvciAoaW50ZXJmYWNlSXRlbSBvZiBpbnRlcmZhY2VzRG9jOyB0cmFjayBpbnRlcmZhY2VJdGVtLm5hbWUpIHtcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiYmctZ3JheS01MCBwLTYgcm91bmRlZC1sZ1wiPlxuICAgICAgICAgICAgPGg0IGNsYXNzPVwidGV4dC1sZyBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDAgbWItM1wiPnt7IGludGVyZmFjZUl0ZW0ubmFtZSB9fTwvaDQ+XG4gICAgICAgICAgICA8cHJlXG4gICAgICAgICAgICAgIGNsYXNzPVwiYmctZ3JheS0xMDAgcC00IHJvdW5kZWQtbGcgb3ZlcmZsb3cteC1hdXRvIHRleHQtc20gbWItM1wiPjxjb2RlPnt7IGludGVyZmFjZUl0ZW0uY29kZSB9fTwvY29kZT48L3ByZT5cbiAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1ncmF5LTYwMFwiPnt7IGludGVyZmFjZUl0ZW0uZGVzY3JpcHRpb24gfX08L3A+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuICAgIDwvc2VjdGlvbj5cblxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBwLTggbWItOCBzaGFkb3ctc21cIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTUgcGItMyBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5Uw61uaCBuxINuZzwvaDI+XG4gICAgICA8dWwgY2xhc3M9XCJzcGFjZS15LTZcIj5cbiAgICAgICAgQGZvciAoZmVhdHVyZSBvZiBmZWF0dXJlczsgdHJhY2sgZmVhdHVyZS5pZCkge1xuICAgICAgICAgIDxsaSBjbGFzcz1cImZsZXggaXRlbXMtc3RhcnRcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC0yeGwgdGV4dC1ibHVlLTUwMCBtci00XCI+e3sgZmVhdHVyZS5pY29uIH19PC9zcGFuPlxuICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgPGgzIGNsYXNzPVwidGV4dC1sZyBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDAgbWItMVwiPnt7IGZlYXR1cmUudGl0bGUgfX08L2gzPlxuICAgICAgICAgICAgICA8cCBjbGFzcz1cInRleHQtZ3JheS02MDBcIj57eyBmZWF0dXJlLmRlc2NyaXB0aW9uIH19PC9wPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9saT5cbiAgICAgICAgfVxuICAgICAgPC91bD5cbiAgICA8L3NlY3Rpb24+XG4gIDwvbWFpbj5cbjwvZGl2PlxuIl19
154
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2UtZWRpdG9yLWRlbW8uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vbGlicy11aS9jb21wb25lbnRzL2ltYWdlLWVkaXRvci9zcmMvZGVtby9pbWFnZS1lZGl0b3ItZGVtby5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvaW1hZ2UtZWRpdG9yL3NyYy9kZW1vL2ltYWdlLWVkaXRvci1kZW1vLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNqRSxPQUFPLEVBQUUsc0NBQXNDLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUM1RixPQUFPLEVBQUUsb0NBQW9DLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQzs7QUFhakYsTUFBTSxPQUFPLHdDQUF3QztJQUN0QixjQUFjLENBQWdDO0lBRTNFLFdBQVcsR0FBRyxFQUFFLENBQUM7SUFDakIsVUFBVSxHQUFHLEtBQUssQ0FBQztJQUNuQixjQUFjLEdBQUcsRUFBRSxDQUFDO0lBQ3BCLFlBQVksR0FBZ0IsSUFBSSxDQUFDO0lBQ2pDLFNBQVMsR0FBRyxFQUFFLENBQUM7SUFFZiwyQ0FBMkM7SUFDM0MsU0FBUyxHQUFHO1FBQ1YsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsa0RBQWtELEVBQUU7UUFDeEgsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsc0JBQXNCLEVBQUU7UUFDeEYsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxXQUFX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c0JBQTFDLFNBQVM7dUJBQUMsZ0JBQWdCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IExpYnNVaUNvbXBvbmVudHNCdXR0b25zQnV0dG9uQ29tcG9uZW50IH0gZnJvbSAnQGxpYnMtdWkvY29tcG9uZW50cy1idXR0b25zLWJ1dHRvbic7XG5pbXBvcnQgeyBMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnQgfSBmcm9tICcuLi9pbWFnZS1lZGl0b3IuY29tcG9uZW50JztcbmltcG9ydCB7IElTYXZlRmlsZSB9IGZyb20gJy4uL2ludGVyZmFjZXMvaW1hZ2UtZWRpdG9yLmludGVyZmFjZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2xpYi1pbWFnZS1lZGl0b3ItZGVtbycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBMaWJzVWlDb21wb25lbnRzQnV0dG9uc0J1dHRvbkNvbXBvbmVudCxcbiAgICBMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnRcbiAgXSxcbiAgdGVtcGxhdGVVcmw6ICcuL2ltYWdlLWVkaXRvci1kZW1vLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL2ltYWdlLWVkaXRvci1kZW1vLmNvbXBvbmVudC5zY3NzJ1xufSlcbmV4cG9ydCBjbGFzcyBMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JEZW1vQ29tcG9uZW50IHtcbiAgQFZpZXdDaGlsZCgnaW1hZ2VGaWxlSW5wdXQnKSBpbWFnZUZpbGVJbnB1dCE6IEVsZW1lbnRSZWY8SFRNTElucHV0RWxlbWVudD47XG5cbiAgaW1hZ2VTb3VyY2UgPSAnJztcbiAgc2hvd0VkaXRvciA9IGZhbHNlO1xuICBlZGl0ZWRJbWFnZVVybCA9ICcnO1xuICBzZWxlY3RlZEZpbGU6IEZpbGUgfCBudWxsID0gbnVsbDtcbiAgaW1hZ2VOYW1lID0gJyc7XG5cbiAgLy8gRG9jdW1lbnRhdGlvbiBkYXRhIGFzIHJlZ3VsYXIgcHJvcGVydGllc1xuICBpbnB1dHNEb2MgPSBbXG4gICAgeyBuYW1lOiAnaW1nU3JjJywgdHlwZTogJ3N0cmluZycsIGRlZmF1bHQ6ICdC4bqvdCBideG7mWMnLCBkZXNjcmlwdGlvbjogJ8SQxrDhu51uZyBk4bqrbiBob+G6t2MgYmFzZTY0IGPhu6dhIGjDrG5oIOG6o25oIGPhuqduIGNo4buJbmggc+G7rWEnIH0sXG4gICAgeyBuYW1lOiAnb3JpZ2luVXJsJywgdHlwZTogJ3N0cmluZycsIGRlZmF1bHQ6ICctJywgZGVzY3JpcHRpb246ICdVUkwgZ+G7kWMgY+G7p2EgaMOsbmgg4bqjbmgnIH0sXG4gICAgeyBuYW1lOiAnbmFtZUZpbGUnLCB0eXBlOiAnc3RyaW5nJywgZGVmYXVsdDogJy0nLCBkZXNjcmlwdGlvbjogJ1TDqm4gZmlsZSBraGkgbMawdScgfSxcbiAgICB7IG5hbWU6ICdtb2RlU2hvd0J1dHRvbicsIHR5cGU6ICdcXCdzYXZlLWZpbGVcXCcgfCBcXCdzYXZlLWFwaVxcJycsIGRlZmF1bHQ6ICdcXCdzYXZlLWZpbGVcXCcnLCBkZXNjcmlwdGlvbjogJ0No4bq/IMSR4buZIG7DunQgbMawdScgfSxcbiAgICB7IG5hbWU6ICdtaW1ldHlwZScsIHR5cGU6ICdzdHJpbmcnLCBkZWZhdWx0OiAnLScsIGRlc2NyaXB0aW9uOiAnxJDhu4tuaCBk4bqhbmcgY+G7p2EgaMOsbmgg4bqjbmgnIH0sXG4gICAgeyBuYW1lOiAnekluZGV4JywgdHlwZTogJ251bWJlcicsIGRlZmF1bHQ6ICcxMjAwJywgZGVzY3JpcHRpb246ICd6LWluZGV4IGPhu6dhIGNvbXBvbmVudCcgfSxcbiAgICB7IG5hbWU6ICdoYXNab29tJywgdHlwZTogJ2Jvb2xlYW4nLCBkZWZhdWx0OiAnZmFsc2UnLCBkZXNjcmlwdGlvbjogJ0NobyBwaMOpcCBwaMOzbmcgdG8vdGh1IG5o4buPIGjDrG5oIOG6o25oJyB9LFxuICAgIHsgbmFtZTogJ2FzcGVjdFJhdGlvJywgdHlwZTogJ0lBc3BlY3RSYXRpbycsIGRlZmF1bHQ6ICctJywgZGVzY3JpcHRpb246ICdU4bu3IGzhu4cga2h1bmcgaMOsbmggbeG6t2MgxJHhu4tuaCcgfSxcbiAgICB7IG5hbWU6ICdyZXF1aXJlZENyb3BGb2xsb3dSYXRpbycsIHR5cGU6ICdib29sZWFuJywgZGVmYXVsdDogJ2ZhbHNlJywgZGVzY3JpcHRpb246ICdC4bqvdCBideG7mWMgY+G6r3QgdGhlbyB04bu3IGzhu4cgxJHDoyBjaOG7jW4nIH1cbiAgXTtcblxuICBvdXRwdXRzRG9jID0gW1xuICAgIHsgbmFtZTogJ291dENsb3NlJywgdHlwZTogJ3tpc0NsaWNrQnV0dG9uQ2xvc2U6IGJvb2xlYW59JywgZGVzY3JpcHRpb246ICdT4buxIGtp4buHbiBraGkgxJHDs25nIHRyw6xuaCBjaOG7iW5oIHPhu61hJyB9LFxuICAgIHsgbmFtZTogJ291dFNhdmVGaWxlJywgdHlwZTogJ0lTYXZlRmlsZScsIGRlc2NyaXB0aW9uOiAnU+G7sSBraeG7h24ga2hpIGzGsHUgZmlsZScgfSxcbiAgICB7IG5hbWU6ICdvdXRGdW5jdGlvbnNDb250cm9sJywgdHlwZTogJ0lJbWFnZUVkaXRvckZ1bmN0aW9uQ29udHJvbEV2ZW50JywgZGVzY3JpcHRpb246ICdT4buxIGtp4buHbiDEkeG7gyBraeG7g20gc2/DoXQgY8OhYyBjaOG7qWMgbsSDbmcnIH1cbiAgXTtcblxuICBpbnRlcmZhY2VzRG9jID0gW1xuICAgIHtcbiAgICAgIG5hbWU6ICdJU2F2ZUZpbGUnLFxuICAgICAgY29kZTogJ2V4cG9ydCBpbnRlcmZhY2UgSVNhdmVGaWxlIHtcXG4gIGZpbGU6IEJsb2I7XFxuICB1cmw6IHN0cmluZztcXG4gIG1vZGU6IFxcJ3NhdmUtZmlsZVxcJyB8IFxcJ3NhdmUtYXBpXFwnIHwgXFwnc2F2ZS1hcGktYXMtbmV3LWZpbGVcXCc7XFxufScsXG4gICAgICBkZXNjcmlwdGlvbjogJ0ludGVyZmFjZSDEkeG7i25oIG5naMSpYSBk4buvIGxp4buHdSBraGkgbMawdSBmaWxlLidcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdJSW1hZ2VFZGl0b3JGdW5jdGlvbkNvbnRyb2xFdmVudCcsXG4gICAgICBjb2RlOiAnZXhwb3J0IGludGVyZmFjZSBJSW1hZ2VFZGl0b3JGdW5jdGlvbkNvbnRyb2xFdmVudCB7XFxuICBjcm9wSW1hZ2U6ICgpID0+IFByb21pc2U8c3RyaW5nPjtcXG4gIHNldExvYWRpbmdTdGF0ZTogKGxvYWRpbmc6IGJvb2xlYW4pID0+IHZvaWQ7XFxufScsXG4gICAgICBkZXNjcmlwdGlvbjogJ0ludGVyZmFjZSDEkeG7i25oIG5naMSpYSBjw6FjIGjDoG0gxJFp4buBdSBraGnhu4NuIGPDsyB0aOG7gyDEkcaw4bujYyBn4buNaSB04burIGLDqm4gbmdvw6BpIGNvbXBvbmVudC4nXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiAnSUFzcGVjdFJhdGlvJyxcbiAgICAgIGNvZGU6ICdleHBvcnQgaW50ZXJmYWNlIElBc3BlY3RSYXRpbyB7XFxuICBrZXk6IHN0cmluZztcXG4gIHZhbHVlOiBudW1iZXI7XFxufScsXG4gICAgICBkZXNjcmlwdGlvbjogJ0ludGVyZmFjZSDEkeG7i25oIG5naMSpYSB04bu3IGzhu4cga2h1bmcgaMOsbmguJ1xuICAgIH1cbiAgXTtcblxuICBmZWF0dXJlcyA9IFtcbiAgICB7XG4gICAgICBpZDogMSxcbiAgICAgIGljb246ICfinILvuI8nLFxuICAgICAgdGl0bGU6ICdD4bqvdCDhuqNuaCcsXG4gICAgICBkZXNjcmlwdGlvbjogJ0Phuq90IGjDrG5oIOG6o25oIHRoZW8ga2h1IHbhu7FjIHTDuXkgY2jhu4luaCBob+G6t2MgZOG7sWEgdHLDqm4gdOG7tyBs4buHIMSR4buLbmggdHLGsOG7m2MgKDE6MSwgNDozLCAxNjo5LCB2LnYuKS4nXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogMixcbiAgICAgIGljb246ICfwn5SEJyxcbiAgICAgIHRpdGxlOiAnWG9heSB2w6AgbOG6rXQnLFxuICAgICAgZGVzY3JpcHRpb246ICdYb2F5IGjDrG5oIOG6o25oIHRoZW8gY8OhYyBnw7NjIGtow6FjIG5oYXUgaG/hurdjIGzhuq10IHRoZW8gY2hp4buBdSBuZ2FuZy9k4buNYy4nXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogMyxcbiAgICAgIGljb246ICfwn5OPJyxcbiAgICAgIHRpdGxlOiAnVGhheSDEkeG7lWkga8OtY2ggdGjGsOG7m2MnLFxuICAgICAgZGVzY3JpcHRpb246ICdUaGF5IMSR4buVaSBrw61jaCB0aMaw4bubYyBow6xuaCDhuqNuaCB0aGVvIHThu7cgbOG7hyBwaOG6p24gdHLEg20gaG/hurdjIGvDrWNoIHRoxrDhu5tjIGPhu6UgdGjhu4MuJ1xuICAgIH0sXG4gICAge1xuICAgICAgaWQ6IDQsXG4gICAgICBpY29uOiAn8J+SvicsXG4gICAgICB0aXRsZTogJ05oaeG7gXUgY2jhur8gxJHhu5kgbMawdScsXG4gICAgICBkZXNjcmlwdGlvbjogJ0jhu5cgdHLhu6Mgbmhp4buBdSBjaOG6vyDEkeG7mSBsxrB1OiB04bqjaSB4deG7kW5nIHRy4buxYyB0aeG6v3AgaG/hurdjIGfhu61pIMSR4bq/biBBUEkuJ1xuICAgIH0sXG4gICAge1xuICAgICAgaWQ6IDUsXG4gICAgICBpY29uOiAn8J+UjScsXG4gICAgICB0aXRsZTogJ1Bow7NuZyB0by90aHUgbmjhu48nLFxuICAgICAgZGVzY3JpcHRpb246ICdUw61uaCBuxINuZyBwaMOzbmcgdG8vdGh1IG5o4buPIMSR4buDIHhlbSBjaGkgdGnhur90IGjDrG5oIOG6o25oIGtoaSBj4bqnbiB0aGnhur90LidcbiAgICB9XG4gIF07XG5cbiAgY29kZUV4YW1wbGVzID0gW1xuICAgIHtcbiAgICAgIGlkOiAxLFxuICAgICAgdGl0bGU6ICdT4butIGThu6VuZyBjxqEgYuG6o24nLFxuICAgICAgY29kZTogYGltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xcbmltcG9ydCB7IExpYnNVaUNvbXBvbmVudHNJbWFnZUVkaXRvckNvbXBvbmVudCB9IGZyb20gJ0BsaWJzLXVpL2NvbXBvbmVudHMtaW1hZ2UtZWRpdG9yJztcXG5cXG5AQ29tcG9uZW50KHtcXG4gIHNlbGVjdG9yOiAnYXBwLWV4YW1wbGUnLFxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcXG4gIGltcG9ydHM6IFtMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnRdLFxcbiAgdGVtcGxhdGU6IFxcYFxcbiAgICA8bGlic191aS1jb21wb25lbnRzLWltYWdlX2VkaXRvclxcbiAgICAgIFsoaW1nU3JjKV09XCJpbWFnZVNvdXJjZVwiXFxuICAgICAgW21vZGVTaG93QnV0dG9uXT1cIidzYXZlLWZpbGUnXCJcXG4gICAgICBbbmFtZUZpbGVdPVwiJ2ltYWdlLmpwZydcIlxcbiAgICAgIChvdXRTYXZlRmlsZSk9XCJvblNhdmVGaWxlKCRldmVudClcIlxcbiAgICAgIChvdXRDbG9zZSk9XCJvbkNsb3NlKCRldmVudClcIj5cXG4gICAgPC9saWJzX3VpLWNvbXBvbmVudHMtaW1hZ2VfZWRpdG9yPlxcbiAgXFxgXFxufSlcXG5leHBvcnQgY2xhc3MgRXhhbXBsZUNvbXBvbmVudCB7XFxuICBpbWFnZVNvdXJjZSA9ICdodHRwczovL2V4YW1wbGUuY29tL3BhdGgvdG8vaW1hZ2UuanBnJztcXG5cXG4gIG9uU2F2ZUZpbGUoZGF0YToge2ZpbGU6IEJsb2IsIHVybDogc3RyaW5nLCBtb2RlOiBzdHJpbmd9KSB7XFxuICAgIGNvbnNvbGUubG9nKCdGaWxlIMSRw6MgxJHGsOG7o2MgbMawdTonLCBkYXRhKTtcXG4gIH1cXG5cXG4gIG9uQ2xvc2UoZGF0YToge2lzQ2xpY2tCdXR0b25DbG9zZTogYm9vbGVhbn0pIHtcXG4gICAgY29uc29sZS5sb2coJ8SQw6MgxJHDs25nIHRyw6xuaCBjaOG7iW5oIHPhu61hIOG6o25oJyk7XFxuICB9XFxufWBcbiAgICB9LFxuICAgIHtcbiAgICAgIGlkOiAyLFxuICAgICAgdGl0bGU6ICdT4butIGThu6VuZyB24bubaSB04bu3IGzhu4cgY+G7kSDEkeG7i25oJyxcbiAgICAgIGNvZGU6IGBpbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcXG5pbXBvcnQgeyBMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnQgfSBmcm9tICdAbGlicy11aS9jb21wb25lbnRzLWltYWdlLWVkaXRvcic7XFxuaW1wb3J0IHsgSUFzcGVjdFJhdGlvIH0gZnJvbSAnQGxpYnMtdWkvaW50ZXJmYWNlcy10eXBlcyc7XFxuXFxuQENvbXBvbmVudCh7XFxuICBzZWxlY3RvcjogJ2FwcC1leGFtcGxlJyxcXG4gIHN0YW5kYWxvbmU6IHRydWUsXFxuICBpbXBvcnRzOiBbTGlic1VpQ29tcG9uZW50c0ltYWdlRWRpdG9yQ29tcG9uZW50XSxcXG4gIHRlbXBsYXRlOiBcXGBcXG4gICAgPGxpYnNfdWktY29tcG9uZW50cy1pbWFnZV9lZGl0b3JcXG4gICAgICBbKGltZ1NyYyldPVwiaW1hZ2VTb3VyY2VcIlxcbiAgICAgIFthc3BlY3RSYXRpb109XCJhc3BlY3RSYXRpb1wiXFxuICAgICAgW3JlcXVpcmVkQ3JvcEZvbGxvd1JhdGlvXT1cInRydWVcIlxcbiAgICAgIChvdXRTYXZlRmlsZSk9XCJvblNhdmVGaWxlKCRldmVudClcIj5cXG4gICAgPC9saWJzX3VpLWNvbXBvbmVudHMtaW1hZ2VfZWRpdG9yPlxcbiAgXFxgXFxufSlcXG5leHBvcnQgY2xhc3MgRXhhbXBsZUNvbXBvbmVudCB7XFxuICBpbWFnZVNvdXJjZSA9ICdodHRwczovL2V4YW1wbGUuY29tL3BhdGgvdG8vaW1hZ2UuanBnJztcXG4gIGFzcGVjdFJhdGlvOiBJQXNwZWN0UmF0aW8gPSB7XFxuICAgIGtleTogJzE6MScsXFxuICAgIHZhbHVlOiAxXFxuICB9O1xcblxcbiAgb25TYXZlRmlsZShkYXRhOiBhbnkpIHtcXG4gICAgY29uc29sZS5sb2coJ8SQw6MgbMawdSBow6xuaCDhuqNuaCB24bubaSB04bu3IGzhu4cgMToxJyk7XFxuICB9XFxufWBcbiAgICB9LFxuICAgIHtcbiAgICAgIGlkOiAzLFxuICAgICAgdGl0bGU6ICdT4butIGThu6VuZyB24bubaSBwaOG6p24gxJFp4buBdSBraGnhu4NuIGLDqm4gbmdvw6BpJyxcbiAgICAgIGNvZGU6IGBpbXBvcnQgeyBDb21wb25lbnQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xcbmltcG9ydCB7IExpYnNVaUNvbXBvbmVudHNJbWFnZUVkaXRvckNvbXBvbmVudCwgSUltYWdlRWRpdG9yRnVuY3Rpb25Db250cm9sRXZlbnQgfSBmcm9tICdAbGlicy11aS9jb21wb25lbnRzLWltYWdlLWVkaXRvcic7XFxuXFxuQENvbXBvbmVudCh7XFxuICBzZWxlY3RvcjogJ2FwcC1leGFtcGxlJyxcXG4gIHN0YW5kYWxvbmU6IHRydWUsXFxuICBpbXBvcnRzOiBbTGlic1VpQ29tcG9uZW50c0ltYWdlRWRpdG9yQ29tcG9uZW50XSxcXG4gIHRlbXBsYXRlOiBcXGBcXG4gICAgPGJ1dHRvbiAoY2xpY2spPVwiY3JvcEFuZFNhdmUoKVwiPkPhuq90IHbDoCBsxrB1IG5nYXk8L2J1dHRvbj5cXG4gICAgPGxpYnNfdWktY29tcG9uZW50cy1pbWFnZV9lZGl0b3JcXG4gICAgICBbKGltZ1NyYyldPVwiaW1hZ2VTb3VyY2VcIlxcbiAgICAgIChvdXRGdW5jdGlvbnNDb250cm9sKT1cIm9uRnVuY3Rpb25zQ29udHJvbCgkZXZlbnQpXCI+XFxuICAgIDwvbGlic191aS1jb21wb25lbnRzLWltYWdlX2VkaXRvcj5cXG4gIFxcYFxcbn0pXFxuZXhwb3J0IGNsYXNzIEV4YW1wbGVDb21wb25lbnQge1xcbiAgaW1hZ2VTb3VyY2UgPSAnaHR0cHM6Ly9leGFtcGxlLmNvbS9wYXRoL3RvL2ltYWdlLmpwZyc7XFxuICBlZGl0b3JGdW5jdGlvbnMhOiBJSW1hZ2VFZGl0b3JGdW5jdGlvbkNvbnRyb2xFdmVudDtcXG5cXG4gIG9uRnVuY3Rpb25zQ29udHJvbChldmVudDogSUltYWdlRWRpdG9yRnVuY3Rpb25Db250cm9sRXZlbnQpIHtcXG4gICAgdGhpcy5lZGl0b3JGdW5jdGlvbnMgPSBldmVudDtcXG4gIH1cXG5cXG4gIGFzeW5jIGNyb3BBbmRTYXZlKCkge1xcbiAgICBpZiAodGhpcy5lZGl0b3JGdW5jdGlvbnMpIHtcXG4gICAgICB0aGlzLmVkaXRvckZ1bmN0aW9ucy5zZXRMb2FkaW5nU3RhdGUodHJ1ZSk7XFxuICAgICAgdHJ5IHtcXG4gICAgICAgIGNvbnN0IGRhdGFVcmwgPSBhd2FpdCB0aGlzLmVkaXRvckZ1bmN0aW9ucy5jcm9wSW1hZ2UoKTtcXG4gICAgICAgIGNvbnNvbGUubG9nKCdIw6xuaCDhuqNuaCDEkcOjIMSRxrDhu6NjIGPhuq90OicsIGRhdGFVcmwpO1xcbiAgICAgIH0gZmluYWxseSB7XFxuICAgICAgICB0aGlzLmVkaXRvckZ1bmN0aW9ucy5zZXRMb2FkaW5nU3RhdGUoZmFsc2UpO1xcbiAgICAgIH1cXG4gICAgfVxcbiAgfVxcbn1gXG4gICAgfVxuICBdO1xuXG4gIGNvcHlUb0NsaXBib2FyZCh0ZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dCh0ZXh0KS50aGVuKCgpID0+IHtcbiAgICAgIGFsZXJ0KCfEkMOjIHNhbyBjaMOpcCB2w6BvIGNsaXBib2FyZCcpO1xuICAgIH0pLmNhdGNoKGVyciA9PiB7XG4gICAgICBjb25zb2xlLmVycm9yKCdLaMO0bmcgdGjhu4Mgc2FvIGNow6lwOiAnLCBlcnIpO1xuICAgIH0pO1xuICB9XG5cbiAgb25GaWxlU2VsZWN0ZWQoZXZlbnQ6IEV2ZW50KSB7XG4gICAgY29uc3QgaW5wdXQgPSBldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICBpZiAoaW5wdXQuZmlsZXMgJiYgaW5wdXQuZmlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5zZWxlY3RlZEZpbGUgPSBpbnB1dC5maWxlc1swXTtcbiAgICAgIHRoaXMuaW1hZ2VOYW1lID0gdGhpcy5zZWxlY3RlZEZpbGUubmFtZTtcbiAgICAgIGNvbnNvbGUubG9nKCdGaWxlIHNlbGVjdGVkOicsIHRoaXMuc2VsZWN0ZWRGaWxlLm5hbWUpO1xuICAgIH1cbiAgfVxuXG4gIHVwbG9hZEFuZEVkaXQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNlbGVjdGVkRmlsZSkge1xuICAgICAgYWxlcnQoJ1Z1aSBsw7JuZyBjaOG7jW4gbeG7mXQgZmlsZSBow6xuaCDhuqNuaCB0csaw4bubYycpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG4gICAgcmVhZGVyLm9ubG9hZCA9IChlOiBQcm9ncmVzc0V2ZW50PEZpbGVSZWFkZXI+KSA9PiB7XG4gICAgICBpZiAoZS50YXJnZXQ/LnJlc3VsdCkge1xuICAgICAgICB0aGlzLmltYWdlU291cmNlID0gZS50YXJnZXQucmVzdWx0IGFzIHN0cmluZztcbiAgICAgICAgdGhpcy5zaG93RWRpdG9yID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKHRoaXMuc2VsZWN0ZWRGaWxlKTtcbiAgfVxuXG4gIG9uU2F2ZUltYWdlKGRhdGE6IElTYXZlRmlsZSk6IHZvaWQge1xuICAgIGNvbnNvbGUubG9nKCdJbWFnZSBzYXZlZDonLCBkYXRhKTtcbiAgICB0aGlzLmVkaXRlZEltYWdlVXJsID0gZGF0YS51cmw7XG4gICAgdGhpcy5zaG93RWRpdG9yID0gZmFsc2U7XG4gIH1cblxuICBvbkNsb3NlRWRpdG9yKGRhdGE6IHsgaXNDbGlja0J1dHRvbkNsb3NlOiBib29sZWFuIH0pOiB2b2lkIHtcbiAgICBjb25zb2xlLmxvZygnRWRpdG9yIGNsb3NlZDonLCBkYXRhKTtcbiAgICB0aGlzLnNob3dFZGl0b3IgPSBmYWxzZTtcbiAgfVxuXG4gIGRvd25sb2FkSW1hZ2UoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZWRpdGVkSW1hZ2VVcmwpIHtcbiAgICAgIGNvbnN0IGxpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgICBsaW5rLmhyZWYgPSB0aGlzLmVkaXRlZEltYWdlVXJsO1xuICAgICAgbGluay5kb3dubG9hZCA9IHRoaXMuaW1hZ2VOYW1lIHx8ICdlZGl0ZWQtaW1hZ2UuanBnJztcbiAgICAgIGxpbmsuY2xpY2soKTtcbiAgICB9XG4gIH1cbn0gIiwiPGRpdiBjbGFzcz1cIm1heC13LTZ4bCBteC1hdXRvIHAtNSBmb250LXNhbnMgdGV4dC1ncmF5LTgwMFwiPlxuICA8aGVhZGVyIGNsYXNzPVwidGV4dC1jZW50ZXIgcHktMTAgYmctd2hpdGUgcm91bmRlZC1sZyBtYi04IHNoYWRvdy1zbVwiPlxuICAgIDxoMSBjbGFzcz1cInRleHQtNHhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTJcIj5EZW1vIFRyw6xuaCBDaOG7iW5oIFPhu61hIEjDrG5oIOG6om5oPC9oMT5cbiAgICA8cCBjbGFzcz1cInRleHQteGwgdGV4dC1ncmF5LTUwMFwiPlRoxrAgdmnhu4duIGNvbXBvbmVudCBjaG8gQW5ndWxhciDEkeG7gyBjaOG7iW5oIHPhu61hIGjDrG5oIOG6o25oPC9wPlxuICA8L2hlYWRlcj5cblxuICA8bWFpbj5cbiAgICA8c2VjdGlvbiBjbGFzcz1cImJnLXdoaXRlIHJvdW5kZWQtbGcgcC04IG1iLTggc2hhZG93LXNtXCI+XG4gICAgICA8aDIgY2xhc3M9XCJ0ZXh0LTJ4bCBmb250LWJvbGQgdGV4dC1ncmF5LTgwMCBtYi01IHBiLTMgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+R2nhu5tpIHRoaeG7h3U8L2gyPlxuICAgICAgPHA+XG4gICAgICAgIDxjb2RlIGNsYXNzPVwidGV4dC1zbSBiZy1ncmF5LTEwMCBweC0xLjUgcHktMC41IHJvdW5kZWRcIj4mIzY0O2xpYnMtdWkvY29tcG9uZW50cy1pbWFnZS1lZGl0b3I8L2NvZGU+IGzDoCBt4buZdFxuICAgICAgICBjb21wb25lbnQgQW5ndWxhciBt4bqhbmggbeG6vSBjaG8gcGjDqXAgbmfGsOG7nWkgZMO5bmcgdGjhu7FjIGhp4buHbiBjw6FjIHRoYW8gdMOhYyBjaOG7iW5oIHPhu61hIGjDrG5oIOG6o25oIG5oxrAgY+G6r3QsIHRoYXkgxJHhu5VpIGvDrWNoXG4gICAgICAgIHRoxrDhu5tjLCB4b2F5LCBs4bqtdCB2w6Agw6FwIGThu6VuZyB04bu3IGzhu4cgY+G7kSDEkeG7i25oLlxuICAgICAgPC9wPlxuICAgIDwvc2VjdGlvbj5cblxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBwLTggbWItOCBzaGFkb3ctc21cIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTUgcGItMyBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5Dw6BpIMSR4bq3dDwvaDI+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJtYi02XCI+XG4gICAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTNcIj5Zw6p1IGPhuqd1PC9oMz5cbiAgICAgICAgPHVsIGNsYXNzPVwibGlzdC1kaXNjIHBsLTUgc3BhY2UteS0yIHRleHQtZ3JheS02MDBcIj5cbiAgICAgICAgICA8bGk+PHNwYW4gY2xhc3M9XCJmb250LXNlbWlib2xkXCI+QW5ndWxhcjwvc3Bhbj46IDE4LjAuMCB0cuG7nyBsw6puPC9saT5cbiAgICAgICAgICA8bGk+PHNwYW4gY2xhc3M9XCJmb250LXNlbWlib2xkXCI+VGFpbHdpbmQgQ1NTPC9zcGFuPjogMy4zLjAgdHLhu58gbMOqbjwvbGk+XG4gICAgICAgIDwvdWw+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPHAgY2xhc3M9XCJtYi00XCI+xJDhu4MgY8OgaSDEkeG6t3QgdGjGsCB2aeG7h24sIHPhu60gZOG7pW5nIG5wbSBob+G6t2MgeWFybjo8L3A+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBiZy1ncmF5LTEwMCBwLTQgcm91bmRlZC1sZyBtYi02XCI+XG4gICAgICAgIDxwcmUgY2xhc3M9XCJmbGV4LTEgdGV4dC1zbSBvdmVyZmxvdy14LWF1dG9cIj48Y29kZT5ucG0gaW5zdGFsbCAmIzY0O2xpYnMtdWkvY29tcG9uZW50cy1pbWFnZS1lZGl0b3I8L2NvZGU+PC9wcmU+XG4gICAgICAgIDxidXR0b24gY2xhc3M9XCJtbC00IHB4LTMgcHktMSBiZy1ibHVlLTUwMCB0ZXh0LXdoaXRlIHJvdW5kZWQgaG92ZXI6YmctYmx1ZS02MDAgdHJhbnNpdGlvbi1jb2xvcnNcIlxuICAgICAgICAgIChjbGljayk9XCJjb3B5VG9DbGlwYm9hcmQoJ25wbSBpbnN0YWxsIEBsaWJzLXVpL2NvbXBvbmVudHMtaW1hZ2UtZWRpdG9yJylcIj5cbiAgICAgICAgICBTYW8gY2jDqXBcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPHAgY2xhc3M9XCJtYi00XCI+SG/hurdjIHbhu5tpIHlhcm46PC9wPlxuXG4gICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgYmctZ3JheS0xMDAgcC00IHJvdW5kZWQtbGcgbWItNlwiPlxuICAgICAgICA8cHJlIGNsYXNzPVwiZmxleC0xIHRleHQtc20gb3ZlcmZsb3cteC1hdXRvXCI+PGNvZGU+eWFybiBhZGQgJiM2NDtsaWJzLXVpL2NvbXBvbmVudHMtaW1hZ2UtZWRpdG9yPC9jb2RlPjwvcHJlPlxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwibWwtNCBweC0zIHB5LTEgYmctYmx1ZS01MDAgdGV4dC13aGl0ZSByb3VuZGVkIGhvdmVyOmJnLWJsdWUtNjAwIHRyYW5zaXRpb24tY29sb3JzXCJcbiAgICAgICAgICAoY2xpY2spPVwiY29weVRvQ2xpcGJvYXJkKCd5YXJuIGFkZCBAbGlicy11aS9jb21wb25lbnRzLWltYWdlLWVkaXRvcicpXCI+XG4gICAgICAgICAgU2FvIGNow6lwXG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgPC9zZWN0aW9uPlxuXG4gICAgPHNlY3Rpb24gY2xhc3M9XCJiZy13aGl0ZSByb3VuZGVkLWxnIHAtOCBtYi04IHNoYWRvdy1zbVwiPlxuICAgICAgPGgyIGNsYXNzPVwidGV4dC0yeGwgZm9udC1ib2xkIHRleHQtZ3JheS04MDAgbWItNSBwYi0zIGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPkRlbW8gdHLhu7FjIHRp4bq/cDwvaDI+XG4gICAgICA8ZGl2PlxuICAgICAgICA8cCBjbGFzcz1cIm1iLTRcIj5U4bqjaSBsw6puIGjDrG5oIOG6o25oIHbDoCBjaOG7iW5oIHPhu61hIG5nYXkgdHLDqm4gdHLDrG5oIGR1eeG7h3Q6PC9wPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LXdyYXAgaXRlbXMtY2VudGVyIGdhcC00IG1iLThcIj5cbiAgICAgICAgICA8aW5wdXQgdHlwZT1cImZpbGVcIlxuICAgICAgICAgICAgI2ltYWdlRmlsZUlucHV0XG4gICAgICAgICAgICBhY2NlcHQ9XCJpbWFnZS8qXCJcbiAgICAgICAgICAgIGNsYXNzPVwiYm9yZGVyIGJvcmRlci1ncmF5LTMwMCByb3VuZGVkIHB4LTMgcHktMlwiXG4gICAgICAgICAgICAoY2hhbmdlKT1cIm9uRmlsZVNlbGVjdGVkKCRldmVudClcIiAvPlxuICAgICAgICAgIDxsaWJzX3VpLWNvbXBvbmVudHMtYnV0dG9ucy1idXR0b24gbGFiZWw9XCJU4bqjaSBsw6puIHbDoCBjaOG7iW5oIHPhu61hXCJcbiAgICAgICAgICAgIChjbGljayk9XCJ1cGxvYWRBbmRFZGl0KClcIj5cbiAgICAgICAgICA8L2xpYnNfdWktY29tcG9uZW50cy1idXR0b25zLWJ1dHRvbj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgQGlmIChlZGl0ZWRJbWFnZVVybCkge1xuICAgICAgICAgIDxkaXYgY2xhc3M9XCJtdC04IHAtNiBiZy1ncmF5LTUwIHJvdW5kZWQtbGdcIj5cbiAgICAgICAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTRcIj5L4bq/dCBxdeG6ozwvaDM+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWF4LXcteGwgbXgtYXV0byBtYi00IGJvcmRlciBib3JkZXItZ3JheS0yMDAgcm91bmRlZC1sZyBvdmVyZmxvdy1oaWRkZW4gc2hhZG93LW1kXCI+XG4gICAgICAgICAgICAgIDxpbWcgW3NyY109XCJlZGl0ZWRJbWFnZVVybFwiXG4gICAgICAgICAgICAgICAgYWx0PVwiSMOsbmgg4bqjbmggxJHDoyBjaOG7iW5oIHPhu61hXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cInctZnVsbCBoLWF1dG9cIiAvPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBqdXN0aWZ5LWNlbnRlclwiPlxuICAgICAgICAgICAgICA8bGlic191aS1jb21wb25lbnRzLWJ1dHRvbnMtYnV0dG9uIGxhYmVsPVwiVOG6o2kgeHXhu5FuZyBow6xuaCDhuqNuaFwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImRvd25sb2FkSW1hZ2UoKVwiPlxuICAgICAgICAgICAgICA8L2xpYnNfdWktY29tcG9uZW50cy1idXR0b25zLWJ1dHRvbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICA8L3NlY3Rpb24+XG5cbiAgICBAaWYgKHNob3dFZGl0b3IpIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJmaXhlZCBpbnNldC0wIHotNTBcIj5cbiAgICAgICAgPGxpYnNfdWktY29tcG9uZW50cy1pbWFnZV9lZGl0b3IgWyhpbWdTcmMpXT1cImltYWdlU291cmNlXCJcbiAgICAgICAgICBbbmFtZUZpbGVdPVwiaW1hZ2VOYW1lIHx8ICdkZW1vLWltYWdlLmpwZydcIlxuICAgICAgICAgIFttb2RlU2hvd0J1dHRvbl09XCInc2F2ZS1maWxlJ1wiXG4gICAgICAgICAgW2hhc1pvb21dPVwidHJ1ZVwiXG4gICAgICAgICAgKG91dFNhdmVGaWxlKT1cIm9uU2F2ZUltYWdlKCRldmVudClcIlxuICAgICAgICAgIChvdXRDbG9zZSk9XCJvbkNsb3NlRWRpdG9yKCRldmVudClcIiAvPlxuICAgICAgPC9kaXY+XG4gICAgfVxuXG4gICAgPHNlY3Rpb24gY2xhc3M9XCJiZy13aGl0ZSByb3VuZGVkLWxnIHAtOCBtYi04IHNoYWRvdy1zbVwiPlxuICAgICAgPGgyIGNsYXNzPVwidGV4dC0yeGwgZm9udC1ib2xkIHRleHQtZ3JheS04MDAgbWItNSBwYi0zIGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPkPDoWNoIHPhu60gZOG7pW5nPC9oMj5cblxuICAgICAgPGRpdiBjbGFzcz1cIm1iLThcIj5cbiAgICAgICAgPGgzIGNsYXNzPVwidGV4dC14bCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDAgbWItNFwiPkPDoWNoIDE6IFPhu60gZOG7pW5nIGZpbGUgSFRNTCByacOqbmcgYmnhu4d0PC9oMz5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiZ3JpZCBncmlkLWNvbHMtMSBtZDpncmlkLWNvbHMtMiBnYXAtNiBtYi00XCI+XG4gICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgIDxoNCBjbGFzcz1cImZvbnQtc2VtaWJvbGQgbWItMiB0ZXh0LWdyYXktNzAwXCI+SFRNTCAoZXhhbXBsZS5jb21wb25lbnQuaHRtbCk8L2g0PlxuICAgICAgICAgICAgPHByZSBjbGFzcz1cImJnLWdyYXktMTAwIHAtNCByb3VuZGVkLWxnIG92ZXJmbG93LXgtYXV0byB0ZXh0LXNtXCI+PGNvZGU+Jmx0O2xpYnNfdWktY29tcG9uZW50cy1pbWFnZV9lZGl0b3JcbiAgWyhpbWdTcmMpXT1cImltYWdlU291cmNlXCJcbiAgW25hbWVGaWxlXT1cIidpbWFnZS5qcGcnXCJcbiAgW21vZGVTaG93QnV0dG9uXT1cIidzYXZlLWZpbGUnXCJcbiAgKG91dFNhdmVGaWxlKT1cIm9uU2F2ZUZpbGUoJGV2ZW50KVwiXG4gIChvdXRDbG9zZSk9XCJvbkNsb3NlKCRldmVudClcIiZndDtcbiZsdDsvbGlic191aS1jb21wb25lbnRzLWltYWdlX2VkaXRvciZndDs8L2NvZGU+PC9wcmU+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgPGg0IGNsYXNzPVwiZm9udC1zZW1pYm9sZCBtYi0yIHRleHQtZ3JheS03MDBcIj5UeXBlU2NyaXB0IChleGFtcGxlLmNvbXBvbmVudC50cyk8L2g0PlxuICAgICAgICAgICAgPHByZSBjbGFzcz1cImJnLWdyYXktMTAwIHAtNCByb3VuZGVkLWxnIG92ZXJmbG93LXgtYXV0byB0ZXh0LXNtXCI+PGNvZGU+aW1wb3J0ICYjMTIzOyBDb21wb25lbnQgJiMxMjU7IGZyb20gJyYjNjQ7YW5ndWxhci9jb3JlJztcbmltcG9ydCAmIzEyMzsgTGlic1VpQ29tcG9uZW50c0ltYWdlRWRpdG9yQ29tcG9uZW50ICYjMTI1OyBmcm9tICcmIzY0O2xpYnMtdWkvY29tcG9uZW50cy1pbWFnZS1lZGl0b3InO1xuXG4mIzY0O0NvbXBvbmVudCgmIzEyMztcbiAgc2VsZWN0b3I6ICdhcHAtZXhhbXBsZScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnRdLFxuICB0ZW1wbGF0ZVVybDogJy4vZXhhbXBsZS5jb21wb25lbnQuaHRtbCdcbiYjMTI1OylcbmV4cG9ydCBjbGFzcyBFeGFtcGxlQ29tcG9uZW50ICYjMTIzO1xuICBpbWFnZVNvdXJjZSA9ICdodHRwczovL2V4YW1wbGUuY29tL3BhdGgvdG8vaW1hZ2UuanBnJztcblxuICBvblNhdmVGaWxlKGRhdGE6ICYjMTIzO2ZpbGU6IEJsb2IsIHVybDogc3RyaW5nLCBtb2RlOiBzdHJpbmcmIzEyNTspICYjMTIzO1xuICAgIGNvbnNvbGUubG9nKCdGaWxlIMSRw6MgxJHGsOG7o2MgbMawdTonLCBkYXRhKTtcbiAgJiMxMjU7XG5cbiAgb25DbG9zZShkYXRhOiAmIzEyMztpc0NsaWNrQnV0dG9uQ2xvc2U6IGJvb2xlYW4mIzEyNTspICYjMTIzO1xuICAgIGNvbnNvbGUubG9nKCfEkMOjIMSRw7NuZyB0csOsbmggY2jhu4luaCBz4butYSDhuqNuaCcpO1xuICAmIzEyNTtcbiYjMTI1OzwvY29kZT48L3ByZT5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGRpdiBjbGFzcz1cIm1iLThcIj5cbiAgICAgICAgPGgzIGNsYXNzPVwidGV4dC14bCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDAgbWItNFwiPkPDoWNoIDI6IFbhu5tpIHRyw6xuaCBjaOG7iW5oIHPhu61hIGPDsyB0aOG7gyDEkcOzbmcvbeG7nzwvaDM+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cImdyaWQgZ3JpZC1jb2xzLTEgbWQ6Z3JpZC1jb2xzLTIgZ2FwLTYgbWItNFwiPlxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8aDQgY2xhc3M9XCJmb250LXNlbWlib2xkIG1iLTIgdGV4dC1ncmF5LTcwMFwiPkhUTUwgKHRvZ2dsZS1lZGl0b3IuY29tcG9uZW50Lmh0bWwpPC9oND5cbiAgICAgICAgICAgIDxwcmUgY2xhc3M9XCJiZy1ncmF5LTEwMCBwLTQgcm91bmRlZC1sZyBvdmVyZmxvdy14LWF1dG8gdGV4dC1zbVwiPjxjb2RlPiZsdDtidXR0b24gKGNsaWNrKT1cIm9wZW5FZGl0b3IoKVwiIGNsYXNzPVwicHgtNCBweS0yIGJnLWJsdWUtNTAwIHRleHQtd2hpdGUgcm91bmRlZFwiJmd0O1xuICBN4bufIHRyw6xuaCBjaOG7iW5oIHPhu61hIOG6o25oXG4mbHQ7L2J1dHRvbiZndDtcblxuJiM2NDtpZiAoc2hvd0VkaXRvcikgJiMxMjM7XG4gICZsdDtsaWJzX3VpLWNvbXBvbmVudHMtaW1hZ2VfZWRpdG9yXG4gICAgWyhpbWdTcmMpXT1cImltYWdlU291cmNlXCJcbiAgICBbbmFtZUZpbGVdPVwiJ215LWltYWdlLmpwZydcIlxuICAgIChvdXRTYXZlRmlsZSk9XCJvblNhdmVGaWxlKCRldmVudClcIlxuICAgIChvdXRDbG9zZSk9XCJvbkNsb3NlRWRpdG9yKCRldmVudClcIiZndDtcbiAgJmx0Oy9saWJzX3VpLWNvbXBvbmVudHMtaW1hZ2VfZWRpdG9yJmd0O1xuJiMxMjU7XG5cbiYjNjQ7aWYgKGVkaXRlZEltYWdlVXJsKSAmIzEyMztcbiAgJmx0O2RpdiBjbGFzcz1cIm10LTRcIiZndDtcbiAgICAmbHQ7aDMgY2xhc3M9XCJ0ZXh0LWxnIGZvbnQtc2VtaWJvbGRcIiZndDtIw6xuaCDhuqNuaCDEkcOjIGNo4buJbmggc+G7rWE6Jmx0Oy9oMyZndDtcbiAgICAmbHQ7aW1nIFtzcmNdPVwiZWRpdGVkSW1hZ2VVcmxcIiBhbHQ9XCJIw6xuaCDhuqNuaCDEkcOjIGNo4buJbmggc+G7rWFcIiBjbGFzcz1cIm10LTIgbWF4LXctZnVsbCBoLWF1dG9cIiAvJmd0O1xuICAmbHQ7L2RpdiZndDtcbiYjMTI1OzwvY29kZT48L3ByZT5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8aDQgY2xhc3M9XCJmb250LXNlbWlib2xkIG1iLTIgdGV4dC1ncmF5LTcwMFwiPlR5cGVTY3JpcHQgKHRvZ2dsZS1lZGl0b3IuY29tcG9uZW50LnRzKTwvaDQ+XG4gICAgICAgICAgICA8cHJlIGNsYXNzPVwiYmctZ3JheS0xMDAgcC00IHJvdW5kZWQtbGcgb3ZlcmZsb3cteC1hdXRvIHRleHQtc21cIj48Y29kZT5pbXBvcnQgJiMxMjM7IENvbXBvbmVudCAmIzEyNTsgZnJvbSAnJiM2NDthbmd1bGFyL2NvcmUnO1xuaW1wb3J0ICYjMTIzOyBMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnQgJiMxMjU7IGZyb20gJyYjNjQ7bGlicy11aS9jb21wb25lbnRzLWltYWdlLWVkaXRvcic7XG5pbXBvcnQgJiMxMjM7IElTYXZlRmlsZSAmIzEyNTsgZnJvbSAnJiM2NDtsaWJzLXVpL2NvbXBvbmVudHMtaW1hZ2UtZWRpdG9yJztcblxuJiM2NDtDb21wb25lbnQoJiMxMjM7XG4gIHNlbGVjdG9yOiAnYXBwLXRvZ2dsZS1lZGl0b3InLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbTGlic1VpQ29tcG9uZW50c0ltYWdlRWRpdG9yQ29tcG9uZW50XSxcbiAgdGVtcGxhdGVVcmw6ICcuL3RvZ2dsZS1lZGl0b3IuY29tcG9uZW50Lmh0bWwnXG4mIzEyNTspXG5leHBvcnQgY2xhc3MgVG9nZ2xlRWRpdG9yQ29tcG9uZW50ICYjMTIzO1xuICBpbWFnZVNvdXJjZSA9ICdodHRwczovL2V4YW1wbGUuY29tL3BhdGgvdG8vaW1hZ2UuanBnJztcbiAgc2hvd0VkaXRvciA9IGZhbHNlO1xuICBlZGl0ZWRJbWFnZVVybCA9ICcnO1xuXG4gIG9wZW5FZGl0b3IoKSAmIzEyMztcbiAgICB0aGlzLnNob3dFZGl0b3IgPSB0cnVlO1xuICAmIzEyNTtcblxuICBvblNhdmVGaWxlKGRhdGE6IElTYXZlRmlsZSkgJiMxMjM7XG4gICAgdGhpcy5lZGl0ZWRJbWFnZVVybCA9IGRhdGEudXJsO1xuICAgIHRoaXMuc2hvd0VkaXRvciA9IGZhbHNlO1xuICAgIGNvbnNvbGUubG9nKCfEkMOjIGzGsHUgZmlsZTonLCBkYXRhLmZpbGUpO1xuICAmIzEyNTtcblxuICBvbkNsb3NlRWRpdG9yKGRhdGE6ICYjMTIzO2lzQ2xpY2tCdXR0b25DbG9zZTogYm9vbGVhbiYjMTI1OykgJiMxMjM7XG4gICAgdGhpcy5zaG93RWRpdG9yID0gZmFsc2U7XG4gICYjMTI1O1xuJiMxMjU7PC9jb2RlPjwvcHJlPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2IGNsYXNzPVwibWItOFwiPlxuICAgICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi00XCI+Q8OhY2ggMzogVuG7m2kgdOG7tyBs4buHIGtodW5nIGjDrG5oIGPhu5EgxJHhu4tuaDwvaDM+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cImdyaWQgZ3JpZC1jb2xzLTEgbWQ6Z3JpZC1jb2xzLTIgZ2FwLTYgbWItNFwiPlxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8aDQgY2xhc3M9XCJmb250LXNlbWlib2xkIG1iLTIgdGV4dC1ncmF5LTcwMFwiPkhUTUwgKGZpeGVkLXJhdGlvLmNvbXBvbmVudC5odG1sKTwvaDQ+XG4gICAgICAgICAgICA8cHJlIGNsYXNzPVwiYmctZ3JheS0xMDAgcC00IHJvdW5kZWQtbGcgb3ZlcmZsb3cteC1hdXRvIHRleHQtc21cIj48Y29kZT4mbHQ7bGlic191aS1jb21wb25lbnRzLWltYWdlX2VkaXRvclxuICBbKGltZ1NyYyldPVwiaW1hZ2VTb3VyY2VcIlxuICBbYXNwZWN0UmF0aW9dPVwiYXNwZWN0UmF0aW9cIlxuICBbcmVxdWlyZWRDcm9wRm9sbG93UmF0aW9dPVwidHJ1ZVwiXG4gIChvdXRTYXZlRmlsZSk9XCJvblNhdmVGaWxlKCRldmVudClcIiZndDtcbiZsdDsvbGlic191aS1jb21wb25lbnRzLWltYWdlX2VkaXRvciZndDs8L2NvZGU+PC9wcmU+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgPGg0IGNsYXNzPVwiZm9udC1zZW1pYm9sZCBtYi0yIHRleHQtZ3JheS03MDBcIj5UeXBlU2NyaXB0IChmaXhlZC1yYXRpby5jb21wb25lbnQudHMpPC9oND5cbiAgICAgICAgICAgIDxwcmUgY2xhc3M9XCJiZy1ncmF5LTEwMCBwLTQgcm91bmRlZC1sZyBvdmVyZmxvdy14LWF1dG8gdGV4dC1zbVwiPjxjb2RlPmltcG9ydCAmIzEyMzsgQ29tcG9uZW50ICYjMTI1OyBmcm9tICcmIzY0O2FuZ3VsYXIvY29yZSc7XG5pbXBvcnQgJiMxMjM7IExpYnNVaUNvbXBvbmVudHNJbWFnZUVkaXRvckNvbXBvbmVudCAmIzEyNTsgZnJvbSAnJiM2NDtsaWJzLXVpL2NvbXBvbmVudHMtaW1hZ2UtZWRpdG9yJztcbmltcG9ydCAmIzEyMzsgSUFzcGVjdFJhdGlvICYjMTI1OyBmcm9tICcmIzY0O2xpYnMtdWkvaW50ZXJmYWNlcy10eXBlcyc7XG5cbiYjNjQ7Q29tcG9uZW50KCYjMTIzO1xuICBzZWxlY3RvcjogJ2FwcC1maXhlZC1yYXRpbycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtMaWJzVWlDb21wb25lbnRzSW1hZ2VFZGl0b3JDb21wb25lbnRdLFxuICB0ZW1wbGF0ZVVybDogJy4vZml4ZWQtcmF0aW8uY29tcG9uZW50Lmh0bWwnXG4mIzEyNTspXG5leHBvcnQgY2xhc3MgRml4ZWRSYXRpb0NvbXBvbmVudCAmIzEyMztcbiAgaW1hZ2VTb3VyY2UgPSAnaHR0cHM6Ly9leGFtcGxlLmNvbS9wYXRoL3RvL2ltYWdlLmpwZyc7XG4gIGFzcGVjdFJhdGlvOiBJQXNwZWN0UmF0aW8gPSAmIzEyMztcbiAgICBrZXk6ICcxOjEnLFxuICAgIHZhbHVlOiAxXG4gICYjMTI1OztcblxuICBvblNhdmVGaWxlKGRhdGE6IGFueSkgJiMxMjM7XG4gICAgY29uc29sZS5sb2coJ8SQw6MgbMawdSBow6xuaCDhuqNuaCB24bubaSB04bu3IGzhu4cgMToxJyk7XG4gICYjMTI1O1xuJiMxMjU7PC9jb2RlPjwvcHJlPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvc2VjdGlvbj5cblxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBwLTggbWItOCBzaGFkb3ctc21cIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTUgcGItMyBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5Uw6BpIGxp4buHdSBBUEk8L2gyPlxuXG4gICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi00XCI+SW5wdXRzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJvdmVyZmxvdy14LWF1dG8gbWItOFwiPlxuICAgICAgICA8dGFibGUgY2xhc3M9XCJtaW4tdy1mdWxsIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDBcIj5cbiAgICAgICAgICA8dGhlYWQ+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0aCBjbGFzcz1cInB5LTMgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDAgYmctZ3JheS0xMDAgdGV4dC1sZWZ0IGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMFwiPlTDqm48L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwIGJnLWdyYXktMTAwIHRleHQtbGVmdCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDBcIj5LaeG7g3UgZOG7r1xuICAgICAgICAgICAgICAgIGxp4buHdVxuICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwIGJnLWdyYXktMTAwIHRleHQtbGVmdCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDBcIj5N4bq3YyDEkeG7i25oXG4gICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICAgIDx0aCBjbGFzcz1cInB5LTMgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDAgYmctZ3JheS0xMDAgdGV4dC1sZWZ0IGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMFwiPk3DtCB04bqjXG4gICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICA8L3RyPlxuICAgICAgICAgIDwvdGhlYWQ+XG4gICAgICAgICAgPHRib2R5PlxuICAgICAgICAgICAgQGZvciAoaW5wdXQgb2YgaW5wdXRzRG9jOyB0cmFjayBpbnB1dC5uYW1lKSB7XG4gICAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIGJnLWdyYXktMTAwIHB4LTEuNSBweS0wLjUgcm91bmRlZFwiPnt7IGlucHV0Lm5hbWUgfX08L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIGJnLWdyYXktMTAwIHB4LTEuNSBweS0wLjUgcm91bmRlZFwiPnt7IGlucHV0LnR5cGUgfX08L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+e3sgaW5wdXQuZGVmYXVsdCB9fTwvdGQ+XG4gICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPnt7IGlucHV0LmRlc2NyaXB0aW9uIH19PC90ZD5cbiAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L3Rib2R5PlxuICAgICAgICA8L3RhYmxlPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTRcIj5PdXRwdXRzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJvdmVyZmxvdy14LWF1dG8gbWItOFwiPlxuICAgICAgICA8dGFibGUgY2xhc3M9XCJtaW4tdy1mdWxsIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDBcIj5cbiAgICAgICAgICA8dGhlYWQ+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0aCBjbGFzcz1cInB5LTMgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDAgYmctZ3JheS0xMDAgdGV4dC1sZWZ0IGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMFwiPlTDqm48L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwIGJnLWdyYXktMTAwIHRleHQtbGVmdCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDBcIj5LaeG7g3UgZOG7r1xuICAgICAgICAgICAgICAgIGxp4buHdVxuICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwIGJnLWdyYXktMTAwIHRleHQtbGVmdCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDBcIj5Nw7QgdOG6o1xuICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L3RoZWFkPlxuICAgICAgICAgIDx0Ym9keT5cbiAgICAgICAgICAgIEBmb3IgKG91dHB1dCBvZiBvdXRwdXRzRG9jOyB0cmFjayBvdXRwdXQubmFtZSkge1xuICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPjxjb2RlXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1zbSBiZy1ncmF5LTEwMCBweC0xLjUgcHktMC41IHJvdW5kZWRcIj57eyBvdXRwdXQubmFtZSB9fTwvY29kZT48L3RkPlxuICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtc20gYmctZ3JheS0xMDAgcHgtMS41IHB5LTAuNSByb3VuZGVkXCI+e3sgb3V0cHV0LnR5cGUgfX08L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+e3sgb3V0cHV0LmRlc2NyaXB0aW9uIH19PC90ZD5cbiAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L3Rib2R5PlxuICAgICAgICA8L3RhYmxlPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTRcIj5JbnRlcmZhY2VzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJzcGFjZS15LTZcIj5cbiAgICAgICAgQGZvciAoaW50ZXJmYWNlSXRlbSBvZiBpbnRlcmZhY2VzRG9jOyB0cmFjayBpbnRlcmZhY2VJdGVtLm5hbWUpIHtcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiYmctZ3JheS01MCBwLTYgcm91bmRlZC1sZ1wiPlxuICAgICAgICAgICAgPGg0IGNsYXNzPVwidGV4dC1sZyBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDAgbWItM1wiPnt7IGludGVyZmFjZUl0ZW0ubmFtZSB9fTwvaDQ+XG4gICAgICAgICAgICA8cHJlXG4gICAgICAgICAgICAgIGNsYXNzPVwiYmctZ3JheS0xMDAgcC00IHJvdW5kZWQtbGcgb3ZlcmZsb3cteC1hdXRvIHRleHQtc20gbWItM1wiPjxjb2RlPnt7IGludGVyZmFjZUl0ZW0uY29kZSB9fTwvY29kZT48L3ByZT5cbiAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1ncmF5LTYwMFwiPnt7IGludGVyZmFjZUl0ZW0uZGVzY3JpcHRpb24gfX08L3A+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuICAgIDwvc2VjdGlvbj5cblxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBwLTggbWItOCBzaGFkb3ctc21cIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTUgcGItMyBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5Uw61uaCBuxINuZzwvaDI+XG4gICAgICA8dWwgY2xhc3M9XCJzcGFjZS15LTZcIj5cbiAgICAgICAgQGZvciAoZmVhdHVyZSBvZiBmZWF0dXJlczsgdHJhY2sgZmVhdHVyZS5pZCkge1xuICAgICAgICAgIDxsaSBjbGFzcz1cImZsZXggaXRlbXMtc3RhcnRcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC0yeGwgdGV4dC1ibHVlLTUwMFwiPnt7IGZlYXR1cmUuaWNvbiB9fTwvc3Bhbj5cbiAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgIDxoMyBjbGFzcz1cInRleHQtbGcgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTFcIj57eyBmZWF0dXJlLnRpdGxlIH19PC9oMz5cbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJ0ZXh0LWdyYXktNjAwXCI+e3sgZmVhdHVyZS5kZXNjcmlwdGlvbiB9fTwvcD5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvbGk+XG4gICAgICAgIH1cbiAgICAgIDwvdWw+XG4gICAgPC9zZWN0aW9uPlxuICA8L21haW4+XG48L2Rpdj5cbiJdfQ==
@@ -1121,14 +1121,14 @@ class LibsUiComponentsImageEditorDemoComponent {
1121
1121
  }
1122
1122
  }
1123
1123
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsImageEditorDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1124
- 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 mr-4\">{{ 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
+ 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"] }] });
1125
1125
  }
1126
1126
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsImageEditorDemoComponent, decorators: [{
1127
1127
  type: Component,
1128
1128
  args: [{ selector: 'lib-image-editor-demo', standalone: true, imports: [
1129
1129
  LibsUiComponentsButtonsButtonComponent,
1130
1130
  LibsUiComponentsImageEditorComponent
1131
- ], 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 mr-4\">{{ 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
+ ], 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"] }]
1132
1132
  }], propDecorators: { imageFileInput: [{
1133
1133
  type: ViewChild,
1134
1134
  args: ['imageFileInput']