87 lines
2.7 KiB
TypeScript
87 lines
2.7 KiB
TypeScript
import { HTMLAttributes, useCallback } from 'react';
|
|
import { FC } from 'react';
|
|
import { LedStripConfig } from '../models/led-strip-config';
|
|
import tw, { styled } from 'twin.macro';
|
|
import { faLeftRight, faMinus, faPlus } from '@fortawesome/free-solid-svg-icons';
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
|
|
export interface LedStripEditorProps
|
|
extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {
|
|
config: LedStripConfig | null;
|
|
onChange?: (config: LedStripConfig | null) => void;
|
|
}
|
|
|
|
const StyledContainer = styled.section(
|
|
tw`flex flex-wrap gap-2 self-start justify-self-start`,
|
|
);
|
|
|
|
const StyledButton = styled.button(
|
|
tw`
|
|
bg-yellow-500 dark:bg-amber-600 rounded-full h-4 w-4 text-xs shadow select-none`,
|
|
tw`hocus:scale-105 hocus:active:scale-95 active:bg-amber-600 active:dark:bg-amber-500`,
|
|
);
|
|
|
|
export const LedStripEditor: FC<LedStripEditorProps> = ({
|
|
config,
|
|
onChange,
|
|
...htmlAttrs
|
|
}) => {
|
|
const addLed = useCallback(() => {
|
|
if (config) {
|
|
if (config.global_start_position <= config.global_end_position) {
|
|
onChange?.({ ...config, global_end_position: config.global_end_position + 1 });
|
|
} else {
|
|
onChange?.({
|
|
...config,
|
|
global_start_position: config.global_start_position + 1,
|
|
});
|
|
}
|
|
} else {
|
|
onChange?.(new LedStripConfig(0, 0, 0));
|
|
}
|
|
}, [config, onChange]);
|
|
const removeLed = useCallback(() => {
|
|
if (!config) {
|
|
onChange?.(null);
|
|
} else if (Math.abs(config.global_start_position - config.global_end_position) <= 1) {
|
|
onChange?.(null);
|
|
} else {
|
|
if (config.global_start_position <= config.global_end_position) {
|
|
onChange?.({ ...config, global_end_position: config.global_end_position - 1 });
|
|
} else {
|
|
onChange?.({
|
|
...config,
|
|
global_start_position: config.global_start_position - 1,
|
|
});
|
|
}
|
|
}
|
|
}, [config, onChange]);
|
|
const reverse = useCallback(() => {
|
|
if (!config) {
|
|
return;
|
|
}
|
|
onChange?.({
|
|
...config,
|
|
global_start_position: config.global_end_position,
|
|
global_end_position: config.global_start_position,
|
|
});
|
|
}, [config, onChange]);
|
|
|
|
return (
|
|
<StyledContainer {...htmlAttrs}>
|
|
<StyledButton title="Add LED" onClick={addLed}>
|
|
<FontAwesomeIcon icon={faPlus} />
|
|
</StyledButton>
|
|
<StyledButton title="Remove LED" onClick={removeLed}>
|
|
<FontAwesomeIcon icon={faMinus} />
|
|
</StyledButton>
|
|
<StyledButton title="Reverse" onClick={reverse}>
|
|
<FontAwesomeIcon icon={faLeftRight} />
|
|
</StyledButton>
|
|
{`s: ${config?.global_start_position ?? 'x'}, e: ${
|
|
config?.global_end_position ?? 'x'
|
|
}`}
|
|
</StyledContainer>
|
|
);
|
|
};
|