@instantdb/components 0.22.89-experimental.drewh-ssr.20277611943.1 → 0.22.89-experimental.drewh-fix-export.20277749804.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@instantdb/components",
3
3
  "private": false,
4
- "version": "0.22.89-experimental.drewh-ssr.20277611943.1",
4
+ "version": "0.22.89-experimental.drewh-fix-export.20277749804.1",
5
5
  "type": "module",
6
6
  "description": "Instant's UI components",
7
7
  "homepage": "https://github.com/instantdb/instant/tree/main/client/packages/components",
@@ -92,11 +92,11 @@
92
92
  "swr": "^2.2.4",
93
93
  "tailwind-merge": "^2.2.1",
94
94
  "uuid": "^11.1.0",
95
- "@instantdb/admin": "0.22.89-experimental.drewh-ssr.20277611943.1",
96
- "@instantdb/platform": "0.22.89-experimental.drewh-ssr.20277611943.1",
97
- "@instantdb/react": "0.22.89-experimental.drewh-ssr.20277611943.1",
98
- "@instantdb/version": "0.22.89-experimental.drewh-ssr.20277611943.1",
99
- "@instantdb/core": "0.22.89-experimental.drewh-ssr.20277611943.1"
95
+ "@instantdb/admin": "0.22.89-experimental.drewh-fix-export.20277749804.1",
96
+ "@instantdb/platform": "0.22.89-experimental.drewh-fix-export.20277749804.1",
97
+ "@instantdb/version": "0.22.89-experimental.drewh-fix-export.20277749804.1",
98
+ "@instantdb/react": "0.22.89-experimental.drewh-fix-export.20277749804.1",
99
+ "@instantdb/core": "0.22.89-experimental.drewh-fix-export.20277749804.1"
100
100
  },
