@filip.mazev/blocks 1.4.14 → 1.4.16

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 (44) hide show
  1. package/README.md +5 -5
  2. package/core/styles/_a11y.scss +5 -0
  3. package/core/styles/_field-state.scss +12 -3
  4. package/core/styles/_helpers.scss +1 -0
  5. package/core/styles/_index.scss +4 -9
  6. package/core/styles/_palettes.scss +54 -10
  7. package/core/styles/_slider.scss +116 -6
  8. package/core/styles/_text-overflow.scss +7 -0
  9. package/core/styles/_text.scss +5 -0
  10. package/core/styles/_validation.scss +48 -0
  11. package/core/styles/themes/_azure-ember-theme.scss +4 -0
  12. package/core/styles/themes/_brick-rose-cyan-theme.scss +4 -0
  13. package/core/styles/themes/_carbon-cobalt-theme.scss +4 -0
  14. package/fesm2022/filip.mazev-blocks-core.mjs +102 -48
  15. package/fesm2022/filip.mazev-blocks-core.mjs.map +1 -1
  16. package/fesm2022/filip.mazev-blocks-effects-runtime.mjs +14 -3
  17. package/fesm2022/filip.mazev-blocks-effects-runtime.mjs.map +1 -1
  18. package/fesm2022/filip.mazev-blocks-effects.mjs +16 -8
  19. package/fesm2022/filip.mazev-blocks-effects.mjs.map +1 -1
  20. package/fesm2022/filip.mazev-blocks-forms.mjs +5004 -1078
  21. package/fesm2022/filip.mazev-blocks-forms.mjs.map +1 -1
  22. package/fesm2022/filip.mazev-blocks-primitives.mjs +2373 -1294
  23. package/fesm2022/filip.mazev-blocks-primitives.mjs.map +1 -1
  24. package/fesm2022/filip.mazev-blocks.mjs +1 -1
  25. package/fesm2022/filip.mazev-blocks.mjs.map +1 -1
  26. package/forms/README.md +80 -0
  27. package/package.json +1 -1
  28. package/schematics/ng-add/index.d.ts +1 -10
  29. package/schematics/ng-add/index.js +4 -13
  30. package/schematics/ng-add/schema.json +11 -17
  31. package/types/filip.mazev-blocks-core.d.ts +26 -15
  32. package/types/filip.mazev-blocks-effects.d.ts +1 -1
  33. package/types/filip.mazev-blocks-forms.d.ts +1216 -76
  34. package/types/filip.mazev-blocks-primitives.d.ts +304 -6
  35. package/types/filip.mazev-blocks.d.ts +1 -1
  36. package/core/styles/themes/_azure-coral-theme.scss +0 -4
  37. package/core/styles/themes/_blue-theme.scss +0 -5
  38. package/core/styles/themes/_graphite-sky-blue-theme.scss +0 -19
  39. package/core/styles/themes/_green-theme.scss +0 -5
  40. package/core/styles/themes/_orange-theme.scss +0 -5
  41. package/core/styles/themes/_purple-theme.scss +0 -5
  42. package/core/styles/themes/_red-theme.scss +0 -5
  43. package/core/styles/themes/_scarlet-cyan-theme.scss +0 -4
  44. package/core/styles/themes/_white-theme.scss +0 -5
package/README.md CHANGED
@@ -18,7 +18,7 @@ ng add @filip.mazev/blocks
18
18
 
19
19
  When you run the command above, the Angular CLI will execute our custom schematic to handle the boilerplate for you:
20
20
 
21
- * Palette selection: Graphite / Sky Blue is the CLI default. Azure / Coral, Violet / Teal, Tangerine / Indigo, Scarlet / Cyan, Lime / Violet, and Cyberpunk are also available. Use `--theme=azure-coral` to select Azure / Coral.
21
+ * Palette selection: Carbon / Cobalt is the CLI default. Azure / Ember, Violet / Teal, Tangerine / Indigo, Brick Rose / Cyan, Lime / Violet, and Cyberpunk are also available. Use `--theme=azure-ember` to select Azure / Ember.
22
22
  * Dependency Management: Automatically adds the latest versions of the Blocks ecosystem to your package.json and runs npm install.
