@mono-lit/helper 0.0.8 → 0.0.10

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 (161) hide show
  1. package/dist/accordion-core-DaNyPWRr.js +277 -0
  2. package/dist/alert-core-DWtHbX_-.js +134 -0
  3. package/dist/breadcrumb-list-core-Dh68T8Cf.js +747 -0
  4. package/dist/{mono-button-CLkHg3WW.js → button-core-DerXg84Q.js} +3 -276
  5. package/dist/button-dropdown-core-DKYEOyjy.js +654 -0
  6. package/dist/button-utils-D5-66M02.js +63 -0
  7. package/dist/card-utils-l80qAmrN.js +312 -0
  8. package/dist/chart-core-DV7hD3ZY.js +801 -0
  9. package/dist/checkbox-utils-DKdrhAzF.js +337 -0
  10. package/dist/chip-utils-DpRrd7Zj.js +403 -0
  11. package/dist/{data-source-controller-C6C4ej_M.js → data-source-controller-DS_JLrmS.js} +1 -1
  12. package/dist/{data-source-options-fxT5QIX4.js → data-source-options-DJUNU26C.js} +6 -6
  13. package/dist/{data-source-read-BL266IW0.js → data-source-read-uKJpRAzx.js} +2 -2
  14. package/dist/date-core-CyuSyvvG.js +734 -0
  15. package/dist/drawer-core-DbFWvNln.js +759 -0
  16. package/dist/dropdown-core-BCH1pK14.js +511 -0
  17. package/dist/dropdown-table-core-SfHUJVFq.js +1342 -0
  18. package/dist/export.js +1 -1
  19. package/dist/{field-path-BabiMrrA.js → field-path-DK2VBWHl.js} +1 -1
  20. package/dist/field-tooltip.css_raw-DVblekCl.js +5 -0
  21. package/dist/{field-validation.css_raw-Cx6SGrfP.js → field-validation.css_raw-BU7C6173.js} +1 -170
  22. package/dist/file-upload-core-Cz_dBQMx.js +624 -0
  23. package/dist/filter-builder-core-DyWjbBP7.js +381 -0
  24. package/dist/{filter-builder-B6Y2mmbM.js → filter-builder-vbqIuPhX.js} +1 -1
  25. package/dist/{filter-eval-ChDSaAUH.js → filter-eval-CqeBnMYh.js} +1 -1
  26. package/dist/{filter-odata-Bi27XUpQ.js → filter-odata-GsczYKNC.js} +1 -1
  27. package/dist/{hydration-flush-BaE9gN3C.js → hydration-flush-Volt9X7Q.js} +2 -1071
  28. package/dist/index.js +11 -11
  29. package/dist/{index.node-CLqE8F8P.js → index.node-Csy9zrr1.js} +4 -4
  30. package/dist/index.node.js +11 -11
  31. package/dist/input-utils-BglY-k0H.js +1145 -0
  32. package/dist/menu-core-DkAYuCZ2.js +831 -0
  33. package/dist/modal-core-CSBSPN_m.js +844 -0
  34. package/dist/mono-button-DVvZ03P-.js +280 -0
  35. package/dist/{mono-button.shadow-DqZMpcqY.js → mono-button.shadow-BANxMGln.js} +6 -594
  36. package/dist/{mono-data-chart-NKPdAgVq.js → mono-data-chart-ChF4J9RT.js} +6 -6
  37. package/dist/{mono-data-dropdown-DUXo_jxd.js → mono-data-dropdown-Bgj2PDfm.js} +1 -1
  38. package/dist/{mono-data-grid-Bb00QM72.js → mono-data-grid-DJkp96N-.js} +346 -51
  39. package/dist/{mono-event-BPku9HpS.js → mono-event-CAZf0F_k.js} +14 -9
  40. package/dist/{mono-form-controller-BrA10erm.js → mono-form-controller-DxZLvyg6.js} +2 -1
  41. package/dist/mono-table-checkbox-core-BKOMx8R5.js +5288 -0
  42. package/dist/nav-core-B5qU2dzn.js +225 -0
  43. package/dist/{normalize-error-D93O4q8g.js → normalize-error-BEcd1tmS.js} +2 -2
  44. package/dist/otp-core-DXg3vFLh.js +758 -0
  45. package/dist/radio-utils-Dk9Tl1jz.js +319 -0
  46. package/dist/rich-text-editor-core-Ddd_QaLn.js +1280 -0
  47. package/dist/select-utils-BgArYHk8.js +2140 -0
  48. package/dist/sidebar-core-CD6txDo3.js +583 -0
  49. package/dist/slider-core-vcWr321-.js +1014 -0
  50. package/dist/src/components/dropdown-table/dropdown-table-core.d.ts +2 -2
  51. package/dist/src/components/dropdown-table/dropdown-table-types.d.ts +1 -1
  52. package/dist/src/components/dropdown-table/index.d.ts +1 -1
  53. package/dist/src/components/dropdown-table/index.shadow.d.ts +1 -1
  54. package/dist/src/components/dropdown-table/mono-data-dropdown.d.ts +1 -1
  55. package/dist/src/components/form/form-types.d.ts +9 -3
  56. package/dist/src/components/input/input-core.d.ts +1 -1
  57. package/dist/src/components/input/input-types.d.ts +1 -1
  58. package/dist/src/components/otp/otp-core.d.ts +1 -1
  59. package/dist/src/components/select/select-core.d.ts +1 -1
  60. package/dist/src/components/select/select-types.d.ts +1 -1
  61. package/dist/src/components/slider/slider-core.d.ts +1 -1
  62. package/dist/src/components/slider/slider-types.d.ts +1 -1
  63. package/dist/src/components/table/filter-suggestion.d.ts +171 -0
  64. package/dist/src/components/table/index.d.ts +5 -4
  65. package/dist/src/components/table/index.shadow.d.ts +5 -4
  66. package/dist/src/components/table/mono-data-grid.d.ts +58 -3
  67. package/dist/src/components/table/mono-table-empty-core.d.ts +37 -0
  68. package/dist/src/components/table/mono-table-search-core.d.ts +22 -3
  69. package/dist/src/components/table/table-types.d.ts +74 -4
  70. package/dist/src/components/tag-input/tag-input-core.d.ts +1 -1
  71. package/dist/src/components/tag-input/tag-input-types.d.ts +1 -1
  72. package/dist/src/components/textarea/textarea-core.d.ts +1 -1
  73. package/dist/src/composables/mono-event.d.ts +7 -1
  74. package/dist/src/entries/index.d.ts +8 -6
  75. package/dist/src/entries/index.node.d.ts +8 -6
  76. package/dist/src/search/index.d.ts +1 -1
  77. package/dist/src/utils/group-count.d.ts +36 -0
  78. package/dist/switch-utils-CTZ4id2V.js +338 -0
  79. package/dist/tabs-core-r5-B8k_N.js +317 -0
  80. package/dist/tag-input-utils-D2JA90DQ.js +3060 -0
  81. package/dist/textarea-utils-VU1KeXm8.js +821 -0
  82. package/dist/ui/accordion.js +2 -274
  83. package/dist/ui/alert.js +2 -131
  84. package/dist/ui/breadcrumb.js +4 -745
  85. package/dist/ui/button-dropdown.js +4 -652
  86. package/dist/ui/button.js +2 -63
  87. package/dist/ui/card.js +2 -310
  88. package/dist/ui/chart.js +4 -800
  89. package/dist/ui/checkbox.js +4 -335
  90. package/dist/ui/chip.js +4 -402
  91. package/dist/ui/date.js +3 -732
  92. package/dist/ui/drawer.js +3 -757
  93. package/dist/ui/dropdown-table.js +5 -1341
  94. package/dist/ui/dropdown.js +4 -509
  95. package/dist/ui/file-upload.js +3 -622
  96. package/dist/ui/filter.js +5 -380
  97. package/dist/ui/form.js +1 -1
  98. package/dist/ui/index.css +130 -5
  99. package/dist/ui/input.js +3 -1141
  100. package/dist/ui/menu.js +4 -828
  101. package/dist/ui/modal.js +4 -843
  102. package/dist/ui/nav.js +4 -223
  103. package/dist/ui/otp.js +4 -756
  104. package/dist/ui/radio.js +4 -317
  105. package/dist/ui/rich-text-editor.js +4 -1278
  106. package/dist/ui/select.js +5 -2138
  107. package/dist/ui/shadow/accordion.js +4 -273
  108. package/dist/ui/shadow/alert.js +4 -130
  109. package/dist/ui/shadow/breadcrumb.js +5 -744
  110. package/dist/ui/shadow/button-dropdown.js +6 -652
  111. package/dist/ui/shadow/button.js +3 -63
  112. package/dist/ui/shadow/card.js +4 -309
  113. package/dist/ui/shadow/chart.js +6 -1576
  114. package/dist/ui/shadow/checkbox.js +4 -334
  115. package/dist/ui/shadow/chip.js +4 -396
  116. package/dist/ui/shadow/date.js +7 -731
  117. package/dist/ui/shadow/drawer.js +4 -756
  118. package/dist/ui/shadow/dropdown-table.js +8 -1762
  119. package/dist/ui/shadow/dropdown.js +4 -508
  120. package/dist/ui/shadow/file-upload.js +4 -620
  121. package/dist/ui/shadow/filter.js +7 -379
  122. package/dist/ui/shadow/input.js +6 -1140
  123. package/dist/ui/shadow/menu.js +5 -828
  124. package/dist/ui/shadow/modal.js +6 -1063
  125. package/dist/ui/shadow/nav.js +5 -223
  126. package/dist/ui/shadow/otp.js +6 -754
  127. package/dist/ui/shadow/radio.js +4 -316
  128. package/dist/ui/shadow/rich-text-editor.js +4 -1276
  129. package/dist/ui/shadow/select.js +6 -2136
  130. package/dist/ui/shadow/sidebar.js +5 -581
  131. package/dist/ui/shadow/slider.js +5 -1010
  132. package/dist/ui/shadow/switch.js +4 -335
  133. package/dist/ui/shadow/table.js +10 -4501
  134. package/dist/ui/shadow/tabs.js +6 -315
  135. package/dist/ui/shadow/tag-input.js +7 -3057
  136. package/dist/ui/shadow/textarea.js +6 -817
  137. package/dist/ui/sidebar.js +3 -581
  138. package/dist/ui/slider.js +4 -1012
  139. package/dist/ui/switch.js +4 -336
  140. package/dist/ui/table.js +9 -4502
  141. package/dist/ui/tabs.js +4 -315
  142. package/dist/ui/tag-input.js +5 -3058
  143. package/dist/ui/textarea.js +4 -819
  144. package/dist/vue.d.ts +3 -2
  145. package/package.json +3 -3
  146. package/dist/chip-strip-bNfLn52Z.js +0 -215
  147. package/dist/data-source-controller-Dx6IQ2CN.js +0 -243
  148. package/dist/data-source-options-BM4r4PRw.js +0 -558
  149. package/dist/data-source-read-HyBCRg1t.js +0 -242
  150. package/dist/excel-BXzr3uI1.js +0 -784
  151. package/dist/export-ixRdCS2y.js +0 -2388
  152. package/dist/field-tooltip-addon-CWCp19mJ.js +0 -702
  153. package/dist/field-tooltip.css_raw-U5UeTa2d.js +0 -269
  154. package/dist/filter-builder-C0T3pMx2.js +0 -208
  155. package/dist/form-control-core-BbiACMtL.js +0 -226
  156. package/dist/icon-ClxnYhBG.js +0 -19
  157. package/dist/import-Dc4eXC02.js +0 -612
  158. package/dist/light-slots-_no0r2Z-.js +0 -246
  159. package/dist/markdown-uGlE_OfJ.js +0 -20191
  160. package/dist/mono-data-grid-Bkr-e1-i.js +0 -4043
  161. package/dist/normalize-error-BmLbgANw.js +0 -1048
