{"id":46109583,"url":"https://github.com/waga97/Mundane-UI","last_synced_at":"2026-03-13T17:00:46.980Z","repository":{"id":338263007,"uuid":"1157236816","full_name":"waga97/Mundane-UI","owner":"waga97","description":"Because every npm datatable looks great until your designer opens Figma. Zero deps, framework-agnostic, CSS that actually listens to you.","archived":false,"fork":false,"pushed_at":"2026-02-13T16:48:58.000Z","size":2062,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-14T00:24:44.794Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://mundane-ui.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/waga97.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-13T15:37:07.000Z","updated_at":"2026-02-13T16:51:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/waga97/Mundane-UI","commit_stats":null,"previous_names":["waga97/mundane-ui"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/waga97/Mundane-UI","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waga97%2FMundane-UI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waga97%2FMundane-UI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waga97%2FMundane-UI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waga97%2FMundane-UI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/waga97","download_url":"https://codeload.github.com/waga97/Mundane-UI/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waga97%2FMundane-UI/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30471114,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-13T11:00:43.441Z","status":"ssl_error","status_checked_at":"2026-03-13T11:00:23.173Z","response_time":60,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-03-01T22:00:55.626Z","updated_at":"2026-03-13T17:00:46.974Z","avatar_url":"https://github.com/waga97.png","language":"TypeScript","funding_links":[],"categories":["Third Party Components"],"sub_categories":["UI Libraries"],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"mundane-logo.png\" alt=\"Mundane UI\" width=\"120\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eMundane UI\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eThe boring UI library.\u003c/strong\u003e\u003cbr\u003e\n  Framework-agnostic, zero-dependency, lightweight UI component library.\u003cbr\u003e\n  Written in TypeScript, works everywhere — React, Vue, Angular, Svelte, or plain HTML.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/mundane-ui\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/mundane-ui?color=ea580c\u0026label=npm\" alt=\"npm version\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/mundane-ui\"\u003e\u003cimg src=\"https://img.shields.io/npm/dm/mundane-ui?color=f97316\" alt=\"npm downloads\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/waga97/Mundane-UI/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/waga97/Mundane-UI?color=f48c06\" alt=\"license\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/dependencies-0-brightgreen\" alt=\"zero dependencies\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/gzipped-~9KB-blue\" alt=\"bundle size\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://mundane-ui.vercel.app\"\u003eDocumentation\u003c/a\u003e ·\n  \u003ca href=\"https://mundane-ui.vercel.app/guide/getting-started\"\u003eGetting Started\u003c/a\u003e ·\n  \u003ca href=\"https://mundane-ui.vercel.app/guide/why\"\u003eWhy This Exists\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## Install\n\n```bash\nnpm install mundane-ui\n```\n\n## Quick Start\n\n```html\n\u003clink rel=\"stylesheet\" href=\"mundane-ui/css/plain.css\"\u003e\n\u003cdiv id=\"my-table\"\u003e\u003c/div\u003e\n```\n\n```js\nimport { DataTable } from 'mundane-ui'\nimport 'mundane-ui/css/plain.css'\n\nconst table = DataTable.create({\n  el: '#my-table',\n  mode: 'frontend',\n  data: [\n    { name: 'Alice', age: 30, email: 'alice@example.com' },\n    { name: 'Bob', age: 25, email: 'bob@example.com' },\n  ],\n  columns: [\n    { key: 'name', label: 'Name', type: 'string', sortable: true },\n    { key: 'age', label: 'Age', type: 'number', sortable: true, thousandSeparator: true },\n    { key: 'email', label: 'Email', type: 'string', sortable: true },\n  ],\n})\n```\n\n## Features\n\n- **Zero dependencies** — pure vanilla TypeScript\n- **Framework-agnostic** — plain JS class, mounts to any DOM element\n- **Two modes** — frontend (client-side) and backend (server-side with QSP emission)\n- **Sorting** — single-column, per-type comparators (string, number, date, custom)\n- **Search** — global search, column filters, or both (debounced)\n- **Pagination** — configurable page sizes, ellipsis for large page counts\n- **Column alignment** — left/center/right per column (numbers default to right)\n- **Number formatting** — optional thousand separator (e.g. `1,000,000`)\n- **Date parsing** — built-in parser for common date formats (YYYY, MM, DD, HH, mm, ss)\n- **Custom columns** — render any HTML with your own function\n- **XSS safe** — all data values are HTML-escaped\n- **CSS customizable** — CSS custom properties, class overrides, or Tailwind utility classes\n- **Lightweight** — ~9KB gzipped\n\n## Frontend Mode\n\nAll data is held in memory. Sorting, filtering, and pagination happen client-side.\n\n```js\nconst table = DataTable.create({\n  el: '#table',\n  mode: 'frontend',\n  data: myData,\n  pageSize: 25,\n  search: { enabled: true, mode: 'both', debounce: 300 },\n  columns: [\n    { key: 'id', label: 'ID', type: 'number', sortable: true, align: 'center' },\n    { key: 'name', label: 'Name', type: 'string', sortable: true },\n    { key: 'salary', label: 'Salary', type: 'number', sortable: true, thousandSeparator: true },\n    { key: 'joinDate', label: 'Joined', type: 'date', dateFormat: 'DD/MM/YYYY', sortable: true },\n    {\n      key: 'actions', label: 'Actions', type: 'custom',\n      render: (row) =\u003e `\u003cbutton onclick=\"edit(${row.id})\"\u003eEdit\u003c/button\u003e`,\n    },\n  ],\n})\n```\n\n## Backend Mode\n\nThe component does not sort/filter/paginate. It emits query string parameters on every state change, and you fetch the data however you want.\n\n```js\nconst table = DataTable.create({\n  el: '#table',\n  mode: 'backend',\n  data: initialPageData,\n  totalRows: 500,\n  columns: [ /* ... */ ],\n  onStateChange: async (queryString, state) =\u003e {\n    // queryString: \"?page=2\u0026pageSize=10\u0026sortBy=name\u0026sortOrder=asc\u0026search=john\"\n    const res = await fetch('/api/users' + queryString)\n    const { data, total } = await res.json()\n    table.setData(data, total)\n  },\n})\n```\n\n## Column Types\n\n| Type | Default Align | Sortable | Searchable | Options |\n|------|--------------|----------|------------|---------|\n| `string` | left | localeCompare | substring match | — |\n| `number` | right | numeric | toString match | `thousandSeparator` |\n| `date` | left | Date comparison | display string match | `dateFormat`, `displayFormat` |\n| `custom` | left | via `comparator` | via `filterFn` | `render` |\n\n## CSS Customization\n\n**Layer 1 — Theme file:**\n```js\nimport 'mundane-ui/css/plain.css'\n```\n\n**Layer 2 — CSS custom properties:**\n```css\n.mu-datatable {\n  --mu-color-border: #e2e8f0;\n  --mu-color-bg-header: #f8fafc;\n  --mu-border-radius: 8px;\n}\n```\n\n**Layer 3 — Direct class overrides:**\n```css\n.mu-datatable__header-cell {\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n}\n```\n\n**Layer 4 — Tailwind via `classes` config:**\n```js\nDataTable.create({\n  classes: {\n    root: 'rounded-xl border border-gray-200 shadow-sm',\n    headerCell: 'bg-gray-50 text-xs font-semibold uppercase',\n    row: 'hover:bg-blue-50 transition-colors',\n    pageButtonActive: 'bg-blue-600 text-white',\n  },\n  // ...\n})\n```\n\n## Public API\n\n| Method | Description |\n|--------|-------------|\n| `setData(data, totalRows?)` | Replace dataset, triggers re-render |\n| `updateRow(index, rowData)` | Update a specific row |\n| `addRow(rowData, index?)` | Add a row |\n| `removeRow(index)` | Remove a row |\n| `setPageSize(size)` | Change page size (resets to page 1) |\n| `goToPage(page)` | Navigate to a page |\n| `setSearch(value)` | Set global search programmatically |\n| `setColumnFilter(key, value)` | Set a column filter |\n| `clearFilters()` | Clear all filters and search |\n| `setLoading(bool)` | Show/hide loading overlay |\n| `getState()` | Get current state object |\n| `getQueryString()` | Get current query string |\n| `setColumns(columns)` | Update column definitions |\n| `destroy()` | Remove DOM and event listeners |\n| `refresh()` | Force full re-render |\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwaga97%2FMundane-UI","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwaga97%2FMundane-UI","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwaga97%2FMundane-UI/lists"}