@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,13 @@
1
+ import { html } from '@genesislcap/web-core';
2
+ import { ExpressionGroup } from './expression-group/expression-group';
3
+ ExpressionGroup;
4
+ /** @alpha **/
5
+ export const template = html `
6
+ <div class="query-builder">
7
+ <expression-group
8
+ :model=${(x) => x.model}
9
+ :config=${(x) => x.config}
10
+ :styles=${(x) => x.styles}
11
+ ></expression-group>
12
+ </div>
13
+ `;
@@ -0,0 +1,121 @@
1
+ import { __decorate } from "tslib";
2
+ import { customElement, GenesisElement, observable, volatile } from '@genesislcap/web-core';
3
+ import { applyCustomStyles } from '../../utils/misc';
4
+ import { Events } from '../events';
5
+ import { styles } from './expression-group.styles';
6
+ import { template } from './expression-group.template';
7
+ let ExpressionGroup = class ExpressionGroup extends GenesisElement {
8
+ connectedCallback() {
9
+ super.connectedCallback();
10
+ applyCustomStyles(this, this.styles, 'group');
11
+ }
12
+ get allowNestedGroup() {
13
+ var _a, _b;
14
+ if (!this.model)
15
+ return false;
16
+ if (!((_a = this.config) === null || _a === void 0 ? void 0 : _a.maxNesting) || ((_b = this.config) === null || _b === void 0 ? void 0 : _b.maxNesting) < 1)
17
+ return true;
18
+ return this.config.maxNesting > this.model.level;
19
+ }
20
+ // configChanged(_, newConfig: Config) {
21
+ // if (!this.combinator) {
22
+ // this.combinator = newConfig.combinators[0];
23
+ // }
24
+ // }
25
+ //
26
+ // modelChanged(_, newModel: ModelGroup) {
27
+ // if (!newModel) return;
28
+ // this.combinator = newModel.combinator;
29
+ // }
30
+ dispatchAddRule(event) {
31
+ event.stopPropagation();
32
+ const detail = {
33
+ parentGroupId: this.model.groupId,
34
+ };
35
+ this.dispatchEvent(new CustomEvent(Events.AddRule, { detail, bubbles: true, composed: true }));
36
+ }
37
+ dispatchAddGroup(event) {
38
+ event.stopPropagation();
39
+ if (!this.allowNestedGroup)
40
+ throw new Error('Cannot add further nested groups');
41
+ const detail = {
42
+ parentGroupId: this.model.groupId,
43
+ newGroup: {
44
+ level: this.model.level + 1,
45
+ },
46
+ };
47
+ this.dispatchEvent(new CustomEvent(Events.AddGroup, { detail, bubbles: true, composed: true }));
48
+ }
49
+ dispatchDeleteGroup(event) {
50
+ event.stopPropagation();
51
+ const detail = {
52
+ groupId: this.model.groupId,
53
+ };
54
+ this.dispatchEvent(new CustomEvent(Events.DelGroup, { detail, bubbles: true, composed: true }));
55
+ }
56
+ handleCombinatorChange(event) {
57
+ event.stopPropagation();
58
+ const target = event.target;
59
+ const value = target.value;
60
+ this.updateCombinator(value);
61
+ }
62
+ handleCustomCombinatorChange(event) {
63
+ var _a;
64
+ event.stopPropagation();
65
+ if (!((_a = this.model) === null || _a === void 0 ? void 0 : _a.groupId) || !event.target)
66
+ return; // can happen when the radio is first initialised
67
+ const target = event.target;
68
+ const value = target.getAttribute('value');
69
+ if (!value) {
70
+ throw new Error('No value found in the custom radio group event target');
71
+ }
72
+ this.updateCombinator(value);
73
+ }
74
+ updateCombinator(value) {
75
+ var _a, _b;
76
+ const combinator = this.config.combinators.find(({ type }) => type === value);
77
+ if (!combinator) {
78
+ throw new Error(`Cannot find selected combinator ${value}`);
79
+ }
80
+ // Can happen when web component is initialised
81
+ if (((_b = (_a = this.model) === null || _a === void 0 ? void 0 : _a.combinator) === null || _b === void 0 ? void 0 : _b.type) === combinator.type) {
82
+ return;
83
+ }
84
+ this.dispatchGroupDataUpdated(combinator);
85
+ }
86
+ dispatchGroupDataUpdated(combinator) {
87
+ const detail = {
88
+ groupId: this.model.groupId,
89
+ newData: {
90
+ combinator,
91
+ },
92
+ };
93
+ this.dispatchEvent(new CustomEvent(Events.UpdateGroup, { detail, bubbles: true, composed: true }));
94
+ }
95
+ };
96
+ __decorate([
97
+ observable
98
+ ], ExpressionGroup.prototype, "config", void 0);
99
+ __decorate([
100
+ observable
101
+ ], ExpressionGroup.prototype, "styles", void 0);
102
+ __decorate([
103
+ observable
104
+ ], ExpressionGroup.prototype, "model", void 0);
105
+ __decorate([
106
+ observable
107
+ ], ExpressionGroup.prototype, "index", void 0);
108
+ __decorate([
109
+ volatile
110
+ ], ExpressionGroup.prototype, "allowNestedGroup", null);
111
+ ExpressionGroup = __decorate([
112
+ customElement({
113
+ name: 'expression-group',
114
+ template,
115
+ styles: styles,
116
+ shadowOptions: {
117
+ delegatesFocus: true, // Ensure the element can be focused
118
+ },
119
+ })
120
+ ], ExpressionGroup);
121
+ export { ExpressionGroup };
@@ -0,0 +1,45 @@
1
+ import { css } from '@genesislcap/web-core';
2
+ export const styles = css `
3
+ .rules-group-container {
4
+ border: 1px solid #ccc;
5
+ margin-bottom: 10px;
6
+ padding: 10px;
7
+ }
8
+
9
+ .rules-group-header {
10
+ margin-bottom: 5px;
11
+ }
12
+
13
+ .btn-group {
14
+ margin-right: 5px;
15
+ }
16
+
17
+ .btn {
18
+ padding: 0.25rem 0.5rem;
19
+ font-size: 0.875rem;
20
+ line-height: 1.5;
21
+ border-radius: 0.2rem;
22
+ cursor: pointer;
23
+ }
24
+
25
+ .btn-success {
26
+ color: #fff;
27
+ background-color: #28a745;
28
+ border-color: #28a745;
29
+ }
30
+
31
+ .btn-danger {
32
+ color: #fff;
33
+ background-color: #dc3545;
34
+ border-color: #dc3545;
35
+ }
36
+
37
+ .radio-group-container {
38
+ display: flex;
39
+ }
40
+
41
+ .rules-list {
42
+ list-style: none;
43
+ padding-left: 0;
44
+ }
45
+ `;
@@ -0,0 +1,102 @@
1
+ import { html, repeat, when, whenElse } from '@genesislcap/web-core';
2
+ export const template = html `
3
+ ${(context) => {
4
+ var _a, _b, _c, _d;
5
+ const buttonTag = ((_b = (_a = context.styles) === null || _a === void 0 ? void 0 : _a.customElements) === null || _b === void 0 ? void 0 : _b.button) || 'button';
6
+ const maybeRadioBlock = (_d = (_c = context.styles) === null || _c === void 0 ? void 0 : _c.customElements) === null || _d === void 0 ? void 0 : _d.radio;
7
+ const { radioTag, radioGroupTag } = maybeRadioBlock
8
+ ? { radioTag: maybeRadioBlock.input, radioGroupTag: maybeRadioBlock.group }
9
+ : { radioTag: 'input', radioGroupTag: 'div' };
10
+ return html `
11
+ <div class="rules-group-container">
12
+ <div class="rules-group-header">
13
+ <div class="btn-group float-end group-actions">
14
+ <${buttonTag}
15
+ type="button"
16
+ class="btn btn-sm btn-success"
17
+ data-add="rule"
18
+ @click="${(x, c) => x.dispatchAddRule(c.event)}"
19
+ >
20
+ Add Rule
21
+ </${buttonTag}>
22
+ ${when((x) => x.allowNestedGroup, html `
23
+ <${buttonTag}
24
+ type="button"
25
+ class="btn btn-sm btn-success"
26
+ data-add="group"
27
+ @click="${(x, c) => x.dispatchAddGroup(c.event)}"
28
+ >
29
+ Add Group
30
+ </${buttonTag}>
31
+ `)}
32
+ ${when((x) => typeof x.index === 'number', html `
33
+ <${buttonTag}
34
+ type="button"
35
+ class="btn btn-sm btn-danger"
36
+ data-delete="group"
37
+ @click="${(x, c) => x.dispatchDeleteGroup(c.event)}"
38
+ >
39
+ Delete Group
40
+ </${buttonTag}>
41
+ `)}
42
+ <div class="btn-group group-conditions">
43
+ ${whenElse((_) => radioTag !== 'input', html `
44
+ <${radioGroupTag}
45
+ class="radio-group-container"
46
+ name="combinator"
47
+ @change="${(x, c) => x.handleCombinatorChange(c.event)}"
48
+ value="${(x) => { var _a, _b; return (_b = (_a = x.model) === null || _a === void 0 ? void 0 : _a.combinator) === null || _b === void 0 ? void 0 : _b.type; }}"
49
+ >
50
+ ${repeat((x) => x.config.combinators, html `
51
+ <${radioTag}
52
+ value="${(x) => x.type}"
53
+ ?checked=${(x, c) => { var _a, _b; return ((_b = (_a = c.parent.model) === null || _a === void 0 ? void 0 : _a.combinator) === null || _b === void 0 ? void 0 : _b.type) === x.type; }}
54
+ >
55
+ ${(x) => { var _a; return (_a = x.label) !== null && _a !== void 0 ? _a : x.type; }}
56
+ </${radioTag}>
57
+ `)}
58
+ </${radioGroupTag}>
59
+ `, html `
60
+ <div class="radio-group-container">
61
+ ${repeat((x) => x.config.combinators, html `
62
+ <label class="btn btn-sm btn-primary">
63
+ <input
64
+ type="radio"
65
+ name="combinator"
66
+ value="${(x) => x.type}"
67
+ @change="${(_, c) => c.parent.handleCombinatorChange(c.event)}"
68
+ ?checked=${(x, c) => { var _a, _b; return ((_b = (_a = c.parent.model) === null || _a === void 0 ? void 0 : _a.combinator) === null || _b === void 0 ? void 0 : _b.type) === x.type; }}
69
+ />
70
+ ${(x) => { var _a; return (_a = x.label) !== null && _a !== void 0 ? _a : x.type; }}
71
+ </label>
72
+ `)}
73
+ </div>
74
+ `)}
75
+ </div>
76
+ </div>
77
+ <div class="rules-group-body">
78
+ <div class="rules-list">
79
+ ${repeat((x) => { var _a, _b; return (_b = (_a = x.model) === null || _a === void 0 ? void 0 : _a.children) !== null && _b !== void 0 ? _b : []; }, html `
80
+ ${whenElse((x) => 'children' in x, html `
81
+ <expression-group
82
+ :config=${(_, c) => c.parent.config}
83
+ :styles=${(_, c) => c.parent.styles}
84
+ :model=${(x) => x}
85
+ :index=${(_, c) => c.index}
86
+ ></expression-group>
87
+ `, html `
88
+ <expression-rule
89
+ :config=${(_, c) => c.parent.config}
90
+ :styles=${(_, c) => c.parent.styles}
91
+ :model=${(x) => x}
92
+ :index=${(_, c) => c.index}
93
+ ></expression-rule>
94
+ `)}
95
+ `, { recycle: false, positioning: true })}
96
+ </div>
97
+ </div>
98
+ </div>
99
+ </div>
100
+ `;
101
+ }}
102
+ `;
@@ -0,0 +1,25 @@
1
+ import { formatDateString, formatDateTimeString } from '../../utils';
2
+ export const defaultVal = (f) => f.defaultValue !== undefined ? f.defaultValue : fieldDefault(f);
3
+ export const fieldDefault = (f) => {
4
+ switch (f.type) {
5
+ case 'string':
6
+ return '';
7
+ case 'boolean':
8
+ return false;
9
+ case 'date':
10
+ return formatDateString(new Date());
11
+ case 'date-time':
12
+ return formatDateTimeString(new Date());
13
+ case 'double':
14
+ case 'int':
15
+ case 'bigdecimal':
16
+ case 'short':
17
+ case 'long':
18
+ return 0;
19
+ case 'enum': {
20
+ if (Object.keys(f.values).length === 0)
21
+ throw new Error('Enums require configured values');
22
+ return Object.keys(f.values)[0];
23
+ }
24
+ }
25
+ };
@@ -0,0 +1,203 @@
1
+ import { __decorate } from "tslib";
2
+ import { customElement, GenesisElement, observable, volatile } from '@genesislcap/web-core';
3
+ import { applyCustomStyles } from '../../utils/misc';
4
+ import { Events } from '../events';
5
+ import { RuleField } from '../rule-field/rule-field';
6
+ import { RuleOperator } from '../rule-operator/rule-operator';
7
+ import { RuleValue } from '../rule-value/rule-value';
8
+ import { defaultVal } from './expression-rule.helpers';
9
+ import { styles } from './expression-rule.styles';
10
+ import { template } from './expression-rule.template';
11
+ RuleOperator;
12
+ RuleField;
13
+ RuleValue;
14
+ let ExpressionRule = class ExpressionRule extends GenesisElement {
15
+ connectedCallback() {
16
+ super.connectedCallback();
17
+ applyCustomStyles(this, this.styles, 'rule');
18
+ }
19
+ variadicRule(model) {
20
+ return model.operator.nbInputs === 'many' && 'value' in model && Array.isArray(model.value);
21
+ }
22
+ /**
23
+ * @internal
24
+ * Creates an array of length n to represent to number of argument to the operator
25
+ */
26
+ get operandIterator() {
27
+ var _a, _b, _c;
28
+ if (((_a = this.model.operator) === null || _a === void 0 ? void 0 : _a.nbInputs) === 'many') {
29
+ if (!this.variadicRule(this.model))
30
+ throw new Error('Varargs disabled for many nbInputs');
31
+ return Array(this.model.value.length).fill(true);
32
+ }
33
+ return Array((_c = (_b = this.model.operator) === null || _b === void 0 ? void 0 : _b.nbInputs) !== null && _c !== void 0 ? _c : 0).fill(true);
34
+ }
35
+ operandValue(index) {
36
+ if (!this.model.operator)
37
+ return undefined;
38
+ if (this.model.operator.nbInputs === 1 && 'value' in this.model) {
39
+ return this.model.value;
40
+ }
41
+ else if ((this.model.operator.nbInputs === 2 || this.model.operator.nbInputs === 'many') &&
42
+ 'value' in this.model &&
43
+ Array.isArray(this.model.value)) {
44
+ return this.model.value[index];
45
+ }
46
+ throw new Error('Invalid operand lookup');
47
+ }
48
+ dispatchAddVarArg() {
49
+ if (!this.variadicRule(this.model))
50
+ throw new Error('Cannot add inputs for non-variadic operator, or invalid format');
51
+ const detail = {
52
+ ruleId: this.model.ruleId,
53
+ newData: {
54
+ operator: this.model.operator,
55
+ field: this.model.field,
56
+ value: [...this.model.value, defaultVal(this.model.field)],
57
+ },
58
+ };
59
+ this.dispatchEvent(new CustomEvent(Events.UpdateRule, { detail, bubbles: true, composed: true }));
60
+ }
61
+ handleRemoveVarArg(event) {
62
+ const { index } = event.detail;
63
+ if (!this.variadicRule(this.model))
64
+ throw new Error('Cannot remove inputs for non-variadic operator, or invalid format');
65
+ const detail = {
66
+ ruleId: this.model.ruleId,
67
+ newData: {
68
+ operator: this.model.operator,
69
+ field: this.model.field,
70
+ value: this.model.value.filter((_, i) => i !== index),
71
+ },
72
+ };
73
+ this.dispatchEvent(new CustomEvent(Events.UpdateRule, { detail, bubbles: true, composed: true }));
74
+ }
75
+ dispatchDeleteRule(event) {
76
+ event.stopPropagation();
77
+ const detail = {
78
+ ruleId: this.model.ruleId,
79
+ };
80
+ this.dispatchEvent(new CustomEvent(Events.DelRule, { detail, bubbles: true, composed: true }));
81
+ }
82
+ handleFieldSelected(event) {
83
+ var _a;
84
+ event.stopPropagation();
85
+ const { fieldId } = event.detail;
86
+ const newFiler = (_a = this.config.fields.find((filter) => filter.fieldId === fieldId)) !== null && _a !== void 0 ? _a : null;
87
+ if (!newFiler) {
88
+ throw new Error(`Unable to find field with id ${fieldId}`);
89
+ }
90
+ const detail = {
91
+ ruleId: this.model.ruleId,
92
+ newData: {
93
+ field: newFiler,
94
+ value: null,
95
+ operator: null,
96
+ },
97
+ };
98
+ this.dispatchEvent(new CustomEvent(Events.UpdateRule, { detail, bubbles: true, composed: true }));
99
+ }
100
+ handleValueChanged(event) {
101
+ event.stopPropagation();
102
+ const { value, index } = event.detail;
103
+ const buildUpdatedModel = (operator) => {
104
+ switch (operator.nbInputs) {
105
+ case 0:
106
+ throw new Error('Cannot set the value for a UniraryOperator');
107
+ case 1:
108
+ return {
109
+ field: this.model.field,
110
+ operator: operator,
111
+ value,
112
+ };
113
+ case 2:
114
+ case 'many': {
115
+ if (!('value' in this.model) || !Array.isArray(this.model.value))
116
+ throw new Error('Invalid value shape for rule');
117
+ return {
118
+ field: this.model.field,
119
+ operator: operator,
120
+ value: this.model.value.map((v, i) => (i === index ? value : v)),
121
+ };
122
+ }
123
+ }
124
+ };
125
+ const detail = {
126
+ ruleId: this.model.ruleId,
127
+ newData: buildUpdatedModel(this.model.operator),
128
+ };
129
+ this.dispatchEvent(new CustomEvent(Events.UpdateRule, { detail, bubbles: true, composed: true }));
130
+ }
131
+ handleOperatorSelected(event) {
132
+ var _a;
133
+ event.stopPropagation();
134
+ const { operatorId: operatorType } = event.detail;
135
+ if (!operatorType)
136
+ return; // occurs when selecting "Select an operator"
137
+ const newOperator = (_a = this.config.operators.find((operator) => operator.type === operatorType)) !== null && _a !== void 0 ? _a : null;
138
+ if (!newOperator) {
139
+ throw new Error(`Unable to find operator of type ${operatorType}`);
140
+ }
141
+ const buildUpdatedModel = (operator) => {
142
+ switch (operator.nbInputs) {
143
+ case 0:
144
+ return {
145
+ field: this.model.field,
146
+ operator: operator,
147
+ };
148
+ case 1:
149
+ return {
150
+ field: this.model.field,
151
+ operator: operator,
152
+ value: defaultVal(this.model.field),
153
+ };
154
+ case 2:
155
+ return {
156
+ field: this.model.field,
157
+ operator: operator,
158
+ value: [defaultVal(this.model.field), defaultVal(this.model.field)],
159
+ };
160
+ case 'many':
161
+ return {
162
+ field: this.model.field,
163
+ operator: operator,
164
+ value: [defaultVal(this.model.field)],
165
+ };
166
+ }
167
+ };
168
+ this.dispatchEvent(new CustomEvent(Events.UpdateRule, {
169
+ detail: {
170
+ ruleId: this.model.ruleId,
171
+ newData: buildUpdatedModel(newOperator),
172
+ },
173
+ bubbles: true,
174
+ composed: true,
175
+ }));
176
+ }
177
+ };
178
+ __decorate([
179
+ observable
180
+ ], ExpressionRule.prototype, "config", void 0);
181
+ __decorate([
182
+ observable
183
+ ], ExpressionRule.prototype, "styles", void 0);
184
+ __decorate([
185
+ observable
186
+ ], ExpressionRule.prototype, "model", void 0);
187
+ __decorate([
188
+ observable
189
+ ], ExpressionRule.prototype, "index", void 0);
190
+ __decorate([
191
+ volatile
192
+ ], ExpressionRule.prototype, "operandIterator", null);
193
+ ExpressionRule = __decorate([
194
+ customElement({
195
+ name: 'expression-rule',
196
+ template,
197
+ styles: styles,
198
+ shadowOptions: {
199
+ delegatesFocus: true, // Ensure the element can be focused
200
+ },
201
+ })
202
+ ], ExpressionRule);
203
+ export { ExpressionRule };
@@ -0,0 +1,57 @@
1
+ import { css } from '@genesislcap/web-core';
2
+ export const styles = css `
3
+ .rule-container {
4
+ border: 1px solid #eee;
5
+ margin-bottom: 5px;
6
+ padding: 5px;
7
+ display: grid;
8
+ grid-template-columns: auto 1fr;
9
+ }
10
+
11
+ .margin {
12
+ margin-left: calc(var(--design-unit) * 1px);
13
+ margin-right: calc(var(--design-unit) * 1px);
14
+ }
15
+
16
+ .rule-header {
17
+ margin-bottom: 5px;
18
+ display: flex;
19
+ justify-content: flex-end;
20
+ }
21
+
22
+ .rule-actions {
23
+ display: inline-block;
24
+ }
25
+
26
+ .rule-content {
27
+ display: flex;
28
+ flex-wrap: wrap;
29
+ align-items: center;
30
+ }
31
+
32
+ .rule-field-container,
33
+ .rule-operator-container,
34
+ .rule-value-container {
35
+ display: inline-block;
36
+ margin: 0 5px 0 0;
37
+ vertical-align: middle;
38
+ }
39
+
40
+ .rule-value-container {
41
+ border-left: var(--rule-value-separator);
42
+ padding-left: 5px;
43
+ }
44
+
45
+ .rule-value-container label {
46
+ margin-bottom: 0;
47
+ font-weight: normal;
48
+ }
49
+
50
+ .rule-value-container label.block {
51
+ display: block;
52
+ }
53
+
54
+ expression-rule-value {
55
+ display: flex;
56
+ }
57
+ `;
@@ -0,0 +1,65 @@
1
+ import { html, repeat, when } from '@genesislcap/web-core';
2
+ export const template = html `
3
+ ${(context) => {
4
+ var _a, _b;
5
+ const buttonTag = ((_b = (_a = context.styles) === null || _a === void 0 ? void 0 : _a.customElements) === null || _b === void 0 ? void 0 : _b.button) || 'button';
6
+ return html `
7
+ <div class="rule-container">
8
+ <div class="rule-content">
9
+ <expression-rule-field
10
+ class="margin"
11
+ :fields=${(x) => x.config.fields}
12
+ :field=${(x) => { var _a; return (_a = x.model) === null || _a === void 0 ? void 0 : _a.field; }}
13
+ :config=${(x) => x.config}
14
+ :styles=${(x) => x.styles}
15
+ @field-selected=${(x, c) => x.handleFieldSelected(c.event)}
16
+ ></expression-rule-field>
17
+ <expression-rule-operator
18
+ class="margin"
19
+ :operators=${(x) => x.config.operators}
20
+ :field=${(x) => x.model.field}
21
+ :operator=${(x) => { var _a; return (_a = x.model) === null || _a === void 0 ? void 0 : _a.operator; }}
22
+ :config=${(x) => x.config}
23
+ :styles=${(x) => x.styles}
24
+ @operator-selected=${(x, c) => x.handleOperatorSelected(c.event)}
25
+ ></expression-rule-operator>
26
+ ${repeat((x) => x.operandIterator, html `
27
+ <expression-rule-value
28
+ class="margin"
29
+ :config=${(_, c) => c.parent.config}
30
+ :styles=${(_, c) => c.parent.styles}
31
+ :field=${(_, c) => c.parent.model.field}
32
+ :value=${(_, c) => c.parent.operandValue(c.index)}
33
+ value-index=${(_, c) => c.index}
34
+ ?variadic=${(_, c) => { var _a, _b; return ((_b = (_a = c.parent.model) === null || _a === void 0 ? void 0 : _a.operator) === null || _b === void 0 ? void 0 : _b.nbInputs) === 'many'; }}
35
+ @value-updated=${(_, c) => c.parent.handleValueChanged(c.event)}
36
+ @remove-variadic-operand=${(_, c) => c.parent.handleRemoveVarArg(c.event)}
37
+ ></expression-rule-value>
38
+ `, { positioning: true, recycle: false })}
39
+ ${when((x) => { var _a, _b; return ((_b = (_a = x.model) === null || _a === void 0 ? void 0 : _a.operator) === null || _b === void 0 ? void 0 : _b.nbInputs) === 'many'; }, html `
40
+ <${buttonTag}
41
+ type="button"
42
+ class="btn btn-sm btn-accept"
43
+ @click="${(x) => x.dispatchAddVarArg()}"
44
+ >
45
+ +
46
+ </${buttonTag}>
47
+ `)}
48
+ </div>
49
+
50
+ <div class="rule-header">
51
+ <div class="btn-group rule-actions">
52
+ <${buttonTag}
53
+ type="button"
54
+ class="btn btn-sm btn-danger"
55
+ data-delete="rule"
56
+ @click="${(x, c) => x.dispatchDeleteRule(c.event)}"
57
+ >
58
+ Delete Rule
59
+ </${buttonTag}>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ `;
64
+ }}
65
+ `;
@@ -0,0 +1,3 @@
1
+ export * from './expression-builder';
2
+ export * from './expression-builder.styles';
3
+ export * from './expression-builder.template';
@@ -0,0 +1,48 @@
1
+ import { __decorate } from "tslib";
2
+ import { customElement, GenesisElement, observable, volatile } from '@genesislcap/web-core';
3
+ import { applyCustomStyles, processOptGroups } from '../../utils';
4
+ import { Events } from '../events';
5
+ import { template } from './rule-field.template';
6
+ let RuleField = class RuleField extends GenesisElement {
7
+ constructor() {
8
+ super(...arguments);
9
+ this.fields = [];
10
+ }
11
+ connectedCallback() {
12
+ super.connectedCallback();
13
+ applyCustomStyles(this, this.styles, 'field');
14
+ }
15
+ get groupedFieldss() {
16
+ return processOptGroups(this.fields);
17
+ }
18
+ dispatchFieldsChanged(event) {
19
+ event.stopPropagation();
20
+ const fieldId = event.target.value;
21
+ const detail = {
22
+ fieldId: fieldId,
23
+ };
24
+ this.dispatchEvent(new CustomEvent(Events.FieldSelected, { detail, bubbles: true, composed: true }));
25
+ }
26
+ };
27
+ __decorate([
28
+ observable
29
+ ], RuleField.prototype, "fields", void 0);
30
+ __decorate([
31
+ observable
32
+ ], RuleField.prototype, "field", void 0);
33
+ __decorate([
34
+ observable
35
+ ], RuleField.prototype, "config", void 0);
36
+ __decorate([
37
+ observable
38
+ ], RuleField.prototype, "styles", void 0);
39
+ __decorate([
40
+ volatile
41
+ ], RuleField.prototype, "groupedFieldss", null);
42
+ RuleField = __decorate([
43
+ customElement({
44
+ name: 'expression-rule-field',
45
+ template: template,
46
+ })
47
+ ], RuleField);
48
+ export { RuleField };