@limetech/lime-crm-building-blocks 1.101.0 → 1.102.1

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 (116) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/lime-crm-building-blocks.cjs.js +1 -1
  3. package/dist/cjs/lime-query-validation-6be10fa7.js +558 -0
  4. package/dist/cjs/limebb-lime-query-builder.cjs.entry.js +4 -514
  5. package/dist/cjs/{limebb-lime-query-filter-builder_4.cjs.entry.js → limebb-lime-query-filter-builder_3.cjs.entry.js} +1 -243
  6. package/dist/cjs/limebb-lime-query-filter-comparison_2.cjs.entry.js +1 -1
  7. package/dist/cjs/limebb-lime-query-filter-group_3.cjs.entry.js +165 -71
  8. package/dist/cjs/limebb-lime-query-order-by-item.cjs.entry.js +2 -2
  9. package/dist/cjs/limebb-lime-query-response-format-builder.cjs.entry.js +242 -0
  10. package/dist/cjs/limebb-lime-query-response-format-editor_2.cjs.entry.js +322 -0
  11. package/dist/cjs/limebb-live-docs-info.cjs.entry.js +2 -2
  12. package/dist/cjs/limebb-locale-picker.cjs.entry.js +1 -1
  13. package/dist/cjs/limebb-mention-group-counter.cjs.entry.js +2 -2
  14. package/dist/cjs/limebb-navigation-button_2.cjs.entry.js +3 -3
  15. package/dist/cjs/limebb-notification-item.cjs.entry.js +1 -1
  16. package/dist/cjs/limebb-percentage-visualizer.cjs.entry.js +2 -2
  17. package/dist/cjs/limebb-text-editor.cjs.entry.js +1 -1
  18. package/dist/cjs/limebb-trend-indicator.cjs.entry.js +1 -1
  19. package/dist/cjs/loader.cjs.js +1 -1
  20. package/dist/collection/collection-manifest.json +3 -2
  21. package/dist/collection/components/lime-query-builder/expressions/filter-group-logic.js +150 -0
  22. package/dist/collection/components/lime-query-builder/expressions/lime-query-filter-comparison.js +1 -1
  23. package/dist/collection/components/lime-query-builder/expressions/lime-query-filter-group.js +15 -71
  24. package/dist/collection/components/lime-query-builder/expressions/lime-query-filter-not.js +1 -1
  25. package/dist/collection/components/lime-query-builder/lime-query-builder.js +1 -1
  26. package/dist/collection/components/lime-query-builder/lime-query-response-format-builder.css +91 -0
  27. package/dist/collection/components/lime-query-builder/lime-query-response-format-builder.js +355 -0
  28. package/dist/collection/components/lime-query-builder/lime-query-validation.js +40 -0
  29. package/dist/collection/components/lime-query-builder/limetype-field/limetype-field.js +1 -1
  30. package/dist/collection/components/lime-query-builder/order-by/order-by-item.js +2 -2
  31. package/dist/collection/components/lime-query-builder/{response-format-editor.css → response-format/response-format-editor.css} +1 -1
  32. package/dist/collection/components/lime-query-builder/{response-format-editor.js → response-format/response-format-editor.js} +5 -5
  33. package/dist/collection/components/lime-query-builder/response-format/response-format-helpers.js +92 -0
  34. package/dist/collection/components/lime-query-builder/{response-format-item.css → response-format/response-format-item.css} +1 -1
  35. package/dist/collection/components/lime-query-builder/{response-format-item.js → response-format/response-format-item.js} +6 -6
  36. package/dist/collection/components/limeobject/file-viewer/live-docs-info.js +2 -2
  37. package/dist/collection/components/locale-picker/locale-picker.js +1 -1
  38. package/dist/collection/components/notification-list/notification-item/notification-item.js +1 -1
  39. package/dist/collection/components/percentage-visualizer/percentage-visualizer.js +2 -2
  40. package/dist/collection/components/summary-popover/summary-popover.js +3 -3
  41. package/dist/collection/components/text-editor/mention-group-counter.js +2 -2
  42. package/dist/collection/components/text-editor/text-editor.js +1 -1
  43. package/dist/collection/components/trend-indicator/trend-indicator.js +1 -1
  44. package/dist/components/lime-query-filter-comparison.js +1 -1
  45. package/dist/components/lime-query-filter-expression.js +165 -71
  46. package/dist/components/lime-query-validation.js +555 -0
  47. package/dist/components/limebb-lime-query-builder.js +14 -524
  48. package/dist/components/limebb-lime-query-response-format-builder.d.ts +11 -0
  49. package/dist/components/limebb-lime-query-response-format-builder.js +283 -0
  50. package/dist/components/limebb-lime-query-response-format-editor.d.ts +11 -0
  51. package/dist/components/{limebb-response-format-editor.js → limebb-lime-query-response-format-editor.js} +2 -2
  52. package/dist/components/limebb-lime-query-response-format-item.d.ts +11 -0
  53. package/dist/components/{limebb-response-format-item.js → limebb-lime-query-response-format-item.js} +2 -2
  54. package/dist/components/limebb-locale-picker.js +1 -1
  55. package/dist/components/limebb-mention-group-counter.js +2 -2
  56. package/dist/components/limebb-percentage-visualizer.js +2 -2
  57. package/dist/components/limebb-text-editor.js +1 -1
  58. package/dist/components/limebb-trend-indicator.js +1 -1
  59. package/dist/components/limetype-field.js +1 -1
  60. package/dist/components/live-docs-info.js +2 -2
  61. package/dist/components/notification-item.js +1 -1
  62. package/dist/components/order-by-item.js +2 -2
  63. package/dist/components/response-format-editor.js +11 -11
  64. package/dist/components/response-format-item.js +9 -9
  65. package/dist/components/summary-popover.js +3 -3
  66. package/dist/esm/lime-crm-building-blocks.js +1 -1
  67. package/dist/esm/lime-query-validation-573223a5.js +555 -0
  68. package/dist/esm/limebb-lime-query-builder.entry.js +4 -514
  69. package/dist/esm/{limebb-lime-query-filter-builder_4.entry.js → limebb-lime-query-filter-builder_3.entry.js} +2 -243
  70. package/dist/esm/limebb-lime-query-filter-comparison_2.entry.js +1 -1
  71. package/dist/esm/limebb-lime-query-filter-group_3.entry.js +165 -71
  72. package/dist/esm/limebb-lime-query-order-by-item.entry.js +2 -2
  73. package/dist/esm/limebb-lime-query-response-format-builder.entry.js +238 -0
  74. package/dist/esm/limebb-lime-query-response-format-editor_2.entry.js +317 -0
  75. package/dist/esm/limebb-live-docs-info.entry.js +2 -2
  76. package/dist/esm/limebb-locale-picker.entry.js +1 -1
  77. package/dist/esm/limebb-mention-group-counter.entry.js +2 -2
  78. package/dist/esm/limebb-navigation-button_2.entry.js +3 -3
  79. package/dist/esm/limebb-notification-item.entry.js +1 -1
  80. package/dist/esm/limebb-percentage-visualizer.entry.js +2 -2
  81. package/dist/esm/limebb-text-editor.entry.js +1 -1
  82. package/dist/esm/limebb-trend-indicator.entry.js +1 -1
  83. package/dist/esm/loader.js +1 -1
  84. package/dist/lime-crm-building-blocks/lime-crm-building-blocks.esm.js +1 -1
  85. package/dist/lime-crm-building-blocks/{p-5cf4898d.entry.js → p-0de79b7f.entry.js} +1 -1
  86. package/dist/lime-crm-building-blocks/{p-8c2fb1c9.entry.js → p-0f7135ff.entry.js} +1 -1
  87. package/dist/lime-crm-building-blocks/{p-6aa216ec.entry.js → p-186e9f1a.entry.js} +1 -1
  88. package/dist/lime-crm-building-blocks/p-289ce8b9.entry.js +1 -0
  89. package/dist/lime-crm-building-blocks/p-3351395b.entry.js +1 -0
  90. package/dist/lime-crm-building-blocks/p-33e6d0ec.entry.js +1 -0
  91. package/dist/lime-crm-building-blocks/{p-a1ee8990.entry.js → p-3d1be1c9.entry.js} +1 -1
  92. package/dist/lime-crm-building-blocks/{p-92dfc5f8.entry.js → p-577d8909.entry.js} +1 -1
  93. package/dist/lime-crm-building-blocks/{p-d84874dc.entry.js → p-6f6fed59.entry.js} +1 -1
  94. package/dist/lime-crm-building-blocks/p-7731e1b0.entry.js +1 -0
  95. package/dist/lime-crm-building-blocks/{p-0cd036ed.entry.js → p-7e5528f6.entry.js} +1 -1
  96. package/dist/lime-crm-building-blocks/{p-8601eab5.entry.js → p-a9ac501f.entry.js} +1 -1
  97. package/dist/lime-crm-building-blocks/p-be845252.entry.js +1 -0
  98. package/dist/lime-crm-building-blocks/{p-2725671e.entry.js → p-cb338753.entry.js} +1 -1
  99. package/dist/lime-crm-building-blocks/{p-425eaba2.entry.js → p-d0721b22.entry.js} +1 -1
  100. package/dist/lime-crm-building-blocks/p-fa2da6bc.js +1 -0
  101. package/dist/types/components/lime-query-builder/expressions/filter-group-logic.d.ts +89 -0
  102. package/dist/types/components/lime-query-builder/lime-query-response-format-builder.d.ts +102 -0
  103. package/dist/types/components/lime-query-builder/lime-query-validation.d.ts +13 -0
  104. package/dist/types/components/lime-query-builder/{response-format-editor.d.ts → response-format/response-format-editor.d.ts} +2 -2
  105. package/dist/types/components/lime-query-builder/response-format/response-format-helpers.d.ts +42 -0
  106. package/dist/types/components/lime-query-builder/{response-format-item.d.ts → response-format/response-format-item.d.ts} +2 -2
  107. package/dist/types/components.d.ts +394 -222
  108. package/package.json +1 -1
  109. package/dist/cjs/limebb-response-format-item.cjs.entry.js +0 -80
  110. package/dist/components/limebb-response-format-editor.d.ts +0 -11
  111. package/dist/components/limebb-response-format-item.d.ts +0 -11
  112. package/dist/esm/limebb-response-format-item.entry.js +0 -76
  113. package/dist/lime-crm-building-blocks/p-244ee55b.entry.js +0 -1
  114. package/dist/lime-crm-building-blocks/p-67c174d0.entry.js +0 -1
  115. package/dist/lime-crm-building-blocks/p-ccf34631.entry.js +0 -1
  116. package/dist/lime-crm-building-blocks/p-f9efca1d.entry.js +0 -1
