shirkasoft-ui-components 1.3.8 → 1.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -12
- package/fesm2022/shirkasoft-ui-components-button.mjs +2 -2
- package/fesm2022/shirkasoft-ui-components-button.mjs.map +1 -1
- package/fesm2022/shirkasoft-ui-components-confirm-dialog.mjs +2 -2
- package/fesm2022/shirkasoft-ui-components-confirm-dialog.mjs.map +1 -1
- package/fesm2022/shirkasoft-ui-components-date-picker.mjs +2 -2
- package/fesm2022/shirkasoft-ui-components-date-picker.mjs.map +1 -1
- package/fesm2022/shirkasoft-ui-components-loading.mjs +2 -2
- package/fesm2022/shirkasoft-ui-components-loading.mjs.map +1 -1
- package/fesm2022/shirkasoft-ui-components-modal.mjs +2 -2
- package/fesm2022/shirkasoft-ui-components-modal.mjs.map +1 -1
- package/fesm2022/shirkasoft-ui-components-notification.mjs +2 -2
- package/fesm2022/shirkasoft-ui-components-notification.mjs.map +1 -1
- package/fesm2022/shirkasoft-ui-components-price-input.mjs +2 -2
- package/fesm2022/shirkasoft-ui-components-price-input.mjs.map +1 -1
- package/fesm2022/shirkasoft-ui-components-select.mjs +2 -2
- package/fesm2022/shirkasoft-ui-components-select.mjs.map +1 -1
- package/fesm2022/shirkasoft-ui-components-table.mjs +198 -12
- package/fesm2022/shirkasoft-ui-components-table.mjs.map +1 -1
- package/fesm2022/shirkasoft-ui-components-tabs.mjs +7 -12
- package/fesm2022/shirkasoft-ui-components-tabs.mjs.map +1 -1
- package/fesm2022/shirkasoft-ui-components-tag.mjs +3 -3
- package/fesm2022/shirkasoft-ui-components-tag.mjs.map +1 -1
- package/fesm2022/shirkasoft-ui-components-text-field.mjs +2 -2
- package/fesm2022/shirkasoft-ui-components-text-field.mjs.map +1 -1
- package/fesm2022/shirkasoft-ui-components-toggle.mjs +61 -24
- package/fesm2022/shirkasoft-ui-components-toggle.mjs.map +1 -1
- package/package.json +1 -1
- package/src/theme.css +80 -0
- package/types/shirkasoft-ui-components-table.d.ts +86 -9
- package/types/shirkasoft-ui-components-toggle.d.ts +7 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shirkasoft-ui-components-loading.mjs","sources":["../../../projects/ui-components/loading/loading-spinner.component.ts","../../../projects/ui-components/loading/loading-bar.component.ts","../../../projects/ui-components/loading/loading-overlay.component.ts","../../../projects/ui-components/loading/loading-dots.component.ts","../../../projects/ui-components/loading/shirkasoft-ui-components-loading.ts"],"sourcesContent":["import { Component, input, ChangeDetectionStrategy } from '@angular/core';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/** Circular indeterminate spinner. */\n@Component({\n selector: 'shk-loading-spinner',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div\n class=\"shk-loading-spinner\"\n [style]=\"{\n width: size(),\n height: size(),\n }\"\n role=\"status\"\n aria-label=\"Cargando\"\n >\n <div\n class=\"shk-loading-spinner-circle\"\n [style]=\"{\n borderWidth: thickness(),\n borderTopColor: color() || undefined,\n }\"\n ></div>\n </div>\n @if (label()) {\n <span class=\"shk-loading-spinner-label\">{{ label() }}</span>\n }\n `,\n styles: [\n `\n :host {\n display: inline-flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n }\n .shk-loading-spinner {\n display: inline-block;\n }\n .shk-loading-spinner-circle {\n width: 100%;\n height: 100%;\n border-radius: 9999px;\n border-style: solid;\n border-color: color-mix(in srgb, var(--shk-primary-600) 20%, transparent);\n border-top-color: var(--shk-primary-600);\n animation: shk-loading-spin 0.8s linear infinite;\n }\n .shk-loading-spinner-label {\n font-size: 0.8125rem;\n color: var(--shk-surface-500);\n }\n @keyframes shk-loading-spin {\n to {\n transform: rotate(360deg);\n }\n }\n `,\n ],\n})\nexport class LoadingSpinnerComponent {\n /** Diameter of the spinner. */\n size = input<string>('2rem');\n /** Border thickness in px. */\n thickness = input<number>(3);\n /** Color of the moving arc. Defaults to the primary token. */\n color = input<string>('');\n /** Optional text shown under the spinner. */\n label = input<string>('');\n}\n","import { Component, computed, input, ChangeDetectionStrategy } from '@angular/core';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/** Progress bar with an indeterminate sweep or a determinate percentage. */\n@Component({\n selector: 'shk-loading-bar',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div\n class=\"shk-loading-bar\"\n [class.shk-loading-bar-indeterminate]=\"indeterminate()\"\n [style]=\"{ height: height(), borderRadius: rounded() ? '9999px' : undefined }\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"indeterminate() ? undefined : progress()\"\n aria-label=\"Progreso\"\n >\n <div\n class=\"shk-loading-bar-fill\"\n [style]=\"fillStyle()\"\n [style.background-color]=\"color() || undefined\"\n [style.border-radius]=\"rounded() ? '9999px' : undefined\"\n ></div>\n </div>\n `,\n styles: [\n `\n .shk-loading-bar {\n width: 100%;\n position: relative;\n overflow: hidden;\n background-color: var(--shk-surface-200);\n }\n .shk-loading-bar-fill {\n height: 100%;\n background-color: var(--shk-primary-600);\n transition: width 0.3s ease-in-out;\n }\n .shk-loading-bar-indeterminate .shk-loading-bar-fill {\n width: 40%;\n animation: shk-loading-bar-sweep 1.2s ease-in-out infinite;\n }\n @keyframes shk-loading-bar-sweep {\n 0% {\n transform: translateX(-100%);\n }\n 100% {\n transform: translateX(350%);\n }\n }\n `,\n ],\n})\nexport class LoadingBarComponent {\n /** Height of the bar. */\n height = input<string>('0.25rem');\n /** When true the bar animates without a known percentage. */\n indeterminate = input<boolean>(true);\n /** Current progress 0-100 when `indeterminate` is false. */\n progress = input<number>(0);\n /** Fill color. Defaults to the primary token. */\n color = input<string>('');\n /** Renders fully rounded ends. */\n rounded = input<boolean>(true);\n\n /** Fill width/style for the determinate mode, empty for indeterminate. */\n protected fillStyle = computed(() => {\n if (this.indeterminate()) return {};\n return { width: `${Math.max(0, Math.min(100, this.progress()))}%` };\n });\n}\n","import { Component, input, ChangeDetectionStrategy } from '@angular/core';\nimport { LoadingSpinnerComponent } from './loading-spinner.component';\n\n/** Backdrop style behind the overlay: none, light or dark. */\nexport type LoadingOverlayBackdrop = 'transparent' | 'light' | 'dark';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/** Wraps content and shows a centered spinner over it while `visible` is true. */\n@Component({\n selector: 'shk-loading-overlay',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [LoadingSpinnerComponent],\n template: `\n <div\n class=\"shk-loading-overlay\"\n [class.shk-loading-overlay-light]=\"backdrop() === 'light'\"\n [class.shk-loading-overlay-dark]=\"backdrop() === 'dark'\"\n >\n <ng-content></ng-content>\n @if (visible()) {\n <div class=\"shk-loading-overlay-layer\">\n <shk-loading-spinner [size]=\"spinnerSize()\" [color]=\"color()\" [label]=\"message()\" />\n </div>\n }\n </div>\n `,\n styles: [\n `\n :host {\n display: block;\n }\n .shk-loading-overlay {\n position: relative;\n min-height: 1.5rem;\n }\n .shk-loading-overlay-layer {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n }\n .shk-loading-overlay-light .shk-loading-overlay-layer {\n background-color: rgba(255, 255, 255, 0.65);\n }\n .dark .shk-loading-overlay-light .shk-loading-overlay-layer {\n background-color: rgba(0, 0, 0, 0.55);\n }\n .shk-loading-overlay-dark .shk-loading-overlay-layer {\n background-color: rgba(0, 0, 0, 0.4);\n }\n `,\n ],\n})\nexport class LoadingOverlayComponent {\n /** Controls whether the spinner layer is shown. */\n visible = input<boolean>(false);\n /** Optional text under the spinner. */\n message = input<string>('');\n /** Diameter of the spinner. */\n spinnerSize = input<string>('2.5rem');\n /** Spinner color. Defaults to the primary token. */\n color = input<string>('');\n /** Backdrop behind the spinner. */\n backdrop = input<LoadingOverlayBackdrop>('transparent');\n}\n","import { Component, computed, input, ChangeDetectionStrategy } from '@angular/core';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/** Bouncing dots loading indicator. */\n@Component({\n selector: 'shk-loading-dots',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <span class=\"shk-loading-dots\" role=\"status\" aria-label=\"Cargando\">\n @for (dot of dots(); track $index) {\n <span\n class=\"shk-loading-dot\"\n [style]=\"{\n width: size(),\n height: size(),\n backgroundColor: color() || undefined,\n animationDelay: $index * 0.12 + 's',\n }\"\n ></span>\n }\n </span>\n @if (label()) {\n <span class=\"shk-loading-dots-label\">{{ label() }}</span>\n }\n `,\n styles: [\n `\n :host {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n }\n .shk-loading-dots {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n }\n .shk-loading-dot {\n border-radius: 9999px;\n background-color: var(--shk-primary-600);\n animation: shk-loading-dots-bounce 1.4s ease-in-out infinite;\n }\n .shk-loading-dots-label {\n font-size: 0.8125rem;\n color: var(--shk-surface-500);\n }\n @keyframes shk-loading-dots-bounce {\n 0%,\n 80%,\n 100% {\n transform: scale(0.6);\n opacity: 0.5;\n }\n 40% {\n transform: scale(1);\n opacity: 1;\n }\n }\n `,\n ],\n})\nexport class LoadingDotsComponent {\n /** Diameter of each dot. */\n size = input<string>('0.5rem');\n /** Dot color. Defaults to the primary token. */\n color = input<string>('');\n /** Number of dots. */\n count = input<number>(3);\n /** Optional text shown next to the dots. */\n label = input<string>('');\n\n /** Array of dot indices to render based on the `count` input. */\n protected dots = computed(() => Array.from({ length: Math.max(1, this.count()) }));\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shirkasoft-ui-components-loading.mjs","sources":["../../../projects/ui-components/loading/loading-spinner.component.ts","../../../projects/ui-components/loading/loading-bar.component.ts","../../../projects/ui-components/loading/loading-overlay.component.ts","../../../projects/ui-components/loading/loading-dots.component.ts","../../../projects/ui-components/loading/shirkasoft-ui-components-loading.ts"],"sourcesContent":["import { Component, input, ChangeDetectionStrategy } from '@angular/core';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/** Circular indeterminate spinner. */\n@Component({\n selector: 'shk-loading-spinner',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div\n class=\"shk-loading-spinner\"\n [style]=\"{\n width: size(),\n height: size(),\n }\"\n role=\"status\"\n aria-label=\"Cargando\"\n >\n <div\n class=\"shk-loading-spinner-circle\"\n [style]=\"{\n borderWidth: thickness(),\n borderTopColor: color() || undefined,\n }\"\n ></div>\n </div>\n @if (label()) {\n <span class=\"shk-loading-spinner-label\">{{ label() }}</span>\n }\n `,\n styles: [\n `\n :host {\n display: inline-flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n }\n .shk-loading-spinner {\n display: inline-block;\n }\n .shk-loading-spinner-circle {\n width: 100%;\n height: 100%;\n border-radius: 9999px;\n border-style: solid;\n border-color: color-mix(in srgb, var(--shk-primary-600) 20%, transparent);\n border-top-color: var(--shk-primary-600);\n animation: shk-loading-spin 0.8s linear infinite;\n }\n .shk-loading-spinner-label {\n font-size: 0.8125rem;\n color: var(--shk-surface-500);\n }\n @keyframes shk-loading-spin {\n to {\n transform: rotate(360deg);\n }\n }\n `,\n ],\n})\nexport class LoadingSpinnerComponent {\n /** Diameter of the spinner. */\n size = input<string>('2rem');\n /** Border thickness in px. */\n thickness = input<number>(3);\n /** Color of the moving arc. Defaults to the primary token. */\n color = input<string>('');\n /** Optional text shown under the spinner. */\n label = input<string>('');\n}\n","import { Component, computed, input, ChangeDetectionStrategy } from '@angular/core';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/** Progress bar with an indeterminate sweep or a determinate percentage. */\n@Component({\n selector: 'shk-loading-bar',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div\n class=\"shk-loading-bar\"\n [class.shk-loading-bar-indeterminate]=\"indeterminate()\"\n [style]=\"{ height: height(), borderRadius: rounded() ? '9999px' : undefined }\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"indeterminate() ? undefined : progress()\"\n aria-label=\"Progreso\"\n >\n <div\n class=\"shk-loading-bar-fill\"\n [style]=\"fillStyle()\"\n [style.background-color]=\"color() || undefined\"\n [style.border-radius]=\"rounded() ? '9999px' : undefined\"\n ></div>\n </div>\n `,\n styles: [\n `\n .shk-loading-bar {\n width: 100%;\n position: relative;\n overflow: hidden;\n background-color: var(--shk-surface-200);\n }\n .shk-loading-bar-fill {\n height: 100%;\n background-color: var(--shk-primary-600);\n transition: width 0.3s ease-in-out;\n }\n .shk-loading-bar-indeterminate .shk-loading-bar-fill {\n width: 40%;\n animation: shk-loading-bar-sweep 1.2s ease-in-out infinite;\n }\n @keyframes shk-loading-bar-sweep {\n 0% {\n transform: translateX(-100%);\n }\n 100% {\n transform: translateX(350%);\n }\n }\n `,\n ],\n})\nexport class LoadingBarComponent {\n /** Height of the bar. */\n height = input<string>('0.25rem');\n /** When true the bar animates without a known percentage. */\n indeterminate = input<boolean>(true);\n /** Current progress 0-100 when `indeterminate` is false. */\n progress = input<number>(0);\n /** Fill color. Defaults to the primary token. */\n color = input<string>('');\n /** Renders fully rounded ends. */\n rounded = input<boolean>(true);\n\n /** Fill width/style for the determinate mode, empty for indeterminate. */\n protected fillStyle = computed(() => {\n if (this.indeterminate()) return {};\n return { width: `${Math.max(0, Math.min(100, this.progress()))}%` };\n });\n}\n","import { Component, input, ChangeDetectionStrategy } from '@angular/core';\nimport { LoadingSpinnerComponent } from './loading-spinner.component';\n\n/** Backdrop style behind the overlay: none, light or dark. */\nexport type LoadingOverlayBackdrop = 'transparent' | 'light' | 'dark';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/** Wraps content and shows a centered spinner over it while `visible` is true. */\n@Component({\n selector: 'shk-loading-overlay',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [LoadingSpinnerComponent],\n template: `\n <div\n class=\"shk-loading-overlay\"\n [class.shk-loading-overlay-light]=\"backdrop() === 'light'\"\n [class.shk-loading-overlay-dark]=\"backdrop() === 'dark'\"\n >\n <ng-content></ng-content>\n @if (visible()) {\n <div class=\"shk-loading-overlay-layer\">\n <shk-loading-spinner [size]=\"spinnerSize()\" [color]=\"color()\" [label]=\"message()\" />\n </div>\n }\n </div>\n `,\n styles: [\n `\n :host {\n display: block;\n }\n .shk-loading-overlay {\n position: relative;\n min-height: 1.5rem;\n }\n .shk-loading-overlay-layer {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n }\n .shk-loading-overlay-light .shk-loading-overlay-layer {\n background-color: rgba(255, 255, 255, 0.65);\n }\n :host-context(.dark) .shk-loading-overlay-light .shk-loading-overlay-layer {\n background-color: rgba(0, 0, 0, 0.55);\n }\n .shk-loading-overlay-dark .shk-loading-overlay-layer {\n background-color: rgba(0, 0, 0, 0.4);\n }\n `,\n ],\n})\nexport class LoadingOverlayComponent {\n /** Controls whether the spinner layer is shown. */\n visible = input<boolean>(false);\n /** Optional text under the spinner. */\n message = input<string>('');\n /** Diameter of the spinner. */\n spinnerSize = input<string>('2.5rem');\n /** Spinner color. Defaults to the primary token. */\n color = input<string>('');\n /** Backdrop behind the spinner. */\n backdrop = input<LoadingOverlayBackdrop>('transparent');\n}\n","import { Component, computed, input, ChangeDetectionStrategy } from '@angular/core';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/** Bouncing dots loading indicator. */\n@Component({\n selector: 'shk-loading-dots',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <span class=\"shk-loading-dots\" role=\"status\" aria-label=\"Cargando\">\n @for (dot of dots(); track $index) {\n <span\n class=\"shk-loading-dot\"\n [style]=\"{\n width: size(),\n height: size(),\n backgroundColor: color() || undefined,\n animationDelay: $index * 0.12 + 's',\n }\"\n ></span>\n }\n </span>\n @if (label()) {\n <span class=\"shk-loading-dots-label\">{{ label() }}</span>\n }\n `,\n styles: [\n `\n :host {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n }\n .shk-loading-dots {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n }\n .shk-loading-dot {\n border-radius: 9999px;\n background-color: var(--shk-primary-600);\n animation: shk-loading-dots-bounce 1.4s ease-in-out infinite;\n }\n .shk-loading-dots-label {\n font-size: 0.8125rem;\n color: var(--shk-surface-500);\n }\n @keyframes shk-loading-dots-bounce {\n 0%,\n 80%,\n 100% {\n transform: scale(0.6);\n opacity: 0.5;\n }\n 40% {\n transform: scale(1);\n opacity: 1;\n }\n }\n `,\n ],\n})\nexport class LoadingDotsComponent {\n /** Diameter of each dot. */\n size = input<string>('0.5rem');\n /** Dot color. Defaults to the primary token. */\n color = input<string>('');\n /** Number of dots. */\n count = input<number>(3);\n /** Optional text shown next to the dots. */\n label = input<string>('');\n\n /** Array of dot indices to render based on the `count` input. */\n protected dots = computed(() => Array.from({ length: Math.max(1, this.count()) }));\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -275,11 +275,11 @@ class ModalComponent {
|
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
277
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
278
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: ModalComponent, isStandalone: true, selector: "shk-modal", viewQueries: [{ propertyName: "container", first: true, predicate: ["dynamicContent"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "@if (visible()) {\n <div\n class=\"fixed inset-0 bg-black/40 backdrop-blur-sm flex items-center justify-center z-40 p-4 pt-4 overflow-y-auto _shk-scrollbar\"\n (click)=\"closeModal()\"\n >\n <div\n class=\"bg-white dark:[background-color:var(--shk-surface-100)] rounded-xl shadow-2xl overflow-hidden flex flex-col
|
|
278
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: ModalComponent, isStandalone: true, selector: "shk-modal", viewQueries: [{ propertyName: "container", first: true, predicate: ["dynamicContent"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "@if (visible()) {\n <div\n class=\"shk-dialog-backdrop fixed inset-0 bg-black/40 backdrop-blur-sm flex items-center justify-center z-40 p-4 pt-4 overflow-y-auto _shk-scrollbar\"\n (click)=\"closeModal()\"\n >\n <div\n class=\"shk-dialog-panel bg-white dark:[background-color:var(--shk-surface-100)] rounded-xl shadow-2xl overflow-hidden flex flex-col\"\n [class.w-[95vw]]=\"isExpanded()\"\n [class.h-[90vh]]=\"isExpanded()\"\n [class.w-full]=\"!isExpanded()\"\n [style.max-width]=\"isExpanded() ? undefined : computedModalWidth()\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"shk-modal-header flex items-center justify-between px-6 pt-4 pb-2 shrink-0\">\n <span class=\"font-semibold text-lg _shk-text-surface-800 dark:[color:var(--shk-surface-800)]\">{{ title() }}</span>\n <div class=\"flex items-center gap-2\">\n @if (showExpandButton()) {\n <button\n type=\"button\"\n (click)=\"toggleExpand()\"\n class=\"p-1.5 rounded-lg hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] _shk-text-surface-500 dark:[color:var(--shk-surface-500)] transition-colors\"\n >\n @if (isExpanded()) {\n <svg [lucideIcon]=\"getIcon('minimize-2')\" class=\"w-4 h-4\"></svg>\n } @else {\n <svg [lucideIcon]=\"getIcon('maximize-2')\" class=\"w-4 h-4\"></svg>\n }\n </button>\n }\n <button\n type=\"button\"\n (click)=\"closeModal()\"\n class=\"p-1.5 rounded-lg hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] _shk-text-surface-500 dark:[color:var(--shk-surface-500)] transition-colors\"\n >\n <svg [lucideIcon]=\"getIcon('x')\" class=\"w-4 h-4\"></svg>\n </button>\n </div>\n </div>\n\n <div class=\"overflow-y-auto px-6 py-4 flex-1 max-h-[70vh] _shk-scrollbar\">\n <ng-container #dynamicContent></ng-container>\n </div>\n\n @if (modalButtonsVisible()) {\n <hr class=\"border-t _shk-border dark:[border-color:var(--shk-surface-200)] shrink-0\" />\n <div class=\"flex justify-end gap-3 px-6 py-4 shrink-0\">\n <button\n type=\"button\"\n (click)=\"closeModal()\"\n [disabled]=\"loading()\"\n class=\"px-4 py-2 text-sm font-semibold _shk-text-surface-600 dark:[color:var(--shk-surface-600)] _shk-bg-surface-100 dark:[background-color:var(--shk-surface-200)] hover:[background-color:var(--shk-surface-200)] dark:hover:[background-color:var(--shk-surface-300)] rounded-lg transition-colors flex items-center gap-2 disabled:opacity-50\"\n >\n <svg [lucideIcon]=\"getIcon('x')\" class=\"w-4 h-4\"></svg>\n {{ cancelLabel() }}\n </button>\n <button\n type=\"button\"\n (click)=\"onAccept()\"\n [disabled]=\"loading()\"\n class=\"px-4 py-2 text-sm font-semibold _shk-text-white _shk-bg-emerald hover:[background-color:var(--shk-emerald-700)] rounded-lg shadow-md transition-all flex items-center gap-2 disabled:opacity-50\"\n >\n @if (loading()) {\n <svg [lucideIcon]=\"getIcon('loader-circle')\" class=\"w-4 h-4 animate-spin\"></svg>\n } @else {\n <svg [lucideIcon]=\"getIcon('check')\" class=\"w-4 h-4\"></svg>\n }\n {{ acceptLabel() }}\n </button>\n </div>\n }\n </div>\n </div>\n}\n", styles: [".shk-dialog-backdrop{animation:shk-dialog-fade .15s ease-out}.shk-dialog-panel{border:1px solid var(--shk-surface-200);box-shadow:0 24px 48px -12px #00000040,0 8px 16px -8px #0000001a;animation:shk-dialog-in .2s cubic-bezier(.21,1.02,.73,1)}:host-context(.dark) .shk-dialog-panel{box-shadow:0 24px 48px -12px #000000b3,0 8px 16px -8px #00000080}@keyframes shk-dialog-fade{0%{opacity:0}}@keyframes shk-dialog-in{0%{opacity:0;transform:translateY(8px) scale(.97)}}.shk-modal-header{padding-top:1.25rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
279
279
|
}
|
|
280
280
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: ModalComponent, decorators: [{
|
|
281
281
|
type: Component,
|
|
282
|
-
args: [{ selector: 'shk-modal', standalone: true, imports: [CommonModule, LucideDynamicIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (visible()) {\n <div\n class=\"fixed inset-0 bg-black/40 backdrop-blur-sm flex items-center justify-center z-40 p-4 pt-4 overflow-y-auto _shk-scrollbar\"\n (click)=\"closeModal()\"\n >\n <div\n class=\"bg-white dark:[background-color:var(--shk-surface-100)] rounded-xl shadow-2xl overflow-hidden flex flex-col
|
|
282
|
+
args: [{ selector: 'shk-modal', standalone: true, imports: [CommonModule, LucideDynamicIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (visible()) {\n <div\n class=\"shk-dialog-backdrop fixed inset-0 bg-black/40 backdrop-blur-sm flex items-center justify-center z-40 p-4 pt-4 overflow-y-auto _shk-scrollbar\"\n (click)=\"closeModal()\"\n >\n <div\n class=\"shk-dialog-panel bg-white dark:[background-color:var(--shk-surface-100)] rounded-xl shadow-2xl overflow-hidden flex flex-col\"\n [class.w-[95vw]]=\"isExpanded()\"\n [class.h-[90vh]]=\"isExpanded()\"\n [class.w-full]=\"!isExpanded()\"\n [style.max-width]=\"isExpanded() ? undefined : computedModalWidth()\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"shk-modal-header flex items-center justify-between px-6 pt-4 pb-2 shrink-0\">\n <span class=\"font-semibold text-lg _shk-text-surface-800 dark:[color:var(--shk-surface-800)]\">{{ title() }}</span>\n <div class=\"flex items-center gap-2\">\n @if (showExpandButton()) {\n <button\n type=\"button\"\n (click)=\"toggleExpand()\"\n class=\"p-1.5 rounded-lg hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] _shk-text-surface-500 dark:[color:var(--shk-surface-500)] transition-colors\"\n >\n @if (isExpanded()) {\n <svg [lucideIcon]=\"getIcon('minimize-2')\" class=\"w-4 h-4\"></svg>\n } @else {\n <svg [lucideIcon]=\"getIcon('maximize-2')\" class=\"w-4 h-4\"></svg>\n }\n </button>\n }\n <button\n type=\"button\"\n (click)=\"closeModal()\"\n class=\"p-1.5 rounded-lg hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] _shk-text-surface-500 dark:[color:var(--shk-surface-500)] transition-colors\"\n >\n <svg [lucideIcon]=\"getIcon('x')\" class=\"w-4 h-4\"></svg>\n </button>\n </div>\n </div>\n\n <div class=\"overflow-y-auto px-6 py-4 flex-1 max-h-[70vh] _shk-scrollbar\">\n <ng-container #dynamicContent></ng-container>\n </div>\n\n @if (modalButtonsVisible()) {\n <hr class=\"border-t _shk-border dark:[border-color:var(--shk-surface-200)] shrink-0\" />\n <div class=\"flex justify-end gap-3 px-6 py-4 shrink-0\">\n <button\n type=\"button\"\n (click)=\"closeModal()\"\n [disabled]=\"loading()\"\n class=\"px-4 py-2 text-sm font-semibold _shk-text-surface-600 dark:[color:var(--shk-surface-600)] _shk-bg-surface-100 dark:[background-color:var(--shk-surface-200)] hover:[background-color:var(--shk-surface-200)] dark:hover:[background-color:var(--shk-surface-300)] rounded-lg transition-colors flex items-center gap-2 disabled:opacity-50\"\n >\n <svg [lucideIcon]=\"getIcon('x')\" class=\"w-4 h-4\"></svg>\n {{ cancelLabel() }}\n </button>\n <button\n type=\"button\"\n (click)=\"onAccept()\"\n [disabled]=\"loading()\"\n class=\"px-4 py-2 text-sm font-semibold _shk-text-white _shk-bg-emerald hover:[background-color:var(--shk-emerald-700)] rounded-lg shadow-md transition-all flex items-center gap-2 disabled:opacity-50\"\n >\n @if (loading()) {\n <svg [lucideIcon]=\"getIcon('loader-circle')\" class=\"w-4 h-4 animate-spin\"></svg>\n } @else {\n <svg [lucideIcon]=\"getIcon('check')\" class=\"w-4 h-4\"></svg>\n }\n {{ acceptLabel() }}\n </button>\n </div>\n }\n </div>\n </div>\n}\n", styles: [".shk-dialog-backdrop{animation:shk-dialog-fade .15s ease-out}.shk-dialog-panel{border:1px solid var(--shk-surface-200);box-shadow:0 24px 48px -12px #00000040,0 8px 16px -8px #0000001a;animation:shk-dialog-in .2s cubic-bezier(.21,1.02,.73,1)}:host-context(.dark) .shk-dialog-panel{box-shadow:0 24px 48px -12px #000000b3,0 8px 16px -8px #00000080}@keyframes shk-dialog-fade{0%{opacity:0}}@keyframes shk-dialog-in{0%{opacity:0;transform:translateY(8px) scale(.97)}}.shk-modal-header{padding-top:1.25rem}\n"] }]
|
|
283
283
|
}], ctorParameters: () => [], propDecorators: { container: [{ type: i0.ViewChild, args: ['dynamicContent', { ...{ read: ViewContainerRef }, isSignal: true }] }] } });
|
|
284
284
|
|
|
285
285
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shirkasoft-ui-components-modal.mjs","sources":["../../../projects/ui-components/modal/modal.service.ts","../../../projects/ui-components/modal/modal.component.ts","../../../projects/ui-components/modal/modal.component.html","../../../projects/ui-components/modal/shirkasoft-ui-components-modal.ts"],"sourcesContent":["import { Injectable, Type, signal, computed, inject, DestroyRef } from '@angular/core';\nimport { Router } from '@angular/router';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/** Options for opening a modal through the service. */\nexport interface ModalConfig {\n /** Title shown in the modal header. */\n title: string;\n /** Component rendered inside the modal body. */\n component: Type<any>;\n /** Data passed to the modal component via inputs. */\n data?: Record<string, any>;\n /** Modal width (CSS value). */\n width?: string;\n /** Whether the accept/cancel buttons are shown. */\n showButtons?: boolean;\n /** Whether the expand (fullscreen) button is shown. */\n showExpandButton?: boolean;\n /** Label of the accept button. */\n acceptLabel?: string;\n /** Label of the cancel button. */\n cancelLabel?: string;\n /** Optional callback invoked when the modal closes. */\n onClose?: () => void;\n}\n\n/**\n * Global modal manager. Opens modals on a stack, exposing reactive access to\n * the current modal and the top-most opened config.\n */\n@Injectable({ providedIn: 'root' })\nexport class ModalService {\n /** Stack of open modals (top-most renders on top). */\n private stackSignal = signal<ModalConfig[]>([]);\n /** Counter emitted on each close, used to trigger close animations. */\n private closeRequestSignal = signal<number>(0);\n private router = inject(Router);\n private destroyRef = inject(DestroyRef);\n\n constructor() {\n // Close all modals on navigation and on service destruction.\n this.router.events.subscribe(() => {\n this.stackSignal.set([]);\n });\n this.destroyRef.onDestroy(() => this.stackSignal.set([]));\n }\n\n /** Reactive list of open modals. */\n modalStack = computed(() => this.stackSignal());\n /** Top-most modal on the stack, or null. */\n currentModal = computed<ModalConfig | null>(() => {\n const stack = this.stackSignal();\n return stack.length > 0 ? stack[stack.length - 1] : null;\n });\n /** Reactive close-request counter. */\n closeRequest = computed(() => this.closeRequestSignal());\n\n /** Opens a new modal on top of the stack. */\n open(config: ModalConfig) {\n this.stackSignal.update((stack) => [...stack, config]);\n }\n\n /** Alias of `close()` used by the accept button. */\n accept() {\n this.close();\n }\n\n /** Closes the top-most modal, invoking its onClose callback. */\n close() {\n const stack = this.stackSignal();\n if (stack.length > 0) {\n stack[stack.length - 1]?.onClose?.();\n this.stackSignal.set(stack.slice(0, -1));\n this.closeRequestSignal.update((v) => v + 1);\n }\n }\n\n /** Closes all open modals at once. */\n clear() {\n this.stackSignal.set([]);\n }\n}","import {\n Component,\n viewChild,\n ViewContainerRef,\n ComponentRef,\n inject,\n effect,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n signal,\n DestroyRef,\n computed,\n untracked,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport {\n LucideDynamicIcon,\n LucideX,\n} from '@lucide/angular';\nimport { Subscription } from 'rxjs';\nimport { FormControl, FormGroup } from '@angular/forms';\nimport { TranslocoService } from '@jsverse/transloco';\nimport { ModalService, ModalConfig } from './modal.service';\nimport { NotificationService } from 'shirkasoft-ui-components/notification';\nimport { getIcon as getIconFromCentral } from 'shirkasoft-ui-components/utils';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/**\n * Modal dialog that renders a dynamically loaded component, tracks its\n * form validity and submit outputs, and delegates accept/cancel to the\n * shared ModalService.\n */\n@Component({\n selector: 'shk-modal',\n standalone: true,\n imports: [CommonModule, LucideDynamicIcon],\n templateUrl: './modal.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ModalComponent {\n protected getIcon = (name: any) => getIconFromCentral(name, LucideX);\n\n private notificationSrv = inject(NotificationService);\n private destroyRef = inject(DestroyRef);\n private modalSrv = inject(ModalService);\n private transloco = inject(TranslocoService);\n private cdr = inject(ChangeDetectorRef);\n\n /** Reference where the dynamic content is rendered. */\n container = viewChild('dynamicContent', { read: ViewContainerRef });\n\n /** Configuration of the modal currently open (from the service). */\n currentConfig = signal<ModalConfig | null>(null);\n /** Modal title. */\n title = signal('');\n /** Whether the modal is visible. */\n visible = signal(false);\n /** Generic loading flag for the footer actions. */\n loading = signal(false);\n /** Whether the accept action is being processed. */\n isProcessing = signal(false);\n /** Whether the modal is currently expanded to fullscreen. */\n isExpanded = signal(false);\n /** True when the dynamic component reports a valid form. */\n isFormValid = signal(false);\n\n /** Reference to the dynamically created component. */\n componentRef: ComponentRef<any> | null = null;\n /** Subscriptions to the dynamic component outputs. */\n private subscriptions: Subscription[] = [];\n\n /** Width of the modal (fullscreen when expanded). */\n computedModalWidth = computed(() => {\n return this.isExpanded() ? '100vw' : (this.currentConfig()?.width ?? '560px');\n });\n\n /** Whether the footer buttons should be rendered. */\n modalButtonsVisible = computed(() => this.currentConfig()?.showButtons ?? true);\n /** Whether the expand/fullscreen button is shown. */\n showExpandButton = computed(() => this.currentConfig()?.showExpandButton ?? false);\n /** Resolved cancel button label. */\n cancelLabel = computed(() => this.currentConfig()?.cancelLabel || 'Cancelar');\n /** Resolved accept button label. */\n acceptLabel = computed(() => this.currentConfig()?.acceptLabel || 'Aceptar');\n\n constructor() {\n effect(() => {\n const config = this.modalSrv.currentModal();\n if (config) {\n this.currentConfig.set(config);\n this.title.set(config.title);\n this.isExpanded.set(false);\n this.visible.set(true);\n this.isProcessing.set(false);\n this.loading.set(false);\n this.cdr.markForCheck();\n setTimeout(() => {\n untracked(() => this.loadComponent(config));\n });\n } else {\n this.visible.set(false);\n this.currentConfig.set(null);\n this.cdr.markForCheck();\n }\n });\n\n this.destroyRef.onDestroy(() => this.cleanup());\n }\n\n /** Updates visibility when the backdrop/close controls change. */\n onVisibleChange(show: boolean) {\n this.visible.set(show);\n if (!show) {\n this.closeModal();\n }\n this.cdr.markForCheck();\n }\n\n /** Creates the dynamic component and wires its form/submit outputs. */\n private loadComponent(config: ModalConfig) {\n const containerRef = this.container();\n if (!containerRef) return;\n\n this.cleanup();\n containerRef.clear();\n\n this.componentRef = containerRef.createComponent(config.component);\n\n if (config.data) {\n Object.entries(config.data).forEach(([key, value]) => {\n this.componentRef?.setInput(key, value);\n });\n }\n\n const instance = this.componentRef.instance;\n\n this.subscribeToOutput(instance.formValid, (valid: boolean) => {\n this.isFormValid.set(valid);\n this.cdr.markForCheck();\n });\n this.subscribeToOutput(instance.submitSuccess, () =>\n this.handleSubmit(true),\n );\n this.subscribeToOutput(instance.submitError, () =>\n this.handleSubmit(false),\n );\n\n this.componentRef.changeDetectorRef.markForCheck();\n this.cdr.markForCheck();\n }\n\n /** Subscribes to a dynamic component output if it exists. */\n private subscribeToOutput(output: any, callback: (value: any) => void) {\n if (output?.subscribe) {\n this.subscriptions.push(output.subscribe(callback));\n }\n }\n\n /** Finalizes the submit flow, accepting the modal on success. */\n private handleSubmit(success: boolean) {\n this.isProcessing.set(false);\n this.loading.set(false);\n this.cdr.markForCheck();\n if (success) {\n untracked(() => this.modalSrv.accept());\n }\n }\n\n /** Closes the modal, calling the dynamic component's `handleCancel` if any. */\n closeModal() {\n if (this.componentRef?.instance?.handleCancel) {\n this.componentRef.instance.handleCancel();\n }\n this.doClose();\n }\n\n /** Performs the actual close sequence and cleanup. */\n doClose() {\n this.visible.set(false);\n this.isProcessing.set(false);\n this.loading.set(false);\n if (this.isExpanded()) {\n this.isExpanded.set(false);\n }\n this.cdr.markForCheck();\n setTimeout(() => {\n this.cleanup();\n this.modalSrv.close();\n }, 100);\n }\n\n /** Toggles between normal width and fullscreen. */\n toggleExpand() {\n this.isExpanded.update((v) => !v);\n this.cdr.markForCheck();\n }\n\n /** Validates the dynamic component form and triggers its `onSubmit`. */\n onAccept() {\n if (!this.componentRef || !this.isDynamicComponent(this.componentRef.instance)) return;\n\n if (this.isProcessing()) return;\n\n const instance = this.componentRef.instance;\n const form = this.getForm(instance);\n\n if (form) {\n this.markAllAsTouched(form);\n this.componentRef.changeDetectorRef.markForCheck();\n this.cdr.markForCheck();\n\n if (this.hasRealErrors(form)) {\n this.notificationSrv.addNotification(\n this.transloco.translate('modal.formInvalid'),\n 'warning',\n );\n return;\n }\n }\n\n this.isProcessing.set(true);\n this.loading.set(true);\n this.cdr.markForCheck();\n instance.onSubmit();\n }\n\n /** Resolves the dynamic component's form (property or getter function). */\n private getForm(instance: any): FormGroup | null {\n if (!instance['form']) return null;\n return typeof instance['form'] === 'function'\n ? instance['form']()\n : instance['form'];\n }\n\n /** Recursively checks for real validation errors (ignoring 'warning'). */\n private hasRealErrors(control: FormGroup | FormControl): boolean {\n if (control instanceof FormControl) {\n const errors = control.errors;\n return errors\n ? Object.keys(errors).some((key) => key !== 'warning')\n : false;\n }\n\n const groupErrors = control.errors;\n if (\n groupErrors &&\n Object.keys(groupErrors).some((key) => key !== 'warning')\n ) {\n return true;\n }\n\n return Object.values(control.controls).some((child) =>\n this.hasRealErrors(child as any),\n );\n }\n\n /** Marks a form (and all its descendants) as touched. */\n private markAllAsTouched(control: FormGroup | FormControl): void {\n control.markAsTouched();\n control.updateValueAndValidity({ onlySelf: true, emitEvent: true });\n\n if (control instanceof FormGroup) {\n Object.values(control.controls).forEach((child) =>\n this.markAllAsTouched(child as any),\n );\n }\n }\n\n /** True when the component exposes both `onSubmit` and a `form`. */\n private isDynamicComponent(instance: any): boolean {\n return typeof instance?.onSubmit === 'function' && instance?.form !== undefined;\n }\n\n /** Unsubscribes outputs and destroys the dynamic component. */\n private cleanup() {\n this.subscriptions.forEach((sub) => sub.unsubscribe());\n this.subscriptions = [];\n\n if (this.componentRef) {\n this.componentRef.destroy();\n this.componentRef = null;\n }\n }\n}\n","@if (visible()) {\n <div\n class=\"fixed inset-0 bg-black/40 backdrop-blur-sm flex items-center justify-center z-40 p-4 pt-4 overflow-y-auto _shk-scrollbar\"\n (click)=\"closeModal()\"\n >\n <div\n class=\"bg-white dark:[background-color:var(--shk-surface-100)] rounded-xl shadow-2xl overflow-hidden flex flex-col animate-in fade-in zoom-in duration-200\"\n [class.w-[95vw]]=\"isExpanded()\"\n [class.h-[90vh]]=\"isExpanded()\"\n [class.w-full]=\"!isExpanded()\"\n [style.max-width]=\"isExpanded() ? undefined : computedModalWidth()\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"h-1.5 w-full _shk-gradient-emerald shrink-0\"></div>\n\n <div class=\"flex items-center justify-between px-6 pt-4 pb-2 shrink-0\">\n <span class=\"font-semibold text-lg _shk-text-surface-800 dark:[color:var(--shk-surface-800)]\">{{ title() }}</span>\n <div class=\"flex items-center gap-2\">\n @if (showExpandButton()) {\n <button\n type=\"button\"\n (click)=\"toggleExpand()\"\n class=\"p-1.5 rounded-lg hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] _shk-text-surface-500 dark:[color:var(--shk-surface-500)] transition-colors\"\n >\n @if (isExpanded()) {\n <svg [lucideIcon]=\"getIcon('minimize-2')\" class=\"w-4 h-4\"></svg>\n } @else {\n <svg [lucideIcon]=\"getIcon('maximize-2')\" class=\"w-4 h-4\"></svg>\n }\n </button>\n }\n <button\n type=\"button\"\n (click)=\"closeModal()\"\n class=\"p-1.5 rounded-lg hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] _shk-text-surface-500 dark:[color:var(--shk-surface-500)] transition-colors\"\n >\n <svg [lucideIcon]=\"getIcon('x')\" class=\"w-4 h-4\"></svg>\n </button>\n </div>\n </div>\n\n <div class=\"overflow-y-auto px-6 py-4 flex-1 max-h-[70vh] _shk-scrollbar\">\n <ng-container #dynamicContent></ng-container>\n </div>\n\n @if (modalButtonsVisible()) {\n <hr class=\"border-t _shk-border dark:[border-color:var(--shk-surface-200)] shrink-0\" />\n <div class=\"flex justify-end gap-3 px-6 py-4 shrink-0\">\n <button\n type=\"button\"\n (click)=\"closeModal()\"\n [disabled]=\"loading()\"\n class=\"px-4 py-2 text-sm font-semibold _shk-text-surface-600 dark:[color:var(--shk-surface-600)] _shk-bg-surface-100 dark:[background-color:var(--shk-surface-200)] hover:[background-color:var(--shk-surface-200)] dark:hover:[background-color:var(--shk-surface-300)] rounded-lg transition-colors flex items-center gap-2 disabled:opacity-50\"\n >\n <svg [lucideIcon]=\"getIcon('x')\" class=\"w-4 h-4\"></svg>\n {{ cancelLabel() }}\n </button>\n <button\n type=\"button\"\n (click)=\"onAccept()\"\n [disabled]=\"loading()\"\n class=\"px-4 py-2 text-sm font-semibold _shk-text-white _shk-bg-emerald hover:[background-color:var(--shk-emerald-700)] rounded-lg shadow-md transition-all flex items-center gap-2 disabled:opacity-50\"\n >\n @if (loading()) {\n <svg [lucideIcon]=\"getIcon('loader-circle')\" class=\"w-4 h-4 animate-spin\"></svg>\n } @else {\n <svg [lucideIcon]=\"getIcon('check')\" class=\"w-4 h-4\"></svg>\n }\n {{ acceptLabel() }}\n </button>\n </div>\n }\n </div>\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["getIconFromCentral"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shirkasoft-ui-components-modal.mjs","sources":["../../../projects/ui-components/modal/modal.service.ts","../../../projects/ui-components/modal/modal.component.ts","../../../projects/ui-components/modal/modal.component.html","../../../projects/ui-components/modal/shirkasoft-ui-components-modal.ts"],"sourcesContent":["import { Injectable, Type, signal, computed, inject, DestroyRef } from '@angular/core';\nimport { Router } from '@angular/router';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/** Options for opening a modal through the service. */\nexport interface ModalConfig {\n /** Title shown in the modal header. */\n title: string;\n /** Component rendered inside the modal body. */\n component: Type<any>;\n /** Data passed to the modal component via inputs. */\n data?: Record<string, any>;\n /** Modal width (CSS value). */\n width?: string;\n /** Whether the accept/cancel buttons are shown. */\n showButtons?: boolean;\n /** Whether the expand (fullscreen) button is shown. */\n showExpandButton?: boolean;\n /** Label of the accept button. */\n acceptLabel?: string;\n /** Label of the cancel button. */\n cancelLabel?: string;\n /** Optional callback invoked when the modal closes. */\n onClose?: () => void;\n}\n\n/**\n * Global modal manager. Opens modals on a stack, exposing reactive access to\n * the current modal and the top-most opened config.\n */\n@Injectable({ providedIn: 'root' })\nexport class ModalService {\n /** Stack of open modals (top-most renders on top). */\n private stackSignal = signal<ModalConfig[]>([]);\n /** Counter emitted on each close, used to trigger close animations. */\n private closeRequestSignal = signal<number>(0);\n private router = inject(Router);\n private destroyRef = inject(DestroyRef);\n\n constructor() {\n // Close all modals on navigation and on service destruction.\n this.router.events.subscribe(() => {\n this.stackSignal.set([]);\n });\n this.destroyRef.onDestroy(() => this.stackSignal.set([]));\n }\n\n /** Reactive list of open modals. */\n modalStack = computed(() => this.stackSignal());\n /** Top-most modal on the stack, or null. */\n currentModal = computed<ModalConfig | null>(() => {\n const stack = this.stackSignal();\n return stack.length > 0 ? stack[stack.length - 1] : null;\n });\n /** Reactive close-request counter. */\n closeRequest = computed(() => this.closeRequestSignal());\n\n /** Opens a new modal on top of the stack. */\n open(config: ModalConfig) {\n this.stackSignal.update((stack) => [...stack, config]);\n }\n\n /** Alias of `close()` used by the accept button. */\n accept() {\n this.close();\n }\n\n /** Closes the top-most modal, invoking its onClose callback. */\n close() {\n const stack = this.stackSignal();\n if (stack.length > 0) {\n stack[stack.length - 1]?.onClose?.();\n this.stackSignal.set(stack.slice(0, -1));\n this.closeRequestSignal.update((v) => v + 1);\n }\n }\n\n /** Closes all open modals at once. */\n clear() {\n this.stackSignal.set([]);\n }\n}","import {\n Component,\n viewChild,\n ViewContainerRef,\n ComponentRef,\n inject,\n effect,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n signal,\n DestroyRef,\n computed,\n untracked,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport {\n LucideDynamicIcon,\n LucideX,\n} from '@lucide/angular';\nimport { Subscription } from 'rxjs';\nimport { FormControl, FormGroup } from '@angular/forms';\nimport { TranslocoService } from '@jsverse/transloco';\nimport { ModalService, ModalConfig } from './modal.service';\nimport { NotificationService } from 'shirkasoft-ui-components/notification';\nimport { getIcon as getIconFromCentral } from 'shirkasoft-ui-components/utils';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/**\n * Modal dialog that renders a dynamically loaded component, tracks its\n * form validity and submit outputs, and delegates accept/cancel to the\n * shared ModalService.\n */\n@Component({\n selector: 'shk-modal',\n standalone: true,\n imports: [CommonModule, LucideDynamicIcon],\n templateUrl: './modal.component.html',\n styles: [\n `\n /* Own enter animation (the animate-in/zoom-in utilities used before\n need a Tailwind plugin that isn't part of the library). */\n .shk-dialog-backdrop {\n animation: shk-dialog-fade 0.15s ease-out;\n }\n .shk-dialog-panel {\n border: 1px solid var(--shk-surface-200);\n box-shadow:\n 0 24px 48px -12px rgba(0, 0, 0, 0.25),\n 0 8px 16px -8px rgba(0, 0, 0, 0.1);\n animation: shk-dialog-in 0.2s cubic-bezier(0.21, 1.02, 0.73, 1);\n }\n :host-context(.dark) .shk-dialog-panel {\n box-shadow:\n 0 24px 48px -12px rgba(0, 0, 0, 0.7),\n 0 8px 16px -8px rgba(0, 0, 0, 0.5);\n }\n @keyframes shk-dialog-fade {\n from {\n opacity: 0;\n }\n }\n @keyframes shk-dialog-in {\n from {\n opacity: 0;\n transform: translateY(8px) scale(0.97);\n }\n }\n .shk-modal-header {\n padding-top: 1.25rem;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ModalComponent {\n protected getIcon = (name: any) => getIconFromCentral(name, LucideX);\n\n private notificationSrv = inject(NotificationService);\n private destroyRef = inject(DestroyRef);\n private modalSrv = inject(ModalService);\n private transloco = inject(TranslocoService);\n private cdr = inject(ChangeDetectorRef);\n\n /** Reference where the dynamic content is rendered. */\n container = viewChild('dynamicContent', { read: ViewContainerRef });\n\n /** Configuration of the modal currently open (from the service). */\n currentConfig = signal<ModalConfig | null>(null);\n /** Modal title. */\n title = signal('');\n /** Whether the modal is visible. */\n visible = signal(false);\n /** Generic loading flag for the footer actions. */\n loading = signal(false);\n /** Whether the accept action is being processed. */\n isProcessing = signal(false);\n /** Whether the modal is currently expanded to fullscreen. */\n isExpanded = signal(false);\n /** True when the dynamic component reports a valid form. */\n isFormValid = signal(false);\n\n /** Reference to the dynamically created component. */\n componentRef: ComponentRef<any> | null = null;\n /** Subscriptions to the dynamic component outputs. */\n private subscriptions: Subscription[] = [];\n\n /** Width of the modal (fullscreen when expanded). */\n computedModalWidth = computed(() => {\n return this.isExpanded() ? '100vw' : (this.currentConfig()?.width ?? '560px');\n });\n\n /** Whether the footer buttons should be rendered. */\n modalButtonsVisible = computed(() => this.currentConfig()?.showButtons ?? true);\n /** Whether the expand/fullscreen button is shown. */\n showExpandButton = computed(() => this.currentConfig()?.showExpandButton ?? false);\n /** Resolved cancel button label. */\n cancelLabel = computed(() => this.currentConfig()?.cancelLabel || 'Cancelar');\n /** Resolved accept button label. */\n acceptLabel = computed(() => this.currentConfig()?.acceptLabel || 'Aceptar');\n\n constructor() {\n effect(() => {\n const config = this.modalSrv.currentModal();\n if (config) {\n this.currentConfig.set(config);\n this.title.set(config.title);\n this.isExpanded.set(false);\n this.visible.set(true);\n this.isProcessing.set(false);\n this.loading.set(false);\n this.cdr.markForCheck();\n setTimeout(() => {\n untracked(() => this.loadComponent(config));\n });\n } else {\n this.visible.set(false);\n this.currentConfig.set(null);\n this.cdr.markForCheck();\n }\n });\n\n this.destroyRef.onDestroy(() => this.cleanup());\n }\n\n /** Updates visibility when the backdrop/close controls change. */\n onVisibleChange(show: boolean) {\n this.visible.set(show);\n if (!show) {\n this.closeModal();\n }\n this.cdr.markForCheck();\n }\n\n /** Creates the dynamic component and wires its form/submit outputs. */\n private loadComponent(config: ModalConfig) {\n const containerRef = this.container();\n if (!containerRef) return;\n\n this.cleanup();\n containerRef.clear();\n\n this.componentRef = containerRef.createComponent(config.component);\n\n if (config.data) {\n Object.entries(config.data).forEach(([key, value]) => {\n this.componentRef?.setInput(key, value);\n });\n }\n\n const instance = this.componentRef.instance;\n\n this.subscribeToOutput(instance.formValid, (valid: boolean) => {\n this.isFormValid.set(valid);\n this.cdr.markForCheck();\n });\n this.subscribeToOutput(instance.submitSuccess, () =>\n this.handleSubmit(true),\n );\n this.subscribeToOutput(instance.submitError, () =>\n this.handleSubmit(false),\n );\n\n this.componentRef.changeDetectorRef.markForCheck();\n this.cdr.markForCheck();\n }\n\n /** Subscribes to a dynamic component output if it exists. */\n private subscribeToOutput(output: any, callback: (value: any) => void) {\n if (output?.subscribe) {\n this.subscriptions.push(output.subscribe(callback));\n }\n }\n\n /** Finalizes the submit flow, accepting the modal on success. */\n private handleSubmit(success: boolean) {\n this.isProcessing.set(false);\n this.loading.set(false);\n this.cdr.markForCheck();\n if (success) {\n untracked(() => this.modalSrv.accept());\n }\n }\n\n /** Closes the modal, calling the dynamic component's `handleCancel` if any. */\n closeModal() {\n if (this.componentRef?.instance?.handleCancel) {\n this.componentRef.instance.handleCancel();\n }\n this.doClose();\n }\n\n /** Performs the actual close sequence and cleanup. */\n doClose() {\n this.visible.set(false);\n this.isProcessing.set(false);\n this.loading.set(false);\n if (this.isExpanded()) {\n this.isExpanded.set(false);\n }\n this.cdr.markForCheck();\n setTimeout(() => {\n this.cleanup();\n this.modalSrv.close();\n }, 100);\n }\n\n /** Toggles between normal width and fullscreen. */\n toggleExpand() {\n this.isExpanded.update((v) => !v);\n this.cdr.markForCheck();\n }\n\n /** Validates the dynamic component form and triggers its `onSubmit`. */\n onAccept() {\n if (!this.componentRef || !this.isDynamicComponent(this.componentRef.instance)) return;\n\n if (this.isProcessing()) return;\n\n const instance = this.componentRef.instance;\n const form = this.getForm(instance);\n\n if (form) {\n this.markAllAsTouched(form);\n this.componentRef.changeDetectorRef.markForCheck();\n this.cdr.markForCheck();\n\n if (this.hasRealErrors(form)) {\n this.notificationSrv.addNotification(\n this.transloco.translate('modal.formInvalid'),\n 'warning',\n );\n return;\n }\n }\n\n this.isProcessing.set(true);\n this.loading.set(true);\n this.cdr.markForCheck();\n instance.onSubmit();\n }\n\n /** Resolves the dynamic component's form (property or getter function). */\n private getForm(instance: any): FormGroup | null {\n if (!instance['form']) return null;\n return typeof instance['form'] === 'function'\n ? instance['form']()\n : instance['form'];\n }\n\n /** Recursively checks for real validation errors (ignoring 'warning'). */\n private hasRealErrors(control: FormGroup | FormControl): boolean {\n if (control instanceof FormControl) {\n const errors = control.errors;\n return errors\n ? Object.keys(errors).some((key) => key !== 'warning')\n : false;\n }\n\n const groupErrors = control.errors;\n if (\n groupErrors &&\n Object.keys(groupErrors).some((key) => key !== 'warning')\n ) {\n return true;\n }\n\n return Object.values(control.controls).some((child) =>\n this.hasRealErrors(child as any),\n );\n }\n\n /** Marks a form (and all its descendants) as touched. */\n private markAllAsTouched(control: FormGroup | FormControl): void {\n control.markAsTouched();\n control.updateValueAndValidity({ onlySelf: true, emitEvent: true });\n\n if (control instanceof FormGroup) {\n Object.values(control.controls).forEach((child) =>\n this.markAllAsTouched(child as any),\n );\n }\n }\n\n /** True when the component exposes both `onSubmit` and a `form`. */\n private isDynamicComponent(instance: any): boolean {\n return typeof instance?.onSubmit === 'function' && instance?.form !== undefined;\n }\n\n /** Unsubscribes outputs and destroys the dynamic component. */\n private cleanup() {\n this.subscriptions.forEach((sub) => sub.unsubscribe());\n this.subscriptions = [];\n\n if (this.componentRef) {\n this.componentRef.destroy();\n this.componentRef = null;\n }\n }\n}\n","@if (visible()) {\n <div\n class=\"shk-dialog-backdrop fixed inset-0 bg-black/40 backdrop-blur-sm flex items-center justify-center z-40 p-4 pt-4 overflow-y-auto _shk-scrollbar\"\n (click)=\"closeModal()\"\n >\n <div\n class=\"shk-dialog-panel bg-white dark:[background-color:var(--shk-surface-100)] rounded-xl shadow-2xl overflow-hidden flex flex-col\"\n [class.w-[95vw]]=\"isExpanded()\"\n [class.h-[90vh]]=\"isExpanded()\"\n [class.w-full]=\"!isExpanded()\"\n [style.max-width]=\"isExpanded() ? undefined : computedModalWidth()\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"shk-modal-header flex items-center justify-between px-6 pt-4 pb-2 shrink-0\">\n <span class=\"font-semibold text-lg _shk-text-surface-800 dark:[color:var(--shk-surface-800)]\">{{ title() }}</span>\n <div class=\"flex items-center gap-2\">\n @if (showExpandButton()) {\n <button\n type=\"button\"\n (click)=\"toggleExpand()\"\n class=\"p-1.5 rounded-lg hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] _shk-text-surface-500 dark:[color:var(--shk-surface-500)] transition-colors\"\n >\n @if (isExpanded()) {\n <svg [lucideIcon]=\"getIcon('minimize-2')\" class=\"w-4 h-4\"></svg>\n } @else {\n <svg [lucideIcon]=\"getIcon('maximize-2')\" class=\"w-4 h-4\"></svg>\n }\n </button>\n }\n <button\n type=\"button\"\n (click)=\"closeModal()\"\n class=\"p-1.5 rounded-lg hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] _shk-text-surface-500 dark:[color:var(--shk-surface-500)] transition-colors\"\n >\n <svg [lucideIcon]=\"getIcon('x')\" class=\"w-4 h-4\"></svg>\n </button>\n </div>\n </div>\n\n <div class=\"overflow-y-auto px-6 py-4 flex-1 max-h-[70vh] _shk-scrollbar\">\n <ng-container #dynamicContent></ng-container>\n </div>\n\n @if (modalButtonsVisible()) {\n <hr class=\"border-t _shk-border dark:[border-color:var(--shk-surface-200)] shrink-0\" />\n <div class=\"flex justify-end gap-3 px-6 py-4 shrink-0\">\n <button\n type=\"button\"\n (click)=\"closeModal()\"\n [disabled]=\"loading()\"\n class=\"px-4 py-2 text-sm font-semibold _shk-text-surface-600 dark:[color:var(--shk-surface-600)] _shk-bg-surface-100 dark:[background-color:var(--shk-surface-200)] hover:[background-color:var(--shk-surface-200)] dark:hover:[background-color:var(--shk-surface-300)] rounded-lg transition-colors flex items-center gap-2 disabled:opacity-50\"\n >\n <svg [lucideIcon]=\"getIcon('x')\" class=\"w-4 h-4\"></svg>\n {{ cancelLabel() }}\n </button>\n <button\n type=\"button\"\n (click)=\"onAccept()\"\n [disabled]=\"loading()\"\n class=\"px-4 py-2 text-sm font-semibold _shk-text-white _shk-bg-emerald hover:[background-color:var(--shk-emerald-700)] rounded-lg shadow-md transition-all flex items-center gap-2 disabled:opacity-50\"\n >\n @if (loading()) {\n <svg [lucideIcon]=\"getIcon('loader-circle')\" class=\"w-4 h-4 animate-spin\"></svg>\n } @else {\n <svg [lucideIcon]=\"getIcon('check')\" class=\"w-4 h-4\"></svg>\n }\n {{ acceptLabel() }}\n </button>\n </div>\n }\n </div>\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["getIconFromCentral"],"mappings":"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"}
|
|
@@ -128,11 +128,11 @@ class NotificationComponent {
|
|
|
128
128
|
return Math.round(progress || 0);
|
|
129
129
|
}
|
|
130
130
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: NotificationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
131
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: NotificationComponent, isStandalone: true, selector: "shk-notification", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div [class]=\"positionClass()\">\n @for (notification of sortedNotifications(); track notification.id) {\n <div\n
|
|
131
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: NotificationComponent, isStandalone: true, selector: "shk-notification", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div [class]=\"positionClass()\">\n @for (notification of sortedNotifications(); track notification.id) {\n <div\n class=\"shk-toast mb-4\"\n [ngClass]=\"'shk-toast-' + notification.type\"\n role=\"alert\"\n >\n <div class=\"shk-toast-icon\">\n <svg [lucideIcon]=\"getIcon(getNotificationIcon(notification.type))\"></svg>\n </div>\n <div class=\"shk-toast-message\">\n {{ notification.message }}\n </div>\n <button\n type=\"button\"\n (click)=\"removeNotification(notification)\"\n aria-label=\"Close\"\n class=\"shk-toast-close\"\n >\n <svg [lucideIcon]=\"getIcon('x')\"></svg>\n </button>\n </div>\n }\n</div>\n", styles: [".shk-toast{--shk-toast-accent: var(--shk-info-600);display:flex;align-items:center;gap:.75rem;width:100%;min-width:320px;max-width:28rem;padding:.75rem .75rem .75rem .875rem;border-radius:.75rem;background-color:#fff;border:1px solid var(--shk-surface-200);color:var(--shk-surface-800);box-shadow:0 12px 32px -8px #0000002e,0 4px 10px -4px #00000014;animation:shk-toast-in .25s cubic-bezier(.21,1.02,.73,1)}:host-context(.dark) .shk-toast{background-color:var(--shk-surface-100);border-color:var(--shk-surface-200);box-shadow:0 12px 32px -8px #0009,0 4px 10px -4px #0006}.shk-toast-success{--shk-toast-accent: var(--shk-success-600)}.shk-toast-error{--shk-toast-accent: var(--shk-error-600)}:host-context(.dark) .shk-toast-error{--shk-toast-accent: var(--shk-error-500)}.shk-toast-warning{--shk-toast-accent: var(--shk-warning-600)}.shk-toast-icon{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:2rem;height:2rem;border-radius:9999px;color:var(--shk-toast-accent);background-color:color-mix(in srgb,var(--shk-toast-accent) 14%,transparent)}.shk-toast-icon svg{width:1.125rem;height:1.125rem}.shk-toast-message{flex:1;min-width:0;font-size:.875rem;line-height:1.25rem;font-weight:500;overflow-wrap:break-word}.shk-toast-close{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;border-radius:.375rem;background:transparent;color:var(--shk-surface-400);transition:background-color .15s ease,color .15s ease}.shk-toast-close:hover{color:var(--shk-surface-700);background-color:var(--shk-surface-100)}:host-context(.dark) .shk-toast-close:hover{background-color:var(--shk-surface-200)}.shk-toast-close:focus-visible{outline:none;box-shadow:0 0 0 2px color-mix(in srgb,var(--shk-primary-500) 45%,transparent)}.shk-toast-close svg{width:1rem;height:1rem}@keyframes shk-toast-in{0%{opacity:0;transform:translateY(-8px) scale(.97)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
132
132
|
}
|
|
133
133
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: NotificationComponent, decorators: [{
|
|
134
134
|
type: Component,
|
|
135
|
-
args: [{ selector: 'shk-notification', standalone: true, imports: [CommonModule, LucideDynamicIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"positionClass()\">\n @for (notification of sortedNotifications(); track notification.id) {\n <div\n
|
|
135
|
+
args: [{ selector: 'shk-notification', standalone: true, imports: [CommonModule, LucideDynamicIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"positionClass()\">\n @for (notification of sortedNotifications(); track notification.id) {\n <div\n class=\"shk-toast mb-4\"\n [ngClass]=\"'shk-toast-' + notification.type\"\n role=\"alert\"\n >\n <div class=\"shk-toast-icon\">\n <svg [lucideIcon]=\"getIcon(getNotificationIcon(notification.type))\"></svg>\n </div>\n <div class=\"shk-toast-message\">\n {{ notification.message }}\n </div>\n <button\n type=\"button\"\n (click)=\"removeNotification(notification)\"\n aria-label=\"Close\"\n class=\"shk-toast-close\"\n >\n <svg [lucideIcon]=\"getIcon('x')\"></svg>\n </button>\n </div>\n }\n</div>\n", styles: [".shk-toast{--shk-toast-accent: var(--shk-info-600);display:flex;align-items:center;gap:.75rem;width:100%;min-width:320px;max-width:28rem;padding:.75rem .75rem .75rem .875rem;border-radius:.75rem;background-color:#fff;border:1px solid var(--shk-surface-200);color:var(--shk-surface-800);box-shadow:0 12px 32px -8px #0000002e,0 4px 10px -4px #00000014;animation:shk-toast-in .25s cubic-bezier(.21,1.02,.73,1)}:host-context(.dark) .shk-toast{background-color:var(--shk-surface-100);border-color:var(--shk-surface-200);box-shadow:0 12px 32px -8px #0009,0 4px 10px -4px #0006}.shk-toast-success{--shk-toast-accent: var(--shk-success-600)}.shk-toast-error{--shk-toast-accent: var(--shk-error-600)}:host-context(.dark) .shk-toast-error{--shk-toast-accent: var(--shk-error-500)}.shk-toast-warning{--shk-toast-accent: var(--shk-warning-600)}.shk-toast-icon{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:2rem;height:2rem;border-radius:9999px;color:var(--shk-toast-accent);background-color:color-mix(in srgb,var(--shk-toast-accent) 14%,transparent)}.shk-toast-icon svg{width:1.125rem;height:1.125rem}.shk-toast-message{flex:1;min-width:0;font-size:.875rem;line-height:1.25rem;font-weight:500;overflow-wrap:break-word}.shk-toast-close{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;border-radius:.375rem;background:transparent;color:var(--shk-surface-400);transition:background-color .15s ease,color .15s ease}.shk-toast-close:hover{color:var(--shk-surface-700);background-color:var(--shk-surface-100)}:host-context(.dark) .shk-toast-close:hover{background-color:var(--shk-surface-200)}.shk-toast-close:focus-visible{outline:none;box-shadow:0 0 0 2px color-mix(in srgb,var(--shk-primary-500) 45%,transparent)}.shk-toast-close svg{width:1rem;height:1rem}@keyframes shk-toast-in{0%{opacity:0;transform:translateY(-8px) scale(.97)}}\n"] }]
|
|
136
136
|
}], propDecorators: { position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }] } });
|
|
137
137
|
|
|
138
138
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shirkasoft-ui-components-notification.mjs","sources":["../../../projects/ui-components/notification/notification.service.ts","../../../projects/ui-components/notification/notification.component.ts","../../../projects/ui-components/notification/notification.component.html","../../../projects/ui-components/notification/shirkasoft-ui-components-notification.ts"],"sourcesContent":["import { Injectable, signal } from '@angular/core';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/** Toast-style notification entry. */\nexport interface Notification {\n id: string;\n message: string;\n type: 'success' | 'error' | 'warning' | 'info';\n /** Current progress 0-100 when `showProgress` is true. */\n progress?: number;\n /** Whether the notification renders a progress indicator. */\n showProgress?: boolean;\n}\n\n/**\n * Central notification store. Components push/update/remove notifications\n * reactively through signals for the notification component to render.\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class NotificationService {\n /** Reactive list of visible notifications. */\n private notificationsSignal = signal<Notification[]>([]);\n /** Monotonic id counter for new notifications. */\n private currentId = 0;\n\n /** Readonly reactive list of visible notifications. */\n notifications = this.notificationsSignal.asReadonly();\n\n /**\n * Adds a notification and returns its id. When `showProgress` is false and\n * `duration` is positive, it auto-removes after that many ms.\n */\n addNotification(\n message: string,\n type: Notification['type'] = 'info',\n showProgress: boolean = false,\n duration: number = 5000\n ): string {\n const id = (++this.currentId).toString();\n const notification: Notification = {\n id,\n message,\n type,\n progress: showProgress ? 0 : undefined,\n showProgress,\n };\n\n this.notificationsSignal.update((notifications) => [\n ...notifications,\n notification,\n ]);\n\n if (duration > 0 && !showProgress) {\n setTimeout(() => this.removeNotificationById(id), duration);\n }\n\n return id;\n }\n\n /** Updates a progress notification; auto-removes when progress hits 100. */\n updateProgress(notificationId: string, progress: number) {\n const currentNotifications = this.notificationsSignal();\n const index = currentNotifications.findIndex(\n (n) => n.id === notificationId\n );\n\n if (index > -1 && currentNotifications[index].showProgress) {\n const updatedProgress = Math.min(100, Math.max(0, progress));\n\n this.notificationsSignal.update((notifications) =>\n notifications.map((n, i) =>\n i === index ? { ...n, progress: updatedProgress } : n\n )\n );\n\n if (progress >= 100) {\n setTimeout(() => this.removeNotificationById(notificationId), 2000);\n }\n }\n }\n\n /** Removes the given notification. */\n removeNotification(notification: Notification): void {\n this.removeNotificationById(notification.id);\n }\n\n /** Removes the notification with the given id. */\n removeNotificationById(notificationId: string): void {\n this.notificationsSignal.update((notifications) =>\n notifications.filter((n) => n.id !== notificationId)\n );\n }\n\n /** Removes every visible notification. */\n clearAll(): void {\n this.notificationsSignal.set([]);\n }\n}","import {\n Component,\n input,\n inject,\n ChangeDetectionStrategy,\n computed,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport {\n NotificationService,\n Notification,\n} from './notification.service';\nimport {\n LucideDynamicIcon,\n LucideInfo,\n LucideTriangleAlert,\n} from '@lucide/angular';\nimport { getIcon as getIconFromCentral } from 'shirkasoft-ui-components/utils';\n\nexport type NotificationPosition = 'center-top' | 'right-top' | 'left-top';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/**\n * Toast notification host that renders the notifications pushed through the\n * NotificationService in the configured position.\n */\n@Component({\n selector: 'shk-notification',\n templateUrl: './notification.component.html',\n standalone: true,\n imports: [CommonModule, LucideDynamicIcon],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class NotificationComponent {\n /** Position of the notification stack: center, right or left top. */\n position = input<NotificationPosition>('center-top');\n\n private notificationService = inject(NotificationService);\n protected getIcon = (name: any) => getIconFromCentral(name, LucideInfo);\n\n /** Maps each notification type to its internal icon name. */\n private readonly iconMap: Record<string, string> = {\n success: 'check',\n error: 'circle-x',\n info: 'info',\n warning: 'triangle-alert',\n };\n\n /** Resolves the icon name for a notification type. */\n getNotificationIcon(type: string): string {\n return this.iconMap[type] || 'info';\n }\n\n /** Live list of active notifications. */\n notifications = this.notificationService.notifications;\n\n /** Notifications sorted with the newest first. */\n sortedNotifications = computed(\n () => [...this.notifications()].reverse(),\n );\n\n /** Removes a notification through the service. */\n removeNotification(notification: Notification): void {\n this.notificationService.removeNotification(notification);\n }\n\n /** Rounds the progress value of a notification. */\n roundProgress(progress: number | undefined): number {\n return Math.round(progress || 0);\n }\n\n /** Whether there are notifications to show. */\n hasNotifications = computed(() => this.notifications().length > 0);\n\n /** CSS classes positioning the stack according to `position`. */\n positionClass = computed(() => {\n const base = 'fixed top-4 z-[9999] space-y-4 sm:space-y-6 sm:top-6 lg:top-8';\n switch (this.position()) {\n case 'right-top':\n return `${base} right-4`;\n case 'left-top':\n return `${base} left-4`;\n default:\n return `${base} left-1/2 -translate-x-1/2`;\n }\n });\n}\n","<div [class]=\"positionClass()\">\n @for (notification of sortedNotifications(); track notification.id) {\n <div\n [ngClass]=\"{\n 'bg-green-50/80 dark:bg-green-900/30 border-green-400 dark:border-green-600 text-green-800 dark:text-green-200':\n notification.type === 'success',\n 'bg-red-50/80 dark:bg-red-900/30 border-red-400 dark:border-red-600 text-red-800 dark:text-red-200':\n notification.type === 'error',\n 'bg-blue-50/80 dark:bg-blue-900/30 border-blue-400 dark:border-blue-600 text-blue-800 dark:text-blue-200':\n notification.type === 'info',\n 'bg-yellow-50/80 dark:bg-yellow-900/30 border-yellow-400 dark:border-yellow-500 text-yellow-800 dark:text-yellow-200':\n notification.type === 'warning',\n }\"\n class=\"flex items-center w-full min-w-[320px] max-w-xs sm:max-w-sm lg:max-w-md p-4 mb-4 border-l-4 rounded-lg shadow-lg backdrop-blur-sm transition-all duration-300 transform hover:scale-105 hover:shadow-xl\"\n role=\"alert\"\n >\n <div\n [ngClass]=\"{\n 'text-green-600': notification.type === 'success',\n 'text-red-600': notification.type === 'error',\n 'text-blue-600': notification.type === 'info',\n 'text-yellow-600': notification.type === 'warning',\n }\"\n class=\"inline-flex items-center justify-center flex-shrink-0 w-10 h-10 rounded-lg bg-opacity-10\"\n >\n <svg [lucideIcon]=\"getIcon(getNotificationIcon(notification.type))\" class=\"w-6 h-6\"></svg>\n </div>\n <div class=\"ms-4 flex-1 text-sm font-medium break-words\">\n {{ notification.message }}\n </div>\n <button\n type=\"button\"\n (click)=\"removeNotification(notification)\"\n aria-label=\"Close\"\n [ngClass]=\"{\n 'text-green-600 hover:text-green-800':\n notification.type === 'success',\n 'text-red-600 hover:text-red-800': notification.type === 'error',\n 'text-blue-600 hover:text-blue-800': notification.type === 'info',\n 'text-yellow-600 hover:text-yellow-800':\n notification.type === 'warning',\n }\"\n class=\"mx-2 -my-1.5 bg-transparent focus:outline-none\"\n >\n <svg [lucideIcon]=\"getIcon('x')\" class=\"w-4 h-4\"></svg>\n </button>\n </div>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["getIconFromCentral"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shirkasoft-ui-components-notification.mjs","sources":["../../../projects/ui-components/notification/notification.service.ts","../../../projects/ui-components/notification/notification.component.ts","../../../projects/ui-components/notification/notification.component.html","../../../projects/ui-components/notification/shirkasoft-ui-components-notification.ts"],"sourcesContent":["import { Injectable, signal } from '@angular/core';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/** Toast-style notification entry. */\nexport interface Notification {\n id: string;\n message: string;\n type: 'success' | 'error' | 'warning' | 'info';\n /** Current progress 0-100 when `showProgress` is true. */\n progress?: number;\n /** Whether the notification renders a progress indicator. */\n showProgress?: boolean;\n}\n\n/**\n * Central notification store. Components push/update/remove notifications\n * reactively through signals for the notification component to render.\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class NotificationService {\n /** Reactive list of visible notifications. */\n private notificationsSignal = signal<Notification[]>([]);\n /** Monotonic id counter for new notifications. */\n private currentId = 0;\n\n /** Readonly reactive list of visible notifications. */\n notifications = this.notificationsSignal.asReadonly();\n\n /**\n * Adds a notification and returns its id. When `showProgress` is false and\n * `duration` is positive, it auto-removes after that many ms.\n */\n addNotification(\n message: string,\n type: Notification['type'] = 'info',\n showProgress: boolean = false,\n duration: number = 5000\n ): string {\n const id = (++this.currentId).toString();\n const notification: Notification = {\n id,\n message,\n type,\n progress: showProgress ? 0 : undefined,\n showProgress,\n };\n\n this.notificationsSignal.update((notifications) => [\n ...notifications,\n notification,\n ]);\n\n if (duration > 0 && !showProgress) {\n setTimeout(() => this.removeNotificationById(id), duration);\n }\n\n return id;\n }\n\n /** Updates a progress notification; auto-removes when progress hits 100. */\n updateProgress(notificationId: string, progress: number) {\n const currentNotifications = this.notificationsSignal();\n const index = currentNotifications.findIndex(\n (n) => n.id === notificationId\n );\n\n if (index > -1 && currentNotifications[index].showProgress) {\n const updatedProgress = Math.min(100, Math.max(0, progress));\n\n this.notificationsSignal.update((notifications) =>\n notifications.map((n, i) =>\n i === index ? { ...n, progress: updatedProgress } : n\n )\n );\n\n if (progress >= 100) {\n setTimeout(() => this.removeNotificationById(notificationId), 2000);\n }\n }\n }\n\n /** Removes the given notification. */\n removeNotification(notification: Notification): void {\n this.removeNotificationById(notification.id);\n }\n\n /** Removes the notification with the given id. */\n removeNotificationById(notificationId: string): void {\n this.notificationsSignal.update((notifications) =>\n notifications.filter((n) => n.id !== notificationId)\n );\n }\n\n /** Removes every visible notification. */\n clearAll(): void {\n this.notificationsSignal.set([]);\n }\n}","import {\n Component,\n input,\n inject,\n ChangeDetectionStrategy,\n computed,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport {\n NotificationService,\n Notification,\n} from './notification.service';\nimport {\n LucideDynamicIcon,\n LucideInfo,\n LucideTriangleAlert,\n} from '@lucide/angular';\nimport { getIcon as getIconFromCentral } from 'shirkasoft-ui-components/utils';\n\nexport type NotificationPosition = 'center-top' | 'right-top' | 'left-top';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/**\n * Toast notification host that renders the notifications pushed through the\n * NotificationService in the configured position.\n */\n@Component({\n selector: 'shk-notification',\n templateUrl: './notification.component.html',\n standalone: true,\n imports: [CommonModule, LucideDynamicIcon],\n changeDetection: ChangeDetectionStrategy.OnPush,\n styles: [\n `\n .shk-toast {\n --shk-toast-accent: var(--shk-info-600);\n display: flex;\n align-items: center;\n gap: 0.75rem;\n width: 100%;\n min-width: 320px;\n max-width: 28rem;\n padding: 0.75rem 0.75rem 0.75rem 0.875rem;\n border-radius: 0.75rem;\n background-color: #fff;\n border: 1px solid var(--shk-surface-200);\n color: var(--shk-surface-800);\n box-shadow:\n 0 12px 32px -8px rgba(0, 0, 0, 0.18),\n 0 4px 10px -4px rgba(0, 0, 0, 0.08);\n animation: shk-toast-in 0.25s cubic-bezier(0.21, 1.02, 0.73, 1);\n }\n :host-context(.dark) .shk-toast {\n background-color: var(--shk-surface-100);\n border-color: var(--shk-surface-200);\n box-shadow:\n 0 12px 32px -8px rgba(0, 0, 0, 0.6),\n 0 4px 10px -4px rgba(0, 0, 0, 0.4);\n }\n .shk-toast-success {\n --shk-toast-accent: var(--shk-success-600);\n }\n .shk-toast-error {\n --shk-toast-accent: var(--shk-error-600);\n }\n :host-context(.dark) .shk-toast-error {\n --shk-toast-accent: var(--shk-error-500);\n }\n .shk-toast-warning {\n --shk-toast-accent: var(--shk-warning-600);\n }\n .shk-toast-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 2rem;\n height: 2rem;\n border-radius: 9999px;\n color: var(--shk-toast-accent);\n background-color: color-mix(in srgb, var(--shk-toast-accent) 14%, transparent);\n }\n .shk-toast-icon svg {\n width: 1.125rem;\n height: 1.125rem;\n }\n .shk-toast-message {\n flex: 1;\n min-width: 0;\n font-size: 0.875rem;\n line-height: 1.25rem;\n font-weight: 500;\n overflow-wrap: break-word;\n }\n .shk-toast-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 0.375rem;\n background: transparent;\n color: var(--shk-surface-400);\n transition:\n background-color 0.15s ease,\n color 0.15s ease;\n }\n .shk-toast-close:hover {\n color: var(--shk-surface-700);\n background-color: var(--shk-surface-100);\n }\n :host-context(.dark) .shk-toast-close:hover {\n background-color: var(--shk-surface-200);\n }\n .shk-toast-close:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--shk-primary-500) 45%, transparent);\n }\n .shk-toast-close svg {\n width: 1rem;\n height: 1rem;\n }\n @keyframes shk-toast-in {\n from {\n opacity: 0;\n transform: translateY(-8px) scale(0.97);\n }\n }\n `,\n ],\n})\nexport class NotificationComponent {\n /** Position of the notification stack: center, right or left top. */\n position = input<NotificationPosition>('center-top');\n\n private notificationService = inject(NotificationService);\n protected getIcon = (name: any) => getIconFromCentral(name, LucideInfo);\n\n /** Maps each notification type to its internal icon name. */\n private readonly iconMap: Record<string, string> = {\n success: 'check',\n error: 'circle-x',\n info: 'info',\n warning: 'triangle-alert',\n };\n\n /** Resolves the icon name for a notification type. */\n getNotificationIcon(type: string): string {\n return this.iconMap[type] || 'info';\n }\n\n /** Live list of active notifications. */\n notifications = this.notificationService.notifications;\n\n /** Notifications sorted with the newest first. */\n sortedNotifications = computed(\n () => [...this.notifications()].reverse(),\n );\n\n /** Removes a notification through the service. */\n removeNotification(notification: Notification): void {\n this.notificationService.removeNotification(notification);\n }\n\n /** Rounds the progress value of a notification. */\n roundProgress(progress: number | undefined): number {\n return Math.round(progress || 0);\n }\n\n /** Whether there are notifications to show. */\n hasNotifications = computed(() => this.notifications().length > 0);\n\n /** CSS classes positioning the stack according to `position`. */\n positionClass = computed(() => {\n const base = 'fixed top-4 z-[9999] space-y-4 sm:space-y-6 sm:top-6 lg:top-8';\n switch (this.position()) {\n case 'right-top':\n return `${base} right-4`;\n case 'left-top':\n return `${base} left-4`;\n default:\n return `${base} left-1/2 -translate-x-1/2`;\n }\n });\n}\n","<div [class]=\"positionClass()\">\n @for (notification of sortedNotifications(); track notification.id) {\n <div\n class=\"shk-toast mb-4\"\n [ngClass]=\"'shk-toast-' + notification.type\"\n role=\"alert\"\n >\n <div class=\"shk-toast-icon\">\n <svg [lucideIcon]=\"getIcon(getNotificationIcon(notification.type))\"></svg>\n </div>\n <div class=\"shk-toast-message\">\n {{ notification.message }}\n </div>\n <button\n type=\"button\"\n (click)=\"removeNotification(notification)\"\n aria-label=\"Close\"\n class=\"shk-toast-close\"\n >\n <svg [lucideIcon]=\"getIcon('x')\"></svg>\n </button>\n </div>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["getIconFromCentral"],"mappings":"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"}
|
|
@@ -222,7 +222,7 @@ class PriceInputComponent {
|
|
|
222
222
|
useExisting: forwardRef(() => PriceInputComponent),
|
|
223
223
|
multi: true,
|
|
224
224
|
},
|
|
225
|
-
], ngImport: i0, template: "<div>\n @if (label()) {\n <div class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] mb-1\">\n {{ label() }}\n @if (required()) {\n <span class=\"text-red-400\">*</span>\n }\n </div>\n }\n <div class=\"flex\">\n <input\n [id]=\"inputId()\"\n type=\"text\"\n inputmode=\"decimal\"\n autocomplete=\"off\"\n [value]=\"displayText()\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel() || label()\"\n [attr.aria-invalid]=\"showError() || null\"\n [disabled]=\"isDisabled()\"\n (focus)=\"onFocus($event)\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n (input)=\"onInput($event)\"\n class=\"block w-full px-3 py-2 _shk-text-surface-700 dark:[color:var(--shk-surface-700)] _shk-bg-surface-50 dark:[background-color:var(--shk-surface-100)] border rounded-l-lg transition-colors placeholder:[color:var(--shk-surface-400)] dark:placeholder:[color:var(--shk-surface-400)] focus:outline-none focus:[background-color:var(--shk-surface-50)] dark:focus:[background-color:var(--shk-surface-100)] focus:ring-1 disabled:[background-color:var(--shk-surface-50)] dark:disabled:[background-color:var(--shk-surface-100)] disabled:cursor-not-allowed sm:text-sm\"\n [ngClass]=\"{\n 'border-red-500 focus:border-red-500 focus:ring-red-500': showError(),\n '_shk-border dark:[border-color:var(--shk-surface-200)] focus:[border-color:var(--shk-primary-500)] focus:[--tw-ring-color:var(--shk-primary-500)]': !showError()\n }\"\n />\n <button\n type=\"button\"\n (click)=\"toggleMode()\"\n [disabled]=\"isDisabled()\"\n class=\"px-3 py-2 text-sm font-medium border rounded-r-lg transition-colors shrink-0\"\n [ngClass]=\"{\n '_shk-bg-primary-soft _shk-border-primary-200 _shk-text-primary-700 dark:[background-color:var(--shk-primary-900)] dark:[border-color:var(--shk-primary-700)] dark:[color:var(--shk-primary-300)]': isPercentage(),\n '_shk-bg-white _shk-border _shk-text-surface-500 dark:[background-color:var(--shk-surface-100)] dark:[border-color:var(--shk-surface-200)] dark:[color:var(--shk-surface-400)]': !isPercentage(),\n 'cursor-not-allowed opacity-50': isDisabled()\n }\"\n >\n {{ isPercentage() ? '%' : currency() }}\n </button>\n </div>\n @if (showError()) {\n <div class=\"text-xs _shk-text-red-500 mt-1\">\n {{ errorMessage() }}\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
225
|
+
], ngImport: i0, template: "<div>\n @if (label()) {\n <div class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] mb-1\">\n {{ label() }}\n @if (required()) {\n <span class=\"text-red-400\">*</span>\n }\n </div>\n }\n <div class=\"flex\">\n <input\n [id]=\"inputId()\"\n type=\"text\"\n inputmode=\"decimal\"\n autocomplete=\"off\"\n [value]=\"displayText()\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel() || label()\"\n [attr.aria-invalid]=\"showError() || null\"\n [disabled]=\"isDisabled()\"\n (focus)=\"onFocus($event)\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n (input)=\"onInput($event)\"\n class=\"shk-control shk-control-addon block w-full px-3 py-2 _shk-text-surface-700 dark:[color:var(--shk-surface-700)] _shk-bg-surface-50 dark:[background-color:var(--shk-surface-100)] border rounded-l-lg transition-colors placeholder:[color:var(--shk-surface-400)] dark:placeholder:[color:var(--shk-surface-400)] focus:outline-none focus:[background-color:var(--shk-surface-50)] dark:focus:[background-color:var(--shk-surface-100)] focus:ring-1 disabled:[background-color:var(--shk-surface-50)] dark:disabled:[background-color:var(--shk-surface-100)] disabled:cursor-not-allowed sm:text-sm\"\n [ngClass]=\"{\n 'border-red-500 focus:border-red-500 focus:ring-red-500': showError(),\n '_shk-border dark:[border-color:var(--shk-surface-200)] focus:[border-color:var(--shk-primary-500)] focus:[--tw-ring-color:var(--shk-primary-500)]': !showError()\n }\"\n />\n <button\n type=\"button\"\n (click)=\"toggleMode()\"\n [disabled]=\"isDisabled()\"\n class=\"px-3 py-2 text-sm font-medium border rounded-r-lg transition-colors shrink-0\"\n [ngClass]=\"{\n '_shk-bg-primary-soft _shk-border-primary-200 _shk-text-primary-700 dark:[background-color:var(--shk-primary-900)] dark:[border-color:var(--shk-primary-700)] dark:[color:var(--shk-primary-300)]': isPercentage(),\n '_shk-bg-white _shk-border _shk-text-surface-500 dark:[background-color:var(--shk-surface-100)] dark:[border-color:var(--shk-surface-200)] dark:[color:var(--shk-surface-400)]': !isPercentage(),\n 'cursor-not-allowed opacity-50': isDisabled()\n }\"\n >\n {{ isPercentage() ? '%' : currency() }}\n </button>\n </div>\n @if (showError()) {\n <div class=\"text-xs _shk-text-red-500 mt-1\">\n {{ errorMessage() }}\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
226
226
|
}
|
|
227
227
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: PriceInputComponent, decorators: [{
|
|
228
228
|
type: Component,
|
|
@@ -232,7 +232,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImpo
|
|
|
232
232
|
useExisting: forwardRef(() => PriceInputComponent),
|
|
233
233
|
multi: true,
|
|
234
234
|
},
|
|
235
|
-
], template: "<div>\n @if (label()) {\n <div class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] mb-1\">\n {{ label() }}\n @if (required()) {\n <span class=\"text-red-400\">*</span>\n }\n </div>\n }\n <div class=\"flex\">\n <input\n [id]=\"inputId()\"\n type=\"text\"\n inputmode=\"decimal\"\n autocomplete=\"off\"\n [value]=\"displayText()\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel() || label()\"\n [attr.aria-invalid]=\"showError() || null\"\n [disabled]=\"isDisabled()\"\n (focus)=\"onFocus($event)\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n (input)=\"onInput($event)\"\n class=\"block w-full px-3 py-2 _shk-text-surface-700 dark:[color:var(--shk-surface-700)] _shk-bg-surface-50 dark:[background-color:var(--shk-surface-100)] border rounded-l-lg transition-colors placeholder:[color:var(--shk-surface-400)] dark:placeholder:[color:var(--shk-surface-400)] focus:outline-none focus:[background-color:var(--shk-surface-50)] dark:focus:[background-color:var(--shk-surface-100)] focus:ring-1 disabled:[background-color:var(--shk-surface-50)] dark:disabled:[background-color:var(--shk-surface-100)] disabled:cursor-not-allowed sm:text-sm\"\n [ngClass]=\"{\n 'border-red-500 focus:border-red-500 focus:ring-red-500': showError(),\n '_shk-border dark:[border-color:var(--shk-surface-200)] focus:[border-color:var(--shk-primary-500)] focus:[--tw-ring-color:var(--shk-primary-500)]': !showError()\n }\"\n />\n <button\n type=\"button\"\n (click)=\"toggleMode()\"\n [disabled]=\"isDisabled()\"\n class=\"px-3 py-2 text-sm font-medium border rounded-r-lg transition-colors shrink-0\"\n [ngClass]=\"{\n '_shk-bg-primary-soft _shk-border-primary-200 _shk-text-primary-700 dark:[background-color:var(--shk-primary-900)] dark:[border-color:var(--shk-primary-700)] dark:[color:var(--shk-primary-300)]': isPercentage(),\n '_shk-bg-white _shk-border _shk-text-surface-500 dark:[background-color:var(--shk-surface-100)] dark:[border-color:var(--shk-surface-200)] dark:[color:var(--shk-surface-400)]': !isPercentage(),\n 'cursor-not-allowed opacity-50': isDisabled()\n }\"\n >\n {{ isPercentage() ? '%' : currency() }}\n </button>\n </div>\n @if (showError()) {\n <div class=\"text-xs _shk-text-red-500 mt-1\">\n {{ errorMessage() }}\n </div>\n }\n</div>\n" }]
|
|
235
|
+
], template: "<div>\n @if (label()) {\n <div class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] mb-1\">\n {{ label() }}\n @if (required()) {\n <span class=\"text-red-400\">*</span>\n }\n </div>\n }\n <div class=\"flex\">\n <input\n [id]=\"inputId()\"\n type=\"text\"\n inputmode=\"decimal\"\n autocomplete=\"off\"\n [value]=\"displayText()\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel() || label()\"\n [attr.aria-invalid]=\"showError() || null\"\n [disabled]=\"isDisabled()\"\n (focus)=\"onFocus($event)\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n (input)=\"onInput($event)\"\n class=\"shk-control shk-control-addon block w-full px-3 py-2 _shk-text-surface-700 dark:[color:var(--shk-surface-700)] _shk-bg-surface-50 dark:[background-color:var(--shk-surface-100)] border rounded-l-lg transition-colors placeholder:[color:var(--shk-surface-400)] dark:placeholder:[color:var(--shk-surface-400)] focus:outline-none focus:[background-color:var(--shk-surface-50)] dark:focus:[background-color:var(--shk-surface-100)] focus:ring-1 disabled:[background-color:var(--shk-surface-50)] dark:disabled:[background-color:var(--shk-surface-100)] disabled:cursor-not-allowed sm:text-sm\"\n [ngClass]=\"{\n 'border-red-500 focus:border-red-500 focus:ring-red-500': showError(),\n '_shk-border dark:[border-color:var(--shk-surface-200)] focus:[border-color:var(--shk-primary-500)] focus:[--tw-ring-color:var(--shk-primary-500)]': !showError()\n }\"\n />\n <button\n type=\"button\"\n (click)=\"toggleMode()\"\n [disabled]=\"isDisabled()\"\n class=\"px-3 py-2 text-sm font-medium border rounded-r-lg transition-colors shrink-0\"\n [ngClass]=\"{\n '_shk-bg-primary-soft _shk-border-primary-200 _shk-text-primary-700 dark:[background-color:var(--shk-primary-900)] dark:[border-color:var(--shk-primary-700)] dark:[color:var(--shk-primary-300)]': isPercentage(),\n '_shk-bg-white _shk-border _shk-text-surface-500 dark:[background-color:var(--shk-surface-100)] dark:[border-color:var(--shk-surface-200)] dark:[color:var(--shk-surface-400)]': !isPercentage(),\n 'cursor-not-allowed opacity-50': isDisabled()\n }\"\n >\n {{ isPercentage() ? '%' : currency() }}\n </button>\n </div>\n @if (showError()) {\n <div class=\"text-xs _shk-text-red-500 mt-1\">\n {{ errorMessage() }}\n </div>\n }\n</div>\n" }]
|
|
236
236
|
}], ctorParameters: () => [], propDecorators: { control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], isPercentage: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPercentage", required: false }] }, { type: i0.Output, args: ["isPercentageChange"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], decimals: [{ type: i0.Input, args: [{ isSignal: true, alias: "decimals", required: false }] }], currency: [{ type: i0.Input, args: [{ isSignal: true, alias: "currency", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], preventNegative: [{ type: i0.Input, args: [{ isSignal: true, alias: "preventNegative", required: false }] }], showError: [{ type: i0.Input, args: [{ isSignal: true, alias: "showError", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }] } });
|
|
237
237
|
|
|
238
238
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shirkasoft-ui-components-price-input.mjs","sources":["../../../projects/ui-components/price-input/price-input.component.ts","../../../projects/ui-components/price-input/price-input.component.html","../../../projects/ui-components/price-input/shirkasoft-ui-components-price-input.ts"],"sourcesContent":["import {\n Component,\n model,\n input,\n signal,\n computed,\n effect,\n inject,\n forwardRef,\n DestroyRef,\n ChangeDetectionStrategy,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport {\n ControlValueAccessor,\n FormControl,\n NG_VALUE_ACCESSOR,\n ReactiveFormsModule,\n} from '@angular/forms';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/**\n * Currency/percentage numeric input with reactive forms support.\n *\n * Binding modes (highest precedence first):\n * - `control`: a FormControl (or use it inside a form with `formControlName`).\n * - `value`/`valueChange` or `[(value)]`: two-way model signals.\n *\n * Text-based input (`type=\"text\"` + `inputmode=\"decimal\"`) with decimal\n * precision control, min/max clamping on blur and thousands formatting.\n */\n@Component({\n selector: 'shk-price-input',\n standalone: true,\n imports: [CommonModule, ReactiveFormsModule],\n templateUrl: './price-input.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => PriceInputComponent),\n multi: true,\n },\n ],\n})\nexport class PriceInputComponent implements ControlValueAccessor {\n /** Reactive control. When provided it takes precedence over `value`/`valueChange`. */\n control = input<FormControl<number | null> | undefined>(undefined);\n /** Numeric value (two-way), used when no `control` is bound. */\n value = model<number | null>(0);\n /** Whether the input works as a percentage (two-way). */\n isPercentage = model<boolean>(false);\n /** Label displayed above the field. */\n label = input<string>('');\n /** id attribute applied to the native input. */\n inputId = input<string>('');\n /** Marks the field as required. */\n required = input<boolean>(false);\n /** Disables the input. */\n disabled = input<boolean>(false);\n /** Minimum allowed value (clamped on blur). */\n min = input<number>(0);\n /** Maximum allowed value (clamped on blur). */\n max = input<number>(Infinity);\n /** Maximum number of decimal places (0 = integer). */\n decimals = input<number>(2);\n /** Symbol shown in the mode toggle button when not a percentage. */\n currency = input<string>('$');\n /** Placeholder text of the native input. */\n placeholder = input<string>('');\n /** Accessible label; falls back to `label`. */\n ariaLabel = input<string>('');\n /** Blocks the minus sign from being typed. */\n preventNegative = input<boolean>(false);\n /** Shows the error styling on the field. */\n showError = input<boolean>(false);\n /** Message rendered when the field is in error state. */\n errorMessage = input<string>('');\n\n private destroyRef = inject(DestroyRef);\n\n /** Text currently shown in the input (raw while focused, formatted on blur). */\n displayText = signal<string>('');\n /** Whether the native input currently has focus. */\n focused = signal<boolean>(false);\n /** Disabled state coming from the reactive control. */\n private controlDisabled = signal<boolean>(false);\n /** Prevents re-subscribing to the same form control. */\n private ctrlSubscribed = false;\n\n /** Effective disabled state combining the input and the form binding. */\n isDisabled = computed(() => this.disabled() || this.controlDisabled());\n\n /** Callbacks used by the ControlValueAccessor contract. */\n private onChange: (value: number | null) => void = () => {};\n private onTouched: () => void = () => {};\n\n constructor() {\n // Subscribe once to the bound control for change/status tracking.\n effect(() => {\n const ctrl = this.control();\n if (!ctrl || this.ctrlSubscribed) return;\n this.ctrlSubscribed = true;\n this.controlDisabled.set(ctrl.disabled);\n\n ctrl.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((v) => {\n if (!this.focused()) {\n this.displayText.set(this.formatNumber(v ?? 0));\n }\n });\n ctrl.statusChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {\n this.controlDisabled.set(ctrl.disabled);\n });\n });\n\n // Reflect the effective value into the display (unless the user is typing).\n effect(() => {\n const ctrl = this.control();\n const v = ctrl ? (ctrl.value as number | null) : this.value();\n if (!this.focused()) {\n this.displayText.set(this.formatNumber(v ?? 0));\n }\n });\n }\n\n /** Toggles between amount and percentage modes (unless disabled). */\n toggleMode(): void {\n if (this.isDisabled()) return;\n this.isPercentage.update((v) => !v);\n }\n\n /** Selects the whole value on focus so the user can type over it. */\n onFocus(event: FocusEvent): void {\n this.focused.set(true);\n (event.target as HTMLInputElement).select();\n }\n\n /** Clamps, rounds and formats the value when the field loses focus. */\n onBlur(): void {\n this.focused.set(false);\n this.onTouched();\n\n let v = parseFloat(this.displayText().replace(/,/g, ''));\n if (isNaN(v)) v = 0;\n\n const min = this.min();\n const max = this.max();\n if (isFinite(min) && v < min) v = min;\n if (isFinite(max) && v > max) v = max;\n\n v = this.roundTo(v);\n this.setValue(v);\n this.displayText.set(this.formatNumber(v));\n }\n\n /** Blocks characters that would break the numeric format. */\n onKeydown(event: KeyboardEvent): void {\n const allowed = [\n 'Backspace',\n 'Tab',\n 'End',\n 'Home',\n 'ArrowLeft',\n 'ArrowRight',\n 'Delete',\n 'Enter',\n 'Escape',\n ];\n if (allowed.includes(event.key)) return;\n if (/^\\d$/.test(event.key)) return;\n\n if (event.key === '.' || event.key === ',') {\n const input = event.target as HTMLInputElement;\n if (input.value.includes('.') || input.value.includes(',')) event.preventDefault();\n return;\n }\n\n if (event.key === '-') {\n const input = event.target as HTMLInputElement;\n if (this.preventNegative() || this.min() >= 0) {\n event.preventDefault();\n } else if (input.value.includes('-')) {\n event.preventDefault();\n }\n return;\n }\n\n event.preventDefault();\n }\n\n /** Sanitizes the raw input (digits + one separator + optional sign) and writes the value once. */\n onInput(event: Event): void {\n const input = event.target as HTMLInputElement;\n const pos = input.selectionStart ?? input.value.length;\n\n let cleaned = input.value.replace(/[^0-9.,-]/g, '');\n if (this.preventNegative() || this.min() >= 0) cleaned = cleaned.replace(/-/g, '');\n cleaned = cleaned.replace(/,/g, '.');\n\n const dot = cleaned.indexOf('.');\n if (dot >= 0) {\n const dec = Math.max(0, this.decimals());\n const intPart = cleaned.slice(0, dot);\n const decPart = cleaned.slice(dot + 1, dot + 1 + dec);\n cleaned = intPart + '.' + decPart;\n }\n\n input.value = cleaned;\n const newPos = Math.min(pos, cleaned.length);\n input.setSelectionRange(newPos, newPos);\n this.displayText.set(cleaned);\n\n const num = parseFloat(cleaned);\n this.setValue(isNaN(num) ? 0 : num);\n }\n\n /** Writes the value to the effective binding source. */\n private setValue(v: number): void {\n const ctrl = this.control();\n if (ctrl) {\n ctrl.setValue(v, { emitEvent: true });\n } else {\n this.value.set(v);\n }\n this.onChange(v);\n }\n\n private roundTo(v: number): number {\n const factor = Math.pow(10, Math.max(0, this.decimals()));\n return Math.round(v * factor) / factor;\n }\n\n /** Formats a number with thousands separator and up to `decimals` places. */\n private formatNumber(v: number): string {\n if (v == null || isNaN(v)) return '0';\n const dec = Math.max(0, this.decimals());\n return v.toLocaleString('en-US', { minimumFractionDigits: 0, maximumFractionDigits: dec });\n }\n\n // ── ControlValueAccessor ───────────────────────────────────────────────────\n\n writeValue(value: any): void {\n if (!this.focused()) {\n this.displayText.set(this.formatNumber(value ?? 0));\n }\n }\n\n registerOnChange(fn: any): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: any): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.controlDisabled.set(isDisabled);\n }\n}\n","<div>\n @if (label()) {\n <div class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] mb-1\">\n {{ label() }}\n @if (required()) {\n <span class=\"text-red-400\">*</span>\n }\n </div>\n }\n <div class=\"flex\">\n <input\n [id]=\"inputId()\"\n type=\"text\"\n inputmode=\"decimal\"\n autocomplete=\"off\"\n [value]=\"displayText()\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel() || label()\"\n [attr.aria-invalid]=\"showError() || null\"\n [disabled]=\"isDisabled()\"\n (focus)=\"onFocus($event)\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n (input)=\"onInput($event)\"\n class=\"block w-full px-3 py-2 _shk-text-surface-700 dark:[color:var(--shk-surface-700)] _shk-bg-surface-50 dark:[background-color:var(--shk-surface-100)] border rounded-l-lg transition-colors placeholder:[color:var(--shk-surface-400)] dark:placeholder:[color:var(--shk-surface-400)] focus:outline-none focus:[background-color:var(--shk-surface-50)] dark:focus:[background-color:var(--shk-surface-100)] focus:ring-1 disabled:[background-color:var(--shk-surface-50)] dark:disabled:[background-color:var(--shk-surface-100)] disabled:cursor-not-allowed sm:text-sm\"\n [ngClass]=\"{\n 'border-red-500 focus:border-red-500 focus:ring-red-500': showError(),\n '_shk-border dark:[border-color:var(--shk-surface-200)] focus:[border-color:var(--shk-primary-500)] focus:[--tw-ring-color:var(--shk-primary-500)]': !showError()\n }\"\n />\n <button\n type=\"button\"\n (click)=\"toggleMode()\"\n [disabled]=\"isDisabled()\"\n class=\"px-3 py-2 text-sm font-medium border rounded-r-lg transition-colors shrink-0\"\n [ngClass]=\"{\n '_shk-bg-primary-soft _shk-border-primary-200 _shk-text-primary-700 dark:[background-color:var(--shk-primary-900)] dark:[border-color:var(--shk-primary-700)] dark:[color:var(--shk-primary-300)]': isPercentage(),\n '_shk-bg-white _shk-border _shk-text-surface-500 dark:[background-color:var(--shk-surface-100)] dark:[border-color:var(--shk-surface-200)] dark:[color:var(--shk-surface-400)]': !isPercentage(),\n 'cursor-not-allowed opacity-50': isDisabled()\n }\"\n >\n {{ isPercentage() ? '%' : currency() }}\n </button>\n </div>\n @if (showError()) {\n <div class=\"text-xs _shk-text-red-500 mt-1\">\n {{ errorMessage() }}\n </div>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shirkasoft-ui-components-price-input.mjs","sources":["../../../projects/ui-components/price-input/price-input.component.ts","../../../projects/ui-components/price-input/price-input.component.html","../../../projects/ui-components/price-input/shirkasoft-ui-components-price-input.ts"],"sourcesContent":["import {\n Component,\n model,\n input,\n signal,\n computed,\n effect,\n inject,\n forwardRef,\n DestroyRef,\n ChangeDetectionStrategy,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport {\n ControlValueAccessor,\n FormControl,\n NG_VALUE_ACCESSOR,\n ReactiveFormsModule,\n} from '@angular/forms';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/**\n * Currency/percentage numeric input with reactive forms support.\n *\n * Binding modes (highest precedence first):\n * - `control`: a FormControl (or use it inside a form with `formControlName`).\n * - `value`/`valueChange` or `[(value)]`: two-way model signals.\n *\n * Text-based input (`type=\"text\"` + `inputmode=\"decimal\"`) with decimal\n * precision control, min/max clamping on blur and thousands formatting.\n */\n@Component({\n selector: 'shk-price-input',\n standalone: true,\n imports: [CommonModule, ReactiveFormsModule],\n templateUrl: './price-input.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => PriceInputComponent),\n multi: true,\n },\n ],\n})\nexport class PriceInputComponent implements ControlValueAccessor {\n /** Reactive control. When provided it takes precedence over `value`/`valueChange`. */\n control = input<FormControl<number | null> | undefined>(undefined);\n /** Numeric value (two-way), used when no `control` is bound. */\n value = model<number | null>(0);\n /** Whether the input works as a percentage (two-way). */\n isPercentage = model<boolean>(false);\n /** Label displayed above the field. */\n label = input<string>('');\n /** id attribute applied to the native input. */\n inputId = input<string>('');\n /** Marks the field as required. */\n required = input<boolean>(false);\n /** Disables the input. */\n disabled = input<boolean>(false);\n /** Minimum allowed value (clamped on blur). */\n min = input<number>(0);\n /** Maximum allowed value (clamped on blur). */\n max = input<number>(Infinity);\n /** Maximum number of decimal places (0 = integer). */\n decimals = input<number>(2);\n /** Symbol shown in the mode toggle button when not a percentage. */\n currency = input<string>('$');\n /** Placeholder text of the native input. */\n placeholder = input<string>('');\n /** Accessible label; falls back to `label`. */\n ariaLabel = input<string>('');\n /** Blocks the minus sign from being typed. */\n preventNegative = input<boolean>(false);\n /** Shows the error styling on the field. */\n showError = input<boolean>(false);\n /** Message rendered when the field is in error state. */\n errorMessage = input<string>('');\n\n private destroyRef = inject(DestroyRef);\n\n /** Text currently shown in the input (raw while focused, formatted on blur). */\n displayText = signal<string>('');\n /** Whether the native input currently has focus. */\n focused = signal<boolean>(false);\n /** Disabled state coming from the reactive control. */\n private controlDisabled = signal<boolean>(false);\n /** Prevents re-subscribing to the same form control. */\n private ctrlSubscribed = false;\n\n /** Effective disabled state combining the input and the form binding. */\n isDisabled = computed(() => this.disabled() || this.controlDisabled());\n\n /** Callbacks used by the ControlValueAccessor contract. */\n private onChange: (value: number | null) => void = () => {};\n private onTouched: () => void = () => {};\n\n constructor() {\n // Subscribe once to the bound control for change/status tracking.\n effect(() => {\n const ctrl = this.control();\n if (!ctrl || this.ctrlSubscribed) return;\n this.ctrlSubscribed = true;\n this.controlDisabled.set(ctrl.disabled);\n\n ctrl.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((v) => {\n if (!this.focused()) {\n this.displayText.set(this.formatNumber(v ?? 0));\n }\n });\n ctrl.statusChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {\n this.controlDisabled.set(ctrl.disabled);\n });\n });\n\n // Reflect the effective value into the display (unless the user is typing).\n effect(() => {\n const ctrl = this.control();\n const v = ctrl ? (ctrl.value as number | null) : this.value();\n if (!this.focused()) {\n this.displayText.set(this.formatNumber(v ?? 0));\n }\n });\n }\n\n /** Toggles between amount and percentage modes (unless disabled). */\n toggleMode(): void {\n if (this.isDisabled()) return;\n this.isPercentage.update((v) => !v);\n }\n\n /** Selects the whole value on focus so the user can type over it. */\n onFocus(event: FocusEvent): void {\n this.focused.set(true);\n (event.target as HTMLInputElement).select();\n }\n\n /** Clamps, rounds and formats the value when the field loses focus. */\n onBlur(): void {\n this.focused.set(false);\n this.onTouched();\n\n let v = parseFloat(this.displayText().replace(/,/g, ''));\n if (isNaN(v)) v = 0;\n\n const min = this.min();\n const max = this.max();\n if (isFinite(min) && v < min) v = min;\n if (isFinite(max) && v > max) v = max;\n\n v = this.roundTo(v);\n this.setValue(v);\n this.displayText.set(this.formatNumber(v));\n }\n\n /** Blocks characters that would break the numeric format. */\n onKeydown(event: KeyboardEvent): void {\n const allowed = [\n 'Backspace',\n 'Tab',\n 'End',\n 'Home',\n 'ArrowLeft',\n 'ArrowRight',\n 'Delete',\n 'Enter',\n 'Escape',\n ];\n if (allowed.includes(event.key)) return;\n if (/^\\d$/.test(event.key)) return;\n\n if (event.key === '.' || event.key === ',') {\n const input = event.target as HTMLInputElement;\n if (input.value.includes('.') || input.value.includes(',')) event.preventDefault();\n return;\n }\n\n if (event.key === '-') {\n const input = event.target as HTMLInputElement;\n if (this.preventNegative() || this.min() >= 0) {\n event.preventDefault();\n } else if (input.value.includes('-')) {\n event.preventDefault();\n }\n return;\n }\n\n event.preventDefault();\n }\n\n /** Sanitizes the raw input (digits + one separator + optional sign) and writes the value once. */\n onInput(event: Event): void {\n const input = event.target as HTMLInputElement;\n const pos = input.selectionStart ?? input.value.length;\n\n let cleaned = input.value.replace(/[^0-9.,-]/g, '');\n if (this.preventNegative() || this.min() >= 0) cleaned = cleaned.replace(/-/g, '');\n cleaned = cleaned.replace(/,/g, '.');\n\n const dot = cleaned.indexOf('.');\n if (dot >= 0) {\n const dec = Math.max(0, this.decimals());\n const intPart = cleaned.slice(0, dot);\n const decPart = cleaned.slice(dot + 1, dot + 1 + dec);\n cleaned = intPart + '.' + decPart;\n }\n\n input.value = cleaned;\n const newPos = Math.min(pos, cleaned.length);\n input.setSelectionRange(newPos, newPos);\n this.displayText.set(cleaned);\n\n const num = parseFloat(cleaned);\n this.setValue(isNaN(num) ? 0 : num);\n }\n\n /** Writes the value to the effective binding source. */\n private setValue(v: number): void {\n const ctrl = this.control();\n if (ctrl) {\n ctrl.setValue(v, { emitEvent: true });\n } else {\n this.value.set(v);\n }\n this.onChange(v);\n }\n\n private roundTo(v: number): number {\n const factor = Math.pow(10, Math.max(0, this.decimals()));\n return Math.round(v * factor) / factor;\n }\n\n /** Formats a number with thousands separator and up to `decimals` places. */\n private formatNumber(v: number): string {\n if (v == null || isNaN(v)) return '0';\n const dec = Math.max(0, this.decimals());\n return v.toLocaleString('en-US', { minimumFractionDigits: 0, maximumFractionDigits: dec });\n }\n\n // ── ControlValueAccessor ───────────────────────────────────────────────────\n\n writeValue(value: any): void {\n if (!this.focused()) {\n this.displayText.set(this.formatNumber(value ?? 0));\n }\n }\n\n registerOnChange(fn: any): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: any): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.controlDisabled.set(isDisabled);\n }\n}\n","<div>\n @if (label()) {\n <div class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] mb-1\">\n {{ label() }}\n @if (required()) {\n <span class=\"text-red-400\">*</span>\n }\n </div>\n }\n <div class=\"flex\">\n <input\n [id]=\"inputId()\"\n type=\"text\"\n inputmode=\"decimal\"\n autocomplete=\"off\"\n [value]=\"displayText()\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel() || label()\"\n [attr.aria-invalid]=\"showError() || null\"\n [disabled]=\"isDisabled()\"\n (focus)=\"onFocus($event)\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n (input)=\"onInput($event)\"\n class=\"shk-control shk-control-addon block w-full px-3 py-2 _shk-text-surface-700 dark:[color:var(--shk-surface-700)] _shk-bg-surface-50 dark:[background-color:var(--shk-surface-100)] border rounded-l-lg transition-colors placeholder:[color:var(--shk-surface-400)] dark:placeholder:[color:var(--shk-surface-400)] focus:outline-none focus:[background-color:var(--shk-surface-50)] dark:focus:[background-color:var(--shk-surface-100)] focus:ring-1 disabled:[background-color:var(--shk-surface-50)] dark:disabled:[background-color:var(--shk-surface-100)] disabled:cursor-not-allowed sm:text-sm\"\n [ngClass]=\"{\n 'border-red-500 focus:border-red-500 focus:ring-red-500': showError(),\n '_shk-border dark:[border-color:var(--shk-surface-200)] focus:[border-color:var(--shk-primary-500)] focus:[--tw-ring-color:var(--shk-primary-500)]': !showError()\n }\"\n />\n <button\n type=\"button\"\n (click)=\"toggleMode()\"\n [disabled]=\"isDisabled()\"\n class=\"px-3 py-2 text-sm font-medium border rounded-r-lg transition-colors shrink-0\"\n [ngClass]=\"{\n '_shk-bg-primary-soft _shk-border-primary-200 _shk-text-primary-700 dark:[background-color:var(--shk-primary-900)] dark:[border-color:var(--shk-primary-700)] dark:[color:var(--shk-primary-300)]': isPercentage(),\n '_shk-bg-white _shk-border _shk-text-surface-500 dark:[background-color:var(--shk-surface-100)] dark:[border-color:var(--shk-surface-200)] dark:[color:var(--shk-surface-400)]': !isPercentage(),\n 'cursor-not-allowed opacity-50': isDisabled()\n }\"\n >\n {{ isPercentage() ? '%' : currency() }}\n </button>\n </div>\n @if (showError()) {\n <div class=\"text-xs _shk-text-red-500 mt-1\">\n {{ errorMessage() }}\n </div>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|