@kupola/kupola 1.2.0 → 1.3.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/LICENSE +21 -0
- package/README.md +330 -286
- package/adapters/axios.d.ts +34 -0
- package/adapters/axios.js +122 -0
- package/adapters/navios-http.d.ts +110 -0
- package/adapters/navios-http.js +151 -0
- package/dist/css/accessibility.css +119 -0
- package/dist/css/animations.css +224 -0
- package/dist/css/brand-themes.css +300 -0
- package/dist/css/colors_and_type.css +441 -0
- package/dist/css/components-ext.css +4165 -0
- package/dist/css/components.css +1483 -0
- package/dist/css/responsive.css +697 -0
- package/dist/css/scaffold.css +145 -0
- package/dist/css/states.css +316 -0
- package/dist/css/theme-dark.css +296 -0
- package/dist/css/theme-light.css +296 -0
- package/dist/css/utilities.css +171 -0
- package/dist/kupola.cjs.js +219 -161
- package/dist/kupola.cjs.js.map +1 -1
- package/dist/kupola.esm.js +6643 -5709
- package/dist/kupola.esm.js.map +1 -1
- package/dist/kupola.umd.js +219 -161
- package/dist/kupola.umd.js.map +1 -1
- package/dist/plugins/vite-plugin-kupola.js +120 -0
- package/dist/types/kupola.d.ts +421 -323
- package/js/calendar.js +334 -25
- package/js/carousel.js +182 -48
- package/js/collapse.js +148 -34
- package/js/color-picker.js +416 -108
- package/js/component.js +8 -19
- package/js/countdown.js +9 -8
- package/js/data-bind.js +73 -16
- package/js/datepicker.js +488 -110
- package/js/depends.js +710 -0
- package/js/dialog.js +4 -2
- package/js/drawer.js +172 -8
- package/js/dropdown.js +272 -17
- package/js/dynamic-tags.js +156 -40
- package/js/fileupload.js +9 -8
- package/js/form.js +280 -254
- package/js/global-events.js +281 -188
- package/js/heatmap.js +10 -7
- package/js/i18n.js +18 -10
- package/js/icons.js +141 -161
- package/js/image-preview.js +146 -2
- package/js/initializer.js +113 -71
- package/js/kupola-core.js +123 -45
- package/js/kupola-lifecycle.js +13 -11
- package/js/message.js +8 -1
- package/js/modal.js +207 -59
- package/js/notification.js +8 -1
- package/js/numberinput.js +9 -8
- package/js/pagination.js +263 -0
- package/js/registry.js +29 -12
- package/js/select.js +482 -27
- package/js/slide-captcha.js +11 -2
- package/js/slider.js +442 -25
- package/js/statcard.js +9 -7
- package/js/table.js +1210 -0
- package/js/tag.js +268 -14
- package/js/theme.js +14 -43
- package/js/timepicker.js +335 -66
- package/js/tooltip.js +317 -86
- package/js/utils.js +6 -2
- package/js/validation.js +6 -2
- package/js/virtual-list.js +11 -7
- package/js/web-components.js +288 -0
- package/package.json +77 -67
- package/plugins/vite-plugin-kupola.js +120 -0
- package/types/kupola.d.ts +421 -323
- package/CHANGELOG.md +0 -130
- package/INTEGRATION.md +0 -440
- package/PROJECT_SUMMARY.md +0 -312
- package/SKILL.md +0 -572
- package/dist/utils/utils/Kupola.cs +0 -77
- package/dist/utils/utils/Kupola.java +0 -104
- package/dist/utils/utils/kupola.go +0 -120
- package/dist/utils/utils/kupola.js +0 -63
- package/dist/utils/utils/kupola.py +0 -1392
- package/dist/utils/utils/kupola.rb +0 -69
- package/js/composition-api.js +0 -458
- package/js/error-handler.js +0 -181
- package/js/http.js +0 -419
- package/js/kupola-devtools.js +0 -598
- package/js/performance.js +0 -250
- package/js/router.js +0 -396
- package/js/security.js +0 -189
- package/js/test-utils.js +0 -251
- package/templates/base.html +0 -30
- package/templates/base_dashboard.html +0 -99
- package/utils/Kupola.cs +0 -77
- package/utils/Kupola.java +0 -104
- package/utils/kupola.go +0 -120
- package/utils/kupola.js +0 -63
- package/utils/kupola.py +0 -1392
- package/utils/kupola.rb +0 -69
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Axios adapter for Kupola HTTP client plugin system.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface AxiosAdapterOptions {
|
|
6
|
+
/** Additional Axios request config to merge into every request */
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Create a Kupola-compatible HTTP client from an Axios instance.
|
|
12
|
+
*
|
|
13
|
+
* @param axiosInstance - An Axios instance (from axios.create() or default axios)
|
|
14
|
+
* @param options - Additional Axios request config to merge into every request
|
|
15
|
+
* @returns Kupola HTTP client object with a `fetch` function
|
|
16
|
+
*/
|
|
17
|
+
export function createAxiosAdapter(
|
|
18
|
+
axiosInstance: any,
|
|
19
|
+
options?: AxiosAdapterOptions
|
|
20
|
+
): {
|
|
21
|
+
fetch(url: string, fetchOptions?: {
|
|
22
|
+
method?: string;
|
|
23
|
+
headers?: Record<string, string>;
|
|
24
|
+
body?: string;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
ok: boolean;
|
|
27
|
+
status: number;
|
|
28
|
+
statusText: string;
|
|
29
|
+
headers: Record<string, string>;
|
|
30
|
+
url: string;
|
|
31
|
+
json(): Promise<any>;
|
|
32
|
+
text(): Promise<string>;
|
|
33
|
+
}>;
|
|
34
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Axios adapter for Kupola HTTP client plugin system.
|
|
3
|
+
*
|
|
4
|
+
* Allows using Axios (with interceptors, custom config, etc.) as the HTTP
|
|
5
|
+
* client for all useDeps() / useQuery() requests.
|
|
6
|
+
*
|
|
7
|
+
* @module adapters/axios
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* import { configureHttpClient } from 'kupola';
|
|
11
|
+
* import { createAxiosAdapter } from 'kupola/adapters/axios';
|
|
12
|
+
* import axios from 'axios';
|
|
13
|
+
*
|
|
14
|
+
* const api = axios.create({ baseURL: '/api', timeout: 10000 });
|
|
15
|
+
*
|
|
16
|
+
* // Axios interceptors work as expected
|
|
17
|
+
* api.interceptors.request.use(config => {
|
|
18
|
+
* config.headers.Authorization = `Bearer ${getToken()}`;
|
|
19
|
+
* return config;
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* configureHttpClient(createAxiosAdapter(api));
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Create a Kupola-compatible HTTP client from an Axios instance.
|
|
27
|
+
*
|
|
28
|
+
* @param {Object} axiosInstance - An Axios instance (from axios.create() or default axios)
|
|
29
|
+
* @param {Object} [options] - Additional Axios request config to merge into every request
|
|
30
|
+
* @returns {{ fetch: Function }} Kupola HTTP client object
|
|
31
|
+
*/
|
|
32
|
+
export function createAxiosAdapter(axiosInstance, options = {}) {
|
|
33
|
+
if (!axiosInstance || typeof axiosInstance.request !== 'function') {
|
|
34
|
+
throw new TypeError('[Kupola] createAxiosAdapter: invalid Axios instance (must have .request method)');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
/**
|
|
39
|
+
* Fetch function compatible with Kupola's HTTP client interface.
|
|
40
|
+
* Translates Fetch API semantics to Axios, and Axios response back to
|
|
41
|
+
* Fetch API Response shape.
|
|
42
|
+
*
|
|
43
|
+
* @param {string} url - Request URL
|
|
44
|
+
* @param {Object} [fetchOptions] - Fetch-style options
|
|
45
|
+
* @param {string} [fetchOptions.method='GET'] - HTTP method
|
|
46
|
+
* @param {Object} [fetchOptions.headers] - Request headers
|
|
47
|
+
* @param {string} [fetchOptions.body] - Request body (JSON string)
|
|
48
|
+
* @returns {Promise<Object>} Response-like object { ok, status, headers, json(), text() }
|
|
49
|
+
*/
|
|
50
|
+
fetch: async function (url, fetchOptions = {}) {
|
|
51
|
+
// Build Axios config
|
|
52
|
+
const axiosConfig = {
|
|
53
|
+
url,
|
|
54
|
+
method: (fetchOptions.method || 'GET').toLowerCase(),
|
|
55
|
+
headers: fetchOptions.headers || {},
|
|
56
|
+
// Don't throw on non-2xx — let Kupola handle error status
|
|
57
|
+
validateStatus: () => true,
|
|
58
|
+
...options
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Parse body if present (Fetch sends body as JSON string)
|
|
62
|
+
if (fetchOptions.body) {
|
|
63
|
+
try {
|
|
64
|
+
axiosConfig.data = JSON.parse(fetchOptions.body);
|
|
65
|
+
} catch (_) {
|
|
66
|
+
axiosConfig.data = fetchOptions.body;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const response = await axiosInstance.request(axiosConfig);
|
|
72
|
+
|
|
73
|
+
// Cache the parsed data to avoid re-parsing on multiple .json() calls
|
|
74
|
+
let _cachedData;
|
|
75
|
+
let _dataParsed = false;
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
ok: response.status >= 200 && response.status < 300,
|
|
79
|
+
status: response.status,
|
|
80
|
+
statusText: response.statusText || '',
|
|
81
|
+
headers: response.headers || {},
|
|
82
|
+
url,
|
|
83
|
+
|
|
84
|
+
json() {
|
|
85
|
+
if (!_dataParsed) {
|
|
86
|
+
_cachedData = response.data;
|
|
87
|
+
_dataParsed = true;
|
|
88
|
+
}
|
|
89
|
+
return Promise.resolve(_cachedData);
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
text() {
|
|
93
|
+
if (!_dataParsed) {
|
|
94
|
+
_cachedData = typeof response.data === 'string'
|
|
95
|
+
? response.data
|
|
96
|
+
: JSON.stringify(response.data);
|
|
97
|
+
_dataParsed = true;
|
|
98
|
+
}
|
|
99
|
+
return Promise.resolve(_cachedData);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
} catch (error) {
|
|
103
|
+
// Network error or request was blocked
|
|
104
|
+
return {
|
|
105
|
+
ok: false,
|
|
106
|
+
status: 0,
|
|
107
|
+
statusText: error.message || 'Network Error',
|
|
108
|
+
headers: {},
|
|
109
|
+
url,
|
|
110
|
+
|
|
111
|
+
json() {
|
|
112
|
+
return Promise.resolve({ error: error.message });
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
text() {
|
|
116
|
+
return Promise.resolve(error.message);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @navios/http adapter for Kupola HTTP client plugin system.
|
|
3
|
+
*
|
|
4
|
+
* @navios/http is a lightweight, fetch-based axios replacement that supports
|
|
5
|
+
* interceptors, multiple response types, and works with Next.js / RSC.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** Additional @navios/http request config fields that can be merged into every request. */
|
|
9
|
+
export interface NaviosAdapterOptions {
|
|
10
|
+
/** Response type: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData' | 'stream' */
|
|
11
|
+
responseType?: string;
|
|
12
|
+
/** Custom status validator, e.g. (status) => status < 500 */
|
|
13
|
+
validateStatus?: (status: number) => boolean;
|
|
14
|
+
/** Request credentials: 'omit' | 'same-origin' | 'include' */
|
|
15
|
+
credentials?: string;
|
|
16
|
+
/** URL search parameters */
|
|
17
|
+
params?: Record<string, any> | URLSearchParams;
|
|
18
|
+
/** Allow any other @navios/http requestConfig fields */
|
|
19
|
+
[key: string]: any;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Minimal @navios/http client interface required by the adapter. */
|
|
23
|
+
export interface NaviosHttpClient {
|
|
24
|
+
request(config: any): Promise<{
|
|
25
|
+
data: any;
|
|
26
|
+
status: number;
|
|
27
|
+
statusText?: string;
|
|
28
|
+
headers?: Record<string, string>;
|
|
29
|
+
config?: any;
|
|
30
|
+
}>;
|
|
31
|
+
get(url: string, config?: any): Promise<any>;
|
|
32
|
+
post(url: string, data?: any, config?: any): Promise<any>;
|
|
33
|
+
put(url: string, data?: any, config?: any): Promise<any>;
|
|
34
|
+
patch(url: string, data?: any, config?: any): Promise<any>;
|
|
35
|
+
delete(url: string, config?: any): Promise<any>;
|
|
36
|
+
head(url: string, config?: any): Promise<any>;
|
|
37
|
+
options(url: string, config?: any): Promise<any>;
|
|
38
|
+
defaults: Record<string, any>;
|
|
39
|
+
interceptors: {
|
|
40
|
+
request: { use(onFulfilled: Function, onRejected?: Function): number };
|
|
41
|
+
response: { use(onFulfilled: Function, onRejected?: Function): number };
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Create a Kupola-compatible HTTP client from a @navios/http instance.
|
|
47
|
+
*
|
|
48
|
+
* @param naviosClient - A @navios/http client instance (from create() or default import)
|
|
49
|
+
* @param options - Additional @navios/http request config to merge into every request
|
|
50
|
+
* @returns Kupola HTTP client object with a `fetch` function
|
|
51
|
+
*/
|
|
52
|
+
export function createNaviosAdapter(
|
|
53
|
+
naviosClient: NaviosHttpClient,
|
|
54
|
+
options?: NaviosAdapterOptions
|
|
55
|
+
): {
|
|
56
|
+
fetch(url: string, fetchOptions?: {
|
|
57
|
+
method?: string;
|
|
58
|
+
headers?: Record<string, string>;
|
|
59
|
+
body?: string;
|
|
60
|
+
}): Promise<{
|
|
61
|
+
ok: boolean;
|
|
62
|
+
status: number;
|
|
63
|
+
statusText: string;
|
|
64
|
+
headers: Record<string, string>;
|
|
65
|
+
url: string;
|
|
66
|
+
json(): Promise<any>;
|
|
67
|
+
text(): Promise<string>;
|
|
68
|
+
}>;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* @navios/http adapter for Kupola HTTP client plugin system.
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
export interface NaviosAdapterOptions {
|
|
75
|
+
/** Additional request config to merge into every request */
|
|
76
|
+
[key: string]: any;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Create a Kupola-compatible HTTP client from a @navios/http instance.
|
|
81
|
+
*
|
|
82
|
+
* @param naviosClient - A @navios/http client instance (from create())
|
|
83
|
+
* @param options - Additional request config to merge into every request
|
|
84
|
+
* @returns Kupola HTTP client object with a `fetch` function
|
|
85
|
+
*/
|
|
86
|
+
export function createNaviosAdapter(
|
|
87
|
+
naviosClient: {
|
|
88
|
+
request(config: any): Promise<{
|
|
89
|
+
status: number;
|
|
90
|
+
statusText?: string;
|
|
91
|
+
headers?: Record<string, string>;
|
|
92
|
+
data: any;
|
|
93
|
+
}>;
|
|
94
|
+
},
|
|
95
|
+
options?: NaviosAdapterOptions
|
|
96
|
+
): {
|
|
97
|
+
fetch(url: string, fetchOptions?: {
|
|
98
|
+
method?: string;
|
|
99
|
+
headers?: Record<string, string>;
|
|
100
|
+
body?: string;
|
|
101
|
+
}): Promise<{
|
|
102
|
+
ok: boolean;
|
|
103
|
+
status: number;
|
|
104
|
+
statusText: string;
|
|
105
|
+
headers: Record<string, string>;
|
|
106
|
+
url: string;
|
|
107
|
+
json(): Promise<any>;
|
|
108
|
+
text(): Promise<string>;
|
|
109
|
+
}>;
|
|
110
|
+
};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @navios/http adapter for Kupola HTTP client plugin system.
|
|
3
|
+
*
|
|
4
|
+
* Allows using @navios/http (with interceptors, custom config, etc.) as the HTTP
|
|
5
|
+
* client for all useDeps() / useQuery() requests.
|
|
6
|
+
*
|
|
7
|
+
* @navios/http is a lightweight, fetch-based axios replacement that supports
|
|
8
|
+
* interceptors, multiple response types, and works with Next.js / RSC.
|
|
9
|
+
*
|
|
10
|
+
* @module adapters/navios-http
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* import { configureHttpClient } from 'kupola';
|
|
14
|
+
* import { createNaviosAdapter } from 'kupola/adapters/navios-http';
|
|
15
|
+
* import { create } from '@navios/http';
|
|
16
|
+
*
|
|
17
|
+
* const client = create({ baseURL: '/api' });
|
|
18
|
+
*
|
|
19
|
+
* // @navios/http interceptors work as expected
|
|
20
|
+
* client.interceptors.request.use((config) => {
|
|
21
|
+
* config.headers['Authorization'] = `Bearer ${getToken()}`;
|
|
22
|
+
* return config;
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* configureHttpClient(createNaviosAdapter(client));
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Create a Kupola-compatible HTTP client from a @navios/http instance.
|
|
30
|
+
*
|
|
31
|
+
* Translates Kupola's fetch-style calls into @navios/http requests,
|
|
32
|
+
* and maps @navios/http responses back to Kupola's standard format:
|
|
33
|
+
* { ok, status, statusText, headers, url, json(), text() }
|
|
34
|
+
*
|
|
35
|
+
* @param {Object} naviosClient - A @navios/http client instance (from create() or default import)
|
|
36
|
+
* Must expose: .request(config), .get(url, config), .post(url, data, config), etc.
|
|
37
|
+
* @param {Object} [options] - Additional @navios/http request config merged into every request.
|
|
38
|
+
* Supports all @navios/http requestConfig fields:
|
|
39
|
+
* - responseType {string}: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData' | 'stream'
|
|
40
|
+
* - validateStatus {Function}: custom status validator, e.g. () => true
|
|
41
|
+
* - credentials {string}: 'omit' | 'same-origin' | 'include'
|
|
42
|
+
* - params {Object|URLSearchParams}: URL search parameters
|
|
43
|
+
* @returns {{ fetch: Function }} Kupola HTTP client object
|
|
44
|
+
*/
|
|
45
|
+
export function createNaviosAdapter(naviosClient, options = {}) {
|
|
46
|
+
if (!naviosClient || typeof naviosClient.request !== 'function') {
|
|
47
|
+
throw new TypeError('[Kupola] createNaviosAdapter: invalid @navios/http client (must have .request method)');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
/**
|
|
52
|
+
* Fetch function compatible with Kupola's HTTP client interface.
|
|
53
|
+
* Translates Fetch API semantics to @navios/http, and response back to
|
|
54
|
+
* Fetch API Response shape.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} url - Request URL
|
|
57
|
+
* @param {Object} [fetchOptions] - Fetch-style options
|
|
58
|
+
* @param {string} [fetchOptions.method='GET'] - HTTP method
|
|
59
|
+
* @param {Object} [fetchOptions.headers] - Request headers
|
|
60
|
+
* @param {string} [fetchOptions.body] - Request body (JSON string)
|
|
61
|
+
* @returns {Promise<Object>} Response-like object { ok, status, headers, json(), text() }
|
|
62
|
+
*/
|
|
63
|
+
fetch: async function (url, fetchOptions = {}) {
|
|
64
|
+
const method = (fetchOptions.method || 'GET').toUpperCase();
|
|
65
|
+
|
|
66
|
+
// Build request config for @navios/http
|
|
67
|
+
// Note: @navios/http uses `data` for body (axios-style), not `body` (fetch-style)
|
|
68
|
+
const requestConfig = {
|
|
69
|
+
url,
|
|
70
|
+
method,
|
|
71
|
+
headers: fetchOptions.headers || {},
|
|
72
|
+
// Accept all status codes here; Kupola handles ok/status checking itself
|
|
73
|
+
validateStatus: () => true,
|
|
74
|
+
...options
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Parse body if present (Fetch sends body as JSON string,
|
|
78
|
+
// but @navios/http accepts objects directly as `data`)
|
|
79
|
+
if (fetchOptions.body && ['POST', 'PUT', 'PATCH'].includes(method)) {
|
|
80
|
+
try {
|
|
81
|
+
requestConfig.data = JSON.parse(fetchOptions.body);
|
|
82
|
+
} catch (_) {
|
|
83
|
+
requestConfig.data = fetchOptions.body;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const response = await naviosClient.request(requestConfig);
|
|
89
|
+
|
|
90
|
+
// Cache the parsed data to avoid re-parsing on multiple .json() calls
|
|
91
|
+
let _cachedData;
|
|
92
|
+
let _dataParsed = false;
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
ok: response.status >= 200 && response.status < 300,
|
|
96
|
+
status: response.status,
|
|
97
|
+
statusText: response.statusText || '',
|
|
98
|
+
headers: response.headers || {},
|
|
99
|
+
url,
|
|
100
|
+
|
|
101
|
+
json() {
|
|
102
|
+
if (!_dataParsed) {
|
|
103
|
+
_cachedData = response.data;
|
|
104
|
+
_dataParsed = true;
|
|
105
|
+
}
|
|
106
|
+
return Promise.resolve(_cachedData);
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
text() {
|
|
110
|
+
if (!_dataParsed) {
|
|
111
|
+
_cachedData = typeof response.data === 'string'
|
|
112
|
+
? response.data
|
|
113
|
+
: JSON.stringify(response.data);
|
|
114
|
+
_dataParsed = true;
|
|
115
|
+
}
|
|
116
|
+
return Promise.resolve(_cachedData);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
} catch (error) {
|
|
120
|
+
// Network error or interceptor rejection.
|
|
121
|
+
// @navios/http error shape: { message, response?: { status, headers, data }, config }
|
|
122
|
+
const errStatus = (error.response && error.response.status) || 0;
|
|
123
|
+
const errHeaders = (error.response && error.response.headers) || {};
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
ok: false,
|
|
127
|
+
status: errStatus,
|
|
128
|
+
statusText: error.message || 'Network Error',
|
|
129
|
+
headers: errHeaders,
|
|
130
|
+
url,
|
|
131
|
+
|
|
132
|
+
json() {
|
|
133
|
+
// Try to return structured error data if available
|
|
134
|
+
if (error.response && error.response.data !== undefined) {
|
|
135
|
+
return Promise.resolve(error.response.data);
|
|
136
|
+
}
|
|
137
|
+
return Promise.resolve({ error: error.message });
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
text() {
|
|
141
|
+
if (error.response && error.response.data !== undefined) {
|
|
142
|
+
const d = error.response.data;
|
|
143
|
+
return Promise.resolve(typeof d === 'string' ? d : JSON.stringify(d));
|
|
144
|
+
}
|
|
145
|
+
return Promise.resolve(error.message);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/* Accessibility (a11y) */
|
|
2
|
+
|
|
3
|
+
/* Focus styles */
|
|
4
|
+
*:focus-visible {
|
|
5
|
+
outline: 2px solid var(--bg-brand);
|
|
6
|
+
outline-offset: 2px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
*:focus:not(:focus-visible) {
|
|
10
|
+
outline: none;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* Skip link */
|
|
14
|
+
.skip-link {
|
|
15
|
+
position: absolute;
|
|
16
|
+
top: -40px;
|
|
17
|
+
left: 0;
|
|
18
|
+
padding: 8px 12px;
|
|
19
|
+
background-color: var(--bg-brand);
|
|
20
|
+
color: var(--text-onbrand);
|
|
21
|
+
font-size: 13px;
|
|
22
|
+
font-weight: 500;
|
|
23
|
+
text-decoration: none;
|
|
24
|
+
z-index: 1000;
|
|
25
|
+
transition: top 0.2s ease;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.skip-link:focus {
|
|
29
|
+
top: 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Screen reader only */
|
|
33
|
+
.sr-only {
|
|
34
|
+
position: absolute;
|
|
35
|
+
width: 1px;
|
|
36
|
+
height: 1px;
|
|
37
|
+
padding: 0;
|
|
38
|
+
margin: -1px;
|
|
39
|
+
overflow: hidden;
|
|
40
|
+
clip: rect(0, 0, 0, 0);
|
|
41
|
+
white-space: nowrap;
|
|
42
|
+
border: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* High contrast mode */
|
|
46
|
+
@media (prefers-contrast: high) {
|
|
47
|
+
:root {
|
|
48
|
+
--border-neutral-l1: #000000;
|
|
49
|
+
--border-neutral-l2: #000000;
|
|
50
|
+
--border-neutral-l3: #000000;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.ds-btn {
|
|
54
|
+
border-width: 2px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.ds-input {
|
|
58
|
+
border-width: 2px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.ds-card {
|
|
62
|
+
border-width: 2px;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Reduced motion */
|
|
67
|
+
@media (prefers-reduced-motion: reduce) {
|
|
68
|
+
*,
|
|
69
|
+
*::before,
|
|
70
|
+
*::after {
|
|
71
|
+
animation-duration: 0.01ms !important;
|
|
72
|
+
animation-iteration-count: 1 !important;
|
|
73
|
+
transition-duration: 0.01ms !important;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Keyboard navigation */
|
|
78
|
+
.ds-btn:not(:disabled):focus-visible,
|
|
79
|
+
.ds-input:focus-visible,
|
|
80
|
+
.ds-toggle input:focus-visible + .ds-toggle__track {
|
|
81
|
+
outline: 2px solid var(--bg-brand);
|
|
82
|
+
outline-offset: 2px;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* Active states for keyboard users */
|
|
86
|
+
.ds-btn:not(:disabled):active,
|
|
87
|
+
.ds-btn:not(:disabled):focus:active {
|
|
88
|
+
transform: translateY(1px);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* Visible focus for better keyboard navigation */
|
|
92
|
+
.ds-dashboard__sidebar-item:focus-visible,
|
|
93
|
+
.ds-activityrail__item:focus-visible,
|
|
94
|
+
.ds-statusbar__item:focus-visible {
|
|
95
|
+
outline: 2px solid var(--bg-brand);
|
|
96
|
+
outline-offset: 2px;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Color contrast */
|
|
100
|
+
.ds-statcard__delta.is-up {
|
|
101
|
+
color: var(--status-success-default);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.ds-statcard__delta.is-down {
|
|
105
|
+
color: var(--status-error-default);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Selection color */
|
|
109
|
+
::selection {
|
|
110
|
+
background-color: var(--bg-brand-popup);
|
|
111
|
+
color: var(--text-brand);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Clearfix */
|
|
115
|
+
.ds-clearfix::after {
|
|
116
|
+
content: '';
|
|
117
|
+
display: table;
|
|
118
|
+
clear: both;
|
|
119
|
+
}
|