Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/ci-solid.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: CI Solid

on:
pull_request:
paths:
- '.github/workflows/ci-solid.yml'
- '.github/workflows/publish-solid.yml'
- 'projects/ui-grid-solid/**'
- 'projects/ui-grid-core/**'
- 'projects/ui-grid-vanilla/**'
- 'scripts/build-solid.mjs'
- 'scripts/sync-versions.mjs'
- 'package.json'
- 'package-lock.json'
push:
branches:
- main
paths:
- '.github/workflows/ci-solid.yml'
- '.github/workflows/publish-solid.yml'
- 'projects/ui-grid-solid/**'
- 'projects/ui-grid-core/**'
- 'projects/ui-grid-vanilla/**'
- 'scripts/build-solid.mjs'
- 'scripts/sync-versions.mjs'
- 'package.json'
- 'package-lock.json'
workflow_dispatch:

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
- name: Checkout source
uses: actions/checkout@v7

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 26.4.0
cache: npm
cache-dependency-path: |
package-lock.json
projects/ui-grid-solid/package-lock.json

- name: Install repository dependencies
run: npm ci --legacy-peer-deps

- name: Install Solid adapter dependencies
run: npm ci --prefix projects/ui-grid-solid

- name: Build Solid adapter and internal dependencies
run: npm run build:solid

- name: Run Solid integration, SSR, hydration, package, and example checks
run: npm run test:solid
76 changes: 76 additions & 0 deletions .github/workflows/publish-solid.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Publish Solid package

on:
workflow_dispatch:
inputs:
ref:
description: Branch, tag, or commit to publish
required: true
default: main
version:
description: Public version to publish
required: true
default: 0.1.0

jobs:
publish:
runs-on: ubuntu-latest

steps:
- name: Checkout source
uses: actions/checkout@v7
with:
ref: ${{ inputs.ref }}

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 26.4.0
registry-url: https://registry.npmjs.org
scope: '@ornery'
always-auth: true
cache: npm
cache-dependency-path: |
package-lock.json
projects/ui-grid-solid/package-lock.json

- name: Install repository dependencies
run: npm ci --legacy-peer-deps

- name: Install Solid adapter dependencies
run: npm ci --prefix projects/ui-grid-solid

- name: Verify internal packages are published
run: |
VERSION="${{ inputs.version }}"
npm view "@ornery/ui-grid-core@$VERSION" version
npm view "@ornery/ui-grid-vanilla@$VERSION" version

- name: Build and test the Solid package
run: |
npm run build:solid
npm run test:solid

- name: Set and verify the publish manifest
env:
VERSION: ${{ inputs.version }}
run: |
node - <<'NODE'
const fs = require('node:fs');
const path = './projects/ui-grid-solid/package.json';
const pkg = require(path);
pkg.version = process.env.VERSION;
for (const name of ['@ornery/ui-grid-core', '@ornery/ui-grid-vanilla']) {
pkg.peerDependencies[name] = process.env.VERSION;
}
fs.writeFileSync(path, `${JSON.stringify(pkg, null, 2)}\n`);
if (pkg.version !== process.env.VERSION) throw new Error('Package version was not updated');
for (const name of ['@ornery/ui-grid-core', '@ornery/ui-grid-vanilla']) {
if (pkg.peerDependencies[name] !== process.env.VERSION) throw new Error(`Invalid ${name} peer`);
}
NODE

- name: Publish to npm
run: npm publish ./projects/ui-grid-solid --access public --registry=https://registry.npmjs.org
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
134 changes: 104 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# UI Grid — Remastered

**The modern multi-platform data grid. Every feature free and open source. Built for Angular, Web-Components, React, native Rust/egui, and native C/LVGL.**
**The modern multi-platform data grid. Every feature free and open source. Built for Angular, Web Components, React, SolidJS, native Rust/egui, and native C/LVGL.**

