@fusedashlabs/widgets 0.4.3 → 0.4.5
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/CHANGELOG.md +12 -0
- package/dist/components/bar-chart/element/styles.js +3 -3
- package/dist/components/bar-chart/element/styles.js.map +1 -1
- package/dist/components/box-plot-chart/element/styles.js +3 -3
- package/dist/components/box-plot-chart/element/styles.js.map +1 -1
- package/dist/components/chart-renderer/element/styles.d.ts.map +1 -1
- package/dist/components/chart-renderer/element/styles.js +4 -1
- package/dist/components/chart-renderer/element/styles.js.map +1 -1
- package/dist/components/chart-renderer/element/ui9000-chart-renderer.d.ts.map +1 -1
- package/dist/components/chart-renderer/element/ui9000-chart-renderer.js +12 -0
- package/dist/components/chart-renderer/element/ui9000-chart-renderer.js.map +1 -1
- package/dist/components/chart-renderer/metadata.json.d.ts +6 -1
- package/dist/components/chart-renderer/metadata.json.js +1 -1
- package/dist/components/custom-widget/element/styles.d.ts +2 -0
- package/dist/components/custom-widget/element/styles.d.ts.map +1 -0
- package/dist/components/custom-widget/element/styles.js +286 -0
- package/dist/components/custom-widget/element/styles.js.map +1 -0
- package/dist/components/custom-widget/element/ui9000-custom-widget.d.ts +48 -0
- package/dist/components/custom-widget/element/ui9000-custom-widget.d.ts.map +1 -0
- package/dist/components/custom-widget/element/ui9000-custom-widget.js +265 -0
- package/dist/components/custom-widget/element/ui9000-custom-widget.js.map +1 -0
- package/dist/components/custom-widget/index.d.ts +4 -0
- package/dist/components/custom-widget/index.d.ts.map +1 -0
- package/dist/components/custom-widget/index.js +19 -0
- package/dist/components/custom-widget/index.js.map +1 -0
- package/dist/components/custom-widget/lib/content.d.ts +13 -0
- package/dist/components/custom-widget/lib/content.d.ts.map +1 -0
- package/dist/components/custom-widget/lib/content.js +22 -0
- package/dist/components/custom-widget/lib/content.js.map +1 -0
- package/dist/components/custom-widget/lib/index.d.ts +8 -0
- package/dist/components/custom-widget/lib/index.d.ts.map +1 -0
- package/dist/components/custom-widget/lib/layout.d.ts +35 -0
- package/dist/components/custom-widget/lib/layout.d.ts.map +1 -0
- package/dist/components/custom-widget/lib/layout.js +13 -0
- package/dist/components/custom-widget/lib/layout.js.map +1 -0
- package/dist/components/custom-widget/lib/markdown.d.ts +4 -0
- package/dist/components/custom-widget/lib/markdown.d.ts.map +1 -0
- package/dist/components/custom-widget/lib/markdown.js +125 -0
- package/dist/components/custom-widget/lib/markdown.js.map +1 -0
- package/dist/components/custom-widget/lib/normalize.d.ts +6 -0
- package/dist/components/custom-widget/lib/normalize.d.ts.map +1 -0
- package/dist/components/custom-widget/lib/normalize.js +144 -0
- package/dist/components/custom-widget/lib/normalize.js.map +1 -0
- package/dist/components/custom-widget/lib/table.d.ts +55 -0
- package/dist/components/custom-widget/lib/table.d.ts.map +1 -0
- package/dist/components/custom-widget/lib/table.js +181 -0
- package/dist/components/custom-widget/lib/table.js.map +1 -0
- package/dist/components/custom-widget/lib/types.d.ts +55 -0
- package/dist/components/custom-widget/lib/types.d.ts.map +1 -0
- package/dist/components/custom-widget/metadata.json.d.ts +96 -0
- package/dist/components/custom-widget/metadata.json.js +42 -0
- package/dist/components/custom-widget/metadata.json.js.map +1 -0
- package/dist/components/histogram-chart/element/styles.js +2 -2
- package/dist/components/histogram-chart/element/styles.js.map +1 -1
- package/dist/components/line-chart/element/styles.js +2 -2
- package/dist/components/line-chart/element/styles.js.map +1 -1
- package/dist/components/lollipop/element/styles.js +3 -3
- package/dist/components/lollipop/element/styles.js.map +1 -1
- package/dist/components/map-chart/lib/constants.d.ts +2 -0
- package/dist/components/map-chart/lib/constants.d.ts.map +1 -1
- package/dist/components/map-chart/lib/constants.js +6 -0
- package/dist/components/map-chart/lib/constants.js.map +1 -1
- package/dist/components/map-chart/lib/geo-index.d.ts.map +1 -1
- package/dist/components/map-chart/lib/geo-index.js +5 -1
- package/dist/components/map-chart/lib/geo-index.js.map +1 -1
- package/dist/components/step-line-chart/element/styles.js +2 -2
- package/dist/components/step-line-chart/element/styles.js.map +1 -1
- package/dist/element/chart-shell-styles.d.ts.map +1 -1
- package/dist/element/chart-shell-styles.js +11 -4
- package/dist/element/chart-shell-styles.js.map +1 -1
- package/dist/element/ui9000-chart-base.d.ts +5 -0
- package/dist/element/ui9000-chart-base.d.ts.map +1 -1
- package/dist/element/ui9000-chart-base.js +7 -1
- package/dist/element/ui9000-chart-base.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -1
- package/dist/index.js.map +1 -1
- package/dist/lazy/custom-widget.d.ts +4 -0
- package/dist/lazy/custom-widget.d.ts.map +1 -0
- package/dist/lazy/index.d.ts +2 -1
- package/dist/lazy/index.d.ts.map +1 -1
- package/dist/lazy/index.js +8 -0
- package/dist/lazy/index.js.map +1 -1
- package/package.json +9 -1
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { normalizeTextContent, normalizeImageContent } from "./content.js";
|
|
2
|
+
import { MAX_PANES } from "./layout.js";
|
|
3
|
+
import { parseTableHeaders, getSourceFromContains, normalizeTableModel } from "./table.js";
|
|
4
|
+
const PANE_KINDS = [
|
|
5
|
+
"chartWidget",
|
|
6
|
+
"tableWidget",
|
|
7
|
+
"textWidget",
|
|
8
|
+
"imageWidget"
|
|
9
|
+
];
|
|
10
|
+
const CONTENT_CHART_TYPES = ["tableChart", "textChart", "imageChart"];
|
|
11
|
+
const CHART_EMPTY_TITLE = "Custom Chart";
|
|
12
|
+
const CHART_EMPTY_SUBTITLE = "Choose a chart from recommended or configure it by your own.";
|
|
13
|
+
const PANE_EMPTY_TITLES = {
|
|
14
|
+
chartWidget: CHART_EMPTY_TITLE,
|
|
15
|
+
tableWidget: "Table",
|
|
16
|
+
textWidget: "Text",
|
|
17
|
+
imageWidget: "Image"
|
|
18
|
+
};
|
|
19
|
+
const EMPTY_MODEL = {
|
|
20
|
+
title: "",
|
|
21
|
+
direction: "vertical",
|
|
22
|
+
hasKpi: false,
|
|
23
|
+
panes: [],
|
|
24
|
+
widget: null,
|
|
25
|
+
isEmpty: true
|
|
26
|
+
};
|
|
27
|
+
function isPaneKind(value) {
|
|
28
|
+
return typeof value === "string" && PANE_KINDS.includes(value);
|
|
29
|
+
}
|
|
30
|
+
function isContentChartType(chartType) {
|
|
31
|
+
return !!chartType && CONTENT_CHART_TYPES.includes(chartType);
|
|
32
|
+
}
|
|
33
|
+
function emptyPane(kind, index, widgetId, title, subtitle) {
|
|
34
|
+
return {
|
|
35
|
+
key: `${widgetId}-${kind}-${index}`,
|
|
36
|
+
kind,
|
|
37
|
+
renderable: false,
|
|
38
|
+
emptyTitle: title,
|
|
39
|
+
emptySubtitle: subtitle
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function buildPane(kind, index, widget) {
|
|
43
|
+
const widgetId = typeof widget.id === "string" ? widget.id : "";
|
|
44
|
+
const chartType = widget.chartType;
|
|
45
|
+
if (kind === "chartWidget") {
|
|
46
|
+
const renderable = !isContentChartType(chartType);
|
|
47
|
+
return {
|
|
48
|
+
key: `${widgetId}-${kind}-${index}`,
|
|
49
|
+
kind,
|
|
50
|
+
renderable,
|
|
51
|
+
emptyTitle: PANE_EMPTY_TITLES.chartWidget,
|
|
52
|
+
emptySubtitle: CHART_EMPTY_SUBTITLE
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (kind === "tableWidget") {
|
|
56
|
+
const headers = parseTableHeaders(widget.headers);
|
|
57
|
+
if (!headers.length) {
|
|
58
|
+
return emptyPane(
|
|
59
|
+
kind,
|
|
60
|
+
index,
|
|
61
|
+
widgetId,
|
|
62
|
+
"No table columns yet",
|
|
63
|
+
"Use MCP chat to describe which dataset fields, chart fields, or personal table data to show in this table."
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
if (headers.some((header) => !getSourceFromContains(header))) {
|
|
67
|
+
return emptyPane(
|
|
68
|
+
kind,
|
|
69
|
+
index,
|
|
70
|
+
widgetId,
|
|
71
|
+
"Table columns need sources",
|
|
72
|
+
"Each column must specify a dataset, chart, or static (tableData) field via MCP chat."
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
const table = normalizeTableModel(widget);
|
|
76
|
+
return {
|
|
77
|
+
key: `${widgetId}-${kind}-${index}`,
|
|
78
|
+
kind,
|
|
79
|
+
renderable: true,
|
|
80
|
+
emptyTitle: PANE_EMPTY_TITLES.tableWidget,
|
|
81
|
+
emptySubtitle: "",
|
|
82
|
+
table: table ?? { columns: [], cells: [] }
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (kind === "textWidget") {
|
|
86
|
+
const text = normalizeTextContent(widget);
|
|
87
|
+
if (!text) {
|
|
88
|
+
return emptyPane(
|
|
89
|
+
kind,
|
|
90
|
+
index,
|
|
91
|
+
widgetId,
|
|
92
|
+
"Add text",
|
|
93
|
+
"Click to write your own text or use AI to generate content"
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
key: `${widgetId}-${kind}-${index}`,
|
|
98
|
+
kind,
|
|
99
|
+
renderable: true,
|
|
100
|
+
emptyTitle: PANE_EMPTY_TITLES.textWidget,
|
|
101
|
+
emptySubtitle: "",
|
|
102
|
+
text
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const image = normalizeImageContent(widget);
|
|
106
|
+
if (!image) {
|
|
107
|
+
return emptyPane(
|
|
108
|
+
kind,
|
|
109
|
+
index,
|
|
110
|
+
widgetId,
|
|
111
|
+
"Upload or Generate an Image",
|
|
112
|
+
"The image should reflect the presented information"
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
key: `${widgetId}-${kind}-${index}`,
|
|
117
|
+
kind,
|
|
118
|
+
renderable: true,
|
|
119
|
+
emptyTitle: PANE_EMPTY_TITLES.imageWidget,
|
|
120
|
+
emptySubtitle: "",
|
|
121
|
+
image
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function normalizeCustomWidget(input) {
|
|
125
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return EMPTY_MODEL;
|
|
126
|
+
const widget = input;
|
|
127
|
+
const arranging = widget.arranging ?? {};
|
|
128
|
+
const direction = arranging.direction === "horizontal" ? "horizontal" : "vertical";
|
|
129
|
+
const hasKpi = !!arranging.hasKpi;
|
|
130
|
+
const panes = (Array.isArray(arranging.widgets) ? arranging.widgets : []).filter(isPaneKind).slice(0, MAX_PANES).map((kind, index) => buildPane(kind, index, widget));
|
|
131
|
+
return {
|
|
132
|
+
title: typeof widget.name === "string" ? widget.name.trim() : "",
|
|
133
|
+
direction,
|
|
134
|
+
hasKpi,
|
|
135
|
+
panes,
|
|
136
|
+
widget,
|
|
137
|
+
isEmpty: panes.length === 0 && !hasKpi
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
export {
|
|
141
|
+
isContentChartType,
|
|
142
|
+
normalizeCustomWidget
|
|
143
|
+
};
|
|
144
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sources":["../../../../src/components/custom-widget/lib/normalize.ts"],"sourcesContent":["import { normalizeImageContent, normalizeTextContent } from './content.js';\nimport { MAX_PANES } from './layout.js';\nimport { getSourceFromContains, normalizeTableModel, parseTableHeaders } from './table.js';\nimport type {\n ArrangingDirection,\n CustomPane,\n CustomPaneKind,\n CustomWidgetModel,\n CustomWidgetPayload,\n} from './types.js';\n\nconst PANE_KINDS: readonly CustomPaneKind[] = [\n 'chartWidget',\n 'tableWidget',\n 'textWidget',\n 'imageWidget',\n];\n\n/** Client `CONTENT_WIDGET_TYPES` — chart panes fall back to the empty state for these */\nconst CONTENT_CHART_TYPES = ['tableChart', 'textChart', 'imageChart'];\n\n/** Copy lifted from the client `ChartWidget` empty state */\nconst CHART_EMPTY_TITLE = 'Custom Chart';\nconst CHART_EMPTY_SUBTITLE =\n 'Choose a chart from recommended or configure it by your own.';\n\nconst PANE_EMPTY_TITLES: Record<CustomPaneKind, string> = {\n chartWidget: CHART_EMPTY_TITLE,\n tableWidget: 'Table',\n textWidget: 'Text',\n imageWidget: 'Image',\n};\n\nconst EMPTY_MODEL: CustomWidgetModel = {\n title: '',\n direction: 'vertical',\n hasKpi: false,\n panes: [],\n widget: null,\n isEmpty: true,\n};\n\nfunction isPaneKind(value: unknown): value is CustomPaneKind {\n return typeof value === 'string' && PANE_KINDS.includes(value as CustomPaneKind);\n}\n\n/** Chart panes whose widget `chartType` is a content type render empty, as in the client */\nexport function isContentChartType(chartType: string | undefined): boolean {\n return !!chartType && CONTENT_CHART_TYPES.includes(chartType);\n}\n\nfunction emptyPane(\n kind: CustomPaneKind,\n index: number,\n widgetId: string,\n title: string,\n subtitle: string,\n): CustomPane {\n return {\n key: `${widgetId}-${kind}-${index}`,\n kind,\n renderable: false,\n emptyTitle: title,\n emptySubtitle: subtitle,\n };\n}\n\nfunction buildPane(kind: CustomPaneKind, index: number, widget: CustomWidgetPayload): CustomPane {\n const widgetId = typeof widget.id === 'string' ? widget.id : '';\n const chartType = widget.chartType;\n\n if (kind === 'chartWidget') {\n const renderable = !isContentChartType(chartType);\n return {\n key: `${widgetId}-${kind}-${index}`,\n kind,\n renderable,\n emptyTitle: PANE_EMPTY_TITLES.chartWidget,\n emptySubtitle: CHART_EMPTY_SUBTITLE,\n };\n }\n\n if (kind === 'tableWidget') {\n const headers = parseTableHeaders(widget.headers);\n if (!headers.length) {\n return emptyPane(\n kind,\n index,\n widgetId,\n 'No table columns yet',\n 'Use MCP chat to describe which dataset fields, chart fields, or personal table data to show in this table.',\n );\n }\n if (headers.some((header) => !getSourceFromContains(header))) {\n return emptyPane(\n kind,\n index,\n widgetId,\n 'Table columns need sources',\n 'Each column must specify a dataset, chart, or static (tableData) field via MCP chat.',\n );\n }\n const table = normalizeTableModel(widget);\n return {\n key: `${widgetId}-${kind}-${index}`,\n kind,\n renderable: true,\n emptyTitle: PANE_EMPTY_TITLES.tableWidget,\n emptySubtitle: '',\n table: table ?? { columns: [], cells: [] },\n };\n }\n\n if (kind === 'textWidget') {\n const text = normalizeTextContent(widget);\n if (!text) {\n return emptyPane(\n kind,\n index,\n widgetId,\n 'Add text',\n 'Click to write your own text or use AI to generate content',\n );\n }\n return {\n key: `${widgetId}-${kind}-${index}`,\n kind,\n renderable: true,\n emptyTitle: PANE_EMPTY_TITLES.textWidget,\n emptySubtitle: '',\n text,\n };\n }\n\n const image = normalizeImageContent(widget);\n if (!image) {\n return emptyPane(\n kind,\n index,\n widgetId,\n 'Upload or Generate an Image',\n 'The image should reflect the presented information',\n );\n }\n return {\n key: `${widgetId}-${kind}-${index}`,\n kind,\n renderable: true,\n emptyTitle: PANE_EMPTY_TITLES.imageWidget,\n emptySubtitle: '',\n image,\n };\n}\n\n/** Build the shell model from a FuseDash CustomWidget payload. */\nexport function normalizeCustomWidget(input: unknown): CustomWidgetModel {\n if (!input || typeof input !== 'object' || Array.isArray(input)) return EMPTY_MODEL;\n\n const widget = input as CustomWidgetPayload;\n const arranging = widget.arranging ?? {};\n const direction: ArrangingDirection =\n arranging.direction === 'horizontal' ? 'horizontal' : 'vertical';\n const hasKpi = !!arranging.hasKpi;\n\n const panes = (Array.isArray(arranging.widgets) ? arranging.widgets : [])\n .filter(isPaneKind)\n .slice(0, MAX_PANES)\n .map((kind, index) => buildPane(kind, index, widget));\n\n return {\n title: typeof widget.name === 'string' ? widget.name.trim() : '',\n direction,\n hasKpi,\n panes,\n widget,\n isEmpty: panes.length === 0 && !hasKpi,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** Client CustomWidget TableWidget — sources, zip-by-index rows, MCP preview fallback. */
|
|
2
|
+
export type TableColumnSource = {
|
|
3
|
+
type: 'dataset';
|
|
4
|
+
datasetId: string;
|
|
5
|
+
field: string;
|
|
6
|
+
} | {
|
|
7
|
+
type: 'chart';
|
|
8
|
+
field: string;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'static';
|
|
11
|
+
field: string;
|
|
12
|
+
};
|
|
13
|
+
export interface TableHeaderContains {
|
|
14
|
+
key?: string;
|
|
15
|
+
source?: TableColumnSource;
|
|
16
|
+
}
|
|
17
|
+
export interface TableHeader {
|
|
18
|
+
label: string;
|
|
19
|
+
contains?: TableHeaderContains[];
|
|
20
|
+
}
|
|
21
|
+
export type DataRow = Record<string, string | number | boolean | null | undefined>;
|
|
22
|
+
export interface TableCellModel {
|
|
23
|
+
text: string;
|
|
24
|
+
badge?: 'success' | 'error';
|
|
25
|
+
}
|
|
26
|
+
export interface CustomTableModel {
|
|
27
|
+
columns: {
|
|
28
|
+
key: string;
|
|
29
|
+
label: string;
|
|
30
|
+
}[];
|
|
31
|
+
cells: TableCellModel[][];
|
|
32
|
+
}
|
|
33
|
+
export declare function stripDataPrefix(field: string): string;
|
|
34
|
+
export declare function buildQualifiedDatasetColumnKey(datasetId: string, field: string): string;
|
|
35
|
+
export declare function buildQualifiedChartColumnKey(field: string): string;
|
|
36
|
+
export declare function buildQualifiedStaticColumnKey(field: string): string;
|
|
37
|
+
export declare function getSourceFromContains(header: TableHeader): TableColumnSource | undefined;
|
|
38
|
+
export declare function parseTableHeaders(input: unknown): TableHeader[];
|
|
39
|
+
export declare function asDataRows(input: unknown): DataRow[];
|
|
40
|
+
/** Client `buildLiveTableRowsFromSources` — zip sources by row index, not a join. */
|
|
41
|
+
export declare function buildLiveTableRowsFromSources({ headers, datasetRows, chartRows, tableDataRows, }: {
|
|
42
|
+
headers: TableHeader[];
|
|
43
|
+
datasetRows: DataRow[];
|
|
44
|
+
chartRows: DataRow[];
|
|
45
|
+
tableDataRows?: DataRow[];
|
|
46
|
+
}): DataRow[];
|
|
47
|
+
/** Client `getCellValue` — stringify + Findings badge. */
|
|
48
|
+
export declare function formatTableCell(header: TableHeader, row: DataRow): TableCellModel;
|
|
49
|
+
export declare function normalizeTableModel(widget: {
|
|
50
|
+
headers?: unknown;
|
|
51
|
+
data?: unknown;
|
|
52
|
+
tableData?: unknown;
|
|
53
|
+
tablePreviewRows?: unknown;
|
|
54
|
+
}): CustomTableModel | null;
|
|
55
|
+
//# sourceMappingURL=table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../../src/components/custom-widget/lib/table.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAE1F,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAClC;AAED,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;AAEnF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1C,KAAK,EAAE,cAAc,EAAE,EAAE,CAAC;CAC3B;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvF;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnE;AAgBD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,GAAG,SAAS,CAExF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,EAAE,CAqB/D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,EAAE,CAKpD;AAED,qFAAqF;AACrF,wBAAgB,6BAA6B,CAAC,EAC5C,OAAO,EACP,WAAW,EACX,SAAS,EACT,aAAkB,GACnB,EAAE;IACD,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,WAAW,EAAE,OAAO,EAAE,CAAC;IACvB,SAAS,EAAE,OAAO,EAAE,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC;CAC3B,GAAG,OAAO,EAAE,CAwDZ;AAsBD,0DAA0D;AAC1D,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,OAAO,GAAG,cAAc,CA8BjF;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG,gBAAgB,GAAG,IAAI,CAqB1B"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
function stripDataPrefix(field) {
|
|
2
|
+
return field.startsWith("data.") ? field.slice("data.".length) : field;
|
|
3
|
+
}
|
|
4
|
+
function buildQualifiedDatasetColumnKey(datasetId, field) {
|
|
5
|
+
return `${field}__${datasetId}`;
|
|
6
|
+
}
|
|
7
|
+
function buildQualifiedChartColumnKey(field) {
|
|
8
|
+
return `${field}__chart`;
|
|
9
|
+
}
|
|
10
|
+
function buildQualifiedStaticColumnKey(field) {
|
|
11
|
+
return `${field}__static`;
|
|
12
|
+
}
|
|
13
|
+
function parseSource(raw) {
|
|
14
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
15
|
+
const o = raw;
|
|
16
|
+
const field = typeof o.field === "string" ? stripDataPrefix(o.field.trim()) : "";
|
|
17
|
+
if (!field) return void 0;
|
|
18
|
+
if (o.type === "chart" || o.type === "static") return { type: o.type, field };
|
|
19
|
+
if (o.type === "dataset") {
|
|
20
|
+
const datasetId = typeof o.datasetId === "string" ? o.datasetId.trim() : "";
|
|
21
|
+
if (!datasetId) return void 0;
|
|
22
|
+
return { type: "dataset", datasetId, field };
|
|
23
|
+
}
|
|
24
|
+
return void 0;
|
|
25
|
+
}
|
|
26
|
+
function getSourceFromContains(header) {
|
|
27
|
+
var _a, _b;
|
|
28
|
+
return (_b = (_a = header.contains) == null ? void 0 : _a[0]) == null ? void 0 : _b.source;
|
|
29
|
+
}
|
|
30
|
+
function parseTableHeaders(input) {
|
|
31
|
+
if (!Array.isArray(input)) return [];
|
|
32
|
+
const headers = [];
|
|
33
|
+
for (const item of input) {
|
|
34
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
|
|
35
|
+
const raw = item;
|
|
36
|
+
const label = typeof raw.label === "string" ? raw.label : "";
|
|
37
|
+
const containsRaw = Array.isArray(raw.contains) ? raw.contains : [];
|
|
38
|
+
const contains = containsRaw.flatMap((entry) => {
|
|
39
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return [];
|
|
40
|
+
const e = entry;
|
|
41
|
+
return [
|
|
42
|
+
{
|
|
43
|
+
key: typeof e.key === "string" ? e.key : void 0,
|
|
44
|
+
source: parseSource(e.source)
|
|
45
|
+
}
|
|
46
|
+
];
|
|
47
|
+
});
|
|
48
|
+
headers.push({ label, contains });
|
|
49
|
+
}
|
|
50
|
+
return headers;
|
|
51
|
+
}
|
|
52
|
+
function asDataRows(input) {
|
|
53
|
+
if (!Array.isArray(input)) return [];
|
|
54
|
+
return input.filter(
|
|
55
|
+
(row) => !!row && typeof row === "object" && !Array.isArray(row)
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
function buildLiveTableRowsFromSources({
|
|
59
|
+
headers,
|
|
60
|
+
datasetRows,
|
|
61
|
+
chartRows,
|
|
62
|
+
tableDataRows = []
|
|
63
|
+
}) {
|
|
64
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
65
|
+
const sourcedHeaders = headers.filter((header) => Boolean(getSourceFromContains(header)));
|
|
66
|
+
if (!sourcedHeaders.length) return [];
|
|
67
|
+
const needsDataset = sourcedHeaders.some((h) => {
|
|
68
|
+
var _a2;
|
|
69
|
+
return ((_a2 = getSourceFromContains(h)) == null ? void 0 : _a2.type) === "dataset";
|
|
70
|
+
});
|
|
71
|
+
const needsChart = sourcedHeaders.some((h) => {
|
|
72
|
+
var _a2;
|
|
73
|
+
return ((_a2 = getSourceFromContains(h)) == null ? void 0 : _a2.type) === "chart";
|
|
74
|
+
});
|
|
75
|
+
const needsStatic = sourcedHeaders.some((h) => {
|
|
76
|
+
var _a2;
|
|
77
|
+
return ((_a2 = getSourceFromContains(h)) == null ? void 0 : _a2.type) === "static";
|
|
78
|
+
});
|
|
79
|
+
const rowCount = Math.max(
|
|
80
|
+
needsDataset ? datasetRows.length : 0,
|
|
81
|
+
needsChart ? chartRows.length : 0,
|
|
82
|
+
needsStatic ? tableDataRows.length : 0,
|
|
83
|
+
0
|
|
84
|
+
);
|
|
85
|
+
const rows = [];
|
|
86
|
+
for (let index = 0; index < rowCount; index += 1) {
|
|
87
|
+
const row = {};
|
|
88
|
+
for (const header of sourcedHeaders) {
|
|
89
|
+
const contains = (_a = header.contains) == null ? void 0 : _a[0];
|
|
90
|
+
const source = getSourceFromContains(header);
|
|
91
|
+
if (!contains || !source) continue;
|
|
92
|
+
if (source.type === "chart") {
|
|
93
|
+
const chartField = stripDataPrefix(source.field);
|
|
94
|
+
const outputKey2 = contains.key || buildQualifiedChartColumnKey(chartField);
|
|
95
|
+
row[outputKey2] = ((_b = chartRows[index]) == null ? void 0 : _b[chartField]) ?? ((_c = chartRows[index]) == null ? void 0 : _c[source.field]) ?? null;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (source.type === "static") {
|
|
99
|
+
const staticField = stripDataPrefix(source.field);
|
|
100
|
+
const outputKey2 = contains.key || buildQualifiedStaticColumnKey(staticField);
|
|
101
|
+
row[outputKey2] = ((_d = tableDataRows[index]) == null ? void 0 : _d[staticField]) ?? ((_e = tableDataRows[index]) == null ? void 0 : _e[source.field]) ?? ((_f = tableDataRows[index]) == null ? void 0 : _f[outputKey2]) ?? null;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const bareField = stripDataPrefix(source.field);
|
|
105
|
+
const outputKey = contains.key || buildQualifiedDatasetColumnKey(source.datasetId, bareField);
|
|
106
|
+
const qualifiedKey = buildQualifiedDatasetColumnKey(source.datasetId, bareField);
|
|
107
|
+
const legacyQualified = buildQualifiedDatasetColumnKey(source.datasetId, source.field);
|
|
108
|
+
row[outputKey] = ((_g = datasetRows[index]) == null ? void 0 : _g[qualifiedKey]) ?? ((_h = datasetRows[index]) == null ? void 0 : _h[legacyQualified]) ?? ((_i = datasetRows[index]) == null ? void 0 : _i[bareField]) ?? ((_j = datasetRows[index]) == null ? void 0 : _j[source.field]) ?? null;
|
|
109
|
+
}
|
|
110
|
+
rows.push(row);
|
|
111
|
+
}
|
|
112
|
+
return rows;
|
|
113
|
+
}
|
|
114
|
+
function formatJsonToReadable(value) {
|
|
115
|
+
if (!value) return void 0;
|
|
116
|
+
let obj = null;
|
|
117
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
118
|
+
obj = value;
|
|
119
|
+
} else if (typeof value === "string") {
|
|
120
|
+
const trimmed = value.trim();
|
|
121
|
+
if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return void 0;
|
|
122
|
+
try {
|
|
123
|
+
obj = JSON.parse(trimmed);
|
|
124
|
+
} catch {
|
|
125
|
+
return void 0;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (!obj) return void 0;
|
|
129
|
+
return Object.entries(obj).map(([key, val]) => `${key} : ${String(val)}`).join(", ");
|
|
130
|
+
}
|
|
131
|
+
function formatTableCell(header, row) {
|
|
132
|
+
var _a;
|
|
133
|
+
const contains = (_a = header.contains) == null ? void 0 : _a[0];
|
|
134
|
+
const source = getSourceFromContains(header);
|
|
135
|
+
const bareField = ((source == null ? void 0 : source.field) ?? "").replace(/^data\./, "");
|
|
136
|
+
const keyField = (contains == null ? void 0 : contains.key) || ((source == null ? void 0 : source.type) === "dataset" ? `${bareField}__${source.datasetId}` : (source == null ? void 0 : source.type) === "chart" ? `${bareField}__chart` : (source == null ? void 0 : source.type) === "static" ? `${bareField}__static` : "");
|
|
137
|
+
if (!keyField) return { text: "-" };
|
|
138
|
+
const rawValue = row[keyField];
|
|
139
|
+
const modelValue = formatJsonToReadable(rawValue);
|
|
140
|
+
const cellValue = modelValue ?? (rawValue == null ? void 0 : typeof rawValue === "string" || typeof rawValue === "number" || typeof rawValue === "boolean" ? String(rawValue) : JSON.stringify(rawValue));
|
|
141
|
+
const text = cellValue ?? "-";
|
|
142
|
+
if (keyField.toLowerCase() === "findings") {
|
|
143
|
+
return { text, badge: text === "Optimal" ? "success" : "error" };
|
|
144
|
+
}
|
|
145
|
+
return { text };
|
|
146
|
+
}
|
|
147
|
+
function normalizeTableModel(widget) {
|
|
148
|
+
const headers = parseTableHeaders(widget.headers);
|
|
149
|
+
if (!headers.length) return null;
|
|
150
|
+
if (headers.some((header) => !getSourceFromContains(header))) return null;
|
|
151
|
+
const rows = buildLiveTableRowsFromSources({
|
|
152
|
+
headers,
|
|
153
|
+
datasetRows: asDataRows(widget.tablePreviewRows),
|
|
154
|
+
chartRows: asDataRows(widget.data),
|
|
155
|
+
tableDataRows: asDataRows(widget.tableData)
|
|
156
|
+
});
|
|
157
|
+
const columns = headers.map((header, index) => {
|
|
158
|
+
var _a, _b, _c, _d;
|
|
159
|
+
return {
|
|
160
|
+
key: ((_b = (_a = header.contains) == null ? void 0 : _a[0]) == null ? void 0 : _b.key) || `col-${index}`,
|
|
161
|
+
label: header.label || ((_d = (_c = header.contains) == null ? void 0 : _c[0]) == null ? void 0 : _d.key) || `Column ${index + 1}`
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
return {
|
|
165
|
+
columns,
|
|
166
|
+
cells: rows.map((row) => headers.map((header) => formatTableCell(header, row)))
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
export {
|
|
170
|
+
asDataRows,
|
|
171
|
+
buildLiveTableRowsFromSources,
|
|
172
|
+
buildQualifiedChartColumnKey,
|
|
173
|
+
buildQualifiedDatasetColumnKey,
|
|
174
|
+
buildQualifiedStaticColumnKey,
|
|
175
|
+
formatTableCell,
|
|
176
|
+
getSourceFromContains,
|
|
177
|
+
normalizeTableModel,
|
|
178
|
+
parseTableHeaders,
|
|
179
|
+
stripDataPrefix
|
|
180
|
+
};
|
|
181
|
+
//# sourceMappingURL=table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.js","sources":["../../../../src/components/custom-widget/lib/table.ts"],"sourcesContent":["/** Client CustomWidget TableWidget — sources, zip-by-index rows, MCP preview fallback. */\n\nexport type TableColumnSource =\n | { type: 'dataset'; datasetId: string; field: string }\n | { type: 'chart'; field: string }\n | { type: 'static'; field: string };\n\nexport interface TableHeaderContains {\n key?: string;\n source?: TableColumnSource;\n}\n\nexport interface TableHeader {\n label: string;\n contains?: TableHeaderContains[];\n}\n\nexport type DataRow = Record<string, string | number | boolean | null | undefined>;\n\nexport interface TableCellModel {\n text: string;\n badge?: 'success' | 'error';\n}\n\nexport interface CustomTableModel {\n columns: { key: string; label: string }[];\n cells: TableCellModel[][];\n}\n\nexport function stripDataPrefix(field: string): string {\n return field.startsWith('data.') ? field.slice('data.'.length) : field;\n}\n\nexport function buildQualifiedDatasetColumnKey(datasetId: string, field: string): string {\n return `${field}__${datasetId}`;\n}\n\nexport function buildQualifiedChartColumnKey(field: string): string {\n return `${field}__chart`;\n}\n\nexport function buildQualifiedStaticColumnKey(field: string): string {\n return `${field}__static`;\n}\n\nfunction parseSource(raw: unknown): TableColumnSource | undefined {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;\n const o = raw as Record<string, unknown>;\n const field = typeof o.field === 'string' ? stripDataPrefix(o.field.trim()) : '';\n if (!field) return undefined;\n if (o.type === 'chart' || o.type === 'static') return { type: o.type, field };\n if (o.type === 'dataset') {\n const datasetId = typeof o.datasetId === 'string' ? o.datasetId.trim() : '';\n if (!datasetId) return undefined;\n return { type: 'dataset', datasetId, field };\n }\n return undefined;\n}\n\nexport function getSourceFromContains(header: TableHeader): TableColumnSource | undefined {\n return header.contains?.[0]?.source;\n}\n\nexport function parseTableHeaders(input: unknown): TableHeader[] {\n if (!Array.isArray(input)) return [];\n const headers: TableHeader[] = [];\n for (const item of input) {\n if (!item || typeof item !== 'object' || Array.isArray(item)) continue;\n const raw = item as Record<string, unknown>;\n const label = typeof raw.label === 'string' ? raw.label : '';\n const containsRaw = Array.isArray(raw.contains) ? raw.contains : [];\n const contains: TableHeaderContains[] = containsRaw.flatMap((entry) => {\n if (!entry || typeof entry !== 'object' || Array.isArray(entry)) return [];\n const e = entry as Record<string, unknown>;\n return [\n {\n key: typeof e.key === 'string' ? e.key : undefined,\n source: parseSource(e.source),\n },\n ];\n });\n headers.push({ label, contains });\n }\n return headers;\n}\n\nexport function asDataRows(input: unknown): DataRow[] {\n if (!Array.isArray(input)) return [];\n return input.filter(\n (row): row is DataRow => !!row && typeof row === 'object' && !Array.isArray(row),\n ) as DataRow[];\n}\n\n/** Client `buildLiveTableRowsFromSources` — zip sources by row index, not a join. */\nexport function buildLiveTableRowsFromSources({\n headers,\n datasetRows,\n chartRows,\n tableDataRows = [],\n}: {\n headers: TableHeader[];\n datasetRows: DataRow[];\n chartRows: DataRow[];\n tableDataRows?: DataRow[];\n}): DataRow[] {\n const sourcedHeaders = headers.filter((header) => Boolean(getSourceFromContains(header)));\n if (!sourcedHeaders.length) return [];\n\n const needsDataset = sourcedHeaders.some((h) => getSourceFromContains(h)?.type === 'dataset');\n const needsChart = sourcedHeaders.some((h) => getSourceFromContains(h)?.type === 'chart');\n const needsStatic = sourcedHeaders.some((h) => getSourceFromContains(h)?.type === 'static');\n\n const rowCount = Math.max(\n needsDataset ? datasetRows.length : 0,\n needsChart ? chartRows.length : 0,\n needsStatic ? tableDataRows.length : 0,\n 0,\n );\n\n const rows: DataRow[] = [];\n for (let index = 0; index < rowCount; index += 1) {\n const row: DataRow = {};\n for (const header of sourcedHeaders) {\n const contains = header.contains?.[0];\n const source = getSourceFromContains(header);\n if (!contains || !source) continue;\n\n if (source.type === 'chart') {\n const chartField = stripDataPrefix(source.field);\n const outputKey = contains.key || buildQualifiedChartColumnKey(chartField);\n row[outputKey] =\n chartRows[index]?.[chartField] ?? chartRows[index]?.[source.field] ?? null;\n continue;\n }\n\n if (source.type === 'static') {\n const staticField = stripDataPrefix(source.field);\n const outputKey = contains.key || buildQualifiedStaticColumnKey(staticField);\n row[outputKey] =\n tableDataRows[index]?.[staticField] ??\n tableDataRows[index]?.[source.field] ??\n tableDataRows[index]?.[outputKey] ??\n null;\n continue;\n }\n\n const bareField = stripDataPrefix(source.field);\n const outputKey = contains.key || buildQualifiedDatasetColumnKey(source.datasetId, bareField);\n const qualifiedKey = buildQualifiedDatasetColumnKey(source.datasetId, bareField);\n const legacyQualified = buildQualifiedDatasetColumnKey(source.datasetId, source.field);\n row[outputKey] =\n datasetRows[index]?.[qualifiedKey] ??\n datasetRows[index]?.[legacyQualified] ??\n datasetRows[index]?.[bareField] ??\n datasetRows[index]?.[source.field] ??\n null;\n }\n rows.push(row);\n }\n return rows;\n}\n\nfunction formatJsonToReadable(value: unknown): string | undefined {\n if (!value) return undefined;\n let obj: Record<string, unknown> | null = null;\n if (typeof value === 'object' && !Array.isArray(value)) {\n obj = value as Record<string, unknown>;\n } else if (typeof value === 'string') {\n const trimmed = value.trim();\n if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) return undefined;\n try {\n obj = JSON.parse(trimmed) as Record<string, unknown>;\n } catch {\n return undefined;\n }\n }\n if (!obj) return undefined;\n return Object.entries(obj)\n .map(([key, val]) => `${key} : ${String(val)}`)\n .join(', ');\n}\n\n/** Client `getCellValue` — stringify + Findings badge. */\nexport function formatTableCell(header: TableHeader, row: DataRow): TableCellModel {\n const contains = header.contains?.[0];\n const source = getSourceFromContains(header);\n const bareField = (source?.field ?? '').replace(/^data\\./, '');\n const keyField =\n contains?.key ||\n (source?.type === 'dataset'\n ? `${bareField}__${source.datasetId}`\n : source?.type === 'chart'\n ? `${bareField}__chart`\n : source?.type === 'static'\n ? `${bareField}__static`\n : '');\n if (!keyField) return { text: '-' };\n\n const rawValue = row[keyField];\n const modelValue = formatJsonToReadable(rawValue);\n const cellValue =\n modelValue ??\n (rawValue == null\n ? undefined\n : typeof rawValue === 'string' || typeof rawValue === 'number' || typeof rawValue === 'boolean'\n ? String(rawValue)\n : JSON.stringify(rawValue));\n const text = cellValue ?? '-';\n\n if (keyField.toLowerCase() === 'findings') {\n return { text, badge: text === 'Optimal' ? 'success' : 'error' };\n }\n return { text };\n}\n\nexport function normalizeTableModel(widget: {\n headers?: unknown;\n data?: unknown;\n tableData?: unknown;\n tablePreviewRows?: unknown;\n}): CustomTableModel | null {\n const headers = parseTableHeaders(widget.headers);\n if (!headers.length) return null;\n if (headers.some((header) => !getSourceFromContains(header))) return null;\n\n const rows = buildLiveTableRowsFromSources({\n headers,\n datasetRows: asDataRows(widget.tablePreviewRows),\n chartRows: asDataRows(widget.data),\n tableDataRows: asDataRows(widget.tableData),\n });\n\n const columns = headers.map((header, index) => ({\n key: header.contains?.[0]?.key || `col-${index}`,\n label: header.label || header.contains?.[0]?.key || `Column ${index + 1}`,\n }));\n\n return {\n columns,\n cells: rows.map((row) => headers.map((header) => formatTableCell(header, row))),\n };\n}\n"],"names":["_a","outputKey"],"mappings":"AA6BO,SAAS,gBAAgB,OAAuB;AACrD,SAAO,MAAM,WAAW,OAAO,IAAI,MAAM,MAAM,QAAQ,MAAM,IAAI;AACnE;AAEO,SAAS,+BAA+B,WAAmB,OAAuB;AACvF,SAAO,GAAG,KAAK,KAAK,SAAS;AAC/B;AAEO,SAAS,6BAA6B,OAAuB;AAClE,SAAO,GAAG,KAAK;AACjB;AAEO,SAAS,8BAA8B,OAAuB;AACnE,SAAO,GAAG,KAAK;AACjB;AAEA,SAAS,YAAY,KAA6C;AAChE,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAQ,GAAG,EAAG,QAAO;AAClE,QAAM,IAAI;AACV,QAAM,QAAQ,OAAO,EAAE,UAAU,WAAW,gBAAgB,EAAE,MAAM,KAAA,CAAM,IAAI;AAC9E,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,EAAE,SAAS,WAAW,EAAE,SAAS,SAAU,QAAO,EAAE,MAAM,EAAE,MAAM,MAAA;AACtE,MAAI,EAAE,SAAS,WAAW;AACxB,UAAM,YAAY,OAAO,EAAE,cAAc,WAAW,EAAE,UAAU,SAAS;AACzE,QAAI,CAAC,UAAW,QAAO;AACvB,WAAO,EAAE,MAAM,WAAW,WAAW,MAAA;AAAA,EACvC;AACA,SAAO;AACT;AAEO,SAAS,sBAAsB,QAAoD;AA9BnF;AA+BL,UAAO,kBAAO,aAAP,mBAAkB,OAAlB,mBAAsB;AAC/B;AAEO,SAAS,kBAAkB,OAA+B;AAC/D,MAAI,CAAC,MAAM,QAAQ,KAAK,UAAU,CAAA;AAClC,QAAM,UAAyB,CAAA;AAC/B,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,EAAG;AAC9D,UAAM,MAAM;AACZ,UAAM,QAAQ,OAAO,IAAI,UAAU,WAAW,IAAI,QAAQ;AAC1D,UAAM,cAAc,MAAM,QAAQ,IAAI,QAAQ,IAAI,IAAI,WAAW,CAAA;AACjE,UAAM,WAAkC,YAAY,QAAQ,CAAC,UAAU;AACrE,UAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAA;AACxE,YAAM,IAAI;AACV,aAAO;AAAA,QACL;AAAA,UACE,KAAK,OAAO,EAAE,QAAQ,WAAW,EAAE,MAAM;AAAA,UACzC,QAAQ,YAAY,EAAE,MAAM;AAAA,QAAA;AAAA,MAC9B;AAAA,IAEJ,CAAC;AACD,YAAQ,KAAK,EAAE,OAAO,SAAA,CAAU;AAAA,EAClC;AACA,SAAO;AACT;AAEO,SAAS,WAAW,OAA2B;AACpD,MAAI,CAAC,MAAM,QAAQ,KAAK,UAAU,CAAA;AAClC,SAAO,MAAM;AAAA,IACX,CAAC,QAAwB,CAAC,CAAC,OAAO,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAG;AAAA,EAAA;AAEnF;AAGO,SAAS,8BAA8B;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB,CAAA;AAClB,GAKc;AA3EP;AA4EL,QAAM,iBAAiB,QAAQ,OAAO,CAAC,WAAW,QAAQ,sBAAsB,MAAM,CAAC,CAAC;AACxF,MAAI,CAAC,eAAe,OAAQ,QAAO,CAAA;AAEnC,QAAM,eAAe,eAAe,KAAK,CAAC;AA/ErC,QAAAA;AA+E2C,aAAAA,MAAA,sBAAsB,CAAC,MAAvB,gBAAAA,IAA0B,UAAS;AAAA,GAAS;AAC5F,QAAM,aAAa,eAAe,KAAK,CAAC;AAhFnC,QAAAA;AAgFyC,aAAAA,MAAA,sBAAsB,CAAC,MAAvB,gBAAAA,IAA0B,UAAS;AAAA,GAAO;AACxF,QAAM,cAAc,eAAe,KAAK,CAAC;AAjFpC,QAAAA;AAiF0C,aAAAA,MAAA,sBAAsB,CAAC,MAAvB,gBAAAA,IAA0B,UAAS;AAAA,GAAQ;AAE1F,QAAM,WAAW,KAAK;AAAA,IACpB,eAAe,YAAY,SAAS;AAAA,IACpC,aAAa,UAAU,SAAS;AAAA,IAChC,cAAc,cAAc,SAAS;AAAA,IACrC;AAAA,EAAA;AAGF,QAAM,OAAkB,CAAA;AACxB,WAAS,QAAQ,GAAG,QAAQ,UAAU,SAAS,GAAG;AAChD,UAAM,MAAe,CAAA;AACrB,eAAW,UAAU,gBAAgB;AACnC,YAAM,YAAW,YAAO,aAAP,mBAAkB;AACnC,YAAM,SAAS,sBAAsB,MAAM;AAC3C,UAAI,CAAC,YAAY,CAAC,OAAQ;AAE1B,UAAI,OAAO,SAAS,SAAS;AAC3B,cAAM,aAAa,gBAAgB,OAAO,KAAK;AAC/C,cAAMC,aAAY,SAAS,OAAO,6BAA6B,UAAU;AACzE,YAAIA,UAAS,MACX,eAAU,KAAK,MAAf,mBAAmB,kBAAe,eAAU,KAAK,MAAf,mBAAmB,OAAO,WAAU;AACxE;AAAA,MACF;AAEA,UAAI,OAAO,SAAS,UAAU;AAC5B,cAAM,cAAc,gBAAgB,OAAO,KAAK;AAChD,cAAMA,aAAY,SAAS,OAAO,8BAA8B,WAAW;AAC3E,YAAIA,UAAS,MACX,mBAAc,KAAK,MAAnB,mBAAuB,mBACvB,mBAAc,KAAK,MAAnB,mBAAuB,OAAO,aAC9B,mBAAc,KAAK,MAAnB,mBAAuBA,gBACvB;AACF;AAAA,MACF;AAEA,YAAM,YAAY,gBAAgB,OAAO,KAAK;AAC9C,YAAM,YAAY,SAAS,OAAO,+BAA+B,OAAO,WAAW,SAAS;AAC5F,YAAM,eAAe,+BAA+B,OAAO,WAAW,SAAS;AAC/E,YAAM,kBAAkB,+BAA+B,OAAO,WAAW,OAAO,KAAK;AACrF,UAAI,SAAS,MACX,iBAAY,KAAK,MAAjB,mBAAqB,oBACrB,iBAAY,KAAK,MAAjB,mBAAqB,uBACrB,iBAAY,KAAK,MAAjB,mBAAqB,iBACrB,iBAAY,KAAK,MAAjB,mBAAqB,OAAO,WAC5B;AAAA,IACJ;AACA,SAAK,KAAK,GAAG;AAAA,EACf;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,OAAoC;AAChE,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,MAAsC;AAC1C,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG;AACtD,UAAM;AAAA,EACR,WAAW,OAAO,UAAU,UAAU;AACpC,UAAM,UAAU,MAAM,KAAA;AACtB,QAAI,CAAC,QAAQ,WAAW,GAAG,KAAK,CAAC,QAAQ,SAAS,GAAG,EAAG,QAAO;AAC/D,QAAI;AACF,YAAM,KAAK,MAAM,OAAO;AAAA,IAC1B,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,OAAO,QAAQ,GAAG,EACtB,IAAI,CAAC,CAAC,KAAK,GAAG,MAAM,GAAG,GAAG,MAAM,OAAO,GAAG,CAAC,EAAE,EAC7C,KAAK,IAAI;AACd;AAGO,SAAS,gBAAgB,QAAqB,KAA8B;AA1J5E;AA2JL,QAAM,YAAW,YAAO,aAAP,mBAAkB;AACnC,QAAM,SAAS,sBAAsB,MAAM;AAC3C,QAAM,cAAa,iCAAQ,UAAS,IAAI,QAAQ,WAAW,EAAE;AAC7D,QAAM,YACJ,qCAAU,UACT,iCAAQ,UAAS,YACd,GAAG,SAAS,KAAK,OAAO,SAAS,MACjC,iCAAQ,UAAS,UACf,GAAG,SAAS,aACZ,iCAAQ,UAAS,WACf,GAAG,SAAS,aACZ;AACV,MAAI,CAAC,SAAU,QAAO,EAAE,MAAM,IAAA;AAE9B,QAAM,WAAW,IAAI,QAAQ;AAC7B,QAAM,aAAa,qBAAqB,QAAQ;AAChD,QAAM,YACJ,eACC,YAAY,OACT,SACA,OAAO,aAAa,YAAY,OAAO,aAAa,YAAY,OAAO,aAAa,YAClF,OAAO,QAAQ,IACf,KAAK,UAAU,QAAQ;AAC/B,QAAM,OAAO,aAAa;AAE1B,MAAI,SAAS,YAAA,MAAkB,YAAY;AACzC,WAAO,EAAE,MAAM,OAAO,SAAS,YAAY,YAAY,QAAA;AAAA,EACzD;AACA,SAAO,EAAE,KAAA;AACX;AAEO,SAAS,oBAAoB,QAKR;AAC1B,QAAM,UAAU,kBAAkB,OAAO,OAAO;AAChD,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,MAAI,QAAQ,KAAK,CAAC,WAAW,CAAC,sBAAsB,MAAM,CAAC,EAAG,QAAO;AAErE,QAAM,OAAO,8BAA8B;AAAA,IACzC;AAAA,IACA,aAAa,WAAW,OAAO,gBAAgB;AAAA,IAC/C,WAAW,WAAW,OAAO,IAAI;AAAA,IACjC,eAAe,WAAW,OAAO,SAAS;AAAA,EAAA,CAC3C;AAED,QAAM,UAAU,QAAQ,IAAI,CAAC,QAAQ,UAAA;AA3MhC;AA2M2C;AAAA,MAC9C,OAAK,kBAAO,aAAP,mBAAkB,OAAlB,mBAAsB,QAAO,OAAO,KAAK;AAAA,MAC9C,OAAO,OAAO,WAAS,kBAAO,aAAP,mBAAkB,OAAlB,mBAAsB,QAAO,UAAU,QAAQ,CAAC;AAAA,IAAA;AAAA,GACvE;AAEF,SAAO;AAAA,IACL;AAAA,IACA,OAAO,KAAK,IAAI,CAAC,QAAQ,QAAQ,IAAI,CAAC,WAAW,gBAAgB,QAAQ,GAAG,CAAC,CAAC;AAAA,EAAA;AAElF;"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { CustomTableModel } from './table.js';
|
|
2
|
+
/** Pane types a FuseDash CustomWidget can arrange (`arranging.widgets`). */
|
|
3
|
+
export type CustomPaneKind = 'chartWidget' | 'tableWidget' | 'textWidget' | 'imageWidget';
|
|
4
|
+
/**
|
|
5
|
+
* Flex direction of the pane row, using FuseDash semantics:
|
|
6
|
+
* `vertical` lays panes out side by side, `horizontal` stacks them.
|
|
7
|
+
*/
|
|
8
|
+
export type ArrangingDirection = 'vertical' | 'horizontal';
|
|
9
|
+
export interface CustomWidgetArranging {
|
|
10
|
+
widgets?: string[];
|
|
11
|
+
hasKpi?: boolean;
|
|
12
|
+
direction?: ArrangingDirection;
|
|
13
|
+
}
|
|
14
|
+
/** FuseDash `WidgetItem` subset the shell reads; the rest is forwarded to panes. */
|
|
15
|
+
export interface CustomWidgetPayload {
|
|
16
|
+
id?: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
chartType?: string;
|
|
19
|
+
arranging?: CustomWidgetArranging;
|
|
20
|
+
kpis?: unknown[];
|
|
21
|
+
text?: string;
|
|
22
|
+
imageUrl?: string;
|
|
23
|
+
alt?: string;
|
|
24
|
+
headers?: unknown[];
|
|
25
|
+
data?: unknown;
|
|
26
|
+
tableData?: unknown;
|
|
27
|
+
tablePreviewRows?: unknown;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
export interface CustomPane {
|
|
31
|
+
/** Stable key for list rendering — mirrors the client `${id}-${chartType}-${index}` */
|
|
32
|
+
key: string;
|
|
33
|
+
kind: CustomPaneKind;
|
|
34
|
+
/** true when the pane mounts content; false renders the pane empty state */
|
|
35
|
+
renderable: boolean;
|
|
36
|
+
emptyTitle: string;
|
|
37
|
+
emptySubtitle: string;
|
|
38
|
+
table?: CustomTableModel;
|
|
39
|
+
text?: string;
|
|
40
|
+
image?: {
|
|
41
|
+
src: string;
|
|
42
|
+
alt: string;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export interface CustomWidgetModel {
|
|
46
|
+
title: string;
|
|
47
|
+
direction: ArrangingDirection;
|
|
48
|
+
hasKpi: boolean;
|
|
49
|
+
panes: CustomPane[];
|
|
50
|
+
/** Payload handed to chart / KPI panes, or null when the input was unusable */
|
|
51
|
+
widget: CustomWidgetPayload | null;
|
|
52
|
+
/** No panes and no KPI band — the client `WidgetDefaultState` */
|
|
53
|
+
isEmpty: boolean;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/custom-widget/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,4EAA4E;AAC5E,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,aAAa,GAAG,YAAY,GAAG,aAAa,CAAC;AAE1F;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,YAAY,CAAC;AAE3D,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,kBAAkB,CAAC;CAChC;AAED,oFAAoF;AACpF,MAAM,WAAW,mBAAmB;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,uFAAuF;IACvF,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,cAAc,CAAC;IACrB,4EAA4E;IAC5E,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACtC;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,kBAAkB,CAAC;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,+EAA+E;IAC/E,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACnC,iEAAiE;IACjE,OAAO,EAAE,OAAO,CAAC;CAClB"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
"id": "custom-widget",
|
|
3
|
+
"tag": "ui9000-custom-widget",
|
|
4
|
+
"title": "Custom Widget",
|
|
5
|
+
"description": "FuseDash CustomWidget shell — title, optional KPI band, and up to two arranged panes. Chart panes mount ui9000-chart-renderer, the KPI band mounts ui9000-kpi-widget, table/text/image panes render inline. No Redux.",
|
|
6
|
+
"chartTypeKeys": ["customWidget"],
|
|
7
|
+
"source": "client/libs/shared/components/src/Widgets/CustomWidget/",
|
|
8
|
+
"stack": "composite",
|
|
9
|
+
"lazyImport": "@ui9000/widgets/lazy/custom-widget",
|
|
10
|
+
"entry": "@ui9000/widgets/custom-widget",
|
|
11
|
+
"usageConditions": {
|
|
12
|
+
"host": "mcp-chat",
|
|
13
|
+
"notFor": "fusedash-editor",
|
|
14
|
+
"mapsExcluded": true,
|
|
15
|
+
"requiresArranging": "Reads arranging.widgets / arranging.hasKpi / arranging.direction; renders the default state when both are absent.",
|
|
16
|
+
"panesSupported": ["chartWidget", "tableWidget", "textWidget", "imageWidget"],
|
|
17
|
+
"maxPanes": 2
|
|
18
|
+
},
|
|
19
|
+
"allowedActions": ["resize", "download"],
|
|
20
|
+
"propsSchema": {
|
|
21
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
22
|
+
"type": "object",
|
|
23
|
+
"properties": {
|
|
24
|
+
"data": {
|
|
25
|
+
"type": "object",
|
|
26
|
+
"description": "FuseDash WidgetItem JSON for the custom widget, including arranging, kpis, and pane fields (text, imageUrl, headers, tableData, tablePreviewRows)",
|
|
27
|
+
"properties": {
|
|
28
|
+
"id": { "type": "string" },
|
|
29
|
+
"name": { "type": "string" },
|
|
30
|
+
"chartType": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "Chart type of the chartWidget pane; content types (tableChart, textChart, imageChart) render the pane empty state"
|
|
33
|
+
},
|
|
34
|
+
"text": { "type": "string", "description": "Markdown/plain text for a textWidget pane" },
|
|
35
|
+
"imageUrl": { "type": "string", "description": "http(s) URL for an imageWidget pane" },
|
|
36
|
+
"alt": { "type": "string" },
|
|
37
|
+
"headers": {
|
|
38
|
+
"type": "array",
|
|
39
|
+
"description": "Table columns. Each contains[].source is dataset | chart | static"
|
|
40
|
+
},
|
|
41
|
+
"tableData": { "type": "array", "description": "Personal/static rows for static-sourced columns" },
|
|
42
|
+
"tablePreviewRows": {
|
|
43
|
+
"type": "array",
|
|
44
|
+
"description": "MCP snapshot used as dataset rows when the host has no live select"
|
|
45
|
+
},
|
|
46
|
+
"arranging": {
|
|
47
|
+
"type": "object",
|
|
48
|
+
"properties": {
|
|
49
|
+
"widgets": {
|
|
50
|
+
"type": "array",
|
|
51
|
+
"maxItems": 2,
|
|
52
|
+
"items": {
|
|
53
|
+
"type": "string",
|
|
54
|
+
"enum": ["chartWidget", "tableWidget", "textWidget", "imageWidget"]
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"hasKpi": { "type": "boolean", "default": false },
|
|
58
|
+
"direction": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"enum": ["vertical", "horizontal"],
|
|
61
|
+
"default": "vertical",
|
|
62
|
+
"description": "FuseDash semantics — vertical lays panes side by side, horizontal stacks them"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"kpis": {
|
|
67
|
+
"type": "array",
|
|
68
|
+
"description": "KPI items rendered in the KPI band when arranging.hasKpi is true"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"chartTitle": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"description": "Header title override; falls back to data.name"
|
|
75
|
+
},
|
|
76
|
+
"direction": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"enum": ["vertical", "horizontal"],
|
|
79
|
+
"description": "Overrides data.arranging.direction"
|
|
80
|
+
},
|
|
81
|
+
"scale": {
|
|
82
|
+
"type": "string",
|
|
83
|
+
"enum": ["compact", "default", "comfortable"],
|
|
84
|
+
"default": "default"
|
|
85
|
+
},
|
|
86
|
+
"showHeader": { "type": "boolean", "default": true },
|
|
87
|
+
"showGrid": { "type": "boolean", "default": true },
|
|
88
|
+
"showLegend": { "type": "boolean", "default": true },
|
|
89
|
+
"showTooltip": { "type": "boolean", "default": true }
|
|
90
|
+
},
|
|
91
|
+
"required": ["data"]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
;
|
|
95
|
+
|
|
96
|
+
export default _default;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const id = "custom-widget";
|
|
2
|
+
const tag = "ui9000-custom-widget";
|
|
3
|
+
const title = "Custom Widget";
|
|
4
|
+
const description = "FuseDash CustomWidget shell — title, optional KPI band, and up to two arranged panes. Chart panes mount ui9000-chart-renderer, the KPI band mounts ui9000-kpi-widget, table/text/image panes render inline. No Redux.";
|
|
5
|
+
const chartTypeKeys = ["customWidget"];
|
|
6
|
+
const source = "client/libs/shared/components/src/Widgets/CustomWidget/";
|
|
7
|
+
const stack = "composite";
|
|
8
|
+
const lazyImport = "@ui9000/widgets/lazy/custom-widget";
|
|
9
|
+
const entry = "@ui9000/widgets/custom-widget";
|
|
10
|
+
const usageConditions = { "host": "mcp-chat", "notFor": "fusedash-editor", "mapsExcluded": true, "requiresArranging": "Reads arranging.widgets / arranging.hasKpi / arranging.direction; renders the default state when both are absent.", "panesSupported": ["chartWidget", "tableWidget", "textWidget", "imageWidget"], "maxPanes": 2 };
|
|
11
|
+
const allowedActions = ["resize", "download"];
|
|
12
|
+
const propsSchema = { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "data": { "type": "object", "description": "FuseDash WidgetItem JSON for the custom widget, including arranging, kpis, and pane fields (text, imageUrl, headers, tableData, tablePreviewRows)", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "chartType": { "type": "string", "description": "Chart type of the chartWidget pane; content types (tableChart, textChart, imageChart) render the pane empty state" }, "text": { "type": "string", "description": "Markdown/plain text for a textWidget pane" }, "imageUrl": { "type": "string", "description": "http(s) URL for an imageWidget pane" }, "alt": { "type": "string" }, "headers": { "type": "array", "description": "Table columns. Each contains[].source is dataset | chart | static" }, "tableData": { "type": "array", "description": "Personal/static rows for static-sourced columns" }, "tablePreviewRows": { "type": "array", "description": "MCP snapshot used as dataset rows when the host has no live select" }, "arranging": { "type": "object", "properties": { "widgets": { "type": "array", "maxItems": 2, "items": { "type": "string", "enum": ["chartWidget", "tableWidget", "textWidget", "imageWidget"] } }, "hasKpi": { "type": "boolean", "default": false }, "direction": { "type": "string", "enum": ["vertical", "horizontal"], "default": "vertical", "description": "FuseDash semantics — vertical lays panes side by side, horizontal stacks them" } } }, "kpis": { "type": "array", "description": "KPI items rendered in the KPI band when arranging.hasKpi is true" } } }, "chartTitle": { "type": "string", "description": "Header title override; falls back to data.name" }, "direction": { "type": "string", "enum": ["vertical", "horizontal"], "description": "Overrides data.arranging.direction" }, "scale": { "type": "string", "enum": ["compact", "default", "comfortable"], "default": "default" }, "showHeader": { "type": "boolean", "default": true }, "showGrid": { "type": "boolean", "default": true }, "showLegend": { "type": "boolean", "default": true }, "showTooltip": { "type": "boolean", "default": true } }, "required": ["data"] };
|
|
13
|
+
const metadata = {
|
|
14
|
+
id,
|
|
15
|
+
tag,
|
|
16
|
+
title,
|
|
17
|
+
description,
|
|
18
|
+
chartTypeKeys,
|
|
19
|
+
source,
|
|
20
|
+
stack,
|
|
21
|
+
lazyImport,
|
|
22
|
+
entry,
|
|
23
|
+
usageConditions,
|
|
24
|
+
allowedActions,
|
|
25
|
+
propsSchema
|
|
26
|
+
};
|
|
27
|
+
export {
|
|
28
|
+
allowedActions,
|
|
29
|
+
chartTypeKeys,
|
|
30
|
+
metadata as default,
|
|
31
|
+
description,
|
|
32
|
+
entry,
|
|
33
|
+
id,
|
|
34
|
+
lazyImport,
|
|
35
|
+
propsSchema,
|
|
36
|
+
source,
|
|
37
|
+
stack,
|
|
38
|
+
tag,
|
|
39
|
+
title,
|
|
40
|
+
usageConditions
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=metadata.json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;"}
|