@@ -308,7 +308,7 @@ const LimetypeField = class {
308
308
  value: '',
309
309
  };
310
310
  options.unshift(emptyOption);
311
- return (index.h("limel-select", { key: 'fd9522c5df730f65a5ac57140bca6c05c5acd63d', label: this.label, options: options, value: selectedOption, required: this.required, helperText: this.helperText, invalid: invalid, disabled: this.disabled || this.readonly, onChange: this.handleChange }));
311
+ return (index.h("limel-select", { key: 'ee9fdc46424c9e6dc5897260cb16bcbedd43413a', label: this.label, options: options, value: selectedOption, required: this.required, helperText: this.helperText, invalid: invalid, disabled: this.disabled || this.readonly, onChange: this.handleChange }));
312
312
  }
313
313
  componentWillRender() {
314
314
  this.updatePropertyFields(this.value || '');
@@ -346,248 +346,6 @@ const limeTypeToOption = (limetype$1) => ({
346
346
  icon: limetype.getIcon(limetype$1),
347
347
  });
348
348
 
349
- /**
350
- * Process a single property value and add to items array
351
- * @param items Array to add items to
352
- * @param fullPath Full property path
353
- * @param value Property value to process
354
- */
355
- function processPropertyValue(items, fullPath, value) {
356
- if (value === null) {
357
- items.push({ path: fullPath });
358
- return;
359
- }
360
- // Cast to record for checking
361
- const valueObj = value;
362
- const keys = Object.keys(valueObj);
363
- const hasAlias = '_alias' in valueObj;
364
- const hasDescription = '#description' in valueObj;
365
- const otherKeys = keys.filter((k) => k !== '_alias' && k !== '#description');
366
- // If it's {} or only has metadata (_alias, #description), treat as simple property
367
- if (otherKeys.length === 0) {
368
- const aliasValue = valueObj._alias;
369
- const descriptionValue = valueObj['#description'];
370
- if (aliasValue || descriptionValue) {
371
- items.push({
372
- path: fullPath,
373
- alias: aliasValue,
374
- description: descriptionValue,
375
- });
376
- }
377
- else {
378
- items.push({ path: fullPath });
379
- }
380
- return;
381
- }
382
- // If has metadata + other properties, we need to handle both
383
- // Add the nested properties (metadata is preserved in conversion back)
384
- if (hasAlias || hasDescription) {
385
- // Build a PropertySelection without the metadata for recursion
386
- const nestedSelection = {};
387
- for (const key of otherKeys) {
388
- nestedSelection[key] = valueObj[key];
389
- }
390
- items.push(...propertySelectionToItems(nestedSelection, fullPath));
391
- return;
392
- }
393
- // Nested property selection without metadata
394
- items.push(...propertySelectionToItems(value, fullPath));
395
- }
396
- /**
397
- * Convert a nested PropertySelection to a flat list of property items
398
- * @param selection The nested PropertySelection object
399
- * @param prefix Current path prefix (used for recursion)
400
- * @returns Flat array of PropertySelectionItem objects
401
- */
402
- function propertySelectionToItems(selection, prefix = '') {
403
- if (!selection) {
404
- return [];
405
- }
406
- const items = [];
407
- for (const [key, value] of Object.entries(selection)) {
408
- const fullPath = prefix ? `${prefix}.${key}` : key;
409
- if (typeof value === 'object') {
410
- // NOTE: We want to send null values to the processPropertyValue
411
- // function but we don't need a special check for null, since
412
- // `typeof null === 'object'`
413
- processPropertyValue(items, fullPath, value);
414
- }
415
- }
416
- return items;
417
- }
418
- /**
419
- * Set the final property value (with or without alias/description)
420
- * @param current Current PropertySelection object
421
- * @param part Property name/key
422
- * @param item Property selection item with path and optional alias/description
423
- */
424
- function setPropertyValue(current, part, item) {
425
- // Check if there's already a nested PropertySelection with properties
426
- const existing = current[part];
427
- if (existing &&
428
- typeof existing === 'object' &&
429
- !('_alias' in existing) &&
430
- !('#description' in existing)) {
431
- // There's already a nested PropertySelection object with properties
432
- // Don't overwrite it - preserve the nested selections
433
- return;
434
- }
435
- // Build metadata object, stripping empty values
436
- const metadata = {};
437
- if (item.alias && item.alias.trim() !== '') {
438
- metadata._alias = item.alias;
439
- }
440
- if (item.description && item.description.trim() !== '') {
441
- metadata['#description'] = item.description;
442
- }
443
- // If we have metadata, use it; otherwise use null
444
- if (Object.keys(metadata).length > 0) {
445
- current[part] = metadata;
446
- }
447
- else {
448
- current[part] = null;
449
- }
450
- }
451
- /**
452
- * Ensure a nested object exists and return it
453
- * Preserves any existing _alias and #description when converting to nested object
454
- * @param current Current PropertySelection object
455
- * @param part Property name/key
456
- * @returns The nested PropertySelection object
457
- */
458
- function ensureNestedObject(current, part) {
459
- const existing = current[part];
460
- // If doesn't exist or is null, create empty object
461
- if (!existing) {
462
- current[part] = {};
463
- return current[part];
464
- }
465
- // If it's already a PropertySelection object, check for metadata
466
- if (typeof existing === 'object') {
467
- const existingObj = existing;
468
- // If it has metadata but no other properties, preserve the metadata
469
- const keys = Object.keys(existingObj);
470
- const hasMetadata = '_alias' in existingObj || '#description' in existingObj;
471
- const otherKeys = keys.filter((k) => k !== '_alias' && k !== '#description');
472
- if (hasMetadata && otherKeys.length === 0) {
473
- // Convert { _alias: "...", "#description": "..." } to { _alias: "...", "#description": "...", ...nested }
474
- // Keep the existing object and return it (caller will add nested props)
475
- return existingObj;
476
- }
477
- // Already has nested properties, return as is
478
- return existingObj;
479
- }
480
- // Shouldn't reach here, but fallback to creating new object
481
- current[part] = {};
482
- return current[part];
483
- }
484
- /**
485
- * Convert a flat list of property items to a nested PropertySelection structure
486
- * @param items Array of PropertySelectionItem objects
487
- * @returns Nested PropertySelection object
488
- */
489
- function itemsToPropertySelection(items) {
490
- const result = {};
491
- for (const item of items) {
492
- const parts = item.path.split('.');
493
- let current = result;
494
- for (let i = 0; i < parts.length; i++) {
495
- const part = parts[i];
496
- const isLast = i === parts.length - 1;
497
- if (isLast) {
498
- setPropertyValue(current, part, item);
499
- }
500
- else {
501
- current = ensureNestedObject(current, part);
502
- }
503
- }
504
- }
505
- return result;
506
- }
507
-
508
- const responseFormatEditorCss = ":host(limebb-response-format-editor){display:block;width:100%}.response-format-editor{display:flex;flex-direction:column;gap:1rem;padding:1rem}.header{display:flex;justify-content:space-between;align-items:center;gap:1rem}.header h4{margin:0;font-size:1rem;font-weight:600;color:rgb(var(--contrast-1000))}.property-list{display:flex;flex-direction:column;gap:1rem;padding:0.5rem;border:1px solid rgb(var(--contrast-300));border-radius:0.25rem;background-color:rgb(var(--contrast-50));min-height:4rem}.property-item{padding:0.5rem;border-radius:0.25rem;transition:background-color 0.2s}.property-item:hover{background-color:rgb(var(--contrast-100))}.actions{display:flex;justify-content:flex-start}.summary{display:flex;justify-content:space-between;align-items:center;padding-top:0.5rem;border-top:1px solid rgb(var(--contrast-300))}.summary .count{font-size:0.875rem;font-weight:500;color:rgb(var(--contrast-900))}.empty-state{padding:2rem;text-align:center;color:rgb(var(--contrast-700));font-style:italic}.empty-state p{margin:0}";
509
- const LimebbResponseFormatEditorStyle0 = responseFormatEditorCss;
510
-
511
- const ResponseFormatEditor = class {
512
- constructor(hostRef) {
513
- index.registerInstance(this, hostRef);
514
- this.change = index.createEvent(this, "change", 7);
515
- /**
516
- * Optional label
517
- */
518
- this.label = 'Select Properties to Return';
519
- this.items = [{ path: '_id' }];
520
- this.handleItemChange = (index) => (event) => {
521
- event.stopPropagation();
522
- const newItems = [...this.items];
523
- if (event.detail === null) {
524
- // Remove item
525
- newItems.splice(index, 1);
526
- }
527
- else {
528
- // Update item
529
- newItems[index] = event.detail;
530
- }
531
- // Ensure we always have at least _id
532
- if (newItems.length === 0) {
533
- newItems.push({ path: '_id' });
534
- }
535
- this.items = newItems;
536
- this.emitChange();
537
- };
538
- this.handleAddProperty = () => {
539
- this.items = [...this.items, { path: '' }];
540
- this.emitChange();
541
- };
542
- }
543
- componentWillLoad() {
544
- var _a;
545
- if ((_a = this.value) === null || _a === void 0 ? void 0 : _a.object) {
546
- const converted = propertySelectionToItems(this.value.object);
547
- if (converted.length > 0) {
548
- this.items = converted;
549
- }
550
- }
551
- }
552
- componentWillUpdate() {
553
- var _a;
554
- if ((_a = this.value) === null || _a === void 0 ? void 0 : _a.object) {
555
- const currentItems = propertySelectionToItems(this.value.object);
556
- // Check if items have changed
557
- const itemsChanged = currentItems.length !== this.items.length ||
558
- !currentItems.every((item, index) => {
559
- const current = this.items[index];
560
- return (current &&
561
- item.path === current.path &&
562
- item.alias === current.alias &&
563
- item.description === current.description);
564
- });
565
- if (itemsChanged) {
566
- this.items =
567
- currentItems.length > 0 ? currentItems : [{ path: '_id' }];
568
- }
569
- }
570
- }
571
- render() {
572
- if (!this.limetype) {
573
- return (index.h("div", { class: "empty-state" }, index.h("p", null, "Select a limetype to choose properties")));
574
- }
575
- return (index.h("div", { class: "response-format-editor" }, index.h("div", { class: "header" }, index.h("h4", null, this.label)), index.h("div", { class: "property-list" }, this.items.map((item, index) => this.renderItem(item, index))), index.h("div", { class: "actions" }, index.h("limel-button", { label: "Add Property", icon: "plus_math", onClick: this.handleAddProperty })), index.h("div", { class: "summary" }, index.h("span", { class: "count" }, this.items.length, ' ', this.items.length === 1 ? 'property' : 'properties', ' ', "selected"))));
576
- }
577
- renderItem(item, index$1) {
578
- return (index.h("limebb-response-format-item", { key: `${item.path}-${index$1}`, class: "property-item", platform: this.platform, context: this.context, limetype: this.limetype, item: item, onItemChange: this.handleItemChange(index$1) }));
579
- }
580
- emitChange() {
581
- const propertySelection = itemsToPropertySelection(this.items);
582
- const responseFormat = {
583
- object: propertySelection,
584
- };
585
- this.change.emit(responseFormat);
586
- }
587
- };
588
- ResponseFormatEditor.style = LimebbResponseFormatEditorStyle0;
589
-
590
349
  exports.limebb_lime_query_filter_builder = LimeQueryFilterBuilderComponent;
591
350
  exports.limebb_lime_query_order_by_editor = OrderByEditor;
592
351
  exports.limebb_limetype_field = LimetypeField;
593
- exports.limebb_response_format_editor = ResponseFormatEditor;
@@ -82,7 +82,7 @@ const LimeQueryFilterComparisonComponent = class {
82
82
  };
83
83
  }
