@genesislcap/expression-builder 14.248.0

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.
Files changed (114) hide show
  1. package/FUTURE.md +164 -0
  2. package/README.md +3 -0
  3. package/custom-elements-manifest.config.js +14 -0
  4. package/dist/custom-elements.json +1971 -0
  5. package/dist/dts/config/combinators.d.ts +6 -0
  6. package/dist/dts/config/combinators.d.ts.map +1 -0
  7. package/dist/dts/config/index.d.ts +3 -0
  8. package/dist/dts/config/index.d.ts.map +1 -0
  9. package/dist/dts/config/operators.d.ts +4 -0
  10. package/dist/dts/config/operators.d.ts.map +1 -0
  11. package/dist/dts/index.d.ts +6 -0
  12. package/dist/dts/index.d.ts.map +1 -0
  13. package/dist/dts/main/events.d.ts +50 -0
  14. package/dist/dts/main/events.d.ts.map +1 -0
  15. package/dist/dts/main/expression-builder.d.ts +44 -0
  16. package/dist/dts/main/expression-builder.d.ts.map +1 -0
  17. package/dist/dts/main/expression-builder.helpers.d.ts +19 -0
  18. package/dist/dts/main/expression-builder.helpers.d.ts.map +1 -0
  19. package/dist/dts/main/expression-builder.styles.d.ts +3 -0
  20. package/dist/dts/main/expression-builder.styles.d.ts.map +1 -0
  21. package/dist/dts/main/expression-builder.template.d.ts +4 -0
  22. package/dist/dts/main/expression-builder.template.d.ts.map +1 -0
  23. package/dist/dts/main/expression-group/expression-group.d.ts +18 -0
  24. package/dist/dts/main/expression-group/expression-group.d.ts.map +1 -0
  25. package/dist/dts/main/expression-group/expression-group.styles.d.ts +2 -0
  26. package/dist/dts/main/expression-group/expression-group.styles.d.ts.map +1 -0
  27. package/dist/dts/main/expression-group/expression-group.template.d.ts +3 -0
  28. package/dist/dts/main/expression-group/expression-group.template.d.ts.map +1 -0
  29. package/dist/dts/main/expression-rule/expression-rule.d.ts +27 -0
  30. package/dist/dts/main/expression-rule/expression-rule.d.ts.map +1 -0
  31. package/dist/dts/main/expression-rule/expression-rule.helpers.d.ts +4 -0
  32. package/dist/dts/main/expression-rule/expression-rule.helpers.d.ts.map +1 -0
  33. package/dist/dts/main/expression-rule/expression-rule.styles.d.ts +2 -0
  34. package/dist/dts/main/expression-rule/expression-rule.styles.d.ts.map +1 -0
  35. package/dist/dts/main/expression-rule/expression-rule.template.d.ts +3 -0
  36. package/dist/dts/main/expression-rule/expression-rule.template.d.ts.map +1 -0
  37. package/dist/dts/main/index.d.ts +4 -0
  38. package/dist/dts/main/index.d.ts.map +1 -0
  39. package/dist/dts/main/rule-field/rule-field.d.ts +15 -0
  40. package/dist/dts/main/rule-field/rule-field.d.ts.map +1 -0
  41. package/dist/dts/main/rule-field/rule-field.template.d.ts +3 -0
  42. package/dist/dts/main/rule-field/rule-field.template.d.ts.map +1 -0
  43. package/dist/dts/main/rule-operator/rule-operator.d.ts +17 -0
  44. package/dist/dts/main/rule-operator/rule-operator.d.ts.map +1 -0
  45. package/dist/dts/main/rule-operator/rule-operator.template.d.ts +3 -0
  46. package/dist/dts/main/rule-operator/rule-operator.template.d.ts.map +1 -0
  47. package/dist/dts/main/rule-value/rule-value.d.ts +17 -0
  48. package/dist/dts/main/rule-value/rule-value.d.ts.map +1 -0
  49. package/dist/dts/main/rule-value/rule-value.helpers.d.ts +6 -0
  50. package/dist/dts/main/rule-value/rule-value.helpers.d.ts.map +1 -0
  51. package/dist/dts/main/rule-value/rule-value.styles.d.ts +2 -0
  52. package/dist/dts/main/rule-value/rule-value.styles.d.ts.map +1 -0
  53. package/dist/dts/main/rule-value/rule-value.template.d.ts +3 -0
  54. package/dist/dts/main/rule-value/rule-value.template.d.ts.map +1 -0
  55. package/dist/dts/types/index.d.ts +3 -0
  56. package/dist/dts/types/index.d.ts.map +1 -0
  57. package/dist/dts/types/private.types.d.ts +21 -0
  58. package/dist/dts/types/private.types.d.ts.map +1 -0
  59. package/dist/dts/types/public.types.d.ts +160 -0
  60. package/dist/dts/types/public.types.d.ts.map +1 -0
  61. package/dist/dts/utils/data-model.d.ts +27 -0
  62. package/dist/dts/utils/data-model.d.ts.map +1 -0
  63. package/dist/dts/utils/formatting.d.ts +13 -0
  64. package/dist/dts/utils/formatting.d.ts.map +1 -0
  65. package/dist/dts/utils/index.d.ts +4 -0
  66. package/dist/dts/utils/index.d.ts.map +1 -0
  67. package/dist/dts/utils/misc.d.ts +14 -0
  68. package/dist/dts/utils/misc.d.ts.map +1 -0
  69. package/dist/esm/config/combinators.js +31 -0
  70. package/dist/esm/config/index.js +2 -0
  71. package/dist/esm/config/operators.js +91 -0
  72. package/dist/esm/index.js +5 -0
  73. package/dist/esm/main/events.js +13 -0
  74. package/dist/esm/main/expression-builder.helpers.js +129 -0
  75. package/dist/esm/main/expression-builder.js +157 -0
  76. package/dist/esm/main/expression-builder.styles.js +177 -0
  77. package/dist/esm/main/expression-builder.template.js +13 -0
  78. package/dist/esm/main/expression-group/expression-group.js +121 -0
  79. package/dist/esm/main/expression-group/expression-group.styles.js +45 -0
  80. package/dist/esm/main/expression-group/expression-group.template.js +102 -0
  81. package/dist/esm/main/expression-rule/expression-rule.helpers.js +25 -0
  82. package/dist/esm/main/expression-rule/expression-rule.js +203 -0
  83. package/dist/esm/main/expression-rule/expression-rule.styles.js +57 -0
  84. package/dist/esm/main/expression-rule/expression-rule.template.js +65 -0
  85. package/dist/esm/main/index.js +3 -0
  86. package/dist/esm/main/rule-field/rule-field.js +48 -0
  87. package/dist/esm/main/rule-field/rule-field.template.js +46 -0
  88. package/dist/esm/main/rule-operator/rule-operator.js +60 -0
  89. package/dist/esm/main/rule-operator/rule-operator.template.js +46 -0
  90. package/dist/esm/main/rule-value/rule-value.helpers.js +17 -0
  91. package/dist/esm/main/rule-value/rule-value.js +115 -0
  92. package/dist/esm/main/rule-value/rule-value.styles.js +11 -0
  93. package/dist/esm/main/rule-value/rule-value.template.js +106 -0
  94. package/dist/esm/types/index.js +2 -0
  95. package/dist/esm/types/private.types.js +1 -0
  96. package/dist/esm/types/public.types.js +1 -0
  97. package/dist/esm/utils/data-model.js +51 -0
  98. package/dist/esm/utils/formatting.js +23 -0
  99. package/dist/esm/utils/index.js +3 -0
  100. package/dist/esm/utils/misc.js +62 -0
  101. package/dist/expression-builder.api.json +212 -0
  102. package/dist/expression-builder.d.ts +322 -0
  103. package/dist/tsdoc-metadata.json +11 -0
  104. package/docs/.gitattributes +2 -0
  105. package/docs/api/expression-builder.config.md +6 -0
  106. package/docs/api/expression-builder.md +13 -0
  107. package/docs/api/expression-builder.types.md +6 -0
  108. package/docs/api/index.md +12 -0
  109. package/docs/api-report.md +260 -0
  110. package/license.txt +46 -0
  111. package/package.json +66 -0
  112. package/playwright.config.ts +5 -0
  113. package/test/unit/test.ts +1 -0
  114. package/tsdoc.json +4 -0
