shirkasoft-ui-components 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/fesm2022/shirkasoft-ui-components-breadcrumb.mjs +199 -0
  2. package/fesm2022/shirkasoft-ui-components-breadcrumb.mjs.map +1 -0
  3. package/fesm2022/shirkasoft-ui-components-button.mjs +148 -0
  4. package/fesm2022/shirkasoft-ui-components-button.mjs.map +1 -0
  5. package/fesm2022/shirkasoft-ui-components-chart.mjs +153 -0
  6. package/fesm2022/shirkasoft-ui-components-chart.mjs.map +1 -0
  7. package/fesm2022/shirkasoft-ui-components-confirm-dialog.mjs +143 -0
  8. package/fesm2022/shirkasoft-ui-components-confirm-dialog.mjs.map +1 -0
  9. package/fesm2022/shirkasoft-ui-components-date-picker.mjs +638 -0
  10. package/fesm2022/shirkasoft-ui-components-date-picker.mjs.map +1 -0
  11. package/fesm2022/shirkasoft-ui-components-fieldset.mjs +94 -0
  12. package/fesm2022/shirkasoft-ui-components-fieldset.mjs.map +1 -0
  13. package/fesm2022/shirkasoft-ui-components-file-upload.mjs +242 -0
  14. package/fesm2022/shirkasoft-ui-components-file-upload.mjs.map +1 -0
  15. package/fesm2022/shirkasoft-ui-components-knob.mjs +269 -0
  16. package/fesm2022/shirkasoft-ui-components-knob.mjs.map +1 -0
  17. package/fesm2022/shirkasoft-ui-components-loading.mjs +255 -0
  18. package/fesm2022/shirkasoft-ui-components-loading.mjs.map +1 -0
  19. package/fesm2022/shirkasoft-ui-components-modal.mjs +290 -0
  20. package/fesm2022/shirkasoft-ui-components-modal.mjs.map +1 -0
  21. package/fesm2022/shirkasoft-ui-components-notification.mjs +143 -0
  22. package/fesm2022/shirkasoft-ui-components-notification.mjs.map +1 -0
  23. package/fesm2022/shirkasoft-ui-components-price-input.mjs +64 -0
  24. package/fesm2022/shirkasoft-ui-components-price-input.mjs.map +1 -0
  25. package/fesm2022/shirkasoft-ui-components-rail-sidebar.mjs +205 -0
  26. package/fesm2022/shirkasoft-ui-components-rail-sidebar.mjs.map +1 -0
  27. package/fesm2022/shirkasoft-ui-components-select.mjs +737 -0
  28. package/fesm2022/shirkasoft-ui-components-select.mjs.map +1 -0
  29. package/fesm2022/shirkasoft-ui-components-sidebar.mjs +185 -0
  30. package/fesm2022/shirkasoft-ui-components-sidebar.mjs.map +1 -0
  31. package/fesm2022/shirkasoft-ui-components-skeleton.mjs +74 -0
  32. package/fesm2022/shirkasoft-ui-components-skeleton.mjs.map +1 -0
  33. package/fesm2022/shirkasoft-ui-components-table.mjs +689 -0
  34. package/fesm2022/shirkasoft-ui-components-table.mjs.map +1 -0
  35. package/fesm2022/shirkasoft-ui-components-tabs.mjs +249 -0
  36. package/fesm2022/shirkasoft-ui-components-tabs.mjs.map +1 -0
  37. package/fesm2022/shirkasoft-ui-components-tag.mjs +70 -0
  38. package/fesm2022/shirkasoft-ui-components-tag.mjs.map +1 -0
  39. package/fesm2022/shirkasoft-ui-components-text-field.mjs +370 -0
  40. package/fesm2022/shirkasoft-ui-components-text-field.mjs.map +1 -0
  41. package/fesm2022/shirkasoft-ui-components-timeline.mjs +222 -0
  42. package/fesm2022/shirkasoft-ui-components-timeline.mjs.map +1 -0
  43. package/fesm2022/shirkasoft-ui-components-toggle.mjs +186 -0
  44. package/fesm2022/shirkasoft-ui-components-toggle.mjs.map +1 -0
  45. package/fesm2022/shirkasoft-ui-components-tooltip.mjs +169 -0
  46. package/fesm2022/shirkasoft-ui-components-tooltip.mjs.map +1 -0
  47. package/fesm2022/shirkasoft-ui-components-utils.mjs +64 -0
  48. package/fesm2022/shirkasoft-ui-components-utils.mjs.map +1 -0
  49. package/fesm2022/shirkasoft-ui-components-wizard.mjs +167 -0
  50. package/fesm2022/shirkasoft-ui-components-wizard.mjs.map +1 -0
  51. package/fesm2022/shirkasoft-ui-components.mjs +0 -5729
  52. package/fesm2022/shirkasoft-ui-components.mjs.map +1 -1
  53. package/package.json +101 -1
  54. package/types/shirkasoft-ui-components-breadcrumb.d.ts +68 -0
  55. package/types/shirkasoft-ui-components-button.d.ts +59 -0
  56. package/types/shirkasoft-ui-components-chart.d.ts +65 -0
  57. package/types/shirkasoft-ui-components-confirm-dialog.d.ts +88 -0
  58. package/types/shirkasoft-ui-components-date-picker.d.ts +200 -0
  59. package/types/shirkasoft-ui-components-fieldset.d.ts +72 -0
  60. package/types/shirkasoft-ui-components-file-upload.d.ts +87 -0
  61. package/types/shirkasoft-ui-components-knob.d.ts +69 -0
  62. package/types/shirkasoft-ui-components-loading.d.ts +94 -0
  63. package/types/shirkasoft-ui-components-modal.d.ts +139 -0
  64. package/types/shirkasoft-ui-components-notification.d.ts +82 -0
  65. package/types/shirkasoft-ui-components-price-input.d.ts +41 -0
  66. package/types/shirkasoft-ui-components-rail-sidebar.d.ts +121 -0
  67. package/types/shirkasoft-ui-components-select.d.ts +182 -0
  68. package/types/shirkasoft-ui-components-sidebar.d.ts +106 -0
  69. package/types/shirkasoft-ui-components-skeleton.d.ts +36 -0
  70. package/types/shirkasoft-ui-components-table.d.ts +293 -0
  71. package/types/shirkasoft-ui-components-tabs.d.ts +102 -0
  72. package/types/shirkasoft-ui-components-tag.d.ts +31 -0
  73. package/types/shirkasoft-ui-components-text-field.d.ts +120 -0
  74. package/types/shirkasoft-ui-components-timeline.d.ts +178 -0
  75. package/types/shirkasoft-ui-components-toggle.d.ts +48 -0
  76. package/types/shirkasoft-ui-components-tooltip.d.ts +47 -0
  77. package/types/shirkasoft-ui-components-utils.d.ts +9 -0
  78. package/types/shirkasoft-ui-components-wizard.d.ts +101 -0
  79. package/types/shirkasoft-ui-components.d.ts +1 -2333
