tailjng 0.1.6 → 0.1.8
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 +27 -5
- package/cli/execute/init-app.js +5 -2
- package/cli/execute/sync-app.js +14 -2
- package/cli/settings/colors-config-utils.js +69 -11
- package/cli/settings/icons-config-utils.js +62 -0
- package/cli/settings/path-utils.js +32 -2
- package/cli/settings/project-utils.js +7 -1
- package/cli/templates/app.generator.js +8 -5
- package/fesm2022/tailjng.mjs +247 -80
- package/fesm2022/tailjng.mjs.map +1 -1
- package/lib/services/static/theme.service.d.ts +39 -1
- package/lib/utils/theme/theme-variables.util.d.ts +31 -0
- package/package.json +1 -1
- package/public-api.d.ts +2 -1
- package/registry/components.json +41 -18
- package/src/colors.safelist.css +2 -2
- package/src/lib/components/.config/README.md +11 -0
- package/src/lib/components/.config/colors/README.md +40 -0
- package/src/lib/components/{colors-config → .config/colors}/colors.config.ts +5 -5
- package/src/lib/components/{colors-config → .config/colors}/colors.safelist.css +2 -2
- package/src/lib/components/.config/icons/README.md +26 -0
- package/src/lib/components/.config/icons/icons.lucide.ts +134 -0
- package/src/lib/components/.config/input/README.md +24 -0
- package/src/lib/components/.config/input/input.classes.ts +119 -0
- package/src/lib/components/alert/alert-dialog/dialog-alert.component.css +177 -6
- package/src/lib/components/alert/alert-dialog/dialog-alert.component.html +24 -37
- package/src/lib/components/alert/alert-dialog/dialog-alert.component.ts +66 -56
- package/src/lib/components/alert/alert-dialog/dialog-alert.types.ts +19 -0
- package/src/lib/components/alert/alert-toast/toast-alert.component.css +494 -14
- package/src/lib/components/alert/alert-toast/toast-alert.component.html +106 -102
- package/src/lib/components/alert/alert-toast/toast-alert.component.ts +485 -128
- package/src/lib/components/alert/alert-toast/toast-alert.types.ts +25 -0
- package/src/lib/components/badge/badge.component.html +34 -21
- package/src/lib/components/badge/badge.component.ts +140 -31
- package/src/lib/components/button/button.component.html +16 -10
- package/src/lib/components/button/button.component.ts +162 -22
- package/src/lib/components/card/card-complete/complete-card.component.html +2 -2
- package/src/lib/components/card/card-complete/complete-card.component.ts +26 -16
- package/src/lib/components/card/card-crud-complete/complete-crud-card.component.html +2 -2
- package/src/lib/components/card/card-crud-complete/complete-crud-card.component.ts +26 -16
- package/src/lib/components/checkbox/checkbox-input/input-checkbox.component.css +30 -0
- package/src/lib/components/checkbox/checkbox-input/input-checkbox.component.html +58 -46
- package/src/lib/components/checkbox/checkbox-input/input-checkbox.component.ts +135 -64
- package/src/lib/components/checkbox/checkbox-input/input-checkbox.types.ts +3 -0
- package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.css +62 -0
- package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.html +39 -25
- package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.ts +74 -15
- package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.types.ts +1 -0
- package/src/lib/components/coach-mark/coach-mark.component.html +6 -24
- package/src/lib/components/coach-mark/coach-mark.component.scss +1 -7
- package/src/lib/components/coach-mark/coach-mark.component.ts +51 -18
- package/src/lib/components/coach-mark/coach-mark.directive.ts +133 -78
- package/src/lib/components/coach-mark/coach-mark.types.ts +12 -0
- package/src/lib/components/dialog/dialog.component.css +1 -1
- package/src/lib/components/dialog/dialog.component.html +56 -65
- package/src/lib/components/dialog/dialog.component.ts +136 -110
- package/src/lib/components/dialog/dialog.types.ts +19 -0
- package/src/lib/components/filter/filter-complete/complete-filter.component.html +17 -20
- package/src/lib/components/filter/filter-complete/complete-filter.component.scss +25 -0
- package/src/lib/components/filter/filter-complete/complete-filter.component.ts +58 -34
- package/src/lib/components/filter/filter-complete/complete-filter.types.ts +7 -0
- package/src/lib/components/filter/filter-complete/complete-filter.util.ts +16 -0
- package/src/lib/components/form/form-container/container-form.component.css +4 -0
- package/src/lib/components/form/form-container/container-form.component.html +2 -2
- package/src/lib/components/form/form-container/container-form.component.ts +72 -16
- package/src/lib/components/form/form-container/container-form.types.ts +42 -0
- package/src/lib/components/form/form-container/form-col-span.directive.ts +25 -0
- package/src/lib/components/form/form-sidebar/sidebar-form.component.css +45 -0
- package/src/lib/components/form/form-sidebar/sidebar-form.component.html +128 -124
- package/src/lib/components/form/form-sidebar/sidebar-form.component.ts +114 -34
- package/src/lib/components/form/form-sidebar/sidebar-form.types.ts +3 -0
- package/src/lib/components/{toggle-radio/toggle-radio.component.css → form/form-validation/validation-form.component.css} +0 -1
- package/src/lib/components/form/form-validation/validation-form.component.html +10 -6
- package/src/lib/components/form/form-validation/validation-form.component.ts +99 -12
- package/src/lib/components/form/form-validation/validation-form.types.ts +33 -0
- package/src/lib/components/icon/icon.component.html +8 -5
- package/src/lib/components/icon/icon.component.ts +111 -9
- package/src/lib/components/input/input/input.component.css +0 -14
- package/src/lib/components/input/input/input.component.html +19 -16
- package/src/lib/components/input/input/input.component.ts +130 -53
- package/src/lib/components/input/input/input.types.ts +8 -0
- package/src/lib/components/input/input-file/file-input.component.html +65 -56
- package/src/lib/components/input/input-file/file-input.component.ts +276 -173
- package/src/lib/components/input/input-file/file-input.types.ts +2 -0
- package/src/lib/components/input/input-range/range-input.component.css +67 -0
- package/src/lib/components/input/input-range/range-input.component.html +50 -58
- package/src/lib/components/input/input-range/range-input.component.ts +148 -60
- package/src/lib/components/input/input-range/range-input.types.ts +7 -0
- package/src/lib/components/input/input-textarea/textarea-input.component.html +16 -7
- package/src/lib/components/input/input-textarea/textarea-input.component.ts +140 -50
- package/src/lib/components/input/input-textarea/textarea-input.types.ts +2 -0
- package/src/lib/components/label/label.component.html +17 -16
- package/src/lib/components/label/label.component.ts +94 -16
- package/src/lib/components/label/label.types.ts +2 -0
- package/src/lib/components/menu/menu-options-table/menu-options-defaults.ts +34 -0
- package/src/lib/components/menu/menu-options-table/options-table-menu.component.html +34 -20
- package/src/lib/components/menu/menu-options-table/options-table-menu.component.ts +211 -58
- package/src/lib/components/menu/menu-options-table/options-table-menu.types.ts +38 -0
- package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.html +49 -52
- package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.ts +112 -24
- package/src/lib/components/menu/options-coach-menu/options-coach-menu.types.ts +9 -0
- package/src/lib/components/mode-toggle/mode-toggle.component.html +11 -16
- package/src/lib/components/mode-toggle/mode-toggle.component.ts +69 -33
- package/src/lib/components/paginator/paginator-complete/complete-paginator.component.html +4 -4
- package/src/lib/components/paginator/paginator-complete/complete-paginator.component.ts +31 -7
- package/src/lib/components/paginator/paginator-complete/complete-paginator.types.ts +12 -0
- package/src/lib/components/paginator/paginator-complete/complete-paginator.util.ts +36 -0
- package/src/lib/components/progress-bar/progress-bar.component.html +41 -40
- package/src/lib/components/progress-bar/progress-bar.component.ts +95 -11
- package/src/lib/components/progress-bar/progress-bar.types.ts +2 -0
- package/src/lib/components/select/select-dropdown/dropdown-select.component.html +56 -46
- package/src/lib/components/select/select-dropdown/dropdown-select.component.ts +450 -509
- package/src/lib/components/select/select-dropdown/dropdown-select.types.ts +43 -0
- package/src/lib/components/select/select-dropdown/dropdown-select.util.ts +179 -0
- package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.html +131 -42
- package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.ts +491 -475
- package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.types.ts +22 -0
- package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.util.ts +20 -0
- package/src/lib/components/select/select-multi-table/multi-table-select.component.css +4 -0
- package/src/lib/components/select/select-multi-table/multi-table-select.component.html +76 -60
- package/src/lib/components/select/select-multi-table/multi-table-select.component.ts +250 -313
- package/src/lib/components/select/select-multi-table/multi-table-select.types.ts +10 -0
- package/src/lib/components/select/select-multi-table/multi-table-select.util.ts +5 -0
- package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.css +155 -0
- package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.html +72 -53
- package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.ts +84 -27
- package/src/lib/components/sidebar/sidebar-static/static-sidebar.types.ts +2 -0
- package/src/lib/components/table/table-complete/complete-table.component.html +21 -23
- package/src/lib/components/table/table-complete/complete-table.component.ts +190 -338
- package/src/lib/components/table/table-complete/complete-table.types.ts +28 -0
- package/src/lib/components/table/table-complete/complete-table.util.ts +236 -0
- package/src/lib/components/table/table-complete/index.ts +2 -0
- package/src/lib/components/table/table-crud-complete/complete-crud-table.animations.ts +34 -0
- package/src/lib/components/table/table-crud-complete/complete-crud-table.component.html +87 -142
- package/src/lib/components/table/table-crud-complete/complete-crud-table.component.scss +0 -63
- package/src/lib/components/table/table-crud-complete/complete-crud-table.component.ts +544 -831
- package/src/lib/components/table/table-crud-complete/complete-crud-table.types.ts +57 -0
- package/src/lib/components/table/table-crud-complete/complete-crud-table.util.ts +723 -0
- package/src/lib/components/table/table-crud-complete/index.ts +3 -0
- package/src/lib/components/theme-generator/theme-generator.component.css +21 -0
- package/src/lib/components/theme-generator/theme-generator.component.html +141 -116
- package/src/lib/components/theme-generator/theme-generator.component.ts +44 -24
- package/src/lib/components/toggle-radio/shared/toggle-options.types.ts +8 -0
- package/src/lib/components/toggle-radio/shared/toggle-options.util.ts +62 -0
- package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.css +22 -0
- package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.html +65 -0
- package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.ts +192 -0
- package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.types.ts +1 -0
- package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.css +34 -0
- package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.html +47 -0
- package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.ts +187 -0
- package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.types.ts +1 -0
- package/src/lib/components/tooltip/tooltip.directive.ts +12 -9
- package/src/lib/components/tooltip/tooltip.service.ts +331 -133
- package/src/lib/components/tooltip/tooltip.types.ts +9 -0
- package/src/lib/components/viewer/viewer-image/image-viewer.component.css +14 -4
- package/src/lib/components/viewer/viewer-image/image-viewer.component.html +61 -95
- package/src/lib/components/viewer/viewer-image/image-viewer.component.ts +182 -177
- package/src/lib/components/viewer/viewer-image/image-viewer.types.ts +3 -0
- package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.css +25 -0
- package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.html +95 -24
- package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.ts +168 -15
- package/src/lib/components/viewer/viewer-pdf/pdf-viewer.types.ts +1 -0
- package/src/styles.css +2 -2
- package/lib/services/static/icons.service.d.ts +0 -65
- package/src/lib/components/colors-config/README.md +0 -38
- package/src/lib/components/form/form-sidebar/sidebar-form.component.scss +0 -0
- package/src/lib/components/form/form-validation/validation-form.component.scss +0 -0
- package/src/lib/components/menu/menu-options-table/options-table-menu.component.scss +0 -0
- package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.scss +0 -12
- package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.scss +0 -0
- package/src/lib/components/toggle-radio/toggle-radio.component.html +0 -51
- package/src/lib/components/toggle-radio/toggle-radio.component.ts +0 -222
- package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.scss +0 -0
- package/tailjng-0.1.6.tgz +0 -0
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export * from './complete-crud-table.animations';
|
|
2
|
+
export * from './complete-crud-table.types';
|
|
3
|
+
export * from './complete-crud-table.util';
|
|
1
4
|
export * from './expand-grid/table-expand-grid.builder';
|
|
2
5
|
export * from './expand-grid/table-expand-grid.helper';
|
|
3
6
|
export * from './expand-grid/table-expand-grid.types';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
@keyframes theme-save-pop {
|
|
2
|
+
0% {
|
|
3
|
+
transform: scale(1);
|
|
4
|
+
box-shadow: none;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
35% {
|
|
8
|
+
transform: scale(1.35);
|
|
9
|
+
box-shadow: 0 0 0 4px color-mix(in srgb, var(--color-primary) 40%, transparent);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
100% {
|
|
13
|
+
transform: scale(1);
|
|
14
|
+
box-shadow: none;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
:host ::ng-deep button.theme-save-applied {
|
|
19
|
+
animation: theme-save-pop 0.65s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
20
|
+
color: var(--color-primary);
|
|
21
|
+
}
|
|
@@ -1,123 +1,148 @@
|
|
|
1
1
|
<main class="container mx-auto">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<div class="relative h-64 w-full overflow-hidden rounded-lg border border-border dark:border-dark-border">
|
|
13
|
-
<div class="absolute inset-0 bg-gradient-to-br from-white to-transparent" style="z-index: 1;"></div>
|
|
14
|
-
<div class="absolute inset-0 bg-gradient-to-b from-transparent to-black" style="z-index: 2;"></div>
|
|
15
|
-
<div class="absolute inset-0" [style.background]="'linear-gradient(to right, hsl(' + huePosition + ', 0%, 50%), hsl(' + huePosition + ', 100%, 50%))'" style="z-index: 0;"></div>
|
|
16
|
-
<div class="absolute w-6 h-6 rounded-full border-2 border-white transform -translate-x-1/2 -translate-y-1/2 cursor-pointer" [style.left.%]="colorPickerPosition.x" [style.top.%]="colorPickerPosition.y" style="z-index: 3;"></div>
|
|
17
|
-
<div class="absolute inset-0 cursor-pointer" (mousedown)="startColorPicking($event)" (mousemove)="updateColorPicking($event)" (mouseup)="stopColorPicking()" (mouseleave)="stopColorPicking()" style="z-index: 4;"></div>
|
|
18
|
-
</div>
|
|
19
|
-
|
|
20
|
-
<!-- Color Spectrum -->
|
|
21
|
-
<div class="space-y-4">
|
|
22
|
-
<div class="relative">
|
|
23
|
-
|
|
24
|
-
<!-- Picker bar -->
|
|
25
|
-
<div class="h-8 w-full rounded-lg overflow-hidden border border-border dark:border-dark-border relative">
|
|
26
|
-
<div class="absolute inset-0" [style.background]="hueGradient"></div>
|
|
27
|
-
|
|
28
|
-
<input
|
|
29
|
-
type="range"
|
|
30
|
-
min="0"
|
|
31
|
-
max="360"
|
|
32
|
-
[value]="huePosition"
|
|
33
|
-
(input)="updateHueFromInput($event)"
|
|
34
|
-
class="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
|
|
35
|
-
/>
|
|
36
|
-
</div>
|
|
37
|
-
|
|
38
|
-
<!-- Ball outside the flow to stand out -->
|
|
39
|
-
<div class="absolute top-1/2 transform -translate-y-1/2 -translate-x-1/2 w-9 h-9 rounded-full border-2 border-white z-10 pointer-events-none"
|
|
40
|
-
[style.left.%]="(huePosition / 360) * 100"
|
|
41
|
-
[style.backgroundColor]="hslToHex(huePosition, 100, 50)">
|
|
42
|
-
</div>
|
|
43
|
-
|
|
44
|
-
</div>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
<!-- Hex Input -->
|
|
48
|
-
<JFormContainer>
|
|
49
|
-
<JFormContainer>
|
|
50
|
-
<JLabel for="baseColor" classes="opacity-60">Ingresa un valor Hex</JLabel>
|
|
51
|
-
|
|
52
|
-
<JFormContainer [rows]="true">
|
|
53
|
-
|
|
54
|
-
<JFormContainer class="flex-1">
|
|
55
|
-
<JInput
|
|
56
|
-
id="baseColor"
|
|
57
|
-
type="text"
|
|
58
|
-
[(ngModel)]="baseColor"
|
|
59
|
-
(input)="updateFromHexInput()"
|
|
60
|
-
placeholder="#000000"
|
|
61
|
-
/>
|
|
62
|
-
</JFormContainer>
|
|
63
|
-
|
|
64
|
-
<!-- Color Preview -->
|
|
65
|
-
<div class="h-[35px] w-[60px] rounded shadow-md" [style.background-color]="baseColor"></div>
|
|
66
|
-
|
|
67
|
-
</JFormContainer>
|
|
68
|
-
</JFormContainer>
|
|
69
|
-
|
|
70
|
-
<!-- Saturation Slider -->
|
|
71
|
-
<JRangeInput
|
|
72
|
-
[min]="0"
|
|
73
|
-
[max]="100"
|
|
74
|
-
[(ngModel)]="saturation"
|
|
75
|
-
(input)="generateTheme()"
|
|
76
|
-
placeholder="Saturación"
|
|
77
|
-
[isLabel]="true"
|
|
78
|
-
simbol="%"
|
|
79
|
-
/>
|
|
80
|
-
|
|
81
|
-
<!-- Lightness Slider -->
|
|
82
|
-
<JRangeInput
|
|
83
|
-
[min]="0"
|
|
84
|
-
[max]="100"
|
|
85
|
-
[(ngModel)]="lightness"
|
|
86
|
-
(input)="generateTheme()"
|
|
87
|
-
placeholder="Luminosidad"
|
|
88
|
-
[isLabel]="true"
|
|
89
|
-
simbol="%"
|
|
90
|
-
/>
|
|
91
|
-
|
|
92
|
-
</JFormContainer>
|
|
93
|
-
|
|
94
|
-
</div>
|
|
95
|
-
</div>
|
|
96
|
-
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
99
|
-
|
|
100
|
-
<!-- Code Preview -->
|
|
101
|
-
<div class="relative">
|
|
2
|
+
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
3
|
+
<!-- Controls Panel -->
|
|
4
|
+
<div class="space-y-8 select-none">
|
|
5
|
+
<div>
|
|
6
|
+
<h2 class="text-sm font-bold mb-1 opacity-60">Selector de color</h2>
|
|
7
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
8
|
+
<!-- Color Picker -->
|
|
9
|
+
<div
|
|
10
|
+
class="relative h-64 w-full overflow-hidden rounded-lg border border-border dark:border-dark-border"
|
|
11
|
+
>
|
|
102
12
|
<div
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
13
|
+
class="absolute inset-0 z-[1] bg-gradient-to-br from-white to-transparent"
|
|
14
|
+
></div>
|
|
15
|
+
<div
|
|
16
|
+
class="absolute inset-0 z-[2] bg-gradient-to-b from-transparent to-black"
|
|
17
|
+
></div>
|
|
18
|
+
<div
|
|
19
|
+
class="absolute inset-0 z-0"
|
|
20
|
+
[style.background]="
|
|
21
|
+
'linear-gradient(to right, hsl(' +
|
|
22
|
+
huePosition +
|
|
23
|
+
', 0%, 50%), hsl(' +
|
|
24
|
+
huePosition +
|
|
25
|
+
', 100%, 50%))'
|
|
26
|
+
"
|
|
27
|
+
></div>
|
|
28
|
+
<div
|
|
29
|
+
class="absolute z-[3] w-6 h-6 rounded-full border-2 border-white transform -translate-x-1/2 -translate-y-1/2 cursor-pointer"
|
|
30
|
+
[style.left.%]="colorPickerPosition.x"
|
|
31
|
+
[style.top.%]="colorPickerPosition.y"
|
|
32
|
+
></div>
|
|
33
|
+
<div
|
|
34
|
+
class="absolute inset-0 z-[4] cursor-pointer"
|
|
35
|
+
(mousedown)="startColorPicking($event)"
|
|
36
|
+
(mousemove)="updateColorPicking($event)"
|
|
37
|
+
(mouseup)="stopColorPicking()"
|
|
38
|
+
(mouseleave)="stopColorPicking()"
|
|
39
|
+
></div>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<!-- Color Spectrum -->
|
|
43
|
+
<div class="space-y-4">
|
|
44
|
+
<div class="relative">
|
|
45
|
+
<!-- Picker bar -->
|
|
46
|
+
<div
|
|
47
|
+
class="h-8 w-full rounded-lg overflow-hidden border border-border dark:border-dark-border relative"
|
|
48
|
+
>
|
|
49
|
+
<div
|
|
50
|
+
class="absolute inset-0"
|
|
51
|
+
[style.background]="hueGradient"
|
|
52
|
+
></div>
|
|
53
|
+
|
|
54
|
+
<input
|
|
55
|
+
type="range"
|
|
56
|
+
min="0"
|
|
57
|
+
max="360"
|
|
58
|
+
[value]="huePosition"
|
|
59
|
+
(input)="updateHueFromInput($event)"
|
|
60
|
+
class="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
|
|
118
61
|
/>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<!-- Ball outside the flow to stand out -->
|
|
65
|
+
<div
|
|
66
|
+
class="absolute top-1/2 transform -translate-y-1/2 -translate-x-1/2 w-9 h-9 rounded-full border-2 border-white z-10 pointer-events-none"
|
|
67
|
+
[style.left.%]="(huePosition / 360) * 100"
|
|
68
|
+
[style.backgroundColor]="hslToHex(huePosition, 100, 50)"
|
|
69
|
+
></div>
|
|
119
70
|
</div>
|
|
71
|
+
|
|
72
|
+
<!-- Hex Input -->
|
|
73
|
+
<JFormContainer>
|
|
74
|
+
<JFormContainer>
|
|
75
|
+
<JLabel for="baseColor" classes="opacity-60"
|
|
76
|
+
>Ingresa un valor Hex</JLabel
|
|
77
|
+
>
|
|
78
|
+
|
|
79
|
+
<JFormContainer [rows]="true" [gap]="3">
|
|
80
|
+
<JFormContainer class="flex-1">
|
|
81
|
+
<JInput
|
|
82
|
+
id="baseColor"
|
|
83
|
+
type="text"
|
|
84
|
+
[(ngModel)]="baseColor"
|
|
85
|
+
(input)="updateFromHexInput()"
|
|
86
|
+
placeholder="#000000"
|
|
87
|
+
/>
|
|
88
|
+
</JFormContainer>
|
|
89
|
+
|
|
90
|
+
<!-- Color Preview -->
|
|
91
|
+
<div
|
|
92
|
+
class="h-[35px] w-[60px] rounded shadow-md"
|
|
93
|
+
[style.background-color]="baseColor"
|
|
94
|
+
></div>
|
|
95
|
+
</JFormContainer>
|
|
96
|
+
</JFormContainer>
|
|
97
|
+
|
|
98
|
+
<!-- Saturation Slider -->
|
|
99
|
+
<JRangeInput
|
|
100
|
+
[min]="0"
|
|
101
|
+
[max]="100"
|
|
102
|
+
[(ngModel)]="saturation"
|
|
103
|
+
(input)="generateTheme()"
|
|
104
|
+
placeholder="Saturación"
|
|
105
|
+
[isLabel]="true"
|
|
106
|
+
simbol="%"
|
|
107
|
+
/>
|
|
108
|
+
|
|
109
|
+
<!-- Lightness Slider -->
|
|
110
|
+
<JRangeInput
|
|
111
|
+
[min]="0"
|
|
112
|
+
[max]="100"
|
|
113
|
+
[(ngModel)]="lightness"
|
|
114
|
+
(input)="generateTheme()"
|
|
115
|
+
placeholder="Luminosidad"
|
|
116
|
+
[isLabel]="true"
|
|
117
|
+
simbol="%"
|
|
118
|
+
/>
|
|
119
|
+
</JFormContainer>
|
|
120
|
+
</div>
|
|
120
121
|
</div>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
121
124
|
|
|
125
|
+
<!-- Code Preview -->
|
|
126
|
+
<div class="relative">
|
|
127
|
+
<div
|
|
128
|
+
class="h-70 bg-background dark:bg-dark-background text-black dark:text-white overflow-auto rounded-lg font-mono text-sm whitespace-pre-wrap border border-border dark:border-dark-border scroll-element"
|
|
129
|
+
>
|
|
130
|
+
<div class="p-4">
|
|
131
|
+
<span>{{ themeCode }}</span>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
<div class="absolute top-4 right-4 flex gap-1">
|
|
136
|
+
<JButton
|
|
137
|
+
(clicked)="copyThemeToClipboard()"
|
|
138
|
+
[icon]="Icons.Copy"
|
|
139
|
+
[iconChange]="Icons.Check"
|
|
140
|
+
[isChangeIcon]="copied"
|
|
141
|
+
[iconSize]="15"
|
|
142
|
+
tooltip="Copiar"
|
|
143
|
+
classes="w-[25px] h-[25px]"
|
|
144
|
+
/>
|
|
145
|
+
</div>
|
|
122
146
|
</div>
|
|
123
|
-
</
|
|
147
|
+
</div>
|
|
148
|
+
</main>
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { Component } from '@angular/core';
|
|
1
|
+
import { Component, OnDestroy, OnInit, effect } from '@angular/core';
|
|
2
2
|
import { FormsModule } from '@angular/forms';
|
|
3
|
-
import { LucideAngularModule } from 'lucide-angular';
|
|
4
3
|
import { JInputComponent } from '../input/input/input.component';
|
|
5
4
|
import { JRangeInputComponent } from '../input/input-range/range-input.component';
|
|
6
5
|
import { JButtonComponent } from '../button/button.component';
|
|
7
6
|
import { JLabelComponent } from '../label/label.component';
|
|
8
|
-
import { ColorPosition, GeneratedColors,
|
|
7
|
+
import { ColorPosition, GeneratedColors, JThemeService, ThemeMode, applyGeneratedColorsToDocument, clearGeneratedColorsFromDocument } from 'tailjng';
|
|
9
8
|
import { JFormContainerComponent } from '../form/form-container/container-form.component';
|
|
9
|
+
import { Icons } from '../.config/icons/icons.lucide';
|
|
10
10
|
|
|
11
11
|
@Component({
|
|
12
12
|
selector: 'JThemeGenerator',
|
|
13
|
-
imports: [
|
|
13
|
+
imports: [JInputComponent, JRangeInputComponent, JButtonComponent, FormsModule, JLabelComponent, JFormContainerComponent],
|
|
14
14
|
templateUrl: './theme-generator.component.html',
|
|
15
|
-
styleUrl: './theme-generator.component.css'
|
|
16
15
|
})
|
|
17
|
-
export class JThemeGeneratorComponent {
|
|
16
|
+
export class JThemeGeneratorComponent implements OnInit, OnDestroy {
|
|
17
|
+
readonly Icons = Icons;
|
|
18
18
|
|
|
19
19
|
// Color picker state
|
|
20
20
|
baseColor: string = '#415884';
|
|
@@ -48,22 +48,27 @@ export class JThemeGeneratorComponent {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
constructor(
|
|
51
|
-
public readonly iconsService: JIconsService,
|
|
52
51
|
public readonly themeService: JThemeService
|
|
53
|
-
) {
|
|
52
|
+
) {
|
|
53
|
+
effect(() => {
|
|
54
|
+
this.themeService.themeSignal();
|
|
55
|
+
if (this.generatedColors) {
|
|
56
|
+
this.applyColorsToApp(this.generatedColors);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
this.
|
|
61
|
+
ngOnDestroy(): void {
|
|
62
|
+
if (typeof this.themeService.clearPreviewColors === 'function') {
|
|
63
|
+
this.themeService.clearPreviewColors();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
57
66
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.lastTheme = current;
|
|
64
|
-
this.generateTheme();
|
|
65
|
-
}
|
|
66
|
-
}, 300);
|
|
67
|
+
clearGeneratedColorsFromDocument();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
ngOnInit() {
|
|
71
|
+
this.syncFromHSL(false);
|
|
67
72
|
}
|
|
68
73
|
|
|
69
74
|
|
|
@@ -179,9 +184,9 @@ export class JThemeGeneratorComponent {
|
|
|
179
184
|
/**
|
|
180
185
|
* Sync the internal state from HSL values.
|
|
181
186
|
*/
|
|
182
|
-
syncFromHSL(): void {
|
|
187
|
+
syncFromHSL(applyToApp = true): void {
|
|
183
188
|
this.baseColor = this.hslToHex(this.huePosition, this.saturation, this.lightness);
|
|
184
|
-
this.generateTheme();
|
|
189
|
+
this.generateTheme(applyToApp);
|
|
185
190
|
}
|
|
186
191
|
|
|
187
192
|
|
|
@@ -251,7 +256,7 @@ export class JThemeGeneratorComponent {
|
|
|
251
256
|
/**
|
|
252
257
|
* Generate the theme colors.
|
|
253
258
|
*/
|
|
254
|
-
generateTheme(): void {
|
|
259
|
+
generateTheme(applyToApp = true): void {
|
|
255
260
|
this.baseColor = this.hslToHex(this.huePosition, this.saturation * 0.9, this.lightness);
|
|
256
261
|
|
|
257
262
|
const vars = this.generatedColors = {
|
|
@@ -298,8 +303,7 @@ export class JThemeGeneratorComponent {
|
|
|
298
303
|
darkDestructiveForeground: this.hslToHex(this.huePosition, this.saturation * 0.2, 90),
|
|
299
304
|
darkBorder: this.hslToHex(this.huePosition, this.saturation * 0.5, 45),
|
|
300
305
|
darkInput: this.hslToHex(this.huePosition, this.saturation * 0.5, 45),
|
|
301
|
-
darkRing: this.hslToHex(this.huePosition, this.saturation * 0.7, 28)
|
|
302
|
-
};
|
|
306
|
+
darkRing: this.hslToHex(this.huePosition, this.saturation * 0.7, 28)};
|
|
303
307
|
|
|
304
308
|
const toCssVar = (key: string, value: string) =>
|
|
305
309
|
` --color-${key.replace(/[A-Z]/g, m => '-' + m.toLowerCase())}: ${value};`;
|
|
@@ -320,8 +324,24 @@ export class JThemeGeneratorComponent {
|
|
|
320
324
|
lines.push(` --color-dark-radius: 0.5rem;`);
|
|
321
325
|
|
|
322
326
|
this.themeCode = `@theme {\n${lines.join('\n')}\n}`;
|
|
327
|
+
|
|
328
|
+
if (applyToApp) {
|
|
329
|
+
this.applyColorsToApp(vars);
|
|
330
|
+
}
|
|
323
331
|
}
|
|
324
332
|
|
|
333
|
+
/**
|
|
334
|
+
* Applies palette CSS variables to the whole app.
|
|
335
|
+
* @param colors Generated palette.
|
|
336
|
+
*/
|
|
337
|
+
private applyColorsToApp(colors: GeneratedColors): void {
|
|
338
|
+
if (typeof this.themeService.applyPreviewColors === 'function') {
|
|
339
|
+
this.themeService.applyPreviewColors(colors);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
applyGeneratedColorsToDocument(colors);
|
|
344
|
+
}
|
|
325
345
|
|
|
326
346
|
copyThemeToClipboard(): void {
|
|
327
347
|
navigator.clipboard.writeText(this.themeCode);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ToggleOption, ToggleSortOrder } from './toggle-options.types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Query params for toggle API loads (`findAll`).
|
|
5
|
+
* Arrays are kept as arrays so `JParamsHttpService` serializes them as
|
|
6
|
+
* `filter[key][0]`, `filter[key][1]`, …
|
|
7
|
+
*/
|
|
8
|
+
export function buildToggleLoadParams(
|
|
9
|
+
sort: ToggleSortOrder,
|
|
10
|
+
defaultFilters: Record<string, unknown>,
|
|
11
|
+
): Record<string, unknown> {
|
|
12
|
+
const params: Record<string, unknown> = { sortOrder: sort };
|
|
13
|
+
|
|
14
|
+
Object.keys(defaultFilters).forEach((key) => {
|
|
15
|
+
params[`filter[${key}]`] = defaultFilters[key];
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
return params;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Reads a nested property using dot notation.
|
|
23
|
+
*/
|
|
24
|
+
export function getNestedToggleValue(obj: unknown, path: string): string {
|
|
25
|
+
if (!obj || typeof obj !== 'object') {
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const value = path.split('.').reduce<unknown>((acc, part) => {
|
|
30
|
+
if (acc && typeof acc === 'object' && part in (acc as Record<string, unknown>)) {
|
|
31
|
+
return (acc as Record<string, unknown>)[part];
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}, obj);
|
|
35
|
+
|
|
36
|
+
return value == null ? '' : String(value);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Normalizes static options into `{ value, label }` pairs.
|
|
41
|
+
*/
|
|
42
|
+
export function normalizeToggleOptions(
|
|
43
|
+
options: unknown[],
|
|
44
|
+
optionLabel: string,
|
|
45
|
+
optionValue: string,
|
|
46
|
+
): ToggleOption[] {
|
|
47
|
+
if (!options.length) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (typeof options[0] === 'object' && options[0] !== null) {
|
|
52
|
+
return options.map((opt) => ({
|
|
53
|
+
value: (opt as Record<string, unknown>)[optionValue],
|
|
54
|
+
label: getNestedToggleValue(opt, optionLabel),
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return options.map((opt) => ({
|
|
59
|
+
value: opt,
|
|
60
|
+
label: String(opt),
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: block;
|
|
3
|
+
width: 100%;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.j-radio-group--horizontal {
|
|
7
|
+
flex-flow: row wrap;
|
|
8
|
+
gap: 1rem 1.25rem;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.j-radio-group--disabled {
|
|
12
|
+
opacity: 0.55;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.j-radio-option--disabled {
|
|
16
|
+
cursor: not-allowed;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.j-radio-input:focus-visible + .j-radio-indicator {
|
|
20
|
+
outline: 2px solid var(--color-ring);
|
|
21
|
+
outline-offset: 2px;
|
|
22
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
@if (internalOptions.length > 0) {
|
|
2
|
+
<div [ngClass]="groupClasses" role="radiogroup" class="flex flex-col gap-2.5">
|
|
3
|
+
@for (opt of internalOptions; track $index) {
|
|
4
|
+
<label
|
|
5
|
+
class="j-radio-option inline-flex items-center gap-2.5 cursor-pointer select-none"
|
|
6
|
+
[class.j-radio-option--selected]="isSelected(opt.value)"
|
|
7
|
+
[class.j-radio-option--disabled]="isInteractionDisabled"
|
|
8
|
+
[for]="optionId(opt.value, $index)"
|
|
9
|
+
>
|
|
10
|
+
<input
|
|
11
|
+
class="j-radio-input absolute opacity-0 w-0 h-0 m-0 pointer-events-none"
|
|
12
|
+
type="radio"
|
|
13
|
+
[id]="optionId(opt.value, $index)"
|
|
14
|
+
[name]="name"
|
|
15
|
+
[value]="opt.value"
|
|
16
|
+
[checked]="isSelected(opt.value)"
|
|
17
|
+
[disabled]="isInteractionDisabled"
|
|
18
|
+
(change)="select(opt.value)"
|
|
19
|
+
/>
|
|
20
|
+
|
|
21
|
+
<span
|
|
22
|
+
class="j-radio-indicator inline-flex items-center justify-center w-[1.125rem] h-[1.125rem] shrink-0 border-[1.5px] rounded-full bg-background dark:bg-dark-background transition-[border-color,background-color] duration-150 ease-in-out"
|
|
23
|
+
[ngClass]="{
|
|
24
|
+
'border-primary dark:border-dark-primary': isSelected(opt.value),
|
|
25
|
+
'border-border dark:border-dark-border': !isSelected(opt.value),
|
|
26
|
+
}"
|
|
27
|
+
aria-hidden="true"
|
|
28
|
+
>
|
|
29
|
+
<span
|
|
30
|
+
class="j-radio-dot w-[0.4375rem] h-[0.4375rem] rounded-full bg-primary dark:bg-dark-primary transition-transform duration-150 ease-in-out"
|
|
31
|
+
[class.scale-0]="!isSelected(opt.value)"
|
|
32
|
+
[class.scale-100]="isSelected(opt.value)"
|
|
33
|
+
></span>
|
|
34
|
+
</span>
|
|
35
|
+
|
|
36
|
+
<span class="text-sm leading-[1.35] text-foreground dark:text-dark-foreground">{{ opt.label }}</span>
|
|
37
|
+
</label>
|
|
38
|
+
}
|
|
39
|
+
</div>
|
|
40
|
+
} @else if (isLoading) {
|
|
41
|
+
<div class="flex items-center justify-start gap-2 min-h-8 text-muted-foreground dark:text-dark-muted-foreground text-sm">
|
|
42
|
+
<JIcon
|
|
43
|
+
[icon]="Icons.Loader2"
|
|
44
|
+
[size]="16"
|
|
45
|
+
iconClass="animate-spin text-muted-foreground"
|
|
46
|
+
[ariaHidden]="true"
|
|
47
|
+
/>
|
|
48
|
+
<span>Cargando...</span>
|
|
49
|
+
</div>
|
|
50
|
+
} @else {
|
|
51
|
+
<div class="flex items-center justify-start gap-2 min-h-8 text-muted-foreground dark:text-dark-muted-foreground text-sm">
|
|
52
|
+
No hay opciones
|
|
53
|
+
</div>
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@if (showClear && selectedValue !== null) {
|
|
57
|
+
<button
|
|
58
|
+
type="button"
|
|
59
|
+
class="mt-2.5 p-0 border-0 bg-transparent text-destructive text-xs underline cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
|
|
60
|
+
(click)="clear()"
|
|
61
|
+
[disabled]="isInteractionDisabled"
|
|
62
|
+
>
|
|
63
|
+
Limpiar selección
|
|
64
|
+
</button>
|
|
65
|
+
}
|