@@ -0,0 +1,27 @@
1
+ import { Config, Group, ModelGroup, ModelRule, Rule } from '../types';
2
+ /** @internal */
3
+ export interface MetadataProvider {
4
+ getGroupId(): string;
5
+ getRuleId(): string;
6
+ getConfig(): Config;
7
+ }
8
+ /**
9
+ * Converts a Group to a ModelGroup (adds required metadata)
10
+ */
11
+ export declare function groupToModelGroup(group: Group, provider: MetadataProvider): ModelGroup;
12
+ /**
13
+ * Converts a ModelGroup (internal data structure) to a public Group structure.
14
+ * This function recursively processes the rules within the group.
15
+ *
16
+ * @param modelGroup The internal ModelGroup to convert.
17
+ * @returns A public Group object.
18
+ */
19
+ export declare function modelGroupToGroup(modelGroup: ModelGroup): Group;
20
+ /**
21
+ * Converts a ModelRule (internal data structure) to a public Rule structure.
22
+ *
23
+ * @param modelRule The internal ModelRule to convert.
24
+ * @returns A public Rule object.
25
+ */
26
+ export declare function modelRuleToRule(modelRule: ModelRule): Rule;
27
+ //# sourceMappingURL=data-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-model.d.ts","sourceRoot":"","sources":["../../../src/utils/data-model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEtE,gBAAgB;AAChB,MAAM,WAAW,gBAAgB;IAC/B,UAAU,IAAI,MAAM,CAAC;IACrB,SAAS,IAAI,MAAM,CAAC;IACpB,SAAS,IAAI,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,gBAAgB,GAAG,UAAU,CA4BtF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,KAAK,CAe/D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAO1D"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Gets the string representation from a `Date` which is the format a `date` input uses.
3
+ * `yyyy-mm-dd`
4
+ * @alpha
5
+ */
6
+ export declare const formatDateString: (date: Date) => string;
7
+ /**
8
+ * Gets the string representation from a `Date` which is the format a `datetime-local` input uses.
9
+ * `yyyy-mm-ddThh:mm:ss`
10
+ * @alpha
11
+ */
12
+ export declare const formatDateTimeString: (date: Date) => string;
13
+ //# sourceMappingURL=formatting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatting.d.ts","sourceRoot":"","sources":["../../../src/utils/formatting.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,SAAU,IAAI,WAK1C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,SAAU,IAAI,WAM9C,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './data-model';
2
+ export * from './formatting';
3
+ export * from './misc';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { Field, Operator, Styles } from '../types';
2
+ export declare const processOptGroups: <T extends Operator | Field>(xs: T[]) => (T | {
3
+ optgroup: string | null;
4
+ xs: T[];
5
+ })[];
6
+ /**
7
+ * Utility function to add custom styles to a web component's shadow root
8
+ *
9
+ * @param component The web component instance
10
+ * @param styles The styles configuration object
11
+ * @param styleKey The key in styles.customStyles to use for custom styles
12
+ */
13
+ export declare function applyCustomStyles(component: HTMLElement, styles: Styles | undefined | null, styleKey: keyof NonNullable<Styles['customStyles']>): void;
14
+ //# sourceMappingURL=misc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"misc.d.ts","sourceRoot":"","sources":["../../../src/utils/misc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEnD,eAAO,MAAM,gBAAgB;cAET,MAAM,GAAG,IAAI;;IAyChC,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACjC,QAAQ,EAAE,MAAM,WAAW,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,GAClD,IAAI,CAeN"}
@@ -0,0 +1,31 @@
1
+ /** @alpha */
2
+ export const BASE_LOGICAL_COMBINATORS = [
3
+ {
4
+ type: 'AND',
5
+ maxRules: 'many',
6
+ },
7
+ {
8
+ type: 'OR',
9
+ maxRules: 'many',
10
+ },
11
+ ];
12
+ /** @alpha */
13
+ export const LOGICAL_COMBINATORS = [
14
+ ...BASE_LOGICAL_COMBINATORS,
15
+ {
16
+ type: 'NOT',
17
+ maxRules: 2,
18
+ },
19
+ {
20
+ type: 'NAND',
21
+ maxRules: 'many',
22
+ },
23
+ {
24
+ type: 'NOR',
25
+ maxRules: 'many',
26
+ },
27
+ {
28
+ type: 'XOR',
29
+ maxRules: 2,
30
+ },
31
+ ];
@@ -0,0 +1,2 @@
1
+ export * from './combinators';
2
+ export * from './operators';
@@ -0,0 +1,91 @@
1
+ const enumTypes = ['enum'];
2
+ const numericTypes = ['int', 'short', 'long', 'bigdecimal', 'double'];
3
+ const stringTypes = ['string'];
4
+ const dateTypes = ['date', 'date-time'];
5
+ const booleanTypes = ['boolean'];
6
+ const allTypes = [
7
+ ...enumTypes,
8
+ ...numericTypes,
9
+ ...stringTypes,
10
+ ...dateTypes,
11
+ ...booleanTypes,
12
+ ];
13
+ /** @alpha **/
14
+ export const BASE_OPERATORS = [
15
+ {
16
+ type: 'equal',
17
+ nbInputs: 1,
18
+ applyTo: allTypes,
19
+ optgroup: 'Equality',
20
+ },
21
+ {
22
+ type: 'not_equal',
23
+ nbInputs: 1,
24
+ applyTo: allTypes,
25
+ optgroup: 'Equality',
26
+ },
27
+ {
28
+ type: 'greater',
29
+ nbInputs: 1,
30
+ applyTo: [...numericTypes, ...dateTypes],
31
+ optgroup: 'Comparison',
32
+ },
33
+ {
34
+ type: 'less',
35
+ nbInputs: 1,
36
+ applyTo: [...numericTypes, ...dateTypes],
37
+ optgroup: 'Comparison',
38
+ },
39
+ {
40
+ type: 'contains',
41
+ nbInputs: 1,
42
+ applyTo: ['string'],
43
+ optgroup: 'String',
44
+ },
45
+ {
46
+ type: 'starts_with',
47
+ nbInputs: 1,
48
+ applyTo: ['string'],
49
+ optgroup: 'String',
50
+ },
51
+ {
52
+ type: 'ends_with',
53
+ nbInputs: 1,
54
+ applyTo: ['string'],
55
+ optgroup: 'String',
56
+ },
57
+ {
58
+ type: 'one_of',
59
+ nbInputs: 'many',
60
+ applyTo: [...allTypes].filter((t) => t !== 'boolean'),
61
+ },
62
+ {
63
+ type: 'not_any_of',
64
+ nbInputs: 'many',
65
+ applyTo: [...allTypes].filter((t) => t !== 'boolean'),
66
+ },
67
+ {
68
+ type: 'within_inclusive',
69
+ nbInputs: 2,
70
+ applyTo: [...numericTypes, ...dateTypes],
71
+ optgroup: 'Range',
72
+ },
73
+ {
74
+ type: 'within_exclusive',
75
+ nbInputs: 2,
76
+ applyTo: [...numericTypes, ...dateTypes],
77
+ optgroup: 'Range',
78
+ },
79
+ {
80
+ type: 'is_null',
81
+ nbInputs: 0,
82
+ applyTo: [...allTypes],
83
+ optgroup: 'Null',
84
+ },
85
+ {
86
+ type: 'not_null',
87
+ nbInputs: 0,
88
+ applyTo: [...allTypes],
89
+ optgroup: 'Null',
90
+ },
91
+ ];
@@ -0,0 +1,5 @@
1
+ import * as Config from './config';
2
+ import * as Types from './types/public.types';
3
+ export { formatDateString, formatDateTimeString } from './utils';
4
+ export * from './main';
5
+ export { Types, Config };
@@ -0,0 +1,13 @@
1
+ export var Events;
2
+ (function (Events) {
3
+ Events["AddGroup"] = "add-group";
4
+ Events["DelGroup"] = "del-group";
5
+ Events["AddRule"] = "add-rule";
6
+ Events["DelRule"] = "del-rule";
7
+ Events["UpdateGroup"] = "update-group";
8
+ Events["UpdateRule"] = "update-rule";
9
+ Events["FieldSelected"] = "field-selected";
10
+ Events["OperatorSelected"] = "operator-selected";
11
+ Events["ValueUpdated"] = "value-updated";
12
+ Events["RemoveVarArg"] = "remove-variadic-operand";
13
+ })(Events || (Events = {}));
@@ -0,0 +1,129 @@
1
+ import rfdc from 'rfdc';
2
+ const deepClone = rfdc(); // create the fast deep copy function
3
+ /**
4
+ * Finds a group within a model and applies a function to create a new children
5
+ * @param model The root group to start searching from
6
+ * @param groupId The Group ID to find
7
+ * @param fn The function to apply to the children of the found group. A *new* object must be created and returned
8
+ * @returns A *new* root `Group` object which the function has been applied to. If the group isn't found an error is thrown
9
+ */
10
+ export function findOperateOnGroup(model, groupId, fn) {
11
+ function findAndUpdate(node) {
12
+ const newNode = deepClone(node);
13
+ if (newNode.groupId === groupId) {
14
+ newNode.children = fn(newNode.children);
15
+ return newNode;
16
+ }
17
+ const updatedChildren = [];
18
+ let found = false;
19
+ for (const child of newNode.children) {
20
+ if ('children' in child) {
21
+ const updatedGroup = findAndUpdate(child);
22
+ if (updatedGroup) {
23
+ updatedChildren.push(updatedGroup);
24
+ found = true;
25
+ }
26
+ else {
27
+ updatedChildren.push(child);
28
+ }
29
+ }
30
+ else {
31
+ updatedChildren.push(child);
32
+ }
33
+ }
34
+ newNode.children = updatedChildren;
35
+ // Only return the modified node if a group was found and modified within it
36
+ return found ? newNode : null;
37
+ }
38
+ const newModel = findAndUpdate(model);
39
+ if (!newModel)
40
+ throw new Error(`Unable to find group with groupId ${groupId}`);
41
+ return newModel;
42
+ }
43
+ function findNode(model, targetId, predicate) {
44
+ function find(node) {
45
+ for (const child of node.children) {
46
+ if (predicate(child, targetId)) {
47
+ return node; // Found
48
+ }
49
+ if ('children' in child) {
50
+ const found = find(child);
51
+ if (found) {
52
+ return found;
53
+ }
54
+ }
55
+ }
56
+ return null;
57
+ }
58
+ return find(model);
59
+ }
60
+ // Helper function to find the parent
61
+ function findParentGroupOfGroup(model, groupId) {
62
+ const predicate = (node, targetId) => {
63
+ return 'children' in node && node.groupId === targetId;
64
+ };
65
+ const res = findNode(model, groupId, predicate);
66
+ if (!res)
67
+ throw new Error(`No parent group found for group with ID ${groupId}`);
68
+ return res;
69
+ }
70
+ // Helper function to find the parent of a Rule
71
+ function findParentGroupOfRule(model, ruleId) {
72
+ const predicate = (node, targetId) => {
73
+ return 'ruleId' in node && node.ruleId === targetId;
74
+ };
75
+ const res = findNode(model, ruleId, predicate);
76
+ if (!res)
77
+ throw new Error(`No parent group found for rule with ID ${ruleId}`);
78
+ return res;
79
+ }
80
+ export function addGroupOrRule(model, parentGroupId, newItem) {
81
+ const addGroupFn = (children) => {
82
+ return [...children, newItem];
83
+ };
84
+ return findOperateOnGroup(model, parentGroupId, addGroupFn);
85
+ }
86
+ export function deleteGroup(model, groupIdToDelete) {
87
+ const deleteGroupFn = (children) => children.filter((child) => {
88
+ if ('groupId' in child) {
89
+ return child.groupId !== groupIdToDelete;
90
+ }
91
+ return true; // Keep rules
92
+ });
93
+ const parentGroup = findParentGroupOfGroup(model, groupIdToDelete);
94
+ return findOperateOnGroup(model, parentGroup.groupId, deleteGroupFn);
95
+ }
96
+ export function deleteRule(model, ruleIdToDelete) {
97
+ const deleteRuleFn = (children) => children.filter((child) => {
98
+ if ('ruleId' in child) {
99
+ return child.ruleId !== ruleIdToDelete;
100
+ }
101
+ return true; // Keep Groups
102
+ });
103
+ const parentGroup = findParentGroupOfRule(model, ruleIdToDelete);
104
+ return findOperateOnGroup(model, parentGroup.groupId, deleteRuleFn);
105
+ }
106
+ export const ROOT_GROUP = 'group-root';
107
+ export function updateGroupData(model, groupIdToUpdate, newData) {
108
+ if (groupIdToUpdate === ROOT_GROUP) {
109
+ return Object.assign(Object.assign({}, model), newData);
110
+ }
111
+ const updateGroupFn = (children) => children.map((child) => {
112
+ if ('groupId' in child && child.groupId === groupIdToUpdate) {
113
+ return Object.assign(Object.assign({}, child), newData);
114
+ }
115
+ return child;
116
+ });
117
+ const parentGroup = findParentGroupOfGroup(model, groupIdToUpdate);
118
+ return findOperateOnGroup(model, parentGroup.groupId, updateGroupFn);
119
+ }
120
+ export function updateRuleData(model, ruleIdToUpdate, newData) {
121
+ const updateRuleFn = (children) => children.map((child) => {
122
+ if ('ruleId' in child && child.ruleId === ruleIdToUpdate) {
123
+ return Object.assign(Object.assign({}, child), newData);
124
+ }
125
+ return child;
126
+ });
127
+ const parentGroup = findParentGroupOfRule(model, ruleIdToUpdate);
128
+ return findOperateOnGroup(model, parentGroup.groupId, updateRuleFn);
129
+ }
@@ -0,0 +1,157 @@
1
+ import { __decorate } from "tslib";
2
+ import { customElement, GenesisElement, observable } from '@genesislcap/web-core';
3
+ import { groupToModelGroup, modelGroupToGroup } from '../utils/data-model';
4
+ import { Events } from './events';
5
+ import { addGroupOrRule, deleteGroup, deleteRule, ROOT_GROUP, updateGroupData, updateRuleData, } from './expression-builder.helpers';
6
+ import { styles } from './expression-builder.styles';
7
+ import { template } from './expression-builder.template';
8
+ import { ExpressionGroup } from './expression-group/expression-group';
9
+ import { ExpressionRule } from './expression-rule/expression-rule';
10
+ ExpressionGroup;
11
+ ExpressionRule;
12
+ /** @alpha **/
13
+ let ExpressionBuilder = class ExpressionBuilder extends GenesisElement {
14
+ constructor() {
15
+ super(...arguments);
16
+ this.model = null;
17
+ this.ruleCount = 0;
18
+ this.groupCount = 0;
19
+ this.handleAddGroup = this._handleAddGroup.bind(this);
20
+ this.handleAddRule = this._handleAddRule.bind(this);
21
+ this.handleDeleteGroup = this._handleDeleteGroup.bind(this);
22
+ this.handleDeleteRule = this._handleDeleteRule.bind(this);
23
+ this.handleUpdateGroupData = this._handleUpdateGroupData.bind(this);
24
+ this.handleUpdateRuleData = this._handleUpdateRuleData.bind(this);
25
+ }
26
+ /** @internal */
27
+ configChanged(_, newConfig) {
28
+ if (newConfig.model) {
29
+ this.ruleCount = 0;
30
+ this.groupCount = 0;
31
+ this.model = groupToModelGroup(newConfig.model, this);
32
+ }
33
+ }
34
+ /** @internal */
35
+ modelChanged(_, newModel) {
36
+ if (!newModel)
37
+ return;
38
+ const group = modelGroupToGroup(newModel);
39
+ this.dispatchChangeEvent(group);
40
+ }
41
+ /**
42
+ * @alpha
43
+ * Dispatches the provided model to the DOM.
44
+ *
45
+ * @remarks
46
+ * Override this to change the shape of model the component returns
47
+ */
48
+ dispatchChangeEvent(group) {
49
+ this.dispatchEvent(new CustomEvent('change', {
50
+ detail: group,
51
+ bubbles: true,
52
+ cancelable: true,
53
+ composed: true,
54
+ }));
55
+ }
56
+ // Implement MetadataProvider interface
57
+ /** @internal */
58
+ getConfig() {
59
+ return this.config;
60
+ }
61
+ /** @internal */
62
+ getGroupId() {
63
+ this.groupCount += 1;
64
+ return `group-${this.groupCount}`;
65
+ }
66
+ /** @internal */
67
+ getRuleId() {
68
+ this.ruleCount += 1;
69
+ return `rule-${this.ruleCount}`;
70
+ }
71
+ // Behaviour
72
+ connectedCallback() {
73
+ super.connectedCallback();
74
+ if (!this.config || !this.config.combinators || !this.config.operators || !this.config.fields) {
75
+ throw new Error("Invalid config passed to ExpressionBuilder. Verify you've defined operators, fields, and combinators.");
76
+ }
77
+ this.addEventListener(Events.AddGroup, this.handleAddGroup);
78
+ this.addEventListener(Events.DelGroup, this.handleDeleteGroup);
79
+ this.addEventListener(Events.AddRule, this.handleAddRule);
80
+ this.addEventListener(Events.DelRule, this.handleDeleteRule);
81
+ this.addEventListener(Events.UpdateGroup, this.handleUpdateGroupData);
82
+ this.addEventListener(Events.UpdateRule, this.handleUpdateRuleData);
83
+ if (this.config.model)
84
+ return;
85
+ this.model = {
86
+ children: [],
87
+ level: 1,
88
+ groupId: ROOT_GROUP,
89
+ config: this.config,
90
+ combinator: this.config.combinators[0],
91
+ };
92
+ }
93
+ disconnectedCallback() {
94
+ super.disconnectedCallback();
95
+ this.removeEventListener(Events.AddGroup, this.handleAddGroup);
96
+ this.removeEventListener(Events.DelGroup, this.handleDeleteGroup);
97
+ this.removeEventListener(Events.AddRule, this.handleAddRule);
98
+ this.removeEventListener(Events.DelRule, this.handleDeleteRule);
99
+ this.removeEventListener(Events.UpdateGroup, this.handleUpdateGroupData);
100
+ this.removeEventListener(Events.UpdateRule, this.handleUpdateRuleData);
101
+ }
102
+ _handleAddGroup(event) {
103
+ const { parentGroupId, newGroup: _newGroup } = event.detail;
104
+ const newGroup = {
105
+ groupId: this.getGroupId(),
106
+ level: _newGroup.level,
107
+ children: [],
108
+ config: this.config,
109
+ combinator: this.config.combinators[0],
110
+ };
111
+ this.model = addGroupOrRule(this.model, parentGroupId, newGroup);
112
+ }
113
+ _handleAddRule(event) {
114
+ const { parentGroupId } = event.detail;
115
+ const newRule = {
116
+ ruleId: this.getRuleId(),
117
+ config: this.config,
118
+ field: null,
119
+ operator: null,
120
+ value: null,
121
+ };
122
+ this.model = addGroupOrRule(this.model, parentGroupId, newRule);
123
+ }
124
+ _handleDeleteGroup(event) {
125
+ const { groupId } = event.detail;
126
+ this.model = deleteGroup(this.model, groupId);
127
+ }
128
+ _handleDeleteRule(event) {
129
+ const { ruleId } = event.detail;
130
+ this.model = deleteRule(this.model, ruleId);
131
+ }
132
+ _handleUpdateGroupData(event) {
133
+ const { groupId, newData } = event.detail;
134
+ this.model = updateGroupData(this.model, groupId, newData);
135
+ }
136
+ _handleUpdateRuleData(event) {
137
+ const { ruleId, newData } = event.detail;
138
+ this.model = updateRuleData(this.model, ruleId, newData);
139
+ }
140
+ };
141
+ __decorate([
142
+ observable
143
+ ], ExpressionBuilder.prototype, "config", void 0);
144
+ __decorate([
145
+ observable
146
+ ], ExpressionBuilder.prototype, "styles", void 0);
147
+ __decorate([
148
+ observable
149
+ ], ExpressionBuilder.prototype, "model", void 0);
150
+ ExpressionBuilder = __decorate([
151
+ customElement({
152
+ name: 'expression-builder',
153
+ template,
154
+ styles,
155
+ })
156
+ ], ExpressionBuilder);
157
+ export { ExpressionBuilder };
@@ -0,0 +1,177 @@
1
+ import { css } from '@genesislcap/web-core';
2
+ /** @alpha **/
3
+ export const styles = css `
4
+ :host {
5
+ --item-vertical-spacing: 4px;
6
+ --item-border-radius: 5px;
7
+ --group-background-color: rgb(250 240 210 / 50%);
8
+ --group-border-color: #dcc896;
9
+ --group-border: 1px solid var(--group-border-color);
10
+ --group-padding: 10px;
11
+ --rule-background-color: rgb(255 255 255 / 90%);
12
+ --rule-border-color: #eee;
13
+ --rule-border: 1px solid var(--rule-border-color);
14
+ --rule-padding: 5px;
15
+ --rule-value-separator: 1px solid #ddd;
16
+ --error-icon-color: #f00;
17
+ --error-border-color: #f99;
18
+ --error-background-color: #fdd;
19
+ --ticks-width: 2px;
20
+ --ticks-color: #ccc;
21
+ }
22
+
23
+ p.test {
24
+ color: black;
25
+ }
26
+
27
+ .query-builder {
28
+ font-family: sans-serif;
29
+ }
30
+
31
+ .rules-group-container {
32
+ position: relative;
33
+ margin: var(--item-vertical-spacing) 0;
34
+ border-radius: var(--item-border-radius);
35
+ padding: var(--group-padding);
36
+ border: var(--group-border);
37
+ background: var(--group-background-color);
38
+ }
39
+
40
+ .rules-group-header {
41
+ margin-bottom: var(--group-padding);
42
+ }
43
+
44
+ .group-conditions {
45
+ display: inline-block;
46
+ }
47
+
48
+ .group-conditions .btn {
49
+ padding: 0.25rem 0.5rem;
50
+ font-size: 0.875rem;
51
+ line-height: 1.5;
52
+ border-radius: 0.2rem;
53
+ border: 1px solid #007bff;
54
+ color: #007bff;
55
+ background-color: transparent;
56
+ cursor: pointer;
57
+ }
58
+
59
+ .group-conditions .btn:hover {
60
+ background-color: #007bff;
61
+ color: #fff;
62
+ }
63
+
64
+ .group-conditions .btn.active {
65
+ background-color: #007bff;
66
+ color: #fff;
67
+ }
68
+
69
+ .group-actions {
70
+ display: inline-block;
71
+ float: right;
72
+ }
73
+
74
+ .rules-list {
75
+ list-style: none;
76
+ padding: 0 0 0 20px; /* Adjusted ticks position */
77
+ margin: 0;
78
+ }
79
+
80
+ .rule-container {
81
+ position: relative;
82
+ margin: var(--item-vertical-spacing) 0;
83
+ border-radius: var(--item-border-radius);
84
+ padding: var(--rule-padding);
85
+ border: var(--rule-border);
86
+ background: var(--rule-background-color);
87
+ }
88
+
89
+ .rule-header {
90
+ margin-bottom: 5px;
91
+ }
92
+
93
+ .rule-actions {
94
+ display: inline-block;
95
+ float: right;
96
+ }
97
+
98
+ .rule-field-container,
99
+ .rule-operator-container,
100
+ .rule-value-container {
101
+ display: inline-block;
102
+ margin: 0 5px 0 0;
103
+ vertical-align: middle;
104
+ }
105
+
106
+ .rule-value-container {
107
+ border-left: var(--rule-value-separator);
108
+ padding-left: 5px;
109
+ }
110
+
111
+ .rule-value-container label {
112
+ margin-bottom: 0;
113
+ font-weight: normal;
114
+ }
115
+
116
+ .rule-value-container label.block {
117
+ display: block;
118
+ }
119
+
120
+ .error-container {
121
+ display: none;
122
+ cursor: help;
123
+ color: var(--error-icon-color);
124
+ margin-left: 5px;
125
+ }
126
+
127
+ .rule-container.has-error,
128
+ .rules-group-container.has-error {
129
+ background-color: var(--error-background-color);
130
+ border-color: var(--error-border-color);
131
+ }
132
+
133
+ .rule-container.has-error .error-container,
134
+ .rules-group-container.has-error .error-container {
135
+ display: inline-block !important;
136
+ }
137
+
138
+ /* Ticks */
139
+ .rules-list > * {
140
+ position: relative;
141
+ }
142
+
143
+ .rules-list > *::before,
144
+ .rules-list > *::after {
145
+ content: '';
146
+ position: absolute;
147
+ left: -10px; /* Adjusted ticks position */
148
+ width: 10px; /* Adjusted ticks position */
149
+ border-color: var(--ticks-color);
150
+ border-style: solid;
151
+ }
152
+
153
+ .rules-list > *::before {
154
+ top: -2px; /* Adjusted ticks position */
155
+ height: calc(50% + var(--item-vertical-spacing));
156
+ border-width: 0 0 var(--ticks-width) var(--ticks-width);
157
+ }
158
+
159
+ .rules-list > *::after {
160
+ top: 50%;
161
+ border-width: 0 0 0 var(--ticks-width);
162
+ height: 50%;
163
+ }
164
+
165
+ .rules-list > *:first-child::before {
166
+ top: calc(-1 * var(--group-padding) - var(--ticks-width));
167
+ height: calc(50% + var(--group-padding) + var(--item-vertical-spacing));
168
+ }
169
+
170
+ .rules-list > *:last-child::before {
171
+ border-radius: 0 0 0 calc(2 * var(--ticks-width));
172
+ }
173
+
174
+ .rules-list > *:last-child::after {
175
+ display: none;
176
+ }
177
+ `;