@yuktishaalaa/yuktai 5.0.1 → 5.1.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 +361 -649
- 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 +7 -2
package/README.md
CHANGED
|
@@ -1,121 +1,93 @@
|
|
|
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, and an accessible data grid with Agentic AI + WebMCP
|
|
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, and an accessible data grid with Agentic AI + WebMCP. 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
|
+
**7,000+ developers** have already installed yuktai. Built entirely 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
|
-
Five modules ship in
|
|
31
|
+
Five 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 |
|
|
42
|
-
|
|
43
|
-
| **
|
|
44
|
-
|
|
45
|
-
| **3. In-Tab RAG** | 11 | Ask questions about any page — offline, no API |
|
|
46
|
-
|
|
47
|
-
| **4. Autonomous AI Agent** | 13 | Natural-language browser automation |
|
|
48
|
-
|
|
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 |
|
|
49
39
|
| **5. Vibe Coder** | 19 | Generate full Next.js projects from plain English |
|
|
50
40
|
|
|
51
|
-
Plus Grid Assistant capabilities, Grid Agent tools, WebMCP integration, 7 custom SVG icons, and a voice + chat assistant.
|
|
52
|
-
|
|
53
41
|
---
|
|
54
42
|
|
|
55
|
-
## What's new
|
|
56
|
-
|
|
57
|
-
### v4.6.4 — YuktaiGrid Agentic AI + WebMCP
|
|
58
|
-
|
|
59
|
-
YuktaiGrid now brings Grid UI, Grid AI Assistant, reusable Grid Tools, Agent execution, and WebMCP registration together.
|
|
60
|
-
|
|
61
|
-
- Shared Grid Tools for Agent and WebMCP execution
|
|
62
|
-
|
|
63
|
-
- Search grid rows
|
|
64
|
-
|
|
65
|
-
- Count grid rows
|
|
66
|
-
|
|
67
|
-
- Get grid columns
|
|
68
|
-
|
|
69
|
-
- Get a row by ID
|
|
70
|
-
|
|
71
|
-
- Highlight rows
|
|
72
|
-
|
|
73
|
-
- Select a row
|
|
74
|
-
|
|
75
|
-
- Open a row
|
|
76
|
-
|
|
77
|
-
- WebMCP registration through document.modelContext
|
|
78
|
-
|
|
79
|
-
- useYuktaiGridAgent for programmatic Grid tool execution
|
|
43
|
+
## What's new in v4.6.4: YuktaiGrid Agentic AI + WebMCP
|
|
80
44
|
|
|
45
|
+
- Shared Grid Tools used by both the Agent and WebMCP
|
|
46
|
+
- Tools: search, count, columns, get row, highlight, select, open
|
|
47
|
+
- WebMCP registration through `document.modelContext`
|
|
48
|
+
- `useYuktaiGridAgent` hook for programmatic tool execution
|
|
81
49
|
- Embedded Grid AI Assistant inside YuktaiGrid
|
|
50
|
+
- English and Telugu AI UI, with English or Telugu voice input
|
|
51
|
+
- Working page-size switching (10 → 20 → 50 → 100)
|
|
52
|
+
- Seven inline SVG icons, no external icon dependency
|
|
82
53
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
- English voice input by default with Telugu voice-input support
|
|
86
|
-
|
|
87
|
-
- language, inputLanguage, and embedded AI options
|
|
54
|
+
**Architecture:** User → Agent / WebMCP → Grid Tools → YuktaiGrid → Data
|
|
88
55
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
- Inline SVG Grid icons with no external icon dependency
|
|
92
|
-
|
|
93
|
-
- Public seven-icon package API
|
|
56
|
+
---
|
|
94
57
|
|
|
95
|
-
|
|
58
|
+
## Works on every device
|
|
96
59
|
|
|
97
|
-
|
|
60
|
+
| Device | Browser | Core features | AI engine |
|
|
61
|
+
|---|---|---|---|
|
|
62
|
+
| 🖥 Desktop | Chrome 147+ | ✅ All | Gemini Nano |
|
|
63
|
+
| 🖥 Desktop | Firefox / Edge / Safari | ✅ All | Transformers.js |
|
|
64
|
+
| 📱 Android | Chrome Mobile | ✅ All | Transformers.js |
|
|
65
|
+
| 📱 iOS | Safari Mobile | ✅ All | Transformers.js |
|
|
66
|
+
| 📲 PWA offline | All browsers | ✅ All | Offline after first load |
|
|
98
67
|
|
|
99
|
-
|
|
68
|
+
yuktai picks the best AI engine automatically. Users never need to know which one is running.
|
|
100
69
|
|
|
101
70
|
---
|
|
102
71
|
|
|
103
72
|
## Install
|
|
104
73
|
|
|
105
|
-
|
|
74
|
+
**Next.js 16 + React 19 (recommended)**
|
|
106
75
|
|
|
107
76
|
```bash
|
|
108
|
-
|
|
109
77
|
npm install @yuktishaalaa/yuktai --legacy-peer-deps
|
|
110
|
-
|
|
111
78
|
```
|
|
112
79
|
|
|
113
|
-
|
|
80
|
+
**Next.js 13, 14, 15**
|
|
114
81
|
|
|
115
82
|
```bash
|
|
116
|
-
|
|
117
83
|
npm install @yuktishaalaa/yuktai
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Yarn / pnpm**
|
|
118
87
|
|
|
88
|
+
```bash
|
|
89
|
+
yarn add @yuktishaalaa/yuktai
|
|
90
|
+
pnpm add @yuktishaalaa/yuktai
|
|
119
91
|
```
|
|
120
92
|
|
|
121
93
|
Requirements: Node.js 18+, npm 8+, Next.js 13+.
|
|
@@ -124,771 +96,511 @@ Requirements: Node.js 18+, npm 8+, Next.js 13+.
|
|
|
124
96
|
|
|
125
97
|
## Quick start
|
|
126
98
|
|
|
127
|
-
### Step 1
|
|
99
|
+
### Step 1: `next.config.js`
|
|
128
100
|
|
|
129
101
|
```js
|
|
130
|
-
|
|
131
102
|
const nextConfig = {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
103
|
+
transpilePackages: ["@yuktishaalaa/yuktai"],
|
|
104
|
+
async headers() {
|
|
105
|
+
return [
|
|
106
|
+
{
|
|
107
|
+
source: "/(.*)",
|
|
108
|
+
headers: [
|
|
109
|
+
// Needed for voice control and voice input
|
|
110
|
+
{ key: "Permissions-Policy", value: "microphone=*, speaker=*" },
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
];
|
|
114
|
+
},
|
|
135
115
|
};
|
|
136
116
|
|
|
137
117
|
module.exports = nextConfig;
|
|
138
|
-
|
|
139
118
|
```
|
|
140
119
|
|
|
141
|
-
### Step 2
|
|
120
|
+
### Step 2: Client wrapper
|
|
142
121
|
|
|
143
122
|
```tsx
|
|
144
|
-
|
|
145
123
|
// components/YuktaiClient.tsx
|
|
146
|
-
|
|
147
124
|
"use client";
|
|
148
125
|
|
|
149
126
|
import { useState, useEffect, type ReactNode } from "react";
|
|
150
|
-
|
|
151
127
|
import { YuktAIWrapper } from "@yuktishaalaa/yuktai";
|
|
152
128
|
|
|
153
129
|
export default function YuktaiClient({ children }: { children: ReactNode }) {
|
|
130
|
+
const [mounted, setMounted] = useState(false);
|
|
131
|
+
useEffect(() => setMounted(true), []);
|
|
154
132
|
|
|
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
|
-
);
|
|
133
|
+
if (!mounted) return <>{children}</>;
|
|
170
134
|
|
|
135
|
+
return (
|
|
136
|
+
<YuktAIWrapper position="left" showRag showAgent>
|
|
137
|
+
{children}
|
|
138
|
+
</YuktAIWrapper>
|
|
139
|
+
);
|
|
171
140
|
}
|
|
172
|
-
|
|
173
141
|
```
|
|
174
142
|
|
|
175
|
-
### Step 3
|
|
143
|
+
### Step 3: `app/layout.tsx`
|
|
176
144
|
|
|
177
145
|
```tsx
|
|
178
|
-
|
|
179
146
|
import YuktaiClient from "@/components/YuktaiClient";
|
|
180
147
|
|
|
181
148
|
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
|
-
|
|
149
|
+
return (
|
|
150
|
+
<html lang="en">
|
|
151
|
+
<body>
|
|
152
|
+
<YuktaiClient>
|
|
153
|
+
<main>{children}</main>
|
|
154
|
+
</YuktaiClient>
|
|
155
|
+
</body>
|
|
156
|
+
</html>
|
|
157
|
+
);
|
|
201
158
|
}
|
|
202
|
-
|
|
203
159
|
```
|
|
204
160
|
|
|
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`.
|
|
161
|
+
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
162
|
|
|
215
|
-
###
|
|
163
|
+
### Wrapper props
|
|
216
164
|
|
|
217
|
-
|
|
165
|
+
| Prop | Type | Default | Description |
|
|
166
|
+
|---|---|---|---|
|
|
167
|
+
| `position` | `"left" \| "right"` | `"left"` | Which side the buttons appear on |
|
|
168
|
+
| `showRag` | `boolean` | `false` | Show the 💬 Ask-this-page button |
|
|
169
|
+
| `showAgent` | `boolean` | `false` | Show the AI agent button |
|
|
170
|
+
| `config` | `Partial<A11yConfig>` | `undefined` | Accessibility config overrides |
|
|
171
|
+
| `children` | `ReactNode` | required | Your app content |
|
|
218
172
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
- Voice control — say commands to navigate
|
|
222
|
-
|
|
223
|
-
- High contrast · Dark mode · Reduce motion · Large targets (44×44)
|
|
224
|
-
|
|
225
|
-
- Colour-blind modes — Deuteranopia, Protanopia, Tritanopia, Greyscale
|
|
173
|
+
---
|
|
226
174
|
|
|
227
|
-
|
|
175
|
+
## Module 1: Accessibility Engine
|
|
228
176
|
|
|
229
|
-
|
|
177
|
+
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
178
|
|
|
231
|
-
|
|
179
|
+
**Features**
|
|
232
180
|
|
|
233
|
-
-
|
|
181
|
+
- WCAG 2.2 auto-fix: ARIA, roles, tabindex, scope, autocomplete, alt text
|
|
182
|
+
- Speak on focus using browser SpeechSynthesis
|
|
183
|
+
- Voice control using the SpeechRecognition API
|
|
184
|
+
- Visual alerts for deaf and hard-of-hearing users
|
|
185
|
+
- High contrast, dark mode, reduce motion, large targets (44×44)
|
|
186
|
+
- Colour-blind modes: Deuteranopia, Protanopia, Tritanopia, Greyscale
|
|
187
|
+
- Dyslexia font: Atkinson Hyperlegible
|
|
188
|
+
- Local font picker and font scaling from 80% to 130%
|
|
189
|
+
- Audit badge with a WCAG score from 0 to 100 (localhost only)
|
|
190
|
+
- Skip links, focus trap, saved preferences, reset
|
|
234
191
|
|
|
235
|
-
|
|
192
|
+
**Direct API**
|
|
236
193
|
|
|
237
194
|
```ts
|
|
195
|
+
import { wcagPlugin, type A11yConfig } from "@yuktishaalaa/yuktai";
|
|
238
196
|
|
|
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
|
-
});
|
|
197
|
+
const config: A11yConfig = {
|
|
198
|
+
enabled: true,
|
|
199
|
+
highContrast: false,
|
|
200
|
+
darkMode: false,
|
|
201
|
+
reduceMotion: false,
|
|
202
|
+
largeTargets: false,
|
|
203
|
+
speechEnabled: false,
|
|
204
|
+
colorBlindMode: "none", // none | deuteranopia | protanopia | tritanopia | achromatopsia
|
|
205
|
+
autoFix: true,
|
|
206
|
+
showPreferencePanel: true,
|
|
207
|
+
showSkipLinks: true,
|
|
208
|
+
showAuditBadge: false, // dev only (localhost)
|
|
209
|
+
fontSizeMultiplier: 1,
|
|
210
|
+
timeoutWarning: 0, // seconds, 0 = off
|
|
211
|
+
};
|
|
262
212
|
|
|
263
|
-
|
|
213
|
+
const report = wcagPlugin.applyFixes(config);
|
|
214
|
+
console.log(report.fixed); // number of fixes applied
|
|
215
|
+
console.log(report.score); // 0–100
|
|
216
|
+
```
|
|
264
217
|
|
|
265
|
-
|
|
218
|
+
### WCAG coverage
|
|
266
219
|
|
|
267
|
-
|
|
220
|
+
| Standard | Criteria | Examples |
|
|
221
|
+
|---|---|---|
|
|
222
|
+
| WCAG 2.0 | 19 | Alt text, roles, labels, tables, landmarks, focus |
|
|
223
|
+
| WCAG 2.1 | 7 | Touch targets, reflow, motion, orientation |
|
|
224
|
+
| WCAG 2.2 | 3 | Focus appearance, target size, timeout warning |
|
|
225
|
+
| Beyond WCAG | Extras | Speech, visual alerts, colour-blind modes, dyslexia font, audit score |
|
|
268
226
|
|
|
269
227
|
---
|
|
270
228
|
|
|
271
|
-
## Module 2
|
|
229
|
+
## Module 2: YuktaiGrid ⭐
|
|
272
230
|
|
|
273
|
-
An accessible data grid
|
|
231
|
+
An accessible data grid for Next.js, with an embedded AI assistant, agent tools, and WebMCP support.
|
|
274
232
|
|
|
275
|
-
###
|
|
233
|
+
### Basic usage
|
|
276
234
|
|
|
277
235
|
```tsx
|
|
278
|
-
|
|
279
236
|
"use client";
|
|
280
237
|
|
|
281
238
|
import { YuktaiGrid } from "@yuktishaalaa/yuktai";
|
|
282
239
|
|
|
283
240
|
const data = [
|
|
284
|
-
|
|
285
|
-
{ id:
|
|
286
|
-
|
|
287
|
-
{ id: 2, name: "Priya", role: "Designer", salary: 90000 },
|
|
288
|
-
|
|
241
|
+
{ id: 1, name: "Sandeep", role: "Developer", salary: 85000 },
|
|
242
|
+
{ id: 2, name: "Priya", role: "Designer", salary: 90000 },
|
|
289
243
|
];
|
|
290
244
|
|
|
291
245
|
export default function EmployeesPage() {
|
|
246
|
+
return (
|
|
247
|
+
<YuktaiGrid
|
|
248
|
+
data={data}
|
|
249
|
+
rowKey="id"
|
|
250
|
+
columns={[
|
|
251
|
+
{ key: "name", label: "Name", sortable: true },
|
|
252
|
+
{ key: "role", label: "Role" },
|
|
253
|
+
{ key: "salary", label: "Salary", type: "number", align: "right" },
|
|
254
|
+
]}
|
|
255
|
+
theme="default" // default | high-contrast | dark | color-blind | dyslexia
|
|
256
|
+
locale="en-US" // en-US | te-IN
|
|
257
|
+
view="auto" // auto | table | card
|
|
258
|
+
search
|
|
259
|
+
ai
|
|
260
|
+
pagination={{
|
|
261
|
+
pageSize: 20,
|
|
262
|
+
showSizeChanger: true,
|
|
263
|
+
sizeOptions: [10, 20, 50, 100],
|
|
264
|
+
}}
|
|
265
|
+
/>
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
```
|
|
292
269
|
|
|
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
|
|
270
|
+
### Grid features
|
|
314
271
|
|
|
315
|
-
|
|
272
|
+
- Real-time search, column sorting, client-side pagination with page-size switching
|
|
273
|
+
- Mobile card view below a configurable breakpoint
|
|
274
|
+
- Loading and empty states
|
|
275
|
+
- 5 WCAG themes
|
|
276
|
+
- Row selection, custom cell render, `rowKey`
|
|
277
|
+
- Row highlighting with optional auto-scroll
|
|
278
|
+
- Keyboard navigation, ARIA grid semantics, 44×44 targets
|
|
279
|
+
- English and Telugu UI
|
|
280
|
+
- Embedded Grid AI Assistant with voice and chat
|
|
316
281
|
|
|
317
|
-
|
|
282
|
+
### Grid AI Assistant
|
|
318
283
|
|
|
319
|
-
|
|
320
|
-
pageSize: 20,
|
|
321
|
-
showSizeChanger: true,
|
|
322
|
-
sizeOptions: [10, 20, 50, 100],
|
|
323
|
-
}}
|
|
284
|
+
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
285
|
|
|
286
|
+
```tsx
|
|
287
|
+
<YuktaiGridAI
|
|
288
|
+
data={data}
|
|
289
|
+
columns={columns}
|
|
290
|
+
onSearch={handleSearch}
|
|
291
|
+
onSort={handleSort}
|
|
292
|
+
language="te-IN" // AI UI and responses: en-US | te-IN
|
|
293
|
+
inputLanguage="te-IN" // voice input: en-US | te-IN
|
|
294
|
+
embedded
|
|
325
295
|
/>
|
|
326
|
-
|
|
327
|
-
);
|
|
328
|
-
|
|
329
|
-
}
|
|
330
|
-
|
|
331
296
|
```
|
|
332
297
|
|
|
333
|
-
|
|
298
|
+
Voice recognition depends on browser Web Speech API support.
|
|
334
299
|
|
|
335
|
-
|
|
300
|
+
### Agent tools
|
|
336
301
|
|
|
337
|
-
|
|
302
|
+
Generic, reusable grid operations shared by the Agent and WebMCP:
|
|
338
303
|
|
|
339
|
-
|
|
304
|
+
```ts
|
|
305
|
+
import {
|
|
306
|
+
searchGrid,
|
|
307
|
+
countGrid,
|
|
308
|
+
getColumns,
|
|
309
|
+
getRow,
|
|
310
|
+
highlightRows,
|
|
311
|
+
selectRow,
|
|
312
|
+
openRow,
|
|
313
|
+
} from "@yuktishaalaa/yuktai";
|
|
314
|
+
```
|
|
340
315
|
|
|
341
|
-
|
|
316
|
+
Run tools programmatically:
|
|
342
317
|
|
|
343
|
-
|
|
318
|
+
```tsx
|
|
319
|
+
import { useYuktaiGridAgent, type GridAgentTool } from "@yuktishaalaa/yuktai";
|
|
344
320
|
|
|
345
|
-
|
|
321
|
+
const tools: GridAgentTool[] = [
|
|
322
|
+
{
|
|
323
|
+
name: "search",
|
|
324
|
+
description: "Search grid rows by a text query",
|
|
325
|
+
execute: async ({ query }) => searchGrid(data, query),
|
|
326
|
+
},
|
|
327
|
+
];
|
|
346
328
|
|
|
347
|
-
|
|
329
|
+
const { executeTool, loading } = useYuktaiGridAgent({ tools });
|
|
330
|
+
```
|
|
348
331
|
|
|
349
|
-
|
|
332
|
+
**Design principle:** keep generic tools in the package and put app-specific rules in your app.
|
|
350
333
|
|
|
351
|
-
|
|
334
|
+
```text
|
|
335
|
+
Generic YuktAI tools + Your domain rules = Your application agent
|
|
336
|
+
```
|
|
352
337
|
|
|
353
|
-
|
|
338
|
+
### WebMCP
|
|
354
339
|
|
|
355
|
-
|
|
340
|
+
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.
|
|
341
|
+
|
|
342
|
+
```tsx
|
|
343
|
+
<YuktaiGrid
|
|
344
|
+
data={rows}
|
|
345
|
+
columns={columns}
|
|
346
|
+
ai
|
|
347
|
+
webmcp
|
|
348
|
+
toolName="my_grid"
|
|
349
|
+
toolDescriptions={TOOL_DESCRIPTIONS}
|
|
350
|
+
onWebMCPStatusChange={setStatus} // unsupported | registering | ready | partial | error
|
|
351
|
+
/>
|
|
352
|
+
```
|
|
356
353
|
|
|
357
|
-
|
|
354
|
+
Or standalone:
|
|
358
355
|
|
|
359
|
-
|
|
356
|
+
```tsx
|
|
357
|
+
<YuktaiGridWebMCP data={data} columns={columns} />
|
|
358
|
+
```
|
|
360
359
|
|
|
361
|
-
|
|
360
|
+
WebMCP is not available in every browser, so always handle the `unsupported` status gracefully.
|
|
362
361
|
|
|
363
|
-
|
|
362
|
+
### Large datasets (100K+ rows)
|
|
364
363
|
|
|
365
|
-
|
|
364
|
+
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
365
|
|
|
367
|
-
|
|
366
|
+
`src/app/api/employees/route.ts`:
|
|
368
367
|
|
|
369
368
|
```ts
|
|
370
|
-
|
|
371
369
|
import { NextRequest, NextResponse } from "next/server";
|
|
372
370
|
|
|
373
371
|
let cachedData: any[] | null = null;
|
|
374
|
-
|
|
375
372
|
let cacheTime = 0;
|
|
376
|
-
|
|
377
373
|
const TTL_MS = 60_000;
|
|
378
374
|
|
|
379
375
|
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
|
-
|
|
376
|
+
const now = Date.now();
|
|
377
|
+
if (cachedData && now - cacheTime < TTL_MS) return cachedData;
|
|
378
|
+
const res = await fetch("https://your-api.com/employees", { cache: "no-store" });
|
|
379
|
+
const json = await res.json();
|
|
380
|
+
cachedData = Array.isArray(json) ? json : json.employees ?? json.data ?? [];
|
|
381
|
+
cacheTime = now;
|
|
382
|
+
return cachedData;
|
|
395
383
|
}
|
|
396
384
|
|
|
397
385
|
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
|
-
|
|
386
|
+
const p = req.nextUrl.searchParams;
|
|
387
|
+
const page = Math.max(1, parseInt(p.get("page") || "1"));
|
|
388
|
+
const pageSize = Math.max(1, parseInt(p.get("pageSize") || "5000"));
|
|
389
|
+
const search = (p.get("search") || "").toLowerCase().trim();
|
|
390
|
+
|
|
391
|
+
const all = await fetchAll();
|
|
392
|
+
const filtered = search
|
|
393
|
+
? all.filter((r) => Object.values(r).some((v) => String(v).toLowerCase().includes(search)))
|
|
394
|
+
: all;
|
|
395
|
+
|
|
396
|
+
const total = filtered.length;
|
|
397
|
+
const rows = filtered.slice((page - 1) * pageSize, page * pageSize);
|
|
398
|
+
|
|
399
|
+
return NextResponse.json({
|
|
400
|
+
rows,
|
|
401
|
+
pagination: { page, pageSize, totalRows: total, totalPages: Math.ceil(total / pageSize) },
|
|
402
|
+
});
|
|
427
403
|
}
|
|
428
|
-
|
|
429
404
|
```
|
|
430
405
|
|
|
431
|
-
|
|
406
|
+
Page:
|
|
432
407
|
|
|
433
408
|
```tsx
|
|
434
|
-
|
|
435
|
-
const [
|
|
436
|
-
|
|
437
|
-
const [currentPage, setPage] = useState(1);
|
|
409
|
+
const [apiResp, setApiResp] = useState<any>(null);
|
|
410
|
+
const [currentPage, setPage] = useState(1);
|
|
438
411
|
|
|
439
412
|
useEffect(() => {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
.then(r => r.json())
|
|
444
|
-
|
|
445
|
-
.then(setApiResp);
|
|
446
|
-
|
|
413
|
+
fetch(`/api/employees?page=${currentPage}&pageSize=5000`)
|
|
414
|
+
.then((r) => r.json())
|
|
415
|
+
.then(setApiResp);
|
|
447
416
|
}, [currentPage]);
|
|
448
417
|
|
|
449
418
|
<YuktaiGrid
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
pagination={false} // disable — we handle pagination server-side
|
|
458
|
-
|
|
459
|
-
loading={!apiResp}
|
|
460
|
-
|
|
461
|
-
/>
|
|
462
|
-
|
|
419
|
+
data={apiResp?.rows ?? []}
|
|
420
|
+
columns={columns}
|
|
421
|
+
search={false} // handled server-side
|
|
422
|
+
pagination={false} // handled server-side
|
|
423
|
+
loading={!apiResp}
|
|
424
|
+
/>;
|
|
463
425
|
```
|
|
464
426
|
|
|
465
|
-
|
|
427
|
+
Render your own pagination bar from `apiResp.pagination`. The browser only ever holds one page in memory.
|
|
466
428
|
|
|
467
429
|
---
|
|
468
430
|
|
|
469
|
-
|
|
431
|
+
## Showcase: Ratnalabala (Telugu poetry)
|
|
470
432
|
|
|
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";
|
|
524
|
-
|
|
525
|
-
<YuktaiGridWebMCP
|
|
526
|
-
data={data}
|
|
527
|
-
columns={columns}
|
|
528
|
-
/>
|
|
433
|
+
[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
434
|
|
|
435
|
+
| User says | Agent action |
|
|
436
|
+
|---|---|
|
|
437
|
+
| `ఎన్ని పద్యాలు` (how many poems) | `count` → "మొత్తం 36 పద్యాలు ఉన్నాయి." |
|
|
438
|
+
| `గర్వం తెరువు` (open "Garvam") | `open` |
|
|
439
|
+
| `"బుద్ధి" ఉన్న పద్యాలు` (poems with "buddhi") | `search` + highlight |
|
|
440
|
+
| `అక్షర క్రమంలో` (alphabetical) | `sort(title, asc)` |
|
|
441
|
+
| `ఈరోజు పద్యం` (poem of the day) | custom rule + highlight |
|
|
442
|
+
|
|
443
|
+
**Stack:** Next.js · React + TypeScript · MUI · YuktAI Grid · FastAPI (Python) · PostgreSQL on Neon · Vercel · Web Speech API · WebMCP
|
|
444
|
+
|
|
445
|
+
```text
|
|
446
|
+
PostgreSQL → FastAPI → Next.js API proxy → Ratnalabala UI → YuktAI Grid
|
|
447
|
+
├── Agent
|
|
448
|
+
└── WebMCP
|
|
530
449
|
```
|
|
531
450
|
|
|
532
|
-
WebMCP registration is invisible in the UI and uses document.modelContext when available.
|
|
533
|
-
|
|
534
|
-
### Embedded Grid AI Assistant
|
|
535
|
-
|
|
536
451
|
```tsx
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
locale="te-IN"
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
}
|
|
452
|
+
<YuktaiGrid<PoemRow>
|
|
453
|
+
data={rows}
|
|
454
|
+
columns={COLUMNS}
|
|
455
|
+
rowKey="id"
|
|
456
|
+
locale="te-IN"
|
|
457
|
+
inputLanguage="te-IN"
|
|
458
|
+
customRules={POEM_RULES}
|
|
459
|
+
search
|
|
460
|
+
highlightIds={highlightIds}
|
|
461
|
+
autoScrollToHighlight
|
|
462
|
+
onRowClick={(row) => onOpenPoem(row.title)}
|
|
463
|
+
ai
|
|
464
|
+
webmcp
|
|
465
|
+
toolName="ratnalabala_poems"
|
|
466
|
+
toolDescriptions={TOOL_DESCRIPTIONS}
|
|
467
|
+
onWebMCPStatusChange={setWebmcp}
|
|
548
468
|
/>
|
|
549
|
-
|
|
550
469
|
```
|
|
551
470
|
|
|
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
471
|
---
|
|
563
472
|
|
|
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)
|
|
473
|
+
## Module 3: In-Tab RAG (Ask This Page)
|
|
569
474
|
|
|
570
|
-
-
|
|
475
|
+
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.
|
|
571
476
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
- Auto engine detection and switching
|
|
577
|
-
|
|
578
|
-
- Works offline after first load
|
|
579
|
-
|
|
580
|
-
- q4 quantization on mobile (32-bit → 4-bit weights)
|
|
581
|
-
|
|
582
|
-
- `flan-t5-small` for full-sentence answers
|
|
583
|
-
|
|
584
|
-
- Cosine similarity semantic search
|
|
585
|
-
|
|
586
|
-
- Deduped DOM text extraction
|
|
477
|
+
| Device | Engine | How it works |
|
|
478
|
+
|---|---|---|
|
|
479
|
+
| Desktop Chrome with Gemini Nano | `window.LanguageModel` | Page text sent as context, instant answer |
|
|
480
|
+
| Mobile and all other browsers | Transformers.js | Embeddings + `flan-t5-small`, q4 quantized |
|
|
587
481
|
|
|
588
|
-
|
|
482
|
+
- About 30 MB one-time model download on mobile, cached in IndexedDB
|
|
483
|
+
- Works fully offline after first load
|
|
484
|
+
- All processing on device, no data sent anywhere
|
|
589
485
|
|
|
590
|
-
|
|
486
|
+
**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.
|
|
591
487
|
|
|
592
488
|
---
|
|
593
489
|
|
|
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.
|
|
597
|
-
|
|
598
|
-
### Features (13)
|
|
599
|
-
|
|
600
|
-
- Plain-English goal input
|
|
490
|
+
## Module 4: Autonomous AI Agent
|
|
601
491
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
- Scans all form fields — 11 label strategies
|
|
492
|
+
Type a goal in plain English. yuktai reads the page, finds the right elements, plans the steps, and highlights what to do.
|
|
605
493
|
|
|
494
|
+
- 9 DOM traversal strategies and 11 form-label strategies
|
|
606
495
|
- Works on static HTML, React, WordPress, and old government portals
|
|
496
|
+
- Gemini Nano planning on desktop, Transformers.js on mobile, rule-based fallback
|
|
497
|
+
- Highlights target fields, scrolls to sections, shows a numbered plan, handles iframes
|
|
607
498
|
|
|
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.
|
|
499
|
+
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
500
|
|
|
622
501
|
---
|
|
623
502
|
|
|
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)
|
|
503
|
+
## Module 5: Vibe Coder
|
|
629
504
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
- Detects theme colour (8), extracts site name
|
|
505
|
+
Type a business requirement and download a full Next.js 16 project as a ZIP.
|
|
633
506
|
|
|
507
|
+
- Detects website type (12), pages (21), features (14), theme colour (8), and site name
|
|
634
508
|
- Preview before generating
|
|
509
|
+
- TypeScript, Tailwind + CSS Modules, mobile responsive
|
|
510
|
+
- Navbar, Footer, Home, About, Contact, Services, Pricing, Auth, Dashboard
|
|
511
|
+
- `npm run dev` works immediately
|
|
635
512
|
|
|
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.
|
|
513
|
+
No AI writes the code. It's pure template engineering.
|
|
645
514
|
|
|
646
515
|
---
|
|
647
516
|
|
|
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
|
|
661
|
-
|
|
662
|
-
- Highest / maximum
|
|
663
|
-
|
|
664
|
-
- Lowest / minimum
|
|
517
|
+
## Gemini Nano setup (desktop Chrome, one time)
|
|
665
518
|
|
|
666
|
-
|
|
519
|
+
Needed only for Gemini Nano features on desktop Chrome. Mobile and other browsers use Transformers.js automatically.
|
|
667
520
|
|
|
668
|
-
|
|
521
|
+
1. Open `chrome://flags` and enable: Prompt API for Gemini Nano, Summarization API, Writer API, Rewriter API, Translation API.
|
|
522
|
+
2. Click **Relaunch**.
|
|
523
|
+
3. Open `chrome://components`, find **Optimization Guide On Device Model**, and click **Check for update**.
|
|
524
|
+
4. Refresh your page. AI features unlock automatically.
|
|
669
525
|
|
|
670
|
-
-
|
|
671
|
-
|
|
672
|
-
- English and Telugu AI UI
|
|
673
|
-
|
|
674
|
-
- English voice input by default
|
|
675
|
-
|
|
676
|
-
- Telugu voice input with inputLanguage="te-IN"
|
|
677
|
-
|
|
678
|
-
Example:
|
|
679
|
-
|
|
680
|
-
```tsx
|
|
681
|
-
|
|
682
|
-
<YuktaiGridAI
|
|
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
|
-
```
|
|
526
|
+
**Gemini Nano features:** plain-English rewriting, 3-sentence page summary, AI-generated ARIA labels, page translation in 18 languages.
|
|
693
527
|
|
|
694
|
-
|
|
528
|
+
> Chrome 147 moved the APIs from `window.ai` to standalone globals such as `window.LanguageModel`. yuktai supports both.
|
|
695
529
|
|
|
696
530
|
---
|
|
697
531
|
|
|
698
|
-
##
|
|
532
|
+
## Icons
|
|
699
533
|
|
|
700
|
-
|
|
534
|
+
Seven custom SVG icons with no external dependency.
|
|
701
535
|
|
|
702
536
|
```tsx
|
|
703
|
-
|
|
704
537
|
import {
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
ChevronLeftIcon,
|
|
713
|
-
|
|
714
|
-
ChevronRightIcon,
|
|
715
|
-
|
|
716
|
-
CheckIcon,
|
|
717
|
-
|
|
718
|
-
CloseIcon,
|
|
719
|
-
|
|
538
|
+
SearchIcon,
|
|
539
|
+
SortUpIcon,
|
|
540
|
+
SortDownIcon,
|
|
541
|
+
ChevronLeftIcon,
|
|
542
|
+
ChevronRightIcon,
|
|
543
|
+
CheckIcon,
|
|
544
|
+
CloseIcon,
|
|
720
545
|
} from "@yuktishaalaa/yuktai";
|
|
721
546
|
|
|
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
|
-
|
|
734
|
-
```
|
|
735
|
-
|
|
736
|
-
Props: `size` (default 20), `color` (default `currentColor`), `strokeWidth` (default 2.5), `label` (adds ARIA — decorative if omitted).
|
|
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
|
-
|
|
547
|
+
<SearchIcon size={20} />
|
|
548
|
+
<CheckIcon size={20} color="#10b981" label="Task complete" />
|
|
802
549
|
```
|
|
803
550
|
|
|
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 |
|
|
551
|
+
Props: `size` (default 20), `color` (default `currentColor`), `strokeWidth` (default 2.5), `label` (adds ARIA; decorative if omitted).
|
|
819
552
|
|
|
820
553
|
---
|
|
821
554
|
|
|
822
555
|
## Design principles
|
|
823
556
|
|
|
824
|
-
- **Zero
|
|
825
|
-
|
|
826
|
-
- **Zero
|
|
827
|
-
|
|
828
|
-
- **
|
|
829
|
-
|
|
830
|
-
- **Honest limits** — client-side grid pagination works for a few thousand rows. Beyond that, use server-side pagination (pattern shown above).
|
|
557
|
+
- **Zero API keys, zero cost, zero telemetry.** Everything runs in the browser.
|
|
558
|
+
- **Zero injected ids.** Injected nodes are tracked by JavaScript references, so they never collide with your app's ids.
|
|
559
|
+
- **Zero framework lock-in.** `core/renderer.ts` has no framework imports.
|
|
560
|
+
- **Never reads its own UI.** Panels are marked with `data-yuktai-panel`.
|
|
561
|
+
- **SSR safe.** No `window` errors on the server.
|
|
562
|
+
- **Honest limits.** Client-side pagination is for a few thousand rows; use server-side beyond that.
|
|
831
563
|
|
|
832
564
|
---
|
|
833
565
|
|
|
834
566
|
## Compatibility
|
|
835
567
|
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
| Version | Supported |
|
|
839
|
-
|
|
568
|
+
| | Supported |
|
|
840
569
|
|---|---|
|
|
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+
|
|
570
|
+
| Next.js | 13, 14, 15, 16 |
|
|
571
|
+
| React | 17, 18, 19 (19 needs `--legacy-peer-deps`) |
|
|
572
|
+
| Node.js | 18+ |
|
|
573
|
+
| Browsers | Chrome 90+, Firefox 90+, Safari 15+, Edge 90+, Samsung Internet 14+ |
|
|
865
574
|
|
|
866
575
|
---
|
|
867
576
|
|
|
868
577
|
## Roadmap
|
|
869
578
|
|
|
870
|
-
Shipped
|
|
579
|
+
- **Shipped (v4.6.4):** YuktaiGrid Agentic AI + WebMCP, embedded Grid AI Assistant, English/Telugu UI, page-size switching, icon polish
|
|
580
|
+
- **Next:** more Grid Agent tools and WebMCP capabilities, multilingual RAG (Telugu, Hindi, Tamil, Bengali)
|
|
581
|
+
- **Later:** RTL support, richer browser-native AI, multimodal grid experiences
|
|
582
|
+
|
|
583
|
+
---
|
|
871
584
|
|
|
872
|
-
|
|
585
|
+
## Contributing
|
|
873
586
|
|
|
874
|
-
|
|
587
|
+
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
588
|
|
|
876
589
|
---
|
|
877
590
|
|
|
878
591
|
## Links
|
|
879
592
|
|
|
880
|
-
- npm
|
|
881
|
-
|
|
882
|
-
-
|
|
883
|
-
|
|
884
|
-
- Live demo — [aksharatantra.vercel.app](https://aksharatantra.vercel.app)
|
|
593
|
+
- npm: [@yuktishaalaa/yuktai](https://www.npmjs.com/package/@yuktishaalaa/yuktai)
|
|
594
|
+
- GitHub: [sandeepmiriyala03/yuktai](https://github.com/sandeepmiriyala03/yuktai)
|
|
595
|
+
- Demo: [aksharatantra.miriyala.in/staffdirectory](https://aksharatantra.miriyala.in/staffdirectory)
|
|
596
|
+
- Showcase: [ratnalabala.vercel.app](https://ratnalabala.vercel.app/poems?view=grid)
|
|
885
597
|
|
|
886
598
|
---
|
|
887
599
|
|
|
888
600
|
## License
|
|
889
601
|
|
|
890
|
-
ISC © Sandeep Miriyala
|
|
602
|
+
ISC © Sandeep Miriyala, [Yuktishaalaa AI Lab](https://github.com/sandeepmiriyala03)
|
|
891
603
|
|
|
892
|
-
Built in free time
|
|
604
|
+
Built in free time, with help from Claude, GPT, and Gemini for learning. Every line written, every bug fixed, and every decision made by me.
|
|
893
605
|
|
|
894
|
-
Free forever. Open source.
|
|
606
|
+
**Free forever. Open source. Built for every user.** 🏺
|