Skip to content

Commit 9400b6e

Browse files
committed
Merge remote-tracking branch 'upstream/main' into fix-85553-rbr-carousel-sorting
2 parents 84831a4 + 094dbfd commit 9400b6e

45 files changed

Lines changed: 534 additions & 299 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/CONST/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,6 +1580,7 @@ const CONST = {
15801580
UPDATE_ADDRESS: 'POLICYCHANGELOG_UPDATE_ADDRESS',
15811581
UPDATE_FEATURE_ENABLED: 'POLICYCHANGELOG_UPDATE_FEATURE_ENABLED',
15821582
UPDATE_IS_ATTENDEE_TRACKING_ENABLED: 'POLICYCHANGELOG_UPDATE_IS_ATTENDEE_TRACKING_ENABLED',
1583+
UPDATE_REQUIRE_COMPANY_CARDS_ENABLED: 'POLICYCHANGELOG_UPDATE_REQUIRE_COMPANY_CARDS_ENABLED',
15831584
UPDATE_DEFAULT_APPROVER: 'POLICYCHANGELOG_UPDATE_DEFAULT_APPROVER',
15841585
UPDATE_SUBMITS_TO: 'POLICYCHANGELOG_UPDATE_SUBMITS_TO',
15851586
UPDATE_FORWARDS_TO: 'POLICYCHANGELOG_UPDATE_FORWARDS_TO',

src/ROUTES.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,14 @@ const DYNAMIC_ROUTES = {
304304
path: 'imported',
305305
entryScreens: [SCREENS.WORKSPACE.CATEGORIES],
306306
},
307+
WORKSPACE_CATEGORIES_SETTINGS: {
308+
path: 'categories-settings',
309+
entryScreens: [SCREENS.WORKSPACE.CATEGORIES],
310+
},
311+
WORKSPACE_CATEGORY_CREATE: {
312+
path: 'category-new',
313+
entryScreens: [SCREENS.WORKSPACE.CATEGORIES],
314+
},
307315
SPEND_CATEGORY_SELECTOR: {
308316
path: 'spend-category-selector/:groupID',
309317
entryScreens: [SCREENS.WORKSPACE.CATEGORIES_SETTINGS, SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORIES_SETTINGS],
@@ -2361,14 +2369,6 @@ const ROUTES = {
23612369
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
23622370
getRoute: (backTo?: string) => getUrlWithBackToParam(`workspaces/pay-and-downgrade` as const, backTo),
23632371
},
2364-
WORKSPACE_CATEGORIES_SETTINGS: {
2365-
route: 'workspaces/:policyID/categories/settings',
2366-
getRoute: (policyID: string) => `workspaces/${policyID}/categories/settings` as const,
2367-
},
2368-
WORKSPACE_CATEGORY_CREATE: {
2369-
route: 'workspaces/:policyID/categories/new',
2370-
getRoute: (policyID: string) => `workspaces/${policyID}/categories/new` as const,
2371-
},
23722372
WORKSPACE_CATEGORY_EDIT: {
23732373
route: 'workspaces/:policyID/category/:categoryName/edit',
23742374
getRoute: (policyID: string, categoryName: string) => `workspaces/${policyID}/category/${encodeURIComponent(categoryName)}/edit` as const,

src/SCREENS.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,7 @@ const SCREENS = {
777777
NAME: 'Workspace_Overview_Name',
778778
CLIENT_ID: 'Workspace_Overview_Client_ID',
779779
CATEGORY_CREATE: 'Category_Create',
780+
DYNAMIC_CATEGORY_CREATE: 'Dynamic_Category_Create',
780781
CATEGORY_EDIT: 'Category_Edit',
781782
CATEGORY_PAYROLL_CODE: 'Category_Payroll_Code',
782783
CATEGORY_GL_CODE: 'Category_GL_Code',
@@ -789,6 +790,7 @@ const SCREENS = {
789790
CATEGORY_REQUIRE_ITEMIZED_RECEIPTS_OVER: 'Category_Require_Itemized_Receipts_Over',
790791
CATEGORY_REQUIRED_FIELDS: 'Category_Required_Fields',
791792
CATEGORIES_SETTINGS: 'Categories_Settings',
793+
DYNAMIC_CATEGORIES_SETTINGS: 'Dynamic_Categories_Settings',
792794
DYNAMIC_CATEGORIES_IMPORT: 'Dynamic_Categories_Import',
793795
DYNAMIC_CATEGORIES_IMPORTED: 'Dynamic_Categories_Imported',
794796
DYNAMIC_SPEND_CATEGORY_SELECTOR: 'Dynamic_Spend_Category_Selector',

src/components/Charts/BarChart/BarChartContent.tsx

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import ChartTooltipLayer from '@components/Charts/components/ChartTooltipLayer';
1010
import ChartXAxisLabels from '@components/Charts/components/ChartXAxisLabels';
1111
import ChartYAxisLabels from '@components/Charts/components/ChartYAxisLabels';
1212
import {AXIS_LABEL_GAP, CHART_CONTENT_MIN_HEIGHT, CHART_PADDING, GLYPH_PADDING, X_AXIS_LINE_WIDTH, Y_AXIS_LINE_WIDTH, Y_AXIS_TICK_COUNT} from '@components/Charts/constants';
13-
import type {ComputeGeometryFn, HitTestArgs} from '@components/Charts/hooks';
13+
import type {HitTestArgs} from '@components/Charts/hooks';
1414
import {
1515
useChartFontManager,
1616
useChartInteractions,
@@ -22,7 +22,7 @@ import {
2222
useYAxisLabelWidth,
2323
} from '@components/Charts/hooks';
2424
import type {CartesianChartProps, ChartDataPoint} from '@components/Charts/types';
25-
import {calculateMinDomainPadding, DEFAULT_CHART_COLOR, getAdditionalOffset, getChartColor, rotatedLabelYOffset} from '@components/Charts/utils';
25+
import {calculateMinDomainPadding, DEFAULT_CHART_COLOR, getChartColor} from '@components/Charts/utils';
2626
import useTheme from '@hooks/useTheme';
2727
import useThemeStyles from '@hooks/useThemeStyles';
2828
import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
@@ -36,29 +36,6 @@ const BAR_INNER_PADDING = 0.3;
3636
*/
3737
const BASE_DOMAIN_PADDING = {top: 32, bottom: 1, left: 0, right: 0};
3838

39-
/**
40-
* Bar chart geometry for label hit-testing.
41-
* Labels are center-anchored: the 45° parallelogram's upper-right corner is offset
42-
* by (halfLabelWidth * sinA) right and up, so the box straddles the tick symmetrically.
43-
*/
44-
const computeBarLabelGeometry: ComputeGeometryFn = ({ascent, descent, sinA, angleRad, labelWidths, padding}) => {
45-
const maxLabelWidth = labelWidths.length > 0 ? Math.max(...labelWidths) : 0;
46-
const centeredUpwardOffset = angleRad > 0 ? (maxLabelWidth / 2) * sinA : 0;
47-
const halfLabelSins = labelWidths.map((w) => (w / 2) * sinA - variables.iconSizeExtraSmall / 3);
48-
const halfWidths = labelWidths.map((w) => w / 2);
49-
const additionalOffset = getAdditionalOffset(angleRad);
50-
return {
51-
labelYOffset: AXIS_LABEL_GAP + rotatedLabelYOffset(ascent, descent, angleRad) + centeredUpwardOffset - additionalOffset,
52-
iconSin: variables.iconSizeExtraSmall * sinA,
53-
labelSins: labelWidths.map((w) => w * sinA),
54-
halfWidths,
55-
cornerAnchorDX: halfLabelSins,
56-
cornerAnchorDY: halfLabelSins.map((v) => -v),
57-
yMin90Offsets: halfWidths.map((hw) => -hw + padding),
58-
yMax90Offsets: halfWidths.map((hw) => hw + padding),
59-
};
60-
};
61-
6239
type BarChartProps = CartesianChartProps & {
6340
/** Callback when a bar is pressed */
6441
onBarPress?: (dataPoint: ChartDataPoint, index: number) => void;
@@ -141,14 +118,12 @@ function BarChartContent({data, isLoading, yAxisUnit, yAxisUnitPosition = 'left'
141118
labelRotation,
142119
labelSkipInterval,
143120
chartBottom,
144-
computeGeometry: computeBarLabelGeometry,
145121
});
146122

147123
const handleChartBoundsChange = (bounds: ChartBounds) => {
148124
const domainWidth = bounds.right - bounds.left;
149125
const calculatedBarWidth = ((1 - BAR_INNER_PADDING) * domainWidth) / data.length;
150126
barWidth.set(calculatedBarWidth);
151-
chartBottom.set(bounds.bottom);
152127
yZero.set(0);
153128
setBarAreaWidth(domainWidth);
154129
setBoundsLeft(bounds.left);
@@ -216,6 +191,10 @@ function BarChartContent({data, isLoading, yAxisUnit, yAxisUnitPosition = 'left'
216191
if (!fontMgr || xAxisLabelHeight === undefined) {
217192
return null;
218193
}
194+
195+
const chartBoundsBottom = args.yScale(Math.min(...args.yTicks));
196+
chartBottom.set(chartBoundsBottom);
197+
219198
return (
220199
<>
221200
<ChartXAxisLabels
@@ -231,8 +210,7 @@ function BarChartContent({data, isLoading, yAxisUnit, yAxisUnitPosition = 'left'
231210
fontMgr={fontMgr}
232211
labelColor={theme.textSupporting}
233212
xScale={args.xScale}
234-
chartBoundsBottom={args.chartBounds.bottom}
235-
centerRotatedLabels
213+
chartBoundsBottom={chartBoundsBottom}
236214
/>
237215
<ChartYAxisLabels
238216
yTicks={args.yTicks}
@@ -258,7 +236,7 @@ function BarChartContent({data, isLoading, yAxisUnit, yAxisUnitPosition = 'left'
258236
fontMgr,
259237
variables.iconSizeExtraSmall,
260238
);
261-
const chartPadding = {...CHART_PADDING, bottom: labelSpace + CHART_PADDING.bottom + variables.iconSizeExtraSmall, left: yAxisLabelWidth + GLYPH_PADDING};
239+
const chartPadding = {...CHART_PADDING, bottom: labelSpace + CHART_PADDING.bottom, left: yAxisLabelWidth + GLYPH_PADDING};
262240

263241
if (isLoading || !fontMgr) {
264242
const reasonAttributes: SkeletonSpanReasonAttributes = {context: 'BarChartContent', isLoading, isFontLoading: !fontMgr};

src/components/Charts/LineChart/LineChartContent.tsx

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import ChartYAxisLabels from '@components/Charts/components/ChartYAxisLabels';
1212
import LeftFrameLine from '@components/Charts/components/LeftFrameLine';
1313
import ScatterPoints from '@components/Charts/components/ScatterPoints';
1414
import {AXIS_LABEL_GAP, CHART_CONTENT_MIN_HEIGHT, CHART_PADDING, GLYPH_PADDING, X_AXIS_LINE_WIDTH, Y_AXIS_LINE_WIDTH, Y_AXIS_TICK_COUNT} from '@components/Charts/constants';
15-
import type {ComputeGeometryFn, HitTestArgs} from '@components/Charts/hooks';
15+
import type {HitTestArgs} from '@components/Charts/hooks';
1616
import {
1717
useChartFontManager,
1818
useChartInteractions,
@@ -24,7 +24,7 @@ import {
2424
useYAxisLabelWidth,
2525
} from '@components/Charts/hooks';
2626
import type {CartesianChartProps, ChartDataPoint} from '@components/Charts/types';
27-
import {calculateMinDomainPadding, DEFAULT_CHART_COLOR, getAdditionalOffset, rotatedLabelYOffset} from '@components/Charts/utils';
27+
import {calculateMinDomainPadding, DEFAULT_CHART_COLOR} from '@components/Charts/utils';
2828
import useTheme from '@hooks/useTheme';
2929
import useThemeStyles from '@hooks/useThemeStyles';
3030
import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
@@ -42,26 +42,6 @@ const MIN_SAFE_PADDING = DOT_RADIUS + DOT_HOVER_EXTRA_RADIUS;
4242
/** Base domain padding applied to all sides */
4343
const BASE_DOMAIN_PADDING = {top: 16, bottom: 16, left: 0, right: 0};
4444

45-
/**
46-
* Line chart geometry for label hit-testing.
47-
* Labels are start-anchored at the tick: the 45° parallelogram's upper-right corner is
48-
* offset by (iconSize/3 * sinA) left and down, placing the box just below the axis line.
49-
*/
50-
const computeLineLabelGeometry: ComputeGeometryFn = ({ascent, descent, sinA, angleRad, labelWidths, padding}) => {
51-
const iconThirdSin = (variables.iconSizeExtraSmall / 3) * sinA;
52-
const additionalOffset = getAdditionalOffset(angleRad);
53-
return {
54-
labelYOffset: AXIS_LABEL_GAP + rotatedLabelYOffset(ascent, descent, angleRad) - additionalOffset,
55-
iconSin: variables.iconSizeExtraSmall * sinA,
56-
labelSins: labelWidths.map((w) => w * sinA),
57-
halfWidths: labelWidths.map((w) => w / 2),
58-
cornerAnchorDX: labelWidths.map(() => -iconThirdSin),
59-
cornerAnchorDY: labelWidths.map(() => iconThirdSin),
60-
yMin90Offsets: labelWidths.map(() => padding),
61-
yMax90Offsets: labelWidths.map((w) => w + padding),
62-
};
63-
};
64-
6545
type LineChartProps = CartesianChartProps & {
6646
/** Callback when a data point is pressed */
6747
onPointPress?: (dataPoint: ChartDataPoint, index: number) => void;
@@ -139,7 +119,6 @@ function LineChartContent({data, isLoading, yAxisUnit, yAxisUnitPosition = 'left
139119
labelAreaWidth: plotAreaWidth,
140120
firstTickLeftSpace: boundsLeft + domainPadding.left * paddingScale,
141121
lastTickRightSpace: chartWidth > 0 ? chartWidth - boundsRight + domainPadding.right * paddingScale : 0,
142-
allowTightDiagonalPacking: true,
143122
measurements,
144123
});
145124

@@ -158,14 +137,12 @@ function LineChartContent({data, isLoading, yAxisUnit, yAxisUnitPosition = 'left
158137
labelRotation,
159138
labelSkipInterval,
160139
chartBottom,
161-
computeGeometry: computeLineLabelGeometry,
162140
});
163141

164142
const handleChartBoundsChange = (bounds: ChartBounds) => {
165143
setPlotAreaWidth(bounds.right - bounds.left);
166144
setBoundsLeft(bounds.left);
167145
setBoundsRight(bounds.right);
168-
chartBottom.set(bounds.bottom);
169146
};
170147

171148
const checkIsOverDot = (args: HitTestArgs) => {
@@ -197,6 +174,8 @@ function LineChartContent({data, isLoading, yAxisUnit, yAxisUnitPosition = 'left
197174
}));
198175

199176
const renderOutside = (args: CartesianChartRenderArg<{x: number; y: number}, 'y'>) => {
177+
const chartBoundsBottom = args.yScale(Math.min(...args.yTicks));
178+
chartBottom.set(chartBoundsBottom);
200179
return (
201180
<>
202181
<LeftFrameLine
@@ -224,7 +203,7 @@ function LineChartContent({data, isLoading, yAxisUnit, yAxisUnitPosition = 'left
224203
fontMgr={fontMgr}
225204
labelColor={theme.textSupporting}
226205
xScale={args.xScale}
227-
chartBoundsBottom={args.chartBounds.bottom}
206+
chartBoundsBottom={chartBoundsBottom}
228207
/>
229208
)}
230209
{!!fontMgr && (
@@ -253,7 +232,7 @@ function LineChartContent({data, isLoading, yAxisUnit, yAxisUnitPosition = 'left
253232
fontMgr,
254233
variables.iconSizeExtraSmall,
255234
);
256-
const chartPadding = {...CHART_PADDING, bottom: labelSpace + CHART_PADDING.bottom + variables.iconSizeExtraSmall, left: yAxisLabelWidth + GLYPH_PADDING};
235+
const chartPadding = {...CHART_PADDING, bottom: labelSpace + CHART_PADDING.bottom, left: yAxisLabelWidth + GLYPH_PADDING};
257236

258237
if (isLoading || !fontMgr) {
259238
const reasonAttributes: SkeletonSpanReasonAttributes = {context: 'LineChartContent', isLoading, isFontLoading: !fontMgr};

src/components/Charts/components/ChartXAxisLabels.tsx

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {AXIS_LABEL_GAP, GLYPH_PADDING, MAX_X_AXIS_LABEL_WIDTH} from '@components
55
import {useChartParagraphs} from '@components/Charts/hooks';
66
import type {LabelRotation} from '@components/Charts/types';
77
import {getFontLineMetrics, rotatedLabelCenterCorrection, rotatedLabelYOffset, truncateLabel} from '@components/Charts/utils';
8-
import variables from '@styles/variables';
98

109
type ChartXAxisLabelsProps = {
1110
/** Original (non-truncated) label strings from the data. */
@@ -46,9 +45,6 @@ type ChartXAxisLabelsProps = {
4645

4746
/** Y-pixel coordinate of the bottom edge of the chart plot area. */
4847
chartBoundsBottom: number;
49-
50-
/** When true, rotated labels are centered on the tick. When false, they are right-aligned (end of text at tick). */
51-
centerRotatedLabels?: boolean;
5248
};
5349

5450
function ChartXAxisLabels({
@@ -65,7 +61,6 @@ function ChartXAxisLabels({
6561
labelColor,
6662
xScale,
6763
chartBoundsBottom,
68-
centerRotatedLabels = false,
6964
}: ChartXAxisLabelsProps) {
7065
const angleRad = (Math.abs(labelRotation) * Math.PI) / 180;
7166
const truncatedLabels = (() => {
@@ -83,14 +78,11 @@ function ChartXAxisLabels({
8378

8479
const paragraphs = useChartParagraphs(truncatedLabels, fontMgr, fontSize, labelColor, MAX_X_AXIS_LABEL_WIDTH);
8580

86-
const renderedWidths = truncatedLabels.map((_, i) => paragraphs?.at(i)?.width ?? 0);
87-
8881
// Derive ascent/descent from the first available paragraph's line metrics.
8982
const {ascent, descent} = getFontLineMetrics(fontMgr, fontSize);
9083

9184
const correction = rotatedLabelCenterCorrection(ascent, descent, angleRad);
92-
const centeredUpwardOffset = centerRotatedLabels && angleRad > 0 ? (Math.max(...renderedWidths) / 2) * Math.sin(angleRad) : 0;
93-
const labelY = chartBoundsBottom + AXIS_LABEL_GAP + rotatedLabelYOffset(ascent, descent, angleRad) + centeredUpwardOffset;
85+
const labelY = chartBoundsBottom + AXIS_LABEL_GAP + rotatedLabelYOffset(ascent, descent, angleRad);
9486

9587
return truncatedLabels.map((label, i) => {
9688
if (i % labelSkipInterval !== 0 || label.length === 0) {
@@ -111,13 +103,13 @@ function ChartXAxisLabels({
111103
key={`x-label-${label}-${tickX}`}
112104
paragraph={paraData.para}
113105
x={tickX - renderWidth / 2}
114-
y={labelY - variables.iconSizeExtraSmall}
106+
y={labelY - ascent}
115107
width={renderWidth + GLYPH_PADDING}
116108
/>
117109
);
118110
}
119111

120-
const textX = centerRotatedLabels ? tickX - renderWidth / 2 : tickX - renderWidth;
112+
const textX = tickX - renderWidth;
121113
const origin = vec(tickX, labelY);
122114

123115
return (

src/components/Charts/hooks/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,3 @@ export {default as useChartLabelFormats} from './useChartLabelFormats';
99
export {default as useDynamicYDomain} from './useDynamicYDomain';
1010
export {useTooltipData} from './useTooltipData';
1111
export {default as useLabelHitTesting} from './useLabelHitTesting';
12-
export type {ComputeGeometryFn, ComputeGeometryInput} from './useLabelHitTesting';

0 commit comments

Comments
 (0)