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 e8b4208
Show file tree
Hide file tree
Showing 13 changed files with 313 additions and 58 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,30 +1,39 @@
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}>
<StudioTextarea
hideLabel
onFocus={(event) => event.currentTarget.select()}
ref={ref}
size='small'
{...rest}
/>
<StudioTextarea hideLabel 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 e8b4208

Please sign in to comment.