Lists & Store Reference

This reference documents Coralite's application state management and high-performance list rendering utilities: the signal-backed Global Store and the built-in Lists Plugin.

1. Global Store #

The Global Store provides centralized, application-wide state management. It is declared in your project's configuration file and injected automatically into component and page execution contexts.

Declaration #

Declare initial store defaults in coralite.config.js using the store key:

javascript
Code copied!
  import { defineConfig } from 'coralite'
  
  export default defineConfig({
    public: 'public',
    output: 'dist',
    pages: 'src/pages',
    components: 'src/components',
    store: {
      user: { name: 'Alex', role: 'admin' },
      theme: 'dark',
      notifications: []
    }
  })

Component & Page Access #

Access the store directly via the store context key in component and page blocks (getters, client, etc.):

javascript
Code copied!
  import { defineComponent } from 'coralite'
  
  export default defineComponent({
    getters: {
      userName: ({ store }) => store.user.name,
      isDark: ({ store }) => store.theme === 'dark'
    },
  
    client({ store, observe }) {
      // Read and update global store state
      console.log('Current user:', store.user)
  
      // Update store state reactively
      store.theme = 'light'
    }
  })

Reactivity: The Global Store is signal-backed. Reading a store property inside a getters declaration automatically registers subscriber tracking. When store.theme changes, any getter or component depending on store.theme re-evaluates and updates the DOM immediately.

Server vs. Client Behavior: On the server during build-time rendering, store is a read-only snapshot. Attempting to mutate store properties during SSR throws a CoraliteError. On the client runtime, store is fully reactive and mutable.

Store Methods #

The store object provides helper methods for subscription tracking, batched state mutations, and resetting state:

2. Lists Plugin (Basic Usage) #

The lists plugin is built-in and auto-registered in Coralite. It provides fine-grained DOM list rendering and virtualized collections without Virtual DOM diffing overhead.

Accessing the Plugin #

Destructure lists directly from the client() block context:

javascript
Code copied!
  import { defineComponent } from 'coralite'
  
  export default defineComponent({
    client({ lists, refs, signal }) {
      // 1. Create a keyed list store
      const listStore = lists.createStore({
        key: 'id',
        initial: [
          { id: '1', title: 'Task One', done: false },
          { id: '2', title: 'Task Two', done: true }
        ]
      })
  
      // 2. Bind the list store to a DOM container
      lists.bind({
        container: refs.listContainer,
        store: listStore,
        signal,
        create: (item) => {
          const el = document.createElement('li')
          el.className = 'task-item'
          el.textContent = item.title
          return el
        },
        update: (el, item) => {
          el.classList.toggle('completed', item.done)
          el.textContent = item.title
        }
      })
    }
  })

Keyed DOM Updates: lists.bind tracks items by unique key (specified via key: 'id'). Appending an item creates exactly one DOM element. Updating an item modifies only that item's DOM node. Swapping or reordering items re-positions existing DOM nodes without destroying component state or re-creating elements.

3. Lists Virtualization #

For large datasets, lists.bind supports built-in virtualization to keep rendering fast and DOM memory footprint low.

The virtual option supports three modes:

Configuring size: Specify a numeric pixel value (e.g. size: 48) for fixed-height items, or pass size: 'measure' to dynamically compute item heights as elements enter the viewport.

4. Chat & Feeds (Anchor Features) #

The lists plugin provides built-in anchor options designed for real-time messaging, chat interfaces, and infinite scrolling feeds.

Chat Layouts (anchorTo & followOnAppend) #

For chat applications where messages append to the bottom and require automatically scrolling down when new messages arrive:

javascript
Code copied!
  lists.bind({
    container: refs.chatContainer,
    store: chatStore,
    signal,
    anchorTo: 'end',        // Stick scroll position relative to bottom
    followOnAppend: true,   // Automatically scroll to newest message when appended
    create: (msg) => renderMessage(msg)
  })

Infinite Scroll Feeds (onReachStart & onReachEnd) #

Attach scroll threshold callbacks to trigger pagination or dynamic data loading when users reach the top or bottom of a list:

javascript
Code copied!
  lists.bind({
    container: refs.feedContainer,
    store: feedStore,
    signal,
    scrollEndThreshold: 150, // Trigger when within 150px of list boundary
    onReachEnd: async () => {
      // User scrolled near the bottom — load next page
      const nextItems = await fetchNextPage()
      feedStore.push(...nextItems)
    },
    onReachStart: async () => {
      // User scrolled near the top — load previous history
      const prevItems = await fetchHistory()
      feedStore.unshift(...prevItems)
    },
    create: (post) => renderPost(post)
  })

5. Layouts & Groups #

Customize list presentation and structure using built-in grid layouts and grouping options.

Layout Modes #

Set layout to standard display arrangements:

javascript
Code copied!
  lists.bind({
    container: refs.gridContainer,
    store: galleryStore,
    signal,
    layout: 'grid',
    lanes: 'auto',
    minLaneWidth: 200, // Minimum column width in pixels
    gap: 16,           // Gap between items in pixels
    create: (photo) => renderPhotoCard(photo)
  })

Grouping & Sticky Headers #

Group items dynamically by key and render custom header elements:

javascript
Code copied!
  lists.bind({
    container: refs.groupedList,
    store: transactionStore,
    signal,
    groupBy: (item) => item.date, // Group transactions by date string
    stickyGroups: true,          // Keep active group header sticky at top during scroll
    createHeader: (groupKey, groupItems) => {
      const header = document.createElement('div')
      header.className = 'group-header'
      header.textContent = `${groupKey} (${groupItems.length} transactions)`
      return header
    },
    create: (tx) => renderTransactionRow(tx)
  })

Start Building with Coralite!

Use the scaffolding script to get jump started into your next project with Coralite

Copied commandline!