diff --git a/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid-filters.scss b/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid-filters.scss index 7e32a1ef8c..6a04fc9631 100644 --- a/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid-filters.scss +++ b/packages/modules/data-widgets/src/themesource/datawidgets/web/_datagrid-filters.scss @@ -20,12 +20,12 @@ position: relative; .filter-input { - border-top-left-radius: 0; - border-bottom-left-radius: 0; + border-start-start-radius: 0; + border-end-start-radius: 0; } .btn-calendar { - margin-left: 5px; //Review in atlas, the current date picker is also 5px + margin-inline-start: 5px; //Review in atlas, the current date picker is also 5px .button-icon { width: 18px; height: 18px; @@ -43,16 +43,16 @@ .filter-selector-button { padding: 8px; - border-top-right-radius: 0; - border-bottom-right-radius: 0; - border-right: none; + border-start-end-radius: 0; + border-end-end-radius: 0; + border-inline-end: none; height: 100%; &:before { justify-content: center; width: 20px; height: 20px; - padding-left: 4px; /* The font has spaces in the right side, so to align in the middle we need this */ + padding-inline-start: 4px; /* The font has spaces in the right side, so to align in the middle we need this */ } } } diff --git a/packages/pluggableWidgets/datagrid-web/jest.config.js b/packages/pluggableWidgets/datagrid-web/jest.config.js index 22d837ab37..0ed441f0b2 100644 --- a/packages/pluggableWidgets/datagrid-web/jest.config.js +++ b/packages/pluggableWidgets/datagrid-web/jest.config.js @@ -1,8 +1,11 @@ +const base = require("@mendix/pluggable-widgets-tools/test-config/jest.enzyme-free.config.js"); + module.exports = { - ...require("@mendix/pluggable-widgets-tools/test-config/jest.enzyme-free.config.js"), + ...base, /** * `nanoevents` package is ESM module and because ESM is not supported by Jest yet * we mark `nanoevents` as a module that should be transformed by ts-jest. */ - transformIgnorePatterns: ["node_modules/(?!nanoevents)/"] + transformIgnorePatterns: ["node_modules/(?!nanoevents)/"], + setupFilesAfterEnv: [...base.setupFilesAfterEnv, "/jest.setup.ts"] }; diff --git a/packages/pluggableWidgets/datagrid-web/src/components/ColumnSelector.tsx b/packages/pluggableWidgets/datagrid-web/src/components/ColumnSelector.tsx index 3cf353dcb1..3f59648dfd 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/ColumnSelector.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/ColumnSelector.tsx @@ -37,15 +37,78 @@ export function ColumnSelector(props: ColumnSelectorProps): ReactElement { } }) ], - transform: false + transform: false, + whileElementsMounted: (reference, _, updateFn) => { + if (reference instanceof Element) { + const observer = new ResizeObserver(() => updateFn()); + observer.observe(reference); + return () => observer.disconnect(); + } + + updateFn(); + return () => {}; + } }); + const isRTL = useMemo(() => { + const refEl = refs.reference.current; + + if (refEl instanceof Element) { + try { + const dir = getComputedStyle(refEl).direction; + return dir === "rtl"; + } catch { + return document?.dir === "rtl"; + } + } + + if (typeof document !== "undefined") { + return document.dir === "rtl"; + } + + return false; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [refs.reference.current]); + + const correctedFloatingStyles = useMemo(() => { + const styles = floatingStyles; + + if (!isRTL || !styles || styles.left == null) { + return styles; + } + + const leftVal = + typeof styles.left === "number" ? styles.left : parseFloat(String(styles.left).replace("px", "")); + + const floatingEl = refs.floating.current; + const floatingWidth = floatingEl instanceof HTMLElement ? floatingEl.offsetWidth : 0; + + const viewportWidth = typeof window !== "undefined" ? window.innerWidth : 0; + const rightVal = Math.max(0, viewportWidth - leftVal - floatingWidth); + + return { + ...styles, + left: "auto", + right: rightVal + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isRTL, floatingStyles, refs.floating.current]); + + useEffect(() => { + update(); + }, [isRTL, update]); + useEffect(() => { - if (!show || !refs.reference.current || !refs.floating.current) { - return; + if (!show) return; + + const ref = refs.reference.current; + const flt = refs.floating.current; + if (ref && flt) { + const cleanup = autoUpdate(ref, flt, update); + return () => cleanup(); } - return autoUpdate(refs.reference.current, refs.floating.current, update); - }, [show, refs.reference, refs.floating, update]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [show, refs.reference.current, refs.floating.current, update]); const dismiss = useDismiss(context); const click = useClick(context); @@ -63,7 +126,7 @@ export function ColumnSelector(props: ColumnSelectorProps): ReactElement { className={`column-selectors`} data-focusindex={0} role="menu" - style={{ ...floatingStyles, maxHeight }} + style={{ ...correctedFloatingStyles, maxHeight }} {...getFloatingProps()} > {props.columns.map((column, index) => { diff --git a/packages/pluggableWidgets/datagrid-web/src/components/__tests__/ColumnResizer.spec.tsx b/packages/pluggableWidgets/datagrid-web/src/components/__tests__/ColumnResizer.spec.tsx index daa0d9572b..4fcd572b02 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/__tests__/ColumnResizer.spec.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/__tests__/ColumnResizer.spec.tsx @@ -1,4 +1,3 @@ -import "@testing-library/jest-dom"; import { render } from "@testing-library/react"; import { ColumnResizer } from "../ColumnResizer"; diff --git a/packages/pluggableWidgets/datagrid-web/src/components/__tests__/ColumnSelector.spec.tsx b/packages/pluggableWidgets/datagrid-web/src/components/__tests__/ColumnSelector.spec.tsx index 12830ab090..daf6c0c0b0 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/__tests__/ColumnSelector.spec.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/__tests__/ColumnSelector.spec.tsx @@ -1,6 +1,5 @@ import { act, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import "@testing-library/jest-dom"; import { ColumnSelector, ColumnSelectorProps } from "../ColumnSelector"; import { ColumnId, GridColumn } from "../../typings/GridColumn"; diff --git a/packages/pluggableWidgets/datagrid-web/src/components/__tests__/Header.spec.tsx b/packages/pluggableWidgets/datagrid-web/src/components/__tests__/Header.spec.tsx index defbdfd369..8700700918 100644 --- a/packages/pluggableWidgets/datagrid-web/src/components/__tests__/Header.spec.tsx +++ b/packages/pluggableWidgets/datagrid-web/src/components/__tests__/Header.spec.tsx @@ -1,5 +1,4 @@ import { dynamic } from "@mendix/widget-plugin-test-utils"; -import "@testing-library/jest-dom"; import { render } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { ContainerProvider } from "brandi-react"; diff --git a/packages/pluggableWidgets/datagrid-web/src/jest.setup.ts b/packages/pluggableWidgets/datagrid-web/src/jest.setup.ts new file mode 100644 index 0000000000..865ef41cd6 --- /dev/null +++ b/packages/pluggableWidgets/datagrid-web/src/jest.setup.ts @@ -0,0 +1,6 @@ +import "@testing-library/jest-dom"; + +global.ResizeObserver = jest.fn().mockImplementation(() => ({ + observe: jest.fn(), + disconnect: jest.fn() +}));