Загрузка данных


import { InputText } from 'exchange-elements/v2';
import { ChangeEvent, useEffect, useRef, useState } from 'react';

import styles from './index.module.scss';

interface ColorFieldProps {
  label: string;
  value: string;
  onValueChange: (value: string) => void;
}

function normalizeHex(value: string): string {
  const next = value.trim();

  if (!next) {
    return '#000000';
  }

  const withHash = next.startsWith('#') ? next : `#${next}`;

  if (/^#[0-9A-Fa-f]{6}$/.test(withHash)) {
    return withHash.toLowerCase();
  }

  return '#000000';
}

function isValidHex(value: string): boolean {
  const withHash = value.startsWith('#') ? value : `#${value}`;

  return /^#[0-9A-Fa-f]{6}$/.test(withHash);
}

export const ColorField = ({ label, value, onValueChange }: ColorFieldProps) => {
  const colorInputRef = useRef<HTMLInputElement | null>(null);
  const [draft, setDraft] = useState(normalizeHex(value));

  useEffect(() => {
    setDraft(normalizeHex(value));
  }, [value]);

  const handleBlur = () => {
    if (!isValidHex(draft)) {
      setDraft(normalizeHex(value));
      return;
    }

    const next = normalizeHex(draft);

    setDraft(next);
    onValueChange(next);
  };

  return (
    <div className={styles.inputWrapper}>
      <InputText
        value={draft}
        label={label}
        labelPos="top"
        size="sm"
        onChange={(event: ChangeEvent<HTMLInputElement>) => {
          setDraft(event.target.value);
        }}
        onBlur={handleBlur}
      />

      <button
        type="button"
        className={styles.button_color}
        style={{ backgroundColor: normalizeHex(value) }}
        onClick={() => colorInputRef.current?.click()}
      />

      <input
        ref={colorInputRef}
        type="color"
        className={styles.input_hidden}
        value={normalizeHex(value)}
        onChange={(event) => {
          setDraft(event.target.value);
          onValueChange(event.target.value);
        }}
        tabIndex={-1}
      />
    </div>
  );
};




[data-theme='mxt'],
[data-theme='mb'][data-mode='light'] {
  --dd-item-text-selected: var(--neutral-2);
  --dd-item-bg-selected: var(--neutral-12);
}

[data-theme='tr'],
[data-theme='mb'][data-mode='dark'] {
  --dd-item-text-selected: var(--neutral-13);
  --dd-item-bg-selected: var(--neutral-5);
}

.input {
  color: var(--neutral-12);

  input {
    color: var(--neutral-12);
  }
}

.dropdown {
  li {
    &[aria-selected='true'] {
      background-color: var(--dd-item-bg-selected);

      div[aria-label='Label'] {
        color: var(--dd-item-text-selected);
      }
    }

    svg {
      color: transparent;
    }
  }
}

.inputWrapper {
  position: relative;

  &:focus-within {
    background-color: transparent !important;
  }

  div {
    background-color: transparent;

    &:focus-within {
      background-color: transparent !important;
    }

    .input {
      background-color: transparent;
    }
  }
}

.button_color {
  position: absolute;
  bottom: var(--space-0375);
  right: var(--space-0500);
  width: var(--space-1250);
  height: var(--space-1250);
  border-radius: var(--space-0125);
  cursor: pointer;
}

.input_hidden {
  position: absolute;
  bottom: 0;
  right: var(--space-0500);
  opacity: 0;
  pointer-events: none;
}