@instantdb/components 0.0.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.
Files changed (128) hide show
  1. package/.env +2 -0
  2. package/.turbo/turbo-build.log +18 -0
  3. package/README.md +78 -0
  4. package/app/App.css +38 -0
  5. package/app/App.tsx +61 -0
  6. package/app/index.css +18 -0
  7. package/app/main.tsx +10 -0
  8. package/dist/components/StyleMe.d.ts +15 -0
  9. package/dist/components/StyleMe.d.ts.map +1 -0
  10. package/dist/components/error-boundary.d.ts +17 -0
  11. package/dist/components/error-boundary.d.ts.map +1 -0
  12. package/dist/components/explorer/edit-namespace-dialog.d.ts +14 -0
  13. package/dist/components/explorer/edit-namespace-dialog.d.ts.map +1 -0
  14. package/dist/components/explorer/edit-row-dialog.d.ts +10 -0
  15. package/dist/components/explorer/edit-row-dialog.d.ts.map +1 -0
  16. package/dist/components/explorer/expandable-deleted-attr.d.ts +15 -0
  17. package/dist/components/explorer/expandable-deleted-attr.d.ts.map +1 -0
  18. package/dist/components/explorer/explorer-layout.d.ts +8 -0
  19. package/dist/components/explorer/explorer-layout.d.ts.map +1 -0
  20. package/dist/components/explorer/index.d.ts +44 -0
  21. package/dist/components/explorer/index.d.ts.map +1 -0
  22. package/dist/components/explorer/inner-explorer.d.ts +16 -0
  23. package/dist/components/explorer/inner-explorer.d.ts.map +1 -0
  24. package/dist/components/explorer/new-namespace-dialog.d.ts +10 -0
  25. package/dist/components/explorer/new-namespace-dialog.d.ts.map +1 -0
  26. package/dist/components/explorer/query-inspector.d.ts +11 -0
  27. package/dist/components/explorer/query-inspector.d.ts.map +1 -0
  28. package/dist/components/explorer/recently-deleted.d.ts +36 -0
  29. package/dist/components/explorer/recently-deleted.d.ts.map +1 -0
  30. package/dist/components/explorer/search-input.d.ts +9 -0
  31. package/dist/components/explorer/search-input.d.ts.map +1 -0
  32. package/dist/components/explorer/table-components.d.ts +16 -0
  33. package/dist/components/explorer/table-components.d.ts.map +1 -0
  34. package/dist/components/explorer/view-settings.d.ts +10 -0
  35. package/dist/components/explorer/view-settings.d.ts.map +1 -0
  36. package/dist/components/rosePineDawnTheme.d.ts +13 -0
  37. package/dist/components/rosePineDawnTheme.d.ts.map +1 -0
  38. package/dist/components/select.d.ts +16 -0
  39. package/dist/components/select.d.ts.map +1 -0
  40. package/dist/components/toast.d.ts +4 -0
  41. package/dist/components/toast.d.ts.map +1 -0
  42. package/dist/components/ui.d.ts +336 -0
  43. package/dist/components/ui.d.ts.map +1 -0
  44. package/dist/config.d.ts +14 -0
  45. package/dist/config.d.ts.map +1 -0
  46. package/dist/hooks/explorer.d.ts +29 -0
  47. package/dist/hooks/explorer.d.ts.map +1 -0
  48. package/dist/hooks/useAttrNotes.d.ts +10 -0
  49. package/dist/hooks/useAttrNotes.d.ts.map +1 -0
  50. package/dist/hooks/useClickOutside.d.ts +3 -0
  51. package/dist/hooks/useClickOutside.d.ts.map +1 -0
  52. package/dist/hooks/useColumnVisibility.d.ts +12 -0
  53. package/dist/hooks/useColumnVisibility.d.ts.map +1 -0
  54. package/dist/hooks/useEditBlobConstraints.d.ts +32 -0
  55. package/dist/hooks/useEditBlobConstraints.d.ts.map +1 -0
  56. package/dist/hooks/useExplorerHistory.d.ts +1 -0
  57. package/dist/hooks/useExplorerHistory.d.ts.map +1 -0
  58. package/dist/hooks/useIsOverflow.d.ts +6 -0
  59. package/dist/hooks/useIsOverflow.d.ts.map +1 -0
  60. package/dist/hooks/useLocalStorage.d.ts +2 -0
  61. package/dist/hooks/useLocalStorage.d.ts.map +1 -0
  62. package/dist/hooks/useMonacoJSONSchema.d.ts +3 -0
  63. package/dist/hooks/useMonacoJSONSchema.d.ts.map +1 -0
  64. package/dist/hooks/useStableDB.d.ts +7 -0
  65. package/dist/hooks/useStableDB.d.ts.map +1 -0
  66. package/dist/index.cjs +15 -0
  67. package/dist/index.d.ts +7 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +9270 -0
  70. package/dist/schema.d.ts +5 -0
  71. package/dist/schema.d.ts.map +1 -0
  72. package/dist/style.css +1 -0
  73. package/dist/types.d.ts +241 -0
  74. package/dist/types.d.ts.map +1 -0
  75. package/dist/utils/format.d.ts +2 -0
  76. package/dist/utils/format.d.ts.map +1 -0
  77. package/dist/utils/indexingJobs.d.ts +24 -0
  78. package/dist/utils/indexingJobs.d.ts.map +1 -0
  79. package/dist/utils/parsePermsJSON.d.ts +11 -0
  80. package/dist/utils/parsePermsJSON.d.ts.map +1 -0
  81. package/dist/utils/renames.d.ts +3 -0
  82. package/dist/utils/renames.d.ts.map +1 -0
  83. package/dist/utils/tableWidthSize.d.ts +9 -0
  84. package/dist/utils/tableWidthSize.d.ts.map +1 -0
  85. package/index.html +13 -0
  86. package/package.json +109 -0
  87. package/src/components/StyleMe.tsx +97 -0
  88. package/src/components/error-boundary.tsx +76 -0
  89. package/src/components/explorer/edit-namespace-dialog.tsx +1886 -0
  90. package/src/components/explorer/edit-row-dialog.tsx +1151 -0
  91. package/src/components/explorer/expandable-deleted-attr.tsx +170 -0
  92. package/src/components/explorer/explorer-layout.tsx +156 -0
  93. package/src/components/explorer/index.tsx +217 -0
  94. package/src/components/explorer/inner-explorer.tsx +1341 -0
  95. package/src/components/explorer/new-namespace-dialog.tsx +54 -0
  96. package/src/components/explorer/query-inspector.tsx +394 -0
  97. package/src/components/explorer/recently-deleted.tsx +344 -0
  98. package/src/components/explorer/search-input.tsx +358 -0
  99. package/src/components/explorer/table-components.tsx +341 -0
  100. package/src/components/explorer/view-settings.tsx +75 -0
  101. package/src/components/rosePineDawnTheme.ts +45 -0
  102. package/src/components/select.tsx +198 -0
  103. package/src/components/toast.tsx +18 -0
  104. package/src/components/ui.tsx +1561 -0
  105. package/src/config.ts +61 -0
  106. package/src/hooks/explorer.tsx +125 -0
  107. package/src/hooks/useAttrNotes.ts +27 -0
  108. package/src/hooks/useClickOutside.ts +23 -0
  109. package/src/hooks/useColumnVisibility.ts +39 -0
  110. package/src/hooks/useEditBlobConstraints.ts +185 -0
  111. package/src/hooks/useExplorerHistory.ts +0 -0
  112. package/src/hooks/useIsOverflow.ts +24 -0
  113. package/src/hooks/useLocalStorage.ts +51 -0
  114. package/src/hooks/useMonacoJSONSchema.ts +41 -0
  115. package/src/hooks/useStableDB.ts +30 -0
  116. package/src/index.tsx +8 -0
  117. package/src/schema.ts +285 -0
  118. package/src/style.css +5 -0
  119. package/src/types.ts +359 -0
  120. package/src/utils/format.ts +13 -0
  121. package/src/utils/indexingJobs.ts +126 -0
  122. package/src/utils/parsePermsJSON.ts +35 -0
  123. package/src/utils/renames.ts +42 -0
  124. package/src/utils/tableWidthSize.ts +62 -0
  125. package/tailwind.config.cjs +42 -0
  126. package/tsconfig.json +22 -0
  127. package/vite-env.d.ts +1 -0
  128. package/vite.config.ts +49 -0
