Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@h6s/table

Package Overview
Dependencies
Maintainers
2
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@h6s/table - npm Package Compare versions

Comparing version 1.0.5-alpha.1 to 2.0.0

dist/index.cjs

160

dist/index.d.ts

@@ -1,4 +0,156 @@

export * from './core/TableCore';
export { composeDataset } from './helpers/composeDataset';
export * from './react';
export * from './types';
import { PropsWithChildren, ReactNode } from 'react';
type Primitive = null | undefined | string | number | boolean;
type IsTuple<T extends readonly any[]> = number extends T['length'] ? false : true;
type TupleKey<T extends readonly any[]> = Exclude<keyof T, keyof any[]>;
type ArrayKey = number;
type PathImpl<K extends string | number, V> = V extends Primitive ? `${K}` : `${K}` | `${K}.${Path<V>}`;
type Path<T> = T extends ReadonlyArray<infer V> ? IsTuple<T> extends true ? {
[K in TupleKey<T>]-?: PathImpl<K & string, T[K]>;
}[TupleKey<T>] : PathImpl<ArrayKey, V> : {
[K in keyof T]-?: PathImpl<K & string, T[K]>;
}[keyof T];
type ArrayPathImpl<K extends string | number, V> = V extends Primitive ? never : V extends ReadonlyArray<infer U> ? U extends Primitive ? never : `${K}` | `${K}.${ArrayPath<V>}` : `${K}.${ArrayPath<V>}`;
type ArrayPath<T> = T extends ReadonlyArray<infer V> ? IsTuple<T> extends true ? {
[K in TupleKey<T>]-?: ArrayPathImpl<K & string, T[K]>;
}[TupleKey<T>] : ArrayPathImpl<ArrayKey, V> : {
[K in keyof T]-?: ArrayPathImpl<K & string, T[K]>;
}[keyof T];
type PathValue<T, P extends Path<T> | ArrayPath<T>> = T extends any ? P extends `${infer K}.${infer R}` ? K extends keyof T ? R extends Path<T[K]> ? PathValue<T[K], R> : never : K extends `${ArrayKey}` ? T extends ReadonlyArray<infer V> ? PathValue<V, R & Path<V>> : never : never : P extends keyof T ? T[P] : P extends `${ArrayKey}` ? T extends ReadonlyArray<infer V> ? V : never : never : never;
type IteratorWithGeneric<T> = T[];
type InferGeneric<TargetType> = TargetType extends IteratorWithGeneric<infer InferType> ? InferType : never;
interface ComposeDatasetOptions<Row, Key extends Path<Row>> {
groupBy: Key;
compose: (rows: Array<Omit<Row, Key>>, key: PathValue<Row, Key>) => Array<Omit<Row, Key>>;
}
declare function composeDataset<Row extends Record<string, any>, Key extends Path<Row>>(rows: Row[], { groupBy: key, compose }: ComposeDatasetOptions<Row, Key>): Row[];
interface CommonCell {
id: string;
rowSpan: number;
colSpan: number;
value: Primitive;
}
interface THead<Row> extends CommonCell {
accessor: Path<Row> | null;
depth: number;
render: CellRecursiveRenderer<THead<Row>>;
labelSequence: string[];
label: string;
}
interface Cell<Row> extends CommonCell {
accessor: Path<Row>;
rowValues: Row;
render: CellRecursiveRenderer<Cell<Row>>;
labelSequence: string[];
label: string;
}
interface TFoot<Row> extends CommonCell {
accessor: Path<Row> | null;
render: CellRecursiveRenderer<TFoot<Row>>;
}
interface PrivateAggregatedCell<Row> extends Pick<Renderer<Row>, 'rules'>, Pick<CommonCell, 'id'> {
accessor: Path<Row>;
render: CellRecursiveRenderer<Cell<Row>>;
labelSequence: string[];
label: string;
}
type CellRendererProps<CellType extends CommonCell> = PropsWithChildren<{
cellProps: CellType;
}>;
type CellRecursiveRenderer<CellType extends CommonCell> = (props: PropsWithChildren<{
cellProps: CellType;
}>) => JSX.Element | null;
type CellComponent<CellType extends CommonCell> = (props: {
cellProps: CellType;
}) => ReactNode | Primitive;
interface RendererRules<Row> {
mergeRow?: Path<Row> | Array<Path<Row>> | ((rowValues: Row) => string);
colSpanAs?: number | ((rowValues: Row) => number);
extendsFoot?: boolean;
}
interface Renderer<Row> {
accessor: Path<Row> | Array<Renderer<Row>>;
label: string;
head?: CellComponent<THead<Row>> | Array<CellRecursiveRenderer<THead<Row>>>;
cell?: CellComponent<Cell<Row>> | Array<CellRecursiveRenderer<Cell<Row>>>;
foot?: CellComponent<TFoot<Row>> | Array<CellRecursiveRenderer<TFoot<Row>>>;
rules?: RendererRules<Row>;
}
type RendererModel<Row> = Array<Renderer<Row>>;
type HeadId<Row> = Path<Row>;
type HeadMeta = Record<string, {
label: string;
show: boolean;
countOfChild: number;
countOfParent: number;
}>;
interface RowProps {
id: string;
rowSpan: number;
}
type TableInstance<Row> = {
theadGroups: Array<{
getRowProps: () => RowProps;
theads: Array<THead<Row>>;
}>;
rows: Array<{
getRowProps: () => RowProps;
cells: Array<Cell<Row>>;
}>;
tfoots: Array<TFoot<Row>> | null;
headMeta: HeadMeta;
selectableHeadIds: HeadId<Row>[];
visibleHeadIds: HeadId<Row>[];
};
type CommonRenderer<CellType extends CommonCell> = CellComponent<CellType> | Array<CellRecursiveRenderer<CellType>>;
type CellConfig<CellType extends CommonCell> = CommonRenderer<CellType> | Record<string, unknown>;
interface TableColumn<Row> {
accessor: Path<Row> | Array<TableColumn<Row>>;
label: string;
head?: CommonRenderer<THead<Row>> | {
render: CommonRenderer<THead<Row>>;
};
cell?: CommonRenderer<Cell<Row>> | {
render?: CommonRenderer<Cell<Row>>;
mergeRow?: Path<Row> | Array<Path<Row>> | ((rowValues: Row) => string);
colSpanAs?: number | ((rowValues: Row) => number);
};
foot?: CommonRenderer<TFoot<Row>> | {
render: CommonRenderer<TFoot<Row>>;
extends?: boolean;
};
}
type TableModel<Row> = Array<TableColumn<Row>>;
declare function isRenderer<CellType extends CommonCell>(value?: CellConfig<CellType>): value is CommonRenderer<CellType>;
interface Options$1<Row extends Record<string, any>, CellRenderer> {
source?: Row[];
cellRenderer?: CellRenderer;
defaultHeadIds?: Array<HeadId<Row>>;
}
declare class TableCore<Row extends Record<string, any>, CellRenderer> {
static compose: typeof composeDataset;
private rendererModel;
private headMeta;
private options;
constructor(model: TableModel<Row>, options: Options$1<Row, CellRenderer>);
updateHead(headIds?: Array<HeadId<Row>>): this;
updateSource(source?: Row[]): this;
generate(): TableInstance<Row>;
composeRows<Key extends Path<Row>>(composeOptions: ComposeDatasetOptions<Row, Key>): this;
}
interface Options<Row extends Record<string, any>> {
model: TableModel<Row>;
source?: Row[];
options?: {
defaultHeadIds?: Array<HeadId<Row>>;
};
}
declare function useTable<Row extends Record<string, any>>({ model, source, options: { defaultHeadIds }, }: Options<Row>): readonly [TableInstance<Row>, {
updateHead(headIds?: Array<HeadId<Row>>): void;
}];
export { type ArrayPath, type Cell, type CellComponent, type CellRecursiveRenderer, type CellRendererProps, type CommonCell, type HeadId, type HeadMeta, type InferGeneric, type Path, type PathValue, type Primitive, type PrivateAggregatedCell, type RendererModel, type RendererRules, type TFoot, type THead, TableCore, type TableInstance, type TableModel, composeDataset, isRenderer, useTable };

