@feugene/granularity 0.47.0 → 0.48.0

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 (58) hide show
  1. package/README.md +1 -1
  2. package/dist/chunks/{config-DeyT9dJl.js → config-Bs1HwUcx.js} +47 -4
  3. package/dist/chunks/{config-DeyT9dJl.js.map → config-Bs1HwUcx.js.map} +1 -1
  4. package/dist/chunks/{config-B3J0alyY.js → config-CzeZg2LO.js} +49 -4
  5. package/dist/chunks/config-CzeZg2LO.js.map +1 -0
  6. package/dist/chunks/{config-DCq4JySZ.js → config-D3HOuHDe.js} +1 -1
  7. package/dist/chunks/{config-DCq4JySZ.js.map → config-D3HOuHDe.js.map} +1 -1
  8. package/dist/chunks/{en-DjTnfTqM.js → en-Bxyn5lW7.js} +9 -1
  9. package/dist/chunks/en-Bxyn5lW7.js.map +1 -0
  10. package/dist/chunks/{es-DIFzSXSZ.js → es-Bj_vc18Z.js} +3 -3
  11. package/dist/chunks/{es-DIFzSXSZ.js.map → es-Bj_vc18Z.js.map} +1 -1
  12. package/dist/chunks/{es-Bc_t3FI8.js → es-Dtl-a7ui.js} +9 -1
  13. package/dist/chunks/es-Dtl-a7ui.js.map +1 -0
  14. package/dist/chunks/{generated-CQ4h6Ieq.js → generated-hELWB0gZ.js} +98 -0
  15. package/dist/chunks/{generated-CQ4h6Ieq.js.map → generated-hELWB0gZ.js.map} +1 -1
  16. package/dist/chunks/{grTableStyles-uuMPSOBR.js → grTableStyles-DkQPMfx9.js} +16 -3
  17. package/dist/chunks/grTableStyles-DkQPMfx9.js.map +1 -0
  18. package/dist/chunks/{granular-provider-AKukmYva.js → granular-provider-BOQp7N5o.js} +3 -3
  19. package/dist/chunks/{granular-provider-AKukmYva.js.map → granular-provider-BOQp7N5o.js.map} +1 -1
  20. package/dist/chunks/{ru-Bb-co59W.js → ru-hrB4I1u_.js} +9 -1
  21. package/dist/chunks/ru-hrB4I1u_.js.map +1 -0
  22. package/dist/components/GrAvatar/chunks/{GrAvatar-dWEXiCJG.js → GrAvatar-Do5-C409.js} +12 -1
  23. package/dist/components/GrAvatar/chunks/GrAvatar-Do5-C409.js.map +1 -0
  24. package/dist/components/GrAvatar/index.js +2 -2
  25. package/dist/components/GrAvatar/themes/light.css +35 -0
  26. package/dist/components/GrDataTable/chunks/{GrDataTable-Dp9Fp_P5.js → GrDataTable-DQxYYgQk.js} +438 -160
  27. package/dist/components/GrDataTable/chunks/GrDataTable-DQxYYgQk.js.map +1 -0
  28. package/dist/components/GrDataTable/index.js +2 -2
  29. package/dist/components/GrDataTable/themes/light.css +10 -0
  30. package/dist/components/GrTable/chunks/{GrTable-iwzHvlMC.js → GrTable-CKJ-HrsN.js} +1 -1
  31. package/dist/components/GrTable/chunks/{GrTable-iwzHvlMC.js.map → GrTable-CKJ-HrsN.js.map} +1 -1
  32. package/dist/components/GrTable/index.js +2 -2
  33. package/dist/granular-provider-node.js +1 -1
  34. package/dist/granular-provider.js +1 -1
  35. package/dist/i18n/all.js +1 -1
  36. package/dist/i18n/index.js +1 -1
  37. package/dist/index.js +6 -6
  38. package/dist/theme.js +1 -1
  39. package/dist/tokens.js +1 -1
  40. package/dist/types/components/GrAvatar/GrAvatar.vue.d.ts +11 -0
  41. package/dist/types/components/GrAvatar/defaults.d.ts +1 -0
  42. package/dist/types/components/GrAvatar/grAvatarStyles.d.ts +26 -1
  43. package/dist/types/components/GrDataTable/GrDataTable.vue.d.ts +59 -0
  44. package/dist/types/components/GrDataTable/composables/useDataTableExpansion.d.ts +46 -0
  45. package/dist/types/components/GrDataTable/grDataTableStyles.d.ts +23 -0
  46. package/dist/types/components/GrTable/grTableStyles.d.ts +16 -3
  47. package/dist/types/i18n/messages/en.d.ts +16 -0
  48. package/dist/types/i18n/messages/es.d.ts +16 -0
  49. package/dist/types/i18n/messages/ru.d.ts +16 -0
  50. package/dist/web-types.json +76 -1
  51. package/package.json +1 -1
  52. package/dist/chunks/config-B3J0alyY.js.map +0 -1
  53. package/dist/chunks/en-DjTnfTqM.js.map +0 -1
  54. package/dist/chunks/es-Bc_t3FI8.js.map +0 -1
  55. package/dist/chunks/grTableStyles-uuMPSOBR.js.map +0 -1
  56. package/dist/chunks/ru-Bb-co59W.js.map +0 -1
  57. package/dist/components/GrAvatar/chunks/GrAvatar-dWEXiCJG.js.map +0 -1
  58. package/dist/components/GrDataTable/chunks/GrDataTable-Dp9Fp_P5.js.map +0 -1
@@ -4,16 +4,19 @@ import { t as loader_circle_default } from "../../../chunks/loader-circle-CfVLz7
4
4
  import { t as GrIcon_default } from "../../GrIcon/chunks/GrIcon-DTZIgmje.js";
5
5
  import { useVirtualList } from "../../../composables/useVirtualList.js";
6
6
  import { useRovingFocus } from "../../../composables/useRovingFocus.js";
7
+ import { t as GrSkeleton_default } from "../../GrSkeleton/chunks/GrSkeleton-CgfXxPQ2.js";
8
+ import { t as GrButton_default } from "../../GrButton/chunks/GrButton-CS4TqMtG.js";
7
9
  import { useAnnouncer } from "../../../composables/useAnnouncer.js";
