react-color#SketchPicker TypeScript Examples

The following examples show how to use react-color#SketchPicker. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: BubbleBackgroundColorSlider.tsx    From Oratio with MIT License 6 votes vote down vote up
export default function BubbleBackgroundColorPicker() {
  const { t } = useTranslation();
  const initColor = localStorage.getItem('bubbleColor') || '#ffffff';
  const [bubbleColor, setBackgroundColor] = React.useState<string>(initColor);

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const handlebackgroundColorChange = (color: any) => {
    setBackgroundColor(color.hex);
    localStorage.setItem('bubbleColor', color.hex);
  };

  return (
    <div>
      <Typography id="color-selector" gutterBottom>
        <ColorLensIcon /> {t('Speech Bubble Color')}
      </Typography>
      <Grid container spacing={3}>
        <Grid item xs>
          <SketchPicker
            color={bubbleColor}
            onChangeComplete={handlebackgroundColorChange}
          />
        </Grid>
      </Grid>
    </div>
  );
}
Example #2
Source File: FontColorPicker.tsx    From Oratio with MIT License 6 votes vote down vote up
export default function FontColorPicker() {
  const { t } = useTranslation();
  const initColor = localStorage.getItem('fontColor') || '#ffffff';
  const [fontColor, setFontColor] = React.useState<string>(initColor);

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const handleFontColorChange = (color: any) => {
    setFontColor(color.hex);
    localStorage.setItem('fontColor', color.hex);
  };

  return (
    <div>
      <Typography id="color-selector" gutterBottom>
        <ColorLensIcon /> {t('Text Color')}
      </Typography>
      <Grid container spacing={3}>
        <Grid item xs>
          <SketchPicker
            color={fontColor}
            onChangeComplete={handleFontColorChange}
          />
        </Grid>
      </Grid>
    </div>
  );
}
Example #3
Source File: custom-manual-palette.tsx    From S2 with MIT License 6 votes vote down vote up
function ColorTable({ palette, onChange }) {
  const columns = [
    {
      title: '#',
      render(r, v, idx) {
        return idx + 1;
      },
    },
    {
      title: '色值',
      dataIndex: 'color',
    },
    {
      title: '点击调整',
      dataIndex: 'color',
      render(val, _, idx) {
        return (
          <Popover
            trigger="click"
            content={
              <SketchPicker
                disableAlpha
                presetColors={[]}
                color={val}
                onChangeComplete={(evt) => {
                  const nextBasicColors = [...palette.basicColors];
                  nextBasicColors.splice(idx, 1, evt.hex);
                  onChange({
                    ...palette,
                    basicColors: nextBasicColors,
                  });
                }}
              />
            }
          >
            <Row justify="center">
              <div
                style={{
                  width: 30,
                  height: 30,
                  boxShadow: `0 0 8px rgba(0, 0, 0, 0.2)`,
                  cursor: 'pointer',
                  backgroundColor: val,
                }}
              />
            </Row>
          </Popover>
        );
      },
    },
    {
      title: '说明',
      dataIndex: 'desc',
    },
  ];

  const dataSource = palette.basicColors.map((color, idx) => ({
    color,
    desc: paletteDesc[idx],
  }));

  return (
    <Table
      size="small"
      rowKey="desc"
      bordered
      columns={columns}
      pagination={false}
      dataSource={dataSource}
    />
  );
}
Example #4
Source File: PropertiesPanel.tsx    From MagicUI with Apache License 2.0 6 votes vote down vote up
function BackgroundProperties(props: IBackgroundPropertiesProps) {
  const dispatch = useDispatch();
  const [color, setColor] = useState('');
  const [opacity, setOpacity] = useState(0);
  const [showPicker, toggleShowPicker, pickerRef] = useShowPicker(false);
  useEffect(() => setColor(props.background.fill), [props.background.fill]);
  useEffect(() => setOpacity(props.background.opacity), [props.background.opacity]);
  const handleChangeColor = (e: any) => {
    setColor(e.hex);
    dispatch(changeComponentBackground(e.hex, props.background.opacity));
  };
  const handleChangeOpacity = (e: any) => {
    setOpacity(+e.target.value);
    dispatch(changeComponentBackground(props.background.fill, +e.target.value));
  };

  return (
    <PropertiesItem name="BACKGROUND">
      <div className={style.bg_color_props}>
        <span>Fill</span>
        <input value={color} onClick={() => toggleShowPicker()}/>
        <div className={cls(style.bg_color_picker, showPicker && style.show)} ref={pickerRef}>
          <SketchPicker color={color} onChange={handleChangeColor}/>
        </div>
      </div>
      <div className={style.bg_opacity_props}>
        <span>Opacity</span>
        <input value={opacity} onChange={handleChangeOpacity}/>
      </div>
    </PropertiesItem>
  );
}
Example #5
Source File: index.tsx    From screenshot.rocks with MIT License 6 votes vote down vote up
ColorPicker = ({initialColor, onColorChange}: IColorPickerProps) => {
    const [displayColorPicker, setDisplayColorPicker] = useState(false);
    const [color, setColor] = useState<RGBColor>(hex2rgba(initialColor))

    const handleClick = () => {
        setDisplayColorPicker(!displayColorPicker);
    };

    const handleClose = () => {
        setDisplayColorPicker(false)
    };

    const handleChange = (color: any) => {
        setColor(color.rgb)
        onColorChange(color.rgb);
    };

    return (
        <div className={styles(color)}>
            <div className="swatch" onClick={handleClick}>
                <div className="color"/>
            </div>
            {displayColorPicker ?
                <div className="popup">
                    <div className="cover" onClick={handleClose}/>
                    <SketchPicker color={color} onChange={handleChange}/>
                </div> : null}
        </div>
    );
}
Example #6
Source File: ColorEditorItem.spec.tsx    From next-basics with GNU General Public License v3.0 6 votes vote down vote up
describe("ColorEditor", () => {
  jest.spyOn(window, "getComputedStyle").mockReturnValue({
    getPropertyValue: () => {
      return "#e8e8e8";
    },
  } as any);

  it("ColorEditorItem should work", () => {
    const wrapper = mount(
      <Form>
        <ColorEditorItem name="color" label="颜色" />
      </Form>
    );

    expect(wrapper.find(".popover").length).toEqual(0);
    wrapper.find(".colorCube").simulate("click");

    wrapper.update();
    expect(wrapper.find(".popover").length).toEqual(1);

    wrapper.find(SketchPicker).invoke("onChangeComplete")({
      hex: "#e9e9e9",
    });

    expect(wrapper.find(ColorPick).prop("value")).toEqual("#e9e9e9");

    wrapper.find(".cover").simulate("click");
    expect(wrapper.find(".popover").length).toEqual(0);
  });
});
Example #7
Source File: ColorPickerInput.tsx    From yana with MIT License 6 votes vote down vote up
ColorPickerInput: React.FC<{
  color: string;
  onChange: (newColor: string) => void;
  inputProps?: IInputGroupProps & HTMLInputProps;
}> = props => {
  return (
    <Popover content={<SketchPicker color={props.color} onChangeComplete={col => props.onChange(col.hex)} />}>
      <InputGroup
        value={props.color}
        leftIcon={<Icon icon={'symbol-square'} color={props.color} />}
        {...(props.inputProps || {})}
      />
    </Popover>
  );
}
Example #8
Source File: index.tsx    From imove with MIT License 6 votes vote down vote up
ColorPicker: React.FC<IProps> = (props) => {
  const { color, onChangeComplete: changeCb } = props;
  const [curColor, setCurColor] = useState(color);

  // life
  useEffect(() => setCurColor(color), [color]);

  // events
  const onChange = (color: ColorResult): void => setCurColor(color.hex);
  const onChangeComplete = (color: ColorResult): void => changeCb(color.hex);

  return (
    <SketchPicker
      color={curColor}
      onChange={onChange}
      onChangeComplete={onChangeComplete}
    />
  );
}
Example #9
Source File: ColorEditorItem.tsx    From next-basics with GNU General Public License v3.0 5 votes vote down vote up
export function LegacyColorPick(
  props: ColorEditorItemProps,
  ref: React.Ref<any>
) {
  const [value, setValue] = useState(props.value);
  const [visible, setVisible] = useState(false);

  useEffect(() => {
    setValue(props.value);
  }, [props.value]);

  const handleChangeComplete = (color: ColorResult) => {
    setValue(color.hex);
    props.onChange(color.hex);
  };

  const handleClick = () => {
    setVisible(true);
  };

  return (
    <div className={styles.colorContainer}>
      <div className={styles.colorCube} onClick={handleClick}>
        <div
          className={styles.colorContent}
          style={{ backgroundColor: value }}
        />
      </div>
      {visible && (
        <div className={styles.popover}>
          <div className={styles.cover} onClick={() => setVisible(false)} />
          <SketchPicker
            width="230px"
            ref={ref}
            color={value}
            onChangeComplete={handleChangeComplete}
            presetColors={getPresetColors(COLORS_MAP)}
          />
        </div>
      )}
    </div>
  );
}
Example #10
Source File: PropertiesPanel.tsx    From MagicUI with Apache License 2.0 5 votes vote down vote up
function TextProperties(props: ITextPropertiesProps) {
  const dispatch = useDispatch();
  const [text, setText] = useState('');
  const [color, setColor] = useState('');
  const [fontSize, setFontSize] = useState(0);
  const [showPicker, toggleShowPicker, pickerRef] = useShowPicker(false);

  useEffect(() => setText(props.text.text), [props.text.text]);
  useEffect(() => setColor(props.text.fill), [props.text.fill]);
  useEffect(() => setFontSize(props.text.fontSize), [props.text.fontSize]);

  const handleChangeText = (e: any) => {
    const value = e.target.value;
    setText(value);
    dispatch(changeComponentText(color, value, fontSize));
  };

  const handleChangeFontSize = (e: any) => {
    const value = e.target.value;
    setFontSize(value);
    dispatch(changeComponentText(color, text, value));
  };

  const handleChangeColor = (e: any) => {
    const value = e.hex;
    setColor(value);
    dispatch(changeComponentText(value, text, fontSize));
  };

  return (
    <PropertiesItem name="TEXT">
      <div className={style.text_props}>
        <span>Text</span>
        <input value={text} onChange={handleChangeText}/>
      </div>
      <div className={style.text_font_size_props}>
        <span>Size</span>
        <input value={fontSize} onChange={handleChangeFontSize}/>
      </div>
      <div className={style.text_color_props}>
        <span>Fill</span>
        <input value={color} onClick={toggleShowPicker}/>
        <div className={cls(style.text_color_picker, showPicker && style.show)} ref={pickerRef}>
          <SketchPicker color={color} onChange={handleChangeColor}/>
        </div>
      </div>
    </PropertiesItem>
  );
}
Example #11
Source File: PropertiesPanel.tsx    From MagicUI with Apache License 2.0 5 votes vote down vote up
function ShadowProperties(props: IShadowPropertiesProps) {
  const dispatch = useDispatch();
  const [offsetX, setOffsetX] = useState(0);
  const [offsetY, setOffsetY] = useState(0);
  const [blur, setBlur] = useState(0);
  const [color, setColor] = useState('');
  const [showPicker, toggleShowPicker, pickerRef] = useShowPicker(false);

  useEffect(() => setOffsetX(props.shadow.offsetX), [props.shadow.offsetX]);
  useEffect(() => setOffsetY(props.shadow.offsetY), [props.shadow.offsetY]);
  useEffect(() => setColor(props.shadow.fill), [props.shadow.fill]);
  useEffect(() => setBlur(props.shadow.blur), [props.shadow.blur]);

  const handleChangeOffsetX = (e: any) => {
    const value = +e.target.value;
    setOffsetX(value);
    dispatch(changeComponentShadow(color, blur, value, offsetY));
  };

  const handleChangeOffsetY = (e: any) => {
    const value = +e.target.value;
    setOffsetY(value);
    dispatch(changeComponentShadow(color, blur, offsetX, value));
  };

  const handleChangeBlur = (e: any) => {
    const value = +e.target.value;
    setBlur(value);
    dispatch(changeComponentShadow(color, value, offsetX, offsetY));
  };

  const handleChangeColor = (e: any) => {
    const value = e.hex;
    setColor(value);
    dispatch(changeComponentShadow(value, blur, offsetX, offsetY));
  };

  return (
    <PropertiesItem name="SHADOW">
      <div className={style.shadow_offset_props}>
        <div>
          <span>X</span>
          <input value={offsetX} onChange={handleChangeOffsetX}/>
        </div>
        <div>
          <span>Y</span>
          <input value={offsetY} onChange={handleChangeOffsetY}/>
        </div>
      </div>
      <div className={style.shadow_blur_props}>
        <span>Blur</span>
        <input value={blur} onChange={handleChangeBlur}/>
      </div>
      <div className={style.shadow_color_props}>
        <span>Fill</span>
        <input value={color} onClick={toggleShowPicker}/>
        <div className={cls(style.shadow_color_picker, showPicker && style.show)} ref={pickerRef}>
          <SketchPicker color={color} onChange={handleChangeColor}/>
        </div>
      </div>
    </PropertiesItem>
  );
}
Example #12
Source File: PropertiesPanel.tsx    From MagicUI with Apache License 2.0 5 votes vote down vote up
function BorderProperties(props: IBorderPropertiesProps) {
  const dispatch = useDispatch();
  const [width, setWidth] = useState(0);
  const [radius, setRadius] = useState(0);
  const [color, setColor] = useState('');
  const [showPicker, toggleShowPicker, pickerRef] = useShowPicker(false);

  useEffect(() => setWidth(props.border.width), [props.border.width]);
  useEffect(() => setRadius(props.border.radius), [props.border.radius]);
  useEffect(() => setColor(props.border.fill), [props.border.fill]);

  const handleChangeColor = (e: any) => {
    setColor(e.hex);
    dispatch(changeComponentBorder(e.hex, width, radius));
  };

  const handleChangeWidth = (e: any) => {
    setWidth(e.target.value);
    dispatch(changeComponentBorder(color, +e.target.value, radius));
  };

  const handleChangeRadius = (e: any) => {
    setRadius(e.target.value);
    dispatch(changeComponentBorder(color, width, +e.target.value));
  };

  return (
    <PropertiesItem name="BORDER">
      <div className={style.border_props}>
        <div>
          <span>W</span>
          <input value={width} onChange={handleChangeWidth}/>
        </div>
        <div>
          <span>R</span>
          <input value={radius} onChange={handleChangeRadius}/>
        </div>
      </div>
      <div className={style.border_color_props}>
        <span>Fill</span>
        <input value={color} onClick={toggleShowPicker}/>
        <div className={cls(style.border_color_picker, showPicker && style.show)} ref={pickerRef}>
          <SketchPicker color={color} onChange={handleChangeColor}/>
        </div>
      </div>
    </PropertiesItem>
  );
}
Example #13
Source File: index.tsx    From fe-v5 with Apache License 2.0 5 votes vote down vote up
export default function index(props: IProps) {
  const { value = '#000', onChange } = props;
  const [visible, setVisible] = useState(false);
  const eleRef = useRef<HTMLDivElement>(null);

  useOnClickOutside(eleRef, () => {
    setVisible(false);
  });

  return (
    <Popover
      trigger='click'
      placement='left'
      visible={visible}
      overlayClassName='color-picker-popover'
      content={
        <div
          ref={eleRef}
          onMouseLeave={() => {
            setVisible(false);
          }}
        >
          <SketchPicker
            color={value}
            onChange={(val) => {
              if (onChange) {
                onChange(val.hex);
              }
            }}
          />
        </div>
      }
    >
      <div
        style={{ background: value, width: 32, height: 32, borderRadius: 2, cursor: 'pointer' }}
        onClick={() => {
          setVisible(!visible);
        }}
      />
    </Popover>
  );
}
Example #14
Source File: index.tsx    From fe-v5 with Apache License 2.0 5 votes vote down vote up
export default function index(props: IProps) {
  const { value = '#000', onChange } = props;
  const [visible, setVisible] = useState(false);
  const eleRef = useRef<HTMLDivElement>(null);

  useOnClickOutside(eleRef, () => {
    setVisible(false);
  });

  return (
    <Popover
      trigger='click'
      placement='left'
      visible={visible}
      overlayClassName='color-picker-popover'
      content={
        <div
          ref={eleRef}
          onMouseLeave={() => {
            setVisible(false);
          }}
        >
          <SketchPicker
            color={value}
            onChange={(val) => {
              if (onChange) {
                onChange(val.hex);
              }
            }}
          />
        </div>
      }
    >
      <div
        style={{ background: value, width: 32, height: 32, borderRadius: 2, cursor: 'pointer' }}
        onClick={() => {
          setVisible(!visible);
        }}
      />
    </Popover>
  );
}
Example #15
Source File: button-font-color.tsx    From fantasy-editor with MIT License 5 votes vote down vote up
ButtonFontColor: FunctionComponent<Props> = props => {
  const [visible, setVisible] = useState(false);
  const editor = useSlate();
  const {
    editor: { removeColor },
  } = useLocale();
  const [color, setColor] = useState<string>('#1890ff');
  const [mark, setMark] = useState<Range | null>(null);

  const handleColorChange = (v: ColorResult) => {
    setColor(v.hex);
    setVisible(false);
    if (mark) {
      ReactEditor.focus(editor);
      Transforms.select(editor, mark);
      if (isMarkActive(editor, MARK_COLOR) && v.hex === '#000000') {
        editor.removeMark(MARK_COLOR);
      } else {
        editor.addMark(MARK_COLOR, v.hex);
      }
    }
  };

  const cleanColor = () => {
    editor.removeMark(MARK_COLOR);
    setVisible(false);
  };

  const show = () => {
    const { selection } = editor;
    setMark(selection);
    setVisible(true);
  };

  const overlay = (
    <div className={classNames('fc-btn-font-content', 'ant-dropdown-menu')} onMouseDown={e => e.stopPropagation()}>
      <div className="fc-btn-font-header" onClick={cleanColor}>
        <IconClear />
        <span>{removeColor}</span>
      </div>
      <SketchPicker disableAlpha={true} color={color} onChange={handleColorChange} />
    </div>
  );

  return (
    <Dropdown
      trigger={['click']}
      overlay={overlay}
      visible={visible}
      overlayClassName="fc-btn-font-overlay"
      onVisibleChange={setVisible}
      disabled={isBlockActive(editor, BLOCK_CODE)}
    >
      <DropdownButton width={45} onMouseDown={show}
                      disabled={isBlockActive(editor, BLOCK_CODE)}>
        <IconFontColor />
      </DropdownButton>
    </Dropdown>
  );
}
Example #16
Source File: button-bg-color.tsx    From fantasy-editor with MIT License 5 votes vote down vote up
ButtonBgColor: FunctionComponent<Props> = props => {
  const [visible, setVisible] = useState(false);
  const editor = useSlate();
  const {
    editor: { removeColor },
  } = useLocale();
  const [color, setColor] = useState<string>('#1890ff');
  const [mark, setMark] = useState<Range | null>(null);

  const handleColorChange = (v: ColorResult) => {
    setColor(v.hex);
    setVisible(false);
    if (mark) {
      ReactEditor.focus(editor);
      Transforms.select(editor, mark);
      if (isMarkActive(editor, MARK_BG_COLOR) && v.hex === '#fff') {
        editor.removeMark(MARK_BG_COLOR);
      } else {
        editor.addMark(MARK_BG_COLOR, v.hex);
      }
    }
  };

  const cleanColor = () => {
    editor.removeMark(MARK_BG_COLOR);
    setVisible(false);
  };

  const show = () => {
    const { selection } = editor;
    setMark(selection);
    setVisible(true);
  };

  const overlay = (
    <div className={classNames('fc-btn-bg-content', 'ant-dropdown-menu')} onMouseDown={e => e.stopPropagation()}>
      <div className="fc-btn-bg-header" onClick={cleanColor}>
        <IconClear />
        <span>{removeColor}</span>
      </div>
      <SketchPicker disableAlpha={true} color={color} onChange={handleColorChange} />
    </div>
  );

  return (
    <Dropdown
      trigger={['click']}
      overlay={overlay}
      visible={visible}
      overlayClassName="fc-btn-bg-overlay"
      onVisibleChange={setVisible}
      disabled={isBlockActive(editor, BLOCK_CODE)}
    >
      <DropdownButton width={45} onMouseDown={show}
                      disabled={isBlockActive(editor, BLOCK_CODE)}>
        <IconBgColor />
      </DropdownButton>
    </Dropdown>
  );
}
Example #17
Source File: color.tsx    From XFlow with MIT License 5 votes vote down vote up
ColorPicker: React.FC<IProps> = props => {
  const { label, value = '', onChange } = props
  const [show, setShow] = useState(false)
  const colorRef = useRef<string>(value)
  const { graphProvider } = useXFlowApp()
  const graphConfig = useRef<IGraphConfig>()
  graphProvider.getGraphOptions().then(x6GraphConfig => {
    graphConfig.current = x6GraphConfig
  })

  const PickContainer = () => {
    return (
      <div className={`${PREFIX}-pick-color-container`}>
        <div className={`${PREFIX}-popover`}>
          <SketchPicker
            onChange={color => {
              colorRef.current = color.hex
            }}
          />
          <div className="foolter">
            <Button
              onClick={() => {
                setShow(false)
              }}
            >
              取消
            </Button>
            <Button
              type="primary"
              onClick={() => {
                onChange?.(colorRef.current)
                setShow(false)
              }}
            >
              确认
            </Button>
          </div>
        </div>
      </div>
    )
  }

  const createPickColorContainer = (visible: boolean) => {
    const existElements = document.getElementsByClassName(`${PREFIX}-pick-color-container`)
    if (existElements.length) {
      Array.from(existElements).forEach(ele => {
        ele.parentNode?.removeChild(ele)
      })
    }
    if (!visible) {
      return
    }
    const div = document.createElement('div')
    render(createPortal(<PickContainer />, document.getElementsByTagName('body')[0]), div)
  }

  return (
    <div className="group">
      {label && <label>{label}</label>}
      <div
        className={`${PREFIX}-color-container`}
        onClick={() => {
          setShow(true)
        }}
      >
        <div
          className={`${PREFIX}-color`}
          style={{
            backgroundColor: value,
            height: '100%',
          }}
        />
      </div>
      {createPickColorContainer(show)}
    </div>
  )
}
Example #18
Source File: Color.tsx    From yugong with MIT License 4 votes vote down vote up
Color: React.FC<Props> = ({
    defaultColor,
    label,
    onChange,
    children,
    span,
    ...other
}) => {
    const [displayColorPicker, setDisplayColorPicker] = useState(false);
    const [color, setColor] = useState<RGBColor>();
    const [pickWrapStyle, setPickWrapStyle] = useState({});
    const picker = useRef(null);

    useEffect(() => {
        if (defaultColor) {
            const optColor: any = {};
            const temp = parse(defaultColor);
            if (temp.space) {
                optColor.r = temp.values[0];
                optColor.g = temp.values[1];
                optColor.b = temp.values[2];
                optColor.a = temp.alpha;
                setColor(optColor);
            }
        } else {
            setColor(undefined);
        }
    }, [defaultColor]);

    const handleClick = useCallback(
        (e) => {
            setDisplayColorPicker(!displayColorPicker);
            const style: any = {
                position: 'absolute',
            };

            const width = document.body.offsetWidth,
                height = document.body.offsetHeight,
                sWidth = 270,
                sHeight = 350,
                X = e.screenX,
                Y = e.screenY;

            // 1、判断拾色器的宽度小于窗口宽度
            if (width > sWidth) {
                if (X + sWidth > width) {
                    style.position = 'fixed';
                    style.right = `10px`;
                }
            }
            // 2、判断拾色器的高度大于窗口高度
            if (height > sHeight) {
                if (Y + sHeight > height) {
                    style.position = 'fixed';
                    style.bottom = `10px`;
                }
            }
            setPickWrapStyle(style);
        },
        [displayColorPicker]
    );

    const handleClose = useCallback(() => {
        setDisplayColorPicker(false);
    }, []);

    /**
     * 高频编辑防抖处理
     */
     const refChange = useSafeCallback(onChange);
     const onChangeDebounce = useMemo(
        () =>
            throttle((value) => {
                refChange(value);
            }, 500),
        [refChange]
    );


    const handleChange = useCallback(
        (color: ColorResult | 'inherit') => {
          let colorResult: any = color;
            if (color === 'inherit') {
                colorResult = undefined;
                setColor(undefined);
            } else {
                setColor(color.rgb);
            }

            onChangeDebounce({
                name: 'color',
                value: colorResult,
            });
        },
        [onChangeDebounce]
    );

    
    const renderColor = () => {
        return (
            <>
                {displayColorPicker ? (
                    <div className={s.popover}>
                        <div className={s.cover} onClick={handleClose} />
                        <div
                            className={s.wrap}
                            style={pickWrapStyle}
                            ref={picker}
                            onClick={(e) => e.stopPropagation()}
                        >
                            <SketchPicker
                                color={color || undefined}
                                width="250px"
                                onChange={handleChange}
                                className={s.picker}
                                presetColors={[
                                    '#f44336',
                                    '#e91e63',
                                    '#9c27b0',
                                    '#673ab7',
                                    '#3f51b5',
                                    '#2196f3',
                                    '#03a9f4',
                                    '#00bcd4',
                                    '#009688',
                                    '#4caf50',
                                    '#8bc34a',
                                    '#cddc39',
                                    '#ffeb3b',
                                    '#ffc107',
                                    '#ff9800',
                                    '#ff5722',
                                    '#aaaaaa',
                                    '#000000',
                                    '#fff',
                                    'transparent',
                                ]}
                            />
                            <div
                                onClick={() => handleChange('inherit')}
                                className={s.inherit}
                            >
                                移除
                            </div>
                        </div>
                    </div>
                ) : null}
            </>
        );
    };

    const displayColor = color && `rgba(${(color as any).r}, ${(color as any).g}, ${
      (color as any).b
  }, ${(color as any).a})`

    return (
        <>
            {children ? (
                <>
                    <span {...other} onClick={handleClick}>
                        {children}
                    </span>
                    {renderColor()}
                </>
            ) : (
                <Row className={s.row} gutter={4}>
                    <Col className={s.label} span={span?.label || 7}>
                        {label || ''}
                    </Col>
                    <Col span={ span?.value || 17}>
                        <div className={s.swatch} onClick={handleClick}>
                            {color ? (
                                <div
                                    className={s.color}
                                    style={{
                                        backgroundColor: displayColor,
                                    }}
                                />
                            ) : (
                                <div className={ClassNames(s.color, s.empty)}>
                                    <BgColorsOutlined />
                                </div>
                            )}
                            {renderColor()}
                        </div>
                    </Col>
                </Row>
            )}
        </>
    );
}
Example #19
Source File: AdminConfigForm.tsx    From binaural-meet with GNU General Public License v3.0 4 votes vote down vote up
AdminConfigForm: React.FC<AdminConfigFormProps> = (props: AdminConfigFormProps) => {
  const [clearName, setClearName] = React.useState('')
  const [showFillPicker, setShowFillPicker] = React.useState(false)
  const [showColorPicker, setShowColorPicker] = React.useState(false)
  const [downloadLink, setDownloadLink] = React.useState('')
  const fileToPlay = React.useRef<HTMLInputElement>(null)
  const fillButton = React.useRef<HTMLButtonElement>(null)
  const colorButton = React.useRef<HTMLButtonElement>(null)
  const {roomInfo, participants} = props.stores

  return <Observer>{()=>{
    const textForFill = isDarkColor(roomInfo.backgroundFill) ? 'white' : 'black'
    const textForColor = isDarkColor(roomInfo.backgroundColor) ? 'white' : 'black'
    const btnColor = roomInfo.passMatched ? 'primary' : 'default'

    return  <Box m={2}>
      <Box m={2}>
        <RemoteTrackLimitControl key="remotelimitcontrol" {...props.stores}/>
      </Box>
      <Box mt={2} mb={2}>
        <TextField autoFocus label="Admin password" type="password" style={{marginTop:-12}}
          value={roomInfo?.password} onChange={(ev)=>{ roomInfo.password=ev.currentTarget.value}}
          onKeyPress={(ev)=>onKeyPress(ev, roomInfo)}/>
        &emsp;
        <Button variant="contained" color="primary" style={{textTransform:'none'}} onClick={() => {
          let pass = roomInfo.roomProps.get('password')
          if (!pass){ pass = '' }
          roomInfo.passMatched = roomInfo?.password === pass
        }}> Check </Button>&emsp;
        {roomInfo.passMatched ? 'OK': 'Not matched'}
      </Box>
      <Box mt={2} mb={2}>
        <TextField label="New password to update" type="text" style={{marginTop:-12}}
          value={roomInfo?.newPassword} onChange={(ev)=>{roomInfo.newPassword=ev.currentTarget.value}}
        />&emsp;
        <Button variant="contained" color={btnColor} disabled={!roomInfo.passMatched} style={{textTransform:'none'}}
          onClick={() => {
            if (roomInfo.passMatched){
              connection.conference.setRoomProp('password', roomInfo.newPassword)
            }
          }}> Update password </Button>&emsp;
      </Box>
      <Box mt={2}>
        <Button variant="contained" color={btnColor} style={{textTransform:'none'}}
          disabled={!roomInfo.passMatched} onClick={() => {
          if (roomInfo.passMatched) { connection.conference.sendMessage(MessageType.MUTE_VIDEO, true) }
        }}> Mute all videos </Button> &nbsp;
        <Button variant="contained" color={btnColor} style={{textTransform:'none'}}
          disabled={!roomInfo.passMatched} onClick={() => {
          if (roomInfo.passMatched) { connection.conference.sendMessage(MessageType.MUTE_VIDEO, false) }
        }}> Show all videos </Button>&emsp;
        <Button variant="contained" color={btnColor} style={{textTransform:'none'}}
          disabled={!roomInfo.passMatched} onClick={() => {
          if (roomInfo.passMatched) { connection.conference.sendMessage(MessageType.MUTE_AUDIO, true) }
        }}> Mute all mics </Button>&nbsp;
        <Button variant="contained" color={btnColor} style={{textTransform:'none'}}
          disabled={!roomInfo.passMatched} onClick={() => {
          if (roomInfo.passMatched) { connection.conference.sendMessage(MessageType.MUTE_AUDIO, false) }
        }}> Switch on all mics </Button>
      </Box>
      <Box mt={2}>
        <Button variant="contained" color={btnColor} style={{textTransform:'none'}}
          disabled={!roomInfo.passMatched} onClick={() => {
          if (roomInfo.passMatched) {
            contents.removeAllContents()
          }
        }}> Remove all Contents </Button>&emsp;
        <Button variant="contained" color={btnColor} style={{textTransform:'none'}}
          disabled={!roomInfo.passMatched} onClick={() => {
            if (roomInfo.passMatched){
              const ids = new Set(contents.roomContentsInfo.keys())
              contents.all.forEach(c => ids.add(c.id))
              contents.all.filter(c => c.ownerName === clearName).forEach(c => contents.removeByLocal(c.id))
            }
        }}> Clear contents by user name </Button> &thinsp;
        <TextField label="name" type="text" style={{marginTop:-12}}
            value={clearName} onChange={(ev)=>{setClearName(ev.currentTarget.value)}} />
      </Box>
      <Box mt={2}>
        <Button variant="contained" color={btnColor} style={{textTransform:'none'}}
          disabled={!roomInfo.passMatched} onClick={() => {
          if (roomInfo.passMatched) {
            connection.conference.sendMessageViaJitsi(MessageType.RELOAD_BROWSER, {})
            if (connection.conference.bmRelaySocket?.readyState === WebSocket.OPEN){
              connection.conference.pushOrUpdateMessageViaRelay(MessageType.RELOAD_BROWSER, {})
            }
          }
        }}> Reload </Button>&emsp;

        <Button variant="contained" disabled={!roomInfo.passMatched}
          style={roomInfo.passMatched ?
            {backgroundColor:rgb2Color(roomInfo.backgroundFill), color:textForFill, textTransform:'none'}
            : {textTransform:'none'} }
          onClick={()=>{if (roomInfo.passMatched){ setShowFillPicker(true) }}} ref={fillButton}>
          Back color</Button>
        <Popover open={showFillPicker}
          onClose={()=>{
            setShowFillPicker(false)
            connection.conference.setRoomProp('backgroundFill', JSON.stringify(roomInfo.backgroundFill))
          }}
          anchorEl={fillButton.current} anchorOrigin={{vertical:'bottom', horizontal:'right'}}>
          <SketchPicker color = {{r:roomInfo.backgroundFill[0], g:roomInfo.backgroundFill[1],
            b:roomInfo.backgroundFill[2]}} disableAlpha
            onChange={(color, event)=>{
              event.preventDefault()
              roomInfo.backgroundFill = [color.rgb.r, color.rgb.g, color.rgb.b]
            }}
          />
        </Popover>
        &nbsp;
        <Button variant="contained" disabled={!roomInfo.passMatched}
          style={roomInfo.passMatched ?
            {backgroundColor:rgb2Color(roomInfo.backgroundColor), color:textForColor, textTransform:'none'}
            : {textTransform:'none'} }
          onClick={()=>{if (roomInfo.passMatched){ setShowColorPicker(true)} }} ref={colorButton}>
          Pattern color</Button>
        <Popover open={showColorPicker}
          onClose={()=>{
            setShowColorPicker(false)
            connection.conference.setRoomProp('backgroundColor', JSON.stringify(roomInfo.backgroundColor))
          }}
          anchorEl={colorButton.current} anchorOrigin={{vertical:'bottom', horizontal:'right'}}>
          <SketchPicker color = {{r:roomInfo.backgroundColor[0], g:roomInfo.backgroundColor[1],
            b:roomInfo.backgroundColor[2]}} disableAlpha
            onChange={(color, event)=>{
              event.preventDefault()
              roomInfo.backgroundColor = [color.rgb.r, color.rgb.g, color.rgb.b]
            }}
          />
        </Popover>&nbsp;
        <Button variant="contained" color={btnColor} style={{textTransform:'none'}}
          disabled={!roomInfo.passMatched} onClick={() => {
          if (roomInfo.passMatched) {
            roomInfo.backgroundFill = roomInfo.defaultBackgroundFill
            roomInfo.backgroundColor = roomInfo.defaultBackgroundColor
            connection.conference.setRoomProp('backgroundFill', JSON.stringify(roomInfo.backgroundFill))
            connection.conference.setRoomProp('backgroundColor', JSON.stringify(roomInfo.backgroundColor))
          }
        }}> Default </Button>&emsp;
        <Button variant="contained" color={btnColor} style={{textTransform:'none'}}
          disabled={!roomInfo.passMatched} onClick={() => {
            participants.local.recording = !participants.local.recording
            if (participants.local.recording){
              if (props.close) { props.close() }
              recorder.start(props.stores)
            }else{
              recorder.stop().then((all)=>{
                setDownloadLink(URL.createObjectURL(all))
                if (false){
                  all.slice(0, 4).arrayBuffer().then(buffer => {
                    const view = new Int32Array(buffer)
                    const headerLen = view[0]
                    all.slice(4, 4+headerLen).text().then(text => {
                      const headers = JSON.parse(text) as BlobHeader[]
                      console.log(JSON.stringify(headers))
                      for (const header of headers){ console.log(`blob: ${JSON.stringify(header)}`) }
                    })
                  })
                }
              })
            }
          }}>{participants.local.recording ? 'Stop Recorder' : 'Start Recorder'}</Button>&nbsp;
        {downloadLink ? <><a href={downloadLink} download="BMRecord.bin">Download</a>&nbsp;</> : undefined}
        <input type="file" accept="application/octet-stream" ref={fileToPlay} style={{display:'none'}}
          onChange={ (ev) => {
            const files = ev.currentTarget?.files
            if (files && files.length) {
              if (props.close){ props.close() }
              player.load(files[0]).then(()=>{
                player.play()
              })
            }
          }}  />
        <Button variant="contained" color='primary' style={{textTransform:'none'}}
          onClick={() => {
            fileToPlay.current?.click()
          }}>Play</Button>
      </Box>

    </Box>}
  }</Observer>
}
Example #20
Source File: WidgetsGroupModal.tsx    From hub with Apache License 2.0 4 votes vote down vote up
WidgetsGroupModal = (props: Props) => {
  const widthInput = useRef<RefInputField>(null);
  const whiteLabel = isWhiteLabel();
  const [theme, setTheme] = useState<string>(DEFAULT_THEME);
  const [header, setHeader] = useState<boolean>(false);
  const [stars, setStars] = useState<boolean>(true);
  const [loading, setLoading] = useState<boolean>(true);
  const [color, setColor] = useState<string>(DEFAULT_COLOR);
  const [fixedWidth, setFixedWidth] = useState<string | undefined>();
  const [groupWrapperWidthOpt, setGroupWrapperWidthOpt] = useState<string>(DEFAULT_WRAPPER_OPTION);
  const [isValidCode, setIsValidCode] = useState<boolean>(true);

  const onFixedWidthChange = (e: ChangeEvent<HTMLInputElement>) => {
    setFixedWidth(e.target.value);
    widthInput.current!.checkIsValid().then((res: boolean) => {
      setIsValidCode(res);
    });
  };

  const buildWidgetsGroupCode = (): string => {
    const code = `<div class="artifacthub-widget-group" data-url="${
      window.location.href
    }" data-theme="${theme}" data-header="${!header ? 'false' : 'true'}" data-stars="${
      !stars ? 'false' : 'true'
    }" data-color="${color}" data-responsive="${groupWrapperWidthOpt === 'responsive'}" ${
      fixedWidth ? `data-width="${fixedWidth}"` : ''
    } data-loading="${loading ? 'true' : 'false'}"></div><script async src="${
      window.location.origin
    }/artifacthub-widget.js"></script>`;

    return code;
  };

  const [widgetCode, setWidgetCode] = useState<string>(buildWidgetsGroupCode());

  const resetValues = () => {
    setTheme(DEFAULT_THEME);
    setHeader(false);
    setLoading(true);
    setFixedWidth(undefined);
    setColor(DEFAULT_COLOR);
    setGroupWrapperWidthOpt(DEFAULT_WRAPPER_OPTION);
    setWidgetCode(buildWidgetsGroupCode());
  };

  const onCloseModal = () => {
    props.setOpenStatus(false);
    resetValues();
  };

  const handleColorChange = (color: any) => {
    setColor(color.hex);
  };

  useEffect(() => {
    setWidgetCode(buildWidgetsGroupCode());
    /* eslint-disable react-hooks/exhaustive-deps */
  }, [
    theme,
    header,
    stars,
    fixedWidth,
    groupWrapperWidthOpt,
    color,
    loading,
    props.visibleWidget,
  ]); /* eslint-enable react-hooks/exhaustive-deps */

  return (
    <>
      {props.visibleWidget && (
        <Modal
          modalDialogClassName="fs-6"
          header={<div className={`h3 m-2 flex-grow-1 ${styles.title}`}>Widgets group</div>}
          onClose={onCloseModal}
          open={props.visibleWidget}
        >
          <div className="w-100 position-relative">
            <label className={`form-label fw-bold ${styles.label}`} htmlFor="theme">
              Theme
            </label>
            <div className="d-flex flex-row mb-3">
              {THEMES.map((themeOpt: RadioProps) => {
                return (
                  <div className="form-check me-4" key={`radio_theme_${themeOpt.name}`}>
                    <input
                      className="form-check-input"
                      type="radio"
                      name="theme"
                      id={themeOpt.name}
                      value={themeOpt.name}
                      checked={theme === themeOpt.name}
                      onChange={() => {
                        setTheme(themeOpt.name);
                      }}
                      required
                    />
                    <label className="form-label text-capitalize form-check-label" htmlFor={themeOpt.name}>
                      <div className="d-flex flex-row align-items-center">
                        {themeOpt.icon}
                        <span className="ms-1">{themeOpt.name}</span>
                      </div>
                    </label>
                  </div>
                );
              })}
            </div>

            {!whiteLabel && (
              <div className="mt-4 mb-3">
                <div className="form-check form-switch ps-0">
                  <label htmlFor="header" className={`form-check-label fw-bold ${styles.label}`}>
                    Header
                  </label>
                  <input
                    id="header"
                    type="checkbox"
                    className="form-check-input position-absolute ms-2"
                    value="true"
                    role="switch"
                    onChange={() => setHeader(!header)}
                    checked={header}
                  />
                </div>

                <div className="form-text text-muted mt-2">Display Artifact Hub header at the top of the widget.</div>
              </div>
            )}

            <div className="mt-4 mb-3">
              <div className="form-check form-switch ps-0">
                <label htmlFor="stars" className={`form-check-label fw-bold ${styles.label}`}>
                  Stars
                </label>
                <input
                  id="stars"
                  type="checkbox"
                  className="form-check-input position-absolute ms-2"
                  value="true"
                  role="switch"
                  onChange={() => setStars(!stars)}
                  checked={stars}
                />
              </div>

              <div className="form-text text-muted mt-2">Display number of stars given to the package.</div>
            </div>

            <div className="d-flex flex-row">
              <div>
                <label className={`form-label fw-bold ${styles.label}`} htmlFor="groupWrapperWidthOpt">
                  Container width
                </label>
                <div className="d-flex flex-row">
                  {WRAPPER_OPTIONS.map((wrapperOpt: RadioProps) => {
                    return (
                      <div className="form-check me-4" key={`radio_wrapperOpt_${wrapperOpt.name}`}>
                        <input
                          className="form-check-input"
                          type="radio"
                          name="groupWrapperWidthOpt"
                          id={wrapperOpt.name}
                          value={wrapperOpt.name}
                          checked={groupWrapperWidthOpt === wrapperOpt.name}
                          onChange={() => {
                            if (wrapperOpt.name === 'fixed') {
                              setFixedWidth((WIDGET_WIDTH * 2).toString());
                            } else {
                              setIsValidCode(true);
                              setFixedWidth(undefined);
                            }
                            setGroupWrapperWidthOpt(wrapperOpt.name);
                          }}
                          required
                        />
                        <label className="text-capitalize form-check-label" htmlFor={wrapperOpt.name}>
                          <div className="d-flex flex-row align-items-center">
                            {wrapperOpt.icon}
                            <span className="ms-1">{wrapperOpt.name}</span>
                          </div>
                        </label>
                      </div>
                    );
                  })}
                </div>
              </div>
              <div className={`position-relative ${styles.inputWrapper}`}>
                {groupWrapperWidthOpt === 'fixed' && (
                  <div className="position-absolute d-flex flex-row">
                    <InputField
                      ref={widthInput}
                      type="number"
                      name="fixedWidth"
                      min={380}
                      className="mb-0"
                      inputClassName={styles.input}
                      invalidText={{
                        default: 'This field is required',
                        rangeUnderflow: 'The min value is 380',
                      }}
                      onChange={onFixedWidthChange}
                      value={fixedWidth}
                      validateOnBlur
                      required
                    />
                    <div className="mt-1 text-muted ms-2">px</div>
                  </div>
                )}
              </div>
            </div>
            <div className="mt-4 mb-3">
              <div className="form-check form-switch ps-0">
                <label htmlFor="loading" className={`form-check-label fw-bold ${styles.label}`}>
                  Loading spinner
                </label>
                <input
                  id="loading"
                  type="checkbox"
                  role="switch"
                  className="form-check-input position-absolute ms-2"
                  value="true"
                  onChange={() => setLoading(!loading)}
                  checked={loading}
                />
              </div>

              <div className="form-text text-muted mt-2">Display loading spinner while waiting for search results.</div>
            </div>

            <div className="mt-4 mb-3">
              <div className="d-flex flex-row align-items-center">
                <label htmlFor="color" className={`form-label fw-bold mb-0 ${styles.label}`}>
                  Color
                </label>
                <div className={`btn btn-sm btn-light border p-1 ms-2 ${styles.colorInputWrapper}`}>
                  <div
                    className={styles.colorInput}
                    style={{
                      backgroundColor: color,
                    }}
                  />
                </div>
                {color !== DEFAULT_COLOR && (
                  <button
                    className="btn btn-sm btn-link text-muted py-0"
                    onClick={() => setColor(DEFAULT_COLOR)}
                    aria-label="Reset to default"
                  >
                    <IoIosClose />
                    <small>Reset to default</small>
                  </button>
                )}
              </div>
              <div className="form-text text-muted mt-3 mb-2">
                Color used for widgets border, header and loading spinner.
              </div>
              <div className={`pb-2 ${styles.colorPickerWrapper}`}>
                <SketchPicker
                  color={color}
                  presetColors={PRESET_COLORS}
                  onChangeComplete={handleColorChange}
                  disableAlpha
                />
              </div>
            </div>

            <div className="mt-3 mb-2">
              <label className={`form-label fw-bold ${styles.label}`}>Code</label>

              <div data-testid="block-content" className={`flex-grow-1 me-3 user-select-none ${styles.blockWrapper}`}>
                <SyntaxHighlighter
                  language="text"
                  style={docco}
                  customStyle={{
                    backgroundColor: 'var(--color-1-10)',
                  }}
                >
                  {widgetCode}
                </SyntaxHighlighter>
              </div>

              <ButtonCopyToClipboard
                text={widgetCode}
                tooltipClassName={`bs-tooltip-end ${styles.copyBtnTooltip}`}
                arrowClassName={styles.copyBtnArrow}
                visibleBtnText
                contentBtn="Copy code to clipboard"
                className="btn-outline-secondary px-2 py-1 text-uppercase"
                disabled={!isValidCode}
                label="Copy code to clipboard"
              />
            </div>
          </div>
        </Modal>
      )}
    </>
  );
}
Example #21
Source File: ColorPicker.tsx    From easy-email with MIT License 4 votes vote down vote up
export function ColorPicker(props: ColorPickerProps) {
  const { colors: presetColors, addCurrentColor } =
    useContext(PresetColorsContext);
  const [color, setColor] = useState('');
  const { value = '', onChange, children, showInput = true } = props;

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

  const onChangeComplete = useCallback(
    (color: ColorResult, event: React.ChangeEvent<HTMLInputElement>) => {
      if (event.target.value && event.target.value.replace('#', '').length < 6)
        return;
      const newColor = color.hex;
      setColor(newColor);
      onChange?.(newColor);
      addCurrentColor(newColor);
    },
    [addCurrentColor, onChange]
  );

  const onInputChange = useCallback(
    (value: string) => {
      setColor(value);
      onChange?.(value);
      addCurrentColor(value);
    },
    [addCurrentColor, onChange]
  );
  return (
    <div style={{ flex: 1, display: 'flex' }}>
      <Popover
        title={props.label}
        trigger='click'
        {...props}
        content={(
          <div className={styles.colorPicker}>
            <SketchPicker
              presetColors={presetColors}
              color={color}
              disableAlpha
              onChangeComplete={onChangeComplete}
            />
          </div>
        )}
      >
        {children || (
          <div
            style={{
              display: 'inline-block',
              height: 32,
              width: 32,
              boxSizing: 'border-box',
              padding: 4,
              border: '1px solid var(--color-neutral-3, rgb(229, 230, 235))',
              borderRadius: showInput ? undefined : 4,
              fontSize: 0,
              borderRight: showInput ? 'none' : undefined,
              position: 'relative',
              cursor: 'pointer',
            }}
          >
            {props.value ? (
              <span
                style={{
                  position: 'relative',
                  display: 'block',
                  border:
                    '1px solid var(--color-neutral-3, rgb(229, 230, 235))',

                  borderRadius: 2,
                  width: '100%',
                  height: '100%',
                  textAlign: 'center',
                  backgroundColor: value,
                }}
              />
            ) : (
              <img
                style={{
                  maxWidth: '100%',
                  maxHeight: '100%',
                  filter:
                    'invert(  0.78  )  drop-shadow(0 0px 0 rgb(0 0 0 / 45%))',
                }}
                src={getImg('AttributePanel_02')}
              />
            )}
          </div>
        )}
      </Popover>
      {showInput && (
        <Input
          value={props.value}
          style={{ outline: 'none', flex: 1 }}
          onChange={onInputChange}
        />
      )}
    </div>
  );
}
Example #22
Source File: AvatarUI.tsx    From avalon.ist with MIT License 4 votes vote down vote up
render() {
    const fontSize = Math.min(this.props.tableWidth * 0.04, this.props.fontSize);

    return (
      <>
        <div
          id="Avatar-UI"
          style={{
            top: this.props.avatarPosition[0] + 'px',
            left: this.props.avatarPosition[1] + 'px',
            display: this.props.avatarShow ? undefined : 'none',
          }}
          onMouseOver={this.renderButtonsTrue}
          onMouseLeave={this.renderButtonsFalse}
        >
          <div
            id="ave-graphics"
            style={{
              width: this.props.avatarSize + 'px',
              height: this.props.avatarSize + 'px',
              maxHeight: Math.max(this.props.tableWidth * 0.08, 45) + 'px',
              maxWidth: Math.max(this.props.tableWidth * 0.08, 45) + 'px',
              opacity: this.props.afk ? '0.5' : '1',
            }}
          >
            <div
              id="ave-background"
              className={
                this.background[this.state.currentBackground] +
                ' ' +
                ((this.state.avatarSelected && this.props.isPickable) || (this.props.highlighted) ? 'picked' : '')
              }
            />

            <div
              className={
                'ave tooltip ' +
                (this.props.killed ? 'killed ' : '') +
                (this.props.isPickable ? 'pickable' : 'not-pickable')
              }
              style={{
                backgroundImage:
                  'url(' +
                  (this.props.isRes ? this.props.resUrl : this.props.spyUrl) +
                  ')',
              }}
              onClick={this.pickPlayer}
            >
              {this.props.isPickable ? (
                <span className="tooltip-text">Click on this player to pick them</span>
              ) : null}
            </div>
            {this.props.hasClaimed ? (
              <div className="claim">
                <FontAwesomeIcon icon={faExclamationTriangle} />
              </div>
            ) : null}
            {this.props.killed ? <div className="ave-sword" /> : null}
            {this.props.onMission ? (
              <div className="ave-shield" ref={this.shieldLocation}>
                {this.props.shieldShow ? (
                  <div
                    style={{
                      transform: 'scale(' + this.props.shieldScale + ')',
                      top: this.props.shieldPosition[0] + 'px',
                      left: this.props.shieldPosition[1] + 'px',
                    }}
                    className="ave-shield-display"
                  />
                ) : null}
              </div>
            ) : null}
            {this.props.leader ? <div className="ave-flag" /> : null}
            {this.props.vote > -1 ? (
              <div className={'ave-vote-bubble ' + (this.props.vote === 1)} />
            ) : null}
            {this.state.renderButtons ? (
              <div className="ave-buttons">
                <button onClick={this.setBackgroundColor} className="tooltip">
                  <span className="tooltip-text">Mark this player's allegiance</span>
                  <FontAwesomeIcon icon={faStamp} />
                </button>
                <button onClick={this.toggleHighlightChat} className="tooltip">
                  <span className="tooltip-text">
                    Highlight this player's chat messages
                  </span>
                  <FontAwesomeIcon
                    style={{
                      backgroundColor: this.state.highlightChat
                        ? this.toHtmlHex(this.state.currentHighlight)
                        : '',
                    }}
                    icon={faPen}
                  />
                </button>
                <button onClick={this.showColorPicker} className="tooltip">
                  <span className="tooltip-text">
                    Change this player's highlight color
                  </span>
                  <FontAwesomeIcon icon={faPaintBrush} />
                </button>
              </div>
            ) : null}
          </div>
          <p
            className={'ave-username ' + (this.props.isMe ? 'me' : '')}
            style={{
              width: Math.max(this.props.tableWidth * 0.15, 40) + 'px',
              fontSize: Math.max(fontSize, 10) + 'px',
            }}
          >
            {this.props.card ? <FontAwesomeIcon icon={faAddressCard} /> : null}{' '}
            {this.props.hammer ? <FontAwesomeIcon icon={faGavel} /> : null}{' '}
            {this.props.username}
          </p>
          <p
            className={'ave-role ' + this.props.isRes}
            style={{
              opacity:
                this.props.role !== 'Spy?' && this.props.role !== 'Resistance?'
                  ? '1'
                  : '0',
              fontSize: Math.max(fontSize * 0.8, 8) + 'px',
            }}
          >
            {this.props.role}
          </p>
        </div>
        {this.state.renderPicker ? (
          <div className="hl-picker">
            <AvalonScrollbars>
              <div className="hl-stuff">
                <p>CHANGE HIGHLIGHT COLOR</p>
                <SketchPicker
                  color={this.state.currentHighlight}
                  onChange={this.handleHighlight}
                />
                <button onClick={this.hideColorPicker}>
                  <FontAwesomeIcon icon={faCheck} />
                </button>
              </div>
            </AvalonScrollbars>
          </div>
        ) : null}
      </>
    );
  }
