> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monolex.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# OnIt State Management

> Minimal state design and unidirectional data flow in the OnIt viewer

## State Overview

WikiOnitViewer maintains the simplest state model among all wiki viewers: just **one custom array** plus inherited properties from the base class.

```
┌─────────────────────────────────────────────────────┐
│  State Inventory                                    │
├─────────────────────────────────────────────────────┤
│                                                     │
│  Own State:                                         │
│    sessions: OnitSession[]                          │
│                                                     │
│  Inherited State (from WikiBaseViewer):             │
│    container: HTMLElement | null                    │
│    projectSlug: string                              │
│    category: string                                 │
│    isWip: boolean                                   │
│    settings: WikiViewerSettings                     │
│    currentDocument: string                          │
│                                                     │
│  Total: 7 properties (6 inherited + 1 own)          │
│                                                     │
└─────────────────────────────────────────────────────┘
```

## Sessions Array

The only state property unique to OnIt:

```
┌───────────────────────────────────────────────────────────────────────┐
│  SESSIONS ARRAY                                                       │
├───────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  DECLARATION:                                                         │
│    private sessions: OnitSession[] = []                               │
│                                                                       │
│  CHARACTERISTICS:                                                     │
│  ├── Array of parsed session objects                                  │
│  ├── Sorted newest first (descending sortKey)                         │
│  ├── Populated during loadSessions()                                  │
│  └── Completely replaced on refresh()                                 │
│                                                                       │
└───────────────────────────────────────────────────────────────────────┘
```

**Example Session:**

```
┌───────────────────────────────────────────────────────────────────────┐
│  sessions[0] = {                                                      │
│                                                                       │
│    path:        "/full/path/2025-12-28-14-30-session.md"              │
│    name:        "2025-12-28-14-30-session.md"                         │
│    date:        "2025-12-28"                                          │
│    time:        "14:30"                                               │
│    sessionName: "session"                                             │
│    pattern:     3                                                     │
│    sortKey:     "2025-12-28T14:30:00"                                 │
│    status:      "active"                                              │
│                                                                       │
│  }                                                                    │
└───────────────────────────────────────────────────────────────────────┘
```

## State Lifecycle

### Initialization

```
┌─────────────────────────────────────────────────────┐
│  Initialization State Changes                       │
├─────────────────────────────────────────────────────┤
│                                                     │
│  BEFORE init():                                     │
│    container: null                                  │
│    sessions: []                                     │
│    isWip: true (default)                            │
│                                                     │
│       ↓ init(container, projectSlug, "onit")        │
│                                                     │
│  AFTER init():                                      │
│    container: HTMLElement (assigned)                │
│    sessions: [OnitSession, ...]                     │
│    isWip: true (unchanged)                          │
│    category: "onit"                                 │
│    settings: loaded from localStorage               │
│                                                     │
└─────────────────────────────────────────────────────┘
```

### Toggle Transition

```
┌─────────────────────────────────────────────────────┐
│  WIP/Wiki Toggle Effect                             │
├─────────────────────────────────────────────────────┤
│                                                     │
│  WIP Mode:                                          │
│    isWip: true                                      │
│    sessions: [WIP sessions from wip/onit/]          │
│                                                     │
│       ↓ User clicks [Wiki] button                   │
│                                                     │
│  Wiki Mode:                                         │
│    isWip: false                                     │
│    sessions: [Wiki sessions from wiki/onit/]        │
│                                                     │
│  Note: Other properties unchanged                   │
│                                                     │
└─────────────────────────────────────────────────────┘
```

### Refresh Cycle

```
┌─────────────────────────────────────────────────────┐
│  Refresh State Changes                              │
├─────────────────────────────────────────────────────┤
│                                                     │
│  BEFORE refresh():                                  │
│    sessions: [old data - may be stale]              │
│                                                     │
│       ↓ refresh() called                            │
│                                                     │
│  AFTER refresh():                                   │
│    sessions: [new data - fresh from filesystem]     │
│                                                     │
│  Note: Complete array replacement                   │
│        DOM fully re-rendered                        │
│        Accordion states LOST                        │
│                                                     │
└─────────────────────────────────────────────────────┘
```

## State Dependencies

Path construction depends on three state properties:

```
┌───────────────────────────────────────────────────────────────────────┐
│  PATH CALCULATION (getBasePath)                                       │
├───────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  BASE = "~/Library/Application Support/monolex/protocols/niia/work"   │
│                                                                       │
│  FORMULA:                                                             │
│    folder = isWip ? "wip" : "wiki"                                    │
│    path = "{base}/{projectSlug}/{folder}/{category}"                  │
│                                                                       │
│  EXAMPLE:                                                             │
│    projectSlug = "monolex-006"                                        │
│    isWip = true                                                       │
│    category = "onit"                                                  │
│                                                                       │
│    Result: ~/Library/.../work/monolex-006/wip/onit/                   │
│                                                                       │
│  Changing ANY dependency changes the filesystem path                  │
│  and thus the loaded sessions.                                        │
│                                                                       │
└───────────────────────────────────────────────────────────────────────┘
```

