@dxos/react-ui-table 0.8.4-main.f9ba587 → 0.8.4-main.fcfe5033a5
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/dist/lib/browser/chunk-BF54SSNL.mjs +70 -0
- package/dist/lib/browser/chunk-BF54SSNL.mjs.map +7 -0
- package/dist/lib/browser/chunk-F7Y374KL.mjs +1751 -0
- package/dist/lib/browser/chunk-F7Y374KL.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1195 -2846
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +114 -0
- package/dist/lib/browser/testing/index.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +3 -5
- package/dist/lib/node-esm/chunk-CCJ4LOVM.mjs +1753 -0
- package/dist/lib/node-esm/chunk-CCJ4LOVM.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-SIRDIPHZ.mjs +71 -0
- package/dist/lib/node-esm/chunk-SIRDIPHZ.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1195 -2846
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +115 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +3 -5
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +2 -3
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/ColumnSettings.d.ts +4 -2
- package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.d.ts +7 -7
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts +35 -3
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Relations.stories.d.ts +110 -0
- package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -0
- package/dist/types/src/components/Table/RowActionsMenu.d.ts +1 -1
- package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts +21 -18
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +109 -6
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/TableContent.d.ts +17 -0
- package/dist/types/src/components/Table/TableContent.d.ts.map +1 -0
- package/dist/types/src/components/Table/TableToolbar.d.ts +21 -0
- package/dist/types/src/components/Table/TableToolbar.d.ts.map +1 -0
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts +1 -1
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +14 -9
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +12 -18
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +38 -5
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/index.d.ts +1 -0
- package/dist/types/src/components/TableCellEditor/index.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +0 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +26 -56
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useAddRow.d.ts +6 -6
- package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
- package/dist/types/src/hooks/useProjectionModel.d.ts +6 -0
- package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -0
- package/dist/types/src/hooks/useTableModel.d.ts +11 -10
- package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/model/modal-controller.d.ts +5 -8
- package/dist/types/src/model/modal-controller.d.ts.map +1 -1
- package/dist/types/src/model/selection-model.d.ts +17 -7
- package/dist/types/src/model/selection-model.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +116 -34
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts +5 -2
- package/dist/types/src/model/table-presentation.d.ts.map +1 -1
- package/dist/types/src/playwright/TableManager.d.ts +2 -1
- package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/useTestTableModel.d.ts +25 -0
- package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +21 -23
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Table.d.ts +26 -0
- package/dist/types/src/types/Table.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +1 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.d.ts +15 -14
- package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.test.d.ts +2 -0
- package/dist/types/src/util/dynamic-table.test.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +2 -1
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/query-ast.d.ts +7 -0
- package/dist/types/src/util/query-ast.d.ts.map +1 -0
- package/dist/types/src/util/schema.d.ts +1 -1
- package/dist/types/src/util/schema.d.ts.map +1 -1
- package/dist/types/src/util/sort.d.ts +12 -0
- package/dist/types/src/util/sort.d.ts.map +1 -0
- package/dist/types/src/util/table-buttons.d.ts.map +1 -1
- package/dist/types/src/util/table-controls.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +70 -55
- package/src/components/Table/ColumnActionsMenu.tsx +16 -12
- package/src/components/Table/ColumnSettings.tsx +18 -15
- package/src/components/Table/DynamicTable.stories.tsx +38 -35
- package/src/components/Table/DynamicTable.tsx +38 -34
- package/src/components/Table/Relations.stories.tsx +245 -0
- package/src/components/Table/RowActionsMenu.tsx +26 -17
- package/src/components/Table/Table.stories.tsx +196 -218
- package/src/components/Table/Table.tsx +47 -376
- package/src/components/Table/TableContent.tsx +421 -0
- package/src/components/Table/TableToolbar.tsx +111 -0
- package/src/components/TableCellEditor/CellValidationMessage.tsx +6 -6
- package/src/components/TableCellEditor/FormCellEditor.tsx +152 -49
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +37 -77
- package/src/components/TableCellEditor/TableCellEditor.tsx +104 -233
- package/src/components/TableCellEditor/index.ts +1 -0
- package/src/components/index.ts +0 -1
- package/src/components/testing.ts +46 -37
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useAddRow.ts +14 -14
- package/src/hooks/useProjectionModel.ts +39 -0
- package/src/hooks/useTableModel.ts +41 -35
- package/src/index.ts +0 -1
- package/src/model/modal-controller.ts +24 -41
- package/src/model/selection-model.ts +75 -41
- package/src/model/table-model.test.ts +91 -56
- package/src/model/table-model.ts +468 -187
- package/src/model/table-presentation.test.ts +69 -59
- package/src/model/table-presentation.ts +112 -66
- package/src/playwright/TableManager.ts +13 -6
- package/src/playwright/playwright.config.ts +1 -1
- package/src/playwright/smoke.spec.ts +180 -43
- package/src/testing/index.ts +5 -0
- package/src/testing/useTestTableModel.ts +133 -0
- package/src/translations.ts +20 -22
- package/src/types/Table.ts +79 -0
- package/src/types/index.ts +2 -2
- package/src/util/dynamic-table.test.ts +70 -0
- package/src/util/dynamic-table.ts +51 -36
- package/src/util/index.ts +2 -1
- package/src/util/query-ast.ts +22 -0
- package/src/util/schema.ts +4 -4
- package/src/util/sort.ts +90 -0
- package/src/util/table-buttons.ts +4 -3
- package/src/util/table-controls.ts +6 -3
- package/dist/lib/browser/chunk-Q5QQXJUO.mjs +0 -27
- package/dist/lib/browser/chunk-Q5QQXJUO.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ZNOU6LHG.mjs +0 -29
- package/dist/lib/node-esm/chunk-ZNOU6LHG.mjs.map +0 -7
- package/dist/types/src/components/Table/CreateRefPanel.d.ts +0 -9
- package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +0 -1
- package/dist/types/src/components/Table/relations.stories.d.ts +0 -9
- package/dist/types/src/components/Table/relations.stories.d.ts.map +0 -1
- package/dist/types/src/components/TableCellEditor/extension.d.ts +0 -13
- package/dist/types/src/components/TableCellEditor/extension.d.ts.map +0 -1
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +0 -21
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +0 -1
- package/dist/types/src/components/TableToolbar/index.d.ts +0 -2
- package/dist/types/src/components/TableToolbar/index.d.ts.map +0 -1
- package/dist/types/src/model/table-sorting.d.ts +0 -53
- package/dist/types/src/model/table-sorting.d.ts.map +0 -1
- package/dist/types/src/types/table.d.ts +0 -56
- package/dist/types/src/types/table.d.ts.map +0 -1
- package/dist/types/src/util/table.d.ts +0 -14
- package/dist/types/src/util/table.d.ts.map +0 -1
- package/src/components/Table/CreateRefPanel.tsx +0 -84
- package/src/components/Table/relations.stories.tsx +0 -123
- package/src/components/TableCellEditor/extension.ts +0 -61
- package/src/components/TableToolbar/TableToolbar.tsx +0 -102
- package/src/components/TableToolbar/index.ts +0 -5
- package/src/model/table-sorting.ts +0 -216
- package/src/types/table.ts +0 -27
- package/src/util/table.ts +0 -127
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { Schema } from 'effect';
|
|
2
|
-
import { Type } from '@dxos/echo';
|
|
3
|
-
import { Expando } from '@dxos/echo-schema';
|
|
4
|
-
export declare const TableSchema: Schema.Struct<{
|
|
5
|
-
id: import("@dxos/keys").ObjectIdClass;
|
|
6
|
-
name: Schema.optional<typeof Schema.String>;
|
|
7
|
-
view: Schema.optional<import("@dxos/echo-schema").Ref$<import("@dxos/echo-schema").TypedObjectFields<{
|
|
8
|
-
name: Schema.SchemaClass<string, string, never>;
|
|
9
|
-
query: Schema.Schema<import("@dxos/echo-schema").QueryType, import("@dxos/echo-schema").QueryType, never>;
|
|
10
|
-
schema: Schema.optional<Schema.Schema<Type.JsonSchema, Type.JsonSchema, never>>;
|
|
11
|
-
fields: Schema.mutable<Schema.Array$<Schema.mutable<Schema.Struct<{
|
|
12
|
-
id: typeof Schema.String;
|
|
13
|
-
path: Schema.Schema<import("@dxos/effect").JsonPath, import("@dxos/effect").JsonPath, never>;
|
|
14
|
-
visible: Schema.optional<typeof Schema.Boolean>;
|
|
15
|
-
referencePath: Schema.optional<Schema.Schema<import("@dxos/effect").JsonPath, import("@dxos/effect").JsonPath, never>>;
|
|
16
|
-
size: Schema.optional<typeof Schema.Number>;
|
|
17
|
-
}>>>>;
|
|
18
|
-
hiddenFields: Schema.optional<Schema.mutable<Schema.Array$<Schema.mutable<Schema.Struct<{
|
|
19
|
-
id: typeof Schema.String;
|
|
20
|
-
path: Schema.Schema<import("@dxos/effect").JsonPath, import("@dxos/effect").JsonPath, never>;
|
|
21
|
-
visible: Schema.optional<typeof Schema.Boolean>;
|
|
22
|
-
referencePath: Schema.optional<Schema.Schema<import("@dxos/effect").JsonPath, import("@dxos/effect").JsonPath, never>>;
|
|
23
|
-
size: Schema.optional<typeof Schema.Number>;
|
|
24
|
-
}>>>>>;
|
|
25
|
-
metadata: Schema.optional<Schema.mutable<Schema.Record$<typeof Schema.String, typeof Schema.Any>>>;
|
|
26
|
-
}, import("@dxos/echo-schema").TypedObjectOptions>>>;
|
|
27
|
-
threads: Schema.optional<Schema.Array$<import("@dxos/echo-schema").Ref$<Expando>>>;
|
|
28
|
-
}>;
|
|
29
|
-
export declare const TableType: Type.obj<Schema.Struct<{
|
|
30
|
-
id: import("@dxos/keys").ObjectIdClass;
|
|
31
|
-
name: Schema.optional<typeof Schema.String>;
|
|
32
|
-
view: Schema.optional<import("@dxos/echo-schema").Ref$<import("@dxos/echo-schema").TypedObjectFields<{
|
|
33
|
-
name: Schema.SchemaClass<string, string, never>;
|
|
34
|
-
query: Schema.Schema<import("@dxos/echo-schema").QueryType, import("@dxos/echo-schema").QueryType, never>;
|
|
35
|
-
schema: Schema.optional<Schema.Schema<Type.JsonSchema, Type.JsonSchema, never>>;
|
|
36
|
-
fields: Schema.mutable<Schema.Array$<Schema.mutable<Schema.Struct<{
|
|
37
|
-
id: typeof Schema.String;
|
|
38
|
-
path: Schema.Schema<import("@dxos/effect").JsonPath, import("@dxos/effect").JsonPath, never>;
|
|
39
|
-
visible: Schema.optional<typeof Schema.Boolean>;
|
|
40
|
-
referencePath: Schema.optional<Schema.Schema<import("@dxos/effect").JsonPath, import("@dxos/effect").JsonPath, never>>;
|
|
41
|
-
size: Schema.optional<typeof Schema.Number>;
|
|
42
|
-
}>>>>;
|
|
43
|
-
hiddenFields: Schema.optional<Schema.mutable<Schema.Array$<Schema.mutable<Schema.Struct<{
|
|
44
|
-
id: typeof Schema.String;
|
|
45
|
-
path: Schema.Schema<import("@dxos/effect").JsonPath, import("@dxos/effect").JsonPath, never>;
|
|
46
|
-
visible: Schema.optional<typeof Schema.Boolean>;
|
|
47
|
-
referencePath: Schema.optional<Schema.Schema<import("@dxos/effect").JsonPath, import("@dxos/effect").JsonPath, never>>;
|
|
48
|
-
size: Schema.optional<typeof Schema.Number>;
|
|
49
|
-
}>>>>>;
|
|
50
|
-
metadata: Schema.optional<Schema.mutable<Schema.Record$<typeof Schema.String, typeof Schema.Any>>>;
|
|
51
|
-
}, import("@dxos/echo-schema").TypedObjectOptions>>>;
|
|
52
|
-
threads: Schema.optional<Schema.Array$<import("@dxos/echo-schema").Ref$<Expando>>>;
|
|
53
|
-
}>>;
|
|
54
|
-
export interface TableType extends Schema.Schema.Type<typeof TableType> {
|
|
55
|
-
}
|
|
56
|
-
//# sourceMappingURL=table.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../../src/types/table.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAiB,OAAO,EAAmB,MAAM,mBAAmB,CAAC;AAG5E,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;EAMc,CAAC;AAGvC,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;GAKrB,CAAC;AACF,MAAM,WAAW,SAAU,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,SAAS,CAAC;CAAG"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { Schema } from 'effect';
|
|
2
|
-
import { type Client } from '@dxos/react-client';
|
|
3
|
-
import { type Space } from '@dxos/react-client/echo';
|
|
4
|
-
import { type TableType } from '../types';
|
|
5
|
-
type InitialiseTableProps = {
|
|
6
|
-
client: Client;
|
|
7
|
-
space: Space;
|
|
8
|
-
table: TableType;
|
|
9
|
-
typename?: string;
|
|
10
|
-
initialRow?: boolean;
|
|
11
|
-
};
|
|
12
|
-
export declare const initializeTable: ({ client, space, table, typename, initialRow, }: InitialiseTableProps) => Promise<Schema.Schema.AnyNoContext>;
|
|
13
|
-
export {};
|
|
14
|
-
//# sourceMappingURL=table.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../../src/util/table.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAYhC,OAAO,EAAE,KAAK,MAAM,EAAa,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAQ,KAAK,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAG3D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAG1C,KAAK,oBAAoB,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,iDAMnC,oBAAoB,KAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CA0C3D,CAAC"}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { Schema } from 'effect';
|
|
6
|
-
import React, { useCallback, useMemo } from 'react';
|
|
7
|
-
|
|
8
|
-
import { live } from '@dxos/react-client/echo';
|
|
9
|
-
import { Popover } from '@dxos/react-ui';
|
|
10
|
-
import { Form } from '@dxos/react-ui-form';
|
|
11
|
-
import { type GridScopedProps, useGridContext } from '@dxos/react-ui-grid';
|
|
12
|
-
|
|
13
|
-
import { type TableModel, type ModalController } from '../../model';
|
|
14
|
-
|
|
15
|
-
export type CreateRefPanelProps = { model?: TableModel; modals: ModalController };
|
|
16
|
-
|
|
17
|
-
// TODO(burdon): Factor out Space dependency (to plugin?)
|
|
18
|
-
export const CreateRefPanel = ({ model, modals, __gridScope }: GridScopedProps<CreateRefPanelProps>) => {
|
|
19
|
-
const { id: gridId } = useGridContext('TableCellEditor', __gridScope);
|
|
20
|
-
const space = model?.space;
|
|
21
|
-
const state = modals.state.value;
|
|
22
|
-
|
|
23
|
-
const schema = useMemo<Schema.Schema<any> | undefined>(() => {
|
|
24
|
-
if (!space || state?.type !== 'createRefPanel') {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const [schema] = space.db.schemaRegistry.query({ typename: state.typename }).runSync();
|
|
29
|
-
if (schema) {
|
|
30
|
-
const omit = Schema.omit<any, any, ['id']>('id');
|
|
31
|
-
return omit(schema);
|
|
32
|
-
}
|
|
33
|
-
}, [space, state]);
|
|
34
|
-
|
|
35
|
-
const handleSave = useCallback(
|
|
36
|
-
(values: any) => {
|
|
37
|
-
if (!model || !space || state?.type !== 'createRefPanel') {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const [schema] = space.db.schemaRegistry.query({ typename: state.typename }).runSync();
|
|
42
|
-
if (schema) {
|
|
43
|
-
const obj = space.db.add(live(schema, values));
|
|
44
|
-
state.onCreate?.(obj);
|
|
45
|
-
}
|
|
46
|
-
void modals.close();
|
|
47
|
-
},
|
|
48
|
-
[modals, space, state],
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
const handleCancel = useCallback(() => {
|
|
52
|
-
if (model) {
|
|
53
|
-
modals.close();
|
|
54
|
-
}
|
|
55
|
-
}, [modals]);
|
|
56
|
-
|
|
57
|
-
if (!model?.view || !model.projection) {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return (
|
|
62
|
-
<Popover.Root
|
|
63
|
-
modal={false}
|
|
64
|
-
open={state?.type === 'createRefPanel' && !!schema}
|
|
65
|
-
onOpenChange={(nextOpen) => {
|
|
66
|
-
if (model && !nextOpen) {
|
|
67
|
-
return modals.close();
|
|
68
|
-
}
|
|
69
|
-
}}
|
|
70
|
-
>
|
|
71
|
-
<Popover.VirtualTrigger virtualRef={modals.trigger} />
|
|
72
|
-
<Popover.Portal>
|
|
73
|
-
<Popover.Content classNames='md:is-64' data-grid={gridId}>
|
|
74
|
-
<Popover.Viewport>
|
|
75
|
-
{state?.type === 'createRefPanel' && schema && (
|
|
76
|
-
<Form schema={schema} values={state.initialValues ?? {}} onSave={handleSave} onCancel={handleCancel} />
|
|
77
|
-
)}
|
|
78
|
-
</Popover.Viewport>
|
|
79
|
-
<Popover.Arrow />
|
|
80
|
-
</Popover.Content>
|
|
81
|
-
</Popover.Portal>
|
|
82
|
-
</Popover.Root>
|
|
83
|
-
);
|
|
84
|
-
};
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import '@dxos-theme';
|
|
6
|
-
|
|
7
|
-
import { type StoryObj, type Meta } from '@storybook/react-vite';
|
|
8
|
-
import { SchemaAST } from 'effect';
|
|
9
|
-
import React, { useEffect, useMemo } from 'react';
|
|
10
|
-
|
|
11
|
-
import { Obj, Ref, type Type } from '@dxos/echo';
|
|
12
|
-
import { getSchemaTypename, toJsonSchema } from '@dxos/echo-schema';
|
|
13
|
-
import { getAnnotation } from '@dxos/effect';
|
|
14
|
-
import { invariant } from '@dxos/invariant';
|
|
15
|
-
import { faker } from '@dxos/random';
|
|
16
|
-
import { useClient } from '@dxos/react-client';
|
|
17
|
-
import { useClientProvider, withClientProvider } from '@dxos/react-client/testing';
|
|
18
|
-
import { DataType, createView, ViewProjection, ViewType } from '@dxos/schema';
|
|
19
|
-
import { createAsyncGenerator, type ValueGenerator } from '@dxos/schema/testing';
|
|
20
|
-
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
21
|
-
|
|
22
|
-
import { Table } from './Table';
|
|
23
|
-
import { useTableModel } from '../../hooks';
|
|
24
|
-
import { type TableFeatures, TablePresentation, type TableRow } from '../../model';
|
|
25
|
-
import { translations } from '../../translations';
|
|
26
|
-
import { TableType } from '../../types';
|
|
27
|
-
|
|
28
|
-
faker.seed(1);
|
|
29
|
-
const generator: ValueGenerator = faker as any;
|
|
30
|
-
|
|
31
|
-
// TODO(burdon): Many-to-many relations.
|
|
32
|
-
// TODO(burdon): Mutable and immutable views.
|
|
33
|
-
// TODO(burdon): Reconcile schemas types and utils (see API PR).
|
|
34
|
-
// TODO(burdon): Base type for T (with id); see ECHO API PR?
|
|
35
|
-
const useTestModel = <S extends Type.Obj.Any>(schema: S, count: number) => {
|
|
36
|
-
const { space } = useClientProvider();
|
|
37
|
-
|
|
38
|
-
const jsonSchema = useMemo(() => toJsonSchema(schema), [schema]);
|
|
39
|
-
const table = useMemo(() => {
|
|
40
|
-
if (!space) {
|
|
41
|
-
return undefined;
|
|
42
|
-
}
|
|
43
|
-
const typename = getSchemaTypename(schema);
|
|
44
|
-
invariant(typename);
|
|
45
|
-
const name = getAnnotation<string>(SchemaAST.TitleAnnotationId)(schema.ast) ?? typename;
|
|
46
|
-
const view = createView({ name, typename, jsonSchema });
|
|
47
|
-
return space.db.add(Obj.make(TableType, { view: Ref.make(view) }));
|
|
48
|
-
}, [schema, space, jsonSchema]);
|
|
49
|
-
|
|
50
|
-
const projection = useMemo(() => {
|
|
51
|
-
if (!table?.view?.target) {
|
|
52
|
-
return undefined;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// TODO(burdon): Just pass in view? Reuse same jsonSchema instance? View determines if mutable, etc.
|
|
56
|
-
return new ViewProjection(jsonSchema, table.view.target);
|
|
57
|
-
}, [jsonSchema, table]);
|
|
58
|
-
|
|
59
|
-
const features = useMemo<TableFeatures>(
|
|
60
|
-
() => ({ schemaEditable: false, dataEditable: true, selection: { enabled: false } }),
|
|
61
|
-
[],
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
const model = useTableModel<TableRow>({ table, projection, rows: [], features });
|
|
65
|
-
useEffect(() => {
|
|
66
|
-
if (!model || !space) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const objectGenerator = createAsyncGenerator(generator, schema, { db: space?.db, force: true });
|
|
71
|
-
void objectGenerator.createObjects(count).then((objects) => {
|
|
72
|
-
model.setRows(objects);
|
|
73
|
-
});
|
|
74
|
-
}, [model, space]);
|
|
75
|
-
|
|
76
|
-
const presentation = useMemo(() => {
|
|
77
|
-
if (!model) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return new TablePresentation(model);
|
|
82
|
-
}, [model]);
|
|
83
|
-
|
|
84
|
-
return { model, presentation };
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const DefaultStory = () => {
|
|
88
|
-
const client = useClient();
|
|
89
|
-
const { model: orgModel, presentation: orgPresentation } = useTestModel(DataType.Organization, 50);
|
|
90
|
-
const { model: contactModel, presentation: contactPresentation } = useTestModel(DataType.Person, 50);
|
|
91
|
-
|
|
92
|
-
return (
|
|
93
|
-
<div className='is-full bs-full grid grid-cols-2 divide-x divide-separator'>
|
|
94
|
-
<Table.Root>
|
|
95
|
-
<Table.Main model={orgModel} presentation={orgPresentation} client={client} ignoreAttention />
|
|
96
|
-
</Table.Root>
|
|
97
|
-
<Table.Root>
|
|
98
|
-
<Table.Main model={contactModel} presentation={contactPresentation} client={client} ignoreAttention />
|
|
99
|
-
</Table.Root>
|
|
100
|
-
</div>
|
|
101
|
-
);
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
const meta: Meta<typeof DefaultStory> = {
|
|
105
|
-
title: 'ui/react-ui-table/relations',
|
|
106
|
-
render: DefaultStory,
|
|
107
|
-
parameters: { translations, controls: { disable: true } },
|
|
108
|
-
decorators: [
|
|
109
|
-
withClientProvider({
|
|
110
|
-
types: [TableType, ViewType, DataType.Organization, DataType.Person],
|
|
111
|
-
createIdentity: true,
|
|
112
|
-
createSpace: true,
|
|
113
|
-
}),
|
|
114
|
-
withTheme,
|
|
115
|
-
withLayout({ fullscreen: true }),
|
|
116
|
-
],
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
export default meta;
|
|
120
|
-
|
|
121
|
-
type Story = StoryObj<typeof DefaultStory>;
|
|
122
|
-
|
|
123
|
-
export const Default: Story = {};
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
autocompletion,
|
|
7
|
-
pickedCompletion,
|
|
8
|
-
type CompletionContext,
|
|
9
|
-
type CompletionResult,
|
|
10
|
-
} from '@codemirror/autocomplete';
|
|
11
|
-
import { type Extension } from '@codemirror/state';
|
|
12
|
-
import { EditorView } from '@codemirror/view';
|
|
13
|
-
|
|
14
|
-
export type CompletionOptions = {
|
|
15
|
-
debug?: boolean;
|
|
16
|
-
onQuery: (text: string) => Promise<CompletionResult['options']>;
|
|
17
|
-
onMatch: (data: any) => void;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Autocomplete Codemirror extension.
|
|
22
|
-
* https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
|
23
|
-
*/
|
|
24
|
-
export const completion = ({ debug, onQuery, onMatch }: CompletionOptions): Extension => {
|
|
25
|
-
return [
|
|
26
|
-
EditorView.theme({
|
|
27
|
-
'.cm-completionDialog': {
|
|
28
|
-
width: 'var(--dx-gridCellWidth)',
|
|
29
|
-
},
|
|
30
|
-
}),
|
|
31
|
-
|
|
32
|
-
autocompletion({
|
|
33
|
-
icons: false,
|
|
34
|
-
activateOnTyping: true,
|
|
35
|
-
closeOnBlur: !debug,
|
|
36
|
-
override: [
|
|
37
|
-
async (context: CompletionContext): Promise<CompletionResult> => {
|
|
38
|
-
const text = context.state.doc.toString();
|
|
39
|
-
return {
|
|
40
|
-
from: 0,
|
|
41
|
-
options: await onQuery(text),
|
|
42
|
-
};
|
|
43
|
-
},
|
|
44
|
-
],
|
|
45
|
-
|
|
46
|
-
// TODO(burdon): Consts from grid (to line-up with grid).
|
|
47
|
-
tooltipClass: () => 'cm-completionDialog !mt-[8px] !-ml-[4px] [&>ul]:!max-h-[264px]',
|
|
48
|
-
optionClass: () => 'flex h-[33px] items-center',
|
|
49
|
-
}),
|
|
50
|
-
|
|
51
|
-
// Check for accepted completion metadata in the transaction.
|
|
52
|
-
EditorView.updateListener.of((update) => {
|
|
53
|
-
update.transactions.forEach((tr) => {
|
|
54
|
-
const completion = tr.annotation(pickedCompletion);
|
|
55
|
-
if (completion) {
|
|
56
|
-
onMatch((completion as any).data);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
}),
|
|
60
|
-
];
|
|
61
|
-
};
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { Rx } from '@effect-rx/rx-react';
|
|
6
|
-
import React, { useMemo } from 'react';
|
|
7
|
-
|
|
8
|
-
import { live } from '@dxos/live-object';
|
|
9
|
-
import { type ThemedClassName } from '@dxos/react-ui';
|
|
10
|
-
import {
|
|
11
|
-
type ActionGraphEdges,
|
|
12
|
-
type ActionGraphNodes,
|
|
13
|
-
type ActionGraphProps,
|
|
14
|
-
createGapSeparator,
|
|
15
|
-
createMenuAction,
|
|
16
|
-
type MenuAction,
|
|
17
|
-
MenuProvider,
|
|
18
|
-
ToolbarMenu,
|
|
19
|
-
useMenuActions,
|
|
20
|
-
} from '@dxos/react-ui-menu';
|
|
21
|
-
import { rxFromSignal } from '@dxos/react-ui-menu';
|
|
22
|
-
|
|
23
|
-
import { translationKey } from '../../translations';
|
|
24
|
-
|
|
25
|
-
export type TableToolbarActionProperties = { type: TableToolbarActionType };
|
|
26
|
-
|
|
27
|
-
export type TableToolbarAction = MenuAction<TableToolbarActionProperties>;
|
|
28
|
-
|
|
29
|
-
export type TableToolbarActionType = 'add-row' | 'comment' | 'save-view';
|
|
30
|
-
|
|
31
|
-
type TableToolbarState = Partial<{ viewDirty: boolean }>;
|
|
32
|
-
|
|
33
|
-
export type TableToolbarProps = ThemedClassName<
|
|
34
|
-
TableToolbarState & {
|
|
35
|
-
onAdd: () => void;
|
|
36
|
-
onSave: () => void;
|
|
37
|
-
attendableId?: string;
|
|
38
|
-
customActions?: Rx.Rx<ActionGraphProps>;
|
|
39
|
-
}
|
|
40
|
-
>;
|
|
41
|
-
|
|
42
|
-
const createTableToolbarActions = ({
|
|
43
|
-
state,
|
|
44
|
-
onAdd,
|
|
45
|
-
onSave,
|
|
46
|
-
customActions,
|
|
47
|
-
}: {
|
|
48
|
-
state: TableToolbarState;
|
|
49
|
-
onAdd: () => void;
|
|
50
|
-
onSave: () => void;
|
|
51
|
-
customActions?: Rx.Rx<ActionGraphProps>;
|
|
52
|
-
}) =>
|
|
53
|
-
Rx.make((get) => {
|
|
54
|
-
const add = createMenuAction<TableToolbarActionProperties>('add-row', onAdd, {
|
|
55
|
-
type: 'add-row' as const,
|
|
56
|
-
icon: 'ph--plus--regular',
|
|
57
|
-
label: ['add row', { ns: translationKey }],
|
|
58
|
-
testId: 'table.toolbar.add-row',
|
|
59
|
-
});
|
|
60
|
-
const save = createMenuAction<TableToolbarActionProperties>('save-view', onSave, {
|
|
61
|
-
type: 'save-view' as const,
|
|
62
|
-
icon: 'ph--floppy-disk--regular',
|
|
63
|
-
label: ['save view label', { ns: translationKey }],
|
|
64
|
-
testId: 'table.toolbar.save-view',
|
|
65
|
-
iconOnly: false,
|
|
66
|
-
hidden: get(rxFromSignal(() => !state.viewDirty)),
|
|
67
|
-
});
|
|
68
|
-
const gap = createGapSeparator();
|
|
69
|
-
const nodes: ActionGraphNodes = [add, save, ...gap.nodes];
|
|
70
|
-
const edges: ActionGraphEdges = nodes.map(({ id: target }) => ({ source: 'root', target }));
|
|
71
|
-
if (customActions) {
|
|
72
|
-
const custom = get(customActions);
|
|
73
|
-
nodes.push(...custom.nodes);
|
|
74
|
-
edges.push(...custom.edges);
|
|
75
|
-
}
|
|
76
|
-
return {
|
|
77
|
-
nodes,
|
|
78
|
-
edges,
|
|
79
|
-
};
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
export const TableToolbar = ({
|
|
83
|
-
classNames,
|
|
84
|
-
viewDirty,
|
|
85
|
-
attendableId,
|
|
86
|
-
onAdd,
|
|
87
|
-
onSave,
|
|
88
|
-
customActions,
|
|
89
|
-
}: TableToolbarProps) => {
|
|
90
|
-
const state = useMemo(() => live<TableToolbarState>({ viewDirty }), []);
|
|
91
|
-
const actionsCreator = useMemo(
|
|
92
|
-
() => createTableToolbarActions({ state, onAdd, onSave, customActions }),
|
|
93
|
-
[state, onAdd, onSave, customActions],
|
|
94
|
-
);
|
|
95
|
-
const menu = useMenuActions(actionsCreator);
|
|
96
|
-
|
|
97
|
-
return (
|
|
98
|
-
<MenuProvider {...menu} attendableId={attendableId}>
|
|
99
|
-
<ToolbarMenu classNames={classNames} />
|
|
100
|
-
</MenuProvider>
|
|
101
|
-
);
|
|
102
|
-
};
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { computed, signal, type Signal, type ReadonlySignal } from '@preact/signals-core';
|
|
6
|
-
import orderBy from 'lodash.orderby';
|
|
7
|
-
|
|
8
|
-
import { getValue, FormatEnum, TypeEnum, type SortDirectionType, type FieldSortType } from '@dxos/echo-schema';
|
|
9
|
-
import { formatForDisplay } from '@dxos/react-ui-form';
|
|
10
|
-
import type { PropertyType, FieldType, ViewProjection, ViewType } from '@dxos/schema';
|
|
11
|
-
|
|
12
|
-
import { type TableRow } from './table-model';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Represents the local sort state.
|
|
16
|
-
* - undefined: No local sort set, fallback to view sort.
|
|
17
|
-
* - cleared: Sort explicitly cleared by user.
|
|
18
|
-
* - active: Active local sort with sort configuration.
|
|
19
|
-
*/
|
|
20
|
-
type LocalSort = { type: 'cleared' } | { type: 'active'; sort: FieldSortType } | undefined;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Manages table sorting functionality through display and data index mapping.
|
|
24
|
-
*
|
|
25
|
-
* When a table is sorted, rows visually reorder but we need to maintain references
|
|
26
|
-
* to the original data positions. This is handled through two types of indices:
|
|
27
|
-
*
|
|
28
|
-
* - Display indices: The visual positions after sorting
|
|
29
|
-
* - Data indices: The original positions in the source data
|
|
30
|
-
*
|
|
31
|
-
* The _displayToDataIndex map maintains these relationships, enabling lookups
|
|
32
|
-
* between visual and source positions.
|
|
33
|
-
*
|
|
34
|
-
* Example mapping between display and data indices:
|
|
35
|
-
*
|
|
36
|
-
* Original Data: Sorted Display: Mapping: (Display → Data)
|
|
37
|
-
* ┌──────────────┐ ┌──────────────┐ ┌────────┐
|
|
38
|
-
* │ 0: "Banana" │ => │ 0: "Apple" │ => │ 0 => 1 │
|
|
39
|
-
* │ 1: "Apple" │ => │ 1: "Banana" │ => │ 1 => 0 │
|
|
40
|
-
* │ 2: "Cherry" │ => │ 2: "Cherry" │ => │ 2 => 2 │
|
|
41
|
-
* └──────────────┘ └──────────────┘ └────────┘
|
|
42
|
-
*/
|
|
43
|
-
export class TableSorting<T extends TableRow> {
|
|
44
|
-
private readonly _displayToDataIndex = new Map<number, number>();
|
|
45
|
-
private readonly _rows: Signal<T[]>;
|
|
46
|
-
private readonly _localSort = signal<LocalSort>(undefined);
|
|
47
|
-
private readonly _isDirty: ReadonlySignal<boolean>;
|
|
48
|
-
public readonly sortedRows: ReadonlySignal<T[]>;
|
|
49
|
-
|
|
50
|
-
constructor(
|
|
51
|
-
rows: Signal<T[]>,
|
|
52
|
-
private readonly _view: ViewType | undefined,
|
|
53
|
-
private readonly _projection: ViewProjection,
|
|
54
|
-
) {
|
|
55
|
-
this._rows = rows;
|
|
56
|
-
this._isDirty = computed(() => {
|
|
57
|
-
const local = this._localSort.value;
|
|
58
|
-
const viewSort = this._view?.query.sort?.[0];
|
|
59
|
-
if (local?.type === 'cleared') {
|
|
60
|
-
return viewSort !== undefined;
|
|
61
|
-
}
|
|
62
|
-
if (local?.type === 'active') {
|
|
63
|
-
if (!viewSort) {
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
return local.sort.fieldId !== viewSort.fieldId || local.sort.direction !== viewSort.direction;
|
|
67
|
-
}
|
|
68
|
-
return false;
|
|
69
|
-
});
|
|
70
|
-
this.sortedRows = this.initialiseSortedRows();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* @reactive
|
|
75
|
-
* @returns Local sort if present, falls back to view sort.
|
|
76
|
-
*/
|
|
77
|
-
public get sorting(): FieldSortType | undefined {
|
|
78
|
-
const local = this._localSort.value;
|
|
79
|
-
if (local?.type === 'cleared') {
|
|
80
|
-
return undefined;
|
|
81
|
-
}
|
|
82
|
-
if (local?.type === 'active') {
|
|
83
|
-
return local.sort;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return this._view?.query.sort?.[0];
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* @reactive
|
|
91
|
-
* @returns Whether local sort differs from view sort.
|
|
92
|
-
*/
|
|
93
|
-
public get isDirty(): boolean {
|
|
94
|
-
return this._isDirty.value;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
public getDataIndex(displayIndex: number): number {
|
|
98
|
-
return this._displayToDataIndex.get(displayIndex) ?? displayIndex;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
public setSort(fieldId: string, direction: SortDirectionType): void {
|
|
102
|
-
this._localSort.value = {
|
|
103
|
-
type: 'active',
|
|
104
|
-
sort: { fieldId, direction },
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
public toggleSort(fieldId: string): void {
|
|
109
|
-
if (!this._view || !this.sorting || this.sorting.fieldId !== fieldId) {
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
switch (this.sorting.direction) {
|
|
114
|
-
case 'asc': {
|
|
115
|
-
this.setSort(fieldId, 'desc');
|
|
116
|
-
break;
|
|
117
|
-
}
|
|
118
|
-
case 'desc': {
|
|
119
|
-
this.setSort(fieldId, 'asc');
|
|
120
|
-
break;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
public clearSort(): void {
|
|
126
|
-
this._localSort.value = { type: 'cleared' };
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
public save(): void {
|
|
130
|
-
if (this._view && this._localSort.value !== undefined) {
|
|
131
|
-
if (this._localSort.value.type === 'active') {
|
|
132
|
-
this._view.query.sort = [this._localSort.value.sort];
|
|
133
|
-
} else {
|
|
134
|
-
this._view.query.sort = [];
|
|
135
|
-
}
|
|
136
|
-
this._localSort.value = undefined;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
//
|
|
141
|
-
// Initialisation.
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
private initialiseSortedRows(): ReadonlySignal<T[]> {
|
|
145
|
-
return computed(() => {
|
|
146
|
-
this._displayToDataIndex.clear();
|
|
147
|
-
const sort = this.sorting;
|
|
148
|
-
if (!sort || !this._view) {
|
|
149
|
-
return this._rows.value;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const field = this._view.fields.find((f) => f.id === sort.fieldId);
|
|
153
|
-
if (!field) {
|
|
154
|
-
return this._rows.value;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
158
|
-
|
|
159
|
-
const dataWithIndices = this._rows.value.map((item, index) => {
|
|
160
|
-
const sortValue = this.getSortValue(props, field, item);
|
|
161
|
-
const isEmpty = !(props.type === TypeEnum.Boolean) && (sortValue == null || sortValue === '');
|
|
162
|
-
|
|
163
|
-
return { item, index, value: sortValue, isEmpty };
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
const ordered = orderBy(dataWithIndices, ['isEmpty', 'value'], ['asc', sort.direction]);
|
|
167
|
-
|
|
168
|
-
ordered.forEach(({ index: dataIndex }, displayIndex) => {
|
|
169
|
-
if (displayIndex !== dataIndex) {
|
|
170
|
-
this._displayToDataIndex.set(displayIndex, dataIndex);
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
return ordered.map(({ item }) => item);
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
private getSortValue(props: PropertyType, field: FieldType, item: T) {
|
|
179
|
-
const { type, format } = props;
|
|
180
|
-
const value = getValue(item, field.path);
|
|
181
|
-
|
|
182
|
-
if (type === TypeEnum.Boolean) {
|
|
183
|
-
return !!value; // Coerce null/undefined to false for booleans.
|
|
184
|
-
}
|
|
185
|
-
if (type === TypeEnum.Number) {
|
|
186
|
-
return value;
|
|
187
|
-
}
|
|
188
|
-
if (value == null) {
|
|
189
|
-
return value;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* For single select fields, the sort value is determined by the index of the option in the
|
|
194
|
-
* options array. This ensures sort order matches the configured option order.
|
|
195
|
-
*/
|
|
196
|
-
if (format === FormatEnum.SingleSelect) {
|
|
197
|
-
const options = props.options;
|
|
198
|
-
if (!options) {
|
|
199
|
-
return undefined;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const option = options.find((option) => option.id === value);
|
|
203
|
-
return option ? options.indexOf(option) : undefined;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// TODO(ZaymonFC): Should we format this returned value for display based on the referenced prop format?
|
|
207
|
-
// Right now we're going to be sorting based on the raw values.
|
|
208
|
-
// Maybe we need to recurse this function with the referenced prop format and field?
|
|
209
|
-
if (format === FormatEnum.Ref && field.referencePath) {
|
|
210
|
-
const refValue = getValue(value.target, field.referencePath);
|
|
211
|
-
return refValue;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return formatForDisplay({ type, format, value });
|
|
215
|
-
}
|
|
216
|
-
}
|