web-mojo 2.1.977 → 2.1.979

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 (49) hide show
  1. package/dist/admin.cjs.js +1 -1
  2. package/dist/admin.cjs.js.map +1 -1
  3. package/dist/admin.es.js +50 -8
  4. package/dist/admin.es.js.map +1 -1
  5. package/dist/auth.cjs.js +1 -1
  6. package/dist/auth.cjs.js.map +1 -1
  7. package/dist/auth.es.js +2 -2
  8. package/dist/auth.es.js.map +1 -1
  9. package/dist/charts.cjs.js +1 -1
  10. package/dist/charts.es.js +2 -2
  11. package/dist/chunks/{ChatView-C1IPSfjo.js → ChatView-C1702ZPZ.js} +3 -3
  12. package/dist/chunks/{ChatView-C1IPSfjo.js.map → ChatView-C1702ZPZ.js.map} +1 -1
  13. package/dist/chunks/{ChatView-DFP_Gptr.js → ChatView-CVZScWPz.js} +2 -2
  14. package/dist/chunks/{ChatView-DFP_Gptr.js.map → ChatView-CVZScWPz.js.map} +1 -1
  15. package/dist/chunks/{Dialog-Dq_QZWO3.js → Dialog-Be1EkdvX.js} +3 -3
  16. package/dist/chunks/{Dialog-Dq_QZWO3.js.map → Dialog-Be1EkdvX.js.map} +1 -1
  17. package/dist/chunks/{Dialog-Cm8FBKBR.js → Dialog-YnhCC4C2.js} +2 -2
  18. package/dist/chunks/{Dialog-Cm8FBKBR.js.map → Dialog-YnhCC4C2.js.map} +1 -1
  19. package/dist/chunks/{FormView-B_nJKNfq.js → FormView-CQbR3S82.js} +284 -216
  20. package/dist/chunks/FormView-CQbR3S82.js.map +1 -0
  21. package/dist/chunks/{FormView-BPH70cm4.js → FormView-DHz1ydYg.js} +2 -2
  22. package/dist/chunks/FormView-DHz1ydYg.js.map +1 -0
  23. package/dist/chunks/{MetricsMiniChartWidget-Br4Hg74G.js → MetricsMiniChartWidget-CHsOuS2O.js} +2 -2
  24. package/dist/chunks/{MetricsMiniChartWidget-Br4Hg74G.js.map → MetricsMiniChartWidget-CHsOuS2O.js.map} +1 -1
  25. package/dist/chunks/{MetricsMiniChartWidget-C8BVRLtm.js → MetricsMiniChartWidget-DMGjpLSU.js} +2 -2
  26. package/dist/chunks/{MetricsMiniChartWidget-C8BVRLtm.js.map → MetricsMiniChartWidget-DMGjpLSU.js.map} +1 -1
  27. package/dist/chunks/{PDFViewer-XlOIcSxd.js → PDFViewer-BN200UnI.js} +2 -2
  28. package/dist/chunks/{PDFViewer-XlOIcSxd.js.map → PDFViewer-BN200UnI.js.map} +1 -1
  29. package/dist/chunks/{PDFViewer-DxCgaoOw.js → PDFViewer-BlWEqtY5.js} +2 -2
  30. package/dist/chunks/{PDFViewer-DxCgaoOw.js.map → PDFViewer-BlWEqtY5.js.map} +1 -1
  31. package/dist/chunks/{TopNav-D8hDsmyN.js → TopNav-DF8w5mgO.js} +2 -2
  32. package/dist/chunks/{TopNav-D8hDsmyN.js.map → TopNav-DF8w5mgO.js.map} +1 -1
  33. package/dist/chunks/{TopNav-CBSoNCFK.js → TopNav-ueVUoXcv.js} +2 -2
  34. package/dist/chunks/{TopNav-CBSoNCFK.js.map → TopNav-ueVUoXcv.js.map} +1 -1
  35. package/dist/chunks/{WebApp-DRvyOIDY.js → WebApp-gsWqZg8e.js} +13 -13
  36. package/dist/chunks/{WebApp-DRvyOIDY.js.map → WebApp-gsWqZg8e.js.map} +1 -1
  37. package/dist/chunks/{WebApp-yLQ-WHm0.js → WebApp-m17riaNV.js} +2 -2
  38. package/dist/chunks/{WebApp-yLQ-WHm0.js.map → WebApp-m17riaNV.js.map} +1 -1
  39. package/dist/core.css +138 -4
  40. package/dist/css/web-mojo.css +1 -1
  41. package/dist/docit.cjs.js +1 -1
  42. package/dist/docit.es.js +3 -3
  43. package/dist/index.cjs.js +1 -1
  44. package/dist/index.es.js +7 -7
  45. package/dist/lightbox.cjs.js +1 -1
  46. package/dist/lightbox.es.js +3 -3
  47. package/package.json +1 -1
  48. package/dist/chunks/FormView-BPH70cm4.js.map +0 -1
  49. package/dist/chunks/FormView-B_nJKNfq.js.map +0 -1
