apexgrid-skill 2.1.0 → 2.1.1

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/.cursorrules ADDED
@@ -0,0 +1,283 @@
1
+ # Apex Grid — AI Coding Rules
2
+
3
+ You are working with `apex-grid`, a Lit-based web-component data grid by ApexCharts.
4
+ Documentation: https://github.com/apexcharts/apexgrid
5
+ NPM: apex-grid (with a hyphen — no `apexgrid` package exists)
6
+ GitHub: https://github.com/apexcharts/apexgrid
7
+ Confirmed versions: apex-grid@3.0.1, lit@^3.0.0
8
+
9
+ ## Quickstart — register + size the host
10
+
11
+ The grid styles itself out of the box — there is **no theme CSS to import**.
12
+ The one real gotcha is host sizing: it virtualizes rows and needs a bounded
13
+ height or it collapses and renders nothing. `setup()` handles both.
14
+
15
+ ### 1. Install
16
+ ```bash
17
+ npm install apex-grid lit
18
+ ```
19
+ `igniteui-webcomponents` installs transitively — you do NOT import theme CSS from it.
20
+
21
+ ### 2. Register + size — `setup()` does both
22
+ ```ts
23
+ import { setup } from 'apex-grid';
24
+ setup(); // registers <apex-grid> + adopts host sizing. Idempotent.
25
+ ```
26
+ Manual alternative: `import 'apex-grid/define'` (or `ApexGrid.register()`) plus your own
27
+ `apex-grid { height: 480px; }`. `setup({ hostStyles: false })` skips the injected sizing.
28
+
29
+ ### 3. Style via `--ag-*` CSS variables (no theme import)
30
+ The grid is styled out of the box; retheme by overriding `--ag-*` custom properties on
31
+ `apex-grid`. The deprecated `theme` option / `configureTheme()` does NOT affect appearance.
32
+ ```css
33
+ apex-grid { height: 480px; /* + any --ag-* overrides */ }
34
+ ```
35
+
36
+ ### Minimal example
37
+
38
+ ```ts
39
+ import { html, render } from 'lit';
40
+ import { setup } from 'apex-grid';
41
+ import type { ColumnConfiguration } from 'apex-grid';
42
+
43
+ setup(); // register + host sizing; no theme import needed
44
+
45
+ type User = { id: number; name: string; age: number; subscribed: boolean };
46
+
47
+ const data: User[] = [
48
+ { id: 1, name: 'Ada Lovelace', age: 36, subscribed: true },
49
+ { id: 2, name: 'Carl Sagan', age: 62, subscribed: false },
50
+ ];
51
+
52
+ // Explicit widths prevent the last-column-stretches trap.
53
+ const columns: ColumnConfiguration<User>[] = [
54
+ { key: 'id', type: 'number', width: '80px', sort: true, filter: true },
55
+ { key: 'name', type: 'string', width: '240px', sort: true, filter: true },
56
+ { key: 'age', type: 'number', width: '100px', sort: true, filter: true },
57
+ { key: 'subscribed', type: 'boolean', width: '140px', sort: true, filter: true },
58
+ ];
59
+
60
+ render(
61
+ html`<apex-grid .data=${data} .columns=${columns}></apex-grid>`,
62
+ document.getElementById('app')!,
63
+ );
64
+ ```
65
+
66
+ ### What success looks like
67
+
68
+ - Visible borders between rows and columns
69
+ - Sort arrows (↕) next to each column header
70
+ - A filter row below the headers with a "Filter" chip per column
71
+ - Hover state on rows
72
+ - Smooth scrolling; only ~20 `<apex-grid-row>` in the DOM at any time
73
+
74
+ ---
75
+
76
+ ## Naming
77
+
78
+ | Form | What it is |
79
+ |---|---|
80
+ | `apex-grid` | npm package name (with hyphen) |
81
+ | `<apex-grid>` | the custom-element tag rendered in the DOM |
82
+ | `ApexGrid<T>` | the exported class — used for types and `ApexGrid.register()` |
83
+
84
+ ---
85
+
86
+ ## Critical Rules
87
+
88
+ 1. **Apex Grid is a Lit web component, not a JS class.** Don't `new ApexGrid(...)`. Render `<apex-grid>` and set `.data` / `.columns` as properties.
89
+ 2. **Two setup steps:** register the element and give the host a bounded height — `setup()` does both. **No theme CSS import is needed** (the grid self-styles via `--ag-*`).
90
+ 3. **`columns` and `data` are properties, not attributes.** Use property binding.
91
+ 4. **`column.key` must be a real `keyof T`.** No aliases. Compute derived values in `cellTemplate`.
92
+ 5. **Set `type` per column.** Primitive `'string'`/`'number'`/`'boolean'` drive sort/filter/editing (default `'string'`). Presentation types also exist: `'select'`, `'rating'`, `'date'`, `'image'`, `'currency'`, `'avatar'`, `'badge'`, `'progress'`, `'sparkline'`, `'status'`.
93
+ 6. **`cellTemplate` and `headerTemplate` must return Lit `TemplateResult`s** (`html\`...\``). Strings render as escaped text.
94
+ 7. **Sort/filter events fire only for UI-initiated operations.** Programmatic `grid.sort(...)` / `grid.filter(...)` are silent.
95
+
96
+ ---
97
+
98
+ ## Column Configuration
99
+
100
+ ```ts
101
+ interface ColumnConfiguration<T, K extends keyof T> {
102
+ key: K; // REQUIRED
103
+ type?: DataType; // default 'string' (13 types — see rule 5)
104
+ headerText?: string; // default: String(key)
105
+ width?: string; // CSS — recommended
106
+ hidden?: boolean;
107
+ resizable?: boolean;
108
+ pinned?: 'start' | 'end' | null; // freeze during horizontal scroll
109
+ reorderable?: boolean; // per-column opt-out of drag reorder
110
+ exportable?: boolean; // default true
111
+ editable?: boolean; // requires grid editing.enabled
112
+ group?: string; // id of a columnGroups spanning header
113
+ validators?: Validator<T, K>[]; // edit-time validation (3.2+)
114
+ sort?: boolean | { caseSensitive?, comparer? };
115
+ filter?: boolean | { caseSensitive? };
116
+ headerTemplate?: (ctx) => TemplateResult;
117
+ cellTemplate?: (ctx) => TemplateResult;
118
+ editorTemplate?: (ctx) => TemplateResult;
119
+ // type-specific: options ('select'), max ('rating'/'progress'), format ('date'),
120
+ // shape/alt ('image'), currency/locale ('currency'), badgeVariant, statusVariant, showDelta
121
+ }
122
+ ```
123
+
124
+ Applied defaults: `{ type: 'string', resizable: false, hidden: false, sort: false, filter: false, exportable: true }`.
125
+
126
+ ### Templates
127
+
128
+ ```ts
129
+ import { html } from 'lit';
130
+
131
+ cellTemplate: ({ value, row, parent, column }) =>
132
+ html`<strong>${value}</strong>`,
133
+ ```
134
+
135
+ ### Auto-generation — 3-line demo
136
+
137
+ ```ts
138
+ render(html`<apex-grid auto-generate .data=${data}></apex-grid>`, root);
139
+ // Ignored if `columns` is non-empty. Reset grid.columns = [] before swapping data.
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Filter Operands
145
+
146
+ | Type | Operands |
147
+ |---|---|
148
+ | `'string'` | `contains`, `doesNotContain`, `startsWith`, `endsWith`, `equals`, `doesNotEqual`, `empty`, `notEmpty` |
149
+ | `'number'` | `equals`, `doesNotEqual`, `greaterThan`, `lessThan`, `greaterThanOrEqual`, `lessThanOrEqual`, `empty`, `notEmpty` |
150
+ | `'boolean'` | `all`, `true`, `false`, `empty`, `notEmpty` (all unary — no `searchTerm`) |
151
+
152
+ ```ts
153
+ import { StringOperands, NumberOperands, BooleanOperands } from 'apex-grid';
154
+ grid.filter({ key: 'name', condition: 'contains', searchTerm: 'ad' });
155
+ grid.filter({ key: 'subscribed', condition: 'true' }); // unary
156
+ grid.filter([
157
+ { key: 'age', condition: 'greaterThan', searchTerm: 30 },
158
+ { key: 'age', condition: 'lessThan', searchTerm: 50, criteria: 'and' },
159
+ ]);
160
+ ```
161
+
162
+ ---
163
+
164
+ ## API
165
+
166
+ | Property | Type | Notes |
167
+ |---|---|---|
168
+ | `data` | `T[]` | |
169
+ | `columns` | `ColumnConfiguration<T>[]` | |
170
+ | `autoGenerate` | `boolean` | Ignored if `columns` non-empty |
171
+ | `sortConfiguration` | `{ multiple, triState }` | Multi-column + tri-state toggles |
172
+ | `dataPipelineConfiguration` | `{ sort?, filter?, pagination?, quickFilter? }` | Server-side hooks |
173
+ | `selection` / `editing` / `pagination` / `tree` / `expansion` | config objects | Opt-in: `{ enabled, ... }` (see SKILL.md §5) |
174
+ | `quickFilter` / `columnReordering` | `string` / `boolean` | Global search / drag-reorder headers |
175
+ | `sortExpressions` / `filterExpressions` | array (get/set) | To clear, use `clearSort()` / `clearFilter()` |
176
+ | `selectedRows` / `expandedRows` | `T[]` (get/set) | Snapshots; set to replace |
177
+ | `rows` (getter) | `ApexGridRow<T>[]` | Currently rendered only (virtualized) |
178
+ | `dataView` / `pageItems` (getters) | `readonly T[]` | Full post-filter/sort / current page |
179
+ | `totalItems` / `pageCount` (getters) | `number` | |
180
+
181
+ | Method | Description |
182
+ |---|---|
183
+ | `sort(expr \| expr[])` | Programmatic. **No events.** |
184
+ | `filter(expr \| expr[])` | Programmatic. **No events.** |
185
+ | `clearSort(key?)` / `clearFilter(key?)` | Reset state. |
186
+ | `getColumn(keyOrIndex)` / `updateColumns(col \| col[])` | Find / merge columns by `key`. |
187
+ | `moveColumn(from, to, position?)` | Reorder within pinning group. |
188
+ | `exportToCSV(opts?)` / `exportAs(formatId, opts?)` | Export data (CSV built in). |
189
+ | `selectRow`/`deselectRow`/`selectAllRows`/`clearSelection`/`isRowSelected` | Selection. |
190
+ | `expandRow`/`collapseRow`/`isRowExpanded` (+ `…TreeRow` variants) | Expansion / tree. |
191
+ | `commitEdit()` / `cancelEdit()` | Row-edit batch (`editing.mode: 'row'`). |
192
+ | `ApexGrid.register()` | Static; idempotent. |
193
+
194
+ Events are **UI-initiated only** (programmatic calls are silent). `*-ing` events are
195
+ cancellable (`preventDefault()`); `*-ed` are notifications. Pairs:
196
+ `sorting/sorted`, `filtering/filtered`, `quickFilterChanging/Changed`, `pageChanging/Changed`,
197
+ `columnPinning/Pinned`, `columnMoving/Moved`, `cellValueChanging/Changed`,
198
+ `rowEditStarted/Ended`, `rowSelecting/Selected`, `rowExpanding/Expanded`, `treeRowExpanding/Expanded`.
199
+
200
+ ---
201
+
202
+ ## Server-side data
203
+
204
+ ```ts
205
+ grid.dataPipelineConfiguration = {
206
+ filter: async ({ data, grid }) =>
207
+ fetch('/api/users/filter', {
208
+ method: 'POST',
209
+ body: JSON.stringify(grid.filterExpressions),
210
+ }).then((r) => r.json()),
211
+ };
212
+ ```
213
+
214
+ Built-in pipeline is skipped for whichever operations have a hook. Omit one to keep it in-memory. Hooks fire for both UI and programmatic operations.
215
+
216
+ ---
217
+
218
+ ## Pitfalls — ❌ Wrong vs ✅ Correct
219
+
220
+ ### 1. `new ApexGrid(...)`
221
+ ❌ `new ApexGrid({ container, columns, data })`
222
+ ✅ Render `<apex-grid .data=${data} .columns=${columns}></apex-grid>`
223
+
224
+ ### 2. Missing registration
225
+ ❌ Importing `ApexGrid` without `register()` — `<apex-grid>` is inert.
226
+ ✅ `import 'apex-grid/define'` once at startup.
227
+
228
+ ### 3. Importing a theme CSS that no longer exists
229
+ ❌ `import 'igniteui-webcomponents/themes/.../bootstrap.css'` + `configureTheme(...)` — obsolete; no effect.
230
+ ✅ No import needed — grid self-styles; retheme via `--ag-*`. The only required CSS is host height.
231
+
232
+ ### 4. Stringified attribute
233
+ ❌ `<apex-grid columns="[...]">`
234
+ ✅ `.columns=${columns}` / `:columns.prop=` / `[columns]=` / `el.columns = ...`
235
+
236
+ ### 5. `column.key` not a `keyof T`
237
+ ❌ `{ key: 'fullName' }` when not in `T`
238
+ ✅ `cellTemplate: ({ row }) => html\`${row.firstName} ${row.lastName}\``
239
+
240
+ ### 6. String from `cellTemplate`
241
+ ❌ `cellTemplate: ({ value }) => \`<b>\${value}</b>\``
242
+ ✅ `cellTemplate: ({ value }) => html\`<b>\${value}</b>\``
243
+
244
+ ### 7. Numbers sorted as strings
245
+ ❌ `{ key: 'age', sort: true }` (default `type: 'string'`)
246
+ ✅ `{ key: 'age', type: 'number', sort: true }`
247
+
248
+ ### 8. Faking date columns
249
+ ❌ `type: 'number'` timestamps or string + custom comparer to handle dates.
250
+ ✅ `{ key: 'created', type: 'date', format: 'medium' }` — real type; accepts Date/ISO/timestamp.
251
+
252
+ ### 9. Clearing sort/filter
253
+ ❌ Rebuilding state by hand to clear it.
254
+ ✅ `grid.clearSort()` / `grid.clearFilter()` (optionally per `key`).
255
+
256
+ ### 10. Expecting events from programmatic calls
257
+ ❌ `grid.addEventListener('sorted'); grid.sort(...)` — silent.
258
+ ✅ Wrap the call yourself, or watch `grid.dataView`.
259
+
260
+ ### 11. Wrong package name
261
+ ❌ `import ... from 'apexgrid'` — no such package.
262
+ ✅ `import ... from 'apex-grid'`.
263
+
264
+ ---
265
+
266
+ ## New in 3.1–3.3
267
+
268
+ - **Row pinning**: `rowPinning = { enabled }`, `pinRow(row, 'top'|'bottom')`/`unpinRow(row)`, `pinnedRows` getter, `rowPinning`/`rowPinned` events.
269
+ - **Row reordering**: `rowReordering = { enabled, applyToData?, handle? }`, `moveRow(from, to, position?)`, `rowMoving`/`rowMoved` events (clears on sort).
270
+ - **Inline-edit undo/redo**: `editing.history = { enabled, stackSize? }`, `undo()`/`redo()`/`clearHistory()`, `canUndo`/`canRedo`, `historyChanged` event.
271
+ - **Validators**: `column.validators: Validator[]` + `required`/`min`/`max`/`pattern`/`custom` factories, `cellValidationFailed` event.
272
+ - **Column groups**: `columnGroups = [{ id, headerText }]` + `column.group` (members contiguous within a pin region).
273
+ - **State/schema**: `getState()`/`setState()`/`getSchema()`, `rowId`, `stateChanged` event (`setState` is partial + defensive).
274
+ - **Programmatic (these DO emit events, unlike sort/filter)**: `gotoPage`/`nextPage`/`setPageSize`/…, `setQuickFilter()`, `pinColumn`/`unpinColumn`.
275
+ - **Localization**: `localeText` (`GridLocaleText`), `localize()`, `esLocale` export.
276
+ - **Misc**: `columnMenu`/`columnSeparator`; `exportToCSV`/`exportAs` `source: 'view'|'page'|'selected'|'all'`.
277
+ - Full detail: `references/state-and-features.md`.
278
+
279
+ ---
280
+
281
+ ## Dev-server reminder
282
+
283
+ ES module imports require an HTTP server — opening with `file://` fails CORS. Use Vite (`npm create vite@latest`) or any static server.
@@ -0,0 +1,19 @@
1
+ # Installing Apex Grid Skill for Claude Code
2
+
3
+ ```bash
4
+ mkdir -p .claude/skills
5
+ cd .claude/skills
6
+ git clone https://github.com/apexcharts/apexgrid-skill.git
7
+ ```
8
+
9
+ Claude Code will automatically detect `SKILL.md` and load it when working on `apex-grid` code.
10
+
11
+ ## Verification
12
+
13
+ > Build a sortable, filterable Apex Grid for a `User` table with a custom avatar cell template.
14
+
15
+ Claude should:
16
+ - Register the custom element via `import 'apex-grid/define'` (or `ApexGrid.register()`) at app startup
17
+ - Define a `ColumnConfiguration<User>[]` with `sort: true` and `filter: true` per column, plus the right `type`
18
+ - Return a Lit `html\`...\`` template from `cellTemplate`, not a string
19
+ - Set `.data` and `.columns` as **properties** on the `<apex-grid>` element, not as attributes
@@ -0,0 +1,22 @@
1
+ # Installing Apex Grid Skill for GitHub Copilot
2
+
3
+ ## VS Code + Copilot Chat
4
+
5
+ ### Option 1: Add as Workspace Context
6
+
7
+ 1. Clone this repository or download `SKILL.md` into your project
8
+ 2. In Copilot Chat: `@workspace #file:SKILL.md`
9
+ 3. Ask your data-grid question
10
+
11
+ ### Option 2: Custom Instructions
12
+
13
+ 1. Open VS Code Settings (Cmd/Ctrl + ,)
14
+ 2. Search for "Copilot Custom Instructions"
15
+ 3. Paste the contents of `.cursorrules`
16
+
17
+ ## Verification
18
+
19
+ Ask Copilot to generate an Apex Grid. It should:
20
+ - Import from `apex-grid` (with a hyphen), not `apexgrid`
21
+ - Register the custom element exactly once at app startup
22
+ - Pass `columns` and `data` via property binding
@@ -0,0 +1,18 @@
1
+ # Installing Apex Grid Skill for Cursor
2
+
3
+ ```bash
4
+ curl -o .cursorrules https://raw.githubusercontent.com/apexcharts/apexgrid-skill/main/.cursorrules
5
+ ```
6
+
7
+ Restart Cursor or open a new window. Cursor automatically reads `.cursorrules` files in the project root as context.
8
+
9
+ ## For Windsurf
10
+
11
+ Same approach — Windsurf also reads `.cursorrules`.
12
+
13
+ ## Verification
14
+
15
+ Ask Cursor to generate an Apex Grid with multi-column sort and a server-side filter pipeline. It should:
16
+ - Set `sortConfiguration: { multiple: true, triState: true }` (or rely on the default)
17
+ - Provide an async `dataPipelineConfiguration.filter` hook that returns the new data array
18
+ - Use property bindings (`.columns=${...}`), not attribute syntax
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apexgrid-skill",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "AI coding skill for the apex-grid web component — structured reference docs that help AI assistants (Claude, Cursor, Copilot, etc.) generate correct apex-grid code.",
5
5
  "keywords": [
6
6
  "apex-grid",
@@ -39,7 +39,9 @@
39
39
  "files": [
40
40
  "index.js",
41
41
  "SKILL.md",
42
- "references"
42
+ "references",
43
+ "install",
44
+ ".cursorrules"
43
45
  ],
44
46
  "engines": {
45
47
  "node": ">=18"