@@ -1,9 +1,9 @@
1
- import { n as isPath, t as getFieldValue } from "./field-path-BabiMrrA.js";
2
- import { r as readAllRows } from "./data-source-read-BL266IW0.js";
3
- import { n as andPredicates, r as compileFilterPredicate, t as andFilters } from "./filter-eval-ChDSaAUH.js";
4
- import { n as describeError, o as isCanceled } from "./normalize-error-D93O4q8g.js";
5
- import { a as resolveDataSourceOptions, d as createApplyGate, f as isRolledUp, h as monoArraySource, i as normalizeSortList, n as extraLoadOptions, o as toList, p as loadApply, r as mergeDataSourceOptions, u as summaryFilterOf } from "./data-source-options-fxT5QIX4.js";
6
- import { t as arrayToODataString } from "./filter-odata-Bi27XUpQ.js";
1
+ import { n as isPath, t as getFieldValue } from "./field-path-DK2VBWHl.js";
2
+ import { r as readAllRows } from "./data-source-read-uKJpRAzx.js";
3
+ import { n as andPredicates, r as compileFilterPredicate, t as andFilters } from "./filter-eval-CqeBnMYh.js";
4
+ import { n as describeError, o as isCanceled } from "./normalize-error-BEcd1tmS.js";
5
+ import { _ as monoArraySource, a as resolveDataSourceOptions, d as createApplyGate, f as isRolledUp, i as normalizeSortList, n as extraLoadOptions, o as toList, p as loadApply, r as mergeDataSourceOptions, u as summaryFilterOf } from "./data-source-options-DJUNU26C.js";
6
+ import { t as arrayToODataString } from "./filter-odata-GsczYKNC.js";
7
7
  import { t as createNotifier } from "./notifier-BIrqUzRh.js";
