@tanstack/table-devtools
Version:
Devtools for TanStack Table.
471 lines (469 loc) • 19.1 kB
JavaScript
import { useTableDevtoolsContext } from "../TableContextProvider.js";
import { useStyles } from "../styles/use-styles.js";
import { useTableStore } from "../useTableStore.js";
import { NoTableConnected } from "./NoTableConnected.js";
import { bundleSizes } from "../bundleSizes.js";
import { estimateBundleSize } from "../estimateBundleSize.js";
import { ResizableSplit } from "./ResizableSplit.js";
import { For, Show, createMemo } from "solid-js";
import { className, createComponent, effect, insert, memo, template } from "solid-js/web";
import { aggregationFns, coreFeatures, filterFns, sortFns, stockFeatures } from "@tanstack/table-core";
//#region src/components/FeaturesPanel.tsx
var _tmpl$ = /*#__PURE__*/ template(`<div><span></span><span></span><span>`);
var _tmpl$2 = /*#__PURE__*/ template(`<div>`);
var _tmpl$3 = /*#__PURE__*/ template(`<div>Features`);
var _tmpl$4 = /*#__PURE__*/ template(`<div><div>Estimated @tanstack/table-core bundle</div><div><span>Core</span><span></span></div><div><span>Registered features</span><span>+</span></div><div><span>Client row models</span><span>+</span></div><div><span>Built-in fns</span><span>+</span></div><div><span>Total</span><span></span></div><div>Minified + brotli, the metric \`pnpm size\` reports, measured for v<!>. Each item shows what it adds on its own; the total counts code that items share once. Excludes the framework adapter and custom features.`);
var _tmpl$5 = /*#__PURE__*/ template(`<div><div>Core Features`);
var _tmpl$6 = /*#__PURE__*/ template(`<div><div>Stock Features`);
var _tmpl$7 = /*#__PURE__*/ template(`<div><div>Additional Plugins`);
var _tmpl$8 = /*#__PURE__*/ template(`<div>Client Side Row Models and Fns`);
var _tmpl$9 = /*#__PURE__*/ template(`<div>Full package: `);
var _tmpl$0 = /*#__PURE__*/ template(`<div><div>Execution Order`);
var _tmpl$1 = /*#__PURE__*/ template(`<div><div><span></span><span> rows, `);
var _tmpl$10 = /*#__PURE__*/ template(`<div><span></span><span>`);
var _tmpl$11 = /*#__PURE__*/ template(`<div><div><span>aggregationFns</span><span> registered`);
var _tmpl$12 = /*#__PURE__*/ template(`<div>No row models configured`);
var _tmpl$13 = /*#__PURE__*/ template(`<span>`);
function toFnBuckets(value) {
return typeof value === "object" && value != null ? value : {};
}
/** Maps each built-in fn back to its registry name to size registered fns */
const BUILT_IN_FN_NAMES = {
filterFns: new Map(Object.entries(filterFns).map(([name, fn]) => [fn, name])),
sortFns: new Map(Object.entries(sortFns).map(([name, fn]) => [fn, name])),
aggregationFns: new Map(Object.entries(aggregationFns).map(([name, fn]) => [fn, name]))
};
const CORE_REACTIVITY_FEATURE_NAME = "coreReactivityFeature";
const CORE_FEATURE_NAMES = [CORE_REACTIVITY_FEATURE_NAME, ...Object.keys(coreFeatures).filter((featureName) => featureName !== CORE_REACTIVITY_FEATURE_NAME)];
const STOCK_FEATURE_NAMES = Object.keys(stockFeatures);
const CORE_FEATURE_SIZES = bundleSizes.coreFeatures;
const FEATURE_SIZES = bundleSizes.features;
const ROW_MODEL_SIZES = bundleSizes.rowModels;
const FN_SIZES = {
filterFns: bundleSizes.filterFns,
sortFns: bundleSizes.sortFns,
aggregationFns: bundleSizes.aggregationFns
};
const ROW_MODEL_FEATURE_SLOTS = [
"coreRowModel",
"filteredRowModel",
"groupedRowModel",
"sortedRowModel",
"expandedRowModel",
"paginatedRowModel",
"facetedRowModel",
"facetedMinMaxValues",
"facetedUniqueValues"
];
const ROW_MODEL_SHARED_SIZE_LABELS = {
preFilteredRowModel: "shared",
preGroupedRowModel: "shared",
preSortedRowModel: "shared"
};
const ROW_MODEL_TO_FN_KIND = {
filteredRowModel: "filterFns",
preFilteredRowModel: "filterFns",
sortedRowModel: "sortFns",
preSortedRowModel: "sortFns",
groupedRowModel: null,
preGroupedRowModel: null
};
const EXECUTION_ORDER_GETTERS = [
"getCoreRowModel",
"getFilteredRowModel",
"getGroupedRowModel",
"getSortedRowModel",
"getExpandedRowModel",
"getPaginatedRowModel",
"getRowModel"
];
function getterToRowModelKey(getter) {
if (getter === "getRowModel") return "paginatedRowModel";
const withoutGet = getter.slice(3);
return withoutGet.charAt(0).toLowerCase() + withoutGet.slice(1);
}
const ROW_MODEL_TO_GETTER = {
coreRowModel: "getCoreRowModel",
filteredRowModel: "getFilteredRowModel",
preFilteredRowModel: "getFilteredRowModel",
groupedRowModel: "getGroupedRowModel",
preGroupedRowModel: "getGroupedRowModel",
sortedRowModel: "getSortedRowModel",
preSortedRowModel: "getSortedRowModel",
expandedRowModel: "getExpandedRowModel",
paginatedRowModel: "getRowModel"
};
function getRowCountForModel(tableInstance, rowModelName) {
const getter = ROW_MODEL_TO_GETTER[rowModelName];
if (!getter || !tableInstance) return 0;
const tableRecord = tableInstance;
if (typeof tableRecord[getter] !== "function") return 0;
return tableRecord[getter]().rows?.length ?? 0;
}
function formatSize(sizeInBytes) {
if (typeof sizeInBytes !== "number") return "n/a";
return `${(sizeInBytes / 1e3).toFixed(2)} kB`;
}
function formatRegisteredFnSize(kind, fn) {
return fn.builtInName ? formatSize(FN_SIZES[kind][fn.builtInName]) : "custom";
}
function normalizeRowModelSizeKey(rowModelName) {
if (rowModelName === "preFilteredRowModel") return "filteredRowModel";
if (rowModelName === "preGroupedRowModel") return "groupedRowModel";
if (rowModelName === "preSortedRowModel") return "sortedRowModel";
return rowModelName;
}
function FeaturesPanel() {
const styles = useStyles();
const { table } = useTableDevtoolsContext();
const tableState = useTableStore(() => table()?.store, (state) => state);
const optionsStoreValue = useTableStore(() => table()?.optionsStore, (options) => options);
const tableFeatures = createMemo(() => {
const tableInstance = table();
if (!tableInstance) return /* @__PURE__ */ new Set();
return new Set(Object.keys(tableInstance._features));
});
const rowModelNames = createMemo(() => {
const tableInstance = table();
if (!tableInstance) return [];
optionsStoreValue();
return Object.keys(tableInstance.options.features ?? {}).filter((key) => ROW_MODEL_FEATURE_SLOTS.includes(key));
});
const getRegisteredFns = (kind) => {
const tableInstance = table();
if (!tableInstance) return [];
optionsStoreValue();
const rowModelFns = toFnBuckets(tableInstance._rowModelFns);
const optionFns = toFnBuckets(tableInstance.options);
const registry = rowModelFns[kind] ?? optionFns[kind] ?? {};
return Object.entries(registry).map(([name, fn]) => ({
name,
builtInName: BUILT_IN_FN_NAMES[kind].get(fn)
}));
};
const additionalPlugins = createMemo(() => {
const currentFeatures = tableFeatures();
const knownFeatures = /* @__PURE__ */ new Set([...CORE_FEATURE_NAMES, ...STOCK_FEATURE_NAMES]);
return [...currentFeatures].filter((f) => !knownFeatures.has(f)).sort();
});
const registeredFns = createMemo(() => ({
filterFns: getRegisteredFns("filterFns"),
sortFns: getRegisteredFns("sortFns"),
aggregationFns: getRegisteredFns("aggregationFns")
}));
const getRowModelFunctions = (rowModelName) => {
const fnKind = ROW_MODEL_TO_FN_KIND[rowModelName];
if (!fnKind) return [];
return registeredFns()[fnKind];
};
const sizeEstimate = createMemo(() => {
const builtInNames = (kind) => registeredFns()[kind].flatMap((fn) => fn.builtInName ? [fn.builtInName] : []);
const withFeatures = { features: [...tableFeatures()] };
const withRowModels = {
...withFeatures,
rowModels: rowModelNames()
};
const withFns = {
...withRowModels,
filterFns: builtInNames("filterFns"),
sortFns: builtInNames("sortFns"),
aggregationFns: builtInNames("aggregationFns")
};
const core = bundleSizes.core;
const features = estimateBundleSize(withFeatures);
const rowModels = estimateBundleSize(withRowModels);
const total = estimateBundleSize(withFns);
return {
core,
features: features - core,
rowModels: rowModels - features,
fns: total - rowModels,
total
};
});
const rowModels = createMemo(() => {
const tableInstance = table();
if (!tableInstance) return [];
tableState();
return rowModelNames().map((rowModelName) => {
const sharedLabel = ROW_MODEL_SHARED_SIZE_LABELS[rowModelName];
return {
rowModelName,
fnKind: ROW_MODEL_TO_FN_KIND[rowModelName] ?? null,
fns: getRowModelFunctions(rowModelName),
rowCount: getRowCountForModel(tableInstance, rowModelName),
sizeLabel: sharedLabel ?? formatSize(ROW_MODEL_SIZES[normalizeRowModelSizeKey(rowModelName)])
};
});
});
const renderFeatureItem = (name, isEnabled, sizeLabel) => (() => {
var _el$ = _tmpl$(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling, _el$4 = _el$3.nextSibling;
insert(_el$2, isEnabled ? "✓" : "○");
insert(_el$3, name);
insert(_el$4, sizeLabel);
effect((_p$) => {
var _v$ = styles().featureListItem, _v$2 = isEnabled ? styles().featureCheck : styles().featureUncheck, _v$3 = styles().featureLabel, _v$4 = styles().featureMeta;
_v$ !== _p$.e && className(_el$, _p$.e = _v$);
_v$2 !== _p$.t && className(_el$2, _p$.t = _v$2);
_v$3 !== _p$.a && className(_el$3, _p$.a = _v$3);
_v$4 !== _p$.o && className(_el$4, _p$.o = _v$4);
return _p$;
}, {
e: void 0,
t: void 0,
a: void 0,
o: void 0
});
return _el$;
})();
return createComponent(Show, {
get fallback() {
return createComponent(NoTableConnected, { title: "Features" });
},
get when() {
return table();
},
get children() {
var _el$5 = _tmpl$2();
insert(_el$5, createComponent(ResizableSplit, {
get left() {
return [
(() => {
var _el$6 = _tmpl$3();
effect(() => className(_el$6, styles().sectionTitle));
return _el$6;
})(),
(() => {
var _el$7 = _tmpl$4(), _el$8 = _el$7.firstChild, _el$9 = _el$8.nextSibling, _el$1 = _el$9.firstChild.nextSibling, _el$10 = _el$9.nextSibling, _el$12 = _el$10.firstChild.nextSibling;
_el$12.firstChild;
var _el$14 = _el$10.nextSibling, _el$16 = _el$14.firstChild.nextSibling;
_el$16.firstChild;
var _el$18 = _el$14.nextSibling, _el$20 = _el$18.firstChild.nextSibling;
_el$20.firstChild;
var _el$22 = _el$18.nextSibling, _el$24 = _el$22.firstChild.nextSibling, _el$25 = _el$22.nextSibling, _el$28 = _el$25.firstChild.nextSibling;
_el$28.nextSibling;
insert(_el$1, () => formatSize(sizeEstimate().core));
insert(_el$12, () => formatSize(sizeEstimate().features), null);
insert(_el$16, () => formatSize(sizeEstimate().rowModels), null);
insert(_el$20, () => formatSize(sizeEstimate().fns), null);
insert(_el$24, () => formatSize(sizeEstimate().total));
insert(_el$25, () => bundleSizes.tableCoreVersion, _el$28);
effect((_p$) => {
var _v$5 = styles().featureEstimateSummary, _v$6 = styles().featureEstimateSummaryTitle, _v$7 = styles().featureEstimateSummaryRow, _v$8 = styles().featureEstimateSummaryRow, _v$9 = styles().featureEstimateSummaryRow, _v$0 = styles().featureEstimateSummaryRow, _v$1 = styles().featureEstimateSummaryTotal, _v$10 = styles().featureEstimateSummaryNote;
_v$5 !== _p$.e && className(_el$7, _p$.e = _v$5);
_v$6 !== _p$.t && className(_el$8, _p$.t = _v$6);
_v$7 !== _p$.a && className(_el$9, _p$.a = _v$7);
_v$8 !== _p$.o && className(_el$10, _p$.o = _v$8);
_v$9 !== _p$.i && className(_el$14, _p$.i = _v$9);
_v$0 !== _p$.n && className(_el$18, _p$.n = _v$0);
_v$1 !== _p$.s && className(_el$22, _p$.s = _v$1);
_v$10 !== _p$.h && className(_el$25, _p$.h = _v$10);
return _p$;
}, {
e: void 0,
t: void 0,
a: void 0,
o: void 0,
i: void 0,
n: void 0,
s: void 0,
h: void 0
});
return _el$7;
})(),
(() => {
var _el$29 = _tmpl$5(), _el$30 = _el$29.firstChild;
insert(_el$29, createComponent(For, {
each: CORE_FEATURE_NAMES,
children: (name) => renderFeatureItem(name, tableFeatures().has(name), name === CORE_REACTIVITY_FEATURE_NAME ? "adapter" : formatSize(CORE_FEATURE_SIZES[name]))
}), null);
effect((_p$) => {
var _v$11 = styles().featureSubsection, _v$12 = styles().featureSubsectionTitle;
_v$11 !== _p$.e && className(_el$29, _p$.e = _v$11);
_v$12 !== _p$.t && className(_el$30, _p$.t = _v$12);
return _p$;
}, {
e: void 0,
t: void 0
});
return _el$29;
})(),
(() => {
var _el$31 = _tmpl$6(), _el$32 = _el$31.firstChild;
insert(_el$31, createComponent(For, {
each: STOCK_FEATURE_NAMES,
children: (name) => renderFeatureItem(name, tableFeatures().has(name), `+${formatSize(FEATURE_SIZES[name])}`)
}), null);
effect((_p$) => {
var _v$13 = styles().featureSubsection, _v$14 = styles().featureSubsectionTitle;
_v$13 !== _p$.e && className(_el$31, _p$.e = _v$13);
_v$14 !== _p$.t && className(_el$32, _p$.t = _v$14);
return _p$;
}, {
e: void 0,
t: void 0
});
return _el$31;
})(),
memo(() => memo(() => additionalPlugins().length > 0)() && (() => {
var _el$33 = _tmpl$7(), _el$34 = _el$33.firstChild;
insert(_el$33, createComponent(For, {
get each() {
return additionalPlugins();
},
children: (name) => renderFeatureItem(name, true, "custom")
}), null);
effect((_p$) => {
var _v$15 = styles().featureSubsection, _v$16 = styles().featureSubsectionTitle;
_v$15 !== _p$.e && className(_el$33, _p$.e = _v$15);
_v$16 !== _p$.t && className(_el$34, _p$.t = _v$16);
return _p$;
}, {
e: void 0,
t: void 0
});
return _el$33;
})())
];
},
get right() {
return [
(() => {
var _el$35 = _tmpl$8();
effect(() => className(_el$35, styles().sectionTitle));
return _el$35;
})(),
createComponent(For, {
get each() {
return rowModels();
},
children: (rowModel) => (() => {
var _el$40 = _tmpl$1(), _el$41 = _el$40.firstChild, _el$42 = _el$41.firstChild, _el$43 = _el$42.nextSibling, _el$44 = _el$43.firstChild;
insert(_el$42, () => rowModel.rowModelName);
insert(_el$43, () => rowModel.rowCount, _el$44);
insert(_el$43, () => rowModel.sizeLabel, null);
insert(_el$40, createComponent(For, {
get each() {
return rowModel.fns;
},
children: (fn) => (() => {
var _el$45 = _tmpl$10(), _el$46 = _el$45.firstChild, _el$47 = _el$46.nextSibling;
insert(_el$46, () => fn.name);
insert(_el$47, (() => {
var _c$ = memo(() => !!rowModel.fnKind);
return () => _c$() ? formatRegisteredFnSize(rowModel.fnKind, fn) : "";
})());
effect((_p$) => {
var _v$22 = styles().rowModelFnItem, _v$23 = styles().featureLabel, _v$24 = styles().featureMeta;
_v$22 !== _p$.e && className(_el$45, _p$.e = _v$22);
_v$23 !== _p$.t && className(_el$46, _p$.t = _v$23);
_v$24 !== _p$.a && className(_el$47, _p$.a = _v$24);
return _p$;
}, {
e: void 0,
t: void 0,
a: void 0
});
return _el$45;
})()
}), null);
effect((_p$) => {
var _v$19 = styles().rowModelItem, _v$20 = styles().featureLabel, _v$21 = styles().featureMeta;
_v$19 !== _p$.e && className(_el$41, _p$.e = _v$19);
_v$20 !== _p$.t && className(_el$42, _p$.t = _v$20);
_v$21 !== _p$.a && className(_el$43, _p$.a = _v$21);
return _p$;
}, {
e: void 0,
t: void 0,
a: void 0
});
return _el$40;
})()
}),
memo(() => memo(() => !!tableFeatures().has("rowAggregationFeature"))() && (() => {
var _el$48 = _tmpl$11(), _el$49 = _el$48.firstChild, _el$50 = _el$49.firstChild, _el$51 = _el$50.nextSibling, _el$52 = _el$51.firstChild;
insert(_el$51, () => registeredFns().aggregationFns.length, _el$52);
insert(_el$48, createComponent(For, {
get each() {
return registeredFns().aggregationFns;
},
children: (fn) => (() => {
var _el$53 = _tmpl$10(), _el$54 = _el$53.firstChild, _el$55 = _el$54.nextSibling;
insert(_el$54, () => fn.name);
insert(_el$55, () => formatRegisteredFnSize("aggregationFns", fn));
effect((_p$) => {
var _v$28 = styles().rowModelFnItem, _v$29 = styles().featureLabel, _v$30 = styles().featureMeta;
_v$28 !== _p$.e && className(_el$53, _p$.e = _v$28);
_v$29 !== _p$.t && className(_el$54, _p$.t = _v$29);
_v$30 !== _p$.a && className(_el$55, _p$.a = _v$30);
return _p$;
}, {
e: void 0,
t: void 0,
a: void 0
});
return _el$53;
})()
}), null);
effect((_p$) => {
var _v$25 = styles().rowModelItem, _v$26 = styles().featureLabel, _v$27 = styles().featureMeta;
_v$25 !== _p$.e && className(_el$49, _p$.e = _v$25);
_v$26 !== _p$.t && className(_el$50, _p$.t = _v$26);
_v$27 !== _p$.a && className(_el$51, _p$.a = _v$27);
return _p$;
}, {
e: void 0,
t: void 0,
a: void 0
});
return _el$48;
})()),
memo(() => memo(() => rowModelNames().length === 0)() && (() => {
var _el$56 = _tmpl$12();
effect(() => className(_el$56, styles().rowModelItem));
return _el$56;
})()),
(() => {
var _el$36 = _tmpl$9();
_el$36.firstChild;
insert(_el$36, () => formatSize(bundleSizes.package), null);
effect(() => className(_el$36, styles().featureEstimateSummaryNote));
return _el$36;
})(),
(() => {
var _el$38 = _tmpl$0(), _el$39 = _el$38.firstChild;
insert(_el$38, createComponent(For, {
each: EXECUTION_ORDER_GETTERS,
children: (getter, index) => {
const rowModelKey = getterToRowModelKey(getter);
const isPresent = rowModelKey !== null && rowModelNames().includes(rowModelKey);
return [memo(() => index() > 0 && " → "), (() => {
var _el$57 = _tmpl$13();
insert(_el$57, getter);
effect(() => className(_el$57, isPresent ? styles().rowModelExecutionOrderBold : void 0));
return _el$57;
})()];
}
}), null);
effect((_p$) => {
var _v$17 = styles().rowModelExecutionOrder, _v$18 = styles().featureSubsectionTitle;
_v$17 !== _p$.e && className(_el$38, _p$.e = _v$17);
_v$18 !== _p$.t && className(_el$39, _p$.t = _v$18);
return _p$;
}, {
e: void 0,
t: void 0
});
return _el$38;
})()
];
}
}));
effect(() => className(_el$5, styles().panelScroll));
return _el$5;
}
});
}
//#endregion
export { FeaturesPanel };