Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .storybook/components/ProjectTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { addCustomCSSWithScoping } from '@ui5/webcomponents-react-base/internal/utils';
import { clsx } from 'clsx';
import type { ReactNode } from 'react';
import { useRef, useState } from 'react';
import { useId, useState } from 'react';
import classes from './ProjectTemplate.module.css';

interface ProjectTemplatePropTypes {
Expand Down Expand Up @@ -58,7 +58,7 @@ export function ProjectTemplate(props: ProjectTemplatePropTypes) {
note,
} = props;
const [popoverOpen, setPopoverOpen] = useState(false);
const linkRef = useRef(null);
const linkId = useId() + '-link';

return (
<ThemeProvider>
Expand All @@ -68,7 +68,7 @@ export function ProjectTemplate(props: ProjectTemplatePropTypes) {
<MessageStrip hideCloseButton design={MessageStripDesign.Critical} className={classes.unssupportedMessage}>
Currently not supported by V2.{' '}
<Link
ref={linkRef}
id={linkId}
accessibleRole="Button"
onClick={() => {
setPopoverOpen(true);
Expand All @@ -79,7 +79,7 @@ export function ProjectTemplate(props: ProjectTemplatePropTypes) {
</MessageStrip>
<Popover
className={classes.popover}
opener={linkRef.current}
opener={linkId}
open={popoverOpen}
onClose={() => {
setPopoverOpen(false);
Expand Down
2 changes: 1 addition & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const config = tseslint.config(
reactPlugin.configs.flat.recommended, // This is not a plugin object, but a shareable config object
reactPlugin.configs.flat['jsx-runtime'], // Add this if you are using React 17+
// eslint-plugin-react-hooks
...reactHooksPlugin.configs.recommended,
reactHooksPlugin.configs.flat.recommended,
{
languageOptions: {
globals: {
Expand Down
26 changes: 22 additions & 4 deletions examples/react-router-ts/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/react-router-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"eslint-plugin-import": "2.32.0",
"eslint-plugin-jsx-a11y": "6.10.2",
"eslint-plugin-react": "7.37.5",
"eslint-plugin-react-hooks": "6.1.1",
"eslint-plugin-react-hooks": "7.0.0",
"globals": "16.5.0",
"typescript": "5.8.3",
"typescript-eslint": "8.46.2",
Expand Down
4 changes: 1 addition & 3 deletions examples/vite-ts/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,16 @@ import tseslint from 'typescript-eslint';
export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
extends: [js.configs.recommended, ...tseslint.configs.recommended, reactHooks.configs.flat.recommended, ],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
},
},
Expand Down
26 changes: 22 additions & 4 deletions examples/vite-ts/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/vite-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"@vitejs/plugin-react": "5.1.0",
"cypress": "15.5.0",
"eslint": "9.39.0",
"eslint-plugin-react-hooks": "6.1.1",
"eslint-plugin-react-hooks": "7.0.0",
"eslint-plugin-react-refresh": "0.4.24",
"globals": "16.5.0",
"typescript-eslint": "8.46.2",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"eslint-plugin-no-only-tests": "3.3.0",
"eslint-plugin-prettier": "5.5.4",
"eslint-plugin-react": "7.37.5",
"eslint-plugin-react-hooks": "6.1.1",
"eslint-plugin-react-hooks": "7.0.0",
"eslint-plugin-storybook": "9.1.16",
"glob": "11.0.3",
"globals": "16.4.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/base/src/internal/hooks/useSyncRef.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export function useSyncRef<RefType = never>(
ref(node);
}
if ({}.hasOwnProperty.call(ref, 'current')) {
// React Refs are mutable
// eslint-disable-next-line react-hooks/immutability
(ref as MutableRefObject<RefType>).current = node;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ describe('withWebComponent', () => {
</Button>
<Popover
open={open}
// eslint-disable-next-line react-hooks/refs
opener={btnRef.current}
onClose={() => {
setOpen(false);
Expand Down
51 changes: 24 additions & 27 deletions packages/charts/src/components/LineChart/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

import { enrichEventWithDetails, ThemingParameters, useIsRTL, useSyncRef } from '@ui5/webcomponents-react-base';
import { forwardRef, useCallback, useRef } from 'react';
import { forwardRef, useRef } from 'react';
import type { LineProps, YAxisProps } from 'recharts';
import {
Brush,
Expand Down Expand Up @@ -182,32 +182,29 @@ const LineChart = forwardRef<HTMLDivElement, LineChartProps>((props, ref) => {

const onItemLegendClick = useLegendItemClick(onLegendClick);
const preventOnClickCall = useRef(0);
const onDataPointClickInternal = useCallback(
(payload, eventOrIndex) => {
if (eventOrIndex.dataKey && typeof onDataPointClick === 'function') {
preventOnClickCall.current = 2;
onDataPointClick(
enrichEventWithDetails({} as any, {
value: eventOrIndex.value,
dataKey: eventOrIndex.dataKey,
dataIndex: eventOrIndex.index,
payload: eventOrIndex.payload,
}),
);
} else if (typeof onClick === 'function' && preventOnClickCall.current === 0) {
onClick(
enrichEventWithDetails(eventOrIndex, {
payload: payload?.activePayload?.[0]?.payload,
activePayloads: payload?.activePayload,
}),
);
}
if (preventOnClickCall.current > 0) {
preventOnClickCall.current -= 1;
}
},
[onDataPointClick, preventOnClickCall.current],
);
const onDataPointClickInternal = (payload, eventOrIndex) => {
if (eventOrIndex.dataKey && typeof onDataPointClick === 'function') {
preventOnClickCall.current = 2;
onDataPointClick(
enrichEventWithDetails({} as any, {
value: eventOrIndex.value,
dataKey: eventOrIndex.dataKey,
dataIndex: eventOrIndex.index,
payload: eventOrIndex.payload,
}),
);
} else if (typeof onClick === 'function' && preventOnClickCall.current === 0) {
onClick(
enrichEventWithDetails(eventOrIndex, {
payload: payload?.activePayload?.[0]?.payload,
activePayloads: payload?.activePayload,
}),
);
}
if (preventOnClickCall.current > 0) {
preventOnClickCall.current -= 1;
}
};

const isBigDataSet = dataset?.length > 30;
const primaryDimensionAccessor = primaryDimension?.accessor;
Expand Down
11 changes: 5 additions & 6 deletions packages/charts/src/components/PieChart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,9 @@ const PieChart = forwardRef<HTMLDivElement, PieChartProps>((props, ref) => {
);
};

const tooltipValueFormatter = useCallback(
(value, name) => [measure.formatter(value), dimension.formatter(name)],
[measure.formatter, dimension.formatter],
);
const tooltipValueFormatter = (value, name) => {
return [measure.formatter(value), dimension.formatter(name)];
};

const onItemLegendClick = useLegendItemClick(onLegendClick, () => measure.accessor);
const onClickInternal = useOnClickInternal(onClick);
Expand Down Expand Up @@ -248,7 +247,7 @@ const PieChart = forwardRef<HTMLDivElement, PieChartProps>((props, ref) => {
</g>
);
},
[showActiveSegmentDataLabel, chartConfig.activeSegment, isDonutChart],
[showActiveSegmentDataLabel, chartConfig.activeSegment, isDonutChart, chartRef, measure],
);

const renderLabelLine = useCallback(
Expand All @@ -258,7 +257,7 @@ const PieChart = forwardRef<HTMLDivElement, PieChartProps>((props, ref) => {
if (hideDataLabel || chartConfig.activeSegment === props.index) return null;
return Pie.renderLabelLineItem({}, props, undefined);
},
[chartConfig.activeSegment, measure.hideDataLabel],
[chartConfig.activeSegment, measure],
);

const legendWrapperStyle = useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ const TimelineChartColumnLabel = ({
const newLabelArray = columnLabels
? columnLabels
: Array.from(Array(totalDuration).keys()).map((num) => `${num + start}`);
// eslint-disable-next-line react-hooks/set-state-in-effect
setLabelArray(newLabelArray);
}
}, [isDiscrete, columnLabels, start, totalDuration]);
Expand All @@ -95,7 +96,7 @@ const TimelineChartColumnLabel = ({
height: `${halfHeaderHeight}px`,
lineHeight: `${halfHeaderHeight}px`,
}}
></div>
/>
{isDiscrete ? (
<div
className={classNames.columnLabelItems}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,25 @@ const TimelineChartBody = ({
const scaleExpRef = useRef(0);
const [displayArrows, setDisplayArrows] = useState(false);

const onMouseWheelEvent = (evt: WheelEvent) => {
evt.preventDefault();
if (evt.deltaY < 0) {
// Only scale up if scaled width will not exceed MAX_BODY_WIDTH
const msrWidth = bodyRef.current.getBoundingClientRect().width;
if (msrWidth * SCALE_FACTOR < MAX_BODY_WIDTH) {
scaleExpRef.current++;
}
} else {
// Only scale down if scaled width will not be less than original
// width
if (scaleExpRef.current > 0) {
resetScroll();
scaleExpRef.current--;
}
}
onScale(Math.pow(SCALE_FACTOR, scaleExpRef.current));
};

useEffect(() => {
const bodyElement = bodyRef.current;
bodyElement?.addEventListener('wheel', onMouseWheelEvent);
Expand All @@ -81,25 +100,6 @@ const TimelineChartBody = ({
};
const hideTooltip = () => tooltipRef.current?.onLeaveItem();

const onMouseWheelEvent = (evt: WheelEvent) => {
evt.preventDefault();
if (evt.deltaY < 0) {
// Only scale up if scaled width will not exceed MAX_BODY_WIDTH
const msrWidth = bodyRef.current.getBoundingClientRect().width;
if (msrWidth * SCALE_FACTOR < MAX_BODY_WIDTH) {
scaleExpRef.current++;
}
} else {
// Only scale down if scaled width will not be less than original
// width
if (scaleExpRef.current > 0) {
resetScroll();
scaleExpRef.current--;
}
}
onScale(Math.pow(SCALE_FACTOR, scaleExpRef.current));
};

const showArrows = () => setDisplayArrows(true);

return (
Expand All @@ -121,6 +121,8 @@ const TimelineChartBody = ({
dataSet={dataset}
width={width}
rowHeight={rowHeight}
// todo: check side-effect
// eslint-disable-next-line react-hooks/refs
bodyRect={bodyRef.current?.getBoundingClientRect()}
/>
</TimelineChartLayer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const TimelineChartRow = ({
showTooltip,
hideTooltip,
}: TimelineChartRowProps) => {
// todo: fix mutation
// eslint-disable-next-line react-hooks/immutability
rowData.color = rowData.color ?? `var(--sapChart_OrderedColor_${(rowIndex % 12) + 1})`;

return (
Expand Down
Loading
Loading