8
10
  import { useDragGesture } from "../../../composables/useDragGesture.js";
11
+ import { t as chevron_right_default } from "../../../chunks/chevron-right-C6Z01h0X.js";
9
12
  import { t as GrCheckbox_default } from "../../GrCheckbox/chunks/GrCheckbox-Dp201frb.js";
10
- import { t as GrTable_default } from "../../GrTable/chunks/GrTable-iwzHvlMC.js";
13
+ import { t as GrTable_default } from "../../GrTable/chunks/GrTable-CKJ-HrsN.js";
11
14
  import { i as moveItem, r as insertionIndex } from "../../../chunks/dragSortGeometry-CY-llfrQ.js";
12
15
  import { useDragSort } from "../../../composables/useDragSort.js";
13
- import { C as sortIconSizes, S as selectColumnWidths, T as summaryRowClass, _ as headerTextSizes, a as columnDropAfterClass, b as rowSelectedClass, c as columnHandleClass, d as columnPinnedRightEdgeClass, f as columnResizerClass, g as headerGaps, h as columnResizerLineClass, i as columnDraggingClass, l as columnPinnedClass, m as columnResizerLineActiveClass, o as columnDropBeforeClass, p as columnResizerHoverClass, r as cellPaddings, s as columnHandleActiveClass, u as columnPinnedLeftEdgeClass, v as placeholderPaddings, w as spinnerSizes, x as selectCheckboxSizes, y as rowHeightEstimates } from "../../../chunks/config-DeyT9dJl.js";
16
+ import { A as selectCheckboxSizes, C as expandIconClass, D as placeholderPaddings, E as headerTextSizes, M as sortIconSizes, N as spinnerSizes, O as rowHeightEstimates, P as summaryRowClass, S as expandColumnWidths, T as headerGaps, _ as detailContentClass, a as columnDropAfterClass, b as detailRowClass, c as columnHandleClass, d as columnPinnedRightEdgeClass, f as columnResizerClass, g as detailCellClass, h as columnResizerLineClass, i as columnDraggingClass, j as selectColumnWidths, k as rowSelectedClass, l as columnPinnedClass, m as columnResizerLineActiveClass, o as columnDropBeforeClass, p as columnResizerHoverClass, r as cellPaddings, s as columnHandleActiveClass, u as columnPinnedLeftEdgeClass, v as detailErrorClass, w as expandIconOpenClass, x as expandButtonClass, y as detailPaddings } from "../../../chunks/config-Bs1HwUcx.js";
14
17
  import { t as arrow_up_default } from "../../../chunks/arrow-up-C_G4jg8M.js";
15
18
  import { t as grip_vertical_default } from "../../../chunks/grip-vertical-lRha2S7q.js";
16
- import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, markRaw, mergeProps, nextTick, normalizeClass, normalizeStyle, onMounted, onUnmounted, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useId, watch, watchEffect, withCtx, withModifiers } from "vue";
19
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, markRaw, mergeProps, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, onUnmounted, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useId, watch, watchEffect, withCtx, withModifiers } from "vue";
17
20
  //#region src/components/GrDataTable/composables/useDataTableRowKeys.ts
18
21
  function useDataTableRowKeys(options) {
19
22
  const syntheticKeys = /* @__PURE__ */ new WeakMap();
@@ -536,6 +539,128 @@ function useDataTableLayout(options) {
536
539
  };
537
540
  }
538
541
  //#endregion
542
+ //#region src/components/GrDataTable/composables/useDataTableExpansion.ts
543
+ function useDataTableExpansion(options) {
544
+ const internalExpanded = ref([]);
545
+ const isExpandedControlled = computed(() => options.expandedKeys() !== void 0);
546
+ const expandedKeys = computed(() => new Set(options.expandedKeys() ?? internalExpanded.value));
547
+ const states = ref(/* @__PURE__ */ new Map());
548
+ const data = ref(/* @__PURE__ */ new Map());
549
+ /**
550
+ * Летящие запросы по ключу. Счётчик поколений отдельно от контроллера: ответ,
551
+ * стартовавший раньше и пришедший позже, обязан проиграть последнему, а
552
+ * `abort()` сам по себе этого не гарантирует — промис уже мог разрешиться.
553
+ */
554
+ const inflight = /* @__PURE__ */ new Map();
555
+ const generation = /* @__PURE__ */ new Map();
556
+ function setState(key, state) {
557
+ const next = new Map(states.value);
558
+ next.set(key, state);
559
+ states.value = next;
560
+ }
561
+ function cancel(key) {
562
+ inflight.get(key)?.abort();
563
+ inflight.delete(key);
564
+ generation.set(key, (generation.get(key) ?? 0) + 1);
565
+ }
566
+ function isRowExpandable(row) {
567
+ const predicate = options.expandableRow();
568
+ return predicate ? predicate(row) : true;
569
+ }
570
+ function isRowExpanded(row) {
571
+ return expandedKeys.value.has(options.rowKeyValue(row));
572
+ }
573
+ function detailStateOf(row) {
574
+ return states.value.get(options.rowKeyValue(row)) ?? "idle";
575
+ }
576
+ function detailDataOf(row) {
577
+ return data.value.get(options.rowKeyValue(row));
578
+ }
579
+ async function load(row, key) {
580
+ const loadDetail = options.loadDetail();
581
+ if (!loadDetail) return;
582
+ cancel(key);
583
+ const controller = new AbortController();
584
+ inflight.set(key, controller);
585
+ const seq = generation.get(key) ?? 0;
586
+ setState(key, "loading");
587
+ try {
588
+ const result = await loadDetail(row, controller.signal);
589
+ if (seq !== generation.get(key)) return;
590
+ const next = new Map(data.value);
591
+ next.set(key, result);
592
+ data.value = next;
593
+ setState(key, "ready");
594
+ } catch (error) {
595
+ if (seq !== generation.get(key) || controller.signal.aborted) return;
596
+ setState(key, "error");
597
+ options.onDetailLoadError(row, key, error);
598
+ } finally {
599
+ if (inflight.get(key) === controller) inflight.delete(key);
600
+ }
601
+ }
602
+ function commit(keys) {
603
+ if (!isExpandedControlled.value) internalExpanded.value = keys;
604
+ options.onExpandedChange(keys);
605
+ }
606
+ function toggleRow(row) {
607
+ if (!isRowExpandable(row)) return;
608
+ const key = options.rowKeyValue(row);
609
+ if (expandedKeys.value.has(key)) {
610
+ cancel(key);
611
+ if (states.value.get(key) === "loading") setState(key, "idle");
612
+ commit([...expandedKeys.value].filter((item) => item !== key));
613
+ options.onCollapse(row, key);
614
+ return;
615
+ }
616
+ commit(options.accordion() ? [key] : [...expandedKeys.value, key]);
617
+ options.onExpand(row, key);
618
+ if (options.loadDetail() && states.value.get(key) !== "ready") load(row, key);
619
+ }
620
+ function collapseAll() {
621
+ for (const key of expandedKeys.value) cancel(key);
622
+ commit([]);
623
+ }
624
+ function retryDetail(row) {
625
+ load(row, options.rowKeyValue(row));
626
+ }
627
+ function invalidateDetail(key) {
628
+ if (key === void 0) {
629
+ for (const item of inflight.keys()) cancel(item);
630
+ states.value = /* @__PURE__ */ new Map();
631
+ data.value = /* @__PURE__ */ new Map();
632
+ return;
633
+ }
634
+ cancel(key);
635
+ const nextStates = new Map(states.value);
636
+ nextStates.delete(key);
637
+ states.value = nextStates;
638
+ const nextData = new Map(data.value);
639
+ nextData.delete(key);
640
+ data.value = nextData;
641
+ }
642
+ /**
643
+ * Смена идентичности набора сбрасывает загруженное — то же правило, что у
644
+ * виртуализатора: мутация массива на месте сохраняет, замена сбрасывает.
645
+ * Иначе строка показывала бы подробности прошлого набора данных.
646
+ */
647
+ watch(() => options.rows(), () => invalidateDetail());
648
+ onBeforeUnmount(() => {
649
+ for (const key of inflight.keys()) cancel(key);
650
+ });
651
+ return {
652
+ expandedKeys,
653
+ isRowExpandable,
654
+ isRowExpanded,
655
+ toggleRow,
656
+ collapseAll,
657
+ detailStateOf,
658
+ detailDataOf,
659
+ retryDetail,
660
+ invalidateDetail
661
+ };
662
+ }
663
+ //#endregion
539
664
  //#region ~icons/lucide/arrow-down
