@metaobjectsdev/runtime-web 0.9.0 → 0.11.0-rc.1
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/grid-from-metadata.d.ts +25 -0
- package/dist/grid-from-metadata.d.ts.map +1 -0
- package/dist/grid-from-metadata.js +54 -0
- package/dist/grid-from-metadata.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +33 -22
- package/src/grid-from-metadata.ts +100 -0
- package/src/index.ts +2 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { MetaObject } from "@metaobjectsdev/metadata";
|
|
2
|
+
import type { GridConfig } from "./fetcher.js";
|
|
3
|
+
/** A neutral, framework-agnostic column descriptor derived from metadata. */
|
|
4
|
+
export interface MetaColumn {
|
|
5
|
+
/** The field's logical name (the data accessor key). */
|
|
6
|
+
field: string;
|
|
7
|
+
/** Display header — the field view's `label`, else the humanized field name. */
|
|
8
|
+
header: string;
|
|
9
|
+
/** Cell-renderer hint — the field's view subtype, else the field subtype. */
|
|
10
|
+
viewKind: string;
|
|
11
|
+
}
|
|
12
|
+
export interface MetaGrid {
|
|
13
|
+
config: GridConfig;
|
|
14
|
+
columns: MetaColumn[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Build a grid (config + columns) from a MetaObject at runtime.
|
|
18
|
+
*
|
|
19
|
+
* If the object declares a `dataGrid` layout (optionally selected by `gridName`),
|
|
20
|
+
* its `@columns`, `@pageSize`, sort and `@filterable` attrs drive the result.
|
|
21
|
+
* Otherwise every field becomes a column with sensible defaults — so it works
|
|
22
|
+
* for ANY object, with or without a declared grid.
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildGrid(meta: MetaObject, gridName?: string): MetaGrid;
|
|
25
|
+
//# sourceMappingURL=grid-from-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid-from-metadata.d.ts","sourceRoot":"","sources":["../src/grid-from-metadata.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAuB,MAAM,0BAA0B,CAAC;AAShF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAQ/C,6EAA6E;AAC7E,MAAM,WAAW,UAAU;IACzB,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAoBD;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CA8BvE"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { LAYOUT_SUBTYPE_DATA_GRID, LAYOUT_DATA_GRID_ATTR_COLUMNS, LAYOUT_DATA_GRID_ATTR_PAGE_SIZE, LAYOUT_DATA_GRID_ATTR_DEFAULT_SORT_FIELD, LAYOUT_DATA_GRID_ATTR_DEFAULT_SORT_ORDER, LAYOUT_DATA_GRID_ATTR_FILTERABLE, } from "@metaobjectsdev/metadata";
|
|
2
|
+
const DEFAULT_PAGE_SIZE = 25;
|
|
3
|
+
const DEFAULT_GRID_NAME = "default";
|
|
4
|
+
// The view's display-label attr. Mirrors the literal used by the columns-file
|
|
5
|
+
// codegen; there is no exported constant for it in @metaobjectsdev/metadata.
|
|
6
|
+
const VIEW_ATTR_LABEL = "label";
|
|
7
|
+
/** camelCase / PascalCase → "Title Case" (matches the codegen `humanize`). */
|
|
8
|
+
function humanize(s) {
|
|
9
|
+
return s.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, (c) => c.toUpperCase());
|
|
10
|
+
}
|
|
11
|
+
function firstView(field) {
|
|
12
|
+
return field.ownViews()[0];
|
|
13
|
+
}
|
|
14
|
+
function header(field) {
|
|
15
|
+
const label = firstView(field)?.ownAttr(VIEW_ATTR_LABEL);
|
|
16
|
+
return typeof label === "string" ? label : humanize(field.name);
|
|
17
|
+
}
|
|
18
|
+
function viewKind(field) {
|
|
19
|
+
return firstView(field)?.subType ?? field.subType;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build a grid (config + columns) from a MetaObject at runtime.
|
|
23
|
+
*
|
|
24
|
+
* If the object declares a `dataGrid` layout (optionally selected by `gridName`),
|
|
25
|
+
* its `@columns`, `@pageSize`, sort and `@filterable` attrs drive the result.
|
|
26
|
+
* Otherwise every field becomes a column with sensible defaults — so it works
|
|
27
|
+
* for ANY object, with or without a declared grid.
|
|
28
|
+
*/
|
|
29
|
+
export function buildGrid(meta, gridName) {
|
|
30
|
+
const layouts = meta.layouts().filter((l) => l.subType === LAYOUT_SUBTYPE_DATA_GRID);
|
|
31
|
+
const layout = gridName ? layouts.find((l) => l.name === gridName) : layouts[0];
|
|
32
|
+
const fieldsByName = new Map(meta.fields().map((f) => [f.name, f]));
|
|
33
|
+
const columnsAttr = layout?.ownAttr(LAYOUT_DATA_GRID_ATTR_COLUMNS);
|
|
34
|
+
const names = Array.isArray(columnsAttr)
|
|
35
|
+
? columnsAttr.filter((x) => typeof x === "string")
|
|
36
|
+
: meta.fields().map((f) => f.name);
|
|
37
|
+
const columns = names
|
|
38
|
+
.map((n) => fieldsByName.get(n))
|
|
39
|
+
.filter((f) => f !== undefined)
|
|
40
|
+
.map((f) => ({ field: f.name, header: header(f), viewKind: viewKind(f) }));
|
|
41
|
+
const pageSizeAttr = layout?.ownAttr(LAYOUT_DATA_GRID_ATTR_PAGE_SIZE);
|
|
42
|
+
const sortField = layout?.ownAttr(LAYOUT_DATA_GRID_ATTR_DEFAULT_SORT_FIELD);
|
|
43
|
+
const sortOrder = layout?.ownAttr(LAYOUT_DATA_GRID_ATTR_DEFAULT_SORT_ORDER);
|
|
44
|
+
const config = {
|
|
45
|
+
name: layout?.name ?? gridName ?? DEFAULT_GRID_NAME,
|
|
46
|
+
pageSize: typeof pageSizeAttr === "number" ? pageSizeAttr : DEFAULT_PAGE_SIZE,
|
|
47
|
+
filterable: layout?.ownAttr(LAYOUT_DATA_GRID_ATTR_FILTERABLE) === true,
|
|
48
|
+
...(typeof sortField === "string"
|
|
49
|
+
? { defaultSort: { field: sortField, order: sortOrder === "desc" ? "desc" : "asc" } }
|
|
50
|
+
: {}),
|
|
51
|
+
};
|
|
52
|
+
return { config, columns };
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=grid-from-metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid-from-metadata.js","sourceRoot":"","sources":["../src/grid-from-metadata.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { formatCurrency, parseCurrency, minorUnitsFor } from "./currency.js";
|
|
2
2
|
export { buildFilterQs } from "./filter-qs.js";
|
|
3
3
|
export type { EntityFetcher, GridConfig } from "./fetcher.js";
|
|
4
|
+
export { buildGrid } from "./grid-from-metadata.js";
|
|
5
|
+
export type { MetaColumn, MetaGrid } from "./grid-from-metadata.js";
|
|
4
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Public API surface for @metaobjectsdev/runtime-web.
|
|
2
2
|
export { formatCurrency, parseCurrency, minorUnitsFor } from "./currency.js";
|
|
3
3
|
export { buildFilterQs } from "./filter-qs.js";
|
|
4
|
+
export { buildGrid } from "./grid-from-metadata.js";
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metaobjectsdev/runtime-web",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0-rc.1",
|
|
4
4
|
"description": "Pure framework-agnostic browser core for metaobjects: currency, filter URL serialization, fetcher contract types.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -12,7 +12,12 @@
|
|
|
12
12
|
"default": "./dist/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
-
"files": [
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"src",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
16
21
|
"scripts": {
|
|
17
22
|
"build": "tsc -p tsconfig.json",
|
|
18
23
|
"typecheck": "tsc -p tsconfig.typecheck.json",
|
|
@@ -22,24 +27,30 @@
|
|
|
22
27
|
"author": "Doug Mealing <doug@dougmealing.com>",
|
|
23
28
|
"homepage": "https://metaobjects.dev",
|
|
24
29
|
"bugs": {
|
|
25
|
-
|
|
26
|
-
},
|
|
27
|
-
"repository": {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
},
|
|
32
|
-
"keywords": [
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
30
|
+
"url": "https://github.com/metaobjectsdev/metaobjects/issues"
|
|
31
|
+
},
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/metaobjectsdev/metaobjects.git",
|
|
35
|
+
"directory": "client/web/packages/runtime-web"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"metaobjects",
|
|
39
|
+
"runtime",
|
|
40
|
+
"browser",
|
|
41
|
+
"currency",
|
|
42
|
+
"filter"
|
|
43
|
+
],
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@metaobjectsdev/metadata": "0.11.0-rc.1",
|
|
49
|
+
"qs": "^6.13.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/qs": "^6.9.0",
|
|
53
|
+
"bun-types": "latest",
|
|
54
|
+
"typescript": "^5.6.0"
|
|
55
|
+
}
|
|
45
56
|
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Metadata-driven grid — the runtime twin of the `tanstackGrid()` codegen.
|
|
2
|
+
//
|
|
3
|
+
// Builds grid columns + config by walking a loaded MetaObject's fields and
|
|
4
|
+
// views at RUNTIME. Fully generic: no object or field names are hardcoded, so
|
|
5
|
+
// one call renders any object you've described in metadata. Pass any MetaObject
|
|
6
|
+
// (e.g. obtained from a loader, or via a MetaObjectAware row's getMetaData()).
|
|
7
|
+
//
|
|
8
|
+
// Mirrors the derivation in codegen-ts-tanstack's columns-file (humanized
|
|
9
|
+
// headers, the field's view subtype as the cell-renderer hint, @columns / grid
|
|
10
|
+
// attrs from the dataGrid layout) so a runtime-built grid matches a generated
|
|
11
|
+
// one. Browser-safe: depends only on @metaobjectsdev/metadata.
|
|
12
|
+
import type { MetaObject, MetaField, MetaView } from "@metaobjectsdev/metadata";
|
|
13
|
+
import {
|
|
14
|
+
LAYOUT_SUBTYPE_DATA_GRID,
|
|
15
|
+
LAYOUT_DATA_GRID_ATTR_COLUMNS,
|
|
16
|
+
LAYOUT_DATA_GRID_ATTR_PAGE_SIZE,
|
|
17
|
+
LAYOUT_DATA_GRID_ATTR_DEFAULT_SORT_FIELD,
|
|
18
|
+
LAYOUT_DATA_GRID_ATTR_DEFAULT_SORT_ORDER,
|
|
19
|
+
LAYOUT_DATA_GRID_ATTR_FILTERABLE,
|
|
20
|
+
} from "@metaobjectsdev/metadata";
|
|
21
|
+
import type { GridConfig } from "./fetcher.js";
|
|
22
|
+
|
|
23
|
+
const DEFAULT_PAGE_SIZE = 25;
|
|
24
|
+
const DEFAULT_GRID_NAME = "default";
|
|
25
|
+
// The view's display-label attr. Mirrors the literal used by the columns-file
|
|
26
|
+
// codegen; there is no exported constant for it in @metaobjectsdev/metadata.
|
|
27
|
+
const VIEW_ATTR_LABEL = "label";
|
|
28
|
+
|
|
29
|
+
/** A neutral, framework-agnostic column descriptor derived from metadata. */
|
|
30
|
+
export interface MetaColumn {
|
|
31
|
+
/** The field's logical name (the data accessor key). */
|
|
32
|
+
field: string;
|
|
33
|
+
/** Display header — the field view's `label`, else the humanized field name. */
|
|
34
|
+
header: string;
|
|
35
|
+
/** Cell-renderer hint — the field's view subtype, else the field subtype. */
|
|
36
|
+
viewKind: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface MetaGrid {
|
|
40
|
+
config: GridConfig;
|
|
41
|
+
columns: MetaColumn[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** camelCase / PascalCase → "Title Case" (matches the codegen `humanize`). */
|
|
45
|
+
function humanize(s: string): string {
|
|
46
|
+
return s.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, (c) => c.toUpperCase());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function firstView(field: MetaField): MetaView | undefined {
|
|
50
|
+
return field.ownViews()[0];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function header(field: MetaField): string {
|
|
54
|
+
const label = firstView(field)?.ownAttr(VIEW_ATTR_LABEL);
|
|
55
|
+
return typeof label === "string" ? label : humanize(field.name);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function viewKind(field: MetaField): string {
|
|
59
|
+
return firstView(field)?.subType ?? field.subType;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Build a grid (config + columns) from a MetaObject at runtime.
|
|
64
|
+
*
|
|
65
|
+
* If the object declares a `dataGrid` layout (optionally selected by `gridName`),
|
|
66
|
+
* its `@columns`, `@pageSize`, sort and `@filterable` attrs drive the result.
|
|
67
|
+
* Otherwise every field becomes a column with sensible defaults — so it works
|
|
68
|
+
* for ANY object, with or without a declared grid.
|
|
69
|
+
*/
|
|
70
|
+
export function buildGrid(meta: MetaObject, gridName?: string): MetaGrid {
|
|
71
|
+
const layouts = meta.layouts().filter((l) => l.subType === LAYOUT_SUBTYPE_DATA_GRID);
|
|
72
|
+
const layout = gridName ? layouts.find((l) => l.name === gridName) : layouts[0];
|
|
73
|
+
|
|
74
|
+
const fieldsByName = new Map(meta.fields().map((f) => [f.name, f] as const));
|
|
75
|
+
|
|
76
|
+
const columnsAttr = layout?.ownAttr(LAYOUT_DATA_GRID_ATTR_COLUMNS);
|
|
77
|
+
const names: string[] = Array.isArray(columnsAttr)
|
|
78
|
+
? columnsAttr.filter((x): x is string => typeof x === "string")
|
|
79
|
+
: meta.fields().map((f) => f.name);
|
|
80
|
+
|
|
81
|
+
const columns: MetaColumn[] = names
|
|
82
|
+
.map((n) => fieldsByName.get(n))
|
|
83
|
+
.filter((f): f is MetaField => f !== undefined)
|
|
84
|
+
.map((f) => ({ field: f.name, header: header(f), viewKind: viewKind(f) }));
|
|
85
|
+
|
|
86
|
+
const pageSizeAttr = layout?.ownAttr(LAYOUT_DATA_GRID_ATTR_PAGE_SIZE);
|
|
87
|
+
const sortField = layout?.ownAttr(LAYOUT_DATA_GRID_ATTR_DEFAULT_SORT_FIELD);
|
|
88
|
+
const sortOrder = layout?.ownAttr(LAYOUT_DATA_GRID_ATTR_DEFAULT_SORT_ORDER);
|
|
89
|
+
|
|
90
|
+
const config: GridConfig = {
|
|
91
|
+
name: layout?.name ?? gridName ?? DEFAULT_GRID_NAME,
|
|
92
|
+
pageSize: typeof pageSizeAttr === "number" ? pageSizeAttr : DEFAULT_PAGE_SIZE,
|
|
93
|
+
filterable: layout?.ownAttr(LAYOUT_DATA_GRID_ATTR_FILTERABLE) === true,
|
|
94
|
+
...(typeof sortField === "string"
|
|
95
|
+
? { defaultSort: { field: sortField, order: sortOrder === "desc" ? "desc" : "asc" } }
|
|
96
|
+
: {}),
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
return { config, columns };
|
|
100
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -2,3 +2,5 @@
|
|
|
2
2
|
export { formatCurrency, parseCurrency, minorUnitsFor } from "./currency.js";
|
|
3
3
|
export { buildFilterQs } from "./filter-qs.js";
|
|
4
4
|
export type { EntityFetcher, GridConfig } from "./fetcher.js";
|
|
5
|
+
export { buildGrid } from "./grid-from-metadata.js";
|
|
6
|
+
export type { MetaColumn, MetaGrid } from "./grid-from-metadata.js";
|