@acontplus/ng-components 4.0.0 → 5.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acontplus/ng-components",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "Comprehensive Angular Material UI component library featuring dynamic Tabulator tables, theme toggle with dark mode, dialog wrappers, autocomplete components, cards, buttons, icons, input chips, spinners, directives, pipes, and SCSS styling utilities.",
5
5
  "peerDependencies": {
6
6
  "@acontplus/ui-kit": "^1.0.2",
@@ -1,69 +1,72 @@
1
1
  @use 'sass:map';
2
+ @use 'sass:meta';
3
+ @use 'sass:string';
2
4
  @use '@angular/material' as mat;
3
5
  @use '../../../core/tokens/m3-utils';
4
6
  @use '../../../core/tokens/m3';
5
7
 
8
+ /// Same semantic palettes as `acp-badge`, so both components share the same colors per type.
9
+ $_semantic-palettes: (
10
+ info: mat.$azure-palette,
11
+ success: mat.$green-palette,
12
+ warning: mat.$orange-palette,
13
+ danger: mat.$red-palette,
14
+ );
15
+
6
16
  @function get-tokens($theme: m3.$sys-theme) {
7
17
  $system: m3-utils.get-system($theme);
8
- $is-dark: map.get($system, md-sys-type) == dark;
18
+
19
+ $color-tokens: (
20
+ // `default` type, derived from the theme surface colors
21
+ alert-outline-color: map.get($system, outline-variant),
22
+ alert-background-color: map.get($system, surface-container),
23
+ alert-text-color: map.get($system, on-surface),
24
+ alert-icon-color: map.get($system, on-surface-variant),
25
+ alert-solid-background-color: map.get($system, inverse-surface),
26
+ alert-solid-text-color: map.get($system, inverse-on-surface),
27
+ // `outlined` variant container, shared by every type
28
+ alert-outlined-background-color: map.get($system, surface),
29
+ alert-outlined-text-color: map.get($system, on-surface)
30
+ );
31
+
32
+ // System values are custom property names; wrap them to use inside `color-mix()`
33
+ $surface: map.get($system, surface);
34
+ @if meta.type-of($surface) == string and string.index($surface, '--') == 1 {
35
+ $surface: var($surface);
36
+ }
37
+ $on-surface: map.get($system, on-surface);
38
+
39
+ @each $name, $palette in $_semantic-palettes {
40
+ // Material's semantic palettes are very saturated at tone 80, so soften them in dark mode
41
+ $accent: light-dark(
42
+ map.get($palette, 40),
43
+ color-mix(in oklab, #{map.get($palette, 80)} 70%, white)
44
+ );
45
+
46
+ $color-tokens: map.merge(
47
+ $color-tokens,
48
+ (
49
+ // `soft` variant: subtle tint of the theme surface
50
+ alert-#{$name}-background-color: color-mix(in srgb, #{$accent} 12%, #{$surface}),
51
+ alert-#{$name}-text-color: $on-surface,
52
+ alert-#{$name}-outline-color: color-mix(in srgb, #{$accent} 35%, #{$surface}),
53
+ // Icon, heading, `outlined` border
54
+ alert-#{$name}-icon-color: $accent,
55
+ // `filled` variant
56
+ alert-#{$name}-solid-background-color: light-dark(
57
+ map.get($palette, 40),
58
+ map.get($palette, 30)
59
+ ),
60
+ alert-#{$name}-solid-text-color: map.get($palette, 100)
61
+ )
62
+ );
63
+ }
9
64
 
10
65
  $tokens: (
11
66
  base: (
12
67
  alert-container-shape: map.get($system, corner-small),
13
68
  ),
14
- color: (
15
- alert-outline-color: map.get($system, outline-variant),
16
- alert-background-color: map.get($system, surface-container),
17
- alert-text-color: map.get($system, on-surface),
18
- alert-info-outline-color: light-dark(
19
- map.get(mat.$azure-palette, 80),
20
- map.get(mat.$azure-palette, 40)
21
- ),
22
- alert-info-background-color: light-dark(
23
- map.get(mat.$azure-palette, 90),
24
- map.get(mat.$azure-palette, 20)
25
- ),
26
- alert-info-text-color: light-dark(
27
- map.get(mat.$azure-palette, 20),
28
- map.get(mat.$azure-palette, 90)
29
- ),
30
- alert-success-outline-color: light-dark(
31
- map.get(mat.$green-palette, 80),
32
- map.get(mat.$green-palette, 40)
33
- ),
34
- alert-success-background-color: light-dark(
35
- map.get(mat.$green-palette, 95),
36
- map.get(mat.$green-palette, 20)
37
- ),
38
- alert-success-text-color: light-dark(
39
- map.get(mat.$green-palette, 20),
40
- map.get(mat.$green-palette, 95)
41
- ),
42
- alert-warning-outline-color: light-dark(
43
- map.get(mat.$yellow-palette, 80),
44
- map.get(mat.$yellow-palette, 40)
45
- ),
46
- alert-warning-background-color: light-dark(
47
- map.get(mat.$yellow-palette, 98),
48
- map.get(mat.$yellow-palette, 20)
49
- ),
50
- alert-warning-text-color: light-dark(
51
- map.get(mat.$yellow-palette, 20),
52
- map.get(mat.$yellow-palette, 98)
53
- ),
54
- alert-danger-outline-color: light-dark(
55
- map.get(mat.$red-palette, 80),
56
- map.get(mat.$red-palette, 40)
57
- ),
58
- alert-danger-background-color: light-dark(
59
- map.get(mat.$red-palette, 90),
60
- map.get(mat.$red-palette, 20)
61
- ),
62
- alert-danger-text-color: light-dark(
63
- map.get(mat.$red-palette, 20),
64
- map.get(mat.$red-palette, 90)
65
- ),
66
- ),
69
+ color: $color-tokens,
67
70
  typography: (),
68
71
  density: (),
69
72
  );
@@ -2,59 +2,110 @@
2
2
  @use './m3-alert';
3
3
 
4
4
  $fallbacks: m3-alert.get-tokens();
5
+ $_types: (info, success, warning, danger);
5
6
 
6
7
  .acp-alert {
8
+ --acp-alert-bg: #{token-utils.slot(alert-background-color, $fallbacks)};
9
+ --acp-alert-fg: #{token-utils.slot(alert-text-color, $fallbacks)};
10
+ --acp-alert-border: #{token-utils.slot(alert-outline-color, $fallbacks)};
11
+ --acp-alert-icon: #{token-utils.slot(alert-icon-color, $fallbacks)};
12
+ --acp-alert-solid-bg: #{token-utils.slot(alert-solid-background-color, $fallbacks)};
13
+ --acp-alert-solid-fg: #{token-utils.slot(alert-solid-text-color, $fallbacks)};
14
+
7
15
  position: relative;
8
- display: block;
16
+ display: flex;
17
+ align-items: flex-start;
18
+ gap: 0.75rem;
9
19
  padding: 0.75rem 1rem;
10
- margin-bottom: 1rem;
20
+ box-sizing: border-box;
11
21
  line-height: 1.5;
12
- border: 1px solid token-utils.slot(alert-outline-color, $fallbacks);
22
+ border: 1px solid var(--acp-alert-border);
13
23
  border-radius: token-utils.slot(alert-container-shape, $fallbacks);
14
- background-color: token-utils.slot(alert-background-color, $fallbacks);
15
- color: token-utils.slot(alert-text-color, $fallbacks);
24
+ background-color: var(--acp-alert-bg);
25
+ color: var(--acp-alert-fg);
16
26
 
17
- &.acp-alert-info {
18
- border-color: token-utils.slot(alert-info-outline-color, $fallbacks);
19
- background-color: token-utils.slot(alert-info-background-color, $fallbacks);
20
- color: token-utils.slot(alert-info-text-color, $fallbacks);
27
+ &[hidden] {
28
+ display: none;
21
29
  }
22
30
 
23
- &.acp-alert-success {
24
- border-color: token-utils.slot(alert-success-outline-color, $fallbacks);
25
- background-color: token-utils.slot(alert-success-background-color, $fallbacks);
26
- color: token-utils.slot(alert-success-text-color, $fallbacks);
31
+ @each $type in $_types {
32
+ &.acp-alert-#{$type} {
33
+ --acp-alert-bg: #{token-utils.slot(alert-#{$type}-background-color, $fallbacks)};
34
+ --acp-alert-fg: #{token-utils.slot(alert-#{$type}-text-color, $fallbacks)};
35
+ --acp-alert-border: #{token-utils.slot(alert-#{$type}-outline-color, $fallbacks)};
36
+ --acp-alert-icon: #{token-utils.slot(alert-#{$type}-icon-color, $fallbacks)};
37
+ --acp-alert-solid-bg: #{token-utils.slot(alert-#{$type}-solid-background-color, $fallbacks)};
38
+ --acp-alert-solid-fg: #{token-utils.slot(alert-#{$type}-solid-text-color, $fallbacks)};
39
+ }
27
40
  }
28
41
 
29
- &.acp-alert-warning {
30
- border-color: token-utils.slot(alert-warning-outline-color, $fallbacks);
31
- background-color: token-utils.slot(alert-warning-background-color, $fallbacks);
32
- color: token-utils.slot(alert-warning-text-color, $fallbacks);
42
+ &.acp-alert--outlined {
43
+ border-color: var(--acp-alert-icon);
44
+ background-color: token-utils.slot(alert-outlined-background-color, $fallbacks);
45
+ color: token-utils.slot(alert-outlined-text-color, $fallbacks);
33
46
  }
34
47
 
35
- &.acp-alert-danger {
36
- border-color: token-utils.slot(alert-danger-outline-color, $fallbacks);
37
- background-color: token-utils.slot(alert-danger-background-color, $fallbacks);
38
- color: token-utils.slot(alert-danger-text-color, $fallbacks);
48
+ &:not(.acp-alert--filled) .acp-alert-title {
49
+ color: var(--acp-alert-icon);
50
+ }
51
+
52
+ &.acp-alert--filled {
53
+ --acp-alert-icon: currentColor;
54
+
55
+ border-color: transparent;
56
+ background-color: var(--acp-alert-solid-bg);
57
+ color: var(--acp-alert-solid-fg);
39
58
  }
59
+
60
+ &.acp-alert-dismissible {
61
+ padding-right: 0.25rem;
62
+
63
+ [dir='rtl'] & {
64
+ padding-right: 1rem;
65
+ padding-left: 0.25rem;
66
+ }
67
+ }
68
+ }
69
+
70
+ .acp-alert-icon {
71
+ flex-shrink: 0;
72
+ width: 1.5rem;
73
+ height: 1.5rem;
74
+ font-size: 1.5rem;
75
+ color: var(--acp-alert-icon);
76
+ }
77
+
78
+ .acp-alert-body {
79
+ flex: 1;
80
+ min-width: 0;
81
+ // Align the first text line with the 24px icon
82
+ padding-top: calc((1.5rem - 1lh) / 2);
83
+ }
84
+
85
+ .acp-alert-title {
86
+ margin-bottom: 0.125rem;
87
+ font-weight: 600;
40
88
  }
41
89
 
42
- .acp-alert-close {
43
- position: absolute;
44
- top: 0;
45
- right: 0;
90
+ .acp-alert-content:empty,
91
+ .acp-alert-actions:empty {
92
+ display: none;
93
+ }
94
+
95
+ .acp-alert-actions {
46
96
  display: flex;
47
- align-items: center;
48
- justify-content: center;
49
- width: 3rem;
50
- height: 3rem;
51
-
52
- [dir='rtl'] & {
53
- right: auto;
54
- left: 0;
55
- }
97
+ flex-wrap: wrap;
98
+ gap: 0.5rem;
99
+ margin-top: 0.75rem;
56
100
  }
57
101
 
58
- .acp-alert-dismissible {
59
- padding-right: 3rem;
102
+ .acp-alert-close.mat-mdc-icon-button {
103
+ --mat-icon-button-icon-color: currentColor;
104
+ --mat-icon-button-state-layer-color: currentColor;
105
+ --mat-icon-button-state-layer-size: 2.25rem;
106
+
107
+ flex-shrink: 0;
108
+ margin-top: calc((1.5rem - 2.25rem) / 2);
109
+ padding: 0.5rem;
110
+ color: inherit;
60
111
  }
@@ -19,7 +19,12 @@
19
19
  $color-tokens,
20
20
  (
21
21
  badge-#{$name}-fg: light-dark(map.get($palette, 95), map.get($palette, 20)),
22
- badge-#{$name}-bg: light-dark(map.get($palette, 40), map.get($palette, 80))
22
+ // Material's semantic palettes are very saturated at tone 80; soften them in dark mode
23
+ // (same treatment as `acp-alert`)
24
+ badge-#{$name}-bg: light-dark(
25
+ map.get($palette, 40),
26
+ color-mix(in oklab, #{map.get($palette, 80)} 70%, white)
27
+ )
23
28
  )
24
29
  );
25
30
  }
@@ -111,6 +111,12 @@ $fallbacks: m3-badge.get-tokens();
111
111
  --acp-badge-fg: #{token-utils.slot(badge-neutral-color, $fallbacks)};
112
112
  }
113
113
 
114
+ // `surface-variant` is a container color: as text (soft, tonal, outlined, text) it is almost
115
+ // invisible, so those variants use `on-surface-variant` instead
116
+ &.acp-badge--neutral:not(.acp-badge--filled) {
117
+ --acp-badge-bg: #{token-utils.slot(badge-neutral-color, $fallbacks)};
118
+ }
119
+
114
120
  &.acp-badge--custom {
115
121
  --acp-badge-bg: var(--acp-badge-custom-bg, #{token-utils.slot(badge-custom-bg, $fallbacks)});
116
122
  --acp-badge-fg: var(--acp-badge-custom-fg, #{token-utils.slot(badge-custom-color, $fallbacks)});
@@ -167,16 +173,22 @@ $fallbacks: m3-badge.get-tokens();
167
173
  }
168
174
 
169
175
  &.acp-badge--tonal &__chip.mat-mdc-chip {
176
+ // The 22% tint is darker than `soft`; darken the text in light mode to keep WCAG AA contrast
177
+ --acp-badge-tonal-fg: light-dark(
178
+ color-mix(in oklab, var(--acp-badge-bg) 80%, black),
179
+ var(--acp-badge-bg)
180
+ );
181
+
170
182
  @include mat.chips-overrides(
171
183
  (
172
184
  elevated-container-color: color-mix(in srgb, var(--acp-badge-bg) 22%, transparent),
173
185
  elevated-selected-container-color: color-mix(in srgb, var(--acp-badge-bg) 22%, transparent),
174
- label-text-color: var(--acp-badge-bg),
175
- selected-label-text-color: var(--acp-badge-bg),
176
- with-icon-icon-color: var(--acp-badge-bg),
177
- with-icon-selected-icon-color: var(--acp-badge-bg),
178
- with-trailing-icon-trailing-icon-color: var(--acp-badge-bg),
179
- selected-trailing-icon-color: var(--acp-badge-bg),
186
+ label-text-color: var(--acp-badge-tonal-fg),
187
+ selected-label-text-color: var(--acp-badge-tonal-fg),
188
+ with-icon-icon-color: var(--acp-badge-tonal-fg),
189
+ with-icon-selected-icon-color: var(--acp-badge-tonal-fg),
190
+ with-trailing-icon-trailing-icon-color: var(--acp-badge-tonal-fg),
191
+ selected-trailing-icon-color: var(--acp-badge-tonal-fg),
180
192
  outline-color: transparent,
181
193
  )
182
194
  );
@@ -33,10 +33,24 @@ $fallbacks: m3-grid.get-tokens();
33
33
  }
34
34
  }
35
35
 
36
+ .mat-mdc-row.acp-grid-row-active {
37
+ background-color: token-utils.slot(grid-table-row-hover-background-color, $fallbacks);
38
+ }
39
+
36
40
  .mat-mdc-row.selected {
37
41
  background-color: token-utils.slot(grid-table-row-selected-background-color, $fallbacks);
38
42
  }
39
43
 
44
+ .mat-mdc-row:focus {
45
+ outline: none;
46
+ }
47
+
48
+ .mat-mdc-row:focus-visible,
49
+ .mat-mdc-row.acp-grid-row-active:not(:focus) {
50
+ outline: 2px solid token-utils.slot(grid-table-cell-selected-outline-color, $fallbacks);
51
+ outline-offset: -2px;
52
+ }
53
+
40
54
  .mat-mdc-cell.selected {
41
55
  box-shadow: inset 0 0 0 1px
42
56
  token-utils.slot(grid-table-cell-selected-outline-color, $fallbacks);
@@ -243,3 +257,50 @@ $fallbacks: m3-grid.get-tokens();
243
257
  vertical-align: middle;
244
258
  }
245
259
  }
260
+
261
+ .acp-grid-size-small {
262
+ --mat-table-header-container-height: 40px;
263
+ --mat-table-row-item-container-height: 36px;
264
+ --mat-table-footer-container-height: 36px;
265
+ --mat-table-header-headline-size: 0.8125rem;
266
+ --mat-table-row-item-label-text-size: 0.8125rem;
267
+ --mat-table-footer-supporting-text-size: 0.8125rem;
268
+ --mat-icon-button-state-layer-size: 32px;
269
+ --mat-checkbox-state-layer-size: 32px;
270
+ --mat-paginator-container-size: 48px;
271
+ --mat-button-outlined-container-height: 32px;
272
+ --mat-button-filled-container-height: 32px;
273
+ --mat-button-protected-container-height: 32px;
274
+ --mat-button-text-container-height: 32px;
275
+ --mat-button-tonal-container-height: 32px;
276
+
277
+ :is(.mat-mdc-header-cell, .mat-mdc-footer-cell, .mat-mdc-cell):not(.acp-grid-checkbox-cell) {
278
+ padding-left: 8px;
279
+ padding-right: 8px;
280
+ }
281
+
282
+ .acp-grid-toolbar,
283
+ .acp-grid-statusbar {
284
+ padding: 4px;
285
+ }
286
+ }
287
+
288
+ .acp-grid-size-large {
289
+ --mat-table-header-container-height: 64px;
290
+ --mat-table-row-item-container-height: 60px;
291
+ --mat-table-footer-container-height: 60px;
292
+ --mat-table-header-headline-size: 1rem;
293
+ --mat-table-row-item-label-text-size: 1rem;
294
+ --mat-table-footer-supporting-text-size: 1rem;
295
+ --mat-paginator-container-size: 64px;
296
+
297
+ :is(.mat-mdc-header-cell, .mat-mdc-footer-cell, .mat-mdc-cell):not(.acp-grid-checkbox-cell) {
298
+ padding-left: 20px;
299
+ padding-right: 20px;
300
+ }
301
+
302
+ .acp-grid-toolbar,
303
+ .acp-grid-statusbar {
304
+ padding: 12px;
305
+ }
306
+ }