@allxsmith/bestax-bulma 5.54.0 → 5.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/esm/components/Command.js +22 -22
  4. package/dist/esm/components/Command.js.map +1 -1
  5. package/dist/esm/components/DataTable.js +215 -0
  6. package/dist/esm/components/DataTable.js.map +1 -0
  7. package/dist/esm/components/useDataTable.js +482 -0
  8. package/dist/esm/components/useDataTable.js.map +1 -0
  9. package/dist/esm/elements/ColorSwatch.js +49 -0
  10. package/dist/esm/elements/ColorSwatch.js.map +1 -0
  11. package/dist/esm/elements/RingProgress.js +3 -3
  12. package/dist/esm/elements/Td.js +4 -2
  13. package/dist/esm/elements/Td.js.map +1 -1
  14. package/dist/esm/elements/Th.js +13 -5
  15. package/dist/esm/elements/Th.js.map +1 -1
  16. package/dist/esm/elements/Tr.js.map +1 -1
  17. package/dist/esm/form/ColorPicker.js +540 -0
  18. package/dist/esm/form/ColorPicker.js.map +1 -0
  19. package/dist/esm/form/Combobox.js +18 -18
  20. package/dist/esm/form/Combobox.js.map +1 -1
  21. package/dist/esm/form/Dropzone.js +524 -0
  22. package/dist/esm/form/Dropzone.js.map +1 -0
  23. package/dist/esm/form/File.js.map +1 -1
  24. package/dist/esm/form/_colorInternals/colorMath.js +292 -0
  25. package/dist/esm/form/_colorInternals/colorMath.js.map +1 -0
  26. package/dist/esm/form/_colorInternals/pickerState.js +160 -0
  27. package/dist/esm/form/_colorInternals/pickerState.js.map +1 -0
  28. package/dist/esm/helpers/statusRegion.js +3 -3
  29. package/dist/esm/helpers/statusRegion.js.map +1 -1
  30. package/dist/esm/helpers/useFocusTrap.js +2 -2
  31. package/dist/extras.css +1 -1
  32. package/dist/extras.css.map +1 -1
  33. package/dist/index.cjs +2986 -796
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.esm.js +5 -0
  36. package/dist/index.esm.js.map +1 -1
  37. package/dist/types/components/DataTable.d.ts +120 -0
  38. package/dist/types/components/useDataTable.d.ts +445 -0
  39. package/dist/types/elements/ColorSwatch.d.ts +54 -0
  40. package/dist/types/elements/Td.d.ts +9 -1
  41. package/dist/types/elements/Th.d.ts +14 -2
  42. package/dist/types/elements/Tr.d.ts +10 -1
  43. package/dist/types/form/ColorPicker.d.ts +266 -0
  44. package/dist/types/form/Dropzone.d.ts +138 -0
  45. package/dist/types/form/File.d.ts +2 -0
  46. package/dist/types/form/_colorInternals/colorMath.d.ts +63 -0
  47. package/dist/types/form/_colorInternals/pickerState.d.ts +62 -0
  48. package/dist/types/index.d.ts +4 -0
  49. package/dist/types-cjs/components/DataTable.d.ts +120 -0
  50. package/dist/types-cjs/components/useDataTable.d.ts +445 -0
  51. package/dist/types-cjs/elements/ColorSwatch.d.ts +54 -0
  52. package/dist/types-cjs/elements/Td.d.ts +9 -1
  53. package/dist/types-cjs/elements/Th.d.ts +14 -2
  54. package/dist/types-cjs/elements/Tr.d.ts +10 -1
  55. package/dist/types-cjs/form/ColorPicker.d.ts +266 -0
  56. package/dist/types-cjs/form/Dropzone.d.ts +138 -0
  57. package/dist/types-cjs/form/File.d.ts +2 -0
  58. package/dist/types-cjs/form/_colorInternals/colorMath.d.ts +63 -0
  59. package/dist/types-cjs/form/_colorInternals/pickerState.d.ts +62 -0
  60. package/dist/types-cjs/index.d.ts +4 -0
  61. package/dist/versions/bestax-no-dark-mode.css +1 -1
  62. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  63. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  64. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  65. package/dist/versions/bestax-no-helpers.css +1 -1
  66. package/dist/versions/bestax-no-helpers.css.map +1 -1
  67. package/dist/versions/bestax-prefixed.css +1 -1
  68. package/dist/versions/bestax-prefixed.css.map +1 -1
  69. package/package.json +1 -1
  70. package/src/scss/components/_datatable.scss +152 -0
  71. package/src/scss/components/_index.scss +1 -0
  72. package/src/scss/elements/_colorswatch.scss +100 -0
  73. package/src/scss/elements/_index.scss +1 -0
  74. package/src/scss/form/_checkbox.scss +53 -0
  75. package/src/scss/form/_colorpicker.scss +354 -0
  76. package/src/scss/form/_dropzone.scss +233 -0
  77. package/src/scss/form/_file.scss +29 -1
  78. package/src/scss/form/_index.scss +2 -0
