@svgrid/enterprise 2.6.1 → 2.6.3

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.
Files changed (49) hide show
  1. package/README.md +1 -1
  2. package/dist/ExpressionEditorHarness.svelte +47 -0
  3. package/dist/ExpressionEditorHarness.svelte.d.ts +15 -0
  4. package/dist/SvAdvancedFilter.svelte +208 -0
  5. package/dist/SvAdvancedFilter.svelte.d.ts +37 -0
  6. package/dist/SvExpressionEditor.svelte +251 -123
  7. package/dist/SvGridEditPanel.svelte +1157 -1157
  8. package/dist/advanced-filter/expr-columns-from-grid.d.ts +30 -0
  9. package/dist/advanced-filter/expr-columns-from-grid.js +44 -0
  10. package/dist/advanced-filter-enable.d.ts +5 -0
  11. package/dist/advanced-filter-enable.js +35 -0
  12. package/dist/cdn/svgrid-enterprise.svelte-external.js +8274 -7706
  13. package/dist/designer/assets/GridMenus-DuogVgW0.js +7 -0
  14. package/dist/designer/assets/SvGrid.helpers-C6wxF55r.js +1 -0
  15. package/dist/designer/assets/SvGridCellEditor-CMtmQINJ.js +2 -0
  16. package/dist/designer/assets/{SvListBox-BVzVfCG3.js → SvListBox-CWCIPM4P.js} +1 -1
  17. package/dist/designer/assets/editor-registry-BB1Qb5mp.js +1 -0
  18. package/dist/designer/assets/{index-CKdwDseq.js → index-aTVomkp-.js} +43 -43
  19. package/dist/designer/assets/js-scroller.svelte-C7LaeUEW.js +110 -0
  20. package/dist/designer/assets/row-drag-touch-IuJPEt0z.js +1 -0
  21. package/dist/designer/assets/src-B5lLfIhK.css +1 -0
  22. package/dist/designer/assets/src-DLoHsbp5.js +2893 -0
  23. package/dist/designer/index.html +7 -5
  24. package/dist/expressions/builder-tree.d.ts +62 -0
  25. package/dist/expressions/builder-tree.js +133 -0
  26. package/dist/expressions/compile.d.ts +14 -0
  27. package/dist/expressions/compile.js +286 -0
  28. package/dist/expressions/expression-columns.d.ts +1 -11
  29. package/dist/expressions/expression-columns.js +40 -11
  30. package/dist/index.d.ts +4 -0
  31. package/dist/index.js +4 -0
  32. package/dist/install.js +2 -0
  33. package/dist/node/studio.js +61 -13
  34. package/dist/sources/rest.js +25 -0
  35. package/dist/sources/supabase.js +49 -3
  36. package/dist/studio/emit-project.js +2125 -2125
  37. package/dist/studio/ui-components.generated.js +33 -0
  38. package/dist/sveltekit/in-memory.js +96 -3
  39. package/dist/sveltekit/query-plan.d.ts +32 -1
  40. package/dist/sveltekit/query-plan.js +88 -1
  41. package/dist/sveltekit/sql.d.ts +20 -0
  42. package/dist/sveltekit/sql.js +26 -0
  43. package/dist/version.d.ts +1 -1
  44. package/dist/version.js +1 -1
  45. package/package.json +4 -4
  46. package/dist/designer/assets/GridMenus-CW-rnHS9.js +0 -7
  47. package/dist/designer/assets/js-scroller.svelte-tHanKJx0.js +0 -110
  48. package/dist/designer/assets/src-DCKhP5Xy.css +0 -1
  49. package/dist/designer/assets/src-DLsSdh3J.js +0 -2893
package/README.md CHANGED
@@ -24,7 +24,7 @@
24
24
 
25
25
  ## What it adds
26
26
 
27
- - **Data export** - Excel (`.xlsx`), PDF, CSV, TSV, and HTML, with theme-matched styling, headers/footers, and image support.
27
+ - **Data export** - Excel (`.xlsx`), PDF, styled HTML and XML, with theme-matched styling, headers/footers, and image support. CSV, TSV and JSON export (and copy-to-clipboard) are free in `@svgrid/grid`; Enterprise adds the paid formats and a single `exportGrid()` entry point over all of them.
28
28
  - **Data import** - read Excel / CSV / TSV / JSON into typed rows with column auto-mapping, type inference, and per-row validation, plus a ready-made `SvImportDialog`.