84
84
  render() {
85
- return (index.h("div", { key: 'a077c982ced9840beec3e574cd3e2e336cff6071', class: "expression" }, this.label && index.h("limel-header", { key: 'fbcb5cf515aac2c8e68d29947c7560684f30822c', heading: this.label }), index.h("div", { key: 'ffea426ea1295ae11aaa3c910f835acbeed24cd9', class: "expression-container" }, this.renderPropertySelector(), this.renderOperator(), this.renderValueInput(), index.h("limel-icon-button", { key: '20064f9fe42a4dfa71b2e1e2d393d50bbe20e2cb', class: "remove", icon: "trash", label: "Remove condition", onClick: this.removeExpression }))));
85
+ return (index.h("div", { key: '41fc60ed4ce76de8bbed05ee8cc658a188347cbd', class: "expression" }, this.label && index.h("limel-header", { key: '95cb9b556e2e0f2c8f3fd8ebe3909c402a844fe3', heading: this.label }), index.h("div", { key: 'feac7dcf059a0a20ad499d1549fa45d775d6bec8', class: "expression-container" }, this.renderPropertySelector(), this.renderOperator(), this.renderValueInput(), index.h("limel-icon-button", { key: '0fee01518c1c4a29c347a47ce1ce7856b32dfa8f', class: "remove", icon: "trash", label: "Remove condition", onClick: this.removeExpression }))));
86
86
  }
