@lad-sapienza/scms-core 0.1.0-alpha.0
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/LICENSE +14 -0
- package/README.md +73 -0
- package/components/BSNavbar.tsx +264 -0
- package/components/DataTb/DataTb.astro +33 -0
- package/components/DataTb/DataTb.tsx +340 -0
- package/components/DataTb/DataTbMdx.tsx +75 -0
- package/components/DataTb/README.md +275 -0
- package/components/DataTb/index.ts +36 -0
- package/components/DataTb/sources/ApiSource.tsx +89 -0
- package/components/DataTb/sources/CsvSource.tsx +69 -0
- package/components/DataTb/sources/DirectusSource.tsx +98 -0
- package/components/DataTb/sources/JsonSource.tsx +65 -0
- package/components/DataTb/sources/index.ts +17 -0
- package/components/DataTb/types.ts +215 -0
- package/components/DataTb/utils.ts +186 -0
- package/components/Gallery/Gallery.astro +65 -0
- package/components/Gallery/Gallery.tsx +136 -0
- package/components/Gallery/README.md +118 -0
- package/components/Gallery/__tests__/galleryUtils.test.ts +178 -0
- package/components/Gallery/galleryUtils.ts +186 -0
- package/components/Gallery/index.ts +7 -0
- package/components/Gallery/react-photoswipe-gallery.d.ts +26 -0
- package/components/Gallery/types.ts +46 -0
- package/components/Gallery/virtual-gallery.d.ts +15 -0
- package/components/Map/LayerControl.tsx +368 -0
- package/components/Map/Map.tsx +735 -0
- package/components/Map/MapMdx.tsx +37 -0
- package/components/Map/RasterLayerLibre.tsx +33 -0
- package/components/Map/Search/SearchOperators.ts +31 -0
- package/components/Map/Search/SearchUI.tsx +75 -0
- package/components/Map/Search/SearchUIAdvanced.tsx +289 -0
- package/components/Map/Search/SearchUISimple.tsx +115 -0
- package/components/Map/Search/index.ts +7 -0
- package/components/Map/defaultBasemaps.ts +88 -0
- package/components/Map/index.ts +6 -0
- package/components/Map/types.ts +179 -0
- package/components/Map/utils.ts +367 -0
- package/components/README.md +62 -0
- package/components/Record/Field.tsx +35 -0
- package/components/Record/Image.tsx +114 -0
- package/components/Record/RecordFetcher.tsx +127 -0
- package/components/Record/context.tsx +14 -0
- package/components/Record/index.ts +11 -0
- package/components/Record/useRecordFetcher.ts +104 -0
- package/components/Record/utils.ts +13 -0
- package/components/SEO/SEO.astro +132 -0
- package/components/TableOfContents/TableOfContents.astro +86 -0
- package/components/ZoteroGeoViewer/README.md +195 -0
- package/components/ZoteroGeoViewer/ZoteroGeoViewer.astro +26 -0
- package/components/ZoteroGeoViewer/ZoteroGeoViewer.tsx +483 -0
- package/components/ZoteroGeoViewer/ZoteroRecordsPreview.tsx +185 -0
- package/components/ZoteroGeoViewer/index.ts +16 -0
- package/components/ZoteroGeoViewer/types.ts +123 -0
- package/index.ts +26 -0
- package/integrations/__tests__/galleryIntegration.test.ts +70 -0
- package/integrations/contentAssetsIntegration.ts +132 -0
- package/integrations/directusLoader.ts +98 -0
- package/integrations/galleryIntegration.ts +78 -0
- package/package.json +56 -0
- package/scms.ts +95 -0
- package/utils/content.ts +88 -0
- package/utils/data-fetcher.ts +128 -0
- package/utils/directus-config.ts +160 -0
- package/utils/record-fetcher.ts +132 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataTb Component Exports
|
|
3
|
+
*
|
|
4
|
+
* Exports the MDX-safe wrapper by default for better compatibility
|
|
5
|
+
* with Astro MDX files
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { DataTb } from './DataTbMdx';
|
|
9
|
+
|
|
10
|
+
// Source components
|
|
11
|
+
export {
|
|
12
|
+
CsvSource,
|
|
13
|
+
JsonSource,
|
|
14
|
+
DirectusSource,
|
|
15
|
+
ApiSource,
|
|
16
|
+
} from './sources';
|
|
17
|
+
|
|
18
|
+
// Types
|
|
19
|
+
export type {
|
|
20
|
+
DataRow,
|
|
21
|
+
ColumnConfig,
|
|
22
|
+
PaginationConfig,
|
|
23
|
+
DataTbProps,
|
|
24
|
+
CsvSourceConfig,
|
|
25
|
+
JsonSourceConfig,
|
|
26
|
+
DirectusSourceConfig,
|
|
27
|
+
ApiSourceConfig,
|
|
28
|
+
SourceConfig,
|
|
29
|
+
} from './types';
|
|
30
|
+
|
|
31
|
+
export type {
|
|
32
|
+
CsvSourceProps,
|
|
33
|
+
JsonSourceProps,
|
|
34
|
+
DirectusSourceProps,
|
|
35
|
+
ApiSourceProps,
|
|
36
|
+
} from './sources';
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ApiSource Component
|
|
3
|
+
*
|
|
4
|
+
* Loads data from any API endpoint with custom transformation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { useEffect } from 'react';
|
|
8
|
+
import type { DataRow, SourceComponentProps } from '../types';
|
|
9
|
+
|
|
10
|
+
export interface ApiSourceProps extends SourceComponentProps {
|
|
11
|
+
/** API endpoint URL */
|
|
12
|
+
url: string;
|
|
13
|
+
|
|
14
|
+
/** HTTP method (default: GET) */
|
|
15
|
+
method?: 'GET' | 'POST';
|
|
16
|
+
|
|
17
|
+
/** Request headers */
|
|
18
|
+
headers?: Record<string, string>;
|
|
19
|
+
|
|
20
|
+
/** Request body (for POST) */
|
|
21
|
+
body?: any;
|
|
22
|
+
|
|
23
|
+
/** Transform response to data rows */
|
|
24
|
+
transformer?: (data: any) => DataRow[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function ApiSource({
|
|
28
|
+
url,
|
|
29
|
+
method = 'GET',
|
|
30
|
+
headers,
|
|
31
|
+
body,
|
|
32
|
+
transformer,
|
|
33
|
+
onDataLoad,
|
|
34
|
+
onLoadingChange,
|
|
35
|
+
onError,
|
|
36
|
+
}: ApiSourceProps) {
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
const loadApiData = async () => {
|
|
39
|
+
try {
|
|
40
|
+
onLoadingChange?.(true);
|
|
41
|
+
|
|
42
|
+
const options: RequestInit = {
|
|
43
|
+
method,
|
|
44
|
+
headers: {
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
...headers,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
if (body && method === 'POST') {
|
|
51
|
+
options.body = JSON.stringify(body);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const response = await fetch(url, options);
|
|
55
|
+
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const responseData = await response.json();
|
|
61
|
+
|
|
62
|
+
// Apply transformer if provided
|
|
63
|
+
let data: DataRow[];
|
|
64
|
+
if (transformer) {
|
|
65
|
+
data = transformer(responseData);
|
|
66
|
+
} else if (Array.isArray(responseData)) {
|
|
67
|
+
data = responseData;
|
|
68
|
+
} else if (responseData.data && Array.isArray(responseData.data)) {
|
|
69
|
+
// Common API pattern: { data: [...] }
|
|
70
|
+
data = responseData.data;
|
|
71
|
+
} else {
|
|
72
|
+
// Single object response
|
|
73
|
+
data = [responseData];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
onDataLoad(data);
|
|
77
|
+
onLoadingChange?.(false);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
onError?.(error instanceof Error ? error : new Error('Failed to load API data'));
|
|
80
|
+
onLoadingChange?.(false);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
loadApiData();
|
|
85
|
+
}, [url, method, JSON.stringify(headers), JSON.stringify(body)]);
|
|
86
|
+
|
|
87
|
+
// This component doesn't render anything
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CsvSource Component
|
|
3
|
+
*
|
|
4
|
+
* Loads data from CSV files (local or remote)
|
|
5
|
+
* Uses PapaParse for parsing
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useEffect } from 'react';
|
|
9
|
+
import Papa from 'papaparse';
|
|
10
|
+
import type { SourceComponentProps } from '../types';
|
|
11
|
+
|
|
12
|
+
export interface CsvSourceProps extends SourceComponentProps {
|
|
13
|
+
/** CSV file URL (local or remote) */
|
|
14
|
+
url: string;
|
|
15
|
+
|
|
16
|
+
/** Delimiter character (default: ',') */
|
|
17
|
+
delimiter?: string;
|
|
18
|
+
|
|
19
|
+
/** Skip first N rows */
|
|
20
|
+
skipRows?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function CsvSource({
|
|
24
|
+
url,
|
|
25
|
+
delimiter = ',',
|
|
26
|
+
skipRows = 0,
|
|
27
|
+
onDataLoad,
|
|
28
|
+
onLoadingChange,
|
|
29
|
+
onError,
|
|
30
|
+
}: CsvSourceProps) {
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const loadCsv = async () => {
|
|
33
|
+
try {
|
|
34
|
+
onLoadingChange?.(true);
|
|
35
|
+
|
|
36
|
+
Papa.parse(url, {
|
|
37
|
+
download: true,
|
|
38
|
+
header: true,
|
|
39
|
+
delimiter,
|
|
40
|
+
skipEmptyLines: true,
|
|
41
|
+
dynamicTyping: true, // Convert numbers and booleans
|
|
42
|
+
complete: (results) => {
|
|
43
|
+
let data = results.data;
|
|
44
|
+
|
|
45
|
+
// Skip rows if specified
|
|
46
|
+
if (skipRows > 0) {
|
|
47
|
+
data = data.slice(skipRows);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
onDataLoad(data as import('../types').DataRow[]);
|
|
51
|
+
onLoadingChange?.(false);
|
|
52
|
+
},
|
|
53
|
+
error: (error) => {
|
|
54
|
+
onError?.(new Error(`Failed to parse CSV: ${error.message}`));
|
|
55
|
+
onLoadingChange?.(false);
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
} catch (error) {
|
|
59
|
+
onError?.(error instanceof Error ? error : new Error('Failed to load CSV'));
|
|
60
|
+
onLoadingChange?.(false);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
loadCsv();
|
|
65
|
+
}, [url, delimiter, skipRows]);
|
|
66
|
+
|
|
67
|
+
// This component doesn't render anything
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DirectusSource Component
|
|
3
|
+
*
|
|
4
|
+
* Loads data from Directus collections using the Directus SDK
|
|
5
|
+
* Requires directusConfig in user.config.mjs
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useEffect } from 'react';
|
|
9
|
+
import { createDirectus, rest, staticToken, readItems } from '@directus/sdk';
|
|
10
|
+
import type { SourceComponentProps } from '../types';
|
|
11
|
+
|
|
12
|
+
export interface DirectusSourceProps extends SourceComponentProps {
|
|
13
|
+
/** Collection name */
|
|
14
|
+
collection: string;
|
|
15
|
+
|
|
16
|
+
/** Directus configuration */
|
|
17
|
+
config: {
|
|
18
|
+
url: string;
|
|
19
|
+
token: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** Filter query */
|
|
23
|
+
filter?: Record<string, any>;
|
|
24
|
+
|
|
25
|
+
/** Fields to select */
|
|
26
|
+
fields?: string[];
|
|
27
|
+
|
|
28
|
+
/** Sort order (e.g., ['-date_created', 'title']) */
|
|
29
|
+
sort?: string[];
|
|
30
|
+
|
|
31
|
+
/** Limit results */
|
|
32
|
+
limit?: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function DirectusSource({
|
|
36
|
+
collection,
|
|
37
|
+
config,
|
|
38
|
+
filter,
|
|
39
|
+
fields,
|
|
40
|
+
sort,
|
|
41
|
+
limit,
|
|
42
|
+
onDataLoad,
|
|
43
|
+
onLoadingChange,
|
|
44
|
+
onError,
|
|
45
|
+
}: DirectusSourceProps) {
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
const loadDirectusData = async () => {
|
|
48
|
+
try {
|
|
49
|
+
if (!config.url || !config.token) {
|
|
50
|
+
throw new Error('Directus configuration (url and token) is required');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
onLoadingChange?.(true);
|
|
54
|
+
|
|
55
|
+
// Create Directus client
|
|
56
|
+
const client = createDirectus(config.url)
|
|
57
|
+
.with(staticToken(config.token))
|
|
58
|
+
.with(rest());
|
|
59
|
+
|
|
60
|
+
// Build query options
|
|
61
|
+
const queryOptions: any = {};
|
|
62
|
+
|
|
63
|
+
if (filter) {
|
|
64
|
+
queryOptions.filter = filter;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (fields) {
|
|
68
|
+
queryOptions.fields = fields;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (sort) {
|
|
72
|
+
queryOptions.sort = sort;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (limit) {
|
|
76
|
+
queryOptions.limit = limit;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Fetch data
|
|
80
|
+
const items = await client.request(
|
|
81
|
+
readItems(collection, queryOptions)
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
onDataLoad(items as any[]);
|
|
85
|
+
onLoadingChange?.(false);
|
|
86
|
+
} catch (error) {
|
|
87
|
+
const message = error instanceof Error ? error.message : 'Failed to load Directus data';
|
|
88
|
+
onError?.(new Error(`Directus error: ${message}`));
|
|
89
|
+
onLoadingChange?.(false);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
loadDirectusData();
|
|
94
|
+
}, [collection, config.url, config.token, JSON.stringify(filter), JSON.stringify(fields), JSON.stringify(sort), limit]);
|
|
95
|
+
|
|
96
|
+
// This component doesn't render anything
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JsonSource Component
|
|
3
|
+
*
|
|
4
|
+
* Loads data from JSON (inline or remote)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { useEffect } from 'react';
|
|
8
|
+
import type { DataRow, SourceComponentProps } from '../types';
|
|
9
|
+
|
|
10
|
+
export interface JsonSourceProps extends SourceComponentProps {
|
|
11
|
+
/** Inline JSON data */
|
|
12
|
+
data?: DataRow[];
|
|
13
|
+
|
|
14
|
+
/** URL to fetch JSON from */
|
|
15
|
+
url?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function JsonSource({
|
|
19
|
+
data,
|
|
20
|
+
url,
|
|
21
|
+
onDataLoad,
|
|
22
|
+
onLoadingChange,
|
|
23
|
+
onError,
|
|
24
|
+
}: JsonSourceProps) {
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const loadJson = async () => {
|
|
27
|
+
try {
|
|
28
|
+
// Use inline data if provided
|
|
29
|
+
if (data) {
|
|
30
|
+
onDataLoad(data);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Fetch from URL
|
|
35
|
+
if (!url) {
|
|
36
|
+
onError?.(new Error('JsonSource requires either data or url prop'));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
onLoadingChange?.(true);
|
|
41
|
+
|
|
42
|
+
const response = await fetch(url);
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const jsonData = await response.json();
|
|
48
|
+
|
|
49
|
+
// Handle both array and object responses
|
|
50
|
+
const arrayData = Array.isArray(jsonData) ? jsonData : [jsonData];
|
|
51
|
+
|
|
52
|
+
onDataLoad(arrayData);
|
|
53
|
+
onLoadingChange?.(false);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
onError?.(error instanceof Error ? error : new Error('Failed to load JSON'));
|
|
56
|
+
onLoadingChange?.(false);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
loadJson();
|
|
61
|
+
}, [data, url]);
|
|
62
|
+
|
|
63
|
+
// This component doesn't render anything
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataTb Source Components
|
|
3
|
+
*
|
|
4
|
+
* Export all source components for easy importing
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { CsvSource } from './CsvSource';
|
|
8
|
+
export type { CsvSourceProps } from './CsvSource';
|
|
9
|
+
|
|
10
|
+
export { JsonSource } from './JsonSource';
|
|
11
|
+
export type { JsonSourceProps } from './JsonSource';
|
|
12
|
+
|
|
13
|
+
export { DirectusSource } from './DirectusSource';
|
|
14
|
+
export type { DirectusSourceProps } from './DirectusSource';
|
|
15
|
+
|
|
16
|
+
export { ApiSource } from './ApiSource';
|
|
17
|
+
export type { ApiSourceProps } from './ApiSource';
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataTb Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Core types for the DataTb component system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import type { DirectusShorthand, DirectusSourceConfig } from '../../utils/directus-config';
|
|
9
|
+
|
|
10
|
+
declare module '@tanstack/react-table' {
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
12
|
+
interface ColumnMeta<TData = unknown, TValue = unknown> {
|
|
13
|
+
/** Raw CSS width from ColumnConfig.width, applied directly to the <th>/<td> (any CSS length unit). */
|
|
14
|
+
width?: string;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Base data row type - can be extended with specific fields
|
|
20
|
+
*/
|
|
21
|
+
export type DataRow = Record<string, any>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Column configuration with optional formatting
|
|
25
|
+
*/
|
|
26
|
+
export interface ColumnConfig {
|
|
27
|
+
/** Column key matching data property */
|
|
28
|
+
key: string;
|
|
29
|
+
|
|
30
|
+
/** Display header text */
|
|
31
|
+
header: string;
|
|
32
|
+
|
|
33
|
+
/** Enable sorting for this column */
|
|
34
|
+
sortable?: boolean;
|
|
35
|
+
|
|
36
|
+
/** Format type for automatic formatting */
|
|
37
|
+
format?: 'date' | 'number' | 'currency' | 'percent';
|
|
38
|
+
|
|
39
|
+
/** Custom render function */
|
|
40
|
+
render?: (value: any, row: DataRow) => React.ReactNode;
|
|
41
|
+
|
|
42
|
+
/** Value mapping labels (e.g. { "true": "Yes", "false": "No" }) */
|
|
43
|
+
labels?: Record<string, string>;
|
|
44
|
+
|
|
45
|
+
/** Column width (CSS value) */
|
|
46
|
+
width?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Pagination configuration
|
|
51
|
+
*/
|
|
52
|
+
export interface PaginationConfig {
|
|
53
|
+
/** Number of rows per page */
|
|
54
|
+
pageSize?: number;
|
|
55
|
+
|
|
56
|
+
/** Show page size selector */
|
|
57
|
+
showPageSize?: boolean;
|
|
58
|
+
|
|
59
|
+
/** Available page size options */
|
|
60
|
+
pageSizeOptions?: number[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Source type discriminators
|
|
65
|
+
*/
|
|
66
|
+
export type SourceType = 'csv' | 'json' | 'directus' | 'api';
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* CSV Source configuration
|
|
70
|
+
*/
|
|
71
|
+
export interface CsvSourceConfig {
|
|
72
|
+
type: 'csv';
|
|
73
|
+
url: string;
|
|
74
|
+
/** Delimiter (default: ',') */
|
|
75
|
+
delimiter?: string;
|
|
76
|
+
/** Skip first N rows */
|
|
77
|
+
skipRows?: number;
|
|
78
|
+
/** Longitude column name (for map conversion) */
|
|
79
|
+
lng?: string;
|
|
80
|
+
/** Latitude column name (for map conversion) */
|
|
81
|
+
lat?: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* JSON Source configuration
|
|
86
|
+
*/
|
|
87
|
+
export interface JsonSourceConfig {
|
|
88
|
+
type: 'json';
|
|
89
|
+
/** Inline data */
|
|
90
|
+
data?: DataRow[];
|
|
91
|
+
/** URL to fetch JSON from */
|
|
92
|
+
url?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Re-export DirectusSourceConfig from shared utils
|
|
96
|
+
export type { DirectusSourceConfig } from '../../utils/directus-config';
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Generic API Source configuration
|
|
100
|
+
*/
|
|
101
|
+
export interface ApiSourceConfig {
|
|
102
|
+
type: 'api';
|
|
103
|
+
/** API endpoint URL */
|
|
104
|
+
url: string;
|
|
105
|
+
/** HTTP method */
|
|
106
|
+
method?: 'GET' | 'POST';
|
|
107
|
+
/** Request headers */
|
|
108
|
+
headers?: Record<string, string>;
|
|
109
|
+
/** Request body (for POST) */
|
|
110
|
+
body?: any;
|
|
111
|
+
/** Transform response data */
|
|
112
|
+
transformer?: (data: any) => DataRow[];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* GeoJSON Source configuration
|
|
117
|
+
*/
|
|
118
|
+
export interface GeoJsonSourceConfig {
|
|
119
|
+
type: 'geojson';
|
|
120
|
+
/** GeoJSON data object */
|
|
121
|
+
data?: any;
|
|
122
|
+
/** URL to fetch GeoJSON from */
|
|
123
|
+
url?: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Vector Tile Source configuration (from MapLibre style JSON)
|
|
128
|
+
*/
|
|
129
|
+
export interface VectorSourceConfig {
|
|
130
|
+
type: 'vector';
|
|
131
|
+
/** Vector tile URL or template */
|
|
132
|
+
url?: string;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Union of all source configurations
|
|
137
|
+
*/
|
|
138
|
+
export type SourceConfig =
|
|
139
|
+
| CsvSourceConfig
|
|
140
|
+
| JsonSourceConfig
|
|
141
|
+
| DirectusSourceConfig
|
|
142
|
+
| ApiSourceConfig
|
|
143
|
+
| GeoJsonSourceConfig
|
|
144
|
+
| VectorSourceConfig;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Props for source components
|
|
148
|
+
*/
|
|
149
|
+
export interface SourceComponentProps {
|
|
150
|
+
/** Callback to provide data to parent */
|
|
151
|
+
onDataLoad: (data: DataRow[]) => void;
|
|
152
|
+
/** Callback for loading state */
|
|
153
|
+
onLoadingChange?: (loading: boolean) => void;
|
|
154
|
+
/** Callback for error state */
|
|
155
|
+
onError?: (error: Error) => void;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* DataTb main component props
|
|
160
|
+
*/
|
|
161
|
+
export interface DataTbProps {
|
|
162
|
+
/** Column definitions (optional - will auto-detect if not provided) */
|
|
163
|
+
columns?: ColumnConfig[];
|
|
164
|
+
|
|
165
|
+
/** Enable global search/filter */
|
|
166
|
+
searchable?: boolean;
|
|
167
|
+
|
|
168
|
+
/** Pagination configuration */
|
|
169
|
+
pagination?: boolean | PaginationConfig;
|
|
170
|
+
|
|
171
|
+
/** Enable column sorting */
|
|
172
|
+
sortable?: boolean;
|
|
173
|
+
|
|
174
|
+
/** Initial sort state */
|
|
175
|
+
initialSort?: {
|
|
176
|
+
columnKey: string;
|
|
177
|
+
direction: 'asc' | 'desc';
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/** Custom CSS classes */
|
|
181
|
+
className?: string;
|
|
182
|
+
|
|
183
|
+
/** Data source configuration */
|
|
184
|
+
source?: SourceConfig;
|
|
185
|
+
|
|
186
|
+
/** Loading state message */
|
|
187
|
+
loadingMessage?: string;
|
|
188
|
+
|
|
189
|
+
/** Empty state message */
|
|
190
|
+
emptyMessage?: string;
|
|
191
|
+
|
|
192
|
+
/** Error message */
|
|
193
|
+
errorMessage?: string;
|
|
194
|
+
|
|
195
|
+
/** Truncate large cell content by default */
|
|
196
|
+
truncateContent?: boolean;
|
|
197
|
+
|
|
198
|
+
/** Max width for truncated cell content (CSS value) */
|
|
199
|
+
truncateMaxWidth?: string;
|
|
200
|
+
|
|
201
|
+
/** Table body content size */
|
|
202
|
+
contentSize?: 'sm' | 'md';
|
|
203
|
+
|
|
204
|
+
/** Simplified CSV Source URL (MDX friendly) */
|
|
205
|
+
csv?: string;
|
|
206
|
+
|
|
207
|
+
/** Simplified JSON Source Data or URL (MDX friendly) */
|
|
208
|
+
json?: any[] | string;
|
|
209
|
+
|
|
210
|
+
/** Simplified API Source URL (MDX friendly) */
|
|
211
|
+
api?: string;
|
|
212
|
+
|
|
213
|
+
/** Simplified Directus configuration (MDX friendly) - uses same interface as Map component */
|
|
214
|
+
directus?: DirectusShorthand;
|
|
215
|
+
}
|