npm & Framework Usage

Install and use @codeseasy/collapsetable with npm. Recipes for React, Next.js/Remix, Vue 3, Svelte, and Angular. Matches the theme of the main docs.

UMD / ESM / CJS Types included v1.2.0

1) Install

npm

npm i @codeseasy/collapsetable

pnpm

pnpm add @codeseasy/collapsetable

yarn

yarn add @codeseasy/collapsetable

2) Import patterns

ESM (Vite, Rollup, modern bundlers)

import CollapseTable from '@codeseasy/collapsetable';

const ct = new CollapseTable();
ct.set('#orders');

CommonJS (Webpack, older Node configs)

const CollapseTable = require('@codeseasy/collapsetable');

const ct = new CollapseTable();
ct.set('#orders');

Default export with bundled TypeScript types for great IntelliSense.

3) Minimal example (npm)

HTML

<table id="table1">
  <thead>
    <tr>
      <th data-priority="1" data-min="180">Project</th>
      <th data-priority="2" data-min="140">Client</th>
      <th data-priority="3" data-min="120">Status</th>
      <th data-priority="4" data-min="120">Budget</th>
    </tr>
  </thead>
  <tbody>
    <tr><td>Website Revamp</td><td>Acme</td><td>Active</td><td>₹2,50,000</td></tr>
    <tr><td>Android App</td><td>Globex</td><td>Planning</td><td>₹1,80,000</td></tr>
  </tbody>
</table>

TypeScript / JS

import CollapseTable from '@codeseasy/collapsetable';

const ct = new CollapseTable();
ct.set('#table1'); // id, selector, or <table> element

4) Markup requirements (quick recap)

5) API (essentials)

const ct = new CollapseTable(globalOptions?);

// Attach / detach
const controller  = ct.set(target, perTableOptions?);      // one table
const controllers = ct.setAll(targets, perTableOptions?);  // many
ct.unset(target);
ct.unsetAll(targets);

// Refresh / controls
ct.refresh(target?);
ct.expandAll(target?);
ct.collapseAll(target?);
ct.expandRow(target, rowOrIndex);
ct.collapseRow(target, rowOrIndex);

// Options helpers
ct.getOptions();
ct.updateOptions(partial);

// Runtime mode
ct.setMode('development');       // 'production' | 'development' (default: 'production')
ct.getMode();                    // -> current mode

// Events
ct.on('expand'|'collapse'|'toggle'|'refit'|'destroy', handler);
ct.off('expand'|'collapse'|'toggle'|'refit'|'destroy', handler);

// Version
CollapseTable.version; // "1.2.0"

6) Runtime mode (development vs production)

Default is production (silent). Switch to development to get helpful, one-time console warnings during integration.

// a) At construction
const ct = new CollapseTable({ mode: 'development' });

// b) Later, at runtime
ct.setMode('development');  // or 'production'

// c) Read current mode
console.log(ct.getMode()); // 'development' | 'production'

7) TypeScript tips

Types

import CollapseTable from '@codeseasy/collapsetable';

type Options     = CollapseTable.Options;
type Controller  = CollapseTable.Controller;
type RefitEvent  = CollapseTable.RefitEventPayload;

const ct = new CollapseTable({ mode: 'development' });

Strongly typed events

ct.on('refit', (e) => {
  // e is CollapseTable.RefitEventPayload
  console.log(e.initial, e.anyHidden);
});

ct.on('toggle', (e) => {
  // e is CollapseTable.ToggleEventPayload
  console.log(e.row, e.expanded);
});

8) Framework recipes

8.1 React (Vite/CRA)

import { useEffect, useRef } from 'react';
import CollapseTable from '@codeseasy/collapsetable';

