@everystate/ui
v1.0.0
Published
EveryState UI: Tree-shakable, transparent, framework-free UI components powered by EveryState
Maintainers
Readme
@everystate/ui
Tree-shakable, transparent, framework-free UI components powered by EveryState.
Every component is readable vanilla JS. No build step. No virtual DOM. No magic. Edit the source - it's yours.
Install
npm i @everystate/ui @everystate/coreQuick Start
<script type="module">
import { createEveryState } from '@everystate/core';
import { mountCounters } from '@everystate/ui/counters';
const store = createEveryState({
counterIds: ['a', 'b'],
counters: { a: { count: 0 }, b: { count: 5 } },
});
mountCounters(store, document.getElementById('app'));
</script>Import Styles
<link rel="stylesheet" href="node_modules/@everystate/ui/styles.css">Or in a bundler:
import '@everystate/ui/styles.css';Components
Every component follows the same contract:
const teardown = mountComponent(store, rootElement);
// later: teardown() to unmount and clean up all subscriptionsDeep imports (tree-shakable, no bundler required)
import { mountTable } from '@everystate/ui/table';
import { mountTodos } from '@everystate/ui/todos';
import { mountGrid } from '@everystate/ui/grid';
import { mountCounters } from '@everystate/ui/counters';
import { mountForm } from '@everystate/ui/form';
import { mountModals } from '@everystate/ui/modals';
import { mountTabs } from '@everystate/ui/tabs';
import { mountAccordion } from '@everystate/ui/accordion';
import { mountToasts } from '@everystate/ui/toasts';
import { mountFSM } from '@everystate/ui/fsm';
import { mountUndoRedo } from '@everystate/ui/undoRedo';
import { mountSwapi } from '@everystate/ui/swapi';
import { mountTheme } from '@everystate/ui/theme';Barrel import
import { mountTable, mountGrid, mountForm } from '@everystate/ui';Utilities
Three thin helpers that name the recurring patterns:
import { syncTOC, collect, derive } from '@everystate/ui/utils';syncTOC(store, tocPath, container, mountFn, options?)- TOC-driven mount/unmount lifecycle. Subscribes to a TOC array, mounts new IDs, unmounts removed IDs, reorders children.collect()- Subscription collector for grouped teardown.derive(store, sources, targetPath, computeFn)- Derived state wiring. Subscribes to source paths, computes a value, sets it at targetPath.
Store Shape per Component
Each component expects certain paths in the store. Here's what to initialize:
Counters
{ counterIds: ['a', 'b'], counters: { a: { count: 0 }, b: { count: 5 } } }Table
{ teamIds: [1, 2, 3], team: { 1: { name: 'Alice', role: 'Engineer' }, ... }, columnIds: ['name', 'role', 'status'], sort: { column: null, dir: 'asc' } }Todos
{ childIds: { root: [1, 2] }, items: { 1: { text: 'First', parentId: 'root' }, 2: { text: 'Second', parentId: 'root' } } }Grid
{ grid: { rowIds: ['r1', 'r2'], colIds: ['c1', 'c2'], cells: { r1: { c1: 10, c2: 20 }, r2: { c1: 30, c2: 40 } } } }Form
{ form: { fields: { name: '', email: '', age: '', password: '' } } }Modals
{ ui: { modalStack: [], modals: {} } }Tabs
{ tabs: { main: { active: 'tab-1', tabIds: ['tab-1', 'tab-2'], panels: { 'tab-1': { label: 'Home', content: '...' }, ... } } } }Accordion
{ accordion: { sectionIds: ['s1', 's2'], sections: { s1: { title: '...', content: '...' } }, open: { s1: true, s2: false } } }Toasts
{ toast: { ids: [], items: {} } }FSM
Initialized by the component itself (traffic light + door lock).
Undo/Redo
Initialized by the component itself. Watches counters.* and counterIds.
SWAPI (Async)
{} // Component fetches and normalizes data into swapi.* pathsTheme
{ theme: 'light' } // 'light' | 'dark' | 'forest'Dependencies
@everystate/core- peer dependency (you provide the store)@everystate/aliases- regular dependency (DOM shorthand, installed automatically)
Philosophy
- Transparent: every line maps to a DOM API or store operation
- No magic: aliases are 1:1 mappings (
mk=createElement,on=addEventListener) - Editable: these are YOUR components - read them, modify them, learn from them
- Zero build step: works with native ES modules in any browser
- Longevity: vanilla JS that works now will work in 10 years
Self-Test
npm test
# or
npx everystate-ui-self-testLicense
MIT
