@lavalogic/scoria 0.37.55 → 0.38.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.
Files changed (49) hide show
  1. package/dist/Components/Table/ARCHITECTURE.md +22 -22
  2. package/dist/Components/Table/Misc/ColumnPanel.svelte +1 -61
  3. package/dist/Components/Table/Misc/ColumnPanel.svelte.d.ts +2 -24
  4. package/dist/Components/Table/Misc/ColumnPanelModal.svelte +3 -92
  5. package/dist/Components/Table/Misc/ColumnPanelModal.svelte.d.ts +2 -24
  6. package/dist/Components/Table/Misc/ColumnPanelModalProps.d.ts +2 -2
  7. package/dist/Components/Table/Misc/TableConfigurationModal.svelte +644 -0
  8. package/dist/Components/Table/Misc/TableConfigurationModal.svelte.d.ts +26 -0
  9. package/dist/Components/Table/Misc/TableConfigurationModalProps.d.ts +13 -0
  10. package/dist/Components/Table/Misc/TableHorizontalBar.svelte +27 -0
  11. package/dist/Components/Table/Misc/TableSidebar.svelte +45 -2
  12. package/dist/Components/Table/Misc/TableViewDropdown.svelte +175 -0
  13. package/dist/Components/Table/Misc/TableViewDropdown.svelte.d.ts +25 -0
  14. package/dist/Components/Table/SubApis.svelte.js +0 -41
  15. package/dist/Components/Table/Types/Columns/JSONTableLayout.d.ts +5 -5
  16. package/dist/Components/Table/Types/Context/ColumnLayoutState.svelte.d.ts +5 -5
  17. package/dist/Components/Table/Types/Context/ColumnLayoutState.svelte.js +5 -5
  18. package/dist/Components/Table/Types/Context/PreferencesState.svelte.d.ts +106 -147
  19. package/dist/Components/Table/Types/Context/PreferencesState.svelte.js +156 -203
  20. package/dist/Components/Table/Types/Context/TableContext.svelte.d.ts +323 -44
  21. package/dist/Components/Table/Types/Context/TableContext.svelte.js +687 -187
  22. package/dist/Components/Table/Types/Context/TableInitOptions.d.ts +9 -0
  23. package/dist/Components/Table/Types/Context/ViewState.svelte.d.ts +152 -0
  24. package/dist/Components/Table/Types/Context/ViewState.svelte.js +223 -0
  25. package/dist/Components/Table/Types/ExpandedPanel.d.ts +9 -5
  26. package/dist/Components/Table/Types/ExpandedPanel.js +9 -5
  27. package/dist/Components/Table/Types/Persistence/DatatableView.d.ts +95 -0
  28. package/dist/Components/Table/Types/Persistence/DatatableViewEnvelope.d.ts +21 -0
  29. package/dist/Components/Table/Types/Persistence/DatatableViewEnvelope.js +1 -0
  30. package/dist/Components/Table/Types/Persistence/DatatableViewKind.d.ts +10 -0
  31. package/dist/Components/Table/Types/Persistence/DatatableViewKind.js +1 -0
  32. package/dist/Components/Table/Types/Persistence/JSONActiveView.d.ts +58 -0
  33. package/dist/Components/Table/Types/Persistence/JSONActiveView.js +41 -0
  34. package/dist/Components/Table/Types/Persistence/JSONTableFilter.d.ts +53 -0
  35. package/dist/Components/Table/Types/Persistence/JSONTableFilter.js +42 -0
  36. package/dist/Components/Table/Types/Persistence/RemoteTableLayoutAdapter.d.ts +47 -0
  37. package/dist/Components/Table/Types/Persistence/RemoteTableLayoutAdapter.js +1 -0
  38. package/dist/Components/Table/Types/Public/CreateTableOptions.d.ts +10 -0
  39. package/dist/Components/Table/Types/Public/TablePersistence.d.ts +1 -4
  40. package/dist/Components/Table/Types/Public/TableSubApis.d.ts +0 -18
  41. package/dist/Components/Table/Types/Public/index.d.ts +1 -1
  42. package/dist/Components/Table/createTable.svelte.js +2 -0
  43. package/dist/index.d.ts +8 -1
  44. package/dist/index.js +9 -0
  45. package/package.json +1 -1
  46. package/dist/Components/Table/Types/Columns/Definitions/ColumnDefSet.d.ts +0 -20
  47. package/dist/Components/Table/Types/Columns/Definitions/JSONColumnDefSet.d.ts +0 -25
  48. /package/dist/Components/Table/{Types/Columns/Definitions/ColumnDefSet.js → Misc/TableConfigurationModalProps.js} +0 -0
  49. /package/dist/Components/Table/Types/{Columns/Definitions/JSONColumnDefSet.js → Persistence/DatatableView.js} +0 -0