@@ -0,0 +1,152 @@
1
+ // Bestax Extras - DataTable Styles
2
+ // DataTable renders Bulma's own table, checkboxes and pager, which Bulma and
3
+ // the Checkbox partial style. This adds what Bulma has no class for: the
4
+ // toolbar above the table, the button a sortable header holds, and the
5
+ // indicator that shows which way it sorts.
6
+ //
7
+ // The sort button is styled on its own class rather than inside
8
+ // `.data-table`, so a table built from `useDataTable`'s props, with no
9
+ // DataTable around it, gets the same button. Its variables are declared on
10
+ // the button for the same reason.
11
+
12
+ @use 'bulma/sass/utilities/initial-variables' as iv;
13
+ @use 'bulma/sass/utilities/css-variables' as cv;
14
+ @use '../mixins' as *;
15
+
16
+ // Between the toolbar's items, and under the toolbar.
17
+ $data-table-gap: 0.75rem !default;
18
+ // Between a header's text and its indicator.
19
+ $data-table-sort-gap: 0.375em !default;
20
+ $data-table-sort-indicator-size: 0.75em !default;
21
+ // How strongly an unsorted column shows that it sorts.
22
+ $data-table-sort-unsorted-opacity: 0.35 !default;
23
+
24
+ // The indicator's shapes, used as masks so they're painted in the text's
25
+ // color, or a system color in forced colors. Private, since they're shapes
26
+ // rather than themable values; the fill only marks what each mask keeps.
27
+ // An unsorted column shows both triangles, a sorted one the one pointing
28
+ // the way it sorts, up for ascending as the APG example draws it.
29
+ $-unsorted: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 1.5 12.5 7h-9zM8 14.5 3.5 9h9z'/%3E%3C/svg%3E");
30
+ $-ascending: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 3.5 13.5 11h-11z'/%3E%3C/svg%3E");
31
+ $-descending: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 12.5 2.5 5h11z'/%3E%3C/svg%3E");
32
+
33
+ .#{iv.$class-prefix}data-table {
34
+ @include cv.register-vars(
35
+ (
36
+ 'data-table-gap': #{$data-table-gap},
37
+ )
38
+ );
39
+ }
40
+
41
+ .#{iv.$class-prefix}data-table-sort {
42
+ @include cv.register-vars(
43
+ (
44
+ 'data-table-sort-gap': #{$data-table-sort-gap},
45
+ 'data-table-sort-indicator-size': #{$data-table-sort-indicator-size},
46
+ 'data-table-sort-unsorted-opacity': #{$data-table-sort-unsorted-opacity},
47
+ )
48
+ );
49
+ }
50
+
51
+ // A block, spaced as Bulma spaces its table and its other blocks.
52
+ .#{iv.$class-prefix}data-table:not(:last-child) {
53
+ margin-block-end: cv.getVar('block-spacing');
54
+ }
55
+
56
+ // The caption names the table from the start of the line, over the header
57
+ // cells it names, rather than centered over them as browsers place it.
58
+ .#{iv.$class-prefix}data-table .#{iv.$class-prefix}table > caption {
59
+ padding-block-end: cv.getVar('data-table-gap');
60
+ text-align: start;
61
+ }
62
+
63
+ // The toolbar: the search field at the start, anything else at the end, and
64
+ // the two stacked when the line runs out of room.
65
+ .#{iv.$class-prefix}data-table-toolbar {
66
+ display: flex;
67
+ flex-wrap: wrap;
68
+ align-items: flex-end;
69
+ gap: cv.getVar('data-table-gap');
70
+ margin-block-end: cv.getVar('data-table-gap');
71
+
72
+ > .#{iv.$class-prefix}field {
73
+ margin-block-end: 0;
74
+ }
75
+ }
76
+
77
+ .#{iv.$class-prefix}data-table-actions {
78
+ display: flex;
79
+ flex-wrap: wrap;
80
+ align-items: center;
81
+ gap: cv.getVar('data-table-gap');
82
+ margin-inline-start: auto;
83
+ }
84
+
85
+ // A sortable header's button reads as the header's own text, with the
86
+ // indicator after it.
87
+ .#{iv.$class-prefix}data-table-sort {
88
+ @include extras-button-reset;
89
+ display: inline-flex;
90
+ align-items: center;
91
+ gap: cv.getVar('data-table-sort-gap');
92
+ font-weight: inherit;
93
+ line-height: inherit;
94
+ text-align: inherit;
95
+
96
+ &::after {
97
+ content: '';
98
+ flex-shrink: 0;
99
+ width: cv.getVar('data-table-sort-indicator-size');
100
+ height: cv.getVar('data-table-sort-indicator-size');
101
+ background-color: currentColor;
102
+ opacity: cv.getVar('data-table-sort-unsorted-opacity');
103
+ -webkit-mask-image: $-unsorted;
104
+ -webkit-mask-size: contain;
105
+ -webkit-mask-repeat: no-repeat;
106
+ -webkit-mask-position: center;
107
+ mask-image: $-unsorted;
108
+ mask-size: contain;
109
+ mask-repeat: no-repeat;
110
+ mask-position: center;
111
+ }
112
+
113
+ &:hover::after {
114
+ opacity: 1;
115
+ }
116
+
117
+ &:focus-visible {
118
+ @include extras-focus-outline;
119
+ }
120
+ }
121
+
122
+ // The sorted header says which way in `aria-sort`, so the indicator reads it
123
+ // from there, and markup built from `useDataTable`'s props shows it too.
124
+ th[aria-sort='ascending'] > .#{iv.$class-prefix}data-table-sort::after {
125
+ opacity: 1;
126
+ -webkit-mask-image: $-ascending;
127
+ mask-image: $-ascending;
128
+ }
129
+
130
+ th[aria-sort='descending'] > .#{iv.$class-prefix}data-table-sort::after {
131
+ opacity: 1;
132
+ -webkit-mask-image: $-descending;
133
+ mask-image: $-descending;
134
+ }
135
+
136
+ // Forced colors replaces a background color that isn't a system one, which
137
+ // would take the indicator's paint away. The mask is left alone, so the
138
+ // shape stays.
139
+ @media (forced-colors: active) {
140
+ .#{iv.$class-prefix}data-table-sort {
141
+ // A faint indicator would fall short of the contrast forced colors is
142
+ // for. The two shapes, one triangle or both, still tell the states apart.
143
+ &::after {
144
+ background-color: ButtonText;
145
+ opacity: 1;
146
+ }
147
+
148
+ &:focus-visible {
149
+ outline-color: Highlight;
150
+ }
151
+ }
152
+ }
@@ -24,3 +24,4 @@
24
24
  @use 'treeview';