29
29
  - **Paginated print** - opens a clean, paginated, printable view of the grid with title and page breaks.
30
30
  - **Pivot tables** - drag-and-drop pivot Designer with row/column/value fields, aggregation, drill-through to source rows, and pivot-to-chart.
@@ -0,0 +1,47 @@
1
+ <script lang="ts">
2
+ /**
3
+ * Test-only harness for `SvExpressionEditor`.
4
+ *
5
+ * Runes cannot live in a `.ts` test file, and the behaviour under test is
6
+ * specifically "a parent reassigns `value`" - so the parent has to be a real
7
+ * component. This is also the shape of the real thing: a preset button, or a
8
+ * saved filter being loaded, replacing the expression from outside.
9
+ */
10
+ import SvExpressionEditor from './SvExpressionEditor.svelte'
11
+ import type { ExprColumn } from './expressions/expression-columns'
12
+ import type { PredicateExpr } from './expressions/expression-types'
13
+
14
+ type Props = {
15
+ columns: ReadonlyArray<ExprColumn>
16
+ initial: PredicateExpr
17
+ /** Applied to `value` when the "preset" button is clicked. */
18
+ preset: PredicateExpr
19
+ onChange?: (v: PredicateExpr) => void
20
+ }
21
+
22
+ let { columns, initial, preset, onChange }: Props = $props()
23
+
24
+ let value = $state<PredicateExpr>(initial)
25
+ let emissions = $state(0)
26
+
27
+ export function currentValue(): PredicateExpr {
28
+ return value
29
+ }
30
+ export function emissionCount(): number {
31
+ return emissions
32
+ }
33
+ </script>
34
+
35
+ <button type="button" data-testid="apply-preset" onclick={() => (value = preset)}>
36
+ preset
37
+ </button>
38
+ <span data-testid="emissions">{emissions}</span>
39
+
40
+ <SvExpressionEditor
41
+ {columns}
42
+ bind:value
43
+ onChange={(v) => {
44
+ emissions += 1
45
+ onChange?.(v)
46
+ }}
47
+ />
@@ -0,0 +1,15 @@
1
+ import type { ExprColumn } from './expressions/expression-columns';
2
+ import type { PredicateExpr } from './expressions/expression-types';
3
+ type Props = {
4
+ columns: ReadonlyArray<ExprColumn>;
5
+ initial: PredicateExpr;
6
+ /** Applied to `value` when the "preset" button is clicked. */
7
+ preset: PredicateExpr;
8
+ onChange?: (v: PredicateExpr) => void;
9
+ };
10
+ declare const ExpressionEditorHarness: import("svelte").Component<Props, {
11
+ currentValue: () => PredicateExpr;
12
+ emissionCount: () => number;
13
+ }, "">;
14
+ type ExpressionEditorHarness = ReturnType<typeof ExpressionEditorHarness>;
15
+ export default ExpressionEditorHarness;
@@ -0,0 +1,208 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvAdvancedFilter - the advanced-filter panel (Pro).
4
+ *
5
+ * Mounted beside the grid by the consumer, like `<SvGridAlerts>`; there is no
6
+ * grid-side renderer to register.
7
+ *
8
+ * The panel holds a DRAFT expression and only pushes it to the grid on Apply.
9
+ * `SvExpressionEditor` emits on every keystroke, which is right for an alert
10
+ * rule editor but would re-run the whole filter pipeline per character here.
11
+ * Holding the draft also makes the live "matches N" counter a genuine preview
12
+ * of what Apply would do, rather than a lagging echo of what already happened.
13
+ */
14
+ import { untrack } from 'svelte'
15
+ import SvExpressionEditor from './SvExpressionEditor.svelte'
16
+ import { exprColumnsFromGrid } from './advanced-filter/expr-columns-from-grid'
17
+ import type { ExprColumn } from './expressions/expression-columns'
18
+ import type { PredicateExpr } from './expressions/expression-types'
19
+
20
+ type MinimalApi = {
21
+ getColumns(): ReadonlyArray<{
22
+ id: string
23
+ field?: string
24
+ header: string
25
+ visible: boolean
26
+ editorType?: string
27
+ }>
28
+ getData?: () => ReadonlyArray<Record<string, unknown>>
29
+ setAdvancedFilter(expr: unknown): void
30
+ getAdvancedFilter(): unknown
31
+ isAdvancedFilterActive(): boolean
32
+ }
33
+
34
+ type Props = {
35
+ /** The grid's API, from `onApiReady` / `bind:api`. */
36
+ api: MinimalApi
37
+ /** Rows for the live match preview. Defaults to the grid's own data. */
38
+ rows?: ReadonlyArray<Record<string, unknown>>
39
+ /** Override the derived column list. */
40
+ columns?: ReadonlyArray<ExprColumn>
41
+ /** Include columns the user has hidden. Default false. */
42
+ includeHidden?: boolean
43
+ /** Called after Apply / Clear with the expression now on the grid. */
44
+ onApply?: (expr: PredicateExpr | null) => void
45
+ /**
46
+ * The expression the panel shows, bindable. Assign it to drive the panel
47
+ * from outside - a preset button, a saved view - and the draft re-seeds to
48
+ * match. Without this a parent that calls `api.setAdvancedFilter()` itself
49
+ * would filter the grid while the panel kept showing its old draft.
50
+ */
51
+ expression?: PredicateExpr | null
52
+ }
53
+
54
+ let {
55
+ api,
56
+ rows,
57
+ columns,
58
+ includeHidden = false,
59
+ onApply,
60
+ expression = $bindable<PredicateExpr | null>(undefined as never),
61
+ }: Props = $props()
62
+
63
+ const EMPTY: PredicateExpr = { kind: 'const', value: true }
64
+
65
+ const resolvedColumns = $derived(
66
+ columns ?? exprColumnsFromGrid(api, { includeHidden }),
67
+ )
68
+ const previewRows = $derived(rows ?? api.getData?.() ?? [])
69
+
70
+ /** The expression currently ON the grid, seeded once from it. */
71
+ let applied = $state<PredicateExpr | null>(
72
+ (untrack(() => api.getAdvancedFilter()) as PredicateExpr | null) ?? null,
73
+ )
74
+ /** What the editor is editing. Not pushed until Apply. */
75
+ let draft = $state<PredicateExpr>(applied ?? EMPTY)
76
+
77
+ const isDirty = $derived(JSON.stringify(draft) !== JSON.stringify(applied ?? EMPTY))
78
+ const canClear = $derived(applied != null)
79
+
80
+ /**
81
+ * Follow an externally assigned `expression`. Compared by reference so the
82
+ * panel's own writes below are skipped and this cannot loop.
83
+ */
84
+ let lastSynced = $state<PredicateExpr | null | undefined>(undefined)
85
+ $effect(() => {
86
+ const incoming = expression
87
+ if (incoming === undefined || incoming === untrack(() => lastSynced)) return
88
+ untrack(() => {
89
+ lastSynced = incoming
90
+ applied = incoming
91
+ draft = incoming ?? { kind: 'const', value: true }
92
+ })
93
+ })
94
+
95
+ function apply() {
96
+ api.setAdvancedFilter(draft as never)
97
+ applied = draft
98
+ lastSynced = draft
99
+ expression = draft
100
+ onApply?.(draft)
101
+ }
102
+
103
+ function clear() {
104
+ api.setAdvancedFilter(null)
105
+ applied = null
106
+ lastSynced = null
107
+ expression = null
108
+ // Reassign so the editor re-seeds - it compares by reference.
109
+ draft = { kind: 'const', value: true }
110
+ onApply?.(null)
111
+ }
112
+
113
+ function revert() {
114
+ draft = applied ?? { kind: 'const', value: true }
115
+ }
116
+
117
+ /** True when an expression is set but no engine is registered to run it. */
118
+ const inactive = $derived(applied != null && !api.isAdvancedFilterActive())
119
+ </script>
120
+
121
+ <section class="sv-adv-filter" aria-label="Advanced filter">
122
+ <header class="sv-adv-filter__head">
123
+ <h2 class="sv-adv-filter__title">Advanced filter</h2>
124
+ {#if applied}
125
+ <span class="sv-adv-filter__badge" aria-label="A filter is applied">Active</span>
126
+ {/if}
127
+ </header>
128
+
129
+ {#if inactive}
130
+ <p class="sv-adv-filter__warn" role="status">
131
+ A filter is set but no advanced-filter engine is registered, so no rows are
132
+ being removed. Call <code>enableAdvancedFilter()</code> from
133
+ <code>@svgrid/enterprise</code>.
134
+ </p>
135
+ {/if}
136
+
137
+ <SvExpressionEditor columns={resolvedColumns} bind:value={draft} rows={previewRows} />
138
+
139
+ <footer class="sv-adv-filter__actions">
140
+ <button type="button" class="sv-adv-filter__btn is-primary" disabled={!isDirty} onclick={apply}>
141
+ Apply
142
+ </button>
143
+ <button type="button" class="sv-adv-filter__btn" disabled={!isDirty} onclick={revert}>
144
+ Revert
145
+ </button>
146
+ <button type="button" class="sv-adv-filter__btn" disabled={!canClear} onclick={clear}>
147
+ Clear
148
+ </button>
149
+ </footer>
150
+ </section>
151
+
152
+ <style>
153
+ .sv-adv-filter {
154
+ display: flex;
155
+ flex-direction: column;
156
+ gap: 0.75rem;
157
+ padding: 1rem;
158
+ border: 1px solid var(--sg-border);
159
+ border-radius: 8px;
160
+ background: var(--sg-bg);
161
+ color: var(--sg-fg);
162
+ }
163
+ .sv-adv-filter__head {
164
+ display: flex;
165
+ align-items: center;
166
+ gap: 0.5rem;
167
+ }
168
+ .sv-adv-filter__title {
169
+ margin: 0;
170
+ font-size: 0.95rem;
171
+ font-weight: 600;
172
+ }
173
+ .sv-adv-filter__badge {
174
+ font-size: 0.7rem;
175
+ font-weight: 600;
176
+ padding: 0.1rem 0.4rem;
177
+ border-radius: 9999px;
178
+ background: var(--sg-accent);
179
+ color: var(--sg-on-accent);
180
+ }
181
+ .sv-adv-filter__warn {
182
+ margin: 0;
183
+ font-size: 0.8rem;
184
+ color: var(--sg-muted);
185
+ }
186
+ .sv-adv-filter__actions {
187
+ display: flex;
188
+ gap: 0.5rem;
189
+ }
190
+ .sv-adv-filter__btn {
191
+ padding: 0.35rem 0.75rem;
192
+ border-radius: 6px;
193
+ border: 1px solid var(--sg-border);
194
+ background: var(--sg-bg);
195
+ color: var(--sg-fg);
196
+ font-size: 0.85rem;
197
+ cursor: pointer;
198
+ }
199
+ .sv-adv-filter__btn:disabled {
200
+ opacity: 0.5;
201
+ cursor: default;
202
+ }
203
+ .sv-adv-filter__btn.is-primary {
204
+ background: var(--sg-accent);
205
+ color: var(--sg-on-accent);
206
+ border-color: var(--sg-accent);
207
+ }
208
+ </style>
@@ -0,0 +1,37 @@
1
+ import type { ExprColumn } from './expressions/expression-columns';
2
+ import type { PredicateExpr } from './expressions/expression-types';
3
+ type MinimalApi = {
4
+ getColumns(): ReadonlyArray<{
5
+ id: string;
6
+ field?: string;
7
+ header: string;
8
+ visible: boolean;
9
+ editorType?: string;
10
+ }>;
11
+ getData?: () => ReadonlyArray<Record<string, unknown>>;
12
+ setAdvancedFilter(expr: unknown): void;
13
+ getAdvancedFilter(): unknown;
14
+ isAdvancedFilterActive(): boolean;
15
+ };
16
+ type Props = {
17
+ /** The grid's API, from `onApiReady` / `bind:api`. */
18
+ api: MinimalApi;
19
+ /** Rows for the live match preview. Defaults to the grid's own data. */
20
+ rows?: ReadonlyArray<Record<string, unknown>>;
21
+ /** Override the derived column list. */
22
+ columns?: ReadonlyArray<ExprColumn>;
23
+ /** Include columns the user has hidden. Default false. */
24
+ includeHidden?: boolean;
25
+ /** Called after Apply / Clear with the expression now on the grid. */
26
+ onApply?: (expr: PredicateExpr | null) => void;
27
+ /**
28
+ * The expression the panel shows, bindable. Assign it to drive the panel
29
+ * from outside - a preset button, a saved view - and the draft re-seeds to
30
+ * match. Without this a parent that calls `api.setAdvancedFilter()` itself
31
+ * would filter the grid while the panel kept showing its old draft.
32
+ */
33
+ expression?: PredicateExpr | null;
34
+ };
35
+ declare const SvAdvancedFilter: import("svelte").Component<Props, {}, "expression">;
36
+ type SvAdvancedFilter = ReturnType<typeof SvAdvancedFilter>;
37
+ export default SvAdvancedFilter;