@flanksource/clicky-ui 0.2.7 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/dist/components/Combobox.cjs +89 -49
  2. package/dist/components/Combobox.cjs.map +1 -1
  3. package/dist/components/Combobox.d.ts +3 -0
  4. package/dist/components/Combobox.d.ts.map +1 -1
  5. package/dist/components/Combobox.js +91 -51
  6. package/dist/components/Combobox.js.map +1 -1
  7. package/dist/components/FilterBar.cjs +42 -44
  8. package/dist/components/FilterBar.cjs.map +1 -1
  9. package/dist/components/FilterBar.d.ts +19 -0
  10. package/dist/components/FilterBar.d.ts.map +1 -1
  11. package/dist/components/FilterBar.js +43 -45
  12. package/dist/components/FilterBar.js.map +1 -1
  13. package/dist/components/JsonSchemaForm.cjs +35 -0
  14. package/dist/components/JsonSchemaForm.cjs.map +1 -0
  15. package/dist/components/JsonSchemaForm.d.ts +3 -0
  16. package/dist/components/JsonSchemaForm.d.ts.map +1 -0
  17. package/dist/components/JsonSchemaForm.js +35 -0
  18. package/dist/components/JsonSchemaForm.js.map +1 -0
  19. package/dist/components/json-schema-form-array.cjs +169 -0
  20. package/dist/components/json-schema-form-array.cjs.map +1 -0
  21. package/dist/components/json-schema-form-array.d.ts +8 -0
  22. package/dist/components/json-schema-form-array.d.ts.map +1 -0
  23. package/dist/components/json-schema-form-array.js +169 -0
  24. package/dist/components/json-schema-form-array.js.map +1 -0
  25. package/dist/components/json-schema-form-fields.cjs +365 -0
  26. package/dist/components/json-schema-form-fields.cjs.map +1 -0
  27. package/dist/components/json-schema-form-fields.d.ts +19 -0
  28. package/dist/components/json-schema-form-fields.d.ts.map +1 -0
  29. package/dist/components/json-schema-form-fields.js +365 -0
  30. package/dist/components/json-schema-form-fields.js.map +1 -0
  31. package/dist/components/json-schema-form-render.cjs +154 -0
  32. package/dist/components/json-schema-form-render.cjs.map +1 -0
  33. package/dist/components/json-schema-form-render.d.ts +40 -0
  34. package/dist/components/json-schema-form-render.d.ts.map +1 -0
  35. package/dist/components/json-schema-form-render.js +154 -0
  36. package/dist/components/json-schema-form-render.js.map +1 -0
  37. package/dist/components/json-schema-form-resolve.cjs +121 -0
  38. package/dist/components/json-schema-form-resolve.cjs.map +1 -0
  39. package/dist/components/json-schema-form-resolve.d.ts +19 -0
  40. package/dist/components/json-schema-form-resolve.d.ts.map +1 -0
  41. package/dist/components/json-schema-form-resolve.js +121 -0
  42. package/dist/components/json-schema-form-resolve.js.map +1 -0
  43. package/dist/components/json-schema-form-types.d.ts +108 -0
  44. package/dist/components/json-schema-form-types.d.ts.map +1 -0
  45. package/dist/components.cjs +7 -0
  46. package/dist/components.cjs.map +1 -1
  47. package/dist/components.d.ts +3 -0
  48. package/dist/components.d.ts.map +1 -1
  49. package/dist/components.js +8 -1
  50. package/dist/components.js.map +1 -1
  51. package/dist/data/Clicky.cjs +1 -1
  52. package/dist/data/Clicky.cjs.map +1 -1
  53. package/dist/data/Clicky.js +1 -1
  54. package/dist/data/Clicky.js.map +1 -1
  55. package/dist/data/DataTable.cjs +16 -15
  56. package/dist/data/DataTable.cjs.map +1 -1
  57. package/dist/data/DataTable.d.ts +2 -1
  58. package/dist/data/DataTable.d.ts.map +1 -1
  59. package/dist/data/DataTable.js +16 -15
  60. package/dist/data/DataTable.js.map +1 -1
  61. package/dist/data/Icon.cjs +11 -0
  62. package/dist/data/Icon.cjs.map +1 -1
  63. package/dist/data/Icon.d.ts +12 -1
  64. package/dist/data/Icon.d.ts.map +1 -1
  65. package/dist/data/Icon.js +12 -1
  66. package/dist/data/Icon.js.map +1 -1
  67. package/dist/data/LogDetails.cjs +277 -0
  68. package/dist/data/LogDetails.cjs.map +1 -0
  69. package/dist/data/LogDetails.d.ts +5 -0
  70. package/dist/data/LogDetails.d.ts.map +1 -0
  71. package/dist/data/LogDetails.js +277 -0
  72. package/dist/data/LogDetails.js.map +1 -0
  73. package/dist/data/LogsTable.cjs +6 -202
  74. package/dist/data/LogsTable.cjs.map +1 -1
  75. package/dist/data/LogsTable.d.ts.map +1 -1
  76. package/dist/data/LogsTable.js +4 -200
  77. package/dist/data/LogsTable.js.map +1 -1
  78. package/dist/data/MatrixTable.cjs +17 -9
  79. package/dist/data/MatrixTable.cjs.map +1 -1
  80. package/dist/data/MatrixTable.d.ts +3 -1
  81. package/dist/data/MatrixTable.d.ts.map +1 -1
  82. package/dist/data/MatrixTable.js +17 -9
  83. package/dist/data/MatrixTable.js.map +1 -1
  84. package/dist/data/Properties.cjs +2 -2
  85. package/dist/data/Properties.cjs.map +1 -1
  86. package/dist/data/Properties.js +2 -2
  87. package/dist/data/Properties.js.map +1 -1
  88. package/dist/data/cells/TagList.cjs +19 -3
  89. package/dist/data/cells/TagList.cjs.map +1 -1
  90. package/dist/data/cells/TagList.d.ts +11 -1
  91. package/dist/data/cells/TagList.d.ts.map +1 -1
  92. package/dist/data/cells/TagList.js +19 -3
  93. package/dist/data/cells/TagList.js.map +1 -1
  94. package/dist/data/cells/Timestamp.cjs +17 -2
  95. package/dist/data/cells/Timestamp.cjs.map +1 -1
  96. package/dist/data/cells/Timestamp.d.ts +2 -0
  97. package/dist/data/cells/Timestamp.d.ts.map +1 -1
  98. package/dist/data/cells/Timestamp.js +17 -2
  99. package/dist/data/cells/Timestamp.js.map +1 -1
  100. package/dist/data/log-utils.cjs +7 -0
  101. package/dist/data/log-utils.cjs.map +1 -0
  102. package/dist/data/log-utils.d.ts +2 -0
  103. package/dist/data/log-utils.d.ts.map +1 -0
  104. package/dist/data/log-utils.js +7 -0
  105. package/dist/data/log-utils.js.map +1 -0
  106. package/dist/data.cjs +3 -0
  107. package/dist/data.cjs.map +1 -1
  108. package/dist/data.d.ts +2 -2
  109. package/dist/data.d.ts.map +1 -1
  110. package/dist/data.js +5 -2
  111. package/dist/index.cjs +13 -0
  112. package/dist/index.cjs.map +1 -1
  113. package/dist/index.js +15 -2
  114. package/dist/index.js.map +1 -1
  115. package/dist/rpc/EntityExplorerApp.cjs +3 -2
  116. package/dist/rpc/EntityExplorerApp.cjs.map +1 -1
  117. package/dist/rpc/EntityExplorerApp.js +3 -2
  118. package/dist/rpc/EntityExplorerApp.js.map +1 -1
  119. package/dist/rpc/OperationActionDialog.cjs +1 -1
  120. package/dist/rpc/OperationActionDialog.cjs.map +1 -1
  121. package/dist/rpc/OperationActionDialog.js +1 -1
  122. package/dist/rpc/OperationActionDialog.js.map +1 -1
  123. package/dist/rpc/OperationCommandPage.cjs +21 -14
  124. package/dist/rpc/OperationCommandPage.cjs.map +1 -1
  125. package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
  126. package/dist/rpc/OperationCommandPage.js +21 -14
  127. package/dist/rpc/OperationCommandPage.js.map +1 -1
  128. package/dist/rpc/apiClient.cjs +316 -0
  129. package/dist/rpc/apiClient.cjs.map +1 -0
  130. package/dist/rpc/apiClient.d.ts +44 -0
  131. package/dist/rpc/apiClient.d.ts.map +1 -0
  132. package/dist/rpc/apiClient.js +316 -0
  133. package/dist/rpc/apiClient.js.map +1 -0
  134. package/dist/rpc/useOperations.cjs.map +1 -1
  135. package/dist/rpc/useOperations.d.ts +2 -1
  136. package/dist/rpc/useOperations.d.ts.map +1 -1
  137. package/dist/rpc/useOperations.js.map +1 -1
  138. package/dist/rpc.cjs +3 -0
  139. package/dist/rpc.cjs.map +1 -1
  140. package/dist/rpc.d.ts +1 -0
  141. package/dist/rpc.d.ts.map +1 -1
  142. package/dist/rpc.js +3 -0
  143. package/dist/rpc.js.map +1 -1
  144. package/dist/styles.css +1 -1
  145. package/package.json +1 -1
