@svgrid/grid 2.2.26 → 2.2.28
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 +79 -25
- package/dist/GridMenus.svelte +10 -4
- package/dist/SvColorInput.svelte +1 -1
- package/dist/SvContextMenu.svelte +4 -4
- package/dist/SvDrawer.svelte +4 -0
- package/dist/SvGrid.css +4 -0
- package/dist/SvPhoneInput.svelte +3 -1
- package/dist/a11y/dismissable.d.ts +11 -0
- package/dist/a11y/dismissable.js +21 -0
- package/dist/ai.js +3 -3
- package/dist/cdn/GridMenus-BbzEvTYO.js +421 -0
- package/dist/cdn/GridMenus-E220X2kM.js +417 -0
- package/dist/cdn/{SvDateTimePicker-CYC7gRER.js → SvDateTimePicker-B8GopjhC.js} +449 -442
- package/dist/cdn/{SvDateTimePicker-DtQKd4Ns.js → SvDateTimePicker-DB0aIEk8.js} +112 -105
- package/dist/cdn/{src-bYfr_7aR.js → src-BxNEslEo.js} +8089 -8089
- package/dist/cdn/{src-DysW9qbk.js → src-C4yKQZ5t.js} +5741 -5741
- package/dist/cdn/svgrid.js +8 -8
- package/dist/cdn/svgrid.svelte-external.js +8 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +21 -4
- package/src/GridMenus.svelte +10 -4
- package/src/SvColorInput.svelte +1 -1
- package/src/SvContextMenu.svelte +4 -4
- package/src/SvDrawer.svelte +4 -0
- package/src/SvDrawer.test.ts +18 -1
- package/src/SvGrid.css +4 -0
- package/src/SvNavPane.test.ts +15 -4
- package/src/SvPhoneInput.svelte +3 -1
- package/src/a11y/dismissable.test.ts +25 -1
- package/src/a11y/dismissable.ts +20 -0
- package/src/ai.ts +3 -3
- package/src/index.ts +1 -0
- package/src/svgrid.filter-menu-scroll.test.ts +102 -0
- package/dist/cdn/GridMenus-GfCAHgkZ.js +0 -420
- package/dist/cdn/GridMenus-GiVNSeDU.js +0 -416
package/README.md
CHANGED
|
@@ -10,21 +10,29 @@
|
|
|
10
10
|
<a href="https://www.npmjs.com/package/@svgrid/grid"><img src="https://img.shields.io/npm/v/%40svgrid%2Fgrid.svg?label=%40svgrid%2Fgrid" alt="npm version" /></a>
|
|
11
11
|
<a href="https://www.npmjs.com/package/@svgrid/grid"><img src="https://img.shields.io/npm/dm/%40svgrid%2Fgrid.svg" alt="npm downloads" /></a>
|
|
12
12
|
<a href="./LICENSE"><img src="https://img.shields.io/badge/license-MIT-brightgreen.svg" alt="MIT License" /></a>
|
|
13
|
-
<a href="
|
|
13
|
+
<a href="https://www.npmjs.com/package/@svgrid/grid"><img src="https://img.shields.io/badge/types-included-blue.svg" alt="TypeScript" /></a>
|
|
14
14
|
<a href="https://svelte.dev"><img src="https://img.shields.io/badge/svelte-5-ff3e00.svg" alt="Svelte 5" /></a>
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
17
|
<p align="center">
|
|
18
18
|
<a href="https://svgrid.com">Website</a> ·
|
|
19
|
-
<a href="https://svgrid.com/docs">Docs</a> ·
|
|
20
|
-
<a href="https://svgrid.com/demos">
|
|
21
|
-
<a href="https://svgrid.com/pricing">Pricing</a> ·
|
|
22
|
-
<a href="https://svgrid.com/roadmap">Roadmap</a>
|
|
19
|
+
<a href="https://svgrid.com/docs/">Docs</a> ·
|
|
20
|
+
<a href="https://svgrid.com/demos/">370+ Demos</a> ·
|
|
21
|
+
<a href="https://svgrid.com/pricing/">Pricing</a> ·
|
|
22
|
+
<a href="https://svgrid.com/roadmap/">Roadmap</a>
|
|
23
23
|
</p>
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
-
A production-grade data grid built from the first line for **
|
|
27
|
+
A production-grade **Svelte 5 data grid and data table** built from the first line for **runes**, not a
|
|
28
|
+
React grid wrapped in a Svelte shim. Virtual scrolling over 100k+ rows, Excel-style filtering, inline
|
|
29
|
+
editing, row grouping, tree data, and server-side data. Compose the headless engine yourself, or drop in
|
|
30
|
+
the full `<SvGrid />` render component and ship. The MIT core has **zero feature gating**: no license key,
|
|
31
|
+
no watermark, no row-count cap.
|
|
32
|
+
|
|
33
|
+
<p align="center">
|
|
34
|
+
<img src="https://svgrid.com/brand/svgrid-hero.png" alt="A SvGrid trading desk: KPI cards, sector filter chips, and a virtualized data table with sparkline trend columns, conditional colour, and pinned columns." width="100%" />
|
|
35
|
+
</p>
|
|
28
36
|
|
|
29
37
|
## Install
|
|
30
38
|
|
|
@@ -61,21 +69,34 @@ npm install @svgrid/grid
|
|
|
61
69
|
<SvGrid data={rows} columns={columns} />
|
|
62
70
|
```
|
|
63
71
|
|
|
64
|
-
That is a real, accessible grid. Sorting, filtering, virtualization, cell selection, and inline editing
|
|
72
|
+
That is a real, accessible grid. Sorting, filtering, virtualization, cell selection, and inline editing
|
|
73
|
+
all wire up the moment you turn on the matching prop.
|
|
74
|
+
|
|
75
|
+
## Quick facts
|
|
76
|
+
|
|
77
|
+
| | |
|
|
78
|
+
|---|---|
|
|
79
|
+
| **License** | MIT, free for commercial use |
|
|
80
|
+
| **Requires** | `svelte@^5` (peer dependency), Node 16+ |
|
|
81
|
+
| **Bundle (gzip)** | ~2 KB headless core, ~80 KB full `<SvGrid>` + ~9 KB CSS |
|
|
82
|
+
| **Types** | Bundled, no `@types/` package needed |
|
|
83
|
+
| **Module format** | ESM, plus a CDN build at `@svgrid/grid/cdn` |
|
|
84
|
+
| **SSR** | Works under SvelteKit SSR and static builds |
|
|
85
|
+
| **Theming** | `--sg-*` CSS custom properties, dark mode + high contrast |
|
|
65
86
|
|
|
66
87
|
## Capabilities
|
|
67
88
|
|
|
68
|
-
- **
|
|
89
|
+
- **Virtual scrolling** - row + column windowing; 100k x 100 stays smooth, with a 1M-row demo.
|
|
69
90
|
- **Filtering** - Excel-style filter menu, inline filter row, set / value-list filter, locale-aware matching, between operators.
|
|
70
91
|
- **Editing** - 14 built-in `editorType`s (text, number, date, datetime, time, select, rich-select with typeahead, textarea, color, checkbox, list, chips, rating, password) plus a `cellEditor` snippet slot for anything custom.
|
|
71
92
|
- **Selection** - cell-range click+drag and Shift+arrows, copy/paste as TSV, Excel-style fill handle, row selection.
|
|
72
|
-
- **Views** -
|
|
73
|
-
- **Layout** - row + column pinning, sticky header + first column, header drag-to-reorder, autosize, keyboard-accessible column sizing, zebra rows.
|
|
93
|
+
- **Views** - row grouping with aggregation, tree data, master/detail, full-width detail rows, spreadsheet mode with formulas.
|
|
94
|
+
- **Layout** - row + column pinning, sticky header + first column, header drag-to-reorder, autosize, keyboard-accessible column sizing, zebra rows, responsive mode.
|
|
74
95
|
- **Data operations** - find in grid (Ctrl+F), undo / redo, transaction API, optimistic updates, server-side row model with sort / filter / group pushdown.
|
|
75
|
-
- **
|
|
96
|
+
- **AI helpers, free** - natural-language filter, smart fill, summarize, classify, anomaly detection, and "chart this". Model-agnostic: register one provider, nothing is bundled.
|
|
97
|
+
- **UI components** - a Svelte 5 component suite ships in the package (inputs, selection, date/time, overlays, layout, feedback), standalone or as grid cell editors.
|
|
76
98
|
- **Accessibility** - WAI-ARIA grid roles, full keyboard navigation, RTL, high-contrast theme.
|
|
77
99
|
- **Engineered for production** - first-class TypeScript types, CSP / Trusted-Types safe rendering, SSR-friendly, themeable via `--sg-*` CSS tokens.
|
|
78
|
-
- **Lean** - ~2 KB gzipped headless core, ~77 KB gzipped full grid (+ ~9 KB CSS); charts, cell editors and export load on demand as their own chunks, and the Kanban board + scheduler are Enterprise views. Svelte stays a peer dependency.
|
|
79
100
|
|
|
80
101
|
## Headless or render-ready
|
|
81
102
|
|
|
@@ -109,37 +130,70 @@ import {
|
|
|
109
130
|
} from '@svgrid/grid'
|
|
110
131
|
```
|
|
111
132
|
|
|
112
|
-
- **Headless** - drive `createSvGrid` and the row-model factories, render your own markup.
|
|
133
|
+
- **Headless** - drive `createSvGrid` and the row-model factories, render your own markup.
|
|
134
|
+
`getGrid*A11yProps` helpers keep custom markup accessible. About 2 KB gzipped.
|
|
113
135
|
- **Render-ready** - `<SvGrid />` is a complete, accessible, themeable grid you configure with props.
|
|
114
136
|
|
|
115
|
-
Compatibility aliases are provided for the framework-neutral names: `createGrid`, `createGridState`,
|
|
137
|
+
Compatibility aliases are provided for the framework-neutral names: `createGrid`, `createGridState`,
|
|
138
|
+
`subscribeGrid`.
|
|
116
139
|
|
|
117
140
|
## AI-native
|
|
118
141
|
|
|
119
|
-
SvGrid publishes an [MCP server](https://www.npmjs.com/package/@svgrid/mcp)
|
|
142
|
+
SvGrid publishes an [MCP server](https://www.npmjs.com/package/@svgrid/mcp) plus
|
|
143
|
+
[llms.txt](https://svgrid.com/llms.txt) and [llms-full.txt](https://svgrid.com/llms-full.txt), so Claude,
|
|
144
|
+
Cursor, and Zed answer with accurate, version-pinned APIs and all 370+ demo sources as context rather
|
|
145
|
+
than hallucinated methods.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
claude mcp add svgrid -- npx -y @svgrid/mcp
|
|
149
|
+
npx skills add sv-grid/sv-grid # always-on house-style rules
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
See [Use sv-grid docs as LLM context](https://svgrid.com/docs/help/llm-grounding/).
|
|
120
153
|
|
|
121
154
|
## Enterprise features
|
|
122
155
|
|
|
123
|
-
The MIT core is free for any use, including commercial, with **no feature gating
|
|
156
|
+
The MIT core is free for any use, including commercial, with **no feature gating**. Sorting, filtering,
|
|
157
|
+
editing, virtualization, the **server-side row model**, and the **AI helpers** all ship in the free
|
|
158
|
+
package. The optional [`@svgrid/enterprise`](https://www.npmjs.com/package/@svgrid/enterprise) pack layers
|
|
159
|
+
on the export- and analytics-heavy features teams tend to need last:
|
|
124
160
|
|
|
125
161
|
- **Excel / PDF / CSV / TSV / HTML export** plus paginated print.
|
|
162
|
+
- **Excel / CSV / TSV / JSON import** with auto-mapping and per-row validation.
|
|
126
163
|
- **Pivot tables** with a drag-and-drop pivot Designer.
|
|
127
|
-
- **
|
|
128
|
-
|
|
164
|
+
- **Kanban board and scheduler / calendar renderers** for the `board` and `scheduler` props.
|
|
165
|
+
|
|
166
|
+
OSS projects receive an Enterprise key free. See [Pricing](https://svgrid.com/pricing/).
|
|
167
|
+
|
|
168
|
+
## Comparison
|
|
169
|
+
|
|
170
|
+
| | SvGrid | AG Grid Community | TanStack Table |
|
|
171
|
+
|---|---|---|---|
|
|
172
|
+
| **Svelte 5 runes native** | Yes | No, JS core + wrapper | Adapter only |
|
|
173
|
+
| **Ships a renderer** | Yes, plus headless | Yes | No, headless only |
|
|
174
|
+
| **Bundle (gzip)** | ~2 KB headless / ~80 KB full | ~340 KB | ~12-14 KB |
|
|
175
|
+
| **Master/detail, tree, range selection** | Free | Enterprise only | Build it yourself |
|
|
129
176
|
|
|
130
|
-
|
|
177
|
+
Full detail: [SvGrid vs AG Grid vs TanStack Table](https://svgrid.com/docs/help/comparison/) ·
|
|
178
|
+
[Migrating from AG Grid](https://svgrid.com/docs/help/migrating-from-ag-grid/)
|
|
131
179
|
|
|
132
180
|
## Documentation
|
|
133
181
|
|
|
134
|
-
- [Getting started](https://svgrid.com/docs) - end-to-end walkthrough.
|
|
135
|
-
- [
|
|
136
|
-
- [Why headless?](https://svgrid.com/docs) - when to compose vs. drop in.
|
|
137
|
-
- [Theming](https://svgrid.com/docs) - re-skin via `--sg-*` tokens and dark mode.
|
|
182
|
+
- [Getting started](https://svgrid.com/docs/getting-started/) - end-to-end walkthrough.
|
|
183
|
+
- [370+ live demos](https://svgrid.com/demos/) - copy-paste recipes for every feature.
|
|
184
|
+
- [Why headless?](https://svgrid.com/docs/why-headless/) - when to compose vs. drop in.
|
|
185
|
+
- [Theming and Tailwind](https://svgrid.com/docs/help/tailwind/) - re-skin via `--sg-*` tokens and dark mode.
|
|
186
|
+
- [Accessibility](https://svgrid.com/docs/help/accessibility/) - the WAI-ARIA grid pattern as implemented.
|
|
187
|
+
- [Bundle size](https://svgrid.com/docs/reference/bundle-size/) - measured numbers and how to reproduce them.
|
|
138
188
|
|
|
139
189
|
## Who's behind it
|
|
140
190
|
|
|
141
|
-
SvGrid is built by [jQWidgets](https://www.jqwidgets.com), shipping UI components since 2011 to 5,000+
|
|
191
|
+
SvGrid is built by [jQWidgets](https://www.jqwidgets.com), shipping UI components since 2011 to 5,000+
|
|
192
|
+
companies including Samsung, Boeing, NVIDIA, Microsoft, Nokia, and Intel. SvGrid is our Svelte 5 native
|
|
193
|
+
effort.
|
|
142
194
|
|
|
143
195
|
## License & trademark
|
|
144
196
|
|
|
145
|
-
The source code is **MIT-licensed** - see [LICENSE](./LICENSE). It is free for commercial use.
|
|
197
|
+
The source code is **MIT-licensed** - see [LICENSE](./LICENSE). It is free for commercial use.
|
|
198
|
+
SvGrid™ and sv-grid™ are trademarks of jQWidgets Ltd; the license covers the code only, not
|
|
199
|
+
the name or logo.
|
package/dist/GridMenus.svelte
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
type TableFeatures,
|
|
40
40
|
} from "./index";
|
|
41
41
|
import "./sv-grid-scrollbar";
|
|
42
|
+
import { onScrollOutside } from "./a11y/dismissable";
|
|
42
43
|
import type { Snippet } from "svelte";
|
|
43
44
|
import { getKeyboardIntent, getNextActiveCell } from "./keyboard";
|
|
44
45
|
import {
|
|
@@ -145,15 +146,20 @@
|
|
|
145
146
|
|
|
146
147
|
// Column/filter/operator menus are position:fixed and anchored to their
|
|
147
148
|
// trigger by a one-time measurement taken when they open. On scroll they'd
|
|
148
|
-
// otherwise detach and float over the wrong place (#88), so close them
|
|
149
|
-
//
|
|
149
|
+
// otherwise detach and float over the wrong place (#88), so close them when
|
|
150
|
+
// anything OUTSIDE them scrolls, or on resize. Scrolling the menu's own body
|
|
151
|
+
// or its facet list has to keep it open - hence onScrollOutside rather than a
|
|
152
|
+
// bare capture-phase listener.
|
|
150
153
|
$effect(() => {
|
|
151
154
|
if (!(columnMenuFor || filterMenuFor || operatorMenuFor || chooseColumnsPos)) return;
|
|
152
155
|
const close = () => closeMenus();
|
|
153
|
-
|
|
156
|
+
const offScroll = onScrollOutside(
|
|
157
|
+
() => Array.from(document.querySelectorAll<HTMLElement>('.sv-grid-menu')),
|
|
158
|
+
close,
|
|
159
|
+
);
|
|
154
160
|
window.addEventListener('resize', close);
|
|
155
161
|
return () => {
|
|
156
|
-
|
|
162
|
+
offScroll();
|
|
157
163
|
window.removeEventListener('resize', close);
|
|
158
164
|
};
|
|
159
165
|
});
|
package/dist/SvColorInput.svelte
CHANGED
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
<SvField frame id={uid} {label} {hint} {error} {required} {dir} {size} {invalid} {disabled} {readonly} {loading} {block} width={block ? undefined : 'fit-content'}>
|
|
108
108
|
<button
|
|
109
109
|
bind:this={triggerEl}
|
|
110
|
-
class="sv-color__trigger"
|
|
110
|
+
class="sv-color sv-color__trigger"
|
|
111
111
|
class:is-disabled={disabled}
|
|
112
112
|
{...col.swatchProps()}
|
|
113
113
|
use:focusOpen
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import type { Snippet } from 'svelte'
|
|
19
19
|
import { portalToBody, popIn } from './popover'
|
|
20
|
-
import { createDismissableLayer } from './a11y/dismissable'
|
|
20
|
+
import { createDismissableLayer, onScrollOutside } from './a11y/dismissable'
|
|
21
21
|
import { createFocusTrap } from './a11y/focus-trap'
|
|
22
22
|
import SvMenuList, { type MenuItem } from './SvMenuList.svelte'
|
|
23
23
|
|
|
@@ -76,9 +76,9 @@
|
|
|
76
76
|
})
|
|
77
77
|
layer.activate()
|
|
78
78
|
// Reposition-close on scroll (a moved anchor would leave the menu stranded).
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return () => { layer.release(); trap.release();
|
|
79
|
+
// Scrolling the menu's own item list doesn't count as the anchor moving.
|
|
80
|
+
const offScroll = onScrollOutside(() => panelEl, () => (open = false))
|
|
81
|
+
return () => { layer.release(); trap.release(); offScroll() }
|
|
82
82
|
})
|
|
83
83
|
</script>
|
|
84
84
|
|
package/dist/SvDrawer.svelte
CHANGED
|
@@ -99,6 +99,10 @@
|
|
|
99
99
|
leaving = true
|
|
100
100
|
leaveTimer = setTimeout(() => { show = false; leaving = false; onClosed?.() }, reduceMotion ? 0 : EXIT_MS)
|
|
101
101
|
}
|
|
102
|
+
// `open` is this effect's only dependency, so the cleanup runs on reopen (a
|
|
103
|
+
// no-op after the clearTimeout above) or on destroy - where it matters, so a
|
|
104
|
+
// drawer unmounted mid-exit doesn't leave a timer firing into a dead scope.
|
|
105
|
+
return () => clearTimeout(leaveTimer)
|
|
102
106
|
})
|
|
103
107
|
|
|
104
108
|
// Swipe-down-to-close for the sheet grab handle.
|
package/dist/SvGrid.css
CHANGED
|
@@ -1780,6 +1780,9 @@ select.sv-grid-fr-editor {
|
|
|
1780
1780
|
z-index: 901;
|
|
1781
1781
|
max-height: calc(100vh - 24px);
|
|
1782
1782
|
overflow: auto;
|
|
1783
|
+
/* Keep a wheel that reaches the end of the menu from scrolling the grid
|
|
1784
|
+
underneath it - that scroll would close the menu out from under the user. */
|
|
1785
|
+
overscroll-behavior: contain;
|
|
1783
1786
|
padding: 4px;
|
|
1784
1787
|
background: var(--sg-bg, #fff);
|
|
1785
1788
|
border: 1px solid var(--sg-border, #d6dee9);
|
|
@@ -2062,6 +2065,7 @@ select.sv-grid-fr-editor {
|
|
|
2062
2065
|
.sv-grid-facet-list {
|
|
2063
2066
|
max-height: 200px;
|
|
2064
2067
|
overflow: auto;
|
|
2068
|
+
overscroll-behavior: contain;
|
|
2065
2069
|
border: 1px solid var(--sg-border, #eaeef4);
|
|
2066
2070
|
border-radius: 5px;
|
|
2067
2071
|
}
|
package/dist/SvPhoneInput.svelte
CHANGED
|
@@ -105,7 +105,9 @@
|
|
|
105
105
|
{width}
|
|
106
106
|
leading={countryChip}
|
|
107
107
|
>
|
|
108
|
-
|
|
108
|
+
<!-- `sv-phone` on the control is the component's public CSS/query hook, the
|
|
109
|
+
same convention SvCountryInput and the rest of the suite follow. -->
|
|
110
|
+
<input class="sv-phone sv-phone__number" {...ph.inputProps()} />
|
|
109
111
|
{#if name}<input type="hidden" {name} value={ph.value} />{/if}
|
|
110
112
|
</SvField>
|
|
111
113
|
|
|
@@ -29,4 +29,15 @@ export type DismissableLayer = {
|
|
|
29
29
|
export declare function createDismissableLayer(options: DismissableOptions): DismissableLayer;
|
|
30
30
|
/** Test/introspection helper: current number of active layers. */
|
|
31
31
|
export declare function dismissableDepth(): number;
|
|
32
|
+
/**
|
|
33
|
+
* Close-on-scroll for popovers that are position:fixed and anchored by a
|
|
34
|
+
* one-time measurement taken when they open. Scrolling an ancestor slides the
|
|
35
|
+
* anchor out from under them, so they have to close - but scrolling INSIDE
|
|
36
|
+
* them (a long menu, a facet list) must not, which is what a bare capture-phase
|
|
37
|
+
* window listener gets wrong: inner scroll containers don't bubble, so the
|
|
38
|
+
* capture listener sees them and dismisses the panel the user is scrolling.
|
|
39
|
+
*
|
|
40
|
+
* Returns the unsubscribe function.
|
|
41
|
+
*/
|
|
42
|
+
export declare function onScrollOutside(element: () => DismissTarget, onOutside: () => void): () => void;
|
|
32
43
|
export {};
|
package/dist/a11y/dismissable.js
CHANGED
|
@@ -52,3 +52,24 @@ export function createDismissableLayer(options) {
|
|
|
52
52
|
export function dismissableDepth() {
|
|
53
53
|
return stack.length;
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Close-on-scroll for popovers that are position:fixed and anchored by a
|
|
57
|
+
* one-time measurement taken when they open. Scrolling an ancestor slides the
|
|
58
|
+
* anchor out from under them, so they have to close - but scrolling INSIDE
|
|
59
|
+
* them (a long menu, a facet list) must not, which is what a bare capture-phase
|
|
60
|
+
* window listener gets wrong: inner scroll containers don't bubble, so the
|
|
61
|
+
* capture listener sees them and dismisses the panel the user is scrolling.
|
|
62
|
+
*
|
|
63
|
+
* Returns the unsubscribe function.
|
|
64
|
+
*/
|
|
65
|
+
export function onScrollOutside(element, onOutside) {
|
|
66
|
+
if (typeof window === 'undefined')
|
|
67
|
+
return () => { };
|
|
68
|
+
const handler = (event) => {
|
|
69
|
+
if (containsTarget(element(), event.target))
|
|
70
|
+
return;
|
|
71
|
+
onOutside();
|
|
72
|
+
};
|
|
73
|
+
window.addEventListener('scroll', handler, true);
|
|
74
|
+
return () => window.removeEventListener('scroll', handler, true);
|
|
75
|
+
}
|
package/dist/ai.js
CHANGED
|
@@ -42,14 +42,14 @@ export function hasAIProvider() {
|
|
|
42
42
|
}
|
|
43
43
|
class NoProviderError extends Error {
|
|
44
44
|
constructor() {
|
|
45
|
-
super('@svgrid/
|
|
45
|
+
super('@svgrid/grid ai: no AI provider registered. Call setAIProvider(fn) ' +
|
|
46
46
|
'with an adapter that talks to OpenAI / Anthropic / your proxy.');
|
|
47
47
|
this.name = 'NoProviderError';
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
class BadJsonError extends Error {
|
|
51
51
|
constructor(raw) {
|
|
52
|
-
super('@svgrid/
|
|
52
|
+
super('@svgrid/grid ai: provider returned non-JSON for a json-format request. ' +
|
|
53
53
|
`First 200 chars: ${raw.slice(0, 200)}`);
|
|
54
54
|
this.name = 'BadJsonError';
|
|
55
55
|
}
|
|
@@ -183,7 +183,7 @@ export async function aiFilter(api, query, opts = {}) {
|
|
|
183
183
|
*/
|
|
184
184
|
export async function aiSmartFill(api, opts) {
|
|
185
185
|
if (opts.examples.length === 0) {
|
|
186
|
-
throw new Error('@svgrid/
|
|
186
|
+
throw new Error('@svgrid/grid ai: aiSmartFill requires at least one example.');
|
|
187
187
|
}
|
|
188
188
|
const data = api.getData();
|
|
189
189
|
const targets = opts.targetRowIndices ??
|