@fkui/vue-labs 6.24.1 → 6.25.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.
@@ -3685,6 +3685,131 @@ function normalizeTableColumns(columns) {
3685
3685
  return normalizeTableColumn(column);
3686
3686
  });
3687
3687
  }
3688
+ function useTabstop(tableRef, metaRows) {
3689
+ let pendingRowRemoval = false;
3690
+ const renderOptions = vue.ref({
3691
+ fallbackToFirstCell: false,
3692
+ focus: false
3693
+ });
3694
+ function fallbackToFirstCell(newRows, oldRows, focus) {
3695
+ logic.assertRef(tableRef);
3696
+ const newFirstRowOldIndex = oldRows.findIndex((it) => it.key === newRows[0].key);
3697
+ if (newFirstRowOldIndex > -1) {
3698
+ const target = getCellTarget(tableRef.value, newFirstRowOldIndex + 1, 0);
3699
+ activateCell(target, {
3700
+ focus
3701
+ });
3702
+ } else {
3703
+ renderOptions.value.focus = focus;
3704
+ renderOptions.value.fallbackToFirstCell = true;
3705
+ }
3706
+ }
3707
+ vue.watch(metaRows, (newRows, oldRows) => {
3708
+ const tabFallback = pendingRowRemoval ? "sticky" : "first-cell";
3709
+ pendingRowRemoval = false;
3710
+ logic.assertRef(tableRef);
3711
+ const oldTabstopElement = tableRef.value.querySelector(`[tabindex="0"]`);
3712
+ logic.assertSet(oldTabstopElement);
3713
+ const oldTabstopFocused = oldTabstopElement === document.activeElement;
3714
+ if (oldTabstopElement.closest("th")) {
3715
+ return;
3716
+ }
3717
+ if (oldRows.length === 0 || newRows.length === 0) {
3718
+ renderOptions.value.fallbackToFirstCell = true;
3719
+ renderOptions.value.focus = oldTabstopFocused;
3720
+ return;
3721
+ }
3722
+ const oldTabstopTd = oldTabstopElement.closest("td");
3723
+ logic.assertSet(oldTabstopTd);
3724
+ const oldTabstopTr = oldTabstopTd.parentElement;
3725
+ const oldTabstopRowKey = oldRows[oldTabstopTr.rowIndex - 1].key;
3726
+ const isBeingRemoved = !newRows.some((it) => it.key === oldTabstopRowKey);
3727
+ if (oldTabstopFocused && !isBeingRemoved) {
3728
+ return;
3729
+ }
3730
+ if (!isBeingRemoved) {
3731
+ if (oldTabstopFocused) {
3732
+ return;
3733
+ } else {
3734
+ fallbackToFirstCell(newRows, oldRows, false);
3735
+ return;
3736
+ }
3737
+ }
3738
+ if (tabFallback === "first-cell") {
3739
+ fallbackToFirstCell(newRows, oldRows, oldTabstopFocused);
3740
+ return;
3741
+ }
3742
+ if (oldTabstopTr.rowIndex === 1) {
3743
+ const hasRowBelowInNewRows = newRows.some((it) => it.key === oldRows[1].key);
3744
+ if (hasRowBelowInNewRows) {
3745
+ const {
3746
+ cell
3747
+ } = getVerticalNavIndex(tableRef.value, {
3748
+ row: 1,
3749
+ cell: oldTabstopTd.cellIndex
3750
+ }, {
3751
+ row: 2,
3752
+ cell: oldTabstopTd.cellIndex
3753
+ });
3754
+ const fallback = getCellTarget(tableRef.value, 2, cell);
3755
+ activateCell(fallback, {
3756
+ focus: true
3757
+ });
3758
+ } else {
3759
+ fallbackToFirstCell(newRows, oldRows, true);
3760
+ }
3761
+ } else {
3762
+ const hasRowAboveInNewRows = newRows.some((it) => it.key === oldRows[oldTabstopTr.rowIndex - 2].key);
3763
+ if (hasRowAboveInNewRows) {
3764
+ const {
3765
+ row,
3766
+ cell
3767
+ } = getVerticalNavIndex(tableRef.value, {
3768
+ row: oldTabstopTr.rowIndex,
3769
+ cell: oldTabstopTd.cellIndex
3770
+ }, {
3771
+ row: oldTabstopTr.rowIndex - 1,
3772
+ cell: oldTabstopTd.cellIndex
3773
+ });
3774
+ const fallback = getCellTarget(tableRef.value, row, cell);
3775
+ activateCell(fallback, {
3776
+ focus: true
3777
+ });
3778
+ } else {
3779
+ fallbackToFirstCell(newRows, oldRows, true);
3780
+ }
3781
+ }
3782
+ });
3783
+ vue.onUpdated(() => {
3784
+ if (!renderOptions.value.fallbackToFirstCell) {
3785
+ return;
3786
+ }
3787
+ logic.assertRef(tableRef);
3788
+ const target = getCellTarget(tableRef.value, 1, 0);
3789
+ if (metaRows.value.length === 0) {
3790
+ target.tabIndex = 0;
3791
+ target.focus();
3792
+ } else {
3793
+ activateCell(target, {
3794
+ focus: renderOptions.value.focus
3795
+ });
3796
+ }
3797
+ renderOptions.value.fallbackToFirstCell = false;
3798
+ });
3799
+ async function withTabstopBehaviour(behaviour, action) {
3800
+ if (behaviour === "row-removal") {
3801
+ pendingRowRemoval = true;
3802
+ }
3803
+ try {
3804
+ await action();
3805
+ } finally {
3806
+ pendingRowRemoval = false;
3807
+ }
3808
+ }
3809
+ return {
3810
+ withTabstopBehaviour
3811
+ };
3812
+ }
3688
3813
  const _hoisted_1 = ["role", "aria-rowcount"];
