color-elements 0.0.1 → 0.0.2

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 (47) hide show
  1. package/README.md +33 -11
  2. package/_build/copy-config.js +11 -1
  3. package/_build/copy-config.json +1 -1
  4. package/_build/eleventy.js +21 -0
  5. package/_build/filters-extra.js +3 -0
  6. package/_data/components.json +8 -0
  7. package/_includes/component.njk +61 -0
  8. package/_includes/partials/_nav-links.njk +12 -0
  9. package/_redirects +1 -1
  10. package/assets/js/index.js +8 -7
  11. package/eslint.config.js +316 -0
  12. package/index.js +6 -4
  13. package/logo.svg +22 -44
  14. package/package.json +11 -5
  15. package/src/channel-slider/README.md +123 -0
  16. package/src/channel-slider/channel-slider.css +19 -0
  17. package/src/channel-slider/channel-slider.js +252 -0
  18. package/{color-gamut → src/color-gamut}/README.md +1 -1
  19. package/{color-gamut → src/color-gamut}/color-gamut.js +1 -1
  20. package/src/color-inline/README.md +31 -0
  21. package/{color-swatch/color-swatch.js → src/color-inline/color-inline.js} +6 -6
  22. package/src/color-inline/style.css +14 -0
  23. package/src/color-picker/README.md +48 -0
  24. package/src/color-picker/color-picker.css +20 -0
  25. package/src/color-picker/color-picker.js +164 -0
  26. package/src/color-slider/README.md +193 -0
  27. package/src/color-slider/color-slider.css +164 -0
  28. package/src/color-slider/color-slider.js +278 -0
  29. package/src/color-swatch/README.md +100 -0
  30. package/src/color-swatch/color-swatch.css +95 -0
  31. package/{css-color/css-color.js → src/color-swatch/color-swatch.js} +30 -8
  32. package/src/common/color.js +12 -0
  33. package/src/common/dom.js +61 -0
  34. package/src/common/util.js +142 -0
  35. package/src/index.js.njk +7 -0
  36. package/src/src.json +3 -0
  37. package/_data/eleventyComputed.11tydata.js +0 -29
  38. package/color-slider/README.md +0 -84
  39. package/color-slider/color-slider.js +0 -79
  40. package/color-slider/style.css +0 -65
  41. package/color-swatch/index.njk +0 -40
  42. package/common/attributes.js +0 -68
  43. package/common/color.js +0 -10
  44. package/css-color/index.njk +0 -43
  45. package/css-color/style.css +0 -67
  46. /package/{color-gamut/style.css → src/color-gamut/color-gamut.css} +0 -0
  47. /package/{color-swatch/color-swatch.css → src/color-inline/color-inline.css} +0 -0
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Defines instance properties by defining an accessor that automatically replaces itself with a writable property when accessed.
3
+ * @param {Function} Class
4
+ * @param {string} name
5
+ * @param {function} getValue
6
+ */
7
+ export function defineInstanceProperty (
8
+ Class, name, getValue,
9
+ {writable = true, configurable = true, enumerable = false} = {}) {
10
+ let setter = function (value) {
11
+ Object.defineProperty(this, name, { value, writable, configurable, enumerable });
12
+ }
13
+ Object.defineProperty(Class.prototype, name, {
14
+ get () {
15
+ let value = getValue.call(this, this);
16
+ setter.call(this, value);
17
+ return value;
18
+ },
19
+ set (value) { // Blind set
20
+ setter.call(this, value);
21
+ },
22
+ configurable: true,
23
+ });
24
+ }
25
+
26
+ export function defineLazyProperty (object, name, options) {
27
+ if (typeof options === "function") {
28
+ options = { get: options };
29
+ }
30
+
31
+ let {get, writable = true, configurable = true, enumerable = false} = options;
32
+
33
+ let setter = function (value) {
34
+ Object.defineProperty(this, name, { value, writable, configurable, enumerable });
35
+ }
36
+ Object.defineProperty(object, name, {
37
+ get () {
38
+ let value = get.call(this);
39
+ setter.call(this, value);
40
+ return value;
41
+ },
42
+ set (value) { // Blind set
43
+ setter.call(this, value);
44
+ },
45
+ configurable: true,
46
+ });
47
+ }
48
+
49
+ export function defineComputed (Class, computed = Class.computed) {
50
+ let dependencies = new Map();
51
+
52
+ for (let name in computed) {
53
+ let spec = computed[name];
54
+ defineInstanceProperty(Class, name, spec.get);
55
+
56
+ if (spec.dependencies) {
57
+ for (let prop of spec.dependencies) {
58
+ let deps = dependencies.get(prop) ?? [];
59
+ deps.push(name);
60
+ dependencies.set(prop, deps);
61
+ }
62
+ }
63
+ }
64
+
65
+ if (dependencies.size > 0) {
66
+ let _propChangedCallback = Class.prototype.propChangedCallback;
67
+
68
+ Class.prototype.propChangedCallback = function(name, change) {
69
+ if (dependencies.has(name)) {
70
+ for (let prop of dependencies.get(name)) {
71
+ this[prop] = computed[prop].get.call(this, this);
72
+ }
73
+ }
74
+
75
+ _propChangedCallback?.call(this, name, change);
76
+ }
77
+ }
78
+ }
79
+
80
+ export function inferDependencies (fn) {
81
+ if (!fn || typeof fn !== "function") {
82
+ return [];
83
+ }
84
+
85
+ let code = fn.toString();
86
+
87
+ return [...code.matchAll(/\bthis\.([$\w]+)\b/g)].map(match => match[1]);
88
+ }
89
+
90
+ export async function wait (ms) {
91
+ return new Promise(resolve => setTimeout(resolve, ms));
92
+ }
93
+
94
+ export async function nextTick (refreshRate = 20) {
95
+ let now = performance.now();
96
+ let remainder = now % refreshRate;
97
+ let delay = refreshRate - remainder;
98
+ let nextAt = now + delay;
99
+ nextTick.start ??= now - remainder;
100
+
101
+ return new Promise(resolve => setTimeout(() => resolve(nextAt - nextTick.start), delay));
102
+ }
103
+
104
+ /**
105
+ * Compute the ideal step for a range, to be used as a default in spinners and sliders
106
+ * @param {number} min
107
+ * @param {number} max
108
+ * @param {options} options
109
+ */
110
+ export function getStep (min, max, {minSteps = 100, maxStep = 1} = {}) {
111
+ let range = Math.abs(max - min);
112
+ let step = range / minSteps;
113
+
114
+ // Find nearest power of 10 that is < step
115
+ step = 10 ** Math.floor(Math.log10(step));
116
+
117
+ return step > maxStep ? maxStep : step;
118
+ }
119
+
120
+ export function sortObject (obj, fn) {
121
+ if (!obj) {
122
+ return obj;
123
+ }
124
+
125
+ return Object.fromEntries(Object.entries(obj).sort(fn));
126
+ }
127
+
128
+ export function mapObject (obj, fn) {
129
+ if (!obj) {
130
+ return obj;
131
+ }
132
+
133
+ return Object.fromEntries(Object.entries(obj).map(fn));
134
+ }
135
+
136
+ export function pick (obj, properties) {
137
+ if (!properties || !obj) {
138
+ return obj;
139
+ }
140
+
141
+ return Object.fromEntries(Object.entries(obj).filter(([key]) => properties.includes(key)));
142
+ }
@@ -0,0 +1,7 @@
1
+ ---
2
+ permalink: "index.js"
3
+ layout: null
4
+ ---
5
+ {% for name in components -%}
6
+ export { default as {{ name | tag_to_class }} } from "./src/{{ name }}/{{ name }}.js";
7
+ {% endfor %}
package/src/src.json ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "layout": "component"
3
+ }
@@ -1,29 +0,0 @@
1
- export default {
2
- // Extract default title from content
3
- foo (data) {
4
- // if (data.title) {
5
- // return data.title;
6
- // }
7
-
8
- // let ext = data.page.inputPath.split(".").pop();
9
-
10
- // // Title must appear in first 1000 chars
11
- // let content = data.page.rawInput.slice(0, 1000);
12
- // let ret;
13
-
14
- // if (ext === "md") {
15
- // // First heading
16
- // ret = content.match(/^#+\s+(.*)/m)?.[1];
17
- // }
18
- // else if (ext === "njk") {
19
- // // First level 1 heading
20
- // ret = content.match(/<h1>(.*)<\/h1>/)?.[1];
21
- // }
22
-
23
- // if (ret) {
24
- // ret = ret.replace(/&lt;/g, "<").replace(/&gt;/g, ">");
25
- // }
26
-
27
- // return ret;
28
- },
29
- };
@@ -1,84 +0,0 @@
1
- # `&lt;color-slider>`
2
- <script src="color-slider.js" type="module"></script>
3
-
4
- Creates a slider with a gradient background, primarily intended for color picking.
5
-
6
- ## Installation
7
-
8
- The quick and dirty way is straight from the CDN (kindly provided by [Netlify](https://www.netlify.com/)):
9
-
10
- ```html
11
- <script src="https://colorjs.io/elements/color-slider/color-slider.js" type="module"></script>
12
- ```
13
-
14
- You can also install it via npm.
15
- There is no separate package currently, you just install the whole `colorjs.io` package:
16
-
17
- ```bash
18
- npm install colorjs.io
19
- ```
20
-
21
- Then, you use the `colorjs.io/elements` import:
22
-
23
- ```js
24
- import {ColorSlider} from "colorjs.io/elements";
25
- ```
26
-
27
- ## Usage
28
-
29
- There are many ways to use this component, depending on what you need.
30
- E.g. if all you need is styling sliders with arbitrary gradients you don’t even need a component,
31
- you can just use the CSS file and a few classes and CSS variables.
32
-
33
- The actual component does a lot more:
34
- - It takes care of applying the right `min` and `max` values to the slider
35
- - It automatically generates the start and end colors,
36
- - It provides a `color` property with the actual color value.
37
- - It can provide an editable tooltip as a tooltip that both shows and edits the current value
38
-
39
- <script src="./color-slider.js" type="module"></script>
40
- <style>@import url("style.css");</style>
41
-
42
- ### Zero hassle, little control
43
-
44
- You get the most value out of this component when using it to control a single component:
45
-
46
- ```html
47
- <color-slider space="oklch" component="h" colorvalue="oklch(50 50% 180)"></color-slider>
48
- ```
49
-
50
- This will automatically use the whole reference range of that component in the specified color space,
51
- and use the current value of the component as the starting value (unless `value` is also specified).
52
- If you don’t want to show the whole range you can also specify `min` and `max` attributes.
53
-
54
- ```html
55
- <color-slider space="oklch" component="l" colorvalue="red" min=".3" max=".95"></color-slider>
56
- ```
57
-
58
- ### Minimal hassle, more control
59
-
60
- If your use case does not involve interpolating across a single component, or you already have the colors you want to plot from and to, you can also do that:
61
-
62
- ```html
63
- <color-slider space="oklch" colormin="gold" colormax="oklch(65% 0.15 210)"></color-slider>
64
- ```
65
-
66
- ### Styling-only usage
67
-
68
- If you just want the styling and are fine dealing with the lower level details on your own, you *can* just use the CSS file:
69
-
70
- ```css
71
- @import url("https://colorjs.io/elements/color-slider/style.css");
72
- ```
73
-
74
- Then use a `color-slider` class on your slider element, and the following CSS variables:
75
-
76
- - `--start-color`: the start color of the gradient
77
- - `--end-color`: the end color of the gradient
78
- - `--color-space`: the color space of the gradient (default: `oklch`)
79
- - `--intermediate-colors`: _(optional)_ any intermediate colors.
80
-
81
- OR:
82
- - `--gradient` if you want to override the whole gradient.
83
-
84
-
@@ -1,79 +0,0 @@
1
- /*
2
- <label v-for="(meta, i) in coord_meta" class="color-slider-label">
3
- {{ meta.name }} ({{ meta.min }}-{{ meta.max }})
4
- <input class="color-slider" type="range" v-model.number="coords[i]" :style="`--stops: ${ slider_steps[i] }`" :min="meta.min" :max="meta.max" :step="meta.step" />
5
- <input type="number" v-model.number="coords[i]" class="autosize" :style="`--percentage: ${coords[i] / (meta.max - meta.min) }`" :min="meta.min" :max="meta.max" :step="meta.step" />
6
- </label>
7
-
8
- <label class="color-slider-label">Alpha (0-100)
9
- <input class="color-slider" type="range" v-model.number="alpha"
10
- :style="`--stops: ${ slider_steps[coord_meta.length] }`" />
11
- <input type="number" class="autosize" v-model.number="alpha" :style="`--percentage: ${alpha / 100}`" max="100" />
12
- </label>*/
13
- import defineAttributes from "../common/attributes.js";
14
- import Color from "../common/color.js";
15
-
16
- export default class ColorSlider extends HTMLElement {
17
- _props = {};
18
-
19
- constructor () {
20
- super();
21
- this.attachShadow({mode: "open"});
22
- this.shadowRoot.innerHTML = `
23
- <style>@import url("${ styleURL }")</style>
24
- <label v-for="(meta, i) in coord_meta" class="color-slider-label">
25
- {{ meta.name }} ({{ meta.min }}-{{ meta.max }})
26
- <input class="color-slider" type="range" v-model.number="coords[i]" :style="`--stops: ${ slider_steps[i] }`" :min="meta.min" :max="meta.max" :step="meta.step" />
27
- <input type="number" :style="`--percentage: ${coords[i] / (meta.max - meta.min) }`" :min="meta.min" :max="meta.max" :step="meta.step" />
28
- </label>
29
- `;
30
- }
31
-
32
-
33
-
34
- attributeChangedCallback (name, value, oldValue) {
35
- if (name in this.constructor.attributes) {
36
- this[name] = value;
37
- }
38
- }
39
-
40
- static get observedAttributes() {
41
- return Object.keys(this.attributes);
42
- }
43
-
44
- static attributes = {
45
- space: {
46
- type: String,
47
- default: "oklch",
48
- },
49
- component: {
50
- type: String,
51
- default: "h",
52
- },
53
- value: {
54
- type: Number,
55
- default: "oklch(0.5 0 180)",
56
- },
57
- min: {
58
- type: Number,
59
- },
60
- max: {
61
- type: Number,
62
- },
63
- step: {
64
- type: Number,
65
- },
66
- colorvalue: {
67
- type: Color,
68
- },
69
- colormin: {
70
- type: Color,
71
- },
72
- colormax: {
73
- type: Color,
74
- },
75
- }
76
- }
77
-
78
- defineAttributes(ColorSlider);
79
- customElements.define("color-slider", ColorSlider);
@@ -1,65 +0,0 @@
1
- .color-slider {
2
- display: block;
3
- margin: 0 1em auto 0;
4
- width: 100%;
5
- -moz-appearance: none;
6
- -webkit-appearance: none;
7
- background: linear-gradient(to right, var(--stops)), var(--transparency);
8
- height: 2.2em;
9
- border-radius: .3em;
10
- box-shadow: 0 0 1px rgba(0, 0, 0, 0.5);
11
-
12
-
13
- &::-webkit-slider-thumb {
14
- width: 1em;
15
- height: 2.3em;
16
- -webkit-appearance: none;
17
- border-radius: .15em;
18
- border: 1px solid black;
19
- box-shadow: 0 0 0 1px white;
20
- }
21
-
22
- &::-moz-range-thumb {
23
- width: 1em;
24
- height: 2.3em;
25
- border-radius: .15em;
26
- border: 1px solid black;
27
- box-shadow: 0 0 0 1px white;
28
- background: transparent;
29
- }
30
-
31
- &::-moz-range-track {
32
- background: none;
33
- }
34
-
35
- & + input[type=number] {
36
- position: absolute;
37
- margin-top: -4em;
38
- left: calc(100% * var(--percentage));
39
- transform: translateX(-50%);
40
- padding: .2em .5em;
41
- width: 3em;
42
- border: 0;
43
- border-radius: .3em;
44
- text-align: center;
45
- color: white;
46
- background: rgba(0,0,0,.8);
47
- font: inherit;
48
- font-size: 120%;
49
- transition: .3s left cubic-bezier(.17,.67,.49,1.48) ;
50
- }
51
-
52
- /* Prevent input from moving all over the place as we type */
53
- & + input[type=number]:focus {
54
- transition-delay: .5s;
55
- }
56
-
57
- label:not(:focus-within):not(:hover) > .color-slider + input[type=number] {
58
- display: none;
59
- }
60
-
61
- }
62
-
63
- .color-slider-label {
64
- position: relative;
65
- }
@@ -1,40 +0,0 @@
1
- ---
2
- title: &lt;color-swatch>
3
- ---
4
-
5
-
6
- <script src="color-swatch.js" type="module"></script>
7
- <style>
8
- html {
9
- color-scheme: light dark;
10
- }
11
-
12
- @media (prefers-color-scheme: dark) {
13
- html {
14
- background: hsl(220 5% 20%);
15
- }
16
- }
17
-
18
- color-swatch {
19
- display: block;
20
- margin: 1em 0;
21
- }
22
- </style>
23
-
24
-
25
- <h1>&lt;color-swatch></h1>
26
-
27
- <section>
28
- <h2>Different font sizes</h2>
29
- <color-swatch style="font-size: 70%" contentEditable>lch(50% 40 30)</color-swatch>
30
- <color-swatch contentEditable>lch(50% 40 30)</color-swatch>
31
- <color-swatch style="font-size: 200%" contentEditable>lch(50% 40 30)</color-swatch>
32
- <color-swatch style="font-size: 400%" contentEditable>lch(50% 40 30)</color-swatch>
33
- <color-swatch style="font-size: 800%" contentEditable>lch(50% 40 30)</color-swatch>
34
- </section>
35
-
36
- <p>Semi-transparent color</p>
37
- <color-swatch>hsl(340 90% 50% / .25)</color-swatch>
38
-
39
- <p>Invalid color</p>
40
- <color-swatch>foobar</color-swatch>
@@ -1,68 +0,0 @@
1
- export default function (Class, attributes = Class.attributes) {
2
- Object.defineProperty(Class.prototype, "_props", {
3
- get () {
4
- let value = {};
5
- Object.defineProperty(this, "_props", {
6
- value,
7
- writable: true,
8
- configurable: true,
9
- enumerable: false,
10
- });
11
- return value;
12
- },
13
- writable: true,
14
- configurable: true,
15
- });
16
-
17
- // Define getters and setters for each attribute
18
- for (let name in attributes) {
19
- let spec = Class.attributes[name] ?? {};
20
- let {type, default: defaultValue} = spec;
21
-
22
- Object.defineProperty(Class.prototype, name, {
23
- get () {
24
- let value = this._props[name];
25
-
26
- if (value === undefined && defaultValue !== undefined) {
27
- return defaultValue;
28
- }
29
-
30
- return value;
31
- },
32
- set (value) {
33
- let oldValue = this._props[name];
34
- let oldAttributeValue = this.getAttribute(name);
35
- let originalValue = value;
36
- let originalClass = value.constructor;
37
- let originalType = typeof value;
38
-
39
- if (type && type !== String) {
40
- if (type === Number) {
41
- value = Number(value);
42
- }
43
- else if (type === Boolean) {
44
- value = value !== null;
45
- }
46
- else {
47
- // Assume it's a class
48
- value = new type(value);
49
- }
50
- }
51
-
52
- this._props[name] = value;
53
-
54
- if (value !== oldValue && oldAttributeValue !== originalValue) {
55
- if (type === Boolean) {
56
- this.toggleAttribute(name, value);
57
- }
58
- else {
59
- this.setAttribute(name, value);
60
- }
61
- }
62
- },
63
- enumerable: true,
64
- });
65
- }
66
-
67
- // Class.prototype._initializeProps = function () {};
68
- }
package/common/color.js DELETED
@@ -1,10 +0,0 @@
1
- let specifier;
2
-
3
- if (import.meta.resolve("colorjs.io")) {
4
- specifier = "colorjs.io";
5
- }
6
- else {
7
- specifier = "../node_modules/colorjs.io/dist/color.js";
8
- }
9
-
10
- export default await import(specifier);
@@ -1,43 +0,0 @@
1
- <h1>&lt;css-color></h1>
2
-
3
- <script src="./css-color.js" type="module"></script>
4
- <h2>Static</h2>
5
- <css-color>oklch(70% 0.25 138)</css-color>
6
- <css-color swatch="large">oklch(70% 0.25 138)</css-color>
7
-
8
- <h2>Editable</h2>
9
- <css-color>
10
- <input value="oklch(70% 0.25 138)" />
11
- </css-color>
12
- <css-color swatch="large">
13
- <input value="oklch(70% 0.25 138)" />
14
- </css-color>
15
-
16
- <h2>With name</h2>
17
- <css-color>
18
- <label slot="before" for=c1>Accent color:</label>
19
- <input value="oklch(70% 0.25 138)" id=c1 />
20
- </css-color>
21
- <css-color swatch="large">
22
- <label slot="before" id=c2>Accent color:</label>
23
- <input value="oklch(70% 0.25 138)" id=c2 />
24
- </css-color>
25
-
26
- <h2>Bound to CSS property</h2>
27
- <css-color swatch="large" property="--color-red">
28
- <input />
29
- </css-color>
30
-
31
- <h2>Update via JS</h2>
32
- <h3>Static</h3>
33
- <css-color id="dynamic_static">oklch(70% 0.25 138)</css-color>
34
- <script type="module">
35
- dynamic_static.color = "oklch(60% 0.15 0)"
36
- </script>
37
- <h3>Editable</h3>
38
- <css-color id="dynamic_editable">
39
- <input value="oklch(70% 0.25 138)" />
40
- </css-color>
41
- <script type="module">
42
- dynamic_editable.color = "oklch(60% 0.15 0)"
43
- </script>
@@ -1,67 +0,0 @@
1
- :host {
2
- display: inline-flex;
3
- gap: .3em;
4
- width: min-content;
5
- white-space: nowrap;
6
- --background-checkerboard: repeating-conic-gradient(rgb(0 0 0 / .12) 0 25%, transparent 0 50%) 0 0 / 1em 1em;
7
- }
8
-
9
- #gamut {
10
- font-size: 80%;
11
- }
12
-
13
- #wrapper {
14
- display: flex;
15
- flex-flow: inherit;
16
-
17
- &.static {
18
- gap: .4em;
19
- }
20
- }
21
-
22
- [part="color-wrapper"] {
23
- position: relative;
24
- display: flex;
25
- gap: .2em;
26
-
27
- &:not(.static *) {
28
- #gamut {
29
- position: absolute;
30
- inset: .3em;
31
- inset-inline-start: auto;
32
- }
33
- }
34
-
35
- ::slotted(input) {
36
- padding-inline-end: 2em;
37
- }
38
- }
39
-
40
- :host(:not([for])) #swatch {
41
- display: block;
42
- inline-size: 2em;
43
- border-radius: .2em;
44
- background: linear-gradient(var(--color, transparent) 0 100%), var(--background-checkerboard);
45
- }
46
-
47
- :host([swatch="none"]) #swatch {
48
- display: none;
49
- }
50
-
51
- :host(:not([for])):host([swatch="large"]) {
52
- flex-flow: column;
53
-
54
- #wrapper {
55
- flex-flow: column;
56
- }
57
- }
58
-
59
- :host(:not([for])):host([swatch="large"]) #swatch {
60
- inline-size: auto;
61
- block-size: 5em;
62
- }
63
-
64
- :host(:not([for])):host([swatch="large"]) #wrapper.static slot {
65
- display: flex;
66
- flex: 1;
67
- }