export default function OrdersTable({ rows }: { rows: Array<any> }) {
  const tableRef = useRef<HTMLTableElement | null>(null);
  const ctRef = useRef<CollapseTable | null>(null);

  useEffect(() => {
    const table = tableRef.current;
    if (!table) return;

    const ct = (ctRef.current ||= new CollapseTable({ mode: 'development' }));
    ct.set(table, {
      icons: { expand: '▶', collapse: '▼' },
    });

    return () => ct.unset(table);
  }, []);

  useEffect(() => {
    if (tableRef.current) ctRef.current?.refresh(tableRef.current);
  }, [rows]);

  return (
    <table ref={tableRef} id="orders">
      <thead>
        <tr>
          <th data-priority="1" data-min="160">Project</th>
          <th data-priority="2" data-min="120">Client</th>
          <th data-priority="3" data-min="120">Status</th>
        </tr>
      </thead>
      <tbody>
        {rows.map((r, i) => (
          <tr key={i}><td>{r.project}</td><td>{r.client}</td><td>{r.status}</td></tr>
        ))}
      </tbody>
    </table>
  );
}

Custom details rendering (React)

Return a DOM Node or HTML string (don’t rely on React synthetic events inside).

detailsRender(row, hiddenCols, cells) {
  const el = document.createElement('div');
  el.className = 'react-details';
  el.innerHTML = hiddenCols.map(c => {
    const label = c.th.getAttribute('data-label') || c.th.textContent || '';
    return `<div><strong>${label}:</strong> ${cells[c.index]?.innerHTML ?? ''}</div>`;
  }).join('');
  return el;
}

8.2 Next.js / Remix (SSR)

'use client';
import { useEffect, useRef } from 'react';
import CollapseTable from '@codeseasy/collapsetable';

export default function OrdersClient() {
  const tableRef = useRef<HTMLTableElement | null>(null);

  useEffect(() => {
    const table = tableRef.current;
    if (!table) return;
    const ct = new CollapseTable({ mode: 'development' });
    ct.set(table);
    return () => ct.unset(table);
  }, []);

  return (/* same markup as React example */);
}

Dynamic import (client-only)

import dynamic from 'next/dynamic';
const OrdersClient = dynamic(() => import('./OrdersClient'), { ssr: false });

8.3 Vue 3 (Composition API)

<script setup lang="ts">
import { onMounted, onBeforeUnmount, ref, nextTick, watch } from 'vue';
import CollapseTable from '@codeseasy/collapsetable';

const tableEl = ref<HTMLTableElement | null>(null);
const rows = ref<Array<any>>([]);
let ct: CollapseTable | null = null;

onMounted(async () => {
  await nextTick();
  if (!tableEl.value) return;
  ct = new CollapseTable({ mode: 'development' });
  ct.set(tableEl.value, { tableLayout: 'auto' });
});

onBeforeUnmount(() => {
  if (ct && tableEl.value) ct.unset(tableEl.value);
});

watch(rows, async () => {
  await nextTick();
  if (ct && tableEl.value) ct.refresh(tableEl.value);
});
</script>

<template>
  <table ref="tableEl" id="orders">
    <thead>
      <tr>
        <th data-priority="1" data-min="160">Project</th>
        <th data-priority="2" data-min="120">Client</th>
        <th data-priority="3" data-min="120">Status</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(r,i) in rows" :key="i">
        <td>{{ r.project }}</td><td>{{ r.client }}</td><td>{{ r.status }}</td>
      </tr>
    </tbody>
  </table>
</template>

8.4 Svelte

<script lang="ts">
  import { onMount, tick } from 'svelte';
  import CollapseTable from '@codeseasy/collapsetable';

  let tableEl: HTMLTableElement;
  export let rows: Array<any> = [];
  let ct: CollapseTable;

  onMount(() => {
    ct = new CollapseTable({ mode: 'development' });
    ct.set(tableEl);
    return () => ct.unset(tableEl);
  });

  // refresh when rows change
  $: (async () => {
    if (!ct || !tableEl) return;
    await tick();
    ct.refresh(tableEl);
  })();