@@ -1,105 +1,62 @@
1
- import type { ColumnPinningState } from '../Columns/ColumnPinningState.js';
2
1
  import { type JSONTableLayout } from '../Columns/JSONTableLayout.js';
3
- import type { ColumnDef } from '../Columns/Definitions/ColumnDef.svelte.js';
4
- import type { ColumnDefSet } from '../Columns/Definitions/ColumnDefSet.js';
5
- import type { JSONColumnDefSet } from '../Columns/Definitions/JSONColumnDefSet.js';
6
- import type { VisibilityState } from '../Columns/VisibilityState.js';
7
- import type { SortingState as SortingStateArray } from '../DataRepository/SortingState.js';
2
+ import { type JSONActiveView } from '../Persistence/JSONActiveView.js';
3
+ import { type JSONTableFilter } from '../Persistence/JSONTableFilter.js';
8
4
  import type { SavedTableSettings, TableSettings } from './TableSettings.js';
9
- /**
10
- * Conservative typeguard for the persisted preset list. Storage is
11
- * same-origin-writable so only the array shape can be trusted;
12
- * downstream `reassignDefsToPresets` performs deeper checks and drops
13
- * presets that fail. Asserts the outer envelope plus the bare minimum
14
- * per entry: a string `name` and an array `columnDefs`.
15
- */
16
- export declare function isJSONColumnDefSetArray(raw: unknown): raw is Array<JSONColumnDefSet>;
17
5
  /**
18
6
  * Typeguard for the persisted user-level table settings blob. Every
19
7
  * field is optional, but every present field must be boolean; anything
20
8
  * else is a sign of schema drift or a tampered slot.
21
9
  */
22
10
  export declare function isSavedTableSettings(raw: unknown): raw is SavedTableSettings;
23
- /**
24
- * Typeguard for a non-empty string. Used for the persisted selected
25
- * preset name slot.
26
- */
27
- export declare function isNonEmptyString(raw: unknown): raw is string;
28
11
  /**
29
12
  * Dependency surface that `PreferencesState` reads from the surrounding
30
13
  * `TableContext`. All dependencies are passed as thunks / function refs
31
14
  * so the sub-context never holds a direct reference to the parent; the
32
- * `userIdSegment` derived reads `getUserId()` lazily and the
33
- * `setSelectedPreset` flow writes back through the column-layout
34
- * setters / `paginationRepo` updater.
15
+ * `userIdSegment` derived reads `getUserId()` lazily.
35
16
  */
