tailjng 0.1.7 → 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.
Files changed (59) hide show
  1. package/README.md +15 -1
  2. package/cli/settings/colors-config-utils.js +26 -3
  3. package/cli/templates/app.generator.js +6 -3
  4. package/package.json +1 -1
  5. package/src/colors.safelist.css +1 -1
  6. package/src/lib/components/.config/colors/README.md +2 -0
  7. package/src/lib/components/.config/colors/colors.safelist.css +1 -1
  8. package/src/lib/components/alert/alert-dialog/dialog-alert.component.css +0 -71
  9. package/src/lib/components/alert/alert-dialog/dialog-alert.component.html +7 -7
  10. package/src/lib/components/alert/alert-toast/toast-alert.component.css +0 -138
  11. package/src/lib/components/alert/alert-toast/toast-alert.component.html +12 -9
  12. package/src/lib/components/checkbox/checkbox-input/input-checkbox.component.css +0 -67
  13. package/src/lib/components/checkbox/checkbox-input/input-checkbox.component.html +11 -7
  14. package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.css +3 -53
  15. package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.html +17 -6
  16. package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.ts +7 -0
  17. package/src/lib/components/coach-mark/coach-mark.component.html +2 -2
  18. package/src/lib/components/coach-mark/coach-mark.component.scss +1 -7
  19. package/src/lib/components/dialog/dialog.component.css +0 -102
  20. package/src/lib/components/dialog/dialog.component.html +17 -6
  21. package/src/lib/components/filter/filter-complete/complete-filter.component.html +5 -5
  22. package/src/lib/components/filter/filter-complete/complete-filter.component.scss +0 -10
  23. package/src/lib/components/form/form-sidebar/sidebar-form.component.css +23 -254
  24. package/src/lib/components/form/form-sidebar/sidebar-form.component.html +22 -10
  25. package/src/lib/components/form/form-sidebar/sidebar-form.component.ts +13 -8
  26. package/src/lib/components/input/input/input.component.css +0 -14
  27. package/src/lib/components/input/input/input.component.html +1 -1
  28. package/src/lib/components/input/input-file/file-input.component.ts +1 -1
  29. package/src/lib/components/label/label.component.ts +24 -0
  30. package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.html +2 -2
  31. package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.ts +2 -2
  32. package/src/lib/components/progress-bar/progress-bar.component.css +0 -11
  33. package/src/lib/components/progress-bar/progress-bar.component.html +3 -3
  34. package/src/lib/components/select/select-dropdown/dropdown-select.component.css +0 -6
  35. package/src/lib/components/select/select-dropdown/dropdown-select.component.html +3 -3
  36. package/src/lib/components/select/select-dropdown/dropdown-select.component.ts +1 -1
  37. package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.css +0 -6
  38. package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.html +3 -3
  39. package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.ts +1 -1
  40. package/src/lib/components/select/select-multi-table/multi-table-select.component.css +0 -6
  41. package/src/lib/components/select/select-multi-table/multi-table-select.component.html +2 -2
  42. package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.css +5 -62
  43. package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.html +16 -6
  44. package/src/lib/components/table/table-complete/complete-table.component.html +6 -6
  45. package/src/lib/components/table/table-crud-complete/complete-crud-table.component.html +14 -14
  46. package/src/lib/components/table/table-crud-complete/complete-crud-table.component.scss +0 -63
  47. package/src/lib/components/table/table-crud-complete/complete-crud-table.component.ts +2 -2
  48. package/src/lib/components/theme-generator/theme-generator.component.html +5 -10
  49. package/src/lib/components/toggle-radio/shared/toggle-options.util.ts +19 -1
  50. package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.css +0 -113
  51. package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.html +22 -9
  52. package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.ts +3 -9
  53. package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.css +0 -74
  54. package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.html +14 -4
  55. package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.ts +3 -9
  56. package/src/lib/components/viewer/viewer-image/image-viewer.component.css +0 -76
  57. package/src/lib/components/viewer/viewer-image/image-viewer.component.html +27 -10
  58. package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.css +0 -152
  59. package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.html +33 -12