@@ -0,0 +1,277 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useState, useMemo } from "react";
3
+ import { getFilterTokens } from "./DataTable.js";
4
+ import { Properties } from "./Properties.js";
5
+ import { TagActionsProvider, TagPropertiesList, normalizeTags } from "./cells/TagList.js";
6
+ import { formatPropertyLabel } from "./properties-utils.js";
7
+ import { asRecord } from "./log-utils.js";
8
+ import { UiCopy } from "../icons/components/UiCopy.js";
9
+ import { UiZoomIn } from "../icons/components/UiZoomIn.js";
10
+ import { UiZoomOut } from "../icons/components/UiZoomOut.js";
11
+ const TAGS_PATH = "details.tags";
12
+ const DETAIL_ROW_CLASS = "grid-cols-[fit-content(30ch)_minmax(0,1fr)]";
13
+ function renderLogDetails(row, context) {
14
+ return /* @__PURE__ */ jsx(
15
+ LogDetails,
16
+ {
17
+ row,
18
+ filterActions: context.filterActionsByColumn,
19
+ columns: context.columns
20
+ }
21
+ );
22
+ }
23
+ function fieldColumnKey(path) {
24
+ if (!path.startsWith("details.") || path === TAGS_PATH) return void 0;
25
+ const rest = path.slice("details.".length);
26
+ return rest && !rest.includes(".") ? rest : void 0;
27
+ }
28
+ function LogDetails({
29
+ row,
30
+ filterActions,
31
+ columns
32
+ }) {
33
+ const [openPaths, setOpenPaths] = useState({});
34
+ const setPathOpen = (path, open) => {
35
+ setOpenPaths((current) => ({ ...current, [path]: open }));
36
+ };
37
+ const details = useMemo(() => buildProcessedLogDetails(row), [row]);
38
+ const labelForPath = (path) => formatPropertyLabel(path.split(".").pop() ?? path);
39
+ const columnByKey = useMemo(
40
+ () => new Map(columns.map((column) => [column.key, column])),
41
+ [columns]
42
+ );
43
+ const fieldFilter = (path) => {
44
+ const key = fieldColumnKey(path);
45
+ if (!key) return void 0;
46
+ const actions = filterActions[key];
47
+ const column = columnByKey.get(key);
48
+ if (!actions || !column) return void 0;
49
+ const token = getFilterTokens(row, column)[0];
50
+ return token ? { actions, token } : void 0;
51
+ };
52
+ const prefixActions = [
53
+ {
54
+ id: "expand",
55
+ icon: UiZoomIn,
56
+ label: (key) => `Expand ${labelForPath(key)}`,
57
+ visible: (_k, _v, item) => !!item.expandable,
58
+ disabled: (_k, _v, item) => !!item.expanded,
59
+ onClick: (_k, _v, item) => {
60
+ var _a;
61
+ return (_a = item.onToggle) == null ? void 0 : _a.call(item, true);
62
+ }
63
+ },
64
+ {
65
+ id: "collapse",
66
+ icon: UiZoomOut,
67
+ label: (key) => `Collapse ${labelForPath(key)}`,
68
+ visible: (_k, _v, item) => !!item.expandable,
69
+ disabled: (_k, _v, item) => !item.expanded,
70
+ onClick: (_k, _v, item) => {
71
+ var _a;
72
+ return (_a = item.onToggle) == null ? void 0 : _a.call(item, false);
73
+ }
74
+ },
75
+ {
76
+ id: "include",
77
+ icon: UiZoomIn,
78
+ label: (key) => `Include ${labelForPath(key)}`,
79
+ visible: (key) => !!fieldFilter(key),
80
+ onClick: (key) => {
81
+ const filter = fieldFilter(key);
82
+ filter == null ? void 0 : filter.actions.toggleInclude(filter.token);
83
+ }
84
+ },
85
+ {
86
+ id: "exclude",
87
+ icon: UiZoomOut,
88
+ label: (key) => `Exclude ${labelForPath(key)}`,
89
+ visible: (key) => !!fieldFilter(key),
90
+ onClick: (key) => {
91
+ const filter = fieldFilter(key);
92
+ filter == null ? void 0 : filter.actions.toggleExclude(filter.token);
93
+ }
94
+ }
95
+ ];
96
+ const suffixActions = [
97
+ {
98
+ id: "copy",
99
+ icon: UiCopy,
100
+ label: (key) => `Copy ${labelForPath(key)}`,
101
+ visible: (key) => key !== TAGS_PATH,
102
+ onClick: (_k, value) => copyLogDetailsValue(value)
103
+ }
104
+ ];
105
+ const renderLabel = (key) => labelForPath(key);
106
+ const renderValue = (key, value, item) => {
107
+ if (key === TAGS_PATH) {
108
+ const count = Array.isArray(value) ? value.length : 0;
109
+ return /* @__PURE__ */ jsxs("span", { className: "font-mono text-muted-foreground", children: [
110
+ "[",
111
+ count,
112
+ " tags]"
113
+ ] });
114
+ }
115
+ return item.expandable ? /* @__PURE__ */ jsx(LogValueSummary, { value }) : /* @__PURE__ */ jsx(LogScalarValue, { value });
116
+ };
117
+ const toItems = (value, path, depth) => getValueEntries(value).map(([key, entryValue]) => {
118
+ const entryPath = `${path}.${String(key)}`;
119
+ const isTags = entryPath === TAGS_PATH;
120
+ const expandable = isTags || isExpandableValue(entryValue);
121
+ const open = openPaths[entryPath] ?? depth < 1;
122
+ return {
123
+ key: entryPath,
124
+ value: entryValue,
125
+ expandable,
126
+ expanded: open,
127
+ onToggle: (next) => setPathOpen(entryPath, next),
128
+ renderChildren: () => isTags ? /* @__PURE__ */ jsx(
129
+ TagPropertiesList,
130
+ {
131
+ tags: normalizeTags(entryValue),
132
+ rowClassName: DETAIL_ROW_CLASS
133
+ }
134
+ ) : /* @__PURE__ */ jsx(
135
+ Properties,
136
+ {
137
+ density: "compact",
138
+ items: toItems(entryValue, entryPath, depth + 1),
139
+ renderLabel,
140
+ renderValue,
141
+ prefixActions,
142
+ suffixActions,
143
+ rowClassName: DETAIL_ROW_CLASS,
144
+ className: "mt-density-1"
145
+ }
146
+ )
147
+ };
148
+ });
149
+ const properties = /* @__PURE__ */ jsx(
150
+ Properties,
151
+ {
152
+ density: "compact",
153
+ items: toItems(details, "details", 0),
154
+ renderLabel,
155
+ renderValue,
156
+ prefixActions,
157
+ suffixActions,
158
+ rowClassName: DETAIL_ROW_CLASS
159
+ }
160
+ );
161
+ const tagActions = filterActions["tags"];
162
+ return /* @__PURE__ */ jsx("div", { className: "space-y-density-3 text-xs", children: tagActions ? /* @__PURE__ */ jsx(TagActionsProvider, { value: tagActions, children: properties }) : properties });
163
+ }
164
+ function LogValueSummary({ value }) {
165
+ if (Array.isArray(value)) {
166
+ return /* @__PURE__ */ jsxs("span", { className: "font-mono text-muted-foreground", children: [
167
+ "[",
168
+ value.length,
169
+ " items]"
170
+ ] });
171
+ }
172
+ const record = asRecord(value);
173
+ if (record) {
174
+ const count = Object.keys(record).length;
175
+ return /* @__PURE__ */ jsxs("span", { className: "font-mono text-muted-foreground", children: [
176
+ "{ ",
177
+ count,
178
+ " properties",
179
+ " }"
180
+ ] });
181
+ }
182
+ return /* @__PURE__ */ jsx(LogScalarValue, { value });
183
+ }
184
+ function LogScalarValue({ value }) {
185
+ if (value === null || value === void 0) {
186
+ return /* @__PURE__ */ jsx("span", { className: "font-mono italic text-muted-foreground", children: "null" });
187
+ }
188
+ if (typeof value === "string") {
189
+ return /* @__PURE__ */ jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-foreground", children: value });
190
+ }
191
+ if (typeof value === "number" || typeof value === "boolean") {
192
+ return /* @__PURE__ */ jsx("span", { className: "font-mono text-blue-700 dark:text-blue-400", children: String(value) });
193
+ }
194
+ return /* @__PURE__ */ jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-foreground", children: stablePrettyString(value) });
195
+ }
196
+ function getValueEntries(value) {
197
+ if (Array.isArray(value)) {
198
+ return value.map((entry, index) => [index, entry]);
199
+ }
200
+ return Object.entries(asRecord(value) ?? {});
201
+ }
202
+ function isExpandableValue(value) {
203
+ return getValueEntries(value).length > 0;
204
+ }
205
+ function stablePrettyString(value) {
206
+ if (typeof value === "string") return value;
207
+ try {
208
+ return JSON.stringify(value, null, 2);
209
+ } catch {
210
+ return String(value);
211
+ }
212
+ }
213
+ function copyLogDetailsValue(value) {
214
+ var _a;
215
+ if (typeof navigator !== "undefined" && ((_a = navigator.clipboard) == null ? void 0 : _a.writeText)) {
216
+ Promise.resolve(navigator.clipboard.writeText(stablePrettyString(value))).catch(
217
+ () => void 0
218
+ );
219
+ }
220
+ }
221
+ function buildProcessedLogDetails(row) {
222
+ const attributes = buildProcessedLogAttributes(row);
223
+ return stripEmptyProperties({
224
+ timestamp: row.timestamp,
225
+ level: row.level,
226
+ pod: row.pod,
227
+ logger: row.logger,
228
+ thread: row.thread,
229
+ message: row.message,
230
+ tags: row.tags,
231
+ ...Object.keys(attributes).length > 0 ? { attributes } : {}
232
+ });
233
+ }
234
+ function buildProcessedLogAttributes(row) {
235
+ const attributes = {
236
+ ...asRecord(row.raw),
237
+ ...asRecord(row.parsedLine)
238
+ };
239
+ const hiddenKeys = /* @__PURE__ */ new Set([
240
+ "@timestamp",
241
+ "container",
242
+ "event.dataset",
243
+ "labels",
244
+ "level",
245
+ "line",
246
+ "log.level",
247
+ "log.logger",
248
+ "logger",
249
+ "message",
250
+ "msg",
251
+ "pod",
252
+ "process.thread.name",
253
+ "service",
254
+ "service.name",
255
+ "severity",
256
+ "thread",
257
+ "time",
258
+ "timestamp"
259
+ ]);
260
+ return stripEmptyProperties(
261
+ Object.fromEntries(Object.entries(attributes).filter(([key]) => !hiddenKeys.has(key)))
262
+ );
263
+ }
264
+ function stripEmptyProperties(record) {
265
+ return Object.fromEntries(
266
+ Object.entries(record).filter(([, value]) => {
267
+ if (value == null) return false;
268
+ if (typeof value === "string") return value.trim().length > 0;
269
+ if (Array.isArray(value)) return value.length > 0;
270
+ return true;
271
+ })
272
+ );
273
+ }
274
+ export {
275
+ renderLogDetails
276
+ };
277
+ //# sourceMappingURL=LogDetails.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LogDetails.js","sources":["../../src/data/LogDetails.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport {\n getFilterTokens,\n type DataTableColumn,\n type DataTableRowDetailContext,\n} from \"./DataTable\";\nimport { Properties, type PropertiesAction, type PropertiesItem } from \"./Properties\";\nimport {\n TagActionsProvider,\n TagPropertiesList,\n type TagActionsContextValue,\n normalizeTags,\n} from \"./cells/TagList\";\nimport { formatPropertyLabel } from \"./properties-utils\";\nimport type { LogsTableRow } from \"./LogsTable\";\nimport { asRecord } from \"./log-utils\";\nimport { UiCopy, UiZoomIn, UiZoomOut } from \"../icons\";\n\nconst TAGS_PATH = \"details.tags\";\n\n// Key column shrinks to its content (no min/fixed width), never wider than 30ch.\nconst DETAIL_ROW_CLASS = \"grid-cols-[fit-content(30ch)_minmax(0,1fr)]\";\n\nexport function renderLogDetails(\n row: LogsTableRow,\n context: DataTableRowDetailContext<LogsTableRow>,\n): ReactNode {\n return (\n <LogDetails\n row={row}\n filterActions={context.filterActionsByColumn}\n columns={context.columns}\n />\n );\n}\n\n/**\n * Maps a top-level detail field path (`details.<columnKey>`) to its column key.\n * Returns undefined for nested paths and the tags array, which have their own\n * filter affordances.\n */\nfunction fieldColumnKey(path: string): string | undefined {\n if (!path.startsWith(\"details.\") || path === TAGS_PATH) return undefined;\n const rest = path.slice(\"details.\".length);\n return rest && !rest.includes(\".\") ? rest : undefined;\n}\n\nfunction LogDetails({\n row,\n filterActions,\n columns,\n}: {\n row: LogsTableRow;\n filterActions: Record<string, TagActionsContextValue>;\n columns: DataTableColumn<LogsTableRow>[];\n}) {\n const [openPaths, setOpenPaths] = useState<Record<string, boolean>>({});\n const setPathOpen = (path: string, open: boolean) => {\n setOpenPaths((current) => ({ ...current, [path]: open }));\n };\n const details = useMemo(() => buildProcessedLogDetails(row), [row]);\n\n const labelForPath = (path: string) => formatPropertyLabel(path.split(\".\").pop() ?? path);\n\n const columnByKey = useMemo(\n () => new Map(columns.map((column) => [column.key, column])),\n [columns],\n );\n\n // Include/exclude is wired only for fields whose column is a multi/nested-multi\n // (tristate) filter; other columns (high-cardinality text, number, timestamp)\n // don't honor multiFilters, so they get no filter actions. The toggle token\n // must match the column's filter token (e.g. a status column maps \"INFO\" to a\n // normalized status), so it is derived via getFilterTokens rather than the\n // displayed value.\n const fieldFilter = (\n path: string,\n ): { actions: TagActionsContextValue; token: string } | undefined => {\n const key = fieldColumnKey(path);\n if (!key) return undefined;\n const actions = filterActions[key];\n const column = columnByKey.get(key);\n if (!actions || !column) return undefined;\n const token = getFilterTokens(row, column)[0];\n return token ? { actions, token } : undefined;\n };\n\n const prefixActions: PropertiesAction<unknown>[] = [\n {\n id: \"expand\",\n icon: UiZoomIn,\n label: (key) => `Expand ${labelForPath(key)}`,\n visible: (_k, _v, item) => !!item.expandable,\n disabled: (_k, _v, item) => !!item.expanded,\n onClick: (_k, _v, item) => item.onToggle?.(true),\n },\n {\n id: \"collapse\",\n icon: UiZoomOut,\n label: (key) => `Collapse ${labelForPath(key)}`,\n visible: (_k, _v, item) => !!item.expandable,\n disabled: (_k, _v, item) => !item.expanded,\n onClick: (_k, _v, item) => item.onToggle?.(false),\n },\n {\n id: \"include\",\n icon: UiZoomIn,\n label: (key) => `Include ${labelForPath(key)}`,\n visible: (key) => !!fieldFilter(key),\n onClick: (key) => {\n const filter = fieldFilter(key);\n filter?.actions.toggleInclude(filter.token);\n },\n },\n {\n id: \"exclude\",\n icon: UiZoomOut,\n label: (key) => `Exclude ${labelForPath(key)}`,\n visible: (key) => !!fieldFilter(key),\n onClick: (key) => {\n const filter = fieldFilter(key);\n filter?.actions.toggleExclude(filter.token);\n },\n },\n ];\n\n // Copy sits immediately after the value (suffix), separate from the leading\n // expand/collapse/include/exclude controls.\n const suffixActions: PropertiesAction<unknown>[] = [\n {\n id: \"copy\",\n icon: UiCopy,\n label: (key) => `Copy ${labelForPath(key)}`,\n visible: (key) => key !== TAGS_PATH,\n onClick: (_k, value) => copyLogDetailsValue(value),\n },\n ];\n\n const renderLabel = (key: string) => labelForPath(key);\n const renderValue = (key: string, value: unknown, item: PropertiesItem<unknown>) => {\n if (key === TAGS_PATH) {\n const count = Array.isArray(value) ? value.length : 0;\n return <span className=\"font-mono text-muted-foreground\">[{count} tags]</span>;\n }\n return item.expandable ? <LogValueSummary value={value} /> : <LogScalarValue value={value} />;\n };\n\n const toItems = (value: unknown, path: string, depth: number): PropertiesItem<unknown>[] =>\n getValueEntries(value).map(([key, entryValue]) => {\n const entryPath = `${path}.${String(key)}`;\n const isTags = entryPath === TAGS_PATH;\n const expandable = isTags || isExpandableValue(entryValue);\n const open = openPaths[entryPath] ?? depth < 1;\n return {\n key: entryPath,\n value: entryValue,\n expandable,\n expanded: open,\n onToggle: (next) => setPathOpen(entryPath, next),\n renderChildren: () =>\n isTags ? (\n <TagPropertiesList\n tags={normalizeTags(entryValue as string[])}\n rowClassName={DETAIL_ROW_CLASS}\n />\n ) : (\n <Properties\n density=\"compact\"\n items={toItems(entryValue, entryPath, depth + 1)}\n renderLabel={renderLabel}\n renderValue={renderValue}\n prefixActions={prefixActions}\n suffixActions={suffixActions}\n rowClassName={DETAIL_ROW_CLASS}\n className=\"mt-density-1\"\n />\n ),\n };\n });\n\n const properties = (\n <Properties\n density=\"compact\"\n items={toItems(details, \"details\", 0)}\n renderLabel={renderLabel}\n renderValue={renderValue}\n prefixActions={prefixActions}\n suffixActions={suffixActions}\n rowClassName={DETAIL_ROW_CLASS}\n />\n );\n\n const tagActions = filterActions[\"tags\"];\n return (\n <div className=\"space-y-density-3 text-xs\">\n {tagActions ? (\n <TagActionsProvider value={tagActions}>{properties}</TagActionsProvider>\n ) : (\n properties\n )}\n </div>\n );\n}\n\nfunction LogValueSummary({ value }: { value: unknown }) {\n if (Array.isArray(value)) {\n return <span className=\"font-mono text-muted-foreground\">[{value.length} items]</span>;\n }\n const record = asRecord(value);\n if (record) {\n const count = Object.keys(record).length;\n return (\n <span className=\"font-mono text-muted-foreground\">\n {\"{ \"}\n {count} properties{\" }\"}\n </span>\n );\n }\n return <LogScalarValue value={value} />;\n}\n\nfunction LogScalarValue({ value }: { value: unknown }) {\n if (value === null || value === undefined) {\n return <span className=\"font-mono italic text-muted-foreground\">null</span>;\n }\n\n if (typeof value === \"string\") {\n return (\n <pre className=\"max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-foreground\">\n {value}\n </pre>\n );\n }\n\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return <span className=\"font-mono text-blue-700 dark:text-blue-400\">{String(value)}</span>;\n }\n\n return (\n <pre className=\"max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-foreground\">\n {stablePrettyString(value)}\n </pre>\n );\n}\n\nfunction getValueEntries(value: unknown): Array<[string | number, unknown]> {\n if (Array.isArray(value)) {\n return value.map((entry, index) => [index, entry]);\n }\n return Object.entries(asRecord(value) ?? {});\n}\n\nfunction isExpandableValue(value: unknown) {\n return getValueEntries(value).length > 0;\n}\n\nfunction stablePrettyString(value: unknown): string {\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\nfunction copyLogDetailsValue(value: unknown) {\n if (typeof navigator !== \"undefined\" && navigator.clipboard?.writeText) {\n Promise.resolve(navigator.clipboard.writeText(stablePrettyString(value))).catch(\n () => undefined,\n );\n }\n}\n\nfunction buildProcessedLogDetails(row: LogsTableRow): Record<string, unknown> {\n const attributes = buildProcessedLogAttributes(row);\n return stripEmptyProperties({\n timestamp: row.timestamp,\n level: row.level,\n pod: row.pod,\n logger: row.logger,\n thread: row.thread,\n message: row.message,\n tags: row.tags,\n ...(Object.keys(attributes).length > 0 ? { attributes } : {}),\n });\n}\n\nfunction buildProcessedLogAttributes(row: LogsTableRow): Record<string, unknown> {\n const attributes = {\n ...asRecord(row.raw),\n ...asRecord(row.parsedLine),\n };\n const hiddenKeys = new Set([\n \"@timestamp\",\n \"container\",\n \"event.dataset\",\n \"labels\",\n \"level\",\n \"line\",\n \"log.level\",\n \"log.logger\",\n \"logger\",\n \"message\",\n \"msg\",\n \"pod\",\n \"process.thread.name\",\n \"service\",\n \"service.name\",\n \"severity\",\n \"thread\",\n \"time\",\n \"timestamp\",\n ]);\n\n return stripEmptyProperties(\n Object.fromEntries(Object.entries(attributes).filter(([key]) => !hiddenKeys.has(key))),\n );\n}\n\nfunction stripEmptyProperties(record: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(record).filter(([, value]) => {\n if (value == null) return false;\n if (typeof value === \"string\") return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n return true;\n }),\n );\n}\n"],"names":[],"mappings":"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"}
@@ -5,11 +5,8 @@ const react = require("react");
5
5
  const utils = require("../lib/utils.cjs");