@@ -1,2 +0,636 @@

var ee=Object.create;var b=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var oe=Object.getOwnPropertyNames;var ne=Object.getPrototypeOf,te=Object.prototype.hasOwnProperty;var B=o=>b(o,"__esModule",{value:!0});var le=(o,e)=>{for(var r in e)b(o,r,{get:e[r],enumerable:!0})},F=(o,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of oe(e))!te.call(o,t)&&(r||t!=="default")&&b(o,t,{get:()=>e[t],enumerable:!(n=re(e,t))||n.enumerable});return o},se=(o,e)=>F(B(b(o!=null?ee(ne(o)):{},"default",!e&&o&&o.__esModule?{get:()=>o.default,enumerable:!0}:{value:o,enumerable:!0})),o),ae=(o=>(e,r)=>o&&o.get(e)||(r=F(B({}),e,1),o&&o.set(e,r),r))(typeof WeakMap!="undefined"?new WeakMap:0);var me={};le(me,{TableCore:()=>h,composeDataset:()=>T,isRenderer:()=>m,useTable:()=>Re});function w(o,e,r=void 0){let n=a=>String.prototype.split.call(e,a).filter(Boolean).reduce((l,s)=>l!=null?l[s]:l,o),t=n(/[,[\]]+?/)||n(/[,[\].]+?/);return t===void 0||t===o?r:t}function g(o,e){return o.reduce((r,n)=>{let t=e(n);return r[t]==null?r[t]=[n]:r[t].push(n),r},{})}function q(o,e){let r=Object.entries(o);return Object.fromEntries(r.map(([n,t])=>[n,e(t)]))}function T(o,{groupBy:e,compose:r}){let n=ie(o,e),t=pe(n,r);return de(t,e)}function ie(o,e){return q(g(o,r=>String(w(r,e))),r=>r.map(({[e]:n,...t})=>t))}function de(o,e){return Object.entries(o).flatMap(([r,n])=>n.map(t=>({[e]:r,...t})))}function pe(o,e){return Object.fromEntries(Object.entries(o).map(([r,n])=>[r,e(n,r)]))}function m(o){return typeof o=="function"||Array.isArray(o)}function S(o){return o.map(e=>({...e,accessor:Array.isArray(e.accessor)?S(e.accessor):e.accessor,head:m(e.head)?e.head:e.head?.render,cell:m(e.cell)?e.cell:e.cell?.render,foot:m(e.foot)?e.foot:e.foot?.render,rules:{mergeRow:m(e.cell)?void 0:e.cell?.mergeRow,colSpanAs:m(e.cell)?void 0:e.cell?.colSpanAs,extendsFoot:m(e.foot)?void 0:e.foot?.extends}}))}function A(o,e=new Error){if(!o)throw typeof e=="string"?new Error(e):e}function v(o){return Object.entries(o)}function y(o){return Array.isArray(o.accessor)?o.accessor.map(e=>y(e)).join("+"):o.accessor}function O(o,e){let r=[];for(let n of o){let t=Array.isArray(n.accessor)?y(n):n.accessor;if(e[t].show){let a=Array.isArray(n.accessor)?{...n,accessor:O(n.accessor,e)}:n;r.push(a)}}return r}function R(){return ue("table")}var H=0,M=new Map;function ue(o){if(M.has(o)){let r=M.get(o)+1;M.set(o,r),H=r}else{let e=1;M.set(o,e),H=e}return`${o}-${H}`}function V(o,e){return E(o,{...e,labelSequence:[]})}function E(o,{cellRenderer:e,labelSequence:r}){let n=[];for(let t of o){let{accessor:a,label:l,cell:s,rules:i}=t,p=Array.isArray(a),c=r.concat(l);p?n.push(...E(a,{labelSequence:c,cellRenderer:e})):n.push({id:R(),accessor:a,label:l,labelSequence:c,render:typeof e=="function"?e(s):({cellProps:d})=>d.value,rules:i})}return n}var P=class{constructor(){this.rowSpanMap=new Map}getColSpan(e,r){let{colSpanRule:n}=this.parseRules(r);return typeof n=="function"?n(e):n??1}getRowSpan(e,r){let n=this.getRowSpanMapKey(e,r);return n==null?1:this.rowSpanMap.get(n)}saveRowSpan(e,r){let n=this.getRowSpanMapKey(e,r);if(n!=null){let t=this.rowSpanMap.get(n);if(t!=null)return this.rowSpanMap.set(n,t+1),!0;this.rowSpanMap.set(n,1)}return!1}getMaxRowSpan(){return Math.max(...this.rowSpanMap.values())}parseRules(e){let{mergeRow:r,colSpanAs:n}=e??{};return{mergeRow:r,colSpanRule:n}}getRowSpanMapKey(e,r){let{mergeRow:n}=this.parseRules(r);if(n!=null)return typeof n=="function"?n(e):Array.isArray(n)?n.map(t=>w(e,t)).join("+"):JSON.stringify(w(e,n))}};function U(o,{cells:e}){let r=new P;return{rows:o.map(a=>e.map(l=>{let s=w(a,l.accessor);return r.saveRowSpan(a,l.rules)?null:{value:s,row:a,...l}}).filter(l=>l!=null)).map(a=>({getRowProps(){return{id:R(),rowSpan:r.getMaxRowSpan()}},cells:a.map(l=>{A(l!=null,"invalid cell");let{row:s,rules:i,value:p,...c}=l;return{rowSpan:r.getRowSpan(s,i)??1,colSpan:r.getColSpan(s,i),rowValues:s,value:p,...c}})}))}}function G(o,e,r){return o.includes(e,r)}function N(o,e){let r=[];for(;o.length>0&&e(o[0]);)r.push(o.shift()??null);return r}function _(o,e){let r=[];for(;o.length>0&&e(o[o.length-1]);)r.push(o.pop()??null);return r}function I(o){let e=[];for(let r of o){let{accessor:n}=r;Array.isArray(n)?e.push(...I(n)):e.push(r)}return e}function z(o,e){let r=ce(o);if(r==null)return{tfoots:null};let{result:{head:n,middle:t,tail:a},colSpanQueue:l}=r,s=L(t,{...e,colSpanQueue:l});return n.length>0&&s.unshift({...x(),colSpan:n.length}),a.length>0&&s.push({...x(),colSpan:a.length}),{tfoots:s.length===0?null:s}}function L(o,{cellRenderer:e,colSpanQueue:r}){let n=[];for(let t of o){let{label:a,accessor:l,foot:s}=t;if(Array.isArray(l))n.push(...L(l,{cellRenderer:e,colSpanQueue:r}));else if(s!=null)n.push({...x(),accessor:l,colSpan:r.shift()??1,value:a,render:typeof e=="function"?e(s):({cellProps:p})=>p.value});else{let p=r.shift();p==null?n.push({...x(),accessor:l,colSpan:1}):r.unshift(p)}}return n}function W(o){let e=[];for(let r of o){let{accessor:n,foot:t,rules:a}=r;if(Array.isArray(n))e.push(...W(n));else if(t!=null)e.push({value:1,extends:a?.extendsFoot??!0});else{let s=e.pop();s!=null?s.extends?e.push({value:(s.value??1)+1,extends:s.extends}):(e.push(s),e.push({value:null,extends:s.extends})):e.push(null)}}return e}function ce(o){let e=I(o);if(e.every(l=>l.foot==null))return null;let r=W(o).map(l=>l?.value??null),n=N(e,l=>l.foot==null),t=_(e,l=>l.foot==null),a=e;if(t.length>0){let l=r.pop()??1;r.push(l-t.length)}return{colSpanQueue:r,result:{head:n,tail:t,middle:a}}}function x(){return{id:R(),accessor:null,rowSpan:1,value:null,render:()=>null}}function C(o){return o.reduce((e,{accessor:r})=>Array.isArray(r)?C(r)+1:e,1)}function K(o,e){return{headMeta:$(o,{...e,depth:0})}}function $(o,e){let r={},{visibleHeadIds:n,depth:t}=e;for(let a of o){let{label:l,accessor:s}=a,i=Array.isArray(s),p=i?s:[{accessor:s}],c=n!=null?p.some(d=>G(n,d.accessor)):!0;r[y(a)]={label:l,show:c,countOfChild:i?C(s):0,countOfParent:t},i&&Object.assign(r,$(s,{...e,depth:t+1}))}return r}function J({theads:o}){let e=Object.values(g(o,n=>String(n.depth)));return{theadGroups:e.map(n=>({theads:n,getRowProps(){return{id:R(),rowSpan:e.length}}}))}}function j(o){return Array.isArray(o.accessor)?o.accessor.reduce((e,r)=>e+j(r),0):1}function Q(o,e){let r=C(o);return X(o,{...e,largestDepth:r,depth:1,labelSequence:[]})}function X(o,{cellRenderer:e,largestDepth:r,depth:n,labelSequence:t}){let a=[];for(let l of o){let{label:s,accessor:i,head:p}=l,c=Array.isArray(i),d=t.concat(s);c&&a.push(...X(i,{largestDepth:r,depth:n+1,labelSequence:d,cellRenderer:e})),a.push({id:R(),accessor:c?null:i,rowSpan:c?1:n>1?r-n+1:r,colSpan:j(l),label:s,value:s,labelSequence:d,render:typeof e=="function"?e(p):({cellProps:Z})=>Z.value,depth:n})}return a}var D=class{constructor(e,r){let n=S(e),{headMeta:t}=K(n,{visibleHeadIds:r.defaultHeadIds});this.options=r,this.rendererModel=n,this.headMeta=t}updateHead(e){A(e==null||e?.length>0,"headIds must be an array");let{headMeta:r}=K(this.rendererModel,{visibleHeadIds:e});return this.headMeta=r,this}updateSource(e){return this.options.source=e,this}generate(){let{rendererModel:e,headMeta:r,options:{source:n=[],cellRenderer:t}}=this,a=O(e,r),{theadGroups:l}=J({theads:Q(a,{cellRenderer:t})}),{rows:s}=U(n,{cells:V(a,{cellRenderer:t})}),{tfoots:i}=z(a,{cellRenderer:t}),p=v(r).filter(([,d])=>d.countOfChild===0).map(([d])=>d),c=v(r).filter(([,d])=>d.show&&d.countOfChild===0).map(([d])=>d);return{theadGroups:l,rows:s,tfoots:i,headMeta:r,selectableHeadIds:p,visibleHeadIds:c}}composeRows(e){return this.options.source=D.compose(this.options.source??[],e),this}},h=D;h.compose=T;var f=require("react");var u=se(require("react"));function Y(o){return({cellProps:e,...r})=>e.colSpan===0?null:o==null||o.length===0?u.default.createElement(u.default.Fragment,null,e.value):typeof o=="string"?u.default.createElement(u.default.Fragment,null,o):typeof o=="function"?u.default.createElement(u.default.Fragment,null,o({cellProps:e,...r})):u.default.createElement(k,{renderers:o,cellProps:e,...r})}function k({renderers:o,index:e=0,cellProps:r}){let n=o[e];return e===o.length-1?e===0?u.default.createElement(n,{cellProps:r,rowSpan:r.rowSpan,colSpan:r.colSpan},r.value):u.default.createElement(n,{cellProps:r},r.value):e===0?u.default.createElement(n,{cellProps:r,rowSpan:r.rowSpan,colSpan:r.colSpan},u.default.createElement(k,{renderers:o,index:e+1,cellProps:r})):u.default.createElement(n,{cellProps:r},u.default.createElement(k,{renderers:o,index:e+1,cellProps:r}))}function Re({model:o,source:e,options:{defaultHeadIds:r}={}}){let n=(0,f.useRef)(new h(o,{source:e,cellRenderer:Y,defaultHeadIds:r})),[t,a]=(0,f.useState)(()=>n.current.generate()),l=(0,f.useMemo)(()=>({updateHead(s){a(()=>n.current.updateHead(s).generate())}}),[]);return(0,f.useEffect)(()=>{a(()=>n.current.updateSource(e).generate())},[e]),[t,l]}module.exports=ae(me);
//# sourceMappingURL=index.js.map
// src/utils/get.ts
function get(obj, path, defaultValue = void 0) {
const travel = (regexp) => String.prototype.split.call(path, regexp).filter(Boolean).reduce((acc, key) => acc !== null && acc !== void 0 ? acc[key] : acc, obj);
const result = travel(/[,[\]]+?/) || travel(/[,[\].]+?/);
return result === void 0 || result === obj ? defaultValue : result;
}
// src/utils/groupBy.ts
function groupBy(data, createKey) {
return data.reduce((result, current) => {
const key = createKey(current);
if (result[key] == null) {
result[key] = [current];
} else {
result[key].push(current);
}
return result;
}, {});
}
// src/utils/mapValues.ts
function mapValues(value, mapper) {
const entries = Object.entries(value);
return Object.fromEntries(
entries.map(([k, v]) => {
return [k, mapper(v)];
})
);
}
// src/helpers/composeDataset.ts
function composeDataset(rows, { groupBy: key, compose }) {
const normalized = normalize(rows, key);
const result = insert(normalized, compose);
return reverseNormalize(result, key);
}
function normalize(rows, key) {
return mapValues(
groupBy(rows, (x) => String(get(x, key))),
(x) => x.map(({ [key]: _, ...rest }) => rest)
);
}
function reverseNormalize(normalizedValue, key) {
return Object.entries(normalizedValue).flatMap(
([id, entries]) => entries.map((entry) => ({ [key]: id, ...entry }))
);
}
function insert(body, compose) {
return Object.fromEntries(
Object.entries(body).map(([key, entities]) => {
return [key, compose(entities, key)];
})
);
}
// src/types/table.ts
function isRenderer(value) {
return typeof value === "function" || Array.isArray(value);
}
// src/helpers/transToRendererModel.ts
function transToRendererModel(model) {
return model.map((x) => {
return {
...x,
accessor: Array.isArray(x.accessor) ? transToRendererModel(x.accessor) : x.accessor,
head: isRenderer(x.head) ? x.head : x.head?.render,
cell: isRenderer(x.cell) ? x.cell : x.cell?.render,
foot: isRenderer(x.foot) ? x.foot : x.foot?.render,
rules: {
mergeRow: isRenderer(x.cell) ? void 0 : x.cell?.mergeRow,
colSpanAs: isRenderer(x.cell) ? void 0 : x.cell?.colSpanAs,
extendsFoot: isRenderer(x.foot) ? void 0 : x.foot?.extends
}
};
});
}
// src/utils/invariant.ts
function invariant(condition, error = new Error()) {
if (!condition) {
if (typeof error === "string") {
throw new Error(error);
} else {
throw error;
}
}
}
// src/utils/object.ts
function objectEntries(obj) {
return Object.entries(obj);
}
// src/core/renderer/getHeaderAccessorId.ts
function getHeaderAccessorId(model) {
return Array.isArray(model.accessor) ? model.accessor.map((model2) => getHeaderAccessorId(model2)).join("+") : model.accessor;
}
// src/core/renderer/buildRendererModel.ts
function buildRendererModel(rendererModel, headMeta) {
const result = [];
for (const model of rendererModel) {
const id = Array.isArray(model.accessor) ? getHeaderAccessorId(model) : model.accessor;
if (headMeta[id].show) {
const value = Array.isArray(model.accessor) ? { ...model, accessor: buildRendererModel(model.accessor, headMeta) } : model;
result.push(value);
}
}
return result;
}
// src/utils/generateTableID.ts
function generateTableID() {
return generateID("table");
}
var randomId = 0;
var map = /* @__PURE__ */ new Map();
function generateID(prefix) {
if (map.has(prefix)) {
const id = map.get(prefix);
const newId = id + 1;
map.set(prefix, newId);
randomId = newId;
} else {
const id = 1;
map.set(prefix, id);
randomId = id;
}
return `${prefix}-${randomId}`;
}
// src/core/row/buildCells.ts
function buildCells(rendererModel, options) {
return _build(rendererModel, { ...options, labelSequence: [] });
}
function _build(rendererModel, { cellRenderer: cellRenderer2, labelSequence }) {
const cells = [];
for (const model of rendererModel) {
const { accessor, label, cell, rules } = model;
const hasChild = Array.isArray(accessor);
const sequence = labelSequence.concat(label);
if (hasChild) {
cells.push(
..._build(accessor, {
labelSequence: sequence,
cellRenderer: cellRenderer2
})
);
} else {
cells.push({
id: generateTableID(),
accessor,
label,
labelSequence: sequence,
render: typeof cellRenderer2 === "function" ? cellRenderer2(cell) : ({ cellProps }) => cellProps.value,
rules
});
}
}
return cells;
}
// src/core/row/CellSpanManager.ts
var CellSpanManager = class {
rowSpanMap;
constructor() {
this.rowSpanMap = /* @__PURE__ */ new Map();
}
getColSpan(Row, rules) {
const { colSpanRule } = this.parseRules(rules);
return typeof colSpanRule === "function" ? colSpanRule(Row) : colSpanRule ?? 1;
}
getRowSpan(Row, rules) {
const key = this.getRowSpanMapKey(Row, rules);
if (key == null) {
return 1;
}
return this.rowSpanMap.get(key);
}
saveRowSpan(Row, rules) {
const key = this.getRowSpanMapKey(Row, rules);
if (key != null) {
const savedRowSpan = this.rowSpanMap.get(key);
if (savedRowSpan != null) {
this.rowSpanMap.set(key, savedRowSpan + 1);
return true;
}
this.rowSpanMap.set(key, 1);
}
return false;
}
getMaxRowSpan() {
return Math.max(...this.rowSpanMap.values());
}
parseRules(rules) {
const { mergeRow, colSpanAs: colSpanRule } = rules ?? {};
return { mergeRow, colSpanRule };
}
getRowSpanMapKey(row, rules) {
const { mergeRow } = this.parseRules(rules);
if (mergeRow == null) {
return;
}
if (typeof mergeRow === "function") {
return mergeRow(row);
}
if (Array.isArray(mergeRow)) {
return mergeRow.map((accessor) => get(row, accessor)).join("+");
}
return JSON.stringify(get(row, mergeRow));
}
};
// src/core/row/buildRows.ts
function buildRows(data, { cells }) {
const manager = new CellSpanManager();
const candidateRows = data.map((row) => {
return cells.map((cell) => {
const value = get(row, cell.accessor);
const dropCell = manager.saveRowSpan(row, cell.rules);
if (dropCell) {
return null;
}
return { value, row, ...cell };
}).filter((x) => x != null);
});
const rows = candidateRows.map((cells2) => {
return {
getRowProps() {
return {
id: generateTableID(),
rowSpan: manager.getMaxRowSpan()
};
},
cells: cells2.map((aggregatedCell) => {
invariant(aggregatedCell != null, "invalid cell");
const { row, rules, value, ...rest } = aggregatedCell;
const cell = {
rowSpan: manager.getRowSpan(row, rules) ?? 1,
colSpan: manager.getColSpan(row, rules),
rowValues: row,
value,
...rest
};
return cell;
})
};
});
return { rows };
}
// src/utils/array.ts
function arrayIncludes(array, item, fromIndex) {
return array.includes(item, fromIndex);
}
function shiftUntil(arr, predicate) {
const result = [];
while (arr.length > 0 && predicate(arr[0])) {
result.push(arr.shift() ?? null);
}
return result;
}
function popUntil(arr, predicate) {
const result = [];
while (arr.length > 0 && predicate(arr[arr.length - 1])) {
result.push(arr.pop() ?? null);
}
return result;
}
// src/core/renderer/flattenRendererModel.ts
function flattenRendererModel(rendererModel) {
const models = [];
for (const model of rendererModel) {
const { accessor } = model;
const hasChild = Array.isArray(accessor);
if (hasChild) {
models.push(...flattenRendererModel(accessor));
} else {
models.push(model);
}
}
return models;
}
// src/core/tfoot/buildTFoots.ts
function buildTFoots(rendererModel, options) {
const parsed = prepare(rendererModel);
if (parsed == null) {
return { tfoots: null };
}
const {
result: { head, middle, tail },
colSpanQueue
} = parsed;
const tfoots = _build2(middle, { ...options, colSpanQueue });
if (head.length > 0) {
tfoots.unshift({ ...getDefaultTFootCell(), colSpan: head.length });
}
if (tail.length > 0) {
tfoots.push({ ...getDefaultTFootCell(), colSpan: tail.length });
}
return { tfoots: tfoots.length === 0 ? null : tfoots };
}
function _build2(rendererModel, { cellRenderer: cellRenderer2, colSpanQueue }) {
const tfoots = [];
for (const model of rendererModel) {
const { label, accessor, foot } = model;
const hasChild = Array.isArray(accessor);
if (hasChild) {
tfoots.push(..._build2(accessor, { cellRenderer: cellRenderer2, colSpanQueue }));
} else {
if (foot != null) {
tfoots.push({
...getDefaultTFootCell(),
accessor,
colSpan: colSpanQueue.shift() ?? 1,
value: label,
render: typeof cellRenderer2 === "function" ? cellRenderer2(foot) : ({ cellProps }) => cellProps.value
});
} else {
const colSpan = colSpanQueue.shift();
if (colSpan == null) {
tfoots.push({
...getDefaultTFootCell(),
accessor,
colSpan: 1
});
} else {
colSpanQueue.unshift(colSpan);
}
}
}
}
return tfoots;
}
function buildColSpanQueue(rendererModel) {
const queue = [];
for (const model of rendererModel) {
const { accessor, foot, rules } = model;
const hasChild = Array.isArray(accessor);
if (hasChild) {
queue.push(...buildColSpanQueue(accessor));
} else {
if (foot != null) {
queue.push({
value: 1,
extends: rules?.extendsFoot ?? true
});
} else {
const lastValue = queue.pop();
if (lastValue != null) {
if (lastValue.extends) {
queue.push({ value: (lastValue.value ?? 1) + 1, extends: lastValue.extends });
} else {
queue.push(lastValue);
queue.push({ value: null, extends: lastValue.extends });
}
} else {
queue.push(null);
}
}
}
}
return queue;
}
function prepare(rendererModel) {
const model = flattenRendererModel(rendererModel);
if (model.every((x) => x.foot == null)) {
return null;
}
const colSpanQueue = buildColSpanQueue(rendererModel).map((x) => x?.value ?? null);
const head = shiftUntil(model, (x) => x.foot == null);
const tail = popUntil(model, (x) => x.foot == null);
const middle = model;
if (tail.length > 0) {
const lastColSpan = colSpanQueue.pop() ?? 1;
colSpanQueue.push(lastColSpan - tail.length);
}
return {
colSpanQueue,
result: {
head,
tail,
middle
}
};
}
function getDefaultTFootCell() {
return {
id: generateTableID(),
accessor: null,
rowSpan: 1,
value: null,
render: () => null
};
}
// src/core/renderer/getLargestDepth.ts
function getLargestDepth(rendererModel) {
return rendererModel.reduce((acc, { accessor }) => {
return Array.isArray(accessor) ? getLargestDepth(accessor) + 1 : acc;
}, 1);
}
// src/core/thead/buildHeadMeta.ts
function buildHeadMeta(rendererModel, options) {
const headMeta = _build3(rendererModel, { ...options, depth: 0 });
return { headMeta };
}
function _build3(rendererModel, options) {
const headMeta = {};
const { visibleHeadIds, depth } = options;
for (const model of rendererModel) {
const { label, accessor } = model;
const hasChild = Array.isArray(accessor);
const base = hasChild ? accessor : [{ accessor }];
const show = visibleHeadIds != null ? base.some((x) => arrayIncludes(visibleHeadIds, x.accessor)) : true;
headMeta[getHeaderAccessorId(model)] = {
label,
show,
countOfChild: hasChild ? getLargestDepth(accessor) : 0,
countOfParent: depth
};
if (hasChild) {
Object.assign(headMeta, _build3(accessor, { ...options, depth: depth + 1 }));
}
}
return headMeta;
}
// src/core/thead/buildTHeadGroups.ts
function buildTHeadGroups({ theads }) {
const groupByDepth = Object.values(groupBy(theads, (x) => String(x.depth)));
const theadGroups = groupByDepth.map((theads2) => {
return {
theads: theads2,
getRowProps() {
return {
id: generateTableID(),
rowSpan: groupByDepth.length
};
}
};
});
return { theadGroups };
}
// src/core/renderer/getChildrenCount.ts
function getChildrenCount(model) {
if (!Array.isArray(model.accessor)) {
return 1;
}
return model.accessor.reduce((acc, result) => {
return acc + getChildrenCount(result);
}, 0);
}
// src/core/thead/buildTHeads.ts
function buildTHeads(rendererModel, options) {
const largestDepth = getLargestDepth(rendererModel);
return _build4(rendererModel, { ...options, largestDepth, depth: 1, labelSequence: [] });
}
function _build4(rendererModel, { cellRenderer: cellRenderer2, largestDepth, depth, labelSequence }) {
const heads = [];
for (const model of rendererModel) {
const { label, accessor, head } = model;
const hasChild = Array.isArray(accessor);
const sequence = labelSequence.concat(label);
if (hasChild) {
heads.push(
..._build4(accessor, {
largestDepth,
depth: depth + 1,
labelSequence: sequence,
cellRenderer: cellRenderer2
})
);
}
heads.push({
id: generateTableID(),
accessor: hasChild ? null : accessor,
rowSpan: hasChild ? 1 : depth > 1 ? largestDepth - depth + 1 : largestDepth,
colSpan: getChildrenCount(model),
label,
value: label,
labelSequence: sequence,
render: typeof cellRenderer2 === "function" ? cellRenderer2(head) : ({ cellProps }) => cellProps.value,
depth
});
}
return heads;
}
// src/core/TableCore.ts
var TableCore = class _TableCore {
static compose = composeDataset;
rendererModel;
headMeta;
options;
constructor(model, options) {
const rendererModel = transToRendererModel(model);
const { headMeta } = buildHeadMeta(rendererModel, {
visibleHeadIds: options.defaultHeadIds
});
this.options = options;
this.rendererModel = rendererModel;
this.headMeta = headMeta;
}
updateHead(headIds) {
invariant(headIds == null || headIds?.length > 0, "headIds must be an array");
const { headMeta } = buildHeadMeta(this.rendererModel, {
visibleHeadIds: headIds
});
this.headMeta = headMeta;
return this;
}
updateSource(source) {
this.options.source = source;
return this;
}
generate() {
const {
rendererModel,
headMeta,
options: { source = [], cellRenderer: cellRenderer2 }
} = this;
const model = buildRendererModel(rendererModel, headMeta);
const { theadGroups } = buildTHeadGroups({
theads: buildTHeads(model, { cellRenderer: cellRenderer2 })
});
const { rows } = buildRows(source, {
cells: buildCells(model, { cellRenderer: cellRenderer2 })
});
const { tfoots } = buildTFoots(model, { cellRenderer: cellRenderer2 });
const selectableHeadIds = objectEntries(headMeta).filter(([, x]) => x.countOfChild === 0).map(([id]) => id);
const visibleHeadIds = objectEntries(headMeta).filter(([, x]) => x.show && x.countOfChild === 0).map(([id]) => id);
return {
theadGroups,
rows,
tfoots,
headMeta,
selectableHeadIds,
visibleHeadIds
};
}
composeRows(composeOptions) {
this.options.source = _TableCore.compose(this.options.source ?? [], composeOptions);
return this;
}
};
// src/react/useTable.ts
import { useEffect, useMemo, useRef, useState } from "react";
// src/helpers/cellRenderer.tsx
import { Fragment, jsx } from "react/jsx-runtime";
function cellRenderer(renderers) {
return ({ cellProps, ...props }) => {
if (cellProps.colSpan === 0) {
return null;
}
if (renderers == null || renderers.length === 0) {
return /* @__PURE__ */ jsx(Fragment, { children: cellProps.value });
}
if (typeof renderers === "string") {
return /* @__PURE__ */ jsx(Fragment, { children: renderers });
}
if (typeof renderers === "function") {
return /* @__PURE__ */ jsx(Fragment, { children: renderers({ cellProps, ...props }) });
}
return /* @__PURE__ */ jsx(CombinedCell, { renderers, cellProps, ...props });
};
}
function CombinedCell({
renderers,
index = 0,
cellProps
}) {
const Renderer = renderers[index];
if (index === renderers.length - 1) {
if (index === 0) {
const CellComponent = Renderer;
return /* @__PURE__ */ jsx(
CellComponent,
{
cellProps,
rowSpan: cellProps.rowSpan,
colSpan: cellProps.colSpan,
children: cellProps.value
}
);
}
return /* @__PURE__ */ jsx(Renderer, { cellProps, children: cellProps.value });
}
if (index === 0) {
const CellComponent = Renderer;
return /* @__PURE__ */ jsx(CellComponent, { cellProps, rowSpan: cellProps.rowSpan, colSpan: cellProps.colSpan, children: /* @__PURE__ */ jsx(CombinedCell, { renderers, index: index + 1, cellProps }) });
}
return /* @__PURE__ */ jsx(Renderer, { cellProps, children: /* @__PURE__ */ jsx(CombinedCell, { renderers, index: index + 1, cellProps }) });
}
// src/react/useTable.ts
function useTable({
model,
source,
options: { defaultHeadIds } = {}
}) {
const tableCore = useRef(
new TableCore(model, {
source,
cellRenderer,
defaultHeadIds
})
);
const [instance, setInstance] = useState(() => tableCore.current.generate());
const controls = useMemo(
() => ({
updateHead(headIds) {
setInstance(() => tableCore.current.updateHead(headIds).generate());
}
}),
[]
);
useEffect(() => {
setInstance(() => tableCore.current.updateSource(source).generate());
}, [source]);
return [instance, controls];
}
export {
TableCore,
composeDataset,
isRenderer,
useTable
};