## Unidirectional Data Flow

State flows in one direction only:

```
┌─────────────────────────────────────────────────────┐
│  Data Flow                                          │
├─────────────────────────────────────────────────────┤
│                                                     │
│  User Action (click toggle/refresh)                 │
│       ↓                                             │
│  Event Handler                                      │
│       ↓                                             │
│  State Update (isWip, sessions)                     │
│       ↓                                             │
│  Re-render (render() called)                        │
│       ↓                                             │
│  DOM Updated (content replaced)                     │
│       ↓                                             │
│  Event Listeners Attached (to new elements)         │
│       ↓                                             │
│  (Loop back to User Action)                         │
│                                                     │
│  No reverse flow: DOM → State                       │
│                                                     │
└─────────────────────────────────────────────────────┘
```

## DOM vs JavaScript State

Clear separation between persistent state and ephemeral UI state:

**JavaScript State (this.\*):**

* `sessions`: OnitSession\[] (source of truth)
* `isWip`: boolean
* `settings`: ViewerSettings
* Persists across renders

**DOM State (in elements):**

* Accordion expanded/collapsed
* Content loaded (`data-loaded`)
* Arrow rotation
* Scroll position
* Lost on re-render

**Relationship:**

* JS state is **source of truth** for data
* DOM state is **ephemeral** (recreated on render)
* Re-render regenerates DOM from JS state
* No two-way binding

## State Reset Pattern

Complete replacement on refresh:

```
┌───────────────────────────────────────────────────────────────────────┐
│  REFRESH PATTERN                                                      │
├───────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  refresh()                                                            │
│    │                                                                  │
│    ├── await this.loadSessions()   ← REPLACES this.sessions           │
│    │                                                                  │
│    └── this.render()               ← Re-renders entire DOM            │
│                                                                       │
│  EFFECT:                                                              │
│  ├── No incremental updates                                           │
│  ├── No diffing/patching                                              │
│  ├── Guaranteed consistency                                           │
│  └── Accordion states lost                                            │
│                                                                       │
│  TRADE-OFFS:                                                          │
│  ├── Simplicity (SMPC principle)                                      │
│  ├── Easy to reason about                                             │
│  ├── Potential performance impact on large lists                      │
│  └── Loses UI state                                                   │
│                                                                       │
└───────────────────────────────────────────────────────────────────────┘
```

## Memory Management

Automatic cleanup via garbage collection:

**On refresh():**

1. `this.sessions = new array` → Old array becomes unreachable
2. Container content replaced → Old DOM nodes removed
3. JavaScript GC cleans up old arrays
4. Browser GC cleans up old DOM nodes
5. Event listeners on old nodes auto-removed

No manual cleanup needed. No memory leaks from orphaned listeners.

## Settings Management

User preferences loaded from localStorage:

```
┌───────────────────────────────────────────────────────────────────────┐
│  WIKI VIEWER SETTINGS                                                 │
├───────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  INTERFACE:                                                           │
│  ┌───────────────────────────────────────────────────────────────┐    │
│  │  fontSize:    string    // "12"                               │    │
│  │  fontWeight:  string    // "300"                              │    │
│  │  lineHeight:  string    // "1.6"                              │    │
│  │  opacity:     string    // "75"                               │    │
│  │  fontFamily:  string    // "CodexMono, CodexMono EA"          │    │
│  └───────────────────────────────────────────────────────────────┘    │
│                                                                       │
│  LOADING:                                                             │
│    For each setting:                                                  │
│      value = localStorage.getItem("wikiViewer{Setting}") || default   │
│                                                                       │
│  DEFAULTS:                                                            │
│    fontSize   = "12"                                                  │
│    fontWeight = "300"                                                 │
│    lineHeight = "1.6"                                                 │
│    opacity    = "75"                                                  │
│    fontFamily = "CodexMono, CodexMono EA"                             │
│                                                                       │
│  Settings apply to entire viewer container via getViewerStyles()      │
│                                                                       │
└───────────────────────────────────────────────────────────────────────┘
```

## State Comparison

OnIt has the simplest state model:

| Viewer  | Own State Props | Total State | Complexity  |
| ------- | --------------- | ----------- | ----------- |
| OnIt    | 1               | 7           | Simplest    |
| Prepare | 2               | 8           | Low-Medium  |
| Prove   | 3               | 9           | Medium      |
| Unified | 4               | 10          | Medium-High |
| Docs    | 5               | 11          | Highest     |

Minimal state aligns with SMPC: simplicity over complexity.

<div style={{ textAlign: 'center', marginTop: '3rem', marginBottom: '2rem', fontSize: '1.5rem', fontWeight: '300', color: '#666' }}>
  THE CENTER

  <div style={{ fontSize: '0.9rem', marginTop: '0.5rem' }}>
    Simple state enables predictable behavior
  </div>
</div>

<Card title="Technical Credibility" icon="code">
  Single source of truth pattern. Unidirectional data flow. TypeScript type safety via interfaces. Automatic garbage collection for memory management. No manual listener cleanup required.
</Card>
