Skip to content

Commit

Permalink
feat(StudioInputTable): Add event listeners on table level
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasEng committed Oct 25, 2024
1 parent 3deec23 commit d3a81c6
Show file tree
Hide file tree
Showing 13 changed files with 313 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { StudioButtonProps } from '../../StudioButton';
import { StudioButton } from '../../StudioButton';
import { BaseInputCell } from './BaseInputCell';
import cn from 'classnames';
import { useEventProps } from './useEventProps';

export type CellButtonProps = StudioButtonProps;

Expand All @@ -14,10 +15,16 @@ export class CellButton extends BaseInputCell<HTMLButtonElement, CellButtonProps
{ className: givenClass, ...rest }: StudioButtonProps,
ref: ForwardedRef<HTMLButtonElement>,
): ReactElement {
/* eslint-disable react-hooks/rules-of-hooks */
/* Eslint misinterprets this as a class component, while it's really just a functional component within a class */

const eventProps = useEventProps<HTMLButtonElement>(rest);

const className = cn(classes.buttonCell, givenClass);

return (
<StudioTable.Cell className={className}>
<StudioButton ref={ref} variant='secondary' {...rest} />
<StudioButton ref={ref} variant='secondary' {...rest} {...eventProps} />
</StudioTable.Cell>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React from 'react';
import type { StudioCheckboxProps } from '../../StudioCheckbox';
import { StudioCheckbox } from '../../StudioCheckbox';
import { BaseInputCell } from './BaseInputCell';
import { useEventProps } from './useEventProps';

export type CellCheckboxProps = StudioCheckboxProps;

Expand All @@ -12,9 +13,14 @@ export class CellCheckbox extends BaseInputCell<HTMLInputElement, CellCheckboxPr
{ className, ...rest }: CellCheckboxProps,
ref: ForwardedRef<HTMLInputElement>,
): ReactElement {
/* eslint-disable react-hooks/rules-of-hooks */
/* Eslint misinterprets this as a class component, while it's really just a functional component within a class */

const eventProps = useEventProps<HTMLInputElement>(rest);

return (
<StudioTable.Cell className={className}>
<StudioCheckbox ref={ref} {...rest} />
<StudioCheckbox ref={ref} {...rest} {...eventProps} />
</StudioTable.Cell>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,35 @@
import { StudioTable } from '../../StudioTable';
import type { ForwardedRef, ReactElement } from 'react';
import React from 'react';
import type { FocusEvent, ForwardedRef, ReactElement } from 'react';
import React, { useCallback } from 'react';

import classes from './Cell.module.css';
import type { StudioTextareaProps } from '../../StudioTextarea';
import { StudioTextarea } from '../../StudioTextarea';
import { BaseInputCell } from './BaseInputCell';
import cn from 'classnames';
import { isCaretAtEnd, isCaretAtStart, isSomethingSelected } from '../dom-utils/caretUtils';
import { useEventProps } from './useEventProps';

export type CellTextareaProps = StudioTextareaProps;

export class CellTextarea extends BaseInputCell<HTMLTextAreaElement, CellTextareaProps> {
render(
{ className: givenClass, ...rest }: CellTextareaProps,
{ className: givenClass, onFocus, ...rest }: CellTextareaProps,
ref: ForwardedRef<HTMLTextAreaElement>,
): ReactElement {
/* eslint-disable react-hooks/rules-of-hooks */
/* Eslint misinterprets this as a class component, while it's really just a functional component within a class */

const handleFocus = useCallback(
(event: FocusEvent<HTMLTextAreaElement>): void => {
onFocus?.(event);
event.currentTarget.select();
},
[onFocus],
);

const eventProps = useEventProps<HTMLTextAreaElement>({ onFocus: handleFocus, ...rest });

const className = cn(classes.textareaCell, givenClass);
return (
<StudioTable.Cell className={className}>
Expand All @@ -24,6 +39,7 @@ export class CellTextarea extends BaseInputCell<HTMLTextAreaElement, CellTextare
ref={ref}
size='small'
{...rest}
{...eventProps}
/>
</StudioTable.Cell>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,40 @@
import { StudioTable } from '../../StudioTable';
import type { ForwardedRef, ReactElement } from 'react';
import React from 'react';
import type { FocusEvent, ForwardedRef, ReactElement } from 'react';
import React, { useCallback } from 'react';

import type { StudioTextfieldProps } from '../../StudioTextfield';
import { StudioTextfield } from '../../StudioTextfield';
import classes from './Cell.module.css';
import { BaseInputCell } from './BaseInputCell';
import cn from 'classnames';
import { isCaretAtEnd, isCaretAtStart, isSomethingSelected } from '../dom-utils/caretUtils';
import { useEventProps } from './useEventProps';

export type CellTextfieldProps = StudioTextfieldProps;

export class CellTextfield extends BaseInputCell<HTMLInputElement, CellTextfieldProps> {
render(
{ className: givenClass, ...rest }: CellTextfieldProps,
{ className: givenClass, onFocus, ...rest }: CellTextfieldProps,
ref: ForwardedRef<HTMLInputElement>,
): ReactElement {
/* eslint-disable react-hooks/rules-of-hooks */
/* Eslint misinterprets this as a class component, while it's really just a functional component within a class */

const handleFocus = useCallback(
(event: FocusEvent<HTMLInputElement>): void => {
onFocus?.(event);
event.currentTarget.select();
},
[onFocus],
);

const eventProps = useEventProps<HTMLInputElement>({ onFocus: handleFocus, ...rest });

const className = cn(classes.textfieldCell, givenClass);

return (
<StudioTable.Cell className={className}>
<StudioTextfield
hideLabel
onFocus={(event) => event.currentTarget.select()}
ref={ref}
size='small'
{...rest}
/>
<StudioTextfield hideLabel ref={ref} size='small' {...rest} {...eventProps} />
</StudioTable.Cell>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { HTMLAttributes } from 'react';
import { useMemo } from 'react';
import { useStudioInputTableContext } from '../StudioInputTableContext';
import type { HTMLCellInputElement } from '../types/HTMLCellInputElement';
import type { EventProps } from '../types/EventProps';

export function useEventProps<Element extends HTMLCellInputElement>({
onBlur,
onFocus,
onChange,
}: Partial<HTMLAttributes<Element>>): EventProps<Element> {
const { onChangeAny, onBlurAny, onFocusAny } = useStudioInputTableContext<Element>();

return useMemo<EventProps<Element>>(
() => ({
onChange: (event) => {
onChange?.(event);
onChangeAny?.(event);
},
onFocus: (event) => {
onFocus?.(event);
onFocusAny?.(event);
},
onBlur: (event) => {
onBlur?.(event);
onBlurAny?.(event);
},
}),
[onChange, onFocus, onBlur, onChangeAny, onBlurAny, onFocusAny],
);
}
Loading

0 comments on commit d3a81c6

Please sign in to comment.