@@ -1697,6 +1697,7 @@ class FormBuilder {
1697
1697
  labelField = "name",
1698
1698
  valueField = "id",
1699
1699
  excludeIds = [],
1700
+ ignoreIds = [],
1700
1701
  size = 8,
1701
1702
  maxHeight = null,
1702
1703
  showSelectAll = true,
@@ -1721,6 +1722,7 @@ class FormBuilder {
1721
1722
  labelField,
1722
1723
  valueField,
1723
1724
  excludeIds,
1725
+ ignoreIds,
1724
1726
  size,
1725
1727
  maxHeight,
1726
1728
  showSelectAll,
@@ -3349,6 +3351,125 @@ class CollectionSelectView extends View {
3349
3351
  return MOJOUtils.getNestedValue(item, fieldPath);
3350
3352
  }
3351
3353
  }
3354
+ class SearchView extends View {
3355
+ constructor(options = {}) {
3356
+ super({
3357
+ tagName: "div",
3358
+ className: "collection-multiselect-search",
3359
+ template: `
3360
+ <input type="text"
3361
+ class="form-control form-control-sm mb-2"
3362
+ placeholder="{{placeholder}}"
3363
+ data-change-action="search"
3364
+ data-filter="live-search"
3365
+ data-filter-debounce="{{debounce}}" />
3366
+ `,
3367
+ ...options
3368
+ });
3369
+ this.placeholder = options.placeholder || "Search...";
3370
+ this.debounce = options.debounce || 400;
3371
+ }
3372
+ async onChangeSearch(event, element) {
3373
+ const searchValue = element.value.trim();
3374
+ this.emit("search", searchValue);
3375
+ }
3376
+ getValue() {
3377
+ return this.element?.querySelector("input")?.value || "";
3378
+ }
3379
+ clear() {
3380
+ const input = this.element?.querySelector("input");
3381
+ if (input) input.value = "";
3382
+ }
3383
+ }
3384
+ class ListItemsView extends View {
3385
+ constructor(options = {}) {
3386
+ super({
3387
+ tagName: "div",
3388
+ className: "collection-multiselect-items",
3389
+ template: `
3390
+ {{#loading}}
3391
+ <div class="text-center py-3">
3392
+ <div class="spinner-border spinner-border-sm" role="status">
3393
+ <span class="visually-hidden">Loading...</span>
3394
+ </div>
3395
+ </div>
3396
+ {{/loading}}
3397
+
3398
+ {{^loading}}
3399
+ {{#items.length}}
3400
+ {{#showSelectAll}}
3401
+ <div class="collection-multiselect-actions d-flex justify-content-between align-items-center mb-2 py-1">
3402
+ <button type="button"
3403
+ class="btn btn-link btn-sm text-decoration-none p-0 {{#allSelected}}text-muted{{/allSelected}}"
3404
+ data-action="select-all"
3405
+ {{#allSelected}}disabled{{/allSelected}}>
3406
+ <i class="bi bi-check-square me-1"></i>
3407
+ SELECT {{#unselectedCount}}({{unselectedCount}}){{/unselectedCount}}
3408
+ </button>
3409
+ <button type="button"
3410
+ class="btn btn-link btn-sm text-decoration-none p-0 {{#noneSelected}}text-muted{{/noneSelected}}"
3411
+ data-action="deselect-all"
3412
+ {{#noneSelected}}disabled{{/noneSelected}}>
3413
+ DESELECT {{#selectedCount}}({{selectedCount}}){{/selectedCount}}
3414
+ <i class="bi bi-square ms-1"></i>
3415
+ </button>
3416
+ </div>
3417
+ {{/showSelectAll}}
3418
+
3419
+ <div class="collection-multiselect-list border rounded"
3420
+ style="max-height: {{maxHeight}}px; overflow-y: auto;">
3421
+ {{#items}}
3422
+ <div class="collection-multiselect-item d-flex align-items-center py-2 px-3 {{^disabled}}clickable{{/disabled}}"
3423
+ data-action="{{^disabled}}toggle{{/disabled}}"
3424
+ data-value="{{value}}"
3425
+ data-index="{{index}}">
3426
+ <i class="bi {{#selected}}bi-check-square-fill text-primary{{/selected}}{{^selected}}bi-square{{/selected}} me-2"
3427
+ style="font-size: 1.1rem;"></i>
3428
+ <span {{#disabled}}class="text-muted"{{/disabled}}>{{label}}</span>
3429
+ </div>
3430
+ {{/items}}
3431
+ </div>
3432
+ {{/items.length}}
3433
+
3434
+ {{^items.length}}
3435
+ <div class="collection-multiselect-empty text-muted text-center py-4 border rounded">
3436
+ <i class="bi bi-inbox fs-3 d-block mb-2 opacity-50"></i>
3437
+ <div>No items available</div>
3438
+ </div>
3439
+ {{/^items.length}}
3440
+ {{/loading}}
3441
+ `,
3442
+ ...options
3443
+ });
3444
+ this.items = options.items || [];
3445
+ this.loading = options.loading || false;
3446
+ this.maxHeight = options.maxHeight || 336;
3447
+ this.showSelectAll = options.showSelectAll !== false;
3448
+ this.selectedCount = options.selectedCount || 0;
3449
+ this.totalCount = options.totalCount || 0;
3450
+ this.unselectedCount = options.unselectedCount || 0;
3451
+ this.allSelected = options.allSelected || false;
3452
+ this.noneSelected = options.noneSelected || true;
3453
+ this.lastClickedIndex = -1;
3454
+ }
3455
+ handleActionToggle(event, element) {
3456
+ const value = element.getAttribute("data-value");
3457
+ const index = parseInt(element.getAttribute("data-index"), 10);
3458
+ this.emit("toggle", { value, index, shiftKey: event.shiftKey });
3459
+ this.lastClickedIndex = index;
3460
+ }
3461
+ async handleActionSelectAll(event) {
3462
+ event.preventDefault();
3463
+ this.emit("select-all");
3464
+ }
3465
+ async handleActionDeselectAll(event) {
3466
+ event.preventDefault();
3467
+ this.emit("deselect-all");
3468
+ }
3469
+ updateState(state) {
3470
+ Object.assign(this, state);
3471
+ }
3472
+ }
3352
3473
  class CollectionMultiSelectView extends View {
3353
3474
  constructor(options = {}) {
3354
3475
  super({
@@ -3361,58 +3482,9 @@ class CollectionMultiSelectView extends View {
3361
3482
  {{label}}{{#required}}<span class="text-danger">*</span>{{/required}}
3362
3483
  </label>
3363
3484
  {{/label}}
3364
-
3365
- {{#enableSearch}}
3366
- <input type="text"
3367
- class="form-control form-control-sm mb-2"
3368
- placeholder="{{searchPlaceholder}}"
3369
- value="{{searchValue}}"
3370
- data-change-action="search-input" />
3371
- {{/enableSearch}}
3372
-
3373
- {{#loading}}
3374
- <div class="text-center py-3">
3375
- <div class="spinner-border spinner-border-sm" role="status">
3376
- <span class="visually-hidden">Loading...</span>
3377
- </div>
3378
- </div>
3379
- {{/loading}}
3380
-
3381
- {{^loading}}
3382
- {{#items.length}}
3383
- <div class="collection-multiselect-list border rounded p-3" style="max-height: {{maxHeight}}px; overflow-y: auto; background: #fff;">
3384
- {{#items}}
3385
- <div class="d-flex align-items-center mb-2 py-1 px-2 rounded {{^disabled}}hover-bg{{/disabled}}"
3386
- style="cursor: {{^disabled}}pointer{{/disabled}}{{#disabled}}not-allowed{{/disabled}}; user-select: none; transition: background-color 0.15s;"
3387
- data-action="{{^disabled}}toggle-item{{/disabled}}"
3388
- data-value="{{value}}"
3389
- data-index="{{index}}"
3390
- {{#disabled}}data-disabled="true"{{/disabled}}>
3391
- <i class="bi {{#isSelected}}bi-check-square-fill text-primary{{/isSelected}}{{^isSelected}}bi-square{{/isSelected}} me-2"
3392
- style="font-size: 1.25rem;"></i>
3393
- <span {{#disabled}}class="text-muted"{{/disabled}}>{{label}}</span>
3394
- </div>
3395
- {{/items}}
3396
- </div>
3397
-
3398
- {{#showSelectAll}}
3399
- <div class="mt-2">
3400
- <button type="button" class="btn btn-sm btn-outline-secondary me-2" data-action="select-all">
3401
- Select All
3402
- </button>
3403
- <button type="button" class="btn btn-sm btn-outline-secondary" data-action="deselect-all">
3404
- Deselect All
3405
- </button>
3406
- </div>
3407
- {{/showSelectAll}}
3408
- {{/items.length}}
3409
-
3410
- {{^items.length}}
3411
- <div class="text-muted text-center py-3 border rounded">
3412
- No items available
3413
- </div>
3414
- {{/^items.length}}
3415
- {{/loading}}
3485
+
3486
+ <div class="collection-multiselect-search-container"></div>
3487
+ <div class="collection-multiselect-list-container"></div>
3416
3488
 
3417
3489
  {{#help}}
3418
3490
  <div class="form-text">{{help}}</div>
@@ -3431,11 +3503,13 @@ class CollectionMultiSelectView extends View {
3431
3503
  this.required = options.required || false;
3432
3504
  this.disabled = options.disabled || false;
3433
3505
  this.collection = options.collection;
3434
- this.collectionParams = options.collectionParams || {};
3435
- this.defaultParams = options.defaultParams || null;
3436
3506
  this.labelField = options.labelField || "name";
3437
3507
  this.valueField = options.valueField || "id";
3438
3508
  this.excludeIds = options.excludeIds || [];
3509
+ this.ignoreIds = options.ignoreIds || [];
3510
+ this.collectionParams = options.collectionParams || {};
3511
+ this.defaultParamsOption = options.defaultParams || null;
3512
+ this.baseParams = {};
3439
3513
  this.requiresActiveGroup = options.requiresActiveGroup || false;
3440
3514
  this.size = options.size || 8;
3441
3515
  this.maxHeight = options.maxHeight || this.size * 42;
@@ -3446,10 +3520,8 @@ class CollectionMultiSelectView extends View {
3446
3520
  this.selectedValues = Array.isArray(options.value) ? options.value : [];
3447
3521
  this.loading = false;
3448
3522
  this.items = [];
3449
- this.lastClickedIndex = -1;
3450
- this.fieldId = options.fieldId || `field_${this.name}`;
3451
- this.searchValue = "";
3452
- this.searchTimer = null;
3523
+ this.searchView = null;
3524
+ this.listView = null;
3453
3525
  }
3454
3526
  onInit() {
3455
3527
  if (this.collection) {
@@ -3457,224 +3529,220 @@ class CollectionMultiSelectView extends View {
3457
3529
  }
3458
3530
  }
3459
3531
  setupCollection() {
3460
- if (!this.collection) {
3461
- console.warn("CollectionMultiSelect: No collection provided");
3462
- return;
3463
- }
3464
- if (this.collectionParams && Object.keys(this.collectionParams).length > 0) {
3465
- this.collection.params = { ...this.collection.params, ...this.collectionParams };
3532
+ this.baseParams = { ...this.collection.params };
3533
+ if (Object.keys(this.collectionParams).length > 0) {
3534
+ Object.assign(this.baseParams, this.collectionParams);
3535
+ Object.assign(this.collection.params, this.collectionParams);
3466
3536
  }
3467
- if (this.defaultParams) {
3468
- const extraParams = typeof this.defaultParams === "function" ? this.defaultParams() : this.defaultParams;
3469
- if (extraParams && typeof extraParams === "object") {
3470
- this.collection.params = { ...this.collection.params, ...extraParams };
3537
+ if (this.defaultParamsOption) {
3538
+ const extraParams = typeof this.defaultParamsOption === "function" ? this.defaultParamsOption() : this.defaultParamsOption;
3539
+ if (extraParams) {
3540
+ Object.assign(this.baseParams, extraParams);
3541
+ Object.assign(this.collection.params, extraParams);
3471
3542
  }
3472
3543
  }
3473
3544
  if (this.requiresActiveGroup) {
3474
3545
  const app = this.getApp();
3475
- if (app && app.activeGroup && app.activeGroup.id) {
3546
+ if (app?.activeGroup?.id) {
3547
+ this.baseParams.group = app.activeGroup.id;
3476
3548
  this.collection.params.group = app.activeGroup.id;
3477
3549
  }
3478
3550
  }
3479
3551
  this.collection.on("fetch:start", () => {
3480
3552
  this.loading = true;
3481
- this.render(false);
3553
+ this.updateListView();
3482
3554
  });
3483
3555
  this.collection.on("fetch:end", () => {
3484
3556
  this.loading = false;
3485
- this.updateItems();
3486
- this.render(false);
3557
+ this.buildItems();
3558
+ this.updateListView();
3487
3559
  });
3488
3560
  if (!this.collection.isEmpty()) {
3489
- this.updateItems();
3561
+ this.buildItems();
3490
3562
  }
3491
3563
  }
3492
- onAfterMount() {
3493
- if (this.collection && this.collection.isEmpty()) {
3564
+ async onAfterRender() {
3565
+ await super.onAfterRender();
3566
+ if (this.enableSearch) {
3567
+ this.createSearchView();
3568
+ }
3569
+ this.createListView();
3570
+ if (this.collection?.isEmpty()) {
3494
3571
  this.collection.fetch();
3495
3572
  }
3496
3573
  }
3497
- /**
3498
- * Update items array from collection
3499
- */
3500
- updateItems() {
3501
- const filteredModels = this.collection.models.filter((model) => {
3502
- const modelId = this.getFieldValue(model, this.valueField);
3503
- return !this.excludeIds.some((id) => id == modelId);
3574
+ createSearchView() {
3575
+ const container = this.element?.querySelector(".collection-multiselect-search-container");
3576
+ if (!container) return;
3577
+ this.searchView = new SearchView({
3578
+ placeholder: this.searchPlaceholder,
3579
+ debounce: this.searchDebounce
3504
3580
  });
3505
- this.items = filteredModels.map((model, index) => {
3506
- const labelValue = this.getFieldValue(model, this.labelField);
3507
- const fieldValue = this.getFieldValue(model, this.valueField);
3508
- return {
3509
- label: labelValue,
3510
- value: fieldValue,
3511
- index,
3512
- isSelected: this.selectedValues.some((v) => v == fieldValue),
3513
- disabled: this.disabled
3514
- };
3581
+ this.searchView.on("search", (searchValue) => {
3582
+ this.handleSearch(searchValue);
3583
+ });
3584
+ this.searchView.render(true, container);
3585
+ }
3586
+ createListView() {
3587
+ const container = this.element?.querySelector(".collection-multiselect-list-container");
3588
+ if (!container) return;
3589
+ const selectedCount = this.selectedValues.length;
3590
+ const totalCount = this.items.length;
3591
+ const unselectedCount = totalCount - selectedCount;
3592
+ this.listView = new ListItemsView({
3593
+ items: this.items,
3594
+ loading: this.loading,
3595
+ maxHeight: this.maxHeight,
3596
+ showSelectAll: this.showSelectAll,
3597
+ selectedCount,
3598
+ totalCount,
3599
+ unselectedCount,
3600
+ allSelected: selectedCount === totalCount && totalCount > 0,
3601
+ noneSelected: selectedCount === 0
3602
+ });
3603
+ this.listView.on("toggle", (data) => {
3604
+ this.handleToggle(data);
3605
+ });
3606
+ this.listView.on("select-all", () => {
3607
+ this.selectAll();
3515
3608
  });
3609
+ this.listView.on("deselect-all", () => {
3610
+ this.deselectAll();
3611
+ });
3612
+ this.listView.render(true, container);
3613
+ }
3614
+ updateListView() {
3615
+ if (this.listView) {
3616
+ const selectedCount = this.selectedValues.length;
3617
+ const totalCount = this.items.length;
3618
+ const unselectedCount = totalCount - selectedCount;
3619
+ this.listView.updateState({
3620
+ items: this.items,
3621
+ loading: this.loading,
3622
+ selectedCount,
3623
+ totalCount,
3624
+ unselectedCount,
3625
+ allSelected: selectedCount === totalCount && totalCount > 0,
3626
+ noneSelected: selectedCount === 0
3627
+ });
3628
+ this.listView.render(false);
3629
+ }
3516
3630
  }
3517
- /**
3518
- * Get field value from model or object, supporting dot notation
3519
- */
3520
- getFieldValue(item, fieldPath) {
3521
- if (!item || !fieldPath) return void 0;
3631
+ // Build items array from collection
3632
+ buildItems() {
3633
+ const models = this.collection.models.filter((model) => {
3634
+ const id = this.getFieldValue(model, this.valueField);
3635
+ if (id == null) return false;
3636
+ if (this.excludeIds.includes(id)) return false;
3637
+ if (this.ignoreIds.some((ignoreId) => ignoreId == id)) return false;
3638
+ return true;
3639
+ });
3640
+ this.items = models.map((model, index) => ({
3641
+ label: this.getFieldValue(model, this.labelField),
3642
+ value: this.getFieldValue(model, this.valueField),
3643
+ index,
3644
+ selected: this.selectedValues.some((v) => v == this.getFieldValue(model, this.valueField)),
3645
+ disabled: this.disabled
3646
+ }));
3647
+ }
3648
+ // Get field value (supports dot notation)
3649
+ getFieldValue(item, field) {
3650
+ if (!item || !field) return void 0;
3522
3651
  if (typeof item.get === "function") {
3523
- const value = item.get(fieldPath);
3524
- if (value === void 0 && fieldPath.includes(".")) {
3525
- return MOJOUtils.getNestedValue(item, fieldPath);
3526
- }
3527
- return value;
3652
+ return item.get(field) ?? MOJOUtils.getNestedValue(item, field);
3528
3653
  }
3529
- return MOJOUtils.getNestedValue(item, fieldPath);
3654
+ return MOJOUtils.getNestedValue(item, field);
3530
3655
  }
3531
- /**
3532
- * Handle item toggle with shift-click range selection support
3533
- */
3534
- handleActionToggleItem(event, element) {
3535
- const value = element.getAttribute("data-value");
3536
- const clickedIndex = parseInt(element.getAttribute("data-index"), 10);
3537
- const numValue = Number(value);
3538
- const typedValue = !isNaN(numValue) && String(numValue) === value ? numValue : value;
3539
- if (event.shiftKey && this.lastClickedIndex !== -1 && this.lastClickedIndex !== clickedIndex) {
3540
- const isCurrentlySelected = this.selectedValues.some((v) => v == typedValue);
3541
- const shouldSelect = !isCurrentlySelected;
3542
- const start = Math.min(this.lastClickedIndex, clickedIndex);
3543
- const end = Math.max(this.lastClickedIndex, clickedIndex);
3656
+ // Handle search
3657
+ handleSearch(searchValue) {
3658
+ const params = { ...this.baseParams };
3659
+ if (searchValue) {
3660
+ params.search = searchValue;
3661
+ }
3662
+ this.collection.updateParams(params, true);
3663
+ }
3664
+ // Handle item toggle
3665
+ handleToggle({ value, index, shiftKey }) {
3666
+ if (shiftKey && this.listView.lastClickedIndex >= 0) {
3667
+ const start = Math.min(this.listView.lastClickedIndex, index);
3668
+ const end = Math.max(this.listView.lastClickedIndex, index);
3669
+ const shouldSelect = !this.items[index].selected;
3544
3670
  for (let i = start; i <= end; i++) {
3545
3671
  const item = this.items[i];
3546
- if (item && !item.disabled) {
3547
- const itemNumValue = Number(item.value);
3548
- const itemTypedValue = !isNaN(itemNumValue) && String(itemNumValue) === String(item.value) ? itemNumValue : item.value;
3672
+ if (!item.disabled) {
3549
3673
  if (shouldSelect) {
3550
- if (!this.selectedValues.some((v) => v == itemTypedValue)) {
3551
- this.selectedValues.push(itemTypedValue);
3674
+ if (!this.selectedValues.includes(item.value)) {
3675
+ this.selectedValues.push(item.value);
3552
3676
  }
3553
- item.isSelected = true;
3554
3677
  } else {
3555
- this.selectedValues = this.selectedValues.filter((v) => v != itemTypedValue);
3556
- item.isSelected = false;
3678
+ this.selectedValues = this.selectedValues.filter((v) => v != item.value);
3557
3679
  }
3680
+ item.selected = shouldSelect;
3558
3681
  }
3559
3682
  }
3560
3683
  } else {
3561
- const isCurrentlySelected = this.selectedValues.some((v) => v == typedValue);
3562
- if (isCurrentlySelected) {
3563
- this.selectedValues = this.selectedValues.filter((v) => v != typedValue);
3684
+ const item = this.items[index];
3685
+ if (item.selected) {
3686
+ this.selectedValues = this.selectedValues.filter((v) => v != value);
3687
+ item.selected = false;
3564
3688
  } else {
3565
- this.selectedValues.push(typedValue);
3566
- }
3567
- const item = this.items.find((i) => i.value == value);
3568
- if (item) {
3569
- item.isSelected = !isCurrentlySelected;
3689
+ this.selectedValues.push(value);
3690
+ item.selected = true;
3570
3691
  }
3571
3692
  }
3572
- this.lastClickedIndex = clickedIndex;
3573
- this.render(false);
3574
- this.emit("change", {
3575
- value: this.selectedValues,
3576
- name: this.name
3577
- });
3693
+ this.updateListView();
3694
+ this.emit("change", { value: this.selectedValues, name: this.name });
3578
3695
  }
3579
- /**
3580
- * Select all items
3581
- */
3582
- async handleActionSelectAll(event, element) {
3583
- event.preventDefault();
3584
- this.selectedValues = this.items.filter((item) => !item.disabled).map((item) => item.value);
3585
- this.items.forEach((item) => {
3586
- if (!item.disabled) {
3587
- item.isSelected = true;
3588
- }
3589
- });
3590
- this.render(false);
3591
- this.emit("change", {
3592
- value: this.selectedValues,
3593
- name: this.name
3696
+ // Select all
3697
+ selectAll() {
3698
+ this.selectedValues = this.items.filter((i) => !i.disabled).map((i) => i.value);
3699
+ this.items.forEach((i) => {
3700
+ if (!i.disabled) i.selected = true;
3594
3701
  });
3702
+ this.updateListView();
3703
+ this.emit("change", { value: this.selectedValues, name: this.name });
3595
3704
  }
3596
- /**
3597
- * Deselect all items
3598
- */
3599
- async handleActionDeselectAll(event, element) {
3600
- event.preventDefault();
3705
+ // Deselect all
3706
+ deselectAll() {
3601
3707
  this.selectedValues = [];
3602
- this.items.forEach((item) => {
3603
- item.isSelected = false;
3604
- });
3605
- this.render(false);
3606
- this.emit("change", {
3607
- value: this.selectedValues,
3608
- name: this.name
3609
- });
3708
+ this.items.forEach((i) => i.selected = false);
3709
+ this.updateListView();
3710
+ this.emit("change", { value: this.selectedValues, name: this.name });
3610
3711
  }
3611
- /**
3612
- * Handle search input with debouncing
3613
- * Event handler for data-change-action="search-input"
3614
- */
3615
- async onChangeSearchInput(event, element) {
3616
- this.searchValue = element.value;
3617
- if (this.searchTimer) {
3618
- clearTimeout(this.searchTimer);
3712
+ async onBeforeDestroy() {
3713
+ await super.onBeforeDestroy();
3714
+ if (this.searchView) {
3715
+ this.searchView.destroy();
3619
3716
  }
3620
- this.searchTimer = setTimeout(() => {
3621
- this.performSearch();
3622
- }, this.searchDebounce);
3623
- }
3624
- /**
3625
- * Perform search on collection
3626
- */
3627
- async performSearch() {
3628
- if (!this.collection) return;
3629
- try {
3630
- const searchParams = { ...this.collection.params };
3631
- if (this.searchValue && this.searchValue.trim()) {
3632
- searchParams.search = this.searchValue.trim();
3633
- } else {
3634
- delete searchParams.search;
3635
- }
3636
- await this.collection.updateParams(searchParams, true);
3637
- } catch (error) {
3638
- console.error("Search error:", error);
3717
+ if (this.listView) {
3718
+ this.listView.destroy();
3639
3719
  }
3640
3720
  }
3641
- /**
3642
- * Get the current selected values
3643
- */
3721
+ // Public API
3644
3722
  getValue() {
3645
3723
  return this.selectedValues;
3646
3724
  }
3647
- /**
3648
- * Set the selected values
3649
- */
3650
3725
  setValue(values) {
3651
3726
  this.selectedValues = Array.isArray(values) ? values : [];
3652
- this.updateItems();
3653
- this.render();
3727
+ this.buildItems();
3728
+ this.updateListView();
3654
3729
  }
3655
- /**
3656
- * Set the excluded IDs
3657
- */
3658
3730
  setExcludeIds(ids) {
3659
3731
  this.excludeIds = Array.isArray(ids) ? ids : [];
3660
- this.updateItems();
3661
- this.render();
3732
+ this.buildItems();
3733
+ this.updateListView();
3734
+ }
3735
+ setIgnoreIds(ids) {
3736
+ this.ignoreIds = Array.isArray(ids) ? ids : [];
3737
+ this.buildItems();
3738
+ this.updateListView();
3662
3739
  }
3663
- /**
3664
- * Refresh the collection
3665
- */
3666
3740
  async refresh() {
3667
3741
  await this.collection.fetch();
3668
3742
  }
3669
- /**
3670
- * Get form value for form submission
3671
- */
3672
3743
  getFormValue() {
3673
3744
  return this.selectedValues;
3674
3745
  }
3675
- /**
3676
- * Set form value from form data
3677
- */
3678
3746
  setFormValue(value) {
3679
3747
  this.setValue(value);
3680
3748
  }
@@ -7402,4 +7470,4 @@ export {
7402
7470
  applyFileDropMixin as a,
7403
7471
  FormView$1 as b
7404
7472
  };
7405
- //# sourceMappingURL=FormView-B_nJKNfq.js.map
7473
+ //# sourceMappingURL=FormView-CQbR3S82.js.map