@@ -0,0 +1,126 @@
1
+ import useSWRSubscription from 'swr/subscription';
2
+ import { CheckedDataType, InstantIndexingJob } from '@lib/types';
3
+
4
+ export async function createJob(
5
+ {
6
+ appId,
7
+ attrId,
8
+ jobType,
9
+ checkedDataType,
10
+ apiURI,
11
+ }: {
12
+ appId: string;
13
+ attrId: string;
14
+ jobType: InstantIndexingJob['job_type'];
15
+ checkedDataType?: CheckedDataType | null | undefined;
16
+ apiURI: string;
17
+ },
18
+ token: string,
19
+ ): Promise<InstantIndexingJob> {
20
+ const res = await fetch(`${apiURI}/dash/apps/${appId}/indexing-jobs`, {
21
+ method: 'POST',
22
+ headers: {
23
+ authorization: `Bearer ${token}`,
24
+ 'content-type': 'application/json',
25
+ },
26
+ body: JSON.stringify({
27
+ 'app-id': appId,
28
+ 'attr-id': attrId,
29
+ 'job-type': jobType,
30
+ 'checked-data-type': checkedDataType,
31
+ }),
32
+ });
33
+
34
+ const json = await res.json();
35
+ return json.job;
36
+ }
37
+
38
+ export function jobFetchLoop(
39
+ appId: string,
40
+ jobId: string,
41
+ token: string,
42
+ apiURI: string,
43
+ ) {
44
+ let stopped = false;
45
+ let errored = false;
46
+ let waitMs = 20;
47
+ let lastBody: string | null = null;
48
+
49
+ const nextWaitMs = (body: string) => {
50
+ if (body !== lastBody) {
51
+ waitMs = 20;
52
+ lastBody = body;
53
+ return waitMs;
54
+ }
55
+ const ret = waitMs;
56
+ waitMs = Math.min(10000, waitMs * 2);
57
+ return ret;
58
+ };
59
+
60
+ const start = async (
61
+ cb: (data: InstantIndexingJob | null, error?: Error) => void,
62
+ ) => {
63
+ while (!stopped && !errored) {
64
+ try {
65
+ const res = await fetch(
66
+ `${apiURI}/dash/apps/${appId}/indexing-jobs/${jobId}`,
67
+ { headers: { authorization: `Bearer ${token}` } },
68
+ );
69
+ const body = await res.text();
70
+ const json = JSON.parse(body);
71
+ const job = json.job;
72
+ cb(job);
73
+ if (job.job_status !== 'processing' && job.job_status !== 'waiting') {
74
+ return job;
75
+ }
76
+ await new Promise((resolve) => setTimeout(resolve, nextWaitMs(body)));
77
+ } catch (e) {
78
+ console.error('Job polling error:', e);
79
+ errored = true;
80
+ cb(null, e as Error);
81
+ }
82
+ }
83
+ };
84
+
85
+ return {
86
+ start: async (
87
+ cb: (data: InstantIndexingJob | null, error?: Error) => void,
88
+ ): Promise<InstantIndexingJob> => {
89
+ return start(cb);
90
+ },
91
+ stop: () => {
92
+ stopped = true;
93
+ },
94
+ };
95
+ }
96
+
97
+ export function useJobSubscription({
98
+ appId,
99
+ jobId,
100
+ token,
101
+ apiURI,
102
+ }: {
103
+ appId: string;
104
+ jobId: string;
105
+ token: string;
106
+ apiURI: string;
107
+ }) {
108
+ const { data, error } = useSWRSubscription(
109
+ ['jobs', appId, jobId],
110
+ ([_, appId, jobId], { next }) => {
111
+ const fetchLoop = jobFetchLoop(appId, jobId, token, apiURI);
112
+ fetchLoop.start((data, error) => next(error, data));
113
+ return () => fetchLoop.stop();
114
+ },
115
+ );
116
+
117
+ return { data, error };
118
+ }
119
+
120
+ export function jobIsErrored(job: InstantIndexingJob) {
121
+ return job.job_status === 'errored';
122
+ }
123
+
124
+ export function jobIsCompleted(job: InstantIndexingJob) {
125
+ return job.job_status === 'completed' || job.job_status === 'errored';
126
+ }
@@ -0,0 +1,35 @@
1
+ import JsonParser from 'json5';
2
+
3
+ // parse string as json5, returning the object,
4
+ // boolean values will be converted to strings
5
+ // return a normal json string
6
+ export const parsePermsJSON = (text: string): Result<string> => {
7
+ const parseResult = doTry(() =>
8
+ JsonParser.parse(text, (_key, value) => {
9
+ if (value === true) {
10
+ return 'true';
11
+ } else if (value === false) {
12
+ return 'false';
13
+ } else {
14
+ return value;
15
+ }
16
+ }),
17
+ );
18
+ return parseResult;
19
+ };
20
+
21
+ export const doTry = <T>(fn: () => T): Result<T> => {
22
+ try {
23
+ const value = fn();
24
+ return { status: 'ok', value };
25
+ } catch (error) {
26
+ return { status: 'error', error: error as Error };
27
+ }
28
+ };
29
+
30
+ type Result<T> =
31
+ | { status: 'ok'; value: T }
32
+ | {
33
+ status: 'error';
34
+ error: Error;
35
+ };
@@ -0,0 +1,42 @@
1
+ import { SchemaNamespace } from '@lib/types';
2
+
3
+ export const createRenameNamespaceOps = (
4
+ newName: string,
5
+ namespace: SchemaNamespace,
6
+ namespaces: SchemaNamespace[],
7
+ ) => {
8
+ const currentName = namespace.name;
9
+ const ops: any[] = [];
10
+ namespace.attrs.forEach((attr) => {
11
+ ops.push([
12
+ 'update-attr',
13
+ {
14
+ id: attr.id,
15
+ 'forward-identity': [
16
+ attr.linkConfig.forward.id,
17
+ newName,
18
+ attr.linkConfig.forward.attr,
19
+ ],
20
+ },
21
+ ]);
22
+ });
23
+
24
+ namespaces.forEach((ns) => {
25
+ ns.attrs.forEach((attr) => {
26
+ if (attr.linkConfig.reverse?.namespace === currentName) {
27
+ ops.push([
28
+ 'update-attr',
29
+ {
30
+ id: attr.id,
31
+ 'reverse-identity': [
32
+ attr.linkConfig.reverse.id,
33
+ newName,
34
+ attr.linkConfig.reverse.attr,
35
+ ],
36
+ },
37
+ ]);
38
+ }
39
+ });
40
+ });
41
+ return ops;
42
+ };
@@ -0,0 +1,62 @@
1
+ /**
2
+ *
3
+ * @param columnId
4
+ * @param max set a maximum width to return
5
+ * @returns minimum width to display all column cells
6
+ * @throws Error if element with class ${columnId} not found
7
+ */
8
+ export const getTableWidthSize = (columnId: string, max: number): number => {
9
+ const header = document.querySelector(`.th-${columnId}`);
10
+ if (!header) {
11
+ throw new Error(`Element with class th-${columnId} not found`);
12
+ }
13
+
14
+ const tableCells = document.querySelectorAll(`span.td-${columnId}`);
15
+
16
+ // Create container for clones
17
+ const container = document.createElement('div');
18
+ container.style.position = 'absolute';
19
+ container.style.visibility = 'hidden';
20
+ container.style.top = '-9999px';
21
+ container.style.left = '-9999px';
22
+ container.style.width = 'auto';
23
+ container.style.whiteSpace = 'nowrap';
24
+
25
+ document.body.appendChild(container);
26
+
27
+ try {
28
+ // Clone and measure header
29
+ const headerClone = header.cloneNode(true) as HTMLElement;
30
+ headerClone.style.display = 'inline-block';
31
+ headerClone.style.overflow = 'visible';
32
+ headerClone.style.width = 'auto';
33
+ headerClone.style.maxWidth = 'none';
34
+ headerClone.style.whiteSpace = 'nowrap';
35
+ container.appendChild(headerClone);
36
+ const headerWidth = headerClone.scrollWidth;
37
+
38
+ // Clone and measure each cell
39
+ const cellWidths = Array.from(tableCells).map((cell) => {
40
+ const cellClone = cell.cloneNode(true) as HTMLElement;
41
+ cellClone.style.display = 'inline-block';
42
+ cellClone.style.overflow = 'visible';
43
+ cellClone.style.width = 'auto';
44
+ cellClone.style.maxWidth = 'none';
45
+ cellClone.style.whiteSpace = 'nowrap';
46
+ container.appendChild(cellClone);
47
+ const width = cellClone.scrollWidth;
48
+ container.removeChild(cellClone);
49
+ return width;
50
+ });
51
+
52
+ const maxCellWidth = cellWidths.length > 0 ? Math.max(...cellWidths) : 0;
53
+ const maxWidth = Math.max(headerWidth, maxCellWidth);
54
+
55
+ // Add padding
56
+ const finalWidth = maxWidth + 12;
57
+
58
+ return Math.min(finalWidth, max);
59
+ } finally {
60
+ document.body.removeChild(container);
61
+ }
62
+ };
@@ -0,0 +1,42 @@
1
+ // Tailwind v4 uses CSS-first configuration via style.css
2
+ // This config is kept for any remaining JS-based customizations
3
+
4
+ const sans = [
5
+ 'ui-sans-serif',
6
+ 'system-ui',
7
+ '-apple-system',
8
+ 'BlinkMacSystemFont',
9
+ 'Segoe UI',
10
+ 'Roboto',
11
+ 'Arial',
12
+ 'Noto Sans',
13
+ 'sans-serif',
14
+ 'Apple Color Emoji',
15
+ 'Segoe UI Emoji',
16
+ 'Segoe UI Symbol',
17
+ 'Noto Color Emoji',
18
+ ];
19
+
20
+ module.exports = {
21
+ darkMode: 'class',
22
+ content: ['./src/**/*.{js,ts,jsx,tsx}'],
23
+ plugins: [],
24
+ theme: {
25
+ fontFamily: {
26
+ sans: ['"IBM Plex Sans"', ...sans],
27
+ mono: [
28
+ 'Berk Mono',
29
+ 'ui-monospace',
30
+ 'SFMono-Regular',
31
+ 'Menlo',
32
+ 'Monaco',
33
+ 'Consolas',
34
+ 'Liberation Mono',
35
+ 'Courier New',
36
+ 'monospace',
37
+ ],
38
+ },
39
+ extend: {},
40
+ },
41
+ future: { hoverOnlyWhenSupported: true },
42
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "include": ["src"],
4
+ "exclude": ["node_modules", "dist"],
5
+ "compilerOptions": {
6
+ "strict": true,
7
+ "outDir": "dist/tsc",
8
+ "moduleResolution": "bundler",
9
+ "module": "ESNext",
10
+ "rootDirs": ["src", "app"],
11
+ "sourceMap": true,
12
+ "jsx": "react",
13
+ "checkJs": false,
14
+ "lib": ["dom", "dom.iterable", "esnext"],
15
+ "skipLibCheck": true,
16
+ "baseUrl": ".",
17
+ "paths": {
18
+ "@lib/*": ["./src/*"]
19
+ },
20
+ "strictNullChecks": true
21
+ }
22
+ }
package/vite-env.d.ts ADDED
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
package/vite.config.ts ADDED
@@ -0,0 +1,49 @@
1
+ import { defineConfig } from 'vite';
2
+ import tailwindcss from '@tailwindcss/vite';
3
+ import path from 'path';
4
+ import react from '@vitejs/plugin-react-swc';
5
+ import { resolve } from 'path';
6
+ import dts from 'unplugin-dts/vite';
7
+
8
+ import { peerDependencies, dependencies } from './package.json';
9
+
10
+ export default defineConfig({
11
+ clearScreen: false,
12
+ plugins: [react({}), tailwindcss({ optimize: true }), dts({})],
13
+ resolve: {
14
+ alias: {
15
+ '@lib': path.resolve(__dirname, 'src'),
16
+ },
17
+ },
18
+ build: {
19
+ outDir: 'dist',
20
+ target: 'esnext',
21
+ emptyOutDir: false,
22
+ cssCodeSplit: true,
23
+ lib: {
24
+ formats: ['es', 'cjs'],
25
+ entry: [
26
+ resolve(__dirname, 'src', 'index.tsx'),
27
+ resolve(__dirname, 'src', 'style.css'),
28
+ ],
29
+ fileName: 'index',
30
+ },
31
+ rollupOptions: {
32
+ external: (id) => {
33
+ // Bundle prism-react-renderer to avoid CJS/ESM interop issues
34
+ if (
35
+ id === 'prism-react-renderer' ||
36
+ id.startsWith('prism-react-renderer/')
37
+ ) {
38
+ return false;
39
+ }
40
+ // Check exact matches and subpath imports (e.g., react/jsx-runtime)
41
+ const allDeps = [
42
+ ...Object.keys(peerDependencies),
43
+ ...Object.keys(dependencies),
44
+ ];
45
+ return allDeps.some((dep) => id === dep || id.startsWith(dep + '/'));
46
+ },
47
+ },
48
+ },
49
+ });