Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
06ecb23
useOverlayTriggerState update to not close popover on document click …
cnathe Oct 9, 2025
ff21fa4
move shouldShowRangeScaleOptions() to utils.ts and add shouldShowAggr…
cnathe Oct 9, 2025
f900b78
move ChartFieldInfo and ChartTypeInfo interfaces to models.ts
cnathe Oct 9, 2025
37747e5
move constants out of ChartBuilderModal.tsx
cnathe Oct 9, 2025
aaa3df0
Factor ChartFieldRangeScaleOptions.tsx out of ChartFieldOption.tsx
cnathe Oct 9, 2025
18023a5
ChartFieldAggregateOptions.tsx and move y-axis bar chart aggregate me…
cnathe Oct 9, 2025
2890669
jest fixes for prop change on ChartFieldOption
cnathe Oct 9, 2025
ea25dc0
jest test fixes for move of y-axis aggregate method to tooltip
cnathe Oct 9, 2025
b73e8d9
6.63.2-chartErrorBars.0
cnathe Oct 9, 2025
1f82a66
RadioGroupInput to only call onSetValue if the option is not disabled
cnathe Oct 9, 2025
4ed0dc4
ChartFieldAggregateOptions.tsx support for error bar radio options
cnathe Oct 9, 2025
9efa259
6.63.2-chartErrorBars.1
cnathe Oct 9, 2025
0216165
support for error bar radio options as separate overlay or to be incl…
cnathe Oct 9, 2025
bbe064c
jest test fix
cnathe Oct 9, 2025
64e716a
6.63.2-chartErrorBars.2
cnathe Oct 9, 2025
671589a
Merge branch 'develop' into fb_chartErrorBars
cnathe Oct 10, 2025
2f82388
6.64.1-chartErrorBars.0
cnathe Oct 10, 2025
c919d98
Merge branch 'develop' into fb_chartErrorBars
cnathe Oct 13, 2025
639db1c
6.64.2-chartErrorBars.0
cnathe Oct 13, 2025
65f780a
Merge branch 'develop' into fb_chartErrorBars
cnathe Oct 13, 2025
08e6ab2
6.64.3-chartErrorBars.0
cnathe Oct 13, 2025
c3075b3
github CR feedback
cnathe Oct 13, 2025
91e4ab4
jest tests for chart field option components
cnathe Oct 14, 2025
2b356e1
RadioGroupInput.tsx label disabled styling
cnathe Oct 15, 2025
d7f71fd
6.64.3-chartErrorBars.1
cnathe Oct 15, 2025
47abfc1
CR feedback re: RadioGroupOption key
cnathe Oct 16, 2025
4bbe06a
add ScaleType interface
cnathe Oct 16, 2025
4dd953c
CR changes - useMemo instead of useEffect, test selector updates, pro…
cnathe Oct 16, 2025
3f1f15f
6.64.3-chartErrorBars.2
cnathe Oct 16, 2025
acbab6d
show range options for bar chart y-axis (but not linear / log)
cnathe Oct 16, 2025
bdc6e00
6.64.3-chartErrorBars.3
cnathe Oct 16, 2025
a4d3a4d
support LKS saved config with multiple y-axis measures (only use first)
cnathe Oct 16, 2025
7dfae7f
6.64.3-chartErrorBars.4
cnathe Oct 16, 2025
c902e3a
Merge branch 'develop' into fb_chartErrorBars
cnathe Oct 20, 2025
c8e1679
6.65.1-chartErrorBars.0
cnathe Oct 20, 2025
2553ac6
Merge branch 'develop' into fb_chartErrorBars
cnathe Oct 22, 2025
7fd4bb3
6.65.2-chartErrorBars.0
cnathe Oct 22, 2025
0327b01
Update release notes with version number and release date
cnathe Oct 23, 2025
3fc89a4
npm run lint-branch-fix
cnathe Oct 23, 2025
0c7c7f2
6.66.0
cnathe Oct 23, 2025
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
4 changes: 2 additions & 2 deletions packages/components/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 packages/components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@labkey/components",
"version": "6.65.2",
"version": "6.66.0",
"description": "Components, models, actions, and utility functions for LabKey applications and pages",
"sideEffects": false,
"files": [
Expand Down
13 changes: 11 additions & 2 deletions packages/components/releaseNotes/components.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
# @labkey/components
Components, models, actions, and utility functions for LabKey applications and pages

### version TBD
*Released*: TBD
### version 6.66.0
*Released*: 23 October 2025
- ChartBuilderModal support for bar/line chart aggregate method and error bar options
- useOverlayTriggerState update to not close popover on document click that is a select option target
- Factor ChartFieldRangeScaleOptions.tsx out of ChartFieldOption.tsx
- Create ChartFieldAggregateOptions.tsx and move y-axis bar chart aggregate method dropdown into tooltip
- support for error bar radio options as separate overlay or to be included in axis options overlay
- Update ChartBuilderModal to pass down aggregate and error bar options to ChartConfig

### version 6.65.2
*Released*: 22 October 2025
- Various minor fixes for exception reports

### version 6.65.1
Expand Down
20 changes: 11 additions & 9 deletions packages/components/src/internal/OverlayTrigger.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import React, {
cloneElement,
Children,
cloneElement,
CSSProperties,
FC,
useRef,
ReactElement,
useState,
useCallback,
MutableRefObject,
CSSProperties,
useMemo,
PropsWithChildren,
ReactElement,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { createPortal } from 'react-dom';

Expand Down Expand Up @@ -86,7 +86,9 @@ export function useOverlayTriggerState<T extends Element = HTMLDivElement>(
event => {
const isToggle = event.target === targetRef.current;
const insideToggle = portalEl?.contains(event.target);
if (!isToggle && !insideToggle) {
const isSelectOption =
event.target instanceof HTMLElement && event.target.classList.contains('select-input__option');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fun

if (!isToggle && !insideToggle && !isSelectOption) {
setShow(false);
}
},
Expand Down Expand Up @@ -168,9 +170,9 @@ export const OverlayTrigger: FC<Props> = ({
return (
<div
className={className_}
onClick={onClick}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onClick={onClick}
style={style}
>
{clonedChild}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@ import {

import {
ChartBuilderModal,
ChartTypeInfo,
getChartBuilderChartConfig,
getChartBuilderQueryConfig,
getChartRenderMsg,
getDefaultBarChartAxisLabel,
MAX_POINT_DISPLAY,
MAX_ROWS_PREVIEW,
} from './ChartBuilderModal';
import { ChartConfig, ChartQueryConfig, GenericChartModel } from './models';
import { MAX_POINT_DISPLAY, MAX_ROWS_PREVIEW } from './constants';
import { ChartConfig, ChartQueryConfig, ChartTypeInfo, GenericChartModel } from './models';

const BAR_CHART_TYPE = {
name: 'bar_chart',
Expand Down Expand Up @@ -319,7 +317,7 @@ describe('ChartBuilderModal', () => {
validate(false, true, true);
});

test('init from bar chart with y axis value and default aggregate method', () => {
test('init from bar chart with y axis value and default aggregate method', async () => {
const savedChartModel = {
canShare: true,
canDelete: true,
Expand Down Expand Up @@ -348,12 +346,20 @@ describe('ChartBuilderModal', () => {
);

validate(false, true, true);
expect(document.querySelectorAll('input')).toHaveLength(8);
expect(document.querySelectorAll('input')).toHaveLength(6);
expect(document.querySelector('input[name=y]').getAttribute('value')).toBe('field2');
expect(document.querySelectorAll('.fa-gear')).toHaveLength(1); // gear icon for y-axis
await userEvent.click(document.querySelector('.fa-gear'));
expect(document.querySelectorAll('input')).toHaveLength(13);
expect(document.querySelector('input[value=automatic]').hasAttribute('checked')).toBe(true);
expect(document.querySelector('input[value=manual]').hasAttribute('checked')).toBe(false);
expect(document.querySelector('input[name=aggregate-method]').getAttribute('value')).toBe('SUM');
expect(document.querySelectorAll('input[name=error-bar-method]')).toHaveLength(3);
expect(document.querySelector('input[value=SD]').hasAttribute('checked')).toBe(false);
expect(document.querySelector('input[value=SEM]').hasAttribute('checked')).toBe(false);
});

test('init from bar chart with y axis value and aggregate method', () => {
test('init from bar chart with y axis value and aggregate method', async () => {
const savedChartModel = {
canShare: true,
canDelete: true,
Expand All @@ -363,7 +369,10 @@ describe('ChartBuilderModal', () => {
visualizationConfig: {
chartConfig: {
renderType: 'bar_chart',
measures: { x: { name: 'field1' }, y: { name: 'field2', aggregate: { value: 'MEAN' } } },
measures: {
x: { name: 'field1' },
y: { name: 'field2', aggregate: { value: 'MEAN' }, errorBars: 'SEM' },
},
labels: { x: 'Field 1', y: 'Field 2' },
},
queryConfig: {
Expand All @@ -382,9 +391,17 @@ describe('ChartBuilderModal', () => {
);

validate(false, true, true);
expect(document.querySelectorAll('input')).toHaveLength(8);
expect(document.querySelectorAll('input')).toHaveLength(6);
expect(document.querySelector('input[name=y]').getAttribute('value')).toBe('field2');
expect(document.querySelectorAll('.fa-gear')).toHaveLength(1); // gear icon for y-axis
await userEvent.click(document.querySelector('.fa-gear'));
expect(document.querySelectorAll('input')).toHaveLength(13);
expect(document.querySelector('input[value=automatic]').hasAttribute('checked')).toBe(true);
expect(document.querySelector('input[value=manual]').hasAttribute('checked')).toBe(false);
expect(document.querySelector('input[name=aggregate-method]').getAttribute('value')).toBe('MEAN');
expect(document.querySelectorAll('input[name=error-bar-method]')).toHaveLength(3);
expect(document.querySelector('input[value=SD]').hasAttribute('checked')).toBe(false);
expect(document.querySelector('input[value=SEM]').hasAttribute('checked')).toBe(true);
expect(document.querySelectorAll('input[name=trendlineType]')).toHaveLength(0);
});

Expand Down Expand Up @@ -490,10 +507,12 @@ describe('ChartBuilderModal', () => {

await userEvent.click(document.querySelectorAll('.fa-gear')[0]); // x-axis options icon, click to close
await userEvent.click(document.querySelectorAll('.fa-gear')[1]); // y-axis options icon
expect(document.querySelectorAll('.radioinput-label.selected')[0].textContent).toBe('Log');
expect(document.querySelectorAll('.radioinput-label.selected')).toHaveLength(3); // error bar, scale, range
expect(document.querySelectorAll('.radioinput-label.selected')[0].textContent).toBe('None');
expect(document.querySelectorAll('.radioinput-label.selected')[1].textContent).toBe('Log');
expect(document.querySelectorAll('.radioinput-label.selected')[2].textContent).toBe('Automatic');
expect(document.querySelectorAll('input[name=scaleTrans]')[0].hasAttribute('checked')).toBe(false); // linear
expect(document.querySelectorAll('input[name=scaleTrans]')[1].hasAttribute('checked')).toBe(true); // log
expect(document.querySelectorAll('.radioinput-label.selected')[1].textContent).toBe('Automatic');
});

test('canDelete and canShare false', () => {
Expand Down
Loading