101
101
  "scripts": {
102
102
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -8,6 +8,10 @@ import {
8
8
  useSensor,
9
9
  useSensors,
10
10
  } from '@dnd-kit/core';
11
+ import { markdownTable } from 'markdown-table';
12
+
13
+ import { mkConfig, generateCsv, download } from 'export-to-csv';
14
+
11
15
  import { restrictToHorizontalAxis } from '@dnd-kit/modifiers';
12
16
  import {
13
17
  arrayMove,
@@ -77,6 +81,7 @@ import { ViewSettings } from './view-settings';
77
81
  import { isObject } from 'lodash';
78
82
  import { EditNamespaceDialog } from './edit-namespace-dialog';
79
83
  import { EditRowDialog } from './edit-row-dialog';
84
+ import copy from 'copy-to-clipboard';
80
85
 
81
86
  const fallbackItems: any[] = [];
82
87
 
@@ -88,6 +93,147 @@ export type TableColMeta = {
88
93
  copyable?: boolean;
89
94
  };
90
95
 
96
+ function exportToCSV(
97
+ rows: any[],
98
+ columns: ColumnDef<any>[],
99
+ namespace: string,
100
+ downloadFile: boolean = false,
101
+ ) {
102
+ if (rows.length === 0) return;
103
+
104
+ const visibleColumns = columns.filter(
105
+ (col) =>
106
+ col.id !== 'select-col' &&
107
+ col.header !== undefined &&
108
+ !(col.meta as TableColMeta | undefined)?.isLink,
109
+ );
110
+
111
+ const data = rows.map((row) => {
112
+ const rowData: Record<string, any> = {};
113
+ visibleColumns.forEach((col: any) => {
114
+ const value = row[col.header];
115
+ // Handle different data types
116
+ if (value === null || value === undefined) {
117
+ rowData[col.header] = '';
118
+ } else if (typeof value === 'object') {
119
+ rowData[col.header] = JSON.stringify(value);
120
+ } else {
121
+ rowData[col.header] = value;
122
+ }
123
+ });
124
+ return rowData;
125
+ });
126
+
127
+ const csvConfig = mkConfig({
128
+ fieldSeparator: ',',
129
+ filename: `${namespace}_export`,
130
+ decimalSeparator: '.',
131
+ useKeysAsHeaders: true,
132
+ });
133
+
134
+ const csv = generateCsv(csvConfig)(data);
135
+
136
+ if (downloadFile) {
137
+ download(csvConfig)(csv);
138
+ successToast('CSV file downloaded');
139
+ } else {
140
+ copy(csv.toString());
141
+ successToast('CSV copied to clipboard');
142
+ }
143
+ }
144
+
145
+ function exportToMarkdown(
146
+ rows: any[],
147
+ columns: any[],
148
+ namespace: string,
149
+ downloadFile: boolean = false,
150
+ ) {
151
+ if (rows.length === 0) return;
152
+
153
+ const visibleColumns = columns.filter(
154
+ (col) =>
155
+ col.id !== 'select-col' &&
156
+ col.header !== undefined &&
157
+ !(col.meta as TableColMeta | undefined)?.isLink,
158
+ );
159
+
160
+ const headers = visibleColumns.map((col: any) => col.header as string);
161
+
162
+ const data = rows.map((row) => {
163
+ return visibleColumns.map((col: any) => {
164
+ const value = row[col.header];
165
+ if (value === null || value === undefined) {
166
+ return ' ';
167
+ } else if (typeof value === 'object') {
168
+ return JSON.stringify(value);
169
+ } else {
170
+ return String(value);
171
+ }
172
+ });
173
+ });
174
+
175
+ const markdown = markdownTable([headers, ...data]);
176
+
177
+ if (downloadFile) {
178
+ const blob = new Blob([markdown], { type: 'text/markdown' });
179
+ const url = URL.createObjectURL(blob);
180
+ const a = document.createElement('a');
181
+ a.href = url;
182
+ a.download = `${namespace}_export.md`;
183
+ document.body.appendChild(a);
184
+ a.click();
185
+ document.body.removeChild(a);
186
+ URL.revokeObjectURL(url);
187
+ successToast('Markdown file downloaded');
188
+ } else {
189
+ copy(markdown);
190
+ successToast('Markdown copied to clipboard');
191
+ }
192
+ }
193
+
194
+ function exportToJSON(
195
+ rows: any[],
196
+ columns: any[],
197
+ namespace: string,
198
+ downloadFile: boolean = false,
199
+ ) {
200
+ if (rows.length === 0) return;
201
+
202
+ const visibleColumns = columns.filter(
203
+ (col) =>
204
+ col.id !== 'select-col' &&
205
+ col.header !== undefined &&
206
+ !(col.meta as TableColMeta | undefined)?.isLink,
207
+ );
208
+
209
+ const data = rows.map((row) => {
210
+ const rowData: Record<string, any> = {};
211
+ visibleColumns.forEach((col: any) => {
212
+ const value = row[col.header];
213
+ rowData[col.header] = value;
214
+ });
215
+ return rowData;
216
+ });
217
+
218
+ const json = JSON.stringify(data, null, 2);
219
+
220
+ if (downloadFile) {
221
+ const blob = new Blob([json], { type: 'application/json' });
222
+ const url = URL.createObjectURL(blob);
223
+ const a = document.createElement('a');
224
+ a.href = url;
225
+ a.download = `${namespace}_export.json`;
226
+ document.body.appendChild(a);
227
+ a.click();
228
+ document.body.removeChild(a);
229
+ URL.revokeObjectURL(url);
230
+ successToast('JSON file downloaded');
231
+ } else {
232
+ copy(json);
233
+ successToast('JSON copied to clipboard');
234
+ }
235
+ }
236
+
91
237
  export const InnerExplorer: React.FC<{
92
238
  db: InstantReactAbstractDatabase<any, any>;
93
239
  namespaces: SchemaNamespace[];
@@ -1086,12 +1232,12 @@ export const InnerExplorer: React.FC<{
1086
1232
  allItems,
1087
1233
  checkedIds,
1088
1234
  );
1089
- // exportToCSV(
1090
- // selectedRows,
1091
- // columns,
1092
- // selectedNamespace.name,
1093
- // isShiftPressed,
1094
- // );
1235
+ exportToCSV(
1236
+ selectedRows,
1237
+ columns,
1238
+ selectedNamespace.name,
1239
+ isShiftPressed,
1240
+ );
1095
1241
  setDropdownOpen(false);
1096
1242
  }}
1097
1243
  className="flex items-center gap-2"
@@ -1106,12 +1252,12 @@ export const InnerExplorer: React.FC<{
1106
1252
  allItems,
1107
1253
  checkedIds,
1108
1254
  );
1109
- // exportToMarkdown(
1110
- // selectedRows,
1111
- // columns,
1112
- // selectedNamespace.name,
1113
- // isShiftPressed,
1114
- // );
1255
+ exportToMarkdown(
1256
+ selectedRows,
1257
+ columns,
1258
+ selectedNamespace.name,
1259
+ isShiftPressed,
1260
+ );
1115
1261
  setDropdownOpen(false);
1116
1262
  }}
1117
1263
  className="flex items-center gap-2"
@@ -1128,12 +1274,12 @@ export const InnerExplorer: React.FC<{
1128
1274
  allItems,
1129
1275
  checkedIds,
1130
1276
  );
1131
- // exportToJSON(
1132
- // selectedRows,
1133
- // columns,
1134
- // selectedNamespace.name,
1135
- // isShiftPressed,
1136
- // );
1277
+ exportToJSON(
1278
+ selectedRows,
1279
+ columns,
1280
+ selectedNamespace.name,
1281
+ isShiftPressed,
1282
+ );
1137
1283
  setDropdownOpen(false);
1138
1284
  }}
1139
1285
  className="flex items-center gap-2"