Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

### Added

- [#422](https://github.com/react-querybuilder/react-querybuilder/issues/422) Adding the class `queryBuilder-branches` displays "tree view" branch lines.
- [#417](https://github.com/react-querybuilder/react-querybuilder/issues/417) Optional `arity` property for operators. When `arity` is either "unary" or a number less than 2, the value editor will not render when that operator is selected (similar to the standard "null"/"notNull" operators).
- [#408](https://github.com/react-querybuilder/react-querybuilder/issues/408) The interfaces `Option` (née `NameLabelPair`), `Field`, and `ValueEditorProps` now accept generics for `name` and other properties.
- [#418](https://github.com/react-querybuilder/react-querybuilder/issues/418) A new `OptionList` type covers the `options` property for all standard selection lists (field, operator, combinator, etc.). Previously this was a union type: `NameLabelPair[] | OptionGroup<NameLabelPair>[]`. `OptionList` is equivalent to this type, but 1) doesn't require typing the base type twice, and 2) uses the new `Option` name instead of the deprecated `NameLabelPair`.
Expand Down
6 changes: 5 additions & 1 deletion examples/ci/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const App = () => {
useValidation,
independentCombinators,
parseNumbers,
showBranches,
...commonOptions
} = options;
const commonProps: QueryBuilderProps<DefaultRuleGroupType> = {
Expand All @@ -38,7 +39,10 @@ export const App = () => {

return (
<div>
<QueryBuilderDnD>
<QueryBuilderDnD
controlClassnames={{
queryBuilder: showBranches ? 'queryBuilder-branches' : '',
}}>
{independentCombinators ? (
<QueryBuilder
key="rqb-ic"
Expand Down
3 changes: 2 additions & 1 deletion examples/ci/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export type CIOption =
| 'enableDragAndDrop'
| 'disabled'
| 'debugMode'
| 'parseNumbers';
| 'parseNumbers'
| 'showBranches';

export type CIOptions = Record<CIOption, boolean>;

Expand Down
2 changes: 2 additions & 0 deletions examples/ci/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const defaultOptions: CIOptions = {
disabled: false,
debugMode: false,
parseNumbers: false,
showBranches: false,
};

export const optionsOrder: CIOption[] = [
Expand All @@ -32,6 +33,7 @@ export const optionsOrder: CIOption[] = [
'disabled',
'debugMode',
'parseNumbers',
'showBranches',
];

export const optionsReducer = (
Expand Down
11 changes: 9 additions & 2 deletions packages/react-querybuilder/dev/App.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import clsx from 'clsx';
import queryString from 'query-string';
import type { ComponentType } from 'react';
import { Fragment, useCallback, useEffect, useMemo, useReducer, useState } from 'react';
Expand All @@ -7,7 +8,7 @@ import type {
RuleGroupType,
RuleGroupTypeIC,
} from '../src';
import { defaultValidator, QueryBuilder } from '../src';
import { defaultValidator, QueryBuilder, standardClassnames } from '../src';
import {
defaultOptions,
emptyQuery,
Expand Down Expand Up @@ -67,7 +68,13 @@ export const App = ({
fields,
...optVals,
validator: optVals.validateQuery ? defaultValidator : undefined,
...{ controlClassnames, controlElements },
controlClassnames: {
...controlClassnames,
queryBuilder: clsx(controlClassnames?.queryBuilder, {
[standardClassnames.branches]: optVals.showBranches,
}),
},
controlElements,
}),
[controlClassnames, controlElements, optVals]
);
Expand Down
7 changes: 7 additions & 0 deletions packages/react-querybuilder/dev/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const defaultOptions: DemoOptions = {
showLockButtons: false,
showNotToggle: false,
validateQuery: false,
showBranches: false,
};

export const optionOrder: DemoOption[] = [
Expand All @@ -47,6 +48,7 @@ export const optionOrder: DemoOption[] = [
'showCombinatorsBetweenRules',
'showLockButtons',
'showNotToggle',
'showBranches',
'validateQuery',
];

Expand Down Expand Up @@ -139,6 +141,11 @@ export const optionsMetadata: Record<
label: 'Parse numbers',
title: 'Parse real numbers from strings in rule values',
},
showBranches: {
link: '/docs/api/classnames',
label: 'Debug mode',
title: 'Enable debug logging for QueryBuilder and React DnD (see console)',
},
};

export const fields: Field[] = [
Expand Down
8 changes: 6 additions & 2 deletions packages/react-querybuilder/dev/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export type DemoOption =
| 'enableDragAndDrop'
| 'disabled'
| 'debugMode'
| 'parseNumbers';
| 'parseNumbers'
| 'showBranches';

export type DemoOptions = Record<DemoOption, boolean>;

Expand All @@ -28,7 +29,10 @@ export type CommonRQBProps = Pick<
| 'validator'
| 'controlClassnames'
| 'controlElements'
| Exclude<DemoOption, 'validateQuery' | 'independentCombinators' | 'parseNumbers'>
| Exclude<
DemoOption,
'validateQuery' | 'independentCombinators' | 'parseNumbers' | 'showBranches'
>
> & { independentCombinators?: boolean };

export type HttpsURL = `${'https'}://${string}`;
1 change: 1 addition & 0 deletions packages/react-querybuilder/src/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ export const standardClassnames = {
lockGroup: 'ruleGroup-lock',
valueSource: 'rule-valueSource',
valueListItem: 'rule-value-list-item',
branches: 'queryBuilder-branches',
} as const;

export const defaultControlClassnames: Classnames = {
Expand Down
96 changes: 92 additions & 4 deletions packages/react-querybuilder/src/query-builder.scss
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
// Variables
// Basic
$rqb-spacing: 0.5rem !default;
$rqb-background-color: rgba(0, 75, 183, 0.2) !default;
$rqb-border-color: #7f81a2 !default;
$rqb-border-style: solid !default;
$rqb-border-radius: 4px !default;
$rqb-border-width: 1px !default;

// Drag-and-drop
$rqb-dnd-hover-border-bottom-color: rebeccapurple !default;
$rqb-dnd-hover-copy-border-bottom-color: #669933 !default;
$rqb-dnd-hover-border-bottom-style: dashed !default;
$rqb-dnd-hover-border-bottom-width: 2px !default;

// Branches
$rqb-branch-indent: $rqb-spacing !default;
$rqb-branch-color: $rqb-border-color !default;
$rqb-branch-width: $rqb-border-width !default;
$rqb-branch-radius: $rqb-border-radius !default;
$rqb-branch-style: $rqb-border-style !default;

// Default styles
.ruleGroup {
display: flex;
flex-direction: column;
row-gap: $rqb-spacing;
gap: $rqb-spacing;
padding: $rqb-spacing;
border-color: $rqb-border-color;
border-style: $rqb-border-style;
Expand All @@ -25,7 +34,7 @@ $rqb-dnd-hover-border-bottom-width: 2px !default;
.ruleGroup-body {
display: flex;
flex-direction: column;
row-gap: $rqb-spacing;
gap: $rqb-spacing;

&:empty {
display: none;
Expand All @@ -35,7 +44,7 @@ $rqb-dnd-hover-border-bottom-width: 2px !default;
.ruleGroup-header,
.rule {
display: flex;
column-gap: $rqb-spacing;
gap: $rqb-spacing;
align-items: center;
}

Expand Down Expand Up @@ -102,3 +111,82 @@ $rqb-dnd-hover-border-bottom-width: 2px !default;
}

// #endregion

// #region Branches

.queryBuilder-branches {
.ruleGroup-body {
margin-left: calc(2 * #{$rqb-branch-indent});
}

.rule,
.ruleGroup .ruleGroup {
position: relative;

&::before,
&::after {
content: '';
width: $rqb-branch-indent;
left: calc(-#{$rqb-branch-indent} - #{$rqb-branch-width});
border-color: $rqb-branch-color;
border-style: $rqb-branch-style;
border-radius: 0;
position: absolute;
}

&::before {
top: -$rqb-spacing;
height: calc(50% + #{$rqb-spacing});
border-width: 0 0 $rqb-branch-width $rqb-branch-width;
}

&:last-child::before {
border-bottom-left-radius: $rqb-branch-radius;
}

&::after {
top: 50%;
height: 50%;
border-width: 0 0 0 $rqb-branch-width;
}

&:last-child::after {
display: none;
}
}

.ruleGroup .ruleGroup {
&::before,
&::after {
left: calc(calc(-#{$rqb-branch-indent} - #{$rqb-branch-width}) - #{$rqb-border-width});
}

&::before {
top: calc(-#{$rqb-spacing} - #{$rqb-border-width});
height: calc(50% + #{$rqb-spacing} + #{$rqb-border-width});
}

&::after {
height: calc(50% + #{$rqb-border-width});
}
}

.betweenRules {
position: relative;

&::before {
content: '';
width: $rqb-branch-indent;
left: calc(-#{$rqb-branch-indent} - #{$rqb-branch-width});
border-color: $rqb-branch-color;
border-style: $rqb-branch-style;
border-radius: 0;
position: absolute;
top: -$rqb-spacing;
height: calc(100% + #{$rqb-spacing});
border-width: 0 0 0 $rqb-branch-width;
}
}
}

// #endregion
5 changes: 3 additions & 2 deletions website/src/pages/demo/_components/Demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -362,9 +362,10 @@ export default function Demo({
() =>
clsx(
{ validateQuery: options.validateQuery, justifiedLayout: options.justifiedLayout },
variant === 'default' ? '' : `rqb-${variant}`
variant === 'default' ? '' : `rqb-${variant}`,
options.showBranches ? 'queryBuilder-branches' : ''
),
[options.justifiedLayout, options.validateQuery, variant]
[options.justifiedLayout, options.showBranches, options.validateQuery, variant]
);

return (
Expand Down
7 changes: 7 additions & 0 deletions website/src/pages/demo/_constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const defaultOptions: DemoOptions = {
debugMode: false,
parseNumbers: false,
justifiedLayout: false,
showBranches: false,
};

export const optionOrder: DemoOption[] = [
Expand All @@ -40,6 +41,7 @@ export const optionOrder: DemoOption[] = [
'debugMode',
'parseNumbers',
'justifiedLayout',
'showBranches',
];

export const optionsMetadata: Record<
Expand Down Expand Up @@ -136,6 +138,11 @@ export const optionsMetadata: Record<
label: 'Justified layout',
title: 'Add custom CSS to push the "clone", "lock", and "remove" buttons to the right edge',
},
showBranches: {
link: '/docs/api/classnames',
label: 'Show branches',
title: 'Add the `.queryBuilder-branches` class to display "tree view" branches',
},
};

export const optionOrderByLabel = optionOrder.sort((a, b) =>
Expand Down
9 changes: 7 additions & 2 deletions website/src/pages/demo/_constants/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export type DemoOption =
| 'disabled'
| 'debugMode'
| 'parseNumbers'
| 'justifiedLayout';
| 'justifiedLayout'
| 'showBranches';

export type DemoOptions = Record<DemoOption, boolean>;

Expand All @@ -31,7 +32,11 @@ export type CommonRQBProps = Pick<
| 'controlElements'
| Exclude<
DemoOption,
'validateQuery' | 'independentCombinators' | 'parseNumbers' | 'justifiedLayout'
| 'validateQuery'
| 'independentCombinators'
| 'parseNumbers'
| 'justifiedLayout'
| 'showBranches'
>
> & { independentCombinators?: boolean; justifiedLayout?: boolean };

Expand Down