8
8
 
9
9
  //#region src/components/chart/chart-odata.ts
@@ -1,4 +1,4 @@
1
- import { t as monoDataGrid } from "./mono-data-grid-Bb00QM72.js";
1
+ import { t as monoDataGrid } from "./mono-data-grid-DJkp96N-.js";
2
2
  import { t as createNotifier } from "./notifier-BIrqUzRh.js";
3
3
 
4
4
  //#region src/components/dropdown-table/mono-data-dropdown.ts
@@ -1,12 +1,12 @@
1
- import { a as parseFieldPath, c as toODataClause, l as toODataSelector, n as isPath, o as projectFields, r as mergePatch, s as setFieldValue, t as getFieldValue } from "./field-path-BabiMrrA.js";
2
- import { a as buildGroups, c as isGroupNode, i as searchFilterOf, o as collectGroupPaths, r as readAllRows, s as flattenLeaves } from "./data-source-read-BL266IW0.js";
3
- import { i as joinFilters, n as andPredicates, r as compileFilterPredicate, t as andFilters } from "./filter-eval-ChDSaAUH.js";
4
- import { A as resolveSearchEntries, C as customRemoteClause, E as hasWildcardSearch, S as customPredicate, T as hasCustomSearch, h as mergeSearchFields, j as searchEntryFor, k as plainSearchColumns, n as describeError, o as isCanceled, u as DEFAULT_SEARCH_FIELDS } from "./normalize-error-D93O4q8g.js";
5
- import { a as resolveDataSourceOptions, c as composeSummaryApply, d as createApplyGate, f as isRolledUp, h as monoArraySource, i as normalizeSortList, l as summaryAliases, m as storeRows, n as extraLoadOptions, o as toList, p as loadApply, s as buildSummaryApply, t as dataSourceOptionsKey, u as summaryFilterOf } from "./data-source-options-fxT5QIX4.js";
1
+ import { a as parseFieldPath, c as toODataClause, l as toODataSelector, n as isPath, o as projectFields, r as mergePatch, s as setFieldValue, t as getFieldValue } from "./field-path-DK2VBWHl.js";
2
+ import { a as buildGroups, c as isGroupNode, i as searchFilterOf, o as collectGroupPaths, r as readAllRows, s as flattenLeaves } from "./data-source-read-uKJpRAzx.js";
3
+ import { i as joinFilters, n as andPredicates, r as compileFilterPredicate, t as andFilters } from "./filter-eval-CqeBnMYh.js";
4
+ import { A as resolveSearchEntries, C as customRemoteClause, E as hasWildcardSearch, S as customPredicate, T as hasCustomSearch, h as mergeSearchFields, j as searchEntryFor, k as plainSearchColumns, n as describeError, o as isCanceled, u as DEFAULT_SEARCH_FIELDS } from "./normalize-error-BEcd1tmS.js";
5
+ import { _ as monoArraySource, a as resolveDataSourceOptions, c as composeSummaryApply, d as createApplyGate, f as isRolledUp, g as storeRows, i as normalizeSortList, l as summaryAliases, n as extraLoadOptions, o as toList, p as loadApply, s as buildSummaryApply, t as dataSourceOptionsKey, u as summaryFilterOf } from "./data-source-options-DJUNU26C.js";
6
6
  import { n as unwrapReactive } from "./reactive-Dtd-esHO.js";
