color-elements 0.0.4 → 0.0.5

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/.claude/settings.local.json +30 -0
  2. package/.editorconfig +8 -0
  3. package/.prettierrc +17 -0
  4. package/.vscode/settings.json +7 -0
  5. package/README.md +27 -18
  6. package/_build/copy-config.js +15 -14
  7. package/_build/copy-config.json +4 -9
  8. package/_build/eleventy.js +8 -8
  9. package/_includes/component.njk +9 -14
  10. package/_includes/plain.njk +5 -0
  11. package/_redirects +1 -1
  12. package/assets/css/style.css +4 -4
  13. package/debug.html +46 -0
  14. package/package.json +19 -8
  15. package/src/channel-picker/channel-picker.css +4 -4
  16. package/src/channel-picker/channel-picker.js +15 -11
  17. package/src/channel-slider/channel-slider.css +14 -7
  18. package/src/channel-slider/channel-slider.js +13 -5
  19. package/src/color-chart/README.md +36 -5
  20. package/src/color-chart/color-chart-global.css +13 -12
  21. package/src/color-chart/color-chart-shadow.css +123 -0
  22. package/src/color-chart/color-chart.css +2 -112
  23. package/src/color-chart/color-chart.js +307 -103
  24. package/src/color-inline/color-inline.css +21 -16
  25. package/src/color-inline/color-inline.js +2 -3
  26. package/src/color-inline/style.css +1 -1
  27. package/src/color-picker/color-picker.css +3 -3
  28. package/src/color-picker/color-picker.js +14 -7
  29. package/src/color-scale/README.md +42 -2
  30. package/src/color-scale/color-scale.css +1 -1
  31. package/src/color-scale/color-scale.js +12 -9
  32. package/src/color-slider/README.md +17 -3
  33. package/src/color-slider/color-slider.css +54 -33
  34. package/src/color-slider/color-slider.js +9 -7
  35. package/src/color-swatch/color-swatch.css +41 -32
  36. package/src/color-swatch/color-swatch.js +17 -9
  37. package/src/common/color-element.js +34 -76
  38. package/src/common/dom.js +4 -2
  39. package/src/common/util.js +1 -1
  40. package/src/gamut-badge/gamut-badge.css +33 -13
  41. package/src/gamut-badge/gamut-badge.js +9 -7
  42. package/src/space-picker/space-picker.css +3 -3
  43. package/src/space-picker/space-picker.js +28 -10
  44. package/src/src.json +1 -1
@@ -11,4 +11,4 @@ html {
11
11
  color-inline {
12
12
  display: block;
13
13
  margin: 1em 0;
14
- }
14
+ }
@@ -5,9 +5,9 @@
5
5
  }
6
6
 
7
7
  #space_picker {
8
- margin-inline-start: -.7em; /* align with the channel names */
8
+ margin-inline-start: -0.7em; /* align with the channel names */
9
9
  font-size: 150%;
10
- transition: border-color .2s;
10
+ transition: border-color 0.2s;
11
11
 
12
12
  &:not(:hover) {
13
13
  border-color: transparent;
@@ -24,7 +24,7 @@ slot[name="color-space"]::slotted(*) {
24
24
  display: flex;
25
25
  flex-flow: column;
26
26
  justify-content: space-between;
27
- gap: .3em;
27
+ gap: 0.3em;
28
28
  min-inline-size: 10em;
29
29
  }
30
30
 
@@ -63,14 +63,17 @@ const Self = class ColorPicker extends ColorElement {
63
63
  }
64
64
  this.color = this._el.swatch.color;
65
65
  }
66
- else if (this._el.space_picker.contains(source) || this._slots.color_space.assignedElements().includes(source)) {
66
+ else if (
67
+ this._el.space_picker.contains(source) ||
68
+ this._slots.color_space.assignedElements().includes(source)
69
+ ) {
67
70
  this.spaceId = event.target.value;
68
71
  }
69
72
 
70
- this.dispatchEvent(new event.constructor(event.type, {...event}));
73
+ this.dispatchEvent(new event.constructor(event.type, { ...event }));
71
74
  }
72
75
 
