Skip to content

Commit

Permalink
Merge branch 'master' of github.com:mantinedev/mantine into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
rtivital committed Sep 19, 2022
2 parents 182ec3f + 30d8e86 commit 7cb237c
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 11 deletions.
10 changes: 9 additions & 1 deletion src/mantine-core/src/ColorInput/ColorInput.tsx
Expand Up @@ -88,6 +88,7 @@ export const ColorInput = forwardRef<HTMLInputElement, ColorInputProps>(
inputProps,
format,
onChange,
onChangeEnd,
onFocus,
onBlur,
value,
Expand Down Expand Up @@ -171,7 +172,13 @@ export const ColorInput = forwardRef<HTMLInputElement, ColorInputProps>(
onBlur={handleInputBlur}
spellCheck={false}
value={_value}
onChange={(event) => setValue(event.currentTarget.value)}
onChange={(event) => {
const inputValue = event.currentTarget.value;
setValue(inputValue);
if (isColorValid(inputValue)) {
onChangeEnd?.(convertHsvaTo(format, parseColor(inputValue)));
}
}}
autoComplete="nope"
icon={
icon ||
Expand All @@ -196,6 +203,7 @@ export const ColorInput = forwardRef<HTMLInputElement, ColorInputProps>(
__staticSelector="ColorInput"
value={_value}
onChange={setValue}
onChangeEnd={onChangeEnd}
format={format}
swatches={swatches}
swatchesPerRow={swatchesPerRow}
Expand Down
Expand Up @@ -5,6 +5,7 @@ import { AlphaSlider, AlphaSliderProps } from './AlphaSlider';
const defaultProps: AlphaSliderProps = {
value: 0.5,
onChange: () => {},
onChangeEnd: () => {},
color: '#FF00FF',
size: 'sm',
};
Expand Down
3 changes: 2 additions & 1 deletion src/mantine-core/src/ColorPicker/AlphaSlider/AlphaSlider.tsx
Expand Up @@ -8,7 +8,7 @@ export interface AlphaSliderProps extends BaseColorSliderProps {
}

export const AlphaSlider = forwardRef<HTMLDivElement, AlphaSliderProps>(
({ value, onChange, color, ...others }: AlphaSliderProps, ref) => {
({ value, onChange, onChangeEnd, color, ...others }: AlphaSliderProps, ref) => {
const theme = useMantineTheme();
const _color = theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[3];

Expand All @@ -18,6 +18,7 @@ export const AlphaSlider = forwardRef<HTMLDivElement, AlphaSliderProps>(
ref={ref}
value={value}
onChange={(val) => onChange(round(val, 2))}
onChangeEnd={(val) => onChangeEnd(round(val, 2))}
maxValue={1}
round={false}
overlays={[
Expand Down
14 changes: 13 additions & 1 deletion src/mantine-core/src/ColorPicker/ColorPicker.test.tsx
@@ -1,5 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react';
import { fireEvent, render } from '@testing-library/react';
import { checkAccessibility, itSupportsSystemProps } from '@mantine/tests';
import { DEFAULT_THEME } from '@mantine/styles';
import { ColorPicker, ColorPickerProps } from './ColorPicker';
Expand Down Expand Up @@ -46,4 +46,16 @@ describe('@mantine/core/ColorPicker', () => {
expect(withPicker.querySelectorAll('.mantine-ColorPicker-saturation')).toHaveLength(1);
expect(withoutPicker.querySelectorAll('.mantine-ColorPicker-saturation')).toHaveLength(0);
});

it('onChangeEnd should be called if clicked on swatch', () => {
const spy = jest.fn();
const { container } = render(
<ColorPicker onChangeEnd={spy} format="hex" swatches={['#ffffff', '#000000']} />
);
fireEvent(
container.querySelectorAll('.mantine-ColorSwatch-root')[0],
new MouseEvent('click', { bubbles: true })
);
expect(spy).toHaveBeenCalledWith('#ffffff');
});
});
16 changes: 16 additions & 0 deletions src/mantine-core/src/ColorPicker/ColorPicker.tsx
Expand Up @@ -30,6 +30,9 @@ export interface ColorPickerBaseProps {
/** Called when color changes */
onChange?(color: string): void;

/** Called when user stops dragging thumb or changes value with arrows */
onChangeEnd?(color: string): void;

/** Color format */
format?: 'hex' | 'rgba' | 'rgb' | 'hsl' | 'hsla';

Expand Down Expand Up @@ -91,6 +94,7 @@ export const ColorPicker = forwardRef<HTMLDivElement, ColorPickerProps>(
value,
defaultValue,
onChange,
onChangeEnd,
format,
swatches,
swatchesPerRow,
Expand Down Expand Up @@ -162,6 +166,9 @@ export const ColorPicker = forwardRef<HTMLDivElement, ColorPickerProps>(
<Saturation
value={parsed}
onChange={handleChange}
onChangeEnd={({ s, v }) =>
onChangeEnd?.(convertHsvaTo(formatRef.current, { ...parsed, s, v }))
}
color={_value}
styles={styles}
classNames={classNames}
Expand All @@ -176,6 +183,9 @@ export const ColorPicker = forwardRef<HTMLDivElement, ColorPickerProps>(
<HueSlider
value={parsed.h}
onChange={(h) => handleChange({ h })}
onChangeEnd={(h) =>
onChangeEnd?.(convertHsvaTo(formatRef.current, { ...parsed, h }))
}
size={size}
styles={styles}
classNames={classNames}
Expand All @@ -188,6 +198,9 @@ export const ColorPicker = forwardRef<HTMLDivElement, ColorPickerProps>(
<AlphaSlider
value={parsed.a}
onChange={(a) => handleChange({ a })}
onChangeEnd={(a) => {
onChangeEnd?.(convertHsvaTo(formatRef.current, { ...parsed, a }));
}}
size={size}
color={convertHsvaTo('hex', parsed)}
style={{ marginTop: 6 }}
Expand Down Expand Up @@ -222,6 +235,9 @@ export const ColorPicker = forwardRef<HTMLDivElement, ColorPickerProps>(
styles={styles}
__staticSelector={__staticSelector}
setValue={setValue}
onChangeEnd={(color) => {
onChangeEnd?.(convertHsvaTo(format, parseColor(color)));
}}
/>
)}
</Box>
Expand Down
Expand Up @@ -4,6 +4,7 @@ import { ColorSlider, ColorSliderProps } from './ColorSlider';
const defaultProps: ColorSliderProps = {
value: 25,
onChange: () => {},
onChangeEnd: () => {},
size: 'sm',
maxValue: 360,
overlays: [{ color: 'red' }],
Expand Down
19 changes: 17 additions & 2 deletions src/mantine-core/src/ColorPicker/ColorSlider/ColorSlider.tsx
@@ -1,4 +1,4 @@
import React, { useState, forwardRef } from 'react';
import React, { useState, forwardRef, useRef } from 'react';
import {
useMove,
clampUseMovePosition,
Expand All @@ -20,6 +20,7 @@ export interface BaseColorSliderProps
Omit<React.ComponentPropsWithoutRef<'div'>, 'value' | 'onChange'> {
value: number;
onChange(value: number): void;
onChangeEnd(value: number): void;
size?: MantineSize;
focusable?: boolean;
__staticSelector?: string;
Expand All @@ -37,6 +38,7 @@ export const ColorSlider = forwardRef<HTMLDivElement, ColorSliderProps>(
{
value,
onChange,
onChangeEnd,
maxValue,
round,
size = 'md',
Expand All @@ -57,8 +59,20 @@ export const ColorSlider = forwardRef<HTMLDivElement, ColorSliderProps>(
{ classNames, styles, name: __staticSelector, unstyled }
);
const [position, setPosition] = useState({ y: 0, x: value / maxValue });
const positionRef = useRef(position);
const getChangeValue = (val: number) => (round ? Math.round(val * maxValue) : val * maxValue);
const { ref: sliderRef } = useMove(({ x }) => onChange(getChangeValue(x)));
const { ref: sliderRef } = useMove(
({ x, y }) => {
positionRef.current = { x, y };
onChange(getChangeValue(x));
},
{
onScrubEnd: () => {
const { x } = positionRef.current;
onChangeEnd(getChangeValue(x));
},
}
);

useDidUpdate(() => {
setPosition({ y: 0, x: value / maxValue });
Expand All @@ -68,6 +82,7 @@ export const ColorSlider = forwardRef<HTMLDivElement, ColorSliderProps>(
event.preventDefault();
const _position = clampUseMovePosition(pos);
onChange(getChangeValue(_position.x));
onChangeEnd(getChangeValue(_position.x));
};

const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
Expand Down
Expand Up @@ -5,6 +5,7 @@ import { HueSlider, HueSliderProps } from './HueSlider';
const defaultProps: HueSliderProps = {
value: 150,
onChange: () => {},
onChangeEnd: () => {},
size: 'sm',
};

Expand Down
3 changes: 2 additions & 1 deletion src/mantine-core/src/ColorPicker/HueSlider/HueSlider.tsx
Expand Up @@ -4,12 +4,13 @@ import { ColorSlider, BaseColorSliderProps } from '../ColorSlider/ColorSlider';
export type HueSliderProps = BaseColorSliderProps;

export const HueSlider = forwardRef<HTMLDivElement, HueSliderProps>(
({ value, onChange, ...others }: HueSliderProps, ref) => (
({ value, onChange, onChangeEnd, ...others }: HueSliderProps, ref) => (
<ColorSlider
{...others}
ref={ref}
value={value}
onChange={onChange}
onChangeEnd={onChangeEnd}
maxValue={360}
thumbColor={`hsl(${value}, 100%, 50%)`}
round
Expand Down
21 changes: 17 additions & 4 deletions src/mantine-core/src/ColorPicker/Saturation/Saturation.tsx
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useRef } from 'react';
import { useMove, clampUseMovePosition, UseMovePosition } from '@mantine/hooks';
import { DefaultProps, MantineSize, Selectors } from '@mantine/styles';
import { HsvaColor } from '../types';
Expand All @@ -13,6 +13,7 @@ export type SaturationStylesNames =
interface SaturationProps extends DefaultProps<SaturationStylesNames> {
value: HsvaColor;
onChange(color: Partial<HsvaColor>): void;
onChangeEnd(color: Partial<HsvaColor>): void;
saturationLabel?: string;
size: MantineSize;
color: string;
Expand All @@ -23,6 +24,7 @@ interface SaturationProps extends DefaultProps<SaturationStylesNames> {
export function Saturation({
value,
onChange,
onChangeEnd,
focusable = true,
__staticSelector = 'saturation',
size,
Expand All @@ -34,10 +36,20 @@ export function Saturation({
}: SaturationProps) {
const { classes } = useStyles({ size }, { classNames, styles, name: __staticSelector, unstyled });
const [position, setPosition] = useState({ x: value.s / 100, y: 1 - value.v / 100 });
const positionRef = useRef(position);

const { ref } = useMove(({ x, y }) => {
onChange({ s: Math.round(x * 100), v: Math.round((1 - y) * 100) });
});
const { ref } = useMove(
({ x, y }) => {
positionRef.current = { x, y };
onChange({ s: Math.round(x * 100), v: Math.round((1 - y) * 100) });
},
{
onScrubEnd: () => {
const { x, y } = positionRef.current;
onChangeEnd({ s: Math.round(x * 100), v: Math.round((1 - y) * 100) });
},
}
);

useEffect(() => {
setPosition({ x: value.s / 100, y: 1 - value.v / 100 });
Expand All @@ -47,6 +59,7 @@ export function Saturation({
event.preventDefault();
const _position = clampUseMovePosition(pos);
onChange({ s: Math.round(_position.x * 100), v: Math.round((1 - _position.y) * 100) });
onChangeEnd({ s: Math.round(_position.x * 100), v: Math.round((1 - _position.y) * 100) });
};

const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
Expand Down
7 changes: 6 additions & 1 deletion src/mantine-core/src/ColorPicker/Swatches/Swatches.tsx
Expand Up @@ -11,6 +11,7 @@ export interface SwatchesProps
data: string[];
swatchesPerRow?: number;
focusable?: boolean;
onChangeEnd?: (color: string) => void;
__staticSelector?: string;
setValue(value: string): void;
}
Expand All @@ -24,6 +25,7 @@ export function Swatches({
__staticSelector = 'color-picker',
unstyled,
setValue,
onChangeEnd,
...others
}: SwatchesProps) {
const { classes } = useStyles(
Expand All @@ -39,7 +41,10 @@ export function Swatches({
color={color}
key={index}
radius="sm"
onClick={() => setValue(color)}
onClick={() => {
setValue(color);
onChangeEnd?.(color);
}}
style={{ cursor: 'pointer' }}
aria-label={color}
tabIndex={focusable ? 0 : -1}
Expand Down

0 comments on commit 7cb237c

Please sign in to comment.