@emuanalytics/flow-rdf-ui 0.0.29 → 0.0.30

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.
package/dist/index.cjs CHANGED
@@ -4172,6 +4172,8 @@ const isString = (val) => typeof val === "string";
4172
4172
  const hasLength = (val) => isDefined(val) && val.length > 0;
4173
4173
  const isStringFull = (val) => isString(val) && hasLength(val);
4174
4174
  const isArrayFull = (val) => Array.isArray(val) && hasLength(val);
4175
+ const isObject = (val) => typeof val === "object" && !isNull(val);
4176
+ const isObjectFull = (val) => isObject(val) && hasLength(Object.keys(val));
4175
4177
  const isNumber = (val) => typeof val === "number" && !Number.isNaN(val) && Number.isFinite(val);
4176
4178
  const isNumeric = (val) => isString(val) && /^[+-]?([0-9]*[.])?[0-9]+$/.test(val);
4177
4179
  const isFunction = (val) => typeof val === "function";
@@ -13085,6 +13087,149 @@ exports.FlowProgressRing = __decorateClass$p([
13085
13087
  decorators_js.customElement("flow-ui-progress-ring")
13086
13088
  ], exports.FlowProgressRing);
13087
13089
 
13090
+ function filterRuleSet(ruleset, options) {
13091
+ return transformRuleSet(ruleset, (rule) => {
13092
+ if (isDefined(rule.field)) {
13093
+ if (isDefined(options.excludeFields) && options.excludeFields.includes(rule.field)) {
13094
+ return;
13095
+ }
13096
+ if (isDefined(options.includeFields) && !options.includeFields.includes(rule.field)) {
13097
+ return;
13098
+ }
13099
+ return rule;
13100
+ }
13101
+ });
13102
+ }
13103
+ function renameRuleSetFields(ruleset, replacements) {
13104
+ return transformRuleSet(ruleset, (rule) => {
13105
+ if (isDefined(rule.field)) {
13106
+ rule.field = rule.field in replacements ? replacements[rule.field] : rule.field;
13107
+ return rule;
13108
+ }
13109
+ });
13110
+ }
13111
+ function transformRuleSet(ruleSet, transformFn, clone = true) {
13112
+ if (clone) {
13113
+ ruleSet = cloneDeep__default(ruleSet);
13114
+ }
13115
+ ruleSet.rules = ruleSet.rules.map((r) => {
13116
+ if (isRule(r)) {
13117
+ return transformFn(r);
13118
+ } else if (isRuleSet(r)) {
13119
+ return transformRuleSet(r, transformFn, false);
13120
+ }
13121
+ }).filter(isRuleOrRuleset);
13122
+ return ruleSet;
13123
+ }
13124
+ const isRule = (r) => isObjectFull(r) && "field" in r;
13125
+ const isRuleSet = (r) => isObjectFull(r) && "fields" in r;
13126
+ const isRuleOrRuleset = (r) => isRule(r) || isRuleSet(r);
13127
+
13128
+ function whereClausesFromRuleSet(rule, config, options) {
13129
+ if (isRule(rule)) {
13130
+ if (!rule.enabled) {
13131
+ return void 0;
13132
+ }
13133
+ if (isNil(rule.field) || isNil(rule.operator)) {
13134
+ console.warn(`flowQueryConverter: Skipping rule with missing field or operator`, rule);
13135
+ return void 0;
13136
+ }
13137
+ const field = config.fields[rule.field];
13138
+ if (!field) {
13139
+ console.warn(`flowQueryConverter: Skipping unknown field '${rule.field}' in rule`, rule);
13140
+ return void 0;
13141
+ }
13142
+ if (isNil(rule.value) && field.nullable !== true) {
13143
+ console.warn(`flowQueryConverter: Skipping nil field '${rule.field}' in rule (non-nullable)`, rule);
13144
+ return void 0;
13145
+ }
13146
+ let fieldName = rule.field;
13147
+ if (options?.renameFields && fieldName in options.renameFields) {
13148
+ fieldName = options.renameFields[fieldName];
13149
+ }
13150
+ let clause = ["is null", "not null"].includes(rule.operator) || !isNil(rule.value) ? { [fieldName]: predicateFromRule(rule, config) } : {};
13151
+ if ((rule.operator === "!=" || rule.operator === "not like") && isObjectFull(clause)) {
13152
+ clause = { $or: [{ [fieldName]: { $is: null } }, clause] };
13153
+ }
13154
+ return clause;
13155
+ } else {
13156
+ const condition = rule.condition === "and" ? "$and" : "$or";
13157
+ const rules = rule.rules.map((r) => whereClausesFromRuleSet(r, config, options)).filter((r) => isObjectFull(r));
13158
+ return rules.length ? { [condition]: rules } : {};
13159
+ }
13160
+ }
13161
+ function predicateFromRule(rule, config) {
13162
+ const field = config.fields[rule.field];
13163
+ let operator;
13164
+ let value = rule.value;
13165
+ if (isFunction(field.convertValue)) {
13166
+ value = field.convertValue(value);
13167
+ }
13168
+ switch (rule.operator) {
13169
+ case "=":
13170
+ operator = "$eq";
13171
+ break;
13172
+ case "!=":
13173
+ operator = "$ne";
13174
+ break;
13175
+ case "<":
13176
+ operator = "$lt";
13177
+ break;
13178
+ case "<=":
13179
+ operator = "$lte";
13180
+ break;
13181
+ case ">":
13182
+ operator = "$gt";
13183
+ break;
13184
+ case ">=":
13185
+ operator = "$gte";
13186
+ break;
13187
+ case "in":
13188
+ operator = "$in";
13189
+ break;
13190
+ case "not in":
13191
+ operator = "$notIn";
13192
+ break;
13193
+ case "like":
13194
+ operator = "$iLike";
13195
+ break;
13196
+ case "not like":
13197
+ operator = "$notILike";
13198
+ break;
13199
+ case "contains":
13200
+ operator = "$iLike";
13201
+ value = `%${value}%`;
13202
+ break;
13203
+ case "is null":
13204
+ operator = "$is";
13205
+ value = null;
13206
+ break;
13207
+ case "not null":
13208
+ operator = "$not";
13209
+ value = null;
13210
+ break;
13211
+ case "between":
13212
+ operator = "$between";
13213
+ break;
13214
+ default:
13215
+ throw new Error(`Unrecognized query operator '${rule.operator}'`);
13216
+ }
13217
+ if (config.fields?.[rule.field]?.type === "datetime") {
13218
+ if (rule.operator === "between") {
13219
+ value = [luxon.DateTime.fromISO(value[0] || 0).toISO(), luxon.DateTime.fromISO(value[1] || 0).toISO()];
13220
+ } else {
13221
+ value = luxon.DateTime.fromISO(value || 0).toISO();
13222
+ }
13223
+ }
13224
+ return { [operator]: value };
13225
+ }
13226
+ const converter = (ruleset, config, options) => {
13227
+ if (options) {
13228
+ ruleset = filterRuleSet(ruleset, options);
13229
+ }
13230
+ return whereClausesFromRuleSet(ruleset, config, options);
13231
+ };
13232
+
13088
13233
  function getDefault(defaultVal, fallback) {
13089
13234
  if (isFunction(defaultVal)) {
13090
13235
  return defaultVal();
@@ -13094,15 +13239,14 @@ function getDefault(defaultVal, fallback) {
13094
13239
  const defaultStringTemplate = (rule, field, qb, update) => {
13095
13240
  const handleChange = (ev) => {
13096
13241
  const target = ev.target;
13097
- rule.value = field.fromDisplayValue?.(target.value) ?? target.value;
13242
+ rule.value = target.value === "" ? void 0 : target.value;
13098
13243
  target.setCustomValidity?.(field.validator?.(rule) ?? "");
13099
13244
  update();
13100
13245
  };
13101
- const value = rule.value && field.toDisplayValue ? field.toDisplayValue(rule.value) : rule.value;
13102
13246
  return lit.html`
13103
13247
  <flow-ui-input
13104
13248
  class="query-builder__rule-value-control"
13105
- value=${ifDefined_js.ifDefined(value)}
13249
+ value=${rule.value ?? ""}
13106
13250
  size=${qb.size}
13107
13251
  ?disabled=${!rule.enabled}
13108
13252
  @flow-ui-change=${handleChange}
@@ -13112,7 +13256,7 @@ const defaultStringTemplate = (rule, field, qb, update) => {
13112
13256
  const defaultNumberTemplate = (rule, field, qb, update) => {
13113
13257
  const handleChange = (ev) => {
13114
13258
  const target = ev.target;
13115
- rule.value = field.fromDisplayValue?.(+target.value) ?? target.value;
13259
+ rule.value = target.value === "" ? void 0 : +target.value;
13116
13260
  target.setCustomValidity?.(field.validator?.(rule) ?? "");
13117
13261
  update();
13118
13262
  };
@@ -13120,7 +13264,7 @@ const defaultNumberTemplate = (rule, field, qb, update) => {
13120
13264
  <flow-ui-input
13121
13265
  class="query-builder__rule-value-control"
13122
13266
  type="number"
13123
- value=${field.toDisplayValue ? field.toDisplayValue(rule.value) : rule.value}
13267
+ value=${rule.value ?? ""}
13124
13268
  size=${qb.size}
13125
13269
  min=${ifDefined_js.ifDefined(field.min)}
13126
13270
  max=${ifDefined_js.ifDefined(field.max)}
@@ -13133,7 +13277,7 @@ const defaultNumberTemplate = (rule, field, qb, update) => {
13133
13277
  const defaultDateTimeTemplate = (rule, field, qb, update) => {
13134
13278
  const handleChange = (ev) => {
13135
13279
  const target = ev.target;
13136
- rule.value = field.fromDisplayValue?.(target.value) ?? target.value;
13280
+ rule.value = target.value === "" ? void 0 : target.value;
13137
13281
  target.setCustomValidity(field.validator?.(rule) ?? "");
13138
13282
  update();
13139
13283
  };
@@ -13143,8 +13287,9 @@ const defaultDateTimeTemplate = (rule, field, qb, update) => {
13143
13287
  return lit.html`
13144
13288
  <flow-ui-date-time-picker
13145
13289
  class="query-builder__rule-value-control"
13146
- value=${rule.value}
13290
+ value=${rule.value ?? ""}
13147
13291
  size=${qb.size}
13292
+ placeholder="Enter a date/time"
13148
13293
  format=${ifDefined_js.ifDefined(format)}
13149
13294
  timezone=${ifDefined_js.ifDefined(timezone)}
13150
13295
  locale=${ifDefined_js.ifDefined(locale)}
@@ -13156,7 +13301,7 @@ const defaultDateTimeTemplate = (rule, field, qb, update) => {
13156
13301
  const defaultDateTemplate = (rule, field, qb, update) => {
13157
13302
  const handleChange = (ev) => {
13158
13303
  const target = ev.target;
13159
- rule.value = field.fromDisplayValue?.(target.value) ?? target.value;
13304
+ rule.value = target.value === "" ? void 0 : target.value;
13160
13305
  target.setCustomValidity(field.validator?.(rule) ?? "");
13161
13306
  update();
13162
13307
  };
@@ -13166,9 +13311,10 @@ const defaultDateTemplate = (rule, field, qb, update) => {
13166
13311
  return lit.html`
13167
13312
  <flow-ui-date-time-picker
13168
13313
  class="query-builder__rule-value-control"
13169
- value=${rule.value}
13314
+ value=${rule.value ?? ""}
13170
13315
  display-mode="date"
13171
13316
  size=${qb.size}
13317
+ placeholder="Enter a date"
13172
13318
  format=${ifDefined_js.ifDefined(format)}
13173
13319
  timezone=${ifDefined_js.ifDefined(timezone)}
13174
13320
  locale=${ifDefined_js.ifDefined(locale)}
@@ -13180,7 +13326,7 @@ const defaultDateTemplate = (rule, field, qb, update) => {
13180
13326
  const defaultTimeTemplate = (rule, field, qb, update) => {
13181
13327
  const handleChange = (ev) => {
13182
13328
  const target = ev.target;
13183
- rule.value = field.fromDisplayValue?.(target.value) ?? target.value;
13329
+ rule.value = target.value === "" ? void 0 : target.value;
13184
13330
  target.setCustomValidity(field.validator?.(rule) ?? "");
13185
13331
  update();
13186
13332
  };
@@ -13190,9 +13336,10 @@ const defaultTimeTemplate = (rule, field, qb, update) => {
13190
13336
  return lit.html`
13191
13337
  <flow-ui-date-time-picker
13192
13338
  class="query-builder__rule-value-control"
13193
- value=${rule.value}
13339
+ value=${rule.value ?? ""}
13194
13340
  display-mode="time"
13195
13341
  size=${qb.size}
13342
+ placeholder="Enter a time"
13196
13343
  format=${ifDefined_js.ifDefined(format)}
13197
13344
  timezone=${ifDefined_js.ifDefined(timezone)}
13198
13345
  locale=${ifDefined_js.ifDefined(locale)}
@@ -13204,14 +13351,14 @@ const defaultTimeTemplate = (rule, field, qb, update) => {
13204
13351
  const defaultSelectTemplate = (rule, field, qb, update) => {
13205
13352
  const handleChange = (ev) => {
13206
13353
  const target = ev.target;
13207
- rule.value = field.fromDisplayValue?.(target.value) ?? target.value;
13354
+ rule.value = target.value === "" ? void 0 : target.value;
13208
13355
  target.setCustomValidity(field.validator?.(rule) ?? "");
13209
13356
  update();
13210
13357
  };
13211
13358
  return lit.html`
13212
13359
  <flow-ui-select
13213
13360
  class="query-builder__rule-value-control"
13214
- value=${field.toDisplayValue ? field.toDisplayValue(rule.value) : rule.value}
13361
+ value=${rule.value ?? ""}
13215
13362
  size=${qb.size}
13216
13363
  ?disabled=${!rule.enabled}
13217
13364
  @flow-ui-change=${handleChange}
@@ -13227,14 +13374,14 @@ const defaultSelectTemplate = (rule, field, qb, update) => {
13227
13374
  const defaultMultiSelectTemplate = (rule, field, qb, update) => {
13228
13375
  const handleChange = (ev) => {
13229
13376
  const target = ev.target;
13230
- rule.value = field.fromDisplayValue?.(target.value) ?? target.value;
13377
+ rule.value = isArrayFull(target.value) ? target.value : void 0;
13231
13378
  target.setCustomValidity(field.validator?.(rule) ?? "");
13232
13379
  update();
13233
13380
  };
13234
13381
  return lit.html`
13235
13382
  <flow-ui-select
13236
13383
  class="query-builder__rule-value-control"
13237
- value=${field.toDisplayValue ? field.toDisplayValue(rule.value) : rule.value}
13384
+ .value=${rule.value ?? []}
13238
13385
  size=${qb.size}
13239
13386
  ?disabled=${!rule.enabled}
13240
13387
  @flow-ui-change=${handleChange}
@@ -13519,6 +13666,65 @@ const _FlowQueryBuilder = class _FlowQueryBuilder extends FlowRdfElement {
13519
13666
  static registerFieldDefinition(type, fieldDefinition) {
13520
13667
  _FlowQueryBuilder.fieldDefinitions.set(type, fieldDefinition);
13521
13668
  }
13669
+ /**
13670
+ * Static helper method to determine if supplied argument is
13671
+ * a `FlowQueryBuilderRule`.
13672
+ *
13673
+ * @param value A value to test
13674
+ */
13675
+ static isRule(value) {
13676
+ return isRule(value);
13677
+ }
13678
+ /**
13679
+ * Static helper method to determine if supplied argument is
13680
+ * a `FlowQueryBuilderRuleSet`.
13681
+ *
13682
+ * @param value A value to test
13683
+ * @returns `true` if supplied value is a FlowQueryBuilderRuleSet
13684
+ */
13685
+ static isRuleSet(value) {
13686
+ return isRuleSet(value);
13687
+ }
13688
+ /**
13689
+ * Static helper method to recursively filter a `FlowQueryBuilderRuleSet`.
13690
+ *
13691
+ * This can be used to sanitize user queries before they are executed.
13692
+ *
13693
+ * @param ruleset Rule set to filter
13694
+ * @param options Fields to include or exclude
13695
+ * @returns The filtered rule set
13696
+ */
13697
+ static filterRuleSet(ruleset, options) {
13698
+ return filterRuleSet(ruleset, options);
13699
+ }
13700
+ /**
13701
+ * Static helper method to rename fields in a `FlowQueryBuilderRuleSet`.
13702
+ *
13703
+ * @param ruleSet A `FlowQueryBuilderRuleSet` to rename.
13704
+ * @param replacements Mapping of string to string for renaming fields.
13705
+ * @returns The renamed rule set.
13706
+ */
13707
+ static renameRuleSetFields(ruleset, replacements) {
13708
+ return renameRuleSetFields(ruleset, replacements);
13709
+ }
13710
+ /**
13711
+ * Static helper method to recursively apply a transform function to each rule
13712
+ * in a `FlowQueryBuilderRuleSet`.
13713
+ *
13714
+ * The transform fn should expect a single FlowQueryBuilderRule and return:
13715
+ *
13716
+ * - the same rule unmodifed or modified in place
13717
+ * - `undefined` to exclude the rule from the rule set
13718
+ *
13719
+ * This can be used to sanitize rule sets before they are used to perform queries.
13720
+ *
13721
+ * @param ruleSet query builder rule set
13722
+ * @param transformFn transform function
13723
+ * @returns The modified rule set
13724
+ */
13725
+ static transformRuleSet(ruleSet, transformFn) {
13726
+ return transformRuleSet(ruleSet, transformFn);
13727
+ }
13522
13728
  valueTemplateForRule(_rule, field) {
13523
13729
  const fieldDef = field?.type && _FlowQueryBuilder.fieldDefinitions.get(field.type);
13524
13730
  if (fieldDef?.template) {
@@ -13614,7 +13820,6 @@ const _FlowQueryBuilder = class _FlowQueryBuilder extends FlowRdfElement {
13614
13820
  emitValueChange() {
13615
13821
  if (!this.subQueryBuilder) {
13616
13822
  this.value = cloneDeep__default(this.value);
13617
- console.log("top-level value", this.value);
13618
13823
  }
13619
13824
  this.emit("flow-ui-change");
13620
13825
  }
@@ -13777,7 +13982,9 @@ const _FlowQueryBuilder = class _FlowQueryBuilder extends FlowRdfElement {
13777
13982
  }
13778
13983
  emptyRulesetTemplate() {
13779
13984
  return lit.html`
13780
- <div class="query-builder__empty-ruleset"><i>A rule set cannot be empty. Please add a rule or remove the set.</div>
13985
+ <div class="query-builder__empty-ruleset">
13986
+ <i>A rule set cannot be empty. Please add a rule or remove the set.</i>
13987
+ </div>
13781
13988
  `;
13782
13989
  }
13783
13990
  render() {
@@ -13845,6 +14052,11 @@ const _FlowQueryBuilder = class _FlowQueryBuilder extends FlowRdfElement {
13845
14052
  };
13846
14053
  _FlowQueryBuilder.styles = styles$o;
13847
14054
  _FlowQueryBuilder.fieldDefinitions = /* @__PURE__ */ new Map();
14055
+ // Static converts and helpers
14056
+ /**
14057
+ *
14058
+ */
14059
+ _FlowQueryBuilder.convertToFlowQuery = converter;
13848
14060
  __decorateClass$o([
13849
14061
  decorators_js.property({ type: Object, reflect: false })
13850
14062
  ], _FlowQueryBuilder.prototype, "value", 2);
@@ -23165,7 +23377,7 @@ const translation = {
23165
23377
  };
23166
23378
  localize.registerTranslation(translation);
23167
23379
 
23168
- const version = "0.0.29";
23380
+ const version = "0.0.30";
23169
23381
 
23170
23382
  const CONSOLE_HIGHLIGHT_STYLE = `
23171
23383
  padding: 2px 4px;
package/dist/index.d.cts CHANGED
@@ -2640,8 +2640,7 @@ interface FlowQueryBuilderFieldBase<ValueType = any> {
2640
2640
  operators?: string[];
2641
2641
  defaultValue?: ValueType | (() => ValueType);
2642
2642
  defaultOperator?: string;
2643
- toDisplayValue?: (value: ValueType) => ValueType;
2644
- fromDisplayValue?: (value: ValueType) => ValueType;
2643
+ convertValue?: (value: ValueType) => any;
2645
2644
  validator?: (rule: FlowQueryBuilderRule<ValueType>) => string;
2646
2645
  }
2647
2646
  interface FlowQueryBuilderStringField extends FlowQueryBuilderFieldBase<string> {
@@ -2686,7 +2685,7 @@ interface FlowQueryBuilderFieldTypeMap {
2686
2685
  }
2687
2686
  type FlowQueryBuilderFieldType = keyof FlowQueryBuilderFieldTypeMap;
2688
2687
  type FlowQueryBuilderField = FlowQueryBuilderFieldTypeMap[keyof FlowQueryBuilderFieldTypeMap];
2689
- type FlowQueryBuilderTemplateFn<T extends FlowQueryBuilderFieldType> = (rule: FlowQueryBuilderRule<T>, field: FlowQueryBuilderFieldTypeMap[T], qb: FlowQueryBuilder, update: () => void) => TemplateResult;
2688
+ type FlowQueryBuilderTemplateFn<FieldType extends FlowQueryBuilderFieldType> = (rule: FlowQueryBuilderRule<FlowQueryBuilderFieldTypeMap[FieldType]['value']>, field: FlowQueryBuilderFieldTypeMap[FieldType], qb: FlowQueryBuilder, update: () => void) => TemplateResult;
2690
2689
  interface FlowQueryBuilderConfig {
2691
2690
  fields: FlowQueryBuilderFieldMap;
2692
2691
  }
@@ -2694,6 +2693,12 @@ interface FlowQueryBuilderFieldDefinition<Field extends FlowQueryBuilderFieldTyp
2694
2693
  operators: string[];
2695
2694
  template: FlowQueryBuilderTemplateFn<Field>;
2696
2695
  }
2696
+ interface FlowQueryBuilderConverterOptions {
2697
+ includeFields?: string[];
2698
+ excludeFields?: string[];
2699
+ renameFields?: Record<string, string>;
2700
+ }
2701
+ type FlowQueryBuilderConverter = (ruleSet: FlowQueryBuilderRuleSet, config: FlowQueryBuilderConfig, options?: FlowQueryBuilderConverterOptions) => any;
2697
2702
 
2698
2703
  type NoUnion<T, U = T> = T extends U ? ([U] extends [T] ? T : never) : never;
2699
2704
  /**
@@ -2718,6 +2723,62 @@ declare class FlowQueryBuilder extends FlowRdfElement {
2718
2723
  * @param fieldDefinition
2719
2724
  */
2720
2725
  static registerFieldDefinition<T extends FlowQueryBuilderFieldType>(type: T, fieldDefinition: FlowQueryBuilderFieldDefinition<NoUnion<T>>): void;
2726
+ /**
2727
+ *
2728
+ */
2729
+ static convertToFlowQuery: FlowQueryBuilderConverter;
2730
+ /**
2731
+ * Static helper method to determine if supplied argument is
2732
+ * a `FlowQueryBuilderRule`.
2733
+ *
2734
+ * @param value A value to test
2735
+ */
2736
+ static isRule(value: unknown): value is FlowQueryBuilderRule;
2737
+ /**
2738
+ * Static helper method to determine if supplied argument is
2739
+ * a `FlowQueryBuilderRuleSet`.
2740
+ *
2741
+ * @param value A value to test
2742
+ * @returns `true` if supplied value is a FlowQueryBuilderRuleSet
2743
+ */
2744
+ static isRuleSet(value: unknown): value is FlowQueryBuilderRuleSet;
2745
+ /**
2746
+ * Static helper method to recursively filter a `FlowQueryBuilderRuleSet`.
2747
+ *
2748
+ * This can be used to sanitize user queries before they are executed.
2749
+ *
2750
+ * @param ruleset Rule set to filter
2751
+ * @param options Fields to include or exclude
2752
+ * @returns The filtered rule set
2753
+ */
2754
+ static filterRuleSet(ruleset: FlowQueryBuilderRuleSet, options: {
2755
+ excludeFields?: string[];
2756
+ includeFields?: string[];
2757
+ }): FlowQueryBuilderRuleSet;
2758
+ /**
2759
+ * Static helper method to rename fields in a `FlowQueryBuilderRuleSet`.
2760
+ *
2761
+ * @param ruleSet A `FlowQueryBuilderRuleSet` to rename.
2762
+ * @param replacements Mapping of string to string for renaming fields.
2763
+ * @returns The renamed rule set.
2764
+ */
2765
+ static renameRuleSetFields(ruleset: FlowQueryBuilderRuleSet, replacements: Record<string, string>): FlowQueryBuilderRuleSet;
2766
+ /**
2767
+ * Static helper method to recursively apply a transform function to each rule
2768
+ * in a `FlowQueryBuilderRuleSet`.
2769
+ *
2770
+ * The transform fn should expect a single FlowQueryBuilderRule and return:
2771
+ *
2772
+ * - the same rule unmodifed or modified in place
2773
+ * - `undefined` to exclude the rule from the rule set
2774
+ *
2775
+ * This can be used to sanitize rule sets before they are used to perform queries.
2776
+ *
2777
+ * @param ruleSet query builder rule set
2778
+ * @param transformFn transform function
2779
+ * @returns The modified rule set
2780
+ */
2781
+ static transformRuleSet(ruleSet: FlowQueryBuilderRuleSet, transformFn: (rule: FlowQueryBuilderRule) => FlowQueryBuilderRule | undefined): FlowQueryBuilderRuleSet;
2721
2782
  private readonly hasSlotController;
2722
2783
  /** The query builder's value object. */
2723
2784
  value: FlowQueryBuilderRuleSet;
@@ -2755,10 +2816,10 @@ declare class FlowQueryBuilder extends FlowRdfElement {
2755
2816
  private operatorsForField;
2756
2817
  private defaultOperatorsForFieldType;
2757
2818
  private toolbarTemplate;
2758
- ruleTemplate(rule: FlowQueryBuilderRule, fieldConfig: FlowQueryBuilderField | undefined, index: number): lit.TemplateResult<1>;
2759
- ruleValueTemplate(rule: FlowQueryBuilderRule, fieldConfig: FlowQueryBuilderField | undefined): lit.TemplateResult<1>;
2760
- subQueryBuilderTemplate(ruleSet: FlowQueryBuilderRuleSet, index: number): lit.TemplateResult<1>;
2761
- emptyRulesetTemplate(): lit.TemplateResult<1>;
2819
+ private ruleTemplate;
2820
+ private ruleValueTemplate;
2821
+ private subQueryBuilderTemplate;
2822
+ private emptyRulesetTemplate;
2762
2823
  render(): lit.TemplateResult<1>;
2763
2824
  }
2764
2825
 
package/dist/index.d.mts CHANGED
@@ -2640,8 +2640,7 @@ interface FlowQueryBuilderFieldBase<ValueType = any> {
2640
2640
  operators?: string[];
2641
2641
  defaultValue?: ValueType | (() => ValueType);
2642
2642
  defaultOperator?: string;
2643
- toDisplayValue?: (value: ValueType) => ValueType;
2644
- fromDisplayValue?: (value: ValueType) => ValueType;
2643
+ convertValue?: (value: ValueType) => any;
2645
2644
  validator?: (rule: FlowQueryBuilderRule<ValueType>) => string;
2646
2645
  }
2647
2646
  interface FlowQueryBuilderStringField extends FlowQueryBuilderFieldBase<string> {
@@ -2686,7 +2685,7 @@ interface FlowQueryBuilderFieldTypeMap {
2686
2685
  }
2687
2686
  type FlowQueryBuilderFieldType = keyof FlowQueryBuilderFieldTypeMap;
2688
2687
  type FlowQueryBuilderField = FlowQueryBuilderFieldTypeMap[keyof FlowQueryBuilderFieldTypeMap];
2689
- type FlowQueryBuilderTemplateFn<T extends FlowQueryBuilderFieldType> = (rule: FlowQueryBuilderRule<T>, field: FlowQueryBuilderFieldTypeMap[T], qb: FlowQueryBuilder, update: () => void) => TemplateResult;
2688
+ type FlowQueryBuilderTemplateFn<FieldType extends FlowQueryBuilderFieldType> = (rule: FlowQueryBuilderRule<FlowQueryBuilderFieldTypeMap[FieldType]['value']>, field: FlowQueryBuilderFieldTypeMap[FieldType], qb: FlowQueryBuilder, update: () => void) => TemplateResult;
2690
2689
  interface FlowQueryBuilderConfig {
2691
2690
  fields: FlowQueryBuilderFieldMap;
2692
2691
  }
@@ -2694,6 +2693,12 @@ interface FlowQueryBuilderFieldDefinition<Field extends FlowQueryBuilderFieldTyp
2694
2693
  operators: string[];
2695
2694
  template: FlowQueryBuilderTemplateFn<Field>;
2696
2695
  }
2696
+ interface FlowQueryBuilderConverterOptions {
2697
+ includeFields?: string[];
2698
+ excludeFields?: string[];
2699
+ renameFields?: Record<string, string>;
2700
+ }
2701
+ type FlowQueryBuilderConverter = (ruleSet: FlowQueryBuilderRuleSet, config: FlowQueryBuilderConfig, options?: FlowQueryBuilderConverterOptions) => any;
2697
2702
 
2698
2703
  type NoUnion<T, U = T> = T extends U ? ([U] extends [T] ? T : never) : never;
2699
2704
  /**
@@ -2718,6 +2723,62 @@ declare class FlowQueryBuilder extends FlowRdfElement {
2718
2723
  * @param fieldDefinition
2719
2724
  */
2720
2725
  static registerFieldDefinition<T extends FlowQueryBuilderFieldType>(type: T, fieldDefinition: FlowQueryBuilderFieldDefinition<NoUnion<T>>): void;
2726
+ /**
2727
+ *
2728
+ */
2729
+ static convertToFlowQuery: FlowQueryBuilderConverter;
2730
+ /**
2731
+ * Static helper method to determine if supplied argument is
2732
+ * a `FlowQueryBuilderRule`.
2733
+ *
2734
+ * @param value A value to test
2735
+ */
2736
+ static isRule(value: unknown): value is FlowQueryBuilderRule;
2737
+ /**
2738
+ * Static helper method to determine if supplied argument is
2739
+ * a `FlowQueryBuilderRuleSet`.
2740
+ *
2741
+ * @param value A value to test
2742
+ * @returns `true` if supplied value is a FlowQueryBuilderRuleSet
2743
+ */
2744
+ static isRuleSet(value: unknown): value is FlowQueryBuilderRuleSet;
2745
+ /**
2746
+ * Static helper method to recursively filter a `FlowQueryBuilderRuleSet`.
2747
+ *
2748
+ * This can be used to sanitize user queries before they are executed.
2749
+ *
2750
+ * @param ruleset Rule set to filter
2751
+ * @param options Fields to include or exclude
2752
+ * @returns The filtered rule set
2753
+ */
2754
+ static filterRuleSet(ruleset: FlowQueryBuilderRuleSet, options: {
2755
+ excludeFields?: string[];
2756
+ includeFields?: string[];
2757
+ }): FlowQueryBuilderRuleSet;
2758
+ /**
2759
+ * Static helper method to rename fields in a `FlowQueryBuilderRuleSet`.
2760
+ *
2761
+ * @param ruleSet A `FlowQueryBuilderRuleSet` to rename.
2762
+ * @param replacements Mapping of string to string for renaming fields.
2763
+ * @returns The renamed rule set.
2764
+ */
2765
+ static renameRuleSetFields(ruleset: FlowQueryBuilderRuleSet, replacements: Record<string, string>): FlowQueryBuilderRuleSet;
2766
+ /**
2767
+ * Static helper method to recursively apply a transform function to each rule
2768
+ * in a `FlowQueryBuilderRuleSet`.
2769
+ *
2770
+ * The transform fn should expect a single FlowQueryBuilderRule and return:
2771
+ *
2772
+ * - the same rule unmodifed or modified in place
2773
+ * - `undefined` to exclude the rule from the rule set
2774
+ *
2775
+ * This can be used to sanitize rule sets before they are used to perform queries.
2776
+ *
2777
+ * @param ruleSet query builder rule set
2778
+ * @param transformFn transform function
2779
+ * @returns The modified rule set
2780
+ */
2781
+ static transformRuleSet(ruleSet: FlowQueryBuilderRuleSet, transformFn: (rule: FlowQueryBuilderRule) => FlowQueryBuilderRule | undefined): FlowQueryBuilderRuleSet;
2721
2782
  private readonly hasSlotController;
2722
2783
  /** The query builder's value object. */
2723
2784
  value: FlowQueryBuilderRuleSet;
@@ -2755,10 +2816,10 @@ declare class FlowQueryBuilder extends FlowRdfElement {
2755
2816
  private operatorsForField;
2756
2817
  private defaultOperatorsForFieldType;
2757
2818
  private toolbarTemplate;
2758
- ruleTemplate(rule: FlowQueryBuilderRule, fieldConfig: FlowQueryBuilderField | undefined, index: number): lit.TemplateResult<1>;
2759
- ruleValueTemplate(rule: FlowQueryBuilderRule, fieldConfig: FlowQueryBuilderField | undefined): lit.TemplateResult<1>;
2760
- subQueryBuilderTemplate(ruleSet: FlowQueryBuilderRuleSet, index: number): lit.TemplateResult<1>;
2761
- emptyRulesetTemplate(): lit.TemplateResult<1>;
2819
+ private ruleTemplate;
2820
+ private ruleValueTemplate;
2821
+ private subQueryBuilderTemplate;
2822
+ private emptyRulesetTemplate;
2762
2823
  render(): lit.TemplateResult<1>;
2763
2824
  }
2764
2825