@nice2dev/erp-adapter 0.1.0 → 1.0.2
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/CHANGELOG.md +48 -1
- package/dist/ErpDataAdapter.d.ts +9 -0
- package/dist/ErpDataAdapter.d.ts.map +1 -1
- package/dist/ErpFileAdapter.d.ts +20 -0
- package/dist/ErpFileAdapter.d.ts.map +1 -1
- package/dist/ErpOfflineQueue.d.ts +66 -0
- package/dist/ErpOfflineQueue.d.ts.map +1 -0
- package/dist/ErpOptimisticStore.d.ts +41 -0
- package/dist/ErpOptimisticStore.d.ts.map +1 -0
- package/dist/ErpRateLimiter.d.ts +42 -0
- package/dist/ErpRateLimiter.d.ts.map +1 -0
- package/dist/__tests__/ErpAuthAdapter.test.d.ts +2 -0
- package/dist/__tests__/ErpAuthAdapter.test.d.ts.map +1 -0
- package/dist/__tests__/ErpDataAdapter.test.d.ts +2 -0
- package/dist/__tests__/ErpDataAdapter.test.d.ts.map +1 -0
- package/dist/__tests__/ErpExportAdapter.test.d.ts +2 -0
- package/dist/__tests__/ErpExportAdapter.test.d.ts.map +1 -0
- package/dist/__tests__/ErpFileAdapter.test.d.ts +2 -0
- package/dist/__tests__/ErpFileAdapter.test.d.ts.map +1 -0
- package/dist/__tests__/ErpOfflineQueue.test.d.ts +2 -0
- package/dist/__tests__/ErpOfflineQueue.test.d.ts.map +1 -0
- package/dist/__tests__/ErpOptimisticStore.test.d.ts +2 -0
- package/dist/__tests__/ErpOptimisticStore.test.d.ts.map +1 -0
- package/dist/__tests__/ErpRateLimiter.test.d.ts +2 -0
- package/dist/__tests__/ErpRateLimiter.test.d.ts.map +1 -0
- package/dist/__tests__/middleware.test.d.ts +2 -0
- package/dist/__tests__/middleware.test.d.ts.map +1 -0
- package/dist/__tests__/registries.test.d.ts +2 -0
- package/dist/__tests__/registries.test.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +1249 -113
- package/dist/index.mjs.map +1 -1
- package/dist/middleware.d.ts +44 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/useCollaborativeDataGrid.d.ts +132 -0
- package/dist/useCollaborativeDataGrid.d.ts.map +1 -0
- package/dist/useEntityPresence.d.ts +136 -0
- package/dist/useEntityPresence.d.ts.map +1 -0
- package/dist/useSignalRLiveData.d.ts +121 -0
- package/dist/useSignalRLiveData.d.ts.map +1 -0
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,54 @@
|
|
|
1
|
-
# Changelog
|
|
1
|
+
# @nice2dev/erp-adapter — Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the OmniVerk ERP adapter.
|
|
4
|
+
|
|
5
|
+
## [0.2.0] — 2026-03-25
|
|
6
|
+
|
|
7
|
+
### Added (FAZA 7.7)
|
|
8
|
+
|
|
9
|
+
- **Batch operations** — `createBatch()`, `updateBatch()` with transactional support
|
|
10
|
+
- **Optimistic updates** — immediate UI update, rollback on error
|
|
11
|
+
- **Offline queue** — CRUD operation queuing offline, sync on reconnect
|
|
12
|
+
- **Middleware pipeline** — pluggable middleware (logging, retry, cache, transform)
|
|
13
|
+
- **Rate limiting** — client-side throttle for high-frequency operations
|
|
14
|
+
- **File upload progress** — progress bar, chunk upload, resume after failure
|
|
15
|
+
|
|
16
|
+
### Added (FAZA 3.2 — Real-time)
|
|
17
|
+
|
|
18
|
+
- **useSignalRLiveData** — push updates to DataGrid rows in real-time
|
|
19
|
+
- **useEntityPresence** — who is currently editing the same record
|
|
20
|
+
- **useCollaborativeDataGrid** — multi-user DataGrid editing (cell locking, conflict resolution)
|
|
21
|
+
|
|
22
|
+
### Tests
|
|
23
|
+
|
|
24
|
+
- REST client, SignalR lifecycle, auth token injection, file upload, batch operations
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## [0.1.0] — 2025-06-01
|
|
29
|
+
|
|
30
|
+
Initial beta release.
|
|
31
|
+
|
|
32
|
+
- REST CRUD client with JWT auth
|
|
33
|
+
- SignalR real-time connection
|
|
34
|
+
- File upload/download
|
|
35
|
+
- Server-side export (xlsx, pdf, csv, json, xml)
|
|
36
|
+
- OData query builder
|
|
2
37
|
|
|
3
38
|
All notable changes to `@nice2dev/erp-adapter` will be documented in this file.
|
|
4
39
|
|
|
40
|
+
## [0.2.0] - 2026-06-16
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- `ErpOfflineQueue` — offline request queue with automatic retry and conflict resolution
|
|
45
|
+
- `ErpOptimisticStore` — optimistic UI update store with rollback on server rejection
|
|
46
|
+
- `ErpRateLimiter` — client-side rate limiting with token bucket algorithm
|
|
47
|
+
- `middleware.ts` — middleware pipeline for request/response transformation
|
|
48
|
+
- Individual registry modules: `audioControls.ts`, `authControls.ts`, `businessControls.ts`, `gamificationControls.ts`, `graphicControls.ts`, `socialControls.ts`, `threeControls.ts`
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
5
52
|
## [0.1.0] - 2026-03-18
|
|
6
53
|
|
|
7
54
|
### Added
|
package/dist/ErpDataAdapter.d.ts
CHANGED
|
@@ -25,5 +25,14 @@ export declare class ErpDataAdapter<T = unknown> {
|
|
|
25
25
|
remove(id: string | number): Promise<ErpResponse<void>>;
|
|
26
26
|
/** Batch delete. */
|
|
27
27
|
removeBatch(ids: (string | number)[]): Promise<ErpResponse<void>>;
|
|
28
|
+
/** Batch create — send multiple items in a single request. */
|
|
29
|
+
createBatch(items: Partial<T>[]): Promise<ErpResponse<T[]>>;
|
|
30
|
+
/** Batch update — send multiple items with ids in a single request. */
|
|
31
|
+
updateBatch(items: {
|
|
32
|
+
id: string | number;
|
|
33
|
+
data: Partial<T>;
|
|
34
|
+
}[]): Promise<ErpResponse<T[]>>;
|
|
35
|
+
/** Partial update (PATCH) a single entity. */
|
|
36
|
+
patch(id: string | number, fields: Partial<T>): Promise<ErpResponse<T>>;
|
|
28
37
|
}
|
|
29
38
|
//# sourceMappingURL=ErpDataAdapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErpDataAdapter.d.ts","sourceRoot":"","sources":["../src/ErpDataAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAsB,MAAM,SAAS,CAAC;AAE/E,MAAM,WAAW,oBAAoB;IACjC,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACjD;AAED,qBAAa,cAAc,CAAC,CAAC,GAAG,OAAO;IACnC,OAAO,CAAC,GAAG,CAAuB;gBAEtB,MAAM,EAAE,oBAAoB,GAAG,MAAM;YAInC,OAAO;IAerB,uCAAuC;IACjC,IAAI,CAAC,GAAG,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;IAW3D,+BAA+B;IACzB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAI3D,qBAAqB;IACf,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAIvD,qBAAqB;IACf,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAI5E,qBAAqB;IACf,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAI7D,oBAAoB;IACd,WAAW,CAAC,GAAG,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ErpDataAdapter.d.ts","sourceRoot":"","sources":["../src/ErpDataAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAsB,MAAM,SAAS,CAAC;AAE/E,MAAM,WAAW,oBAAoB;IACjC,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACjD;AAED,qBAAa,cAAc,CAAC,CAAC,GAAG,OAAO;IACnC,OAAO,CAAC,GAAG,CAAuB;gBAEtB,MAAM,EAAE,oBAAoB,GAAG,MAAM;YAInC,OAAO;IAerB,uCAAuC;IACjC,IAAI,CAAC,GAAG,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;IAW3D,+BAA+B;IACzB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAI3D,qBAAqB;IACf,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAIvD,qBAAqB;IACf,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAI5E,qBAAqB;IACf,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAI7D,oBAAoB;IACd,WAAW,CAAC,GAAG,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAIvE,8DAA8D;IACxD,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;IAIjE,uEAAuE;IACjE,WAAW,CAAC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;IAIhG,8CAA8C;IACxC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;CAGhF"}
|
package/dist/ErpFileAdapter.d.ts
CHANGED
|
@@ -5,6 +5,16 @@ export interface ErpFileAdapterConfig {
|
|
|
5
5
|
fetch?: typeof fetch;
|
|
6
6
|
tokenFactory?: () => string | Promise<string>;
|
|
7
7
|
}
|
|
8
|
+
/** Progress callback for upload tracking. */
|
|
9
|
+
export type UploadProgressCallback = (event: UploadProgressEvent) => void;
|
|
10
|
+
export interface UploadProgressEvent {
|
|
11
|
+
/** Bytes uploaded so far. */
|
|
12
|
+
loaded: number;
|
|
13
|
+
/** Total bytes (0 if unknown). */
|
|
14
|
+
total: number;
|
|
15
|
+
/** Progress as 0–1 fraction (NaN if total unknown). */
|
|
16
|
+
percent: number;
|
|
17
|
+
}
|
|
8
18
|
export declare class ErpFileAdapter {
|
|
9
19
|
private cfg;
|
|
10
20
|
constructor(config: ErpFileAdapterConfig);
|
|
@@ -19,5 +29,15 @@ export declare class ErpFileAdapter {
|
|
|
19
29
|
getDownloadUrl(id: string): Promise<string>;
|
|
20
30
|
/** Delete file by id. */
|
|
21
31
|
remove(id: string): Promise<ErpResponse<void>>;
|
|
32
|
+
/**
|
|
33
|
+
* Upload a file with progress tracking via XMLHttpRequest.
|
|
34
|
+
* Falls back to standard fetch-based upload if XHR is unavailable.
|
|
35
|
+
*/
|
|
36
|
+
uploadWithProgress(file: File, onProgress: UploadProgressCallback, folder?: string, signal?: AbortSignal): Promise<ErpResponse<ErpFileInfo>>;
|
|
37
|
+
/**
|
|
38
|
+
* Upload multiple files with per-file progress tracking.
|
|
39
|
+
* Returns progress for each file individually.
|
|
40
|
+
*/
|
|
41
|
+
uploadMultipleWithProgress(files: File[], onProgress: (fileIndex: number, event: UploadProgressEvent) => void, folder?: string, signal?: AbortSignal): Promise<ErpResponse<ErpFileInfo>[]>;
|
|
22
42
|
}
|
|
23
43
|
//# sourceMappingURL=ErpFileAdapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErpFileAdapter.d.ts","sourceRoot":"","sources":["../src/ErpFileAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAExD,MAAM,WAAW,oBAAoB;IACjC,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACjD;AAED,qBAAa,cAAc;IACvB,OAAO,CAAC,GAAG,CAAuB;gBAEtB,MAAM,EAAE,oBAAoB;YAI1B,OAAO;IAQrB,uDAAuD;IACjD,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IAc5E,6BAA6B;IACvB,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;IAczF,+BAA+B;IACzB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IAS5D,mDAAmD;IAC7C,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUjD,yBAAyB;IACnB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ErpFileAdapter.d.ts","sourceRoot":"","sources":["../src/ErpFileAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAExD,MAAM,WAAW,oBAAoB;IACjC,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACjD;AAED,6CAA6C;AAC7C,MAAM,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAE1E,MAAM,WAAW,mBAAmB;IAChC,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,cAAc;IACvB,OAAO,CAAC,GAAG,CAAuB;gBAEtB,MAAM,EAAE,oBAAoB;YAI1B,OAAO;IAQrB,uDAAuD;IACjD,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IAc5E,6BAA6B;IACvB,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;IAczF,+BAA+B;IACzB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IAS5D,mDAAmD;IAC7C,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUjD,yBAAyB;IACnB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAUpD;;;OAGG;IACH,kBAAkB,CACd,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,sBAAsB,EAClC,MAAM,CAAC,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IAqDpC;;;OAGG;IACG,0BAA0B,CAC5B,KAAK,EAAE,IAAI,EAAE,EACb,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,KAAK,IAAI,EACnE,MAAM,CAAC,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC;CAczC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ErpOfflineQueue — queues requests when offline and replays them on reconnect.
|
|
3
|
+
*
|
|
4
|
+
* Wraps fetch to detect navigator.onLine. When offline, mutations (POST/PUT/PATCH/DELETE)
|
|
5
|
+
* are stored in an IndexedDB-backed queue and replayed in order when connectivity returns.
|
|
6
|
+
*
|
|
7
|
+
* GET requests while offline reject immediately (or return cached data if cacheGets is true).
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* const queue = new ErpOfflineQueue({ onSync: (results) => console.log('Synced', results) });
|
|
11
|
+
* const adapter = new ErpDataAdapter({ baseUrl: '/api/products', fetch: queue.fetch });
|
|
12
|
+
*/
|
|
13
|
+
export interface ErpOfflineQueueConfig {
|
|
14
|
+
/** Base fetch to use when online (default: globalThis.fetch). */
|
|
15
|
+
baseFetch?: typeof fetch;
|
|
16
|
+
/** Called when the queue finishes replaying after reconnect. */
|
|
17
|
+
onSync?: (results: SyncResult[]) => void;
|
|
18
|
+
/** Called when a request is queued while offline. */
|
|
19
|
+
onQueued?: (entry: QueueEntry) => void;
|
|
20
|
+
/** Called on online/offline status change. */
|
|
21
|
+
onStatusChange?: (online: boolean) => void;
|
|
22
|
+
/** Storage key prefix for persistence (default: "erp_offline_"). */
|
|
23
|
+
storageKey?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface QueueEntry {
|
|
26
|
+
id: string;
|
|
27
|
+
url: string;
|
|
28
|
+
method: string;
|
|
29
|
+
headers: Record<string, string>;
|
|
30
|
+
body?: string;
|
|
31
|
+
timestamp: number;
|
|
32
|
+
}
|
|
33
|
+
export interface SyncResult {
|
|
34
|
+
entry: QueueEntry;
|
|
35
|
+
success: boolean;
|
|
36
|
+
status?: number;
|
|
37
|
+
error?: string;
|
|
38
|
+
}
|
|
39
|
+
export declare class ErpOfflineQueue {
|
|
40
|
+
private baseFetch;
|
|
41
|
+
private queue;
|
|
42
|
+
private config;
|
|
43
|
+
private syncing;
|
|
44
|
+
private storageKey;
|
|
45
|
+
private nextId;
|
|
46
|
+
private boundOnline;
|
|
47
|
+
private boundOffline;
|
|
48
|
+
constructor(config?: ErpOfflineQueueConfig);
|
|
49
|
+
/** A fetch-compatible function that queues mutations when offline. */
|
|
50
|
+
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
51
|
+
/** Is the browser currently online? */
|
|
52
|
+
isOnline(): boolean;
|
|
53
|
+
/** Number of entries waiting to be synced. */
|
|
54
|
+
get pendingCount(): number;
|
|
55
|
+
/** Get a snapshot of the current queue. */
|
|
56
|
+
getQueue(): QueueEntry[];
|
|
57
|
+
/** Clear all pending entries without syncing. */
|
|
58
|
+
clear(): void;
|
|
59
|
+
/** Manually trigger sync (e.g. when you detect connectivity). */
|
|
60
|
+
sync(): Promise<SyncResult[]>;
|
|
61
|
+
/** Remove event listeners. */
|
|
62
|
+
destroy(): void;
|
|
63
|
+
private persistQueue;
|
|
64
|
+
private restoreQueue;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=ErpOfflineQueue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErpOfflineQueue.d.ts","sourceRoot":"","sources":["../src/ErpOfflineQueue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,qBAAqB;IAClC,iEAAiE;IACjE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,gEAAgE;IAChE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC;IACzC,qDAAqD;IACrD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACvC,8CAA8C;IAC9C,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3C,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACvB,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,eAAe;IACxB,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,YAAY,CAAa;gBAErB,MAAM,CAAC,EAAE,qBAAqB;IAyB1C,sEAAsE;IACtE,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;IAmCtE,uCAAuC;IACvC,QAAQ,IAAI,OAAO;IAInB,8CAA8C;IAC9C,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,2CAA2C;IAC3C,QAAQ,IAAI,UAAU,EAAE;IAIxB,iDAAiD;IACjD,KAAK,IAAI,IAAI;IAKb,iEAAiE;IAC3D,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IA2CnC,8BAA8B;IAC9B,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,YAAY;CAgBvB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ErpResponse } from './types';
|
|
2
|
+
import { ErpDataAdapter } from './ErpDataAdapter';
|
|
3
|
+
/** Pending mutation waiting for server confirmation. */
|
|
4
|
+
export interface PendingMutation<T = unknown> {
|
|
5
|
+
id: string;
|
|
6
|
+
type: "create" | "update" | "delete";
|
|
7
|
+
entityId?: string | number;
|
|
8
|
+
optimisticData?: T;
|
|
9
|
+
previousData?: T;
|
|
10
|
+
timestamp: number;
|
|
11
|
+
status: "pending" | "confirmed" | "failed";
|
|
12
|
+
error?: string;
|
|
13
|
+
}
|
|
14
|
+
export type OptimisticListener<T> = (items: T[], pending: PendingMutation<T>[]) => void;
|
|
15
|
+
export declare class ErpOptimisticStore<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
16
|
+
private adapter;
|
|
17
|
+
private items;
|
|
18
|
+
private keyField;
|
|
19
|
+
private mutations;
|
|
20
|
+
private listeners;
|
|
21
|
+
private nextMutationId;
|
|
22
|
+
constructor(adapter: ErpDataAdapter<T>, keyField?: string);
|
|
23
|
+
/** Subscribe to state changes. Returns unsubscribe function. */
|
|
24
|
+
subscribe(listener: OptimisticListener<T>): () => void;
|
|
25
|
+
private notify;
|
|
26
|
+
/** Current items including optimistic (unconfirmed) changes. */
|
|
27
|
+
getItems(): T[];
|
|
28
|
+
/** Pending mutations not yet confirmed by server. */
|
|
29
|
+
getPending(): PendingMutation<T>[];
|
|
30
|
+
/** Set initial data (e.g. after load()). */
|
|
31
|
+
setItems(items: T[]): void;
|
|
32
|
+
/** Load data from server and replace local state. */
|
|
33
|
+
load(...args: Parameters<ErpDataAdapter<T>["load"]>): Promise<ErpResponse<T[]>>;
|
|
34
|
+
/** Optimistically create an item. */
|
|
35
|
+
create(item: Partial<T>): Promise<ErpResponse<T>>;
|
|
36
|
+
/** Optimistically update an item. */
|
|
37
|
+
update(id: string | number, changes: Partial<T>): Promise<ErpResponse<T>>;
|
|
38
|
+
/** Optimistically delete an item. */
|
|
39
|
+
remove(id: string | number): Promise<ErpResponse<void>>;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=ErpOptimisticStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErpOptimisticStore.d.ts","sourceRoot":"","sources":["../src/ErpOptimisticStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,wDAAwD;AACxD,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,CAAC,CAAC;IACnB,YAAY,CAAC,EAAE,CAAC,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;AAExF,qBAAa,kBAAkB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACvF,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,cAAc,CAAK;gBAEf,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,QAAQ,SAAO;IAKvD,gEAAgE;IAChE,SAAS,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAKtD,OAAO,CAAC,MAAM;IAMd,gEAAgE;IAChE,QAAQ,IAAI,CAAC,EAAE;IAIf,qDAAqD;IACrD,UAAU,IAAI,eAAe,CAAC,CAAC,CAAC,EAAE;IAIlC,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI;IAK1B,qDAAqD;IAC/C,IAAI,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;IAUrF,qCAAqC;IAC/B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAgDvD,qCAAqC;IAC/B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IA0D/E,qCAAqC;IAC/B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;CA0ChE"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ErpRateLimiter — client-side rate limiting / throttling for ERP requests.
|
|
3
|
+
*
|
|
4
|
+
* Wraps fetch to enforce:
|
|
5
|
+
* - Maximum concurrent requests
|
|
6
|
+
* - Sliding window request rate
|
|
7
|
+
* - Automatic 429 back-off
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* const limiter = new ErpRateLimiter({ maxConcurrent: 4, maxPerSecond: 10 });
|
|
11
|
+
* const adapter = new ErpDataAdapter({ baseUrl: '/api/products', fetch: limiter.fetch });
|
|
12
|
+
*/
|
|
13
|
+
export interface ErpRateLimiterConfig {
|
|
14
|
+
/** Maximum concurrent in-flight requests (default: 6). */
|
|
15
|
+
maxConcurrent?: number;
|
|
16
|
+
/** Maximum requests per second (default: 20). */
|
|
17
|
+
maxPerSecond?: number;
|
|
18
|
+
/** Delay (ms) to wait after receiving a 429 response (default: 2000). */
|
|
19
|
+
backoffDelay?: number;
|
|
20
|
+
/** Base fetch implementation (default: globalThis.fetch). */
|
|
21
|
+
baseFetch?: typeof fetch;
|
|
22
|
+
}
|
|
23
|
+
export declare class ErpRateLimiter {
|
|
24
|
+
private maxConcurrent;
|
|
25
|
+
private maxPerSecond;
|
|
26
|
+
private backoffDelay;
|
|
27
|
+
private baseFetch;
|
|
28
|
+
private inFlight;
|
|
29
|
+
private timestamps;
|
|
30
|
+
private queue;
|
|
31
|
+
private processing;
|
|
32
|
+
private backingOff;
|
|
33
|
+
constructor(config?: ErpRateLimiterConfig);
|
|
34
|
+
/** A fetch-compatible function that respects rate limits. */
|
|
35
|
+
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
36
|
+
/** Number of requests currently waiting in the queue. */
|
|
37
|
+
get pending(): number;
|
|
38
|
+
/** Number of requests currently in flight. */
|
|
39
|
+
get active(): number;
|
|
40
|
+
private drain;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=ErpRateLimiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErpRateLimiter.d.ts","sourceRoot":"","sources":["../src/ErpRateLimiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,oBAAoB;IACjC,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC5B;AASD,qBAAa,cAAc;IACvB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,SAAS,CAAe;IAEhC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAS;gBAEf,MAAM,CAAC,EAAE,oBAAoB;IAUzC,6DAA6D;IAC7D,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;IAOtE,yDAAyD;IACzD,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,8CAA8C;IAC9C,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,OAAO,CAAC,KAAK;CAgEhB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErpAuthAdapter.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ErpAuthAdapter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErpDataAdapter.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ErpDataAdapter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErpExportAdapter.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ErpExportAdapter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErpFileAdapter.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ErpFileAdapter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErpOfflineQueue.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ErpOfflineQueue.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErpOptimisticStore.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ErpOptimisticStore.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErpRateLimiter.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ErpRateLimiter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/middleware.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registries.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/registries.test.ts"],"names":[],"mappings":""}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var g=Object.create;var c=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var v=Object.getPrototypeOf,S=Object.prototype.hasOwnProperty;var k=(r,e,a,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let l of V(e))!S.call(r,l)&&l!==a&&c(r,l,{get:()=>e[l],enumerable:!(t=w(e,l))||t.enumerable});return r};var P=(r,e,a)=>(a=r!=null?g(v(r)):{},k(e||!r||!r.__esModule?c(a,"default",{value:r,enumerable:!0}):a,r));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class A{constructor(e){this.cfg=typeof e=="string"?{baseUrl:e}:e}async request(e,a){const t=this.cfg.fetch??globalThis.fetch,l={"Content-Type":"application/json",...this.cfg.headers};if(this.cfg.tokenFactory){const n=await this.cfg.tokenFactory();l.Authorization=`Bearer ${n}`}const o=await t(`${this.cfg.baseUrl}${e}`,{...a,headers:{...l,...a==null?void 0:a.headers}});if(!o.ok)throw new Error(`ERP request failed: ${o.status} ${o.statusText}`);return o.json()}async load(e){var l,o;const a=new URLSearchParams;(e==null?void 0:e.skip)!=null&&a.set("skip",String(e.skip)),(e==null?void 0:e.take)!=null&&a.set("take",String(e.take)),e!=null&&e.search&&a.set("search",e.search),(l=e==null?void 0:e.sort)!=null&&l.length&&a.set("sort",JSON.stringify(e.sort)),(o=e==null?void 0:e.filters)!=null&&o.length&&a.set("filters",JSON.stringify(e.filters));const t=a.toString();return this.request(t?`?${t}`:"")}async getById(e){return this.request(`/${e}`)}async create(e){return this.request("",{method:"POST",body:JSON.stringify(e)})}async update(e,a){return this.request(`/${e}`,{method:"PUT",body:JSON.stringify(a)})}async remove(e){return this.request(`/${e}`,{method:"DELETE"})}async removeBatch(e){return this.request("/batch-delete",{method:"POST",body:JSON.stringify({ids:e})})}}async function T(r){const e=await import("@microsoft/signalr");let a="disconnected";const t=new Set,l=s=>{a=s,t.forEach(u=>u(s))},n=new e.HubConnectionBuilder().withUrl(r.hubUrl,{accessTokenFactory:r.accessTokenFactory?()=>r.accessTokenFactory():void 0}).withAutomaticReconnect().build();return n.onreconnecting(()=>l("reconnecting")),n.onreconnected(()=>l("connected")),n.onclose(()=>l("disconnected")),{get status(){return a},async start(){l("connecting"),await n.start(),l("connected")},async stop(){await n.stop(),l("disconnected")},on(s,u){n.on(s,u)},off(s,u){n.off(s,u)},invoke(s,...u){return n.invoke(s,...u)},onStatusChange(s){return t.add(s),()=>t.delete(s)}}}class R{constructor(e){this.accessToken=null,this.refreshToken=null,this.tokenFactory=async()=>{if(!this.accessToken)throw new Error("Not authenticated");return this.accessToken},this.cfg=e}getAccessToken(){return this.accessToken}async post(e,a){const l=await(this.cfg.fetch??globalThis.fetch)(`${this.cfg.baseUrl}${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!l.ok)throw new Error(`Auth request failed: ${l.status}`);return l.json()}async login(e){var t,l;const a=await this.post("/login",e);return a.token&&(this.accessToken=a.token,this.refreshToken=a.refreshToken??null,(l=(t=this.cfg).onTokens)==null||l.call(t,a.token,a.refreshToken??"")),a}async refresh(){var a,t;if(!this.refreshToken)throw new Error("No refresh token");const e=await this.post("/refresh",{refreshToken:this.refreshToken});return e.token&&(this.accessToken=e.token,this.refreshToken=e.refreshToken??this.refreshToken,(t=(a=this.cfg).onTokens)==null||t.call(a,e.token,this.refreshToken)),e}async me(){const a=await(this.cfg.fetch??globalThis.fetch)(`${this.cfg.baseUrl}/me`,{headers:{Authorization:`Bearer ${this.accessToken}`}});if(!a.ok)throw new Error(`Auth /me failed: ${a.status}`);return a.json()}async logout(){try{await(this.cfg.fetch??globalThis.fetch)(`${this.cfg.baseUrl}/logout`,{method:"POST",headers:{Authorization:`Bearer ${this.accessToken}`}})}finally{this.accessToken=null,this.refreshToken=null}}}class C{constructor(e){this.cfg=e}async headers(){const e={};return this.cfg.tokenFactory&&(e.Authorization=`Bearer ${await this.cfg.tokenFactory()}`),e}async upload(e,a){const t=this.cfg.fetch??globalThis.fetch,l=new FormData;l.append("file",e),a&&l.append("folder",a);const o=await t(this.cfg.baseUrl,{method:"POST",headers:await this.headers(),body:l});if(!o.ok)throw new Error(`File upload failed: ${o.status}`);return o.json()}async uploadMultiple(e,a){const t=this.cfg.fetch??globalThis.fetch,l=new FormData;e.forEach(n=>l.append("files",n)),a&&l.append("folder",a);const o=await t(`${this.cfg.baseUrl}/batch`,{method:"POST",headers:await this.headers(),body:l});if(!o.ok)throw new Error(`Batch upload failed: ${o.status}`);return o.json()}async getInfo(e){const t=await(this.cfg.fetch??globalThis.fetch)(`${this.cfg.baseUrl}/${e}/info`,{headers:{...await this.headers(),"Content-Type":"application/json"}});if(!t.ok)throw new Error(`File info failed: ${t.status}`);return t.json()}async getDownloadUrl(e){const t=await(this.cfg.fetch??globalThis.fetch)(`${this.cfg.baseUrl}/${e}`,{headers:await this.headers()});if(!t.ok)throw new Error(`File download failed: ${t.status}`);const l=await t.blob();return URL.createObjectURL(l)}async remove(e){const t=await(this.cfg.fetch??globalThis.fetch)(`${this.cfg.baseUrl}/${e}`,{method:"DELETE",headers:{...await this.headers(),"Content-Type":"application/json"}});if(!t.ok)throw new Error(`File delete failed: ${t.status}`);return t.json()}}class E{constructor(e){this.cfg=e}async headers(){const e={"Content-Type":"application/json"};return this.cfg.tokenFactory&&(e.Authorization=`Bearer ${await this.cfg.tokenFactory()}`),e}async requestExport(e){const t=await(this.cfg.fetch??globalThis.fetch)(this.cfg.baseUrl,{method:"POST",headers:await this.headers(),body:JSON.stringify(e)});if(!t.ok)throw new Error(`Export request failed: ${t.status}`);return t.json()}async download(e){const t=await(this.cfg.fetch??globalThis.fetch)(e,{headers:await this.headers()});if(!t.ok)throw new Error(`Export download failed: ${t.status}`);return t.blob()}async downloadToFile(e,a){var i;const t=await this.requestExport(e);if(!((i=t.data)!=null&&i.downloadUrl))throw new Error("No download URL returned");const l=await this.download(t.data.downloadUrl),o=URL.createObjectURL(l),n=document.createElement("a");n.href=o,n.download=a??`export.${e.format}`,document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(o)}}const p=[{type:"NiceAudioPlayer",label:"Audio Player",category:"Audio",icon:"music",defaultProps:{src:"",autoplay:!1,showWaveform:!0},propDescriptors:[{name:"src",type:"string",label:"Audio source URL"},{name:"autoplay",type:"boolean",label:"Auto-play",defaultValue:!1},{name:"loop",type:"boolean",label:"Loop",defaultValue:!1},{name:"showWaveform",type:"boolean",label:"Show waveform",defaultValue:!0},{name:"showPlaylist",type:"boolean",label:"Show playlist",defaultValue:!1},{name:"visualizerMode",type:"select",label:"Visualizer mode",options:[{label:"None",value:"none"},{label:"Bars",value:"bars"},{label:"Wave",value:"wave"},{label:"Circle",value:"circle"}],defaultValue:"bars"},{name:"height",type:"size",label:"Height",group:"Layout"}]},{type:"NiceWaveform",label:"Waveform",category:"Audio",icon:"waveform",defaultProps:{peaks:[],color:"#4a90d9"},propDescriptors:[{name:"peaks",type:"json",label:"Peak data (JSON array)"},{name:"color",type:"color",label:"Waveform color",defaultValue:"#4a90d9"},{name:"progressColor",type:"color",label:"Progress color",defaultValue:"#1b5e20"},{name:"barWidth",type:"number",label:"Bar width (px)",min:1,max:10,step:1,defaultValue:2},{name:"height",type:"size",label:"Height",group:"Layout"},{name:"interactive",type:"boolean",label:"Allow seeking",defaultValue:!0}]},{type:"NicePianoRoll",label:"Piano Roll",category:"Audio",icon:"piano",defaultProps:{notes:[],octaves:4,startOctave:3},propDescriptors:[{name:"notes",type:"json",label:"MIDI notes (JSON)"},{name:"octaves",type:"number",label:"Visible octaves",min:1,max:8,defaultValue:4},{name:"startOctave",type:"number",label:"Start octave",min:0,max:8,defaultValue:3},{name:"quantize",type:"select",label:"Quantize",options:[{label:"1/4",value:"4"},{label:"1/8",value:"8"},{label:"1/16",value:"16"},{label:"1/32",value:"32"}],defaultValue:"16"},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1},{name:"height",type:"size",label:"Height",group:"Layout"}]},{type:"NiceKaraoke",label:"Karaoke",category:"Audio",icon:"microphone",defaultProps:{lyrics:[],audioSrc:""},propDescriptors:[{name:"audioSrc",type:"string",label:"Audio source URL"},{name:"lyrics",type:"json",label:"Lyrics (JSON array of {time, text})"},{name:"showScore",type:"boolean",label:"Show score",defaultValue:!0},{name:"pitchDetection",type:"boolean",label:"Pitch detection",defaultValue:!0},{name:"highlightColor",type:"color",label:"Highlight color",defaultValue:"#ffd700"},{name:"fontSize",type:"size",label:"Font size",group:"Typography"}]}],d=[{type:"NicePixelEditor",label:"Pixel Editor",category:"Graphics",icon:"grid",defaultProps:{width:32,height:32,palette:[]},propDescriptors:[{name:"width",type:"number",label:"Canvas width (px)",min:1,max:256,defaultValue:32},{name:"height",type:"number",label:"Canvas height (px)",min:1,max:256,defaultValue:32},{name:"palette",type:"json",label:"Color palette (JSON array)"},{name:"gridVisible",type:"boolean",label:"Show grid",defaultValue:!0},{name:"zoom",type:"number",label:"Zoom level",min:1,max:32,step:1,defaultValue:8},{name:"layers",type:"boolean",label:"Enable layers",defaultValue:!0},{name:"onion",type:"boolean",label:"Onion skin (animation)",defaultValue:!1}]},{type:"NiceVectorEditor",label:"Vector Editor",category:"Graphics",icon:"pen-tool",defaultProps:{width:800,height:600},propDescriptors:[{name:"width",type:"number",label:"Canvas width",min:100,max:4096,defaultValue:800,group:"Layout"},{name:"height",type:"number",label:"Canvas height",min:100,max:4096,defaultValue:600,group:"Layout"},{name:"showRulers",type:"boolean",label:"Show rulers",defaultValue:!0},{name:"snapToGrid",type:"boolean",label:"Snap to grid",defaultValue:!0},{name:"gridSize",type:"number",label:"Grid size",min:1,max:100,defaultValue:10},{name:"fillColor",type:"color",label:"Default fill",defaultValue:"#ffffff"},{name:"strokeColor",type:"color",label:"Default stroke",defaultValue:"#000000"},{name:"strokeWidth",type:"number",label:"Stroke width",min:0,max:20,step:.5,defaultValue:1}]},{type:"NicePhotoEditor",label:"Photo Editor",category:"Graphics",icon:"image",defaultProps:{src:""},propDescriptors:[{name:"src",type:"string",label:"Image source URL"},{name:"crop",type:"boolean",label:"Allow crop",defaultValue:!0},{name:"rotate",type:"boolean",label:"Allow rotate",defaultValue:!0},{name:"filters",type:"boolean",label:"Show filters",defaultValue:!0},{name:"adjustments",type:"boolean",label:"Show adjustments",defaultValue:!0},{name:"text",type:"boolean",label:"Allow text overlay",defaultValue:!0},{name:"outputFormat",type:"select",label:"Output format",options:[{label:"PNG",value:"png"},{label:"JPEG",value:"jpeg"},{label:"WebP",value:"webp"}],defaultValue:"png"},{name:"maxWidth",type:"number",label:"Max output width",min:100,max:8192,group:"Output"}]}],b=[{type:"NiceModelEditor",label:"3D Model Editor",category:"3D",icon:"cube",defaultProps:{modelUrl:""},propDescriptors:[{name:"modelUrl",type:"string",label:"Model URL (.glb / .gltf)"},{name:"environmentMap",type:"select",label:"Environment",options:[{label:"Studio",value:"studio"},{label:"Outdoor",value:"outdoor"},{label:"Warehouse",value:"warehouse"},{label:"None",value:"none"}],defaultValue:"studio"},{name:"showGrid",type:"boolean",label:"Show grid",defaultValue:!0},{name:"showAxes",type:"boolean",label:"Show axes",defaultValue:!0},{name:"enablePhysics",type:"boolean",label:"Enable physics",defaultValue:!1},{name:"wireframe",type:"boolean",label:"Wireframe mode",defaultValue:!1},{name:"backgroundColor",type:"color",label:"Background",defaultValue:"#1a1a2e"},{name:"height",type:"size",label:"Viewport height",group:"Layout"}]},{type:"NiceModelViewer",label:"3D Model Viewer",category:"3D",icon:"eye",defaultProps:{modelUrl:"",autoRotate:!0},propDescriptors:[{name:"modelUrl",type:"string",label:"Model URL (.glb / .gltf)"},{name:"autoRotate",type:"boolean",label:"Auto-rotate",defaultValue:!0},{name:"rotateSpeed",type:"number",label:"Rotate speed",min:.1,max:10,step:.1,defaultValue:1},{name:"zoom",type:"boolean",label:"Allow zoom",defaultValue:!0},{name:"pan",type:"boolean",label:"Allow pan",defaultValue:!0},{name:"environmentMap",type:"select",label:"Environment",options:[{label:"Studio",value:"studio"},{label:"Outdoor",value:"outdoor"},{label:"Warehouse",value:"warehouse"},{label:"None",value:"none"}],defaultValue:"studio"},{name:"backgroundColor",type:"color",label:"Background",defaultValue:"#1a1a2e"},{name:"showAnnotations",type:"boolean",label:"Show annotations",defaultValue:!1},{name:"height",type:"size",label:"Viewport height",group:"Layout"}]}],h=[{type:"NiceLeaderboard",label:"Leaderboard",category:"Gamification",icon:"trophy",defaultProps:{dataSource:[],maxRows:10},propDescriptors:[{name:"dataSource",type:"json",label:"Data source (JSON)"},{name:"maxRows",type:"number",label:"Max visible rows",min:3,max:100,defaultValue:10},{name:"showRank",type:"boolean",label:"Show rank column",defaultValue:!0},{name:"showAvatar",type:"boolean",label:"Show avatar",defaultValue:!0},{name:"highlightCurrentUser",type:"boolean",label:"Highlight current user",defaultValue:!0},{name:"scoreField",type:"string",label:"Score field name",defaultValue:"score"},{name:"nameField",type:"string",label:"Name field name",defaultValue:"name"},{name:"variant",type:"variant",label:"Visual style",defaultValue:"default"}]},{type:"NiceAchievement",label:"Achievement Badge",category:"Gamification",icon:"award",defaultProps:{title:"Achievement",unlocked:!1},propDescriptors:[{name:"title",type:"string",label:"Achievement title",defaultValue:"Achievement"},{name:"description",type:"string",label:"Description"},{name:"icon",type:"string",label:"Icon URL"},{name:"unlocked",type:"boolean",label:"Unlocked",defaultValue:!1},{name:"progress",type:"number",label:"Progress (0-100)",min:0,max:100,defaultValue:0},{name:"rarity",type:"select",label:"Rarity",options:[{label:"Common",value:"common"},{label:"Rare",value:"rare"},{label:"Epic",value:"epic"},{label:"Legendary",value:"legendary"}],defaultValue:"common"},{name:"size",type:"size",label:"Badge size",group:"Layout"}]},{type:"NiceQuest",label:"Quest Tracker",category:"Gamification",icon:"map",defaultProps:{title:"Quest",steps:[]},propDescriptors:[{name:"title",type:"string",label:"Quest title",defaultValue:"Quest"},{name:"description",type:"string",label:"Quest description"},{name:"steps",type:"json",label:"Steps (JSON array of {title, completed})"},{name:"reward",type:"string",label:"Reward description"},{name:"rewardXP",type:"number",label:"Reward XP",min:0,defaultValue:100},{name:"showProgress",type:"boolean",label:"Show progress bar",defaultValue:!0},{name:"variant",type:"variant",label:"Visual style",defaultValue:"default"}]},{type:"NiceXPBar",label:"XP Progress Bar",category:"Gamification",icon:"zap",defaultProps:{currentXP:0,maxXP:1e3,level:1},propDescriptors:[{name:"currentXP",type:"number",label:"Current XP",min:0,defaultValue:0},{name:"maxXP",type:"number",label:"Max XP (next level)",min:1,defaultValue:1e3},{name:"level",type:"number",label:"Current level",min:1,defaultValue:1},{name:"showLabel",type:"boolean",label:"Show XP label",defaultValue:!0},{name:"showLevel",type:"boolean",label:"Show level badge",defaultValue:!0},{name:"color",type:"color",label:"Bar color",defaultValue:"#4caf50"},{name:"animated",type:"boolean",label:"Animate changes",defaultValue:!0},{name:"height",type:"size",label:"Bar height",group:"Layout"}]}],m=[{type:"NiceAddress",label:"Address Editor",category:"Business",icon:"map-pin",defaultProps:{country:"PL"},propDescriptors:[{name:"street",type:"string",label:"Street",group:"Address"},{name:"city",type:"string",label:"City",group:"Address"},{name:"postalCode",type:"string",label:"Postal code",group:"Address"},{name:"country",type:"select",label:"Country",options:[{label:"Poland",value:"PL"},{label:"Germany",value:"DE"},{label:"USA",value:"US"},{label:"UK",value:"GB"},{label:"France",value:"FR"}],defaultValue:"PL",group:"Address"},{name:"showMap",type:"boolean",label:"Show map preview",defaultValue:!1},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]},{type:"NicePhone",label:"Phone Input",category:"Business",icon:"phone",defaultProps:{countryCode:"+48"},propDescriptors:[{name:"value",type:"string",label:"Phone number"},{name:"countryCode",type:"string",label:"Default country code",defaultValue:"+48"},{name:"showFlag",type:"boolean",label:"Show country flag",defaultValue:!0},{name:"format",type:"select",label:"Format",options:[{label:"International",value:"international"},{label:"National",value:"national"},{label:"E.164",value:"e164"}],defaultValue:"international"},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]},{type:"NiceCurrency",label:"Currency Input",category:"Business",icon:"dollar-sign",defaultProps:{currency:"PLN",decimals:2},propDescriptors:[{name:"value",type:"number",label:"Amount",defaultValue:0},{name:"currency",type:"select",label:"Currency",options:[{label:"PLN",value:"PLN"},{label:"EUR",value:"EUR"},{label:"USD",value:"USD"},{label:"GBP",value:"GBP"}],defaultValue:"PLN"},{name:"decimals",type:"number",label:"Decimal places",min:0,max:4,defaultValue:2},{name:"showCurrencySymbol",type:"boolean",label:"Show symbol",defaultValue:!0},{name:"thousandSeparator",type:"boolean",label:"Thousand separator",defaultValue:!0},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]},{type:"NiceVAT",label:"VAT Input",category:"Business",icon:"percent",defaultProps:{rate:23,country:"PL"},propDescriptors:[{name:"netValue",type:"number",label:"Net value",defaultValue:0,group:"Values"},{name:"rate",type:"number",label:"VAT rate (%)",min:0,max:100,defaultValue:23,group:"Values"},{name:"country",type:"select",label:"Country",options:[{label:"Poland",value:"PL"},{label:"Germany",value:"DE"},{label:"France",value:"FR"}],defaultValue:"PL"},{name:"showGross",type:"boolean",label:"Show gross value",defaultValue:!0},{name:"showVatAmount",type:"boolean",label:"Show VAT amount",defaultValue:!0},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]},{type:"NiceInvoiceLines",label:"Invoice Lines",category:"Business",icon:"file-text",defaultProps:{lines:[],currency:"PLN"},propDescriptors:[{name:"lines",type:"json",label:"Invoice lines (JSON)"},{name:"currency",type:"select",label:"Currency",options:[{label:"PLN",value:"PLN"},{label:"EUR",value:"EUR"},{label:"USD",value:"USD"}],defaultValue:"PLN"},{name:"showVAT",type:"boolean",label:"Show VAT column",defaultValue:!0},{name:"showDiscount",type:"boolean",label:"Show discount column",defaultValue:!1},{name:"showTotal",type:"boolean",label:"Show totals row",defaultValue:!0},{name:"editable",type:"boolean",label:"Editable",defaultValue:!0},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]}],y=[{type:"NiceLoginForm",label:"Login Form",category:"Auth",icon:"log-in",defaultProps:{showRemember:!0,showForgotPassword:!0},propDescriptors:[{name:"title",type:"string",label:"Form title",defaultValue:"Sign In"},{name:"showRemember",type:"boolean",label:"Show 'Remember me'",defaultValue:!0},{name:"showForgotPassword",type:"boolean",label:"Show 'Forgot password'",defaultValue:!0},{name:"showRegisterLink",type:"boolean",label:"Show register link",defaultValue:!1},{name:"showLogo",type:"boolean",label:"Show logo",defaultValue:!0},{name:"logoUrl",type:"string",label:"Logo URL",group:"Branding"},{name:"primaryColor",type:"color",label:"Primary color",defaultValue:"#1976d2",group:"Branding"},{name:"variant",type:"variant",label:"Visual style",defaultValue:"card"}]},{type:"NiceCaptcha",label:"Captcha",category:"Auth",icon:"shield",defaultProps:{provider:"recaptcha",size:"normal"},propDescriptors:[{name:"provider",type:"select",label:"Provider",options:[{label:"reCAPTCHA v2",value:"recaptcha"},{label:"reCAPTCHA v3",value:"recaptcha-v3"},{label:"hCaptcha",value:"hcaptcha"},{label:"Turnstile",value:"turnstile"}],defaultValue:"recaptcha"},{name:"siteKey",type:"string",label:"Site key"},{name:"size",type:"select",label:"Size",options:[{label:"Normal",value:"normal"},{label:"Compact",value:"compact"},{label:"Invisible",value:"invisible"}],defaultValue:"normal"},{name:"theme",type:"select",label:"Theme",options:[{label:"Light",value:"light"},{label:"Dark",value:"dark"}],defaultValue:"light"}]},{type:"Nice2FASetup",label:"2FA Setup",category:"Auth",icon:"key",defaultProps:{method:"totp"},propDescriptors:[{name:"method",type:"select",label:"2FA method",options:[{label:"TOTP (Authenticator)",value:"totp"},{label:"SMS",value:"sms"},{label:"Email",value:"email"}],defaultValue:"totp"},{name:"issuer",type:"string",label:"Issuer name",defaultValue:"OmniVerk"},{name:"showBackupCodes",type:"boolean",label:"Show backup codes",defaultValue:!0},{name:"showQR",type:"boolean",label:"Show QR code",defaultValue:!0},{name:"codeLength",type:"number",label:"Code length",min:4,max:8,defaultValue:6}]}],f=[{type:"NiceComments",label:"Comments",category:"Social",icon:"message-circle",defaultProps:{threadId:"",allowReplies:!0},propDescriptors:[{name:"threadId",type:"string",label:"Thread ID / entity ID"},{name:"allowReplies",type:"boolean",label:"Allow replies (nested)",defaultValue:!0},{name:"maxDepth",type:"number",label:"Max nesting depth",min:1,max:10,defaultValue:3},{name:"sortOrder",type:"select",label:"Default sort",options:[{label:"Newest first",value:"newest"},{label:"Oldest first",value:"oldest"},{label:"Most liked",value:"popular"}],defaultValue:"newest"},{name:"allowReactions",type:"boolean",label:"Allow reactions",defaultValue:!0},{name:"showAvatar",type:"boolean",label:"Show avatars",defaultValue:!0},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]},{type:"NiceRatings",label:"Ratings",category:"Social",icon:"star",defaultProps:{maxStars:5,allowHalf:!0},propDescriptors:[{name:"value",type:"number",label:"Current rating",min:0,max:10,step:.5,defaultValue:0},{name:"maxStars",type:"number",label:"Maximum stars",min:3,max:10,defaultValue:5},{name:"allowHalf",type:"boolean",label:"Allow half stars",defaultValue:!0},{name:"showCount",type:"boolean",label:"Show vote count",defaultValue:!0},{name:"showAverage",type:"boolean",label:"Show average",defaultValue:!0},{name:"color",type:"color",label:"Star color",defaultValue:"#ffc107"},{name:"size",type:"size",label:"Star size",group:"Layout"},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]},{type:"NiceWiki",label:"Wiki Editor",category:"Social",icon:"book",defaultProps:{content:"",showTOC:!0},propDescriptors:[{name:"content",type:"string",label:"Initial content (Markdown)"},{name:"showTOC",type:"boolean",label:"Show table of contents",defaultValue:!0},{name:"showHistory",type:"boolean",label:"Show version history",defaultValue:!0},{name:"allowEdit",type:"boolean",label:"Allow editing",defaultValue:!0},{name:"showToolbar",type:"boolean",label:"Show Markdown toolbar",defaultValue:!0},{name:"previewMode",type:"select",label:"Preview mode",options:[{label:"Side by side",value:"split"},{label:"Tab switch",value:"tabs"},{label:"Live preview",value:"live"}],defaultValue:"split"},{name:"maxLength",type:"number",label:"Max content length",min:0,defaultValue:0}]}],L=[...p,...d,...b,...h,...m,...y,...f];exports.ErpAuthAdapter=R;exports.ErpDataAdapter=A;exports.ErpExportAdapter=E;exports.ErpFileAdapter=C;exports.allControlRegistries=L;exports.audioControlRegistry=p;exports.authControlRegistry=y;exports.businessControlRegistry=m;exports.createSignalRAdapter=T;exports.gamificationControlRegistry=h;exports.graphicControlRegistry=d;exports.socialControlRegistry=f;exports.threeControlRegistry=b;
|
|
1
|
+
"use strict";var we=Object.create;var le=Object.defineProperty;var ve=Object.getOwnPropertyDescriptor;var ke=Object.getOwnPropertyNames;var Se=Object.getPrototypeOf,Ce=Object.prototype.hasOwnProperty;var Ee=(i,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of ke(e))!Ce.call(i,a)&&a!==t&&le(i,a,{get:()=>e[a],enumerable:!(n=ve(e,a))||n.enumerable});return i};var Ve=(i,e,t)=>(t=i!=null?we(Se(i)):{},Ee(e||!i||!i.__esModule?le(t,"default",{value:i,enumerable:!0}):t,i));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react");class Pe{constructor(e){this.cfg=typeof e=="string"?{baseUrl:e}:e}async request(e,t){const n=this.cfg.fetch??globalThis.fetch,a={"Content-Type":"application/json",...this.cfg.headers};if(this.cfg.tokenFactory){const s=await this.cfg.tokenFactory();a.Authorization=`Bearer ${s}`}const r=await n(`${this.cfg.baseUrl}${e}`,{...t,headers:{...a,...t==null?void 0:t.headers}});if(!r.ok)throw new Error(`ERP request failed: ${r.status} ${r.statusText}`);return r.json()}async load(e){var a,r;const t=new URLSearchParams;(e==null?void 0:e.skip)!=null&&t.set("skip",String(e.skip)),(e==null?void 0:e.take)!=null&&t.set("take",String(e.take)),e!=null&&e.search&&t.set("search",e.search),(a=e==null?void 0:e.sort)!=null&&a.length&&t.set("sort",JSON.stringify(e.sort)),(r=e==null?void 0:e.filters)!=null&&r.length&&t.set("filters",JSON.stringify(e.filters));const n=t.toString();return this.request(n?`?${n}`:"")}async getById(e){return this.request(`/${e}`)}async create(e){return this.request("",{method:"POST",body:JSON.stringify(e)})}async update(e,t){return this.request(`/${e}`,{method:"PUT",body:JSON.stringify(t)})}async remove(e){return this.request(`/${e}`,{method:"DELETE"})}async removeBatch(e){return this.request("/batch-delete",{method:"POST",body:JSON.stringify({ids:e})})}async createBatch(e){return this.request("/batch",{method:"POST",body:JSON.stringify({items:e})})}async updateBatch(e){return this.request("/batch",{method:"PUT",body:JSON.stringify({items:e})})}async patch(e,t){return this.request(`/${e}`,{method:"PATCH",body:JSON.stringify(t)})}}async function Te(i){const e=await import("@microsoft/signalr");let t="disconnected";const n=new Set,a=c=>{t=c,n.forEach(m=>m(c))},s=new e.HubConnectionBuilder().withUrl(i.hubUrl,{accessTokenFactory:i.accessTokenFactory?()=>i.accessTokenFactory():void 0}).withAutomaticReconnect().build();return s.onreconnecting(()=>a("reconnecting")),s.onreconnected(()=>a("connected")),s.onclose(()=>a("disconnected")),{get status(){return t},async start(){a("connecting"),await s.start(),a("connected")},async stop(){await s.stop(),a("disconnected")},on(c,m){s.on(c,m)},off(c,m){s.off(c,m)},invoke(c,...m){return s.invoke(c,...m)},onStatusChange(c){return n.add(c),()=>n.delete(c)}}}function ie(i){const{adapter:e,entityName:t,keyField:n,initialData:a=[],onBeforeChange:r,onAfterChange:s,onConflict:l,subscribeMethod:c="SubscribeToEntity",unsubscribeMethod:m="UnsubscribeFromEntity",changeEventName:b="EntityChanged",flashChanges:y=!0,flashDuration:E=500,optimisticUpdates:V=!0}=i,[J,L]=o.useState(a),[H,z]=o.useState(e.status),[Q,O]=o.useState(new Set),[q,x]=o.useState(new Set),[W,X]=o.useState(null),K=o.useRef(new Map),N=o.useRef(new Map),_=o.useCallback((h,v)=>{const{operation:C,key:S,data:g,changes:F}=v;switch(C){case"insert":return!g||h.some(A=>A[n]===S)?h:[...h,g];case"update":return h.map(A=>{if(A[n]!==S)return A;const G=K.current.get(S);if(G&&l){const Y=l({...A,...G.changes},g??{...A,...F},v);return Y==="local"?{...A,...G.changes}:Y==="remote"?(K.current.delete(S),g??{...A,...F}):Y==="merge"?{...A,...F,...G.changes}:Y}return g||{...A,...F}});case"delete":return h.filter(A=>A[n]!==S);default:return h}},[n,l]),I=o.useCallback(h=>{if(!y)return;const v=N.current.get(h);v&&clearTimeout(v),O(S=>new Set([...S,h]));const C=setTimeout(()=>{O(S=>{const g=new Set(S);return g.delete(h),g}),N.current.delete(h)},E);N.current.set(h,C)},[y,E]),$=o.useCallback(async h=>{h.entityName===t&&(r&&!await r(h)||(L(v=>{const C=_(v,h);return s==null||s(h,C),C}),I(h.key)))},[t,r,_,s,I]),P=o.useCallback(h=>{$(h)},[$]),ne=o.useCallback((h,v)=>{if(!V)return;const C=J.find(S=>S[n]===h);C&&(K.current.set(h,{original:C,changes:v}),x(S=>new Set([...S,h])))},[J,n,V]),B=o.useCallback(h=>{K.current.delete(h),x(v=>{const C=new Set(v);return C.delete(h),C})},[]),U=o.useCallback(h=>{const v=K.current.get(h);v&&(L(C=>C.map(S=>S[n]===h?v.original:S)),K.current.delete(h),x(C=>{const S=new Set(C);return S.delete(h),S}))},[n]),Z=o.useCallback(async()=>{if(e.status==="connected")try{await e.invoke(c,t),X(null)}catch(h){X(h instanceof Error?h:new Error(String(h)))}},[e,c,t]),ee=o.useCallback(async()=>{if(e.status==="connected")try{await e.invoke(m,t)}catch{}},[e,m,t]);return o.useEffect(()=>{const h=e.onStatusChange(v=>{z(v),v==="connected"&&Z()});return e.on(b,$),e.status==="connected"&&Z(),()=>{h(),e.off(b,$),ee(),N.current.forEach(v=>clearTimeout(v)),N.current.clear()}},[e,b,$,Z,ee]),o.useEffect(()=>{L(a)},[a]),{data:J,status:H,flashedKeys:Q,pendingKeys:q,error:W,applyRemoteUpdate:P,registerPendingChange:ne,confirmPendingChange:B,rollbackPendingChange:U,resubscribe:Z}}function Re(i){const{adapter:e,entityName:t,keyField:n,fetchMethod:a="GetEntities",insertMethod:r="InsertEntity",updateMethod:s="UpdateEntity",deleteMethod:l="DeleteEntity"}=i;return{async fetchAll(c){return e.invoke(a,t,c)},async insert(c){return e.invoke(r,t,c)},async update(c,m){return e.invoke(s,t,c,m)},async remove(c){return e.invoke(l,t,c)},getKeyField(){return n}}}function xe(i,e,t){const n=new Map(i.map(a=>[a[t],a]));for(const a of e)switch(a.operation){case"insert":a.data&&!n.has(a.key)&&n.set(a.key,a.data);break;case"update":if(n.has(a.key)){const r=n.get(a.key);n.set(a.key,a.data??{...r,...a.changes})}break;case"delete":n.delete(a.key);break}return Array.from(n.values())}function ue(i){const{adapter:e,entityType:t,entityId:n,currentUser:a,initialStatus:r="viewing",heartbeatInterval:s=3e4,idleTimeout:l=6e4,awayTimeout:c=3e5,joinMethod:m="JoinEntityView",leaveMethod:b="LeaveEntityView",updateMethod:y="UpdateEntityPresence",presenceEventName:E="EntityPresenceChanged",joinedEventName:V="EntityUserJoined",leftEventName:J="EntityUserLeft",onPresenceChange:L,onEditConflict:H}=i,[z,Q]=o.useState([]),[O,q]=o.useState(r),[x,W]=o.useState(),[X,K]=o.useState(e.status),N=o.useRef(Date.now()),_=o.useRef(null),I=o.useRef(null),$=o.useRef(null),P=Array.isArray(n)?n:[n],ne=`${t}:${P.sort().join(",")}`,B=o.useCallback(async(d,k,w)=>{if(e.status==="connected")try{await e.invoke(y,{entityType:t,entityIds:P,userId:a.id,status:d,editingField:k,selection:w,timestamp:new Date().toISOString()})}catch{}},[e,y,t,P,a.id]),U=o.useCallback((d,k)=>{q(d),W(k),B(d,k),N.current=Date.now()},[B]),Z=o.useCallback(d=>{const k=z.find(w=>w.user.id!==a.id&&w.status==="editing"&&w.editingField===d);k&&(H==null||H(k.user,d)),U("editing",d)},[z,a.id,H,U]),ee=o.useCallback(()=>{U("viewing",void 0)},[U]),h=o.useCallback(d=>{B(O,x,d),N.current=Date.now()},[B,O,x]),v=o.useCallback(d=>{const k=z.find(w=>w.user.id!==a.id&&w.status==="editing"&&w.editingField===d);return(k==null?void 0:k.user)??null},[z,a.id]),C=o.useCallback(d=>{const k=z.find(w=>w.status==="editing"&&w.editingField===d);return(k==null?void 0:k.user)??null},[z]),S=o.useCallback(async()=>{if(e.status==="connected")try{const d=await e.invoke("GetEntityPresence",t,P);Array.isArray(d)&&(Q(d),L==null||L(d))}catch{}},[e,t,P,L]),g=o.useCallback(()=>{N.current=Date.now(),I.current&&clearTimeout(I.current),$.current&&clearTimeout($.current),(O==="idle"||O==="away")&&U(x?"editing":"viewing",x),I.current=setTimeout(()=>{U("idle",x)},l),$.current=setTimeout(()=>{U("away",x)},c)},[O,x,l,c,U]),F=o.useCallback(d=>{d.entityType!==t||!d.entityIds.some(w=>P.includes(w))||(Q(d.presence.filter(w=>w.user.id!==a.id)),L==null||L(d.presence))},[t,P,a.id,L]),A=o.useCallback(d=>{d.entityType!==t||!d.entityIds.some(w=>P.includes(w))||d.presence.user.id===a.id||Q(w=>{const te=w.findIndex(ae=>ae.user.id===d.presence.user.id);if(te>=0){const ae=[...w];return ae[te]=d.presence,ae}return[...w,d.presence]})},[t,P,a.id]),G=o.useCallback(d=>{d.entityType!==t||!d.entityIds.some(w=>P.includes(w))||Q(w=>w.filter(te=>te.user.id!==d.userId))},[t,P]);o.useEffect(()=>{const d=e.onStatusChange(K);e.on(E,F),e.on(V,A),e.on(J,G);const k=async()=>{if(e.status==="connected")try{await e.invoke(m,{entityType:t,entityIds:P,user:a,status:O}),await S()}catch{}};return e.status==="connected"&&k(),()=>{d(),e.off(E,F),e.off(V,A),e.off(J,G),e.status==="connected"&&e.invoke(b,{entityType:t,entityIds:P,userId:a.id}).catch(()=>{})}},[e,ne,m,b,E,V,J,F,A,G,S,a,O,t,P]),o.useEffect(()=>(_.current=setInterval(()=>{B(O,x)},s),()=>{_.current&&clearInterval(_.current)}),[s,B,O,x]),o.useEffect(()=>{const d=["mousemove","keydown","mousedown","touchstart","scroll"];return d.forEach(k=>window.addEventListener(k,g,{passive:!0})),I.current=setTimeout(()=>{U("idle",x)},l),$.current=setTimeout(()=>{U("away",x)},c),()=>{d.forEach(k=>window.removeEventListener(k,g)),I.current&&clearTimeout(I.current),$.current&&clearTimeout($.current)}},[g,l,c,x,U]);const Y=z.filter(d=>d.status==="viewing"||d.status==="idle").map(d=>d.user),se=z.filter(d=>d.status==="editing").map(d=>d.user),oe=se.length>0;return{presence:z,viewers:Y,editors:se,myStatus:O,setMyStatus:U,startEditing:Z,stopEditing:ee,updateSelection:h,connectionStatus:X,isFieldLocked:v,hasActiveEditors:oe,getFieldEditor:C,refresh:S}}function ce(i){const e=["#3b82f6","#ef4444","#22c55e","#f59e0b","#8b5cf6","#ec4899","#06b6d4","#84cc16","#f97316","#14b8a6"];let t=0;for(let n=0;n<i.length;n++)t=i.charCodeAt(n)+((t<<5)-t);return e[Math.abs(t)%e.length]}function De(i){switch(i){case"viewing":return"Viewing";case"editing":return"Editing";case"idle":return"Idle";case"away":return"Away";default:return"Unknown"}}function Ae(i){const{adapter:e,entityType:t,currentUser:n,batchEventName:a="BatchPresenceUpdate"}=i,[r,s]=o.useState(new Map),l=o.useCallback(y=>{y.entityType===t&&s(new Map(Object.entries(y.presenceByEntity)))},[t]);o.useEffect(()=>(e.on(a,l),()=>{e.off(a,l)}),[e,a,l]);const c=o.useCallback(y=>r.get(y)??[],[r]),m=o.useCallback(y=>{const E=r.get(y);return(E==null?void 0:E.some(V=>V.status==="editing"&&V.user.id!==n.id))??!1},[r,n.id]),b=o.useCallback(y=>{const E=r.get(y);return(E==null?void 0:E.filter(V=>V.status==="editing").map(V=>V.user))??[]},[r]);return{presenceByEntity:r,getPresence:c,isEntityBeingEdited:m,getEntityEditors:b}}function M(i){return`${String(i.rowKey)}:${i.field}`}function Le(i){return i?typeof i=="number"?i:new Date(i).getTime():Date.now()}function Oe(i){const{adapter:e,entityType:t,keyField:n,currentUser:a,initialData:r=[],conflictStrategy:s="last-write-wins",mergeFunction:l,onConflict:c,onBeforeCommit:m,onAfterCommit:b,enableCellLocking:y=!0,lockTimeout:E=6e4,enableCursorSharing:V=!0,cursorDebounce:J=50,optimisticUpdates:L=!0,flashChanges:H=!0,flashDuration:z=500,liveDataOptions:Q={}}=i,[O,q]=o.useState(new Map),[x,W]=o.useState(new Map),[X,K]=o.useState([]),[N,_]=o.useState(null),[I,$]=o.useState([]),[P,ne]=o.useState([]),[B,U]=o.useState(null),[Z,ee]=o.useState([]),h=o.useRef(null),v=o.useRef(new Map),C=o.useCallback(u=>(v.current.has(u)||v.current.set(u,ce(u)),v.current.get(u)),[]),S=o.useCallback((u,f,p)=>{if(!p.changes)return f;const T=x.get(M({rowKey:p.key,field:Object.keys(p.changes)[0]}));if(!T)return f;const D=T.timestamp,R=Le(p.timestamp);switch(s){case"last-write-wins":return D>R?"local":"remote";case"first-write-wins":return D<R?"local":"remote";case"merge":return l?l(u,f,Object.keys(p.changes)[0]):"merge";case"ask-user":const j={cell:{rowKey:p.key,field:Object.keys(p.changes)[0]},localValue:T.newValue,remoteValue:p.changes[Object.keys(p.changes)[0]],localUser:a,remoteUser:p.changedBy?{id:p.changedBy,name:p.changedBy}:{id:"unknown",name:"Unknown"},localTimestamp:D,remoteTimestamp:R};return K(re=>[...re,j]),"local";case"reject":return"remote";default:return"remote"}},[x,s,l,a]),g=ie({adapter:e,entityName:t,keyField:n,initialData:r,flashChanges:H,flashDuration:z,optimisticUpdates:L,onConflict:S,...Q}),F=ue({adapter:e,entityType:t,entityId:"grid",currentUser:a,initialStatus:"viewing"}),A=o.useCallback(()=>{!V||e.status!=="connected"||e.invoke("UpdateGridSelection",{entityType:t,userId:a.id,focusedCell:N,selectedCells:I,selectedRows:P,editingCell:B}).catch(()=>{})},[e,V,t,a.id,N,I,P,B]);o.useEffect(()=>{if(V)return h.current&&clearTimeout(h.current),h.current=setTimeout(A,J),()=>{h.current&&clearTimeout(h.current)}},[V,A,J,N,I,P,B]),o.useEffect(()=>{if(!V)return;const u=f=>{f.entityType!==t||f.userId===a.id||ee(p=>{const T=p.findIndex(R=>R.user.id===f.userId),D={user:{id:f.userId,name:f.userName,avatarUrl:f.avatarUrl},focusedCell:f.focusedCell,selectedCells:f.selectedCells,selectedRows:f.selectedRows,editingCell:f.editingCell,color:C(f.userId)};if(T>=0){const R=[...p];return R[T]=D,R}return[...p,D]})};return e.on("GridSelectionUpdated",u),()=>{e.off("GridSelectionUpdated",u)}},[e,V,t,a.id,C]),o.useEffect(()=>{if(!y)return;const u=p=>{p.entityType===t&&q(T=>{const D=new Map(T);return D.set(M(p.cell),{user:p.user,timestamp:p.timestamp}),D})},f=p=>{p.entityType===t&&q(T=>{const D=new Map(T);return D.delete(M(p.cell)),D})};return e.on("CellLocked",u),e.on("CellUnlocked",f),()=>{e.off("CellLocked",u),e.off("CellUnlocked",f)}},[e,y,t]),o.useEffect(()=>{if(!y)return;const u=setInterval(()=>{const f=Date.now();q(p=>{const T=new Map(p);let D=!1;for(const[R,j]of T)f-j.timestamp>E&&(T.delete(R),D=!0);return D?T:p})},1e4);return()=>clearInterval(u)},[y,E]);const G=o.useCallback(u=>{if(!y)return!1;const f=O.get(M(u));return f?f.user.id!==a.id&&Date.now()-f.timestamp<E:!1},[y,O,a.id,E]),Y=o.useCallback(u=>{const f=O.get(M(u));return!f||Date.now()-f.timestamp>E?null:f.user},[O,E]),se=o.useCallback(u=>G(u)?!1:(U(u),F.startEditing(`${u.rowKey}:${u.field}`),y&&e.status==="connected"&&(e.invoke("AcquireCellLock",{entityType:t,cell:u,user:a,timestamp:Date.now()}).catch(()=>{}),q(f=>{const p=new Map(f);return p.set(M(u),{user:a,timestamp:Date.now()}),p})),!0),[G,F,y,e,t,a]),oe=o.useCallback(async(u,f)=>{const p=g.data.find(R=>R[n]===u.rowKey);if(!p)return!1;const T=p[u.field];if(m&&!await m(u,T,f))return d(u),!1;const D={cell:u,originalValue:T,newValue:f,timestamp:Date.now()};W(R=>{const j=new Map(R);return j.set(M(u),D),j}),L&&g.registerPendingChange(u.rowKey,{[u.field]:f});try{return await e.invoke("UpdateEntityField",{entityType:t,entityId:u.rowKey,field:u.field,value:f,userId:a.id,timestamp:D.timestamp}),g.confirmPendingChange(u.rowKey),W(R=>{const j=new Map(R);return j.delete(M(u)),j}),b==null||b(u,f),y&&(e.invoke("ReleaseCellLock",{entityType:t,cell:u}).catch(()=>{}),q(R=>{const j=new Map(R);return j.delete(M(u)),j})),U(null),F.stopEditing(),!0}catch(R){throw g.rollbackPendingChange(u.rowKey),W(j=>{const re=new Map(j);return re.delete(M(u)),re}),R}},[g,n,m,L,e,t,a.id,b,y,F]),d=o.useCallback(u=>{U(null),F.stopEditing(),y&&e.status==="connected"&&(e.invoke("ReleaseCellLock",{entityType:t,cell:u}).catch(()=>{}),q(f=>{const p=new Map(f);return p.delete(M(u)),p})),W(f=>{const p=new Map(f);return p.delete(M(u)),p})},[F,y,e,t]),k=o.useCallback((u,f)=>{const p=X.find(T=>M(T.cell)===M(u));p&&(f==="remote"&&g.applyRemoteUpdate({operation:"update",entityName:t,key:u.rowKey,changes:{[u.field]:p.remoteValue}}),K(T=>T.filter(D=>M(D.cell)!==M(u))))},[X,g,t]),w=o.useCallback(async u=>{await e.invoke("InsertEntity",t,u)},[e,t]),te=o.useCallback(async(u,f)=>{L&&g.registerPendingChange(u,f);try{await e.invoke("UpdateEntity",t,u,f),g.confirmPendingChange(u)}catch(p){throw g.rollbackPendingChange(u),p}},[e,t,L,g]),ae=o.useCallback(async u=>{await e.invoke("DeleteEntity",t,u)},[e,t]),ge=o.useMemo(()=>({user:a,focusedCell:N,selectedCells:I,selectedRows:P,editingCell:B,color:C(a.id)}),[a,N,I,P,B,C]);return{data:g.data,presence:F.presence,userSelections:Z,mySelection:ge,flashedKeys:g.flashedKeys,pendingEdits:x,connectionStatus:g.status,myPresenceStatus:F.myStatus,setFocusedCell:_,setSelectedCells:$,setSelectedRows:ne,startCellEdit:se,commitCellEdit:oe,cancelCellEdit:d,isCellLocked:G,getCellEditor:Y,getUserColor:C,insertRow:w,updateRow:te,deleteRow:ae,resolveConflict:k,conflicts:X}}class Ue{constructor(e){this.accessToken=null,this.refreshToken=null,this.tokenFactory=async()=>{if(!this.accessToken)throw new Error("Not authenticated");return this.accessToken},this.cfg=e}getAccessToken(){return this.accessToken}async post(e,t){const a=await(this.cfg.fetch??globalThis.fetch)(`${this.cfg.baseUrl}${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!a.ok)throw new Error(`Auth request failed: ${a.status}`);return a.json()}async login(e){var n,a;const t=await this.post("/login",e);return t.token&&(this.accessToken=t.token,this.refreshToken=t.refreshToken??null,(a=(n=this.cfg).onTokens)==null||a.call(n,t.token,t.refreshToken??"")),t}async refresh(){var t,n;if(!this.refreshToken)throw new Error("No refresh token");const e=await this.post("/refresh",{refreshToken:this.refreshToken});return e.token&&(this.accessToken=e.token,this.refreshToken=e.refreshToken??this.refreshToken,(n=(t=this.cfg).onTokens)==null||n.call(t,e.token,this.refreshToken)),e}async me(){const t=await(this.cfg.fetch??globalThis.fetch)(`${this.cfg.baseUrl}/me`,{headers:{Authorization:`Bearer ${this.accessToken}`}});if(!t.ok)throw new Error(`Auth /me failed: ${t.status}`);return t.json()}async logout(){try{await(this.cfg.fetch??globalThis.fetch)(`${this.cfg.baseUrl}/logout`,{method:"POST",headers:{Authorization:`Bearer ${this.accessToken}`}})}finally{this.accessToken=null,this.refreshToken=null}}}class Fe{constructor(e){this.cfg=e}async headers(){const e={};return this.cfg.tokenFactory&&(e.Authorization=`Bearer ${await this.cfg.tokenFactory()}`),e}async upload(e,t){const n=this.cfg.fetch??globalThis.fetch,a=new FormData;a.append("file",e),t&&a.append("folder",t);const r=await n(this.cfg.baseUrl,{method:"POST",headers:await this.headers(),body:a});if(!r.ok)throw new Error(`File upload failed: ${r.status}`);return r.json()}async uploadMultiple(e,t){const n=this.cfg.fetch??globalThis.fetch,a=new FormData;e.forEach(s=>a.append("files",s)),t&&a.append("folder",t);const r=await n(`${this.cfg.baseUrl}/batch`,{method:"POST",headers:await this.headers(),body:a});if(!r.ok)throw new Error(`Batch upload failed: ${r.status}`);return r.json()}async getInfo(e){const n=await(this.cfg.fetch??globalThis.fetch)(`${this.cfg.baseUrl}/${e}/info`,{headers:{...await this.headers(),"Content-Type":"application/json"}});if(!n.ok)throw new Error(`File info failed: ${n.status}`);return n.json()}async getDownloadUrl(e){const n=await(this.cfg.fetch??globalThis.fetch)(`${this.cfg.baseUrl}/${e}`,{headers:await this.headers()});if(!n.ok)throw new Error(`File download failed: ${n.status}`);const a=await n.blob();return URL.createObjectURL(a)}async remove(e){const n=await(this.cfg.fetch??globalThis.fetch)(`${this.cfg.baseUrl}/${e}`,{method:"DELETE",headers:{...await this.headers(),"Content-Type":"application/json"}});if(!n.ok)throw new Error(`File delete failed: ${n.status}`);return n.json()}uploadWithProgress(e,t,n,a){return typeof XMLHttpRequest>"u"?this.upload(e,n):new Promise(async(r,s)=>{const l=new XMLHttpRequest,c=new FormData;if(c.append("file",e),n&&c.append("folder",n),a){if(a.aborted){s(new DOMException("Aborted","AbortError"));return}a.addEventListener("abort",()=>{l.abort(),s(new DOMException("Aborted","AbortError"))})}l.upload.addEventListener("progress",b=>{t({loaded:b.loaded,total:b.total,percent:b.lengthComputable?b.loaded/b.total:NaN})}),l.addEventListener("load",()=>{if(l.status>=200&&l.status<300)try{r(JSON.parse(l.responseText))}catch{s(new Error("Invalid JSON response"))}else s(new Error(`File upload failed: ${l.status}`))}),l.addEventListener("error",()=>s(new Error("Network error during upload"))),l.addEventListener("abort",()=>s(new DOMException("Aborted","AbortError"))),l.open("POST",this.cfg.baseUrl);const m=await this.headers();Object.entries(m).forEach(([b,y])=>l.setRequestHeader(b,y)),l.send(c)})}async uploadMultipleWithProgress(e,t,n,a){const r=[];for(let s=0;s<e.length;s++){if(a!=null&&a.aborted)throw new DOMException("Aborted","AbortError");const l=await this.uploadWithProgress(e[s],c=>t(s,c),n,a);r.push(l)}return r}}class Me{constructor(e){this.cfg=e}async headers(){const e={"Content-Type":"application/json"};return this.cfg.tokenFactory&&(e.Authorization=`Bearer ${await this.cfg.tokenFactory()}`),e}async requestExport(e){const n=await(this.cfg.fetch??globalThis.fetch)(this.cfg.baseUrl,{method:"POST",headers:await this.headers(),body:JSON.stringify(e)});if(!n.ok)throw new Error(`Export request failed: ${n.status}`);return n.json()}async download(e){const n=await(this.cfg.fetch??globalThis.fetch)(e,{headers:await this.headers()});if(!n.ok)throw new Error(`Export download failed: ${n.status}`);return n.blob()}async downloadToFile(e,t){var l;const n=await this.requestExport(e);if(!((l=n.data)!=null&&l.downloadUrl))throw new Error("No download URL returned");const a=await this.download(n.data.downloadUrl),r=URL.createObjectURL(a),s=document.createElement("a");s.href=r,s.download=t??`export.${e.format}`,document.body.appendChild(s),s.click(),document.body.removeChild(s),URL.revokeObjectURL(r)}}function Ne(i){return e=>{const t=e??globalThis.fetch;return(a,r)=>{const c={url:typeof a=="string"?a:a instanceof URL?a.toString():a.url,init:r??{},meta:{}};let m=b=>t(b.url,b.init);for(let b=i.length-1;b>=0;b--){const y=i[b],E=m;m=V=>y(V,E)}return m(c)}}}function Ie(){return async(i,e)=>{const t=performance.now(),n=(i.init.method??"GET").toUpperCase();try{const a=await e(i),r=(performance.now()-t).toFixed(1);return console.debug(`[ERP] ${n} ${i.url} → ${a.status} (${r}ms)`),a}catch(a){const r=(performance.now()-t).toFixed(1);throw console.error(`[ERP] ${n} ${i.url} FAILED (${r}ms)`,a),a}}}function $e(i){const e=(i==null?void 0:i.maxRetries)??3,t=(i==null?void 0:i.baseDelay)??500,n=new Set((i==null?void 0:i.retryOn)??[408,429,500,502,503,504]);return async(a,r)=>{let s;for(let l=0;l<=e;l++){try{const m=await r(a);if(m.ok||!n.has(m.status)||l===e)return m;s=new Error(`HTTP ${m.status}`)}catch(m){if(s=m,l===e)throw m}const c=t*Math.pow(2,l)*(.5+Math.random()*.5);await new Promise(m=>setTimeout(m,c))}throw s}}function Be(i){return async(e,t)=>{const n=typeof i=="function"?await i():i;return e.init.headers={...e.init.headers,...n},t(e)}}class je{constructor(e){this.inFlight=0,this.timestamps=[],this.queue=[],this.processing=!1,this.backingOff=!1,this.maxConcurrent=(e==null?void 0:e.maxConcurrent)??6,this.maxPerSecond=(e==null?void 0:e.maxPerSecond)??20,this.backoffDelay=(e==null?void 0:e.backoffDelay)??2e3,this.baseFetch=(e==null?void 0:e.baseFetch)??globalThis.fetch.bind(globalThis),this.fetch=this.fetch.bind(this)}fetch(e,t){return new Promise((n,a)=>{this.queue.push({resolve:n,reject:a,input:e,init:t}),this.drain()})}get pending(){return this.queue.length}get active(){return this.inFlight}drain(){if(this.processing)return;this.processing=!0;const e=()=>{if(this.queue.length===0||this.backingOff){this.processing=!1;return}if(this.inFlight>=this.maxConcurrent){this.processing=!1;return}const t=Date.now();if(this.timestamps=this.timestamps.filter(a=>t-a<1e3),this.timestamps.length>=this.maxPerSecond){const a=this.timestamps[0],r=1e3-(t-a)+1;setTimeout(()=>{this.processing=!1,this.drain()},r);return}const n=this.queue.shift();this.inFlight++,this.timestamps.push(t),this.baseFetch(n.input,n.init).then(a=>{if(this.inFlight--,a.status===429){this.queue.unshift(n),this.inFlight++,this.inFlight--,this.backingOff=!0,setTimeout(()=>{this.backingOff=!1,this.drain()},this.backoffDelay);return}n.resolve(a),queueMicrotask(e)}).catch(a=>{this.inFlight--,n.reject(a),queueMicrotask(e)}),queueMicrotask(e)};e()}}class ze{constructor(e,t="id"){this.items=[],this.mutations=[],this.listeners=new Set,this.nextMutationId=1,this.adapter=e,this.keyField=t}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}notify(){const e=[...this.items],t=[...this.mutations];this.listeners.forEach(n=>n(e,t))}getItems(){return[...this.items]}getPending(){return this.mutations.filter(e=>e.status==="pending")}setItems(e){this.items=[...e],this.notify()}async load(...e){const t=await this.adapter.load(...e);return t.success&&(this.items=t.data,this.mutations=[],this.notify()),t}async create(e){const t=`__temp_${this.nextMutationId}`,n={...e,[this.keyField]:t},r={id:String(this.nextMutationId++),type:"create",optimisticData:n,timestamp:Date.now(),status:"pending"};this.items=[...this.items,n],this.mutations.push(r),this.notify();try{const s=await this.adapter.create(e);return s.success?(this.items=this.items.map(l=>l[this.keyField]===t?s.data:l),r.status="confirmed",r.entityId=s.data[this.keyField]):(this.items=this.items.filter(l=>l[this.keyField]!==t),r.status="failed",r.error=s.error),this.notify(),s}catch(s){throw this.items=this.items.filter(l=>l[this.keyField]!==t),r.status="failed",r.error=s instanceof Error?s.message:String(s),this.notify(),s}}async update(e,t){const n=this.items.findIndex(l=>l[this.keyField]===e),a=n>=0?{...this.items[n]}:void 0,s={id:String(this.nextMutationId++),type:"update",entityId:e,previousData:a,timestamp:Date.now(),status:"pending"};n>=0&&(this.items=this.items.map((l,c)=>c===n?{...l,...t}:l)),this.mutations.push(s),this.notify();try{const l=await this.adapter.update(e,t);return l.success?(this.items=this.items.map(c=>c[this.keyField]===e?l.data:c),s.status="confirmed"):(a&&n>=0&&(this.items=this.items.map(c=>c[this.keyField]===e?a:c)),s.status="failed",s.error=l.error),this.notify(),l}catch(l){throw a&&n>=0&&(this.items=this.items.map(c=>c[this.keyField]===e?a:c)),s.status="failed",s.error=l instanceof Error?l.message:String(l),this.notify(),l}}async remove(e){const t=this.items.findIndex(s=>s[this.keyField]===e),n=t>=0?{...this.items[t]}:void 0,r={id:String(this.nextMutationId++),type:"delete",entityId:e,previousData:n,timestamp:Date.now(),status:"pending"};this.items=this.items.filter(s=>s[this.keyField]!==e),this.mutations.push(r),this.notify();try{const s=await this.adapter.remove(e);return s.success?r.status="confirmed":(n&&this.items.splice(t,0,n),r.status="failed",r.error=s.error),this.notify(),s}catch(s){throw n&&this.items.splice(t,0,n),r.status="failed",r.error=s instanceof Error?s.message:String(s),this.notify(),s}}}class Ge{constructor(e){this.queue=[],this.syncing=!1,this.nextId=1,this.config=e??{},this.baseFetch=(e==null?void 0:e.baseFetch)??globalThis.fetch.bind(globalThis),this.storageKey=(e==null?void 0:e.storageKey)??"erp_offline_",this.fetch=this.fetch.bind(this),this.restoreQueue(),this.boundOnline=()=>{var t,n;(n=(t=this.config).onStatusChange)==null||n.call(t,!0),this.sync()},this.boundOffline=()=>{var t,n;(n=(t=this.config).onStatusChange)==null||n.call(t,!1)},typeof window<"u"&&(window.addEventListener("online",this.boundOnline),window.addEventListener("offline",this.boundOffline))}fetch(e,t){var s,l;const n=typeof e=="string"?e:e instanceof URL?e.toString():e.url,a=((t==null?void 0:t.method)??"GET").toUpperCase();if(this.isOnline())return this.baseFetch(e,t);if(a==="GET"||a==="HEAD")return Promise.reject(new Error("Offline: GET requests are not queued"));const r={id:`q_${this.nextId++}`,url:n,method:a,headers:{...t==null?void 0:t.headers},body:typeof(t==null?void 0:t.body)=="string"?t.body:void 0,timestamp:Date.now()};return this.queue.push(r),this.persistQueue(),(l=(s=this.config).onQueued)==null||l.call(s,r),Promise.resolve(new Response(JSON.stringify({queued:!0,queueId:r.id}),{status:202,headers:{"Content-Type":"application/json"}}))}isOnline(){return typeof navigator>"u"||navigator.onLine}get pendingCount(){return this.queue.length}getQueue(){return[...this.queue]}clear(){this.queue=[],this.persistQueue()}async sync(){var t,n;if(this.syncing||this.queue.length===0||!this.isOnline())return[];this.syncing=!0;const e=[];for(;this.queue.length>0&&this.isOnline();){const a=this.queue[0];try{const r=await this.baseFetch(a.url,{method:a.method,headers:a.headers,body:a.body});e.push({entry:a,success:r.ok,status:r.status,error:r.ok?void 0:`HTTP ${r.status}`}),this.queue.shift()}catch(r){e.push({entry:a,success:!1,error:r instanceof Error?r.message:String(r)});break}}return this.persistQueue(),this.syncing=!1,e.length>0&&((n=(t=this.config).onSync)==null||n.call(t,e)),e}destroy(){typeof window<"u"&&(window.removeEventListener("online",this.boundOnline),window.removeEventListener("offline",this.boundOffline))}persistQueue(){try{typeof localStorage<"u"&&localStorage.setItem(`${this.storageKey}queue`,JSON.stringify(this.queue))}catch{}}restoreQueue(){try{if(typeof localStorage<"u"){const e=localStorage.getItem(`${this.storageKey}queue`);e&&(this.queue=JSON.parse(e),this.nextId=this.queue.reduce((t,n)=>Math.max(t,parseInt(n.id.replace("q_",""),10)||0),0)+1)}}catch{this.queue=[]}}}const de=[{type:"NiceAudioPlayer",label:"Audio Player",category:"Audio",icon:"music",defaultProps:{src:"",autoplay:!1,showWaveform:!0},propDescriptors:[{name:"src",type:"string",label:"Audio source URL"},{name:"autoplay",type:"boolean",label:"Auto-play",defaultValue:!1},{name:"loop",type:"boolean",label:"Loop",defaultValue:!1},{name:"showWaveform",type:"boolean",label:"Show waveform",defaultValue:!0},{name:"showPlaylist",type:"boolean",label:"Show playlist",defaultValue:!1},{name:"visualizerMode",type:"select",label:"Visualizer mode",options:[{label:"None",value:"none"},{label:"Bars",value:"bars"},{label:"Wave",value:"wave"},{label:"Circle",value:"circle"}],defaultValue:"bars"},{name:"height",type:"size",label:"Height",group:"Layout"}]},{type:"NiceWaveform",label:"Waveform",category:"Audio",icon:"waveform",defaultProps:{peaks:[],color:"#4a90d9"},propDescriptors:[{name:"peaks",type:"json",label:"Peak data (JSON array)"},{name:"color",type:"color",label:"Waveform color",defaultValue:"#4a90d9"},{name:"progressColor",type:"color",label:"Progress color",defaultValue:"#1b5e20"},{name:"barWidth",type:"number",label:"Bar width (px)",min:1,max:10,step:1,defaultValue:2},{name:"height",type:"size",label:"Height",group:"Layout"},{name:"interactive",type:"boolean",label:"Allow seeking",defaultValue:!0}]},{type:"NicePianoRoll",label:"Piano Roll",category:"Audio",icon:"piano",defaultProps:{notes:[],octaves:4,startOctave:3},propDescriptors:[{name:"notes",type:"json",label:"MIDI notes (JSON)"},{name:"octaves",type:"number",label:"Visible octaves",min:1,max:8,defaultValue:4},{name:"startOctave",type:"number",label:"Start octave",min:0,max:8,defaultValue:3},{name:"quantize",type:"select",label:"Quantize",options:[{label:"1/4",value:"4"},{label:"1/8",value:"8"},{label:"1/16",value:"16"},{label:"1/32",value:"32"}],defaultValue:"16"},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1},{name:"height",type:"size",label:"Height",group:"Layout"}]},{type:"NiceKaraoke",label:"Karaoke",category:"Audio",icon:"microphone",defaultProps:{lyrics:[],audioSrc:""},propDescriptors:[{name:"audioSrc",type:"string",label:"Audio source URL"},{name:"lyrics",type:"json",label:"Lyrics (JSON array of {time, text})"},{name:"showScore",type:"boolean",label:"Show score",defaultValue:!0},{name:"pitchDetection",type:"boolean",label:"Pitch detection",defaultValue:!0},{name:"highlightColor",type:"color",label:"Highlight color",defaultValue:"#ffd700"},{name:"fontSize",type:"size",label:"Font size",group:"Typography"}]}],he=[{type:"NicePixelEditor",label:"Pixel Editor",category:"Graphics",icon:"grid",defaultProps:{width:32,height:32,palette:[]},propDescriptors:[{name:"width",type:"number",label:"Canvas width (px)",min:1,max:256,defaultValue:32},{name:"height",type:"number",label:"Canvas height (px)",min:1,max:256,defaultValue:32},{name:"palette",type:"json",label:"Color palette (JSON array)"},{name:"gridVisible",type:"boolean",label:"Show grid",defaultValue:!0},{name:"zoom",type:"number",label:"Zoom level",min:1,max:32,step:1,defaultValue:8},{name:"layers",type:"boolean",label:"Enable layers",defaultValue:!0},{name:"onion",type:"boolean",label:"Onion skin (animation)",defaultValue:!1}]},{type:"NiceVectorEditor",label:"Vector Editor",category:"Graphics",icon:"pen-tool",defaultProps:{width:800,height:600},propDescriptors:[{name:"width",type:"number",label:"Canvas width",min:100,max:4096,defaultValue:800,group:"Layout"},{name:"height",type:"number",label:"Canvas height",min:100,max:4096,defaultValue:600,group:"Layout"},{name:"showRulers",type:"boolean",label:"Show rulers",defaultValue:!0},{name:"snapToGrid",type:"boolean",label:"Snap to grid",defaultValue:!0},{name:"gridSize",type:"number",label:"Grid size",min:1,max:100,defaultValue:10},{name:"fillColor",type:"color",label:"Default fill",defaultValue:"#ffffff"},{name:"strokeColor",type:"color",label:"Default stroke",defaultValue:"#000000"},{name:"strokeWidth",type:"number",label:"Stroke width",min:0,max:20,step:.5,defaultValue:1}]},{type:"NicePhotoEditor",label:"Photo Editor",category:"Graphics",icon:"image",defaultProps:{src:""},propDescriptors:[{name:"src",type:"string",label:"Image source URL"},{name:"crop",type:"boolean",label:"Allow crop",defaultValue:!0},{name:"rotate",type:"boolean",label:"Allow rotate",defaultValue:!0},{name:"filters",type:"boolean",label:"Show filters",defaultValue:!0},{name:"adjustments",type:"boolean",label:"Show adjustments",defaultValue:!0},{name:"text",type:"boolean",label:"Allow text overlay",defaultValue:!0},{name:"outputFormat",type:"select",label:"Output format",options:[{label:"PNG",value:"png"},{label:"JPEG",value:"jpeg"},{label:"WebP",value:"webp"}],defaultValue:"png"},{name:"maxWidth",type:"number",label:"Max output width",min:100,max:8192,group:"Output"}]}],fe=[{type:"NiceModelEditor",label:"3D Model Editor",category:"3D",icon:"cube",defaultProps:{modelUrl:""},propDescriptors:[{name:"modelUrl",type:"string",label:"Model URL (.glb / .gltf)"},{name:"environmentMap",type:"select",label:"Environment",options:[{label:"Studio",value:"studio"},{label:"Outdoor",value:"outdoor"},{label:"Warehouse",value:"warehouse"},{label:"None",value:"none"}],defaultValue:"studio"},{name:"showGrid",type:"boolean",label:"Show grid",defaultValue:!0},{name:"showAxes",type:"boolean",label:"Show axes",defaultValue:!0},{name:"enablePhysics",type:"boolean",label:"Enable physics",defaultValue:!1},{name:"wireframe",type:"boolean",label:"Wireframe mode",defaultValue:!1},{name:"backgroundColor",type:"color",label:"Background",defaultValue:"#1a1a2e"},{name:"height",type:"size",label:"Viewport height",group:"Layout"}]},{type:"NiceModelViewer",label:"3D Model Viewer",category:"3D",icon:"eye",defaultProps:{modelUrl:"",autoRotate:!0},propDescriptors:[{name:"modelUrl",type:"string",label:"Model URL (.glb / .gltf)"},{name:"autoRotate",type:"boolean",label:"Auto-rotate",defaultValue:!0},{name:"rotateSpeed",type:"number",label:"Rotate speed",min:.1,max:10,step:.1,defaultValue:1},{name:"zoom",type:"boolean",label:"Allow zoom",defaultValue:!0},{name:"pan",type:"boolean",label:"Allow pan",defaultValue:!0},{name:"environmentMap",type:"select",label:"Environment",options:[{label:"Studio",value:"studio"},{label:"Outdoor",value:"outdoor"},{label:"Warehouse",value:"warehouse"},{label:"None",value:"none"}],defaultValue:"studio"},{name:"backgroundColor",type:"color",label:"Background",defaultValue:"#1a1a2e"},{name:"showAnnotations",type:"boolean",label:"Show annotations",defaultValue:!1},{name:"height",type:"size",label:"Viewport height",group:"Layout"}]}],pe=[{type:"NiceLeaderboard",label:"Leaderboard",category:"Gamification",icon:"trophy",defaultProps:{dataSource:[],maxRows:10},propDescriptors:[{name:"dataSource",type:"json",label:"Data source (JSON)"},{name:"maxRows",type:"number",label:"Max visible rows",min:3,max:100,defaultValue:10},{name:"showRank",type:"boolean",label:"Show rank column",defaultValue:!0},{name:"showAvatar",type:"boolean",label:"Show avatar",defaultValue:!0},{name:"highlightCurrentUser",type:"boolean",label:"Highlight current user",defaultValue:!0},{name:"scoreField",type:"string",label:"Score field name",defaultValue:"score"},{name:"nameField",type:"string",label:"Name field name",defaultValue:"name"},{name:"variant",type:"variant",label:"Visual style",defaultValue:"default"}]},{type:"NiceAchievement",label:"Achievement Badge",category:"Gamification",icon:"award",defaultProps:{title:"Achievement",unlocked:!1},propDescriptors:[{name:"title",type:"string",label:"Achievement title",defaultValue:"Achievement"},{name:"description",type:"string",label:"Description"},{name:"icon",type:"string",label:"Icon URL"},{name:"unlocked",type:"boolean",label:"Unlocked",defaultValue:!1},{name:"progress",type:"number",label:"Progress (0-100)",min:0,max:100,defaultValue:0},{name:"rarity",type:"select",label:"Rarity",options:[{label:"Common",value:"common"},{label:"Rare",value:"rare"},{label:"Epic",value:"epic"},{label:"Legendary",value:"legendary"}],defaultValue:"common"},{name:"size",type:"size",label:"Badge size",group:"Layout"}]},{type:"NiceQuest",label:"Quest Tracker",category:"Gamification",icon:"map",defaultProps:{title:"Quest",steps:[]},propDescriptors:[{name:"title",type:"string",label:"Quest title",defaultValue:"Quest"},{name:"description",type:"string",label:"Quest description"},{name:"steps",type:"json",label:"Steps (JSON array of {title, completed})"},{name:"reward",type:"string",label:"Reward description"},{name:"rewardXP",type:"number",label:"Reward XP",min:0,defaultValue:100},{name:"showProgress",type:"boolean",label:"Show progress bar",defaultValue:!0},{name:"variant",type:"variant",label:"Visual style",defaultValue:"default"}]},{type:"NiceXPBar",label:"XP Progress Bar",category:"Gamification",icon:"zap",defaultProps:{currentXP:0,maxXP:1e3,level:1},propDescriptors:[{name:"currentXP",type:"number",label:"Current XP",min:0,defaultValue:0},{name:"maxXP",type:"number",label:"Max XP (next level)",min:1,defaultValue:1e3},{name:"level",type:"number",label:"Current level",min:1,defaultValue:1},{name:"showLabel",type:"boolean",label:"Show XP label",defaultValue:!0},{name:"showLevel",type:"boolean",label:"Show level badge",defaultValue:!0},{name:"color",type:"color",label:"Bar color",defaultValue:"#4caf50"},{name:"animated",type:"boolean",label:"Animate changes",defaultValue:!0},{name:"height",type:"size",label:"Bar height",group:"Layout"}]}],me=[{type:"NiceAddress",label:"Address Editor",category:"Business",icon:"map-pin",defaultProps:{country:"PL"},propDescriptors:[{name:"street",type:"string",label:"Street",group:"Address"},{name:"city",type:"string",label:"City",group:"Address"},{name:"postalCode",type:"string",label:"Postal code",group:"Address"},{name:"country",type:"select",label:"Country",options:[{label:"Poland",value:"PL"},{label:"Germany",value:"DE"},{label:"USA",value:"US"},{label:"UK",value:"GB"},{label:"France",value:"FR"}],defaultValue:"PL",group:"Address"},{name:"showMap",type:"boolean",label:"Show map preview",defaultValue:!1},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]},{type:"NicePhone",label:"Phone Input",category:"Business",icon:"phone",defaultProps:{countryCode:"+48"},propDescriptors:[{name:"value",type:"string",label:"Phone number"},{name:"countryCode",type:"string",label:"Default country code",defaultValue:"+48"},{name:"showFlag",type:"boolean",label:"Show country flag",defaultValue:!0},{name:"format",type:"select",label:"Format",options:[{label:"International",value:"international"},{label:"National",value:"national"},{label:"E.164",value:"e164"}],defaultValue:"international"},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]},{type:"NiceCurrency",label:"Currency Input",category:"Business",icon:"dollar-sign",defaultProps:{currency:"PLN",decimals:2},propDescriptors:[{name:"value",type:"number",label:"Amount",defaultValue:0},{name:"currency",type:"select",label:"Currency",options:[{label:"PLN",value:"PLN"},{label:"EUR",value:"EUR"},{label:"USD",value:"USD"},{label:"GBP",value:"GBP"}],defaultValue:"PLN"},{name:"decimals",type:"number",label:"Decimal places",min:0,max:4,defaultValue:2},{name:"showCurrencySymbol",type:"boolean",label:"Show symbol",defaultValue:!0},{name:"thousandSeparator",type:"boolean",label:"Thousand separator",defaultValue:!0},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]},{type:"NiceVAT",label:"VAT Input",category:"Business",icon:"percent",defaultProps:{rate:23,country:"PL"},propDescriptors:[{name:"netValue",type:"number",label:"Net value",defaultValue:0,group:"Values"},{name:"rate",type:"number",label:"VAT rate (%)",min:0,max:100,defaultValue:23,group:"Values"},{name:"country",type:"select",label:"Country",options:[{label:"Poland",value:"PL"},{label:"Germany",value:"DE"},{label:"France",value:"FR"}],defaultValue:"PL"},{name:"showGross",type:"boolean",label:"Show gross value",defaultValue:!0},{name:"showVatAmount",type:"boolean",label:"Show VAT amount",defaultValue:!0},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]},{type:"NiceInvoiceLines",label:"Invoice Lines",category:"Business",icon:"file-text",defaultProps:{lines:[],currency:"PLN"},propDescriptors:[{name:"lines",type:"json",label:"Invoice lines (JSON)"},{name:"currency",type:"select",label:"Currency",options:[{label:"PLN",value:"PLN"},{label:"EUR",value:"EUR"},{label:"USD",value:"USD"}],defaultValue:"PLN"},{name:"showVAT",type:"boolean",label:"Show VAT column",defaultValue:!0},{name:"showDiscount",type:"boolean",label:"Show discount column",defaultValue:!1},{name:"showTotal",type:"boolean",label:"Show totals row",defaultValue:!0},{name:"editable",type:"boolean",label:"Editable",defaultValue:!0},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]}],ye=[{type:"NiceLoginForm",label:"Login Form",category:"Auth",icon:"log-in",defaultProps:{showRemember:!0,showForgotPassword:!0},propDescriptors:[{name:"title",type:"string",label:"Form title",defaultValue:"Sign In"},{name:"showRemember",type:"boolean",label:"Show 'Remember me'",defaultValue:!0},{name:"showForgotPassword",type:"boolean",label:"Show 'Forgot password'",defaultValue:!0},{name:"showRegisterLink",type:"boolean",label:"Show register link",defaultValue:!1},{name:"showLogo",type:"boolean",label:"Show logo",defaultValue:!0},{name:"logoUrl",type:"string",label:"Logo URL",group:"Branding"},{name:"primaryColor",type:"color",label:"Primary color",defaultValue:"#1976d2",group:"Branding"},{name:"variant",type:"variant",label:"Visual style",defaultValue:"card"}]},{type:"NiceCaptcha",label:"Captcha",category:"Auth",icon:"shield",defaultProps:{provider:"recaptcha",size:"normal"},propDescriptors:[{name:"provider",type:"select",label:"Provider",options:[{label:"reCAPTCHA v2",value:"recaptcha"},{label:"reCAPTCHA v3",value:"recaptcha-v3"},{label:"hCaptcha",value:"hcaptcha"},{label:"Turnstile",value:"turnstile"}],defaultValue:"recaptcha"},{name:"siteKey",type:"string",label:"Site key"},{name:"size",type:"select",label:"Size",options:[{label:"Normal",value:"normal"},{label:"Compact",value:"compact"},{label:"Invisible",value:"invisible"}],defaultValue:"normal"},{name:"theme",type:"select",label:"Theme",options:[{label:"Light",value:"light"},{label:"Dark",value:"dark"}],defaultValue:"light"}]},{type:"Nice2FASetup",label:"2FA Setup",category:"Auth",icon:"key",defaultProps:{method:"totp"},propDescriptors:[{name:"method",type:"select",label:"2FA method",options:[{label:"TOTP (Authenticator)",value:"totp"},{label:"SMS",value:"sms"},{label:"Email",value:"email"}],defaultValue:"totp"},{name:"issuer",type:"string",label:"Issuer name",defaultValue:"OmniVerk"},{name:"showBackupCodes",type:"boolean",label:"Show backup codes",defaultValue:!0},{name:"showQR",type:"boolean",label:"Show QR code",defaultValue:!0},{name:"codeLength",type:"number",label:"Code length",min:4,max:8,defaultValue:6}]}],be=[{type:"NiceComments",label:"Comments",category:"Social",icon:"message-circle",defaultProps:{threadId:"",allowReplies:!0},propDescriptors:[{name:"threadId",type:"string",label:"Thread ID / entity ID"},{name:"allowReplies",type:"boolean",label:"Allow replies (nested)",defaultValue:!0},{name:"maxDepth",type:"number",label:"Max nesting depth",min:1,max:10,defaultValue:3},{name:"sortOrder",type:"select",label:"Default sort",options:[{label:"Newest first",value:"newest"},{label:"Oldest first",value:"oldest"},{label:"Most liked",value:"popular"}],defaultValue:"newest"},{name:"allowReactions",type:"boolean",label:"Allow reactions",defaultValue:!0},{name:"showAvatar",type:"boolean",label:"Show avatars",defaultValue:!0},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]},{type:"NiceRatings",label:"Ratings",category:"Social",icon:"star",defaultProps:{maxStars:5,allowHalf:!0},propDescriptors:[{name:"value",type:"number",label:"Current rating",min:0,max:10,step:.5,defaultValue:0},{name:"maxStars",type:"number",label:"Maximum stars",min:3,max:10,defaultValue:5},{name:"allowHalf",type:"boolean",label:"Allow half stars",defaultValue:!0},{name:"showCount",type:"boolean",label:"Show vote count",defaultValue:!0},{name:"showAverage",type:"boolean",label:"Show average",defaultValue:!0},{name:"color",type:"color",label:"Star color",defaultValue:"#ffc107"},{name:"size",type:"size",label:"Star size",group:"Layout"},{name:"readOnly",type:"boolean",label:"Read only",defaultValue:!1}]},{type:"NiceWiki",label:"Wiki Editor",category:"Social",icon:"book",defaultProps:{content:"",showTOC:!0},propDescriptors:[{name:"content",type:"string",label:"Initial content (Markdown)"},{name:"showTOC",type:"boolean",label:"Show table of contents",defaultValue:!0},{name:"showHistory",type:"boolean",label:"Show version history",defaultValue:!0},{name:"allowEdit",type:"boolean",label:"Allow editing",defaultValue:!0},{name:"showToolbar",type:"boolean",label:"Show Markdown toolbar",defaultValue:!0},{name:"previewMode",type:"select",label:"Preview mode",options:[{label:"Side by side",value:"split"},{label:"Tab switch",value:"tabs"},{label:"Live preview",value:"live"}],defaultValue:"split"},{name:"maxLength",type:"number",label:"Max content length",min:0,defaultValue:0}]}],Ke=[...de,...he,...fe,...pe,...me,...ye,...be];exports.ErpAuthAdapter=Ue;exports.ErpDataAdapter=Pe;exports.ErpExportAdapter=Me;exports.ErpFileAdapter=Fe;exports.ErpOfflineQueue=Ge;exports.ErpOptimisticStore=ze;exports.ErpRateLimiter=je;exports.allControlRegistries=Ke;exports.applyBatchChanges=xe;exports.audioControlRegistry=de;exports.authControlRegistry=ye;exports.businessControlRegistry=me;exports.createMiddlewarePipeline=Ne;exports.createSignalRAdapter=Te;exports.createSignalRDataOperations=Re;exports.formatPresenceStatus=De;exports.gamificationControlRegistry=pe;exports.generateUserColor=ce;exports.graphicControlRegistry=he;exports.headerMiddleware=Be;exports.loggingMiddleware=Ie;exports.retryMiddleware=$e;exports.socialControlRegistry=be;exports.threeControlRegistry=fe;exports.useCollaborativeDataGrid=Oe;exports.useEntityPresence=ue;exports.useMultiEntityPresence=Ae;exports.useSignalRLiveData=ie;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|