Example #23
Source File: ColorPicker.tsx    From Cromwell with MIT License 4 votes vote down vote up
export function ColorPicker(props: {
    label?: string;
    value?: string;
    className?: string;
    style?: React.CSSProperties;
    onChange?: (color: string) => void;
}) {
    const colorRef = useRef<string | null>(null);
    const prevValue = useRef<string | null>(null);
    const inputAnchorRef = useRef<HTMLDivElement | null>(null);
    const [open, setOpen] = useState(false);
    const forceUpdate = useForceUpdate();

    if (props.value !== prevValue.current) {
        prevValue.current = props.value;
        colorRef.current = props.value;
    }

    const handleChange = (color: { hex: string; rgb: { r: number; g: number; b: number; a: number } }) => {
        const colorStr = color.rgb.a === 1 ? color.hex : `rgba(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b}, ${color.rgb.a})`;
        colorRef.current = colorStr;
        forceUpdate();
    }

    const handleClose = () => {
        handleApply();
        setOpen(false);
    }

    const handleApply = () => {
        props.onChange?.(colorRef.current);
    }

    const handleInputChange = (event) => {
        colorRef.current = event.target.value;
        forceUpdate();
        handleApply();
    }

    return (
        <>
            <TextField
                InputProps={{
                    startAdornment: (
                        <InputAdornment position="start">
                            <div style={{ backgroundColor: colorRef.current, width: '20px', height: '20px', borderRadius: '100%' }}></div>
                        </InputAdornment>
                    ),
                }}
                variant="standard"
                className={props.className}
                label={props.label}
                fullWidth
                value={colorRef.current}
                ref={inputAnchorRef}
                onChange={handleInputChange}
                onClick={() => setOpen(true)}
                style={props.style}
            />
            <Popover
                open={open}
                anchorEl={inputAnchorRef.current}
                onClose={handleClose}
                anchorOrigin={{
                    vertical: 'bottom',
                    horizontal: 'left',
                }}
                transformOrigin={{
                    vertical: 'top',
                    horizontal: 'left',
                }}
            >
                <div>
                    <SketchPicker
                        color={colorRef.current ?? '#000'}
                        onChangeComplete={handleChange}
                    />
                </div>
            </Popover>
        </>
    )
}
Example #24
Source File: LocalParticipantForm.tsx    From binaural-meet with GNU General Public License v3.0 4 votes vote down vote up
LocalParticipantForm: React.FC<LocalParticipantFormProps> = (props: LocalParticipantFormProps) => {
  const {participants, map} = props.stores
  const local = participants.local
  const [file, setFile] = useState<File|null>()
  const [showColorPicker, setShowColorPicker] = useState(false)
  const [showTextColorPicker, setShowTextColorPicker] = useState(false)
  const {t} = useTranslation()

  function closeConfig(ev:Object, reason:string) {
    if (reason === 'enter' || reason==='backdropClick'){
      local.sendInformation()
      local.saveInformationToStorage(true)
    }
    props.close()
  }


  const onKeyPress = (ev:React.KeyboardEvent) => {
    if (ev.key === 'Enter') {
      closeConfig(ev, 'enter')
    }else if (ev.key === 'Esc' || ev.key === 'Escape') {
      local.loadInformationFromStorage()
    }
  }
  function clearAvatarSrc(ev: React.FormEvent) {
    ev.preventDefault()
    setFile(null)
    local.information.avatarSrc = ''
  }
  function uploadAvatarSrc(ev: React.FormEvent) {
    ev.preventDefault()
    if (file) {
      uploadToGyazo(file).then((url) => {
        local.information.avatarSrc = url
      })
    }
  }

  const colorButton = React.useRef<HTMLButtonElement>(null)
  const textColorButton = React.useRef<HTMLButtonElement>(null)
  const {close, ...popoverProps} = props

  return <Popover {...popoverProps} onClose={closeConfig}>
    <DialogTitle>
      <span  style={{fontSize: isSmartphone() ? '2.5em' : '1em'}}>
        {t('lsTitle')}
      </span>
      <span style={{float:'right'}}>
        <SignalQualityButton open={props.open} stats={local.quality} isLocal={true}/></span>
    </DialogTitle>
    <DialogContent>
      <Observer>{ ()=> {
        const rgb = local.getColorRGB()
        const textRgb = local.getTextColorRGB()
        const textColor = isDarkColor(rgb) ? 'white' : 'black'
        const backColor = isDarkColor(textRgb) ? 'lightgray' : 'gray'
        //  console.log('render color picker', rgb)

        return  <>
          <TextField label={t('YourName')} multiline={false} value={local.information.name} style={tfDivStyle}
            inputProps={{style: tfIStyle, autoFocus:true}} InputLabelProps={{style: tfLStyle}}
            onChange={event => {local.information.name = event.target.value}}
            onKeyPress={onKeyPress} fullWidth={true}
          />
          <Box mt={3}>
            <div style={{fontSize:12}}>{t('lsColor')}</div>
            <Box ml={2}>
              <Button variant="contained"
                style={{backgroundColor:rgb2Color(rgb), color:textColor, textTransform:'none'}}
                onClick={()=>{setShowColorPicker(true)}} ref={colorButton}>
                {t('lsColorAvatar')}</Button>
              <Popover open={showColorPicker} onClose={()=>{setShowColorPicker(false)}}
                anchorEl={colorButton.current} anchorOrigin={{vertical:'bottom', horizontal:'right'}}>
                <SketchPicker color = {{r:rgb[0], g:rgb[1], b:rgb[2]}} disableAlpha
                  onChange={(color, event)=>{
                    event.preventDefault()
                    local.information.color = [color.rgb.r, color.rgb.g, color.rgb.b]
                  }}
                  />
              </Popover>
              <Button variant="contained"
                style={{color:rgb2Color(textRgb), backgroundColor:backColor, marginLeft:15, textTransform:'none'}}
                onClick={()=>{setShowTextColorPicker(true)}} ref={textColorButton}>
                {t('lsColorText')}</Button>
              <Popover open={showTextColorPicker} anchorOrigin={{vertical:'bottom', horizontal:'right'}}
                onClose={()=>{setShowTextColorPicker(false)}} anchorEl={textColorButton.current}>
                <SketchPicker color = {{r:textRgb[0], g:textRgb[1], b:textRgb[2]}}
                  onChange={(color, event)=>{
                    event.preventDefault()
                    local.information.textColor = [color.rgb.r, color.rgb.g, color.rgb.b]
                  }}
                />
              </Popover>
              <Button variant="contained" style={{marginLeft:15, textTransform:'none'}}
                onClick={()=>{local.information.color=[]; local.information.textColor=[]}} >
                {t('lsAutoColor')}</Button>
            </Box>
          </Box>
          <Box mt={3}>
            <div style={{fontSize:12}}>{t('lsImage')}</div>
            <Box mt={-1} ml={2}>
              <form key="information" onSubmit = {uploadAvatarSrc}
                style={{lineHeight:'2em', fontSize: isSmartphone() ? '2.5em' : '1em'}}>
                <div style={{fontSize:12, marginTop:8}}>{t('lsImageFile')}</div>
                {local.information.avatarSrc ? <>
                  <img src={local.information.avatarSrc} style={{height:'1.5em', verticalAlign:'middle'}} alt="avatar"/>
                  <input style={iStyle} type="submit" onClick={clearAvatarSrc} value="✕" /> &nbsp;
                </> : undefined}
                <input style={iStyle} type="file" onChange={(ev) => {
                  setFile(ev.target.files?.item(0))
                }} />
                <input style={iStyle} type="submit" value="Upload" />
              </form>
              <TextField label={t('lsEmail')} multiline={false} value={local.info.email}
                style={{...tfDivStyle, marginTop:8}}
                inputProps={{style: tfIStyle, autoFocus:true}} InputLabelProps={{style: tfLStyle}}
                onChange={event => local.info.email = event.target.value}
                onKeyPress={onKeyPress} fullWidth={true}
              />
            </Box>
          </Box>
          <Box mt={3}>
            <div style={{fontSize:12}}>{t('lsNotification')}</div>
            <Box mt={-1} ml={2}>
            <FormControlLabel control={
              <Checkbox color="primary" checked={local.information.notifyCall}
              onChange={(ev)=>{local.information.notifyCall = ev.target.checked}} />
              } label={t('lsNotifyCall')} />
            <FormControlLabel control={
              <Checkbox color="primary" checked={local.information.notifyTouch}
                onChange={(ev)=>{local.information.notifyTouch = ev.target.checked}} />
              } label={t('lsNotifyTouch')} />
            <FormControlLabel control={
              <Checkbox color="primary" checked={local.information.notifyNear}
                onChange={(ev)=>{local.information.notifyNear = ev.target.checked}} />
              } label={t('lsNotifyNear')} />
            <FormControlLabel control={
              <Checkbox color="primary" checked={local.information.notifyYarn}
                onChange={(ev)=>{local.information.notifyYarn = ev.target.checked}} />
              } label={t('lsNotifyYarn')} />
            </Box>
          </Box>
        </>}}
      </Observer>
      <Box mt={4} mb={3}>
        <Button variant="contained" color="primary" style={{textTransform:'none'}}
          onClick={()=>{
            closeConfig({}, 'enter')
          }}>{t('btSave')}</Button>
        <Button variant="contained" color="secondary" style={{marginLeft:15, textTransform:'none'}}
          onClick={()=>{ local.loadInformationFromStorage()}}>{t('btCancel')}</Button>
        <Button variant="contained" style={{marginLeft:15, textTransform:'none'}}
          onClick={()=>{
            map.focusOn(local)
          }}>{t('ctFocus')}</Button>
      </Box>
    </DialogContent>
  </Popover>
}