25
25
  @use 'scrollarea';
26
26
  @use 'command';
27
+ @use 'datatable';
@@ -0,0 +1,100 @@
1
+ // Bestax Extras - ColorSwatch Styles
2
+ // A color shown as a small chip. Bulma has no swatch.
3
+ //
4
+ // The component sets the color as `--color-swatch-color`, which is painted
5
+ // as a gradient over a checkerboard, so a see-through color shows the
6
+ // checks through it. Forced colors would turn both into the page's
7
+ // background, so the swatch opts out of it and takes an edge in the
8
+ // system's text color instead.
9
+
10
+ @use 'bulma/sass/utilities/initial-variables' as iv;
11
+ @use 'bulma/sass/utilities/css-variables' as cv;
12
+
13
+ $color-swatch-size: 1.5rem !default;
14
+ $color-swatch-size-small: 1rem !default;
15
+ $color-swatch-size-medium: 2rem !default;
16
+ $color-swatch-size-large: 3rem !default;
17
+ $color-swatch-radius: cv.getVar('radius') !default;
18
+ // A faint edge in the text color, so a white swatch shows on a white page
19
+ // and a black one on a dark page.
20
+ $color-swatch-edge-color: hsla(
21
+ cv.getVar('text-h'),
22
+ cv.getVar('text-s'),
23
+ cv.getVar('text-l'),
24
+ 0.2
25
+ ) !default;
26
+ // The checkerboard behind a see-through color, from scheme colors so it
27
+ // follows dark mode.
28
+ $color-swatch-checker-color: cv.getVar('border') !default;
29
+ $color-swatch-checker-background: cv.getVar('scheme-main') !default;
30
+ $color-swatch-checker-size: 0.5rem !default;
31
+
32
+ .#{iv.$class-prefix}color-swatch {
33
+ @include cv.register-vars(
34
+ (
35
+ 'color-swatch-size': #{$color-swatch-size},
36
+ 'color-swatch-radius': #{$color-swatch-radius},
37
+ 'color-swatch-edge-color': #{$color-swatch-edge-color},
38
+ 'color-swatch-checker-color': #{$color-swatch-checker-color},
39
+ 'color-swatch-checker-background': #{$color-swatch-checker-background},
40
+ 'color-swatch-checker-size': #{$color-swatch-checker-size},
41
+ )
42
+ );
43
+ }
44
+
45
+ @each $size,
46
+ $value
47
+ in (
48
+ 'small': $color-swatch-size-small,
49
+ 'medium': $color-swatch-size-medium,
50
+ 'large': $color-swatch-size-large
51
+ )
52
+ {
53
+ .#{iv.$class-prefix}color-swatch.#{iv.$class-prefix}is-#{$size} {
54
+ @include cv.register-vars(
55
+ (
56
+ 'color-swatch-size': #{$value},
57
+ )
58
+ );
59
+ }
60
+ }
61
+
62
+ .#{iv.$class-prefix}color-swatch {
63
+ display: inline-flex;
64
+ flex-shrink: 0;
65
+ align-items: center;
66
+ justify-content: center;
67
+ inline-size: cv.getVar('color-swatch-size');
68
+ block-size: cv.getVar('color-swatch-size');
69
+ border-radius: cv.getVar('color-swatch-radius');
70
+ vertical-align: middle;
71
+ // The color over the checkerboard: a tile of four squares, two of each.
72
+ background:
73
+ linear-gradient(var(--color-swatch-color), var(--color-swatch-color)),
74
+ repeating-conic-gradient(
75
+ cv.getVar('color-swatch-checker-color') 0% 25%,
76
+ cv.getVar('color-swatch-checker-background') 0% 50%
77
+ )
78
+ 0 0 / calc(#{cv.getVar('color-swatch-checker-size')} * 2)
79
+ calc(#{cv.getVar('color-swatch-checker-size')} * 2);
80
+ box-shadow: inset 0 0 0 1px cv.getVar('color-swatch-edge-color');
81
+ // A swatch is its color, so forced colors leaves it alone.
82
+ forced-color-adjust: none;
83
+ }
84
+
85
+ .#{iv.$class-prefix}color-swatch.#{iv.$class-prefix}is-rounded {
86
+ border-radius: cv.getVar('radius-rounded');
87
+ }
88
+
89
+ // What's drawn on the swatch, such as an icon, sits in its middle.
90
+ .#{iv.$class-prefix}color-swatch > span {
91
+ display: inline-flex;
92
+ line-height: 1;
93
+ }
94
+
95
+ @media (forced-colors: active) {
96
+ // Kept apart from the page by the system's text color.
97
+ .#{iv.$class-prefix}color-swatch {
98
+ box-shadow: inset 0 0 0 1px CanvasText;
99
+ }
100
+ }
@@ -2,6 +2,7 @@
2
2
  // Import all element partials here