6
6
  const AnsiHtml = require("./AnsiHtml.cjs");
7
7
  const DataTable = require("./DataTable.cjs");
8
- const Properties = require("./Properties.cjs");
9
- const propertiesUtils = require("./properties-utils.cjs");
10
- const UiCopy = require("../icons/components/UiCopy.cjs");
11
- const UiZoomIn = require("../icons/components/UiZoomIn.cjs");
12
- const UiZoomOut = require("../icons/components/UiZoomOut.cjs");
8
+ const LogDetails = require("./LogDetails.cjs");
9
+ const logUtils = require("./log-utils.cjs");
13
10
  const ANSI_PATTERN = new RegExp(`${String.fromCharCode(27)}\\[[0-9;?]*[ -/]*[@-~]`);
14
11
  const DEFAULT_LOG_COLUMNS = [
15
12
  {
@@ -73,7 +70,7 @@ function LogsTable({
73
70
  ...tableProps
74
71
  }) {
75
72
  const rows = react.useMemo(() => normalizeLogsTableRows(logs), [logs]);
76
- const resolvedRenderExpandedRow = renderExpandedRow ?? (showRawDetails ? renderLogDetails : void 0);
73
+ const resolvedRenderExpandedRow = renderExpandedRow ?? (showRawDetails ? LogDetails.renderLogDetails : void 0);
77
74
  return /* @__PURE__ */ jsxRuntime.jsx(
78
75
  DataTable.DataTable,
79
76
  {
@@ -104,12 +101,12 @@ function splitLogLines(logs) {
104
101
  function normalizeLogEntry(entry, index) {
105
102
  const parsedOuterValue = typeof entry === "string" ? tryParseJson(entry) : entry;
106
103
  const parsedOuter = parsedOuterValue === JSON_PARSE_FAILED ? entry : parsedOuterValue;
107
- const outer = asRecord(parsedOuter);
104
+ const outer = logUtils.asRecord(parsedOuter);
108
105
  const outerLine = stringValue(outer == null ? void 0 : outer.line);
109
106
  const parsedLineValue = outerLine ? tryParseJson(outerLine) : JSON_PARSE_FAILED;
110
107
  const parsedLine = parsedLineValue === JSON_PARSE_FAILED ? void 0 : parsedLineValue;
111
- const inner = asRecord(parsedLine) ?? (outerLine ? void 0 : outer);
112
- const labels = asRecord(outer == null ? void 0 : outer.labels);
108
+ const inner = logUtils.asRecord(parsedLine) ?? (outerLine ? void 0 : outer);
109
+ const labels = logUtils.asRecord(outer == null ? void 0 : outer.labels);
113
110
  const timestamp = firstString(
114
111
  pick(outer, "timestamp"),
115
112
  pick(inner, "@timestamp"),
@@ -216,196 +213,6 @@ function buildTags({
216
213
  }
217
214
  return tags;
218
215
  }
219
- function renderLogDetails(row) {
220
- return /* @__PURE__ */ jsxRuntime.jsx(LogDetails, { row });
221
- }
222
- function LogDetails({ row }) {
223
- const [openPaths, setOpenPaths] = react.useState({});
224
- const setPathOpen = (path, open) => {
225
- setOpenPaths((current) => ({ ...current, [path]: open }));
226
- };
227
- const details = react.useMemo(() => buildProcessedLogDetails(row), [row]);
228
- const labelForPath = (path) => propertiesUtils.formatPropertyLabel(path.split(".").pop() ?? path);
229
- const prefixActions = [
230
- {
231
- id: "expand",
232
- icon: UiZoomIn.UiZoomIn,
233
- label: (key) => `Expand ${labelForPath(key)}`,
234
- visible: (_k, _v, item) => !!item.expandable,
235
- disabled: (_k, _v, item) => !!item.expanded,
236
- onClick: (_k, _v, item) => {
237
- var _a;
238
- return (_a = item.onToggle) == null ? void 0 : _a.call(item, true);
239
- }
240
- },
241
- {
242
- id: "collapse",
243
- icon: UiZoomOut.UiZoomOut,
244
- label: (key) => `Collapse ${labelForPath(key)}`,
245
- visible: (_k, _v, item) => !!item.expandable,
246
- disabled: (_k, _v, item) => !item.expanded,
247
- onClick: (_k, _v, item) => {
248
- var _a;
249
- return (_a = item.onToggle) == null ? void 0 : _a.call(item, false);
250
- }
251
- }
252
- ];
253
- const suffixActions = [
254
- {
255
- id: "copy",
256
- icon: UiCopy.UiCopy,
257
- label: (key) => `Copy ${labelForPath(key)}`,
258
- onClick: (_k, value) => copyLogDetailsValue(value)
259
- }
260
- ];
261
- const renderLabel = (key) => labelForPath(key);
262
- const renderValue = (_key, value, item) => item.expandable ? /* @__PURE__ */ jsxRuntime.jsx(LogValueSummary, { value }) : /* @__PURE__ */ jsxRuntime.jsx(LogScalarValue, { value });
263
- const toItems = (value, path, depth) => getValueEntries(value).map(([key, entryValue]) => {
264
- const entryPath = `${path}.${String(key)}`;
265
- const expandable = isExpandableValue(entryValue);
266
- const open = openPaths[entryPath] ?? depth < 1;
267
- return {
268
- key: entryPath,
269
- value: entryValue,
270
- expandable,
271
- expanded: open,
272
- onToggle: (next) => setPathOpen(entryPath, next),
273
- renderChildren: () => /* @__PURE__ */ jsxRuntime.jsx(
274
- Properties.Properties,
275
- {
276
- density: "compact",
277
- items: toItems(entryValue, entryPath, depth + 1),
278
- renderLabel,
279
- renderValue,
280
- prefixActions,
281
- suffixActions,
282
- className: "mt-density-1"
283
- }
284
- )
285
- };
286
- });
287
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-density-3 text-xs", children: /* @__PURE__ */ jsxRuntime.jsx(
288
- Properties.Properties,
289
- {
290
- density: "compact",
291
- items: toItems(details, "details", 0),
292
- renderLabel,
293
- renderValue,
294
- prefixActions,
295
- suffixActions
296
- }
297
- ) });
298
- }
299
- function LogValueSummary({ value }) {
300
- if (Array.isArray(value)) {
301
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono text-muted-foreground", children: [
302
- "[",
303
- value.length,
304
- " items]"
305
- ] });
306
- }
307
- const record = asRecord(value);
308
- if (record) {
309
- const count = Object.keys(record).length;
310
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono text-muted-foreground", children: [
311
- "{ ",
312
- count,
313
- " properties",
314
- " }"
315
- ] });
316
- }
317
- return /* @__PURE__ */ jsxRuntime.jsx(LogScalarValue, { value });
318
- }
319
- function LogScalarValue({ value }) {
320
- if (value === null || value === void 0) {
321
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono italic text-muted-foreground", children: "null" });
322
- }
323
- if (typeof value === "string") {
324
- return /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-foreground", children: value });
325
- }
326
- if (typeof value === "number" || typeof value === "boolean") {
327
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-blue-700 dark:text-blue-400", children: String(value) });
328
- }
329
- return /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-foreground", children: stablePrettyString(value) });
330
- }
331
- function getValueEntries(value) {
332
- if (Array.isArray(value)) {
333
- return value.map((entry, index) => [index, entry]);
334
- }
335
- return Object.entries(asRecord(value) ?? {});
336
- }
337
- function isExpandableValue(value) {
338
- return getValueEntries(value).length > 0;
339
- }
340
- function stablePrettyString(value) {
341
- if (typeof value === "string") return value;
342
- try {
343
- return JSON.stringify(value, null, 2);
344
- } catch {
345
- return String(value);
346
- }
347
- }
348
- function copyLogDetailsValue(value) {
349
- var _a;
350
- if (typeof navigator !== "undefined" && ((_a = navigator.clipboard) == null ? void 0 : _a.writeText)) {
351
- Promise.resolve(navigator.clipboard.writeText(stablePrettyString(value))).catch(
352
- () => void 0
353
- );
354
- }
355
- }
356
- function buildProcessedLogDetails(row) {
357
- const attributes = buildProcessedLogAttributes(row);
358
- return stripEmptyProperties({
359
- timestamp: row.timestamp,
360
- level: row.level,
361
- pod: row.pod,
362
- logger: row.logger,
363
- thread: row.thread,
364
- message: row.message,
365
- tags: row.tags,
366
- ...Object.keys(attributes).length > 0 ? { attributes } : {}
367
- });
368
- }
369
- function buildProcessedLogAttributes(row) {
370
- const attributes = {
371
- ...asRecord(row.raw),
372
- ...asRecord(row.parsedLine)
373
- };
374
- const hiddenKeys = /* @__PURE__ */ new Set([
375
- "@timestamp",
376
- "container",
377
- "event.dataset",
378
- "labels",
379
- "level",
380
- "line",
381
- "log.level",
382
- "log.logger",
383
- "logger",
384
- "message",
385
- "msg",
386
- "pod",
387
- "process.thread.name",
388
- "service",
389
- "service.name",
390
- "severity",
391
- "thread",
392
- "time",
393
- "timestamp"
394
- ]);
395
- return stripEmptyProperties(
396
- Object.fromEntries(Object.entries(attributes).filter(([key]) => !hiddenKeys.has(key)))
397
- );
398
- }
399
- function stripEmptyProperties(record) {
400
- return Object.fromEntries(
401
- Object.entries(record).filter(([, value]) => {
402
- if (value == null) return false;
403
- if (typeof value === "string") return value.trim().length > 0;
404
- if (Array.isArray(value)) return value.length > 0;
405
- return true;
406
- })
407
- );
408
- }
409
216
  function tryParseJson(value) {
410
217
  try {
411
218
  return JSON.parse(value);
@@ -413,9 +220,6 @@ function tryParseJson(value) {
413
220
  return JSON_PARSE_FAILED;
414
221
  }
415
222
  }
416
- function asRecord(value) {
417
- return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
418
- }
419
223
  function pick(record, path) {
420
224
  if (!record) return void 0;
421
225
  if (Object.prototype.hasOwnProperty.call(record, path)) return record[path];
@@ -1 +1 @@
1
- {"version":3,"file":"LogsTable.cjs","sources":["../../src/data/LogsTable.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { AnsiHtml } from \"./AnsiHtml\";\nimport { DataTable, type DataTableColumn, type DataTableProps } from \"./DataTable\";\nimport { Properties, type PropertiesAction, type PropertiesItem } from \"./Properties\";\nimport { formatPropertyLabel } from \"./properties-utils\";\nimport { UiCopy, UiZoomIn, UiZoomOut } from \"../icons\";\n\nexport type LogsTableInput = string | Record<string, unknown>;\n\nexport type LogsTableRow = {\n id: string;\n timestamp: string;\n level: string;\n pod: string;\n logger: string;\n thread: string;\n message: string;\n tags: string[];\n line: string;\n parsedLine?: unknown;\n raw: unknown;\n};\n\nexport type LogsTableProps = Omit<DataTableProps<LogsTableRow>, \"data\" | \"columns\"> & {\n /** Raw newline-delimited log text or pre-parsed log records. */\n logs: string | LogsTableInput[];\n /** Optional custom columns; defaults to timestamp, level, pod, logger, thread, message, and tags. */\n columns?: DataTableColumn<LogsTableRow>[];\n /** Render parsed/raw log details when a row is expanded. */\n showRawDetails?: boolean;\n};\n\n// Matches CSI / SGR escape sequences (e.g. \"\\x1b[31m\"). Used to skip the\n// AnsiHtml render for plain messages so the cell stays a fast text node.\nconst ANSI_PATTERN = new RegExp(`${String.fromCharCode(27)}\\\\[[0-9;?]*[ -/]*[@-~]`);\n\nconst DEFAULT_LOG_COLUMNS: DataTableColumn<LogsTableRow>[] = [\n {\n key: \"timestamp\",\n label: \"Timestamp\",\n kind: \"timestamp\",\n shrink: true,\n minWidth: 180,\n },\n {\n key: \"level\",\n label: \"Level\",\n kind: \"status\",\n shrink: true,\n minWidth: 96,\n status: { showLabel: true },\n },\n { key: \"pod\", label: \"Pod\", shrink: true, minWidth: 180 },\n { key: \"logger\", label: \"Logger\", shrink: true, minWidth: 220 },\n { key: \"thread\", label: \"Thread\", shrink: true, minWidth: 180 },\n {\n key: \"message\",\n label: \"Message\",\n grow: true,\n minWidth: 360,\n cellClassName: \"font-mono text-xs\",\n render: (value) => {\n const text = typeof value === \"string\" ? value : value == null ? \"\" : String(value);\n if (!ANSI_PATTERN.test(text)) return text;\n return <AnsiHtml as=\"span\" text={text} className=\"whitespace-pre-wrap break-words\" />;\n },\n },\n {\n key: \"tags\",\n label: \"Tags\",\n kind: \"tags\",\n grow: true,\n tags: { maxVisible: 4 },\n },\n];\n\nconst DEFAULT_SORT = {\n key: \"timestamp\",\n dir: \"desc\",\n} satisfies NonNullable<DataTableProps<LogsTableRow>[\"defaultSort\"]>;\nconst JSON_PARSE_FAILED = Symbol(\"json-parse-failed\");\n\nexport function LogsTable({\n logs,\n columns,\n showRawDetails = true,\n className,\n autoFilter = true,\n defaultSort,\n getRowId,\n renderExpandedRow,\n showDensityControl = true,\n showThemeControl = true,\n showFullscreenControl = true,\n fullscreenTitle = \"Logs\",\n fullscreenButtonLabel = \"Open logs full screen\",\n defaultDensity = \"compact\",\n ...tableProps\n}: LogsTableProps) {\n const rows = useMemo(() => normalizeLogsTableRows(logs), [logs]);\n const resolvedRenderExpandedRow =\n renderExpandedRow ?? (showRawDetails ? renderLogDetails : undefined);\n return (\n <DataTable\n {...tableProps}\n data={rows}\n columns={columns ?? DEFAULT_LOG_COLUMNS}\n className={cn(\"rounded-md bg-background p-2\", className)}\n autoFilter={autoFilter}\n defaultDensity={defaultDensity}\n defaultSort={defaultSort ?? DEFAULT_SORT}\n getRowId={getRowId ?? ((row) => row.id)}\n showDensityControl={showDensityControl}\n showThemeControl={showThemeControl}\n showFullscreenControl={showFullscreenControl}\n fullscreenTitle={fullscreenTitle}\n fullscreenButtonLabel={fullscreenButtonLabel}\n {...(resolvedRenderExpandedRow ? { renderExpandedRow: resolvedRenderExpandedRow } : {})}\n />\n );\n}\n\nexport function normalizeLogsTableRows(logs: string | LogsTableInput[]): LogsTableRow[] {\n const entries = typeof logs === \"string\" ? splitLogLines(logs) : logs;\n return entries.map((entry, index) => normalizeLogEntry(entry, index));\n}\n\nfunction splitLogLines(logs: string): string[] {\n return logs.split(/\\r?\\n/).filter((line) => line.length > 0);\n}\n\nfunction normalizeLogEntry(entry: LogsTableInput, index: number): LogsTableRow {\n const parsedOuterValue = typeof entry === \"string\" ? tryParseJson(entry) : entry;\n const parsedOuter = parsedOuterValue === JSON_PARSE_FAILED ? entry : parsedOuterValue;\n const outer = asRecord(parsedOuter);\n const outerLine = stringValue(outer?.line);\n const parsedLineValue = outerLine ? tryParseJson(outerLine) : JSON_PARSE_FAILED;\n const parsedLine = parsedLineValue === JSON_PARSE_FAILED ? undefined : parsedLineValue;\n const inner = asRecord(parsedLine) ?? (outerLine ? undefined : outer);\n const labels = asRecord(outer?.labels);\n\n const timestamp = firstString(\n pick(outer, \"timestamp\"),\n pick(inner, \"@timestamp\"),\n pick(outer, \"ts\"),\n pick(inner, \"timestamp\"),\n pick(outer, \"time\"),\n pick(inner, \"time\"),\n );\n const level = firstString(\n pick(inner, \"log.level\"),\n pick(inner, \"level\"),\n pick(outer, \"level\"),\n pick(outer, \"severity\"),\n pick(inner, \"severity\"),\n );\n const pod = firstString(\n pick(outer, \"pod\"),\n pick(labels, \"pod\"),\n pick(inner, \"kubernetes.pod.name\"),\n );\n const namespace = firstString(\n pick(outer, \"namespace\"),\n pick(labels, \"namespace\"),\n pick(inner, \"kubernetes.namespace\"),\n );\n const container = firstString(\n pick(outer, \"container\"),\n pick(labels, \"container\"),\n pick(inner, \"container.name\"),\n );\n const service = firstString(\n pick(inner, \"service.name\"),\n pick(inner, \"service\"),\n pick(outer, \"service\"),\n pick(labels, \"service\"),\n );\n const dataset = firstString(pick(inner, \"event.dataset\"), pick(inner, \"dataset\"));\n const logger = firstString(\n pick(inner, \"log.logger\"),\n pick(inner, \"logger\"),\n pick(outer, \"logger\"),\n );\n const thread = firstString(\n pick(inner, \"process.thread.name\"),\n pick(inner, \"thread\"),\n pick(outer, \"thread\"),\n );\n const message = firstString(\n pick(inner, \"message\"),\n pick(inner, \"msg\"),\n pick(outer, \"message\"),\n outerLine,\n typeof entry === \"string\" ? entry : undefined,\n );\n\n const tags = buildTags({\n namespace,\n container,\n service,\n dataset,\n ecsVersion: firstString(pick(inner, \"ecs.version\")),\n labels,\n });\n\n return {\n id: `${index}:${timestamp || pod || message || stableString(entry)}`,\n timestamp,\n level,\n pod,\n logger,\n thread,\n message,\n tags,\n line: outerLine ?? (typeof entry === \"string\" ? entry : stableString(entry)),\n raw: parsedOuter,\n ...(parsedLine !== undefined ? { parsedLine } : {}),\n };\n}\n\nfunction buildTags({\n namespace,\n container,\n service,\n dataset,\n ecsVersion,\n labels,\n}: {\n namespace: string;\n container: string;\n service: string;\n dataset: string;\n ecsVersion: string;\n labels: Record<string, unknown> | undefined;\n}) {\n const tags: string[] = [];\n const seen = new Set<string>();\n const addTag = (key: string, value: unknown) => {\n const valueString = stringValue(value);\n if (!valueString) return;\n const tag = `${key}=${valueString}`;\n if (seen.has(tag)) return;\n seen.add(tag);\n tags.push(tag);\n };\n\n addTag(\"namespace\", namespace);\n addTag(\"container\", container);\n addTag(\"service\", service);\n addTag(\"dataset\", dataset);\n addTag(\"ecs.version\", ecsVersion);\n\n if (labels) {\n for (const [key, value] of Object.entries(labels)) {\n addTag(key, value);\n }\n }\n\n return tags;\n}\n\nfunction renderLogDetails(row: LogsTableRow): ReactNode {\n return <LogDetails row={row} />;\n}\n\nfunction LogDetails({ row }: { row: LogsTableRow }) {\n const [openPaths, setOpenPaths] = useState<Record<string, boolean>>({});\n const setPathOpen = (path: string, open: boolean) => {\n setOpenPaths((current) => ({ ...current, [path]: open }));\n };\n const details = useMemo(() => buildProcessedLogDetails(row), [row]);\n\n const labelForPath = (path: string) => formatPropertyLabel(path.split(\".\").pop() ?? path);\n\n const prefixActions: PropertiesAction<unknown>[] = [\n {\n id: \"expand\",\n icon: UiZoomIn,\n label: (key) => `Expand ${labelForPath(key)}`,\n visible: (_k, _v, item) => !!item.expandable,\n disabled: (_k, _v, item) => !!item.expanded,\n onClick: (_k, _v, item) => item.onToggle?.(true),\n },\n {\n id: \"collapse\",\n icon: UiZoomOut,\n label: (key) => `Collapse ${labelForPath(key)}`,\n visible: (_k, _v, item) => !!item.expandable,\n disabled: (_k, _v, item) => !item.expanded,\n onClick: (_k, _v, item) => item.onToggle?.(false),\n },\n ];\n\n const suffixActions: PropertiesAction<unknown>[] = [\n {\n id: \"copy\",\n icon: UiCopy,\n label: (key) => `Copy ${labelForPath(key)}`,\n onClick: (_k, value) => copyLogDetailsValue(value),\n },\n ];\n\n const renderLabel = (key: string) => labelForPath(key);\n const renderValue = (_key: string, value: unknown, item: PropertiesItem<unknown>) =>\n item.expandable ? <LogValueSummary value={value} /> : <LogScalarValue value={value} />;\n\n const toItems = (value: unknown, path: string, depth: number): PropertiesItem<unknown>[] =>\n getValueEntries(value).map(([key, entryValue]) => {\n const entryPath = `${path}.${String(key)}`;\n const expandable = isExpandableValue(entryValue);\n const open = openPaths[entryPath] ?? depth < 1;\n return {\n key: entryPath,\n value: entryValue,\n expandable,\n expanded: open,\n onToggle: (next) => setPathOpen(entryPath, next),\n renderChildren: () => (\n <Properties\n density=\"compact\"\n items={toItems(entryValue, entryPath, depth + 1)}\n renderLabel={renderLabel}\n renderValue={renderValue}\n prefixActions={prefixActions}\n suffixActions={suffixActions}\n className=\"mt-density-1\"\n />\n ),\n };\n });\n\n return (\n <div className=\"space-y-density-3 text-xs\">\n <Properties\n density=\"compact\"\n items={toItems(details, \"details\", 0)}\n renderLabel={renderLabel}\n renderValue={renderValue}\n prefixActions={prefixActions}\n suffixActions={suffixActions}\n />\n </div>\n );\n}\n\nfunction LogValueSummary({ value }: { value: unknown }) {\n if (Array.isArray(value)) {\n return <span className=\"font-mono text-muted-foreground\">[{value.length} items]</span>;\n }\n const record = asRecord(value);\n if (record) {\n const count = Object.keys(record).length;\n return (\n <span className=\"font-mono text-muted-foreground\">\n {\"{ \"}\n {count} properties{\" }\"}\n </span>\n );\n }\n return <LogScalarValue value={value} />;\n}\n\nfunction LogScalarValue({ value }: { value: unknown }) {\n if (value === null || value === undefined) {\n return <span className=\"font-mono italic text-muted-foreground\">null</span>;\n }\n\n if (typeof value === \"string\") {\n return (\n <pre className=\"max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-foreground\">\n {value}\n </pre>\n );\n }\n\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return <span className=\"font-mono text-blue-700 dark:text-blue-400\">{String(value)}</span>;\n }\n\n return (\n <pre className=\"max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-foreground\">\n {stablePrettyString(value)}\n </pre>\n );\n}\n\nfunction getValueEntries(value: unknown): Array<[string | number, unknown]> {\n if (Array.isArray(value)) {\n return value.map((entry, index) => [index, entry]);\n }\n return Object.entries(asRecord(value) ?? {});\n}\n\nfunction isExpandableValue(value: unknown) {\n return getValueEntries(value).length > 0;\n}\n\nfunction stablePrettyString(value: unknown): string {\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\nfunction copyLogDetailsValue(value: unknown) {\n if (typeof navigator !== \"undefined\" && navigator.clipboard?.writeText) {\n Promise.resolve(navigator.clipboard.writeText(stablePrettyString(value))).catch(\n () => undefined,\n );\n }\n}\n\nfunction buildProcessedLogDetails(row: LogsTableRow): Record<string, unknown> {\n const attributes = buildProcessedLogAttributes(row);\n return stripEmptyProperties({\n timestamp: row.timestamp,\n level: row.level,\n pod: row.pod,\n logger: row.logger,\n thread: row.thread,\n message: row.message,\n tags: row.tags,\n ...(Object.keys(attributes).length > 0 ? { attributes } : {}),\n });\n}\n\nfunction buildProcessedLogAttributes(row: LogsTableRow): Record<string, unknown> {\n const attributes = {\n ...asRecord(row.raw),\n ...asRecord(row.parsedLine),\n };\n const hiddenKeys = new Set([\n \"@timestamp\",\n \"container\",\n \"event.dataset\",\n \"labels\",\n \"level\",\n \"line\",\n \"log.level\",\n \"log.logger\",\n \"logger\",\n \"message\",\n \"msg\",\n \"pod\",\n \"process.thread.name\",\n \"service\",\n \"service.name\",\n \"severity\",\n \"thread\",\n \"time\",\n \"timestamp\",\n ]);\n\n return stripEmptyProperties(\n Object.fromEntries(Object.entries(attributes).filter(([key]) => !hiddenKeys.has(key))),\n );\n}\n\nfunction stripEmptyProperties(record: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(record).filter(([, value]) => {\n if (value == null) return false;\n if (typeof value === \"string\") return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n return true;\n }),\n );\n}\n\nfunction tryParseJson(value: string): unknown | typeof JSON_PARSE_FAILED {\n try {\n return JSON.parse(value) as unknown;\n } catch {\n return JSON_PARSE_FAILED;\n }\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nfunction pick(record: Record<string, unknown> | undefined, path: string): unknown {\n if (!record) return undefined;\n if (Object.prototype.hasOwnProperty.call(record, path)) return record[path];\n return path.split(\".\").reduce<unknown>((current, key) => {\n if (current && typeof current === \"object\") {\n return (current as Record<string, unknown>)[key];\n }\n return undefined;\n }, record);\n}\n\nfunction firstString(...values: unknown[]): string {\n for (const value of values) {\n const string = stringValue(value);\n if (string) return string;\n }\n return \"\";\n}\n\nfunction stringValue(value: unknown): string {\n if (value == null) return \"\";\n if (typeof value === \"string\") return value.trim();\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n return \"\";\n}\n\nfunction stableString(value: unknown): string {\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n"],"names":["AnsiHtml","useMemo","jsx","DataTable","cn","useState","formatPropertyLabel","UiZoomIn","UiZoomOut","UiCopy","Properties","jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"LogsTable.cjs","sources":["../../src/data/LogsTable.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { AnsiHtml } from \"./AnsiHtml\";\nimport { DataTable, type DataTableColumn, type DataTableProps } from \"./DataTable\";\nimport { renderLogDetails } from \"./LogDetails\";\nimport { asRecord } from \"./log-utils\";\n\nexport type LogsTableInput = string | Record<string, unknown>;\n\nexport type LogsTableRow = {\n id: string;\n timestamp: string;\n level: string;\n pod: string;\n logger: string;\n thread: string;\n message: string;\n tags: string[];\n line: string;\n parsedLine?: unknown;\n raw: unknown;\n};\n\nexport type LogsTableProps = Omit<DataTableProps<LogsTableRow>, \"data\" | \"columns\"> & {\n /** Raw newline-delimited log text or pre-parsed log records. */\n logs: string | LogsTableInput[];\n /** Optional custom columns; defaults to timestamp, level, pod, logger, thread, message, and tags. */\n columns?: DataTableColumn<LogsTableRow>[];\n /** Render parsed/raw log details when a row is expanded. */\n showRawDetails?: boolean;\n};\n\n// Matches CSI / SGR escape sequences (e.g. \"\\x1b[31m\"). Used to skip the\n// AnsiHtml render for plain messages so the cell stays a fast text node.\nconst ANSI_PATTERN = new RegExp(`${String.fromCharCode(27)}\\\\[[0-9;?]*[ -/]*[@-~]`);\n\nconst DEFAULT_LOG_COLUMNS: DataTableColumn<LogsTableRow>[] = [\n {\n key: \"timestamp\",\n label: \"Timestamp\",\n kind: \"timestamp\",\n shrink: true,\n minWidth: 180,\n },\n {\n key: \"level\",\n label: \"Level\",\n kind: \"status\",\n shrink: true,\n minWidth: 96,\n status: { showLabel: true },\n },\n { key: \"pod\", label: \"Pod\", shrink: true, minWidth: 180 },\n { key: \"logger\", label: \"Logger\", shrink: true, minWidth: 220 },\n { key: \"thread\", label: \"Thread\", shrink: true, minWidth: 180 },\n {\n key: \"message\",\n label: \"Message\",\n grow: true,\n minWidth: 360,\n cellClassName: \"font-mono text-xs\",\n render: (value) => {\n const text = typeof value === \"string\" ? value : value == null ? \"\" : String(value);\n if (!ANSI_PATTERN.test(text)) return text;\n return <AnsiHtml as=\"span\" text={text} className=\"whitespace-pre-wrap break-words\" />;\n },\n },\n {\n key: \"tags\",\n label: \"Tags\",\n kind: \"tags\",\n grow: true,\n tags: { maxVisible: 4 },\n },\n];\n\nconst DEFAULT_SORT = {\n key: \"timestamp\",\n dir: \"desc\",\n} satisfies NonNullable<DataTableProps<LogsTableRow>[\"defaultSort\"]>;\nconst JSON_PARSE_FAILED = Symbol(\"json-parse-failed\");\n\nexport function LogsTable({\n logs,\n columns,\n showRawDetails = true,\n className,\n autoFilter = true,\n defaultSort,\n getRowId,\n renderExpandedRow,\n showDensityControl = true,\n showThemeControl = true,\n showFullscreenControl = true,\n fullscreenTitle = \"Logs\",\n fullscreenButtonLabel = \"Open logs full screen\",\n defaultDensity = \"compact\",\n ...tableProps\n}: LogsTableProps) {\n const rows = useMemo(() => normalizeLogsTableRows(logs), [logs]);\n const resolvedRenderExpandedRow =\n renderExpandedRow ?? (showRawDetails ? renderLogDetails : undefined);\n return (\n <DataTable\n {...tableProps}\n data={rows}\n columns={columns ?? DEFAULT_LOG_COLUMNS}\n className={cn(\"rounded-md bg-background p-2\", className)}\n autoFilter={autoFilter}\n defaultDensity={defaultDensity}\n defaultSort={defaultSort ?? DEFAULT_SORT}\n getRowId={getRowId ?? ((row) => row.id)}\n showDensityControl={showDensityControl}\n showThemeControl={showThemeControl}\n showFullscreenControl={showFullscreenControl}\n fullscreenTitle={fullscreenTitle}\n fullscreenButtonLabel={fullscreenButtonLabel}\n {...(resolvedRenderExpandedRow ? { renderExpandedRow: resolvedRenderExpandedRow } : {})}\n />\n );\n}\n\nexport function normalizeLogsTableRows(logs: string | LogsTableInput[]): LogsTableRow[] {\n const entries = typeof logs === \"string\" ? splitLogLines(logs) : logs;\n return entries.map((entry, index) => normalizeLogEntry(entry, index));\n}\n\nfunction splitLogLines(logs: string): string[] {\n return logs.split(/\\r?\\n/).filter((line) => line.length > 0);\n}\n\nfunction normalizeLogEntry(entry: LogsTableInput, index: number): LogsTableRow {\n const parsedOuterValue = typeof entry === \"string\" ? tryParseJson(entry) : entry;\n const parsedOuter = parsedOuterValue === JSON_PARSE_FAILED ? entry : parsedOuterValue;\n const outer = asRecord(parsedOuter);\n const outerLine = stringValue(outer?.line);\n const parsedLineValue = outerLine ? tryParseJson(outerLine) : JSON_PARSE_FAILED;\n const parsedLine = parsedLineValue === JSON_PARSE_FAILED ? undefined : parsedLineValue;\n const inner = asRecord(parsedLine) ?? (outerLine ? undefined : outer);\n const labels = asRecord(outer?.labels);\n\n const timestamp = firstString(\n pick(outer, \"timestamp\"),\n pick(inner, \"@timestamp\"),\n pick(outer, \"ts\"),\n pick(inner, \"timestamp\"),\n pick(outer, \"time\"),\n pick(inner, \"time\"),\n );\n const level = firstString(\n pick(inner, \"log.level\"),\n pick(inner, \"level\"),\n pick(outer, \"level\"),\n pick(outer, \"severity\"),\n pick(inner, \"severity\"),\n );\n const pod = firstString(\n pick(outer, \"pod\"),\n pick(labels, \"pod\"),\n pick(inner, \"kubernetes.pod.name\"),\n );\n const namespace = firstString(\n pick(outer, \"namespace\"),\n pick(labels, \"namespace\"),\n pick(inner, \"kubernetes.namespace\"),\n );\n const container = firstString(\n pick(outer, \"container\"),\n pick(labels, \"container\"),\n pick(inner, \"container.name\"),\n );\n const service = firstString(\n pick(inner, \"service.name\"),\n pick(inner, \"service\"),\n pick(outer, \"service\"),\n pick(labels, \"service\"),\n );\n const dataset = firstString(pick(inner, \"event.dataset\"), pick(inner, \"dataset\"));\n const logger = firstString(\n pick(inner, \"log.logger\"),\n pick(inner, \"logger\"),\n pick(outer, \"logger\"),\n );\n const thread = firstString(\n pick(inner, \"process.thread.name\"),\n pick(inner, \"thread\"),\n pick(outer, \"thread\"),\n );\n const message = firstString(\n pick(inner, \"message\"),\n pick(inner, \"msg\"),\n pick(outer, \"message\"),\n outerLine,\n typeof entry === \"string\" ? entry : undefined,\n );\n\n const tags = buildTags({\n namespace,\n container,\n service,\n dataset,\n ecsVersion: firstString(pick(inner, \"ecs.version\")),\n labels,\n });\n\n return {\n id: `${index}:${timestamp || pod || message || stableString(entry)}`,\n timestamp,\n level,\n pod,\n logger,\n thread,\n message,\n tags,\n line: outerLine ?? (typeof entry === \"string\" ? entry : stableString(entry)),\n raw: parsedOuter,\n ...(parsedLine !== undefined ? { parsedLine } : {}),\n };\n}\n\nfunction buildTags({\n namespace,\n container,\n service,\n dataset,\n ecsVersion,\n labels,\n}: {\n namespace: string;\n container: string;\n service: string;\n dataset: string;\n ecsVersion: string;\n labels: Record<string, unknown> | undefined;\n}) {\n const tags: string[] = [];\n const seen = new Set<string>();\n const addTag = (key: string, value: unknown) => {\n const valueString = stringValue(value);\n if (!valueString) return;\n const tag = `${key}=${valueString}`;\n if (seen.has(tag)) return;\n seen.add(tag);\n tags.push(tag);\n };\n\n addTag(\"namespace\", namespace);\n addTag(\"container\", container);\n addTag(\"service\", service);\n addTag(\"dataset\", dataset);\n addTag(\"ecs.version\", ecsVersion);\n\n if (labels) {\n for (const [key, value] of Object.entries(labels)) {\n addTag(key, value);\n }\n }\n\n return tags;\n}\n\nfunction tryParseJson(value: string): unknown | typeof JSON_PARSE_FAILED {\n try {\n return JSON.parse(value) as unknown;\n } catch {\n return JSON_PARSE_FAILED;\n }\n}\n\nfunction pick(record: Record<string, unknown> | undefined, path: string): unknown {\n if (!record) return undefined;\n if (Object.prototype.hasOwnProperty.call(record, path)) return record[path];\n return path.split(\".\").reduce<unknown>((current, key) => {\n if (current && typeof current === \"object\") {\n return (current as Record<string, unknown>)[key];\n }\n return undefined;\n }, record);\n}\n\nfunction firstString(...values: unknown[]): string {\n for (const value of values) {\n const string = stringValue(value);\n if (string) return string;\n }\n return \"\";\n}\n\nfunction stringValue(value: unknown): string {\n if (value == null) return \"\";\n if (typeof value === \"string\") return value.trim();\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n return \"\";\n}\n\nfunction stableString(value: unknown): string {\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n"],"names":["AnsiHtml","useMemo","renderLogDetails","jsx","DataTable","cn","asRecord"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"LogsTable.d.ts","sourceRoot":"","sources":["../../src/data/LogsTable.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAa,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAKnF,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9D,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG;IACpF,gEAAgE;IAChE,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,qGAAqG;IACrG,OAAO,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,EAAE,CAAC;IAC1C,4DAA4D;IAC5D,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAoDF,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,OAAO,EACP,cAAqB,EACrB,SAAS,EACT,UAAiB,EACjB,WAAW,EACX,QAAQ,EACR,iBAAiB,EACjB,kBAAyB,EACzB,gBAAuB,EACvB,qBAA4B,EAC5B,eAAwB,EACxB,qBAA+C,EAC/C,cAA0B,EAC1B,GAAG,UAAU,EACd,EAAE,cAAc,2CAsBhB;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,GAAG,YAAY,EAAE,CAGtF"}
1
+ {"version":3,"file":"LogsTable.d.ts","sourceRoot":"","sources":["../../src/data/LogsTable.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAa,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAInF,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9D,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG;IACpF,gEAAgE;IAChE,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,qGAAqG;IACrG,OAAO,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,EAAE,CAAC;IAC1C,4DAA4D;IAC5D,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAoDF,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,OAAO,EACP,cAAqB,EACrB,SAAS,EACT,UAAiB,EACjB,WAAW,EACX,QAAQ,EACR,iBAAiB,EACjB,kBAAyB,EACzB,gBAAuB,EACvB,qBAA4B,EAC5B,eAAwB,EACxB,qBAA+C,EAC/C,cAA0B,EAC1B,GAAG,UAAU,EACd,EAAE,cAAc,2CAsBhB;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,GAAG,YAAY,EAAE,CAGtF"}