3689
3814
  const _hoisted_2 = {
3690
3815
  class: "table-ng__row",
@@ -3730,7 +3855,9 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
3730
3855
  "selectedRowsModifiers": {}
3731
3856
  }),
3732
3857
  emits: ["update:selectedRows"],
3733
- setup(__props) {
3858
+ setup(__props, {
3859
+ expose: __expose
3860
+ }) {
3734
3861
  const selectedRows = vue.useModel(__props, "selectedRows");
3735
3862
  const $t = vue$1.useTranslate();
3736
3863
  const tableRef = vue.useTemplateRef("table");
@@ -3860,6 +3987,14 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
3860
3987
  });
3861
3988
  }
3862
3989
  }
3990
+ function onTableFocusin(e) {
3991
+ logic.assertRef(tableRef);
3992
+ tableRef.value.querySelectorAll(`[tabindex="0"]`).forEach((it) => {
3993
+ if (it !== e.target) {
3994
+ it.setAttribute("tabindex", "-1");
3995
+ }
3996
+ });
3997
+ }
3863
3998
  function isInExpandable(el) {
3864
3999
  if (!el.parentElement) {
3865
4000
  return false;
@@ -3878,7 +4013,9 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
3878
4013
  if (isInExpandable(target)) {
3879
4014
  return;
3880
4015
  }
3881
- logic.assertRef(tableRef);
4016
+ if (!tableRef.value) {
4017
+ return;
4018
+ }
3882
4019
  const outsideTable = !relatedTarget || !tableRef.value.contains(relatedTarget);
3883
4020
  if (outsideTable) {
3884
4021
  const td = target.closest("td");
@@ -3949,6 +4086,8 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
3949
4086
  bindCellApiRef(ref2);
3950
4087
  selectAllRef.value = vue.toValue(ref2.tabstopEl);
3951
4088
  }
4089
+ const tableApi = useTabstop(tableRef, metaRows);
4090
+ __expose(tableApi);
3952
4091
  vue.onMounted(() => {
3953
4092
  logic.assertRef(tableRef);
3954
4093
  registerCallbackOnMount(callbackSortableColumns);
@@ -3961,6 +4100,7 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
3961
4100
  role: role.value,
3962
4101
  class: vue.normalizeClass(tableClasses.value),
3963
4102
  "aria-rowcount": ariaRowcount.value,
4103
+ onFocusin: onTableFocusin,
3964
4104
  onFocusout: onTableFocusout,
3965
4105
  onClick,
3966
4106
  onKeydown