540
665
  var _hoisted_1$1 = {
541
666
  viewBox: "0 0 24 24",
@@ -603,6 +728,7 @@ var _hoisted_15 = {
603
728
  key: 0,
604
729
  "aria-hidden": "true",
605
730
  "data-gr-datatable-spacer": "before",
731
+ "data-gr-table-off-grid": "",
606
732
  style: { pointerEvents: "none" }
607
733
  };
608
734
  var _hoisted_16 = ["colspan"];
@@ -612,15 +738,28 @@ var _hoisted_17 = [
612
738
  "aria-rowindex",
613
739
  "onClick"
614
740
  ];
615
- var _hoisted_18 = {
741
+ var _hoisted_18 = [
742
+ "aria-expanded",
743
+ "aria-controls",
744
+ "aria-label",
745
+ "onClick"
746
+ ];
747
+ var _hoisted_19 = ["id"];
748
+ var _hoisted_20 = ["colspan"];
749
+ var _hoisted_21 = {
750
+ key: 0,
751
+ "data-gr-datatable-detail-loading": ""
752
+ };
753
+ var _hoisted_22 = {
616
754
  key: 1,
617
755
  "aria-hidden": "true",
618
756
  "data-gr-datatable-spacer": "after",
757
+ "data-gr-table-off-grid": "",
619
758
  style: { pointerEvents: "none" }
620
759
  };
621
- var _hoisted_19 = ["colspan"];
622
- var _hoisted_20 = ["aria-rowindex"];
623
- var _hoisted_21 = ["data-column-key"];
760
+ var _hoisted_23 = ["colspan"];
761
+ var _hoisted_24 = ["aria-rowindex"];
762
+ var _hoisted_25 = ["data-column-key"];
624
763
  //#endregion
625
764
  //#region src/components/GrDataTable/GrDataTable.vue
626
765
  var GrDataTable_default = /* @__PURE__ */ defineComponent({
@@ -688,7 +827,28 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
688
827
  type: Boolean,
689
828
  default: false
690
829
  },
691
- columnWidths: { default: void 0 }
830
+ columnWidths: { default: void 0 },
831
+ expandable: {
832
+ type: Boolean,
833
+ default: false
834
+ },
835
+ expandedKeys: { default: void 0 },
836
+ expandableRow: {
837
+ type: Function,
838
+ default: void 0
839
+ },
840
+ loadDetail: {
841
+ type: Function,
842
+ default: void 0
843
+ },
844
+ accordion: {
845
+ type: Boolean,
846
+ default: false
847
+ },
848
+ expandColumn: {
849
+ type: Boolean,
850
+ default: true
851
+ }
692
852
  },
693
853
  emits: [
694
854
  "update:sortKey",
@@ -699,7 +859,11 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
699
859
  "update:columnOrder",
700
860
  "columnReorder",
701
861
  "update:columnWidths",
702
- "columnResize"
862
+ "columnResize",
863
+ "update:expandedKeys",
864
+ "expand",
865
+ "collapse",
866
+ "detailLoadError"
703
867
  ],
704
868
  setup(__props, { expose: __expose, emit: __emit }) {
705
869
  const props = __props;
@@ -785,7 +949,14 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
785
949
  function summaryValue(key) {
786
950
  return props.summaryRow?.[key];
787
951
  }
788
- const totalColumns = computed(() => props.columns.length + (props.selectable ? 1 : 0));
952
+ /**
953
+ * Раскрытие выключено при виртуализации целиком — см. предупреждение ниже.
954
+ * Объявлено здесь, а не рядом с ним: от него зависит `colspan` служебных строк.
955
+ */
956
+ const expandEnabled = computed(() => props.expandable && !props.virtual);
957
+ /** Своя колонка с кнопкой: её может не быть, если кнопку ставит потребитель. */
958
+ const expandColumnVisible = computed(() => expandEnabled.value && props.expandColumn);
959
+ const totalColumns = computed(() => props.columns.length + (props.selectable ? 1 : 0) + (expandColumnVisible.value ? 1 : 0));
789
960
  /**
790
961
  * Карты живут в компоненте, а не в модуле: наполняет их шаблон, а читают все
791
962
  * три колоночных модуля — порядок тянет за ячейку, ширина её замеряет,
@@ -901,6 +1072,48 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
901
1072
  rowKeyValue,
902
1073
  onSelectedChange: (keys) => emit("update:selected", keys)
903
1074
  });
1075
+ const expandDetailId = useId();
1076
+ const { isRowExpandable, isRowExpanded, toggleRow: toggleRowExpanded, detailStateOf, detailDataOf, retryDetail, invalidateDetail } = useDataTableExpansion({
1077
+ expandedKeys: () => props.expandedKeys,
1078
+ rows: () => props.rows,
1079
+ expandableRow: () => props.expandableRow,
1080
+ loadDetail: () => props.loadDetail,
1081
+ accordion: () => props.accordion,
1082
+ rowKeyValue,
1083
+ onExpandedChange: (keys) => emit("update:expandedKeys", keys),
1084
+ onExpand: (row, key) => {
1085
+ emit("expand", {
1086
+ row,
1087
+ key
1088
+ });
1089
+ announce(t("gr.dataTable.detailExpanded", "Row details shown"));
1090
+ },
1091
+ onCollapse: (row, key) => {
1092
+ emit("collapse", {
1093
+ row,
1094
+ key
1095
+ });
1096
+ announce(t("gr.dataTable.detailCollapsed", "Row details hidden"));
1097
+ },
1098
+ onDetailLoadError: (row, key, error) => emit("detailLoadError", {
1099
+ row,
1100
+ key,
1101
+ error
1102
+ })
1103
+ });
1104
+ /** Id строки подробностей: адресат `aria-controls` у кнопки. */
1105
+ function detailRowId(row) {
1106
+ return `${expandDetailId}-${rowKeyValue(row)}`;
1107
+ }
1108
+ /**
1109
+ * Раскрытие и виртуализация вместе пока не работают: замер виртуализатора висит
1110
+ * на самой строке, и высота второго яруса в него не попадает — распорка
1111
+ * разъедется молча. Запрет снимется, когда пара строк переедет в свою группу
1112
+ * `<tbody>`; до тех пор лучше предупредить, чем показать прыгающую таблицу.
1113
+ */
1114
+ if (process.env.NODE_ENV !== "production") watchEffect(() => {
1115
+ if (props.expandable && props.virtual) console.warn("[granularity] GrDataTable: `expandable` вместе с `virtual` пока не поддержан — раскрытие выключено. Замер виртуализатора висит на строке и не видит высоту подробностей, поэтому распорки разъезжаются.");
1116
+ });
904
1117
  const tableRef = ref(null);
905
1118
  const rootId = useId();
906
1119
  function rootEl() {
@@ -981,7 +1194,13 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
981
1194
  /** Снять сортировку (эквивалент третьего состояния). */
982
1195
  clearSort,
983
1196
  /** Отметить/снять все выбираемые строки. */
984
- toggleAll
1197
+ toggleAll,
1198
+ /**
1199
+ * Сбросить загруженные подробности: у одной строки либо у всех.
1200
+ * Нужен, когда запись изменилась на сервере, — само по себе раскрытие
1201
+ * держит загруженное, пока строка жива.
1202
+ */
1203
+ invalidateDetail
985
1204
  });
986
1205
  /**
987
1206
  * Три семейства слотов по ключу колонки — `#cell-<key>` (`{ row, index }`),
@@ -1008,115 +1227,124 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
1008
1227
  header: withCtx(() => [createElementVNode("tr", {
1009
1228
  "data-gr-datatable-header": "",
1010
1229
  "aria-rowindex": __props.virtual ? 1 : void 0
1011
- }, [__props.selectable ? (openBlock(), createElementBlock("th", {
1012
- key: 0,
1013
- ref: (el) => registerEl(unref(headerCellEls), unref(SELECT_COLUMN_KEY), el),
1014
- class: normalizeClass(["text-left", [
1015
- selectColumnClass.value,
1016
- cellClass.value,
1017
- unref(hasPinnedLeft) ? unref(columnPinnedClass) : ""
1018
- ]]),
1019
- style: normalizeStyle(unref(hasPinnedLeft) ? { left: "0px" } : void 0),
1020
- scope: "col"
1021
- }, [createVNode(GrCheckbox_default, {
1022
- "data-gr-datatable-select-all": "",
1023
- "model-value": unref(allSelected),
1024
- indeterminate: unref(someSelected),
1025
- size: checkboxSize.value,
1026
- disabled: __props.loading || unref(selectableRows).length === 0,
1027
- "aria-label": unref(t)("gr.dataTable.selectAll", "Select all rows"),
1028
- "onUpdate:modelValue": unref(toggleAll)
1029
- }, null, 8, [
1030
- "model-value",
1031
- "indeterminate",
1032
- "size",
1033
- "disabled",
1034
- "aria-label",
1035
- "onUpdate:modelValue"
1036
- ])], 6)) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(unref(orderedColumns), (col, colIndex) => {
1037
- return openBlock(), createElementBlock("th", {
1038
- key: col.key,
1039
- ref_for: true,
1040
- ref: (el) => registerEl(unref(headerCellEls), String(col.key), el),
1041
- class: normalizeClass(["font-700", [
1042
- headerTextClass.value,
1230
+ }, [
1231
+ expandColumnVisible.value ? (openBlock(), createElementBlock("th", {
1232
+ key: 0,
1233
+ "data-gr-datatable-expand-head": "",
1234
+ scope: "col",
1235
+ class: normalizeClass([unref(expandColumnWidths)[unref(resolvedSize)], cellClass.value])
1236
+ }, null, 2)) : createCommentVNode("", true),
1237
+ __props.selectable ? (openBlock(), createElementBlock("th", {
1238
+ key: 1,
1239
+ ref: (el) => registerEl(unref(headerCellEls), unref(SELECT_COLUMN_KEY), el),
1240
+ class: normalizeClass(["text-left", [
1241
+ selectColumnClass.value,
1043
1242
  cellClass.value,
1044
- cellAlign(col),
1045
- __props.reorderableColumns || __props.resizableColumns ? "group relative" : "",
1046
- unref(draggingColumnKey) === String(col.key) ? unref(columnDraggingClass) : "",
1047
- unref(columnDropClass)(colIndex),
1048
- ...unref(pinnedCellClass)(col, colIndex)
1243
+ unref(hasPinnedLeft) ? unref(columnPinnedClass) : ""
1049
1244
  ]]),
1050
- "data-column-key": col.key,
1051
- style: normalizeStyle({
1052
- ...columnWidthStyle(unref(widthOf)(col)),
1053
- ...unref(pinnedStyleOf)(col)
1054
- }),
1055
- "aria-sort": unref(ariaSortFor)(col),
1245
+ style: normalizeStyle(unref(hasPinnedLeft) ? { left: "0px" } : void 0),
1056
1246
  scope: "col"
1057
- }, [createElementVNode("div", { class: normalizeClass(["inline-flex items-center", headerGapClass.value]) }, [__props.reorderableColumns ? (openBlock(), createElementBlock("button", {
1058
- key: 0,
1059
- ref_for: true,
1060
- ref: (el) => registerEl(unref(columnHandleEls), String(col.key), el),
1061
- type: "button",
1062
- "data-gr-datatable-column-handle": "",
1063
- class: normalizeClass([unref(columnHandleClass), unref(columnSort).isActive.value ? unref(columnHandleActiveClass) : ""]),
1064
- tabindex: unref(columnRoving).tabindexFor(String(col.key)),
1065
- "aria-label": columnHandleLabel(col),
1066
- disabled: __props.loading,
1067
- onPointerdown: ($event) => unref(columnSort).startFrom(String(col.key))($event),
1068
- onKeydown: ($event) => unref(onColumnHandleKeydown)($event, String(col.key)),
1069
- onFocus: ($event) => unref(columnRoving).setActive(String(col.key)),
1070
- onClick: _cache[0] || (_cache[0] = withModifiers(() => {}, ["stop"]))
1071
- }, [createVNode(unref(grip_vertical_default), {
1072
- class: "block",
1073
- "aria-hidden": "true"
1074
- })], 42, _hoisted_4)) : createCommentVNode("", true), col.sortable ? (openBlock(), createElementBlock("button", {
1075
- key: 1,
1076
- type: "button",
1077
- "data-gr-datatable-sort": "",
1078
- class: normalizeClass(["inline-flex items-center text-[var(--gr-muted-fg)] hover:text-[var(--gr-fg)] transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)] rounded-[var(--gr-radius-sm)]", headerGapClass.value]),
1079
- onClick: ($event) => unref(toggleSort)(col)
1080
- }, [
1081
- createElementVNode("span", null, [renderSlot(_ctx.$slots, `header-${col.key}`, { column: col }, () => [createTextVNode(toDisplayString(col.label), 1)])]),
1082
- createElementVNode("span", _hoisted_6, toDisplayString(sortHint(col)), 1),
1083
- createElementVNode("span", _hoisted_7, [unref(currentSortKey) === col.key && unref(currentSortDir) === "asc" ? (openBlock(), createBlock(GrIcon_default, {
1247
+ }, [createVNode(GrCheckbox_default, {
1248
+ "data-gr-datatable-select-all": "",
1249
+ "model-value": unref(allSelected),
1250
+ indeterminate: unref(someSelected),
1251
+ size: checkboxSize.value,
1252
+ disabled: __props.loading || unref(selectableRows).length === 0,
1253
+ "aria-label": unref(t)("gr.dataTable.selectAll", "Select all rows"),
1254
+ "onUpdate:modelValue": unref(toggleAll)
1255
+ }, null, 8, [
1256
+ "model-value",
1257
+ "indeterminate",
1258
+ "size",
1259
+ "disabled",
1260
+ "aria-label",
1261
+ "onUpdate:modelValue"
1262
+ ])], 6)) : createCommentVNode("", true),
1263
+ (openBlock(true), createElementBlock(Fragment, null, renderList(unref(orderedColumns), (col, colIndex) => {
1264
+ return openBlock(), createElementBlock("th", {
1265
+ key: col.key,
1266
+ ref_for: true,
1267
+ ref: (el) => registerEl(unref(headerCellEls), String(col.key), el),
1268
+ class: normalizeClass(["font-700", [
1269
+ headerTextClass.value,
1270
+ cellClass.value,
1271
+ cellAlign(col),
1272
+ __props.reorderableColumns || __props.resizableColumns ? "group relative" : "",
1273
+ unref(draggingColumnKey) === String(col.key) ? unref(columnDraggingClass) : "",
1274
+ unref(columnDropClass)(colIndex),
1275
+ ...unref(pinnedCellClass)(col, colIndex)
1276
+ ]]),
1277
+ "data-column-key": col.key,
1278
+ style: normalizeStyle({
1279
+ ...columnWidthStyle(unref(widthOf)(col)),
1280
+ ...unref(pinnedStyleOf)(col)
1281
+ }),
1282
+ "aria-sort": unref(ariaSortFor)(col),
1283
+ scope: "col"
1284
+ }, [createElementVNode("div", { class: normalizeClass(["inline-flex items-center", headerGapClass.value]) }, [__props.reorderableColumns ? (openBlock(), createElementBlock("button", {
1084
1285
  key: 0,
1085
- size: sortIconSize.value
1086
- }, {
1087
- default: withCtx(() => [createVNode(unref(arrow_up_default))]),
1088
- _: 1
1089
- }, 8, ["size"])) : unref(currentSortKey) === col.key && unref(currentSortDir) === "desc" ? (openBlock(), createBlock(GrIcon_default, {
1286
+ ref_for: true,
1287
+ ref: (el) => registerEl(unref(columnHandleEls), String(col.key), el),
1288
+ type: "button",
1289
+ "data-gr-datatable-column-handle": "",
1290
+ class: normalizeClass([unref(columnHandleClass), unref(columnSort).isActive.value ? unref(columnHandleActiveClass) : ""]),
1291
+ tabindex: unref(columnRoving).tabindexFor(String(col.key)),
1292
+ "aria-label": columnHandleLabel(col),
1293
+ disabled: __props.loading,
1294
+ onPointerdown: ($event) => unref(columnSort).startFrom(String(col.key))($event),
1295
+ onKeydown: ($event) => unref(onColumnHandleKeydown)($event, String(col.key)),
1296
+ onFocus: ($event) => unref(columnRoving).setActive(String(col.key)),
1297
+ onClick: _cache[0] || (_cache[0] = withModifiers(() => {}, ["stop"]))
1298
+ }, [createVNode(unref(grip_vertical_default), {
1299
+ class: "block",
1300
+ "aria-hidden": "true"
1301
+ })], 42, _hoisted_4)) : createCommentVNode("", true), col.sortable ? (openBlock(), createElementBlock("button", {
1090
1302
  key: 1,
1091
- size: sortIconSize.value
1092
- }, {
1093
- default: withCtx(() => [createVNode(unref(arrow_down_default))]),
1094
- _: 1
1095
- }, 8, ["size"])) : createCommentVNode("", true)])
1096
- ], 10, _hoisted_5)) : (openBlock(), createElementBlock("span", _hoisted_8, [renderSlot(_ctx.$slots, `header-${col.key}`, { column: col }, () => [createTextVNode(toDisplayString(col.label), 1)])]))], 2), __props.resizableColumns ? (openBlock(), createElementBlock("span", {
1097
- key: 0,
1098
- "data-gr-datatable-column-resizer": "",
1099
- role: "separator",
1100
- tabindex: "0",
1101
- "aria-orientation": "vertical",
1102
- class: normalizeClass(unref(columnResizerClass)),
1103
- "aria-label": resizerLabel(col),
1104
- "aria-valuenow": unref(resizerValue)(col),
1105
- "aria-valuemin": unref(48),
1106
- "aria-valuetext": `${unref(resizerValue)(col)}px`,
1107
- onPointerdown: ($event) => unref(onResizerPointerDown)($event, String(col.key)),
1108
- onKeydown: ($event) => unref(onResizerKeydown)($event, String(col.key)),
1109
- onDblclick: ($event) => unref(resetColumnWidth)(String(col.key)),
1110
- onClick: _cache[1] || (_cache[1] = withModifiers(() => {}, ["stop"]))
1111
- }, [createElementVNode("span", {
1112
- class: normalizeClass([
1113
- unref(columnResizerLineClass),
1114
- unref(columnResizerHoverClass),
1115
- unref(resizingKey) === String(col.key) ? unref(columnResizerLineActiveClass) : ""
1116
- ]),
1117
- "aria-hidden": "true"
1118
- }, null, 2)], 42, _hoisted_9)) : createCommentVNode("", true)], 14, _hoisted_3);
1119
- }), 128))], 8, _hoisted_2)]),
1303
+ type: "button",
1304
+ "data-gr-datatable-sort": "",
1305
+ class: normalizeClass(["inline-flex items-center text-[var(--gr-muted-fg)] hover:text-[var(--gr-fg)] transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)] rounded-[var(--gr-radius-sm)]", headerGapClass.value]),
1306
+ onClick: ($event) => unref(toggleSort)(col)
1307
+ }, [
1308
+ createElementVNode("span", null, [renderSlot(_ctx.$slots, `header-${col.key}`, { column: col }, () => [createTextVNode(toDisplayString(col.label), 1)])]),
1309
+ createElementVNode("span", _hoisted_6, toDisplayString(sortHint(col)), 1),
1310
+ createElementVNode("span", _hoisted_7, [unref(currentSortKey) === col.key && unref(currentSortDir) === "asc" ? (openBlock(), createBlock(GrIcon_default, {
1311
+ key: 0,
1312
+ size: sortIconSize.value
1313
+ }, {
1314
+ default: withCtx(() => [createVNode(unref(arrow_up_default))]),
1315
+ _: 1
1316
+ }, 8, ["size"])) : unref(currentSortKey) === col.key && unref(currentSortDir) === "desc" ? (openBlock(), createBlock(GrIcon_default, {
1317
+ key: 1,
1318
+ size: sortIconSize.value
1319
+ }, {
1320
+ default: withCtx(() => [createVNode(unref(arrow_down_default))]),
1321
+ _: 1
1322
+ }, 8, ["size"])) : createCommentVNode("", true)])
1323
+ ], 10, _hoisted_5)) : (openBlock(), createElementBlock("span", _hoisted_8, [renderSlot(_ctx.$slots, `header-${col.key}`, { column: col }, () => [createTextVNode(toDisplayString(col.label), 1)])]))], 2), __props.resizableColumns ? (openBlock(), createElementBlock("span", {
1324
+ key: 0,
1325
+ "data-gr-datatable-column-resizer": "",
1326
+ role: "separator",
1327
+ tabindex: "0",
1328
+ "aria-orientation": "vertical",
1329
+ class: normalizeClass(unref(columnResizerClass)),
1330
+ "aria-label": resizerLabel(col),
1331
+ "aria-valuenow": unref(resizerValue)(col),
1332
+ "aria-valuemin": unref(48),
1333
+ "aria-valuetext": `${unref(resizerValue)(col)}px`,
1334
+ onPointerdown: ($event) => unref(onResizerPointerDown)($event, String(col.key)),
1335
+ onKeydown: ($event) => unref(onResizerKeydown)($event, String(col.key)),
1336
+ onDblclick: ($event) => unref(resetColumnWidth)(String(col.key)),
1337
+ onClick: _cache[1] || (_cache[1] = withModifiers(() => {}, ["stop"]))
1338
+ }, [createElementVNode("span", {
1339
+ class: normalizeClass([
1340
+ unref(columnResizerLineClass),
1341
+ unref(columnResizerHoverClass),
1342
+ unref(resizingKey) === String(col.key) ? unref(columnResizerLineActiveClass) : ""
1343
+ ]),
1344
+ "aria-hidden": "true"
1345
+ }, null, 2)], 42, _hoisted_9)) : createCommentVNode("", true)], 14, _hoisted_3);
1346
+ }), 128))
1347
+ ], 8, _hoisted_2)]),
1120
1348
  default: withCtx(() => [__props.loading ? (openBlock(), createElementBlock("tr", _hoisted_10, [createElementVNode("td", {
1121
1349
  colspan: totalColumns.value,
1122
1350
  class: normalizeClass(["text-center text-[var(--gr-muted-fg)]", placeholderClass.value])
@@ -1136,8 +1364,7 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
1136
1364
  })
1137
1365
  }, null, 12, _hoisted_16)])) : createCommentVNode("", true),
1138
1366
  (openBlock(true), createElementBlock(Fragment, null, renderList(renderedRows.value, ({ row, index }) => {
1139
- return openBlock(), createElementBlock("tr", mergeProps({
1140
- key: unref(rowKeyValue)(row),
1367
+ return openBlock(), createElementBlock(Fragment, { key: unref(rowKeyValue)(row) }, [createElementVNode("tr", mergeProps({
1141
1368
  ref_for: true,
1142
1369
  ref: (el) => __props.virtual && unref(virtualizer).measure(index, el),
1143
1370
  class: ["border-t border-[var(--gr-brd)]", [unref(isRowSelected)(row) ? unref(rowSelectedClass) : "", rowClassName(row, index)]],
@@ -1145,55 +1372,106 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
1145
1372
  "data-row-key": unref(rowKeyValue)(row),
1146
1373
  "data-selected": __props.selectable && unref(isRowSelected)(row) ? "true" : void 0,
1147
1374
  "aria-rowindex": ariaRowIndex(index)
1148
- }, { ref_for: true }, __props.rowProps?.(row, index), { onClick: ($event) => onRowClick(row, index, $event) }), [__props.selectable ? (openBlock(), createElementBlock("td", {
1149
- key: 0,
1150
- class: normalizeClass(["text-left", [
1151
- selectColumnClass.value,
1152
- cellClass.value,
1153
- unref(hasPinnedLeft) ? unref(columnPinnedClass) : "",
1154
- unref(hasPinnedLeft) && unref(isRowSelected)(row) ? unref(rowSelectedClass) : ""
1155
- ]]),
1156
- style: normalizeStyle(unref(hasPinnedLeft) ? { left: "0px" } : void 0)
1157
- }, [unref(isRowSelectable)(row) ? (openBlock(), createBlock(GrCheckbox_default, {
1158
- key: 0,
1159
- "data-gr-datatable-select-row": "",
1160
- "model-value": unref(isRowSelected)(row),
1161
- size: checkboxSize.value,
1162
- "aria-label": unref(t)("gr.dataTable.selectRow", "Select row"),
1163
- onClick: _cache[2] || (_cache[2] = withModifiers(() => {}, ["stop"])),
1164
- "onUpdate:modelValue": ($event) => unref(toggleRow)(row)
1165
- }, null, 8, [
1166
- "model-value",
1167
- "size",
1168
- "aria-label",
1169
- "onUpdate:modelValue"
1170
- ])) : createCommentVNode("", true)], 6)) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(unref(orderedColumns), (col, colIndex) => {
1171
- return openBlock(), createElementBlock("td", {
1172
- key: col.key,
1173
- class: normalizeClass([
1375
+ }, { ref_for: true }, __props.rowProps?.(row, index), { onClick: ($event) => onRowClick(row, index, $event) }), [
1376
+ expandColumnVisible.value ? (openBlock(), createElementBlock("td", {
1377
+ key: 0,
1378
+ "data-gr-datatable-expand-cell": "",
1379
+ class: normalizeClass(["text-left", [unref(expandColumnWidths)[unref(resolvedSize)], cellClass.value]])
1380
+ }, [unref(isRowExpandable)(row) ? (openBlock(), createElementBlock("button", {
1381
+ key: 0,
1382
+ type: "button",
1383
+ "data-gr-datatable-expand": "",
1384
+ class: normalizeClass([unref(expandButtonClass), checkboxSize.value === "xs" ? "h-5 w-5" : "h-6 w-6"]),
1385
+ "aria-expanded": unref(isRowExpanded)(row),
1386
+ "aria-controls": detailRowId(row),
1387
+ "aria-label": unref(isRowExpanded)(row) ? unref(t)("gr.dataTable.collapseRow", "Hide details") : unref(t)("gr.dataTable.expandRow", "Show details"),
1388
+ onClick: withModifiers(($event) => unref(toggleRowExpanded)(row), ["stop"])
1389
+ }, [renderSlot(_ctx.$slots, "expand-icon", {
1390
+ expanded: unref(isRowExpanded)(row),
1391
+ row
1392
+ }, () => [createVNode(unref(chevron_right_default), { class: normalizeClass([unref(expandIconClass), unref(isRowExpanded)(row) ? unref(expandIconOpenClass) : ""]) }, null, 8, ["class"])])], 10, _hoisted_18)) : createCommentVNode("", true)], 2)) : createCommentVNode("", true),
1393
+ __props.selectable ? (openBlock(), createElementBlock("td", {
1394
+ key: 1,
1395
+ class: normalizeClass(["text-left", [
1396
+ selectColumnClass.value,
1174
1397
  cellClass.value,
1175
- cellAlign(col),
1176
- ...unref(pinnedCellClass)(col, colIndex),
1177
- col.pinned && unref(isRowSelected)(row) ? unref(rowSelectedClass) : ""
1178
- ]),
1179
- style: normalizeStyle({
1180
- ...columnWidthStyle(unref(widthOf)(col)),
1181
- ...unref(pinnedStyleOf)(col)
1182
- })
1183
- }, [renderSlot(_ctx.$slots, `cell-${col.key}`, {
1184
- row,
1185
- index
1186
- }, () => [createElementVNode("span", null, toDisplayString(cellValue(row, col.key)), 1)])], 6);
1187
- }), 128))], 16, _hoisted_17);
1398
+ unref(hasPinnedLeft) ? unref(columnPinnedClass) : "",
1399
+ unref(hasPinnedLeft) && unref(isRowSelected)(row) ? unref(rowSelectedClass) : ""
1400
+ ]]),
1401
+ style: normalizeStyle(unref(hasPinnedLeft) ? { left: "0px" } : void 0)
1402
+ }, [unref(isRowSelectable)(row) ? (openBlock(), createBlock(GrCheckbox_default, {
1403
+ key: 0,
1404
+ "data-gr-datatable-select-row": "",
1405
+ "model-value": unref(isRowSelected)(row),
1406
+ size: checkboxSize.value,
1407
+ "aria-label": unref(t)("gr.dataTable.selectRow", "Select row"),
1408
+ onClick: _cache[2] || (_cache[2] = withModifiers(() => {}, ["stop"])),
1409
+ "onUpdate:modelValue": ($event) => unref(toggleRow)(row)
1410
+ }, null, 8, [
1411
+ "model-value",
1412
+ "size",
1413
+ "aria-label",
1414
+ "onUpdate:modelValue"
1415
+ ])) : createCommentVNode("", true)], 6)) : createCommentVNode("", true),
1416
+ (openBlock(true), createElementBlock(Fragment, null, renderList(unref(orderedColumns), (col, colIndex) => {
1417
+ return openBlock(), createElementBlock("td", {
1418
+ key: col.key,
1419
+ class: normalizeClass([
1420
+ cellClass.value,
1421
+ cellAlign(col),
1422
+ ...unref(pinnedCellClass)(col, colIndex),
1423
+ col.pinned && unref(isRowSelected)(row) ? unref(rowSelectedClass) : ""
1424
+ ]),
1425
+ style: normalizeStyle({
1426
+ ...columnWidthStyle(unref(widthOf)(col)),
1427
+ ...unref(pinnedStyleOf)(col)
1428
+ })
1429
+ }, [renderSlot(_ctx.$slots, `cell-${col.key}`, {
1430
+ row,
1431
+ index,
1432
+ expanded: unref(isRowExpanded)(row),
1433
+ toggleExpand: () => unref(toggleRowExpanded)(row)
1434
+ }, () => [createElementVNode("span", null, toDisplayString(cellValue(row, col.key)), 1)])], 6);
1435
+ }), 128))
1436
+ ], 16, _hoisted_17), unref(isRowExpanded)(row) ? (openBlock(), createElementBlock("tr", {
1437
+ key: 0,
1438
+ id: detailRowId(row),
1439
+ "data-gr-datatable-detail": "",
1440
+ "data-gr-table-off-grid": "",
1441
+ class: normalizeClass(unref(detailRowClass))
1442
+ }, [createElementVNode("td", {
1443
+ colspan: totalColumns.value,
1444
+ class: normalizeClass([unref(detailCellClass), unref(detailPaddings)[unref(resolvedSize)]])
1445
+ }, [createElementVNode("div", { class: normalizeClass(unref(detailContentClass)) }, [unref(detailStateOf)(row) === "loading" ? (openBlock(), createElementBlock("div", _hoisted_21, [renderSlot(_ctx.$slots, "detail-loading", { row }, () => [createVNode(GrSkeleton_default, { count: 2 })])])) : unref(detailStateOf)(row) === "error" ? (openBlock(), createElementBlock("div", {
1446
+ key: 1,
1447
+ class: normalizeClass(unref(detailErrorClass)),
1448
+ "data-gr-datatable-detail-error": ""
1449
+ }, [renderSlot(_ctx.$slots, "detail-error", {
1450
+ row,
1451
+ retry: () => unref(retryDetail)(row)
1452
+ }, () => [createElementVNode("span", null, toDisplayString(unref(t)("gr.dataTable.detailError", "Could not load details")), 1), createVNode(GrButton_default, {
1453
+ size: "xs",
1454
+ tone: "danger",
1455
+ variant: "outline",
1456
+ onClick: ($event) => unref(retryDetail)(row)
1457
+ }, {
1458
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(t)("gr.dataTable.detailRetry", "Retry")), 1)]),
1459
+ _: 1
1460
+ }, 8, ["onClick"])])], 2)) : renderSlot(_ctx.$slots, "detail", {
1461
+ row,
1462
+ index,
1463
+ data: unref(detailDataOf)(row),
1464
+ state: unref(detailStateOf)(row)
1465
+ }, void 0, void 0, 2)], 2)], 10, _hoisted_20)], 10, _hoisted_19)) : createCommentVNode("", true)], 64);
1188
1466
  }), 128)),
1189
- __props.virtual && spacerAfter.value > 0 ? (openBlock(), createElementBlock("tr", _hoisted_18, [createElementVNode("td", {
1467
+ __props.virtual && spacerAfter.value > 0 ? (openBlock(), createElementBlock("tr", _hoisted_22, [createElementVNode("td", {
1190
1468
  colspan: totalColumns.value,
1191
1469
  style: normalizeStyle({
1192
1470
  height: `${spacerAfter.value}px`,
1193
1471
  padding: "0",
1194
1472
  border: "0"
1195
1473
  })
1196
- }, null, 12, _hoisted_19)])) : createCommentVNode("", true)
1474
+ }, null, 12, _hoisted_23)])) : createCommentVNode("", true)
1197
1475
  ], 64))]),
1198
1476
  _: 2
1199
1477
  }, [_ctx.$slots.footer || hasSummary.value ? {
@@ -1227,8 +1505,8 @@ var GrDataTable_default = /* @__PURE__ */ defineComponent({
1227
1505
  }, [renderSlot(_ctx.$slots, `summary-${col.key}`, {
1228
1506
  value: summaryValue(col.key),
1229
1507
  column: col
1230
- }, () => [createElementVNode("span", null, toDisplayString(summaryValue(col.key)), 1)])], 14, _hoisted_21);
1231
- }), 128))], 10, _hoisted_20)) : createCommentVNode("", true), renderSlot(_ctx.$slots, "footer", {
1508
+ }, () => [createElementVNode("span", null, toDisplayString(summaryValue(col.key)), 1)])], 14, _hoisted_25);
1509
+ }), 128))], 10, _hoisted_24)) : createCommentVNode("", true), renderSlot(_ctx.$slots, "footer", {
1232
1510
  columns: unref(orderedColumns),
1233
1511
  totalColumns: totalColumns.value
1234
1512
  })]),