color-elements 0.0.3 → 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 (45) 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/partials/_nav-links.njk +1 -0
  11. package/_includes/plain.njk +5 -0
  12. package/_redirects +1 -1
  13. package/assets/css/style.css +4 -4
  14. package/debug.html +38 -439
  15. package/package.json +24 -8
  16. package/src/channel-picker/channel-picker.css +4 -4
  17. package/src/channel-picker/channel-picker.js +16 -12
  18. package/src/channel-slider/channel-slider.css +14 -7
  19. package/src/channel-slider/channel-slider.js +14 -6
  20. package/src/color-chart/README.md +36 -5
  21. package/src/color-chart/color-chart-global.css +19 -14
  22. package/src/color-chart/color-chart-shadow.css +123 -0
  23. package/src/color-chart/color-chart.css +2 -112
  24. package/src/color-chart/color-chart.js +309 -107
  25. package/src/color-inline/color-inline.css +21 -16
  26. package/src/color-inline/color-inline.js +3 -4
  27. package/src/color-inline/style.css +1 -1
  28. package/src/color-picker/color-picker.css +3 -3
  29. package/src/color-picker/color-picker.js +15 -8
  30. package/src/color-scale/README.md +42 -2
  31. package/src/color-scale/color-scale.css +8 -13
  32. package/src/color-scale/color-scale.js +14 -11
  33. package/src/color-slider/README.md +17 -3
  34. package/src/color-slider/color-slider.css +54 -33
  35. package/src/color-slider/color-slider.js +10 -8
  36. package/src/color-swatch/color-swatch.css +52 -34
  37. package/src/color-swatch/color-swatch.js +20 -10
  38. package/src/common/color-element.js +63 -51
  39. package/src/common/dom.js +4 -2
  40. package/src/common/util.js +66 -1
  41. package/src/gamut-badge/gamut-badge.css +33 -13
  42. package/src/gamut-badge/gamut-badge.js +10 -8
  43. package/src/space-picker/space-picker.css +3 -3
  44. package/src/space-picker/space-picker.js +29 -11
  45. package/src/src.json +1 -1
@@ -3,7 +3,7 @@
3
3
 
4
4
  display: grid;
5
5
  grid-template-columns: 1fr auto;
6
- gap: .3em;
6
+ gap: 0.3em;
7
7
  align-items: center;
8
8
 
9
9
  em {
@@ -15,8 +15,15 @@
15
15
  opacity: 0;
16
16
  }
17
17
 