23
23
  * SCSS Injection: Intelligently locates your project's global stylesheet (styles.scss or styles.sass) and injects the required @use statements, mixins, and both light/dark mode CSS variables based on your theme selection.
24
24
 
@@ -37,11 +37,11 @@ Then, manually configure your styles.scss:
37
37
 
38
38
  @layer base {
39
39
  :root {
40
- @include bx-theme($graphite-sky-blue-light-theme);
40
+ @include bx-theme($carbon-cobalt-light-theme);
41
41
  }
42
42
 
43
43
  [data-theme='dark'] {
44
- @include bx-theme($graphite-sky-blue-dark-theme);
44
+ @include bx-theme($carbon-cobalt-dark-theme);
45
45
  }
46
46
  }
47
47
  ```
@@ -52,10 +52,10 @@ Then, manually configure your styles.scss:
52
52
  Use paired palette IDs consistently in the CLI and `ThemingService.setPalette()`. For example:
53
53
 
54
54
  ```sh
55
- ng add @filip.mazev/blocks --theme=azure-coral
55
+ ng add @filip.mazev/blocks --theme=azure-ember
56
56
  ```
57
57
 
58
- The Sass exports use the same names: `$azure-coral-light-theme` and `$azure-coral-dark-theme`. Graphite / Sky Blue is the installer default; the playground starts with Graphite / Sky Blue. Previous IDs and Sass names remain aliases.
58
+ The Sass exports use the same names: `$azure-ember-light-theme` and `$azure-ember-dark-theme`. Carbon / Cobalt is the installer default; the playground starts with Carbon / Cobalt. Only the current palette IDs and Sass names are supported.
59
59
 
60
60
  Buttons and tabs accept `color="accent"` for the second tone. Icons and custom components can use semantic tokens such as `text-accent`, `accent-subtle`, `on-accent`, and `border-accent`. Canvas backgrounds stay neutral; status roles keep their meaning. See [the palette reference](../../documentation/appearance/README.md#palettes) for all seven pairs.
61
61
 
@@ -1,5 +1,10 @@
1
+ @use '@angular/cdk' as cdk;
2
+
1
3
  @forward 'motion';
2
4
 
5
+ // Emit the CDK utility once through the shared global accessibility entry point.
6
+ @include cdk.a11y-visually-hidden;
7
+
3
8
  :root {
4
9
  --bx-reduced-motion: 0;
5
10
 
@@ -14,9 +14,18 @@
14
14
  display: none;
15
15
  }
16
16
 
17
- &:focus-within:not(.is-disabled, :disabled),
18
- &:focus-visible:not(:disabled),
19
- &.is-open:not(:disabled) {
17
+ &:focus-within:not(
18
+ .is-disabled,
19
+ :disabled,
20
+ .is-readonly,
21
+ [readonly],
22
+ [aria-readonly='true'],
23
+ :has([readonly], [aria-readonly='true'])
24
+ ),
25
+ &:focus-visible:not(:disabled, [readonly], [aria-readonly='true']),
26
+ &.is-open:not(:disabled),
27
+ &.is-readonly.is-keyboard-focused:focus-within,
28
+ &:has(.bx-readonly.is-keyboard-focused):focus-within {
20
29
  --bx-glass-edge: var(--bx-border-brand);
21
30
 
22
31
  outline: 2px solid var(--bx-border-brand);
@@ -5,3 +5,4 @@
5
5
  @forward 'motion';
6
6
  @forward 'field-state';
7
7
  @forward 'choice-finish';
8
+ @forward 'text-overflow';
@@ -4,20 +4,15 @@
4
4
  @forward 'palettes';
5
5
  @forward 'theme-engine';
6
6
  @forward 'a11y';
7
- @forward 'themes/graphite-sky-blue-theme';
8
- @forward 'themes/azure-coral-theme';
7
+ @forward 'themes/carbon-cobalt-theme';
8
+ @forward 'themes/azure-ember-theme';
9
+ @forward 'themes/brick-rose-cyan-theme';
9
10
  @forward 'themes/violet-teal-theme';
10
11
  @forward 'themes/tangerine-indigo-theme';
11
- @forward 'themes/scarlet-cyan-theme';
12
12
  @forward 'themes/lime-violet-theme';
13
- @forward 'themes/white-theme';
14
- @forward 'themes/blue-theme';
15
- @forward 'themes/purple-theme';
16
- @forward 'themes/orange-theme';
17
- @forward 'themes/red-theme';
18
- @forward 'themes/green-theme';
19
13
  @forward 'themes/cyberpunk-theme';
20
14
  @forward 'themes/high-contrast-theme';
21
15
  @forward 'slider';
22
16
  @forward 'validation';
23
17
  @forward 'overlay';
18
+ @forward 'text';
@@ -180,28 +180,72 @@ $hc-yellow: #e4d500;
180
180
  $hc-cyan: #00f3f3;
181
181
  $hc-red: #ff0000;
182
182
  $hc-green: #00ff00;
183
- $graphite-palette: _tonal-palette(#525252) !default;
184
- $sky-blue-palette: _tonal-palette(#38bdf8) !default;
185
- $azure-palette: $blue-palette !default;
186
- $coral-palette: _tonal-palette(#f87763) !default;
183
+
184
+ // Tune the upper tones explicitly so dark actions retain their color character.
185
+ $carbon-palette: map.merge(
186
+ _tonal-palette(#292a2d),
187
+ (
188
+ 50: #fdfdfc,
189
+ 100: #f7f7f5,
190
+ 200: #efefed,
191
+ 300: #e2e2e0,
192
+ 400: #77797d,
193
+ )
194
+ ) !default;
195
+ $cobalt-palette: map.merge(
196
+ _tonal-palette(#356fe8),
197
+ (
198
+ 200: #abc5ff,
199
+ 300: #6d9aff,
200
+ 400: #4c82f2,
201
+ )
202
+ ) !default;
203
+ $ember-palette: map.merge(
204
+ _tonal-palette(#d85a1a),
205
+ (
206
+ 200: #f5a365,
207
+ 300: #f27b35,
208
+ 400: #e96926,
209
+ )
210
+ ) !default;
211
+ $brick-rose-palette: map.merge(
212
+ _tonal-palette(#b64a50),
213
+ (
214
+ 200: #e69ba4,
215
+ 300: #d36b77,
216
+ 400: #c55964,
217
+ )
218
+ ) !default;
219
+ $azure-palette: map.merge(
220
+ $blue-palette,
221
+ (
222
+ 300: #72a7ff,
223
+ )
224
+ ) !default;
187
225
  $violet-palette: $purple-palette !default;
188
226
  $teal-palette: _tonal-palette(#0d9488) !default;
189
227
  $tangerine-palette: $orange-palette !default;
190
228
  $indigo-palette: _tonal-palette(#4f78f5) !default;
191
- $scarlet-palette: $red-palette !default;
192
- $cyan-palette: _tonal-palette(#0891b2) !default;
229
+ $cyan-palette: map.merge(
230
+ _tonal-palette(#0891b2),
231
+ (
232
+ 200: #78d8e6,
233
+ 300: #22b8d0,
234
+ 400: #12a4bf,
235
+ )
236
+ ) !default;
193
237
  $lime-palette: _tonal-palette(#c4f53d) !default;
194
238
  $cool-violet-palette: _tonal-palette(#6842a6) !default;
195
239
  $all-palettes: (
196
- 'graphite': $graphite-palette,
197
- 'sky-blue': $sky-blue-palette,
240
+ 'carbon': $carbon-palette,
241
+ 'cobalt': $cobalt-palette,
242
+ 'ember': $ember-palette,
243
+ 'brick-rose': $brick-rose-palette,
198
244
  'azure': $azure-palette,
199
- 'coral': $coral-palette,
200
245
  'violet': $violet-palette,
201
246
  'teal': $teal-palette,
202
247
  'tangerine': $tangerine-palette,
203
248
  'indigo': $indigo-palette,
204
- 'scarlet': $scarlet-palette,
205
249
  'cyan': $cyan-palette,
206
250
  'lime': $lime-palette,
207
251
  'cool-violet': $cool-violet-palette,
@@ -18,8 +18,8 @@
18
18
  @mixin thumb {
19
19
  appearance: none;
20
20
  box-sizing: border-box;
21
- width: spacing(6);
22
- height: spacing(6);
21
+ width: var(--bx-slider-thumb-size, #{spacing(6)});
22
+ height: var(--bx-slider-thumb-size, #{spacing(6)});
23
23
  border-radius: radius(pill);
24
24
  border: 1px solid var(--bx-border-strong);
25
25
  background: var(--bx-bg-surface);
@@ -50,7 +50,38 @@
50
50
  display: block;
51
51
  }
52
52
 
53
- // The native thumb remains the hit target; the opaque decorative thumb reflects nearby colors.
53
+ &::before {
54
+ content: '';
55
+ display: var(--bx-slider-fill-display, block);
56
+ position: absolute;
57
+ top: var(--bx-slider-center-y, 50%);
58
+ left: var(--bx-slider-track-start, 0);
59
+ width: calc(
60
+ var(--bx-slider-thumb-size, #{spacing(6)}) / 2 + var(--bx-slider-position, 0.5) *
61
+ (var(--bx-slider-track-width, 100%) - var(--bx-slider-thumb-size, #{spacing(6)}))
62
+ );
63
+ height: spacing(2);
64
+ transform: translateY(-50%);
65
+ border-radius: radius(pill);
66
+ background: var(--bx-accent);
67
+ pointer-events: none;
68
+ z-index: 1;
69
+ }
70
+
71
+ &:dir(rtl)::before {
72
+ left: auto;
73
+ right: var(--bx-slider-track-start, 0);
74
+ }
75
+
76
+ input.bx-slider::-webkit-slider-runnable-track {
77
+ background: var(--bx-bg-neutral);
78
+ }
79
+
80
+ input.bx-slider::-moz-range-track {
81
+ background: var(--bx-bg-neutral);
82
+ }
83
+
84
+ // The native thumb remains the hit target; the decorative lens paints over it.
54
85
  input.bx-slider::-webkit-slider-thumb {
55
86
  background: transparent;
56
87
  border-color: transparent;
@@ -73,11 +104,41 @@
73
104
  position: absolute;
74
105
  top: var(--bx-slider-center-y, 50%);
75
106
  left: calc(
76
- var(--bx-slider-track-start, 0px) + var(--bx-slider-position, 0.5) *
77
- (var(--bx-slider-track-width, 100%) - #{spacing(6)})
107
+ var(--bx-slider-track-start, 0px) +
108
+ var(--bx-slider-physical-position, var(--bx-slider-position, 0.5)) *
109
+ (var(--bx-slider-track-width, 100%) - var(--bx-slider-thumb-size, #{spacing(6)}))
78
110
  );
79
111
  transform: translateY(-50%);
80
112
  pointer-events: none;
113
+ z-index: 2;
114
+ overflow: hidden;
115
+ background:
116
+ radial-gradient(circle at 35% 0%, rgb(255 255 255 / 45%), transparent 65%),
117
+ color-mix(in srgb, var(--bx-bg-surface) 24%, transparent);
118
+ border-color: color-mix(in srgb, var(--bx-text-primary) 35%, var(--bx-border-strong));
119
+ backdrop-filter: blur(var(--bx-slider-lens-blur, 1.5px));
120
+
121
+ --bx-slider-lens-width: calc(
122
+ var(--bx-slider-track-width) * var(--bx-slider-magnification, 1.5)
123
+ );
124
+ --bx-slider-lens-inset: calc(
125
+ var(--bx-slider-thumb-size, #{spacing(6)}) / 2 * var(--bx-slider-magnification, 1.5)
126
+ );
127
+ --bx-slider-lens-travel: calc(
128
+ (var(--bx-slider-track-width) - var(--bx-slider-thumb-size, #{spacing(6)})) *
129
+ var(--bx-slider-magnification, 1.5)
130
+ );
131
+ --bx-slider-lens-start-offset: calc(
132
+ var(--bx-slider-lens-inset) + var(--bx-slider-lens-start, 0) * var(--bx-slider-lens-travel)
133
+ );
134
+ --bx-slider-lens-end-offset: calc(
135
+ var(--bx-slider-lens-inset) + var(--bx-slider-lens-end, var(--bx-slider-position, 0.5)) *
136
+ var(--bx-slider-lens-travel)
137
+ );
138
+
139
+ &:dir(rtl) {
140
+ --bx-slider-physical-position: calc(1 - var(--bx-slider-position, 0.5));
141
+ }
81
142
 
82
143
  &::after {
83
144
  @include bx-transition(opacity, 0.2s, ease-out);
@@ -101,6 +162,38 @@
101
162
  }
102
163
  }
103
164
 
165
+ // Reuse the rail geometry in CSS instead of sampling screen pixels on drag.
166
+ // A separate rounded fill keeps the magnified selection's end caps curved.
167
+ .bx-slider-lens {
168
+ display: var(--bx-slider-lens-display, block);
169
+ position: absolute;
170
+ top: 50%;
171
+ left: calc(
172
+ var(--bx-slider-thumb-size, #{spacing(6)}) / 2 -
173
+ 1px - var(--bx-slider-lens-inset) - var(
174
+ --bx-slider-physical-position,
175
+ var(--bx-slider-position, 0.5)
176
+ ) *
177
+ var(--bx-slider-lens-travel)
178
+ );
179
+ width: var(--bx-slider-lens-width);
180
+ height: calc(#{spacing(2)} * var(--bx-slider-magnification, 1.5));
181
+ transform: translateY(-50%);
182
+ border-radius: radius(pill);
183
+ background: var(--bx-slider-lens-track-color, var(--bx-bg-neutral));
184
+ filter: blur(var(--bx-slider-lens-blur, 1.5px));
185
+
186
+ &::after {
187
+ content: '';
188
+ position: absolute;
189
+ inset-block: 0;
190
+ inset-inline: var(--bx-slider-lens-start-offset)
191
+ calc(var(--bx-slider-lens-width) - var(--bx-slider-lens-end-offset));
192
+ background: var(--bx-accent);
193
+ border-radius: inherit;
194
+ }
195
+ }
196
+
104
197
  input.bx-slider {
105
198
  appearance: none;
106
199
  width: 100%;
@@ -127,7 +220,7 @@ input.bx-slider {
127
220
  &::-webkit-slider-thumb {
128
221
  @include thumb;
129
222
 
130
- margin-top: calc((#{spacing(2)} - #{spacing(6)}) / 2 - 1px);
223
+ margin-top: calc((#{spacing(2)} - var(--bx-slider-thumb-size, #{spacing(6)})) / 2 - 1px);
131
224
  }
132
225
 
133
226
  &::-moz-range-thumb {
@@ -140,6 +233,10 @@ input.bx-slider {
140
233
  border-radius: radius(pill);
141
234
  }
142
235
 
236
+ &[readonly] {
237
+ cursor: default;
238
+ }
239
+
143
240
  &:disabled {
144
241
  opacity: 0.5;
145
242
  cursor: not-allowed;
@@ -147,6 +244,8 @@ input.bx-slider {
147
244
  }
148
245
 
149
246
  @mixin opaque-thumb {
247
+ --bx-slider-lens-display: none;
248
+
150
249
  background: var(--bx-bg-surface);
151
250
  backdrop-filter: none;
152
251
  }
@@ -217,3 +316,14 @@ input.bx-slider {
217
316
  box-shadow: none;
218
317
  }
219
318
  }
319
+
320
+ .bx-slider-value-label {
321
+ display: block;
322
+ color: var(--bx-text-secondary);
323
+ font-size: 0.75rem;
324
+ text-align: center;
325
+ }
326
+
327
+ .bx-slider-value-label[hidden] {
328
+ display: none;
329
+ }
@@ -0,0 +1,7 @@
1
+ // Shared ellipsis mechanics. Include through helpers when styling a text surface.
2
+ @mixin truncate-text {
3
+ min-inline-size: 0;
4
+ overflow: hidden;
5
+ text-overflow: ellipsis;
6
+ white-space: nowrap;
7
+ }
@@ -0,0 +1,5 @@
1
+ @use 'text-overflow' as *;
2
+
3
+ .bx-truncate {
4
+ @include truncate-text;
5
+ }
@@ -1,4 +1,5 @@
1
1
  @use 'field-state' as *;
2
+ @use 'mixins' as *;
2
3
 
3
4
  // A projected surface inside a form field receives the complete field material,
4
5
  // including its valid focus state, without application-specific effects CSS.
@@ -20,3 +21,50 @@
20
21
  outline-color: Mark;
21
22
  }
22
23
  }
24
+
25
+ .bx-native-control {
26
+ box-sizing: border-box;
27
+ inline-size: 100%;
28
+ padding: spacing(3);
29
+ border: 1px solid var(--bx-border-strong);
30
+ border-radius: radius(sm);
31
+ background: var(--bx-bg-neutral);
32
+ color: var(--bx-text-primary);
33
+ font: inherit;
34
+
35
+ &:focus-visible:not([readonly], [aria-readonly='true']),
36
+ &.is-keyboard-focused:focus-visible {
37
+ outline: 2px solid var(--bx-border-brand);
38
+ outline-offset: 2px;
39
+ }
40
+
41
+ &:disabled {
42
+ opacity: 0.6;
43
+ cursor: not-allowed;
44
+ }
45
+
46
+ &[readonly]:not(:disabled) {
47
+ cursor: default;
48
+ }
49
+
50
+ &[aria-invalid='true'] {
51
+ border-color: var(--bx-border-danger);
52
+ }
53
+ }
54
+
55
+ .bx-field-prefix,
56
+ .bx-field-suffix {
57
+ display: inline-flex;
58
+ align-items: center;
59
+ flex: 0 0 auto;
60
+ }
61
+
62
+ .bx-field-prefix {
63
+ padding-inline: var(--bx-field-adornment-padding, #{spacing(3)})
64
+ var(--bx-field-adornment-gap, #{spacing(2)});
65
+ }
66
+
67
+ .bx-field-suffix {
68
+ padding-inline: var(--bx-field-adornment-gap, #{spacing(2)})
69
+ var(--bx-field-adornment-padding, #{spacing(3)});
70
+ }
@@ -0,0 +1,4 @@
1
+ @use '../theme-engine' as *;
2
+
3
+ $azure-ember-light-theme: make-light-theme('azure', 'ember');
4
+ $azure-ember-dark-theme: make-dark-theme('azure', 'ember');
@@ -0,0 +1,4 @@
1
+ @use '../theme-engine' as *;
2
+
3
+ $brick-rose-cyan-light-theme: make-light-theme('brick-rose', 'cyan');
4
+ $brick-rose-cyan-dark-theme: make-dark-theme('brick-rose', 'cyan');
@@ -0,0 +1,4 @@
1
+ @use '../theme-engine' as *;
2
+
3
+ $carbon-cobalt-light-theme: make-light-theme('carbon', 'cobalt');
4
+ $carbon-cobalt-dark-theme: make-dark-theme('carbon', 'cobalt');