@adecore/database 0.0.1 → 0.16.0-beta.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.
- package/LICENSE +21 -0
- package/README.md +152 -1
- package/dist/DatabaseProvider.d.ts +13 -0
- package/dist/DatabaseProvider.js +17 -0
- package/dist/actions.d.ts +40 -0
- package/dist/actions.js +1 -0
- package/dist/client/client.d.ts +5 -0
- package/dist/client/client.js +245 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +2 -0
- package/dist/client/types.d.ts +97 -0
- package/dist/client/types.js +13 -0
- package/dist/client-context.d.ts +16 -0
- package/dist/client-context.js +17 -0
- package/dist/connections/ConnectionForm.d.ts +10 -0
- package/dist/connections/ConnectionForm.js +145 -0
- package/dist/connections/ConnectionManager.d.ts +12 -0
- package/dist/connections/ConnectionManager.js +93 -0
- package/dist/connections/EngineIcon.d.ts +9 -0
- package/dist/connections/EngineIcon.js +7 -0
- package/dist/connections/connection-config.d.ts +16 -0
- package/dist/connections/connection-config.js +107 -0
- package/dist/connections/docker.d.ts +9 -0
- package/dist/connections/docker.js +38 -0
- package/dist/connections/engine-icons.d.ts +3 -0
- package/dist/connections/engine-icons.js +3 -0
- package/dist/connections/use-docker-containers.d.ts +17 -0
- package/dist/connections/use-docker-containers.js +26 -0
- package/dist/console/DestructiveDialog.d.ts +9 -0
- package/dist/console/DestructiveDialog.js +9 -0
- package/dist/console/HistoryPanel.d.ts +10 -0
- package/dist/console/HistoryPanel.js +15 -0
- package/dist/console/QueryConsole.d.ts +14 -0
- package/dist/console/QueryConsole.js +261 -0
- package/dist/console/SchemaPicker.d.ts +11 -0
- package/dist/console/SchemaPicker.js +8 -0
- package/dist/console/SqlEditor.d.ts +12 -0
- package/dist/console/SqlEditor.js +61 -0
- package/dist/console/StatementResultView.d.ts +18 -0
- package/dist/console/StatementResultView.js +32 -0
- package/dist/console/TransactionControls.d.ts +13 -0
- package/dist/console/TransactionControls.js +12 -0
- package/dist/console/destructive.d.ts +7 -0
- package/dist/console/destructive.js +43 -0
- package/dist/console/editing.d.ts +12 -0
- package/dist/console/editing.js +60 -0
- package/dist/console/history.d.ts +13 -0
- package/dist/console/history.js +43 -0
- package/dist/console/labels.d.ts +1 -0
- package/dist/console/labels.js +6 -0
- package/dist/console/outcome.d.ts +6 -0
- package/dist/console/outcome.js +11 -0
- package/dist/console/schemas.d.ts +2 -0
- package/dist/console/schemas.js +5 -0
- package/dist/console/shortcuts.d.ts +2 -0
- package/dist/console/shortcuts.js +3 -0
- package/dist/console/useConsoleHistory.d.ts +7 -0
- package/dist/console/useConsoleHistory.js +22 -0
- package/dist/ddl/alter-mysql.d.ts +4 -0
- package/dist/ddl/alter-mysql.js +79 -0
- package/dist/ddl/alter-sqlite.d.ts +4 -0
- package/dist/ddl/alter-sqlite.js +80 -0
- package/dist/ddl/alter.d.ts +4 -0
- package/dist/ddl/alter.js +24 -0
- package/dist/ddl/column.d.ts +9 -0
- package/dist/ddl/column.js +62 -0
- package/dist/ddl/create.d.ts +12 -0
- package/dist/ddl/create.js +74 -0
- package/dist/ddl/dialect.d.ts +12 -0
- package/dist/ddl/dialect.js +34 -0
- package/dist/ddl/diff.d.ts +34 -0
- package/dist/ddl/diff.js +111 -0
- package/dist/ddl/draft.d.ts +46 -0
- package/dist/ddl/draft.js +70 -0
- package/dist/ddl/index.d.ts +10 -0
- package/dist/ddl/index.js +10 -0
- package/dist/ddl/parse.d.ts +17 -0
- package/dist/ddl/parse.js +131 -0
- package/dist/ddl/statements.d.ts +6 -0
- package/dist/ddl/statements.js +12 -0
- package/dist/ddl/types.d.ts +6 -0
- package/dist/ddl/types.js +52 -0
- package/dist/ddl/validate.d.ts +7 -0
- package/dist/ddl/validate.js +38 -0
- package/dist/designer/ColumnsEditor.d.ts +2 -0
- package/dist/designer/ColumnsEditor.js +24 -0
- package/dist/designer/DesignerView.d.ts +25 -0
- package/dist/designer/DesignerView.js +33 -0
- package/dist/designer/ForeignKeysEditor.d.ts +7 -0
- package/dist/designer/ForeignKeysEditor.js +24 -0
- package/dist/designer/IndexesEditor.d.ts +2 -0
- package/dist/designer/IndexesEditor.js +13 -0
- package/dist/designer/NamePicker.d.ts +11 -0
- package/dist/designer/NamePicker.js +13 -0
- package/dist/designer/OptionsEditor.d.ts +2 -0
- package/dist/designer/OptionsEditor.js +17 -0
- package/dist/designer/SqlPreview.d.ts +12 -0
- package/dist/designer/SqlPreview.js +17 -0
- package/dist/designer/TableDesigner.d.ts +10 -0
- package/dist/designer/TableDesigner.js +103 -0
- package/dist/designer/edit.d.ts +17 -0
- package/dist/designer/edit.js +115 -0
- package/dist/designer/editor-props.d.ts +10 -0
- package/dist/designer/editor-props.js +1 -0
- package/dist/designer/plan.d.ts +9 -0
- package/dist/designer/plan.js +13 -0
- package/dist/designer/recover.d.ts +2 -0
- package/dist/designer/recover.js +18 -0
- package/dist/designer/useReferenceColumns.d.ts +3 -0
- package/dist/designer/useReferenceColumns.js +36 -0
- package/dist/explorer/DatabaseExplorer.d.ts +13 -0
- package/dist/explorer/DatabaseExplorer.js +264 -0
- package/dist/explorer/RowMenu.d.ts +11 -0
- package/dist/explorer/RowMenu.js +89 -0
- package/dist/explorer/TableDialog.d.ts +15 -0
- package/dist/explorer/TableDialog.js +50 -0
- package/dist/explorer/expansion.d.ts +7 -0
- package/dist/explorer/expansion.js +31 -0
- package/dist/explorer/table-statements.d.ts +5 -0
- package/dist/explorer/table-statements.js +12 -0
- package/dist/explorer/tree.d.ts +125 -0
- package/dist/explorer/tree.js +295 -0
- package/dist/explorer/use-explorer-loads.d.ts +12 -0
- package/dist/explorer/use-explorer-loads.js +109 -0
- package/dist/explorer/use-stored-expansion.d.ts +9 -0
- package/dist/explorer/use-stored-expansion.js +47 -0
- package/dist/grid/CellEditor.d.ts +9 -0
- package/dist/grid/CellEditor.js +29 -0
- package/dist/grid/CopyAsMenu.d.ts +7 -0
- package/dist/grid/CopyAsMenu.js +10 -0
- package/dist/grid/DataGrid.d.ts +36 -0
- package/dist/grid/DataGrid.js +512 -0
- package/dist/grid/EnumPicker.d.ts +17 -0
- package/dist/grid/EnumPicker.js +53 -0
- package/dist/grid/GridHeaderCell.d.ts +36 -0
- package/dist/grid/GridHeaderCell.js +69 -0
- package/dist/grid/RecordView.d.ts +20 -0
- package/dist/grid/RecordView.js +126 -0
- package/dist/grid/ValueDock.d.ts +11 -0
- package/dist/grid/ValueDock.js +28 -0
- package/dist/grid/aggregates.d.ts +22 -0
- package/dist/grid/aggregates.js +62 -0
- package/dist/grid/cell-range.d.ts +14 -0
- package/dist/grid/cell-range.js +11 -0
- package/dist/grid/column-layout.d.ts +18 -0
- package/dist/grid/column-layout.js +49 -0
- package/dist/grid/column-selection.d.ts +11 -0
- package/dist/grid/column-selection.js +28 -0
- package/dist/grid/column-view.d.ts +10 -0
- package/dist/grid/column-view.js +23 -0
- package/dist/grid/copy-formats.d.ts +15 -0
- package/dist/grid/copy-formats.js +80 -0
- package/dist/grid/display.d.ts +20 -0
- package/dist/grid/display.js +81 -0
- package/dist/grid/edit-value.d.ts +5 -0
- package/dist/grid/edit-value.js +55 -0
- package/dist/grid/enum-type.d.ts +7 -0
- package/dist/grid/enum-type.js +52 -0
- package/dist/grid/focused-value.d.ts +4 -0
- package/dist/grid/focused-value.js +19 -0
- package/dist/grid/layout.d.ts +22 -0
- package/dist/grid/layout.js +74 -0
- package/dist/grid/navigation.d.ts +15 -0
- package/dist/grid/navigation.js +52 -0
- package/dist/grid/row-selection.d.ts +9 -0
- package/dist/grid/row-selection.js +24 -0
- package/dist/grid/sort.d.ts +7 -0
- package/dist/grid/sort.js +7 -0
- package/dist/grid/types.d.ts +30 -0
- package/dist/grid/types.js +9 -0
- package/dist/host/helper-path.d.ts +7 -0
- package/dist/host/helper-path.js +15 -0
- package/dist/host/host.d.ts +2 -0
- package/dist/host/host.js +343 -0
- package/dist/host/index.d.ts +5 -0
- package/dist/host/index.js +4 -0
- package/dist/host/spawn.d.ts +7 -0
- package/dist/host/spawn.js +98 -0
- package/dist/host/types.d.ts +19 -0
- package/dist/host/types.js +1 -0
- package/dist/host/validate.d.ts +10 -0
- package/dist/host/validate.js +339 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +13 -0
- package/dist/locales/en.json +577 -0
- package/dist/locales/nl.json +577 -0
- package/dist/locales.d.ts +4 -0
- package/dist/locales.js +14 -0
- package/dist/protocol/connection.d.ts +56 -0
- package/dist/protocol/connection.js +1 -0
- package/dist/protocol/errors.d.ts +7 -0
- package/dist/protocol/errors.js +1 -0
- package/dist/protocol/index.d.ts +5 -0
- package/dist/protocol/index.js +3 -0
- package/dist/protocol/messages.d.ts +250 -0
- package/dist/protocol/messages.js +2 -0
- package/dist/protocol/schema.d.ts +53 -0
- package/dist/protocol/schema.js +1 -0
- package/dist/protocol/values.d.ts +21 -0
- package/dist/protocol/values.js +15 -0
- package/dist/sql-split.d.ts +15 -0
- package/dist/sql-split.js +201 -0
- package/dist/sql.d.ts +29 -0
- package/dist/sql.js +104 -0
- package/dist/structure/StructureView.d.ts +14 -0
- package/dist/structure/StructureView.js +99 -0
- package/dist/structure/structure-text.d.ts +2 -0
- package/dist/structure/structure-text.js +2 -0
- package/dist/table/CommandField.d.ts +14 -0
- package/dist/table/CommandField.js +157 -0
- package/dist/table/ImportDialog.d.ts +27 -0
- package/dist/table/ImportDialog.js +28 -0
- package/dist/table/TableStatusBar.d.ts +19 -0
- package/dist/table/TableStatusBar.js +22 -0
- package/dist/table/TableToolbar.d.ts +43 -0
- package/dist/table/TableToolbar.js +16 -0
- package/dist/table/TableView.d.ts +13 -0
- package/dist/table/TableView.js +508 -0
- package/dist/table/command-field.d.ts +57 -0
- package/dist/table/command-field.js +203 -0
- package/dist/table/grid-rows.d.ts +23 -0
- package/dist/table/grid-rows.js +55 -0
- package/dist/table/import-mapping.d.ts +7 -0
- package/dist/table/import-mapping.js +28 -0
- package/dist/table/layout-store.d.ts +13 -0
- package/dist/table/layout-store.js +43 -0
- package/dist/table/paging.d.ts +12 -0
- package/dist/table/paging.js +20 -0
- package/dist/table/pending.d.ts +32 -0
- package/dist/table/pending.js +94 -0
- package/dist/table/references.d.ts +12 -0
- package/dist/table/references.js +21 -0
- package/dist/table/useLoaded.d.ts +7 -0
- package/dist/table/useLoaded.js +36 -0
- package/dist/table/useStoredLayout.d.ts +8 -0
- package/dist/table/useStoredLayout.js +39 -0
- package/dist/table/useTableTransfer.d.ts +51 -0
- package/dist/table/useTableTransfer.js +125 -0
- package/dist/testing/fake.d.ts +21 -0
- package/dist/testing/fake.js +372 -0
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.js +1 -0
- package/dist/use-popup-press.d.ts +1 -0
- package/dist/use-popup-press.js +24 -0
- package/dist/use-schema-change.d.ts +1 -0
- package/dist/use-schema-change.js +13 -0
- package/dist/use-stable-callback.d.ts +1 -0
- package/dist/use-stable-callback.js +9 -0
- package/dist/value/ValuePanel.d.ts +14 -0
- package/dist/value/ValuePanel.js +103 -0
- package/dist/value/draft.d.ts +33 -0
- package/dist/value/draft.js +44 -0
- package/dist/value/hex.d.ts +14 -0
- package/dist/value/hex.js +46 -0
- package/dist/value/json.d.ts +9 -0
- package/dist/value/json.js +71 -0
- package/dist/value/views.d.ts +22 -0
- package/dist/value/views.js +54 -0
- package/dist/workbench/DatabaseWorkbench.d.ts +9 -0
- package/dist/workbench/DatabaseWorkbench.js +179 -0
- package/dist/workbench/DesignerTab.d.ts +10 -0
- package/dist/workbench/DesignerTab.js +22 -0
- package/dist/workbench/TableTab.d.ts +10 -0
- package/dist/workbench/TableTab.js +8 -0
- package/dist/workbench/tabs.d.ts +42 -0
- package/dist/workbench/tabs.js +139 -0
- package/package.json +79 -3
- package/src/DatabaseProvider.tsx +37 -0
- package/src/actions.ts +34 -0
- package/src/client/client.ts +324 -0
- package/src/client/index.ts +18 -0
- package/src/client/types.ts +161 -0
- package/src/client-context.ts +35 -0
- package/src/connections/ConnectionForm.tsx +474 -0
- package/src/connections/ConnectionManager.tsx +224 -0
- package/src/connections/EngineIcon.tsx +18 -0
- package/src/connections/connection-config.ts +143 -0
- package/src/connections/docker.ts +50 -0
- package/src/connections/engine-icons.ts +5 -0
- package/src/connections/use-docker-containers.ts +41 -0
- package/src/console/DestructiveDialog.tsx +40 -0
- package/src/console/HistoryPanel.tsx +67 -0
- package/src/console/QueryConsole.tsx +439 -0
- package/src/console/SchemaPicker.tsx +32 -0
- package/src/console/SqlEditor.tsx +95 -0
- package/src/console/StatementResultView.tsx +176 -0
- package/src/console/TransactionControls.tsx +53 -0
- package/src/console/destructive.ts +60 -0
- package/src/console/editing.ts +77 -0
- package/src/console/history.ts +62 -0
- package/src/console/labels.ts +7 -0
- package/src/console/outcome.ts +14 -0
- package/src/console/schemas.ts +7 -0
- package/src/console/shortcuts.ts +4 -0
- package/src/console/useConsoleHistory.ts +39 -0
- package/src/ddl/alter-mysql.ts +90 -0
- package/src/ddl/alter-sqlite.ts +93 -0
- package/src/ddl/alter.ts +29 -0
- package/src/ddl/column.ts +74 -0
- package/src/ddl/create.ts +92 -0
- package/src/ddl/dialect.ts +53 -0
- package/src/ddl/diff.ts +164 -0
- package/src/ddl/draft.ts +136 -0
- package/src/ddl/index.ts +10 -0
- package/src/ddl/parse.ts +161 -0
- package/src/ddl/statements.ts +20 -0
- package/src/ddl/types.ts +60 -0
- package/src/ddl/validate.ts +47 -0
- package/src/designer/ColumnsEditor.tsx +204 -0
- package/src/designer/DesignerView.tsx +184 -0
- package/src/designer/ForeignKeysEditor.tsx +132 -0
- package/src/designer/IndexesEditor.tsx +63 -0
- package/src/designer/NamePicker.tsx +44 -0
- package/src/designer/OptionsEditor.tsx +101 -0
- package/src/designer/SqlPreview.tsx +56 -0
- package/src/designer/TableDesigner.tsx +186 -0
- package/src/designer/edit.ts +137 -0
- package/src/designer/editor-props.ts +13 -0
- package/src/designer/plan.ts +25 -0
- package/src/designer/recover.ts +20 -0
- package/src/designer/useReferenceColumns.ts +54 -0
- package/src/explorer/DatabaseExplorer.tsx +450 -0
- package/src/explorer/RowMenu.tsx +134 -0
- package/src/explorer/TableDialog.tsx +80 -0
- package/src/explorer/expansion.ts +47 -0
- package/src/explorer/table-statements.ts +18 -0
- package/src/explorer/tree.ts +453 -0
- package/src/explorer/use-explorer-loads.ts +157 -0
- package/src/explorer/use-stored-expansion.ts +66 -0
- package/src/grid/CellEditor.tsx +53 -0
- package/src/grid/CopyAsMenu.tsx +33 -0
- package/src/grid/DataGrid.tsx +871 -0
- package/src/grid/EnumPicker.tsx +108 -0
- package/src/grid/GridHeaderCell.tsx +243 -0
- package/src/grid/RecordView.tsx +293 -0
- package/src/grid/ValueDock.tsx +52 -0
- package/src/grid/aggregates.ts +94 -0
- package/src/grid/cell-range.ts +26 -0
- package/src/grid/column-layout.ts +71 -0
- package/src/grid/column-selection.ts +42 -0
- package/src/grid/column-view.ts +35 -0
- package/src/grid/copy-formats.ts +108 -0
- package/src/grid/display.ts +109 -0
- package/src/grid/edit-value.ts +60 -0
- package/src/grid/enum-type.ts +62 -0
- package/src/grid/focused-value.ts +23 -0
- package/src/grid/layout.ts +91 -0
- package/src/grid/navigation.ts +74 -0
- package/src/grid/row-selection.ts +35 -0
- package/src/grid/sort.ts +12 -0
- package/src/grid/types.ts +59 -0
- package/src/host/helper-path.ts +41 -0
- package/src/host/host.ts +456 -0
- package/src/host/index.ts +5 -0
- package/src/host/spawn.ts +124 -0
- package/src/host/types.ts +46 -0
- package/src/host/validate.ts +402 -0
- package/src/index.ts +37 -0
- package/src/locales/en.json +577 -0
- package/src/locales/nl.json +577 -0
- package/src/locales.ts +18 -0
- package/src/protocol/connection.ts +86 -0
- package/src/protocol/errors.ts +38 -0
- package/src/protocol/index.ts +33 -0
- package/src/protocol/messages.ts +168 -0
- package/src/protocol/schema.ts +76 -0
- package/src/protocol/values.ts +52 -0
- package/src/sql-split.ts +220 -0
- package/src/sql.ts +152 -0
- package/src/structure/StructureView.tsx +269 -0
- package/src/structure/structure-text.ts +4 -0
- package/src/table/CommandField.tsx +318 -0
- package/src/table/ImportDialog.tsx +168 -0
- package/src/table/TableStatusBar.tsx +91 -0
- package/src/table/TableToolbar.tsx +217 -0
- package/src/table/TableView.tsx +880 -0
- package/src/table/command-field.ts +285 -0
- package/src/table/grid-rows.ts +80 -0
- package/src/table/import-mapping.ts +37 -0
- package/src/table/layout-store.ts +62 -0
- package/src/table/paging.ts +33 -0
- package/src/table/pending.ts +143 -0
- package/src/table/references.ts +38 -0
- package/src/table/useLoaded.ts +58 -0
- package/src/table/useStoredLayout.ts +53 -0
- package/src/table/useTableTransfer.ts +187 -0
- package/src/testing/fake.ts +533 -0
- package/src/testing/index.ts +1 -0
- package/src/use-popup-press.ts +27 -0
- package/src/use-schema-change.ts +19 -0
- package/src/use-stable-callback.ts +12 -0
- package/src/value/ValuePanel.tsx +254 -0
- package/src/value/draft.ts +72 -0
- package/src/value/hex.ts +62 -0
- package/src/value/json.ts +74 -0
- package/src/value/views.ts +68 -0
- package/src/workbench/DatabaseWorkbench.tsx +348 -0
- package/src/workbench/DesignerTab.tsx +37 -0
- package/src/workbench/TableTab.tsx +27 -0
- package/src/workbench/tabs.ts +184 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { valueOfCell, type Cell, type Value } from '../protocol/index.ts';
|
|
2
|
+
import type { Shown } from './display.ts';
|
|
3
|
+
|
|
4
|
+
/* The whole value of a cell, or `undefined` when it is only a preview (or a pending DEFAULT, which holds no value). */
|
|
5
|
+
export const wholeValueOf = (cell: Shown): Value | undefined =>
|
|
6
|
+
cell !== null && typeof cell === 'object' && cell.kind === 'default' ? undefined : valueOfCell(cell as Cell);
|
|
7
|
+
|
|
8
|
+
/* What a cell holds as far as it goes: the whole value, or the preview of a long text or a binary value. */
|
|
9
|
+
export const previewValueOf = (cell: Shown): Value => {
|
|
10
|
+
const whole = wholeValueOf(cell);
|
|
11
|
+
if (whole !== undefined) {
|
|
12
|
+
return whole;
|
|
13
|
+
}
|
|
14
|
+
if (cell !== null && typeof cell === 'object') {
|
|
15
|
+
if (cell.kind === 'longText') {
|
|
16
|
+
return cell.preview;
|
|
17
|
+
}
|
|
18
|
+
if (cell.kind === 'binary') {
|
|
19
|
+
return { kind: 'binary', hex: cell.hex };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/* The measures of the grid, in whole pixels. Row and header heights are steps of the 4px spacing scale. */
|
|
2
|
+
export const ROW_HEIGHT = 28;
|
|
3
|
+
export const HEADER_HEIGHT = 32;
|
|
4
|
+
export const MIN_COLUMN_WIDTH = 64;
|
|
5
|
+
export const MAX_COLUMN_WIDTH = 320;
|
|
6
|
+
/* How far a drag may widen a column; the estimate stops at `MAX_COLUMN_WIDTH`, a person may go further. */
|
|
7
|
+
export const MAX_RESIZED_WIDTH = 1200;
|
|
8
|
+
/* How wide fitting a column to its content may make it. */
|
|
9
|
+
export const MAX_FIT_WIDTH = 640;
|
|
10
|
+
export const OVERSCAN_ROWS = 6;
|
|
11
|
+
/* Two presses on a resize handle this close are a double click. */
|
|
12
|
+
export const DOUBLE_CLICK_MS = 350;
|
|
13
|
+
/* What a viewport is taken to be until it is measured, so a first paint already holds rows. */
|
|
14
|
+
export const FALLBACK_VIEWPORT_HEIGHT = 600;
|
|
15
|
+
|
|
16
|
+
/* A glyph of the 13px mono face is 7.8px wide; a whole pixel on the safe side. */
|
|
17
|
+
const CHARACTER_WIDTH = 8;
|
|
18
|
+
const CELL_PADDING = 24;
|
|
19
|
+
const KEY_ICON_ROOM = 18;
|
|
20
|
+
const GUTTER_MIN_WIDTH = 40;
|
|
21
|
+
const SAMPLE_ROWS = 50;
|
|
22
|
+
/* The arrow and the position number a sorted header carries after its name. */
|
|
23
|
+
const SORT_ROOM = 24;
|
|
24
|
+
|
|
25
|
+
export interface VisibleRange {
|
|
26
|
+
/* Index of the first row to draw. */
|
|
27
|
+
readonly start: number;
|
|
28
|
+
/* One past the last row to draw. */
|
|
29
|
+
readonly end: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* The rows that touch a viewport of `height` pixels starting `top` pixels into the rows, plus `overscan` rows on both sides. */
|
|
33
|
+
export const visibleRange = (top: number, height: number, rowHeight: number, count: number, overscan: number): VisibleRange => {
|
|
34
|
+
if (count <= 0 || height <= 0) {
|
|
35
|
+
return { start: 0, end: 0 };
|
|
36
|
+
}
|
|
37
|
+
const first = Math.floor(Math.max(0, top) / rowHeight);
|
|
38
|
+
const last = Math.ceil(Math.max(0, top + height) / rowHeight);
|
|
39
|
+
return { start: Math.max(0, Math.min(first, count) - overscan), end: Math.min(count, last + overscan) };
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/*
|
|
43
|
+
* Where to scroll so that an item at `start` that is `size` long is in view. `leading` is the part of
|
|
44
|
+
* the viewport a sticky header or gutter covers. Returns `scroll` itself when the item is already visible.
|
|
45
|
+
*/
|
|
46
|
+
export const scrollToReveal = (start: number, size: number, scroll: number, viewport: number, leading: number): number => {
|
|
47
|
+
if (start < scroll + leading) {
|
|
48
|
+
return Math.max(0, start - leading);
|
|
49
|
+
}
|
|
50
|
+
if (start + size > scroll + viewport) {
|
|
51
|
+
return Math.max(0, start + size - viewport);
|
|
52
|
+
}
|
|
53
|
+
return scroll;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/* The left edge of every column, counted from the first one. */
|
|
57
|
+
export const columnOffsets = (widths: readonly number[]): number[] => {
|
|
58
|
+
let offset = 0;
|
|
59
|
+
return widths.map((width) => {
|
|
60
|
+
const left = offset;
|
|
61
|
+
offset += width;
|
|
62
|
+
return left;
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/* Wide enough for the largest row number, never narrower than `GUTTER_MIN_WIDTH`. */
|
|
67
|
+
export const gutterWidth = (rowCount: number): number => Math.max(GUTTER_MIN_WIDTH, String(Math.max(rowCount, 1)).length * CHARACTER_WIDTH + CELL_PADDING);
|
|
68
|
+
|
|
69
|
+
export const clampColumnWidth = (width: number): number => Math.max(MIN_COLUMN_WIDTH, Math.min(Math.ceil(width), MAX_COLUMN_WIDTH));
|
|
70
|
+
|
|
71
|
+
/* From the longest text among the header and the first rows. `keyed` makes room for the key icon in front of the name. */
|
|
72
|
+
export const estimateColumnWidth = (header: string, samples: readonly string[], keyed: boolean): number => {
|
|
73
|
+
const body = samples.slice(0, SAMPLE_ROWS).reduce((longest, text) => Math.max(longest, text.length), 0);
|
|
74
|
+
const named = header.length * CHARACTER_WIDTH + (keyed ? KEY_ICON_ROOM : 0) + SORT_ROOM;
|
|
75
|
+
return clampColumnWidth(Math.max(body * CHARACTER_WIDTH, named) + CELL_PADDING);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/* Wide enough for the header and every text of the column, up to `MAX_FIT_WIDTH`. */
|
|
79
|
+
export const fitColumnWidth = (header: string, texts: readonly string[], keyed: boolean): number => {
|
|
80
|
+
const body = texts.reduce((longest, text) => Math.max(longest, text.length), 0) * CHARACTER_WIDTH;
|
|
81
|
+
const named = header.length * CHARACTER_WIDTH + (keyed ? KEY_ICON_ROOM : 0) + SORT_ROOM;
|
|
82
|
+
return Math.max(MIN_COLUMN_WIDTH, Math.min(Math.ceil(Math.max(body, named) + CELL_PADDING), MAX_FIT_WIDTH));
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const isDoubleClick = (previous: number | null, now: number): boolean => previous !== null && now - previous <= DOUBLE_CLICK_MS;
|
|
86
|
+
|
|
87
|
+
/*
|
|
88
|
+
* The estimated widths of a new page, never narrower than they were. A page with longer content widens
|
|
89
|
+
* a column; a page with shorter content leaves it, so a sort does not make columns jump.
|
|
90
|
+
*/
|
|
91
|
+
export const growWidths = (previous: readonly number[], next: readonly number[]): number[] => next.map((width, index) => Math.max(width, previous[index] ?? 0));
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export interface CellPosition {
|
|
2
|
+
readonly row: number;
|
|
3
|
+
readonly column: number;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface GridSize {
|
|
7
|
+
readonly rows: number;
|
|
8
|
+
readonly columns: number;
|
|
9
|
+
/* How many rows a PageUp or PageDown moves. */
|
|
10
|
+
readonly page: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface NavigationKey {
|
|
14
|
+
readonly key: string;
|
|
15
|
+
readonly shiftKey: boolean;
|
|
16
|
+
/* The platform's own modifier. */
|
|
17
|
+
readonly mod: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* Keys that, with no cell focused yet, only put the focus on the first one. */
|
|
21
|
+
const ENTERING_KEYS: ReadonlySet<string> = new Set(['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'PageUp', 'PageDown', 'Tab']);
|
|
22
|
+
|
|
23
|
+
const clamp = (value: number, max: number): number => Math.max(0, Math.min(value, max - 1));
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
* Where a navigation key takes the focus, or `null` when the key moves nothing and the browser should
|
|
27
|
+
* keep it: that is also how Tab leaves the grid at its first and last cell.
|
|
28
|
+
*/
|
|
29
|
+
export const moveFocus = (from: CellPosition | null, input: NavigationKey, size: GridSize): CellPosition | null => {
|
|
30
|
+
if (size.rows === 0 || size.columns === 0) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
if (from === null && ENTERING_KEYS.has(input.key)) {
|
|
34
|
+
return { row: 0, column: 0 };
|
|
35
|
+
}
|
|
36
|
+
const lastRow = size.rows - 1;
|
|
37
|
+
const lastColumn = size.columns - 1;
|
|
38
|
+
const start = from ?? { row: 0, column: 0 };
|
|
39
|
+
const row = clamp(start.row, size.rows);
|
|
40
|
+
const column = clamp(start.column, size.columns);
|
|
41
|
+
|
|
42
|
+
switch (input.key) {
|
|
43
|
+
case 'ArrowUp':
|
|
44
|
+
return { row: clamp(row - 1, size.rows), column };
|
|
45
|
+
case 'ArrowDown':
|
|
46
|
+
return { row: clamp(row + 1, size.rows), column };
|
|
47
|
+
case 'ArrowLeft':
|
|
48
|
+
return { row, column: clamp(column - 1, size.columns) };
|
|
49
|
+
case 'ArrowRight':
|
|
50
|
+
return { row, column: clamp(column + 1, size.columns) };
|
|
51
|
+
case 'PageUp':
|
|
52
|
+
return { row: clamp(row - size.page, size.rows), column };
|
|
53
|
+
case 'PageDown':
|
|
54
|
+
return { row: clamp(row + size.page, size.rows), column };
|
|
55
|
+
case 'Home':
|
|
56
|
+
return { row: input.mod ? 0 : row, column: 0 };
|
|
57
|
+
case 'End':
|
|
58
|
+
return { row: input.mod ? lastRow : row, column: lastColumn };
|
|
59
|
+
case 'Tab': {
|
|
60
|
+
if (input.shiftKey) {
|
|
61
|
+
if (column > 0) {
|
|
62
|
+
return { row, column: column - 1 };
|
|
63
|
+
}
|
|
64
|
+
return row > 0 ? { row: row - 1, column: lastColumn } : null;
|
|
65
|
+
}
|
|
66
|
+
if (column < lastColumn) {
|
|
67
|
+
return { row, column: column + 1 };
|
|
68
|
+
}
|
|
69
|
+
return row < lastRow ? { row: row + 1, column: 0 } : null;
|
|
70
|
+
}
|
|
71
|
+
default:
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface RowSelection {
|
|
2
|
+
readonly selected: ReadonlySet<string>;
|
|
3
|
+
/* The row a Shift-click extends from. */
|
|
4
|
+
readonly anchor: number;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface RowClick {
|
|
8
|
+
readonly shiftKey: boolean;
|
|
9
|
+
readonly mod: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* The selection after a click on the gutter of `index`: a plain click selects that row alone, Mod
|
|
14
|
+
* toggles it, and Shift selects everything from the anchor to it.
|
|
15
|
+
*/
|
|
16
|
+
export const selectRow = (keys: readonly string[], current: ReadonlySet<string>, anchor: number, index: number, click: RowClick): RowSelection => {
|
|
17
|
+
const key = keys[index];
|
|
18
|
+
if (key === undefined) {
|
|
19
|
+
return { selected: current, anchor };
|
|
20
|
+
}
|
|
21
|
+
if (click.shiftKey && anchor >= 0 && anchor < keys.length) {
|
|
22
|
+
const from = Math.min(anchor, index);
|
|
23
|
+
const to = Math.max(anchor, index);
|
|
24
|
+
const range = keys.slice(from, to + 1);
|
|
25
|
+
return { selected: new Set(click.mod ? [...current, ...range] : range), anchor };
|
|
26
|
+
}
|
|
27
|
+
if (click.mod) {
|
|
28
|
+
const next = new Set(current);
|
|
29
|
+
if (!next.delete(key)) {
|
|
30
|
+
next.add(key);
|
|
31
|
+
}
|
|
32
|
+
return { selected: next, anchor: index };
|
|
33
|
+
}
|
|
34
|
+
return { selected: new Set([key]), anchor: index };
|
|
35
|
+
};
|
package/src/grid/sort.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ColumnSort, SortDirection } from '../sql.ts';
|
|
2
|
+
|
|
3
|
+
export type GridSort = ColumnSort;
|
|
4
|
+
|
|
5
|
+
/* The column as the only sort, in a direction a menu picked. */
|
|
6
|
+
export const sortOnly = (column: string, direction: SortDirection): GridSort[] => [{ column, direction }];
|
|
7
|
+
|
|
8
|
+
/* The sort of a column and its place among the sorts counted from one, or `null` when it is not sorted. */
|
|
9
|
+
export const sortStateOf = (sorts: readonly GridSort[], column: string): { direction: SortDirection; position: number } | null => {
|
|
10
|
+
const index = sorts.findIndex((sort) => sort.column === column);
|
|
11
|
+
return index < 0 ? null : { direction: sorts[index]!.direction, position: index + 1 };
|
|
12
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ColumnInfo, ResultColumn } from '../protocol/index.ts';
|
|
2
|
+
import type { Shown } from './display.ts';
|
|
3
|
+
|
|
4
|
+
/* A column of a result, with what the grid draws from its table when it comes from one. */
|
|
5
|
+
export interface GridColumn extends ResultColumn {
|
|
6
|
+
readonly primaryKey?: boolean;
|
|
7
|
+
/* `false` makes Set NULL unavailable; unknown (an expression) leaves it open. */
|
|
8
|
+
readonly nullable?: boolean;
|
|
9
|
+
/* A column no cell of which can be edited, such as a generated one. */
|
|
10
|
+
readonly readOnly?: boolean;
|
|
11
|
+
/* The default as an SQL expression, for the hint on the header. */
|
|
12
|
+
readonly defaultValue?: string | null;
|
|
13
|
+
/* A cloned row leaves this column to the server. */
|
|
14
|
+
readonly autoIncrement?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type GridRowState = 'inserted' | 'deleted';
|
|
18
|
+
|
|
19
|
+
export interface GridRow {
|
|
20
|
+
/* Stable while the row is on the grid, since the selection and the edits are kept by it. */
|
|
21
|
+
readonly key: string;
|
|
22
|
+
/* The number in the gutter; `null` for a row that does not exist yet. */
|
|
23
|
+
readonly number: number | null;
|
|
24
|
+
readonly cells: readonly Shown[];
|
|
25
|
+
readonly state?: GridRowState;
|
|
26
|
+
/* Indexes of the cells with a pending edit. */
|
|
27
|
+
readonly edited?: ReadonlySet<number>;
|
|
28
|
+
/* A row that cannot be edited even though the grid can, such as one whose key is only a preview. */
|
|
29
|
+
readonly locked?: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Builds the column of a table from the result column and the structure's column of the same name. */
|
|
33
|
+
export const gridColumnOf = (column: ResultColumn, info: ColumnInfo | undefined, primaryKey: readonly string[]): GridColumn => ({
|
|
34
|
+
...column,
|
|
35
|
+
primaryKey: primaryKey.includes(column.name),
|
|
36
|
+
nullable: info?.nullable,
|
|
37
|
+
readOnly: info?.generated === true,
|
|
38
|
+
defaultValue: info?.defaultValue,
|
|
39
|
+
autoIncrement: info?.autoIncrement
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
/* The cell that holds the focus, named by its row's key and its column's index in the columns the grid was given. */
|
|
43
|
+
export interface FocusedCell {
|
|
44
|
+
readonly rowKey: string;
|
|
45
|
+
readonly column: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* What a menu item added to the grid's context menu acts on. */
|
|
49
|
+
export interface GridMenuContext {
|
|
50
|
+
/* The selected rows when the row under the pointer is one of them, else that row alone. */
|
|
51
|
+
readonly rowKeys: readonly string[];
|
|
52
|
+
/* The cell under the pointer; `null` when the menu opened on a row number. */
|
|
53
|
+
readonly cell: FocusedCell | null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* A column to pick and bring into view, named by its index in the columns the grid was given. */
|
|
57
|
+
export interface ColumnRequest {
|
|
58
|
+
readonly column: number;
|
|
59
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { dirname, join, sep } from 'node:path';
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* Finds the prebuilt helper that npm installed for this machine, in the `@adecore/database-<platform>-<arch>`
|
|
7
|
+
* package, or null when there is none: an unsupported platform, or an install with optional dependencies off.
|
|
8
|
+
*
|
|
9
|
+
* A binary cannot run from inside an Electron archive. The path is mapped from `app.asar` to
|
|
10
|
+
* `app.asar.unpacked`, so the app must unpack the packages (electron-builder: `asarUnpack` with
|
|
11
|
+
* `node_modules/@adecore/database-*` followed by `/**`).
|
|
12
|
+
*/
|
|
13
|
+
export interface HelperPathOptions {
|
|
14
|
+
/* `process.platform` when left out. */
|
|
15
|
+
readonly platform?: string;
|
|
16
|
+
/* `process.arch` when left out. */
|
|
17
|
+
readonly arch?: string;
|
|
18
|
+
/* Resolves a package specifier to a file; the module resolution of this file when left out. */
|
|
19
|
+
readonly resolve?: (specifier: string) => string;
|
|
20
|
+
readonly exists?: (path: string) => boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const helperPath = ({
|
|
24
|
+
platform = process.platform,
|
|
25
|
+
arch = process.arch,
|
|
26
|
+
resolve = (specifier) => createRequire(import.meta.url).resolve(specifier),
|
|
27
|
+
exists = existsSync
|
|
28
|
+
}: HelperPathOptions = {}): string | null => {
|
|
29
|
+
let manifest: string;
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
manifest = resolve(`@adecore/database-${platform}-${arch}/package.json`);
|
|
33
|
+
} catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const binary = join(dirname(manifest), 'bin', platform === 'win32' ? 'adecore-database.exe' : 'adecore-database');
|
|
38
|
+
const unpacked = binary.replace(`.asar${sep}`, `.asar.unpacked${sep}`);
|
|
39
|
+
|
|
40
|
+
return exists(unpacked) ? unpacked : null;
|
|
41
|
+
};
|