@kronor/dtv 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 (97) hide show
  1. package/.editorconfig +12 -0
  2. package/.github/copilot-instructions.md +64 -0
  3. package/.github/workflows/ci.yml +51 -0
  4. package/.husky/pre-commit +8 -0
  5. package/README.md +63 -0
  6. package/docs/api/README.md +32 -0
  7. package/docs/api/cell-renderers.md +121 -0
  8. package/docs/api/no-rows-component.md +71 -0
  9. package/docs/api/runtime.md +78 -0
  10. package/e2e/app.spec.ts +6 -0
  11. package/e2e/cell-renderer-setfilterstate.spec.ts +63 -0
  12. package/e2e/filter-sharing.spec.ts +113 -0
  13. package/e2e/filter-url-persistence.spec.ts +36 -0
  14. package/e2e/graphqlMock.ts +144 -0
  15. package/e2e/multi-field-filters.spec.ts +95 -0
  16. package/e2e/pagination.spec.ts +38 -0
  17. package/e2e/payment-request-email-filter.spec.ts +67 -0
  18. package/e2e/save-filter-splitbutton.spec.ts +68 -0
  19. package/e2e/simple-view-email-filter.spec.ts +67 -0
  20. package/e2e/simple-view-transforms.spec.ts +171 -0
  21. package/e2e/simple-view.spec.ts +104 -0
  22. package/e2e/transform-regression.spec.ts +108 -0
  23. package/eslint.config.js +30 -0
  24. package/index.html +17 -0
  25. package/jest.config.js +10 -0
  26. package/package.json +45 -0
  27. package/playwright.config.ts +54 -0
  28. package/public/vite.svg +1 -0
  29. package/src/App.externalRuntime.test.ts +190 -0
  30. package/src/App.tsx +540 -0
  31. package/src/assets/react.svg +1 -0
  32. package/src/components/AIAssistantForm.tsx +241 -0
  33. package/src/components/FilterForm.test.ts +82 -0
  34. package/src/components/FilterForm.tsx +375 -0
  35. package/src/components/PhoneNumberFilter.tsx +102 -0
  36. package/src/components/SavedFilterList.tsx +181 -0
  37. package/src/components/SpeechInput.tsx +67 -0
  38. package/src/components/Table.tsx +119 -0
  39. package/src/components/TablePagination.tsx +40 -0
  40. package/src/components/aiAssistant.test.ts +270 -0
  41. package/src/components/aiAssistant.ts +291 -0
  42. package/src/framework/cell-renderer-components/CurrencyAmount.tsx +30 -0
  43. package/src/framework/cell-renderer-components/LayoutHelpers.tsx +74 -0
  44. package/src/framework/cell-renderer-components/Link.tsx +28 -0
  45. package/src/framework/cell-renderer-components/Mapping.tsx +11 -0
  46. package/src/framework/cell-renderer-components.test.ts +353 -0
  47. package/src/framework/column-definition.tsx +85 -0
  48. package/src/framework/currency.test.ts +46 -0
  49. package/src/framework/currency.ts +62 -0
  50. package/src/framework/data.staticConditions.test.ts +46 -0
  51. package/src/framework/data.test.ts +167 -0
  52. package/src/framework/data.ts +162 -0
  53. package/src/framework/filter-form-state.test.ts +189 -0
  54. package/src/framework/filter-form-state.ts +185 -0
  55. package/src/framework/filter-sharing.test.ts +135 -0
  56. package/src/framework/filter-sharing.ts +118 -0
  57. package/src/framework/filters.ts +194 -0
  58. package/src/framework/graphql.buildHasuraConditions.test.ts +473 -0
  59. package/src/framework/graphql.paginationKey.test.ts +29 -0
  60. package/src/framework/graphql.test.ts +286 -0
  61. package/src/framework/graphql.ts +462 -0
  62. package/src/framework/native-runtime/index.tsx +33 -0
  63. package/src/framework/native-runtime/nativeComponents.test.ts +108 -0
  64. package/src/framework/runtime-reference.test.ts +172 -0
  65. package/src/framework/runtime.ts +15 -0
  66. package/src/framework/saved-filters.test.ts +422 -0
  67. package/src/framework/saved-filters.ts +293 -0
  68. package/src/framework/state.test.ts +86 -0
  69. package/src/framework/state.ts +148 -0
  70. package/src/framework/transform.test.ts +51 -0
  71. package/src/framework/view-parser-initialvalues.test.ts +228 -0
  72. package/src/framework/view-parser.ts +714 -0
  73. package/src/framework/view.test.ts +1805 -0
  74. package/src/framework/view.ts +38 -0
  75. package/src/index.css +6 -0
  76. package/src/main.tsx +99 -0
  77. package/src/views/index.ts +12 -0
  78. package/src/views/payment-requests/components/NoRowsExtendDateRange.tsx +37 -0
  79. package/src/views/payment-requests/components/PaymentMethod.tsx +184 -0
  80. package/src/views/payment-requests/components/PaymentStatusTag.tsx +61 -0
  81. package/src/views/payment-requests/index.ts +1 -0
  82. package/src/views/payment-requests/runtime.tsx +145 -0
  83. package/src/views/payment-requests/view.json +692 -0
  84. package/src/views/payment-requests-initial-values.test.ts +73 -0
  85. package/src/views/request-log/index.ts +2 -0
  86. package/src/views/request-log/runtime.tsx +47 -0
  87. package/src/views/request-log/view.json +123 -0
  88. package/src/views/simple-test-view/index.ts +3 -0
  89. package/src/views/simple-test-view/runtime.tsx +85 -0
  90. package/src/views/simple-test-view/view.json +191 -0
  91. package/src/vite-env.d.ts +1 -0
  92. package/tailwind.config.js +7 -0
  93. package/tsconfig.app.json +26 -0
  94. package/tsconfig.jest.json +6 -0
  95. package/tsconfig.json +7 -0
  96. package/tsconfig.node.json +24 -0
  97. package/vite.config.ts +11 -0