87
87
  renderPropertySelector() {
88
88
  return (index.h("limebb-property-selector", { platform: this.platform, context: this.context, label: "Property", limetype: this.limetype, value: this.expression.key, required: true, onChange: this.handlePropertyChange }));
@@ -6,6 +6,156 @@ const index = require('./index-ff255a0d.js');
6
6
  const index_esm = require('./index.esm-d785eb6e.js');
7
7
  const propertyResolution = require('./property-resolution-fb42a46b.js');
8
8
 
9
+ /**
10
+ * Get the subheading text for a filter group based on its operator and expression count
11
+ *
12
+ * @param operator - The group's operator (AND or OR)
13
+ * @param expressionCount - Number of child expressions
14
+ * @returns Subheading text, or empty string if 0 or 1 expressions
15
+ */
16
+ function getFilterGroupSubheading(operator, expressionCount) {
17
+ if (expressionCount <= 1) {
18
+ return '';
19
+ }
20
+ return operator === index_esm.Zt.AND
21
+ ? 'All of these conditions are true'
22
+ : 'Any of these conditions are true';
23
+ }
24
+ /**
25
+ * Get the label for the "Add condition" button
26
+ *
27
+ * @param operator - The group's operator (AND or OR)
28
+ * @param expressionCount - Number of child expressions
29
+ * @returns Appropriate button label based on context
30
+ */
31
+ function getAddConditionButtonLabel(operator, expressionCount) {
32
+ if (expressionCount === 0) {
33
+ return 'Add a condition';
34
+ }
35
+ return operator === index_esm.Zt.AND
36
+ ? 'Add another condition'
37
+ : 'Add alternative';
38
+ }
39
+ /**
40
+ * Get the label for the "Add group" button
41
+ *
42
+ * @param operator - The group's operator (AND or OR)
43
+ * @param expressionCount - Number of child expressions
44
+ * @returns Appropriate button label based on context
45
+ */
46
+ function getAddGroupButtonLabel(operator, expressionCount) {
47
+ if (expressionCount === 0) {
48
+ return 'Add a group';
49
+ }
50
+ return operator === index_esm.Zt.AND
51
+ ? 'Add another group'
52
+ : 'Add alternative group';
53
+ }
54
+ /**
55
+ * Create a new empty comparison expression
56
+ *
57
+ * @returns A new comparison expression with empty key and value
58
+ */
59
+ function createEmptyComparison() {
60
+ return {
61
+ key: '',
62
+ op: index_esm.Zt.EQUALS,
63
+ exp: '',
64
+ };
65
+ }
66
+ /**
67
+ * Create a new nested group with the opposite operator from the parent
68
+ *
69
+ * @param parentOperator - The parent group's operator
70
+ * @returns A new group with the opposite operator and one empty comparison
71
+ */
72
+ function createNestedGroup(parentOperator) {
73
+ const oppositeOp = parentOperator === index_esm.Zt.AND ? index_esm.Zt.OR : index_esm.Zt.AND;
74
+ return {
75
+ op: oppositeOp,
76
+ exp: [createEmptyComparison()],
77
+ };
78
+ }
79
+ /**
80
+ * Add a new expression to a group immutably
81
+ *
82
+ * @param group - The existing group
83
+ * @param newExpression - The expression to add
84
+ * @returns A new group with the expression added to the end
85
+ */
86
+ function addExpressionToGroup(group, newExpression) {
87
+ return {
88
+ op: group.op,
89
+ exp: [...group.exp, newExpression],
90
+ };
91
+ }
92
+ /**
93
+ * Toggle a group's operator between AND and OR
94
+ *
95
+ * @param group - The group to toggle
96
+ * @returns A new group with the toggled operator
97
+ */
98
+ function toggleGroupOperator(group) {
99
+ const newOperator = group.op === index_esm.Zt.AND ? index_esm.Zt.OR : index_esm.Zt.AND;
100
+ return {
101
+ op: newOperator,
102
+ exp: [...group.exp],
103
+ };
104
+ }
105
+ /**
106
+ * Update a child expression in a group, handling deletion and unwrapping
107
+ *
108
+ * This function handles three scenarios:
109
+ * 1. Update: Replace a child expression with a new one
110
+ * 2. Delete: Remove a child (when updatedChild is undefined)
111
+ * - If last child is deleted, return 'removed' (group should be deleted)
112
+ * - If deletion leaves one child, return 'unwrapped' (unwrap to that child)
113
+ * - Otherwise, return 'updated' with the remaining children
114
+ *
115
+ * @param group - The group containing the child
116
+ * @param childIndex - Index of the child to update
117
+ * @param updatedChild - The new child expression, or undefined to delete
118
+ * @returns Result object with type and resulting expression
119
+ */
120
+ function updateChildExpression(group, childIndex, updatedChild) {
121
+ const expressions = [...group.exp];
122
+ if (!updatedChild) {
123
+ // Deletion - remove the child
124
+ expressions.splice(childIndex, 1);
125
+ if (expressions.length === 0) {
126
+ // No children left - remove the entire group
127
+ return {
128
+ type: 'removed',
129
+ expression: undefined,
130
+ };
131
+ }
132
+ if (expressions.length === 1) {
133
+ // One child left - unwrap to that child
134
+ return {
135
+ type: 'unwrapped',
136
+ expression: expressions[0],
137
+ };
138
+ }
139
+ // Multiple children remain - return updated group
140
+ return {
141
+ type: 'updated',
142
+ expression: {
143
+ op: group.op,
144
+ exp: expressions,
145
+ },
146
+ };
147
+ }
148
+ // Update - replace the child
149
+ expressions[childIndex] = updatedChild;
150
+ return {
151
+ type: 'updated',
152
+ expression: {
153
+ op: group.op,
154
+ exp: expressions,
155
+ },
156
+ };
157
+ }
158
+
9
159
  const limeQueryFilterGroupCss = "@charset \"UTF-8\";.expression{display:flex;flex-direction:column;margin-bottom:1rem;gap:0;background-color:rgb(var(--contrast-100));border:1px solid rgb(var(--contrast-500));border-radius:0.75rem}.expression .clickable-header{cursor:pointer;user-select:none}.expression .clickable-header:hover{background-color:rgb(var(--contrast-200))}.expression>ul{margin-top:0;margin-right:1rem;margin-bottom:1rem;margin-left:1rem;padding-left:1rem;list-style:disc}.expression>ul li{margin-top:1rem}.expression>ul li.add-button{list-style:none;display:flex;gap:0.5rem}";
10
160
  const LimebbLimeQueryFilterGroupStyle0 = limeQueryFilterGroupCss;
11
161
 
@@ -15,80 +165,32 @@ const LimeQueryFilterGroupComponent = class {
15
165
  this.expressionChange = index.createEvent(this, "expressionChange", 7);
16
166
  this.renderChildExpression = (expression, childIndex) => (index.h("li", null, index.h("limebb-lime-query-filter-expression", { platform: this.platform, context: this.context, limetype: this.limetype, activeLimetype: this.activeLimetype, expression: expression, onExpressionChange: this.handleExpressionChange(childIndex) })));
17
167
  this.handleToggleOperator = () => {
18
- const newOperator = this.expression.op === index_esm.Zt.AND ? index_esm.Zt.OR : index_esm.Zt.AND;
19
- this.expressionChange.emit({
20
- op: newOperator,
21
- exp: this.expression.exp,
22
- });
168
+ const newGroup = toggleGroupOperator(this.expression);
169
+ this.expressionChange.emit(newGroup);
23
170
  };
24
171
  this.handleAddChildExpression = () => {
25
- // Always add a new comparison directly to the list
26
- const newChild = {
27
- key: '',
28
- op: index_esm.Zt.EQUALS,
29
- exp: '',
30
- };
31
- this.expressionChange.emit({
32
- op: this.expression.op,
33
- exp: [...this.expression.exp, newChild],
34
- });
172
+ const newChild = createEmptyComparison();
173
+ const newGroup = addExpressionToGroup(this.expression, newChild);
174
+ this.expressionChange.emit(newGroup);
35
175
  };
36
176
  this.handleAddChildGroup = () => {
37
- // Add a nested group of the opposite type
38
- const oppositeOp = this.expression.op === index_esm.Zt.AND ? index_esm.Zt.OR : index_esm.Zt.AND;
39
- const newChild = {
40
- op: oppositeOp,
41
- exp: [
42
- {
43
- key: '',
44
- op: index_esm.Zt.EQUALS,
45
- exp: '',
46
- },
47
- ],
48
- };
49
- this.expressionChange.emit({
50
- op: this.expression.op,
51
- exp: [...this.expression.exp, newChild],
52
- });
177
+ const newChild = createNestedGroup(this.expression.op);
178
+ const newGroup = addExpressionToGroup(this.expression, newChild);
179
+ this.expressionChange.emit(newGroup);
53
180
  };
54
181
  this.handleExpressionChange = (updatedChildIndex) => (event) => {
55
182
  event.stopPropagation();
56
183
  const updatedExpression = event.detail;
57
- const expressions = [...this.expression.exp];
58
- if (updatedExpression === undefined) {
59
- // Deletion - remove the child and potentially unwrap
60
- expressions.splice(updatedChildIndex, 1);
61
- if (expressions.length === 0) {
62
- this.expressionChange.emit(undefined);
63
- return;
64
- }
65
- if (expressions.length === 1) {
66
- // Unwrap when only one child remains after deletion
67
- this.expressionChange.emit(expressions[0]);
68
- return;
69
- }
70
- }
71
- else {
72
- // Update - replace the child, don't unwrap
73
- expressions[updatedChildIndex] = updatedExpression;
74
- }
75
- this.expressionChange.emit({
76
- op: this.expression.op,
77
- exp: expressions,
78
- });
184
+ const result = updateChildExpression(this.expression, updatedChildIndex, updatedExpression);
185
+ this.expressionChange.emit(result.expression);
79
186
  };
80
187
  }
81
188
  render() {
82
189
  const subheading = this.getSubheading();
83
- return (index.h("div", { key: '0ed5a1403d9641926cd6d474910cedf9c7bba89e', class: "expression" }, subheading && (index.h("limel-header", { key: 'ea88a97df09f0fb5a21bf9afb4745256a611c7f8', subheading: subheading, onClick: this.handleToggleOperator, class: "clickable-header" })), index.h("ul", { key: 'cfbcdd539e84f79bf1d778e075cd3317d7409647' }, this.expression.exp.map(this.renderChildExpression), index.h("li", { key: 'ec443459245bf5852920bb4d3e341f2490a7b75b', class: "add-button" }, this.renderAddButton(), this.renderAddGroupButton()))));
190
+ return (index.h("div", { key: 'bf26300a939b4a2a1b401fa7a81593ec745a2a52', class: "expression" }, subheading && (index.h("limel-header", { key: 'f5152a2ca09811540b626965f52f5793e6c99728', subheading: subheading, onClick: this.handleToggleOperator, class: "clickable-header" })), index.h("ul", { key: 'c4cad750e47e0b6c94d6a76b2a4d8b72e36b3402' }, this.expression.exp.map(this.renderChildExpression), index.h("li", { key: 'ddd614f237a0c0314c2977b74a31b365f3251f9d', class: "add-button" }, this.renderAddButton(), this.renderAddGroupButton()))));
84
191
  }
85
192
  getSubheading() {
86
- if (this.expression.exp.length <= 1) {
87
- return '';
88
- }
89
- return this.expression.op === index_esm.Zt.AND
90
- ? 'All of these conditions are true'
91
- : 'Any of these conditions are true';
193
+ return getFilterGroupSubheading(this.expression.op, this.expression.exp.length);
92
194
  }
93
195
  renderAddButton() {
94
196
  const label = this.getAddButtonLabel();
@@ -99,18 +201,10 @@ const LimeQueryFilterGroupComponent = class {
99
201
  return (index.h("limel-button", { label: label, icon: "tree_structure", onClick: this.handleAddChildGroup }));
100
202
  }
101
203
  getAddButtonLabel() {
102
- const isAnd = this.expression.op === index_esm.Zt.AND;
103
- if (this.expression.exp.length === 0) {
104
- return 'Add a condition';
105
- }
106
- return isAnd ? 'Add another condition' : 'Add alternative';
204
+ return getAddConditionButtonLabel(this.expression.op, this.expression.exp.length);
107
205
  }
108
206
  getAddGroupButtonLabel() {
109
- const isAnd = this.expression.op === index_esm.Zt.AND;
110
- if (this.expression.exp.length === 0) {
111
- return 'Add a group';
112
- }
113
- return isAnd ? 'Add another group' : 'Add alternative group';
207
+ return getAddGroupButtonLabel(this.expression.op, this.expression.exp.length);
114
208
  }
115
209
  };
116
210
  LimeQueryFilterGroupComponent.style = LimebbLimeQueryFilterGroupStyle0;
@@ -137,7 +231,7 @@ const LimeQueryFilterNotComponent = class {
137
231
  };
138
232
  }
