@evoke-platform/ui-components 1.0.0-dev.220 → 1.0.0-dev.221

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,6 +22,7 @@ export declare type CriteriaInputProps = {
22
22
  disabled?: boolean;
23
23
  hideBorder?: boolean;
24
24
  presetGroupLabel?: string;
25
+ freeSolo?: boolean;
25
26
  };
26
27
  export declare const valueEditor: (props: ValueEditorProps) => JSX.Element;
27
28
  declare const CriteriaBuilder: (props: CriteriaInputProps) => JSX.Element;
@@ -77,8 +77,9 @@ const customSelector = (props) => {
77
77
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
78
  const rule = props.rule;
79
79
  let width = '90px';
80
- let val = value;
80
+ let displayedValue = value;
81
81
  let opts = options;
82
+ const isFreeSoloEnabled = context.freeSolo && title === 'Fields';
82
83
  let readOnly = false;
83
84
  if (context.disabledCriteria) {
84
85
  readOnly =
@@ -95,24 +96,32 @@ const customSelector = (props) => {
95
96
  opts = options
96
97
  .filter((option) => ['null', 'notNull', 'in', 'notIn'].includes(option.name))
97
98
  .map((option) => ({ name: option.name, label: option.label }));
98
- val = val === '=' ? '' : options.find((option) => option.name === val).name;
99
+ displayedValue =
100
+ value === '='
101
+ ? ''
102
+ : options.find((option) => option.name === displayedValue).name;
99
103
  }
100
104
  else if (((_b = props.fieldData) === null || _b === void 0 ? void 0 : _b.inputType) === 'document') {
101
105
  opts = options
102
106
  .filter((option) => ['null', 'notNull'].includes(option.name))
103
107
  .map((option) => ({ name: option.name, label: option.label }));
104
- val = val === '=' ? '' : options.find((option) => option.name === val).name;
108
+ displayedValue =
109
+ value === '='
110
+ ? ''
111
+ : options.find((option) => option.name === displayedValue).name;
105
112
  }
106
113
  break;
107
114
  case 'Fields':
108
115
  width = '33%';
109
- val = (_c = options.find((option) => option.name === val)) === null || _c === void 0 ? void 0 : _c.name;
116
+ displayedValue = (_c = options.find((option) => option.name === displayedValue)) === null || _c === void 0 ? void 0 : _c.label;
117
+ if (isFreeSoloEnabled && !displayedValue) {
118
+ displayedValue = value;
119
+ }
110
120
  break;
111
121
  }
112
- return (React.createElement(Autocomplete, { options: opts, value: val !== null && val !== void 0 ? val : null, getOptionLabel: (option) => {
113
- var _a;
122
+ return (React.createElement(Autocomplete, { options: opts, value: displayedValue !== null && displayedValue !== void 0 ? displayedValue : null, getOptionLabel: (option) => {
114
123
  if (typeof option === 'string') {
115
- return ((_a = opts.find((o) => option === o.name)) === null || _a === void 0 ? void 0 : _a.label) || '';
124
+ return option;
116
125
  }
117
126
  return option.label;
118
127
  }, isOptionEqualToValue: (option, value) => {
@@ -121,7 +130,11 @@ const customSelector = (props) => {
121
130
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
122
131
  onChange: (event, newValue) => {
123
132
  handleOnChange(newValue === null || newValue === void 0 ? void 0 : newValue.value.name);
124
- }, renderInput: (params) => React.createElement(TextField, Object.assign({}, params, { size: "small" })), sx: { width: width, maxWidth: title === 'Operators' ? '200px' : 'none' }, disableClearable: true, readOnly: readOnly }));
133
+ }, onInputChange: (event, value) => {
134
+ if (isFreeSoloEnabled) {
135
+ handleOnChange(value);
136
+ }
137
+ }, renderInput: (params) => React.createElement(TextField, Object.assign({}, params, { size: "small", name: title })), sx: { width: width, maxWidth: title === 'Operators' ? '200px' : 'none' }, disableClearable: true, readOnly: readOnly }));
125
138
  };
126
139
  const customCombinator = (props) => {
127
140
  const { options, value, handleOnChange, context, level } = props;
@@ -169,7 +182,7 @@ export const valueEditor = (props) => {
169
182
  return ValueEditor(props);
170
183
  };
171
184
  const CriteriaBuilder = (props) => {
172
- const { properties, criteria, setCriteria, originalCriteria, enablePresetValues, presetValues, operators, dynamicContentInput, disabled, disabledCriteria, hideBorder, presetGroupLabel, } = props;
185
+ const { properties, criteria, setCriteria, originalCriteria, enablePresetValues, presetValues, operators, dynamicContentInput, disabled, disabledCriteria, hideBorder, presetGroupLabel, freeSolo, } = props;
173
186
  const [query, setQuery] = useState(undefined);
174
187
  useEffect(() => {
175
188
  if (criteria || originalCriteria) {
@@ -261,6 +274,7 @@ const CriteriaBuilder = (props) => {
261
274
  enablePresetValues,
262
275
  presetGroupLabel,
263
276
  disabledCriteria,
277
+ freeSolo,
264
278
  }, controlClassnames: {
265
279
  queryBuilder: 'queryBuilder-branches',
266
280
  ruleGroup: 'container',
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom/extend-expect';
@@ -0,0 +1,53 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import React from 'react';
11
+ import { render, screen } from '@testing-library/react';
12
+ import userEvent from '@testing-library/user-event';
13
+ import '@testing-library/jest-dom/extend-expect';
14
+ import CriteriaBuilder from './CriteriaBuilder';
15
+ const mockProperties = [
16
+ { id: 'name', name: 'name', type: 'string', required: true },
17
+ { id: 'licenseNumber', name: 'license number', type: 'string', required: true },
18
+ { id: 'issueDate', name: 'issue date', type: 'date', required: false },
19
+ ];
20
+ describe('CriteriaBuilder', () => {
21
+ test('allows selection of a property and clears value input when selected', () => __awaiter(void 0, void 0, void 0, function* () {
22
+ const user = userEvent.setup();
23
+ render(React.createElement(CriteriaBuilder, { properties: mockProperties, criteria: {
24
+ $or: [
25
+ {
26
+ name: 'test value',
27
+ },
28
+ ],
29
+ }, setCriteria: jest.fn(), freeSolo: true }));
30
+ const field = yield screen.findByDisplayValue(/name/);
31
+ const value = yield screen.findByDisplayValue(/test value/);
32
+ yield user.click(field);
33
+ const option = yield screen.findByRole('option', { name: /license number/ });
34
+ yield user.click(option);
35
+ expect(field).toHaveValue('license number');
36
+ expect(value).toHaveValue('');
37
+ }));
38
+ test('allows free solo input when freeSolo is true, clears value input when entered', () => __awaiter(void 0, void 0, void 0, function* () {
39
+ const user = userEvent.setup();
40
+ render(React.createElement(CriteriaBuilder, { properties: mockProperties, criteria: {
41
+ $or: [
42
+ {
43
+ name: 'test value',
44
+ },
45
+ ],
46
+ }, setCriteria: jest.fn(), freeSolo: true }));
47
+ const field = yield screen.findByDisplayValue(/name/);
48
+ const value = yield screen.findByDisplayValue(/test value/);
49
+ yield user.type(field, 'person.license.name');
50
+ expect(field).toHaveValue('person.license.name');
51
+ expect(value).toHaveValue('');
52
+ }));
53
+ });
@@ -4,5 +4,6 @@ import { CriteriaInputProps } from '../components/custom/CriteriaBuilder/Criteri
4
4
  declare const _default: ComponentMeta<(props: CriteriaInputProps) => JSX.Element>;
5
5
  export default _default;
6
6
  export declare const CriteriaBuilder: ComponentStory<(props: CriteriaInputProps) => JSX.Element>;
7
+ export declare const FreeSolo: ComponentStory<(props: CriteriaInputProps) => JSX.Element>;
7
8
  export declare const CriteriaBuilderPresetUserID: ComponentStory<(props: CriteriaInputProps) => JSX.Element>;
8
9
  export declare const CriteriaBuilderGroupedPresetValues: ComponentStory<(props: CriteriaInputProps) => JSX.Element>;
@@ -109,6 +109,23 @@ CriteriaBuilder.args = {
109
109
  },
110
110
  enablePresetValues: false,
111
111
  };
112
+ export const FreeSolo = CriteriaBuilderTemplate.bind({});
113
+ FreeSolo.args = Object.assign(Object.assign({}, CriteriaBuilder.args), { criteria: {
114
+ $or: [
115
+ {
116
+ 'person.license.name': 'bert',
117
+ },
118
+ {
119
+ licensedFor: { $in: ['hot dogs', 'amusements', 'entertainment'] },
120
+ },
121
+ {
122
+ licenseNumber: '123456',
123
+ },
124
+ {
125
+ issueDate: '2023-03-16',
126
+ },
127
+ ],
128
+ }, freeSolo: true });
112
129
  export const CriteriaBuilderPresetUserID = CriteriaBuilderTemplate.bind({});
113
130
  CriteriaBuilderPresetUserID.args = {
114
131
  properties: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evoke-platform/ui-components",
3
- "version": "1.0.0-dev.220",
3
+ "version": "1.0.0-dev.221",
4
4
  "description": "",
5
5
  "main": "dist/published/index.js",
6
6
  "module": "dist/published/index.js",
@@ -72,6 +72,7 @@
72
72
  "eslint-plugin-prettier": "^5.1.2",
73
73
  "eslint-plugin-testing-library": "^6.2.0",
74
74
  "husky": "^8.0.3",
75
+ "identity-obj-proxy": "^3.0.0",
75
76
  "is-ci": "^3.0.1",
76
77
  "jest": "^28.1.2",
77
78
  "jest-environment-jsdom": "^28.1.2",
@@ -143,6 +144,9 @@
143
144
  "jest": {
144
145
  "verbose": true,
145
146
  "testEnvironment": "jsdom",
147
+ "moduleNameMapper": {
148
+ "\\.(css|less|scss|sass)$": "identity-obj-proxy"
149
+ },
146
150
  "testPathIgnorePatterns": [
147
151
  "/node_modules/",
148
152
  "<rootDir>/dist/"