@@ -62,7 +62,7 @@
62
62
  @if (isGroupTable && expandedRows.size > 0) {
63
63
  <colgroup>
64
64
  @if (isNumbering) {
65
- <col class="j-group-number-col" />
65
+ <col class="j-group-number-col box-border w-11 min-w-11 max-w-11" />
66
66
  }
67
67
  @for (column of columns; track $index) {
68
68
  @if (column.visible) {
@@ -70,7 +70,7 @@
70
70
  }
71
71
  }
72
72
  @if (isOptions) {
73
- <col class="j-table-options-col" />
73
+ <col class="j-table-options-col box-border w-[var(--j-table-options-col-width)] min-w-[var(--j-table-options-col-width)] max-w-[var(--j-table-options-col-width)]" />
74
74
  }
75
75
  </colgroup>
76
76
  }
@@ -91,7 +91,7 @@
91
91
  <!-- Counter column -->
92
92
  @if (isNumbering) {
93
93
  <th
94
- class="j-group-number-col px-4 py-2 text-center text-xs font-medium uppercase tracking-wider border-b border-border dark:border-dark-border font-bold text-white"
94
+ class="j-group-number-col box-border w-11 min-w-11 max-w-11 !px-[0.35rem] px-4 py-2 text-center text-xs font-medium uppercase tracking-wider border-b border-border dark:border-dark-border font-bold text-white"
95
95
  >
96
96
 
97
97
  </th>
@@ -155,7 +155,7 @@
155
155
  <!-- Actions column - Sticky header -->
156
156
  @if (isOptions) {
157
157
  <th
158
- class="j-table-options-col !sticky !right-0 relative z-[2] bg-primary px-4 py-2 text-center text-xs font-medium font-bold uppercase tracking-wider text-white shadow-[-4px_0_5px_rgba(0,0,0,0.1)] border-b border-border dark:border-dark-border dark:bg-dark-primary"
158
+ class="j-table-options-col box-border w-[var(--j-table-options-col-width)] min-w-[var(--j-table-options-col-width)] max-w-[var(--j-table-options-col-width)] !sticky !right-0 relative z-[2] bg-primary px-4 py-2 text-center text-xs font-medium font-bold uppercase tracking-wider text-white shadow-[-4px_0_5px_rgba(0,0,0,0.1)] border-b border-border dark:border-dark-border dark:bg-dark-primary"
159
159
  >
160
160
  <span
161
161
  class="text-[10px] opacity-80 border border-border dark:border-dark-border p-2 pl-3 pr-3 rounded-full"
@@ -489,7 +489,7 @@
489
489
  <td
490
490
  onKeyPress
491
491
  (click)="$event.stopPropagation()"
492
- class="j-table-options-col !sticky !right-0 relative overflow-visible border-b border-border bg-white text-center text-sm whitespace-nowrap shadow-[-4px_0_5px_rgba(0,0,0,0.1)] dark:border-dark-border dark:bg-foreground"
492
+ class="j-table-options-col box-border w-[var(--j-table-options-col-width)] min-w-[var(--j-table-options-col-width)] max-w-[var(--j-table-options-col-width)] !sticky !right-0 relative overflow-visible border-b border-border bg-white text-center text-sm whitespace-nowrap shadow-[-4px_0_5px_rgba(0,0,0,0.1)] dark:border-dark-border dark:bg-foreground"
493
493
  [ngStyle]="{ 'z-index': 1 + 1 }"
494
494
  >
495
495
  <div class="flex justify-center items-center">
@@ -567,7 +567,7 @@
567
567
  [class.expanded]="expandedRows.has(item)"
568
568
  >
569
569
  <td
570
- class="j-group-number-col h-[50px] border-b border-border px-2 py-2 text-center text-xs text-black dark:border-dark-border dark:text-white bg-primary/10 dark:bg-primary/20"
570
+ class="j-group-number-col box-border w-11 min-w-11 max-w-11 !px-[0.35rem] h-[50px] border-b border-border px-2 py-2 text-center text-xs text-black dark:border-dark-border dark:text-white bg-primary/10 dark:bg-primary/20"
571
571
  >
572
572
  <JIcon [icon]="Icons.ChevronRight"
573
573
  size="22"
@@ -603,10 +603,10 @@
603
603
  <td
604
604
  onKeyPress
605
605
  (click)="$event.stopPropagation()"
606
- class="j-table-options-col j-group-pagination-cell !sticky !right-0 z-[2] border-b border-border bg-primary/10 dark:bg-primary/20 text-center text-sm whitespace-nowrap shadow-[-4px_0_5px_rgba(0,0,0,0.1)] dark:border-dark-border"
606
+ class="j-table-options-col j-group-pagination-cell box-border w-[var(--j-table-options-col-width)] min-w-[var(--j-table-options-col-width)] max-w-[var(--j-table-options-col-width)] align-middle !sticky !right-0 z-[2] border-b border-border bg-primary/10 dark:bg-primary/20 text-center text-sm whitespace-nowrap shadow-[-4px_0_5px_rgba(0,0,0,0.1)] dark:border-dark-border"
607
607
  >
608
608
  <div
609
- class="j-group-paginator"
609
+ class="j-group-paginator flex flex-col items-center justify-center gap-1 opacity-0 invisible pointer-events-none transition-[opacity,visibility] duration-[320ms] ease-out"
610
610
  [class.is-expanded]="expandedRows.has(item)"
611
611
  >
612
612
  <span
@@ -659,11 +659,11 @@
659
659
  class="j-group-expand-panel overflow-hidden"
660
660
  >
661
661
  <table
662
- class="j-group-inner-table w-full min-w-full border-collapse bg-white dark:bg-foreground"
662
+ class="j-group-inner-table table-fixed w-full min-w-full border-collapse bg-white dark:bg-foreground"
663
663
  >
664
664
  <colgroup>
665
665
  @if (isNumbering) {
666
- <col class="j-group-number-col" />
666
+ <col class="j-group-number-col box-border w-11 min-w-11 max-w-11" />
667
667
  }
668
668
  @for (column of columns; track $index) {
669
669
  @if (column.visible) {
@@ -671,7 +671,7 @@
671
671
  }
672
672
  }
673
673
  @if (isOptions) {
674
- <col class="j-table-options-col" />
674
+ <col class="j-table-options-col box-border w-[var(--j-table-options-col-width)] min-w-[var(--j-table-options-col-width)] max-w-[var(--j-table-options-col-width)]" />
675
675
  }
676
676
  </colgroup>
677
677
  <tbody>
@@ -684,7 +684,7 @@
684
684
  >
685
685
  @if (isNumbering) {
686
686
  <td
687
- class="j-group-number-col h-[50px] border-b border-border px-2 py-2 text-center text-xs text-black dark:border-dark-border dark:text-white"
687
+ class="j-group-number-col box-border w-11 min-w-11 max-w-11 !px-[0.35rem] h-[50px] border-b border-border px-2 py-2 text-center text-xs text-black dark:border-dark-border dark:text-white"
688
688
  >
689
689
  {{
690
690
  (item.meta?.page?.currentPage - 1) *
@@ -806,7 +806,7 @@
806
806
  <td
807
807
  onKeyPress
808
808
  (click)="$event.stopPropagation()"
809
- class="j-table-options-col !sticky !right-0 relative z-[2] overflow-visible border-b border-border bg-white text-center text-sm whitespace-nowrap shadow-[-4px_0_5px_rgba(0,0,0,0.1)] dark:border-dark-border dark:bg-foreground"
809
+ class="j-table-options-col box-border w-[var(--j-table-options-col-width)] min-w-[var(--j-table-options-col-width)] max-w-[var(--j-table-options-col-width)] !sticky !right-0 relative z-[2] overflow-visible border-b border-border bg-white text-center text-sm whitespace-nowrap shadow-[-4px_0_5px_rgba(0,0,0,0.1)] dark:border-dark-border dark:bg-foreground"
810
810
  >
811
811
  <div
812
812
  class="relative flex h-[50px] items-center justify-center overflow-visible px-2 py-2"
@@ -1632,7 +1632,7 @@
1632
1632
 
1633
1633
  <!-- Count register -->
1634
1634
  @if (isGroupTable) {
1635
- <div class="flex flex-wrap mt-3 gap-3 items-center">
1635
+ <div class="flex flex-wrap mt-3 gap-3 max-[768px]:gap-[8px] max-[400px]:gap-[6px] items-center">
1636
1636
  <ng-container [ngTemplateOutlet]="groupsTemplate"></ng-container>
1637
1637
  </div>
1638
1638
  }
@@ -2,79 +2,16 @@
2
2
  --j-table-options-col-width: 7.5rem;
3
3
  }
4
4
 
5
- .j-table-options-col,
6
- .j-group-pagination-cell,
7
- .j-group-expand-table-cell--options {
8
- box-sizing: border-box;
9
- min-width: var(--j-table-options-col-width);
10
- width: var(--j-table-options-col-width);
11
- max-width: var(--j-table-options-col-width);
12
- }
13
-
14
- .j-group-pagination-cell {
15
- vertical-align: middle;
16
- }
17
-
18
- .j-group-paginator {
19
- display: flex;
20
- flex-direction: column;
21
- align-items: center;
22
- justify-content: center;
23
- gap: 0.25rem;
24
- opacity: 0;
25
- visibility: hidden;
26
- pointer-events: none;
27
- transition:
28
- opacity 320ms ease-out,
29
- visibility 320ms;
30
- }
31
-
32
- .j-group-inner-table {
33
- table-layout: fixed;
34
- }
35
-
36
5
  .j-group-paginator.is-expanded {
37
6
  opacity: 1;
38
7
  visibility: visible;
39
8
  pointer-events: auto;
40
9
  }
41
10
 
42
- .j-group-number-col {
43
- box-sizing: border-box;
44
- width: 2.75rem;
45
- min-width: 2.75rem;
46
- max-width: 2.75rem;
47
- padding-left: 0.35rem !important;
48
- padding-right: 0.35rem !important;
49
- }
50
-
51
11
  .j-group-student-row td {
52
12
  vertical-align: middle;
53
13
  }
54
14
 
55
- .j-group-expand-table {
56
- display: table;
57
- width: 100%;
58
- min-width: 100%;
59
- border-collapse: collapse;
60
- table-layout: fixed;
61
- }
62
-
63
- .j-group-expand-table-row {
64
- display: table-row;
65
- }
66
-
67
- .j-group-expand-table-cell {
68
- display: table-cell;
69
- vertical-align: middle;
70
- }
71
-
72
- .j-group-expand-table-cell--options {
73
- position: sticky;
74
- right: 0;
75
- z-index: 2;
76
- }
77
-
78
15
  :host ::ng-deep thead.j-group-thead-expanded th {
79
16
  animation: group-thead-reveal 300ms ease-out both;
80
17
  }
@@ -834,10 +834,10 @@ export class JCompleteCrudTableComponent implements OnInit {
834
834
  this.loadingStates.aditionalButtons[key] = 'idle';
835
835
  }
836
836
 
837
- isAditionalButtonLoading(buttonType: string, id?: number | string): boolean {
837
+ isAditionalButtonLoading = (buttonType: string, id?: number | string): boolean => {
838
838
  const key = id !== undefined ? `${buttonType}_${id}` : buttonType;
839
839
  return this.loadingStates.aditionalButtons[key] === 'loading';
840
- }
840
+ };
841
841
 
842
842
  // =====================================================
843
843
  // Expand rows
@@ -10,15 +10,13 @@
10
10
  class="relative h-64 w-full overflow-hidden rounded-lg border border-border dark:border-dark-border"
11
11
  >
12
12
  <div
13
- class="absolute inset-0 bg-gradient-to-br from-white to-transparent"
14
- style="z-index: 1"
13
+ class="absolute inset-0 z-[1] bg-gradient-to-br from-white to-transparent"
15
14
  ></div>
16
15
  <div
17
- class="absolute inset-0 bg-gradient-to-b from-transparent to-black"
18
- style="z-index: 2"
16
+ class="absolute inset-0 z-[2] bg-gradient-to-b from-transparent to-black"
19
17
  ></div>
20
18
  <div
21
- class="absolute inset-0"
19
+ class="absolute inset-0 z-0"
22
20
  [style.background]="
23
21
  'linear-gradient(to right, hsl(' +
24
22
  huePosition +
@@ -26,21 +24,18 @@
26
24
  huePosition +
27
25
  ', 100%, 50%))'
28
26
  "
29
- style="z-index: 0"
30
27
  ></div>
31
28
  <div
32
- class="absolute w-6 h-6 rounded-full border-2 border-white transform -translate-x-1/2 -translate-y-1/2 cursor-pointer"
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"
33
30
  [style.left.%]="colorPickerPosition.x"
34
31
  [style.top.%]="colorPickerPosition.y"
35
- style="z-index: 3"
36
32
  ></div>
37
33
  <div
38
- class="absolute inset-0 cursor-pointer"
34
+ class="absolute inset-0 z-[4] cursor-pointer"
39
35
  (mousedown)="startColorPicking($event)"
40
36
  (mousemove)="updateColorPicking($event)"
41
37
  (mouseup)="stopColorPicking()"
42
38
  (mouseleave)="stopColorPicking()"
43
- style="z-index: 4"
44
39
  ></div>
45
40
  </div>
46
41
 
@@ -1,4 +1,22 @@
1
- import { ToggleOption } from './toggle-options.types';
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
+ }
2
20
 
3
21
  /**
4
22
  * Reads a nested property using dot notation.
@@ -3,12 +3,6 @@
3
3
  width: 100%;
4
4
  }
5
5
 
6
- .j-radio-group {
7
- display: flex;
8
- flex-direction: column;
9
- gap: 0.625rem;
10
- }
11
-
12
6
  .j-radio-group--horizontal {
13
7
  flex-flow: row wrap;
14
8
  gap: 1rem 1.25rem;
@@ -18,118 +12,11 @@
18
12
  opacity: 0.55;
19
13
  }
20
14
 
21
- .j-radio-option {
22
- display: inline-flex;
23
- align-items: center;
24
- gap: 0.625rem;
25
- cursor: pointer;
26
- user-select: none;
27
- }
28
-
29
15
  .j-radio-option--disabled {
30
16
  cursor: not-allowed;
31
17
  }
32
18
 
33
- .j-radio-input {
34
- position: absolute;
35
- opacity: 0;
36
- width: 0;
37
- height: 0;
38
- margin: 0;
39
- pointer-events: none;
40
- }
41
-
42
19
  .j-radio-input:focus-visible + .j-radio-indicator {
43
20
  outline: 2px solid var(--color-ring);
44
21
  outline-offset: 2px;
45
22
  }
46
-
47
- .j-radio-indicator {
48
- display: inline-flex;
49
- align-items: center;
50
- justify-content: center;
51
- width: 1.125rem;
52
- height: 1.125rem;
53
- flex-shrink: 0;
54
- border: 1.5px solid var(--color-border);
55
- border-radius: 9999px;
56
- background-color: var(--color-background);
57
- transition:
58
- border-color 0.15s ease,
59
- background-color 0.15s ease;
60
- }
61
-
62
- :host-context(.dark) .j-radio-indicator,
63
- :host-context(html.dark) .j-radio-indicator {
64
- border-color: var(--color-dark-border);
65
- background-color: var(--color-dark-background);
66
- }
67
-
68
- .j-radio-dot {
69
- width: 0.4375rem;
70
- height: 0.4375rem;
71
- border-radius: 9999px;
72
- background-color: var(--color-primary);
73
- transform: scale(0);
74
- transition: transform 0.15s ease;
75
- }
76
-
77
- :host-context(.dark) .j-radio-dot,
78
- :host-context(html.dark) .j-radio-dot {
79
- background-color: var(--color-dark-primary);
80
- }
81
-
82
- .j-radio-option--selected .j-radio-indicator {
83
- border-color: var(--color-primary);
84
- }
85
-
86
- :host-context(.dark) .j-radio-option--selected .j-radio-indicator,
87
- :host-context(html.dark) .j-radio-option--selected .j-radio-indicator {
88
- border-color: var(--color-dark-primary);
89
- }
90
-
91
- .j-radio-option--selected .j-radio-dot {
92
- transform: scale(1);
93
- }
94
-
95
- .j-radio-label {
96
- font-size: 0.875rem;
97
- line-height: 1.35;
98
- color: var(--color-foreground);
99
- }
100
-
101
- :host-context(.dark) .j-radio-label,
102
- :host-context(html.dark) .j-radio-label {
103
- color: var(--color-dark-foreground);
104
- }
105
-
106
- .j-radio-state {
107
- display: flex;
108
- align-items: center;
109
- justify-content: flex-start;
110
- gap: 0.5rem;
111
- min-height: 2rem;
112
- color: var(--color-muted-foreground);
113
- font-size: 0.875rem;
114
- }
115
-
116
- :host-context(.dark) .j-radio-state,
117
- :host-context(html.dark) .j-radio-state {
118
- color: var(--color-dark-muted-foreground);
119
- }
120
-
121
- .j-radio-clear {
122
- margin-top: 0.625rem;
123
- padding: 0;
124
- border: 0;
125
- background: transparent;
126
- color: var(--color-destructive);
127
- font-size: 0.75rem;
128
- text-decoration: underline;
129
- cursor: pointer;
130
- }
131
-
132
- .j-radio-clear:disabled {
133
- opacity: 0.5;
134
- cursor: not-allowed;
135
- }
@@ -1,14 +1,14 @@
1
1
  @if (internalOptions.length > 0) {
2
- <div [ngClass]="groupClasses" role="radiogroup">
2
+ <div [ngClass]="groupClasses" role="radiogroup" class="flex flex-col gap-2.5">
3
3
  @for (opt of internalOptions; track $index) {
4
4
  <label
5
- class="j-radio-option"
5
+ class="j-radio-option inline-flex items-center gap-2.5 cursor-pointer select-none"
6
6
  [class.j-radio-option--selected]="isSelected(opt.value)"
7
7
  [class.j-radio-option--disabled]="isInteractionDisabled"
8
8
  [for]="optionId(opt.value, $index)"
9
9
  >
10
10
  <input
11
- class="j-radio-input"
11
+ class="j-radio-input absolute opacity-0 w-0 h-0 m-0 pointer-events-none"
12
12
  type="radio"
13
13
  [id]="optionId(opt.value, $index)"
14
14
  [name]="name"
@@ -18,16 +18,27 @@
18
18
  (change)="select(opt.value)"
19
19
  />
20
20
 
21
- <span class="j-radio-indicator" aria-hidden="true">
22
- <span class="j-radio-dot"></span>
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>
23
34
  </span>
24
35
 
25
- <span class="j-radio-label">{{ opt.label }}</span>
36
+ <span class="text-sm leading-[1.35] text-foreground dark:text-dark-foreground">{{ opt.label }}</span>
26
37
  </label>
27
38
  }
28
39
  </div>
29
40
  } @else if (isLoading) {
30
- <div class="j-radio-state">
41
+ <div class="flex items-center justify-start gap-2 min-h-8 text-muted-foreground dark:text-dark-muted-foreground text-sm">
31
42
  <JIcon
32
43
  [icon]="Icons.Loader2"
33
44
  [size]="16"
@@ -37,13 +48,15 @@
37
48
  <span>Cargando...</span>
38
49
  </div>
39
50
  } @else {
40
- <div class="j-radio-state">No hay opciones</div>
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>
41
54
  }
42
55
 
43
56
  @if (showClear && selectedValue !== null) {
44
57
  <button
45
58
  type="button"
46
- class="j-radio-clear"
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"
47
60
  (click)="clear()"
48
61
  [disabled]="isInteractionDisabled"
49
62
  >
@@ -14,7 +14,7 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
14
14
  import { JGenericCrudService } from 'tailjng';
15
15
  import { Icons } from '../../.config/icons/icons.lucide';
16
16
  import { JIconComponent } from '../../icon/icon.component';
17
- import { normalizeToggleOptions } from '../shared/toggle-options.util';
17
+ import { normalizeToggleOptions, buildToggleLoadParams } from '../shared/toggle-options.util';
18
18
  import { ToggleOption, ToggleRadioLayout, ToggleSortOrder } from '../shared/toggle-options.types';
19
19
 
20
20
  export type { ToggleOption, ToggleRadioLayout, ToggleSortOrder } from './toggle-radio.types';
@@ -57,7 +57,7 @@ export class JToggleRadioComponent implements OnInit, OnChanges, ControlValueAcc
57
57
  @Input() classes = '';
58
58
  @Input() ngClasses: Record<string, boolean> = {};
59
59
 
60
- @Output() selectionChange = new EventEmitter<unknown>();
60
+ @Output() selectionChange = new EventEmitter<any>();
61
61
 
62
62
  internalOptions: ToggleOption[] = [];
63
63
  selectedValue: unknown = null;
@@ -115,13 +115,7 @@ export class JToggleRadioComponent implements OnInit, OnChanges, ControlValueAcc
115
115
 
116
116
  this.isLoading = true;
117
117
 
118
- const params: Record<string, string> = {
119
- sortOrder: this.sort,
120
- };
121
-
122
- Object.keys(this.defaultFilters).forEach((key) => {
123
- params[`filter[${key}]`] = String(this.defaultFilters[key]);
124
- });
118
+ const params = buildToggleLoadParams(this.sort, this.defaultFilters);
125
119
 
126
120
  this.genericService.findAll<unknown>({ endpoint: this.endpoint, params }).subscribe({
127
121
  next: (res) => {
@@ -3,43 +3,10 @@
3
3
  width: 100%;
4
4
  }
5
5
 
6
- .j-segment-track {
7
- display: flex;
8
- min-height: 2.5rem;
9
- overflow: hidden;
10
- border: 1px solid var(--color-border);
11
- border-radius: 0.5rem;
12
- font-size: 0.875rem;
13
- user-select: none;
14
- }
15
-
16
- :host-context(.dark) .j-segment-track,
17
- :host-context(html.dark) .j-segment-track {
18
- border-color: var(--color-dark-border);
19
- }
20
-
21
6
  .j-segment-track--disabled {
22
7
  opacity: 0.5;
23
8
  }
24
9
 
25
- .j-segment-item {
26
- flex: 1 1 0;
27
- padding: 0.5rem 1rem;
28
- border: 0;
29
- border-right: 1px solid var(--color-border);
30
- background-color: var(--color-background);
31
- color: var(--color-foreground);
32
- font-weight: 500;
33
- cursor: pointer;
34
- transition:
35
- background-color 0.2s ease,
36
- color 0.2s ease;
37
- }
38
-
39
- .j-segment-item:last-child {
40
- border-right: 0;
41
- }
42
-
43
10
  .j-segment-item:hover:not(.j-segment-item--selected):not(.j-segment-item--disabled) {
44
11
  background-color: color-mix(in srgb, var(--color-muted) 45%, var(--color-background));
45
12
  }
@@ -49,13 +16,6 @@
49
16
  color: var(--color-primary-foreground);
50
17
  }
51
18
 
52
- :host-context(.dark) .j-segment-item,
53
- :host-context(html.dark) .j-segment-item {
54
- border-right-color: var(--color-dark-border);
55
- background-color: var(--color-dark-background);
56
- color: var(--color-dark-foreground);
57
- }
58
-
59
19
  :host-context(.dark) .j-segment-item--selected,
60
20
  :host-context(html.dark) .j-segment-item--selected {
61
21
  background-color: var(--color-dark-primary);
@@ -72,37 +32,3 @@
72
32
  outline-offset: -2px;
73
33
  z-index: 1;
74
34
  }
75
-
76
- .j-segment-state {
77
- display: flex;
78
- align-items: center;
79
- justify-content: center;
80
- gap: 0.5rem;
81
- min-height: 2.5rem;
82
- border: 1px solid var(--color-border);
83
- border-radius: 0.5rem;
84
- color: var(--color-foreground);
85
- font-size: 0.875rem;
86
- }
87
-
88
- :host-context(.dark) .j-segment-state,
89
- :host-context(html.dark) .j-segment-state {
90
- border-color: var(--color-dark-border);
91
- color: var(--color-dark-foreground);
92
- }
93
-
94
- .j-segment-clear {
95
- margin-top: 0.5rem;
96
- padding: 0;
97
- border: 0;
98
- background: transparent;
99
- color: var(--color-destructive);
100
- font-size: 0.75rem;
101
- text-decoration: underline;
102
- cursor: pointer;
103
- }
104
-
105
- .j-segment-clear:disabled {
106
- opacity: 0.5;
107
- cursor: not-allowed;
108
- }
@@ -1,10 +1,14 @@
1
1
  @if (internalOptions.length > 0) {
2
- <div [ngClass]="trackClasses">
2
+ <div
3
+ [ngClass]="trackClasses"
4
+ class="flex min-h-10 overflow-hidden border border-border dark:border-dark-border rounded-lg text-sm select-none"
5
+ >
3
6
  @for (opt of internalOptions; track $index) {
4
7
  <button
5
8
  type="button"
6
9
  [disabled]="isInteractionDisabled"
7
10
  [ngClass]="segmentClasses(opt.value)"
11
+ class="flex-1 basis-0 py-2 px-4 border-0 border-r border-border dark:border-dark-border bg-background dark:bg-dark-background text-foreground dark:text-dark-foreground font-medium cursor-pointer transition-[background-color,color] duration-200 ease-in-out last:border-r-0"
8
12
  (click)="select(opt.value)"
9
13
  >
10
14
  {{ opt.label }}
@@ -12,7 +16,9 @@
12
16
  }
13
17
  </div>
14
18
  } @else if (isLoading) {
15
- <div class="j-segment-state">
19
+ <div
20
+ class="flex items-center justify-center gap-2 min-h-10 border border-border dark:border-dark-border rounded-lg text-foreground dark:text-dark-foreground text-sm"
21
+ >
16
22
  <JIcon
17
23
  [icon]="Icons.Loader2"
18
24
  [size]="16"
@@ -22,13 +28,17 @@
22
28
  <span>Cargando...</span>
23
29
  </div>
24
30
  } @else {
25
- <div class="j-segment-state">No hay opciones</div>
31
+ <div
32
+ class="flex items-center justify-center gap-2 min-h-10 border border-border dark:border-dark-border rounded-lg text-foreground dark:text-dark-foreground text-sm"
33
+ >
34
+ No hay opciones
35
+ </div>
26
36
  }
27
37
 
28
38
  @if (showClear && selectedValue !== null) {
29
39
  <button
30
40
  type="button"
31
- class="j-segment-clear"
41
+ class="mt-2 p-0 border-0 bg-transparent text-destructive text-xs underline cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
32
42
  (click)="clear()"
33
43
  [disabled]="isInteractionDisabled"
34
44
  >
@@ -14,7 +14,7 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
14
14
  import { JGenericCrudService } from 'tailjng';
15
15
  import { Icons } from '../../.config/icons/icons.lucide';
16
16
  import { JIconComponent } from '../../icon/icon.component';
17
- import { normalizeToggleOptions } from '../shared/toggle-options.util';
17
+ import { normalizeToggleOptions, buildToggleLoadParams } from '../shared/toggle-options.util';
18
18
  import { ToggleOption, ToggleSortOrder } from '../shared/toggle-options.types';
19
19
 
20
20
  export type { ToggleOption, ToggleSortOrder } from './segment-toggle.types';
@@ -54,7 +54,7 @@ export class JToggleSegmentComponent implements OnInit, OnChanges, ControlValueA
54
54
  @Input() classesElement = '';
55
55
  @Input() ngClasses: Record<string, boolean> = {};
56
56
 
57
- @Output() selectionChange = new EventEmitter<unknown>();
57
+ @Output() selectionChange = new EventEmitter<any>();
58
58
 
59
59
  internalOptions: ToggleOption[] = [];
60
60
  selectedValue: unknown = null;
@@ -111,13 +111,7 @@ export class JToggleSegmentComponent implements OnInit, OnChanges, ControlValueA
111
111
 
112
112
  this.isLoading = true;
113
113
 
114
- const params: Record<string, string> = {
115
- sortOrder: this.sort,
116
- };
117
-
118
- Object.keys(this.defaultFilters).forEach((key) => {
119
- params[`filter[${key}]`] = String(this.defaultFilters[key]);
120
- });
114
+ const params = buildToggleLoadParams(this.sort, this.defaultFilters);
121
115
 
122
116
  this.genericService.findAll<unknown>({ endpoint: this.endpoint, params }).subscribe({
123
117
  next: (res) => {