72

package.json
{
"name": "@h6s/table",
"version": "1.0.5-alpha.1",
"version": "2.0.0",
"sideEffects": false,
"main": "src/index.ts",
"files": [
"dist",
"esm"
],
"exports": {
".": {
"require": "./src/index.ts",
"import": "./src/index.ts"
},
"./package.json": "./package.json"
},
"type": "module",
"publishConfig": {
"access": "public",
"main": "dist/index.cjs",
"module": "dist/index.js",
"types": "dist/index.d.cts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"require": "./dist/index.js",
"import": "./esm/index.mjs"
},
"./package.json": "./package.json"
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"import": "esm/index.mjs",
"module": "esm/index.mjs"
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
},
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
}
}
},
"files": [
"dist"
],
"scripts": {
"prepack": "yarn build",
"prebuild": "rimraf dist esm",
"build:type": "yarn run -T tsc --emitDeclarationOnly --declaration",
"build": "yarn build:type && node ../../scripts/build.js",
"build": "yarn run -T tsup",
"lint": "yarn run -T eslint 'src/**/*.{js,jsx,ts,tsx}'",
"lint:fix": "yarn lint --fix",
"typecheck": "yarn run -T tsc",
"test": "yarn run -T jest --config ../../jest.config.js --roots './packages/table/src'",
"test:playwright": "playwright test",
"test": "vitest",
"test:cov": "yarn test --coverage",
"test:watch": "yarn test --watch",
"semantic-release": "semantic-release"
"test:watch": "yarn test --watch"
},
"devDependencies": {
"@playwright/test": "1.17.1",
"@storybook/react": "6.4.9",
"@testing-library/react-hooks": "7.0.2",
"@types/jest": "27.4.0",
"@types/node": "17.0.5",
"@types/react": "^18.0.25",
"playwright": "1.17.1",
"@storybook/react": "7.6.4",
"@testing-library/jest-dom": "^6.1.5",
"@testing-library/react-hooks": "8.0.1",
"@types/node": "20.10.4",
"@types/react": "^18.2.43",
"happy-dom": "^12.10.3",
"jsdom": "^23.0.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-test-renderer": "^18.2.0"
"react-test-renderer": "^18.2.0",
"typescript": "^5.3.3",
"vite": "^5.0.7",
"vitest": "^1.0.4"
},
"peerDependencies": {
"react": "^16.8 || ^17.0 || ^18.0"
"react": ">= 18"
},

@@ -61,0 +55,0 @@ "peerDependenciesMeta": {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc