You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
3.2 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. import React, {PropsWithChildren, useCallback, useLayoutEffect, useMemo} from 'react';
  2. import iro from "@jaames/iro";
  3. import "./Forms.sass";
  4. interface FormLineProps {
  5. label: string
  6. id?: string
  7. }
  8. function FormLine({label, id, children}: PropsWithChildren<FormLineProps>) {
  9. return (
  10. <div className="FormLine">
  11. <label htmlFor={id}>{label}:</label>
  12. {children}
  13. </div>
  14. );
  15. }
  16. interface InputProps {
  17. label: string
  18. value: string
  19. onChange?: (s: string) => void,
  20. onChangeNumeric?: (n: number) => void
  21. numeric?: boolean
  22. }
  23. export function Input({label, numeric, onChange, onChangeNumeric, value}: InputProps) {
  24. const id = useMemo(() => `input-${randomId()}`, []);
  25. const actualOnChange = useCallback((newValue: string) => {
  26. if (onChangeNumeric) {
  27. onChangeNumeric(parseInt(newValue));
  28. } else if (onChange) {
  29. onChange(newValue);
  30. }
  31. }, [onChange, onChangeNumeric]);
  32. return (
  33. <FormLine label={label} id={id}>
  34. <input id={id} value={value}
  35. type={numeric ? "number" : "text"}
  36. onChange={i => actualOnChange(i.target.value)}
  37. />
  38. </FormLine>
  39. )
  40. }
  41. interface ColorPickerProps {
  42. label?: string
  43. h: number
  44. s: number
  45. onChange: (h: number, s: number) => void
  46. }
  47. const randomId = () => Math.floor(Math.random() * 100000);
  48. export const HSColorPicker: React.FC<ColorPickerProps> = ({h, s, onChange, label}) => {
  49. const myId = useMemo(() => `color-picker-${randomId()}`, []);
  50. useLayoutEffect(() => {
  51. // @ts-ignore
  52. const colorPicker = new iro.ColorPicker(`#${myId}`, {
  53. color: {h, s: s * 100, v: 255},
  54. layout: [
  55. {
  56. component: iro.ui.Wheel,
  57. options: {}
  58. }
  59. ],
  60. });
  61. colorPicker.on("input:end", (color: { hsv: { h: number, s: number } }) => {
  62. onChange(color.hsv.h || 0, (color.hsv.s || 0) / 100);
  63. });
  64. return () => {
  65. const elem = document.getElementById(myId);
  66. if (elem === null) {
  67. return;
  68. }
  69. elem.innerHTML = "";
  70. };
  71. }, [h, s, onChange, myId]);
  72. return (
  73. <FormLine label={label || "HS-farge"}>
  74. <div id={myId} style={{margin: "0 auto"}}/>
  75. </FormLine>
  76. );
  77. };
  78. interface KelvinColorPickerProps {
  79. label?: string
  80. kelvin: number
  81. onChange: (kelvin: number) => void
  82. }
  83. export const KelvinColorPicker: React.FC<KelvinColorPickerProps> = ({label, kelvin, onChange}) => {
  84. const myId = useMemo(() => `color-picker-${randomId()}`, []);
  85. useLayoutEffect(() => {
  86. // @ts-ignore
  87. const colorPicker = new iro.ColorPicker(`#${myId}`, {
  88. color: {kelvin},
  89. layout: [
  90. {
  91. component: iro.ui.Slider,
  92. options: {
  93. sliderType: "kelvin",
  94. }
  95. }
  96. ],
  97. });
  98. colorPicker.on("input:end", (color: iro.Color) => {
  99. onChange(Math.floor(color.kelvin));
  100. });
  101. return () => {
  102. const elem = document.getElementById(myId);
  103. if (elem === null) {
  104. return;
  105. }
  106. elem.innerHTML = "";
  107. };
  108. }, [kelvin, onChange, myId]);
  109. return (
  110. <FormLine label={label || "KV-farge"}>
  111. <div title={`${kelvin}K`} id={myId} style={{margin: "0 auto"}}/>
  112. </FormLine>
  113. );
  114. }