139
233
  render() {
140
- return (index.h("div", { key: '9ab4a6b1e99668a0bcee3e3ba8cbbbe5185222e0', class: "expression" }, this.label && index.h("limel-header", { key: '85e997b0f96db306dd7a4433da959a74303aacfa', heading: this.label }), index.h("limebb-lime-query-filter-expression", { key: '14f634e125ee78f2aa70c7537b270a31699ba7c2', platform: this.platform, context: this.context, label: "Not", limetype: this.limetype, activeLimetype: this.activeLimetype, expression: this.expression.exp, onExpressionChange: this.handleExpressionChange })));
234
+ return (index.h("div", { key: '29770b10d0b892750ad2aab3520cec5a82063774', class: "expression" }, this.label && index.h("limel-header", { key: '9e47d14c6cb526c9c31d67e11a5ed5ec665c7f62', heading: this.label }), index.h("limebb-lime-query-filter-expression", { key: '943c1529057aa6cc918dc935f1a5782b149351ae', platform: this.platform, context: this.context, label: "Not", limetype: this.limetype, activeLimetype: this.activeLimetype, expression: this.expression.exp, onExpressionChange: this.handleExpressionChange })));
141
235
  }
142
236
  };
143
237
  LimeQueryFilterNotComponent.style = LimebbLimeQueryFilterNotStyle0;