3
3
 
4
4
  // Element Components
5
+ @use 'colorswatch';
5
6
  @use 'descriptionlist';
6
7
  @use 'kbd';
7
8
  @use 'linkbutton';
@@ -2,8 +2,10 @@
2
2
  // Custom-styled checkbox with colors, sizes, and visual states
3
3
  // Follows Bulma v1 CSS variable convention (see _dialog.scss)
4
4
 
5
+ @use "sass:list";
5
6
  @use "bulma/sass/utilities/initial-variables" as iv;
6
7
  @use "bulma/sass/utilities/css-variables" as cv;
8
+ @use "bulma/sass/utilities/derived-variables" as dv;
7
9
  @use "bulma/sass/utilities/mixins" as mx;
8
10
 
9
11
  // Bulma's horizontal field: `.field-label` takes one part of the row and
@@ -182,6 +184,57 @@ $-check-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'
182
184
  }
183
185
  }
184
186
 
187
+ // On Bulma's selected table row (`Tr isSelected`, or a cell with
188
+ // `is-selected`), the row's fill is the same color a checked box fills and
189
+ // borders with, so the box would vanish into it and leave its tick floating.
190
+ // There the box takes the row's text color, and its tick and dash the row's
191
+ // fill, so it reads as the row's text does. An unchecked box's border takes
192
+ // the text color too. This outranks the color variants on purpose: any color
193
+ // on that fill is a guess, and the row's own pair is the one Bulma made to
194
+ // read.
195
+ //
196
+ // Only a Checkbox placed straight in one of those cells sits on the row's
197
+ // fill, so the rule names each step down to it rather than any checkbox
198
+ // below the row. One inside a menu, a card or a table nested in the cell sits
199
+ // on that surface's own background, and keeps its own colors there.
200
+ //
201
+ // A cell with a color of its own (`Td color="white"`) paints its own
202
+ // background over the row's, and so does every cell of a row with a color
203
+ // (`Tr color="white" isSelected`), which hands its color to its cells. Both
204
+ // are left out, and a box there keeps its usual look. Bulma colors those cells with custom properties alone, which a
205
+ // selector can't read, so the cells are named by class, one for each color
206
+ // Bulma makes them from: its `$colors` map, which its table's
207
+ // `$table-colors` is built from, custom colors included. A selected cell is
208
+ // the row's fill whatever its color, as Bulma paints it.
209
+ $-colored-cells: ();
210
+ @each $name, $color in dv.$colors {
211
+ $-colored-cells: list.append(
212
+ $-colored-cells,
213
+ ".#{iv.$class-prefix}is-#{$name}",
214
+ $separator: comma
215
+ );
216
+ }
217
+
218
+ .#{iv.$class-prefix}table {
219
+ tr.#{iv.$class-prefix}is-selected:not(#{$-colored-cells})
220
+ > td:not(#{$-colored-cells}),
221
+ tr.#{iv.$class-prefix}is-selected:not(#{$-colored-cells})
222
+ > th:not(#{$-colored-cells}),
223
+ td.#{iv.$class-prefix}is-selected,
224
+ th.#{iv.$class-prefix}is-selected {
225
+ > .#{iv.$class-prefix}styled-checkbox {
226
+ @include cv.register-vars(
227
+ (
228
+ "checkbox-border-color": #{cv.getVar("table-row-active-color")},
229
+ "checkbox-active-color": #{cv.getVar("table-row-active-color")},
230
+ "checkbox-indeterminate-color": #{cv.getVar("table-row-active-color")},
231
+ "checkbox-check-color": #{cv.getVar("table-row-active-background-color")},
232
+ )
233
+ );
234
+ }
235
+ }
236
+ }
237
+
185
238
  // Size variants
