chroma-panel 0.1.4 → 1.0.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.
- package/README.md +47 -9
- package/dist/a11y/contrast.cjs +94 -0
- package/dist/a11y/contrast.d.cts +8 -0
- package/dist/a11y/contrast.d.ts +8 -0
- package/dist/a11y/contrast.js +93 -2
- package/dist/color/css4.cjs +397 -0
- package/dist/color/css4.d.cts +10 -0
- package/dist/color/css4.d.ts +10 -0
- package/dist/color/css4.js +392 -0
- package/dist/color/parse.cjs +3 -1
- package/dist/color/parse.js +3 -1
- package/dist/color/types.d.cts +16 -0
- package/dist/color/types.d.ts +16 -0
- package/dist/color/value.cjs +11 -0
- package/dist/color/value.d.cts +4 -0
- package/dist/color/value.d.ts +4 -0
- package/dist/color/value.js +12 -0
- package/dist/color.cjs +43 -0
- package/dist/color.d.cts +9 -0
- package/dist/color.d.ts +9 -0
- package/dist/color.js +8 -0
- package/dist/components/ChromaPanel.cjs +21 -7
- package/dist/components/ChromaPanel.d.cts +5 -2
- package/dist/components/ChromaPanel.d.ts +5 -2
- package/dist/components/ChromaPanel.js +21 -7
- package/dist/components/ColorInput.cjs +1 -1
- package/dist/components/ColorInput.js +1 -1
- package/dist/components/PanelFooter.cjs +37 -4
- package/dist/components/PanelFooter.js +39 -6
- package/dist/contrast.cjs +3 -0
- package/dist/contrast.d.cts +2 -2
- package/dist/contrast.d.ts +2 -2
- package/dist/contrast.js +2 -2
- package/dist/core/context.d.cts +3 -0
- package/dist/core/context.d.ts +3 -0
- package/dist/core/store.cjs +17 -9
- package/dist/core/store.d.cts +6 -6
- package/dist/core/store.d.ts +6 -6
- package/dist/core/store.js +17 -9
- package/dist/core.cjs +10 -0
- package/dist/core.d.cts +4 -2
- package/dist/core.d.ts +4 -2
- package/dist/core.js +3 -1
- package/dist/export/tokens.cjs +39 -0
- package/dist/export/tokens.d.cts +16 -0
- package/dist/export/tokens.d.ts +16 -0
- package/dist/export/tokens.js +37 -0
- package/dist/export.cjs +6 -0
- package/dist/export.d.cts +2 -0
- package/dist/export.d.ts +2 -0
- package/dist/export.js +2 -0
- package/dist/gradient/GradientEditor.cjs +196 -0
- package/dist/gradient/GradientEditor.d.cts +17 -0
- package/dist/gradient/GradientEditor.d.ts +17 -0
- package/dist/gradient/GradientEditor.js +195 -0
- package/dist/gradient/model.cjs +63 -0
- package/dist/gradient/model.d.cts +23 -0
- package/dist/gradient/model.d.ts +23 -0
- package/dist/gradient/model.js +60 -0
- package/dist/gradient.cjs +9 -0
- package/dist/gradient.d.cts +3 -0
- package/dist/gradient.d.ts +3 -0
- package/dist/gradient.js +3 -0
- package/dist/image/extract.cjs +23 -6
- package/dist/image/extract.d.cts +2 -0
- package/dist/image/extract.d.ts +2 -0
- package/dist/image/extract.js +23 -6
- package/dist/index.cjs +13 -0
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +4 -2
- package/dist/modes/image/index.cjs +155 -14
- package/dist/modes/image/index.d.cts +1 -0
- package/dist/modes/image/index.d.ts +1 -0
- package/dist/modes/image/index.js +155 -14
- package/dist/modes/registry.d.cts +1 -1
- package/dist/modes/registry.d.ts +1 -1
- package/dist/modes.cjs +30 -0
- package/dist/modes.d.cts +10 -0
- package/dist/modes.d.ts +10 -0
- package/dist/modes.js +17 -0
- package/dist/panel.cjs +10 -0
- package/dist/panel.d.cts +4 -2
- package/dist/panel.d.ts +4 -2
- package/dist/panel.js +3 -1
- package/dist/primitives/ChannelSlider.cjs +4 -4
- package/dist/primitives/ChannelSlider.js +4 -4
- package/dist/primitives/ColorArea.cjs +6 -6
- package/dist/primitives/ColorArea.js +6 -6
- package/dist/primitives/ColorDisc.cjs +6 -6
- package/dist/primitives/ColorDisc.js +6 -6
- package/dist/primitives/ColorField.cjs +2 -2
- package/dist/primitives/ColorField.js +2 -2
- package/dist/primitives/NumberField.cjs +2 -2
- package/dist/primitives/NumberField.js +2 -2
- package/dist/primitives/SwatchGrid.cjs +2 -2
- package/dist/primitives/SwatchGrid.js +2 -2
- package/dist/primitives/icons.cjs +8 -0
- package/dist/primitives/icons.d.cts +1 -1
- package/dist/primitives/icons.d.ts +1 -1
- package/dist/primitives/icons.js +8 -0
- package/dist/style.css +1 -1
- package/dist/styles/css.cjs +1 -1
- package/dist/styles/css.js +1 -1
- package/package.json +46 -2
package/dist/gradient.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { addGradientStop, gradientToCss, isGradientColorSupported, normalizeGradient, sampleGradient } from "./gradient/model.js";
|
|
2
|
+
import { GradientEditor } from "./gradient/GradientEditor.js";
|
|
3
|
+
export { GradientEditor, addGradientStop, gradientToCss, isGradientColorSupported, normalizeGradient, sampleGradient };
|
package/dist/image/extract.cjs
CHANGED
|
@@ -9,13 +9,27 @@ async function toBlob(source) {
|
|
|
9
9
|
if (!response.ok) throw new Error(`chroma-panel: could not load image (${response.status}).`);
|
|
10
10
|
return await response.blob();
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
const DEFAULT_MAX_FILE_SIZE = 20971520;
|
|
13
|
+
const DEFAULT_MAX_SOURCE_PIXELS = 4e7;
|
|
14
|
+
function validateBlob(blob, maxFileSize) {
|
|
15
|
+
if (blob.size > maxFileSize) {
|
|
16
|
+
const limit = Math.round(maxFileSize / 1048576);
|
|
17
|
+
throw new RangeError(`chroma-panel: image must be ${limit} MB or smaller.`);
|
|
18
|
+
}
|
|
19
|
+
if (blob.type !== "" && !blob.type.toLowerCase().startsWith("image/")) throw new TypeError("chroma-panel: the selected file is not an image.");
|
|
20
|
+
}
|
|
21
|
+
async function decode(blob, size, maxSourcePixels) {
|
|
13
22
|
if (typeof createImageBitmap !== "function") throw new Error("chroma-panel: this browser cannot decode images off-thread.");
|
|
14
23
|
const longest = Math.max(8, Math.round(size));
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const wide = probe.width >= probe.height;
|
|
24
|
+
const probe = await createImageBitmap(blob);
|
|
25
|
+
if (probe.width * probe.height > maxSourcePixels) {
|
|
18
26
|
probe.close();
|
|
27
|
+
const megapixels = Math.round(maxSourcePixels / 1e6);
|
|
28
|
+
throw new RangeError(`chroma-panel: image dimensions must not exceed ${megapixels} megapixels.`);
|
|
29
|
+
}
|
|
30
|
+
const wide = probe.width >= probe.height;
|
|
31
|
+
probe.close();
|
|
32
|
+
try {
|
|
19
33
|
return await createImageBitmap(blob, {
|
|
20
34
|
...wide ? { resizeWidth: longest } : { resizeHeight: longest },
|
|
21
35
|
resizeQuality: "medium",
|
|
@@ -71,14 +85,17 @@ function runInWorker(worker, data, maxColors, alphaThreshold, signal) {
|
|
|
71
85
|
});
|
|
72
86
|
}
|
|
73
87
|
async function extractPalette(source, options = {}) {
|
|
74
|
-
const { maxColors = 8, size = 100, alphaThreshold = 128, worker, signal } = options;
|
|
88
|
+
const { maxColors = 8, size = 100, alphaThreshold = 128, maxFileSize = DEFAULT_MAX_FILE_SIZE, maxSourcePixels = DEFAULT_MAX_SOURCE_PIXELS, worker, signal } = options;
|
|
75
89
|
if (!Number.isFinite(maxColors) || maxColors < 2) throw new RangeError("chroma-panel: maxColors must be a number of at least 2.");
|
|
76
90
|
if (!Number.isFinite(size) || size < 8) throw new RangeError("chroma-panel: size must be a number of at least 8.");
|
|
77
91
|
if (!Number.isFinite(alphaThreshold) || alphaThreshold < 0 || alphaThreshold > 255) throw new RangeError("chroma-panel: alphaThreshold must be between 0 and 255.");
|
|
92
|
+
if (!Number.isFinite(maxFileSize) || maxFileSize <= 0) throw new RangeError("chroma-panel: maxFileSize must be greater than 0.");
|
|
93
|
+
if (!Number.isFinite(maxSourcePixels) || maxSourcePixels < 64) throw new RangeError("chroma-panel: maxSourcePixels must be at least 64.");
|
|
78
94
|
if (aborted(signal)) throw new DOMException("Aborted", "AbortError");
|
|
79
95
|
const blob = await toBlob(source);
|
|
96
|
+
validateBlob(blob, maxFileSize);
|
|
80
97
|
if (aborted(signal)) throw new DOMException("Aborted", "AbortError");
|
|
81
|
-
const bitmap = await decode(blob, size);
|
|
98
|
+
const bitmap = await decode(blob, size, maxSourcePixels);
|
|
82
99
|
let data;
|
|
83
100
|
try {
|
|
84
101
|
if (aborted(signal)) throw new DOMException("Aborted", "AbortError");
|
package/dist/image/extract.d.cts
CHANGED
package/dist/image/extract.d.ts
CHANGED
package/dist/image/extract.js
CHANGED
|
@@ -9,13 +9,27 @@ async function toBlob(source) {
|
|
|
9
9
|
if (!response.ok) throw new Error(`chroma-panel: could not load image (${response.status}).`);
|
|
10
10
|
return await response.blob();
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
const DEFAULT_MAX_FILE_SIZE = 20971520;
|
|
13
|
+
const DEFAULT_MAX_SOURCE_PIXELS = 4e7;
|
|
14
|
+
function validateBlob(blob, maxFileSize) {
|
|
15
|
+
if (blob.size > maxFileSize) {
|
|
16
|
+
const limit = Math.round(maxFileSize / 1048576);
|
|
17
|
+
throw new RangeError(`chroma-panel: image must be ${limit} MB or smaller.`);
|
|
18
|
+
}
|
|
19
|
+
if (blob.type !== "" && !blob.type.toLowerCase().startsWith("image/")) throw new TypeError("chroma-panel: the selected file is not an image.");
|
|
20
|
+
}
|
|
21
|
+
async function decode(blob, size, maxSourcePixels) {
|
|
13
22
|
if (typeof createImageBitmap !== "function") throw new Error("chroma-panel: this browser cannot decode images off-thread.");
|
|
14
23
|
const longest = Math.max(8, Math.round(size));
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const wide = probe.width >= probe.height;
|
|
24
|
+
const probe = await createImageBitmap(blob);
|
|
25
|
+
if (probe.width * probe.height > maxSourcePixels) {
|
|
18
26
|
probe.close();
|
|
27
|
+
const megapixels = Math.round(maxSourcePixels / 1e6);
|
|
28
|
+
throw new RangeError(`chroma-panel: image dimensions must not exceed ${megapixels} megapixels.`);
|
|
29
|
+
}
|
|
30
|
+
const wide = probe.width >= probe.height;
|
|
31
|
+
probe.close();
|
|
32
|
+
try {
|
|
19
33
|
return await createImageBitmap(blob, {
|
|
20
34
|
...wide ? { resizeWidth: longest } : { resizeHeight: longest },
|
|
21
35
|
resizeQuality: "medium",
|
|
@@ -71,14 +85,17 @@ function runInWorker(worker, data, maxColors, alphaThreshold, signal) {
|
|
|
71
85
|
});
|
|
72
86
|
}
|
|
73
87
|
async function extractPalette(source, options = {}) {
|
|
74
|
-
const { maxColors = 8, size = 100, alphaThreshold = 128, worker, signal } = options;
|
|
88
|
+
const { maxColors = 8, size = 100, alphaThreshold = 128, maxFileSize = DEFAULT_MAX_FILE_SIZE, maxSourcePixels = DEFAULT_MAX_SOURCE_PIXELS, worker, signal } = options;
|
|
75
89
|
if (!Number.isFinite(maxColors) || maxColors < 2) throw new RangeError("chroma-panel: maxColors must be a number of at least 2.");
|
|
76
90
|
if (!Number.isFinite(size) || size < 8) throw new RangeError("chroma-panel: size must be a number of at least 8.");
|
|
77
91
|
if (!Number.isFinite(alphaThreshold) || alphaThreshold < 0 || alphaThreshold > 255) throw new RangeError("chroma-panel: alphaThreshold must be between 0 and 255.");
|
|
92
|
+
if (!Number.isFinite(maxFileSize) || maxFileSize <= 0) throw new RangeError("chroma-panel: maxFileSize must be greater than 0.");
|
|
93
|
+
if (!Number.isFinite(maxSourcePixels) || maxSourcePixels < 64) throw new RangeError("chroma-panel: maxSourcePixels must be at least 64.");
|
|
78
94
|
if (aborted(signal)) throw new DOMException("Aborted", "AbortError");
|
|
79
95
|
const blob = await toBlob(source);
|
|
96
|
+
validateBlob(blob, maxFileSize);
|
|
80
97
|
if (aborted(signal)) throw new DOMException("Aborted", "AbortError");
|
|
81
|
-
const bitmap = await decode(blob, size);
|
|
98
|
+
const bitmap = await decode(blob, size, maxSourcePixels);
|
|
82
99
|
let data;
|
|
83
100
|
try {
|
|
84
101
|
if (aborted(signal)) throw new DOMException("Aborted", "AbortError");
|
package/dist/index.cjs
CHANGED
|
@@ -7,6 +7,7 @@ const require_useColorStore = require("./core/useColorStore.cjs");
|
|
|
7
7
|
const require_usePointerDrag = require("./core/usePointerDrag.cjs");
|
|
8
8
|
const require_ChannelSlider = require("./primitives/ChannelSlider.cjs");
|
|
9
9
|
const require_ColorDisc = require("./primitives/ColorDisc.cjs");
|
|
10
|
+
const require_css4 = require("./color/css4.cjs");
|
|
10
11
|
const require_parse = require("./color/parse.cjs");
|
|
11
12
|
const require_serialize = require("./color/serialize.cjs");
|
|
12
13
|
const require_ColorField = require("./primitives/ColorField.cjs");
|
|
@@ -33,6 +34,7 @@ const require_Popover = require("./components/Popover.cjs");
|
|
|
33
34
|
const require_ColorInput = require("./components/ColorInput.cjs");
|
|
34
35
|
const require_ColorArea = require("./primitives/ColorArea.cjs");
|
|
35
36
|
const require_Swatch = require("./primitives/Swatch.cjs");
|
|
37
|
+
const require_value = require("./color/value.cjs");
|
|
36
38
|
const require_contrast = require("./a11y/contrast.cjs");
|
|
37
39
|
//#region src/index.ts
|
|
38
40
|
require_registry.registerMode(require_index.wheelMode);
|
|
@@ -64,14 +66,19 @@ exports.WheelPanel = require_index.WheelPanel;
|
|
|
64
66
|
exports.apcaContrast = require_contrast.apcaContrast;
|
|
65
67
|
exports.clamp = require_convert.clamp;
|
|
66
68
|
exports.clearNamedColors = require_parse.clearNamedColors;
|
|
69
|
+
exports.colorValueToHsva = require_css4.colorValueToHsva;
|
|
70
|
+
exports.compositeColor = require_contrast.compositeColor;
|
|
67
71
|
exports.contrastRatio = require_contrast.contrastRatio;
|
|
72
|
+
exports.contrastRatioWithAlpha = require_contrast.contrastRatioWithAlpha;
|
|
68
73
|
exports.contrastReport = require_contrast.contrastReport;
|
|
74
|
+
exports.convertColor = require_css4.convertColor;
|
|
69
75
|
exports.createColorStore = require_store.createColorStore;
|
|
70
76
|
exports.defaultPalettes = require_defaults.defaultPalettes;
|
|
71
77
|
exports.defaultPencils = require_defaults.defaultPencils;
|
|
72
78
|
exports.extractPalette = require_extract.extractPalette;
|
|
73
79
|
exports.getMode = require_registry.getMode;
|
|
74
80
|
exports.hslaToHsva = require_convert.hslaToHsva;
|
|
81
|
+
exports.hsvaToColorValue = require_css4.hsvaToColorValue;
|
|
75
82
|
exports.hsvaToHsl = require_convert.hsvaToHsl;
|
|
76
83
|
exports.hsvaToHsla = require_convert.hsvaToHsla;
|
|
77
84
|
exports.hsvaToHwba = require_convert.hsvaToHwba;
|
|
@@ -81,12 +88,16 @@ exports.hwbaToHsva = require_convert.hwbaToHsva;
|
|
|
81
88
|
exports.imageMode = require_index$3.imageMode;
|
|
82
89
|
exports.ingest = require_sticky.ingest;
|
|
83
90
|
exports.injectStyles = require_styleInjector.injectStyles;
|
|
91
|
+
exports.isInGamut = require_css4.isInGamut;
|
|
84
92
|
exports.isValidColor = require_parse.isValidColor;
|
|
93
|
+
exports.mapToGamut = require_css4.mapToGamut;
|
|
85
94
|
exports.meetsContrast = require_contrast.meetsContrast;
|
|
86
95
|
exports.meetsNonTextContrast = require_contrast.meetsNonTextContrast;
|
|
87
96
|
exports.normalizeHue = require_convert.normalizeHue;
|
|
88
97
|
exports.palettesMode = require_index$2.palettesMode;
|
|
89
98
|
exports.parse = require_parse.parse;
|
|
99
|
+
exports.parseColor = require_value.parseColor;
|
|
100
|
+
exports.parseCss4Color = require_css4.parseCss4Color;
|
|
90
101
|
exports.pencilsMode = require_index$4.pencilsMode;
|
|
91
102
|
exports.pushRecent = require_PanelFooter.pushRecent;
|
|
92
103
|
exports.quantize = require_mmcq.quantize;
|
|
@@ -99,8 +110,10 @@ exports.rgbaToHsva = require_convert.rgbaToHsva;
|
|
|
99
110
|
exports.roundRgba = require_convert.roundRgba;
|
|
100
111
|
exports.sameHsva = require_sticky.sameHsva;
|
|
101
112
|
exports.sameRendered = require_sticky.sameRendered;
|
|
113
|
+
exports.serializeColor = require_css4.serializeColor;
|
|
102
114
|
exports.setStyleNonce = require_styleInjector.setStyleNonce;
|
|
103
115
|
exports.slidersMode = require_index$1.slidersMode;
|
|
116
|
+
exports.suggestAccessibleColor = require_contrast.suggestAccessibleColor;
|
|
104
117
|
exports.toFormat = require_serialize.toFormat;
|
|
105
118
|
exports.toHex = require_serialize.toHex;
|
|
106
119
|
exports.toHexa = require_serialize.toHexa;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { ColorChangeResult, ColorFormat, Hsl, Hsla, Hsva, Hwb, Hwba, Rgb, Rgba } from "./color/types.cjs";
|
|
2
|
-
import { ContrastOptions, ContrastReport, TextSize, WcagLevel, apcaContrast, contrastRatio, contrastReport, meetsContrast, meetsNonTextContrast, readableTextColor, relativeLuminance, wcagLevel } from "./a11y/contrast.cjs";
|
|
1
|
+
import { ColorChangeMeta, ColorChangeResult, ColorChangeSource, ColorFormat, ColorValue, Hsl, Hsla, Hsva, Hwb, Hwba, ModernColorSpace, Rgb, Rgba, SerializeColorOptions } from "./color/types.cjs";
|
|
3
2
|
import { clamp, hslaToHsva, hsvaToHsl, hsvaToHsla, hsvaToHwba, hsvaToRgb, hsvaToRgba, hwbaToHsva, normalizeHue, rgbaToHsva, roundRgba } from "./color/convert.cjs";
|
|
4
3
|
import { clearNamedColors, isValidColor, parse, registerNamedColors } from "./color/parse.cjs";
|
|
4
|
+
import { parseColor } from "./color/value.cjs";
|
|
5
|
+
import { colorValueToHsva, convertColor, hsvaToColorValue, isInGamut, mapToGamut, parseCss4Color, serializeColor } from "./color/css4.cjs";
|
|
5
6
|
import { toFormat, toHex, toHexa, toHslString, toHslaString, toResult, toRgbString, toRgbaString } from "./color/serialize.cjs";
|
|
6
7
|
import { ingest, sameHsva, sameRendered } from "./color/sticky.cjs";
|
|
7
8
|
import { ColorListener, ColorStore, Unsubscribe, createColorStore } from "./core/store.cjs";
|
|
9
|
+
import { AccessibleColorSuggestion, ContrastOptions, ContrastReport, TextSize, WcagLevel, apcaContrast, compositeColor, contrastRatio, contrastRatioWithAlpha, contrastReport, meetsContrast, meetsNonTextContrast, readableTextColor, relativeLuminance, suggestAccessibleColor, wcagLevel } from "./a11y/contrast.cjs";
|
|
8
10
|
import { QuantizedSwatch, quantize } from "./image/mmcq.cjs";
|
|
9
11
|
import { ExtractOptions, ExtractResult, extractPalette } from "./image/extract.cjs";
|
|
10
12
|
import { ModeId, PickerMode, getMode, registerMode, resolveModes } from "./modes/registry.cjs";
|
|
@@ -33,4 +35,4 @@ import { PENCIL_COLUMNS, defaultPalettes, defaultPencils } from "./data/defaults
|
|
|
33
35
|
import { useColorValue, useTransientColor } from "./core/useColorStore.cjs";
|
|
34
36
|
import { useAxisKeyboard, usePointerDrag } from "./core/usePointerDrag.cjs";
|
|
35
37
|
import { injectStyles, setStyleNonce } from "./core/styleInjector.cjs";
|
|
36
|
-
export { ChannelSlider, type ChannelSliderProps, type ChromaClassNames, ChromaPanel, type ChromaPanelProps, ColorArea, type ColorAreaProps, ColorChangeResult, ColorDisc, type ColorDiscProps, ColorField, type ColorFieldProps, ColorFormat, ColorInput, type ColorInputProps, type ColorListener, type ColorPalette, type ColorStore, type ContrastOptions, type ContrastReport, type ExtractOptions, type ExtractResult, type Eyedropper, Hsl, Hsla, Hsva, Hwb, Hwba, Icon, type IconName, type IconProps, ImagePanel, type ModeId, ModeToolbar, type ModeToolbarProps, NumberField, type NumberFieldProps, PENCIL_COLUMNS, PalettesPanel, PanelFooter, type PanelOptions, PencilsPanel, type PickerMode, Popover, type PopoverProps, type QuantizedSwatch, Rgb, Rgba, SegmentedControl, type SegmentedControlProps, type SegmentedItem, SlidersPanel, Swatch, type SwatchEntry, SwatchGrid, type SwatchGridProps, type SwatchProps, type SwatchVariant, type TextSize, type Unsubscribe, type WcagLevel, WheelPanel, apcaContrast, clamp, clearNamedColors, contrastRatio, contrastReport, createColorStore, defaultPalettes, defaultPencils, extractPalette, getMode, hslaToHsva, hsvaToHsl, hsvaToHsla, hsvaToHwba, hsvaToRgb, hsvaToRgba, hwbaToHsva, imageMode, ingest, injectStyles, isValidColor, meetsContrast, meetsNonTextContrast, normalizeHue, palettesMode, parse, pencilsMode, pushRecent, quantize, readableTextColor, registerMode, registerNamedColors, relativeLuminance, resolveModes, rgbaToHsva, roundRgba, sameHsva, sameRendered, setStyleNonce, slidersMode, toFormat, toHex, toHexa, toHslString, toHslaString, toResult, toRgbString, toRgbaString, useAxisKeyboard, useColorValue, useEyedropper, usePanel, usePointerDrag, useTransientColor, wcagLevel, wheelMode };
|
|
38
|
+
export { type AccessibleColorSuggestion, ChannelSlider, type ChannelSliderProps, type ChromaClassNames, ChromaPanel, type ChromaPanelProps, ColorArea, type ColorAreaProps, ColorChangeMeta, ColorChangeResult, ColorChangeSource, ColorDisc, type ColorDiscProps, ColorField, type ColorFieldProps, ColorFormat, ColorInput, type ColorInputProps, type ColorListener, type ColorPalette, type ColorStore, ColorValue, type ContrastOptions, type ContrastReport, type ExtractOptions, type ExtractResult, type Eyedropper, Hsl, Hsla, Hsva, Hwb, Hwba, Icon, type IconName, type IconProps, ImagePanel, type ModeId, ModeToolbar, type ModeToolbarProps, ModernColorSpace, NumberField, type NumberFieldProps, PENCIL_COLUMNS, PalettesPanel, PanelFooter, type PanelOptions, PencilsPanel, type PickerMode, Popover, type PopoverProps, type QuantizedSwatch, Rgb, Rgba, SegmentedControl, type SegmentedControlProps, type SegmentedItem, SerializeColorOptions, SlidersPanel, Swatch, type SwatchEntry, SwatchGrid, type SwatchGridProps, type SwatchProps, type SwatchVariant, type TextSize, type Unsubscribe, type WcagLevel, WheelPanel, apcaContrast, clamp, clearNamedColors, colorValueToHsva, compositeColor, contrastRatio, contrastRatioWithAlpha, contrastReport, convertColor, createColorStore, defaultPalettes, defaultPencils, extractPalette, getMode, hslaToHsva, hsvaToColorValue, hsvaToHsl, hsvaToHsla, hsvaToHwba, hsvaToRgb, hsvaToRgba, hwbaToHsva, imageMode, ingest, injectStyles, isInGamut, isValidColor, mapToGamut, meetsContrast, meetsNonTextContrast, normalizeHue, palettesMode, parse, parseColor, parseCss4Color, pencilsMode, pushRecent, quantize, readableTextColor, registerMode, registerNamedColors, relativeLuminance, resolveModes, rgbaToHsva, roundRgba, sameHsva, sameRendered, serializeColor, setStyleNonce, slidersMode, suggestAccessibleColor, toFormat, toHex, toHexa, toHslString, toHslaString, toResult, toRgbString, toRgbaString, useAxisKeyboard, useColorValue, useEyedropper, usePanel, usePointerDrag, useTransientColor, wcagLevel, wheelMode };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { ColorChangeResult, ColorFormat, Hsl, Hsla, Hsva, Hwb, Hwba, Rgb, Rgba } from "./color/types.js";
|
|
2
|
-
import { ContrastOptions, ContrastReport, TextSize, WcagLevel, apcaContrast, contrastRatio, contrastReport, meetsContrast, meetsNonTextContrast, readableTextColor, relativeLuminance, wcagLevel } from "./a11y/contrast.js";
|
|
1
|
+
import { ColorChangeMeta, ColorChangeResult, ColorChangeSource, ColorFormat, ColorValue, Hsl, Hsla, Hsva, Hwb, Hwba, ModernColorSpace, Rgb, Rgba, SerializeColorOptions } from "./color/types.js";
|
|
3
2
|
import { clamp, hslaToHsva, hsvaToHsl, hsvaToHsla, hsvaToHwba, hsvaToRgb, hsvaToRgba, hwbaToHsva, normalizeHue, rgbaToHsva, roundRgba } from "./color/convert.js";
|
|
4
3
|
import { clearNamedColors, isValidColor, parse, registerNamedColors } from "./color/parse.js";
|
|
4
|
+
import { parseColor } from "./color/value.js";
|
|
5
|
+
import { colorValueToHsva, convertColor, hsvaToColorValue, isInGamut, mapToGamut, parseCss4Color, serializeColor } from "./color/css4.js";
|
|
5
6
|
import { toFormat, toHex, toHexa, toHslString, toHslaString, toResult, toRgbString, toRgbaString } from "./color/serialize.js";
|
|
6
7
|
import { ingest, sameHsva, sameRendered } from "./color/sticky.js";
|
|
7
8
|
import { ColorListener, ColorStore, Unsubscribe, createColorStore } from "./core/store.js";
|
|
9
|
+
import { AccessibleColorSuggestion, ContrastOptions, ContrastReport, TextSize, WcagLevel, apcaContrast, compositeColor, contrastRatio, contrastRatioWithAlpha, contrastReport, meetsContrast, meetsNonTextContrast, readableTextColor, relativeLuminance, suggestAccessibleColor, wcagLevel } from "./a11y/contrast.js";
|
|
8
10
|
import { QuantizedSwatch, quantize } from "./image/mmcq.js";
|
|
9
11
|
import { ExtractOptions, ExtractResult, extractPalette } from "./image/extract.js";
|
|
10
12
|
import { ModeId, PickerMode, getMode, registerMode, resolveModes } from "./modes/registry.js";
|
|
@@ -33,4 +35,4 @@ import { PENCIL_COLUMNS, defaultPalettes, defaultPencils } from "./data/defaults
|
|
|
33
35
|
import { useColorValue, useTransientColor } from "./core/useColorStore.js";
|
|
34
36
|
import { useAxisKeyboard, usePointerDrag } from "./core/usePointerDrag.js";
|
|
35
37
|
import { injectStyles, setStyleNonce } from "./core/styleInjector.js";
|
|
36
|
-
export { ChannelSlider, type ChannelSliderProps, type ChromaClassNames, ChromaPanel, type ChromaPanelProps, ColorArea, type ColorAreaProps, ColorChangeResult, ColorDisc, type ColorDiscProps, ColorField, type ColorFieldProps, ColorFormat, ColorInput, type ColorInputProps, type ColorListener, type ColorPalette, type ColorStore, type ContrastOptions, type ContrastReport, type ExtractOptions, type ExtractResult, type Eyedropper, Hsl, Hsla, Hsva, Hwb, Hwba, Icon, type IconName, type IconProps, ImagePanel, type ModeId, ModeToolbar, type ModeToolbarProps, NumberField, type NumberFieldProps, PENCIL_COLUMNS, PalettesPanel, PanelFooter, type PanelOptions, PencilsPanel, type PickerMode, Popover, type PopoverProps, type QuantizedSwatch, Rgb, Rgba, SegmentedControl, type SegmentedControlProps, type SegmentedItem, SlidersPanel, Swatch, type SwatchEntry, SwatchGrid, type SwatchGridProps, type SwatchProps, type SwatchVariant, type TextSize, type Unsubscribe, type WcagLevel, WheelPanel, apcaContrast, clamp, clearNamedColors, contrastRatio, contrastReport, createColorStore, defaultPalettes, defaultPencils, extractPalette, getMode, hslaToHsva, hsvaToHsl, hsvaToHsla, hsvaToHwba, hsvaToRgb, hsvaToRgba, hwbaToHsva, imageMode, ingest, injectStyles, isValidColor, meetsContrast, meetsNonTextContrast, normalizeHue, palettesMode, parse, pencilsMode, pushRecent, quantize, readableTextColor, registerMode, registerNamedColors, relativeLuminance, resolveModes, rgbaToHsva, roundRgba, sameHsva, sameRendered, setStyleNonce, slidersMode, toFormat, toHex, toHexa, toHslString, toHslaString, toResult, toRgbString, toRgbaString, useAxisKeyboard, useColorValue, useEyedropper, usePanel, usePointerDrag, useTransientColor, wcagLevel, wheelMode };
|
|
38
|
+
export { type AccessibleColorSuggestion, ChannelSlider, type ChannelSliderProps, type ChromaClassNames, ChromaPanel, type ChromaPanelProps, ColorArea, type ColorAreaProps, ColorChangeMeta, ColorChangeResult, ColorChangeSource, ColorDisc, type ColorDiscProps, ColorField, type ColorFieldProps, ColorFormat, ColorInput, type ColorInputProps, type ColorListener, type ColorPalette, type ColorStore, ColorValue, type ContrastOptions, type ContrastReport, type ExtractOptions, type ExtractResult, type Eyedropper, Hsl, Hsla, Hsva, Hwb, Hwba, Icon, type IconName, type IconProps, ImagePanel, type ModeId, ModeToolbar, type ModeToolbarProps, ModernColorSpace, NumberField, type NumberFieldProps, PENCIL_COLUMNS, PalettesPanel, PanelFooter, type PanelOptions, PencilsPanel, type PickerMode, Popover, type PopoverProps, type QuantizedSwatch, Rgb, Rgba, SegmentedControl, type SegmentedControlProps, type SegmentedItem, SerializeColorOptions, SlidersPanel, Swatch, type SwatchEntry, SwatchGrid, type SwatchGridProps, type SwatchProps, type SwatchVariant, type TextSize, type Unsubscribe, type WcagLevel, WheelPanel, apcaContrast, clamp, clearNamedColors, colorValueToHsva, compositeColor, contrastRatio, contrastRatioWithAlpha, contrastReport, convertColor, createColorStore, defaultPalettes, defaultPencils, extractPalette, getMode, hslaToHsva, hsvaToColorValue, hsvaToHsl, hsvaToHsla, hsvaToHwba, hsvaToRgb, hsvaToRgba, hwbaToHsva, imageMode, ingest, injectStyles, isInGamut, isValidColor, mapToGamut, meetsContrast, meetsNonTextContrast, normalizeHue, palettesMode, parse, parseColor, parseCss4Color, pencilsMode, pushRecent, quantize, readableTextColor, registerMode, registerNamedColors, relativeLuminance, resolveModes, rgbaToHsva, roundRgba, sameHsva, sameRendered, serializeColor, setStyleNonce, slidersMode, suggestAccessibleColor, toFormat, toHex, toHexa, toHslString, toHslaString, toResult, toRgbString, toRgbaString, useAxisKeyboard, useColorValue, useEyedropper, usePanel, usePointerDrag, useTransientColor, wcagLevel, wheelMode };
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { useColorValue, useTransientColor } from "./core/useColorStore.js";
|
|
|
6
6
|
import { useAxisKeyboard, usePointerDrag } from "./core/usePointerDrag.js";
|
|
7
7
|
import { ChannelSlider } from "./primitives/ChannelSlider.js";
|
|
8
8
|
import { ColorDisc } from "./primitives/ColorDisc.js";
|
|
9
|
+
import { colorValueToHsva, convertColor, hsvaToColorValue, isInGamut, mapToGamut, parseCss4Color, serializeColor } from "./color/css4.js";
|
|
9
10
|
import { clearNamedColors, isValidColor, parse, registerNamedColors } from "./color/parse.js";
|
|
10
11
|
import { toFormat, toHex, toHexa, toHslString, toHslaString, toResult, toRgbString, toRgbaString } from "./color/serialize.js";
|
|
11
12
|
import { ColorField } from "./primitives/ColorField.js";
|
|
@@ -32,7 +33,8 @@ import { Popover } from "./components/Popover.js";
|
|
|
32
33
|
import { ColorInput } from "./components/ColorInput.js";
|
|
33
34
|
import { ColorArea } from "./primitives/ColorArea.js";
|
|
34
35
|
import { Swatch } from "./primitives/Swatch.js";
|
|
35
|
-
import {
|
|
36
|
+
import { parseColor } from "./color/value.js";
|
|
37
|
+
import { apcaContrast, compositeColor, contrastRatio, contrastRatioWithAlpha, contrastReport, meetsContrast, meetsNonTextContrast, readableTextColor, relativeLuminance, suggestAccessibleColor, wcagLevel } from "./a11y/contrast.js";
|
|
36
38
|
//#region src/index.ts
|
|
37
39
|
registerMode(wheelMode);
|
|
38
40
|
registerMode(slidersMode);
|
|
@@ -40,5 +42,5 @@ registerMode(palettesMode);
|
|
|
40
42
|
registerMode(imageMode);
|
|
41
43
|
registerMode(pencilsMode);
|
|
42
44
|
//#endregion
|
|
43
|
-
export { ChannelSlider, ChromaPanel, ColorArea, ColorDisc, ColorField, ColorInput, Icon, ImagePanel, ModeToolbar, NumberField, PENCIL_COLUMNS, PalettesPanel, PanelFooter, PencilsPanel, Popover, SegmentedControl, SlidersPanel, Swatch, SwatchGrid, WheelPanel, apcaContrast, clamp, clearNamedColors, contrastRatio, contrastReport, createColorStore, defaultPalettes, defaultPencils, extractPalette, getMode, hslaToHsva, hsvaToHsl, hsvaToHsla, hsvaToHwba, hsvaToRgb, hsvaToRgba, hwbaToHsva, imageMode, ingest, injectStyles, isValidColor, meetsContrast, meetsNonTextContrast, normalizeHue, palettesMode, parse, pencilsMode, pushRecent, quantize, readableTextColor, registerMode, registerNamedColors, relativeLuminance, resolveModes, rgbaToHsva, roundRgba, sameHsva, sameRendered, setStyleNonce, slidersMode, toFormat, toHex, toHexa, toHslString, toHslaString, toResult, toRgbString, toRgbaString, useAxisKeyboard, useColorValue, useEyedropper, usePanel, usePointerDrag, useTransientColor, wcagLevel, wheelMode };
|
|
45
|
+
export { ChannelSlider, ChromaPanel, ColorArea, ColorDisc, ColorField, ColorInput, Icon, ImagePanel, ModeToolbar, NumberField, PENCIL_COLUMNS, PalettesPanel, PanelFooter, PencilsPanel, Popover, SegmentedControl, SlidersPanel, Swatch, SwatchGrid, WheelPanel, apcaContrast, clamp, clearNamedColors, colorValueToHsva, compositeColor, contrastRatio, contrastRatioWithAlpha, contrastReport, convertColor, createColorStore, defaultPalettes, defaultPencils, extractPalette, getMode, hslaToHsva, hsvaToColorValue, hsvaToHsl, hsvaToHsla, hsvaToHwba, hsvaToRgb, hsvaToRgba, hwbaToHsva, imageMode, ingest, injectStyles, isInGamut, isValidColor, mapToGamut, meetsContrast, meetsNonTextContrast, normalizeHue, palettesMode, parse, parseColor, parseCss4Color, pencilsMode, pushRecent, quantize, readableTextColor, registerMode, registerNamedColors, relativeLuminance, resolveModes, rgbaToHsva, roundRgba, sameHsva, sameRendered, serializeColor, setStyleNonce, slidersMode, suggestAccessibleColor, toFormat, toHex, toHexa, toHslString, toHslaString, toResult, toRgbString, toRgbaString, useAxisKeyboard, useColorValue, useEyedropper, usePanel, usePointerDrag, useTransientColor, wcagLevel, wheelMode };
|
|
44
46
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
const require_runtime = require("../../_virtual/_rolldown/runtime.cjs");
|
|
3
3
|
const require_context = require("../../core/context.cjs");
|
|
4
|
+
const require_convert = require("../../color/convert.cjs");
|
|
5
|
+
const require_parse = require("../../color/parse.cjs");
|
|
4
6
|
const require_icons = require("../../primitives/icons.cjs");
|
|
5
7
|
const require_SwatchGrid = require("../../primitives/SwatchGrid.cjs");
|
|
6
8
|
const require_extract = require("../../image/extract.cjs");
|
|
@@ -16,7 +18,7 @@ const EMPTY = {
|
|
|
16
18
|
preview: null
|
|
17
19
|
};
|
|
18
20
|
function ImagePanel(props) {
|
|
19
|
-
const { extractOptions } = props;
|
|
21
|
+
const { extractOptions, sortBy = "population" } = props;
|
|
20
22
|
const { idPrefix, disabled } = require_context.usePanel();
|
|
21
23
|
const inputId = `${idPrefix}-image-file`;
|
|
22
24
|
const { store } = require_context.usePanel();
|
|
@@ -25,7 +27,13 @@ function ImagePanel(props) {
|
|
|
25
27
|
const [message, setMessage] = react.useState(restored.message);
|
|
26
28
|
const [swatches, setSwatches] = react.useState(restored.swatches);
|
|
27
29
|
const [preview, setPreview] = react.useState(restored.preview);
|
|
30
|
+
const [point, setPoint] = react.useState(null);
|
|
28
31
|
const inputRef = react.useRef(null);
|
|
32
|
+
const imageRef = react.useRef(null);
|
|
33
|
+
const [clipboardRead, setClipboardRead] = react.useState(false);
|
|
34
|
+
react.useEffect(() => {
|
|
35
|
+
setClipboardRead(typeof navigator.clipboard?.read === "function");
|
|
36
|
+
}, []);
|
|
29
37
|
react.useEffect(() => {
|
|
30
38
|
if (preview === null && status === "idle") kept.delete(store);
|
|
31
39
|
else kept.set(store, {
|
|
@@ -84,6 +92,50 @@ function ImagePanel(props) {
|
|
|
84
92
|
const file = files?.[0];
|
|
85
93
|
if (file !== void 0) run(file);
|
|
86
94
|
};
|
|
95
|
+
const pasteFile = (items) => {
|
|
96
|
+
for (const item of Array.from(items)) {
|
|
97
|
+
if (item.kind !== "file" || !item.type.startsWith("image/")) continue;
|
|
98
|
+
const file = item.getAsFile();
|
|
99
|
+
if (file !== null) run(file);
|
|
100
|
+
return file !== null;
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
};
|
|
104
|
+
const readClipboard = async () => {
|
|
105
|
+
try {
|
|
106
|
+
const items = await navigator.clipboard.read();
|
|
107
|
+
for (const item of items) {
|
|
108
|
+
const type = item.types.find((candidate) => candidate.startsWith("image/"));
|
|
109
|
+
if (type === void 0) continue;
|
|
110
|
+
const blob = await item.getType(type);
|
|
111
|
+
await run(new File([blob], "clipboard-image", { type }));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
setStatus("error");
|
|
115
|
+
setMessage("The clipboard does not contain an image.");
|
|
116
|
+
} catch {
|
|
117
|
+
setStatus("error");
|
|
118
|
+
setMessage("Clipboard access was not allowed. Use paste or choose a file instead.");
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const sortedSwatches = react.useMemo(() => [...swatches].sort((a, b) => {
|
|
122
|
+
if (sortBy === "population") return b.population - a.population;
|
|
123
|
+
if (sortBy === "luminance") {
|
|
124
|
+
const luminance = (rgb) => .2126 * rgb[0] + .7152 * rgb[1] + .0722 * rgb[2];
|
|
125
|
+
return luminance(b.rgb) - luminance(a.rgb);
|
|
126
|
+
}
|
|
127
|
+
return require_convert.rgbaToHsva({
|
|
128
|
+
r: a.rgb[0],
|
|
129
|
+
g: a.rgb[1],
|
|
130
|
+
b: a.rgb[2],
|
|
131
|
+
a: 1
|
|
132
|
+
}).h - require_convert.rgbaToHsva({
|
|
133
|
+
r: b.rgb[0],
|
|
134
|
+
g: b.rgb[1],
|
|
135
|
+
b: b.rgb[2],
|
|
136
|
+
a: 1
|
|
137
|
+
}).h;
|
|
138
|
+
}), [swatches, sortBy]);
|
|
87
139
|
const clear = () => {
|
|
88
140
|
controller.current?.abort();
|
|
89
141
|
releasePreview();
|
|
@@ -91,8 +143,47 @@ function ImagePanel(props) {
|
|
|
91
143
|
setSwatches([]);
|
|
92
144
|
setMessage("");
|
|
93
145
|
setStatus("idle");
|
|
146
|
+
setPoint(null);
|
|
94
147
|
if (inputRef.current !== null) inputRef.current.value = "";
|
|
95
148
|
};
|
|
149
|
+
const locate = (image, clientX, clientY) => {
|
|
150
|
+
const rect = image.getBoundingClientRect();
|
|
151
|
+
if (rect.width <= 0 || rect.height <= 0 || image.naturalWidth <= 0 || image.naturalHeight <= 0) return null;
|
|
152
|
+
const scale = Math.min(rect.width / image.naturalWidth, rect.height / image.naturalHeight);
|
|
153
|
+
const width = image.naturalWidth * scale;
|
|
154
|
+
const height = image.naturalHeight * scale;
|
|
155
|
+
const left = rect.left + (rect.width - width) / 2;
|
|
156
|
+
const top = rect.top + (rect.height - height) / 2;
|
|
157
|
+
if (clientX < left || clientX > left + width || clientY < top || clientY > top + height) return null;
|
|
158
|
+
return {
|
|
159
|
+
x: Math.min(1, Math.max(0, (clientX - left) / width)),
|
|
160
|
+
y: Math.min(1, Math.max(0, (clientY - top) / height)),
|
|
161
|
+
left: Math.min(1, Math.max(0, (clientX - rect.left) / rect.width)),
|
|
162
|
+
top: Math.min(1, Math.max(0, (clientY - rect.top) / rect.height))
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
const selectPixel = (next) => {
|
|
166
|
+
const image = imageRef.current;
|
|
167
|
+
if (image === null || image.naturalWidth <= 0 || image.naturalHeight <= 0) return;
|
|
168
|
+
const canvas = document.createElement("canvas");
|
|
169
|
+
canvas.width = 1;
|
|
170
|
+
canvas.height = 1;
|
|
171
|
+
const context = canvas.getContext("2d", { willReadFrequently: true });
|
|
172
|
+
if (context === null) return;
|
|
173
|
+
const sx = Math.min(image.naturalWidth - 1, Math.floor(next.x * image.naturalWidth));
|
|
174
|
+
const sy = Math.min(image.naturalHeight - 1, Math.floor(next.y * image.naturalHeight));
|
|
175
|
+
context.drawImage(image, sx, sy, 1, 1, 0, 0, 1, 1);
|
|
176
|
+
const [r = 0, g = 0, b = 0, a = 0] = context.getImageData(0, 0, 1, 1).data;
|
|
177
|
+
if (a === 0) {
|
|
178
|
+
setMessage("That pixel is transparent. Choose another point.");
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const parsed = require_parse.parse(`rgba(${r}, ${g}, ${b}, ${Math.round(a / 255 * 1e3) / 1e3})`);
|
|
182
|
+
if (parsed === null) return;
|
|
183
|
+
store.ingest(parsed, "image");
|
|
184
|
+
store.commit("image");
|
|
185
|
+
setMessage("Color selected from image.");
|
|
186
|
+
};
|
|
96
187
|
const dragDepth = react.useRef(0);
|
|
97
188
|
const [dragging, setDragging] = react.useState(false);
|
|
98
189
|
const endDrag = () => {
|
|
@@ -101,6 +192,9 @@ function ImagePanel(props) {
|
|
|
101
192
|
};
|
|
102
193
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
103
194
|
className: "cp-panel",
|
|
195
|
+
onPaste: (event) => {
|
|
196
|
+
if (!disabled && pasteFile(event.clipboardData.items)) event.preventDefault();
|
|
197
|
+
},
|
|
104
198
|
onDragEnter: (e) => {
|
|
105
199
|
e.preventDefault();
|
|
106
200
|
if (disabled) return;
|
|
@@ -145,18 +239,52 @@ function ImagePanel(props) {
|
|
|
145
239
|
]
|
|
146
240
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
147
241
|
className: "cp-image-preview",
|
|
148
|
-
children: [
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
242
|
+
children: [
|
|
243
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
244
|
+
ref: imageRef,
|
|
245
|
+
src: preview,
|
|
246
|
+
alt: "Uploaded image. Move over it and click to select a color.",
|
|
247
|
+
role: "button",
|
|
248
|
+
tabIndex: disabled ? -1 : 0,
|
|
249
|
+
"aria-label": "Pick a color from the uploaded image",
|
|
250
|
+
onPointerMove: (event) => setPoint(locate(event.currentTarget, event.clientX, event.clientY)),
|
|
251
|
+
onPointerLeave: () => setPoint(null),
|
|
252
|
+
onClick: (event) => {
|
|
253
|
+
if (disabled) return;
|
|
254
|
+
const next = locate(event.currentTarget, event.clientX, event.clientY);
|
|
255
|
+
if (next !== null) selectPixel(next);
|
|
256
|
+
},
|
|
257
|
+
onKeyDown: (event) => {
|
|
258
|
+
if (disabled || event.key !== "Enter" && event.key !== " ") return;
|
|
259
|
+
event.preventDefault();
|
|
260
|
+
selectPixel(point ?? {
|
|
261
|
+
x: .5,
|
|
262
|
+
y: .5,
|
|
263
|
+
left: .5,
|
|
264
|
+
top: .5
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}),
|
|
268
|
+
point !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
269
|
+
className: "cp-image-loupe",
|
|
270
|
+
"aria-hidden": "true",
|
|
271
|
+
style: {
|
|
272
|
+
left: `${point.left * 100}%`,
|
|
273
|
+
top: `${point.top * 100}%`,
|
|
274
|
+
backgroundImage: `url("${preview}")`,
|
|
275
|
+
backgroundPosition: `${point.x * 100}% ${point.y * 100}%`
|
|
276
|
+
}
|
|
277
|
+
}),
|
|
278
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
279
|
+
type: "button",
|
|
280
|
+
className: "cp-image-remove",
|
|
281
|
+
"aria-label": "Remove image",
|
|
282
|
+
title: "Remove image",
|
|
283
|
+
disabled,
|
|
284
|
+
onClick: clear,
|
|
285
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons.Icon, { name: "x" })
|
|
286
|
+
})
|
|
287
|
+
]
|
|
160
288
|
}),
|
|
161
289
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
162
290
|
ref: inputRef,
|
|
@@ -169,12 +297,25 @@ function ImagePanel(props) {
|
|
|
169
297
|
tabIndex: preview === null ? void 0 : -1,
|
|
170
298
|
onChange: (e) => onFiles(e.currentTarget.files)
|
|
171
299
|
}),
|
|
300
|
+
preview === null && clipboardRead && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
301
|
+
type: "button",
|
|
302
|
+
className: "cp-button",
|
|
303
|
+
disabled,
|
|
304
|
+
onClick: () => {
|
|
305
|
+
readClipboard();
|
|
306
|
+
},
|
|
307
|
+
children: "Paste image"
|
|
308
|
+
}),
|
|
172
309
|
preview !== null && status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
173
310
|
className: "cp-empty",
|
|
174
311
|
children: message
|
|
175
312
|
}),
|
|
313
|
+
preview !== null && status !== "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
314
|
+
className: "cp-image-hint",
|
|
315
|
+
children: "Click the image to pick an exact color."
|
|
316
|
+
}),
|
|
176
317
|
status === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_SwatchGrid.SwatchGrid, {
|
|
177
|
-
swatches:
|
|
318
|
+
swatches: sortedSwatches.map((s) => ({
|
|
178
319
|
color: s.hex,
|
|
179
320
|
name: s.hex
|
|
180
321
|
})),
|
|
@@ -4,6 +4,7 @@ import * as React from "react";
|
|
|
4
4
|
//#region src/modes/image/index.d.ts
|
|
5
5
|
export interface ImagePanelProps {
|
|
6
6
|
extractOptions?: ExtractOptions;
|
|
7
|
+
sortBy?: "population" | "luminance" | "hue";
|
|
7
8
|
}
|
|
8
9
|
export declare function ImagePanel(props: ImagePanelProps): React.ReactElement;
|
|
9
10
|
export declare const imageMode: PickerMode;
|
|
@@ -4,6 +4,7 @@ import * as React from "react";
|
|
|
4
4
|
//#region src/modes/image/index.d.ts
|
|
5
5
|
export interface ImagePanelProps {
|
|
6
6
|
extractOptions?: ExtractOptions;
|
|
7
|
+
sortBy?: "population" | "luminance" | "hue";
|
|
7
8
|
}
|
|
8
9
|
export declare function ImagePanel(props: ImagePanelProps): React.ReactElement;
|
|
9
10
|
export declare const imageMode: PickerMode;
|