@@ -0,0 +1,73 @@
1
+ import { parseInitialValue } from '../framework/view-parser';
2
+
3
+ describe('Payment Requests Date Range Initial Values', () => {
4
+ // Mock runtime with initial values similar to payment requests
5
+ const mockRuntime = {
6
+ cellRenderers: {},
7
+ queryTransforms: {},
8
+ noRowsComponents: {},
9
+ customFilterComponents: {},
10
+ initialValues: {
11
+ dateRangeStart: (() => {
12
+ const date = new Date();
13
+ date.setMonth(date.getMonth() - 1);
14
+ return date; // Return Date object for calendar component
15
+ })(),
16
+ dateRangeEnd: (() => {
17
+ const date = new Date();
18
+ return date; // Return Date object for calendar component
19
+ })()
20
+ }
21
+ };
22
+
23
+ it('should resolve date range start initial value correctly', () => {
24
+ const startRef = {
25
+ section: 'initialValues',
26
+ key: 'dateRangeStart'
27
+ };
28
+
29
+ const resolvedValue = parseInitialValue(startRef, mockRuntime);
30
+ expect(resolvedValue).toBeInstanceOf(Date); // Should be a Date object
31
+
32
+ // Calculate expected date (one month back)
33
+ const expectedDate = new Date();
34
+ expectedDate.setMonth(expectedDate.getMonth() - 1);
35
+
36
+ // Compare dates by converting to same day start (ignoring milliseconds)
37
+ expect(resolvedValue.toDateString()).toBe(expectedDate.toDateString());
38
+ }); it('should resolve date range end initial value correctly', () => {
39
+ const endRef = {
40
+ section: 'initialValues',
41
+ key: 'dateRangeEnd'
42
+ };
43
+
44
+ const resolvedValue = parseInitialValue(endRef, mockRuntime);
45
+ expect(resolvedValue).toBeInstanceOf(Date); // Should be a Date object
46
+
47
+ // Should be today's date
48
+ const today = new Date();
49
+ expect(resolvedValue.toDateString()).toBe(today.toDateString());
50
+ });
51
+
52
+ it('should have start date earlier than end date', () => {
53
+ const startRef = { section: 'initialValues', key: 'dateRangeStart' };
54
+ const endRef = { section: 'initialValues', key: 'dateRangeEnd' };
55
+
56
+ const startDate = parseInitialValue(startRef, mockRuntime);
57
+ const endDate = parseInitialValue(endRef, mockRuntime);
58
+
59
+ expect(startDate.getTime()).toBeLessThan(endDate.getTime());
60
+ });
61
+
62
+ it('should have approximately one month difference', () => {
63
+ const startRef = { section: 'initialValues', key: 'dateRangeStart' };
64
+ const endRef = { section: 'initialValues', key: 'dateRangeEnd' };
65
+
66
+ const startDate = parseInitialValue(startRef, mockRuntime);
67
+ const endDate = parseInitialValue(endRef, mockRuntime);
68
+
69
+ const diffInDays = Math.ceil((endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24));
70
+ expect(diffInDays).toBeGreaterThan(27); // At least 27 days (shortest month minus a few days)
71
+ expect(diffInDays).toBeLessThanOrEqual(32); // At most 32 days (longest month plus a day)
72
+ });
73
+ });
@@ -0,0 +1,2 @@
1
+ export { requestLogViewRuntime } from "./runtime";
2
+ export { default as view } from "./view.json";
@@ -0,0 +1,47 @@
1
+ import { CellRenderer } from "../../framework/column-definition";
2
+ import { DateTime, FlexRow } from "../../framework/cell-renderer-components/LayoutHelpers";
3
+ import { Runtime } from "../../framework/runtime";
4
+
5
+ // Merchant cell renderer
6
+ const merchantCellRenderer: CellRenderer = ({ data: { merchantId } }) =>
7
+ (({ 1: 'Boozt', 2: 'Boozt Dev' } as any)[merchantId]);
8
+
9
+ // Date cell renderer
10
+ const dateCellRenderer: CellRenderer = ({ data: { createdAt } }) =>
11
+ <DateTime date={createdAt} options={{ dateStyle: "long", timeStyle: "medium" }} />;
12
+
13
+ // Idempotency key cell renderer
14
+ const idempotencyKeyCellRenderer: CellRenderer = ({ data: { idempotencyKey } }) =>
15
+ <div className="tw:whitespace-pre-wrap">{idempotencyKey}</div>;
16
+
17
+ // Namespace cell renderer
18
+ const namespaceCellRenderer: CellRenderer = ({ data: { namespace } }) =>
19
+ <div className="tw:whitespace-pre-wrap">{namespace}</div>;
20
+
21
+ // JSON cell renderer for request params
22
+ const jsonCellRenderer: CellRenderer = ({ data: { requestParams } }) =>
23
+ <FlexRow align="center" justify="start">
24
+ <pre className="tw:text-left">{JSON.stringify(requestParams, null, 2)}</pre>
25
+ </FlexRow>;
26
+
27
+ // JSON response cell renderer
28
+ const jsonResponseCellRenderer: CellRenderer = ({ data: { responseBody } }) =>
29
+ <FlexRow align="center" justify="start">
30
+ <pre>{JSON.stringify(responseBody, null, 2)}</pre>
31
+ </FlexRow>;
32
+
33
+ // Runtime configuration for request log view
34
+ export const requestLogViewRuntime: Runtime = {
35
+ cellRenderers: {
36
+ merchantCellRenderer,
37
+ dateCellRenderer,
38
+ idempotencyKeyCellRenderer,
39
+ namespaceCellRenderer,
40
+ jsonCellRenderer,
41
+ jsonResponseCellRenderer
42
+ },
43
+ queryTransforms: {},
44
+ noRowsComponents: {},
45
+ customFilterComponents: {},
46
+ initialValues: {}
47
+ };
@@ -0,0 +1,123 @@
1
+ {
2
+ "title": "Request Logs",
3
+ "id": "request-logs",
4
+ "collectionName": "requestsLog",
5
+ "paginationKey": "createdAt",
6
+ "boolExpType": "RequestLogBoolExp",
7
+ "orderByType": "[RequestLogOrderBy!]",
8
+ "columns": [
9
+ {
10
+ "data": [
11
+ {
12
+ "type": "field",
13
+ "path": "merchantId"
14
+ }
15
+ ],
16
+ "name": "Merchant",
17
+ "cellRenderer": {
18
+ "section": "cellRenderers",
19
+ "key": "merchant"
20
+ }
21
+ },
22
+ {
23
+ "data": [
24
+ {
25
+ "type": "field",
26
+ "path": "createdAt"
27
+ }
28
+ ],
29
+ "name": "Date",
30
+ "cellRenderer": {
31
+ "section": "cellRenderers",
32
+ "key": "placedAt"
33
+ }
34
+ },
35
+ {
36
+ "data": [
37
+ {
38
+ "type": "field",
39
+ "path": "idempotencyKey"
40
+ }
41
+ ],
42
+ "name": "Idempotency Key",
43
+ "cellRenderer": {
44
+ "section": "cellRenderers",
45
+ "key": "text"
46
+ }
47
+ },
48
+ {
49
+ "data": [
50
+ {
51
+ "type": "field",
52
+ "path": "namespace"
53
+ }
54
+ ],
55
+ "name": "Namespace",
56
+ "cellRenderer": {
57
+ "section": "cellRenderers",
58
+ "key": "text"
59
+ }
60
+ },
61
+ {
62
+ "data": [
63
+ {
64
+ "type": "field",
65
+ "path": "requestParams"
66
+ }
67
+ ],
68
+ "name": "Request",
69
+ "cellRenderer": {
70
+ "section": "cellRenderers",
71
+ "key": "json"
72
+ }
73
+ },
74
+ {
75
+ "data": [
76
+ {
77
+ "type": "field",
78
+ "path": "responseBody"
79
+ }
80
+ ],
81
+ "name": "Response",
82
+ "cellRenderer": {
83
+ "section": "cellRenderers",
84
+ "key": "json"
85
+ }
86
+ }
87
+ ],
88
+ "filterSchema": {
89
+ "groups": [
90
+ {
91
+ "name": "default",
92
+ "label": "Default Filters"
93
+ }
94
+ ],
95
+ "filters": [
96
+ {
97
+ "id": "date-range",
98
+ "label": "Date",
99
+ "expression": {
100
+ "type": "and",
101
+ "filters": [
102
+ {
103
+ "type": "greaterThanOrEqual",
104
+ "field": "createdAt",
105
+ "value": {
106
+ "type": "date"
107
+ }
108
+ },
109
+ {
110
+ "type": "lessThanOrEqual",
111
+ "field": "createdAt",
112
+ "value": {
113
+ "type": "date"
114
+ }
115
+ }
116
+ ]
117
+ },
118
+ "group": "default",
119
+ "aiGenerated": false
120
+ }
121
+ ]
122
+ }
123
+ }
@@ -0,0 +1,3 @@
1
+ export { simpleTestViewRuntime } from "./runtime";
2
+ export { default as view } from "./view.json";
3
+ export type { SimpleTestData } from "./runtime";
@@ -0,0 +1,85 @@
1
+ import { CellRenderer } from "../../framework/column-definition";
2
+ import { PhoneNumberFilter } from "../../components/PhoneNumberFilter";
3
+ import { Runtime } from "../../framework/runtime";
4
+
5
+ // Define a simple data type for this view
6
+ export type SimpleTestData = {
7
+ id: number;
8
+ testField: string;
9
+ amount: number;
10
+ email: string;
11
+ phone?: string;
12
+ };
13
+
14
+ // Email cell renderer that allows filtering by email
15
+ const emailCellRenderer: CellRenderer = ({ data, updateFilterById, applyFilters }) => {
16
+ const handleEmailClick = () => {
17
+ updateFilterById('email-eq', (currentFilter: any) => {
18
+ return { ...currentFilter, value: data.email };
19
+ });
20
+ applyFilters();
21
+ };
22
+
23
+ return (
24
+ <button
25
+ className="tw:text-blue-500 tw:underline hover:tw:text-blue-700 tw:cursor-pointer"
26
+ onClick={handleEmailClick}
27
+ title={`Filter by email: ${data.email}`}
28
+ >
29
+ {data.email}
30
+ </button>
31
+ );
32
+ };
33
+
34
+ // Amount cell renderer that demonstrates using the Badge component and FlexRow layout
35
+ const amountCellRenderer: CellRenderer = ({ data, components, createElement }) => {
36
+ const { Badge, FlexRow } = components;
37
+ const amount = data.amount;
38
+
39
+ // Determine severity based on amount value
40
+ const getSeverity = (amount: number) => {
41
+ if (amount > 250) return 'success';
42
+ if (amount > 200) return 'warning';
43
+ return 'danger';
44
+ };
45
+
46
+ return createElement(FlexRow, {
47
+ align: 'center',
48
+ gap: 'gap-2',
49
+ children: [
50
+ createElement(Badge, {
51
+ value: `$${amount}`,
52
+ severity: getSeverity(amount),
53
+ style: { fontSize: '.8rem', padding: '0.3em 1em' }
54
+ }),
55
+ amount > 200 ? '🔥' : '💰'
56
+ ]
57
+ });
58
+ };
59
+
60
+ // Runtime configuration for simple test view
61
+ export const simpleTestViewRuntime: Runtime = {
62
+ cellRenderers: {
63
+ emailCellRenderer,
64
+ amountCellRenderer
65
+ },
66
+ queryTransforms: {
67
+ amountOffset: {
68
+ toQuery: (input: number) => ({ value: input + 5 })
69
+ },
70
+ keyValueTransform: {
71
+ toQuery: (input: any) => {
72
+ // Handle empty or null input
73
+ if (!input || input === '') {
74
+ return { value: input }; // Return object with original value for empty input
75
+ }
76
+ return { field: "transformedField", value: `prefix_${input}` };
77
+ }
78
+ }
79
+ },
80
+ noRowsComponents: {},
81
+ customFilterComponents: {
82
+ PhoneNumberFilter
83
+ },
84
+ initialValues: {}
85
+ };
@@ -0,0 +1,191 @@
1
+ {
2
+ "title": "Simple Test View",
3
+ "id": "simple-test-view",
4
+ "collectionName": "simpleTestDataCollection",
5
+ "paginationKey": "id",
6
+ "boolExpType": "SimpleTestBoolExp",
7
+ "orderByType": "[SimpleTestOrderBy!]",
8
+ "columns": [
9
+ {
10
+ "data": [
11
+ {
12
+ "type": "field",
13
+ "path": "testField"
14
+ }
15
+ ],
16
+ "name": "Test Column Header",
17
+ "cellRenderer": {
18
+ "section": "cellRenderers",
19
+ "key": "text"
20
+ }
21
+ },
22
+ {
23
+ "data": [
24
+ {
25
+ "type": "field",
26
+ "path": "amount"
27
+ }
28
+ ],
29
+ "name": "Amount",
30
+ "cellRenderer": {
31
+ "section": "cellRenderers",
32
+ "key": "amountCellRenderer"
33
+ }
34
+ },
35
+ {
36
+ "data": [
37
+ {
38
+ "type": "field",
39
+ "path": "email"
40
+ }
41
+ ],
42
+ "name": "Email",
43
+ "cellRenderer": {
44
+ "section": "cellRenderers",
45
+ "key": "emailCellRenderer"
46
+ }
47
+ },
48
+ {
49
+ "data": [
50
+ {
51
+ "type": "field",
52
+ "path": "phone"
53
+ }
54
+ ],
55
+ "name": "Phone",
56
+ "cellRenderer": {
57
+ "section": "cellRenderers",
58
+ "key": "text"
59
+ }
60
+ }
61
+ ],
62
+ "filterSchema": {
63
+ "groups": [
64
+ {
65
+ "name": "default",
66
+ "label": "Default Filters"
67
+ },
68
+ {
69
+ "name": "extra",
70
+ "label": "Extra Filters"
71
+ }
72
+ ],
73
+ "filters": [
74
+ {
75
+ "id": "amount-gte",
76
+ "label": "Amount",
77
+ "expression": {
78
+ "type": "greaterThanOrEqual",
79
+ "field": "amount",
80
+ "value": {
81
+ "type": "number"
82
+ },
83
+ "transform": {
84
+ "section": "queryTransforms",
85
+ "key": "amountOffset"
86
+ }
87
+ },
88
+ "group": "default",
89
+ "aiGenerated": false
90
+ },
91
+ {
92
+ "id": "test-field-eq",
93
+ "label": "Test Field",
94
+ "expression": {
95
+ "type": "equals",
96
+ "field": "testField",
97
+ "value": {
98
+ "type": "text"
99
+ }
100
+ },
101
+ "group": "extra",
102
+ "aiGenerated": false
103
+ },
104
+ {
105
+ "id": "email-eq",
106
+ "label": "Email",
107
+ "expression": {
108
+ "type": "equals",
109
+ "field": "email",
110
+ "value": {
111
+ "type": "text"
112
+ }
113
+ },
114
+ "group": "default",
115
+ "aiGenerated": false
116
+ },
117
+ {
118
+ "id": "phone-eq",
119
+ "label": "Phone",
120
+ "expression": {
121
+ "type": "equals",
122
+ "field": "phone",
123
+ "value": {
124
+ "type": "custom",
125
+ "component": {
126
+ "section": "customFilterComponents",
127
+ "key": "PhoneNumberFilter"
128
+ }
129
+ }
130
+ },
131
+ "group": "extra",
132
+ "aiGenerated": false
133
+ },
134
+ {
135
+ "id": "test-field-kv-transform",
136
+ "label": "Test Field (Key-Value Transform)",
137
+ "expression": {
138
+ "type": "equals",
139
+ "field": "testField",
140
+ "value": {
141
+ "type": "text"
142
+ },
143
+ "transform": {
144
+ "section": "queryTransforms",
145
+ "key": "keyValueTransform"
146
+ }
147
+ },
148
+ "group": "extra",
149
+ "aiGenerated": false
150
+ },
151
+ {
152
+ "id": "search-multi-fields-or",
153
+ "label": "Search Multiple Fields (OR)",
154
+ "expression": {
155
+ "type": "iLike",
156
+ "field": {
157
+ "or": [
158
+ "testField",
159
+ "email"
160
+ ]
161
+ },
162
+ "value": {
163
+ "type": "text",
164
+ "placeholder": "Search in test field or email..."
165
+ }
166
+ },
167
+ "group": "default",
168
+ "aiGenerated": false
169
+ },
170
+ {
171
+ "id": "match-multi-fields-and",
172
+ "label": "Match Multiple Fields (AND)",
173
+ "expression": {
174
+ "type": "equals",
175
+ "field": {
176
+ "and": [
177
+ "testField",
178
+ "email"
179
+ ]
180
+ },
181
+ "value": {
182
+ "type": "text",
183
+ "placeholder": "Value that must match both fields..."
184
+ }
185
+ },
186
+ "group": "extra",
187
+ "aiGenerated": false
188
+ }
189
+ ]
190
+ }
191
+ }
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
3
+ theme: {
4
+ extend: {},
5
+ },
6
+ plugins: []
7
+ };
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
+ "target": "ES2020",
5
+ "useDefineForClassFields": true,
6
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
7
+ "module": "ESNext",
8
+ "skipLibCheck": true,
9
+
10
+ /* Bundler mode */
11
+ "moduleResolution": "bundler",
12
+ "allowImportingTsExtensions": true,
13
+ "isolatedModules": true,
14
+ "moduleDetection": "force",
15
+ "noEmit": true,
16
+ "jsx": "react-jsx",
17
+
18
+ /* Linting */
19
+ "strict": true,
20
+ "noUnusedLocals": true,
21
+ "noUnusedParameters": true,
22
+ "noFallthroughCasesInSwitch": true,
23
+ "noUncheckedSideEffectImports": true
24
+ },
25
+ "include": ["src"]
26
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "jsx": "react-jsx"
5
+ }
6
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ]
7
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "ES2022",
5
+ "lib": ["ES2023"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+
9
+ /* Bundler mode */
10
+ "moduleResolution": "bundler",
11
+ "allowImportingTsExtensions": true,
12
+ "isolatedModules": true,
13
+ "moduleDetection": "force",
14
+ "noEmit": true,
15
+
16
+ /* Linting */
17
+ "strict": true,
18
+ "noUnusedLocals": true,
19
+ "noUnusedParameters": true,
20
+ "noFallthroughCasesInSwitch": true,
21
+ "noUncheckedSideEffectImports": true
22
+ },
23
+ "include": ["vite.config.ts"]
24
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,11 @@
1
+ import react from '@vitejs/plugin-react';
2
+ import { defineConfig } from 'vite';
3
+ import tailwindcss from '@tailwindcss/vite'
4
+
5
+ export default defineConfig({
6
+ base: '/portal/static/assets/table-views',
7
+ plugins: [
8
+ react(),
9
+ tailwindcss(),
10
+ ],
11
+ });