186
239
  .#{iv.$class-prefix}styled-checkbox.#{iv.$class-prefix}is-small {
187
240
  font-size: cv.getVar("size-small");
@@ -0,0 +1,354 @@
1
+ // Bestax Extras - ColorPicker Styles
2
+ // A panel for choosing a color: a saturation and brightness square, a hue
3
+ // slider, an alpha slider, the value as text, and swatches. Bulma has no
4
+ // color picker.
5
+ //
6
+ // The square and the sliders are drawn here, and the native range inputs
7
+ // that operate them are visually hidden inside their thumbs. The component
8
+ // sets the hue as `--color-picker-hue`, the color's channels as
9
+ // `--color-picker-rgb`, and the thumbs' places as `--color-area-x`,
10
+ // `--color-area-y` and `--color-slider-position`. Forced colors would wipe
11
+ // the gradients, so everything that shows a color opts out of it and takes
12
+ // an edge in the system's text color instead.
13
+
14
+ @use 'bulma/sass/utilities/initial-variables' as iv;
15
+ @use 'bulma/sass/utilities/css-variables' as cv;
16
+ @use '../mixins' as *;
17
+
18
+ // The square and the hue track are the color model itself, so they're
19
+ // fixed, not themed.
20
+ $-black: hsl(0, 0%, 0%);
21
+ $-white: hsl(0, 0%, 100%);
22
+ $-hue-stops: hsl(0, 100%, 50%), hsl(60, 100%, 50%), hsl(120, 100%, 50%), hsl(180, 100%, 50%), hsl(240, 100%, 50%), hsl(300, 100%, 50%), hsl(360, 100%, 50%);
23
+ // The check on a chosen swatch, black or white, whichever reads better, in
24
+ // a ring of the other, so it shows whatever is under it.
25
+ $-ink-dark: hsl(0, 0%, 0%);
26
+ $-ink-light: hsl(0, 0%, 100%);
27
+
28
+ $color-picker-width: 16rem !default;
29
+ $color-picker-gap: 0.75rem !default;
30
+ $color-picker-area-height: 10rem !default;
31
+ $color-picker-area-radius: cv.getVar('radius') !default;
32
+ // The sliders' height is what a press lands on; the track is drawn thinner
33
+ // inside it.
34
+ $color-picker-slider-height: 1.5rem !default;
35
+ $color-picker-track-height: 0.75rem !default;
36
+ $color-picker-track-radius: cv.getVar('radius-rounded') !default;
37
+ $color-picker-thumb-size: 1.25rem !default;
38
+ $color-picker-thumb-border-width: 3px !default;
39
+ $color-picker-thumb-color: hsl(0, 0%, 100%) !default;
40
+ // A dark ring each side of the white one, so a thumb shows on any color.
41
+ $color-picker-thumb-shadow: 0 0 0 1px hsla(0, 0%, 0%, 0.45), inset 0 0 0 1px hsla(0, 0%, 0%, 0.45) !default;
42
+ $color-picker-edge-color: hsla(
43
+ cv.getVar('text-h'),
44
+ cv.getVar('text-s'),
45
+ cv.getVar('text-l'),
46
+ 0.2
47
+ ) !default;
48
+ $color-picker-checker-color: cv.getVar('border') !default;
49
+ $color-picker-checker-background: cv.getVar('scheme-main') !default;
50
+ $color-picker-checker-size: 0.375rem !default;
51
+ $color-picker-swatch-size: 1.5rem !default;
52
+ $color-picker-swatch-gap: 0.25rem !default;
53
+ $color-picker-swatch-radius: cv.getVar('radius') !default;
54
+ $color-picker-swatch-ring-color: cv.getVar('text-strong') !default;
55
+ $color-picker-preview-size: 1.875rem !default;
56
+ $color-picker-disabled-opacity: 0.5 !default;
57
+
58
+ .#{iv.$class-prefix}color-picker {
59
+ @include cv.register-vars(
60
+ (
61
+ 'color-picker-width': #{$color-picker-width},
62
+ 'color-picker-gap': #{$color-picker-gap},
63
+ 'color-picker-area-height': #{$color-picker-area-height},
64
+ 'color-picker-area-radius': #{$color-picker-area-radius},
65
+ 'color-picker-slider-height': #{$color-picker-slider-height},
66
+ 'color-picker-track-height': #{$color-picker-track-height},
67
+ 'color-picker-track-radius': #{$color-picker-track-radius},
68
+ 'color-picker-thumb-size': #{$color-picker-thumb-size},
69
+ 'color-picker-thumb-border-width': #{$color-picker-thumb-border-width},
70
+ 'color-picker-thumb-color': #{$color-picker-thumb-color},
71
+ 'color-picker-thumb-shadow': #{$color-picker-thumb-shadow},
72
+ 'color-picker-edge-color': #{$color-picker-edge-color},
73
+ 'color-picker-checker-color': #{$color-picker-checker-color},
74
+ 'color-picker-checker-background': #{$color-picker-checker-background},
75
+ 'color-picker-checker-size': #{$color-picker-checker-size},
76
+ 'color-picker-swatch-size': #{$color-picker-swatch-size},
77
+ 'color-picker-swatch-gap': #{$color-picker-swatch-gap},
78
+ 'color-picker-swatch-radius': #{$color-picker-swatch-radius},
79
+ 'color-picker-swatch-ring-color': #{$color-picker-swatch-ring-color},
80
+ 'color-picker-preview-size': #{$color-picker-preview-size},
81
+ 'color-picker-disabled-opacity': #{$color-picker-disabled-opacity},
82
+ )
83
+ );
84
+ }
85
+
86
+ // ---- The panel -------------------------------------------------------------------
87
+
88
+ .#{iv.$class-prefix}color-picker {
89
+ display: flex;
90
+ flex-direction: column;
91
+ gap: cv.getVar('color-picker-gap');
92
+ inline-size: cv.getVar('color-picker-width');
93
+ max-inline-size: 100%;
94
+ }
95
+
96
+ // ---- The square ------------------------------------------------------------------
97
+
98
+ .#{iv.$class-prefix}color-area {
99
+ position: relative;
100
+ block-size: cv.getVar('color-picker-area-height');
101
+ border-radius: cv.getVar('color-picker-area-radius');
102
+ // White to the hue across, black up from the bottom: saturation by
103
+ // brightness at this hue.
104
+ background:
105
+ linear-gradient(to top, #{$-black}, transparent),
106
+ linear-gradient(
107
+ to right,
108
+ #{$-white},
109
+ hsl(var(--color-picker-hue, 0) 100% 50%)
110
+ );
111
+ box-shadow: inset 0 0 0 1px cv.getVar('color-picker-edge-color');
112
+ cursor: crosshair;
113
+ // A drag moves the thumb rather than scrolling the page.
114
+ touch-action: none;
115
+ user-select: none;
116
+ forced-color-adjust: none;
117
+ }
118
+
119
+ // Saturation runs from the inline start, so right to left it grows leftward.
120
+ .#{iv.$class-prefix}color-area:dir(rtl) {
121
+ background:
122
+ linear-gradient(to top, #{$-black}, transparent),
123
+ linear-gradient(
124
+ to left,
125
+ #{$-white},
126
+ hsl(var(--color-picker-hue, 0) 100% 50%)
127
+ );
128
+ }
129
+
130
+ // ---- The sliders -----------------------------------------------------------------
131
+
132
+ .#{iv.$class-prefix}color-slider {
133
+ position: relative;
134
+ block-size: cv.getVar('color-picker-slider-height');
135
+ cursor: pointer;
136
+ touch-action: none;
137
+ user-select: none;
138
+ forced-color-adjust: none;
139
+ }
140
+
141
+ .#{iv.$class-prefix}color-slider-track {
142
+ position: absolute;
143
+ inset-inline: 0;
144
+ inset-block-start: 50%;
145
+ block-size: cv.getVar('color-picker-track-height');
146
+ margin-block-start: calc(#{cv.getVar('color-picker-track-height')} / -2);
147
+ border-radius: cv.getVar('color-picker-track-radius');
148
+ box-shadow: inset 0 0 0 1px cv.getVar('color-picker-edge-color');
149
+ }
150
+
151
+ .#{iv.$class-prefix}color-slider.#{iv.$class-prefix}is-hue
152
+ .#{iv.$class-prefix}color-slider-track {
153
+ background: linear-gradient(to right, $-hue-stops);
154
+ }
155
+
156
+ .#{iv.$class-prefix}color-slider.#{iv.$class-prefix}is-hue
157
+ .#{iv.$class-prefix}color-slider-track:dir(rtl) {
158
+ background: linear-gradient(to left, $-hue-stops);
159
+ }
160
+
161
+ // From see-through to the solid color, over a checkerboard.
162
+ .#{iv.$class-prefix}color-slider.#{iv.$class-prefix}is-alpha
163
+ .#{iv.$class-prefix}color-slider-track {
164
+ background:
165
+ linear-gradient(
166
+ to right,
167
+ rgb(var(--color-picker-rgb, 0 0 0) / 0),
168
+ rgb(var(--color-picker-rgb, 0 0 0))
169
+ ),
170
+ repeating-conic-gradient(
171
+ cv.getVar('color-picker-checker-color') 0% 25%,
172
+ cv.getVar('color-picker-checker-background') 0% 50%
173
+ )
174
+ 0 0 / calc(#{cv.getVar('color-picker-checker-size')} * 2)
175
+ calc(#{cv.getVar('color-picker-checker-size')} * 2);
176
+ }
177
+
178
+ .#{iv.$class-prefix}color-slider.#{iv.$class-prefix}is-alpha
179
+ .#{iv.$class-prefix}color-slider-track:dir(rtl) {
180
+ background:
181
+ linear-gradient(
182
+ to left,
183
+ rgb(var(--color-picker-rgb, 0 0 0) / 0),
184
+ rgb(var(--color-picker-rgb, 0 0 0))
185
+ ),
186
+ repeating-conic-gradient(
187
+ cv.getVar('color-picker-checker-color') 0% 25%,
188
+ cv.getVar('color-picker-checker-background') 0% 50%
189
+ )
190
+ 0 0 / calc(#{cv.getVar('color-picker-checker-size')} * 2)
191
+ calc(#{cv.getVar('color-picker-checker-size')} * 2);
192
+ }
193
+
194
+ // ---- Thumbs ----------------------------------------------------------------------
195
+
196
+ // A ring that shows the color under it; its centre is the value.
197
+ .#{iv.$class-prefix}color-area-thumb,
198
+ .#{iv.$class-prefix}color-slider-thumb {
199
+ position: absolute;
200
+ inline-size: cv.getVar('color-picker-thumb-size');
201
+ block-size: cv.getVar('color-picker-thumb-size');
202
+ margin-inline-start: calc(#{cv.getVar('color-picker-thumb-size')} / -2);
203
+ margin-block-start: calc(#{cv.getVar('color-picker-thumb-size')} / -2);
204
+ border: cv.getVar('color-picker-thumb-border-width') solid
205
+ cv.getVar('color-picker-thumb-color');
206
+ border-radius: 50%;
207
+ box-shadow: cv.getVar('color-picker-thumb-shadow');
208
+ pointer-events: none;
209
+ }
210
+
211
+ .#{iv.$class-prefix}color-area-thumb {
212
+ inset-inline-start: var(--color-area-x, 0%);
213
+ inset-block-start: var(--color-area-y, 100%);
214
+ }
215
+
216
+ .#{iv.$class-prefix}color-slider-thumb {
217
+ inset-inline-start: var(--color-slider-position, 0%);
218
+ inset-block-start: 50%;
219
+ }
220
+
221
+ // The inputs that operate them, there for the keyboard and assistive tech.
222
+ .#{iv.$class-prefix}color-area-input,
223
+ .#{iv.$class-prefix}color-slider-input {
224
+ @include extras-sr-only;
225
+ }
226
+
227
+ .#{iv.$class-prefix}color-area-thumb:has(:focus-visible),
228
+ .#{iv.$class-prefix}color-slider-thumb:has(:focus-visible) {
229
+ @include extras-focus-outline;
230
+ }
231
+
232
+ // ---- The value -------------------------------------------------------------------
233
+
234
+ .#{iv.$class-prefix}color-picker-value {
235
+ display: flex;
236
+ align-items: center;
237
+ gap: 0.5rem;
238
+ }
239
+
240
+ .#{iv.$class-prefix}color-picker-value
241
+ > .#{iv.$class-prefix}color-picker-preview {
242
+ inline-size: cv.getVar('color-picker-preview-size');
243
+ block-size: cv.getVar('color-picker-preview-size');
244
+ }
245
+
246
+ .#{iv.$class-prefix}color-picker-value > .#{iv.$class-prefix}input {
247
+ flex: 1 1 auto;
248
+ min-inline-size: 0;
249
+ font-variant-numeric: tabular-nums;
250
+ }
251
+
252
+ // ---- Swatches --------------------------------------------------------------------
253
+
254
+ .#{iv.$class-prefix}color-picker-swatches {
255
+ display: flex;
256
+ flex-wrap: wrap;
257
+ gap: cv.getVar('color-picker-swatch-gap');
258
+ }
259
+
260
+ // The button rings the swatch when it's chosen, so the choice shows as an
261
+ // edge and a check as well as a color.
262
+ .#{iv.$class-prefix}color-picker-swatch {
263
+ @include extras-button-reset;
264
+ display: inline-flex;
265
+ padding: 2px;
266
+ border: 2px solid transparent;
267
+ border-radius: calc(#{cv.getVar('color-picker-swatch-radius')} + 4px);
268
+ line-height: 0;
269
+
270
+ &:focus-visible {
271
+ @include extras-focus-outline;
272
+ }
273
+
274
+ .#{iv.$class-prefix}color-swatch {
275
+ inline-size: cv.getVar('color-picker-swatch-size');
276
+ block-size: cv.getVar('color-picker-swatch-size');
277
+ border-radius: cv.getVar('color-picker-swatch-radius');
278
+ color: $-ink-light;
279
+ font-size: calc(#{cv.getVar('color-picker-swatch-size')} * 0.75);
280
+ }
281
+
282
+ .#{iv.$class-prefix}color-picker-check-halo {
283
+ stroke: $-ink-dark;
284
+ }
285
+
286
+ &.#{iv.$class-prefix}is-dark-ink {
287
+ .#{iv.$class-prefix}color-swatch {
288
+ color: $-ink-dark;
289
+ }
290
+
291
+ .#{iv.$class-prefix}color-picker-check-halo {
292
+ stroke: $-ink-light;
293
+ }
294
+ }
295
+
296
+ // A see-through swatch shows the checkerboard under it, which is drawn in
297
+ // the scheme's colors, so the check takes the scheme's text color in a ring
298
+ // of its background, and follows dark mode.
299
+ &.#{iv.$class-prefix}is-see-through {
300
+ .#{iv.$class-prefix}color-swatch {
301
+ color: cv.getVar('text-strong');
302
+ }
303
+
304
+ .#{iv.$class-prefix}color-picker-check-halo {
305
+ stroke: cv.getVar('scheme-main');
306
+ }
307
+ }
308
+
309
+ &.#{iv.$class-prefix}is-checked {
310
+ border-color: cv.getVar('color-picker-swatch-ring-color');
311
+ }
312
+
313
+ &:disabled {
314
+ cursor: not-allowed;
315
+ }
316
+ }
317
+
318
+ // ---- Disabled --------------------------------------------------------------------
319
+
320
+ .#{iv.$class-prefix}color-picker.#{iv.$class-prefix}is-disabled,
321
+ .#{iv.$class-prefix}color-area.#{iv.$class-prefix}is-disabled,
322
+ .#{iv.$class-prefix}color-slider.#{iv.$class-prefix}is-disabled {
323
+ cursor: not-allowed;
324
+ }
325
+
326
+ .#{iv.$class-prefix}color-area.#{iv.$class-prefix}is-disabled,
327
+ .#{iv.$class-prefix}color-slider.#{iv.$class-prefix}is-disabled,
328
+ .#{iv.$class-prefix}color-picker-swatches[aria-disabled='true'] {
329
+ opacity: cv.getVar('color-picker-disabled-opacity');
330
+ }
331
+
332
+ // ---- Forced colors ---------------------------------------------------------------
333
+
334
+ @media (forced-colors: active) {
335
+ // The colors stay, edged in the system's text color.
336
+ .#{iv.$class-prefix}color-area,
337
+ .#{iv.$class-prefix}color-slider-track {
338
+ box-shadow: inset 0 0 0 1px CanvasText;
339
+ }
340
+
341
+ .#{iv.$class-prefix}color-area-thumb:has(:focus-visible),
342
+ .#{iv.$class-prefix}color-slider-thumb:has(:focus-visible) {
343
+ outline-color: Highlight;
344
+ }
345
+
346
+ // An unchosen swatch's border would otherwise show like the chosen one's.
347
+ .#{iv.$class-prefix}color-picker-swatch {
348
+ border-color: Canvas;
349
+ }
350
+
351
+ .#{iv.$class-prefix}color-picker-swatch.#{iv.$class-prefix}is-checked {
352
+ border-color: Highlight;
353
+ }
354
+ }