18
- input[type=number] {
19
- --_border-color: var(--border-color, color-mix(in oklab, currentcolor calc(var(--_current-color-percent, 30) * 1%), oklab(none none none / 0%)));
18
+ input[type="number"] {
19
+ --_border-color: var(
20
+ --border-color,
21
+ color-mix(
22
+ in oklab,
23
+ currentcolor calc(var(--_current-color-percent, 30) * 1%),
24
+ oklab(none none none / 0%)
25
+ )
26
+ );
20
27
 
21
28
  all: unset;
22
29
 
@@ -24,8 +31,8 @@
24
31
  width: calc(var(--content-width, 2ch) + 1.2em);
25
32
  min-width: calc(2ch + 1.2em);
26
33
  box-sizing: content-box;
27
- padding: .1em .2em;
28
- border-radius: .2em;
34
+ padding: 0.1em 0.2em;
35
+ border-radius: 0.2em;
29
36
  border: 1px solid var(--_border-color);
30
37
  text-align: center;
31
38
  font-size: 90%;
@@ -33,7 +40,7 @@
33
40
  transition-property: opacity, border-color;
34
41
 
35
42
  &::-webkit-textfield-decoration-container {
36
- gap: .2em;
43
+ gap: 0.2em;
37
44
  }
38
45
 
39
46
  &:not(:hover, :focus) {
@@ -44,7 +51,7 @@
44
51
 
45
52
  &::-webkit-inner-spin-button {
46
53
  /* Fade out the spin buttons in Chrome and Safari */
47
- opacity: .35;
54
+ opacity: 0.35;
48
55
  filter: contrast(2);
49
56
  }
50
57
  }
@@ -6,7 +6,7 @@ import { getStep } from "../common/util.js";
6
6
  const Self = class ChannelSlider extends ColorElement {
7
7
  static tagName = "channel-slider";
8
8
  static url = import.meta.url;
9
- static shadowStyle = true;
9
+ static styles = "./channel-slider.css";
10
10
  static shadowTemplate = `
11
11
  <label class="color-slider-label" part="label">
12
12
  <slot>
@@ -86,7 +86,7 @@ const Self = class ChannelSlider extends ColorElement {
86
86
  return this._el.slider.progressAt(p);
87
87
  }
88
88
 
89
- propChangedCallback ({name, prop, detail: change}) {
89
+ propChangedCallback ({ name, prop, detail: change }) {
90
90
  if (["space", "min", "max", "step", "value", "defaultValue"].includes(name)) {
91
91
  prop.applyChange(this._el.slider, change);
92
92
 
@@ -104,11 +104,17 @@ const Self = class ChannelSlider extends ColorElement {
104
104
  }
105
105
  }
106
106
 
107
- if (name === "defaultColor" || name === "space" || name === "channel" || name === "min" || name === "max") {
107
+ if (
108
+ name === "defaultColor" ||
109
+ name === "space" ||
110
+ name === "channel" ||
111
+ name === "min" ||
112
+ name === "max"
113
+ ) {
108
114
  this._el.slider.stops = this.stops;
109
115
 
110
116
  if (name === "space" || name === "channel" || name === "min" || name === "max") {
111
- this._el.channel_info.innerHTML = `${ this.channelName } <em>(${ this.min }&thinsp;&ndash;&thinsp;${ this.max })</em>`;
117
+ this._el.channel_info.innerHTML = `${this.channelName} <em>(${this.min}&thinsp;&ndash;&thinsp;${this.max})</em>`;
112
118
  }
113
119
  }
114
120
  }
@@ -164,7 +170,9 @@ const Self = class ChannelSlider extends ColorElement {
164
170
 
165
171
  if (!channelSpec && this.space) {
166
172
  channelSpec = Object.values(this.space.coords)[0];
167
- console.warn(`Unknown channel ${ this.channel } in space ${ this.space }. Using first channel (${ channelSpec.name }) instead.`);
173
+ console.warn(
174
+ `Unknown channel ${this.channel} in space ${this.space}. Using first channel (${channelSpec.name}) instead.`,
175
+ );
168
176
  }
169
177
 
170
178
  return channelSpec;
@@ -274,7 +282,7 @@ const Self = class ChannelSlider extends ColorElement {
274
282
  },
275
283
  };
276
284
 
277
- static formAssociated = {
285
+ static formBehavior = {
278
286
  like: el => el._el.slider,
279
287
  role: "slider",
280
288
  valueProp: "value",
@@ -5,6 +5,7 @@ Display lists of colors as a scatterplot or line chart.
5
5
  ## Features
6
6
 
7
7
  - Plot any coordinate, in any color space
8
+ - Customize both X and Y axes independently
8
9
 
9
10
  ## Examples
10
11
 
@@ -18,6 +19,10 @@ Plotting a single color scale:
18
19
  </color-chart>
19
20
  ```
20
21
 
22
+ _(Colors courtesy of Tailwind)_
23
+
24
+ ### Default X coordinate
25
+
21
26
  By default, the other coordinate would be the index of the color in the list, but you can specify it explicitly:
22
27
 
23
28
  ```html
@@ -26,7 +31,7 @@ By default, the other coordinate would be the index of the color in the list, bu
26
31
  </color-chart>
27
32
  ```
28
33
 
29
- You can also specify a whole label, and if it contains a number, the number will become the X coordinate:
34
+ You can also specify a whole label, and if it contains a number, the number will become the default X coordinate:
30
35
 
31
36
  ```html
32
37
  <color-chart y="oklch.c">
@@ -36,11 +41,33 @@ You can also specify a whole label, and if it contains a number, the number will
36
41
  </color-chart>
37
42
  ```
38
43
 
39
- _(Colors courtesy of Tailwind)_
44
+ ### Explicit X coordinate
45
+
46
+ You can also specify the X coordinate explicitly.
47
+
48
+ ```html
49
+ <color-chart y="oklch.c" x="oklch.l">
50
+ <color-scale colors="#e3f2fd, #bbdefb, #90caf9, #64b5f6, #42a5f5, #2196f3, #1e88e5, #1976d2, #1565c0, #0d47a1"></color-scale>
51
+ </color-chart>
52
+ ```
53
+
54
+ ### Custom X and Y axis ranges
55
+
56
+ You can customize the ranges of both X and Y axes independently:
57
+
58
+ ```html
59
+ <color-chart y="oklch.c" ymin="0" ymax="0.2" x="oklch.l" xmin="0.3" xmax=".9">
60
+ <color-scale colors="#e3f2fd, #bbdefb, #90caf9, #64b5f6, #42a5f5, #2196f3, #1e88e5, #1976d2, #1565c0, #0d47a1"></color-scale>
61
+ </color-chart>
62
+ ```
63
+
64
+ This can be useful when plotting data that changes dynamically, so that the axes are always the same size.
40
65
 
41
66
  ### Plotting hues { #hues}
42
67
 
43
- Hues will be shifted as needed to produce a better result:
68
+ Since hues are angles, there are often multiple ways they can be plotted.
69
+ E.g. A hue of `10` could also be plotted as `-350` or `370`.
70
+ `<color-chart>` will automatically shift the hue based on the other hues in the same scale to produce a nicer result.
44
71
 
45
72
  ```html
46
73
  <color-chart y="hsl.h">
@@ -73,7 +100,7 @@ Reactively changing the Y coordinate:
73
100
 
74
101
  ```html
75
102
  <button onclick="this.nextElementSibling.y = 'hwb.w'">
76
- Switch to HWB Whiteness
103
+ Switch to "HWB Whiteness"
77
104
  </button>
78
105
  <color-chart y="oklch.l">
79
106
  <color-scale colors="Red 50: #fef2f2, Red 100: #fee2e2, Red 200: #fecaca, Red 300: #fca5a5, Red 400: #f87171, Red 500: #ef4444, Red 600: #dc2626, Red 700: #b91c1c, Red 800: #991b1b, Red 900: #7f1d1d, Red 950: #450a0a"></color-scale>
@@ -104,8 +131,12 @@ Reactively setting/changing the colors:
104
131
  | Attribute | Property | Property type | Default value | Description |
105
132
  |-----------|----------|---------------|---------------|-------------|
106
133
  | `x` | `x` | `string` | `null` | The coord to plot on the X axis, if any |
134
+ | `xmin` | `xMin` | `number` or `"coord"` or `"auto"` | - | The minimum value of the X axis. Defaults to the minimum value of the X coord. |
135
+ | `xmax` | `xMax` | `number` or `"coord"` or `"auto"` | - | The maximum value of the X axis. Defaults to the maximum value of the X coord. |
107
136
  | `y` | `y` | `string` | `"oklch.l"` | The coord to plot on the Y axis, if any |
108
- | `info` | `info` | `string` | - | Comma-separated list of coords of the color point to be shown. |
137
+ | `ymin` | `yMin` | `number` or `"coord"` or `"auto"` | - | The minimum value of the Y axis. Defaults to the minimum value of the Y coord. |
138
+ | `ymax` | `yMax` | `number` or `"coord"` or `"auto"` | - | The maximum value of the Y axis. Defaults to the maximum value of the Y coord. |
139
+ | `info` | `info` | `string` | - | Comma-separated list of coords of the color point to be shown in the tooltip. |
109
140
 
110
141
  ### Events
111
142
 
@@ -1,5 +1,5 @@
1
1
  @property --chart-width {
2
- syntax: '<length-percentage>';
2
+ syntax: "<length-percentage>";
3
3
  initial-value: 100%;
4
4
  inherits: true;
5
5
  }
@@ -22,30 +22,34 @@
22
22
  inherits: true;
23
23
  }
24
24
 
25
+ color-chart {
26
+ --_point-size: var(--point-size, 0.6em);
27
+ --_line-width: var(--line-width, 0.2em);
28
+ --color-swatch-width: var(--color-swatch-width, var(--_point-size));
29
+ --color-swatch-radius: var(--color-swatch-radius, 50%);
30
+ }
31
+
25
32
  color-chart > color-scale {
26
33
  --extent-x: calc(var(--max-x) - var(--min-x));
27
34
  --extent-y: calc(var(--max-y) - var(--min-y));
28
35
 
29
36
  &::part(color-swatch) {
30
- --_point-size: var(--point-size, .6em);
31
- --_line-width: var(--line-width, .2em);
32
-
33
37
  position: absolute;
34
- top: calc((1 - (var(--y) - var(--min-y)) / (var(--max-y) - var(--min-y))) * 100cqh);
35
- left: calc( (var(--x) - var(--min-x)) / (var(--max-x) - var(--min-x)) * 100%);
38
+ top: calc((1 - (var(--y) - var(--min-y)) / (var(--max-y) - var(--min-y))) * 100cqh);
39
+ left: calc((var(--x) - var(--min-x)) / (var(--max-x) - var(--min-x)) * 100%);
36
40
  width: var(--_point-size);
37
41
  aspect-ratio: 1;
38
42
  border-radius: 50%;
39
43
  background: yellow;
40
44
  min-block-size: 0;
41
45
  translate: -50% -50%;
42
- transition: 300ms;
43
- transition-property: width;
46
+ transition: 300ms 0.01ms;
47
+ transition-property: width, opacity;
44
48
  }
45
49
 
46
50
  &::part(color-swatch):hover {
47
51
  /* Cannot use CSS transforms here because that also affects the line */
48
- --_point-size: calc(var(--point-size, .6em) * 1.5);
52
+ --_point-size: calc(var(--point-size, 0.6em) * 1.5);
49
53
  z-index: 1;
50
54
  }
51
55
 
@@ -57,8 +61,8 @@ color-chart > color-scale {
57
61
  --delta-y-abs: max(var(--delta-y), -1 * var(--delta-y));
58
62
  --delta-y-sign: calc(var(--delta-y) / var(--delta-y-abs));
59
63
 
60
- --width: calc( var(--chart-width) * var(--delta-x) / var(--extent-x));
61
- --height: calc( var(--chart-height) * var(--delta-y-abs) / var(--extent-y));
64
+ --width: calc(var(--chart-width) * var(--delta-x) / var(--extent-x));
65
+ --height: calc(var(--chart-height) * var(--delta-y-abs) / var(--extent-y));
62
66
  --angle: atan2(var(--height), var(--width));
63
67
 
64
68
  content: "";
@@ -78,11 +82,12 @@ color-chart > color-scale {
78
82
  }
79
83
  }
80
84
 
81
- &::part(info) {}
85
+ &::part(info) {
86
+ }
82
87
 
83
88
  &::part(swatch) {
84
89
  min-block-size: 0;
85
- padding: .2em;
90
+ padding: 0.2em;
86
91
  }
87
92
 
88
93
  &::part(gamut) {
@@ -92,6 +97,6 @@ color-chart > color-scale {
92
97
 
93
98
  color-chart:has(> color-scale:hover) {
94
99
  > color-scale:not(:hover) {
95
- opacity: .4;
100
+ opacity: 0.4;
96
101
  }
97
102
  }
@@ -0,0 +1,123 @@
1
+ :host {
2
+ display: grid;
3
+ grid-template-columns: auto 1fr;
4
+ grid-template-rows: auto 1fr auto;
5
+ height: clamp(0em, 20em, 100vh);
6
+ contain: size;
7
+ container-name: chart;
8
+ container-type: size;
9
+ }
10
+
11
+ .axis {
12
+ display: flex;
13
+
14
+ .ticks {
15
+ flex: 1;
16
+ display: grid;
17
+
18
+ > * {
19
+ font-size: 60%;
20
+ line-height: 1;
21
+ }
22
+ }
23
+
24
+ .label {
25
+ text-align: center;
26
+ }
27
+ }
28
+
29
+ [part="color-channel"],
30
+ slot[name="color-channel"]::slotted(*) {
31
+ /* <channel-picker>, or anything acting like one, should occupy the whole row above the chart so as not to mess up with the rest of the layout */
32
+ grid-column: 1 / -1;
33
+ justify-self: start;
34
+
35
+ margin-block: 0.5em 0.7em;
36
+ font-size: 130%;
37
+ }
38
+
39
+ #x_axis {
40
+ grid-column: 2;
41
+ grid-row: 3;
42
+
43
+ display: grid;
44
+
45
+ .ticks {
46
+ grid-row: 1;
47
+ grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
48
+
49
+ > * {
50
+ padding-block-start: 0.5em;
51
+ margin-inline-end: auto;
52
+ translate: -50% 0;
53
+ }
54
+ }
55
+
56
+ .label {
57
+ grid-row: 2;
58
+ margin-block-start: .75em;
59
+ }
60
+ }
61
+
62
+ #y_axis {
63
+ grid-column: 1;
64
+ grid-row: 2;
65
+
66
+ .ticks {
67
+ align-items: end;
68
+
69
+ > * {
70
+ padding-inline-end: 0.5em;
71
+ translate: 0 0.5lh;
72
+ }
73
+ }
74
+
75
+ .label {
76
+ writing-mode: vertical-lr;
77
+ rotate: 0.5turn;
78
+ margin-right: 0.5em;
79
+ }
80
+ }
81
+
82
+ @property --chart-width {
83
+ syntax: "<length-percentage>";
84
+ initial-value: 100%;
85
+ inherits: true;
86
+ }
87
+
88
+ #chart-container {
89
+ container-name: chart;
90
+ container-type: size;
91
+ }
92
+
93
+ #chart {
94
+ overflow: hidden;
95
+
96
+ position: relative;
97
+ border: 1px solid gray;
98
+ min-height: 100%;
99
+ background:
100
+ linear-gradient(to bottom, hsl(220 10% 50% / 40%) 0 1px, transparent 0) 0 -1px / 100%
101
+ calc(100% / var(--steps-y, 10)),
102
+ linear-gradient(to right, hsl(220 10% 50% / 30%) 0 1px, transparent 0) -1px 0 /
103
+ calc(100% / var(--steps-x, 10)) 100%;
104
+
105
+ --chart-width: 100cqw;
106
+ --chart-height: 100cqh;
107
+ --extent-x: calc(var(--max-x) - var(--min-x));
108
+ --extent-y: calc(var(--max-y) - var(--min-y));
109
+ }
110
+
111
+ ::slotted(color-scale) {
112
+ --details-style: compact;
113
+
114
+ /*
115
+ We want color scales to be easy to style: one can hide them, lower their opacity, etc.
116
+ At the same time, we don't want their containers to mess up with other chart parts.
117
+ For example, we don't want color scales to get the hover styles when one moves the cursor to the top left part of the chart,
118
+ where all the color scale containers reside. So, we need to shrink them.
119
+ */
120
+ display: block;
121
+ width: 0;
122
+ height: 0;
123
+ }
@@ -1,112 +1,2 @@
1
- :host {
2
- display: grid;
3
- grid-template-columns: auto 1fr;
4
- grid-template-rows: auto 1fr auto;
5
- height: clamp(0em, 20em, 100vh);
6
- contain: size;
7
- container-name: chart;
8
- container-type: size;
9
- }
10
-
11
- .axis {
12
- display: flex;
13
-
14
- .ticks {
15
- flex: 1;
16
- display: grid;
17
-
18
- > * {
19
- font-size: 60%;
20
- line-height: 1;
21
- }
22
- }
23
-
24
- .label {
25
- text-align: center;
26
- }
27
- }
28
-
29
- [part="color-channel"],
30
- slot[name="color-channel"]::slotted(*) {
31
- /* <channel-picker>, or anything acting like one, should occupy the whole row above the chart so as not to mess up with the rest of the layout */
32
- grid-column: 1 / -1;
33
- justify-self: start;
34
-
35
- margin-block: .5em .7em;
36
- font-size: 130%;
37
- }
38
-
39
- #x_axis {
40
- grid-column: 2;
41
- grid-row: 3;
42
-
43
- .ticks {
44
- grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
45
-
46
- > * {
47
- padding-block-start: .5em;
48
- margin-inline-end: auto;
49
- translate: -50% 0;
50
- }
51
- }
52
- }
53
-
54
- #y_axis {
55
- grid-column: 1;
56
- grid-row: 2;
57
-
58
- .ticks {
59
- align-items: end;
60
-
61
- > * {
62
- padding-inline-end: .5em;
63
- translate: 0 .5lh;
64
- }
65
- }
66
-
67
- .label {
68
- writing-mode: vertical-lr;
69
- rotate: .5turn;
70
- margin-right: .5em;
71
- }
72
- }
73
-
74
- @property --chart-width {
75
- syntax: '<length-percentage>';
76
- initial-value: 100%;
77
- inherits: true;
78
- }
79
-
80
- #chart-container {
81
- container-name: chart;
82
- container-type: size;
83
- }
84
-
85
- #chart {
86
- overflow: hidden;
87
-
88
- position: relative;
89
- border: 1px solid gray;
90
- min-height: 100%;
91
- background: linear-gradient(to bottom, hsl(220 10% 50% / 40%) 0 1px, transparent 0) 0 -1px / 100% calc(100% / var(--steps-y, 10)),
92
- linear-gradient(to right, hsl(220 10% 50% / 30%) 0 1px, transparent 0) -1px 0 / calc(100% / var(--steps-x, 10)) 100%;
93
-
94
- --chart-width: 100cqw;
95
- --chart-height: 100cqh;
96
- --extent-x: calc(var(--max-x) - var(--min-x));
97
- --extent-y: calc(var(--max-y) - var(--min-y));
98
- }
99
-
100
- ::slotted(color-scale) {
101
- --details-style: compact;
102
-
103
- /*
104
- We want color scales to be easy to style: one can hide them, lower their opacity, etc.
105
- At the same time, we don't want their containers to mess up with other chart parts.
106
- For example, we don't want color scales to get the hover styles when one moves the cursor to the top left part of the chart,
107
- where all the color scale containers reside. So, we need to shrink them.
108
- */
109
- display: block;
110
- width: 0;
111
- height: 0;
112
- }
1
+ @import url("color-chart-shadow.css");
2
+ @import url("color-chart-global.css");