7
- import { t as arrayToODataString } from "./filter-odata-Bi27XUpQ.js";
7
+ import { t as arrayToODataString } from "./filter-odata-GsczYKNC.js";
8
8
  import { t as createNotifier } from "./notifier-BIrqUzRh.js";
9
- import { t as monoFilterBuilder } from "./filter-builder-C0T3pMx2.js";
9
+ import { t as monoFilterBuilder } from "./filter-builder-vbqIuPhX.js";
10
10
 
11
11
  //#region src/components/table/store-group-source.ts
12
12
  /**
@@ -377,6 +377,114 @@ function inRange(d, r) {
377
377
  return t >= r.from.getTime() && t < r.to.getTime();
378
378
  }
379
379
 
380
+ //#endregion
381
+ //#region src/utils/group-count.ts
382
+ /**
383
+ * Per-value row counts for ONE field, as `{ value, count }` rows.
384
+ *
385
+ * Two consumers share this: the grid's header filter (`distinctValues`) and the
386
+ * table search's filter suggestion (`components/table/filter-suggestion.ts`),
387
+ * which asks "how many rows match this search under each OTHER value of Dept".
388
+ *
389
+ * Remote: one `$apply=filter(…)/groupby((field),aggregate($count as count))`
390
+ * through the store (see `data-source-apply.ts` for why it rides `urlOverride`).
391
+ * Array: a plain tally over the rows.
392
+ */
393
+ /**
394
+ * Group-count `field` through `store` with ONE `$apply`, or `null` when that path
395
+ * is not available — the gate is off, a wildcard path (nothing to group by), a
396
+ * store that cannot carry an `$apply` (a CustomStore), a failed request (reported
397
+ * to the gate), or a response that is not rolled up (a server that ignored the
398
+ * clause). An EMPTY grouped result is a real answer and comes back as `[]`.
399
+ *
400
+ * The rows are returned in server order — the caller sorts.
401
+ */
402
+ async function groupCountViaApply(store, field, filter, gate, options = {}) {
403
+ const rows = await groupCountsViaApply(store, [field], filter, gate, options);
404
+ return rows ? rows.map((r) => ({
405
+ value: r.values[field],
406
+ count: r.count
407
+ })) : null;
408
+ }
409
+ /**
410
+ * {@link groupCountViaApply} over SEVERAL fields at once — one
411
+ * `groupby((A,B),aggregate($count as count))` request, one row per combination
412
+ * that exists. Same `null` contract.
413
+ */
414
+ async function groupCountsViaApply(store, fields, filter, gate, options = {}) {
415
+ if (gate.skip || !fields.length) return null;
416
+ const selectors = [];
417
+ for (const field of fields) {
418
+ if (parseFieldPath(field).hasWildcard) return null;
419
+ const selector = isPath(field) ? toODataSelector(field) : field;
420
+ if (!selector) return null;
421
+ selectors.push(selector);
422
+ }
423
+ const apply = `groupby((${selectors.join(",")}),aggregate($count as count))`;
424
+ const odataFilter = filter != null ? arrayToODataString(filter) : "";
425
+ const clause = odataFilter ? `filter(${odataFilter})/${apply}` : apply;
426
+ const top = typeof options.top === "number" && options.top >= 0 ? options.top : void 0;
427
+ let rows;
428
+ try {
429
+ rows = await loadApply(store, clause, { top });
430
+ } catch (err) {
431
+ gate.reject(err);
432
+ return null;
433
+ }
434
+ if (!rows) return null;
435
+ if (!rows.length) return [];
436
+ const first = rows[0];
437
+ if (!first || typeof first !== "object" || !isCount(first.count)) return null;
438
+ if (!isRolledUp(rows, [...fields, "count"])) return null;
439
+ return rows.map((r) => ({
440
+ values: pickValues(r, fields),
441
+ count: Number(r.count) || 0
442
+ }));
443
+ }
444
+ /** Each field's value off a row, path-aware. */
445
+ function pickValues(row, fields) {
446
+ const out = {};
447
+ for (const f of fields) out[f] = isPath(f) ? getFieldValue(row, f) : row?.[f];
448
+ return out;
449
+ }
450
+ /** {@link countValues} over several fields: one tuple per combination, with its row count. */
451
+ function countTuples(rows, fields) {
452
+ const by = /* @__PURE__ */ new Map();
453
+ for (const r of rows) {
454
+ const values = pickValues(r, fields);
455
+ const key = JSON.stringify(fields.map((f) => values[f] ?? null));
456
+ const hit = by.get(key);
457
+ if (hit) hit.count++;
458
+ else by.set(key, {
459
+ values,
460
+ count: 1
461
+ });
462
+ }
463
+ return [...by.values()];
464
+ }
465
+ /** A number, or a string that is one (`"12"`). */
466
+ function isCount(v) {
467
+ if (typeof v === "number") return Number.isFinite(v);
468
+ return typeof v === "string" && v.trim() !== "" && Number.isFinite(Number(v));
469
+ }
470
+ /** Count occurrences of `field` across `rows` (path-aware; a wildcard path flattens). */
471
+ function countValues(rows, field) {
472
+ const counts = /* @__PURE__ */ new Map();
473
+ const bump = (v) => {
474
+ counts.set(v, (counts.get(v) ?? 0) + 1);
475
+ };
476
+ const path = isPath(field);
477
+ for (const r of rows) if (path) {
478
+ const v = getFieldValue(r, field);
479
+ if (Array.isArray(v)) v.forEach(bump);
480
+ else bump(v);
481
+ } else bump(r?.[field]);
482
+ return [...counts.entries()].map(([value, count]) => ({
483
+ value,
484
+ count
485
+ }));
486
+ }
487
+
380
488
  //#endregion