A from-scratch rewrite of the original [AngularJS ui-grid](https://github.com/angular-ui/ui-grid) — by the original author. Same `gridOptions` / `columnDefs` / `onRegisterApi` api surface, modern Angular signals internals, and zero legacy baggage.

Expand All @@ -24,7 +24,7 @@ It proves that the datagrid cabal wants you to think it's hard to write a data g

- **Original authorship** — built by the same engineer who created AngularJS ui-grid, with a decade of hindsight on what worked and what didn't
- **Familiar API** — if you used the original ui-grid, you already know this one: `gridOptions`, `columnDefs`, `onRegisterApi`, `gridApi.core.*`
- **Modern internals** — shared vanilla web component core with Shadow DOM encapsulation; Angular and React wrappers are thin bridges that project framework templates into the vanilla element via slot-based portals
- **Modern internals** — shared vanilla web component core with Shadow DOM encapsulation; Angular, React, and SolidJS wrappers are thin bridges that project framework templates into the vanilla element via slot-based portals
- **No legacy** — no `$scope`, no Bower, no Grunt, no jQuery, no module system from 2013

---
Expand Down Expand Up @@ -62,6 +62,7 @@ Everything below ships free and MIT-licensed. No enterprise tier, no license key
| **SSR Support** | **Free** | — | ~$999/dev/yr | — | — | — |
| i18n (6 locales built-in) | **Free** | Free | — | Free | Paid | Community\* |
| React | **Yes** | Wrapper | Wrapper | No | Wrapper | Wrapper |
| SolidJS | **Yes** | Wrapper | Wrapper | No | Wrapper | Wrapper |
| Rust/egui Native | **Yes** | No | No | No | No | No |
| C/LVGL Native | **Yes** | No | No | No | No | No |
| Angular | **Yes** | Wrapper | Wrapper | No | Wrapper | Wrapper |
Expand Down Expand Up @@ -138,9 +139,76 @@ function MyGrid() {
}
```

### SolidJS

The SolidJS adapter mounts the same vanilla Web Component while preserving
SolidJS ownership, reactive props, local renderer state, and lifecycle cleanup.
It supports browser rendering, SSR and hydration, custom JSX cells and headers,
expandable detail rows, and JSX cell editors.

```bash
npm install @ornery/ui-grid-solid @ornery/ui-grid-core @ornery/ui-grid-vanilla solid-js @solidjs/web
```

Configure the SolidJS JSX runtime with `jsxImportSource: "@solidjs/web"`, then
pass reactive options to `UiGrid`:

```tsx
/** @jsxImportSource @solidjs/web */
import { createSignal } from 'solid-js';
import { UiGrid, type GridOptions, type UiGridCellRenderers } from '@ornery/ui-grid-solid';

const cellRenderers: UiGridCellRenderers = {
name: (context) => <strong>{String(context.value)}</strong>,
};

export function PeopleGrid() {
const [rows, setRows] = createSignal([
{ id: 1, name: 'Alice', role: 'Engineer' },
{ id: 2, name: 'Bob', role: 'Designer' },
]);

const options = (): GridOptions => ({
id: 'people-grid',
data: rows(),
columnDefs: [{ name: 'name' }, { name: 'role' }],
rowIdentity: (row) => String(row['id']),
enableSorting: true,
enableFiltering: true,
enableVirtualization: true,
});

return (
<section style={{ height: '420px' }}>
<button
onClick={() =>
setRows((current) => [
...current,
{ id: current.length + 1, name: 'New user', role: 'Engineer' },
])
}
>
Add row
</button>
<UiGrid options={options()} cellRenderers={cellRenderers} />
</section>
);
}
```

`options` uses the shared `GridOptions` contract. The adapter updates the same
grid element when signals change, so interactive sorting, filters, column order,
and other controller state remain intact. `onRegisterApi` exposes the shared
`UiGridApi`; all projected SolidJS roots and subscriptions are disposed when the
component unmounts.

See the [SolidJS adapter guide](projects/ui-grid-solid/README.md), the
[implementation notes](<SolidJS Adapter Implementation.md>), and the
[SolidStart example](projects/ui-grid-solid/examples/solid-start/README.md).

### Web Components (Vanilla)

The grid's rendering engine is a framework-free custom element (`<ui-grid-element>`) built on `@ornery/ui-grid-core` with pure DOM rendering and Shadow DOM encapsulation. Both the Angular and React wrappers are thin bridges around this same element — they mount `<ui-grid-element>`, pass options, and project framework-specific templates into it via a slot-based portal system.
The grid's rendering engine is a framework-free custom element (`<ui-grid-element>`) built on `@ornery/ui-grid-core` with pure DOM rendering and Shadow DOM encapsulation. The Angular, React, and SolidJS wrappers are thin bridges around this same element — they mount `<ui-grid-element>`, pass options, and project framework-specific templates into it via a slot-based portal system.

```bash
npm install @ornery/ui-grid-vanilla @ornery/ui-grid-core
Expand Down Expand Up @@ -282,9 +350,9 @@ The LVGL demo currently exercises the native C grid shell with sorting, grouping
- **Save/Restore State** — serialize and restore sort, filters, grouping, collapsed groups, pinning, column order, column widths, pagination, selection, focused cell, tree/expandable expansion, and scroll position (per-field opt-in flags)
- **Native Rust and C Grids** — shared Rust core with native Rust/egui and native C/LVGL adapters driven by the same projection and command contract
- **Auto Resize** — ResizeObserver-driven viewport height recalculation
- **Custom Cell Templates** — Angular `ng-template`, React `cellRenderers` map (per-column render functions), vanilla `<template>` slots with slot-based portal projection
- **Custom Cell Templates** — Angular `ng-template`, React and SolidJS `cellRenderers` maps, and vanilla `<template>` slots with slot-based portal projection
- **Shadow DOM** — encapsulated styles with CSS custom property and `::part()` hooks
- **Web Component** — ships as `<ui-grid-element>`, a framework-free vanilla custom element (`@ornery/ui-grid-vanilla`); Angular and React wrappers mount this same element and project templates into it
- **Web Component** — ships as `<ui-grid-element>`, a framework-free vanilla custom element (`@ornery/ui-grid-vanilla`); Angular, React, and SolidJS wrappers mount this same element and project templates into it
- **Feature-Flag Builds** — compile-time tree-shaking of unused features
- **i18n** — 6 locales built-in (English, Spanish, French, German, Japanese, Simplified Chinese), runtime `gridApi.i18n` for language switching, fallback chain (`options.labels` → current locale → en-US), register additional locales via `gridApi.i18n.add()`
- **SSR Support** — server-side rendering with platform-safe guards
Expand Down Expand Up @@ -342,22 +410,24 @@ See [docs/custom-builds.md](./docs/custom-builds.md) for the full feature flag t

## Documentation

| Guide | Description |
| -------------------------------------------- | ------------------------------------------------------ |
| [Getting Started](./docs/getting-started.md) | Install, minimal setup, run the demo |
| [Features](./docs/features.md) | Overview of all features with code examples |
| [Theming](./docs/theming.md) | CSS custom properties, `::part()` hooks, sample themes |
| [API Reference](./docs/api-reference.md) | GridOptions, GridColumnDef, UiGridApi |
| [Cell Editing](./docs/cell-editing.md) | Keyboard navigation, conditional editing, API |
| [Tree View](./docs/tree-view.md) | Hierarchical data, options, API |
| [Expandable Rows](./docs/expandable-rows.md) | Master/detail, template context, API |
| [Custom Builds](./docs/custom-builds.md) | Feature flags, build presets, locale baking |
| [Web Component](./docs/web-component.md) | Vanilla `<ui-grid-element>` custom element usage |
| [Internationalization](./docs/i18n.md) | Runtime overrides, build-time locales |
| [Accessibility](./docs/accessibility.md) | ARIA roles, keyboard navigation, screen reader support |
| [Rust / WASM](./docs/rust.md) | Rust pipeline in Angular, React, and vanilla hosts |
| [Rust / egui](./docs/rust-egui.md) | Native egui adapter with pinning, export, save/restore |
| `README native C / LVGL section` | Native C/LVGL build and demo run instructions |
| Guide | Description |
| ------------------------------------------------------------- | ------------------------------------------------------ |
| [Getting Started](./docs/getting-started.md) | Install, minimal setup, run the demo |
| [Features](./docs/features.md) | Overview of all features with code examples |
| [Theming](./docs/theming.md) | CSS custom properties, `::part()` hooks, sample themes |
| [API Reference](./docs/api-reference.md) | GridOptions, GridColumnDef, UiGridApi |
| [Cell Editing](./docs/cell-editing.md) | Keyboard navigation, conditional editing, API |
| [Tree View](./docs/tree-view.md) | Hierarchical data, options, API |
| [Expandable Rows](./docs/expandable-rows.md) | Master/detail, template context, API |
| [Custom Builds](./docs/custom-builds.md) | Feature flags, build presets, locale baking |
| [Web Component](./docs/web-component.md) | Vanilla `<ui-grid-element>` custom element usage |
| [Internationalization](./docs/i18n.md) | Runtime overrides, build-time locales |
| [Accessibility](./docs/accessibility.md) | ARIA roles, keyboard navigation, screen reader support |
| [Rust / WASM](./docs/rust.md) | Rust pipeline in Angular, React, and vanilla hosts |
| [Rust / egui](./docs/rust-egui.md) | Native egui adapter with pinning, export, save/restore |
| [SolidJS Adapter](projects/ui-grid-solid/README.md) | Setup, lifecycle, JSX renderers, SSR, and examples |
| [SolidJS Implementation](<SolidJS Adapter Implementation.md>) | Architecture, implementation decisions, and validation |
| `README native C / LVGL section` | Native C/LVGL build and demo run instructions |

Interactive versions of all documentation are also available in the [live demo](https://orneryd.github.io/uiGrid/).

Expand All @@ -370,6 +440,9 @@ npm start # Dev server at localhost:4200
npm test # Run tests (Vitest)
npm run build # Production build
npm run build:library # Build the library (ng-packagr)
npm run build:solid # Build core, vanilla, and the SolidJS adapter
npm run test:solid # Test SolidJS, SSR, hydration, and package consumption
npm run start:solid # Run the SolidJS demo with 100,000 rows
npm run build:rust:web # Build the browser-native Rust/WASM artifact
npm run start:vanilla # Run the Rust-backed browser demo at 127.0.0.1:4174
```
Expand Down Expand Up @@ -400,15 +473,16 @@ cmake --build target/ui-grid-lvgl -j4

## Compatibility

| Dependency | Version |
| ---------- | ------- |
| Angular | 21.2 |
| TypeScript | 5.9 |
| RxJS | 7.8 |
| Node | 22.20 |
| npm | 11.11 |
| Rust | 1.95+ |
| egui | 0.34 |
| Dependency | Version |
| ---------- | --------------- |
| Angular | 21.2 |
| SolidJS | >=2.0.0-rc.4 <3 |
| TypeScript | 5.9 |
| RxJS | 7.8 |
| Node | 22.20 |
| npm | 11.11 |
| Rust | 1.95+ |
| egui | 0.34 |

---

Expand Down
53 changes: 53 additions & 0 deletions SolidJS Adapter Contribution Draft.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Draft Kontribusi Adapter SolidJS

## Draft issue

**Judul:** Add an official SolidJS adapter

Saya mengusulkan package `@ornery/ui-grid-solid` yang membungkus
`<ui-grid-element>` untuk SolidJS. Adapter mempertahankan engine dan renderer
vanilla yang sudah ada, lalu menyediakan lifecycle reaktif, Grid API, renderer
JSX untuk cell/header/detail, serta custom cell editor di dalam package Solid.

Implementasi mencakup entry browser/server, SSR dan hydration, cleanup owner
Solid, error isolation, virtualisasi 100.000 row, contoh SolidStart, pengujian
consumer tarball, dan workflow CI/publish khusus package. Tidak ada perubahan
source pada core, vanilla, React, atau Angular yang diperlukan.

Hal yang perlu disepakati dengan maintainer:

- nama package dan rentang peer dependency SolidJS;
- apakah cell, header, detail, dan editor dikirim dalam satu PR atau beberapa PR;
- posisi adapter dalam CI, version sync, dan urutan release monorepo;
- versi awal package dan kepemilikan token publish npm.

## Draft pull request

**Judul:** feat(solid): add SolidJS adapter

Menambahkan `@ornery/ui-grid-solid` sebagai adapter SolidJS untuk renderer
vanilla uiGrid. `UiGrid` menyinkronkan options tanpa mengganti elemen, meneruskan
Grid API, aman untuk SSR/hydration, dan membersihkan seluruh root serta
subscription saat unmount.

Adapter menyediakan renderer JSX reaktif untuk cell, header, dan expandable
detail, serta custom cell editor dengan focus, commit/cancel, keyboard, blur,
validation, dan error recovery. Contoh demo memakai 100.000 row, dan contoh
SolidStart mengunci JSX runtime ke `@solidjs/web` agar `UiGrid` dikenali sebagai
komponen Solid oleh TypeScript.

Validasi:

- Solid: 27 tes integrasi; SSR, hydration, package consumer, dan example
typecheck lulus;
- core: 41 file / 273 tes lulus;
- vanilla: 150 tes lulus;
- React: 19 tes lulus;
- Angular: 4 file / 48 tes lulus;
- Rust: 69 tes workspace dan seluruh doc-test lulus;
- `cargo fmt`, Clippy `-D warnings`, target WASM, WASM bundler/web release, dan
production build lulus.

Pemeriksaan browser manual untuk scroll dan heap snapshot masih perlu dilakukan
ketika runtime browser tersedia. Harness stress dan metrik disposal sudah ada di
route demo `?stress`.
Loading