@yuktishaalaa/yuktai 5.0.1 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +469 -625
- package/dist/index.d.mts +540 -2
- package/dist/index.d.ts +540 -2
- package/dist/index.js +67 -55
- package/dist/index.mjs +30 -18
- package/package.json +11 -4
package/README.md
CHANGED
|
@@ -1,121 +1,205 @@
|
|
|
1
1
|
# @yuktishaalaa/yuktai
|
|
2
2
|
|
|
3
|
-
> Universal Next.js plugin for accessibility, AI, and data. One install brings WCAG 2.2 auto-fix, in-browser RAG, an AI agent, code generation,
|
|
3
|
+
> Universal Next.js plugin for accessibility, AI, and data. One install brings WCAG 2.2 auto-fix, in-browser RAG, an AI agent, code generation, an accessible data grid with Agentic AI + WebMCP, and an agentic toolkit that audits, explains and fixes pages and answers questions about your data. Zero API keys, zero cost, works offline.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@yuktishaalaa/yuktai)
|
|
6
|
-
|
|
7
6
|
[](https://www.npmjs.com/package/@yuktishaalaa/yuktai)
|
|
8
|
-
|
|
9
7
|
[](./LICENSE)
|
|
10
|
-
|
|
11
8
|
[](https://nodejs.org)
|
|
9
|
+
[](https://nextjs.org)
|
|
12
10
|
|
|
13
|
-
[
|
|
11
|
+
Built in free time by [Sandeep Miriyala](https://github.com/sandeepmiriyala03).
|
|
14
12
|
|
|
15
|
-
**
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
**Live demos:**
|
|
14
|
+
- Staff directory: https://aksharatantra.miriyala.in/staffdirectory
|
|
15
|
+
- Ratnalabala, a Telugu poetry app built on YuktAI Grid: https://ratnalabala.vercel.app/poems?view=grid
|
|
18
16
|
|
|
19
17
|
---
|
|
20
18
|
|
|
21
19
|
## The story
|
|
22
20
|
|
|
23
|
-
I have been building web apps since 2013. In all those years the same things kept breaking on almost every website I touched
|
|
24
|
-
|
|
25
|
-
I wanted something without any of those barriers.
|
|
21
|
+
I have been building web apps since 2013. In all those years, the same things kept breaking on almost every website I touched: missing ARIA labels, no keyboard navigation, forms that senior citizens couldn't figure out, data grids that broke on mobile, accessibility tools that cost money, and AI tools that needed API keys.
|
|
26
22
|
|
|
27
|
-
Free. Open source. One install. Works on every device. No account. No key. No server.
|
|
23
|
+
I wanted something without any of those barriers. Free. Open source. One install. Works on every device. No account. No key. No server.
|
|
28
24
|
|
|
29
|
-
So I built yuktai
|
|
25
|
+
So I built yuktai, one weekend and one late night at a time.
|
|
30
26
|
|
|
31
27
|
---
|
|
32
28
|
|
|
33
29
|
## What's inside
|
|
34
30
|
|
|
35
|
-
|
|
31
|
+
Six modules ship in a single npm package:
|
|
36
32
|
|
|
37
33
|
| Module | Features | What it does |
|
|
38
|
-
|
|
39
34
|
|---|---|---|
|
|
40
|
-
|
|
41
35
|
| **1. Accessibility Engine** | 16 | WCAG 2.2 auto-fix, speak on focus, colour-blind modes, dyslexia font, skip links |
|
|
36
|
+
| **2. YuktaiGrid** ⭐ | 19 | Accessible data grid with Agentic AI, WebMCP, 5 WCAG themes, English/Telugu UI |
|
|
37
|
+
| **3. In-Tab RAG** | 11 | Ask questions about any page, offline, no API |
|
|
38
|
+
| **4. Autonomous AI Agent** | 13 | Natural-language browser guidance |
|
|
39
|
+
| **5. Vibe Coder** | 19 | Generate full Next.js projects from plain English |
|
|
40
|
+
| **6. Agentic AI Toolkit** 🆕 | 10 | Accessibility copilot, QA reports, form and design review, smart grid queries, BI answers, multi-step tasks, voice settings |
|
|
42
41
|
|
|
43
|
-
|
|
42
|
+
---
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
## What's new in v5.1: Agentic AI Toolkit
|
|
46
45
|
|
|
47
|
-
|
|
46
|
+
Ten agentic features, all running in the browser. No API keys, and no page or grid data leaves the device unless you plug in your own model through a `generate` or `summarize` hook.
|
|
48
47
|
|
|
49
|
-
|
|
|
48
|
+
| # | Feature | What it does | Main export |
|
|
49
|
+
|---|---|---|---|
|
|
50
|
+
| 1 | Accessibility Copilot | Watches the page live, explains each issue in plain English, applies safe fixes and undoes them | `createA11yCopilot` |
|
|
51
|
+
| 2 | Page Understanding | Answers "What does this page do?" and "Which form fields are missing labels?" | `analyzePage`, `askAboutPage` |
|
|
52
|
+
| 3 | Smart Data Grid | Turns "overdue and over ₹10,000" into real filters, finds unusual rows, summarises data | `runGridQuery`, `detectAnomalies`, `summarizeRows` |
|
|
53
|
+
| 4 | Voice Accessibility | "Turn on high contrast", "bigger text", "next row", plus Telugu phrases like "పెద్ద అక్షరాలు" | `createVoiceA11yController` |
|
|
54
|
+
| 5 | QA Tester | 15 checks with WCAG references, a score, pass/fail, and a Markdown or JSON report | `runQaAudit`, `auditToMarkdown` |
|
|
55
|
+
| 6 | Forms Agent | Reviews labels, autocomplete, error messages and senior-friendliness | `reviewForms` |
|
|
56
|
+
| 7 | Page + Data RAG | Answers from page text and grid rows, Telugu-aware, offline | `createContextIndex` |
|
|
57
|
+
| 8 | Multi-Step Tasks | "Show overdue, highlight the errors, then summarise what changed" | `runTasks` |
|
|
58
|
+
| 9 | BI Copilot | "Which region had the highest drop in conversion this week?" | `askInsight`, `comparePeriods` |
|
|
59
|
+
| 10 | Design Review | Hierarchy, readability, focus states, clutter, consistency | `reviewDesign` |
|
|
50
60
|
|
|
51
|
-
|
|
61
|
+
### Page tools in one panel
|
|
52
62
|
|
|
53
|
-
|
|
63
|
+
```tsx
|
|
64
|
+
"use client";
|
|
65
|
+
import { AgenticPanel } from "@yuktishaalaa/yuktai";
|
|
66
|
+
|
|
67
|
+
export default function A11yTools() {
|
|
68
|
+
return <AgenticPanel defaultTab="copilot" voiceLang="en-IN" />;
|
|
69
|
+
}
|
|
70
|
+
```
|
|
54
71
|
|
|
55
|
-
|
|
72
|
+
Tabs: **Copilot**, **QA report**, **Forms**, **Design**, **Ask page**, **Voice**. The panel marks itself with `data-yuktai-panel`, so it never audits its own UI.
|
|
56
73
|
|
|
57
|
-
###
|
|
74
|
+
### Ask your grid
|
|
58
75
|
|
|
59
|
-
|
|
76
|
+
```tsx
|
|
77
|
+
"use client";
|
|
78
|
+
import { YuktaiGrid, useAgenticGrid, AgenticGridBar } from "@yuktishaalaa/yuktai";
|
|
79
|
+
|
|
80
|
+
const columns = [
|
|
81
|
+
{ key: "name", label: "Customer" },
|
|
82
|
+
{ key: "status", label: "Status" },
|
|
83
|
+
{ key: "region", label: "Region" },
|
|
84
|
+
{ key: "balance", label: "Balance", type: "number" as const },
|
|
85
|
+
{ key: "dueDate", label: "Due date", type: "date" as const },
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
export default function Customers({ rows }: { rows: Customer[] }) {
|
|
89
|
+
const grid = useAgenticGrid({ data: rows, columns, rowKey: "id" });
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<>
|
|
93
|
+
<AgenticGridBar
|
|
94
|
+
grid={grid}
|
|
95
|
+
examples={[
|
|
96
|
+
"overdue and over ₹10,000",
|
|
97
|
+
"anything unusual?",
|
|
98
|
+
"total balance by region",
|
|
99
|
+
"show overdue, then sort by balance desc, then summarize what changed",
|
|
100
|
+
]}
|
|
101
|
+
/>
|
|
102
|
+
<YuktaiGrid
|
|
103
|
+
data={grid.gridData}
|
|
104
|
+
columns={columns}
|
|
105
|
+
rowKey="id"
|
|
106
|
+
highlightIds={grid.highlightIds}
|
|
107
|
+
autoScrollToHighlight
|
|
108
|
+
/>
|
|
109
|
+
</>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
60
113
|
|
|
61
|
-
|
|
114
|
+
`grid.ask(text)` picks the right tool for the question:
|
|
62
115
|
|
|
63
|
-
|
|
116
|
+
| Question type | Example | Handled by |
|
|
117
|
+
|---|---|---|
|
|
118
|
+
| Filters and lookups | "customer starting with A and balance between 1k and 9k" | Smart grid query |
|
|
119
|
+
| Unusual data | "anything unusual?" | Outliers and duplicate rows |
|
|
120
|
+
| Group and period questions | "which region had the highest drop in conversion this week?" | BI copilot |
|
|
121
|
+
| Several steps | "show overdue, then highlight errors, then summarise" | Task runner, with a before/after report |
|
|
64
122
|
|
|
65
|
-
|
|
123
|
+
Amounts like `₹10,000`, `10k`, `1.5 lakh` and `2 crore` are understood.
|
|
66
124
|
|
|
67
|
-
|
|
125
|
+
### Use the functions directly
|
|
68
126
|
|
|
69
|
-
|
|
127
|
+
```ts
|
|
128
|
+
import { runQaAudit, auditToMarkdown, askInsight, runGridQuery } from "@yuktishaalaa/yuktai";
|
|
70
129
|
|
|
71
|
-
|
|
130
|
+
// In the browser: accessibility QA report
|
|
131
|
+
const report = runQaAudit();
|
|
132
|
+
console.log(report.score, report.passed);
|
|
133
|
+
const md = auditToMarkdown(report); // attach to a ticket or PR
|
|
72
134
|
|
|
73
|
-
|
|
135
|
+
// Anywhere: data questions
|
|
136
|
+
askInsight("which region had the highest drop in conversion this week", rows, columns).answer;
|
|
137
|
+
runGridQuery("overdue and over 10k", { data: rows, columns }).ids;
|
|
138
|
+
```
|
|
74
139
|
|
|
75
|
-
|
|
140
|
+
### Plug in your own model (optional)
|
|
76
141
|
|
|
77
|
-
-
|
|
142
|
+
Everything works offline with rules and keyword search. To get model-written answers, pass a `generate` hook, for example Gemini Nano or your own API:
|
|
78
143
|
|
|
79
|
-
|
|
144
|
+
```tsx
|
|
145
|
+
<AgenticPanel generate={async (question, context) => myModel(question, context)} />
|
|
146
|
+
```
|
|
80
147
|
|
|
81
|
-
|
|
148
|
+
### Honest limits
|
|
82
149
|
|
|
83
|
-
-
|
|
150
|
+
- Questions are understood with rules, not a language model, so unusual phrasing may need rewording. The parser returns `notes` explaining any assumption it made.
|
|
151
|
+
- The QA and design checks are automatic heuristics. They catch common problems but don't replace testing with real users and assistive technology.
|
|
84
152
|
|
|
85
|
-
|
|
153
|
+
---
|
|
86
154
|
|
|
87
|
-
|
|
155
|
+
## What's new in v4.6.4: YuktaiGrid Agentic AI + WebMCP
|
|
88
156
|
|
|
89
|
-
-
|
|
157
|
+
- Shared Grid Tools used by both the Agent and WebMCP
|
|
158
|
+
- Tools: search, count, columns, get row, highlight, select, open
|
|
159
|
+
- WebMCP registration through `document.modelContext`
|
|
160
|
+
- `useYuktaiGridAgent` hook for programmatic tool execution
|
|
161
|
+
- Embedded Grid AI Assistant inside YuktaiGrid
|
|
162
|
+
- English and Telugu AI UI, with English or Telugu voice input
|
|
163
|
+
- Working page-size switching (10 → 20 → 50 → 100)
|
|
164
|
+
- Seven inline SVG icons, no external icon dependency
|
|
90
165
|
|
|
91
|
-
|
|
166
|
+
**Architecture:** User → Agent / WebMCP → Grid Tools → YuktaiGrid → Data
|
|
92
167
|
|
|
93
|
-
|
|
168
|
+
---
|
|
94
169
|
|
|
95
|
-
|
|
170
|
+
## Works on every device
|
|
96
171
|
|
|
97
|
-
|
|
172
|
+
| Device | Browser | Core features | AI engine |
|
|
173
|
+
|---|---|---|---|
|
|
174
|
+
| 🖥 Desktop | Chrome 147+ | ✅ All | Gemini Nano |
|
|
175
|
+
| 🖥 Desktop | Firefox / Edge / Safari | ✅ All | Transformers.js |
|
|
176
|
+
| 📱 Android | Chrome Mobile | ✅ All | Transformers.js |
|
|
177
|
+
| 📱 iOS | Safari Mobile | ✅ All | Transformers.js |
|
|
178
|
+
| 📲 PWA offline | All browsers | ✅ All | Offline after first load |
|
|
98
179
|
|
|
99
|
-
|
|
180
|
+
yuktai picks the best AI engine automatically. Users never need to know which one is running.
|
|
100
181
|
|
|
101
182
|
---
|
|
102
183
|
|
|
103
184
|
## Install
|
|
104
185
|
|
|
105
|
-
|
|
186
|
+
**Next.js 16 + React 19 (recommended)**
|
|
106
187
|
|
|
107
188
|
```bash
|
|
108
|
-
|
|
109
189
|
npm install @yuktishaalaa/yuktai --legacy-peer-deps
|
|
110
|
-
|
|
111
190
|
```
|
|
112
191
|
|
|
113
|
-
|
|
192
|
+
**Next.js 13, 14, 15**
|
|
114
193
|
|
|
115
194
|
```bash
|
|
116
|
-
|
|
117
195
|
npm install @yuktishaalaa/yuktai
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Yarn / pnpm**
|
|
118
199
|
|
|
200
|
+
```bash
|
|
201
|
+
yarn add @yuktishaalaa/yuktai
|
|
202
|
+
pnpm add @yuktishaalaa/yuktai
|
|
119
203
|
```
|
|
120
204
|
|
|
121
205
|
Requirements: Node.js 18+, npm 8+, Next.js 13+.
|
|
@@ -124,771 +208,531 @@ Requirements: Node.js 18+, npm 8+, Next.js 13+.
|
|
|
124
208
|
|
|
125
209
|
## Quick start
|
|
126
210
|
|
|
127
|
-
### Step 1
|
|
211
|
+
### Step 1: `next.config.js`
|
|
128
212
|
|
|
129
213
|
```js
|
|
130
|
-
|
|
131
214
|
const nextConfig = {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
215
|
+
transpilePackages: ["@yuktishaalaa/yuktai"],
|
|
216
|
+
async headers() {
|
|
217
|
+
return [
|
|
218
|
+
{
|
|
219
|
+
source: "/(.*)",
|
|
220
|
+
headers: [
|
|
221
|
+
// Needed for voice control and voice input
|
|
222
|
+
{ key: "Permissions-Policy", value: "microphone=*, speaker=*" },
|
|
223
|
+
],
|
|
224
|
+
},
|
|
225
|
+
];
|
|
226
|
+
},
|
|
135
227
|
};
|
|
136
228
|
|
|
137
229
|
module.exports = nextConfig;
|
|
138
|
-
|
|
139
230
|
```
|
|
140
231
|
|
|
141
|
-
### Step 2
|
|
232
|
+
### Step 2: Client wrapper
|
|
142
233
|
|
|
143
234
|
```tsx
|
|
144
|
-
|
|
145
235
|
// components/YuktaiClient.tsx
|
|
146
|
-
|
|
147
236
|
"use client";
|
|
148
237
|
|
|
149
238
|
import { useState, useEffect, type ReactNode } from "react";
|
|
150
|
-
|
|
151
239
|
import { YuktAIWrapper } from "@yuktishaalaa/yuktai";
|
|
152
240
|
|
|
153
241
|
export default function YuktaiClient({ children }: { children: ReactNode }) {
|
|
242
|
+
const [mounted, setMounted] = useState(false);
|
|
243
|
+
useEffect(() => setMounted(true), []);
|
|
154
244
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
useEffect(() => setMounted(true), []);
|
|
158
|
-
|
|
159
|
-
if (!mounted) return <>{children}</>;
|
|
160
|
-
|
|
161
|
-
return (
|
|
162
|
-
|
|
163
|
-
<YuktAIWrapper position="left">
|
|
164
|
-
|
|
165
|
-
{children}
|
|
166
|
-
|
|
167
|
-
</YuktAIWrapper>
|
|
168
|
-
|
|
169
|
-
);
|
|
245
|
+
if (!mounted) return <>{children}</>;
|
|
170
246
|
|
|
247
|
+
return (
|
|
248
|
+
<YuktAIWrapper position="left" showRag showAgent>
|
|
249
|
+
{children}
|
|
250
|
+
</YuktAIWrapper>
|
|
251
|
+
);
|
|
171
252
|
}
|
|
172
|
-
|
|
173
253
|
```
|
|
174
254
|
|
|
175
|
-
### Step 3
|
|
255
|
+
### Step 3: `app/layout.tsx`
|
|
176
256
|
|
|
177
257
|
```tsx
|
|
178
|
-
|
|
179
258
|
import YuktaiClient from "@/components/YuktaiClient";
|
|
180
259
|
|
|
181
260
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
<main>{children}</main>
|
|
192
|
-
|
|
193
|
-
</YuktaiClient>
|
|
194
|
-
|
|
195
|
-
</body>
|
|
196
|
-
|
|
197
|
-
</html>
|
|
198
|
-
|
|
199
|
-
);
|
|
200
|
-
|
|
261
|
+
return (
|
|
262
|
+
<html lang="en">
|
|
263
|
+
<body>
|
|
264
|
+
<YuktaiClient>
|
|
265
|
+
<main>{children}</main>
|
|
266
|
+
</YuktaiClient>
|
|
267
|
+
</body>
|
|
268
|
+
</html>
|
|
269
|
+
);
|
|
201
270
|
}
|
|
202
|
-
|
|
203
271
|
```
|
|
204
272
|
|
|
205
|
-
That's it.
|
|
206
|
-
|
|
207
|
-
---
|
|
208
|
-
|
|
209
|
-
## Module 1 — Accessibility Engine
|
|
210
|
-
|
|
211
|
-
Scans every element and injects missing accessibility attributes automatically.
|
|
212
|
-
|
|
213
|
-
Covers: headings, images, forms, tables, lists, landmarks, ARIA widgets. Watches for new DOM elements via `MutationObserver`.
|
|
273
|
+
That's it. Floating buttons appear on every page: ♿ opens the accessibility panel, 💬 opens "Ask this page", and the agent button opens the AI agent.
|
|
214
274
|
|
|
215
|
-
|
|
275
|
+
To add the v5.1 agentic tools, place `<AgenticPanel />` or `useAgenticGrid` in any client component (see [What's new in v5.1](#whats-new-in-v51-agentic-ai-toolkit)).
|
|
216
276
|
|
|
217
|
-
|
|
277
|
+
### Wrapper props
|
|
218
278
|
|
|
219
|
-
|
|
279
|
+
| Prop | Type | Default | Description |
|
|
280
|
+
|---|---|---|---|
|
|
281
|
+
| `position` | `"left" \| "right"` | `"left"` | Which side the buttons appear on |
|
|
282
|
+
| `showRag` | `boolean` | `false` | Show the 💬 Ask-this-page button |
|
|
283
|
+
| `showAgent` | `boolean` | `false` | Show the AI agent button |
|
|
284
|
+
| `config` | `Partial<A11yConfig>` | `undefined` | Accessibility config overrides |
|
|
285
|
+
| `children` | `ReactNode` | required | Your app content |
|
|
220
286
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
- High contrast · Dark mode · Reduce motion · Large targets (44×44)
|
|
224
|
-
|
|
225
|
-
- Colour-blind modes — Deuteranopia, Protanopia, Tritanopia, Greyscale
|
|
287
|
+
---
|
|
226
288
|
|
|
227
|
-
|
|
289
|
+
## Module 1: Accessibility Engine
|
|
228
290
|
|
|
229
|
-
|
|
291
|
+
Scans every element and injects missing accessibility attributes automatically. Covers headings, images, forms, tables, lists, landmarks, and ARIA widgets. Watches for new DOM elements with `MutationObserver`.
|
|
230
292
|
|
|
231
|
-
|
|
293
|
+
**Features**
|
|
232
294
|
|
|
233
|
-
-
|
|
295
|
+
- WCAG 2.2 auto-fix: ARIA, roles, tabindex, scope, autocomplete, alt text
|
|
296
|
+
- Speak on focus using browser SpeechSynthesis
|
|
297
|
+
- Voice control using the SpeechRecognition API
|
|
298
|
+
- Visual alerts for deaf and hard-of-hearing users
|
|
299
|
+
- High contrast, dark mode, reduce motion, large targets (44×44)
|
|
300
|
+
- Colour-blind modes: Deuteranopia, Protanopia, Tritanopia, Greyscale
|
|
301
|
+
- Dyslexia font: Atkinson Hyperlegible
|
|
302
|
+
- Local font picker and font scaling from 80% to 130%
|
|
303
|
+
- Audit badge with a WCAG score from 0 to 100 (localhost only)
|
|
304
|
+
- Skip links, focus trap, saved preferences, reset
|
|
234
305
|
|
|
235
|
-
|
|
306
|
+
**Direct API**
|
|
236
307
|
|
|
237
308
|
```ts
|
|
309
|
+
import { wcagPlugin, type A11yConfig } from "@yuktishaalaa/yuktai";
|
|
238
310
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
speechEnabled: false,
|
|
256
|
-
|
|
257
|
-
colorBlindMode:"none",
|
|
258
|
-
|
|
259
|
-
autoFix: true,
|
|
260
|
-
|
|
261
|
-
});
|
|
311
|
+
const config: A11yConfig = {
|
|
312
|
+
enabled: true,
|
|
313
|
+
highContrast: false,
|
|
314
|
+
darkMode: false,
|
|
315
|
+
reduceMotion: false,
|
|
316
|
+
largeTargets: false,
|
|
317
|
+
speechEnabled: false,
|
|
318
|
+
colorBlindMode: "none", // none | deuteranopia | protanopia | tritanopia | achromatopsia
|
|
319
|
+
autoFix: true,
|
|
320
|
+
showPreferencePanel: true,
|
|
321
|
+
showSkipLinks: true,
|
|
322
|
+
showAuditBadge: false, // dev only (localhost)
|
|
323
|
+
fontSizeMultiplier: 1,
|
|
324
|
+
timeoutWarning: 0, // seconds, 0 = off
|
|
325
|
+
};
|
|
262
326
|
|
|
263
|
-
|
|
327
|
+
const report = wcagPlugin.applyFixes(config);
|
|
328
|
+
console.log(report.fixed); // number of fixes applied
|
|
329
|
+
console.log(report.score); // 0–100
|
|
330
|
+
```
|
|
264
331
|
|
|
265
|
-
|
|
332
|
+
### WCAG coverage
|
|
266
333
|
|
|
267
|
-
|
|
334
|
+
| Standard | Criteria | Examples |
|
|
335
|
+
|---|---|---|
|
|
336
|
+
| WCAG 2.0 | 19 | Alt text, roles, labels, tables, landmarks, focus |
|
|
337
|
+
| WCAG 2.1 | 7 | Touch targets, reflow, motion, orientation |
|
|
338
|
+
| WCAG 2.2 | 3 | Focus appearance, target size, timeout warning |
|
|
339
|
+
| Beyond WCAG | Extras | Speech, visual alerts, colour-blind modes, dyslexia font, audit score |
|
|
268
340
|
|
|
269
341
|
---
|
|
270
342
|
|
|
271
|
-
## Module 2
|
|
343
|
+
## Module 2: YuktaiGrid ⭐
|
|
272
344
|
|
|
273
|
-
An accessible data grid
|
|
345
|
+
An accessible data grid for Next.js, with an embedded AI assistant, agent tools, and WebMCP support.
|
|
274
346
|
|
|
275
|
-
###
|
|
347
|
+
### Basic usage
|
|
276
348
|
|
|
277
349
|
```tsx
|
|
278
|
-
|
|
279
350
|
"use client";
|
|
280
351
|
|
|
281
352
|
import { YuktaiGrid } from "@yuktishaalaa/yuktai";
|
|
282
353
|
|
|
283
354
|
const data = [
|
|
284
|
-
|
|
285
|
-
{ id:
|
|
286
|
-
|
|
287
|
-
{ id: 2, name: "Priya", role: "Designer", salary: 90000 },
|
|
288
|
-
|
|
355
|
+
{ id: 1, name: "Sandeep", role: "Developer", salary: 85000 },
|
|
356
|
+
{ id: 2, name: "Priya", role: "Designer", salary: 90000 },
|
|
289
357
|
];
|
|
290
358
|
|
|
291
359
|
export default function EmployeesPage() {
|
|
360
|
+
return (
|
|
361
|
+
<YuktaiGrid
|
|
362
|
+
data={data}
|
|
363
|
+
rowKey="id"
|
|
364
|
+
columns={[
|
|
365
|
+
{ key: "name", label: "Name", sortable: true },
|
|
366
|
+
{ key: "role", label: "Role" },
|
|
367
|
+
{ key: "salary", label: "Salary", type: "number", align: "right" },
|
|
368
|
+
]}
|
|
369
|
+
theme="default" // default | high-contrast | dark | color-blind | dyslexia
|
|
370
|
+
locale="en-US" // en-US | te-IN
|
|
371
|
+
view="auto" // auto | table | card
|
|
372
|
+
search
|
|
373
|
+
ai
|
|
374
|
+
pagination={{
|
|
375
|
+
pageSize: 20,
|
|
376
|
+
showSizeChanger: true,
|
|
377
|
+
sizeOptions: [10, 20, 50, 100],
|
|
378
|
+
}}
|
|
379
|
+
/>
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
```
|
|
292
383
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
\<YuktaiGrid
|
|
296
|
-
|
|
297
|
-
data={data}
|
|
298
|
-
|
|
299
|
-
columns={[
|
|
300
|
-
|
|
301
|
-
{ key: "name", label: "Name", sortable: true },
|
|
302
|
-
|
|
303
|
-
{ key: "role", label: "Role" },
|
|
304
|
-
|
|
305
|
-
{ key: "salary", label: "Salary", type: "number", align: "right" },
|
|
306
|
-
|
|
307
|
-
]}
|
|
308
|
-
|
|
309
|
-
theme="default" // default | high-contrast | dark | color-blind | dyslexia
|
|
310
|
-
|
|
311
|
-
locale="en-US" // en-US | te-IN
|
|
312
|
-
|
|
313
|
-
search={true} // real-time filtering
|
|
384
|
+
### Grid features
|
|
314
385
|
|
|
315
|
-
|
|
386
|
+
- Real-time search, column sorting, client-side pagination with page-size switching
|
|
387
|
+
- Mobile card view below a configurable breakpoint
|
|
388
|
+
- Loading and empty states
|
|
389
|
+
- 5 WCAG themes
|
|
390
|
+
- Row selection, custom cell render, `rowKey`
|
|
391
|
+
- Row highlighting with optional auto-scroll
|
|
392
|
+
- Keyboard navigation, ARIA grid semantics, 44×44 targets
|
|
393
|
+
- English and Telugu UI
|
|
394
|
+
- Embedded Grid AI Assistant with voice and chat
|
|
395
|
+
- **New in v5.1:** compound natural-language questions, anomaly detection and BI answers through `useAgenticGrid`
|
|
316
396
|
|
|
317
|
-
|
|
397
|
+
### Grid AI Assistant
|
|
318
398
|
|
|
319
|
-
|
|
320
|
-
pageSize: 20,
|
|
321
|
-
showSizeChanger: true,
|
|
322
|
-
sizeOptions: [10, 20, 50, 100],
|
|
323
|
-
}}
|
|
399
|
+
Runs embedded in the grid or as a standalone component. Intent parsing runs locally and supports search, sort, count, highest, lowest, average, total, and row lookup.
|
|
324
400
|
|
|
401
|
+
```tsx
|
|
402
|
+
<YuktaiGridAI
|
|
403
|
+
data={data}
|
|
404
|
+
columns={columns}
|
|
405
|
+
onSearch={handleSearch}
|
|
406
|
+
onSort={handleSort}
|
|
407
|
+
language="te-IN" // AI UI and responses: en-US | te-IN
|
|
408
|
+
inputLanguage="te-IN" // voice input: en-US | te-IN
|
|
409
|
+
embedded
|
|
325
410
|
/>
|
|
326
|
-
|
|
327
|
-
);
|
|
328
|
-
|
|
329
|
-
}
|
|
330
|
-
|
|
331
411
|
```
|
|
332
412
|
|
|
333
|
-
|
|
413
|
+
Voice recognition depends on browser Web Speech API support.
|
|
334
414
|
|
|
335
|
-
|
|
415
|
+
### Agent tools
|
|
336
416
|
|
|
337
|
-
|
|
417
|
+
Generic, reusable grid operations shared by the Agent and WebMCP:
|
|
338
418
|
|
|
339
|
-
|
|
419
|
+
```ts
|
|
420
|
+
import {
|
|
421
|
+
searchGrid,
|
|
422
|
+
countGrid,
|
|
423
|
+
getColumns,
|
|
424
|
+
getRow,
|
|
425
|
+
highlightRows,
|
|
426
|
+
selectRow,
|
|
427
|
+
openRow,
|
|
428
|
+
} from "@yuktishaalaa/yuktai";
|
|
429
|
+
```
|
|
340
430
|
|
|
341
|
-
|
|
431
|
+
Run tools programmatically:
|
|
342
432
|
|
|
343
|
-
|
|
433
|
+
```tsx
|
|
434
|
+
import { useYuktaiGridAgent, type GridAgentTool } from "@yuktishaalaa/yuktai";
|
|
344
435
|
|
|
345
|
-
|
|
436
|
+
const tools: GridAgentTool[] = [
|
|
437
|
+
{
|
|
438
|
+
name: "search",
|
|
439
|
+
description: "Search grid rows by a text query",
|
|
440
|
+
execute: async ({ query }) => searchGrid(data, query),
|
|
441
|
+
},
|
|
442
|
+
];
|
|
346
443
|
|
|
347
|
-
|
|
444
|
+
const { executeTool, loading } = useYuktaiGridAgent({ tools });
|
|
445
|
+
```
|
|
348
446
|
|
|
349
|
-
|
|
447
|
+
**Design principle:** keep generic tools in the package and put app-specific rules in your app.
|
|
350
448
|
|
|
351
|
-
|
|
449
|
+
```text
|
|
450
|
+
Generic YuktAI tools + Your domain rules = Your application agent
|
|
451
|
+
```
|
|
352
452
|
|
|
353
|
-
|
|
453
|
+
### WebMCP
|
|
354
454
|
|
|
355
|
-
|
|
455
|
+
Exposes grid tools to browser AI agents through `document.modelContext`, so agents call real operations instead of guessing from the DOM. Registration is invisible in the UI.
|
|
356
456
|
|
|
357
|
-
|
|
457
|
+
```tsx
|
|
458
|
+
<YuktaiGrid
|
|
459
|
+
data={rows}
|
|
460
|
+
columns={columns}
|
|
461
|
+
ai
|
|
462
|
+
webmcp
|
|
463
|
+
toolName="my_grid"
|
|
464
|
+
toolDescriptions={TOOL_DESCRIPTIONS}
|
|
465
|
+
onWebMCPStatusChange={setStatus} // unsupported | registering | ready | partial | error
|
|
466
|
+
/>
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
Or standalone:
|
|
358
470
|
|
|
359
|
-
|
|
471
|
+
```tsx
|
|
472
|
+
<YuktaiGridWebMCP data={data} columns={columns} />
|
|
473
|
+
```
|
|
360
474
|
|
|
361
|
-
|
|
475
|
+
WebMCP is not available in every browser, so always handle the `unsupported` status gracefully.
|
|
362
476
|
|
|
363
|
-
|
|
477
|
+
### Large datasets (100K+ rows)
|
|
364
478
|
|
|
365
|
-
|
|
479
|
+
Client-side pagination handles a few thousand rows well. For anything larger, use server-side pagination and disable the grid's built-in search and pagination.
|
|
366
480
|
|
|
367
|
-
|
|
481
|
+
`src/app/api/employees/route.ts`:
|
|
368
482
|
|
|
369
483
|
```ts
|
|
370
|
-
|
|
371
484
|
import { NextRequest, NextResponse } from "next/server";
|
|
372
485
|
|
|
373
486
|
let cachedData: any[] | null = null;
|
|
374
|
-
|
|
375
487
|
let cacheTime = 0;
|
|
376
|
-
|
|
377
488
|
const TTL_MS = 60_000;
|
|
378
489
|
|
|
379
490
|
async function fetchAll(): Promise<any[]> {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
const json = await res.json();
|
|
388
|
-
|
|
389
|
-
cachedData = Array.isArray(json) ? json : (json.employees ?? json.data ?? []);
|
|
390
|
-
|
|
391
|
-
cacheTime = now;
|
|
392
|
-
|
|
393
|
-
return cachedData;
|
|
394
|
-
|
|
491
|
+
const now = Date.now();
|
|
492
|
+
if (cachedData && now - cacheTime < TTL_MS) return cachedData;
|
|
493
|
+
const res = await fetch("https://your-api.com/employees", { cache: "no-store" });
|
|
494
|
+
const json = await res.json();
|
|
495
|
+
cachedData = Array.isArray(json) ? json : json.employees ?? json.data ?? [];
|
|
496
|
+
cacheTime = now;
|
|
497
|
+
return cachedData;
|
|
395
498
|
}
|
|
396
499
|
|
|
397
500
|
export async function GET(req: NextRequest) {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
const total = filtered.length;
|
|
416
|
-
|
|
417
|
-
const rows = filtered.slice((page - 1) * pageSize, page * pageSize);
|
|
418
|
-
|
|
419
|
-
return NextResponse.json({
|
|
420
|
-
|
|
421
|
-
rows,
|
|
422
|
-
|
|
423
|
-
pagination: { page, pageSize, totalRows: total, totalPages: Math.ceil(total / pageSize) },
|
|
424
|
-
|
|
425
|
-
});
|
|
426
|
-
|
|
501
|
+
const p = req.nextUrl.searchParams;
|
|
502
|
+
const page = Math.max(1, parseInt(p.get("page") || "1"));
|
|
503
|
+
const pageSize = Math.max(1, parseInt(p.get("pageSize") || "5000"));
|
|
504
|
+
const search = (p.get("search") || "").toLowerCase().trim();
|
|
505
|
+
|
|
506
|
+
const all = await fetchAll();
|
|
507
|
+
const filtered = search
|
|
508
|
+
? all.filter((r) => Object.values(r).some((v) => String(v).toLowerCase().includes(search)))
|
|
509
|
+
: all;
|
|
510
|
+
|
|
511
|
+
const total = filtered.length;
|
|
512
|
+
const rows = filtered.slice((page - 1) * pageSize, page * pageSize);
|
|
513
|
+
|
|
514
|
+
return NextResponse.json({
|
|
515
|
+
rows,
|
|
516
|
+
pagination: { page, pageSize, totalRows: total, totalPages: Math.ceil(total / pageSize) },
|
|
517
|
+
});
|
|
427
518
|
}
|
|
428
|
-
|
|
429
519
|
```
|
|
430
520
|
|
|
431
|
-
|
|
521
|
+
Page:
|
|
432
522
|
|
|
433
523
|
```tsx
|
|
434
|
-
|
|
435
|
-
const [
|
|
436
|
-
|
|
437
|
-
const [currentPage, setPage] = useState(1);
|
|
524
|
+
const [apiResp, setApiResp] = useState<any>(null);
|
|
525
|
+
const [currentPage, setPage] = useState(1);
|
|
438
526
|
|
|
439
527
|
useEffect(() => {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
.then(r => r.json())
|
|
444
|
-
|
|
445
|
-
.then(setApiResp);
|
|
446
|
-
|
|
528
|
+
fetch(`/api/employees?page=${currentPage}&pageSize=5000`)
|
|
529
|
+
.then((r) => r.json())
|
|
530
|
+
.then(setApiResp);
|
|
447
531
|
}, [currentPage]);
|
|
448
532
|
|
|
449
533
|
<YuktaiGrid
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
pagination={false} // disable — we handle pagination server-side
|
|
458
|
-
|
|
459
|
-
loading={!apiResp}
|
|
460
|
-
|
|
461
|
-
/>
|
|
462
|
-
|
|
534
|
+
data={apiResp?.rows ?? []}
|
|
535
|
+
columns={columns}
|
|
536
|
+
search={false} // handled server-side
|
|
537
|
+
pagination={false} // handled server-side
|
|
538
|
+
loading={!apiResp}
|
|
539
|
+
/>;
|
|
463
540
|
```
|
|
464
541
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
---
|
|
542
|
+
Render your own pagination bar from `apiResp.pagination`. The browser only ever holds one page in memory.
|
|
468
543
|
|
|
469
544
|
---
|
|
470
545
|
|
|
471
|
-
##
|
|
472
|
-
|
|
473
|
-
YuktaiGrid exposes reusable Grid operations so an Agent can work with grid data through a shared tool layer and WebMCP.
|
|
474
|
-
|
|
475
|
-
### Grid tools
|
|
476
|
-
|
|
477
|
-
```ts
|
|
478
|
-
|
|
479
|
-
import {
|
|
480
|
-
searchGrid,
|
|
481
|
-
countGrid,
|
|
482
|
-
getColumns,
|
|
483
|
-
getRow,
|
|
484
|
-
highlightRows,
|
|
485
|
-
selectRow,
|
|
486
|
-
openRow,
|
|
487
|
-
} from "@yuktishaalaa/yuktai";
|
|
488
|
-
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
These operations form the common execution layer for programmatic Agent tools and WebMCP.
|
|
492
|
-
|
|
493
|
-
### Agent execution
|
|
494
|
-
|
|
495
|
-
```tsx
|
|
496
|
-
|
|
497
|
-
import {
|
|
498
|
-
useYuktaiGridAgent,
|
|
499
|
-
type GridAgentTool,
|
|
500
|
-
} from "@yuktishaalaa/yuktai";
|
|
501
|
-
|
|
502
|
-
const tools: GridAgentTool[] = [
|
|
503
|
-
{
|
|
504
|
-
name: "search",
|
|
505
|
-
description: "Search grid rows",
|
|
506
|
-
execute: async ({ query }) => {
|
|
507
|
-
return { query };
|
|
508
|
-
},
|
|
509
|
-
},
|
|
510
|
-
];
|
|
511
|
-
|
|
512
|
-
const { executeTool, loading } =
|
|
513
|
-
useYuktaiGridAgent({ tools });
|
|
514
|
-
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
### WebMCP
|
|
518
|
-
|
|
519
|
-
```tsx
|
|
520
|
-
|
|
521
|
-
import {
|
|
522
|
-
YuktaiGridWebMCP,
|
|
523
|
-
} from "@yuktishaalaa/yuktai";
|
|
546
|
+
## Showcase: Ratnalabala (Telugu poetry)
|
|
524
547
|
|
|
525
|
-
|
|
526
|
-
data={data}
|
|
527
|
-
columns={columns}
|
|
528
|
-
/>
|
|
548
|
+
[Ratnalabala](https://ratnalabala.vercel.app/poems?view=grid) shows that an agentic grid is more than a chatbot next to a table. Users type or speak in Telugu, and the grid acts.
|
|
529
549
|
|
|
550
|
+
| User says | Agent action |
|
|
551
|
+
|---|---|
|
|
552
|
+
| `ఎన్ని పద్యాలు` (how many poems) | `count` → "మొత్తం 36 పద్యాలు ఉన్నాయి." |
|
|
553
|
+
| `గర్వం తెరువు` (open "Garvam") | `open` |
|
|
554
|
+
| `"బుద్ధి" ఉన్న పద్యాలు` (poems with "buddhi") | `search` + highlight |
|
|
555
|
+
| `అక్షర క్రమంలో` (alphabetical) | `sort(title, asc)` |
|
|
556
|
+
| `ఈరోజు పద్యం` (poem of the day) | custom rule + highlight |
|
|
557
|
+
|
|
558
|
+
**Stack:** Next.js · React + TypeScript · MUI · YuktAI Grid · FastAPI (Python) · PostgreSQL on Neon · Vercel · Web Speech API · WebMCP
|
|
559
|
+
|
|
560
|
+
```text
|
|
561
|
+
PostgreSQL → FastAPI → Next.js API proxy → Ratnalabala UI → YuktAI Grid
|
|
562
|
+
├── Agent
|
|
563
|
+
└── WebMCP
|
|
530
564
|
```
|
|
531
565
|
|
|
532
|
-
WebMCP registration is invisible in the UI and uses document.modelContext when available.
|
|
533
|
-
|
|
534
|
-
### Embedded Grid AI Assistant
|
|
535
|
-
|
|
536
566
|
```tsx
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
locale="te-IN"
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
}
|
|
567
|
+
<YuktaiGrid<PoemRow>
|
|
568
|
+
data={rows}
|
|
569
|
+
columns={COLUMNS}
|
|
570
|
+
rowKey="id"
|
|
571
|
+
locale="te-IN"
|
|
572
|
+
inputLanguage="te-IN"
|
|
573
|
+
customRules={POEM_RULES}
|
|
574
|
+
search
|
|
575
|
+
highlightIds={highlightIds}
|
|
576
|
+
autoScrollToHighlight
|
|
577
|
+
onRowClick={(row) => onOpenPoem(row.title)}
|
|
578
|
+
ai
|
|
579
|
+
webmcp
|
|
580
|
+
toolName="ratnalabala_poems"
|
|
581
|
+
toolDescriptions={TOOL_DESCRIPTIONS}
|
|
582
|
+
onWebMCPStatusChange={setWebmcp}
|
|
548
583
|
/>
|
|
549
|
-
|
|
550
584
|
```
|
|
551
585
|
|
|
552
|
-
Grid AI supports:
|
|
553
|
-
|
|
554
|
-
- language="en-US" or language="te-IN" for AI UI and responses
|
|
555
|
-
|
|
556
|
-
- inputLanguage="en-US" or inputLanguage="te-IN" for voice input
|
|
557
|
-
|
|
558
|
-
- embedded mode for rendering AI inside the Grid
|
|
559
|
-
|
|
560
|
-
- Local intent parsing for search, sort, count, highest, lowest, average, total, and lookup
|
|
561
|
-
|
|
562
586
|
---
|
|
563
587
|
|
|
564
|
-
## Module 3
|
|
565
|
-
|
|
566
|
-
Retrieval-Augmented Generation running entirely in the browser. Extracts semantic chunks from the current DOM, embeds them, finds the best match for the user's question, and answers — offline, no API key.
|
|
567
|
-
|
|
568
|
-
### Features (11)
|
|
569
|
-
|
|
570
|
-
- Ask any question about any page
|
|
571
|
-
|
|
572
|
-
- Gemini Nano on desktop Chrome — zero download, zero API
|
|
573
|
-
|
|
574
|
-
- Transformers.js on mobile — 30 MB one-time model load
|
|
588
|
+
## Module 3: In-Tab RAG (Ask This Page)
|
|
575
589
|
|
|
576
|
-
-
|
|
590
|
+
Retrieval-Augmented Generation running entirely in the browser. It extracts text chunks from the current page, embeds them, finds the best match for the question, and answers. Offline, no API key.
|
|
577
591
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
- `flan-t5-small` for full-sentence answers
|
|
583
|
-
|
|
584
|
-
- Cosine similarity semantic search
|
|
592
|
+
| Device | Engine | How it works |
|
|
593
|
+
|---|---|---|
|
|
594
|
+
| Desktop Chrome with Gemini Nano | `window.LanguageModel` | Page text sent as context, instant answer |
|
|
595
|
+
| Mobile and all other browsers | Transformers.js | Embeddings + `flan-t5-small`, q4 quantized |
|
|
585
596
|
|
|
586
|
-
-
|
|
597
|
+
- About 30 MB one-time model download on mobile, cached in IndexedDB
|
|
598
|
+
- Works fully offline after first load
|
|
599
|
+
- All processing on device, no data sent anywhere
|
|
587
600
|
|
|
588
|
-
|
|
601
|
+
**What I learned:** Transformers.js kept crashing on iOS Safari with out-of-memory errors. Quantization (same model, 75% smaller) fixed it. DistilBERT gave short, useless spans; `flan-t5-small` gives real sentences.
|
|
589
602
|
|
|
590
|
-
|
|
603
|
+
**New in v5.1:** `createContextIndex` also searches grid rows (including rows on other pages of the grid) and your own documents, with keyword search that handles Telugu and Hindi script correctly.
|
|
591
604
|
|
|
592
605
|
---
|
|
593
606
|
|
|
594
|
-
## Module 4
|
|
595
|
-
|
|
596
|
-
User types a goal in plain English. Yuktai reads the DOM, finds the right elements, plans steps, and highlights what to do.
|
|
607
|
+
## Module 4: Autonomous AI Agent
|
|
597
608
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
- Plain-English goal input
|
|
601
|
-
|
|
602
|
-
- Reads full page DOM — 9 traversal strategies
|
|
603
|
-
|
|
604
|
-
- Scans all form fields — 11 label strategies
|
|
609
|
+
Type a goal in plain English. yuktai reads the page, finds the right elements, plans the steps, and highlights what to do.
|
|
605
610
|
|
|
611
|
+
- 9 DOM traversal strategies and 11 form-label strategies
|
|
606
612
|
- Works on static HTML, React, WordPress, and old government portals
|
|
613
|
+
- Gemini Nano planning on desktop, Transformers.js on mobile, rule-based fallback
|
|
614
|
+
- Highlights target fields, scrolls to sections, shows a numbered plan, handles iframes
|
|
607
615
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
- Rule-based fallback if AI fails
|
|
611
|
-
|
|
612
|
-
- Highlights target field with teal outline
|
|
613
|
-
|
|
614
|
-
- Scrolls to relevant section by keyword
|
|
615
|
-
|
|
616
|
-
- Numbered step-by-step plan
|
|
617
|
-
|
|
618
|
-
- Handles iframes
|
|
619
|
-
|
|
620
|
-
The 11 label strategies came from real websites — old government portals put labels in the previous table cell, modern apps use `aria-label`, static pages use `placeholder`. Every strategy solved a problem I had actually hit.
|
|
616
|
+
Every label strategy came from a real website: old portals put labels in the previous table cell, modern apps use `aria-label`, static pages use `placeholder`.
|
|
621
617
|
|
|
622
618
|
---
|
|
623
619
|
|
|
624
|
-
## Module 5
|
|
625
|
-
|
|
626
|
-
Type a business requirement. Yuktai generates a full Next.js 16 project as a downloadable ZIP.
|
|
627
|
-
|
|
628
|
-
### Features (19)
|
|
620
|
+
## Module 5: Vibe Coder
|
|
629
621
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
- Detects theme colour (8), extracts site name
|
|
622
|
+
Type a business requirement and download a full Next.js 16 project as a ZIP.
|
|
633
623
|
|
|
624
|
+
- Detects website type (12), pages (21), features (14), theme colour (8), and site name
|
|
634
625
|
- Preview before generating
|
|
626
|
+
- TypeScript, Tailwind + CSS Modules, mobile responsive
|
|
627
|
+
- Navbar, Footer, Home, About, Contact, Services, Pricing, Auth, Dashboard
|
|
628
|
+
- `npm run dev` works immediately
|
|
635
629
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
- Navbar, Footer, Home, About, Contact, Services, Pricing, Auth, Dashboard pages
|
|
639
|
-
|
|
640
|
-
- Downloads as ZIP · `npm run dev` works immediately
|
|
641
|
-
|
|
642
|
-
- Pure templates — no AI writes the code
|
|
643
|
-
|
|
644
|
-
No AI writes a single line. Pure template engineering. Same reusable-utility thinking from 2013 jQuery — now generating entire Next.js projects.
|
|
630
|
+
No AI writes the code. It's pure template engineering.
|
|
645
631
|
|
|
646
632
|
---
|
|
647
633
|
|
|
648
|
-
##
|
|
649
|
-
|
|
650
|
-
The Grid AI Assistant can run embedded inside YuktaiGrid or as a standalone component.
|
|
651
|
-
|
|
652
|
-
Voice input uses the browser Web Speech API. AI responses can be spoken with SpeechSynthesis. Intent parsing runs locally for the supported Grid operations.
|
|
653
|
-
|
|
654
|
-
Supports:
|
|
655
|
-
|
|
656
|
-
- Search
|
|
657
|
-
|
|
658
|
-
- Sort
|
|
659
|
-
|
|
660
|
-
- Count
|
|
634
|
+
## Module 6: Agentic AI Toolkit 🆕
|
|
661
635
|
|
|
662
|
-
|
|
636
|
+
The ten v5.1 features, described in detail in [What's new in v5.1](#whats-new-in-v51-agentic-ai-toolkit).
|
|
663
637
|
|
|
664
|
-
-
|
|
638
|
+
- **Copilot and QA:** 15 WCAG checks, plain-English explanations, safe fixes with undo, downloadable reports
|
|
639
|
+
- **Forms and design review:** labels, autocomplete, error messages, focus states, hierarchy, clutter, senior-friendly tips
|
|
640
|
+
- **Data:** compound grid questions, outliers and duplicates, group-by, period comparison, trends
|
|
641
|
+
- **Automation:** multi-step instructions with a before/after summary
|
|
642
|
+
- **Voice:** accessibility settings and grid row navigation by voice, in English and Telugu
|
|
643
|
+
- **React:** `AgenticPanel`, `AgenticGridBar`, `useAgenticGrid`
|
|
665
644
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
- Total
|
|
669
|
-
|
|
670
|
-
- Row lookup
|
|
671
|
-
|
|
672
|
-
- English and Telugu AI UI
|
|
645
|
+
---
|
|
673
646
|
|
|
674
|
-
|
|
647
|
+
## Gemini Nano setup (desktop Chrome, one time)
|
|
675
648
|
|
|
676
|
-
|
|
649
|
+
Needed only for Gemini Nano features on desktop Chrome. Mobile and other browsers use Transformers.js automatically.
|
|
677
650
|
|
|
678
|
-
|
|
651
|
+
1. Open `chrome://flags` and enable: Prompt API for Gemini Nano, Summarization API, Writer API, Rewriter API, Translation API.
|
|
652
|
+
2. Click **Relaunch**.
|
|
653
|
+
3. Open `chrome://components`, find **Optimization Guide On Device Model**, and click **Check for update**.
|
|
654
|
+
4. Refresh your page. AI features unlock automatically.
|
|
679
655
|
|
|
680
|
-
|
|
656
|
+
**Gemini Nano features:** plain-English rewriting, 3-sentence page summary, AI-generated ARIA labels, page translation in 18 languages.
|
|
681
657
|
|
|
682
|
-
|
|
683
|
-
data={data}
|
|
684
|
-
columns={columns}
|
|
685
|
-
onSearch={handleSearch}
|
|
686
|
-
onSort={handleSort}
|
|
687
|
-
language="te-IN"
|
|
688
|
-
inputLanguage="en-US"
|
|
689
|
-
embedded
|
|
690
|
-
/>
|
|
691
|
-
|
|
692
|
-
```
|
|
693
|
-
|
|
694
|
-
Voice recognition depends on browser Web Speech API support.
|
|
658
|
+
> Chrome 147 moved the APIs from `window.ai` to standalone globals such as `window.LanguageModel`. yuktai supports both.
|
|
695
659
|
|
|
696
660
|
---
|
|
697
661
|
|
|
698
|
-
##
|
|
662
|
+
## Icons
|
|
699
663
|
|
|
700
|
-
|
|
664
|
+
Seven custom SVG icons with no external dependency.
|
|
701
665
|
|
|
702
666
|
```tsx
|
|
703
|
-
|
|
704
667
|
import {
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
ChevronLeftIcon,
|
|
713
|
-
|
|
714
|
-
ChevronRightIcon,
|
|
715
|
-
|
|
716
|
-
CheckIcon,
|
|
717
|
-
|
|
718
|
-
CloseIcon,
|
|
719
|
-
|
|
668
|
+
SearchIcon,
|
|
669
|
+
SortUpIcon,
|
|
670
|
+
SortDownIcon,
|
|
671
|
+
ChevronLeftIcon,
|
|
672
|
+
ChevronRightIcon,
|
|
673
|
+
CheckIcon,
|
|
674
|
+
CloseIcon,
|
|
720
675
|
} from "@yuktishaalaa/yuktai";
|
|
721
676
|
|
|
722
|
-
<SearchIcon
|
|
723
|
-
|
|
724
|
-
<SortUpIcon size={20} color="#0D9488" />
|
|
725
|
-
|
|
726
|
-
<CheckIcon size={20} color="#10b981" label="Task complete" />
|
|
727
|
-
|
|
728
|
-
<CloseIcon size={20} color="#dc2626" />
|
|
729
|
-
|
|
730
|
-
<ChevronLeftIcon size={24} label="Previous" />
|
|
731
|
-
|
|
732
|
-
<ChevronRightIcon size={24} label="Next" />
|
|
733
|
-
|
|
677
|
+
<SearchIcon size={20} />
|
|
678
|
+
<CheckIcon size={20} color="#10b981" label="Task complete" />
|
|
734
679
|
```
|
|
735
680
|
|
|
736
|
-
Props: `size` (default 20), `color` (default `currentColor`), `strokeWidth` (default 2.5), `label` (adds ARIA
|
|
737
|
-
|
|
738
|
-
---
|
|
739
|
-
|
|
740
|
-
## Gemini Nano (Chrome 147+)
|
|
741
|
-
|
|
742
|
-
- Plain-English mode — rewrites complex text
|
|
743
|
-
|
|
744
|
-
- Summarise page — 3-sentence summary
|
|
745
|
-
|
|
746
|
-
- Smart ARIA labels — AI generates labels
|
|
747
|
-
|
|
748
|
-
- Translate page — 18 languages
|
|
749
|
-
|
|
750
|
-
- Chrome 147+ standalone globals (`window.LanguageModel`)
|
|
751
|
-
|
|
752
|
-
- Fallback to old `window.ai` namespace
|
|
753
|
-
|
|
754
|
-
Chrome 147 silently removed `window.ai` and moved everything to standalone globals. Debugged for an evening before finding it in the release notes.
|
|
755
|
-
|
|
756
|
-
---
|
|
757
|
-
|
|
758
|
-
## Technical (17 features)
|
|
759
|
-
|
|
760
|
-
Zero API keys · Zero cost · Zero telemetry · Works on all browsers · Works on mobile (Android + iOS) · Works offline after first load · PWA compatible · Next.js 16 compatible · React 19 compatible · TypeScript throughout · SSR safe (no window errors) · Escape closes all panels · Each panel closes others · `data-yuktai-panel` — never reads own UI · Three stacked FAB buttons · Mobile full-screen panels · Tablet responsive · `showRag`, `showAgent`, `position` props.
|
|
761
|
-
|
|
762
|
-
---
|
|
763
|
-
|
|
764
|
-
## Configuration
|
|
765
|
-
|
|
766
|
-
```ts
|
|
767
|
-
|
|
768
|
-
import { wcagPlugin, A11yConfig } from "@yuktishaalaa/yuktai";
|
|
769
|
-
|
|
770
|
-
const config: A11yConfig = {
|
|
771
|
-
|
|
772
|
-
enabled: true, // required
|
|
773
|
-
|
|
774
|
-
highContrast: false,
|
|
775
|
-
|
|
776
|
-
darkMode: false,
|
|
777
|
-
|
|
778
|
-
reduceMotion: false,
|
|
779
|
-
|
|
780
|
-
largeTargets: false,
|
|
781
|
-
|
|
782
|
-
speechEnabled: false,
|
|
783
|
-
|
|
784
|
-
colorBlindMode: "none", // none | deuteranopia | protanopia | tritanopia | achromatopsia
|
|
785
|
-
|
|
786
|
-
autoFix: true,
|
|
787
|
-
|
|
788
|
-
showPreferencePanel: true,
|
|
789
|
-
|
|
790
|
-
showSkipLinks: true,
|
|
791
|
-
|
|
792
|
-
showAuditBadge: false, // dev only (localhost)
|
|
793
|
-
|
|
794
|
-
fontSizeMultiplier: 1,
|
|
795
|
-
|
|
796
|
-
timeoutWarning: 0, // seconds (0 = off)
|
|
797
|
-
|
|
798
|
-
};
|
|
799
|
-
|
|
800
|
-
await wcagPlugin.execute(config);
|
|
801
|
-
|
|
802
|
-
```
|
|
803
|
-
|
|
804
|
-
---
|
|
805
|
-
|
|
806
|
-
## WCAG coverage
|
|
807
|
-
|
|
808
|
-
| Standard | Criteria covered |
|
|
809
|
-
|
|
810
|
-
|---|---|
|
|
811
|
-
|
|
812
|
-
| WCAG 2.0 | 19 criteria |
|
|
813
|
-
|
|
814
|
-
| WCAG 2.1 | 7 criteria |
|
|
815
|
-
|
|
816
|
-
| WCAG 2.2 | 3 criteria (focus appearance, target size, timeout) |
|
|
817
|
-
|
|
818
|
-
| Beyond WCAG | SpeechSynthesis, visual alerts, keyboard cheatsheet, audit score, colour-blind modes, dyslexia font |
|
|
681
|
+
Props: `size` (default 20), `color` (default `currentColor`), `strokeWidth` (default 2.5), `label` (adds ARIA; decorative if omitted).
|
|
819
682
|
|
|
820
683
|
---
|
|
821
684
|
|
|
822
685
|
## Design principles
|
|
823
686
|
|
|
824
|
-
- **Zero
|
|
825
|
-
|
|
826
|
-
- **Zero
|
|
827
|
-
|
|
828
|
-
- **
|
|
829
|
-
|
|
830
|
-
- **Honest limits
|
|
687
|
+
- **Zero API keys, zero cost, zero telemetry.** Everything runs in the browser.
|
|
688
|
+
- **Zero injected ids.** Injected nodes are tracked by JavaScript references, so they never collide with your app's ids.
|
|
689
|
+
- **Zero framework lock-in.** `core/renderer.ts` has no framework imports.
|
|
690
|
+
- **Never reads its own UI.** Panels are marked with `data-yuktai-panel`.
|
|
691
|
+
- **SSR safe.** No `window` errors on the server.
|
|
692
|
+
- **Every automatic fix can be undone.** The v5.1 copilot records each change it makes.
|
|
693
|
+
- **Honest limits.** Client-side pagination is for a few thousand rows; use server-side beyond that.
|
|
831
694
|
|
|
832
695
|
---
|
|
833
696
|
|
|
834
697
|
## Compatibility
|
|
835
698
|
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
| Version | Supported |
|
|
839
|
-
|
|
699
|
+
| | Supported |
|
|
840
700
|
|---|---|
|
|
841
|
-
|
|
842
|
-
|
|
|
843
|
-
|
|
844
|
-
|
|
|
845
|
-
|
|
846
|
-
| Next.js 14 | ✅ |
|
|
847
|
-
|
|
848
|
-
| Next.js 13 | ✅ |
|
|
849
|
-
|
|
850
|
-
### React versions
|
|
851
|
-
|
|
852
|
-
| Version | Supported | Install flag |
|
|
853
|
-
|
|
854
|
-
|---|---|---|
|
|
855
|
-
|
|
856
|
-
| React 19 | ✅ | `--legacy-peer-deps` |
|
|
857
|
-
|
|
858
|
-
| React 18 | ✅ | none |
|
|
859
|
-
|
|
860
|
-
| React 17 | ✅ | none |
|
|
861
|
-
|
|
862
|
-
### Browsers
|
|
863
|
-
|
|
864
|
-
Chrome 90+ · Firefox 90+ · Safari 15+ · Edge 90+ · Samsung Internet 14+
|
|
701
|
+
| Next.js | 13, 14, 15, 16 |
|
|
702
|
+
| React | 17, 18, 19 (19 needs `--legacy-peer-deps`) |
|
|
703
|
+
| Node.js | 18+ |
|
|
704
|
+
| Browsers | Chrome 90+, Firefox 90+, Safari 15+, Edge 90+, Samsung Internet 14+ |
|
|
865
705
|
|
|
866
706
|
---
|
|
867
707
|
|
|
868
708
|
## Roadmap
|
|
869
709
|
|
|
870
|
-
Shipped
|
|
710
|
+
- **Shipped (v5.1):** Agentic AI Toolkit: accessibility copilot, QA reports, form and design review, smart grid queries, BI answers, multi-step tasks, page + data RAG, voice accessibility commands
|
|
711
|
+
- **Shipped (v4.6.4):** YuktaiGrid Agentic AI + WebMCP, embedded Grid AI Assistant, English/Telugu UI, page-size switching, icon polish
|
|
712
|
+
- **Next:** expose the v5.1 agentic tools through WebMCP, more Grid Agent tools, multilingual RAG (Telugu, Hindi, Tamil, Bengali)
|
|
713
|
+
- **Later:** RTL support, richer browser-native AI, multimodal grid experiences
|
|
714
|
+
|
|
715
|
+
---
|
|
871
716
|
|
|
872
|
-
|
|
717
|
+
## Contributing
|
|
873
718
|
|
|
874
|
-
|
|
719
|
+
Issues and pull requests are welcome at [github.com/sandeepmiriyala03/yuktai](https://github.com/sandeepmiriyala03/yuktai). For security issues, see [SECURITY.md](./SECURITY.md).
|
|
875
720
|
|
|
876
721
|
---
|
|
877
722
|
|
|
878
723
|
## Links
|
|
879
724
|
|
|
880
|
-
- npm
|
|
881
|
-
|
|
882
|
-
-
|
|
883
|
-
|
|
884
|
-
- Live demo — [aksharatantra.vercel.app](https://aksharatantra.vercel.app)
|
|
725
|
+
- npm: [@yuktishaalaa/yuktai](https://www.npmjs.com/package/@yuktishaalaa/yuktai)
|
|
726
|
+
- GitHub: [sandeepmiriyala03/yuktai](https://github.com/sandeepmiriyala03/yuktai)
|
|
727
|
+
- Demo: [aksharatantra.miriyala.in/staffdirectory](https://aksharatantra.miriyala.in/staffdirectory)
|
|
728
|
+
- Showcase: [ratnalabala.vercel.app](https://ratnalabala.vercel.app/poems?view=grid)
|
|
885
729
|
|
|
886
730
|
---
|
|
887
731
|
|
|
888
732
|
## License
|
|
889
733
|
|
|
890
|
-
ISC © Sandeep Miriyala
|
|
734
|
+
ISC © Sandeep Miriyala, [Yuktishaalaa AI Lab](https://github.com/sandeepmiriyala03)
|
|
891
735
|
|
|
892
|
-
Built in free time.
|
|
736
|
+
Built in free time. AI coding assistants (Claude, GPT and Gemini) helped me learn, and helped write and test parts of the code. Every design decision, review and release is mine.
|
|
893
737
|
|
|
894
|
-
Free forever. Open source.
|
|
738
|
+
**Free forever. Open source. Built for every user.** 🏺
|