</script>

<table bind:this={tableEl} id="orders">
  <thead>
    <tr>
      <th data-priority="1" data-min="160">Project</th>
      <th data-priority="2" data-min="120">Client</th>
      <th data-priority="3" data-min="120">Status</th>
    </tr>
  </thead>
  <tbody>
    {#each rows as r, i}
      <tr><td>{r.project}</td><td>{r.client}</td><td>{r.status}</td></tr>
    {/each}
  </tbody>
</table>

8.5 Angular

Component (TypeScript)

import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } from '@angular/core';
import CollapseTable from '@codeseasy/collapsetable';

@Component({
  selector: 'app-orders',
  templateUrl: './orders.component.html',
})
export class OrdersComponent implements AfterViewInit, OnDestroy {
  @ViewChild('ordersTable', { static: true }) tableRef!: ElementRef<HTMLTableElement>;
  rows = [...]; // your data
  private ct = new CollapseTable({ mode: 'development' });

  ngAfterViewInit(): void {
    this.ct.set(this.tableRef.nativeElement, { icons: { expand: '+', collapse: '−' } });
  }

  ngOnDestroy(): void {
    this.ct.unset(this.tableRef.nativeElement);
  }

  // Call after data updates that affect columns/widths:
  refresh(): void {
    this.ct.refresh(this.tableRef.nativeElement);
  }
}

Template (HTML)

<table #ordersTable id="orders">
  <thead>
    <tr>
      <th data-priority="1" data-min="160">Project</th>
      <th data-priority="2" data-min="120">Client</th>
      <th data-priority="3" data-min="120">Status</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let r of rows">
      <td>{{ r.project }}</td><td>{{ r.client }}</td><td>{{ r.status }}</td>
    </tr>
  </tbody>
</table>

9) Dynamic data & lifecycle best practices

10) Multiple tables

const ct = new CollapseTable({ mode: 'production' });

ct.setAll('table.responsive', { tableLayout: 'fixed' });
// later…
ct.expandAll();        // across all attached
ct.collapseAll('#a');  // only table #a
ct.unsetAll('table.responsive');

11) Custom details rendering

ct.set('#orders', {
  detailsRender(row, hiddenColumns, cells) {
    const wrap = document.createElement('div');
    wrap.className = 'details-grid';
    hiddenColumns.forEach(c => {
      const label = c.th.getAttribute('data-label') || c.th.textContent || '';
      const item = document.createElement('div');
      item.className = 'details-item';
      item.innerHTML = `<strong>${label}:</strong> ${cells[c.index]?.innerHTML ?? ''}`;
      wrap.appendChild(item);
    });
    return wrap; // or return a string of HTML
  },
});

Receives the row <tr>, an array of hidden column metadata, and the cells. Return a Node or string; return nothing to use the default renderer.

12) Styling & theming (npm)

The library injects tiny, scoped CSS under .ctbl automatically. To match your design system, you can:

.ctbl            .ctbl-control    .ctbl-toggle
.ctbl-details    .ctbl-details-inner
.ctbl-detail     .ctbl-name       .ctbl-value
.ctbl-hide       .ctbl-vh

Bootstrap example (multi-class toggle + wider control column)

const ct = new CollapseTable();
ct.set('#table-project-list', {
  classNames: {
    root: 'ctbl',
    control: 'ctbl-control',
    toggle: 'ctbl-toggle btn btn-secondary btn-sm'
  },
  controlWidth: 56
});

13) Bundler notes

14) Troubleshooting (npm context)

15) Advanced: programmatic control

// Expand 1st row (0-based across all TBODY rows)
ct.expandRow('#orders', 0);

// Collapse a specific row element
const row = document.querySelector('#orders tbody tr:nth-child(3)')!;
ct.collapseRow('#orders', row);

16) Version & support

console.log(CollapseTable.version); // "1.2.0"