@@ -0,0 +1,64 @@
1
+ import * as i0 from '@angular/core';
2
+ import { model, input, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import * as i2 from '@angular/forms';
6
+ import { FormsModule } from '@angular/forms';
7
+
8
+ /**
9
+ * Shirkasoft UI Components.
10
+ * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).
11
+ * Belongs to Shirkasoft.
12
+ */
13
+ /**
14
+ * Numeric input tailored for currency values with a optional percentage mode.
15
+ * Uses two-way bindable models: `value` and `isPercentage`.
16
+ */
17
+ class PriceInputComponent {
18
+ constructor() {
19
+ /** Numeric value, bindable with [(value)]. */
20
+ this.value = model.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
21
+ /** Whether the input works as a percentage, bindable with [(isPercentage)]. */
22
+ this.isPercentage = model(false, ...(ngDevMode ? [{ debugName: "isPercentage" }] : /* istanbul ignore next */ []));
23
+ /** Label displayed above the field. */
24
+ this.label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
25
+ /** id attribute applied to the native input. */
26
+ this.inputId = input('', ...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
27
+ /** Marks the field as required. */
28
+ this.required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
29
+ /** Disables the input. */
30
+ this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
31
+ /** Minimum allowed value. */
32
+ this.min = input(0, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
33
+ /** Maximum allowed value. */
34
+ this.max = input(Infinity, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
35
+ /** Shows the error styling on the field. */
36
+ this.showError = input(false, ...(ngDevMode ? [{ debugName: "showError" }] : /* istanbul ignore next */ []));
37
+ /** Message rendered when the field is in error state. */
38
+ this.errorMessage = input('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
39
+ }
40
+ /** Toggles between amount and percentage modes (unless disabled). */
41
+ toggleMode() {
42
+ if (this.disabled())
43
+ return;
44
+ this.isPercentage.update(v => !v);
45
+ }
46
+ /** Parses the user input and updates the bound `value`. */
47
+ onInput(event) {
48
+ const input = event.target;
49
+ this.value.set(parseFloat(input.value) || 0);
50
+ }
51
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: PriceInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
52
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: PriceInputComponent, isStandalone: true, selector: "shk-price-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, isPercentage: { classPropertyName: "isPercentage", publicName: "isPercentage", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, showError: { classPropertyName: "showError", publicName: "showError", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", isPercentage: "isPercentageChange" }, 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=\"number\"\n [ngModel]=\"value()\"\n (ngModelChange)=\"value.set($event ?? 0)\"\n (input)=\"onInput($event)\"\n [disabled]=\"disabled()\"\n [min]=\"min()\"\n [max]=\"max()\"\n step=\"0.01\"\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]=\"disabled()\"\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': disabled()\n }\"\n >\n {{ isPercentage() ? '%' : '$' }}\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: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i2.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
53
+ }
54
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: PriceInputComponent, decorators: [{
55
+ type: Component,
56
+ args: [{ selector: 'shk-price-input', standalone: true, imports: [CommonModule, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, 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=\"number\"\n [ngModel]=\"value()\"\n (ngModelChange)=\"value.set($event ?? 0)\"\n (input)=\"onInput($event)\"\n [disabled]=\"disabled()\"\n [min]=\"min()\"\n [max]=\"max()\"\n step=\"0.01\"\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]=\"disabled()\"\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': disabled()\n }\"\n >\n {{ isPercentage() ? '%' : '$' }}\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" }]
57
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }, { 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 }] }], showError: [{ type: i0.Input, args: [{ isSignal: true, alias: "showError", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }] } });
58
+
59
+ /**
60
+ * Generated bundle index. Do not edit.
61
+ */
62
+
63
+ export { PriceInputComponent };
64
+ //# sourceMappingURL=shirkasoft-ui-components-price-input.mjs.map
@@ -0,0 +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 { Component, model, input, ChangeDetectionStrategy } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\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 * Numeric input tailored for currency values with a optional percentage mode.\n * Uses two-way bindable models: `value` and `isPercentage`.\n */\n@Component({\n selector: 'shk-price-input',\n standalone: true,\n imports: [CommonModule, FormsModule],\n templateUrl: './price-input.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class PriceInputComponent {\n /** Numeric value, bindable with [(value)]. */\n value = model.required<number>();\n /** Whether the input works as a percentage, bindable with [(isPercentage)]. */\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. */\n min = input<number>(0);\n /** Maximum allowed value. */\n max = input<number>(Infinity);\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 /** Toggles between amount and percentage modes (unless disabled). */\n toggleMode(): void {\n if (this.disabled()) return;\n this.isPercentage.update(v => !v);\n }\n\n /** Parses the user input and updates the bound `value`. */\n onInput(event: Event): void {\n const input = event.target as HTMLInputElement;\n this.value.set(parseFloat(input.value) || 0);\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=\"number\"\n [ngModel]=\"value()\"\n (ngModelChange)=\"value.set($event ?? 0)\"\n (input)=\"onInput($event)\"\n [disabled]=\"disabled()\"\n [min]=\"min()\"\n [max]=\"max()\"\n step=\"0.01\"\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]=\"disabled()\"\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': disabled()\n }\"\n >\n {{ isPercentage() ? '%' : '$' }}\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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"}
@@ -0,0 +1,205 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, model, output, signal, computed, effect, Component } from '@angular/core';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import { LucideMenu, LucideDynamicIcon } from '@lucide/angular';
6
+ import { getIcon } from 'shirkasoft-ui-components/utils';
7
+ import { TooltipComponent } from 'shirkasoft-ui-components/tooltip';
8
+
9
+ /**
10
+ * Shirkasoft UI Components.
11
+ * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).
12
+ * Belongs to Shirkasoft.
13
+ */
14
+ /**
15
+ * Narrow "rail" sidebar that expands into sections. Supports sections, roles,
16
+ * language switching, collapse/expand and responsive tooltips.
17
+ */
18
+ class RailSidebarComponent {
19
+ constructor() {
20
+ /** Sections presented as expandable areas of the rail. */
21
+ this.sections = input([], ...(ngDevMode ? [{ debugName: "sections" }] : /* istanbul ignore next */ []));
22
+ /** Current location url used to detect the active section/item. */
23
+ this.activeUrl = input('', ...(ngDevMode ? [{ debugName: "activeUrl" }] : /* istanbul ignore next */ []));
24
+ /** Key of the active section, bindable with [(activeSectionKey)]. */
25
+ this.activeSectionKey = model('', ...(ngDevMode ? [{ debugName: "activeSectionKey" }] : /* istanbul ignore next */ []));
26
+ /** Collapsed (rail only) state, bindable with [(collapsed)]. */
27
+ this.collapsed = model(false, ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
28
+ /** Active language code. */
29
+ this.activeLang = input('es', ...(ngDevMode ? [{ debugName: "activeLang" }] : /* istanbul ignore next */ []));
30
+ /** Languages available in the language switcher. */
31
+ this.langs = input(['es', 'en'], ...(ngDevMode ? [{ debugName: "langs" }] : /* istanbul ignore next */ []));
32
+ /** Brand logo image/url. */
33
+ this.logo = input('', ...(ngDevMode ? [{ debugName: "logo" }] : /* istanbul ignore next */ []));
34
+ /** Application name shown when expanded. */
35
+ this.appName = input('', ...(ngDevMode ? [{ debugName: "appName" }] : /* istanbul ignore next */ []));
36
+ /** Role used to filter items that declare `roles`. */
37
+ this.userRole = input('', ...(ngDevMode ? [{ debugName: "userRole" }] : /* istanbul ignore next */ []));
38
+ /** Optional transform applied to item labels (e.g. i18n). */
39
+ this.labelPipe = input((label) => label, ...(ngDevMode ? [{ debugName: "labelPipe" }] : /* istanbul ignore next */ []));
40
+ /** Width of the collapsed rail. */
41
+ this.railWidth = input('4.5rem', ...(ngDevMode ? [{ debugName: "railWidth" }] : /* istanbul ignore next */ []));
42
+ /** Width when a section is expanded. */
43
+ this.expandedWidth = input('16.5rem', ...(ngDevMode ? [{ debugName: "expandedWidth" }] : /* istanbul ignore next */ []));
44
+ /** Tooltip for the workspace/home action. */
45
+ this.workspaceTooltip = input('Inicio', ...(ngDevMode ? [{ debugName: "workspaceTooltip" }] : /* istanbul ignore next */ []));
46
+ /** Tooltip for the logout action. */
47
+ this.logoutTooltip = input('Cerrar sesión', ...(ngDevMode ? [{ debugName: "logoutTooltip" }] : /* istanbul ignore next */ []));
48
+ /** Tooltip for collapsing the sidebar. */
49
+ this.collapseTooltip = input('Colapsar', ...(ngDevMode ? [{ debugName: "collapseTooltip" }] : /* istanbul ignore next */ []));
50
+ /** Tooltip for expanding the sidebar. */
51
+ this.expandTooltip = input('Expandir', ...(ngDevMode ? [{ debugName: "expandTooltip" }] : /* istanbul ignore next */ []));
52
+ /** Emitted when a section is selected, with its key and optional route. */
53
+ this.sectionSelected = output();
54
+ /** Emitted when a navigation item is clicked. */
55
+ this.itemClick = output();
56
+ /** Emitted with the next language code when the user switches language. */
57
+ this.setLang = output();
58
+ /** Emitted when the user requests to log out. */
59
+ this.logoutRequested = output();
60
+ /** Emitted with the new collapsed state after toggling. */
61
+ this.toggleSidebar = output();
62
+ /** Emitted when the workspace/home entry is clicked. */
63
+ this.workspaceClick = output();
64
+ this.getIcon = (name) => getIcon(name, LucideMenu);
65
+ /** Set of group ids currently expanded. */
66
+ this.expandedGroups = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedGroups" }] : /* istanbul ignore next */ []));
67
+ /** Current sidebar width depending on the collapsed state. */
68
+ this.width = computed(() => this.collapsed() ? this.railWidth() : this.expandedWidth(), ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
69
+ /** The section currently selected. */
70
+ this.activeSection = computed(() => this.sections().find((s) => s.key === this.activeSectionKey()) ?? null, ...(ngDevMode ? [{ debugName: "activeSection" }] : /* istanbul ignore next */ []));
71
+ /** Items of the active section, filtered by role. */
72
+ this.navItems = computed(() => {
73
+ const role = this.userRole();
74
+ const items = this.activeSection()?.items ?? [];
75
+ return items.filter((item) => {
76
+ if (!item.roles || item.roles.length === 0)
77
+ return true;
78
+ return role ? item.roles.includes(role) : false;
79
+ });
80
+ }, ...(ngDevMode ? [{ debugName: "navItems" }] : /* istanbul ignore next */ []));
81
+ effect(() => {
82
+ const url = this.activeUrl();
83
+ if (!url)
84
+ return;
85
+ const section = this.sections().find((s) => {
86
+ if (s.matchPrefixes?.length) {
87
+ return s.matchPrefixes.some((prefix) => url.startsWith(prefix));
88
+ }
89
+ return s.routerLink ? url.startsWith(s.routerLink) : false;
90
+ });
91
+ if (section) {
92
+ this.activeSectionKey.set(section.key);
93
+ }
94
+ });
95
+ }
96
+ /** Applies the `labelPipe` transform to a label. */
97
+ label(label) {
98
+ return this.labelPipe()(label);
99
+ }
100
+ /** Whether the section matches the active key. */
101
+ isSectionActive(section) {
102
+ return section.key === this.activeSectionKey();
103
+ }
104
+ /** Whether the item is the best route match for the active url. */
105
+ isItemActive(item) {
106
+ if (!item.routerLink)
107
+ return false;
108
+ return this.bestMatchItem() === item;
109
+ }
110
+ /** Whether one of the item's children matches the active url. */
111
+ isGroupActive(item) {
112
+ return (item.children?.some((c) => c.routerLink && this.matchesUrl(c.routerLink, this.activeUrl())) ?? false);
113
+ }
114
+ /** Exact or prefix match between a router link and the active url. */
115
+ matchesUrl(routerLink, url) {
116
+ return url === routerLink || url.startsWith(routerLink + '/');
117
+ }
118
+ /** Longest (most specific) item whose route matches the active url. */
119
+ bestMatchItem() {
120
+ const url = this.activeUrl();
121
+ let best = null;
122
+ for (const item of this.navItems()) {
123
+ if (item.routerLink && this.matchesUrl(item.routerLink, url)) {
124
+ if (!best || item.routerLink.length > best.routerLink.length) {
125
+ best = item;
126
+ }
127
+ }
128
+ for (const child of item.children ?? []) {
129
+ if (!child.routerLink || !this.matchesUrl(child.routerLink, url))
130
+ continue;
131
+ if (!best || child.routerLink.length > best.routerLink.length) {
132
+ best = child;
133
+ }
134
+ }
135
+ }
136
+ return best;
137
+ }
138
+ /** Whether a group is expanded. */
139
+ isGroupExpanded(item) {
140
+ return this.expandedGroups().has(item.id);
141
+ }
142
+ /** Toggles the expanded state of a group. */
143
+ toggleGroup(item) {
144
+ this.expandedGroups.update((set) => {
145
+ const next = new Set(set);
146
+ if (next.has(item.id)) {
147
+ next.delete(item.id);
148
+ }
149
+ else {
150
+ next.add(item.id);
151
+ }
152
+ return next;
153
+ });
154
+ }
155
+ /** Selects a section, emits `sectionSelected` and expands the rail when collapsed. */
156
+ onSectionClick(section) {
157
+ this.activeSectionKey.set(section.key);
158
+ this.sectionSelected.emit({ key: section.key, routerLink: section.routerLink });
159
+ if (this.collapsed()) {
160
+ this.collapsed.set(false);
161
+ this.toggleSidebar.emit(false);
162
+ }
163
+ }
164
+ /** Emits `itemClick` for a navigation item (skipping disabled items). */
165
+ onItemClick(item) {
166
+ if (item.disabled)
167
+ return;
168
+ this.itemClick.emit(item);
169
+ }
170
+ /** Emits `workspaceClick` and expands the sidebar if it was collapsed. */
171
+ onWorkspace() {
172
+ this.workspaceClick.emit();
173
+ if (this.collapsed()) {
174
+ this.collapsed.set(false);
175
+ this.toggleSidebar.emit(false);
176
+ }
177
+ }
178
+ /** Cycles to the next language and emits `setLang`. */
179
+ onToggleLang() {
180
+ const langs = this.langs();
181
+ if (langs.length === 0)
182
+ return;
183
+ const idx = langs.indexOf(this.activeLang());
184
+ const next = langs[(idx + 1) % langs.length] ?? langs[0];
185
+ this.setLang.emit(next);
186
+ }
187
+ /** Toggles collapse and emits `toggleSidebar`. */
188
+ onToggleSidebar() {
189
+ this.collapsed.update((v) => !v);
190
+ this.toggleSidebar.emit(this.collapsed());
191
+ }
192
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: RailSidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
193
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: RailSidebarComponent, isStandalone: true, selector: "shk-rail-sidebar", inputs: { sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, activeUrl: { classPropertyName: "activeUrl", publicName: "activeUrl", isSignal: true, isRequired: false, transformFunction: null }, activeSectionKey: { classPropertyName: "activeSectionKey", publicName: "activeSectionKey", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, activeLang: { classPropertyName: "activeLang", publicName: "activeLang", isSignal: true, isRequired: false, transformFunction: null }, langs: { classPropertyName: "langs", publicName: "langs", isSignal: true, isRequired: false, transformFunction: null }, logo: { classPropertyName: "logo", publicName: "logo", isSignal: true, isRequired: false, transformFunction: null }, appName: { classPropertyName: "appName", publicName: "appName", isSignal: true, isRequired: false, transformFunction: null }, userRole: { classPropertyName: "userRole", publicName: "userRole", isSignal: true, isRequired: false, transformFunction: null }, labelPipe: { classPropertyName: "labelPipe", publicName: "labelPipe", isSignal: true, isRequired: false, transformFunction: null }, railWidth: { classPropertyName: "railWidth", publicName: "railWidth", isSignal: true, isRequired: false, transformFunction: null }, expandedWidth: { classPropertyName: "expandedWidth", publicName: "expandedWidth", isSignal: true, isRequired: false, transformFunction: null }, workspaceTooltip: { classPropertyName: "workspaceTooltip", publicName: "workspaceTooltip", isSignal: true, isRequired: false, transformFunction: null }, logoutTooltip: { classPropertyName: "logoutTooltip", publicName: "logoutTooltip", isSignal: true, isRequired: false, transformFunction: null }, collapseTooltip: { classPropertyName: "collapseTooltip", publicName: "collapseTooltip", isSignal: true, isRequired: false, transformFunction: null }, expandTooltip: { classPropertyName: "expandTooltip", publicName: "expandTooltip", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeSectionKey: "activeSectionKeyChange", collapsed: "collapsedChange", sectionSelected: "sectionSelected", itemClick: "itemClick", setLang: "setLang", logoutRequested: "logoutRequested", toggleSidebar: "toggleSidebar", workspaceClick: "workspaceClick" }, ngImport: i0, template: "<aside\n class=\"h-full flex overflow-hidden shrink-0 _shk-bg-white dark:[background-color:var(--shk-surface-50)] border-r _shk-border dark:[border-color:var(--shk-surface-100)]\"\n [style.width]=\"width()\"\n>\n <!-- Rail: vertical icon column -->\n <div\n class=\"h-full flex flex-col items-center shrink-0 px-[0.3rem] py-2 gap-1 border-r _shk-border dark:[border-color:var(--shk-surface-100)]\"\n [style.width]=\"railWidth()\"\n >\n <!-- Workspace / logo -->\n <div class=\"flex items-center justify-center w-full\">\n <button\n type=\"button\"\n (click)=\"onWorkspace()\"\n [class.is-collapsed]=\"collapsed()\"\n class=\"rail-workspace w-[3.2rem] h-[3.2rem] rounded-xl _shk-bg-surface-100 dark:[background-color:var(--shk-surface-200)] border-none grid place-items-center p-0 relative transition-all\"\n [title]=\"workspaceTooltip()\"\n >\n @if (logo()) {\n <img [src]=\"logo()\" alt=\"Logo\" class=\"rail-app-icon w-8 h-8 object-contain\" />\n } @else {\n <svg [lucideIcon]=\"getIcon('menu')\" class=\"rail-app-icon w-6 h-6 _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\"></svg>\n }\n @if (collapsed()) {\n <svg [lucideIcon]=\"getIcon('panel-right')\" class=\"rail-toggle-icon w-5 h-5 _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\"></svg>\n }\n </button>\n </div>\n\n <!-- Section actions -->\n <div class=\"rail-actions flex-1 flex flex-col items-center gap-1 pt-1\">\n @for (section of sections(); track section.key) {\n <shk-tooltip [text]=\"label(section.label)\" position=\"right\" mode=\"fixed\">\n <button\n type=\"button\"\n (click)=\"onSectionClick(section)\"\n class=\"rail-icon w-[3.4rem] h-[3.4rem] rounded-[0.85rem] grid place-items-center transition-all cursor-pointer\"\n [class.is-active]=\"isSectionActive(section)\"\n [attr.aria-label]=\"label(section.label)\"\n >\n <svg [lucideIcon]=\"getIcon(section.icon)\" class=\"w-5 h-5\"></svg>\n </button>\n </shk-tooltip>\n }\n </div>\n\n <!-- Bottom: language + logout -->\n <div class=\"rail-bottom mt-auto flex flex-col items-center gap-1\">\n <button\n type=\"button\"\n (click)=\"onToggleLang()\"\n class=\"rail-icon w-[3.4rem] h-[3.4rem] rounded-[0.85rem] grid place-items-center transition-all cursor-pointer\"\n [title]=\"activeLang()\"\n >\n <div class=\"flex flex-col items-center gap-[0.15rem]\">\n <svg [lucideIcon]=\"getIcon('globe')\" class=\"w-5 h-5\"></svg>\n <span class=\"rail-lang-code text-[0.5rem] font-bold tracking-[0.05em] leading-none\">{{ activeLang() | uppercase }}</span>\n </div>\n </button>\n\n <button\n type=\"button\"\n (click)=\"logoutRequested.emit()\"\n class=\"rail-icon rail-logout w-[3.4rem] h-[3.4rem] rounded-[0.85rem] grid place-items-center transition-all cursor-pointer\"\n [title]=\"logoutTooltip()\"\n >\n <svg [lucideIcon]=\"getIcon('log-out')\" class=\"w-5 h-5\"></svg>\n </button>\n </div>\n </div>\n\n <!-- Nav: section panel (hidden when collapsed) -->\n @if (!collapsed()) {\n <div class=\"flex-1 min-w-0 flex flex-col _shk-bg-white dark:[background-color:var(--shk-surface-50)]\">\n <!-- Brand header -->\n <div class=\"flex items-center justify-between gap-2 px-3 py-4 border-b _shk-border dark:[border-color:var(--shk-surface-100)]\">\n <span class=\"nav-app text-base font-bold whitespace-nowrap overflow-hidden text-ellipsis _shk-text-surface-800 dark:[color:var(--shk-surface-800)]\">\n {{ appName() }}\n </span>\n <button\n type=\"button\"\n (click)=\"onToggleSidebar()\"\n class=\"nav-toggle w-[1.8rem] h-[1.8rem] rounded-lg border-none bg-transparent grid place-items-center cursor-pointer shrink-0 transition-colors _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\"\n [title]=\"collapseTooltip()\"\n >\n <svg [lucideIcon]=\"getIcon('panel-right')\" class=\"w-4 h-4\"></svg>\n </button>\n </div>\n\n <!-- Menu -->\n <nav class=\"flex-1 overflow-y-auto _shk-scrollbar px-2 py-3\">\n @if (activeSection()) {\n <div class=\"px-2 pb-3\">\n <span class=\"nav-section-label text-xs font-bold tracking-[0.08em] uppercase _shk-text-surface-400 dark:[color:var(--shk-surface-500)] block whitespace-nowrap overflow-hidden text-ellipsis\">\n {{ label(activeSection()!.label) }}\n </span>\n </div>\n }\n\n <ul class=\"space-y-1\">\n @for (item of navItems(); track item.id) {\n @if (item.separator) {\n <li class=\"my-2 border-t _shk-border dark:[border-color:var(--shk-surface-200)]\"></li>\n }\n\n @if (item.children?.length) {\n <!-- Expandable group -->\n <li>\n <button\n type=\"button\"\n (click)=\"toggleGroup(item)\"\n class=\"w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-200\"\n [class._shk-bg-primary]=\"isGroupActive(item)\"\n [class._shk-text-white]=\"isGroupActive(item)\"\n [class.shadow-md]=\"isGroupActive(item)\"\n [class._shk-text-surface-700]=\"!isGroupActive(item)\"\n [class.dark:[color:var(--shk-surface-600)]]=\"!isGroupActive(item)\"\n [class.hover:[background-color:var(--shk-surface-100)]]=\"!isGroupActive(item)\"\n [class.dark:hover:[background-color:var(--shk-surface-200)]]=\"!isGroupActive(item)\"\n >\n @if (item.icon) {\n <svg [lucideIcon]=\"getIcon(item.icon)\" class=\"w-5 h-5 shrink-0\"></svg>\n }\n <span class=\"flex-1 text-left whitespace-nowrap overflow-hidden\">{{ label(item.label) }}</span>\n <svg\n [lucideIcon]=\"getIcon('chevron-down')\"\n class=\"w-4 h-4 transition-transform duration-200 shrink-0\"\n [class.rotate-180]=\"isGroupExpanded(item)\"\n ></svg>\n </button>\n\n @if (isGroupExpanded(item)) {\n <ul class=\"ml-3 mt-1 space-y-1 border-l-2 _shk-border dark:[border-color:var(--shk-surface-200)] pl-2\">\n @for (child of item.children; track child.id) {\n <li>\n <button\n type=\"button\"\n (click)=\"onItemClick(child)\"\n class=\"w-full flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium transition-all duration-200\"\n [class._shk-bg-primary-soft]=\"isItemActive(child)\"\n [class._shk-bg-primary-soft-dark]=\"isItemActive(child)\"\n [class._shk-text-primary-700]=\"isItemActive(child)\"\n [class.dark:[color:var(--shk-primary-300)]]=\"isItemActive(child)\"\n [class._shk-text-surface-600]=\"!isItemActive(child)\"\n [class.dark:[color:var(--shk-surface-400)]]=\"!isItemActive(child)\"\n [class.hover:[background-color:var(--shk-surface-100)]]=\"!isItemActive(child)\"\n [class.dark:hover:[background-color:var(--shk-surface-200)]]=\"!isItemActive(child)\"\n [class.hover:[color:var(--shk-surface-900)]]=\"!isItemActive(child)\"\n [class.dark:hover:[color:var(--shk-surface-700)]]=\"!isItemActive(child)\"\n >\n @if (child.icon) {\n <svg [lucideIcon]=\"getIcon(child.icon)\" class=\"w-4 h-4 shrink-0\"></svg>\n }\n <span class=\"whitespace-nowrap overflow-hidden\">{{ label(child.label) }}</span>\n @if (isItemActive(child)) {\n <span class=\"w-1.5 h-1.5 rounded-full _shk-bg-primary shrink-0 ml-auto\"></span>\n }\n </button>\n </li>\n }\n </ul>\n }\n </li>\n } @else {\n <!-- Standalone item -->\n <li>\n <button\n type=\"button\"\n (click)=\"onItemClick(item)\"\n class=\"w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-200\"\n [class._shk-bg-primary]=\"isItemActive(item)\"\n [class._shk-text-white]=\"isItemActive(item)\"\n [class.shadow-md]=\"isItemActive(item)\"\n [class._shk-text-surface-700]=\"!isItemActive(item)\"\n [class.dark:[color:var(--shk-surface-600)]]=\"!isItemActive(item)\"\n [class.hover:[background-color:var(--shk-surface-100)]]=\"!isItemActive(item)\"\n [class.dark:hover:[background-color:var(--shk-surface-200)]]=\"!isItemActive(item)\"\n >\n @if (item.icon) {\n <svg [lucideIcon]=\"getIcon(item.icon)\" class=\"w-5 h-5 shrink-0\"></svg>\n }\n <span class=\"flex-1 text-left whitespace-nowrap overflow-hidden\">{{ label(item.label) }}</span>\n @if (item.badge !== undefined) {\n <span class=\"text-xs font-bold px-2 py-0.5 rounded-full _shk-bg-primary _shk-text-white shrink-0\">\n {{ item.badge }}\n </span>\n }\n </button>\n </li>\n }\n }\n </ul>\n </nav>\n </div>\n }\n</aside>\n", styles: [":host{display:block;height:100%}.rail-workspace{cursor:pointer;transition:opacity .2s ease,box-shadow .2s ease}.rail-workspace.is-collapsed:hover{cursor:col-resize}.rail-workspace .rail-app-icon,.rail-workspace .rail-toggle-icon{grid-area:1 / 1 / 2 / 2;transition:opacity .2s ease}.rail-toggle-icon,.rail-workspace.is-collapsed:hover .rail-app-icon{opacity:0}.rail-workspace.is-collapsed:hover .rail-toggle-icon{opacity:1}.rail-icon{background:transparent;color:var(--shk-surface-700);border:1px solid transparent;transition:transform .18s ease,color .18s ease,background-color .18s ease,box-shadow .18s ease}.rail-icon svg{stroke-width:1.8}.rail-icon:hover{background:var(--shk-surface-100);color:var(--shk-primary-600)}.dark .rail-icon:hover{background:var(--shk-surface-200);color:var(--shk-primary-400)}.rail-icon.is-active{background:var(--shk-primary-600);color:#fff;box-shadow:0 1px 2px #0003}.dark .rail-icon.is-active{background:var(--shk-primary-500);color:#fff}.rail-logout:hover{color:var(--shk-error-500)}.dark .rail-logout:hover{color:var(--shk-error-400)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }, { kind: "component", type: TooltipComponent, selector: "shk-tooltip", inputs: ["text", "position", "mode", "offset"] }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }] }); }
194
+ }
195
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: RailSidebarComponent, decorators: [{
196
+ type: Component,
197
+ args: [{ selector: 'shk-rail-sidebar', standalone: true, imports: [CommonModule, LucideDynamicIcon, TooltipComponent], template: "<aside\n class=\"h-full flex overflow-hidden shrink-0 _shk-bg-white dark:[background-color:var(--shk-surface-50)] border-r _shk-border dark:[border-color:var(--shk-surface-100)]\"\n [style.width]=\"width()\"\n>\n <!-- Rail: vertical icon column -->\n <div\n class=\"h-full flex flex-col items-center shrink-0 px-[0.3rem] py-2 gap-1 border-r _shk-border dark:[border-color:var(--shk-surface-100)]\"\n [style.width]=\"railWidth()\"\n >\n <!-- Workspace / logo -->\n <div class=\"flex items-center justify-center w-full\">\n <button\n type=\"button\"\n (click)=\"onWorkspace()\"\n [class.is-collapsed]=\"collapsed()\"\n class=\"rail-workspace w-[3.2rem] h-[3.2rem] rounded-xl _shk-bg-surface-100 dark:[background-color:var(--shk-surface-200)] border-none grid place-items-center p-0 relative transition-all\"\n [title]=\"workspaceTooltip()\"\n >\n @if (logo()) {\n <img [src]=\"logo()\" alt=\"Logo\" class=\"rail-app-icon w-8 h-8 object-contain\" />\n } @else {\n <svg [lucideIcon]=\"getIcon('menu')\" class=\"rail-app-icon w-6 h-6 _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\"></svg>\n }\n @if (collapsed()) {\n <svg [lucideIcon]=\"getIcon('panel-right')\" class=\"rail-toggle-icon w-5 h-5 _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\"></svg>\n }\n </button>\n </div>\n\n <!-- Section actions -->\n <div class=\"rail-actions flex-1 flex flex-col items-center gap-1 pt-1\">\n @for (section of sections(); track section.key) {\n <shk-tooltip [text]=\"label(section.label)\" position=\"right\" mode=\"fixed\">\n <button\n type=\"button\"\n (click)=\"onSectionClick(section)\"\n class=\"rail-icon w-[3.4rem] h-[3.4rem] rounded-[0.85rem] grid place-items-center transition-all cursor-pointer\"\n [class.is-active]=\"isSectionActive(section)\"\n [attr.aria-label]=\"label(section.label)\"\n >\n <svg [lucideIcon]=\"getIcon(section.icon)\" class=\"w-5 h-5\"></svg>\n </button>\n </shk-tooltip>\n }\n </div>\n\n <!-- Bottom: language + logout -->\n <div class=\"rail-bottom mt-auto flex flex-col items-center gap-1\">\n <button\n type=\"button\"\n (click)=\"onToggleLang()\"\n class=\"rail-icon w-[3.4rem] h-[3.4rem] rounded-[0.85rem] grid place-items-center transition-all cursor-pointer\"\n [title]=\"activeLang()\"\n >\n <div class=\"flex flex-col items-center gap-[0.15rem]\">\n <svg [lucideIcon]=\"getIcon('globe')\" class=\"w-5 h-5\"></svg>\n <span class=\"rail-lang-code text-[0.5rem] font-bold tracking-[0.05em] leading-none\">{{ activeLang() | uppercase }}</span>\n </div>\n </button>\n\n <button\n type=\"button\"\n (click)=\"logoutRequested.emit()\"\n class=\"rail-icon rail-logout w-[3.4rem] h-[3.4rem] rounded-[0.85rem] grid place-items-center transition-all cursor-pointer\"\n [title]=\"logoutTooltip()\"\n >\n <svg [lucideIcon]=\"getIcon('log-out')\" class=\"w-5 h-5\"></svg>\n </button>\n </div>\n </div>\n\n <!-- Nav: section panel (hidden when collapsed) -->\n @if (!collapsed()) {\n <div class=\"flex-1 min-w-0 flex flex-col _shk-bg-white dark:[background-color:var(--shk-surface-50)]\">\n <!-- Brand header -->\n <div class=\"flex items-center justify-between gap-2 px-3 py-4 border-b _shk-border dark:[border-color:var(--shk-surface-100)]\">\n <span class=\"nav-app text-base font-bold whitespace-nowrap overflow-hidden text-ellipsis _shk-text-surface-800 dark:[color:var(--shk-surface-800)]\">\n {{ appName() }}\n </span>\n <button\n type=\"button\"\n (click)=\"onToggleSidebar()\"\n class=\"nav-toggle w-[1.8rem] h-[1.8rem] rounded-lg border-none bg-transparent grid place-items-center cursor-pointer shrink-0 transition-colors _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\"\n [title]=\"collapseTooltip()\"\n >\n <svg [lucideIcon]=\"getIcon('panel-right')\" class=\"w-4 h-4\"></svg>\n </button>\n </div>\n\n <!-- Menu -->\n <nav class=\"flex-1 overflow-y-auto _shk-scrollbar px-2 py-3\">\n @if (activeSection()) {\n <div class=\"px-2 pb-3\">\n <span class=\"nav-section-label text-xs font-bold tracking-[0.08em] uppercase _shk-text-surface-400 dark:[color:var(--shk-surface-500)] block whitespace-nowrap overflow-hidden text-ellipsis\">\n {{ label(activeSection()!.label) }}\n </span>\n </div>\n }\n\n <ul class=\"space-y-1\">\n @for (item of navItems(); track item.id) {\n @if (item.separator) {\n <li class=\"my-2 border-t _shk-border dark:[border-color:var(--shk-surface-200)]\"></li>\n }\n\n @if (item.children?.length) {\n <!-- Expandable group -->\n <li>\n <button\n type=\"button\"\n (click)=\"toggleGroup(item)\"\n class=\"w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-200\"\n [class._shk-bg-primary]=\"isGroupActive(item)\"\n [class._shk-text-white]=\"isGroupActive(item)\"\n [class.shadow-md]=\"isGroupActive(item)\"\n [class._shk-text-surface-700]=\"!isGroupActive(item)\"\n [class.dark:[color:var(--shk-surface-600)]]=\"!isGroupActive(item)\"\n [class.hover:[background-color:var(--shk-surface-100)]]=\"!isGroupActive(item)\"\n [class.dark:hover:[background-color:var(--shk-surface-200)]]=\"!isGroupActive(item)\"\n >\n @if (item.icon) {\n <svg [lucideIcon]=\"getIcon(item.icon)\" class=\"w-5 h-5 shrink-0\"></svg>\n }\n <span class=\"flex-1 text-left whitespace-nowrap overflow-hidden\">{{ label(item.label) }}</span>\n <svg\n [lucideIcon]=\"getIcon('chevron-down')\"\n class=\"w-4 h-4 transition-transform duration-200 shrink-0\"\n [class.rotate-180]=\"isGroupExpanded(item)\"\n ></svg>\n </button>\n\n @if (isGroupExpanded(item)) {\n <ul class=\"ml-3 mt-1 space-y-1 border-l-2 _shk-border dark:[border-color:var(--shk-surface-200)] pl-2\">\n @for (child of item.children; track child.id) {\n <li>\n <button\n type=\"button\"\n (click)=\"onItemClick(child)\"\n class=\"w-full flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium transition-all duration-200\"\n [class._shk-bg-primary-soft]=\"isItemActive(child)\"\n [class._shk-bg-primary-soft-dark]=\"isItemActive(child)\"\n [class._shk-text-primary-700]=\"isItemActive(child)\"\n [class.dark:[color:var(--shk-primary-300)]]=\"isItemActive(child)\"\n [class._shk-text-surface-600]=\"!isItemActive(child)\"\n [class.dark:[color:var(--shk-surface-400)]]=\"!isItemActive(child)\"\n [class.hover:[background-color:var(--shk-surface-100)]]=\"!isItemActive(child)\"\n [class.dark:hover:[background-color:var(--shk-surface-200)]]=\"!isItemActive(child)\"\n [class.hover:[color:var(--shk-surface-900)]]=\"!isItemActive(child)\"\n [class.dark:hover:[color:var(--shk-surface-700)]]=\"!isItemActive(child)\"\n >\n @if (child.icon) {\n <svg [lucideIcon]=\"getIcon(child.icon)\" class=\"w-4 h-4 shrink-0\"></svg>\n }\n <span class=\"whitespace-nowrap overflow-hidden\">{{ label(child.label) }}</span>\n @if (isItemActive(child)) {\n <span class=\"w-1.5 h-1.5 rounded-full _shk-bg-primary shrink-0 ml-auto\"></span>\n }\n </button>\n </li>\n }\n </ul>\n }\n </li>\n } @else {\n <!-- Standalone item -->\n <li>\n <button\n type=\"button\"\n (click)=\"onItemClick(item)\"\n class=\"w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-200\"\n [class._shk-bg-primary]=\"isItemActive(item)\"\n [class._shk-text-white]=\"isItemActive(item)\"\n [class.shadow-md]=\"isItemActive(item)\"\n [class._shk-text-surface-700]=\"!isItemActive(item)\"\n [class.dark:[color:var(--shk-surface-600)]]=\"!isItemActive(item)\"\n [class.hover:[background-color:var(--shk-surface-100)]]=\"!isItemActive(item)\"\n [class.dark:hover:[background-color:var(--shk-surface-200)]]=\"!isItemActive(item)\"\n >\n @if (item.icon) {\n <svg [lucideIcon]=\"getIcon(item.icon)\" class=\"w-5 h-5 shrink-0\"></svg>\n }\n <span class=\"flex-1 text-left whitespace-nowrap overflow-hidden\">{{ label(item.label) }}</span>\n @if (item.badge !== undefined) {\n <span class=\"text-xs font-bold px-2 py-0.5 rounded-full _shk-bg-primary _shk-text-white shrink-0\">\n {{ item.badge }}\n </span>\n }\n </button>\n </li>\n }\n }\n </ul>\n </nav>\n </div>\n }\n</aside>\n", styles: [":host{display:block;height:100%}.rail-workspace{cursor:pointer;transition:opacity .2s ease,box-shadow .2s ease}.rail-workspace.is-collapsed:hover{cursor:col-resize}.rail-workspace .rail-app-icon,.rail-workspace .rail-toggle-icon{grid-area:1 / 1 / 2 / 2;transition:opacity .2s ease}.rail-toggle-icon,.rail-workspace.is-collapsed:hover .rail-app-icon{opacity:0}.rail-workspace.is-collapsed:hover .rail-toggle-icon{opacity:1}.rail-icon{background:transparent;color:var(--shk-surface-700);border:1px solid transparent;transition:transform .18s ease,color .18s ease,background-color .18s ease,box-shadow .18s ease}.rail-icon svg{stroke-width:1.8}.rail-icon:hover{background:var(--shk-surface-100);color:var(--shk-primary-600)}.dark .rail-icon:hover{background:var(--shk-surface-200);color:var(--shk-primary-400)}.rail-icon.is-active{background:var(--shk-primary-600);color:#fff;box-shadow:0 1px 2px #0003}.dark .rail-icon.is-active{background:var(--shk-primary-500);color:#fff}.rail-logout:hover{color:var(--shk-error-500)}.dark .rail-logout:hover{color:var(--shk-error-400)}\n"] }]
198
+ }], ctorParameters: () => [], propDecorators: { sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }], activeUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeUrl", required: false }] }], activeSectionKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeSectionKey", required: false }] }, { type: i0.Output, args: ["activeSectionKeyChange"] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }, { type: i0.Output, args: ["collapsedChange"] }], activeLang: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeLang", required: false }] }], langs: [{ type: i0.Input, args: [{ isSignal: true, alias: "langs", required: false }] }], logo: [{ type: i0.Input, args: [{ isSignal: true, alias: "logo", required: false }] }], appName: [{ type: i0.Input, args: [{ isSignal: true, alias: "appName", required: false }] }], userRole: [{ type: i0.Input, args: [{ isSignal: true, alias: "userRole", required: false }] }], labelPipe: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelPipe", required: false }] }], railWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "railWidth", required: false }] }], expandedWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedWidth", required: false }] }], workspaceTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "workspaceTooltip", required: false }] }], logoutTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoutTooltip", required: false }] }], collapseTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseTooltip", required: false }] }], expandTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandTooltip", required: false }] }], sectionSelected: [{ type: i0.Output, args: ["sectionSelected"] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], setLang: [{ type: i0.Output, args: ["setLang"] }], logoutRequested: [{ type: i0.Output, args: ["logoutRequested"] }], toggleSidebar: [{ type: i0.Output, args: ["toggleSidebar"] }], workspaceClick: [{ type: i0.Output, args: ["workspaceClick"] }] } });
199
+
200
+ /**
201
+ * Generated bundle index. Do not edit.
202
+ */
203
+
204
+ export { RailSidebarComponent };
205
+ //# sourceMappingURL=shirkasoft-ui-components-rail-sidebar.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shirkasoft-ui-components-rail-sidebar.mjs","sources":["../../../projects/ui-components/rail-sidebar/rail-sidebar.component.ts","../../../projects/ui-components/rail-sidebar/rail-sidebar.component.html","../../../projects/ui-components/rail-sidebar/shirkasoft-ui-components-rail-sidebar.ts"],"sourcesContent":["import {\n Component,\n computed,\n effect,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { LucideDynamicIcon, LucideMenu } from '@lucide/angular';\nimport { getIcon as getIconFromCentral } from 'shirkasoft-ui-components/utils';\nimport { TooltipComponent } from 'shirkasoft-ui-components/tooltip';\n\nexport interface RailSidebarItem {\n id: string;\n label: string;\n icon?: string | any;\n routerLink?: string;\n children?: RailSidebarItem[];\n roles?: string[];\n badge?: string | number;\n disabled?: boolean;\n separator?: boolean;\n}\n\nexport interface RailSidebarSection {\n key: string;\n label: string;\n icon?: string | any;\n routerLink?: string;\n matchPrefixes?: string[];\n items?: RailSidebarItem[];\n}\n\nexport interface RailSidebarSectionEvent {\n key: string;\n routerLink?: string;\n}\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 * Narrow \"rail\" sidebar that expands into sections. Supports sections, roles,\n * language switching, collapse/expand and responsive tooltips.\n */\n@Component({\n selector: 'shk-rail-sidebar',\n standalone: true,\n imports: [CommonModule, LucideDynamicIcon, TooltipComponent],\n templateUrl: './rail-sidebar.component.html',\n styleUrls: ['./rail-sidebar.component.css'],\n})\nexport class RailSidebarComponent {\n /** Sections presented as expandable areas of the rail. */\n sections = input<RailSidebarSection[]>([]);\n /** Current location url used to detect the active section/item. */\n activeUrl = input<string>('');\n /** Key of the active section, bindable with [(activeSectionKey)]. */\n activeSectionKey = model<string>('');\n /** Collapsed (rail only) state, bindable with [(collapsed)]. */\n collapsed = model<boolean>(false);\n /** Active language code. */\n activeLang = input<string>('es');\n /** Languages available in the language switcher. */\n langs = input<string[]>(['es', 'en']);\n /** Brand logo image/url. */\n logo = input<string>('');\n /** Application name shown when expanded. */\n appName = input<string>('');\n /** Role used to filter items that declare `roles`. */\n userRole = input<string>('');\n /** Optional transform applied to item labels (e.g. i18n). */\n labelPipe = input<(label: string) => string>((label: string) => label);\n /** Width of the collapsed rail. */\n railWidth = input<string>('4.5rem');\n /** Width when a section is expanded. */\n expandedWidth = input<string>('16.5rem');\n /** Tooltip for the workspace/home action. */\n workspaceTooltip = input<string>('Inicio');\n /** Tooltip for the logout action. */\n logoutTooltip = input<string>('Cerrar sesión');\n /** Tooltip for collapsing the sidebar. */\n collapseTooltip = input<string>('Colapsar');\n /** Tooltip for expanding the sidebar. */\n expandTooltip = input<string>('Expandir');\n\n /** Emitted when a section is selected, with its key and optional route. */\n sectionSelected = output<RailSidebarSectionEvent>();\n /** Emitted when a navigation item is clicked. */\n itemClick = output<RailSidebarItem>();\n /** Emitted with the next language code when the user switches language. */\n setLang = output<string>();\n /** Emitted when the user requests to log out. */\n logoutRequested = output<void>();\n /** Emitted with the new collapsed state after toggling. */\n toggleSidebar = output<boolean>();\n /** Emitted when the workspace/home entry is clicked. */\n workspaceClick = output<void>();\n\n protected getIcon = (name: any) => getIconFromCentral(name, LucideMenu);\n /** Set of group ids currently expanded. */\n protected expandedGroups = signal<Set<string>>(new Set());\n\n constructor() {\n effect(() => {\n const url = this.activeUrl();\n if (!url) return;\n const section = this.sections().find((s) => {\n if (s.matchPrefixes?.length) {\n return s.matchPrefixes.some((prefix) => url.startsWith(prefix));\n }\n return s.routerLink ? url.startsWith(s.routerLink) : false;\n });\n if (section) {\n this.activeSectionKey.set(section.key);\n }\n });\n }\n\n /** Current sidebar width depending on the collapsed state. */\n protected width = computed(() =>\n this.collapsed() ? this.railWidth() : this.expandedWidth(),\n );\n\n /** The section currently selected. */\n protected activeSection = computed<RailSidebarSection | null>(\n () =>\n this.sections().find((s) => s.key === this.activeSectionKey()) ?? null,\n );\n\n /** Items of the active section, filtered by role. */\n protected navItems = computed<RailSidebarItem[]>(() => {\n const role = this.userRole();\n const items = this.activeSection()?.items ?? [];\n return items.filter((item) => {\n if (!item.roles || item.roles.length === 0) return true;\n return role ? item.roles.includes(role) : false;\n });\n });\n\n /** Applies the `labelPipe` transform to a label. */\n protected label(label: string): string {\n return this.labelPipe()(label);\n }\n\n /** Whether the section matches the active key. */\n protected isSectionActive(section: RailSidebarSection): boolean {\n return section.key === this.activeSectionKey();\n }\n\n /** Whether the item is the best route match for the active url. */\n protected isItemActive(item: RailSidebarItem): boolean {\n if (!item.routerLink) return false;\n return this.bestMatchItem() === item;\n }\n\n /** Whether one of the item's children matches the active url. */\n protected isGroupActive(item: RailSidebarItem): boolean {\n return (\n item.children?.some(\n (c) => c.routerLink && this.matchesUrl(c.routerLink, this.activeUrl()),\n ) ?? false\n );\n }\n\n /** Exact or prefix match between a router link and the active url. */\n private matchesUrl(routerLink: string, url: string): boolean {\n return url === routerLink || url.startsWith(routerLink + '/');\n }\n\n /** Longest (most specific) item whose route matches the active url. */\n private bestMatchItem(): RailSidebarItem | null {\n const url = this.activeUrl();\n let best: RailSidebarItem | null = null;\n for (const item of this.navItems()) {\n if (item.routerLink && this.matchesUrl(item.routerLink, url)) {\n if (!best || item.routerLink.length > best.routerLink!.length) {\n best = item;\n }\n }\n for (const child of item.children ?? []) {\n if (!child.routerLink || !this.matchesUrl(child.routerLink, url)) continue;\n if (!best || child.routerLink.length > best.routerLink!.length) {\n best = child;\n }\n }\n }\n return best;\n }\n\n /** Whether a group is expanded. */\n protected isGroupExpanded(item: RailSidebarItem): boolean {\n return this.expandedGroups().has(item.id);\n }\n\n /** Toggles the expanded state of a group. */\n protected toggleGroup(item: RailSidebarItem): void {\n this.expandedGroups.update((set) => {\n const next = new Set(set);\n if (next.has(item.id)) {\n next.delete(item.id);\n } else {\n next.add(item.id);\n }\n return next;\n });\n }\n\n /** Selects a section, emits `sectionSelected` and expands the rail when collapsed. */\n protected onSectionClick(section: RailSidebarSection): void {\n this.activeSectionKey.set(section.key);\n this.sectionSelected.emit({ key: section.key, routerLink: section.routerLink });\n if (this.collapsed()) {\n this.collapsed.set(false);\n this.toggleSidebar.emit(false);\n }\n }\n\n /** Emits `itemClick` for a navigation item (skipping disabled items). */\n protected onItemClick(item: RailSidebarItem): void {\n if (item.disabled) return;\n this.itemClick.emit(item);\n }\n\n /** Emits `workspaceClick` and expands the sidebar if it was collapsed. */\n protected onWorkspace(): void {\n this.workspaceClick.emit();\n if (this.collapsed()) {\n this.collapsed.set(false);\n this.toggleSidebar.emit(false);\n }\n }\n\n /** Cycles to the next language and emits `setLang`. */\n protected onToggleLang(): void {\n const langs = this.langs();\n if (langs.length === 0) return;\n const idx = langs.indexOf(this.activeLang());\n const next = langs[(idx + 1) % langs.length] ?? langs[0];\n this.setLang.emit(next);\n }\n\n /** Toggles collapse and emits `toggleSidebar`. */\n protected onToggleSidebar(): void {\n this.collapsed.update((v) => !v);\n this.toggleSidebar.emit(this.collapsed());\n }\n}\n","<aside\n class=\"h-full flex overflow-hidden shrink-0 _shk-bg-white dark:[background-color:var(--shk-surface-50)] border-r _shk-border dark:[border-color:var(--shk-surface-100)]\"\n [style.width]=\"width()\"\n>\n <!-- Rail: vertical icon column -->\n <div\n class=\"h-full flex flex-col items-center shrink-0 px-[0.3rem] py-2 gap-1 border-r _shk-border dark:[border-color:var(--shk-surface-100)]\"\n [style.width]=\"railWidth()\"\n >\n <!-- Workspace / logo -->\n <div class=\"flex items-center justify-center w-full\">\n <button\n type=\"button\"\n (click)=\"onWorkspace()\"\n [class.is-collapsed]=\"collapsed()\"\n class=\"rail-workspace w-[3.2rem] h-[3.2rem] rounded-xl _shk-bg-surface-100 dark:[background-color:var(--shk-surface-200)] border-none grid place-items-center p-0 relative transition-all\"\n [title]=\"workspaceTooltip()\"\n >\n @if (logo()) {\n <img [src]=\"logo()\" alt=\"Logo\" class=\"rail-app-icon w-8 h-8 object-contain\" />\n } @else {\n <svg [lucideIcon]=\"getIcon('menu')\" class=\"rail-app-icon w-6 h-6 _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\"></svg>\n }\n @if (collapsed()) {\n <svg [lucideIcon]=\"getIcon('panel-right')\" class=\"rail-toggle-icon w-5 h-5 _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\"></svg>\n }\n </button>\n </div>\n\n <!-- Section actions -->\n <div class=\"rail-actions flex-1 flex flex-col items-center gap-1 pt-1\">\n @for (section of sections(); track section.key) {\n <shk-tooltip [text]=\"label(section.label)\" position=\"right\" mode=\"fixed\">\n <button\n type=\"button\"\n (click)=\"onSectionClick(section)\"\n class=\"rail-icon w-[3.4rem] h-[3.4rem] rounded-[0.85rem] grid place-items-center transition-all cursor-pointer\"\n [class.is-active]=\"isSectionActive(section)\"\n [attr.aria-label]=\"label(section.label)\"\n >\n <svg [lucideIcon]=\"getIcon(section.icon)\" class=\"w-5 h-5\"></svg>\n </button>\n </shk-tooltip>\n }\n </div>\n\n <!-- Bottom: language + logout -->\n <div class=\"rail-bottom mt-auto flex flex-col items-center gap-1\">\n <button\n type=\"button\"\n (click)=\"onToggleLang()\"\n class=\"rail-icon w-[3.4rem] h-[3.4rem] rounded-[0.85rem] grid place-items-center transition-all cursor-pointer\"\n [title]=\"activeLang()\"\n >\n <div class=\"flex flex-col items-center gap-[0.15rem]\">\n <svg [lucideIcon]=\"getIcon('globe')\" class=\"w-5 h-5\"></svg>\n <span class=\"rail-lang-code text-[0.5rem] font-bold tracking-[0.05em] leading-none\">{{ activeLang() | uppercase }}</span>\n </div>\n </button>\n\n <button\n type=\"button\"\n (click)=\"logoutRequested.emit()\"\n class=\"rail-icon rail-logout w-[3.4rem] h-[3.4rem] rounded-[0.85rem] grid place-items-center transition-all cursor-pointer\"\n [title]=\"logoutTooltip()\"\n >\n <svg [lucideIcon]=\"getIcon('log-out')\" class=\"w-5 h-5\"></svg>\n </button>\n </div>\n </div>\n\n <!-- Nav: section panel (hidden when collapsed) -->\n @if (!collapsed()) {\n <div class=\"flex-1 min-w-0 flex flex-col _shk-bg-white dark:[background-color:var(--shk-surface-50)]\">\n <!-- Brand header -->\n <div class=\"flex items-center justify-between gap-2 px-3 py-4 border-b _shk-border dark:[border-color:var(--shk-surface-100)]\">\n <span class=\"nav-app text-base font-bold whitespace-nowrap overflow-hidden text-ellipsis _shk-text-surface-800 dark:[color:var(--shk-surface-800)]\">\n {{ appName() }}\n </span>\n <button\n type=\"button\"\n (click)=\"onToggleSidebar()\"\n class=\"nav-toggle w-[1.8rem] h-[1.8rem] rounded-lg border-none bg-transparent grid place-items-center cursor-pointer shrink-0 transition-colors _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\"\n [title]=\"collapseTooltip()\"\n >\n <svg [lucideIcon]=\"getIcon('panel-right')\" class=\"w-4 h-4\"></svg>\n </button>\n </div>\n\n <!-- Menu -->\n <nav class=\"flex-1 overflow-y-auto _shk-scrollbar px-2 py-3\">\n @if (activeSection()) {\n <div class=\"px-2 pb-3\">\n <span class=\"nav-section-label text-xs font-bold tracking-[0.08em] uppercase _shk-text-surface-400 dark:[color:var(--shk-surface-500)] block whitespace-nowrap overflow-hidden text-ellipsis\">\n {{ label(activeSection()!.label) }}\n </span>\n </div>\n }\n\n <ul class=\"space-y-1\">\n @for (item of navItems(); track item.id) {\n @if (item.separator) {\n <li class=\"my-2 border-t _shk-border dark:[border-color:var(--shk-surface-200)]\"></li>\n }\n\n @if (item.children?.length) {\n <!-- Expandable group -->\n <li>\n <button\n type=\"button\"\n (click)=\"toggleGroup(item)\"\n class=\"w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-200\"\n [class._shk-bg-primary]=\"isGroupActive(item)\"\n [class._shk-text-white]=\"isGroupActive(item)\"\n [class.shadow-md]=\"isGroupActive(item)\"\n [class._shk-text-surface-700]=\"!isGroupActive(item)\"\n [class.dark:[color:var(--shk-surface-600)]]=\"!isGroupActive(item)\"\n [class.hover:[background-color:var(--shk-surface-100)]]=\"!isGroupActive(item)\"\n [class.dark:hover:[background-color:var(--shk-surface-200)]]=\"!isGroupActive(item)\"\n >\n @if (item.icon) {\n <svg [lucideIcon]=\"getIcon(item.icon)\" class=\"w-5 h-5 shrink-0\"></svg>\n }\n <span class=\"flex-1 text-left whitespace-nowrap overflow-hidden\">{{ label(item.label) }}</span>\n <svg\n [lucideIcon]=\"getIcon('chevron-down')\"\n class=\"w-4 h-4 transition-transform duration-200 shrink-0\"\n [class.rotate-180]=\"isGroupExpanded(item)\"\n ></svg>\n </button>\n\n @if (isGroupExpanded(item)) {\n <ul class=\"ml-3 mt-1 space-y-1 border-l-2 _shk-border dark:[border-color:var(--shk-surface-200)] pl-2\">\n @for (child of item.children; track child.id) {\n <li>\n <button\n type=\"button\"\n (click)=\"onItemClick(child)\"\n class=\"w-full flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium transition-all duration-200\"\n [class._shk-bg-primary-soft]=\"isItemActive(child)\"\n [class._shk-bg-primary-soft-dark]=\"isItemActive(child)\"\n [class._shk-text-primary-700]=\"isItemActive(child)\"\n [class.dark:[color:var(--shk-primary-300)]]=\"isItemActive(child)\"\n [class._shk-text-surface-600]=\"!isItemActive(child)\"\n [class.dark:[color:var(--shk-surface-400)]]=\"!isItemActive(child)\"\n [class.hover:[background-color:var(--shk-surface-100)]]=\"!isItemActive(child)\"\n [class.dark:hover:[background-color:var(--shk-surface-200)]]=\"!isItemActive(child)\"\n [class.hover:[color:var(--shk-surface-900)]]=\"!isItemActive(child)\"\n [class.dark:hover:[color:var(--shk-surface-700)]]=\"!isItemActive(child)\"\n >\n @if (child.icon) {\n <svg [lucideIcon]=\"getIcon(child.icon)\" class=\"w-4 h-4 shrink-0\"></svg>\n }\n <span class=\"whitespace-nowrap overflow-hidden\">{{ label(child.label) }}</span>\n @if (isItemActive(child)) {\n <span class=\"w-1.5 h-1.5 rounded-full _shk-bg-primary shrink-0 ml-auto\"></span>\n }\n </button>\n </li>\n }\n </ul>\n }\n </li>\n } @else {\n <!-- Standalone item -->\n <li>\n <button\n type=\"button\"\n (click)=\"onItemClick(item)\"\n class=\"w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-200\"\n [class._shk-bg-primary]=\"isItemActive(item)\"\n [class._shk-text-white]=\"isItemActive(item)\"\n [class.shadow-md]=\"isItemActive(item)\"\n [class._shk-text-surface-700]=\"!isItemActive(item)\"\n [class.dark:[color:var(--shk-surface-600)]]=\"!isItemActive(item)\"\n [class.hover:[background-color:var(--shk-surface-100)]]=\"!isItemActive(item)\"\n [class.dark:hover:[background-color:var(--shk-surface-200)]]=\"!isItemActive(item)\"\n >\n @if (item.icon) {\n <svg [lucideIcon]=\"getIcon(item.icon)\" class=\"w-5 h-5 shrink-0\"></svg>\n }\n <span class=\"flex-1 text-left whitespace-nowrap overflow-hidden\">{{ label(item.label) }}</span>\n @if (item.badge !== undefined) {\n <span class=\"text-xs font-bold px-2 py-0.5 rounded-full _shk-bg-primary _shk-text-white shrink-0\">\n {{ item.badge }}\n </span>\n }\n </button>\n </li>\n }\n }\n </ul>\n </nav>\n </div>\n }\n</aside>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["getIconFromCentral"],"mappings":";;;;;;;;AAwCA;;;;AAIG;AAEH;;;AAGG;MAQU,oBAAoB,CAAA;AAmD/B,IAAA,WAAA,GAAA;;AAjDA,QAAA,IAAA,CAAA,QAAQ,GAAG,KAAK,CAAuB,EAAE,+EAAC;;AAE1C,QAAA,IAAA,CAAA,SAAS,GAAG,KAAK,CAAS,EAAE,gFAAC;;AAE7B,QAAA,IAAA,CAAA,gBAAgB,GAAG,KAAK,CAAS,EAAE,uFAAC;;AAEpC,QAAA,IAAA,CAAA,SAAS,GAAG,KAAK,CAAU,KAAK,gFAAC;;AAEjC,QAAA,IAAA,CAAA,UAAU,GAAG,KAAK,CAAS,IAAI,iFAAC;;QAEhC,IAAA,CAAA,KAAK,GAAG,KAAK,CAAW,CAAC,IAAI,EAAE,IAAI,CAAC,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,OAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAC;;AAErC,QAAA,IAAA,CAAA,IAAI,GAAG,KAAK,CAAS,EAAE,2EAAC;;AAExB,QAAA,IAAA,CAAA,OAAO,GAAG,KAAK,CAAS,EAAE,8EAAC;;AAE3B,QAAA,IAAA,CAAA,QAAQ,GAAG,KAAK,CAAS,EAAE,+EAAC;;QAE5B,IAAA,CAAA,SAAS,GAAG,KAAK,CAA4B,CAAC,KAAa,KAAK,KAAK,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,WAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAC;;AAEtE,QAAA,IAAA,CAAA,SAAS,GAAG,KAAK,CAAS,QAAQ,gFAAC;;AAEnC,QAAA,IAAA,CAAA,aAAa,GAAG,KAAK,CAAS,SAAS,oFAAC;;AAExC,QAAA,IAAA,CAAA,gBAAgB,GAAG,KAAK,CAAS,QAAQ,uFAAC;;AAE1C,QAAA,IAAA,CAAA,aAAa,GAAG,KAAK,CAAS,eAAe,oFAAC;;AAE9C,QAAA,IAAA,CAAA,eAAe,GAAG,KAAK,CAAS,UAAU,sFAAC;;AAE3C,QAAA,IAAA,CAAA,aAAa,GAAG,KAAK,CAAS,UAAU,oFAAC;;QAGzC,IAAA,CAAA,eAAe,GAAG,MAAM,EAA2B;;QAEnD,IAAA,CAAA,SAAS,GAAG,MAAM,EAAmB;;QAErC,IAAA,CAAA,OAAO,GAAG,MAAM,EAAU;;QAE1B,IAAA,CAAA,eAAe,GAAG,MAAM,EAAQ;;QAEhC,IAAA,CAAA,aAAa,GAAG,MAAM,EAAW;;QAEjC,IAAA,CAAA,cAAc,GAAG,MAAM,EAAQ;AAErB,QAAA,IAAA,CAAA,OAAO,GAAG,CAAC,IAAS,KAAKA,OAAkB,CAAC,IAAI,EAAE,UAAU,CAAC;;AAE7D,QAAA,IAAA,CAAA,cAAc,GAAG,MAAM,CAAc,IAAI,GAAG,EAAE,qFAAC;;QAmB/C,IAAA,CAAA,KAAK,GAAG,QAAQ,CAAC,MACzB,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,aAAa,EAAE,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,OAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAC3D;;AAGS,QAAA,IAAA,CAAA,aAAa,GAAG,QAAQ,CAChC,MACE,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,gBAAgB,EAAE,CAAC,IAAI,IAAI,oFACzE;;AAGS,QAAA,IAAA,CAAA,QAAQ,GAAG,QAAQ,CAAoB,MAAK;AACpD,YAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE;YAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE,EAAE,KAAK,IAAI,EAAE;AAC/C,YAAA,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KAAI;gBAC3B,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;AAAE,oBAAA,OAAO,IAAI;AACvD,gBAAA,OAAO,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK;AACjD,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,+EAAC;QAlCA,MAAM,CAAC,MAAK;AACV,YAAA,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE;AAC5B,YAAA,IAAI,CAAC,GAAG;gBAAE;AACV,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAI;AACzC,gBAAA,IAAI,CAAC,CAAC,aAAa,EAAE,MAAM,EAAE;AAC3B,oBAAA,OAAO,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;gBACjE;AACA,gBAAA,OAAO,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,KAAK;AAC5D,YAAA,CAAC,CAAC;YACF,IAAI,OAAO,EAAE;gBACX,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC;YACxC;AACF,QAAA,CAAC,CAAC;IACJ;;AAwBU,IAAA,KAAK,CAAC,KAAa,EAAA;AAC3B,QAAA,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC;IAChC;;AAGU,IAAA,eAAe,CAAC,OAA2B,EAAA;QACnD,OAAO,OAAO,CAAC,GAAG,KAAK,IAAI,CAAC,gBAAgB,EAAE;IAChD;;AAGU,IAAA,YAAY,CAAC,IAAqB,EAAA;QAC1C,IAAI,CAAC,IAAI,CAAC,UAAU;AAAE,YAAA,OAAO,KAAK;AAClC,QAAA,OAAO,IAAI,CAAC,aAAa,EAAE,KAAK,IAAI;IACtC;;AAGU,IAAA,aAAa,CAAC,IAAqB,EAAA;AAC3C,QAAA,QACE,IAAI,CAAC,QAAQ,EAAE,IAAI,CACjB,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CACvE,IAAI,KAAK;IAEd;;IAGQ,UAAU,CAAC,UAAkB,EAAE,GAAW,EAAA;AAChD,QAAA,OAAO,GAAG,KAAK,UAAU,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,GAAG,GAAG,CAAC;IAC/D;;IAGQ,aAAa,GAAA;AACnB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE;QAC5B,IAAI,IAAI,GAA2B,IAAI;QACvC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;AAClC,YAAA,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,EAAE;AAC5D,gBAAA,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,UAAW,CAAC,MAAM,EAAE;oBAC7D,IAAI,GAAG,IAAI;gBACb;YACF;YACA,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE;AACvC,gBAAA,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC;oBAAE;AAClE,gBAAA,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,UAAW,CAAC,MAAM,EAAE;oBAC9D,IAAI,GAAG,KAAK;gBACd;YACF;QACF;AACA,QAAA,OAAO,IAAI;IACb;;AAGU,IAAA,eAAe,CAAC,IAAqB,EAAA;QAC7C,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;IAC3C;;AAGU,IAAA,WAAW,CAAC,IAAqB,EAAA;QACzC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,KAAI;AACjC,YAAA,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC;YACzB,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;AACrB,gBAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB;iBAAO;AACL,gBAAA,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB;AACA,YAAA,OAAO,IAAI;AACb,QAAA,CAAC,CAAC;IACJ;;AAGU,IAAA,cAAc,CAAC,OAA2B,EAAA;QAClD,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC;AACtC,QAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;AAC/E,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;AACpB,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACzB,YAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;QAChC;IACF;;AAGU,IAAA,WAAW,CAAC,IAAqB,EAAA;QACzC,IAAI,IAAI,CAAC,QAAQ;YAAE;AACnB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;IAC3B;;IAGU,WAAW,GAAA;AACnB,QAAA,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE;AAC1B,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;AACpB,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACzB,YAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;QAChC;IACF;;IAGU,YAAY,GAAA;AACpB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE;AAC1B,QAAA,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE;QACxB,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;AAC5C,QAAA,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC;AACxD,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;IACzB;;IAGU,eAAe,GAAA;AACvB,QAAA,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IAC3C;+GAlMW,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAApB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,oBAAoB,i+ECzDjC,67TAoMA,EAAA,MAAA,EAAA,CAAA,kjCAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,ED/IY,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,iBAAiB,oFAAE,gBAAgB,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,EAAA,CAAA,aAAA,EAAA,IAAA,EAAA,WAAA,EAAA,CAAA,EAAA,CAAA,CAAA;;4FAIhD,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAPhC,SAAS;+BACE,kBAAkB,EAAA,UAAA,EAChB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,CAAC,EAAA,QAAA,EAAA,67TAAA,EAAA,MAAA,EAAA,CAAA,kjCAAA,CAAA,EAAA;;;AErD9D;;AAEG;;;;"}