import * as React from 'react'; import classNames from 'classnames'; import { useTranslations } from '@shoptet/ui-core-web'; import { Icon } from '../Icon/Icon'; import type { IconName } from '../Icon/IconName'; import { IconButton } from '../IconButton/IconButton'; import { dictionary } from './dictionary'; const DEFAULT_ICON: IconName = 'shp-placeholder'; export type ReorderableListingItemMode = 'parent' | 'subitem'; export type ReorderableListingItemState = 'default' | 'hover' | 'disabled' | 'hidden' | 'dragging'; export interface ReorderableListingItemOwnProps { /** * The row label. Rendered single-line with an ellipsis on overflow. */ label: React.ReactNode; /** * Leading icon. Swappable; defaults to the placeholder icon. * @default 'shp-placeholder' */ icon?: IconName; /** * Renders the leading icon. * @default true */ showIcon?: boolean; /** * Custom leading content (e.g. an image thumbnail). When provided it replaces the `icon`. */ media?: React.ReactNode; /** * Custom action-area content (e.g. multiple buttons). When provided it replaces the built-in * hide button — the consumer owns the actions, including any hide/show control. */ actions?: React.ReactNode; /** * `parent` renders a drag handle, `subitem` renders an indent marker and is not draggable. * @default 'parent' */ mode?: ReorderableListingItemMode; /** * Visual state of the row. * @default 'default' */ state?: ReorderableListingItemState; /** * Renders the hide action button. Ignored in `disabled` state. * @default true */ showHide?: boolean; /** * Callback fired when the hide action is toggled. */ onHideToggle?: () => void; /** * Drag handle node injected by the container (e.g. a React Aria drag button). * When omitted a plain visual handle is rendered. Ignored for subitems. */ dragHandle?: React.ReactNode; /** * Accessible label for the hide action when the row is visible. */ hideLabel?: string; /** * Accessible label for the hide action when the row is hidden. */ showLabel?: string; /** * Additional class name. */ className?: string; } export interface ReorderableListingItemProps extends Omit, 'className'>, ReorderableListingItemOwnProps {} export const ReorderableListingItem = React.forwardRef( function ReorderableListingItem( { label, icon = DEFAULT_ICON, showIcon = true, media, actions, mode = 'parent', state = 'default', showHide = true, onHideToggle, dragHandle, hideLabel, showLabel, className, ...rest }: ReorderableListingItemProps, ref: React.Ref ) { const translations = useTranslations(dictionary); const isSubitem = mode === 'subitem'; const isHidden = state === 'hidden'; const isDisabled = state === 'disabled'; const renderHide = showHide && !isDisabled && state !== 'dragging'; return (
{isSubitem ? ( ) : ( (dragHandle ?? ) )} {media ? ( {media} ) : ( showIcon && ( ) )} {label} event.stopPropagation()} onPointerDown={event => event.stopPropagation()} onKeyDown={event => { if (event.key === 'Enter' || event.key === ' ') { event.stopPropagation(); } }} > {actions ?? (renderHide && ( ))}
); } );