@remotion/studio 4.0.463 → 4.0.465
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/dist/components/CanvasOrLoading.js +1 -1
- package/dist/components/ColorPicker/AlphaSlider.d.ts +9 -0
- package/dist/components/ColorPicker/AlphaSlider.js +88 -0
- package/dist/components/ColorPicker/ColorPicker.d.ts +18 -0
- package/dist/components/ColorPicker/ColorPicker.js +176 -0
- package/dist/components/ColorPicker/ColorPickerPopup.d.ts +8 -0
- package/dist/components/ColorPicker/ColorPickerPopup.js +276 -0
- package/dist/components/ColorPicker/HueSlider.d.ts +6 -0
- package/dist/components/ColorPicker/HueSlider.js +68 -0
- package/dist/components/ColorPicker/SaturationValueArea.d.ts +14 -0
- package/dist/components/ColorPicker/SaturationValueArea.js +93 -0
- package/dist/components/ColorPicker/checker.d.ts +4 -0
- package/dist/components/ColorPicker/checker.js +9 -0
- package/dist/components/ExpandedTracksProvider.d.ts +2 -0
- package/dist/components/ExpandedTracksProvider.js +18 -1
- package/dist/components/NewComposition/CodemodFooter.d.ts +1 -0
- package/dist/components/NewComposition/CodemodFooter.js +35 -23
- package/dist/components/NewComposition/DeleteComposition.js +3 -1
- package/dist/components/NewComposition/DiffPreview.js +1 -1
- package/dist/components/NewComposition/DuplicateComposition.js +3 -1
- package/dist/components/NewComposition/RenameComposition.js +4 -2
- package/dist/components/RenderModal/SchemaEditor/ZodColorEditor.js +8 -47
- package/dist/components/RenderQueue/actions.d.ts +2 -1
- package/dist/components/RenderQueue/actions.js +2 -1
- package/dist/components/Timeline/Padder.js +2 -2
- package/dist/components/Timeline/SubscribeToNodePaths.d.ts +1 -1
- package/dist/components/Timeline/SubscribeToNodePaths.js +9 -4
- package/dist/components/Timeline/Timeline.js +4 -7
- package/dist/components/Timeline/TimelineColorField.js +18 -156
- package/dist/components/Timeline/TimelineEffectFieldRow.d.ts +1 -2
- package/dist/components/Timeline/TimelineEffectFieldRow.js +22 -31
- package/dist/components/Timeline/TimelineEffectGroupRow.d.ts +1 -2
- package/dist/components/Timeline/TimelineEffectGroupRow.js +67 -12
- package/dist/components/Timeline/TimelineExpandedRow.js +15 -30
- package/dist/components/Timeline/TimelineFieldRow.d.ts +1 -2
- package/dist/components/Timeline/TimelineFieldRow.js +19 -16
- package/dist/components/Timeline/TimelineImageInfo.js +5 -17
- package/dist/components/Timeline/TimelineListItem.d.ts +0 -1
- package/dist/components/Timeline/TimelineListItem.js +12 -14
- package/dist/components/Timeline/TimelineRowChrome.d.ts +8 -0
- package/dist/components/Timeline/TimelineRowChrome.js +21 -0
- package/dist/components/Timeline/TimelineTimeIndicators.js +4 -11
- package/dist/components/Timeline/TimelineTracks.js +0 -4
- package/dist/components/Timeline/TimelineVideoInfo.js +25 -8
- package/dist/components/Timeline/get-timeline-video-info-widths.d.ts +9 -0
- package/dist/components/Timeline/get-timeline-video-info-widths.js +11 -0
- package/dist/components/Timeline/save-effect-prop.d.ts +2 -1
- package/dist/components/Timeline/save-effect-prop.js +2 -13
- package/dist/components/Timeline/save-prop-queue.d.ts +1 -2
- package/dist/components/Timeline/save-prop-queue.js +3 -12
- package/dist/components/Timeline/save-sequence-prop.d.ts +2 -1
- package/dist/components/Timeline/save-sequence-prop.js +2 -11
- package/dist/components/Timeline/should-show-track-in-timeline.d.ts +2 -0
- package/dist/components/Timeline/should-show-track-in-timeline.js +23 -0
- package/dist/components/Timeline/timeline-field-row-layout.d.ts +2 -0
- package/dist/components/Timeline/timeline-field-row-layout.js +14 -0
- package/dist/components/Timeline/timeline-indent.d.ts +1 -0
- package/dist/components/Timeline/timeline-indent.js +4 -0
- package/dist/components/Timeline/timeline-row-layout.d.ts +11 -0
- package/dist/components/Timeline/timeline-row-layout.js +27 -0
- package/dist/components/Timeline/use-resolved-stack-react-to-change.d.ts +2 -0
- package/dist/components/Timeline/use-resolved-stack-react-to-change.js +59 -0
- package/dist/components/Timeline/use-resolved-stack.d.ts +1 -0
- package/dist/components/Timeline/use-resolved-stack.js +10 -1
- package/dist/components/Timeline/use-sequence-props-subscription.js +27 -1
- package/dist/error-overlay/remotion-overlay/ShortcutHint.js +5 -3
- package/dist/esm/chunk-6jf1natv.js +25 -0
- package/dist/esm/{chunk-b0m62frw.js → chunk-pqk2qd0d.js} +4971 -4013
- package/dist/esm/index.mjs +16 -0
- package/dist/esm/internals.mjs +4984 -4011
- package/dist/esm/previewEntry.mjs +4995 -4023
- package/dist/esm/renderEntry.mjs +4 -3
- package/dist/helpers/client-id.d.ts +2 -9
- package/dist/helpers/client-id.js +15 -40
- package/dist/helpers/color-conversion.d.ts +36 -0
- package/dist/helpers/color-conversion.js +121 -0
- package/dist/helpers/inject-css.js +4 -7
- package/dist/helpers/migrate-expanded-tracks-for-subscription-key.d.ts +3 -0
- package/dist/helpers/migrate-expanded-tracks-for-subscription-key.js +26 -0
- package/dist/helpers/preview-server-events.d.ts +15 -0
- package/dist/helpers/preview-server-events.js +81 -0
- package/dist/helpers/resolved-stack-to-symbolicated.d.ts +3 -0
- package/dist/helpers/resolved-stack-to-symbolicated.js +16 -0
- package/dist/helpers/timeline-layout.d.ts +0 -1
- package/dist/helpers/timeline-layout.js +29 -25
- package/dist/hot-middleware-client/client.js +10 -16
- package/package.json +10 -10
- package/dist/components/NewComposition/RemInputTypeColor.d.ts +0 -8
- package/dist/components/NewComposition/RemInputTypeColor.js +0 -53
- package/dist/components/Timeline/is-collapsed.d.ts +0 -2
- package/dist/components/Timeline/is-collapsed.js +0 -10
- package/dist/esm/chunk-5gtx3pza.js +0 -9
- package/dist/helpers/color-math.d.ts +0 -1
- package/dist/helpers/color-math.js +0 -13
|
@@ -81,7 +81,7 @@ const loaderContainer = {
|
|
|
81
81
|
overflowY: 'auto',
|
|
82
82
|
};
|
|
83
83
|
const ErrorLoading = ({ error, calculateMetadataContext }) => {
|
|
84
|
-
return (jsx_runtime_1.jsx("div", { style: loaderContainer, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ErrorLoader_1.ErrorLoader, { canHaveDismissButton: false, keyboardShortcuts:
|
|
84
|
+
return (jsx_runtime_1.jsx("div", { style: loaderContainer, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ErrorLoader_1.ErrorLoader, { canHaveDismissButton: false, keyboardShortcuts: true, error: error, onRetry: () => {
|
|
85
85
|
var _a;
|
|
86
86
|
return (_a = remotion_1.Internals.resolveCompositionsRef.current) === null || _a === void 0 ? void 0 : _a.reloadCurrentlySelectedComposition();
|
|
87
87
|
}, calculateMetadata: calculateMetadataContext }, error.stack) }));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare const AlphaSlider: React.FC<{
|
|
3
|
+
readonly hue: number;
|
|
4
|
+
readonly saturation: number;
|
|
5
|
+
readonly value: number;
|
|
6
|
+
readonly alpha: number;
|
|
7
|
+
readonly onChange: (next: number) => void;
|
|
8
|
+
readonly onChangeComplete: (next: number) => void;
|
|
9
|
+
}>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AlphaSlider = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const color_conversion_1 = require("../../helpers/color-conversion");
|
|
7
|
+
const checker_1 = require("./checker");
|
|
8
|
+
const SLIDER_HEIGHT = 12;
|
|
9
|
+
const HANDLE_WIDTH = 8;
|
|
10
|
+
const wrapperStyle = {
|
|
11
|
+
position: 'relative',
|
|
12
|
+
height: SLIDER_HEIGHT,
|
|
13
|
+
width: '100%',
|
|
14
|
+
borderRadius: 3,
|
|
15
|
+
overflow: 'hidden',
|
|
16
|
+
cursor: 'ew-resize',
|
|
17
|
+
backgroundColor: checker_1.CHECKER_BACKGROUND_COLOR,
|
|
18
|
+
backgroundImage: checker_1.CHECKER_BACKGROUND_IMAGE,
|
|
19
|
+
backgroundSize: checker_1.CHECKER_BACKGROUND_SIZE,
|
|
20
|
+
backgroundPosition: checker_1.CHECKER_BACKGROUND_POSITION,
|
|
21
|
+
touchAction: 'none',
|
|
22
|
+
};
|
|
23
|
+
const innerStyle = {
|
|
24
|
+
position: 'absolute',
|
|
25
|
+
inset: 0,
|
|
26
|
+
};
|
|
27
|
+
const AlphaSlider = ({ hue, saturation, value, alpha, onChange, onChangeComplete }) => {
|
|
28
|
+
const ref = (0, react_1.useRef)(null);
|
|
29
|
+
const opaqueColor = (0, react_1.useMemo)(() => {
|
|
30
|
+
const { r, g, b } = (0, color_conversion_1.hsvToRgb)({ h: hue, s: saturation, v: value });
|
|
31
|
+
return `rgb(${r}, ${g}, ${b})`;
|
|
32
|
+
}, [hue, saturation, value]);
|
|
33
|
+
const gradientStyle = (0, react_1.useMemo)(() => {
|
|
34
|
+
return {
|
|
35
|
+
...innerStyle,
|
|
36
|
+
background: `linear-gradient(to right, rgba(0, 0, 0, 0), ${opaqueColor})`,
|
|
37
|
+
};
|
|
38
|
+
}, [opaqueColor]);
|
|
39
|
+
const updateFromEvent = (0, react_1.useCallback)((clientX, isFinal) => {
|
|
40
|
+
const { current } = ref;
|
|
41
|
+
if (!current) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const rect = current.getBoundingClientRect();
|
|
45
|
+
const next = (0, color_conversion_1.clamp)((clientX - rect.left) / rect.width, 0, 1);
|
|
46
|
+
if (isFinal) {
|
|
47
|
+
onChangeComplete(next);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
onChange(next);
|
|
51
|
+
}
|
|
52
|
+
}, [onChange, onChangeComplete]);
|
|
53
|
+
const onPointerDown = (0, react_1.useCallback)((e) => {
|
|
54
|
+
if (e.button !== 0) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
e.preventDefault();
|
|
58
|
+
updateFromEvent(e.clientX, false);
|
|
59
|
+
const onMove = (ev) => {
|
|
60
|
+
updateFromEvent(ev.clientX, false);
|
|
61
|
+
};
|
|
62
|
+
const onUp = (ev) => {
|
|
63
|
+
window.removeEventListener('pointermove', onMove);
|
|
64
|
+
window.removeEventListener('pointerup', onUp);
|
|
65
|
+
updateFromEvent(ev.clientX, true);
|
|
66
|
+
};
|
|
67
|
+
window.addEventListener('pointermove', onMove);
|
|
68
|
+
window.addEventListener('pointerup', onUp);
|
|
69
|
+
}, [updateFromEvent]);
|
|
70
|
+
const handleStyle = (0, react_1.useMemo)(() => {
|
|
71
|
+
return {
|
|
72
|
+
position: 'absolute',
|
|
73
|
+
top: -2,
|
|
74
|
+
left: `${alpha * 100}%`,
|
|
75
|
+
marginLeft: -HANDLE_WIDTH / 2,
|
|
76
|
+
width: HANDLE_WIDTH,
|
|
77
|
+
height: SLIDER_HEIGHT + 4,
|
|
78
|
+
borderRadius: 2,
|
|
79
|
+
border: '2px solid #fff',
|
|
80
|
+
boxShadow: '0 0 0 1px rgba(0, 0, 0, 0.6)',
|
|
81
|
+
pointerEvents: 'none',
|
|
82
|
+
};
|
|
83
|
+
}, [alpha]);
|
|
84
|
+
return (jsx_runtime_1.jsxs("div", { ref: ref, style: wrapperStyle, onPointerDown: onPointerDown, children: [
|
|
85
|
+
jsx_runtime_1.jsx("div", { style: gradientStyle }), jsx_runtime_1.jsx("div", { style: handleStyle })
|
|
86
|
+
] }));
|
|
87
|
+
};
|
|
88
|
+
exports.AlphaSlider = AlphaSlider;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { RemInputStatus } from '../NewComposition/RemInput';
|
|
3
|
+
type Props = {
|
|
4
|
+
readonly value: string;
|
|
5
|
+
readonly onChange: (next: string) => void;
|
|
6
|
+
readonly onChangeComplete: (next: string) => void;
|
|
7
|
+
readonly status: RemInputStatus;
|
|
8
|
+
readonly disabled?: boolean;
|
|
9
|
+
readonly width?: number;
|
|
10
|
+
readonly height?: number;
|
|
11
|
+
readonly borderRadius?: number;
|
|
12
|
+
readonly title?: string;
|
|
13
|
+
readonly name?: string;
|
|
14
|
+
readonly className?: string;
|
|
15
|
+
readonly style?: React.CSSProperties;
|
|
16
|
+
};
|
|
17
|
+
export declare const ColorPicker: React.FC<Props>;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ColorPicker = void 0;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const player_1 = require("@remotion/player");
|
|
9
|
+
const react_1 = require("react");
|
|
10
|
+
const react_dom_1 = __importDefault(require("react-dom"));
|
|
11
|
+
const colors_1 = require("../../helpers/colors");
|
|
12
|
+
const z_index_1 = require("../../state/z-index");
|
|
13
|
+
const is_menu_item_1 = require("../Menu/is-menu-item");
|
|
14
|
+
const portals_1 = require("../Menu/portals");
|
|
15
|
+
const styles_1 = require("../Menu/styles");
|
|
16
|
+
const checker_1 = require("./checker");
|
|
17
|
+
const ColorPickerPopup_1 = require("./ColorPickerPopup");
|
|
18
|
+
// Class name used to opt the swatch button out of the global
|
|
19
|
+
// `button:focus` inset box-shadow defined in inject-css.ts.
|
|
20
|
+
const SWATCH_CLASSNAME = '__remotion_color_swatch';
|
|
21
|
+
const getSwatchBorderColor = ({ status, isFocused, isHovered, }) => {
|
|
22
|
+
if (status === 'warning') {
|
|
23
|
+
return colors_1.WARNING_COLOR;
|
|
24
|
+
}
|
|
25
|
+
if (status === 'error') {
|
|
26
|
+
return colors_1.FAIL_COLOR;
|
|
27
|
+
}
|
|
28
|
+
return isFocused || isHovered
|
|
29
|
+
? colors_1.INPUT_BORDER_COLOR_HOVERED
|
|
30
|
+
: colors_1.INPUT_BORDER_COLOR_UNHOVERED;
|
|
31
|
+
};
|
|
32
|
+
const swatchBaseStyle = {
|
|
33
|
+
position: 'relative',
|
|
34
|
+
display: 'inline-block',
|
|
35
|
+
overflow: 'hidden',
|
|
36
|
+
padding: 0,
|
|
37
|
+
margin: 0,
|
|
38
|
+
cursor: 'pointer',
|
|
39
|
+
backgroundColor: checker_1.CHECKER_BACKGROUND_COLOR,
|
|
40
|
+
backgroundImage: checker_1.CHECKER_BACKGROUND_IMAGE,
|
|
41
|
+
backgroundSize: checker_1.CHECKER_BACKGROUND_SIZE,
|
|
42
|
+
backgroundPosition: checker_1.CHECKER_BACKGROUND_POSITION,
|
|
43
|
+
boxSizing: 'border-box',
|
|
44
|
+
};
|
|
45
|
+
const fillStyle = {
|
|
46
|
+
position: 'absolute',
|
|
47
|
+
inset: 0,
|
|
48
|
+
display: 'block',
|
|
49
|
+
};
|
|
50
|
+
const ColorPicker = ({ value, onChange, onChangeComplete, status, disabled, width = 45, height = 25, borderRadius = 3, title, name, className, style: customStyle, }) => {
|
|
51
|
+
const [opened, setOpened] = (0, react_1.useState)(false);
|
|
52
|
+
const [isHovered, setIsHovered] = (0, react_1.useState)(false);
|
|
53
|
+
const [isFocused, setIsFocused] = (0, react_1.useState)(false);
|
|
54
|
+
const triggerRef = (0, react_1.useRef)(null);
|
|
55
|
+
const { tabIndex, currentZIndex } = (0, z_index_1.useZIndex)();
|
|
56
|
+
const size = player_1.PlayerInternals.useElementSize(triggerRef, {
|
|
57
|
+
triggerOnWindowResize: true,
|
|
58
|
+
shouldApplyCssTransforms: true,
|
|
59
|
+
});
|
|
60
|
+
const refresh = size === null || size === void 0 ? void 0 : size.refresh;
|
|
61
|
+
const onHide = (0, react_1.useCallback)(() => {
|
|
62
|
+
setOpened(false);
|
|
63
|
+
}, []);
|
|
64
|
+
const swatchFill = (0, react_1.useMemo)(() => {
|
|
65
|
+
return {
|
|
66
|
+
...fillStyle,
|
|
67
|
+
backgroundColor: value,
|
|
68
|
+
};
|
|
69
|
+
}, [value]);
|
|
70
|
+
const swatchStyle = (0, react_1.useMemo)(() => {
|
|
71
|
+
return {
|
|
72
|
+
...swatchBaseStyle,
|
|
73
|
+
width,
|
|
74
|
+
height,
|
|
75
|
+
borderRadius,
|
|
76
|
+
borderColor: getSwatchBorderColor({ status, isFocused, isHovered }),
|
|
77
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
78
|
+
opacity: disabled ? 0.5 : 1,
|
|
79
|
+
...(customStyle !== null && customStyle !== void 0 ? customStyle : {}),
|
|
80
|
+
};
|
|
81
|
+
}, [
|
|
82
|
+
borderRadius,
|
|
83
|
+
customStyle,
|
|
84
|
+
disabled,
|
|
85
|
+
height,
|
|
86
|
+
isFocused,
|
|
87
|
+
isHovered,
|
|
88
|
+
status,
|
|
89
|
+
width,
|
|
90
|
+
]);
|
|
91
|
+
const onMouseEnter = (0, react_1.useCallback)(() => setIsHovered(true), []);
|
|
92
|
+
const onMouseLeave = (0, react_1.useCallback)(() => setIsHovered(false), []);
|
|
93
|
+
const onFocus = (0, react_1.useCallback)(() => setIsFocused(true), []);
|
|
94
|
+
const onBlur = (0, react_1.useCallback)(() => setIsFocused(false), []);
|
|
95
|
+
// Toggle on pointerdown (matches Combobox) so the state flips before the
|
|
96
|
+
// HigherZIndex outside-click detection runs on pointerup. If we toggled in
|
|
97
|
+
// onClick, the popup would close in pointerup and immediately re-open in
|
|
98
|
+
// the click that follows.
|
|
99
|
+
const onTriggerPointerDown = (0, react_1.useCallback)(() => {
|
|
100
|
+
if (disabled) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
setOpened((prev) => {
|
|
104
|
+
if (!prev) {
|
|
105
|
+
refresh === null || refresh === void 0 ? void 0 : refresh();
|
|
106
|
+
}
|
|
107
|
+
return !prev;
|
|
108
|
+
});
|
|
109
|
+
}, [disabled, refresh]);
|
|
110
|
+
const onTriggerClick = (0, react_1.useCallback)((e) => {
|
|
111
|
+
if (disabled) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
// Keyboard-initiated activations (Enter/Space) don't fire pointerdown,
|
|
115
|
+
// so handle them here. Mouse clicks are already handled by pointerdown
|
|
116
|
+
// above; ignore them.
|
|
117
|
+
const isKeyboardInitiated = e.detail === 0;
|
|
118
|
+
if (!isKeyboardInitiated) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
setOpened((prev) => {
|
|
122
|
+
if (!prev) {
|
|
123
|
+
refresh === null || refresh === void 0 ? void 0 : refresh();
|
|
124
|
+
}
|
|
125
|
+
return !prev;
|
|
126
|
+
});
|
|
127
|
+
}, [disabled, refresh]);
|
|
128
|
+
const portalStyle = (0, react_1.useMemo)(() => {
|
|
129
|
+
if (!opened || !size) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
const margin = 6;
|
|
133
|
+
const popupHeight = 250;
|
|
134
|
+
const popupWidth = ColorPickerPopup_1.POPUP_WIDTH;
|
|
135
|
+
const spaceBelow = size.windowSize.height - (size.top + size.height);
|
|
136
|
+
const spaceAbove = size.top;
|
|
137
|
+
const openBelow = spaceBelow >= popupHeight + margin || spaceBelow >= spaceAbove;
|
|
138
|
+
const spaceRight = size.windowSize.width - size.left;
|
|
139
|
+
// Try aligning the popup to the trigger's left edge first; fall back
|
|
140
|
+
// to right-aligning if it would clip the viewport.
|
|
141
|
+
const left = spaceRight >= popupWidth + margin
|
|
142
|
+
? size.left
|
|
143
|
+
: Math.max(margin, size.windowSize.width - popupWidth - margin);
|
|
144
|
+
if (openBelow) {
|
|
145
|
+
return {
|
|
146
|
+
...styles_1.menuContainerTowardsBottom,
|
|
147
|
+
top: size.top + size.height + margin,
|
|
148
|
+
left,
|
|
149
|
+
background: 'transparent',
|
|
150
|
+
boxShadow: 'none',
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
...styles_1.menuContainerTowardsTop,
|
|
155
|
+
bottom: size.windowSize.height - size.top + margin,
|
|
156
|
+
left,
|
|
157
|
+
background: 'transparent',
|
|
158
|
+
boxShadow: 'none',
|
|
159
|
+
};
|
|
160
|
+
}, [opened, size]);
|
|
161
|
+
(0, react_1.useEffect)(() => {
|
|
162
|
+
if (!opened) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const onWindowBlur = () => setOpened(false);
|
|
166
|
+
window.addEventListener('blur', onWindowBlur);
|
|
167
|
+
return () => window.removeEventListener('blur', onWindowBlur);
|
|
168
|
+
}, [opened]);
|
|
169
|
+
return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
|
|
170
|
+
jsx_runtime_1.jsx("button", { ref: triggerRef, type: "button", className: [is_menu_item_1.MENU_INITIATOR_CLASSNAME, SWATCH_CLASSNAME, className]
|
|
171
|
+
.filter(Boolean)
|
|
172
|
+
.join(' '), disabled: disabled, name: name, title: title !== null && title !== void 0 ? title : value, tabIndex: tabIndex, style: swatchStyle, onPointerDown: onTriggerPointerDown, onClick: onTriggerClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onFocus: onFocus, onBlur: onBlur, children: jsx_runtime_1.jsx("span", { style: swatchFill }) }), portalStyle
|
|
173
|
+
? react_dom_1.default.createPortal(jsx_runtime_1.jsx("div", { style: styles_1.fullScreenOverlay, children: jsx_runtime_1.jsx("div", { style: styles_1.outerPortal, className: "css-reset", children: jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onOutsideClick: onHide, onEscape: onHide, children: jsx_runtime_1.jsx("div", { style: portalStyle, children: jsx_runtime_1.jsx(ColorPickerPopup_1.ColorPickerPopup, { value: value, onChange: onChange, onChangeComplete: onChangeComplete }) }) }) }) }), (0, portals_1.getPortal)(currentZIndex))
|
|
174
|
+
: null] }));
|
|
175
|
+
};
|
|
176
|
+
exports.ColorPicker = ColorPicker;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare const POPUP_WIDTH = 240;
|
|
3
|
+
export type ChannelKey = 'r' | 'g' | 'b' | 'a-percent';
|
|
4
|
+
export declare const ColorPickerPopup: React.FC<{
|
|
5
|
+
readonly value: string;
|
|
6
|
+
readonly onChange: (next: string) => void;
|
|
7
|
+
readonly onChangeComplete: (next: string) => void;
|
|
8
|
+
}>;
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ColorPickerPopup = exports.POPUP_WIDTH = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const color_conversion_1 = require("../../helpers/color-conversion");
|
|
7
|
+
const colors_1 = require("../../helpers/colors");
|
|
8
|
+
const eyedropper_1 = require("../../icons/eyedropper");
|
|
9
|
+
const z_index_1 = require("../../state/z-index");
|
|
10
|
+
const AlphaSlider_1 = require("./AlphaSlider");
|
|
11
|
+
const checker_1 = require("./checker");
|
|
12
|
+
const HueSlider_1 = require("./HueSlider");
|
|
13
|
+
const SaturationValueArea_1 = require("./SaturationValueArea");
|
|
14
|
+
exports.POPUP_WIDTH = 240;
|
|
15
|
+
const POPUP_PADDING = 12;
|
|
16
|
+
const popupShellStyle = {
|
|
17
|
+
width: exports.POPUP_WIDTH,
|
|
18
|
+
padding: POPUP_PADDING,
|
|
19
|
+
background: '#1f2428',
|
|
20
|
+
border: '1px solid rgba(0, 0, 0, 0.6)',
|
|
21
|
+
borderRadius: 4,
|
|
22
|
+
boxShadow: '0 4px 16px rgba(0, 0, 0, 0.5)',
|
|
23
|
+
display: 'flex',
|
|
24
|
+
flexDirection: 'column',
|
|
25
|
+
gap: 10,
|
|
26
|
+
color: 'white',
|
|
27
|
+
fontSize: 12,
|
|
28
|
+
userSelect: 'none',
|
|
29
|
+
WebkitUserSelect: 'none',
|
|
30
|
+
};
|
|
31
|
+
const sliderRowStyle = {
|
|
32
|
+
display: 'flex',
|
|
33
|
+
alignItems: 'center',
|
|
34
|
+
gap: 8,
|
|
35
|
+
};
|
|
36
|
+
const previewSwatchStyle = {
|
|
37
|
+
position: 'relative',
|
|
38
|
+
width: 28,
|
|
39
|
+
height: 28,
|
|
40
|
+
flex: '0 0 auto',
|
|
41
|
+
borderRadius: 14,
|
|
42
|
+
overflow: 'hidden',
|
|
43
|
+
border: '1px solid rgba(0, 0, 0, 0.6)',
|
|
44
|
+
backgroundColor: checker_1.CHECKER_BACKGROUND_COLOR,
|
|
45
|
+
backgroundImage: checker_1.CHECKER_BACKGROUND_IMAGE,
|
|
46
|
+
backgroundSize: checker_1.CHECKER_BACKGROUND_SIZE,
|
|
47
|
+
backgroundPosition: checker_1.CHECKER_BACKGROUND_POSITION,
|
|
48
|
+
};
|
|
49
|
+
const previewSwatchFillBase = {
|
|
50
|
+
position: 'absolute',
|
|
51
|
+
inset: 0,
|
|
52
|
+
};
|
|
53
|
+
const slidersColumnStyle = {
|
|
54
|
+
display: 'flex',
|
|
55
|
+
flexDirection: 'column',
|
|
56
|
+
gap: 6,
|
|
57
|
+
flex: 1,
|
|
58
|
+
};
|
|
59
|
+
const inputsRowStyle = {
|
|
60
|
+
display: 'flex',
|
|
61
|
+
gap: 6,
|
|
62
|
+
alignItems: 'flex-end',
|
|
63
|
+
};
|
|
64
|
+
const inputColumnStyle = {
|
|
65
|
+
display: 'flex',
|
|
66
|
+
flexDirection: 'column',
|
|
67
|
+
flex: 1,
|
|
68
|
+
minWidth: 0,
|
|
69
|
+
};
|
|
70
|
+
const labelStyle = {
|
|
71
|
+
color: colors_1.LIGHT_TEXT,
|
|
72
|
+
fontSize: 10,
|
|
73
|
+
textTransform: 'uppercase',
|
|
74
|
+
letterSpacing: 0.5,
|
|
75
|
+
marginBottom: 2,
|
|
76
|
+
};
|
|
77
|
+
const baseInputStyle = {
|
|
78
|
+
width: '100%',
|
|
79
|
+
background: colors_1.INPUT_BACKGROUND,
|
|
80
|
+
border: '1px solid rgba(0, 0, 0, 0.6)',
|
|
81
|
+
borderRadius: 3,
|
|
82
|
+
color: 'white',
|
|
83
|
+
padding: '4px 6px',
|
|
84
|
+
fontSize: 12,
|
|
85
|
+
textAlign: 'center',
|
|
86
|
+
boxSizing: 'border-box',
|
|
87
|
+
};
|
|
88
|
+
const eyedropperButtonStyle = {
|
|
89
|
+
background: 'transparent',
|
|
90
|
+
border: '1px solid rgba(0, 0, 0, 0.6)',
|
|
91
|
+
borderRadius: 3,
|
|
92
|
+
padding: 0,
|
|
93
|
+
cursor: 'pointer',
|
|
94
|
+
color: colors_1.LIGHT_TEXT,
|
|
95
|
+
width: 28,
|
|
96
|
+
height: 28,
|
|
97
|
+
display: 'inline-flex',
|
|
98
|
+
alignItems: 'center',
|
|
99
|
+
justifyContent: 'center',
|
|
100
|
+
flex: '0 0 auto',
|
|
101
|
+
};
|
|
102
|
+
const hasEyeDropper = () => typeof window !== 'undefined' && 'EyeDropper' in window;
|
|
103
|
+
const ChannelInput = ({ label, channel, value, min, max, onCommit, }) => {
|
|
104
|
+
const [draft, setDraft] = (0, react_1.useState)(String(Math.round(value)));
|
|
105
|
+
const { tabIndex } = (0, z_index_1.useZIndex)();
|
|
106
|
+
(0, react_1.useEffect)(() => {
|
|
107
|
+
setDraft(String(Math.round(value)));
|
|
108
|
+
}, [value]);
|
|
109
|
+
const onChange = (0, react_1.useCallback)((e) => {
|
|
110
|
+
setDraft(e.target.value);
|
|
111
|
+
}, []);
|
|
112
|
+
const onBlur = (0, react_1.useCallback)(() => {
|
|
113
|
+
const parsed = Number(draft);
|
|
114
|
+
if (Number.isNaN(parsed)) {
|
|
115
|
+
setDraft(String(Math.round(value)));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const clamped = Math.max(min, Math.min(max, parsed));
|
|
119
|
+
setDraft(String(Math.round(clamped)));
|
|
120
|
+
onCommit(channel, clamped);
|
|
121
|
+
}, [channel, draft, max, min, onCommit, value]);
|
|
122
|
+
const onKeyDown = (0, react_1.useCallback)((e) => {
|
|
123
|
+
if (e.key === 'Enter') {
|
|
124
|
+
e.target.blur();
|
|
125
|
+
}
|
|
126
|
+
}, []);
|
|
127
|
+
return (jsx_runtime_1.jsxs("label", { style: inputColumnStyle, children: [
|
|
128
|
+
jsx_runtime_1.jsx("span", { style: labelStyle, children: label }), jsx_runtime_1.jsx("input", { type: "text", inputMode: "numeric", value: draft, onChange: onChange, onBlur: onBlur, onKeyDown: onKeyDown, style: baseInputStyle, tabIndex: tabIndex })
|
|
129
|
+
] }));
|
|
130
|
+
};
|
|
131
|
+
const HexInput = ({ value, onCommit }) => {
|
|
132
|
+
const [draft, setDraft] = (0, react_1.useState)(value);
|
|
133
|
+
const { tabIndex } = (0, z_index_1.useZIndex)();
|
|
134
|
+
(0, react_1.useEffect)(() => {
|
|
135
|
+
setDraft(value);
|
|
136
|
+
}, [value]);
|
|
137
|
+
const onChange = (0, react_1.useCallback)((e) => {
|
|
138
|
+
setDraft(e.target.value);
|
|
139
|
+
}, []);
|
|
140
|
+
const onBlur = (0, react_1.useCallback)(() => {
|
|
141
|
+
try {
|
|
142
|
+
const parsed = (0, color_conversion_1.parseAnyColor)(draft);
|
|
143
|
+
onCommit((0, color_conversion_1.formatRgba)(parsed));
|
|
144
|
+
}
|
|
145
|
+
catch (_a) {
|
|
146
|
+
setDraft(value);
|
|
147
|
+
}
|
|
148
|
+
}, [draft, onCommit, value]);
|
|
149
|
+
const onKeyDown = (0, react_1.useCallback)((e) => {
|
|
150
|
+
if (e.key === 'Enter') {
|
|
151
|
+
e.target.blur();
|
|
152
|
+
}
|
|
153
|
+
}, []);
|
|
154
|
+
const style = (0, react_1.useMemo)(() => {
|
|
155
|
+
return {
|
|
156
|
+
...baseInputStyle,
|
|
157
|
+
textAlign: 'left',
|
|
158
|
+
};
|
|
159
|
+
}, []);
|
|
160
|
+
return (jsx_runtime_1.jsxs("label", { style: inputColumnStyle, children: [
|
|
161
|
+
jsx_runtime_1.jsx("span", { style: labelStyle, children: "Hex" }), jsx_runtime_1.jsx("input", { type: "text", value: draft, onChange: onChange, onBlur: onBlur, onKeyDown: onKeyDown, style: style, autoComplete: "off", spellCheck: false, tabIndex: tabIndex })
|
|
162
|
+
] }));
|
|
163
|
+
};
|
|
164
|
+
const ColorPickerPopup = ({ value, onChange, onChangeComplete }) => {
|
|
165
|
+
// useZIndex is intentionally read inside the popup (which is wrapped by
|
|
166
|
+
// HigherZIndex) so child inputs receive the popup's tabIndex rather than
|
|
167
|
+
// the trigger's, which would resolve to -1 once the popup is open.
|
|
168
|
+
const { tabIndex } = (0, z_index_1.useZIndex)();
|
|
169
|
+
// HSV is the source of truth while the picker is open. We seed it from
|
|
170
|
+
// the incoming value but keep our own state so that hue and saturation
|
|
171
|
+
// don't snap back to 0 when the user drags into pure black/white.
|
|
172
|
+
const [hsva, setHsva] = (0, react_1.useState)(() => (0, color_conversion_1.rgbaToHsva)((0, color_conversion_1.parseAnyColor)(value)));
|
|
173
|
+
const lastEmittedRef = (0, react_1.useRef)((0, color_conversion_1.formatRgba)((0, color_conversion_1.parseAnyColor)(value)));
|
|
174
|
+
(0, react_1.useEffect)(() => {
|
|
175
|
+
// Sync from external value changes that didn't originate from us.
|
|
176
|
+
const incoming = (0, color_conversion_1.formatRgba)((0, color_conversion_1.parseAnyColor)(value));
|
|
177
|
+
if (incoming === lastEmittedRef.current) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
lastEmittedRef.current = incoming;
|
|
181
|
+
setHsva((0, color_conversion_1.rgbaToHsva)((0, color_conversion_1.parseAnyColor)(value)));
|
|
182
|
+
}, [value]);
|
|
183
|
+
const rgba = (0, react_1.useMemo)(() => (0, color_conversion_1.hsvaToRgba)(hsva), [hsva]);
|
|
184
|
+
const formatted = (0, react_1.useMemo)(() => (0, color_conversion_1.formatRgba)(rgba), [rgba]);
|
|
185
|
+
const emit = (0, react_1.useCallback)((next, mode) => {
|
|
186
|
+
setHsva(next);
|
|
187
|
+
const nextRgba = (0, color_conversion_1.hsvaToRgba)(next);
|
|
188
|
+
const nextFormatted = (0, color_conversion_1.formatRgba)(nextRgba);
|
|
189
|
+
lastEmittedRef.current = nextFormatted;
|
|
190
|
+
if (mode === 'complete') {
|
|
191
|
+
onChangeComplete(nextFormatted);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
onChange(nextFormatted);
|
|
195
|
+
}
|
|
196
|
+
}, [onChange, onChangeComplete]);
|
|
197
|
+
const onSvChange = (0, react_1.useCallback)((next) => {
|
|
198
|
+
emit({ ...hsva, s: next.s, v: next.v }, 'change');
|
|
199
|
+
}, [emit, hsva]);
|
|
200
|
+
const onSvComplete = (0, react_1.useCallback)((next) => {
|
|
201
|
+
emit({ ...hsva, s: next.s, v: next.v }, 'complete');
|
|
202
|
+
}, [emit, hsva]);
|
|
203
|
+
const onHueChange = (0, react_1.useCallback)((next) => {
|
|
204
|
+
emit({ ...hsva, h: next }, 'change');
|
|
205
|
+
}, [emit, hsva]);
|
|
206
|
+
const onHueComplete = (0, react_1.useCallback)((next) => {
|
|
207
|
+
emit({ ...hsva, h: next }, 'complete');
|
|
208
|
+
}, [emit, hsva]);
|
|
209
|
+
const onAlphaChange = (0, react_1.useCallback)((next) => {
|
|
210
|
+
emit({ ...hsva, a: next }, 'change');
|
|
211
|
+
}, [emit, hsva]);
|
|
212
|
+
const onAlphaComplete = (0, react_1.useCallback)((next) => {
|
|
213
|
+
emit({ ...hsva, a: next }, 'complete');
|
|
214
|
+
}, [emit, hsva]);
|
|
215
|
+
const onChannelCommit = (0, react_1.useCallback)((channel, next) => {
|
|
216
|
+
if (channel === 'a-percent') {
|
|
217
|
+
const clamped = Math.max(0, Math.min(100, next));
|
|
218
|
+
emit({ ...hsva, a: clamped / 100 }, 'complete');
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
const updatedRgba = { ...rgba, [channel]: next };
|
|
222
|
+
const newHsva = (0, color_conversion_1.rgbaToHsva)(updatedRgba);
|
|
223
|
+
// Preserve hue when transitioning through achromatic colors.
|
|
224
|
+
if (newHsva.s === 0) {
|
|
225
|
+
newHsva.h = hsva.h;
|
|
226
|
+
}
|
|
227
|
+
emit(newHsva, 'complete');
|
|
228
|
+
}, [emit, hsva, rgba]);
|
|
229
|
+
const onHexCommit = (0, react_1.useCallback)((next) => {
|
|
230
|
+
const parsed = (0, color_conversion_1.parseAnyColor)(next);
|
|
231
|
+
const newHsva = (0, color_conversion_1.rgbaToHsva)(parsed);
|
|
232
|
+
if (newHsva.s === 0) {
|
|
233
|
+
newHsva.h = hsva.h;
|
|
234
|
+
}
|
|
235
|
+
emit(newHsva, 'complete');
|
|
236
|
+
}, [emit, hsva.h]);
|
|
237
|
+
const onPickWithEyeDropper = (0, react_1.useCallback)(() => {
|
|
238
|
+
const Ctor = window.EyeDropper;
|
|
239
|
+
if (!Ctor) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
const dropper = new Ctor();
|
|
243
|
+
dropper
|
|
244
|
+
.open()
|
|
245
|
+
.then((result) => {
|
|
246
|
+
const parsed = (0, color_conversion_1.parseAnyColor)(result.sRGBHex);
|
|
247
|
+
// `EyeDropper` always returns full opacity; preserve the user's
|
|
248
|
+
// previously chosen alpha so opening it doesn't drop transparency.
|
|
249
|
+
parsed.a = rgba.a;
|
|
250
|
+
const newHsva = (0, color_conversion_1.rgbaToHsva)(parsed);
|
|
251
|
+
if (newHsva.s === 0) {
|
|
252
|
+
newHsva.h = hsva.h;
|
|
253
|
+
}
|
|
254
|
+
emit(newHsva, 'complete');
|
|
255
|
+
})
|
|
256
|
+
.catch(() => {
|
|
257
|
+
// Aborted; ignore.
|
|
258
|
+
});
|
|
259
|
+
}, [emit, hsva.h, rgba.a]);
|
|
260
|
+
const previewFill = (0, react_1.useMemo)(() => {
|
|
261
|
+
return {
|
|
262
|
+
...previewSwatchFillBase,
|
|
263
|
+
backgroundColor: formatted,
|
|
264
|
+
};
|
|
265
|
+
}, [formatted]);
|
|
266
|
+
const showEyeDropper = hasEyeDropper();
|
|
267
|
+
return (jsx_runtime_1.jsxs("div", { style: popupShellStyle, children: [
|
|
268
|
+
jsx_runtime_1.jsx(SaturationValueArea_1.SaturationValueArea, { hue: hsva.h, saturation: hsva.s, value: hsva.v, onChange: onSvChange, onChangeComplete: onSvComplete }), jsx_runtime_1.jsxs("div", { style: sliderRowStyle, children: [showEyeDropper ? (jsx_runtime_1.jsx("button", { type: "button", style: eyedropperButtonStyle, onClick: onPickWithEyeDropper, tabIndex: tabIndex, title: "Pick color from screen", "aria-label": "Pick color from screen", children: jsx_runtime_1.jsx(eyedropper_1.EyedropperIcon, { style: { width: 14, height: 14 }, color: "currentColor" }) })) : null, jsx_runtime_1.jsx("div", { style: previewSwatchStyle, title: formatted, children: jsx_runtime_1.jsx("div", { style: previewFill }) }), jsx_runtime_1.jsxs("div", { style: slidersColumnStyle, children: [
|
|
269
|
+
jsx_runtime_1.jsx(HueSlider_1.HueSlider, { hue: hsva.h, onChange: onHueChange, onChangeComplete: onHueComplete }), jsx_runtime_1.jsx(AlphaSlider_1.AlphaSlider, { hue: hsva.h, saturation: hsva.s, value: hsva.v, alpha: hsva.a, onChange: onAlphaChange, onChangeComplete: onAlphaComplete })
|
|
270
|
+
] })
|
|
271
|
+
] }), jsx_runtime_1.jsxs("div", { style: inputsRowStyle, children: [
|
|
272
|
+
jsx_runtime_1.jsx(HexInput, { value: formatted, onCommit: onHexCommit }), jsx_runtime_1.jsx(ChannelInput, { label: "R", channel: "r", value: rgba.r, min: 0, max: 255, onCommit: onChannelCommit }), jsx_runtime_1.jsx(ChannelInput, { label: "G", channel: "g", value: rgba.g, min: 0, max: 255, onCommit: onChannelCommit }), jsx_runtime_1.jsx(ChannelInput, { label: "B", channel: "b", value: rgba.b, min: 0, max: 255, onCommit: onChannelCommit }), jsx_runtime_1.jsx(ChannelInput, { label: "A%", channel: "a-percent", value: Math.round(hsva.a * 100), min: 0, max: 100, onCommit: onChannelCommit })
|
|
273
|
+
] })
|
|
274
|
+
] }));
|
|
275
|
+
};
|
|
276
|
+
exports.ColorPickerPopup = ColorPickerPopup;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HueSlider = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const color_conversion_1 = require("../../helpers/color-conversion");
|
|
7
|
+
const SLIDER_HEIGHT = 12;
|
|
8
|
+
const HANDLE_WIDTH = 8;
|
|
9
|
+
const containerStyle = {
|
|
10
|
+
position: 'relative',
|
|
11
|
+
height: SLIDER_HEIGHT,
|
|
12
|
+
width: '100%',
|
|
13
|
+
borderRadius: 3,
|
|
14
|
+
cursor: 'ew-resize',
|
|
15
|
+
background: 'linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%)',
|
|
16
|
+
touchAction: 'none',
|
|
17
|
+
};
|
|
18
|
+
const HueSlider = ({ hue, onChange, onChangeComplete }) => {
|
|
19
|
+
const ref = (0, react_1.useRef)(null);
|
|
20
|
+
const updateFromEvent = (0, react_1.useCallback)((clientX, isFinal) => {
|
|
21
|
+
const { current } = ref;
|
|
22
|
+
if (!current) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const rect = current.getBoundingClientRect();
|
|
26
|
+
const x = (0, color_conversion_1.clamp)((clientX - rect.left) / rect.width, 0, 1);
|
|
27
|
+
const next = x * 360;
|
|
28
|
+
if (isFinal) {
|
|
29
|
+
onChangeComplete(next);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
onChange(next);
|
|
33
|
+
}
|
|
34
|
+
}, [onChange, onChangeComplete]);
|
|
35
|
+
const onPointerDown = (0, react_1.useCallback)((e) => {
|
|
36
|
+
if (e.button !== 0) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
e.preventDefault();
|
|
40
|
+
updateFromEvent(e.clientX, false);
|
|
41
|
+
const onMove = (ev) => {
|
|
42
|
+
updateFromEvent(ev.clientX, false);
|
|
43
|
+
};
|
|
44
|
+
const onUp = (ev) => {
|
|
45
|
+
window.removeEventListener('pointermove', onMove);
|
|
46
|
+
window.removeEventListener('pointerup', onUp);
|
|
47
|
+
updateFromEvent(ev.clientX, true);
|
|
48
|
+
};
|
|
49
|
+
window.addEventListener('pointermove', onMove);
|
|
50
|
+
window.addEventListener('pointerup', onUp);
|
|
51
|
+
}, [updateFromEvent]);
|
|
52
|
+
const handleStyle = (0, react_1.useMemo)(() => {
|
|
53
|
+
return {
|
|
54
|
+
position: 'absolute',
|
|
55
|
+
top: -2,
|
|
56
|
+
left: `${(hue / 360) * 100}%`,
|
|
57
|
+
marginLeft: -HANDLE_WIDTH / 2,
|
|
58
|
+
width: HANDLE_WIDTH,
|
|
59
|
+
height: SLIDER_HEIGHT + 4,
|
|
60
|
+
borderRadius: 2,
|
|
61
|
+
border: '2px solid #fff',
|
|
62
|
+
boxShadow: '0 0 0 1px rgba(0, 0, 0, 0.6)',
|
|
63
|
+
pointerEvents: 'none',
|
|
64
|
+
};
|
|
65
|
+
}, [hue]);
|
|
66
|
+
return (jsx_runtime_1.jsx("div", { ref: ref, style: containerStyle, onPointerDown: onPointerDown, children: jsx_runtime_1.jsx("div", { style: handleStyle }) }));
|
|
67
|
+
};
|
|
68
|
+
exports.HueSlider = HueSlider;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare const SaturationValueArea: React.FC<{
|
|
3
|
+
readonly hue: number;
|
|
4
|
+
readonly saturation: number;
|
|
5
|
+
readonly value: number;
|
|
6
|
+
readonly onChange: (next: {
|
|
7
|
+
s: number;
|
|
8
|
+
v: number;
|
|
9
|
+
}) => void;
|
|
10
|
+
readonly onChangeComplete: (next: {
|
|
11
|
+
s: number;
|
|
12
|
+
v: number;
|
|
13
|
+
}) => void;
|
|
14
|
+
}>;
|