73
- propChangedCallback ({name, prop, detail: change}) {
76
+ propChangedCallback ({ name, prop, detail: change }) {
74
77
  if (name === "space" || name === "alpha") {
75
78
  let space = this.space;
76
79
 
@@ -91,7 +94,10 @@ const Self = class ColorPicker extends ColorElement {
91
94
  slider.channel = channel;
92
95
  }
93
96
  else {
94
- this._el.sliders.insertAdjacentHTML("beforeend", `<channel-slider space="${ space.id }" channel="${ channel }" part="channel-slider"></channel-slider>`);
97
+ this._el.sliders.insertAdjacentHTML(
98
+ "beforeend",
99
+ `<channel-slider space="${space.id}" channel="${channel}" part="channel-slider"></channel-slider>`,
100
+ );
95
101
  }
96
102
  }
97
103
 
@@ -130,7 +136,7 @@ const Self = class ColorPicker extends ColorElement {
130
136
 
131
137
  return value + "";
132
138
  },
133
- changed ({parsedValue, source, ...change}) {
139
+ changed ({ parsedValue, source, ...change }) {
134
140
  if (!parsedValue && source !== "default") {
135
141
  // Something went wrong. We should always have a value. Falling back to the current space
136
142
  this.spaceId = this.space.id;
@@ -152,7 +158,7 @@ const Self = class ColorPicker extends ColorElement {
152
158
  return this._el.space_picker.selectedSpace;
153
159
  },
154
160
  set: true,
155
- changed ({parsedValue, ...change}) {
161
+ changed ({ parsedValue, ...change }) {
156
162
  if (parsedValue === undefined) {
157
163
  // this.spaceId changed
158
164
  if (this._el.space_picker.value !== this.spaceId) {
@@ -167,7 +173,8 @@ const Self = class ColorPicker extends ColorElement {
167
173
  return;
168
174
  }
169
175
 
170
- parsedValue = parsedValue instanceof Self.Color.Space ? parsedValue.id : parsedValue;
176
+ parsedValue =
177
+ parsedValue instanceof Self.Color.Space ? parsedValue.id : parsedValue;
171
178
  if (this.spaceId !== parsedValue) {
172
179
  this._el.space_picker.value = parsedValue;
173
180
  this.spaceId = parsedValue;
@@ -36,7 +36,6 @@ You can also give them optional names:
36
36
  "></color-scale>
37
37
  ```
38
38
 
39
-
40
39
  You can only specify your core colors, and insert steps via interpolation:
41
40
 
42
41
  ```html
@@ -58,7 +57,6 @@ You can specify the `info` attribute to show additional information about the co
58
57
 
59
58
  You can also create compact color scales, by simply setting `--details-style: compact`:
60
59
 
61
-
62
60
  ```html
63
61
  <color-scale space="oklch" info="L: oklch.l, C: oklch.c, H: oklch.h"
64
62
  style="--details-style: compact"
@@ -73,3 +71,45 @@ If you want to insert interpolated colors only in specific places, you can use e
73
71
  ```html
74
72
  <color-scale space="oklch" colors="#e3fafc, , , , , , , , , #0b7285"></color-scale>
75
73
  ``` -->
74
+
75
+ ## Reference
76
+
77
+ ### Attributes & Properties
78
+
79
+ | Attribute | Property | Property type | Default value | Description |
80
+ | --------- | -------- | ------------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------- |
81
+ | `colors` | `colors` | `{ [string]: Color }` &#124; `string` | - | Object or comma-separated string defining the colors and their optional names. |
82
+ | `space` | `space` | `ColorSpace` &#124; `string` | `oklch` | The color space to use for interpolation. |
83
+ | `steps` | `steps` | `number` | `0` | Number of interpolated steps to insert between each pair of colors. |
84
+ | `info` | `info` | `string` | - | Comma-separated list of coords of the colors to be shown. Passed to generated [`<color-swatch>`](../color-swatch/) elements. |
85
+
86
+ ### Getters
87
+
88
+ These properties are read-only.
89
+
90
+ | Property | Type | Description |
91
+ | ---------------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
92
+ | `computedColors` | `Array<{name: string, color: Color}>` &#124; `null` | The array of color objects after processing interpolation and steps. Returns `null` if `this.colors` is not defined. |
93
+
94
+ ### CSS variables
95
+
96
+ The styling of `<color-scale>` is fully customizable via CSS variables provided by the [`<color-swatch>`](../color-swatch/#css-variables) elements it generates.
97
+
98
+ | Name | Type | Description |
99
+ | ----------------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------- |
100
+ | `--details-style` | `compact` &#124; `normal` (default) | Controls how color information is displayed. Inherited by child [`<color-swatch>`](../color-swatch/) elements. |
101
+
102
+ ### Parts
103
+
104
+ | Name | Description |
105
+ | -------------- | --------------------------------------------------------------------------------------------------- |
106
+ | `color-swatch` | Each individual [`<color-swatch>`](../color-swatch/) element generated for the colors in the scale. |
107
+
108
+ The component also exports parts from its child `<color-swatch>` elements: `swatch`, `info`, `gamut`, and `swatch-label` (exported as `label`). See the [`<color-swatch>` parts table](../color-swatch/#parts) for details.
109
+
110
+ ### Events
111
+
112
+ | Name | Description |
113
+ | -------------- | ------------------------------------------------------------------------------------------------------------------ |
114
+ | `colorschange` | Fired when the computed colors change for any reason, and once during initialization. |
115
+ | `colorchange` | Fired when any individual color swatch changes (bubbled from child [`<color-swatch>`](../color-swatch/) elements). |
@@ -1,6 +1,6 @@
1
1
  :host {
2
2
  display: grid;
3
- gap: .3em;
3
+ gap: 0.3em;
4
4
  grid-auto-flow: row;
5
5
  grid-template-rows: auto auto;
6
6
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
@@ -21,19 +21,19 @@ const Self = class ColorScale extends ColorElement {
21
21
 
22
22
  connectedCallback () {
23
23
  super.connectedCallback?.();
24
- this._el.swatches.addEventListener("colorchange", this, {capture: true});
24
+ this._el.swatches.addEventListener("colorchange", this, { capture: true });
25
25
  }
26
26
 
27
27
  disconnectedCallback () {
28
28
  this.#swatches = [];
29
- this._el.swatches.removeEventListener("colorchange", this, {capture: true});
29
+ this._el.swatches.removeEventListener("colorchange", this, { capture: true });
30
30
  }
31
31
 
32
32
  handleEvent (event) {
33
- this.dispatchEvent(new event.constructor(event.type, {...event}));
33
+ this.dispatchEvent(new event.constructor(event.type, { ...event }));
34
34
  }
35
35
 
36
- propChangedCallback ({name, prop, detail: change}) {
36
+ propChangedCallback ({ name, prop, detail: change }) {
37
37
  if (name === "computedColors") {
38
38
  // Re-render swatches
39
39
  this.render();
@@ -53,8 +53,8 @@ const Self = class ColorScale extends ColorElement {
53
53
 
54
54
  let i = 0;
55
55
  let newSwatches = [];
56
- for (let {name, color} of colors) {
57
- let swatch = this.#swatches[i] = this._el.swatches.children[i];
56
+ for (let { name, color } of colors) {
57
+ let swatch = (this.#swatches[i] = this._el.swatches.children[i]);
58
58
 
59
59
  if (!swatch) {
60
60
  this.#swatches[i] = swatch = document.createElement("color-swatch");
@@ -118,7 +118,7 @@ const Self = class ColorScale extends ColorElement {
118
118
  return null;
119
119
  }
120
120
 
121
- let colors = Object.entries(this.colors).map(([name, color]) => ({name, color}));
121
+ let colors = Object.entries(this.colors).map(([name, color]) => ({ name, color }));
122
122
 
123
123
  if (this.steps > 0) {
124
124
  // Insert intermediate steps
@@ -127,11 +127,14 @@ const Self = class ColorScale extends ColorElement {
127
127
  for (let i = 1; i < colors.length; i++) {
128
128
  let start = colors[i - 1];
129
129
  let end = colors[i];
130
- let steps = ColorScale.Color.steps(start.color, end.color, { space: this.space, steps: this.steps + 2 });
130
+ let steps = ColorScale.Color.steps(start.color, end.color, {
131
+ space: this.space,
132
+ steps: this.steps + 2,
133
+ });
131
134
 
132
135
  steps.shift();
133
136
  steps.pop();
134
- steps = steps.map(color => ({name: color + "", color}));
137
+ steps = steps.map(color => ({ name: color + "", color }));
135
138
 
136
139
  tessellated.push(start, ...steps);
137
140
 
@@ -118,10 +118,24 @@ You can style it to look quite different:
118
118
  ### CSS-only usage
119
119
 
120
120
  If you just want the styling of `<color-slider>` and not any of the API (or are fine dealing with the lower level details on your own),
121
- you *can* just use the CSS file:
121
+ you *can* just use the CSS file.
122
+
123
+ If using a local-first dependency manager (e.g. [Nudeps](https://nudeps.dev)), you can import the CSS file using a plain local URL:
124
+
125
+ ```css
126
+ @import "/client_modules/color-elements/color-slider.css";
127
+ ```
128
+
129
+ Or with a bundler that supports CSS imports:
130
+
131
+ ```css
132
+ @import "color-elements/color-slider.css";
133
+ ```
134
+
135
+ Otherwise, use a CDN:
122
136
 
123
137
  ```css
124
- @import url("https://elements.colorjs.io/src/color-slider/color-slider.css");
138
+ @import url("https://esm.sh/color-elements/color-slider.css");
125
139
  ```
126
140
 
127
141
  This is perfect for when the gradient is more of a visual aid than a functional part of your UI,
@@ -217,4 +231,4 @@ These properties are read-only.
217
231
 
218
232
  ## Planned features
219
233
 
220
- - Discrete scales & steps
234
+ - Discrete scales & steps
@@ -6,37 +6,47 @@
6
6
  .color-slider,
7
7
  .slider-tooltip {
8
8
  --transparency-cell-size: 1.5em;
9
- --_transparency-cell-size: var(--transparency-cell-size, .5em);
9
+ --_transparency-cell-size: var(--transparency-cell-size, 0.5em);
10
10
  --_transparency-background: var(--transparency-background, transparent);
11
11
  --_transparency-darkness: var(--transparency-darkness, 5%);
12
- --_transparency-grid: var(--transparency-grid,
13
- repeating-conic-gradient(transparent 0 25%, rgb(0 0 0 / var(--_transparency-darkness)) 0 50%)
14
- 0 0 / calc(2 * var(--_transparency-cell-size)) calc(2 * var(--_transparency-cell-size))
15
- content-box border-box var(--_transparency-background)
12
+ --_transparency-grid: var(
13
+ --transparency-grid,
14
+ repeating-conic-gradient(
15
+ transparent 0 25%,
16
+ rgb(0 0 0 / var(--_transparency-darkness)) 0 50%
17
+ )
18
+ 0 0 / calc(2 * var(--_transparency-cell-size)) calc(2 * var(--_transparency-cell-size))
19
+ content-box border-box var(--_transparency-background)
16
20
  );
17
21
 
18
22
  --_slider-color-stops: var(--slider-color-stops, transparent 0% 100%);
19
- --_slider-gradient: var(--slider-gradient, linear-gradient(to right var(--in-space, ), var(--_slider-color-stops)));
23
+ --_slider-gradient: var(
24
+ --slider-gradient,
25
+ linear-gradient(to right var(--in-space,), var(--_slider-color-stops))
26
+ );
20
27
  --_slider-height: var(--slider-height, 2.2em);
21
28
 
22
29
  --_slider-thumb-width: var(--slider-thumb-width, 1em);
23
30
  --_slider-thumb-height-offset: var(--slider-thumb-height-offset, 2px);
24
- --_slider-thumb-height: var(--slider-thumb-height, calc(var(--_slider-height) + var(--_slider-thumb-height-offset)));
25
- --_slider-thumb-radius: var(--slider-thumb-radius, .16em);
31
+ --_slider-thumb-height: var(
32
+ --slider-thumb-height,
33
+ calc(var(--_slider-height) + var(--_slider-thumb-height-offset))
34
+ );
35
+ --_slider-thumb-radius: var(--slider-thumb-radius, 0.16em);
26
36
  --_slider-thumb-background: var(--slider-thumb-background, var(--color, transparent));
27
- --_slider-thumb-border: var(--slider-thumb-border, 1px solid oklab(.2 0 0));
28
- --_slider-thumb-border-active: var(--slider-thumb-border-active, 2px solid oklab(.4 0 0));
37
+ --_slider-thumb-border: var(--slider-thumb-border, 1px solid oklab(0.2 0 0));
38
+ --_slider-thumb-border-active: var(--slider-thumb-border-active, 2px solid oklab(0.4 0 0));
29
39
  --_slider-thumb-scale-active: var(--slider-thumb-scale-active, 1.1);
30
40
 
31
41
  --_tooltip-background: var(--tooltip-background, hsl(0 0 0 / 80%));
32
- --_tooltip-border-radius: var(--tooltip-border-radius, .3em);
33
- --_tooltip-pointer-height: var(--tooltip-pointer-height, .3em);
42
+ --_tooltip-border-radius: var(--tooltip-border-radius, 0.3em);
43
+ --_tooltip-pointer-height: var(--tooltip-pointer-height, 0.3em);
34
44
  --_tooltip-pointer-angle: var(--tooltip-pointer-angle, 90deg);
35
45
  }
36
46
 
37
47
  .color-slider {
38
48
  @supports (background: linear-gradient(in oklab, red, tan)) {
39
- --in-space: in var(--color-space, oklab) var(--hue-interpolation, );
49
+ --in-space: in var(--color-space, oklab) var(--hue-interpolation,);
40
50
  }
41
51
 
42
52
  display: block;
@@ -48,7 +58,7 @@
48
58
  background-origin: border-box;
49
59
  background-clip: border-box;
50
60
  height: var(--_slider-height);
51
- border-radius: .3em;
61
+ border-radius: 0.3em;
52
62
  border: 1px solid rgb(0 0 0 / 8%);
53
63
 
54
64
  &::-webkit-slider-thumb {
@@ -60,7 +70,9 @@
60
70
  border: var(--_slider-thumb-border);
61
71
  box-shadow: 0 0 0 1px white;
62
72
  background: var(--color, transparent);
63
- transition: 200ms, 0s background;
73
+ transition:
74
+ 200ms,
75
+ 0s background;
64
76
  }
65
77
 
66
78
  &::-moz-range-thumb {
@@ -71,13 +83,15 @@
71
83
  border: var(--_slider-thumb-border);
72
84
  box-shadow: 0 0 0 1px white;
73
85
  background: var(--color, transparent);
74
- transition: 200ms, 0s background;
86
+ transition:
87
+ 200ms,
88
+ 0s background;
75
89
  }
76
90
 
77
- &::-moz-range-thumb:active {
78
- border: var(--_slider-thumb-border-active);
79
- scale: var(--_slider-thumb-scale-active);
80
- }
91
+ &::-moz-range-thumb:active {
92
+ border: var(--_slider-thumb-border-active);
93
+ scale: var(--_slider-thumb-scale-active);
94
+ }
81
95
 
82
96
  &::-moz-range-track {
83
97
  background: none;
@@ -93,22 +107,29 @@
93
107
 
94
108
  .slider-tooltip {
95
109
  position: absolute;
96
- left: clamp(-20%,
97
- 100% * var(--progress)
98
- - (var(--progress) - 0.5) * var(--_slider-thumb-width) / 2 /* center on slider thumb */
99
- , 100%);
110
+ left: clamp(
111
+ -20%,
112
+ 100% * var(--progress) - (var(--progress) - 0.5) * var(--_slider-thumb-width) / 2
113
+ /* center on slider thumb */,
114
+ 100%
115
+ );
100
116
  bottom: calc(100% + 3px);
101
117
  translate: -50%;
102
118
  transform-origin: bottom;
103
119
  display: flex;
104
- padding-block: .3em;
105
- padding-inline: .4em;
120
+ padding-block: 0.3em;
121
+ padding-inline: 0.4em;
106
122
  border: var(--_tooltip-pointer-height) solid transparent;
107
123
  border-radius: calc(var(--_tooltip-border-radius) + var(--_tooltip-pointer-height));
108
124
  text-align: center;
109
125
  color: white;
110
126
  background:
111
- conic-gradient(from calc(-1 * var(--_tooltip-pointer-angle) / 2) at bottom, var(--_tooltip-background) var(--_tooltip-pointer-angle), transparent 0) border-box bottom / 100% var(--_tooltip-pointer-height) no-repeat,
127
+ conic-gradient(
128
+ from calc(-1 * var(--_tooltip-pointer-angle) / 2) at bottom,
129
+ var(--_tooltip-background) var(--_tooltip-pointer-angle),
130
+ transparent 0
131
+ )
132
+ border-box bottom / 100% var(--_tooltip-pointer-height) no-repeat,
112
133
  var(--_tooltip-background) padding-box;
113
134
  color-scheme: dark;
114
135
  transition:
@@ -116,7 +137,7 @@
116
137
  opacity 200ms,
117
138
  scale 200ms,
118
139
  width 100ms,
119
- left 200ms cubic-bezier(.17,.67,.49,1.48);
140
+ left 200ms cubic-bezier(0.17, 0.67, 0.49, 1.48);
120
141
 
121
142
  &::after {
122
143
  content: var(--tooltip-suffix);
@@ -125,14 +146,14 @@
125
146
  input {
126
147
  all: unset;
127
148
 
128
- &:where([type=number]) {
149
+ &:where([type="number"]) {
129
150
  --content-width: calc(var(--value-length) * 1ch);
130
151
  width: calc(var(--content-width, 2ch) + 1.2em);
131
152
  min-width: calc(2ch + 1.2em);
132
153
  box-sizing: content-box;
133
154
 
134
155
  &::-webkit-textfield-decoration-container {
135
- gap: .2em;
156
+ gap: 0.2em;
136
157
  }
137
158
 
138
159
  @container style(--tooltip-suffix) {
@@ -154,14 +175,14 @@
154
175
 
155
176
  /* Prevent input from moving all over the place as we type */
156
177
  &:focus {
157
- transition-delay: .5s;
178
+ transition-delay: 0.5s;
158
179
  }
159
180
  }
160
181
 
161
182
  &:not(:is(:focus-within, :hover) > *, .color-slider:is(:focus, :hover) + *, :focus, :hover) {
162
183
  visibility: hidden;
163
184
  opacity: 0;
164
- scale: .5;
185
+ scale: 0.5;
165
186
  }
166
187
  }
167
188
 
@@ -171,4 +192,4 @@
171
192
 
172
193
  :host([tooltip="progress"]) .slider-tooltip {
173
194
  --tooltip-suffix: "%";
174
- }
195
+ }
@@ -49,11 +49,11 @@ const Self = class ColorSlider extends ColorElement {
49
49
  this.value = event.target.value;
50
50
  }
51
51
 
52
- this.dispatchEvent(new event.constructor(event.type, {...event}));
52
+ this.dispatchEvent(new event.constructor(event.type, { ...event }));
53
53
  }
54
54
  }
55
55
 
56
- propChangedCallback ({name, prop, detail: change}) {
56
+ propChangedCallback ({ name, prop, detail: change }) {
57
57
  if (["min", "max", "step", "value", "defaultValue"].includes(name)) {
58
58
  prop.applyChange(this._el.slider, change);
59
59
 
@@ -64,10 +64,10 @@ const Self = class ColorSlider extends ColorElement {
64
64
  }
65
65
  else {
66
66
  // Spinner values when tooltip is "progress"
67
- value = ({ min: 1, max: 100, step: 1 })[name];
67
+ value = { min: 1, max: 100, step: 1 }[name];
68
68
  }
69
69
  }
70
- prop.applyChange(this._el.spinner, {...change, value: +(+value).toPrecision(4)});
70
+ prop.applyChange(this._el.spinner, { ...change, value: +(+value).toPrecision(4) });
71
71
  }
72
72
 
73
73
  if (name === "stops") {
@@ -106,7 +106,7 @@ const Self = class ColorSlider extends ColorElement {
106
106
  else if (name === "space" && supports.inSpace) {
107
107
  let space = this.space;
108
108
  let spaceId = space.id;
109
- let supported = CSS.supports("background", `linear-gradient(in ${ spaceId }, red, tan)`);
109
+ let supported = CSS.supports("background", `linear-gradient(in ${spaceId}, red, tan)`);
110
110
 
111
111
  if (!supported) {
112
112
  spaceId = this.space.isPolar ? "oklch" : "oklab";
@@ -135,7 +135,9 @@ const Self = class ColorSlider extends ColorElement {
135
135
  let values = this;
136
136
  if (change.value === "progress") {
137
137
  values = {
138
- min: 1, max: 100, step: 1,
138
+ min: 1,
139
+ max: 100,
140
+ step: 1,
139
141
  value: +(this.progress * 100).toPrecision(4),
140
142
  };
141
143
  }
@@ -307,7 +309,7 @@ const Self = class ColorSlider extends ColorElement {
307
309
  },
308
310
  };
309
311
 
310
- static formAssociated = {
312
+ static formBehavior = {
311
313
  like: el => el._el.slider,
312
314
  role: "slider",
313
315
  valueProp: "value",
@@ -1,24 +1,28 @@
1
1
  :host {
2
- --_transparency-cell-size: var(--transparency-cell-size, .5em);
2
+ --_transparency-cell-size: var(--transparency-cell-size, 0.5em);
3
3
  --_transparency-background: var(--transparency-background, transparent);
4
4
  --_transparency-darkness: var(--transparency-darkness, 5%);
5
- --_transparency-grid: var(--transparency-grid,
6
- repeating-conic-gradient(transparent 0 25%, rgb(0 0 0 / var(--_transparency-darkness)) 0 50%)
7
- 0 0 / calc(2 * var(--_transparency-cell-size)) calc(2 * var(--_transparency-cell-size))
8
- content-box border-box var(--_transparency-background)
5
+ --_transparency-grid: var(
6
+ --transparency-grid,
7
+ repeating-conic-gradient(
8
+ transparent 0 25%,
9
+ rgb(0 0 0 / var(--_transparency-darkness)) 0 50%
10
+ )
11
+ 0 0 / calc(2 * var(--_transparency-cell-size)) calc(2 * var(--_transparency-cell-size))
12
+ content-box border-box var(--_transparency-background)
9
13
  );
10
14
 
11
15
  position: relative;
12
16
  display: inline-flex;
13
- gap: .3em;
17
+ gap: 0.3em;
14
18
  width: var(--color-swatch-width, fit-content);
15
- margin: .3em;
16
- border-radius: var(--color-swatch-radius, .2rem);
19
+ margin: 0.3em;
20
+ border-radius: var(--color-swatch-radius, 0.2rem);
17
21
  }
18
22
 
19
23
  :host([size="large"]) {
20
24
  flex-flow: column;
21
- inline-size: 11em;
25
+ inline-size: min(11em, 100%);
22
26
  min-block-size: 6em;
23
27
  contain: inline-size;
24
28
  container-name: color-swatch;
@@ -37,7 +41,7 @@ slot {
37
41
  position: absolute;
38
42
  top: 0;
39
43
  right: 0;
40
- margin: .5rem;
44
+ margin: 0.5rem;
41
45
  }
42
46
 
43
47
  &:not(:host([size="large"]) *) {
@@ -46,7 +50,7 @@ slot {
46
50
  font-size: 50%;
47
51
  top: 0;
48
52
  right: 0;
49
- margin: .2rem;
53
+ margin: 0.2rem;
50
54
  }
51
55
 
52
56
  &:is(.static *) {
@@ -54,8 +58,6 @@ slot {
54
58
  }
55
59
  }
56
60
 
57
-
58
-
59
61
  &[style*="--gamut-level: 0"] {
60
62
  display: none;
61
63
  }
@@ -65,12 +67,12 @@ slot {
65
67
  margin: 0;
66
68
  display: inline-flex;
67
69
  display: none;
68
- gap: .5em;
70
+ gap: 0.5em;
69
71
 
70
72
  &:is(:host([size="large"]) &) {
71
73
  display: grid;
72
74
  grid-template-columns: max-content auto;
73
- gap: .1em .2em;
75
+ gap: 0.1em 0.2em;
74
76
  font-size: max(9px, 80%);
75
77
  justify-content: start;
76
78
 
@@ -81,7 +83,7 @@ slot {
81
83
 
82
84
  .coord {
83
85
  display: flex;
84
- gap: .2em;
86
+ gap: 0.2em;
85
87
 
86
88
  dd {
87
89
  margin: 0;
@@ -114,8 +116,11 @@ slot {
114
116
  }
115
117
 
116
118
  @container style(--details-style: compact) {
117
- --_border-color: var(--border-color, color-mix(in oklab, buttonborder 20%, oklab(none none none / 0%)));
118
- --_pointer-height: var(--pointer-height, .5em);
119
+ --_border-color: var(
120
+ --border-color,
121
+ color-mix(in oklab, buttonborder 20%, oklab(none none none / 0%))
122
+ );
123
+ --_pointer-height: var(--pointer-height, 0.5em);
119
124
  --_transition-duration: var(--transition-duration, 400ms);
120
125
  --_details-popup-width: var(--details-popup-width, max-content);
121
126
 
@@ -124,13 +129,13 @@ slot {
124
129
  z-index: 2;
125
130
  translate: -50% 0;
126
131
  bottom: 100%;
127
- margin-bottom: calc(var(--_pointer-height) * .8);
132
+ margin-bottom: calc(var(--_pointer-height) * 0.8);
128
133
  width: var(--_details-popup-width);
129
134
  background: canvas;
130
135
  border: 1px solid var(--_border-color);
131
- padding: .6em 1em;
132
- border-radius: .2rem;
133
- box-shadow: 0 .05em 1em -.7em black;
136
+ padding: 0.6em 1em;
137
+ border-radius: 0.2rem;
138
+ box-shadow: 0 0.05em 1em -0.7em black;
134
139
  transition: var(--_transition-duration) allow-discrete;
135
140
  transition-property: all, display;
136
141
  transition-delay: 0s, var(--_transition-duration);
@@ -165,8 +170,14 @@ slot {
165
170
  clip-path: polygon(0 0, 0 100%, 100% 100%);
166
171
  }
167
172
 
168
- &:not(:is(:host(:hover), :host(:focus-within), :host(:active), :host(:target), :host([open])) *),
169
- &:is(:host([open=false]) *) {
173
+ /*
174
+ More straightforward selector:
175
+ &:not(:is(:host(:hover), :host(:focus-within), :host(:active), :host(:target), :host([open])) *)
176
+ doesn't work in Safari!
177
+ See https://bugs.webkit.org/show_bug.cgi?id=296577
178
+ */
179
+ &:is(:host(:not(:hover):not(:focus-within):not(:active):not(:target):not([open])) *),
180
+ &:is(:host([open="false"]) *) {
170
181
  display: none;
171
182
  opacity: 0;
172
183
  scale: 0;
@@ -176,7 +187,7 @@ slot {
176
187
 
177
188
  [part="color"] {
178
189
  display: flex;
179
- gap: .2em;
190
+ gap: 0.2em;
180
191
  }
181
192
 
182
193
  [part="label"] {
@@ -199,25 +210,23 @@ slot:not([name]) {
199
210
  }
200
211
 
201
212
  [part="color-wrapper"],
202
- slot[name=swatch]::slotted(*),
213
+ slot[name="swatch"]::slotted(*),
203
214
  #swatch {
204
215
  border-radius: inherit;
205
216
  }
206
217
 
207
- slot[name=swatch]::slotted(*),
218
+ slot[name="swatch"]::slotted(*),
208
219
  #swatch {
209
220
  flex: 1;
210
221
  display: flex;
211
222
  flex-flow: column;
212
223
  align-items: center;
213
224
  justify-content: center;
214
- padding: .5em;
225
+ padding: 0.5em;
215
226
  display: flex;
216
227
  flex-flow: column;
217
228
  flex: 1;
218
- background:
219
- linear-gradient(var(--color) 0 100%),
220
- var(--_transparency-grid);
229
+ background: linear-gradient(var(--color) 0 100%), var(--_transparency-grid);
221
230
 
222
231
  &:is(:host([size="large"]) *) {
223
232
  min-block-size: 3em;
@@ -232,7 +241,7 @@ slot[name=swatch]::slotted(*),
232
241
  }
233
242
  }
234
243
 
235
- slot[name=swatch-content] {
244
+ slot[name="swatch-content"] {
236
245
  /* See https://lea.verou.me/blog/2024/contrast-color/ */
237
246
  --l: clamp(0, (var(--l-threshold, 0.7) / l - 1) * infinity, 1);
238
247
  color: oklch(from var(--color) var(--l) 0 h);