@svgrid/enterprise 3.1.7 → 3.1.9
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 +1 -0
- package/dist/SvAlertRuleEditor.svelte +16 -5
- package/dist/SvGridAlerts.svelte +8 -0
- package/dist/SvGridAlerts.svelte.d.ts +4 -0
- package/dist/SvGridBoard.svelte +69 -10
- package/dist/SvGridBulkEditDrawer.svelte +13 -5
- package/dist/SvGridGallery.svelte +286 -0
- package/dist/SvGridGallery.svelte.d.ts +30 -0
- package/dist/SvGridScheduler.svelte +33 -11
- package/dist/SvGridSelectionBar.svelte +47 -0
- package/dist/advanced-filter/expr-columns-from-grid.d.ts +1 -0
- package/dist/advanced-filter/expr-columns-from-grid.js +11 -7
- package/dist/advanced-filter-enable.d.ts +6 -0
- package/dist/advanced-filter-enable.js +8 -0
- package/dist/alerts/alert-engine.d.ts +7 -0
- package/dist/alerts/alert-engine.js +5 -2
- package/dist/alerts/condition-editor.d.ts +26 -0
- package/dist/alerts/condition-editor.js +17 -0
- package/dist/base/index.d.ts +20 -0
- package/dist/base/index.js +20 -0
- package/dist/bulk-edit.d.ts +11 -0
- package/dist/bulk-edit.js +18 -1
- package/dist/cdn/svgrid-enterprise.svelte-external.js +11375 -10805
- package/dist/designer/assets/GridFooter-Cu8_yBlQ.js +2 -0
- package/dist/designer/assets/GridMenus-BUjkkAU2.js +6 -0
- package/dist/designer/assets/PinSplitter-BgTpgh1d.css +1 -0
- package/dist/designer/assets/PinSplitter-C5AwA1xV.js +1 -0
- package/dist/designer/assets/SvGrid.helpers-CIrmIo9U.js +1 -0
- package/dist/designer/assets/SvGridCellEditor-CJxThKL_.js +4 -0
- package/dist/designer/assets/SvListBox-CS7oUAiX.js +2 -0
- package/dist/designer/assets/conditional-formatting-MDWbF8_Y.js +1 -0
- package/dist/designer/assets/grid-extension.svelte-BZ7AqyJI.js +1 -0
- package/dist/designer/assets/{index-DtBIaQno.js → index-BPU2KNc5.js} +396 -395
- package/dist/designer/assets/index-BmvG99kR.css +1 -0
- package/dist/designer/assets/sparkline-C-NcnB2i.js +1 -0
- package/dist/designer/assets/src-C_U1NKOY.js +58 -0
- package/dist/designer/assets/sv-grid-scrollbar-B9N6Wuj0.js +109 -0
- package/dist/designer/assets/validate-H5u2HEQh.js +1 -0
- package/dist/designer/index.html +11 -7
- package/dist/expressions/compile.js +10 -0
- package/dist/expressions/evaluate.js +18 -0
- package/dist/expressions/expression-types.d.ts +10 -0
- package/dist/expressions/kinds.d.ts +28 -0
- package/dist/expressions/kinds.js +19 -0
- package/dist/expressions/parse.js +9 -1
- package/dist/fields/AttachmentCell.svelte +242 -0
- package/dist/fields/AttachmentCell.svelte.d.ts +5 -0
- package/dist/fields/AttachmentDialog.svelte +357 -0
- package/dist/fields/AttachmentDialog.svelte.d.ts +13 -0
- package/dist/fields/AttachmentEditor.svelte +41 -0
- package/dist/fields/AttachmentEditor.svelte.d.ts +11 -0
- package/dist/fields/AttachmentPreview.svelte +72 -0
- package/dist/fields/AttachmentPreview.svelte.d.ts +8 -0
- package/dist/fields/BarcodeCell.svelte +20 -0
- package/dist/fields/BarcodeCell.svelte.d.ts +5 -0
- package/dist/fields/BaseAutomations.svelte +558 -0
- package/dist/fields/BaseAutomations.svelte.d.ts +18 -0
- package/dist/fields/BaseChartView.svelte +47 -0
- package/dist/fields/BaseChartView.svelte.d.ts +8 -0
- package/dist/fields/BaseTableView.svelte +185 -0
- package/dist/fields/BaseTableView.svelte.d.ts +37 -0
- package/dist/fields/BaseTabs.svelte +308 -0
- package/dist/fields/BaseTabs.svelte.d.ts +21 -0
- package/dist/fields/ButtonCell.svelte +47 -0
- package/dist/fields/ButtonCell.svelte.d.ts +20 -0
- package/dist/fields/CheckboxCell.svelte +46 -0
- package/dist/fields/CheckboxCell.svelte.d.ts +14 -0
- package/dist/fields/DeleteFieldConfirm.svelte +80 -0
- package/dist/fields/DeleteFieldConfirm.svelte.d.ts +8 -0
- package/dist/fields/DeleteRecordConfirm.svelte +48 -0
- package/dist/fields/DeleteRecordConfirm.svelte.d.ts +9 -0
- package/dist/fields/FieldCell.svelte +80 -0
- package/dist/fields/FieldCell.svelte.d.ts +9 -0
- package/dist/fields/FieldEditor.svelte +321 -0
- package/dist/fields/FieldEditor.svelte.d.ts +10 -0
- package/dist/fields/FieldInput.svelte +188 -0
- package/dist/fields/FieldInput.svelte.d.ts +29 -0
- package/dist/fields/FieldsHeaderEnd.svelte +146 -0
- package/dist/fields/FieldsHeaderEnd.svelte.d.ts +6 -0
- package/dist/fields/FootRowAdder.svelte +8 -0
- package/dist/fields/FootRowAdder.svelte.d.ts +6 -0
- package/dist/fields/GroupHeader.svelte +127 -0
- package/dist/fields/GroupHeader.svelte.d.ts +24 -0
- package/dist/fields/LinkCell.svelte +46 -0
- package/dist/fields/LinkCell.svelte.d.ts +9 -0
- package/dist/fields/LinkPickerEditor.svelte +172 -0
- package/dist/fields/LinkPickerEditor.svelte.d.ts +9 -0
- package/dist/fields/LinkPreview.svelte +60 -0
- package/dist/fields/LinkPreview.svelte.d.ts +7 -0
- package/dist/fields/LinkedRecordView.svelte +94 -0
- package/dist/fields/LinkedRecordView.svelte.d.ts +9 -0
- package/dist/fields/LinkedRecordsCell.svelte +59 -0
- package/dist/fields/LinkedRecordsCell.svelte.d.ts +11 -0
- package/dist/fields/LongTextEditor.svelte +157 -0
- package/dist/fields/LongTextEditor.svelte.d.ts +11 -0
- package/dist/fields/NumberEditor.svelte +309 -0
- package/dist/fields/NumberEditor.svelte.d.ts +12 -0
- package/dist/fields/OptionsEditor.svelte +117 -0
- package/dist/fields/OptionsEditor.svelte.d.ts +11 -0
- package/dist/fields/PercentCell.svelte +21 -0
- package/dist/fields/PercentCell.svelte.d.ts +8 -0
- package/dist/fields/PropertyInput.svelte +204 -0
- package/dist/fields/PropertyInput.svelte.d.ts +11 -0
- package/dist/fields/RatingCell.svelte +75 -0
- package/dist/fields/RatingCell.svelte.d.ts +16 -0
- package/dist/fields/RatingEditor.svelte +82 -0
- package/dist/fields/RatingEditor.svelte.d.ts +9 -0
- package/dist/fields/RecordView.svelte +310 -0
- package/dist/fields/RecordView.svelte.d.ts +11 -0
- package/dist/fields/RichTextCell.svelte +30 -0
- package/dist/fields/RichTextCell.svelte.d.ts +5 -0
- package/dist/fields/RowAdder.svelte +93 -0
- package/dist/fields/RowAdder.svelte.d.ts +7 -0
- package/dist/fields/RowHeader.svelte +99 -0
- package/dist/fields/RowHeader.svelte.d.ts +11 -0
- package/dist/fields/SelectCell.svelte +35 -0
- package/dist/fields/SelectCell.svelte.d.ts +15 -0
- package/dist/fields/SelectEditor.svelte +350 -0
- package/dist/fields/SelectEditor.svelte.d.ts +17 -0
- package/dist/fields/SummaryCell.svelte +160 -0
- package/dist/fields/SummaryCell.svelte.d.ts +11 -0
- package/dist/fields/SvBase.svelte +545 -0
- package/dist/fields/SvBase.svelte.d.ts +30 -0
- package/dist/fields/SvBaseForm.svelte +295 -0
- package/dist/fields/SvBaseForm.svelte.d.ts +22 -0
- package/dist/fields/SvBaseViewBar.svelte +644 -0
- package/dist/fields/SvBaseViewBar.svelte.d.ts +26 -0
- package/dist/fields/UserCell.svelte +39 -0
- package/dist/fields/UserCell.svelte.d.ts +9 -0
- package/dist/fields/UserFace.svelte +30 -0
- package/dist/fields/UserFace.svelte.d.ts +12 -0
- package/dist/fields/activity.svelte.d.ts +50 -0
- package/dist/fields/activity.svelte.js +110 -0
- package/dist/fields/attachments.d.ts +95 -0
- package/dist/fields/attachments.js +145 -0
- package/dist/fields/automation-outbound.d.ts +46 -0
- package/dist/fields/automation-outbound.js +61 -0
- package/dist/fields/automation-server.d.ts +53 -0
- package/dist/fields/automation-server.js +333 -0
- package/dist/fields/automations.svelte.d.ts +208 -0
- package/dist/fields/automations.svelte.js +437 -0
- package/dist/fields/bar-request.svelte.d.ts +16 -0
- package/dist/fields/bar-request.svelte.js +15 -0
- package/dist/fields/base-alerts.d.ts +24 -0
- package/dist/fields/base-alerts.js +64 -0
- package/dist/fields/base-connect.d.ts +82 -0
- package/dist/fields/base-connect.js +271 -0
- package/dist/fields/base-schema.d.ts +104 -0
- package/dist/fields/base-schema.js +266 -0
- package/dist/fields/base-sql.d.ts +62 -0
- package/dist/fields/base-sql.js +251 -0
- package/dist/fields/base-sync.d.ts +142 -0
- package/dist/fields/base-sync.js +499 -0
- package/dist/fields/base-tables.d.ts +89 -0
- package/dist/fields/base-tables.js +349 -0
- package/dist/fields/builtin-types.d.ts +13 -0
- package/dist/fields/builtin-types.js +773 -0
- package/dist/fields/button.d.ts +2 -0
- package/dist/fields/button.js +17 -0
- package/dist/fields/chart-view.d.ts +35 -0
- package/dist/fields/chart-view.js +154 -0
- package/dist/fields/column-order.d.ts +6 -0
- package/dist/fields/column-order.js +12 -0
- package/dist/fields/convert.d.ts +16 -0
- package/dist/fields/convert.js +176 -0
- package/dist/fields/copy-text.d.ts +13 -0
- package/dist/fields/copy-text.js +45 -0
- package/dist/fields/editor-request.svelte.d.ts +71 -0
- package/dist/fields/editor-request.svelte.js +52 -0
- package/dist/fields/field-ops.d.ts +72 -0
- package/dist/fields/field-ops.js +334 -0
- package/dist/fields/filter-model.d.ts +84 -0
- package/dist/fields/filter-model.js +446 -0
- package/dist/fields/format.d.ts +109 -0
- package/dist/fields/format.js +288 -0
- package/dist/fields/formula.d.ts +50 -0
- package/dist/fields/formula.js +530 -0
- package/dist/fields/grid-access.d.ts +60 -0
- package/dist/fields/grid-access.js +120 -0
- package/dist/fields/index.d.ts +34 -0
- package/dist/fields/index.js +312 -0
- package/dist/fields/linked-fields.d.ts +8 -0
- package/dist/fields/linked-fields.js +40 -0
- package/dist/fields/links.d.ts +10 -0
- package/dist/fields/links.js +46 -0
- package/dist/fields/name-list.d.ts +16 -0
- package/dist/fields/name-list.js +49 -0
- package/dist/fields/palette.d.ts +47 -0
- package/dist/fields/palette.js +69 -0
- package/dist/fields/record-delete.svelte.d.ts +12 -0
- package/dist/fields/record-delete.svelte.js +5 -0
- package/dist/fields/record-menu.d.ts +9 -0
- package/dist/fields/record-menu.js +78 -0
- package/dist/fields/registry.svelte.d.ts +176 -0
- package/dist/fields/registry.svelte.js +51 -0
- package/dist/fields/rich-text.d.ts +23 -0
- package/dist/fields/rich-text.js +48 -0
- package/dist/fields/row-color-choice.svelte.d.ts +31 -0
- package/dist/fields/row-color-choice.svelte.js +25 -0
- package/dist/fields/row-colors.d.ts +36 -0
- package/dist/fields/row-colors.js +90 -0
- package/dist/fields/row-height.d.ts +28 -0
- package/dist/fields/row-height.js +50 -0
- package/dist/fields/sources.svelte.d.ts +80 -0
- package/dist/fields/sources.svelte.js +131 -0
- package/dist/fields/summaries.d.ts +18 -0
- package/dist/fields/summaries.js +138 -0
- package/dist/fields/view-model.d.ts +129 -0
- package/dist/fields/view-model.js +492 -0
- package/dist/fields/viewbar/ChartPanel.svelte +61 -0
- package/dist/fields/viewbar/ChartPanel.svelte.d.ts +9 -0
- package/dist/fields/viewbar/ColorPanel.svelte +112 -0
- package/dist/fields/viewbar/ColorPanel.svelte.d.ts +9 -0
- package/dist/fields/viewbar/ConditionValue.svelte +153 -0
- package/dist/fields/viewbar/ConditionValue.svelte.d.ts +15 -0
- package/dist/fields/viewbar/FieldIcon.svelte +18 -0
- package/dist/fields/viewbar/FieldIcon.svelte.d.ts +9 -0
- package/dist/fields/viewbar/FilterPanel.svelte +192 -0
- package/dist/fields/viewbar/FilterPanel.svelte.d.ts +13 -0
- package/dist/fields/viewbar/GanttPanel.svelte +60 -0
- package/dist/fields/viewbar/GanttPanel.svelte.d.ts +10 -0
- package/dist/fields/viewbar/HideFieldsPanel.svelte +104 -0
- package/dist/fields/viewbar/HideFieldsPanel.svelte.d.ts +7 -0
- package/dist/fields/viewbar/SortPanel.svelte +85 -0
- package/dist/fields/viewbar/SortPanel.svelte.d.ts +8 -0
- package/dist/fields/viewbar/ViewsMenu.svelte +250 -0
- package/dist/fields/viewbar/ViewsMenu.svelte.d.ts +15 -0
- package/dist/fields/viewbar/panel-focus.d.ts +3 -0
- package/dist/fields/viewbar/panel-focus.js +22 -0
- package/dist/fields/viewbar/sort-state.d.ts +20 -0
- package/dist/fields/viewbar/sort-state.js +24 -0
- package/dist/gallery.d.ts +7 -0
- package/dist/gallery.js +36 -0
- package/dist/gantt/SvGridGantt.svelte +88 -16
- package/dist/gantt/gantt-config.d.ts +28 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +6 -0
- package/dist/install.js +3 -0
- package/dist/license-core.d.ts +3 -3
- package/dist/license.js +1 -0
- package/dist/node/studio.js +141 -20
- package/dist/scheduler-config.d.ts +11 -0
- package/dist/sources/introspect-supabase.js +4 -1
- package/dist/sources/rest.js +6 -2
- package/dist/studio/emit-project.js +25 -6
- package/dist/studio/sveltekit3.js +13 -7
- package/dist/studio/ui-components.generated.js +94 -2
- package/dist/upgrade-prompt.d.ts +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/dist/wc/GridFooter-f5K0aLe_.js +145 -0
- package/dist/wc/GridMenus-FtSN_8t9.js +1369 -0
- package/dist/wc/PinSplitter-D-qtDhSM.js +132 -0
- package/dist/wc/{SvGrid.helpers-zBkDTryR.js → SvGrid.helpers-B2GEKrxS.js} +84 -36
- package/dist/wc/{SvGridCellEditor-CzUKEbkI.js → SvGridCellEditor-B_cLJrsp.js} +20 -9
- package/dist/wc/conditional-formatting-BXis_oP1.js +189 -0
- package/dist/wc/grid-extension.svelte-Bufq4B4C.js +20 -0
- package/dist/wc/sv-sheet-element.js +7561 -7618
- package/dist/wc/svelte-virtualizer.svelte-ehwOupl-.js +360 -0
- package/dist/wc/{validate-43C03DLP.js → validate-BaMO8UPE.js} +1 -1
- package/package.json +14 -3
- package/dist/designer/assets/GridMenus-CvcASlKv.js +0 -8
- package/dist/designer/assets/SvGrid.helpers-DE5mmORW.js +0 -1
- package/dist/designer/assets/SvGridCellEditor-C7NWcnNC.js +0 -4
- package/dist/designer/assets/SvListBox-BlmmzYcU.js +0 -110
- package/dist/designer/assets/index-KmSEY7Lb.css +0 -1
- package/dist/designer/assets/src-DqHCqori.js +0 -58
- package/dist/designer/assets/validate-B71dE1Cs.js +0 -1
- package/dist/wc/GridMenus-fWbBUiRH.js +0 -1088
- package/dist/wc/svelte-virtualizer.svelte-Dntdh8Ms.js +0 -581
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
type Def = Record<string, unknown> & {
|
|
2
|
+
id?: string;
|
|
3
|
+
field?: string;
|
|
4
|
+
header?: unknown;
|
|
5
|
+
fieldType?: string;
|
|
6
|
+
fieldProps?: Record<string, unknown>;
|
|
7
|
+
};
|
|
8
|
+
type Ctrl = {
|
|
9
|
+
props: Record<string, any>;
|
|
10
|
+
internalColumns: Def[];
|
|
11
|
+
internalData: Record<string, unknown>[];
|
|
12
|
+
buildApi?: () => {
|
|
13
|
+
setColumnVisible?: (id: string, visible: boolean) => void;
|
|
14
|
+
};
|
|
15
|
+
scrollContainer?: HTMLElement | null;
|
|
16
|
+
};
|
|
17
|
+
export type FieldDraft = {
|
|
18
|
+
name: string;
|
|
19
|
+
fieldType: string;
|
|
20
|
+
fieldProps: Record<string, unknown>;
|
|
21
|
+
description?: string;
|
|
22
|
+
};
|
|
23
|
+
export declare const defId: (d: Def) => string;
|
|
24
|
+
/** The column as the app declared it, without what its type filled in. */
|
|
25
|
+
export declare function plainDef(d: Def): Def;
|
|
26
|
+
/** The declared columns after a change: what every field event hands the app. */
|
|
27
|
+
export declare const plainColumns: (ctrl: Ctrl) => Def[];
|
|
28
|
+
/** A new column id from a name: lower-case words, unique among the grid's columns. */
|
|
29
|
+
export declare function uniqueId(name: string, taken: Iterable<string>): string;
|
|
30
|
+
/** Whether `name` is free: no other column has that header (case-insensitive). */
|
|
31
|
+
export declare function nameTaken(ctrl: Ctrl, name: string, exceptId?: string): boolean;
|
|
32
|
+
/** Add a field from the editor. Returns the plain column. */
|
|
33
|
+
export declare function addField(ctrl: Ctrl, draft: FieldDraft, index?: number | 'end'): Def;
|
|
34
|
+
/** A new record id: "rec" and nine letters and digits, unique in this page. */
|
|
35
|
+
export declare function newRecordId(): string;
|
|
36
|
+
/**
|
|
37
|
+
* The values a new row gets from its field columns: each type's newRowValue
|
|
38
|
+
* (the next autonumber, the created time, today), else the field's default.
|
|
39
|
+
* `base` (the row adder's own defaults) wins over both.
|
|
40
|
+
*/
|
|
41
|
+
export declare function newRowValues(ctrl: Ctrl, base?: Record<string, unknown>): Record<string, unknown>;
|
|
42
|
+
/**
|
|
43
|
+
* The values a duplicate of `row` starts with: its stored fields, lists
|
|
44
|
+
* copied, without its id or what is stamped on a new record (a type with
|
|
45
|
+
* `copy: false`). Give them to `newRowValues` for the rest.
|
|
46
|
+
*/
|
|
47
|
+
export declare function recordCopyValues(ctrl: Ctrl, row: Record<string, unknown>): Record<string, unknown>;
|
|
48
|
+
/** What changing `columnId` to `draft` would clear: cells not empty now, empty after. */
|
|
49
|
+
export declare function previewChange(ctrl: Ctrl, columnId: string, draft: FieldDraft): number;
|
|
50
|
+
/** Apply the editor's draft to an existing field; converts values when the type changes. */
|
|
51
|
+
export declare function updateField(ctrl: Ctrl, columnId: string, draft: FieldDraft): Def | null;
|
|
52
|
+
/**
|
|
53
|
+
* Add choices to a select field, as typing a new value into its cell does.
|
|
54
|
+
* Options already there (same value) are skipped; fires onColumnChange.
|
|
55
|
+
*/
|
|
56
|
+
export declare function addSelectOptions(ctrl: Ctrl, columnId: string, added: ReadonlyArray<{
|
|
57
|
+
value: string;
|
|
58
|
+
color?: string;
|
|
59
|
+
}>): Def | null;
|
|
60
|
+
/**
|
|
61
|
+
* The summary a field shows in the footer row (`fieldProps.summary`, from
|
|
62
|
+
* the footer's picker; 'none' clears it). Fires onColumnChange.
|
|
63
|
+
*/
|
|
64
|
+
export declare function setFieldSummary(ctrl: Ctrl, columnId: string, kind: string): Def | null;
|
|
65
|
+
/** A copy of a field, values included, right after it. */
|
|
66
|
+
export declare function duplicateField(ctrl: Ctrl, columnId: string): Def | null;
|
|
67
|
+
/** Remove a field's column (its values stay in the rows). */
|
|
68
|
+
export declare function removeField(ctrl: Ctrl, columnId: string): void;
|
|
69
|
+
export declare function hideField(ctrl: Ctrl, columnId: string): void;
|
|
70
|
+
/** The index a field inserted next to `columnId` goes to. */
|
|
71
|
+
export declare function indexBeside(ctrl: Ctrl, columnId: string, side: 'left' | 'right'): number;
|
|
72
|
+
export {};
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the field editor and the column menu do to a grid: add, edit, insert,
|
|
3
|
+
* duplicate and delete a field. They work on the grid's own columns and rows
|
|
4
|
+
* and report each change (onColumnAdd / onColumnChange / onColumnRemove) so
|
|
5
|
+
* the app can store its schema; the grid keeps none.
|
|
6
|
+
*
|
|
7
|
+
* A column the app hands over keeps its plain shape here: `id`, `field`,
|
|
8
|
+
* `header`, `width`, `fieldType`, `fieldProps`, `description`. What a type fills
|
|
9
|
+
* in (editor, format, alignment...) is recomputed from that on every change.
|
|
10
|
+
*/
|
|
11
|
+
import { convertValue, countCleared, keepsStoredValues, optionsFromValues } from './convert.js';
|
|
12
|
+
import { renameFormulaRefs } from './formula.js';
|
|
13
|
+
import { fieldPropsOf, fillFieldColumn, getFieldType, originalColumn } from './registry.svelte.js';
|
|
14
|
+
import { getLinkedTable, linkedRows } from './sources.svelte.js';
|
|
15
|
+
/** Keys a field type fills in. A type change drops them from the declared column too, so the new type's take. */
|
|
16
|
+
const FILLED = ['editorType', 'cellDataType', 'format', 'align', 'editorOptions', 'editorMultiple', 'formatter', 'valueParser'];
|
|
17
|
+
export const defId = (d) => String(d.id ?? d.field ?? '');
|
|
18
|
+
/** The column as the app declared it, without what its type filled in. */
|
|
19
|
+
export function plainDef(d) {
|
|
20
|
+
return { ...originalColumn(d) };
|
|
21
|
+
}
|
|
22
|
+
/** The declared columns after a change: what every field event hands the app. */
|
|
23
|
+
export const plainColumns = (ctrl) => ctrl.internalColumns.map((d) => plainDef(d));
|
|
24
|
+
/** A new column id from a name: lower-case words, unique among the grid's columns. */
|
|
25
|
+
export function uniqueId(name, taken) {
|
|
26
|
+
const used = new Set(taken);
|
|
27
|
+
const base = name.trim().toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '') || 'field';
|
|
28
|
+
let id = base;
|
|
29
|
+
for (let i = 2; used.has(id); i++)
|
|
30
|
+
id = `${base}_${i}`;
|
|
31
|
+
return id;
|
|
32
|
+
}
|
|
33
|
+
/** Whether `name` is free: no other column has that header (case-insensitive). */
|
|
34
|
+
export function nameTaken(ctrl, name, exceptId) {
|
|
35
|
+
const n = name.trim().toLowerCase();
|
|
36
|
+
return ctrl.internalColumns.some((d) => defId(d) !== exceptId && String(d.header ?? '').trim().toLowerCase() === n);
|
|
37
|
+
}
|
|
38
|
+
function cleanProps(p) {
|
|
39
|
+
const out = {};
|
|
40
|
+
for (const [k, v] of Object.entries(p))
|
|
41
|
+
if (v !== undefined && v !== '' && !(Array.isArray(v) && v.length === 0 && k !== 'options'))
|
|
42
|
+
out[k] = v;
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Fill every field column again against `cols`: a formula, lookup or button
|
|
47
|
+
* that names another field must see a renamed, added or removed one.
|
|
48
|
+
*/
|
|
49
|
+
function refill(cols) {
|
|
50
|
+
return cols.map((c) => (originalColumn(c).fieldType ? fillFieldColumn(originalColumn(c), cols) : c));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Scroll the grid sideways, and only the grid, until a column just added is
|
|
54
|
+
* in view: one added past the right edge would otherwise go unseen.
|
|
55
|
+
*/
|
|
56
|
+
function revealColumn(ctrl, id) {
|
|
57
|
+
if (typeof requestAnimationFrame !== 'function')
|
|
58
|
+
return;
|
|
59
|
+
requestAnimationFrame(() => {
|
|
60
|
+
const sc = ctrl.scrollContainer;
|
|
61
|
+
// `id` comes from uniqueId: [a-z0-9_] only, safe in a selector as is.
|
|
62
|
+
const th = sc?.querySelector(`[data-svgrid-header-col="${id}"]`);
|
|
63
|
+
if (!sc || !th)
|
|
64
|
+
return;
|
|
65
|
+
const box = sc.getBoundingClientRect();
|
|
66
|
+
const r = th.getBoundingClientRect();
|
|
67
|
+
const right = box.left + sc.clientWidth;
|
|
68
|
+
if (r.right > right)
|
|
69
|
+
sc.scrollLeft += Math.min(r.right - right, r.left - box.left);
|
|
70
|
+
else if (r.left < box.left)
|
|
71
|
+
sc.scrollLeft -= box.left - r.left;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function insertAt(cols, def, index) {
|
|
75
|
+
const next = cols.slice();
|
|
76
|
+
next.splice(index === 'end' ? next.length : Math.max(0, Math.min(index, next.length)), 0, def);
|
|
77
|
+
return next;
|
|
78
|
+
}
|
|
79
|
+
/** Add a field from the editor. Returns the plain column. */
|
|
80
|
+
export function addField(ctrl, draft, index = 'end') {
|
|
81
|
+
const id = uniqueId(draft.name, ctrl.internalColumns.map(defId));
|
|
82
|
+
const type = getFieldType(draft.fieldType);
|
|
83
|
+
const def = {
|
|
84
|
+
id,
|
|
85
|
+
field: id,
|
|
86
|
+
header: draft.name.trim(),
|
|
87
|
+
width: type?.width ?? 150,
|
|
88
|
+
fieldType: draft.fieldType,
|
|
89
|
+
fieldProps: cleanProps(draft.fieldProps),
|
|
90
|
+
...(draft.description?.trim() ? { description: draft.description.trim() } : {}),
|
|
91
|
+
};
|
|
92
|
+
// Autonumber and created time give every existing row its value now.
|
|
93
|
+
let data;
|
|
94
|
+
const values = type?.onCreate?.({ props: fieldPropsOf(def), field: id, rows: ctrl.internalData });
|
|
95
|
+
if (values) {
|
|
96
|
+
data = ctrl.internalData.map((r, i) => (r == null ? r : { ...r, [id]: values[i] }));
|
|
97
|
+
ctrl.internalData = data;
|
|
98
|
+
}
|
|
99
|
+
ctrl.internalColumns = refill(insertAt(ctrl.internalColumns, def, index));
|
|
100
|
+
ctrl.props.onColumnAdd?.({ column: def, columns: plainColumns(ctrl), ...(data ? { data } : {}) });
|
|
101
|
+
revealColumn(ctrl, id);
|
|
102
|
+
return def;
|
|
103
|
+
}
|
|
104
|
+
let seq = 0;
|
|
105
|
+
/** A new record id: "rec" and nine letters and digits, unique in this page. */
|
|
106
|
+
export function newRecordId() {
|
|
107
|
+
seq = (seq + 1) % 1296;
|
|
108
|
+
return `rec${Date.now().toString(36).slice(-5)}${Math.random().toString(36).slice(2, 4)}${seq.toString(36).padStart(2, '0')}`;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The values a new row gets from its field columns: each type's newRowValue
|
|
112
|
+
* (the next autonumber, the created time, today), else the field's default.
|
|
113
|
+
* `base` (the row adder's own defaults) wins over both.
|
|
114
|
+
*/
|
|
115
|
+
export function newRowValues(ctrl, base = {}) {
|
|
116
|
+
const row = {};
|
|
117
|
+
for (const c of ctrl.internalColumns) {
|
|
118
|
+
const plain = originalColumn(c);
|
|
119
|
+
if (!plain.fieldType || !c.field)
|
|
120
|
+
continue;
|
|
121
|
+
const field = String(c.field);
|
|
122
|
+
const props = fieldPropsOf(plain);
|
|
123
|
+
const fromType = getFieldType(plain.fieldType)?.newRowValue?.({ props, field, rows: ctrl.internalData });
|
|
124
|
+
const value = fromType !== undefined ? fromType : props.default;
|
|
125
|
+
if (value !== undefined)
|
|
126
|
+
row[field] = Array.isArray(value) ? value.slice() : value;
|
|
127
|
+
}
|
|
128
|
+
// A table whose records carry an id (a base, or rows keyed with getRowId on
|
|
129
|
+
// `id`) needs one on the new record too, or two new records share a key.
|
|
130
|
+
if (!('id' in base) && (ctrl.internalData ?? []).some((r) => r && typeof r === 'object' && 'id' in r))
|
|
131
|
+
row.id = newRecordId();
|
|
132
|
+
return { ...row, ...base };
|
|
133
|
+
}
|
|
134
|
+
/** Built-in fields a copy of a record gets fresh, never copied: its number, when and by whom it was made. */
|
|
135
|
+
const STAMPED = new Set(['autoNumber', 'createdTime', 'createdBy', 'lastModifiedTime', 'lastModifiedBy']);
|
|
136
|
+
/** Whether a duplicate gets this field fresh: a built-in stamp, or a type registered with `copy: false`. */
|
|
137
|
+
const freshOnCopy = (fieldType) => STAMPED.has(String(fieldType)) || getFieldType(fieldType)?.copy === false;
|
|
138
|
+
/**
|
|
139
|
+
* The values a duplicate of `row` starts with: its stored fields, lists
|
|
140
|
+
* copied, without its id or what is stamped on a new record (a type with
|
|
141
|
+
* `copy: false`). Give them to `newRowValues` for the rest.
|
|
142
|
+
*/
|
|
143
|
+
export function recordCopyValues(ctrl, row) {
|
|
144
|
+
const out = {};
|
|
145
|
+
for (const c of ctrl.internalColumns) {
|
|
146
|
+
const plain = originalColumn(c);
|
|
147
|
+
if (!c.field || c.fieldFn || plain.fieldFn || freshOnCopy(plain.fieldType))
|
|
148
|
+
continue;
|
|
149
|
+
const v = row[String(c.field)];
|
|
150
|
+
if (v !== undefined)
|
|
151
|
+
out[String(c.field)] = Array.isArray(v) ? v.slice() : v;
|
|
152
|
+
}
|
|
153
|
+
return out;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* A field's values as a type change converts them: what a formula, lookup,
|
|
157
|
+
* rollup or count works out (its records store nothing), a link's records by
|
|
158
|
+
* their primary field (names, not record ids), else what the records store.
|
|
159
|
+
*/
|
|
160
|
+
function valuesToConvert(ctrl, filled, to) {
|
|
161
|
+
const field = String(filled.field);
|
|
162
|
+
const stored = ctrl.internalData.map((r) => r?.[field]);
|
|
163
|
+
if (keepsStoredValues(to))
|
|
164
|
+
return stored;
|
|
165
|
+
const plain = originalColumn(filled);
|
|
166
|
+
// Filled again against today's fields, so the values are the ones shown now.
|
|
167
|
+
const fn = (plain.fieldType ? fillFieldColumn(plain, ctrl.internalColumns) : filled).fieldFn;
|
|
168
|
+
if (typeof fn === 'function') {
|
|
169
|
+
// A formula that does not compile has nothing to keep.
|
|
170
|
+
return ctrl.internalData.map((r) => {
|
|
171
|
+
if (r == null)
|
|
172
|
+
return undefined;
|
|
173
|
+
const v = fn(r);
|
|
174
|
+
return v === '#ERROR' ? null : v;
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
if (plain.fieldType === 'link' && to !== 'link') {
|
|
178
|
+
const table = getLinkedTable(fieldPropsOf(plain).table);
|
|
179
|
+
if (table)
|
|
180
|
+
return stored.map((v) => linkedRows(table, v).map((r) => r[table.primaryField]).filter((x) => x != null && x !== ''));
|
|
181
|
+
}
|
|
182
|
+
return stored;
|
|
183
|
+
}
|
|
184
|
+
/** What changing `columnId` to `draft` would clear: cells not empty now, empty after. */
|
|
185
|
+
export function previewChange(ctrl, columnId, draft) {
|
|
186
|
+
const prev = ctrl.internalColumns.find((d) => defId(d) === columnId);
|
|
187
|
+
if (!prev || prev.fieldType === draft.fieldType || !prev.field)
|
|
188
|
+
return 0;
|
|
189
|
+
return countCleared(valuesToConvert(ctrl, prev, draft.fieldType), prev.fieldType, draft.fieldType, cleanProps(draft.fieldProps));
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Other formulas of the table after a field's header changes from `from` to
|
|
193
|
+
* `to`: each `{from}` that named the field now reads `{to}`. A `{field key}`
|
|
194
|
+
* reference needs nothing, a rename leaves the key as it was.
|
|
195
|
+
*/
|
|
196
|
+
function renameInFormulas(cols, field, from, to) {
|
|
197
|
+
const old = from.trim().toLowerCase();
|
|
198
|
+
if (!old || old === to.trim().toLowerCase())
|
|
199
|
+
return cols;
|
|
200
|
+
return cols.map((c) => {
|
|
201
|
+
const plain = originalColumn(c);
|
|
202
|
+
if (plain.fieldType !== 'formula' || String(plain.field ?? plain.id) === field)
|
|
203
|
+
return c;
|
|
204
|
+
const src = String(plain.fieldProps?.formula ?? '');
|
|
205
|
+
const next = renameFormulaRefs(src, (name) => (name.trim().toLowerCase() === old ? to : null));
|
|
206
|
+
return next === src ? c : { ...plain, fieldProps: { ...plain.fieldProps, formula: next } };
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
/** Apply the editor's draft to an existing field; converts values when the type changes. */
|
|
210
|
+
export function updateField(ctrl, columnId, draft) {
|
|
211
|
+
const index = ctrl.internalColumns.findIndex((d) => defId(d) === columnId);
|
|
212
|
+
if (index < 0)
|
|
213
|
+
return null;
|
|
214
|
+
const previous = plainDef(ctrl.internalColumns[index]);
|
|
215
|
+
const typeChanged = previous.fieldType !== draft.fieldType;
|
|
216
|
+
const fieldProps = cleanProps(draft.fieldProps);
|
|
217
|
+
let data;
|
|
218
|
+
if (typeChanged && previous.field) {
|
|
219
|
+
const field = String(previous.field);
|
|
220
|
+
const before = valuesToConvert(ctrl, ctrl.internalColumns[index], draft.fieldType);
|
|
221
|
+
data = ctrl.internalData.map((r, i) => r == null ? r : { ...r, [field]: convertValue(before[i], previous.fieldType, draft.fieldType, fieldProps) });
|
|
222
|
+
// A select made from other values starts with those values as its options.
|
|
223
|
+
if ((draft.fieldType === 'singleSelect' || draft.fieldType === 'multiSelect') && !fieldProps.options?.length) {
|
|
224
|
+
fieldProps.options = optionsFromValues(data.map((r) => r?.[field]));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const base = { ...previous };
|
|
228
|
+
if (typeChanged)
|
|
229
|
+
for (const k of FILLED)
|
|
230
|
+
delete base[k];
|
|
231
|
+
const next = { ...base, header: draft.name.trim(), fieldType: draft.fieldType, fieldProps };
|
|
232
|
+
if (draft.description?.trim())
|
|
233
|
+
next.description = draft.description.trim();
|
|
234
|
+
else
|
|
235
|
+
delete next.description;
|
|
236
|
+
let cols = ctrl.internalColumns.slice();
|
|
237
|
+
cols[index] = next;
|
|
238
|
+
// A rename carries over to the formulas that name the field by its header.
|
|
239
|
+
if (typeof previous.header === 'string' && previous.field)
|
|
240
|
+
cols = renameInFormulas(cols, String(previous.field), previous.header, String(next.header));
|
|
241
|
+
ctrl.internalColumns = refill(cols);
|
|
242
|
+
if (data)
|
|
243
|
+
ctrl.internalData = data;
|
|
244
|
+
ctrl.props.onColumnChange?.({ column: next, previous, columns: plainColumns(ctrl), ...(data ? { data } : {}) });
|
|
245
|
+
return next;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Add choices to a select field, as typing a new value into its cell does.
|
|
249
|
+
* Options already there (same value) are skipped; fires onColumnChange.
|
|
250
|
+
*/
|
|
251
|
+
export function addSelectOptions(ctrl, columnId, added) {
|
|
252
|
+
const index = ctrl.internalColumns.findIndex((d) => defId(d) === columnId);
|
|
253
|
+
if (index < 0 || !added.length)
|
|
254
|
+
return null;
|
|
255
|
+
const previous = plainDef(ctrl.internalColumns[index]);
|
|
256
|
+
const options = Array.isArray(previous.fieldProps?.options) ? previous.fieldProps.options.slice() : [];
|
|
257
|
+
const have = new Set(options.map((o) => String(o.value)));
|
|
258
|
+
for (const o of added) {
|
|
259
|
+
if (have.has(o.value))
|
|
260
|
+
continue;
|
|
261
|
+
have.add(o.value);
|
|
262
|
+
options.push({ ...o });
|
|
263
|
+
}
|
|
264
|
+
const next = { ...previous, fieldProps: { ...previous.fieldProps, options } };
|
|
265
|
+
const cols = ctrl.internalColumns.slice();
|
|
266
|
+
cols[index] = next;
|
|
267
|
+
ctrl.internalColumns = refill(cols);
|
|
268
|
+
ctrl.props.onColumnChange?.({ column: next, previous, columns: plainColumns(ctrl) });
|
|
269
|
+
return next;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* The summary a field shows in the footer row (`fieldProps.summary`, from
|
|
273
|
+
* the footer's picker; 'none' clears it). Fires onColumnChange.
|
|
274
|
+
*/
|
|
275
|
+
export function setFieldSummary(ctrl, columnId, kind) {
|
|
276
|
+
const index = ctrl.internalColumns.findIndex((d) => defId(d) === columnId);
|
|
277
|
+
if (index < 0)
|
|
278
|
+
return null;
|
|
279
|
+
const previous = plainDef(ctrl.internalColumns[index]);
|
|
280
|
+
const fieldProps = { ...previous.fieldProps };
|
|
281
|
+
if (kind === 'none')
|
|
282
|
+
delete fieldProps.summary;
|
|
283
|
+
else
|
|
284
|
+
fieldProps.summary = kind;
|
|
285
|
+
const next = { ...previous, fieldProps };
|
|
286
|
+
const cols = ctrl.internalColumns.slice();
|
|
287
|
+
cols[index] = next;
|
|
288
|
+
ctrl.internalColumns = refill(cols);
|
|
289
|
+
ctrl.props.onColumnChange?.({ column: next, previous, columns: plainColumns(ctrl) });
|
|
290
|
+
return next;
|
|
291
|
+
}
|
|
292
|
+
/** A copy of a field, values included, right after it. */
|
|
293
|
+
export function duplicateField(ctrl, columnId) {
|
|
294
|
+
const index = ctrl.internalColumns.findIndex((d) => defId(d) === columnId);
|
|
295
|
+
if (index < 0)
|
|
296
|
+
return null;
|
|
297
|
+
const source = plainDef(ctrl.internalColumns[index]);
|
|
298
|
+
const header = `${String(source.header ?? columnId)} copy`;
|
|
299
|
+
const id = uniqueId(header, ctrl.internalColumns.map(defId));
|
|
300
|
+
const def = { ...source, id, field: id, header };
|
|
301
|
+
let data;
|
|
302
|
+
if (source.field) {
|
|
303
|
+
const from = String(source.field);
|
|
304
|
+
data = ctrl.internalData.map((r) => (r == null ? r : { ...r, [id]: structuredCloneSafe(r[from]) }));
|
|
305
|
+
ctrl.internalData = data;
|
|
306
|
+
}
|
|
307
|
+
ctrl.internalColumns = refill(insertAt(ctrl.internalColumns, def, index + 1));
|
|
308
|
+
ctrl.props.onColumnAdd?.({ column: def, columns: plainColumns(ctrl), ...(data ? { data } : {}) });
|
|
309
|
+
revealColumn(ctrl, id);
|
|
310
|
+
return def;
|
|
311
|
+
}
|
|
312
|
+
/** Remove a field's column (its values stay in the rows). */
|
|
313
|
+
export function removeField(ctrl, columnId) {
|
|
314
|
+
ctrl.internalColumns = refill(ctrl.internalColumns.filter((d) => defId(d) !== columnId));
|
|
315
|
+
ctrl.props.onColumnRemove?.({ columnId, columns: plainColumns(ctrl) });
|
|
316
|
+
}
|
|
317
|
+
export function hideField(ctrl, columnId) {
|
|
318
|
+
ctrl.buildApi?.()?.setColumnVisible?.(columnId, false);
|
|
319
|
+
}
|
|
320
|
+
/** The index a field inserted next to `columnId` goes to. */
|
|
321
|
+
export function indexBeside(ctrl, columnId, side) {
|
|
322
|
+
const i = ctrl.internalColumns.findIndex((d) => defId(d) === columnId);
|
|
323
|
+
return i < 0 ? ctrl.internalColumns.length : side === 'left' ? i : i + 1;
|
|
324
|
+
}
|
|
325
|
+
function structuredCloneSafe(v) {
|
|
326
|
+
if (v == null || typeof v !== 'object')
|
|
327
|
+
return v;
|
|
328
|
+
try {
|
|
329
|
+
return structuredClone(v);
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
return Array.isArray(v) ? v.slice() : { ...v };
|
|
333
|
+
}
|
|
334
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The view bar's filter: conditions on fields, each with the operators that
|
|
3
|
+
* fit its type ("has any of" for a multiple select, "is within the past
|
|
4
|
+
* week" for a date), joined by "and" or "or", one level of groups deep.
|
|
5
|
+
*
|
|
6
|
+
* It is the grid's advanced filter (`api.setAdvancedFilter`) with its own
|
|
7
|
+
* expression kind, `fieldFilter`, so it is saved and restored with the rest
|
|
8
|
+
* of the grid's state.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* A person condition's value meaning whoever is signed in (`setCurrentUser`)
|
|
12
|
+
* when the filter runs, so one "My tasks" view works for everyone. With
|
|
13
|
+
* nobody signed in it matches no one.
|
|
14
|
+
*/
|
|
15
|
+
export declare const ME = "@me";
|
|
16
|
+
export declare function resolveMeWith(fn: () => string | undefined): void;
|
|
17
|
+
/** What a condition compares, from the field's type. */
|
|
18
|
+
export type FilterKind = 'text' | 'number' | 'select' | 'multi' | 'checkbox' | 'date' | 'files' | 'link';
|
|
19
|
+
export type FilterOp = 'contains' | 'notContains' | 'is' | 'isNot' | 'isEmpty' | 'isNotEmpty' | 'eq' | 'neq' | 'lt' | 'gt' | 'lte' | 'gte' | 'isAnyOf' | 'isNoneOf' | 'hasAnyOf' | 'hasAllOf' | 'hasNoneOf' | 'isExactly' | 'isBefore' | 'isAfter' | 'isOnOrBefore' | 'isOnOrAfter' | 'isWithin';
|
|
20
|
+
/** A day a date condition names, relative to today or exact. */
|
|
21
|
+
export type DateTarget = {
|
|
22
|
+
mode: 'today' | 'tomorrow' | 'yesterday' | 'oneWeekAgo' | 'oneWeekFromNow' | 'oneMonthAgo' | 'oneMonthFromNow';
|
|
23
|
+
} | {
|
|
24
|
+
mode: 'exactDate';
|
|
25
|
+
date: string;
|
|
26
|
+
};
|
|
27
|
+
/** The span "is within" names. */
|
|
28
|
+
export type DateSpan = {
|
|
29
|
+
span: 'pastWeek' | 'pastMonth' | 'pastYear' | 'nextWeek' | 'nextMonth' | 'nextYear' | 'pastDays' | 'nextDays';
|
|
30
|
+
days?: number;
|
|
31
|
+
};
|
|
32
|
+
export type FieldCondition = {
|
|
33
|
+
/** The column id. */
|
|
34
|
+
column: string;
|
|
35
|
+
kind: FilterKind;
|
|
36
|
+
op: FilterOp;
|
|
37
|
+
value?: unknown;
|
|
38
|
+
/** A link field's table, to match its records by name. */
|
|
39
|
+
table?: string;
|
|
40
|
+
};
|
|
41
|
+
export type FieldConditionGroup = {
|
|
42
|
+
conjunction: 'and' | 'or';
|
|
43
|
+
conditions: FieldCondition[];
|
|
44
|
+
};
|
|
45
|
+
export type FieldFilter = {
|
|
46
|
+
kind: 'fieldFilter';
|
|
47
|
+
conjunction: 'and' | 'or';
|
|
48
|
+
conditions: Array<FieldCondition | FieldConditionGroup>;
|
|
49
|
+
};
|
|
50
|
+
export declare const isGroup: (c: FieldCondition | FieldConditionGroup) => c is FieldConditionGroup;
|
|
51
|
+
/**
|
|
52
|
+
* The kind of comparison a column gets; null for one that cannot be filtered
|
|
53
|
+
* (a button). A built-in type decides it; a computed type (formula, lookup,
|
|
54
|
+
* rollup), a type the app registered, and a plain column follow the
|
|
55
|
+
* column's cellDataType, as the footer summaries do.
|
|
56
|
+
*/
|
|
57
|
+
export declare function filterKindOf(def: Record<string, any>): FilterKind | null;
|
|
58
|
+
/** The operators a kind offers, in the order the menu shows them. */
|
|
59
|
+
export declare function operatorsFor(kind: FilterKind): ReadonlyArray<{
|
|
60
|
+
op: FilterOp;
|
|
61
|
+
label: string;
|
|
62
|
+
}>;
|
|
63
|
+
/** The value a new condition starts with for an operator. */
|
|
64
|
+
export declare function defaultValue(kind: FilterKind, op: FilterOp): unknown;
|
|
65
|
+
/** A new condition on a column, with its first operator. */
|
|
66
|
+
export declare function newCondition(column: string, def: Record<string, any>): FieldCondition | null;
|
|
67
|
+
/** Whether a condition says enough to filter: an empty value is a condition still being written. */
|
|
68
|
+
export declare function isComplete(c: FieldCondition): boolean;
|
|
69
|
+
/** How many complete conditions a filter has (the view bar's count). */
|
|
70
|
+
export declare function conditionCount(filter: FieldFilter | null | undefined): number;
|
|
71
|
+
/** What turns a link value (record ids) into the linked records' names. */
|
|
72
|
+
export type LinkNames = (table: string, value: unknown) => string[];
|
|
73
|
+
/** A value's day as a count of local days, or null. */
|
|
74
|
+
export declare function dayOf(v: unknown): number | null;
|
|
75
|
+
/** One condition as a test of a cell value. */
|
|
76
|
+
export declare function compileCondition(c: FieldCondition, linkNames?: LinkNames, now?: Date): (value: unknown) => boolean;
|
|
77
|
+
/** A whole filter as a row test; incomplete conditions are left out. Null when nothing filters. */
|
|
78
|
+
export declare function compileFieldFilter<TRow>(filter: FieldFilter, getValue: (row: TRow, columnId: string) => unknown, linkNames?: LinkNames, now?: Date): ((row: TRow) => boolean) | null;
|
|
79
|
+
/** One condition as words: "Status is Done", "Due date is before today". */
|
|
80
|
+
export declare function describeCondition(c: FieldCondition, name?: (columnId: string) => string): string;
|
|
81
|
+
/** A filter as words, groups in parentheses; incomplete conditions are left out. */
|
|
82
|
+
export declare function describeFieldFilter(filter: FieldFilter, name?: (columnId: string) => string): string;
|
|
83
|
+
/** The columns a filter's complete conditions read, each once. */
|
|
84
|
+
export declare function fieldFilterColumns(filter: FieldFilter): string[];
|