import { useMemo, useCallback } from "react"; import { Popover, Switch, Stack, Text, Group, Divider, UnstyledButton } from "@mantine/core"; import { Table } from "@tanstack/react-table"; import { IBaseRow, IBaseProperty } from "@/ee/base/types/base.types"; import { propertyTypes } from "@/ee/base/property-types/property-type.registry"; import { useTranslation } from "react-i18next"; import { useEscapeClose } from "@/ee/base/hooks/use-escape-close"; import cellClasses from "@/ee/base/styles/cells.module.css"; import viewClasses from "@/ee/base/styles/views.module.css"; type ViewPropertyVisibilityProps = { opened: boolean; onClose: () => void; table: Table; properties: IBaseProperty[]; onPersist: () => void; children: React.ReactNode; }; export function ViewPropertyVisibility({ opened, onClose, table, properties, onPersist, children, }: ViewPropertyVisibilityProps) { const { t } = useTranslation(); useEscapeClose(opened, onClose); const columns = useMemo(() => { return table .getAllLeafColumns() .filter((col) => col.id !== "__row_number"); }, [table, properties]); const allVisible = columns.every((col) => col.getIsVisible()); const noneVisible = columns.filter((col) => col.getCanHide()).every((col) => !col.getIsVisible()); const handleToggle = useCallback( (columnId: string, visible: boolean) => { const col = table.getColumn(columnId); if (!col) return; col.toggleVisibility(visible); onPersist(); }, [table, onPersist], ); const handleShowAll = useCallback(() => { columns.forEach((col) => { if (col.getCanHide()) { col.toggleVisibility(true); } }); onPersist(); }, [columns, onPersist]); const handleHideAll = useCallback(() => { columns.forEach((col) => { if (col.getCanHide()) { col.toggleVisibility(false); } }); onPersist(); }, [columns, onPersist]); return ( { if (!o) onClose(); }} onClose={onClose} position="bottom-end" shadow="md" width={260} trapFocus closeOnEscape closeOnClickOutside withinPortal > {children} {t("Properties")} {t("Show all")} {t("Hide all")} {columns.map((col) => { const property = col.columnDef.meta?.property as IBaseProperty | undefined; if (!property) return null; const canHide = col.getCanHide(); const isVisible = col.getIsVisible(); const typeConfig = propertyTypes.find((pt) => pt.type === property.type); const TypeIcon = typeConfig?.icon; return ( { if (canHide) { handleToggle(col.id, !isVisible); } }} style={{ opacity: canHide ? 1 : 0.5 }} > {TypeIcon && } {property.name} {}} // Clicking the track synthesizes a second click on the hidden input which bubbles // to UnstyledButton, firing handleToggle twice. stopPropagation blocks only that // synthetic input click so handleToggle fires exactly once. onClick={(e) => e.stopPropagation()} styles={{ track: { cursor: canHide ? "pointer" : "not-allowed" } }} /> ); })} ); }