84 lines
		
	
	
	
		
			1.9 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
	
		
			1.9 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
// Copyright 2021 Signal Messenger, LLC
 | 
						|
// SPDX-License-Identifier: AGPL-3.0-only
 | 
						|
 | 
						|
import type { ReactNode } from 'react';
 | 
						|
import React, { forwardRef, useMemo } from 'react';
 | 
						|
import { v4 as uuid } from 'uuid';
 | 
						|
 | 
						|
import { getClassNamesFor } from '../util/getClassNamesFor.js';
 | 
						|
 | 
						|
export type PropsType = {
 | 
						|
  checked?: boolean;
 | 
						|
  children?: (childrenOpts: {
 | 
						|
    id: string;
 | 
						|
    checkboxNode: JSX.Element;
 | 
						|
    labelNode: JSX.Element;
 | 
						|
    checked?: boolean;
 | 
						|
  }) => JSX.Element;
 | 
						|
  description?: ReactNode;
 | 
						|
  disabled?: boolean;
 | 
						|
  isRadio?: boolean;
 | 
						|
  label: string;
 | 
						|
  moduleClassName?: string;
 | 
						|
  name: string;
 | 
						|
  onChange: (value: boolean) => unknown;
 | 
						|
  onClick?: () => unknown;
 | 
						|
};
 | 
						|
 | 
						|
export const Checkbox = forwardRef(function CheckboxInner(
 | 
						|
  {
 | 
						|
    checked,
 | 
						|
    children,
 | 
						|
    description,
 | 
						|
    disabled,
 | 
						|
    isRadio,
 | 
						|
    label,
 | 
						|
    moduleClassName,
 | 
						|
    name,
 | 
						|
    onChange,
 | 
						|
    onClick,
 | 
						|
  }: PropsType,
 | 
						|
  ref: React.Ref<HTMLInputElement>
 | 
						|
): JSX.Element {
 | 
						|
  const getClassName = getClassNamesFor('Checkbox', moduleClassName);
 | 
						|
  const id = useMemo(() => `${name}::${uuid()}`, [name]);
 | 
						|
 | 
						|
  const checkboxNode = (
 | 
						|
    <div className={getClassName('__checkbox')}>
 | 
						|
      <input
 | 
						|
        checked={Boolean(checked)}
 | 
						|
        disabled={disabled}
 | 
						|
        id={id}
 | 
						|
        name={name}
 | 
						|
        onChange={ev => onChange(ev.target.checked)}
 | 
						|
        onClick={onClick}
 | 
						|
        ref={ref}
 | 
						|
        type={isRadio ? 'radio' : 'checkbox'}
 | 
						|
      />
 | 
						|
    </div>
 | 
						|
  );
 | 
						|
 | 
						|
  const labelNode = (
 | 
						|
    <div>
 | 
						|
      <label htmlFor={id}>
 | 
						|
        <div>{label}</div>
 | 
						|
        <div className={getClassName('__description')}>{description}</div>
 | 
						|
      </label>
 | 
						|
    </div>
 | 
						|
  );
 | 
						|
 | 
						|
  return (
 | 
						|
    <div className={getClassName('')}>
 | 
						|
      <div className={getClassName('__container')}>
 | 
						|
        {children ? (
 | 
						|
          children({ id, checkboxNode, labelNode, checked })
 | 
						|
        ) : (
 | 
						|
          <>
 | 
						|
            {checkboxNode}
 | 
						|
            {labelNode}
 | 
						|
          </>
 | 
						|
        )}
 | 
						|
      </div>
 | 
						|
    </div>
 | 
						|
  );
 | 
						|
});
 |