@@ -41,9 +41,9 @@ const OrderByItemComponent = class {
41
41
  render() {
42
42
  const propertyPath = Object.keys(this.item)[0] || '';
43
43
  const direction = this.item[propertyPath] || 'ASC';
44
- return (index.h("div", { key: 'e0faeb5b370d8aba00a668f0861e8e1cb4eec495', class: "order-by-controls" }, index.h("div", { key: 'd013e829ca193b6ce9cc3756c3700584984f4478', class: "property-path" }, index.h("limebb-property-selector", { key: '11dee28e5de28d0dc6934abdfe613e87a8b8fbed', platform: this.platform, context: this.context, limetype: this.limetype, label: "Property", value: propertyPath, required: true, onChange: this.handlePathChange })), index.h("div", { key: '66aa416b1f9683a15357d609e3685379d8993733', class: "control-buttons" }, index.h("limel-icon-button", { key: '360f271ecd3cf42581ae21617d297c84ee93569e', icon: direction === 'ASC'
44
+ return (index.h("div", { key: '1587617d84be8905a858059ea966b7a9e0d6df78', class: "order-by-controls" }, index.h("div", { key: '8d4f47423c56cad20e91142f82a5726a7325233b', class: "property-path" }, index.h("limebb-property-selector", { key: '42c54528d2d2ee72e5b3f6ca4b31eb7bbcb9b325', platform: this.platform, context: this.context, limetype: this.limetype, label: "Property", value: propertyPath, required: true, onChange: this.handlePathChange })), index.h("div", { key: '1011a34f626c94608a926567e464d380faded349', class: "control-buttons" }, index.h("limel-icon-button", { key: '510a7c333397792a66f3e17a3501f2af96183db9', icon: direction === 'ASC'
45
45
  ? 'sort_ascending'
46
- : 'sort_descending', label: direction === 'ASC' ? 'Ascending' : 'Descending', onClick: this.handleToggleDirection }), index.h("limel-icon-button", { key: '3cbb13bff679a0ca95bb30b7853551b8bc276520', icon: "trash", label: "Remove", onClick: this.handleRemove }))));
46
+ : 'sort_descending', label: direction === 'ASC' ? 'Ascending' : 'Descending', onClick: this.handleToggleDirection }), index.h("limel-icon-button", { key: '5bc160b38c565e30cca03a88d6f2d181284cefdd', icon: "trash", label: "Remove", onClick: this.handleRemove }))));
47
47
  }
48
48
  };
49
49
  OrderByItemComponent.style = LimebbLimeQueryOrderByItemStyle0;