36
- export interface PreferencesStateDeps<T extends object> {
17
+ export interface PreferencesStateDeps {
37
18
  /** The static table name, used as the middle segment of every
38
19
  * persisted key (`scoria-table:<user>:<tableName>:<suffix>`). */
39
20
  getTableName: () => string;
40
21
  /** Caller-supplied user identifier. `userIdSegment` resolves to
41
22
  * `getUserId() ?? 'anon'` so different users on a shared browser
42
- * cannot read each other's column presets. */
23
+ * cannot read each other's persisted layout / filter state. */
43
24
  getUserId: () => string | undefined;
44
- /** Read the current ordered column-defs array (used by
45
- * `saveColumnPreset` to capture the layout into the preset). */
46
- getColumnDefs: () => Array<ColumnDef<T>>;
47
- /** Read the current visibility map (used by `saveColumnPreset`). */
48
- getColumnVisibility: () => VisibilityState;
49
- /** Read the current column-pinning map (used by `saveColumnPreset`). */
50
- getColumnPinning: () => ColumnPinningState;
51
- /** Read the current sort instruction list (used by
52
- * `saveColumnPreset`). May be `undefined` when no pagination
53
- * repository is attached yet. */
54
- getSortingArray: () => SortingStateArray | undefined;
55
- /** Apply the column-defs slot when a preset is restored. */
56
- setColumnDefs: (defs: Array<ColumnDef<T>>) => void;
57
- /** Apply the visibility map when a preset is restored. */
58
- setColumnVisibility: (state: VisibilityState) => void;
59
- /** Apply the column-pinning map when a preset is restored. */
60
- setColumnPinning: (state: ColumnPinningState) => void;
61
- /** Apply the sort instruction list when a preset is restored. The
62
- * writer is a best-effort hook (`paginationRepo?.updateSorting?.()`
63
- * no-ops when no pagination repository is attached yet). */
64
- applySortingState: (state: SortingStateArray) => void;
65
- /** Logger gate; mirrors the parent `TableContext.debug` field. */
66
- getDebug: () => boolean;
25
+ /** The stable per-table `datatableUuid` when the host supplied one
26
+ * (FPM 403). Preferred over `getTableName()` for the storage-key
27
+ * middle segment so two tables that happen to share the same `name`
28
+ * do not collide on the same persisted slots. Returns `undefined`
29
+ * for tables that opt out of datatable views. */
30
+ getDatatableUuid: () => string | undefined;
67
31
  }
68
32
  /**
69
33
  * Sub-context owning every persistence / preferences concern:
70
34
  *
71
- * - `_columnPresets` (persisted preset list `$state`);
72
- * - `_selectedPreset` (currently-active preset `$state`);
73
35
  * - `userIdSegment` (sanitised user-id segment used in storage keys;
74
36
  * `$derived` over `getUserId()`);
75
- * - `saveColumnPreset(name)` (snapshot the live layout, persist the
76
- * list, mark the new preset as selected);
77
- * - `setSelectedPreset(preset)` (apply the preset to the live layout
78
- * and persist the selected name);
79
- * - `loadPresets()` / `loadSelectedPresetName()` /
80
- * `loadSavedSettings()` (boot-time hydration helpers; the parent
81
- * owns the orchestration because it depends on
82
- * `setupDefaultColumnDefs` running first);
83
- * - `clearPresetsAndSelection()` (drop both persisted slots);
84
- * - `persistSettings(settings)` (write the per-table TableSettings
85
- * blob);
86
- * - schema-validation typeguards (`isJSONColumnDefSetArray`,
87
- * `isSavedTableSettings`, `isNonEmptyString`) - exported alongside
88
- * the class.
37
+ * - `loadSavedSettings()` / `persistSettings()` (the per-table
38
+ * TableSettings blob: compact, alternate rows, etc.);
39
+ * - `loadLayout()` / `persistLayout()` / `clearLayout()` (the
40
+ * auto-saved live-layout working copy);
41
+ * - `loadActiveView()` / `persistActiveView()` / `clearActiveView()`
42
+ * (the DB-backed view selection envelope);
43
+ * - the filter counterparts (`loadFilter` / `persistFilter` /
44
+ * `clearFilter`, `loadActiveFilterView` / `persistActiveFilterView` /
45
+ * `clearActiveFilterView`);
46
+ * - schema-validation typeguards (`isSavedTableSettings`) - exported
47
+ * alongside the class.
89
48
  *
90
49
  * Every `localStorage` access is funnelled through this sub-context so
91
50
  * the `scoria-table:<user>:<tableName>:<suffix>` namespace convention
92
51
  * is enforced in a single place.
93
52
  */
94
- export declare class PreferencesState<T extends object> {
53
+ export declare class PreferencesState {
95
54
  private readonly _deps;
96
- private _columnPresets;
97
- private _selectedPreset;
98
55
  /**
99
56
  * Sanitised segment of the persisted-storage key path. Resolves to
100
57
  * `getUserId() ?? 'anon'` so different users on a shared browser
101
- * cannot read each other's column presets, and so anonymous
102
- * sessions still have a stable namespace.
58
+ * cannot read each other's persisted layout / filter state, and so
59
+ * anonymous sessions still have a stable namespace.
103
60
  *
104
61
  * The `$derived.by` form is required here (over plain
105
62
  * `$derived(expr)`) because class-field initialisers run BEFORE
@@ -112,54 +69,19 @@ export declare class PreferencesState<T extends object> {
112
69
  * Constructor-only - no implicit setup so the parent
113
70
  * remains in control of effect ownership and lifecycle.
114
71
  */
115
- constructor(deps: PreferencesStateDeps<T>);
116
- /**
117
- * The current list of saved column presets. Setter is private to
118
- * the sub-context; the parent writes through `setPresets` during
119
- * the boot-time hydration flow.
120
- */
121
- get columnPresets(): ReadonlyArray<ColumnDefSet<T>>;
122
- /**
123
- * Writer for `columnPresets`. Public so the parent boot flow can
124
- * publish the hydrated list; not part of the consumer-facing
125
- * surface (consumer-facing writes go through `saveColumnPreset`).
126
- */
127
- setPresets(v: ReadonlyArray<ColumnDefSet<T>>): void;
128
- /**
129
- * The currently-active preset (the one whose name is persisted in
130
- * the `selected-preset-name` slot). Setter is public so the parent
131
- * boot flow can publish the resolved preset; the consumer-facing
132
- * writer is `setSelectedPreset` below (which also persists the
133
- * name).
134
- */
135
- get selectedPreset(): ColumnDefSet<T> | undefined;
136
- set selectedPreset(v: ColumnDefSet<T> | undefined);
72
+ constructor(deps: PreferencesStateDeps);
137
73
  /**
138
- * Build the canonical `scoria-table:<user>:<tableName>:<suffix>`
139
- * storage key. Centralised so every persisted-state slot reaches
140
- * for the same namespacing convention; the `<user>` segment is
141
- * `getUserId() ?? 'anon'` (see `userIdSegment`).
142
- */
143
- storageKey(suffix: 'presets' | 'selected-preset-name' | 'settings' | 'layout'): string;
144
- /**
145
- * Boot-time hydration helper. Reads the persisted preset list from
146
- * `localStorage`, validates it against `isJSONColumnDefSetArray`,
147
- * and returns the parsed array (or an empty array on every failure
148
- * path). The parent runs this once `setupDefaultColumnDefs` has
149
- * completed so the live `columnDefs` can be compared against the
150
- * persisted snapshot.
74
+ * Build the canonical `scoria-table:<user>:<scope>:<suffix>` storage
75
+ * key. Centralised so every persisted-state slot reaches for the same
76
+ * namespacing convention; the `<user>` segment is `getUserId() ??
77
+ * 'anon'` (see `userIdSegment`).
151
78
  *
152
- * `localStorage` access is gated by the parent's `browser` check;
153
- * this method assumes the caller already verified the environment.
154
- */
155
- loadPresets(): Array<JSONColumnDefSet>;
156
- /**
157
- * Boot-time hydration helper. Reads the persisted selected-preset
158
- * name. Returns `null` for missing / empty / storage-error slots
159
- * so the parent can fall back to the first preset (or the default).
160
- * Emits a dev-only warning on `getItem` failure.
79
+ * The `<scope>` segment is the host-supplied `datatableUuid` when one
80
+ * is present, falling back to the table `name`. Preferring the UUID
81
+ * keeps two tables that share a `name` option from colliding on the
82
+ * same localStorage slots.
161
83
  */
162
- loadSelectedPresetName(): string | null;
84
+ storageKey(suffix: 'settings' | 'layout' | 'active-view' | 'filter' | 'active-filter-view'): string;
163
85
  /**
164
86
  * Boot-time hydration helper. Reads the persisted per-table
165
87
  * settings blob (`isCompact`, `singleClickEditing`, etc.). Returns
@@ -167,12 +89,6 @@ export declare class PreferencesState<T extends object> {
167
89
  * parent can apply its own default policy.
168
90
  */
169
91
  loadSavedSettings(): SavedTableSettings | null;
170
- /**
171
- * Drop the persisted presets and selected-preset-name slots. Used
172
- * by the parent's boot flow when the saved snapshot disagrees with
173
- * the live column-def shape (schema drift or column-set change).
174
- */
175
- clearPresetsAndSelection(): void;
176
92
  /**
177
93
  * Boot-time hydration helper. Reads the auto-saved live-layout
178
94
  * snapshot (column order / visibility / pinning / sizing the user
@@ -198,43 +114,86 @@ export declare class PreferencesState<T extends object> {
198
114
  */
199
115
  clearLayout(): void;
200
116
  /**
201
- * Persist the selected-preset name as plain text (no JSON
202
- * envelope - the slot is a single string by design).
117
+ * Boot-time hydration helper. Reads the persisted active-view
118
+ * envelope (which saved view, if any, the live working copy belongs
119
+ * to, plus its dirty flag). Returns `null` for a missing slot, a
120
+ * schema-version mismatch, or a value that fails validation, so the
121
+ * parent can fall back to the Default view.
122
+ *
123
+ * `localStorage` access is gated by the parent's `browser` check;
124
+ * this method assumes the caller already verified the environment.
203
125
  */
204
- persistSelectedPresetName(name: string): void;
126
+ loadActiveView(): JSONActiveView | null;
205
127
  /**
206
- * Persist the per-table settings blob (`isCompact`,
207
- * `singleClickEditing`, etc.) as JSON.
128
+ * Persist the active-view envelope. Written by the parent (debounced,
129
+ * alongside the working-copy layout) on every layout change, wrapped
130
+ * in a versioned envelope so a future schema bump drops stale
131
+ * snapshots cleanly. Storage failures are swallowed inside
132
+ * `writeJSON`.
208
133
  */
209
- persistSettings(settings: TableSettings): void;
134
+ persistActiveView(v: JSONActiveView): void;
210
135
  /**
211
- * Persist the full preset list as JSON. Each preset's
212
- * `columnPinningState` (Map-based) is flattened into entry arrays
213
- * because Map does not survive `JSON.stringify`; the reader (via
214
- * `loadPresets` -> `reassignDefsToPresets`) rehydrates it through
215
- * `adaptJSONPinningState`.
136
+ * Drop the persisted active-view envelope. Called when table state is
137
+ * explicitly reset; the next mount falls back to the Default view.
216
138
  */
217
- persistPresets(presets: ReadonlyArray<ColumnDefSet<T>>): void;
139
+ clearActiveView(): void;
218
140
  /**
219
- * Apply a saved column preset to the live table layout and persist
220
- * the selection by name:
141
+ * Boot-time hydration helper. Reads the auto-saved live-filter
142
+ * snapshot (the per-column filter values and modes the user built up
143
+ * in the quick-filter row / advanced filter panel without saving a
144
+ * named view). Returns `null` for a missing slot, a schema-version
145
+ * mismatch, or a value that fails validation, so the parent can fall
146
+ * back to the empty filter state.
221
147
  *
222
- * 1. Replace `columnDefs`, `columnVisibility`, `columnPinning`.
223
- * 2. Forward the preset's `sortingState` to the data-repository
224
- * updater (no-op when the repo has no `updateSorting` hook).
225
- * 3. Update `selectedPreset`.
226
- * 4. Persist the preset name to `selected-preset-name`.
148
+ * The filter counterpart of `loadLayout`. `localStorage` access is
149
+ * gated by the parent's `browser` check; this method assumes the
150
+ * caller already verified the environment.
151
+ */
152
+ loadFilter(): JSONTableFilter | null;
153
+ /**
154
+ * Persist the live-filter snapshot. Written by the parent (debounced)
155
+ * on every filter value / mode change, wrapped in a versioned
156
+ * envelope so a future schema bump drops stale snapshots cleanly.
157
+ * Storage failures are swallowed inside `writeJSON`. The filter
158
+ * counterpart of `persistLayout`.
159
+ */
160
+ persistFilter(filter: JSONTableFilter): void;
161
+ /**
162
+ * Drop the persisted live-filter snapshot. Called when the snapshot
163
+ * no longer matches the table's column set (schema drift) or when
164
+ * table state is explicitly reset. The filter counterpart of
165
+ * `clearLayout`.
166
+ */
167
+ clearFilter(): void;
168
+ /**
169
+ * Boot-time hydration helper. Reads the persisted *filter*
170
+ * active-view envelope (which saved filter view, if any, the live
171
+ * filter working copy belongs to, plus its dirty flag). Returns
172
+ * `null` for a missing slot, a schema-version mismatch, or a value
173
+ * that fails validation, so the parent can fall back to the Default
174
+ * filter view. The filter counterpart of `loadActiveView`.
227
175
  *
228
- * Bound as a class property so callers (notably the toolbar
229
- * dropdown) can pass the reference around without binding `this`.
176
+ * `localStorage` access is gated by the parent's `browser` check;
177
+ * this method assumes the caller already verified the environment.
178
+ */
179
+ loadActiveFilterView(): JSONActiveView | null;
180
+ /**
181
+ * Persist the *filter* active-view envelope. Written by the parent
182
+ * (debounced, alongside the working-copy filter) on every filter
183
+ * change, wrapped in a versioned envelope so a future schema bump
184
+ * drops stale snapshots cleanly. Storage failures are swallowed
185
+ * inside `writeJSON`. The filter counterpart of `persistActiveView`.
230
186
  */
231
- readonly setSelectedPreset: (preset: ColumnDefSet<T>) => void;
187
+ persistActiveFilterView(v: JSONActiveView): void;
232
188
  /**
233
- * Snapshot the current column layout into a new preset, replacing
234
- * any existing preset whose name matches case-insensitively, and
235
- * persist the full preset list to `localStorage`. Marks the new
236
- * preset as selected (which also persists its name). No-op when
237
- * `name` is empty.
189
+ * Drop the persisted *filter* active-view envelope. Called when table
190
+ * state is explicitly reset; the next mount falls back to the Default
191
+ * filter view. The filter counterpart of `clearActiveView`.
238
192
  */
239
- readonly saveColumnPreset: (name: string) => void;
193
+ clearActiveFilterView(): void;
194
+ /**
195
+ * Persist the per-table settings blob (`isCompact`,
196
+ * `singleClickEditing`, etc.) as JSON.
197
+ */
198
+ persistSettings(settings: TableSettings): void;
240
199
  }