381
489
  //#region src/components/table/mono-data-grid.ts
382
490
  function monoDataGrid(ds = null, opts = {}) {
@@ -445,6 +553,9 @@ function monoDataGrid(ds = null, opts = {}) {
445
553
  const chunkSize = Math.max(1, opts.chunkSize ?? 100);
446
554
  let suppressSync = false;
447
555
  let allRows = [];
556
+ let browserRows = null;
557
+ let browserPageIndex = 0;
558
+ let browserPageSize = 0;
448
559
  let scrollMode = "off";
449
560
  let accumulated = [];
450
561
  let scrollNextPage = 0;
@@ -504,6 +615,9 @@ function monoDataGrid(ds = null, opts = {}) {
504
615
  pageSizeAll: false,
505
616
  pageCount: 0,
506
617
  searchTerms: [],
618
+ filterSuggestion: null,
619
+ filterSuggestions: [],
620
+ setFilterSuggestion,
507
621
  sorts: [],
508
622
  sortField: null,
509
623
  sortOrder: null,
@@ -2148,16 +2262,21 @@ function monoDataGrid(ds = null, opts = {}) {
2148
2262
  * column sort follows — applied to the group field itself if it is one.
2149
2263
  */
2150
2264
  function effectiveSort() {
2151
- const keys = ctrl.sorts.map((s) => ({
2152
- selector: s.field,
2265
+ const keys = ctrl.sorts.filter((s) => !isBrowserSortKey(s.field)).map((s) => ({
2266
+ field: s.field,
2267
+ selector: declaredSortSelector(s.field) ?? s.field,
2153
2268
  desc: s.order === "desc"
2154
2269
  }));
2155
- if (!groupFields.length) return keys.length ? keys : null;
2270
+ const entry = (k) => ({
2271
+ selector: k.selector,
2272
+ desc: k.desc
2273
+ });
2274
+ if (!groupFields.length) return keys.length ? keys.map(entry) : null;
2156
2275
  const list = groupFields.map((f) => ({
2157
2276
  selector: f,
2158
- desc: keys.find((k) => k.selector === f)?.desc ?? false
2277
+ desc: keys.find((k) => k.field === f)?.desc ?? false
2159
2278
  }));
2160
- for (const k of keys) if (!groupFields.includes(k.selector)) list.push(k);
2279
+ for (const k of keys) if (!groupFields.includes(k.field)) list.push(entry(k));
2161
2280
  return list;
2162
2281
  }
2163
2282
  /**
@@ -2572,6 +2691,10 @@ function monoDataGrid(ds = null, opts = {}) {
2572
2691
  syncScroll();
2573
2692
  return;
2574
2693
  }
2694
+ if (browserRows && browserSortActive()) {
2695
+ syncBrowser();
2696
+ return;
2697
+ }
2575
2698
  if (pageSizeAll) {
2576
2699
  ctrl.grouped = false;
2577
2700
  ctrl.items = allRows;
@@ -2735,6 +2858,11 @@ function monoDataGrid(ds = null, opts = {}) {
2735
2858
  await loadScrollPage(true);
2736
2859
  return;
2737
2860
  }
2861
+ if (browserSortActive()) {
2862
+ await loadBrowserSorted();
2863
+ return;
2864
+ }
2865
+ browserRows = null;
2738
2866
  if (pageSizeAll && !isGrouped()) {
2739
2867
  await loadAllChunked();
2740
2868
  return;
@@ -2756,6 +2884,11 @@ function monoDataGrid(ds = null, opts = {}) {
2756
2884
  await loadScrollPage(true);
2757
2885
  return;
2758
2886
  }
2887
+ if (browserSortActive()) {
2888
+ await loadBrowserSorted();
2889
+ return;
2890
+ }
2891
+ browserRows = null;
2759
2892
  if (pageSizeAll && !isGrouped()) {
2760
2893
  await loadAllChunked();
2761
2894
  return;
@@ -2792,6 +2925,11 @@ function monoDataGrid(ds = null, opts = {}) {
2792
2925
  if (serverMode()) await fetchVisibleRows();
2793
2926
  return;
2794
2927
  }
2928
+ if (browserRows && browserSortActive()) {
2929
+ browserPageIndex = Math.max(0, pageIndex);
2930
+ syncBrowser();
2931
+ return;
2932
+ }
2795
2933
  const s = bound;
2796
2934
  if (!s) return;
2797
2935
  s.pageIndex?.(Math.max(0, pageIndex));
@@ -2809,6 +2947,15 @@ function monoDataGrid(ds = null, opts = {}) {
2809
2947
  }
2810
2948
  const s = bound;
2811
2949
  if (!s) return;
2950
+ if (browserRows && browserSortActive()) {
2951
+ if (!all) {
2952
+ browserPageSize = Math.max(1, pageSize);
2953
+ s.pageSize?.(browserPageSize);
2954
+ }
2955
+ browserPageIndex = 0;
2956
+ syncBrowser();
2957
+ return;
2958
+ }
2812
2959
  if (all) {
2813
2960
  await loadAllChunked();
2814
2961
  return;
@@ -2855,6 +3002,127 @@ function monoDataGrid(ds = null, opts = {}) {
2855
3002
  ctrl.loading = bound?.isLoading?.() ?? false;
2856
3003
  sync();
2857
3004
  }
3005
+ const BROWSER_SORT_MAX_ROWS = 5e3;
3006
+ /** The active sort keys when ANY of them sorts in the browser, else `null`. */
3007
+ function browserSortKeys() {
3008
+ if (!ctrl.sorts.some((s) => isBrowserSortKey(s.field))) return null;
3009
+ return ctrl.sorts.map((s) => {
3010
+ const browser = isBrowserSortKey(s.field);
3011
+ return {
3012
+ field: s.field,
3013
+ selector: declaredSortSelector(s.field) ?? s.field,
3014
+ desc: s.order === "desc",
3015
+ aggregate: browser ? declaredSortConfig(s.field).aggregate ?? "sum" : null
3016
+ };
3017
+ });
3018
+ }
3019
+ /** Browser sort applies: a browser-sorted column is active on a flat, paged, bound table. */
3020
+ function browserSortActive() {
3021
+ return !!bound && !isGrouped() && !serverMode() && !scrollActive() && !!browserSortKeys();
3022
+ }
3023
+ /** The smallest `maxRows` any active browser-sorted column declares (default 5000). */
3024
+ function browserSortCap() {
3025
+ const caps = ctrl.sorts.filter((s) => isBrowserSortKey(s.field)).map((s) => Number(declaredSortConfig(s.field).maxRows)).filter((n) => Number.isFinite(n) && n > 0);
3026
+ return caps.length ? Math.min(...caps) : BROWSER_SORT_MAX_ROWS;
3027
+ }
3028
+ /** A row's matches for `selector` reduced to one sortable value. */
3029
+ function browserSortValue(row, selector, aggregate) {
3030
+ const raw = getFieldValue(row, selector);
3031
+ if (!aggregate) return raw;
3032
+ const list = Array.isArray(raw) ? raw : raw == null ? [] : [raw];
3033
+ if (aggregate === "count") return list.length;
3034
+ const nums = list.map(Number).filter((n) => Number.isFinite(n));
3035
+ if (!nums.length) return aggregate === "sum" ? 0 : null;
3036
+ if (aggregate === "min") return Math.min(...nums);
3037
+ if (aggregate === "max") return Math.max(...nums);
3038
+ const sum = nums.reduce((a, b) => a + b, 0);
3039
+ return aggregate === "avg" ? sum / nums.length : sum;
3040
+ }
3041
+ /** Empties last in either direction; numbers numerically; text numeric-aware. */
3042
+ function compareBrowserValues(a, b) {
3043
+ const ea = a == null || a === "";
3044
+ const eb = b == null || b === "";
3045
+ if (ea || eb) return ea === eb ? 0 : ea ? 1 : -1;
3046
+ if (typeof a === "number" && typeof b === "number") return a - b;
3047
+ if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();
3048
+ return String(a).localeCompare(String(b), void 0, { numeric: true });
3049
+ }
3050
+ /** Every matching row, sorted by the active keys (stable). */
3051
+ function sortBrowserRows(rows) {
3052
+ const keys = browserSortKeys() ?? [];
3053
+ const decorated = rows.map((row, i) => ({
3054
+ row,
3055
+ i,
3056
+ v: keys.map((k) => browserSortValue(row, k.selector, k.aggregate))
3057
+ }));
3058
+ decorated.sort((x, y) => {
3059
+ for (let k = 0; k < keys.length; k++) {
3060
+ const ex = x.v[k] == null || x.v[k] === "";
3061
+ const ey = y.v[k] == null || y.v[k] === "";
3062
+ const c = compareBrowserValues(x.v[k], y.v[k]);
3063
+ if (c) return ex || ey ? c : keys[k].desc ? -c : c;
3064
+ }
3065
+ return x.i - y.i;
3066
+ });
3067
+ return decorated.map((d) => d.row);
3068
+ }
3069
+ /** Too many rows to sort in the browser: drop those keys, warn, load normally. */
3070
+ async function refuseBrowserSort(count, cap) {
3071
+ const fields = ctrl.sorts.filter((s) => isBrowserSortKey(s.field)).map((s) => s.field);
3072
+ console.warn(`[monoDataGrid] sort: "${fields.join("\", \"")}" sorts in the browser and needs every row, but ${count} match (maxRows ${cap}) — sort cleared.`);
3073
+ ctrl.sorts = ctrl.sorts.filter((s) => !isBrowserSortKey(s.field));
3074
+ syncPrimarySort();
3075
+ browserRows = null;
3076
+ applySourceSort();
3077
+ notify();
3078
+ await load();
3079
+ }
3080
+ /** Read every matching row, sort it in memory, show the first page. */
3081
+ async function loadBrowserSorted() {
3082
+ const s = bound;
3083
+ if (!s) return;
3084
+ const cap = browserSortCap();
3085
+ const known = s.totalCount?.();
3086
+ if (typeof known === "number" && known > cap) {
3087
+ await refuseBrowserSort(known, cap);
3088
+ return;
3089
+ }
3090
+ if (!browserPageSize) browserPageSize = Math.max(1, s.pageSize?.() || ctrl.pageSize || 20);
3091
+ ctrl.loading = true;
3092
+ notify();
3093
+ let rows = [];
3094
+ try {
3095
+ await runLoad(async () => {
3096
+ rows = await readAllFromSource();
3097
+ });
3098
+ } finally {
3099
+ ctrl.loading = false;
3100
+ }
3101
+ if (rows.length > cap) {
3102
+ await refuseBrowserSort(rows.length, cap);
3103
+ return;
3104
+ }
3105
+ browserRows = sortBrowserRows(rows);
3106
+ browserPageIndex = 0;
3107
+ sync();
3108
+ recomputeSummaries();
3109
+ }
3110
+ /** Map the in-memory sorted rows (current page, or all) onto `ctrl`. */
3111
+ function syncBrowser() {
3112
+ const rows = browserRows ?? [];
3113
+ const size = pageSizeAll ? Math.max(1, rows.length) : Math.max(1, browserPageSize);
3114
+ const pageCount = Math.max(1, Math.ceil(rows.length / size));
3115
+ browserPageIndex = Math.min(Math.max(0, browserPageIndex), pageCount - 1);
3116
+ const start = browserPageIndex * size;
3117
+ ctrl.grouped = false;
3118
+ ctrl.items = rows.slice(start, start + size);
3119
+ ctrl.pageIndex = browserPageIndex;
3120
+ ctrl.pageSize = size;
3121
+ ctrl.pageSizeAll = pageSizeAll;
3122
+ ctrl.totalCount = rows.length;
3123
+ ctrl.pageCount = pageCount;
3124
+ render();
3125
+ }
2858
3126
  /** Scroll modes only apply to a flat (ungrouped, non-server) grid. */
2859
3127
  function scrollActive() {
2860
3128
  return scrollMode !== "off" && !isGrouped() && !serverMode();
@@ -3192,8 +3460,30 @@ function monoDataGrid(ds = null, opts = {}) {
3192
3460
  }
3193
3461
  await setSearchTerms(ctrl.searchTerms);
3194
3462
  }
3463
+ /** What identifies an offer for the change check — a re-published identical list is a no-op. */
3464
+ const offerKey = (list) => {
3465
+ try {
3466
+ return JSON.stringify(list.map((s) => [
3467
+ s.key,
3468
+ s.count,
3469
+ s.values
3470
+ ]));
3471
+ } catch {
3472
+ return String(Math.random());
3473
+ }
3474
+ };
3475
+ /** Equality-guarded so a re-published identical list costs no notify (no re-render loop). */
3476
+ function setFilterSuggestion(next) {
3477
+ const list = next == null ? [] : Array.isArray(next) ? next.filter(Boolean) : [next];
3478
+ if (offerKey(list) === offerKey(ctrl.filterSuggestions)) return;
3479
+ ctrl.filterSuggestions = list;
3480
+ ctrl.filterSuggestion = list[0] ?? null;
3481
+ notify();
3482
+ }
3195
3483
  async function setSearchTerms(terms) {
3196
3484
  ctrl.searchTerms = (terms ?? []).filter((t) => t && String(t.value ?? "") !== "");
3485
+ ctrl.filterSuggestion = null;
3486
+ ctrl.filterSuggestions = [];
3197
3487
  groupPageIndex = 0;
3198
3488
  bumpSummary("search");
3199
3489
  if (serverMode()) {
@@ -3633,48 +3923,13 @@ function monoDataGrid(ds = null, opts = {}) {
3633
3923
  * exactly as every other request does.
3634
3924
  */
3635
3925
  async function distinctViaApply(store, field, options) {
3636
- if (applyGate.skip) return null;
3637
- if (parseFieldPath(field).hasWildcard) return null;
3638
- const selector = isPath(field) ? toODataSelector(field) : field;
3639
- if (!selector) return null;
3640
- const apply = `groupby((${selector}),aggregate($count as count))`;
3641
- const odataFilter = options?.filter != null ? arrayToODataString(options.filter) : "";
3642
- const clause = odataFilter ? `filter(${odataFilter})/${apply}` : apply;
3643
3926
  const top = typeof options?.take === "number" && options.take >= 0 ? options.take : void 0;
3644
- let rows;
3645
- try {
3646
- rows = await loadApply(store, clause, { top });
3647
- } catch (err) {
3648
- applyGate.reject(err);
3649
- return null;
3650
- }
3651
- if (!rows) return null;
3652
- if (!rows.length) return [];
3653
- const first = rows[0];
3654
- if (!first || typeof first !== "object" || typeof first.count !== "number") return null;
3655
- if (!isRolledUp(rows, [field, "count"])) return null;
3656
- const path = isPath(field);
3657
- return sortColumnValues(rows.map((r) => ({
3658
- value: path ? getFieldValue(r, field) : r[field],
3659
- count: Number(r.count) || 0
3660
- })));
3927
+ const rows = await groupCountViaApply(store, field, options?.filter ?? null, applyGate, { top });
3928
+ return rows ? sortColumnValues(rows) : null;
3661
3929
  }
3662
3930
  /** Count occurrences of `field` across `rows` into a sorted `{value,count}[]`. */
3663
3931
  function distinctFromRows(rows, field) {
3664
- const counts = /* @__PURE__ */ new Map();
3665
- const bump = (v) => {
3666
- counts.set(v, (counts.get(v) ?? 0) + 1);
3667
- };
3668
- const path = isPath(field);
3669
- for (const r of rows) if (path) {
3670
- const v = getFieldValue(r, field);
3671
- if (Array.isArray(v)) v.forEach(bump);
3672
- else bump(v);
3673
- } else bump(r?.[field]);
3674
- return sortColumnValues([...counts.entries()].map(([value, count]) => ({
3675
- value,
3676
- count
3677
- })));
3932
+ return sortColumnValues(countValues(rows, field));
3678
3933
  }
3679
3934
  async function distinctValues(field, options) {
3680
3935
  if (!field) return [];
@@ -3787,6 +4042,41 @@ function monoDataGrid(ds = null, opts = {}) {
3787
4042
  });
3788
4043
  ctrl.sorts = marked.map((m) => m.s);
3789
4044
  }
4045
+ /**
4046
+ * The source selector a column DECLARED via `sort.selector`, if any — what the
4047
+ * DataSource / array source orders by in place of the field. Resolved like
4048
+ * `declaredSortIndex`: central `props.th` config first, then the element's own
4049
+ * `:sort.prop`. A blank string counts as not declared.
4050
+ */
4051
+ function declaredSortSelector(field) {
4052
+ const sel = declaredSortConfig(field).selector;
4053
+ return typeof sel === "string" && sel.trim() ? sel.trim() : void 0;
4054
+ }
4055
+ /**
4056
+ * A column's declared sort OBJECT — the element's `:sort.prop` with central
4057
+ * `props.th` config merged over it (props win key by key, as everywhere). `{}`
4058
+ * for `sort: true` / no config.
4059
+ */
4060
+ function declaredSortConfig(field) {
4061
+ const asObj = (sort) => typeof sort === "object" && sort ? sort : {};
4062
+ let fromEl = {};
4063
+ for (const el of columnEls) if (el.field === field && typeof el.sort === "object" && el.sort) {
4064
+ fromEl = asObj(el.sort);
4065
+ break;
4066
+ }
4067
+ return {
4068
+ ...fromEl,
4069
+ ...asObj((elementProps.th ?? []).find((c) => c?.field === field)?.sort)
4070
+ };
4071
+ }
4072
+ /**
4073
+ * Whether a sorted column is sorted IN THE BROWSER — its selector fans out over a
4074
+ * collection (`[*]`, which no source can order by) or it declares an `aggregate`.
4075
+ */
4076
+ function isBrowserSortKey(field) {
4077
+ const sel = declaredSortSelector(field);
4078
+ return !!sel && parseFieldPath(sel).hasWildcard || !!declaredSortConfig(field).aggregate;
4079
+ }
3790
4080
  /** Keep the single-value mirrors pointing at the primary key. */
3791
4081
  function syncPrimarySort() {
3792
4082
  ctrl.sortField = ctrl.sorts[0]?.field ?? null;
@@ -3975,6 +4265,11 @@ function monoDataGrid(ds = null, opts = {}) {
3975
4265
  * see the intermediate full-list state.
3976
4266
  */
3977
4267
  async function getData() {
4268
+ if (browserRows && browserSortActive()) return [...browserRows];
4269
+ return readAllFromSource();
4270
+ }
4271
+ /** `getData`'s read — every matching row from the source, in its own order. */
4272
+ async function readAllFromSource() {
3978
4273
  const s = bound;
3979
4274
  if (!s) return [];
3980
4275
  const loadOptions = {};
@@ -4041,4 +4336,4 @@ function monoDataGrid(ds = null, opts = {}) {
4041
4336
  }
4042
4337
 
4043
4338
  //#endregion
4044
- export { seedFromRanges as a, minimize as i, buildDateTree as n, setAllChecked as o, checkState as r, setChecked as s, monoDataGrid as t };
4339
+ export { checkState as a, setAllChecked as c, buildDateTree as i, setChecked as l, countTuples as n, minimize as o, groupCountsViaApply as r, seedFromRanges as s, monoDataGrid as t };
@@ -99,31 +99,36 @@ function decorateEvent(event, detail) {
99
99
  * dispatchMonoEvent(this, 'loading-change', detail) // loading-change + loadingChange + mno-loading-change + mnoLoadingChange
100
100
  */
101
101
  function dispatchMonoEvent(target, name, detail, options = {}) {
102
+ const cancelable = !!options.cancelable;
102
103
  const init = {
103
104
  detail,
104
105
  bubbles: true,
105
- composed: true
106
+ composed: true,
107
+ cancelable
106
108
  };
109
+ let allowed = true;
107
110
  const camel = toCamelEventName(`mno-${name}`);
108
- target.dispatchEvent(new CustomEvent(`mno-${name}`, init));
109
- target.dispatchEvent(new CustomEvent(camel, init));
111
+ allowed = target.dispatchEvent(new CustomEvent(`mno-${name}`, init)) && allowed;
112
+ allowed = target.dispatchEvent(new CustomEvent(camel, init)) && allowed;
110
113
  const alias = options.alias === false ? null : options.alias ?? name;
111
- if (!alias) return;
114
+ if (!alias) return allowed;
112
115
  const fromDetail = detail?.sourceEvent;
113
116
  const source = options.sourceEvent !== void 0 ? options.sourceEvent : fromDetail instanceof Event ? fromDetail : null;
114
117
  if (source && source.type === alias && reachesHost(source, target)) {
115
118
  decorateEvent(source, detail);
116
- return;
119
+ return allowed;
117
120
  }
118
- if (MONO_DEVICE_EVENTS.has(alias)) return;
121
+ if (MONO_DEVICE_EVENTS.has(alias)) return allowed;
119
122
  const plainInit = {
120
123
  detail,
121
124
  bubbles: !MONO_NON_BUBBLING_ALIASES.has(alias),
122
- composed: true
125
+ composed: true,
126
+ cancelable
123
127
  };
124
- target.dispatchEvent(new CustomEvent(alias, plainInit));
128
+ allowed = target.dispatchEvent(new CustomEvent(alias, plainInit)) && allowed;
125
129
  const plainCamel = toCamelEventName(alias);
126
- if (plainCamel !== alias) target.dispatchEvent(new CustomEvent(plainCamel, plainInit));
130
+ if (plainCamel !== alias) allowed = target.dispatchEvent(new CustomEvent(plainCamel, plainInit)) && allowed;
131
+ return allowed;
127
132
  }
128
133
 
129
134
  //#endregion
@@ -430,7 +430,8 @@ function monoForm(options) {
430
430
  _register,
431
431
  _report,
432
432
  _reportList,
433
- _propsFor: propsFor
433
+ _propsFor: propsFor,
434
+ _elements: (key) => [...elements[key] ?? []]
434
435
  };
435
436
  }
436
437