web-mojo 2.1.978 → 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-TprskwB8.js → ChatView-C1702ZPZ.js} +3 -3
  12. package/dist/chunks/{ChatView-TprskwB8.js.map → ChatView-C1702ZPZ.js.map} +1 -1
  13. package/dist/chunks/{ChatView-uTteoCA-.js → ChatView-CVZScWPz.js} +2 -2
  14. package/dist/chunks/{ChatView-uTteoCA-.js.map → ChatView-CVZScWPz.js.map} +1 -1
  15. package/dist/chunks/{Dialog-DxLUm896.js → Dialog-Be1EkdvX.js} +3 -3
  16. package/dist/chunks/{Dialog-DxLUm896.js.map → Dialog-Be1EkdvX.js.map} +1 -1
  17. package/dist/chunks/{Dialog-DZGFqslk.js → Dialog-YnhCC4C2.js} +2 -2
  18. package/dist/chunks/{Dialog-DZGFqslk.js.map → Dialog-YnhCC4C2.js.map} +1 -1
  19. package/dist/chunks/{FormView-CwSPMYzE.js → FormView-CQbR3S82.js} +278 -231
  20. package/dist/chunks/FormView-CQbR3S82.js.map +1 -0
  21. package/dist/chunks/{FormView-Tkuf0Sfh.js → FormView-DHz1ydYg.js} +2 -2
  22. package/dist/chunks/FormView-DHz1ydYg.js.map +1 -0
  23. package/dist/chunks/{MetricsMiniChartWidget-DUexek3e.js → MetricsMiniChartWidget-CHsOuS2O.js} +2 -2
  24. package/dist/chunks/{MetricsMiniChartWidget-DUexek3e.js.map → MetricsMiniChartWidget-CHsOuS2O.js.map} +1 -1
  25. package/dist/chunks/{MetricsMiniChartWidget-CtMyQWCr.js → MetricsMiniChartWidget-DMGjpLSU.js} +2 -2
  26. package/dist/chunks/{MetricsMiniChartWidget-CtMyQWCr.js.map → MetricsMiniChartWidget-DMGjpLSU.js.map} +1 -1
  27. package/dist/chunks/{PDFViewer-UqOOvvMW.js → PDFViewer-BN200UnI.js} +2 -2
  28. package/dist/chunks/{PDFViewer-UqOOvvMW.js.map → PDFViewer-BN200UnI.js.map} +1 -1
  29. package/dist/chunks/{PDFViewer-Cqy-VTh9.js → PDFViewer-BlWEqtY5.js} +2 -2
  30. package/dist/chunks/{PDFViewer-Cqy-VTh9.js.map → PDFViewer-BlWEqtY5.js.map} +1 -1
  31. package/dist/chunks/{TopNav-BoPFE5Yo.js → TopNav-DF8w5mgO.js} +2 -2
  32. package/dist/chunks/{TopNav-BoPFE5Yo.js.map → TopNav-DF8w5mgO.js.map} +1 -1
  33. package/dist/chunks/{TopNav-Tr_uef0g.js → TopNav-ueVUoXcv.js} +2 -2
  34. package/dist/chunks/{TopNav-Tr_uef0g.js.map → TopNav-ueVUoXcv.js.map} +1 -1
  35. package/dist/chunks/{WebApp-CBpWtagL.js → WebApp-gsWqZg8e.js} +13 -13
  36. package/dist/chunks/{WebApp-CBpWtagL.js.map → WebApp-gsWqZg8e.js.map} +1 -1
  37. package/dist/chunks/{WebApp-DWLey4KY.js → WebApp-m17riaNV.js} +2 -2
  38. package/dist/chunks/{WebApp-DWLey4KY.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-CwSPMYzE.js.map +0 -1
  49. package/dist/chunks/FormView-Tkuf0Sfh.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,57 +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 collection-multiselect-search"
3368
- placeholder="{{searchPlaceholder}}"
3369
- value="{{searchValue}}" />
3370
- {{/enableSearch}}
3371
-
3372
- {{#loading}}
3373
- <div class="text-center py-3">
3374
- <div class="spinner-border spinner-border-sm" role="status">
3375
- <span class="visually-hidden">Loading...</span>
3376
- </div>
3377
- </div>
3378
- {{/loading}}
3379
-
3380
- {{^loading}}
3381
- {{#items.length}}
3382
- <div class="collection-multiselect-list border rounded p-3" style="max-height: {{maxHeight}}px; overflow-y: auto; background: #fff;">
3383
- {{#items}}
3384
- <div class="d-flex align-items-center mb-2 py-1 px-2 rounded {{^disabled}}hover-bg{{/disabled}}"
3385
- style="cursor: {{^disabled}}pointer{{/disabled}}{{#disabled}}not-allowed{{/disabled}}; user-select: none; transition: background-color 0.15s;"
3386
- data-action="{{^disabled}}toggle-item{{/disabled}}"
3387
- data-value="{{value}}"
3388
- data-index="{{index}}"
3389
- {{#disabled}}data-disabled="true"{{/disabled}}>
3390
- <i class="bi {{#isSelected}}bi-check-square-fill text-primary{{/isSelected}}{{^isSelected}}bi-square{{/isSelected}} me-2"
3391
- style="font-size: 1.25rem;"></i>
3392
- <span {{#disabled}}class="text-muted"{{/disabled}}>{{label}}</span>
3393
- </div>
3394
- {{/items}}
3395
- </div>
3396
-
3397
- {{#showSelectAll}}
3398
- <div class="mt-2">
3399
- <button type="button" class="btn btn-sm btn-outline-secondary me-2" data-action="select-all">
3400
- Select All
3401
- </button>
3402
- <button type="button" class="btn btn-sm btn-outline-secondary" data-action="deselect-all">
3403
- Deselect All
3404
- </button>
3405
- </div>
3406
- {{/showSelectAll}}
3407
- {{/items.length}}
3408
-
3409
- {{^items.length}}
3410
- <div class="text-muted text-center py-3 border rounded">
3411
- No items available
3412
- </div>
3413
- {{/^items.length}}
3414
- {{/loading}}
3485
+
3486
+ <div class="collection-multiselect-search-container"></div>
3487
+ <div class="collection-multiselect-list-container"></div>
3415
3488
 
3416
3489
  {{#help}}
3417
3490
  <div class="form-text">{{help}}</div>
@@ -3430,12 +3503,13 @@ class CollectionMultiSelectView extends View {
3430
3503
  this.required = options.required || false;
3431
3504
  this.disabled = options.disabled || false;
3432
3505
  this.collection = options.collection;
3433
- this.collectionParams = options.collectionParams || {};
3434
- this.defaultParamsOption = options.defaultParams || null;
3435
- this.defaultParams = {};
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,11 +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;
3453
- this.handleSearchInput = this.handleSearchInput.bind(this);
3523
+ this.searchView = null;
3524
+ this.listView = null;
3454
3525
  }
3455
3526
  onInit() {
3456
3527
  if (this.collection) {
@@ -3458,244 +3529,220 @@ class CollectionMultiSelectView extends View {
3458
3529
  }
3459
3530
  }
3460
3531
  setupCollection() {
3461
- if (!this.collection) {
3462
- console.warn("CollectionMultiSelect: No collection provided");
3463
- return;
3464
- }
3465
- this.defaultParams = { ...this.collection.params };
3466
- if (this.collectionParams && Object.keys(this.collectionParams).length > 0) {
3467
- this.collection.params = { ...this.collection.params, ...this.collectionParams };
3468
- this.defaultParams = { ...this.defaultParams, ...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);
3469
3536
  }
3470
3537
  if (this.defaultParamsOption) {
3471
3538
  const extraParams = typeof this.defaultParamsOption === "function" ? this.defaultParamsOption() : this.defaultParamsOption;
3472
- if (extraParams && typeof extraParams === "object") {
3473
- this.collection.params = { ...this.collection.params, ...extraParams };
3474
- this.defaultParams = { ...this.defaultParams, ...extraParams };
3539
+ if (extraParams) {
3540
+ Object.assign(this.baseParams, extraParams);
3541
+ Object.assign(this.collection.params, extraParams);
3475
3542
  }
3476
3543
  }
3477
3544
  if (this.requiresActiveGroup) {
3478
3545
  const app = this.getApp();
3479
- if (app && app.activeGroup && app.activeGroup.id) {
3546
+ if (app?.activeGroup?.id) {
3547
+ this.baseParams.group = app.activeGroup.id;
3480
3548
  this.collection.params.group = app.activeGroup.id;
3481
- this.defaultParams.group = app.activeGroup.id;
3482
3549
  }
3483
3550
  }
3484
3551
  this.collection.on("fetch:start", () => {
3485
3552
  this.loading = true;
3486
- this.render(false);
3553
+ this.updateListView();
3487
3554
  });
3488
3555
  this.collection.on("fetch:end", () => {
3489
3556
  this.loading = false;
3490
- this.updateItems();
3491
- this.render(false);
3557
+ this.buildItems();
3558
+ this.updateListView();
3492
3559
  });
3493
3560
  if (!this.collection.isEmpty()) {
3494
- this.updateItems();
3561
+ this.buildItems();
3495
3562
  }
3496
3563
  }
3497
3564
  async onAfterRender() {
3498
3565
  await super.onAfterRender();
3499
3566
  if (this.enableSearch) {
3500
- const searchInput = this.element?.querySelector(".collection-multiselect-search");
3501
- if (searchInput) {
3502
- searchInput.addEventListener("input", this.handleSearchInput);
3503
- }
3567
+ this.createSearchView();
3504
3568
  }
3505
- if (this.collection && this.collection.isEmpty()) {
3569
+ this.createListView();
3570
+ if (this.collection?.isEmpty()) {
3506
3571
  this.collection.fetch();
3507
3572
  }
3508
3573
  }
3509
- async onBeforeDestroy() {
3510
- await super.onBeforeDestroy();
3511
- if (this.enableSearch) {
3512
- const searchInput = this.element?.querySelector(".collection-multiselect-search");
3513
- if (searchInput) {
3514
- searchInput.removeEventListener("input", this.handleSearchInput);
3515
- }
3516
- }
3517
- if (this.searchTimer) {
3518
- clearTimeout(this.searchTimer);
3519
- }
3520
- }
3521
- /**
3522
- * Update items array from collection
3523
- */
3524
- updateItems() {
3525
- const filteredModels = this.collection.models.filter((model) => {
3526
- const modelId = this.getFieldValue(model, this.valueField);
3527
- 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
3528
3580
  });
3529
- this.items = filteredModels.map((model, index) => {
3530
- const labelValue = this.getFieldValue(model, this.labelField);
3531
- const fieldValue = this.getFieldValue(model, this.valueField);
3532
- return {
3533
- label: labelValue,
3534
- value: fieldValue,
3535
- index,
3536
- isSelected: this.selectedValues.some((v) => v == fieldValue),
3537
- disabled: this.disabled
3538
- };
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();
3608
+ });
3609
+ this.listView.on("deselect-all", () => {
3610
+ this.deselectAll();
3539
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
+ }
3540
3630
  }
3541
- /**
3542
- * Get field value from model or object, supporting dot notation
3543
- */
3544
- getFieldValue(item, fieldPath) {
3545
- 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;
3546
3651
  if (typeof item.get === "function") {
3547
- const value = item.get(fieldPath);
3548
- if (value === void 0 && fieldPath.includes(".")) {
3549
- return MOJOUtils.getNestedValue(item, fieldPath);
3550
- }
3551
- return value;
3652
+ return item.get(field) ?? MOJOUtils.getNestedValue(item, field);
3552
3653
  }
3553
- return MOJOUtils.getNestedValue(item, fieldPath);
3654
+ return MOJOUtils.getNestedValue(item, field);
3554
3655
  }
3555
- /**
3556
- * Handle item toggle with shift-click range selection support
3557
- */
3558
- handleActionToggleItem(event, element) {
3559
- const value = element.getAttribute("data-value");
3560
- const clickedIndex = parseInt(element.getAttribute("data-index"), 10);
3561
- const numValue = Number(value);
3562
- const typedValue = !isNaN(numValue) && String(numValue) === value ? numValue : value;
3563
- if (event.shiftKey && this.lastClickedIndex !== -1 && this.lastClickedIndex !== clickedIndex) {
3564
- const isCurrentlySelected = this.selectedValues.some((v) => v == typedValue);
3565
- const shouldSelect = !isCurrentlySelected;
3566
- const start = Math.min(this.lastClickedIndex, clickedIndex);
3567
- 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;
3568
3670
  for (let i = start; i <= end; i++) {
3569
3671
  const item = this.items[i];
3570
- if (item && !item.disabled) {
3571
- const itemNumValue = Number(item.value);
3572
- const itemTypedValue = !isNaN(itemNumValue) && String(itemNumValue) === String(item.value) ? itemNumValue : item.value;
3672
+ if (!item.disabled) {
3573
3673
  if (shouldSelect) {
3574
- if (!this.selectedValues.some((v) => v == itemTypedValue)) {
3575
- this.selectedValues.push(itemTypedValue);
3674
+ if (!this.selectedValues.includes(item.value)) {
3675
+ this.selectedValues.push(item.value);
3576
3676
  }
3577
- item.isSelected = true;
3578
3677
  } else {
3579
- this.selectedValues = this.selectedValues.filter((v) => v != itemTypedValue);
3580
- item.isSelected = false;
3678
+ this.selectedValues = this.selectedValues.filter((v) => v != item.value);
3581
3679
  }
3680
+ item.selected = shouldSelect;
3582
3681
  }
3583
3682
  }
3584
3683
  } else {
3585
- const isCurrentlySelected = this.selectedValues.some((v) => v == typedValue);
3586
- if (isCurrentlySelected) {
3587
- 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;
3588
3688
  } else {
3589
- this.selectedValues.push(typedValue);
3590
- }
3591
- const item = this.items.find((i) => i.value == value);
3592
- if (item) {
3593
- item.isSelected = !isCurrentlySelected;
3689
+ this.selectedValues.push(value);
3690
+ item.selected = true;
3594
3691
  }
3595
3692
  }
3596
- this.lastClickedIndex = clickedIndex;
3597
- this.render(false);
3598
- this.emit("change", {
3599
- value: this.selectedValues,
3600
- name: this.name
3601
- });
3693
+ this.updateListView();
3694
+ this.emit("change", { value: this.selectedValues, name: this.name });
3602
3695
  }
3603
- /**
3604
- * Select all items
3605
- */
3606
- async handleActionSelectAll(event, element) {
3607
- event.preventDefault();
3608
- this.selectedValues = this.items.filter((item) => !item.disabled).map((item) => item.value);
3609
- this.items.forEach((item) => {
3610
- if (!item.disabled) {
3611
- item.isSelected = true;
3612
- }
3613
- });
3614
- this.render(false);
3615
- this.emit("change", {
3616
- value: this.selectedValues,
3617
- 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;
3618
3701
  });
3702
+ this.updateListView();
3703
+ this.emit("change", { value: this.selectedValues, name: this.name });
3619
3704
  }
3620
- /**
3621
- * Deselect all items
3622
- */
3623
- async handleActionDeselectAll(event, element) {
3624
- event.preventDefault();
3705
+ // Deselect all
3706
+ deselectAll() {
3625
3707
  this.selectedValues = [];
3626
- this.items.forEach((item) => {
3627
- item.isSelected = false;
3628
- });
3629
- this.render(false);
3630
- this.emit("change", {
3631
- value: this.selectedValues,
3632
- name: this.name
3633
- });
3708
+ this.items.forEach((i) => i.selected = false);
3709
+ this.updateListView();
3710
+ this.emit("change", { value: this.selectedValues, name: this.name });
3634
3711
  }
3635
- /**
3636
- * Handle search input with debouncing
3637
- */
3638
- handleSearchInput(event) {
3639
- this.searchValue = event.target.value;
3640
- if (this.searchTimer) {
3641
- clearTimeout(this.searchTimer);
3712
+ async onBeforeDestroy() {
3713
+ await super.onBeforeDestroy();
3714
+ if (this.searchView) {
3715
+ this.searchView.destroy();
3642
3716
  }
3643
- this.searchTimer = setTimeout(() => {
3644
- this.performSearch();
3645
- }, this.searchDebounce);
3646
- }
3647
- /**
3648
- * Perform search on collection
3649
- */
3650
- async performSearch() {
3651
- if (!this.collection) return;
3652
- try {
3653
- const searchParams = { ...this.defaultParams };
3654
- if (this.searchValue && this.searchValue.trim()) {
3655
- searchParams.search = this.searchValue.trim();
3656
- }
3657
- await this.collection.updateParams(searchParams, true);
3658
- } catch (error) {
3659
- console.error("Search error:", error);
3717
+ if (this.listView) {
3718
+ this.listView.destroy();
3660
3719
  }
3661
3720
  }
3662
- /**
3663
- * Get the current selected values
3664
- */
3721
+ // Public API
3665
3722
  getValue() {
3666
3723
  return this.selectedValues;
3667
3724
  }
3668
- /**
3669
- * Set the selected values
3670
- */
3671
3725
  setValue(values) {
3672
3726
  this.selectedValues = Array.isArray(values) ? values : [];
3673
- this.updateItems();
3674
- this.render();
3727
+ this.buildItems();
3728
+ this.updateListView();
3675
3729
  }
3676
- /**
3677
- * Set the excluded IDs
3678
- */
3679
3730
  setExcludeIds(ids) {
3680
3731
  this.excludeIds = Array.isArray(ids) ? ids : [];
3681
- this.updateItems();
3682
- 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();
3683
3739
  }
3684
- /**
3685
- * Refresh the collection
3686
- */
3687
3740
  async refresh() {
3688
3741
  await this.collection.fetch();
3689
3742
  }
3690
- /**
3691
- * Get form value for form submission
3692
- */
3693
3743
  getFormValue() {
3694
3744
  return this.selectedValues;
3695
3745
  }
3696
- /**
3697
- * Set form value from form data
3698
- */
3699
3746
  setFormValue(value) {
3700
3747
  this.setValue(value);
3701
3748
  }
@@ -7423,4 +7470,4 @@ export {
7423
7470
  applyFileDropMixin as a,
7424
7471
  FormView$1 as b
7425
7472
  };
7426
- //# sourceMappingURL=FormView-CwSPMYzE.js.map
7473
+ //# sourceMappingURL=FormView-CQbR3S82.js.map