colibri-ui 0.8.96 → 0.8.97
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/ColorPicker/ColorPicker.d.ts +3 -0
- package/ColorPicker/ColorPicker.js +116 -0
- package/ColorPicker/ColorPicker.module.css +22 -0
- package/ColorPicker/assets/none.png +0 -0
- package/ColorPicker/components/ColorPreview/ColorPreview.module.css +23 -0
- package/ColorPicker/components/ColorPreview/index.d.ts +10 -0
- package/ColorPicker/components/ColorPreview/index.js +29 -0
- package/ColorPicker/components/CustomColorModal/CustomColorModal.module.css +18 -0
- package/ColorPicker/components/CustomColorModal/index.d.ts +15 -0
- package/ColorPicker/components/CustomColorModal/index.js +107 -0
- package/ColorPicker/components/HueSlider/HueSlider.module.css +31 -0
- package/ColorPicker/components/HueSlider/index.d.ts +10 -0
- package/ColorPicker/components/HueSlider/index.js +73 -0
- package/ColorPicker/components/Palette/Palette.module.css +12 -0
- package/ColorPicker/components/Palette/index.d.ts +19 -0
- package/ColorPicker/components/Palette/index.js +99 -0
- package/ColorPicker/components/SaturationPanel/SaturationPanel.module.css +26 -0
- package/ColorPicker/components/SaturationPanel/index.d.ts +13 -0
- package/ColorPicker/components/SaturationPanel/index.js +86 -0
- package/ColorPicker/components/Swatch/Swatch.module.css +36 -0
- package/ColorPicker/components/Swatch/index.d.ts +14 -0
- package/ColorPicker/components/Swatch/index.js +47 -0
- package/ColorPicker/hooks/useEyeDropper.d.ts +8 -0
- package/ColorPicker/hooks/useEyeDropper.js +38 -0
- package/ColorPicker/hooks/useHexDraft.d.ts +19 -0
- package/ColorPicker/hooks/useHexDraft.js +49 -0
- package/ColorPicker/hooks/usePointerDrag.d.ts +20 -0
- package/ColorPicker/hooks/usePointerDrag.js +55 -0
- package/ColorPicker/index.d.ts +3 -0
- package/ColorPicker/index.js +9 -0
- package/ColorPicker/index.props.d.ts +43 -0
- package/ColorPicker/package.json +9 -0
- package/ColorPicker/presets.d.ts +3 -0
- package/ColorPicker/presets.js +92 -0
- package/ColorPicker/utils/color.d.ts +25 -0
- package/ColorPicker/utils/color.js +162 -0
- package/Icons/Pipette.d.ts +3 -0
- package/Icons/Pipette.js +35 -0
- package/Icons/index.d.ts +1 -0
- package/Icons/index.js +2 -0
- package/esm/ColorPicker/ColorPicker.d.ts +3 -0
- package/esm/ColorPicker/ColorPicker.js +108 -0
- package/esm/ColorPicker/ColorPicker.module.css +22 -0
- package/esm/ColorPicker/assets/none.png +0 -0
- package/esm/ColorPicker/components/ColorPreview/ColorPreview.module.css +23 -0
- package/esm/ColorPicker/components/ColorPreview/index.d.ts +10 -0
- package/esm/ColorPicker/components/ColorPreview/index.js +21 -0
- package/esm/ColorPicker/components/CustomColorModal/CustomColorModal.module.css +18 -0
- package/esm/ColorPicker/components/CustomColorModal/index.d.ts +15 -0
- package/esm/ColorPicker/components/CustomColorModal/index.js +100 -0
- package/esm/ColorPicker/components/HueSlider/HueSlider.module.css +31 -0
- package/esm/ColorPicker/components/HueSlider/index.d.ts +10 -0
- package/esm/ColorPicker/components/HueSlider/index.js +66 -0
- package/esm/ColorPicker/components/Palette/Palette.module.css +12 -0
- package/esm/ColorPicker/components/Palette/index.d.ts +19 -0
- package/esm/ColorPicker/components/Palette/index.js +92 -0
- package/esm/ColorPicker/components/SaturationPanel/SaturationPanel.module.css +26 -0
- package/esm/ColorPicker/components/SaturationPanel/index.d.ts +13 -0
- package/esm/ColorPicker/components/SaturationPanel/index.js +79 -0
- package/esm/ColorPicker/components/Swatch/Swatch.module.css +36 -0
- package/esm/ColorPicker/components/Swatch/index.d.ts +14 -0
- package/esm/ColorPicker/components/Swatch/index.js +38 -0
- package/esm/ColorPicker/hooks/useEyeDropper.d.ts +8 -0
- package/esm/ColorPicker/hooks/useEyeDropper.js +36 -0
- package/esm/ColorPicker/hooks/useHexDraft.d.ts +19 -0
- package/esm/ColorPicker/hooks/useHexDraft.js +47 -0
- package/esm/ColorPicker/hooks/usePointerDrag.d.ts +20 -0
- package/esm/ColorPicker/hooks/usePointerDrag.js +53 -0
- package/esm/ColorPicker/index.d.ts +3 -0
- package/esm/ColorPicker/index.js +2 -0
- package/esm/ColorPicker/index.props.d.ts +43 -0
- package/esm/ColorPicker/presets.d.ts +3 -0
- package/esm/ColorPicker/presets.js +89 -0
- package/esm/ColorPicker/utils/color.d.ts +25 -0
- package/esm/ColorPicker/utils/color.js +152 -0
- package/esm/Icons/Pipette.d.ts +3 -0
- package/esm/Icons/Pipette.js +29 -0
- package/esm/Icons/index.d.ts +1 -0
- package/esm/Icons/index.js +1 -0
- package/esm/index.d.ts +2 -0
- package/esm/index.js +3 -0
- package/index.d.ts +2 -0
- package/index.js +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var clsx = require('clsx');
|
|
5
|
+
var index = require('../Button/index.js');
|
|
6
|
+
var index$1 = require('../Dropdown/index.js');
|
|
7
|
+
var index$3 = require('./components/CustomColorModal/index.js');
|
|
8
|
+
var index$2 = require('./components/Palette/index.js');
|
|
9
|
+
var presets = require('./presets.js');
|
|
10
|
+
var color = require('./utils/color.js');
|
|
11
|
+
var styles = require('./ColorPicker.module.css');
|
|
12
|
+
|
|
13
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
+
|
|
15
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
16
|
+
var clsx__default = /*#__PURE__*/_interopDefault(clsx);
|
|
17
|
+
var styles__default = /*#__PURE__*/_interopDefault(styles);
|
|
18
|
+
|
|
19
|
+
const normalizePresets = presets => presets.flatMap(preset => {
|
|
20
|
+
const value = color.normalizeHex(preset.value);
|
|
21
|
+
return value ? [Object.assign(Object.assign({}, preset), {
|
|
22
|
+
value
|
|
23
|
+
})] : [];
|
|
24
|
+
});
|
|
25
|
+
const ColorPicker = ({
|
|
26
|
+
value,
|
|
27
|
+
onChange,
|
|
28
|
+
presets: presets$1 = presets.COLOR_PICKER_PRESETS,
|
|
29
|
+
columns = 6,
|
|
30
|
+
disabled,
|
|
31
|
+
placement = "bottom-start",
|
|
32
|
+
zIndex,
|
|
33
|
+
labels: labelsProp,
|
|
34
|
+
children
|
|
35
|
+
}) => {
|
|
36
|
+
var _a, _b;
|
|
37
|
+
const [isOpen, setOpen] = React.useState(false);
|
|
38
|
+
const [isCustomOpen, setCustomOpen] = React.useState(false);
|
|
39
|
+
const rootRef = React.useRef(null);
|
|
40
|
+
const overlayRef = React.useRef(null);
|
|
41
|
+
const labels = Object.assign(Object.assign({}, presets.DEFAULT_LABELS), labelsProp);
|
|
42
|
+
const current = value ? color.normalizeHex(value) : null;
|
|
43
|
+
const normalizedPresets = React.useMemo(() => normalizePresets(presets$1), [presets$1]);
|
|
44
|
+
// Selection, "+" and Escape remove the focused swatch together with the
|
|
45
|
+
// dropdown: return focus to the trigger. The custom color dialog then
|
|
46
|
+
// restores focus to the trigger as well.
|
|
47
|
+
const closeDropdown = () => {
|
|
48
|
+
var _a, _b;
|
|
49
|
+
const trigger = (_a = rootRef.current) === null || _a === void 0 ? void 0 : _a.firstElementChild;
|
|
50
|
+
if (((_b = overlayRef.current) === null || _b === void 0 ? void 0 : _b.contains(document.activeElement)) && trigger instanceof HTMLElement) {
|
|
51
|
+
trigger.focus();
|
|
52
|
+
}
|
|
53
|
+
setOpen(false);
|
|
54
|
+
};
|
|
55
|
+
const handleVisibleChange = visible => {
|
|
56
|
+
if (visible) setOpen(true);else closeDropdown();
|
|
57
|
+
};
|
|
58
|
+
const handleSelect = hex => {
|
|
59
|
+
closeDropdown();
|
|
60
|
+
onChange(hex);
|
|
61
|
+
};
|
|
62
|
+
const handleAddClick = () => {
|
|
63
|
+
closeDropdown();
|
|
64
|
+
setCustomOpen(true);
|
|
65
|
+
};
|
|
66
|
+
const handleSave = hex => {
|
|
67
|
+
setCustomOpen(false);
|
|
68
|
+
onChange(hex);
|
|
69
|
+
};
|
|
70
|
+
const trigger = children !== null && children !== void 0 ? children : (/*#__PURE__*/React__default.default.createElement(index.Button, {
|
|
71
|
+
variant: "outline",
|
|
72
|
+
className: clsx__default.default({
|
|
73
|
+
[styles__default.default.trigger_empty]: !current
|
|
74
|
+
}),
|
|
75
|
+
disabled: disabled,
|
|
76
|
+
"aria-label": labels.trigger,
|
|
77
|
+
icon: /*#__PURE__*/React__default.default.createElement("span", {
|
|
78
|
+
className: clsx__default.default(styles__default.default.dot, {
|
|
79
|
+
[styles__default.default.dot_hidden]: !current
|
|
80
|
+
}),
|
|
81
|
+
style: current ? {
|
|
82
|
+
backgroundColor: current
|
|
83
|
+
} : undefined
|
|
84
|
+
})
|
|
85
|
+
}));
|
|
86
|
+
return /*#__PURE__*/React__default.default.createElement("span", {
|
|
87
|
+
ref: rootRef,
|
|
88
|
+
className: styles__default.default.root
|
|
89
|
+
}, /*#__PURE__*/React__default.default.createElement(index$1.Dropdown, {
|
|
90
|
+
trigger: ["click"],
|
|
91
|
+
visible: isOpen,
|
|
92
|
+
onVisibleChange: handleVisibleChange,
|
|
93
|
+
preventAutoClose: true,
|
|
94
|
+
disabled: disabled,
|
|
95
|
+
placement: placement,
|
|
96
|
+
zIndex: zIndex,
|
|
97
|
+
overlay: /*#__PURE__*/React__default.default.createElement("div", {
|
|
98
|
+
ref: overlayRef
|
|
99
|
+
}, /*#__PURE__*/React__default.default.createElement(index$2.Palette, {
|
|
100
|
+
presets: normalizedPresets,
|
|
101
|
+
value: current,
|
|
102
|
+
columns: columns,
|
|
103
|
+
labels: labels,
|
|
104
|
+
onSelect: handleSelect,
|
|
105
|
+
onAddClick: handleAddClick,
|
|
106
|
+
onTabOut: closeDropdown
|
|
107
|
+
}))
|
|
108
|
+
}, trigger), isCustomOpen && (/*#__PURE__*/React__default.default.createElement(index$3.CustomColorModal, {
|
|
109
|
+
initialColor: (_b = current !== null && current !== void 0 ? current : (_a = normalizedPresets[0]) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : "#000000",
|
|
110
|
+
labels: labels,
|
|
111
|
+
onSave: handleSave,
|
|
112
|
+
onClose: () => setCustomOpen(false)
|
|
113
|
+
})));
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
exports.ColorPicker = ColorPicker;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
display: contents;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.dot {
|
|
6
|
+
border-radius: var(--radius-full);
|
|
7
|
+
box-shadow: inset 0 0 0 var(--border-width-hairline) var(--color-border-default);
|
|
8
|
+
display: block;
|
|
9
|
+
height: var(--space-4);
|
|
10
|
+
width: var(--space-4);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.trigger_empty {
|
|
14
|
+
background-image: url("./assets/none.png");
|
|
15
|
+
background-position: center;
|
|
16
|
+
background-repeat: no-repeat;
|
|
17
|
+
background-size: cover;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.dot_hidden {
|
|
21
|
+
display: none;
|
|
22
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
align-items: center;
|
|
3
|
+
border-radius: var(--radius-full);
|
|
4
|
+
box-shadow: inset 0 0 0 var(--border-width-hairline) var(--color-border-subtle);
|
|
5
|
+
display: inline-flex;
|
|
6
|
+
flex-shrink: 0;
|
|
7
|
+
font-family: var(--font-family-ui);
|
|
8
|
+
font-size: var(--font-size-heading-md);
|
|
9
|
+
font-weight: var(--font-weight-medium);
|
|
10
|
+
height: var(--space-12);
|
|
11
|
+
justify-content: center;
|
|
12
|
+
line-height: 1;
|
|
13
|
+
transition: background-color 0.1s ease, color 0.1s ease;
|
|
14
|
+
width: var(--space-12);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.text_light {
|
|
18
|
+
color: var(--color-neutral-0);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.text_dark {
|
|
22
|
+
color: var(--color-neutral-950);
|
|
23
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import type { HSV } from "../../utils/color";
|
|
4
|
+
interface ColorPreviewProps {
|
|
5
|
+
color: HSV;
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/** Circle with the color and a sample text in the automatically adjusted color. */
|
|
9
|
+
export declare const ColorPreview: ({ color, children }: ColorPreviewProps) => React.JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var clsx = require('clsx');
|
|
5
|
+
var color = require('../../utils/color.js');
|
|
6
|
+
var styles = require('./ColorPreview.module.css');
|
|
7
|
+
|
|
8
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
|
|
10
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
11
|
+
var clsx__default = /*#__PURE__*/_interopDefault(clsx);
|
|
12
|
+
var styles__default = /*#__PURE__*/_interopDefault(styles);
|
|
13
|
+
|
|
14
|
+
/** Circle with the color and a sample text in the automatically adjusted color. */
|
|
15
|
+
const ColorPreview = ({
|
|
16
|
+
color: color$1,
|
|
17
|
+
children
|
|
18
|
+
}) => {
|
|
19
|
+
const hex = color.hsv2hex(color$1);
|
|
20
|
+
return /*#__PURE__*/React__default.default.createElement("span", {
|
|
21
|
+
"aria-hidden": "true",
|
|
22
|
+
className: clsx__default.default(styles__default.default.root, color.prefersLightText(hex) ? styles__default.default.text_light : styles__default.default.text_dark),
|
|
23
|
+
style: {
|
|
24
|
+
backgroundColor: hex
|
|
25
|
+
}
|
|
26
|
+
}, children);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
exports.ColorPreview = ColorPreview;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
.picker {
|
|
2
|
+
align-items: start;
|
|
3
|
+
display: grid;
|
|
4
|
+
gap: var(--space-5) var(--space-4);
|
|
5
|
+
grid-template-columns: auto 1fr;
|
|
6
|
+
margin-top: var(--space-5);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.side {
|
|
10
|
+
align-items: center;
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-direction: column;
|
|
13
|
+
gap: var(--space-4);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.full_row {
|
|
17
|
+
grid-column: 1/-1;
|
|
18
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { ColorPickerLabels } from "../../index.props";
|
|
3
|
+
interface CustomColorModalProps {
|
|
4
|
+
/** `#rrggbb` the picker starts from. */
|
|
5
|
+
initialColor: string;
|
|
6
|
+
labels: ColorPickerLabels;
|
|
7
|
+
onSave: (hex: string) => void;
|
|
8
|
+
onClose: () => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* "Choose custom color" dialog. The draft is kept in HSV: HEX loses hue and
|
|
12
|
+
* saturation of grey and black, and the sliders would jump.
|
|
13
|
+
*/
|
|
14
|
+
export declare const CustomColorModal: ({ initialColor, labels, onSave, onClose, }: CustomColorModalProps) => React.JSX.Element;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var index$3 = require('../../../Button/index.js');
|
|
5
|
+
require('../../../Icons/index.js');
|
|
6
|
+
var index$6 = require('../../../Input/index.js');
|
|
7
|
+
var index = require('../../../Modal/index.js');
|
|
8
|
+
var index$1 = require('../../../Typography/index.js');
|
|
9
|
+
var useEyeDropper = require('../../hooks/useEyeDropper.js');
|
|
10
|
+
var useHexDraft = require('../../hooks/useHexDraft.js');
|
|
11
|
+
var color = require('../../utils/color.js');
|
|
12
|
+
var index$2 = require('../ColorPreview/index.js');
|
|
13
|
+
var index$5 = require('../HueSlider/index.js');
|
|
14
|
+
var index$4 = require('../SaturationPanel/index.js');
|
|
15
|
+
var styles = require('./CustomColorModal.module.css');
|
|
16
|
+
var Pipette = require('../../../Icons/Pipette.js');
|
|
17
|
+
|
|
18
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
19
|
+
|
|
20
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
21
|
+
var styles__default = /*#__PURE__*/_interopDefault(styles);
|
|
22
|
+
|
|
23
|
+
const BLACK = {
|
|
24
|
+
h: 0,
|
|
25
|
+
s: 0,
|
|
26
|
+
v: 0
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* "Choose custom color" dialog. The draft is kept in HSV: HEX loses hue and
|
|
30
|
+
* saturation of grey and black, and the sliders would jump.
|
|
31
|
+
*/
|
|
32
|
+
const CustomColorModal = ({
|
|
33
|
+
initialColor,
|
|
34
|
+
labels,
|
|
35
|
+
onSave,
|
|
36
|
+
onClose
|
|
37
|
+
}) => {
|
|
38
|
+
const [color$1, setColor] = React.useState(() => {
|
|
39
|
+
var _a;
|
|
40
|
+
return (_a = color.hex2hsv(initialColor)) !== null && _a !== void 0 ? _a : BLACK;
|
|
41
|
+
});
|
|
42
|
+
const hex = color.hsv2hex(color$1);
|
|
43
|
+
const {
|
|
44
|
+
isSupported,
|
|
45
|
+
pick
|
|
46
|
+
} = useEyeDropper.useEyeDropper();
|
|
47
|
+
const setHex = next => setColor(prev => {
|
|
48
|
+
var _a;
|
|
49
|
+
return (_a = color.toHsvPreservingHue(next, prev)) !== null && _a !== void 0 ? _a : prev;
|
|
50
|
+
});
|
|
51
|
+
const {
|
|
52
|
+
invalid,
|
|
53
|
+
inputProps
|
|
54
|
+
} = useHexDraft.useHexDraft(hex, setHex);
|
|
55
|
+
const handlePick = async () => {
|
|
56
|
+
const picked = await pick();
|
|
57
|
+
if (picked) setHex(picked);
|
|
58
|
+
};
|
|
59
|
+
return /*#__PURE__*/React__default.default.createElement(index.Modal, {
|
|
60
|
+
onClose: onClose
|
|
61
|
+
}, /*#__PURE__*/React__default.default.createElement(index.Modal.Header, null, /*#__PURE__*/React__default.default.createElement(index.Modal.Title, null, labels.customTitle)), /*#__PURE__*/React__default.default.createElement(index.Modal.Body, null, /*#__PURE__*/React__default.default.createElement(index$1.Typography, {
|
|
62
|
+
tag: "p",
|
|
63
|
+
variant: "secondary",
|
|
64
|
+
size: "text-sm"
|
|
65
|
+
}, labels.customDescription), /*#__PURE__*/React__default.default.createElement("div", {
|
|
66
|
+
className: styles__default.default.picker
|
|
67
|
+
}, /*#__PURE__*/React__default.default.createElement("div", {
|
|
68
|
+
className: styles__default.default.side
|
|
69
|
+
}, /*#__PURE__*/React__default.default.createElement(index$2.ColorPreview, {
|
|
70
|
+
color: color$1
|
|
71
|
+
}, labels.preview), isSupported && (/*#__PURE__*/React__default.default.createElement(index$3.Button, {
|
|
72
|
+
variant: "secondary",
|
|
73
|
+
size: "l",
|
|
74
|
+
icon: /*#__PURE__*/React__default.default.createElement(Pipette.Pipette, {
|
|
75
|
+
width: 20,
|
|
76
|
+
height: 20,
|
|
77
|
+
"aria-hidden": "true"
|
|
78
|
+
}),
|
|
79
|
+
"aria-label": labels.eyeDropper,
|
|
80
|
+
title: labels.eyeDropper,
|
|
81
|
+
onClick: handlePick
|
|
82
|
+
}))), /*#__PURE__*/React__default.default.createElement(index$4.SaturationPanel, {
|
|
83
|
+
value: color$1,
|
|
84
|
+
onChange: setColor,
|
|
85
|
+
"aria-label": labels.saturation
|
|
86
|
+
}), /*#__PURE__*/React__default.default.createElement("div", {
|
|
87
|
+
className: styles__default.default.full_row
|
|
88
|
+
}, /*#__PURE__*/React__default.default.createElement(index$5.HueSlider, {
|
|
89
|
+
value: color$1,
|
|
90
|
+
onChange: setColor,
|
|
91
|
+
"aria-label": labels.hue
|
|
92
|
+
})), /*#__PURE__*/React__default.default.createElement(index$6.Input, Object.assign({
|
|
93
|
+
className: styles__default.default.full_row,
|
|
94
|
+
label: labels.hex,
|
|
95
|
+
hasError: invalid,
|
|
96
|
+
maxLength: 7,
|
|
97
|
+
spellCheck: false,
|
|
98
|
+
autoComplete: "off"
|
|
99
|
+
}, inputProps)))), /*#__PURE__*/React__default.default.createElement(index.Modal.Footer, null, /*#__PURE__*/React__default.default.createElement(index$3.Button, {
|
|
100
|
+
variant: "clear",
|
|
101
|
+
onClick: onClose
|
|
102
|
+
}, labels.cancel), /*#__PURE__*/React__default.default.createElement(index$3.Button, {
|
|
103
|
+
onClick: () => onSave(hex)
|
|
104
|
+
}, labels.save)));
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
exports.CustomColorModal = CustomColorModal;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
background: linear-gradient(to right, hsl(0, 100%, 50%), hsl(60, 100%, 50%), hsl(120, 100%, 50%), hsl(180, 100%, 50%), hsl(240, 100%, 50%), hsl(300, 100%, 50%), hsl(0, 100%, 50%));
|
|
3
|
+
border-radius: var(--radius-full);
|
|
4
|
+
cursor: pointer;
|
|
5
|
+
height: var(--space-3);
|
|
6
|
+
outline: none;
|
|
7
|
+
position: relative;
|
|
8
|
+
touch-action: none;
|
|
9
|
+
-webkit-user-select: none;
|
|
10
|
+
user-select: none;
|
|
11
|
+
}
|
|
12
|
+
.root::before {
|
|
13
|
+
content: "";
|
|
14
|
+
inset: calc(var(--space-2) * -1) 0;
|
|
15
|
+
position: absolute;
|
|
16
|
+
}
|
|
17
|
+
.root:focus-visible {
|
|
18
|
+
box-shadow: 0 0 0 var(--focus-ring-width) var(--color-focus-ring);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.thumb {
|
|
22
|
+
border: var(--focus-ring-width) solid var(--color-neutral-0);
|
|
23
|
+
border-radius: var(--radius-full);
|
|
24
|
+
box-shadow: var(--shadow-raised);
|
|
25
|
+
height: var(--space-5);
|
|
26
|
+
pointer-events: none;
|
|
27
|
+
position: absolute;
|
|
28
|
+
top: 50%;
|
|
29
|
+
transform: translate(-50%, -50%);
|
|
30
|
+
width: var(--space-5);
|
|
31
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { HSV } from "../../utils/color";
|
|
3
|
+
interface HueSliderProps {
|
|
4
|
+
value: HSV;
|
|
5
|
+
onChange: (value: HSV) => void;
|
|
6
|
+
"aria-label": string;
|
|
7
|
+
}
|
|
8
|
+
/** Hue bar. Arrow keys change by 1°, with Shift by 10°, Home/End go to the ends. */
|
|
9
|
+
export declare const HueSlider: ({ value, onChange, "aria-label": ariaLabel, }: HueSliderProps) => React.JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var usePointerDrag = require('../../hooks/usePointerDrag.js');
|
|
5
|
+
var color = require('../../utils/color.js');
|
|
6
|
+
var styles = require('./HueSlider.module.css');
|
|
7
|
+
|
|
8
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
|
|
10
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
11
|
+
var styles__default = /*#__PURE__*/_interopDefault(styles);
|
|
12
|
+
|
|
13
|
+
const STEP = 1;
|
|
14
|
+
const BIG_STEP = 10;
|
|
15
|
+
/** Hue bar. Arrow keys change by 1°, with Shift by 10°, Home/End go to the ends. */
|
|
16
|
+
const HueSlider = ({
|
|
17
|
+
value,
|
|
18
|
+
onChange,
|
|
19
|
+
"aria-label": ariaLabel
|
|
20
|
+
}) => {
|
|
21
|
+
const {
|
|
22
|
+
h
|
|
23
|
+
} = value;
|
|
24
|
+
const {
|
|
25
|
+
ref,
|
|
26
|
+
handlers
|
|
27
|
+
} = usePointerDrag.usePointerDrag(({
|
|
28
|
+
x
|
|
29
|
+
}) => onChange(Object.assign(Object.assign({}, value), {
|
|
30
|
+
h: x * 360
|
|
31
|
+
})));
|
|
32
|
+
const handleKeyDown = event => {
|
|
33
|
+
const step = event.shiftKey ? BIG_STEP : STEP;
|
|
34
|
+
const next = {
|
|
35
|
+
ArrowLeft: h - step,
|
|
36
|
+
ArrowDown: h - step,
|
|
37
|
+
ArrowRight: h + step,
|
|
38
|
+
ArrowUp: h + step,
|
|
39
|
+
Home: 0,
|
|
40
|
+
End: 360
|
|
41
|
+
};
|
|
42
|
+
if (!(event.key in next)) return;
|
|
43
|
+
event.preventDefault();
|
|
44
|
+
onChange(Object.assign(Object.assign({}, value), {
|
|
45
|
+
h: color.clamp(next[event.key], 0, 360)
|
|
46
|
+
}));
|
|
47
|
+
};
|
|
48
|
+
return /*#__PURE__*/React__default.default.createElement("div", Object.assign({
|
|
49
|
+
ref: ref
|
|
50
|
+
}, handlers, {
|
|
51
|
+
role: "slider",
|
|
52
|
+
tabIndex: 0,
|
|
53
|
+
"aria-label": ariaLabel,
|
|
54
|
+
"aria-orientation": "horizontal",
|
|
55
|
+
"aria-valuemin": 0,
|
|
56
|
+
"aria-valuemax": 360,
|
|
57
|
+
"aria-valuenow": Math.round(h),
|
|
58
|
+
onKeyDown: handleKeyDown,
|
|
59
|
+
className: styles__default.default.root
|
|
60
|
+
}), /*#__PURE__*/React__default.default.createElement("div", {
|
|
61
|
+
className: styles__default.default.thumb,
|
|
62
|
+
style: {
|
|
63
|
+
left: `${h / 360 * 100}%`,
|
|
64
|
+
backgroundColor: color.hsv2css({
|
|
65
|
+
h,
|
|
66
|
+
s: 100,
|
|
67
|
+
v: 100
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
}));
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
exports.HueSlider = HueSlider;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { ColorPickerLabels, ColorPickerPreset } from "../../index.props";
|
|
3
|
+
interface PaletteProps {
|
|
4
|
+
presets: ColorPickerPreset[];
|
|
5
|
+
/** Normalized `#rrggbb` of the current color. */
|
|
6
|
+
value: string | null;
|
|
7
|
+
columns: number;
|
|
8
|
+
labels: ColorPickerLabels;
|
|
9
|
+
onSelect: (hex: string) => void;
|
|
10
|
+
onAddClick: () => void;
|
|
11
|
+
/** Tab or Shift+Tab leaves the palette. */
|
|
12
|
+
onTabOut: () => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Preset grid with the "+" button. A current color missing from the presets
|
|
16
|
+
* is shown as an extra swatch before "+".
|
|
17
|
+
*/
|
|
18
|
+
export declare const Palette: ({ presets, value, columns, labels, onSelect, onAddClick, onTabOut, }: PaletteProps) => React.JSX.Element;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var index$1 = require('../../../Button/index.js');
|
|
5
|
+
require('../../../Icons/index.js');
|
|
6
|
+
var index = require('../Swatch/index.js');
|
|
7
|
+
var styles = require('./Palette.module.css');
|
|
8
|
+
var Plus = require('../../../Icons/Plus.js');
|
|
9
|
+
|
|
10
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
|
|
12
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
13
|
+
var styles__default = /*#__PURE__*/_interopDefault(styles);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Preset grid with the "+" button. A current color missing from the presets
|
|
17
|
+
* is shown as an extra swatch before "+".
|
|
18
|
+
*/
|
|
19
|
+
const Palette = ({
|
|
20
|
+
presets,
|
|
21
|
+
value,
|
|
22
|
+
columns,
|
|
23
|
+
labels,
|
|
24
|
+
onSelect,
|
|
25
|
+
onAddClick,
|
|
26
|
+
onTabOut
|
|
27
|
+
}) => {
|
|
28
|
+
const rootRef = React.useRef(null);
|
|
29
|
+
const hasPreset = presets.some(preset => preset.value === value);
|
|
30
|
+
const colors = value && !hasPreset ? [...presets, {
|
|
31
|
+
value,
|
|
32
|
+
label: value
|
|
33
|
+
}] : presets;
|
|
34
|
+
// The dropdown is portaled to the end of the document: move focus into it,
|
|
35
|
+
// to the selected swatch or the first item ("+" when there are no colors).
|
|
36
|
+
React.useEffect(() => {
|
|
37
|
+
var _a, _b;
|
|
38
|
+
const root = rootRef.current;
|
|
39
|
+
(_b = (_a = root === null || root === void 0 ? void 0 : root.querySelector('[aria-checked="true"]')) !== null && _a !== void 0 ? _a : root === null || root === void 0 ? void 0 : root.querySelector("button")) === null || _b === void 0 ? void 0 : _b.focus();
|
|
40
|
+
}, []);
|
|
41
|
+
// Arrow keys move focus across the grid, Home/End go to the first and the
|
|
42
|
+
// last item. Tab leaves the portaled palette through the trigger, so focus
|
|
43
|
+
// continues from it, also inside a parent focus trap.
|
|
44
|
+
const handleKeyDown = event => {
|
|
45
|
+
var _a;
|
|
46
|
+
if (event.key === "Tab") {
|
|
47
|
+
onTabOut();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const items = Array.from(event.currentTarget.querySelectorAll("button"));
|
|
51
|
+
const index = items.indexOf(event.target);
|
|
52
|
+
const offsets = {
|
|
53
|
+
ArrowLeft: -1,
|
|
54
|
+
ArrowRight: 1,
|
|
55
|
+
ArrowUp: -columns,
|
|
56
|
+
ArrowDown: columns,
|
|
57
|
+
Home: -index,
|
|
58
|
+
End: items.length - 1 - index
|
|
59
|
+
};
|
|
60
|
+
if (index === -1 || !(event.key in offsets)) return;
|
|
61
|
+
event.preventDefault();
|
|
62
|
+
(_a = items[index + offsets[event.key]]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
63
|
+
};
|
|
64
|
+
return (
|
|
65
|
+
/*#__PURE__*/
|
|
66
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- keys come from the focused items
|
|
67
|
+
React__default.default.createElement("div", {
|
|
68
|
+
ref: rootRef,
|
|
69
|
+
role: "group",
|
|
70
|
+
"aria-label": labels.palette,
|
|
71
|
+
className: styles__default.default.root,
|
|
72
|
+
onKeyDown: handleKeyDown,
|
|
73
|
+
style: {
|
|
74
|
+
gridTemplateColumns: `repeat(${columns}, auto)`
|
|
75
|
+
}
|
|
76
|
+
}, colors.map(color => (/*#__PURE__*/React__default.default.createElement(index.Swatch, {
|
|
77
|
+
key: color.value,
|
|
78
|
+
color: color.value,
|
|
79
|
+
label: color.label,
|
|
80
|
+
selected: color.value === value,
|
|
81
|
+
onClick: () => onSelect(color.value)
|
|
82
|
+
}))), /*#__PURE__*/React__default.default.createElement(index$1.Button, {
|
|
83
|
+
className: styles__default.default.add,
|
|
84
|
+
variant: "secondary",
|
|
85
|
+
size: "xs",
|
|
86
|
+
icon: /*#__PURE__*/React__default.default.createElement(Plus.Plus, {
|
|
87
|
+
width: 12,
|
|
88
|
+
height: 12,
|
|
89
|
+
"aria-hidden": "true"
|
|
90
|
+
}),
|
|
91
|
+
role: "menuitem",
|
|
92
|
+
"aria-label": labels.addCustom,
|
|
93
|
+
title: labels.addCustom,
|
|
94
|
+
onClick: onAddClick
|
|
95
|
+
}))
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
exports.Palette = Palette;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
background-image: linear-gradient(to top, black, transparent), linear-gradient(to right, white, transparent);
|
|
3
|
+
border-radius: var(--radius-sm);
|
|
4
|
+
cursor: crosshair;
|
|
5
|
+
height: var(--space-32);
|
|
6
|
+
outline: none;
|
|
7
|
+
position: relative;
|
|
8
|
+
touch-action: none;
|
|
9
|
+
-webkit-user-select: none;
|
|
10
|
+
user-select: none;
|
|
11
|
+
width: 100%;
|
|
12
|
+
}
|
|
13
|
+
.root:focus-visible {
|
|
14
|
+
box-shadow: 0 0 0 var(--focus-ring-width) var(--color-focus-ring);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.thumb {
|
|
18
|
+
border: var(--focus-ring-width) solid var(--color-neutral-0);
|
|
19
|
+
border-radius: var(--radius-full);
|
|
20
|
+
box-shadow: var(--shadow-raised);
|
|
21
|
+
height: var(--space-5);
|
|
22
|
+
pointer-events: none;
|
|
23
|
+
position: absolute;
|
|
24
|
+
transform: translate(-50%, -50%);
|
|
25
|
+
width: var(--space-5);
|
|
26
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { HSV } from "../../utils/color";
|
|
3
|
+
interface SaturationPanelProps {
|
|
4
|
+
value: HSV;
|
|
5
|
+
onChange: (value: HSV) => void;
|
|
6
|
+
"aria-label": string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Saturation (horizontal) and brightness (vertical) area. Arrow keys change
|
|
10
|
+
* by 1, with Shift by 10.
|
|
11
|
+
*/
|
|
12
|
+
export declare const SaturationPanel: ({ value, onChange, "aria-label": ariaLabel, }: SaturationPanelProps) => React.JSX.Element;
|
|
13
|
+
export {};
|