bootstrap-vue-next
Version:
Seamless integration of Vue 3, Bootstrap 5, and TypeScript for modern, type-safe UI development
1,264 lines • 68.3 kB
JavaScript
require("./chunk-CoQrYLCe.js");
const require_keys = require("./keys-durSVUrO.js");
const require_dist = require("./dist-B_c893QG.js");
const require_dom = require("./dom-Bs6DzM72.js");
const require_useId = require("./useId-DTrBK9CE.js");
const require_useDefaults = require("./useDefaults-DK6Y9lar.js");
const require_object = require("./object-CPeShLVx.js");
require("./constants-DMR5FAE3.js");
const require_stringUtils = require("./stringUtils-hUreqC0N.js");
require("./src/types/index.umd.js");
const require_debounce = require("./debounce-BfDJWP7y.js");
const require_BTableSimple = require("./BTableSimple-fwaF0Kws.js");
let vue = require("vue");
//#region src/types/TableTypes.ts
var isTableItem = (value) => typeof value === "object" && value !== null;
var isTableField = (value) => typeof value === "object" && value !== null && "key" in value;
//#endregion
//#region src/components/BTable/BTbody.vue
var BTbody_default = /* @__PURE__ */ (0, vue.defineComponent)({
__name: "BTbody",
props: { variant: { default: null } },
setup(__props) {
const props = require_useDefaults.useDefaults(__props, "BTbody");
const computedClasses = (0, vue.computed)(() => ({ [`thead-${props.variant}`]: props.variant !== null }));
return (_ctx, _cache) => {
return (0, vue.openBlock)(), (0, vue.createElementBlock)("tbody", { class: (0, vue.normalizeClass)(computedClasses.value) }, [(0, vue.renderSlot)(_ctx.$slots, "default")], 2);
};
}
});
//#endregion
//#region src/components/BTable/BTd.vue?vue&type=script&setup=true&lang.ts
var _hoisted_1$3 = [
"colspan",
"rowspan",
"data-label"
];
var _hoisted_2$3 = { key: 0 };
//#endregion
//#region src/components/BTable/BTd.vue
var BTd_default = /* @__PURE__ */ (0, vue.defineComponent)({
__name: "BTd",
props: {
colspan: { default: void 0 },
rowspan: { default: void 0 },
stackedHeading: { default: void 0 },
stickyColumn: {
type: Boolean,
default: false
},
variant: { default: null }
},
setup(__props) {
const props = require_useDefaults.useDefaults(__props, "BTd");
const computedClasses = (0, vue.computed)(() => ({
[`table-${props.variant}`]: props.variant !== null,
"b-table-sticky-column": props.stickyColumn,
"table-b-table-default": props.stickyColumn && props.variant === null
}));
return (_ctx, _cache) => {
return (0, vue.openBlock)(), (0, vue.createElementBlock)("td", {
class: (0, vue.normalizeClass)(computedClasses.value),
colspan: (0, vue.unref)(props).colspan,
rowspan: (0, vue.unref)(props).rowspan,
"data-label": (0, vue.unref)(props).stackedHeading
}, [(0, vue.unref)(props).stackedHeading ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$3, [(0, vue.renderSlot)(_ctx.$slots, "default")])) : (0, vue.renderSlot)(_ctx.$slots, "default", { key: 1 })], 10, _hoisted_1$3);
};
}
});
//#endregion
//#region src/components/BTable/BTfoot.vue
var BTfoot_default = /* @__PURE__ */ (0, vue.defineComponent)({
__name: "BTfoot",
props: { variant: { default: null } },
setup(__props) {
const props = require_useDefaults.useDefaults(__props, "BTfoot");
const computedClasses = (0, vue.computed)(() => ({ [`table-${props.variant}`]: props.variant !== null }));
return (_ctx, _cache) => {
return (0, vue.openBlock)(), (0, vue.createElementBlock)("tfoot", { class: (0, vue.normalizeClass)(computedClasses.value) }, [(0, vue.renderSlot)(_ctx.$slots, "default")], 2);
};
}
});
//#endregion
//#region src/components/BTable/BTh.vue?vue&type=script&setup=true&lang.ts
var _hoisted_1$2 = [
"scope",
"colspan",
"rowspan",
"data-label"
];
var _hoisted_2$2 = { key: 0 };
//#endregion
//#region src/components/BTable/BTh.vue
var BTh_default = /* @__PURE__ */ (0, vue.defineComponent)({
__name: "BTh",
props: {
colspan: { default: void 0 },
rowspan: { default: void 0 },
stackedHeading: { default: void 0 },
stickyColumn: {
type: Boolean,
default: false
},
variant: { default: null },
scope: { default: void 0 }
},
setup(__props) {
const props = require_useDefaults.useDefaults(__props, "BTh");
const computedClasses = (0, vue.computed)(() => ({
[`table-${props.variant}`]: props.variant !== null,
"b-table-sticky-column": props.stickyColumn,
"table-b-table-default": props.stickyColumn && props.variant === null
}));
const localScope = (0, vue.computed)(() => props.scope ? props.scope : props.colspan ? "colgroup" : props.rowspan ? "rowgroup" : "col");
return (_ctx, _cache) => {
return (0, vue.openBlock)(), (0, vue.createElementBlock)("th", {
scope: localScope.value,
class: (0, vue.normalizeClass)(computedClasses.value),
colspan: (0, vue.unref)(props).colspan,
rowspan: (0, vue.unref)(props).rowspan,
"data-label": (0, vue.unref)(props).stackedHeading
}, [(0, vue.unref)(props).stackedHeading !== void 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$2, [(0, vue.renderSlot)(_ctx.$slots, "default")])) : (0, vue.renderSlot)(_ctx.$slots, "default", { key: 1 })], 10, _hoisted_1$2);
};
}
});
//#endregion
//#region src/components/BTable/BThead.vue
var BThead_default = /* @__PURE__ */ (0, vue.defineComponent)({
__name: "BThead",
props: { variant: { default: null } },
setup(__props) {
const props = require_useDefaults.useDefaults(__props, "BThead");
const computedClasses = (0, vue.computed)(() => ({ [`table-${props.variant}`]: props.variant !== null }));
return (_ctx, _cache) => {
return (0, vue.openBlock)(), (0, vue.createElementBlock)("thead", { class: (0, vue.normalizeClass)(computedClasses.value) }, [(0, vue.renderSlot)(_ctx.$slots, "default")], 2);
};
}
});
//#endregion
//#region src/components/BTable/BTr.vue
var BTr_default = /* @__PURE__ */ (0, vue.defineComponent)({
__name: "BTr",
props: { variant: { default: null } },
setup(__props) {
const props = require_useDefaults.useDefaults(__props, "BTr");
const computedClasses = (0, vue.computed)(() => ({ [`table-${props.variant}`]: props.variant !== null }));
return (_ctx, _cache) => {
return (0, vue.openBlock)(), (0, vue.createElementBlock)("tr", { class: (0, vue.normalizeClass)(computedClasses.value) }, [(0, vue.renderSlot)(_ctx.$slots, "default")], 2);
};
}
});
//#endregion
//#region src/utils/tableUtils.ts
var getTableFieldHeadLabel = (field) => typeof field === "string" ? require_stringUtils.titleCase(field) : field.label !== void 0 ? field.label : require_stringUtils.titleCase(field.key);
var getWithGetter = (item, key) => {
if (typeof key === "function") return key(item);
return item[key];
};
var getByFieldKey = (item, field) => typeof item === "object" && item !== null ? getWithGetter(item, field.accessor ?? field.key) : item;
var formatItem = (item, field) => {
const val = getByFieldKey(item, field);
return typeof field.formatter === "function" ? field.formatter({
value: val,
key: field.key,
item
}) : val;
};
var bTableSimpleProps = Object.freeze(Object.keys({
bordered: 0,
borderless: 0,
borderVariant: 0,
captionTop: 0,
dark: 0,
fixed: 0,
hover: 0,
id: 0,
noBorderCollapse: 0,
outlined: 0,
responsive: 0,
small: 0,
stacked: 0,
stickyHeader: 0,
striped: 0,
stripedColumns: 0,
variant: 0,
tableAttrs: 0,
tableClass: 0
}));
var bTableLiteProps = Object.freeze(Object.keys({
align: 0,
caption: 0,
detailsTdClass: 0,
fieldColumnClass: 0,
fields: 0,
footClone: 0,
footRowVariant: 0,
footVariant: 0,
headRowVariant: 0,
headVariant: 0,
items: 0,
labelStacked: 0,
modelValue: 0,
primaryKey: 0,
tbodyClass: 0,
tbodyTrAttrs: 0,
tbodyTrClass: 0,
tfootClass: 0,
expandedItems: 0,
tfootTrClass: 0,
theadClass: 0,
theadTrClass: 0
}));
var getDataLabelAttr = (props, label) => props.stacked && props.labelStacked !== true ? { "data-label": label } : void 0;
//#endregion
//#region src/utils/filterEvent.ts
var TABLE_TAG_NAMES = [
"TD",
"TH",
"TR"
];
var eventFilter = [
"a",
"a *",
"button",
"button *",
"input:not(.disabled):not([disabled])",
"select:not(.disabled):not([disabled])",
"textarea:not(.disabled):not([disabled])",
"[role=\"link\"]",
"[role=\"link\"] *",
"[role=\"button\"]",
"[role=\"button\"] *",
"[tabindex]:not(.disabled):not([disabled])"
].join(",");
var filterEvent = (event) => {
if (!event || !event.target) return false;
const el = event.target;
if ("disabled" in el && el.disabled || TABLE_TAG_NAMES.indexOf(el.tagName) !== -1) return false;
if (el.closest(".dropdown-menu")) return true;
const label = el.tagName === "LABEL" ? el : el.closest("label");
if (label) {
const doc = require_dom.getSafeDocument();
const labelFor = label.getAttribute("for");
const input = labelFor ? doc?.getElementById(labelFor) : label.querySelector("input, select, textarea");
if (input && !input.disabled) return true;
}
return el.matches(eventFilter);
};
//#endregion
//#region src/composables/useTableLiteHelpers.ts
var useTableFieldsMapper = ({ fields, items, stackedProps }) => {
const computedFields = (0, vue.computed)(() => {
const fieldsValue = (0, vue.toValue)(fields);
const itemsValue = (0, vue.toValue)(items);
const stacked = {
stacked: (0, vue.toValue)(stackedProps.stacked),
labelStacked: (0, vue.toValue)(stackedProps.labelStacked)
};
if (!fieldsValue.length && itemsValue.length) {
const [firstItem] = itemsValue;
if (firstItem && (isTableItem(firstItem) || Array.isArray(firstItem))) return { items: Object.keys(firstItem).map((k) => {
const label = require_stringUtils.startCase(k);
return {
key: k,
label,
tdAttr: getDataLabelAttr(stacked, label)
};
}) };
return {
items: [{ key: "" }],
opts: { noHeader: true }
};
}
return { items: fieldsValue.map((f) => {
if (isTableField(f)) {
const dataLabelAttr = getDataLabelAttr(stacked, f.label ?? require_stringUtils.startCase(f.key));
const tdAttr = typeof f.tdAttr === "function" ? (obj) => ({
...dataLabelAttr,
...f.tdAttr(obj)
}) : dataLabelAttr || f.tdAttr ? {
...dataLabelAttr,
...f.tdAttr
} : void 0;
return {
...f,
tdAttr
};
}
const label = require_stringUtils.startCase(f);
return {
key: f,
label,
tdAttr: getDataLabelAttr(stacked, label)
};
}) };
});
const total = (0, vue.computed)(() => computedFields.value.items.length);
return {
total,
showHeaders: (0, vue.computed)(() => !(total.value > 0 && computedFields.value.opts?.noHeader === true)),
fields: (0, vue.computed)(() => computedFields.value.items)
};
};
var useItemTracker = ({ allItems, selectedItems, primaryKey }) => {
const isActivated = (0, vue.computed)(() => selectedItems.value.length > 0);
const pKey = (0, vue.readonly)((0, vue.toRef)(primaryKey));
const get = (item) => {
if (typeof item === "object" && item !== null && pKey.value) return getWithGetter(item, pKey.value);
return item;
};
const add = (item) => {
const value = get(item);
selectedItems.value = [...selectedItems.value, value];
};
const set = (items) => {
selectedItems.value = pKey.value ? items.map(get) : items;
};
const setAll = () => set([...(0, vue.toValue)(allItems)]);
const remove = (item) => {
const value = get(item);
selectedItems.value = selectedItems.value.filter((i) => i !== value);
};
const clear = () => {
selectedItems.value = [];
};
const has = (item) => {
const value = get(item);
return selectedItems.value.includes(value);
};
(0, vue.watch)(pKey, () => {
clear();
});
const objectsMap = (0, vue.computed)(() => {
if (!pKey.value) return /* @__PURE__ */ new Map();
return new Map((0, vue.toValue)(allItems).map((item) => [get(item), item]));
});
const getFromPrimaryKey = (value) => {
if (!pKey.value) return void 0;
return objectsMap.value.get(value);
};
return {
getFromPrimaryKey,
resolvedItems: (0, vue.computed)(() => {
if (!pKey.value) return selectedItems.value;
const arr = [];
selectedItems.value.forEach((item) => {
const resolved = getFromPrimaryKey(item);
if (resolved !== void 0) arr.push(resolved);
});
return arr;
}),
isActivated,
get,
add,
remove,
clear,
set,
has,
setAll
};
};
var useItemExpansion = ({ allItems, primaryKey, expandedItems }) => {
const utils = useItemTracker({
primaryKey,
allItems,
selectedItems: expandedItems
});
const toggle = (item) => {
if (utils.has(item)) utils.remove(item);
else utils.add(item);
};
return {
...utils,
toggle
};
};
var useTableKeyboardNavigation = ({ items, id }, events) => {
const keyboardNavigation = (0, vue.inject)(require_keys.tableKeyboardNavigationKey, null);
const shouldHeaderBeFocusable = (field) => !!(keyboardNavigation?.headerNavigation.value && field.sortable === true);
const shouldRowBeFocusable = (0, vue.computed)(() => !!(keyboardNavigation?.rowNavigation.value && (0, vue.toValue)(items).length > 0));
const headerClicked = (field, event, isFooter = false) => {
events.onHeadClicked({
key: field.key,
field,
event,
isFooter
});
};
const handleHeaderKeydown = (field, event, isFooter = false) => {
const { target, code } = event;
if (target && target.tagName !== "TH" && require_dom.getSafeDocument()?.activeElement === target) return;
if (code === "Enter" || code === "NumpadEnter" || code === "Space") {
event.preventDefault();
headerClicked(field, event, isFooter);
}
};
const handleRowKeydown = (item, itemIndex, event) => {
const { target, code, shiftKey } = event;
if (target && target.tagName !== "TR" && require_dom.getSafeDocument()?.activeElement === target) return;
if (code === "Enter" || code === "NumpadEnter" || code === "Space") {
event.preventDefault();
events.onRowClicked({
item,
index: itemIndex,
event
});
return;
}
if (code === "ArrowDown" || code === "ArrowUp" || code === "Home" || code === "End") {
event.preventDefault();
handleRowNavigation(code, shiftKey, itemIndex);
}
};
const handleRowNavigation = (code, shiftKey, currentIndex) => {
const doc = require_dom.getSafeDocument();
const rows = doc === null ? [] : Array.from(doc.querySelectorAll(`#${(0, vue.toValue)(id)} tbody tr[tabindex]`));
if (rows.length === 0) return;
let targetIndex = currentIndex;
if (code === "ArrowDown") if (shiftKey) targetIndex = rows.length - 1;
else targetIndex = Math.min(currentIndex + 1, rows.length - 1);
else if (code === "ArrowUp") if (shiftKey) targetIndex = 0;
else targetIndex = Math.max(currentIndex - 1, 0);
else if (code === "End") targetIndex = rows.length - 1;
else if (code === "Home") targetIndex = 0;
if (targetIndex !== currentIndex && rows[targetIndex]) rows[targetIndex]?.focus();
};
const handleMiddleClick = (item, itemIndex, event) => {
if (event.button === 1 && !filterEvent(event)) events.onRowMiddleClicked({
item,
index: itemIndex,
event
});
};
return {
shouldHeaderBeFocusable,
headerClicked,
handleHeaderKeydown,
shouldRowBeFocusable,
handleRowKeydown,
handleMiddleClick
};
};
//#endregion
//#region src/components/BTable/BTableLite.vue?vue&type=script&setup=true&lang.ts
var _hoisted_1$1 = { key: 0 };
var _hoisted_2$1 = {
key: 0,
class: "b-table-stacked-label"
};
var _hoisted_3 = { class: "d-inline-flex flex-nowrap align-items-center gap-1" };
var _hoisted_4 = { key: 3 };
//#endregion
//#region src/components/BTable/BTableLite.vue
var BTableLite_default = /* @__PURE__ */ (0, vue.defineComponent)({
__name: "BTableLite",
props: /* @__PURE__ */ (0, vue.mergeModels)({
align: { default: void 0 },
caption: { default: void 0 },
detailsTdClass: { default: void 0 },
fieldColumnClass: {
type: [
Function,
String,
Object,
Array
],
default: void 0
},
fields: { default: () => [] },
footClone: {
type: Boolean,
default: false
},
footRowVariant: { default: void 0 },
footVariant: { default: void 0 },
headRowVariant: { default: void 0 },
headVariant: { default: void 0 },
items: { default: () => [] },
labelStacked: {
type: Boolean,
default: false
},
modelValue: { default: void 0 },
primaryKey: {
type: [String, Function],
default: void 0
},
tbodyClass: { default: void 0 },
tbodyTrAttrs: {
type: [Function, Object],
default: void 0
},
tbodyTrClass: {
type: [
Function,
String,
Array,
Object
],
default: void 0
},
tfootClass: { default: void 0 },
tfootTrClass: { default: void 0 },
theadClass: { default: void 0 },
theadTrClass: { default: void 0 },
bordered: {
type: Boolean,
default: void 0
},
borderless: {
type: Boolean,
default: void 0
},
borderVariant: { default: void 0 },
captionTop: {
type: Boolean,
default: void 0
},
dark: {
type: Boolean,
default: void 0
},
fixed: {
type: Boolean,
default: void 0
},
hover: {
type: Boolean,
default: void 0
},
id: { default: void 0 },
noBorderCollapse: {
type: Boolean,
default: void 0
},
outlined: {
type: Boolean,
default: void 0
},
responsive: {
type: [Boolean, String],
default: void 0
},
small: {
type: Boolean,
default: void 0
},
stacked: {
type: [Boolean, String],
default: void 0
},
stickyHeader: {
type: [
Boolean,
String,
Number
],
default: void 0
},
striped: {
type: Boolean,
default: void 0
},
stripedColumns: {
type: Boolean,
default: void 0
},
variant: { default: void 0 },
tableAttrs: {},
tableClass: { default: void 0 }
}, {
"expandedItems": { default: () => [] },
"expandedItemsModifiers": {}
}),
emits: /* @__PURE__ */ (0, vue.mergeModels)([
"head-clicked",
"row-clicked",
"row-dblclicked",
"row-contextmenu",
"row-hovered",
"row-unhovered",
"row-middle-clicked"
], ["update:expandedItems"]),
setup(__props, { expose: __expose, emit: __emit }) {
const props = require_useDefaults.useDefaults(__props, "BTableLite");
const emit = __emit;
const slots = (0, vue.useSlots)();
const expandedItems = (0, vue.useModel)(__props, "expandedItems");
const computedId = require_useId.useId(() => props.id);
const expandedItemsController = useItemExpansion({
allItems: () => props.items,
primaryKey: (0, vue.toRef)(() => props.primaryKey),
expandedItems
});
const keyboardController = useTableKeyboardNavigation({
items: () => props.items,
id: computedId
}, {
onHeadClicked: (obj) => {
emit("head-clicked", obj);
},
onRowClicked: (obj) => {
emit("row-clicked", obj);
},
onRowMiddleClicked: (obj) => {
emit("row-middle-clicked", obj);
}
});
const { fields: computedFields, total: computedFieldsTotal, showHeaders: showComputedHeaders } = useTableFieldsMapper({
fields: () => props.fields,
items: () => props.items,
stackedProps: {
labelStacked: () => props.labelStacked,
stacked: () => props.stacked
}
});
const calculatedFooterSlot = (key) => slots[`foot(${key})`] ? `foot(${key})` : slots["foot()"] ? "foot()" : slots[`head(${key})`] ? `head(${key})` : "head()";
const computedTableClasses = (0, vue.computed)(() => [props.tableClass, { [`align-${props.align}`]: props.align !== void 0 }]);
const getFieldColumnClasses = (field) => [
field.class,
field.thClass,
{ "b-table-sticky-column": field.stickyColumn },
props.fieldColumnClass ? typeof props.fieldColumnClass === "function" ? props.fieldColumnClass(field) : props.fieldColumnClass : null
];
const getFieldRowClasses = (field, tr) => [
field.class,
typeof field.tdClass === "function" ? field.tdClass(getByFieldKey(tr, field), field.key, tr) : field.tdClass,
(isTableItem(tr) ? tr._cellVariants?.[field.key] : false) ? `table-${tr._cellVariants?.[field.key]}` : null,
{ "b-table-sticky-column": field.stickyColumn }
];
const getRowClasses = (item, type) => props.tbodyTrClass ? typeof props.tbodyTrClass === "function" ? props.tbodyTrClass(item, type) : props.tbodyTrClass : null;
const itemAttributes = (item, field) => field.tdAttr && typeof field.tdAttr === "function" ? field.tdAttr({
value: getByFieldKey(item, field),
key: field.key,
item
}) : field.tdAttr;
const callThAttr = (item, field, type) => field.thAttr && typeof field.thAttr === "function" ? field.thAttr({
value: getByFieldKey(item, field),
key: field.key,
item,
type
}) : field.thAttr;
const callTbodyTrAttrs = (item, type) => props.tbodyTrAttrs ? typeof props.tbodyTrAttrs === "function" ? props.tbodyTrAttrs(item, type) : props.tbodyTrAttrs : null;
const generateTableRowId = (primaryKeyValue) => `${computedId.value}__row_${primaryKeyValue}`;
const getCellComponent = (field) => {
if (field?.isRowHeader) return BTh_default;
return BTd_default;
};
const footerProps = (0, vue.computed)(() => ({
variant: props.footVariant ?? props.headVariant,
class: props.tfootClass ?? props.theadClass
}));
const computedSimpleProps = (0, vue.computed)(() => ({
...require_object.pick(props, bTableSimpleProps),
tableClass: computedTableClasses.value,
id: computedId.value
}));
__expose({ expansion: {
...expandedItemsController,
expandedItems: (0, vue.readonly)(expandedItems)
} });
return (_ctx, _cache) => {
return (0, vue.openBlock)(), (0, vue.createBlock)(require_BTableSimple.BTableSimple_default, (0, vue.normalizeProps)((0, vue.guardReactiveProps)(computedSimpleProps.value)), {
default: (0, vue.withCtx)(() => [
slots["table-colgroup"] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("colgroup", _hoisted_1$1, [(0, vue.renderSlot)(_ctx.$slots, "table-colgroup", { fields: (0, vue.unref)(computedFields) })])) : (0, vue.createCommentVNode)("", true),
(0, vue.withDirectives)((0, vue.createVNode)(BThead_default, {
variant: (0, vue.unref)(props).headVariant,
class: (0, vue.normalizeClass)((0, vue.unref)(props).theadClass)
}, {
default: (0, vue.withCtx)(() => [
(0, vue.renderSlot)(_ctx.$slots, "thead-top", {
columns: (0, vue.unref)(computedFieldsTotal),
fields: (0, vue.unref)(computedFields)
}),
(0, vue.createVNode)(BTr_default, {
variant: (0, vue.unref)(props).headRowVariant,
class: (0, vue.normalizeClass)((0, vue.unref)(props).theadTrClass)
}, {
default: (0, vue.withCtx)(() => [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)((0, vue.unref)(computedFields), (field) => {
return (0, vue.openBlock)(), (0, vue.createBlock)(BTh_default, (0, vue.mergeProps)({
key: field.key,
scope: field.scope,
class: getFieldColumnClasses(field),
title: field.headerTitle,
variant: field.variant,
abbr: field.headerAbbr,
style: field.thStyle,
tabindex: (0, vue.unref)(keyboardController).shouldHeaderBeFocusable(field) ? "0" : void 0
}, { ref_for: true }, callThAttr(null, field, "top"), {
onClick: ($event) => (0, vue.unref)(keyboardController).headerClicked(field, $event),
onKeydown: ($event) => (0, vue.unref)(keyboardController).handleHeaderKeydown(field, $event)
}), {
default: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, slots[`head(${field.key})`] ? `head(${field.key})` : "head()", {
label: field.label,
column: field.key,
field,
isFoot: false
}, () => [(0, vue.createTextVNode)((0, vue.toDisplayString)((0, vue.unref)(getTableFieldHeadLabel)(field)), 1)])]),
_: 2
}, 1040, [
"scope",
"class",
"title",
"variant",
"abbr",
"style",
"tabindex",
"onClick",
"onKeydown"
]);
}), 128))]),
_: 3
}, 8, ["variant", "class"]),
slots["thead-sub"] ? ((0, vue.openBlock)(), (0, vue.createBlock)(BTr_default, { key: 0 }, {
default: (0, vue.withCtx)(() => [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)((0, vue.unref)(computedFields), (field) => {
return (0, vue.openBlock)(), (0, vue.createBlock)(BTd_default, {
key: field.key,
scope: "col",
variant: field.variant,
class: (0, vue.normalizeClass)([field.class, field.thClass])
}, {
default: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "thead-sub", {
items: (0, vue.unref)(props).items,
fields: (0, vue.unref)(computedFields),
field
}, () => [(0, vue.createTextVNode)((0, vue.toDisplayString)(field.label), 1)])]),
_: 2
}, 1032, ["variant", "class"]);
}), 128))]),
_: 3
})) : (0, vue.createCommentVNode)("", true)
]),
_: 3
}, 8, ["variant", "class"]), [[vue.vShow, (0, vue.unref)(showComputedHeaders)]]),
(0, vue.createVNode)(BTbody_default, { class: (0, vue.normalizeClass)((0, vue.unref)(props).tbodyClass) }, {
default: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "custom-body", {
fields: (0, vue.unref)(computedFields),
items: (0, vue.unref)(props).items,
columns: (0, vue.unref)(computedFieldsTotal)
}, () => [
!(0, vue.unref)(props).stacked && slots["top-row"] ? ((0, vue.openBlock)(), (0, vue.createBlock)(BTr_default, (0, vue.mergeProps)({
key: 0,
class: getRowClasses(null, "row-top")
}, callTbodyTrAttrs(null, "row-top")), {
default: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "top-row", {
columns: (0, vue.unref)(computedFieldsTotal),
fields: (0, vue.unref)(computedFields)
})]),
_: 3
}, 16, ["class"])) : (0, vue.createCommentVNode)("", true),
((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)((0, vue.unref)(props).items, (item, itemIndex) => {
return (0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: (0, vue.unref)(props).primaryKey && (0, vue.unref)(isTableItem)(item) && (0, vue.unref)(getWithGetter)(item, (0, vue.unref)(props).primaryKey) ? (0, vue.unref)(getWithGetter)(item, (0, vue.unref)(props).primaryKey) : itemIndex }, [(0, vue.createVNode)(BTr_default, (0, vue.mergeProps)({
id: (0, vue.unref)(props).primaryKey && (0, vue.unref)(isTableItem)(item) && (0, vue.unref)(getWithGetter)(item, (0, vue.unref)(props).primaryKey) ? generateTableRowId((0, vue.unref)(getWithGetter)(item, (0, vue.unref)(props).primaryKey)) : void 0,
class: getRowClasses(item, "row"),
variant: (0, vue.unref)(isTableItem)(item) ? item._rowVariant : void 0,
tabindex: (0, vue.unref)(keyboardController).shouldRowBeFocusable.value ? "0" : void 0
}, { ref_for: true }, callTbodyTrAttrs(item, "row"), {
onClick: ($event) => !(0, vue.unref)(filterEvent)($event) && emit("row-clicked", {
item,
index: itemIndex,
event: $event
}),
onDblclick: ($event) => !(0, vue.unref)(filterEvent)($event) && emit("row-dblclicked", {
item,
index: itemIndex,
event: $event
}),
onContextmenu: ($event) => !(0, vue.unref)(filterEvent)($event) && emit("row-contextmenu", {
item,
index: itemIndex,
event: $event
}),
onMouseenter: ($event) => !(0, vue.unref)(filterEvent)($event) && emit("row-hovered", {
item,
index: itemIndex,
event: $event
}),
onMouseleave: ($event) => !(0, vue.unref)(filterEvent)($event) && emit("row-unhovered", {
item,
index: itemIndex,
event: $event
}),
onMousedown: ($event) => (0, vue.unref)(keyboardController).handleMiddleClick(item, itemIndex, $event),
onKeydown: ($event) => (0, vue.unref)(keyboardController).handleRowKeydown(item, itemIndex, $event)
}), {
default: (0, vue.withCtx)(() => [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)((0, vue.unref)(computedFields), (field) => {
return (0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(getCellComponent(field)), (0, vue.mergeProps)({
key: field.key,
variant: ((0, vue.unref)(isTableItem)(item) ? item._cellVariants?.[field.key] : false) ? null : field.variant,
class: getFieldRowClasses(field, item)
}, { ref_for: true }, itemAttributes(item, field)), {
default: (0, vue.withCtx)(() => [(0, vue.unref)(props).stacked && (0, vue.unref)(props).labelStacked ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("label", _hoisted_2$1, (0, vue.toDisplayString)((0, vue.unref)(getTableFieldHeadLabel)(field)), 1)) : (0, vue.createCommentVNode)("", true), (0, vue.renderSlot)(_ctx.$slots, slots[`cell(${field.key})`] ? `cell(${field.key})` : "cell()", {
value: (0, vue.unref)(formatItem)(item, field),
unformatted: (0, vue.unref)(getByFieldKey)(item, field),
index: itemIndex,
item,
field,
items: (0, vue.unref)(props).items,
toggleExpansion: () => (0, vue.unref)(expandedItemsController).toggle(item),
expansionShowing: (0, vue.unref)(expandedItemsController).has(item)
}, () => [!slots[`cell(${field.key})`] && !slots["cell()"] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [(0, vue.createTextVNode)((0, vue.toDisplayString)((0, vue.unref)(formatItem)(item, field)), 1)], 64)) : (0, vue.createCommentVNode)("", true)])]),
_: 2
}, 1040, ["variant", "class"]);
}), 128))]),
_: 2
}, 1040, [
"id",
"class",
"variant",
"tabindex",
"onClick",
"onDblclick",
"onContextmenu",
"onMouseenter",
"onMouseleave",
"onMousedown",
"onKeydown"
]), (0, vue.unref)(expandedItemsController).has(item) && slots["row-expansion"] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [(0, vue.createVNode)(BTr_default, {
"aria-hidden": "true",
role: "presentation",
class: "d-none"
}), (0, vue.createVNode)(BTr_default, (0, vue.mergeProps)({
class: getRowClasses(item, "row-expansion"),
variant: (0, vue.unref)(isTableItem)(item) ? item._rowVariant : void 0
}, { ref_for: true }, callTbodyTrAttrs(item, "row-expansion")), {
default: (0, vue.withCtx)(() => [(0, vue.createVNode)(BTd_default, {
colspan: (0, vue.unref)(computedFieldsTotal),
class: (0, vue.normalizeClass)(__props.detailsTdClass)
}, {
default: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "row-expansion", {
item,
toggleExpansion: () => (0, vue.unref)(expandedItemsController).toggle(item),
fields: (0, vue.unref)(computedFields),
index: itemIndex
})]),
_: 2
}, 1032, ["colspan", "class"])]),
_: 2
}, 1040, ["class", "variant"])], 64)) : (0, vue.createCommentVNode)("", true)], 64);
}), 128)),
!(0, vue.unref)(props).stacked && slots["bottom-row"] ? ((0, vue.openBlock)(), (0, vue.createBlock)(BTr_default, (0, vue.mergeProps)({
key: 1,
class: ["bottom-row", getRowClasses(null, "row-bottom")]
}, callTbodyTrAttrs(null, "row-bottom")), {
default: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "bottom-row", {
columns: (0, vue.unref)(computedFieldsTotal),
fields: (0, vue.unref)(computedFields)
})]),
_: 3
}, 16, ["class"])) : (0, vue.createCommentVNode)("", true)
])]),
_: 3
}, 8, ["class"]),
(0, vue.unref)(props).footClone ? ((0, vue.openBlock)(), (0, vue.createBlock)(BTfoot_default, (0, vue.normalizeProps)((0, vue.mergeProps)({ key: 1 }, footerProps.value)), {
default: (0, vue.withCtx)(() => [(0, vue.createVNode)(BTr_default, {
variant: (0, vue.unref)(props).footRowVariant ?? (0, vue.unref)(props).headRowVariant,
class: (0, vue.normalizeClass)((0, vue.unref)(props).tfootTrClass ?? (0, vue.unref)(props).theadTrClass)
}, {
default: (0, vue.withCtx)(() => [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)((0, vue.unref)(computedFields), (field) => {
return (0, vue.openBlock)(), (0, vue.createBlock)(BTh_default, (0, vue.mergeProps)({
key: field.key,
scope: "col",
class: getFieldColumnClasses(field),
title: field.headerTitle,
abbr: field.headerAbbr,
style: field.thStyle,
variant: field.variant,
tabindex: (0, vue.unref)(keyboardController).shouldHeaderBeFocusable(field) ? "0" : void 0
}, { ref_for: true }, callThAttr(null, field, "bottom"), {
onClick: ($event) => (0, vue.unref)(keyboardController).headerClicked(field, $event, true),
onKeydown: ($event) => (0, vue.unref)(keyboardController).handleHeaderKeydown(field, $event, true)
}), {
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", _hoisted_3, [(0, vue.createElementVNode)("div", null, [(0, vue.renderSlot)(_ctx.$slots, calculatedFooterSlot(field.key), {
label: field.label,
column: field.key,
field,
isFoot: true
}, () => [(0, vue.createTextVNode)((0, vue.toDisplayString)((0, vue.unref)(getTableFieldHeadLabel)(field)), 1)])])])]),
_: 2
}, 1040, [
"class",
"title",
"abbr",
"style",
"variant",
"tabindex",
"onClick",
"onKeydown"
]);
}), 128))]),
_: 3
}, 8, ["variant", "class"])]),
_: 3
}, 16)) : slots["custom-foot"] ? ((0, vue.openBlock)(), (0, vue.createBlock)(BTfoot_default, (0, vue.normalizeProps)((0, vue.mergeProps)({ key: 2 }, footerProps.value)), {
default: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "custom-foot", {
fields: (0, vue.unref)(computedFields),
items: (0, vue.unref)(props).items,
columns: (0, vue.unref)(computedFieldsTotal)
})]),
_: 3
}, 16)) : (0, vue.createCommentVNode)("", true),
slots["table-caption"] || (0, vue.unref)(props).caption ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("caption", _hoisted_4, [(0, vue.renderSlot)(_ctx.$slots, "table-caption", {}, () => [(0, vue.createTextVNode)((0, vue.toDisplayString)((0, vue.unref)(props).caption), 1)])])) : (0, vue.createCommentVNode)("", true)
]),
_: 3
}, 16);
};
}
});
//#endregion
//#region src/composables/useTableHelpers.ts
var useTableMapper = ({ fields, items, stackedProps, provider, events, pagination }) => {
const sortByModelResolved = (0, vue.readonly)((0, vue.toRef)(pagination.sort.by));
const isSortableResolved = (0, vue.readonly)((0, vue.toRef)(pagination.sort.isSortable));
const filterResolved = (0, vue.readonly)((0, vue.toRef)(pagination.filter.filter));
const usesProviderResolved = (0, vue.readonly)((0, vue.toRef)(provider.usesProvider));
const isFilterableTable = (0, vue.computed)(() => filterResolved.value !== void 0);
const computedFields = (0, vue.computed)(() => (0, vue.toValue)(fields).map((el) => {
if (!isTableField(el)) {
const label = require_stringUtils.startCase(el);
return {
key: el,
label,
tdAttr: getDataLabelAttr({
stacked: (0, vue.toValue)(stackedProps.stacked),
labelStacked: (0, vue.toValue)(stackedProps.labelStacked)
}, label)
};
}
const value = sortByModelResolved.value?.find((sb) => el.key === sb.key);
const sortValue = !el.sortable || isSortableResolved.value === false ? void 0 : value === void 0 ? "none" : value.order === "desc" ? "descending" : value.order === "asc" ? "ascending" : "none";
return {
...el,
thAttr: {
"aria-sort": sortValue,
...el.thAttr
},
thClass: [el.thClass, { "b-table-sort-icon-left": (0, vue.toValue)(pagination.sort.iconLeft) && sortValue !== void 0 }]
};
}));
const getFormatter = (value) => typeof value.sortByFormatted === "function" ? value.sortByFormatted : value.formatter;
const getStringValue = (ob, key) => {
if (!isTableItem(ob)) return String(ob);
const sortField = computedFields.value.find((el) => {
if (isTableField(el)) return el.key === key;
return false;
});
const val = isTableField(sortField) && sortField.accessor ? getWithGetter(ob, sortField.accessor) : getWithGetter(ob, key);
if (isTableField(sortField) && !!sortField.sortByFormatted) {
const formatter = getFormatter(sortField);
if (formatter) return String(formatItem(ob, {
...sortField,
formatter
}));
}
return typeof val === "object" && val !== null ? JSON.stringify(val) : val?.toString() ?? "";
};
const fieldByKey = (0, vue.computed)(() => {
const map = /* @__PURE__ */ new Map();
for (const f of computedFields.value) if (isTableField(f)) map.set(f.key, f);
return map;
});
const computedItems = (0, vue.computed)(() => {
const filterableValue = (0, vue.toValue)(pagination.filter.filterable);
const filterFunctionValue = (0, vue.unref)(pagination.filter.filterFunction);
const itemsValue = (0, vue.toValue)(items);
const sortByItems = sortByModelResolved.value?.filter((el) => !!el.order);
const mapItem = (item) => {
if (typeof item === "object" && item !== null && Object.keys(item).some((key) => key.includes("."))) {
let newItem = {};
for (const key in item) if (key.includes(".")) newItem = require_object.set(newItem, key, item[key]);
else newItem[key] = item[key];
return newItem;
}
return item;
};
const filterItem = (item) => {
if (!isTableItem(item)) return true;
return Object.entries(item).some(([key, val]) => {
if (val === null || val === void 0 || key[0] === "_" || !filterableValue?.includes(key) && !!filterableValue?.length) return false;
if (typeof filterFunctionValue === "function") return filterFunctionValue(item, filterResolved.value);
const realVal = () => {
const filterField = computedFields.value.find((el) => {
if (isTableField(el)) return el.key === key;
return false;
});
if (isTableField(filterField) && !!filterField.filterByFormatted) {
const formatter = getFormatter(filterField);
if (formatter) return String(formatter({
value: val,
key: String(filterField.key),
item
}));
}
return typeof val === "object" ? JSON.stringify(Object.values(val)) : val.toString();
};
return realVal().toLowerCase().includes(filterResolved.value?.toLowerCase() ?? "");
});
};
const noProviderFilteringValue = (0, vue.toValue)(provider.noProviderFiltering);
const mappedItems = itemsValue.reduce((acc, val) => {
const item = mapItem(val);
if (!(isFilterableTable.value && (!usesProviderResolved.value || noProviderFilteringValue)) || filterItem(item)) acc.push(item);
return acc;
}, []);
if (sortByItems?.length && (isSortableResolved.value === true && !usesProviderResolved.value && !(0, vue.toValue)(pagination.sort.noLocalSorting) || isSortableResolved.value === true && usesProviderResolved.value && (0, vue.toValue)(provider.noProviderSorting))) {
const sortCompareValue = (0, vue.unref)(pagination.sort.sortCompare);
return mappedItems.sort((a, b) => {
for (let i = 0; i < sortByItems.length; i++) {
const value = sortByItems[i];
if (value === void 0) continue;
const { key, order } = value;
const comparer = fieldByKey.value.get(key)?.sortCompare || sortCompareValue;
const comparison = comparer ? comparer(a, b, key) : getStringValue(a, key).localeCompare(getStringValue(b, key), void 0, { numeric: true });
if (comparison !== 0) return order === "asc" ? comparison : -comparison;
}
return 0;
});
}
return mappedItems;
});
const computedDisplayItems = (0, vue.computed)(() => {
const perPageNumber = (0, vue.toValue)(pagination.perPage);
const currentPageNumber = (0, vue.toValue)(pagination.currentPage);
if (Number.isNaN(perPageNumber) || usesProviderResolved.value && !(0, vue.toValue)(provider.noProviderPaging)) return computedItems.value;
return computedItems.value.slice((currentPageNumber - 1) * (perPageNumber || Number.POSITIVE_INFINITY), currentPageNumber * (perPageNumber || Number.POSITIVE_INFINITY));
});
(0, vue.watch)(filterResolved, () => {
pagination.currentPage.value = 1;
});
(0, vue.watch)(computedDisplayItems, (v) => {
events.onChange([...v]);
});
return {
items: computedItems,
displayItems: computedDisplayItems,
getStringValue,
fields: computedFields,
isFilterableTable
};
};
var useTableKeyboardNavigationInjector = ({ isSortable, selectable, noSelectOnClick }) => {
(0, vue.provide)(require_keys.tableKeyboardNavigationKey, {
rowNavigation: (0, vue.computed)(() => !!((0, vue.toValue)(selectable) && !(0, vue.toValue)(noSelectOnClick))),
headerNavigation: (0, vue.computed)(() => !!(0, vue.toValue)(isSortable))
});
};
var useTableSelectedItems = ({ selectable, selectMode, selectedItems, events, primaryKey, allItems }) => {
const selectableResolved = (0, vue.readonly)((0, vue.toRef)(selectable));
const selectModeResolved = (0, vue.readonly)((0, vue.toRef)(selectMode));
const allItemsResolved = (0, vue.computed)(() => (0, vue.toValue)(allItems));
const utils = useItemTracker({
allItems: allItemsResolved,
primaryKey,
selectedItems
});
(0, vue.watch)(selectedItems, (newValue, oldValue) => {
Array.from(oldValue).filter((item) => !newValue.includes(item)).forEach((item) => {
events.onRowUnselected(item);
});
Array.from(newValue).filter((item) => !oldValue.includes(item)).forEach((item) => {
events.onRowSelected(item);
});
});
const handleRowSelection = ({ item, index, shiftClicked = false, ctrlClicked = false, metaClicked = false }) => {
if (!selectableResolved.value) return;
if (selectModeResolved.value === "single" || selectModeResolved.value === "multi") {
if (shiftClicked || ctrlClicked) return;
if (utils.has(item)) utils.remove(item);
else if (selectModeResolved.value === "single") utils.set([item]);
else utils.add(item);
} else if (ctrlClicked || metaClicked) if (utils.has(item)) utils.remove(item);
else utils.add(item);
else if (shiftClicked) {
const lastSelectedItem = selectedItems.value[selectedItems.value.length - 1];
const lastSelectedIndex = allItemsResolved.value.findIndex((i) => utils.get(i) === lastSelectedItem);
if (lastSelectedIndex === -1) {
utils.set([item]);
return;
}
const selectStartIndex = Math.min(lastSelectedIndex, index);
const selectEndIndex = Math.max(lastSelectedIndex, index);
const items = allItemsResolved.value.slice(selectStartIndex, selectEndIndex + 1);
utils.set(items);
} else utils.set([item]);
};
return {
...utils,
handleRowSelection,
clear: () => {
if (!selectableResolved.value) return;
utils.clear();
},
setAll: () => {
if (!selectableResolved.value || selectModeResolved.value === "single") return;
utils.setAll();
},
add: (item) => {
if (!selectableResolved.value || utils.has(item)) return;
if (selectModeResolved.value === "single") utils.set([item]);
else utils.add(item);
},
remove: (item) => {
if (!selectableResolved.value) return;
utils.remove(item);
},
has: (item) => {
if (!selectableResolved.value) return false;
return utils.has(item);
}
};
};
var useTableProvider = ({ items, provider, busy, currentPage, debounce, perPage, noProvider, noProviderFiltering, noProviderPaging, noProviderSorting, filter, sortBy, events }) => {
const providerResolved = (0, vue.readonly)((0, vue.toRef)(provider));
const currentPageResolved = (0, vue.readonly)((0, vue.toRef)(currentPage));
const perPageResolved = (0, vue.readonly)((0, vue.toRef)(perPage));
const sortByResolved = (0, vue.readonly)((0, vue.toRef)(sortBy));
const filterResolved = (0, vue.readonly)((0, vue.toRef)(filter));
const usesProvider = (0, vue.computed)(() => providerResolved.value !== void 0);
let abortController = null;
const callItemsProvider = async () => {
if (!usesProvider.value || providerResolved.value === void 0) return;
if (abortController) abortController.abort();
abortController = new AbortController();
const { signal } = abortController;
busy.value = true;
try {
const response = providerResolved.value({
currentPage: currentPageResolved.value,
filter: filterResolved.value,
sortBy: sortByResolved.value,
perPage: perPageResolved.value,
signal
});
const returnValue = response instanceof Promise ? await response : response;
if (signal.aborted) return;
if (returnValue === void 0) return;
items.value = returnValue;
} catch (error) {
if (error instanceof Error && error.name === "AbortError") return;
throw error;
} finally {
if (!signal.aborted) busy.value = false;
}
};
const debouncedCallItemsProvider = require_debounce.useDebounceFn(callItemsProvider, debounce.wait, { maxWait: debounce.maxWait });
const providerPropsWatch = async (prop, val, oldVal) => {
if (require_object.deepEqual(val, oldVal)) return;
const inNoProvider = (key) => (0, vue.toValue)(noProvider)?.includes(key) === true;
const noProvideWhenPaging = (prop === "currentPage" || prop === "perPage") && (inNoProvider("paging") || (0, vue.toValue)(noProviderPaging) === true);
const noProvideWhenFiltering = prop === "filter" && (inNoProvider("filtering") || (0, vue.toValue)(noProviderFiltering) === true);
const noProvideWhenSorting = (prop === "sortBy" || prop === "sortDesc") && (inNoProvider("sorting") || (0, vue.toValue)(noProviderSorting) === true);
if (noProvideWhenPaging || noProvideWhenFiltering || noProvideWhenSorting) return;
if (usesProvider.value === true) await debouncedCallItemsProvider();
if (!(prop === "currentPage" || prop === "perPage")) events.onFiltered();
};
(0, vue.watch)(filterResolved, async (filter, oldFilter) => {
await providerPropsWatch("filter", filter, oldFilter);
});
(0, vue.watch)(currentPageResolved, async (val, oldVal) => {
await providerPropsWatch("currentPage", val, oldVal);
});
(0, vue.watch)(perPageResolved, async (val, oldVal) => {
await providerPropsWatch("perPage", val, oldVal);
});
(0, vue.watch)(sortByResolved, async (val, oldVal) => {
await providerPropsWatch("sortBy", val, oldVal);
}, { deep: true });
(0, vue.watch)(providerResolved, async (newValue) => {
if (newValue === void 0) {
items.value = [];
return;
}
await callItemsProvider();
});
(0, vue.onMounted)(async () => {
await callItemsProvider();
});
return {
usesProvider,
callItemsProvider
};
};
var useTableSort = ({ fields, sortBy, initialSortDirection, multisort, mustSort, events }) => {
const isSortable = (0, vue.computed)(() => sortBy.value !== void 0 || (0, vue.toValue)(fields).some((field) => typeof field === "object" && field !== null && field.sortable === true));
const handleFieldSorting = (field) => {
if (!isSortable.value) return;
const fieldKey = typeof field === "object" && field !== null ? field.key : field;
const fieldSortable = typeof field === "object" && field !== null ? field.sortable : false;
if (!(isSortable.value === true && fieldSortable === true)) return;
const getLastSortDirection = () => {
return [...sortBy.value ?? []].reverse().find((sort) => sort.order !== void 0 && sort.key !== fieldKey)?.order ?? "asc";
};
const getInitialSortDirection = () => {
if (typeof field === "object" && field !== null && field.initialSortDirection) {
if (field.initialSortDirection === "last") return getLastSortDirection();
return field.initialSortDirection;
}
const initialSortDirectionValue = (0, vue.toValue)(initialSortDirection);
if (initialSortDirectionValue) {
if (initialSortDirectionValue === "last") return getLastSortDirection();
return initialSortDirectionValue;
}
return "asc";
};
const resolveOrder = (val) => {
const mustSortValue = (0, vue.toValue)(mustSort);
if (val === void 0) return getInitialSortDirection();
const initial = getInitialSortDirection();
const must = mustSortValue === true || !!mustSortValue && mustSortValue.includes(fieldKey);
if (val === "asc") {
if (initial === "desc") return must ? "desc" : void 0;
return "desc";
}
if (val === "desc") {
if (initial === "desc") return "asc";
return must ? "asc" : void 0;
}
};
const index = sortBy.value?.findIndex((el) => el.key === fieldKey) ?? -1;
const originalValue = sortBy.value?.[index];
const updatedValue = index === -1 || !originalValue ? {
key: fieldKey,
order: getInitialSortDirection()
} : { ...originalValue };
/**
* @returns the updated value to emit for sorted
*/
const handleMultiSort = () => {
const tmp = [...sortBy.value ?? []];
const val = updatedValue;
if (index === -1) tmp.push(val);
else {
const order = resolveOrder(val.order);
if (order) {
val.order = order;
tmp.splice(index, 1, val);
} else {
val.order = void 0;
tmp.splice(index, 1);
}
}
sortBy.value = tmp;
return val;
};
/**
* @returns the updated value to emit for sorted
*/
const handleSingleSort = () => {
const order = index === -1 ? updatedValue.order : resolveOrder(updatedValue.order);
const val = {
...updatedValue,
order
};
sortBy.value = order ? [val] : [];
return val;
};
events.onSorted((0, vue.toValue)(multisort) === true ? handleMultiSort() : handleSingleSort());
};
return {
isSortable,
handleFieldSorting
};
};
//#endregion
//#region src/components/BTable/BTable.vue?vue&type=script&setup=true&lang.