@judo/components 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +277 -0
- package/README.md +200 -0
- package/dist/FlexRenderer-0KCxU9QU.js +1612 -0
- package/dist/FlexRenderer-0KCxU9QU.js.map +1 -0
- package/dist/FormContainerRenderer-B8H4kyz0.js +67 -0
- package/dist/FormContainerRenderer-B8H4kyz0.js.map +1 -0
- package/dist/FormContainerRenderer-CtuXP8jP.js +3 -0
- package/dist/TableContainerRenderer-gKBlsD4S.js +127 -0
- package/dist/TableContainerRenderer-gKBlsD4S.js.map +1 -0
- package/dist/TableContainerRenderer-qbzKI1Cd.js +2 -0
- package/dist/ViewContainerRenderer-7Cx4fcLp.js +3 -0
- package/dist/ViewContainerRenderer-DCRaE_dq.js +132 -0
- package/dist/ViewContainerRenderer-DCRaE_dq.js.map +1 -0
- package/dist/containers/FormContainerRenderer.d.ts +11 -0
- package/dist/containers/FormContainerRenderer.d.ts.map +1 -0
- package/dist/containers/PageRenderer.d.ts +9 -0
- package/dist/containers/PageRenderer.d.ts.map +1 -0
- package/dist/containers/TableContainerRenderer.d.ts +11 -0
- package/dist/containers/TableContainerRenderer.d.ts.map +1 -0
- package/dist/containers/ViewContainerRenderer.d.ts +12 -0
- package/dist/containers/ViewContainerRenderer.d.ts.map +1 -0
- package/dist/dialogs/LinkSelectorDialog.d.ts +21 -0
- package/dist/dialogs/LinkSelectorDialog.d.ts.map +1 -0
- package/dist/errors/ContainerErrorBoundary.d.ts +42 -0
- package/dist/errors/ContainerErrorBoundary.d.ts.map +1 -0
- package/dist/errors/index.d.ts +2 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/find-on-init-action-C5CqxQaH.js +7727 -0
- package/dist/find-on-init-action-C5CqxQaH.js.map +1 -0
- package/dist/hooks/use-file-handling.d.ts +79 -0
- package/dist/hooks/use-file-handling.d.ts.map +1 -0
- package/dist/hooks/use-page-title.d.ts +23 -0
- package/dist/hooks/use-page-title.d.ts.map +1 -0
- package/dist/hooks/use-table-data.d.ts +77 -0
- package/dist/hooks/use-table-data.d.ts.map +1 -0
- package/dist/index.css +2 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +296 -0
- package/dist/index.js.map +1 -0
- package/dist/inputs/BinaryInputComponent.d.ts +15 -0
- package/dist/inputs/BinaryInputComponent.d.ts.map +1 -0
- package/dist/inputs/CheckboxComponent.d.ts +14 -0
- package/dist/inputs/CheckboxComponent.d.ts.map +1 -0
- package/dist/inputs/DateInputComponent.d.ts +14 -0
- package/dist/inputs/DateInputComponent.d.ts.map +1 -0
- package/dist/inputs/DateTimeInputComponent.d.ts +14 -0
- package/dist/inputs/DateTimeInputComponent.d.ts.map +1 -0
- package/dist/inputs/EnumerationComboComponent.d.ts +20 -0
- package/dist/inputs/EnumerationComboComponent.d.ts.map +1 -0
- package/dist/inputs/EnumerationRadioComponent.d.ts +22 -0
- package/dist/inputs/EnumerationRadioComponent.d.ts.map +1 -0
- package/dist/inputs/EnumerationToggleButtonbarComponent.d.ts +23 -0
- package/dist/inputs/EnumerationToggleButtonbarComponent.d.ts.map +1 -0
- package/dist/inputs/InputRenderer.d.ts +11 -0
- package/dist/inputs/InputRenderer.d.ts.map +1 -0
- package/dist/inputs/NumericInputComponent.d.ts +14 -0
- package/dist/inputs/NumericInputComponent.d.ts.map +1 -0
- package/dist/inputs/PasswordInputComponent.d.ts +14 -0
- package/dist/inputs/PasswordInputComponent.d.ts.map +1 -0
- package/dist/inputs/SwitchComponent.d.ts +14 -0
- package/dist/inputs/SwitchComponent.d.ts.map +1 -0
- package/dist/inputs/TextAreaComponent.d.ts +14 -0
- package/dist/inputs/TextAreaComponent.d.ts.map +1 -0
- package/dist/inputs/TextInputComponent.d.ts +19 -0
- package/dist/inputs/TextInputComponent.d.ts.map +1 -0
- package/dist/inputs/TimeInputComponent.d.ts +14 -0
- package/dist/inputs/TimeInputComponent.d.ts.map +1 -0
- package/dist/renderers/ButtonGroupRenderer.d.ts +10 -0
- package/dist/renderers/ButtonGroupRenderer.d.ts.map +1 -0
- package/dist/renderers/FlexRenderer.d.ts +13 -0
- package/dist/renderers/FlexRenderer.d.ts.map +1 -0
- package/dist/renderers/FormattedRenderer.d.ts +12 -0
- package/dist/renderers/FormattedRenderer.d.ts.map +1 -0
- package/dist/renderers/FrameRenderer.d.ts +17 -0
- package/dist/renderers/FrameRenderer.d.ts.map +1 -0
- package/dist/renderers/IconRenderer.d.ts +41 -0
- package/dist/renderers/IconRenderer.d.ts.map +1 -0
- package/dist/renderers/InlineButtonGroupRenderer.d.ts +22 -0
- package/dist/renderers/InlineButtonGroupRenderer.d.ts.map +1 -0
- package/dist/renderers/LinkRenderer.d.ts +17 -0
- package/dist/renderers/LinkRenderer.d.ts.map +1 -0
- package/dist/renderers/PageHeader.d.ts +13 -0
- package/dist/renderers/PageHeader.d.ts.map +1 -0
- package/dist/renderers/RowActionCell.d.ts +28 -0
- package/dist/renderers/RowActionCell.d.ts.map +1 -0
- package/dist/renderers/StandaloneButtonRenderer.d.ts +16 -0
- package/dist/renderers/StandaloneButtonRenderer.d.ts.map +1 -0
- package/dist/renderers/SubThemeWrapper.d.ts +22 -0
- package/dist/renderers/SubThemeWrapper.d.ts.map +1 -0
- package/dist/renderers/TabControllerRenderer.d.ts +10 -0
- package/dist/renderers/TabControllerRenderer.d.ts.map +1 -0
- package/dist/renderers/TableRenderer.d.ts +10 -0
- package/dist/renderers/TableRenderer.d.ts.map +1 -0
- package/dist/renderers/TableToolbar.d.ts +47 -0
- package/dist/renderers/TableToolbar.d.ts.map +1 -0
- package/dist/renderers/VisualElementRenderer.d.ts +17 -0
- package/dist/renderers/VisualElementRenderer.d.ts.map +1 -0
- package/dist/utils/alignment-mappers.d.ts +17 -0
- package/dist/utils/alignment-mappers.d.ts.map +1 -0
- package/dist/utils/build-mask-string.d.ts +31 -0
- package/dist/utils/build-mask-string.d.ts.map +1 -0
- package/dist/utils/build-query-customizer.d.ts +35 -0
- package/dist/utils/build-query-customizer.d.ts.map +1 -0
- package/dist/utils/destructive-action-utils.d.ts +17 -0
- package/dist/utils/destructive-action-utils.d.ts.map +1 -0
- package/dist/utils/find-action-by-definition.d.ts +26 -0
- package/dist/utils/find-action-by-definition.d.ts.map +1 -0
- package/dist/utils/find-on-init-action.d.ts +12 -0
- package/dist/utils/find-on-init-action.d.ts.map +1 -0
- package/dist/utils/find-visual-element.d.ts +18 -0
- package/dist/utils/find-visual-element.d.ts.map +1 -0
- package/dist/utils/flex-layout.d.ts +104 -0
- package/dist/utils/flex-layout.d.ts.map +1 -0
- package/dist/utils/get-visible-buttons.d.ts +33 -0
- package/dist/utils/get-visible-buttons.d.ts.map +1 -0
- package/dist/utils/icon-adornment.d.ts +13 -0
- package/dist/utils/icon-adornment.d.ts.map +1 -0
- package/dist/utils/mdi-alias-map.d.ts +44 -0
- package/dist/utils/mdi-alias-map.d.ts.map +1 -0
- package/dist/utils/mdi-alias-map.generated.d.ts +10 -0
- package/dist/utils/mdi-alias-map.generated.d.ts.map +1 -0
- package/dist/utils/resolve-container-type.d.ts +11 -0
- package/dist/utils/resolve-container-type.d.ts.map +1 -0
- package/dist/utils/singleton-access.d.ts +25 -0
- package/dist/utils/singleton-access.d.ts.map +1 -0
- package/dist/utils/table-column-utils.d.ts +75 -0
- package/dist/utils/table-column-utils.d.ts.map +1 -0
- package/dist/utils/table-filter-utils.d.ts +14 -0
- package/dist/utils/table-filter-utils.d.ts.map +1 -0
- package/dist/utils/table-sort-utils.d.ts +24 -0
- package/dist/utils/table-sort-utils.d.ts.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { JudoRestResponse } from '@judo/actions';
|
|
2
|
+
import { CustomDialogProps } from '@judo/feedback';
|
|
3
|
+
/**
|
|
4
|
+
* Return type of the {@link useFileHandling} hook.
|
|
5
|
+
*/
|
|
6
|
+
export interface FileHandling {
|
|
7
|
+
/**
|
|
8
|
+
* Download a binary attribute's file.
|
|
9
|
+
*
|
|
10
|
+
* Reads the download token from `data[attributeName]` and triggers
|
|
11
|
+
* either a browser download (`attachment`) or an inline preview dialog (`inline`).
|
|
12
|
+
*/
|
|
13
|
+
downloadFile: (data: Record<string, unknown>, attributeName: string, disposition: "inline" | "attachment") => Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Upload a file to a binary attribute via the two-step upload flow.
|
|
16
|
+
* Returns the server response data (upload metadata).
|
|
17
|
+
*/
|
|
18
|
+
uploadFile: (attributePath: string, file: File) => Promise<unknown>;
|
|
19
|
+
/**
|
|
20
|
+
* Extract the original filename from a JUDO binary download token (JWT).
|
|
21
|
+
* Returns `fallbackText` when the token is missing or cannot be decoded.
|
|
22
|
+
*/
|
|
23
|
+
extractFileNameFromToken: (token?: string | null, fallbackText?: string) => string;
|
|
24
|
+
/**
|
|
25
|
+
* Trigger a browser file download from a REST API response that contains a Blob.
|
|
26
|
+
* Reads filename from the `Content-Disposition` header, falling back to `"download"`.
|
|
27
|
+
*/
|
|
28
|
+
exportFile: (response: JudoRestResponse<Blob>) => void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Extract the original filename from a JUDO binary download token (JWT).
|
|
32
|
+
*
|
|
33
|
+
* Can be used outside of React components (e.g. in utility functions).
|
|
34
|
+
* For use inside components, prefer the `extractFileNameFromToken` from {@link useFileHandling}.
|
|
35
|
+
*
|
|
36
|
+
* @param token JWT download token (or null/undefined)
|
|
37
|
+
* @param fallbackText Value returned when the token is absent or decoding fails
|
|
38
|
+
* @returns The decoded filename, or `fallbackText`
|
|
39
|
+
*/
|
|
40
|
+
export declare function extractFileNameFromToken(token?: string | null, fallbackText?: string): string;
|
|
41
|
+
/** @internal Props for the inline preview dialog rendered by `downloadFile`. */
|
|
42
|
+
export interface InlinePreviewDialogProps extends CustomDialogProps<void> {
|
|
43
|
+
url: string;
|
|
44
|
+
fileName: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Dialog component that previews a binary file in an iframe.
|
|
48
|
+
* Opened by `useFileHandling().downloadFile(…, "inline")`.
|
|
49
|
+
*
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
export declare function InlinePreviewDialog({ onClose, url, fileName }: InlinePreviewDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
53
|
+
/**
|
|
54
|
+
* Hook providing file handling operations: download, upload,
|
|
55
|
+
* filename extraction from JWT tokens, and export-to-file.
|
|
56
|
+
*
|
|
57
|
+
* Adapted from the legacy `fileHandling` hook. Uses the JUDO REST
|
|
58
|
+
* API client for upload/download and the feedback dialog service
|
|
59
|
+
* for inline binary previews.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```tsx
|
|
63
|
+
* const { downloadFile, uploadFile, extractFileNameFromToken, exportFile } = useFileHandling();
|
|
64
|
+
*
|
|
65
|
+
* // Download as attachment
|
|
66
|
+
* await downloadFile(transfer, "document", "attachment");
|
|
67
|
+
*
|
|
68
|
+
* // Preview inline
|
|
69
|
+
* await downloadFile(transfer, "preview", "inline");
|
|
70
|
+
*
|
|
71
|
+
* // Upload a file
|
|
72
|
+
* const result = await uploadFile("/admin/Issue/avatar", selectedFile);
|
|
73
|
+
*
|
|
74
|
+
* // Get display name from stored token
|
|
75
|
+
* const name = extractFileNameFromToken(transfer.document, "Unnamed file");
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export declare function useFileHandling(): FileHandling;
|
|
79
|
+
//# sourceMappingURL=use-file-handling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-file-handling.d.ts","sourceRoot":"","sources":["../../src/hooks/use-file-handling.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,KAAK,iBAAiB,EAAa,MAAM,gBAAgB,CAAC;AAMnE;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B;;;;;OAKG;IACH,YAAY,EAAE,CACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,QAAQ,GAAG,YAAY,KAChC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB;;;OAGG;IACH,UAAU,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpE;;;OAGG;IACH,wBAAwB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAEnF;;;OAGG;IACH,UAAU,EAAE,CAAC,QAAQ,EAAE,gBAAgB,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;CACvD;AAkBD;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAS7F;AA4BD,gFAAgF;AAChF,MAAM,WAAW,wBAAyB,SAAQ,iBAAiB,CAAC,IAAI,CAAC;IACxE,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,wBAAwB,2CAuCvF;AAMD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAyE9C"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { PageDefinition } from '@judo/model-api';
|
|
2
|
+
/**
|
|
3
|
+
* Result of usePageTitle.
|
|
4
|
+
*/
|
|
5
|
+
export interface PageTitleResult {
|
|
6
|
+
/** Resolved page title string */
|
|
7
|
+
title: string;
|
|
8
|
+
/** Whether title is dynamic (from attribute data) */
|
|
9
|
+
isDynamic: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Hook that resolves the page title based on the page container's `titleFrom` configuration.
|
|
13
|
+
*
|
|
14
|
+
* - `titleFrom=LABEL` (default): Uses translated label from `useModelLabel(page)`.
|
|
15
|
+
* - `titleFrom=ATTRIBUTE`: Uses the value of `titleAttribute` from the transfer data store,
|
|
16
|
+
* falling back to the translated label while data is loading or unavailable.
|
|
17
|
+
*
|
|
18
|
+
* @param page - The page definition
|
|
19
|
+
* @param transferId - Optional transfer ID override (for cases where the caller is outside PageProvider, e.g. dialog titles)
|
|
20
|
+
* @returns PageTitleResult with the resolved title and whether it's dynamic
|
|
21
|
+
*/
|
|
22
|
+
export declare function usePageTitle(page: PageDefinition, transferId?: string | null): PageTitleResult;
|
|
23
|
+
//# sourceMappingURL=use-page-title.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-page-title.d.ts","sourceRoot":"","sources":["../../src/hooks/use-page-title.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIrE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,SAAS,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,eAAe,CAqD9F"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { PageDefinition, Table } from '@judo/model-api';
|
|
2
|
+
import { GridFilterModel, GridPaginationModel, GridSortModel } from '@mui/x-data-grid';
|
|
3
|
+
/**
|
|
4
|
+
* Options for useTableData hook.
|
|
5
|
+
*/
|
|
6
|
+
export interface UseTableDataOptions {
|
|
7
|
+
/** Table visual element */
|
|
8
|
+
element: Table;
|
|
9
|
+
/** Page definition (needed for action dispatch in non-eager mode) */
|
|
10
|
+
page: PageDefinition | undefined;
|
|
11
|
+
/** Raw data from DataContext */
|
|
12
|
+
rawData: any[] | undefined;
|
|
13
|
+
/** Action dispatcher for non-eager mode (optional) */
|
|
14
|
+
dispatch?: ((action: any) => Promise<void>) | null;
|
|
15
|
+
/** Loading state from data store */
|
|
16
|
+
loading?: boolean;
|
|
17
|
+
/** Whether to request total count from backend (for pagination) */
|
|
18
|
+
showTotalCount?: boolean;
|
|
19
|
+
/** Total count from server (for server-side pagination with showTotalCount) */
|
|
20
|
+
totalCount?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Result type from useTableData hook.
|
|
24
|
+
*/
|
|
25
|
+
export interface TableDataResult {
|
|
26
|
+
/** Raw data rows (DataGrid handles filtering/sorting/pagination based on mode) */
|
|
27
|
+
rows: any[];
|
|
28
|
+
/** Total count (for server-side pagination) */
|
|
29
|
+
rowCount?: number;
|
|
30
|
+
/** Current pagination state */
|
|
31
|
+
paginationModel: GridPaginationModel;
|
|
32
|
+
/** Current sort state */
|
|
33
|
+
sortModel: GridSortModel;
|
|
34
|
+
/** Current filter state */
|
|
35
|
+
filterModel: GridFilterModel;
|
|
36
|
+
/** Pagination mode: 'client' for eager, 'server' for non-eager */
|
|
37
|
+
paginationMode: "client" | "server";
|
|
38
|
+
/** Sorting mode: 'client' for eager, 'server' for non-eager */
|
|
39
|
+
sortingMode: "client" | "server";
|
|
40
|
+
/** Filter mode: 'client' for eager, 'server' for non-eager */
|
|
41
|
+
filterMode: "client" | "server";
|
|
42
|
+
/** Handle pagination change */
|
|
43
|
+
onPaginationModelChange: (model: GridPaginationModel) => void;
|
|
44
|
+
/** Handle sort change */
|
|
45
|
+
onSortModelChange: (model: GridSortModel) => void;
|
|
46
|
+
/** Handle filter change */
|
|
47
|
+
onFilterModelChange: (model: GridFilterModel) => void;
|
|
48
|
+
/** Loading state */
|
|
49
|
+
loading: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Hook for managing table data with support for both eager (client-side)
|
|
53
|
+
* and non-eager (server-side) data management modes.
|
|
54
|
+
*
|
|
55
|
+
* Leverages MUI DataGrid's built-in mode props:
|
|
56
|
+
* - `paginationMode`: 'client' | 'server'
|
|
57
|
+
* - `sortingMode`: 'client' | 'server'
|
|
58
|
+
* - `filterMode`: 'client' | 'server'
|
|
59
|
+
*
|
|
60
|
+
* **Eager Mode** (`element.isEager === true`):
|
|
61
|
+
* - Sets all modes to 'client'
|
|
62
|
+
* - DataGrid handles filtering/sorting/pagination internally
|
|
63
|
+
* - All data passed to DataGrid at once
|
|
64
|
+
* - No backend calls for user interactions
|
|
65
|
+
*
|
|
66
|
+
* **Non-Eager Mode** (`element.isEager === false`):
|
|
67
|
+
* - Sets all modes to 'server'
|
|
68
|
+
* - DataGrid fires events, we dispatch actions
|
|
69
|
+
* - Backend processes all operations and returns results
|
|
70
|
+
*
|
|
71
|
+
* @param element - The Table visual element
|
|
72
|
+
* @param page - The PageDefinition (needed for action dispatch in non-eager mode)
|
|
73
|
+
* @param rawData - The raw data array from backend/context
|
|
74
|
+
* @returns TableDataResult with mode configuration and event handlers
|
|
75
|
+
*/
|
|
76
|
+
export declare function useTableData({ element, page, rawData, dispatch, loading: externalLoading, showTotalCount, totalCount, }: UseTableDataOptions): TableDataResult;
|
|
77
|
+
//# sourceMappingURL=use-table-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-table-data.d.ts","sourceRoot":"","sources":["../../src/hooks/use-table-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAK5F;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,2BAA2B;IAC3B,OAAO,EAAE,KAAK,CAAC;IACf,qEAAqE;IACrE,IAAI,EAAE,cAAc,GAAG,SAAS,CAAC;IACjC,gCAAgC;IAChC,OAAO,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC;IAC3B,sDAAsD;IACtD,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IACnD,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mEAAmE;IACnE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,kFAAkF;IAClF,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,eAAe,EAAE,mBAAmB,CAAC;IACrC,yBAAyB;IACzB,SAAS,EAAE,aAAa,CAAC;IACzB,2BAA2B;IAC3B,WAAW,EAAE,eAAe,CAAC;IAC7B,kEAAkE;IAClE,cAAc,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACpC,+DAA+D;IAC/D,WAAW,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACjC,8DAA8D;IAC9D,UAAU,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAChC,+BAA+B;IAC/B,uBAAuB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC9D,yBAAyB;IACzB,iBAAiB,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAClD,2BAA2B;IAC3B,mBAAmB,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IACtD,oBAAoB;IACpB,OAAO,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,YAAY,CAAC,EAC5B,OAAO,EACP,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,OAAO,EAAE,eAAe,EACxB,cAAsB,EACtB,UAAU,GACV,EAAE,mBAAmB,GAAG,eAAe,CAqHvC"}
|
package/dist/index.css
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export { ContainerErrorBoundary, TableContainerErrorBoundary, FormContainerErrorBoundary, ViewContainerErrorBoundary, type ContainerErrorBoundaryProps, } from './errors';
|
|
2
|
+
export { PageRenderer, type PageRendererProps } from './containers/PageRenderer';
|
|
3
|
+
export { resolveContainerType } from './utils/resolve-container-type';
|
|
4
|
+
export { TableContainerRenderer, type TableContainerRendererProps } from './containers/TableContainerRenderer';
|
|
5
|
+
export { FormContainerRenderer, type FormContainerRendererProps } from './containers/FormContainerRenderer';
|
|
6
|
+
export { ViewContainerRenderer, type ViewContainerRendererProps } from './containers/ViewContainerRenderer';
|
|
7
|
+
export { usePageTitle, type PageTitleResult } from './hooks/use-page-title';
|
|
8
|
+
export { useTableData, type TableDataResult } from './hooks/use-table-data';
|
|
9
|
+
export { useFileHandling, extractFileNameFromToken, type FileHandling, type InlinePreviewDialogProps, } from './hooks/use-file-handling';
|
|
10
|
+
export { VisualElementRenderer, type VisualElementRendererProps } from './renderers/VisualElementRenderer';
|
|
11
|
+
export { FlexRenderer, type FlexRendererProps } from './renderers/FlexRenderer';
|
|
12
|
+
export { TableRenderer, type TableRendererProps } from './renderers/TableRenderer';
|
|
13
|
+
export { LinkRenderer, type LinkRendererProps } from './renderers/LinkRenderer';
|
|
14
|
+
export { LinkSelectorDialog, type LinkSelectorDialogProps } from './dialogs/LinkSelectorDialog';
|
|
15
|
+
export { TabControllerRenderer, type TabControllerRendererProps } from './renderers/TabControllerRenderer';
|
|
16
|
+
export { ButtonGroupRenderer, type ButtonGroupRendererProps } from './renderers/ButtonGroupRenderer';
|
|
17
|
+
export { InlineButtonGroupRenderer, type InlineButtonGroupRendererProps } from './renderers/InlineButtonGroupRenderer';
|
|
18
|
+
export { StandaloneButtonRenderer, type StandaloneButtonRendererProps } from './renderers/StandaloneButtonRenderer';
|
|
19
|
+
export { FrameRenderer, type FrameRendererProps } from './renderers/FrameRenderer';
|
|
20
|
+
export { SubThemeWrapper, type SubThemeWrapperProps } from './renderers/SubThemeWrapper';
|
|
21
|
+
export { IconRenderer, type IconRendererProps } from './renderers/IconRenderer';
|
|
22
|
+
export { PageHeader, type PageHeaderProps } from './renderers/PageHeader';
|
|
23
|
+
export { InputRenderer, type InputRendererProps } from './inputs/InputRenderer';
|
|
24
|
+
export { TextInputComponent, type TextInputComponentProps } from './inputs/TextInputComponent';
|
|
25
|
+
export { NumericInputComponent, type NumericInputComponentProps } from './inputs/NumericInputComponent';
|
|
26
|
+
export { DateInputComponent, type DateInputComponentProps } from './inputs/DateInputComponent';
|
|
27
|
+
export { DateTimeInputComponent, type DateTimeInputComponentProps } from './inputs/DateTimeInputComponent';
|
|
28
|
+
export { TimeInputComponent, type TimeInputComponentProps } from './inputs/TimeInputComponent';
|
|
29
|
+
export { TextAreaComponent, type TextAreaComponentProps } from './inputs/TextAreaComponent';
|
|
30
|
+
export { CheckboxComponent, type CheckboxComponentProps } from './inputs/CheckboxComponent';
|
|
31
|
+
export { SwitchComponent, type SwitchComponentProps } from './inputs/SwitchComponent';
|
|
32
|
+
export { EnumerationComboComponent, type EnumerationComboComponentProps } from './inputs/EnumerationComboComponent';
|
|
33
|
+
export { EnumerationRadioComponent, type EnumerationRadioComponentProps } from './inputs/EnumerationRadioComponent';
|
|
34
|
+
export { EnumerationToggleButtonbarComponent, type EnumerationToggleButtonbarComponentProps, } from './inputs/EnumerationToggleButtonbarComponent';
|
|
35
|
+
export { BinaryInputComponent, type BinaryInputComponentProps } from './inputs/BinaryInputComponent';
|
|
36
|
+
export { PasswordInputComponent, type PasswordInputComponentProps } from './inputs/PasswordInputComponent';
|
|
37
|
+
export { findVisualElementByType, findVisualElementById, findVisualElementBySourceId, flattenVisualElements, } from './utils/find-visual-element';
|
|
38
|
+
export { mapMainAxisAlignment, mapCrossAxisAlignment, mapAlignment } from './utils/alignment-mappers';
|
|
39
|
+
export { findOnInitAction } from './utils/find-on-init-action';
|
|
40
|
+
export { buildMaskString } from './utils/build-mask-string';
|
|
41
|
+
export { isSingletonAccessPage, getSingletonAccessRelation } from './utils/singleton-access';
|
|
42
|
+
export { buildInitialOrderBy, buildInitialSortModel, convertSortModelToOrderBy } from './utils/table-sort-utils';
|
|
43
|
+
export { calculateChildGridSize, calculateHorizontalGridSize, calculateVerticalGridSize, calculateScaledSize, isVerticalLayout, DEFAULT_COL, FULL_GRID_WIDTH, type GridSize, } from './utils/flex-layout';
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { A as calculateVerticalGridSize, C as BinaryInputComponent, D as calculateChildGridSize, E as FULL_GRID_WIDTH, M as mapAlignment, N as mapCrossAxisAlignment, O as calculateHorizontalGridSize, P as mapMainAxisAlignment, S as CheckboxComponent, T as DEFAULT_COL, _ as EnumerationToggleButtonbarComponent, a as StandaloneButtonRenderer, b as DateTimeInputComponent, c as LinkSelectorDialog, d as TimeInputComponent, f as TextInputComponent, g as NumericInputComponent, h as PasswordInputComponent, i as SubThemeWrapper, j as isVerticalLayout, k as calculateScaledSize, l as InlineButtonGroupRenderer, m as SwitchComponent, n as VisualElementRenderer, o as LinkRenderer, p as TextAreaComponent, r as TabControllerRenderer, s as buildMaskString, t as FlexRenderer, u as InputRenderer, v as EnumerationRadioComponent, w as FrameRenderer, x as DateInputComponent, y as EnumerationComboComponent } from "./FlexRenderer-0KCxU9QU.js";
|
|
2
|
+
import { a as buildInitialSortModel, c as ButtonGroupRenderer, i as buildInitialOrderBy, l as IconRenderer, m as usePageTitle, n as TableRenderer, o as convertSortModelToOrderBy, r as useTableData, s as PageHeader, t as findOnInitAction } from "./find-on-init-action-C5CqxQaH.js";
|
|
3
|
+
import { a as findVisualElementByType, i as findVisualElementBySourceId, o as flattenVisualElements, r as findVisualElementById, t as TableContainerRenderer } from "./TableContainerRenderer-gKBlsD4S.js";
|
|
4
|
+
import { t as FormContainerRenderer } from "./FormContainerRenderer-B8H4kyz0.js";
|
|
5
|
+
import { i as isSingletonAccessPage, r as getSingletonAccessRelation, t as ViewContainerRenderer } from "./ViewContainerRenderer-DCRaE_dq.js";
|
|
6
|
+
import ExpandLessIcon from "@mui/icons-material/ExpandLess";
|
|
7
|
+
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
|
8
|
+
import { Alert, AlertTitle, Box, Button, CircularProgress, Collapse, DialogActions, DialogContent, DialogTitle, IconButton, Typography } from "@mui/material";
|
|
9
|
+
import { Component, Suspense, lazy, useCallback } from "react";
|
|
10
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { PageContainerType } from "@judo/model-api";
|
|
12
|
+
import { useApi } from "@judo/actions";
|
|
13
|
+
import { useDialog } from "@judo/feedback";
|
|
14
|
+
import CloseIcon from "@mui/icons-material/Close";
|
|
15
|
+
import { useTranslation } from "react-i18next";
|
|
16
|
+
var ContainerErrorBoundary = class extends Component {
|
|
17
|
+
state = {
|
|
18
|
+
hasError: !1,
|
|
19
|
+
error: null,
|
|
20
|
+
errorInfo: null,
|
|
21
|
+
showDetails: !1
|
|
22
|
+
};
|
|
23
|
+
static getDerivedStateFromError(m) {
|
|
24
|
+
return {
|
|
25
|
+
hasError: !0,
|
|
26
|
+
error: m
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
componentDidCatch(m, U) {
|
|
30
|
+
this.setState({ errorInfo: U }), console.error("Container render error:", m, U);
|
|
31
|
+
}
|
|
32
|
+
toggleDetails = () => {
|
|
33
|
+
this.setState((m) => ({ showDetails: !m.showDetails }));
|
|
34
|
+
};
|
|
35
|
+
safeStringify(m) {
|
|
36
|
+
let U = /* @__PURE__ */ new WeakSet();
|
|
37
|
+
return JSON.stringify(m, (m, W) => {
|
|
38
|
+
if (typeof W == "object" && W) {
|
|
39
|
+
if (U.has(W)) return "[Circular]";
|
|
40
|
+
U.add(W);
|
|
41
|
+
}
|
|
42
|
+
return W;
|
|
43
|
+
}, 2);
|
|
44
|
+
}
|
|
45
|
+
render() {
|
|
46
|
+
if (this.state.hasError) {
|
|
47
|
+
let { containerType: m, element: U } = this.props, { error: W, errorInfo: G, showDetails: K } = this.state;
|
|
48
|
+
return /* @__PURE__ */ jsx(Box, {
|
|
49
|
+
p: 2,
|
|
50
|
+
"data-testid": `error-boundary::${m.toLowerCase()}`,
|
|
51
|
+
children: /* @__PURE__ */ jsxs(Alert, {
|
|
52
|
+
severity: "error",
|
|
53
|
+
children: [
|
|
54
|
+
/* @__PURE__ */ jsxs(AlertTitle, { children: [m, " Container Error"] }),
|
|
55
|
+
/* @__PURE__ */ jsxs(Typography, {
|
|
56
|
+
variant: "body2",
|
|
57
|
+
children: [
|
|
58
|
+
"Failed to render ",
|
|
59
|
+
m.toLowerCase(),
|
|
60
|
+
" container",
|
|
61
|
+
U && ` for element: ${U.name}`
|
|
62
|
+
]
|
|
63
|
+
}),
|
|
64
|
+
/* @__PURE__ */ jsxs(Box, {
|
|
65
|
+
mt: 1,
|
|
66
|
+
children: [/* @__PURE__ */ jsx(IconButton, {
|
|
67
|
+
size: "small",
|
|
68
|
+
onClick: this.toggleDetails,
|
|
69
|
+
"data-testid": "error-boundary::toggle-details",
|
|
70
|
+
"aria-label": K ? "Hide details" : "Show details",
|
|
71
|
+
children: jsx(K ? ExpandLessIcon : ExpandMoreIcon, {})
|
|
72
|
+
}), /* @__PURE__ */ jsxs(Typography, {
|
|
73
|
+
variant: "caption",
|
|
74
|
+
component: "span",
|
|
75
|
+
children: [K ? "Hide" : "Show", " Details"]
|
|
76
|
+
})]
|
|
77
|
+
}),
|
|
78
|
+
/* @__PURE__ */ jsx(Collapse, {
|
|
79
|
+
in: K,
|
|
80
|
+
children: /* @__PURE__ */ jsxs(Box, {
|
|
81
|
+
mt: 2,
|
|
82
|
+
p: 1,
|
|
83
|
+
sx: {
|
|
84
|
+
bgcolor: "grey.100",
|
|
85
|
+
borderRadius: 1
|
|
86
|
+
},
|
|
87
|
+
"data-testid": "error-boundary::details",
|
|
88
|
+
children: [
|
|
89
|
+
/* @__PURE__ */ jsx(Typography, {
|
|
90
|
+
variant: "subtitle2",
|
|
91
|
+
children: "Error:"
|
|
92
|
+
}),
|
|
93
|
+
/* @__PURE__ */ jsx(Typography, {
|
|
94
|
+
variant: "body2",
|
|
95
|
+
fontFamily: "monospace",
|
|
96
|
+
"data-testid": "error-boundary::error-message",
|
|
97
|
+
children: W?.message
|
|
98
|
+
}),
|
|
99
|
+
U && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
100
|
+
/* @__PURE__ */ jsx(Typography, {
|
|
101
|
+
variant: "subtitle2",
|
|
102
|
+
mt: 1,
|
|
103
|
+
children: "Element Path:"
|
|
104
|
+
}),
|
|
105
|
+
/* @__PURE__ */ jsx(Typography, {
|
|
106
|
+
variant: "body2",
|
|
107
|
+
fontFamily: "monospace",
|
|
108
|
+
"data-testid": "error-boundary::element-path",
|
|
109
|
+
children: U.sourceId ?? U["xmi:id"]
|
|
110
|
+
}),
|
|
111
|
+
/* @__PURE__ */ jsx(Typography, {
|
|
112
|
+
variant: "subtitle2",
|
|
113
|
+
mt: 1,
|
|
114
|
+
children: "Model Snippet:"
|
|
115
|
+
}),
|
|
116
|
+
/* @__PURE__ */ jsx(Box, {
|
|
117
|
+
component: "pre",
|
|
118
|
+
fontSize: "0.75rem",
|
|
119
|
+
overflow: "auto",
|
|
120
|
+
maxHeight: 200,
|
|
121
|
+
"data-testid": "error-boundary::model-snippet",
|
|
122
|
+
children: this.safeStringify(U)
|
|
123
|
+
})
|
|
124
|
+
] }),
|
|
125
|
+
G && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Typography, {
|
|
126
|
+
variant: "subtitle2",
|
|
127
|
+
mt: 1,
|
|
128
|
+
children: "Component Stack:"
|
|
129
|
+
}), /* @__PURE__ */ jsx(Box, {
|
|
130
|
+
component: "pre",
|
|
131
|
+
fontSize: "0.75rem",
|
|
132
|
+
overflow: "auto",
|
|
133
|
+
maxHeight: 200,
|
|
134
|
+
"data-testid": "error-boundary::component-stack",
|
|
135
|
+
children: G.componentStack
|
|
136
|
+
})] })
|
|
137
|
+
]
|
|
138
|
+
})
|
|
139
|
+
})
|
|
140
|
+
]
|
|
141
|
+
})
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return this.props.children;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
function TableContainerErrorBoundary({ children: m, element: U }) {
|
|
148
|
+
return /* @__PURE__ */ jsx(ContainerErrorBoundary, {
|
|
149
|
+
containerType: "TABLE",
|
|
150
|
+
element: U,
|
|
151
|
+
children: m
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function FormContainerErrorBoundary({ children: m, element: U }) {
|
|
155
|
+
return /* @__PURE__ */ jsx(ContainerErrorBoundary, {
|
|
156
|
+
containerType: "FORM",
|
|
157
|
+
element: U,
|
|
158
|
+
children: m
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
function ViewContainerErrorBoundary({ children: m, element: U }) {
|
|
162
|
+
return /* @__PURE__ */ jsx(ContainerErrorBoundary, {
|
|
163
|
+
containerType: "VIEW",
|
|
164
|
+
element: U,
|
|
165
|
+
children: m
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
function resolveContainerType(m) {
|
|
169
|
+
return m.type ? m.type : PageContainerType.TABLE;
|
|
170
|
+
}
|
|
171
|
+
var TableContainerRendererLazy = lazy(() => import("./TableContainerRenderer-qbzKI1Cd.js")), FormContainerRendererLazy = lazy(() => import("./FormContainerRenderer-CtuXP8jP.js")), ViewContainerRendererLazy = lazy(() => import("./ViewContainerRenderer-7Cx4fcLp.js"));
|
|
172
|
+
function PageRenderer({ page: m }) {
|
|
173
|
+
let U = m.container;
|
|
174
|
+
if (typeof U == "string") return /* @__PURE__ */ jsxs(Box, {
|
|
175
|
+
p: 2,
|
|
176
|
+
"data-testid": `page-renderer::${m.name}::unresolved`,
|
|
177
|
+
children: ["Container reference not resolved: ", U]
|
|
178
|
+
});
|
|
179
|
+
let W = resolveContainerType(U), G = m["xmi:id"] ?? m.name ?? "unknown-page", K = /* @__PURE__ */ jsx(Box, {
|
|
180
|
+
display: "flex",
|
|
181
|
+
justifyContent: "center",
|
|
182
|
+
p: 4,
|
|
183
|
+
"data-testid": "page-renderer::loading",
|
|
184
|
+
children: /* @__PURE__ */ jsx(CircularProgress, {})
|
|
185
|
+
});
|
|
186
|
+
switch (W) {
|
|
187
|
+
case PageContainerType.TABLE: return /* @__PURE__ */ jsx(TableContainerErrorBoundary, {
|
|
188
|
+
element: U,
|
|
189
|
+
children: /* @__PURE__ */ jsx(Suspense, {
|
|
190
|
+
fallback: K,
|
|
191
|
+
children: /* @__PURE__ */ jsx(TableContainerRendererLazy, { page: m })
|
|
192
|
+
})
|
|
193
|
+
}, G);
|
|
194
|
+
case PageContainerType.FORM: return /* @__PURE__ */ jsx(FormContainerErrorBoundary, {
|
|
195
|
+
element: U,
|
|
196
|
+
children: /* @__PURE__ */ jsx(Suspense, {
|
|
197
|
+
fallback: K,
|
|
198
|
+
children: /* @__PURE__ */ jsx(FormContainerRendererLazy, { page: m })
|
|
199
|
+
})
|
|
200
|
+
}, G);
|
|
201
|
+
default: return /* @__PURE__ */ jsx(ViewContainerErrorBoundary, {
|
|
202
|
+
element: U,
|
|
203
|
+
children: /* @__PURE__ */ jsx(Suspense, {
|
|
204
|
+
fallback: K,
|
|
205
|
+
children: /* @__PURE__ */ jsx(ViewContainerRendererLazy, { page: m })
|
|
206
|
+
})
|
|
207
|
+
}, G);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function decodeJwtPayload(m) {
|
|
211
|
+
let U = m.split(".");
|
|
212
|
+
if (U.length !== 3) throw Error("Invalid JWT format");
|
|
213
|
+
let W = U[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
214
|
+
return JSON.parse(atob(W));
|
|
215
|
+
}
|
|
216
|
+
function extractFileNameFromToken(m, U) {
|
|
217
|
+
if (!m) return U ?? "";
|
|
218
|
+
try {
|
|
219
|
+
return decodeJwtPayload(m).fileName ?? U ?? "";
|
|
220
|
+
} catch {
|
|
221
|
+
return console.error(`Decoding of JWT token failed for: ${m}`), U ?? "";
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function parseFileNameFromContentDisposition(m) {
|
|
225
|
+
if (m) return m.match(/filename="(.*)"/)?.[1];
|
|
226
|
+
}
|
|
227
|
+
function triggerBrowserDownload(m, U) {
|
|
228
|
+
let W = document.createElement("a");
|
|
229
|
+
W.href = m, W.download = U, document.body.appendChild(W), W.click(), document.body.removeChild(W);
|
|
230
|
+
}
|
|
231
|
+
function InlinePreviewDialog({ onClose: m, url: U, fileName: W }) {
|
|
232
|
+
let { t: G } = useTranslation();
|
|
233
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
234
|
+
/* @__PURE__ */ jsxs(DialogTitle, { children: [W, /* @__PURE__ */ jsx(IconButton, {
|
|
235
|
+
"data-testid": "close-inline-binary-dialog-top-button",
|
|
236
|
+
"aria-label": "close",
|
|
237
|
+
onClick: () => m(),
|
|
238
|
+
sx: {
|
|
239
|
+
position: "absolute",
|
|
240
|
+
right: 8,
|
|
241
|
+
top: 8,
|
|
242
|
+
color: (m) => m.palette.grey[500]
|
|
243
|
+
},
|
|
244
|
+
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
245
|
+
})] }),
|
|
246
|
+
/* @__PURE__ */ jsx(DialogContent, {
|
|
247
|
+
dividers: !0,
|
|
248
|
+
children: /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx("iframe", {
|
|
249
|
+
src: U,
|
|
250
|
+
title: W,
|
|
251
|
+
sandbox: "allow-same-origin",
|
|
252
|
+
width: "100%",
|
|
253
|
+
height: typeof document < "u" ? document.body.scrollHeight * .6 : 600,
|
|
254
|
+
style: { border: 0 }
|
|
255
|
+
}) })
|
|
256
|
+
}),
|
|
257
|
+
/* @__PURE__ */ jsx(DialogActions, { children: /* @__PURE__ */ jsx(Button, {
|
|
258
|
+
"data-testid": "close-inline-binary-dialog-button",
|
|
259
|
+
variant: "text",
|
|
260
|
+
onClick: () => m(),
|
|
261
|
+
children: G("system.action.close.label", { defaultValue: "Close" })
|
|
262
|
+
}) })
|
|
263
|
+
] });
|
|
264
|
+
}
|
|
265
|
+
function useFileHandling() {
|
|
266
|
+
let m = useApi(), U = useDialog(), W = useCallback((m, U) => extractFileNameFromToken(m, U), []), G = useCallback((m) => {
|
|
267
|
+
let U = parseFileNameFromContentDisposition(m.headers.get("content-disposition")) ?? "download", W = m.headers.get("content-type"), G = W ? new Blob([m.data], { type: W }) : m.data, K = URL.createObjectURL(G);
|
|
268
|
+
triggerBrowserDownload(K, U), URL.revokeObjectURL(K);
|
|
269
|
+
}, []);
|
|
270
|
+
return {
|
|
271
|
+
downloadFile: useCallback(async (W, G, K) => {
|
|
272
|
+
let q = W[G];
|
|
273
|
+
if (typeof q != "string") throw Error(`No download token found for attribute "${G}"`);
|
|
274
|
+
let J = await m.downloadFile(q, K), Y = J.headers.get("content-disposition"), X = J.headers.get("content-type"), Z = parseFileNameFromContentDisposition(Y) ?? extractFileNameFromToken(q, "download"), Q = X ? new Blob([J.data], { type: X }) : J.data, $ = URL.createObjectURL(Q);
|
|
275
|
+
if (K === "inline") try {
|
|
276
|
+
await U.open({
|
|
277
|
+
component: InlinePreviewDialog,
|
|
278
|
+
props: {
|
|
279
|
+
url: $,
|
|
280
|
+
fileName: Z
|
|
281
|
+
},
|
|
282
|
+
size: "lg",
|
|
283
|
+
fullWidth: !0,
|
|
284
|
+
disableBackdropClick: !0
|
|
285
|
+
});
|
|
286
|
+
} finally {
|
|
287
|
+
URL.revokeObjectURL($);
|
|
288
|
+
}
|
|
289
|
+
else triggerBrowserDownload($, Z), URL.revokeObjectURL($);
|
|
290
|
+
}, [m, U]),
|
|
291
|
+
uploadFile: useCallback(async (U, W) => (await m.uploadFile(U, W)).data, [m]),
|
|
292
|
+
extractFileNameFromToken: W,
|
|
293
|
+
exportFile: G
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
export { BinaryInputComponent, ButtonGroupRenderer, CheckboxComponent, ContainerErrorBoundary, DEFAULT_COL, DateInputComponent, DateTimeInputComponent, EnumerationComboComponent, EnumerationRadioComponent, EnumerationToggleButtonbarComponent, FULL_GRID_WIDTH, FlexRenderer, FormContainerErrorBoundary, FormContainerRenderer, FrameRenderer, IconRenderer, InlineButtonGroupRenderer, InputRenderer, LinkRenderer, LinkSelectorDialog, NumericInputComponent, PageHeader, PageRenderer, PasswordInputComponent, StandaloneButtonRenderer, SubThemeWrapper, SwitchComponent, TabControllerRenderer, TableContainerErrorBoundary, TableContainerRenderer, TableRenderer, TextAreaComponent, TextInputComponent, TimeInputComponent, ViewContainerErrorBoundary, ViewContainerRenderer, VisualElementRenderer, buildInitialOrderBy, buildInitialSortModel, buildMaskString, calculateChildGridSize, calculateHorizontalGridSize, calculateScaledSize, calculateVerticalGridSize, convertSortModelToOrderBy, extractFileNameFromToken, findOnInitAction, findVisualElementById, findVisualElementBySourceId, findVisualElementByType, flattenVisualElements, getSingletonAccessRelation, isSingletonAccessPage, isVerticalLayout, mapAlignment, mapCrossAxisAlignment, mapMainAxisAlignment, resolveContainerType, useFileHandling, usePageTitle, useTableData };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/errors/ContainerErrorBoundary.tsx","../src/utils/resolve-container-type.ts","../src/containers/PageRenderer.tsx","../src/hooks/use-file-handling.tsx"],"sourcesContent":["import type { VisualElement } from \"@judo/model-api\";\nimport ExpandLessIcon from \"@mui/icons-material/ExpandLess\";\nimport ExpandMoreIcon from \"@mui/icons-material/ExpandMore\";\nimport { Alert, AlertTitle, Box, Collapse, IconButton, Typography } from \"@mui/material\";\nimport { Component, type ErrorInfo, type ReactNode } from \"react\";\n\nexport interface ContainerErrorBoundaryProps {\n\tchildren: ReactNode;\n\tcontainerType: \"TABLE\" | \"FORM\" | \"VIEW\";\n\telement?: VisualElement;\n}\n\ninterface ErrorBoundaryState {\n\thasError: boolean;\n\terror: Error | null;\n\terrorInfo: ErrorInfo | null;\n\tshowDetails: boolean;\n}\n\n/**\n * Error boundary for container types.\n * No retry - displays error with model context for debugging.\n */\nexport class ContainerErrorBoundary extends Component<ContainerErrorBoundaryProps, ErrorBoundaryState> {\n\tstate: ErrorBoundaryState = {\n\t\thasError: false,\n\t\terror: null,\n\t\terrorInfo: null,\n\t\tshowDetails: false,\n\t};\n\n\tstatic getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\n\t\treturn { hasError: true, error };\n\t}\n\n\tcomponentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n\t\tthis.setState({ errorInfo });\n\t\t// Log to error reporting service\n\t\tconsole.error(\"Container render error:\", error, errorInfo);\n\t}\n\n\ttoggleDetails = (): void => {\n\t\tthis.setState((prev) => ({ showDetails: !prev.showDetails }));\n\t};\n\n\t/**\n\t * Safely stringify objects with cyclic references.\n\t */\n\tprivate safeStringify(obj: unknown): string {\n\t\tconst seen = new WeakSet();\n\t\treturn JSON.stringify(\n\t\t\tobj,\n\t\t\t(key, value) => {\n\t\t\t\tif (typeof value === \"object\" && value !== null) {\n\t\t\t\t\tif (seen.has(value)) {\n\t\t\t\t\t\treturn \"[Circular]\";\n\t\t\t\t\t}\n\t\t\t\t\tseen.add(value);\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t},\n\t\t\t2\n\t\t);\n\t}\n\n\trender() {\n\t\tif (this.state.hasError) {\n\t\t\tconst { containerType, element } = this.props;\n\t\t\tconst { error, errorInfo, showDetails } = this.state;\n\n\t\t\treturn (\n\t\t\t\t<Box p={2} data-testid={`error-boundary::${containerType.toLowerCase()}`}>\n\t\t\t\t\t<Alert severity=\"error\">\n\t\t\t\t\t\t<AlertTitle>{containerType} Container Error</AlertTitle>\n\t\t\t\t\t\t<Typography variant=\"body2\">\n\t\t\t\t\t\t\tFailed to render {containerType.toLowerCase()} container\n\t\t\t\t\t\t\t{element && ` for element: ${element.name}`}\n\t\t\t\t\t\t</Typography>\n\n\t\t\t\t\t\t<Box mt={1}>\n\t\t\t\t\t\t\t<IconButton\n\t\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\t\tonClick={this.toggleDetails}\n\t\t\t\t\t\t\t\tdata-testid=\"error-boundary::toggle-details\"\n\t\t\t\t\t\t\t\taria-label={showDetails ? \"Hide details\" : \"Show details\"}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{showDetails ? <ExpandLessIcon /> : <ExpandMoreIcon />}\n\t\t\t\t\t\t\t</IconButton>\n\t\t\t\t\t\t\t<Typography variant=\"caption\" component=\"span\">\n\t\t\t\t\t\t\t\t{showDetails ? \"Hide\" : \"Show\"} Details\n\t\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t</Box>\n\n\t\t\t\t\t\t<Collapse in={showDetails}>\n\t\t\t\t\t\t\t<Box mt={2} p={1} sx={{ bgcolor: \"grey.100\", borderRadius: 1 }} data-testid=\"error-boundary::details\">\n\t\t\t\t\t\t\t\t<Typography variant=\"subtitle2\">Error:</Typography>\n\t\t\t\t\t\t\t\t<Typography variant=\"body2\" fontFamily=\"monospace\" data-testid=\"error-boundary::error-message\">\n\t\t\t\t\t\t\t\t\t{error?.message}\n\t\t\t\t\t\t\t\t</Typography>\n\n\t\t\t\t\t\t\t\t{element && (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<Typography variant=\"subtitle2\" mt={1}>\n\t\t\t\t\t\t\t\t\t\t\tElement Path:\n\t\t\t\t\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t\t\t\t\t<Typography variant=\"body2\" fontFamily=\"monospace\" data-testid=\"error-boundary::element-path\">\n\t\t\t\t\t\t\t\t\t\t\t{element.sourceId ?? element[\"xmi:id\"]}\n\t\t\t\t\t\t\t\t\t\t</Typography>\n\n\t\t\t\t\t\t\t\t\t\t<Typography variant=\"subtitle2\" mt={1}>\n\t\t\t\t\t\t\t\t\t\t\tModel Snippet:\n\t\t\t\t\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\t\t\t\tcomponent=\"pre\"\n\t\t\t\t\t\t\t\t\t\t\tfontSize=\"0.75rem\"\n\t\t\t\t\t\t\t\t\t\t\toverflow=\"auto\"\n\t\t\t\t\t\t\t\t\t\t\tmaxHeight={200}\n\t\t\t\t\t\t\t\t\t\t\tdata-testid=\"error-boundary::model-snippet\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{this.safeStringify(element)}\n\t\t\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t{errorInfo && (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<Typography variant=\"subtitle2\" mt={1}>\n\t\t\t\t\t\t\t\t\t\t\tComponent Stack:\n\t\t\t\t\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\t\t\t\tcomponent=\"pre\"\n\t\t\t\t\t\t\t\t\t\t\tfontSize=\"0.75rem\"\n\t\t\t\t\t\t\t\t\t\t\toverflow=\"auto\"\n\t\t\t\t\t\t\t\t\t\t\tmaxHeight={200}\n\t\t\t\t\t\t\t\t\t\t\tdata-testid=\"error-boundary::component-stack\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{errorInfo.componentStack}\n\t\t\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t</Collapse>\n\t\t\t\t\t</Alert>\n\t\t\t\t</Box>\n\t\t\t);\n\t\t}\n\n\t\treturn this.props.children;\n\t}\n}\n\n// Specific error boundaries per container type\nexport function TableContainerErrorBoundary({ children, element }: { children: ReactNode; element?: VisualElement }) {\n\treturn (\n\t\t<ContainerErrorBoundary containerType=\"TABLE\" element={element}>\n\t\t\t{children}\n\t\t</ContainerErrorBoundary>\n\t);\n}\n\nexport function FormContainerErrorBoundary({ children, element }: { children: ReactNode; element?: VisualElement }) {\n\treturn (\n\t\t<ContainerErrorBoundary containerType=\"FORM\" element={element}>\n\t\t\t{children}\n\t\t</ContainerErrorBoundary>\n\t);\n}\n\nexport function ViewContainerErrorBoundary({ children, element }: { children: ReactNode; element?: VisualElement }) {\n\treturn (\n\t\t<ContainerErrorBoundary containerType=\"VIEW\" element={element}>\n\t\t\t{children}\n\t\t</ContainerErrorBoundary>\n\t);\n}\n","import type { PageContainer } from \"@judo/model-api\";\nimport { PageContainerType } from \"@judo/model-api\";\n\n/**\n * Resolve the effective container type.\n * In EMF/ECore, default enum values are not serialized.\n * Since TABLE is the first literal (value 0), it's the default when type is not present.\n *\n * Separated from PageRenderer.tsx to preserve HMR boundaries.\n * See: specs/HMR.md — Standard I: Single-Authority Export Mandate\n */\nexport function resolveContainerType(container: PageContainer): PageContainerType {\n\t// When type is explicitly set in the model, use it\n\tif (container.type) {\n\t\treturn container.type;\n\t}\n\t// When type is not present, it means TABLE (the EMF default)\n\treturn PageContainerType.TABLE;\n}\n","import type { PageDefinition } from \"@judo/model-api\";\nimport { PageContainerType } from \"@judo/model-api\";\nimport { Box, CircularProgress } from \"@mui/material\";\nimport { Suspense, lazy } from \"react\";\nimport { FormContainerErrorBoundary, TableContainerErrorBoundary, ViewContainerErrorBoundary } from \"../errors\";\nimport { resolveContainerType } from \"../utils/resolve-container-type\";\n\n// Lazy-loaded chunks for code splitting by container type\nconst TableContainerRendererLazy = lazy(() => import(\"./TableContainerRenderer\"));\nconst FormContainerRendererLazy = lazy(() => import(\"./FormContainerRenderer\"));\nconst ViewContainerRendererLazy = lazy(() => import(\"./ViewContainerRenderer\"));\n\nexport interface PageRendererProps {\n\tpage: PageDefinition;\n}\n\n/**\n * Main page renderer that delegates to container type.\n */\nexport function PageRenderer({ page }: PageRendererProps) {\n\t// Container should be resolved to PageContainer object after model loading\n\tconst container = page.container;\n\tif (typeof container === \"string\") {\n\t\treturn (\n\t\t\t<Box p={2} data-testid={`page-renderer::${page.name}::unresolved`}>\n\t\t\t\tContainer reference not resolved: {container}\n\t\t\t</Box>\n\t\t);\n\t}\n\n\tconst effectiveType = resolveContainerType(container);\n\n\t// Use page ID as key to force unmount/remount on navigation\n\tconst pageKey = page[\"xmi:id\"] ?? page.name ?? \"unknown-page\";\n\n\tconst LoadingFallback = (\n\t\t<Box display=\"flex\" justifyContent=\"center\" p={4} data-testid=\"page-renderer::loading\">\n\t\t\t<CircularProgress />\n\t\t</Box>\n\t);\n\n\tswitch (effectiveType) {\n\t\tcase PageContainerType.TABLE:\n\t\t\treturn (\n\t\t\t\t<TableContainerErrorBoundary element={container} key={pageKey}>\n\t\t\t\t\t<Suspense fallback={LoadingFallback}>\n\t\t\t\t\t\t<TableContainerRendererLazy page={page} />\n\t\t\t\t\t</Suspense>\n\t\t\t\t</TableContainerErrorBoundary>\n\t\t\t);\n\n\t\tcase PageContainerType.FORM:\n\t\t\treturn (\n\t\t\t\t<FormContainerErrorBoundary element={container} key={pageKey}>\n\t\t\t\t\t<Suspense fallback={LoadingFallback}>\n\t\t\t\t\t\t<FormContainerRendererLazy page={page} />\n\t\t\t\t\t</Suspense>\n\t\t\t\t</FormContainerErrorBoundary>\n\t\t\t);\n\n\t\tdefault:\n\t\t\treturn (\n\t\t\t\t<ViewContainerErrorBoundary element={container} key={pageKey}>\n\t\t\t\t\t<Suspense fallback={LoadingFallback}>\n\t\t\t\t\t\t<ViewContainerRendererLazy page={page} />\n\t\t\t\t\t</Suspense>\n\t\t\t\t</ViewContainerErrorBoundary>\n\t\t\t);\n\t}\n}\n","import { useApi, type JudoRestResponse } from \"@judo/actions\";\nimport { type CustomDialogProps, useDialog } from \"@judo/feedback\";\nimport CloseIcon from \"@mui/icons-material/Close\";\nimport { Box, Button, DialogActions, DialogContent, DialogTitle, IconButton } from \"@mui/material\";\nimport { useCallback } from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\n/**\n * Return type of the {@link useFileHandling} hook.\n */\nexport interface FileHandling {\n\t/**\n\t * Download a binary attribute's file.\n\t *\n\t * Reads the download token from `data[attributeName]` and triggers\n\t * either a browser download (`attachment`) or an inline preview dialog (`inline`).\n\t */\n\tdownloadFile: (\n\t\tdata: Record<string, unknown>,\n\t\tattributeName: string,\n\t\tdisposition: \"inline\" | \"attachment\"\n\t) => Promise<void>;\n\n\t/**\n\t * Upload a file to a binary attribute via the two-step upload flow.\n\t * Returns the server response data (upload metadata).\n\t */\n\tuploadFile: (attributePath: string, file: File) => Promise<unknown>;\n\n\t/**\n\t * Extract the original filename from a JUDO binary download token (JWT).\n\t * Returns `fallbackText` when the token is missing or cannot be decoded.\n\t */\n\textractFileNameFromToken: (token?: string | null, fallbackText?: string) => string;\n\n\t/**\n\t * Trigger a browser file download from a REST API response that contains a Blob.\n\t * Reads filename from the `Content-Disposition` header, falling back to `\"download\"`.\n\t */\n\texportFile: (response: JudoRestResponse<Blob>) => void;\n}\n\n// ────────────────────────────────────────────\n// Standalone utilities\n// ────────────────────────────────────────────\n\n/**\n * Decode a JWT payload without an external library.\n * Works in the browser using `atob`.\n */\nfunction decodeJwtPayload(token: string): Record<string, unknown> {\n\tconst parts = token.split(\".\");\n\tif (parts.length !== 3) throw new Error(\"Invalid JWT format\");\n\t// Handle URL-safe Base64\n\tconst base64 = parts[1].replace(/-/g, \"+\").replace(/_/g, \"/\");\n\treturn JSON.parse(atob(base64));\n}\n\n/**\n * Extract the original filename from a JUDO binary download token (JWT).\n *\n * Can be used outside of React components (e.g. in utility functions).\n * For use inside components, prefer the `extractFileNameFromToken` from {@link useFileHandling}.\n *\n * @param token JWT download token (or null/undefined)\n * @param fallbackText Value returned when the token is absent or decoding fails\n * @returns The decoded filename, or `fallbackText`\n */\nexport function extractFileNameFromToken(token?: string | null, fallbackText?: string): string {\n\tif (!token) return fallbackText ?? \"\";\n\ttry {\n\t\tconst payload = decodeJwtPayload(token) as { fileName?: string };\n\t\treturn payload.fileName ?? fallbackText ?? \"\";\n\t} catch {\n\t\tconsole.error(`Decoding of JWT token failed for: ${token}`);\n\t\treturn fallbackText ?? \"\";\n\t}\n}\n\n/**\n * Extract filename from a `Content-Disposition` header value.\n * Returns `undefined` when the header is missing or does not contain a filename.\n */\nfunction parseFileNameFromContentDisposition(header: string | null): string | undefined {\n\tif (!header) return undefined;\n\tconst match = header.match(/filename=\"(.*)\"/);\n\treturn match?.[1];\n}\n\n/**\n * Trigger a browser download by creating a temporary anchor element.\n */\nfunction triggerBrowserDownload(url: string, fileName: string): void {\n\tconst link = document.createElement(\"a\");\n\tlink.href = url;\n\tlink.download = fileName;\n\tdocument.body.appendChild(link);\n\tlink.click();\n\tdocument.body.removeChild(link);\n}\n\n// ────────────────────────────────────────────\n// Inline Preview Dialog\n// ────────────────────────────────────────────\n\n/** @internal Props for the inline preview dialog rendered by `downloadFile`. */\nexport interface InlinePreviewDialogProps extends CustomDialogProps<void> {\n\turl: string;\n\tfileName: string;\n}\n\n/**\n * Dialog component that previews a binary file in an iframe.\n * Opened by `useFileHandling().downloadFile(…, \"inline\")`.\n *\n * @internal\n */\nexport function InlinePreviewDialog({ onClose, url, fileName }: InlinePreviewDialogProps) {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t<>\n\t\t\t<DialogTitle>\n\t\t\t\t{fileName}\n\t\t\t\t<IconButton\n\t\t\t\t\tdata-testid=\"close-inline-binary-dialog-top-button\"\n\t\t\t\t\taria-label=\"close\"\n\t\t\t\t\tonClick={() => onClose()}\n\t\t\t\t\tsx={{\n\t\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\t\tright: 8,\n\t\t\t\t\t\ttop: 8,\n\t\t\t\t\t\tcolor: (theme) => theme.palette.grey[500],\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<CloseIcon />\n\t\t\t\t</IconButton>\n\t\t\t</DialogTitle>\n\t\t\t<DialogContent dividers>\n\t\t\t\t<Box>\n\t\t\t\t\t<iframe\n\t\t\t\t\t\tsrc={url}\n\t\t\t\t\t\ttitle={fileName}\n\t\t\t\t\t\tsandbox=\"allow-same-origin\"\n\t\t\t\t\t\twidth=\"100%\"\n\t\t\t\t\t\theight={typeof document !== \"undefined\" ? document.body.scrollHeight * 0.6 : 600}\n\t\t\t\t\t\tstyle={{ border: 0 }}\n\t\t\t\t\t/>\n\t\t\t\t</Box>\n\t\t\t</DialogContent>\n\t\t\t<DialogActions>\n\t\t\t\t<Button data-testid=\"close-inline-binary-dialog-button\" variant=\"text\" onClick={() => onClose()}>\n\t\t\t\t\t{t(\"system.action.close.label\", { defaultValue: \"Close\" })}\n\t\t\t\t</Button>\n\t\t\t</DialogActions>\n\t\t</>\n\t);\n}\n\n// ────────────────────────────────────────────\n// Hook\n// ────────────────────────────────────────────\n\n/**\n * Hook providing file handling operations: download, upload,\n * filename extraction from JWT tokens, and export-to-file.\n *\n * Adapted from the legacy `fileHandling` hook. Uses the JUDO REST\n * API client for upload/download and the feedback dialog service\n * for inline binary previews.\n *\n * @example\n * ```tsx\n * const { downloadFile, uploadFile, extractFileNameFromToken, exportFile } = useFileHandling();\n *\n * // Download as attachment\n * await downloadFile(transfer, \"document\", \"attachment\");\n *\n * // Preview inline\n * await downloadFile(transfer, \"preview\", \"inline\");\n *\n * // Upload a file\n * const result = await uploadFile(\"/admin/Issue/avatar\", selectedFile);\n *\n * // Get display name from stored token\n * const name = extractFileNameFromToken(transfer.document, \"Unnamed file\");\n * ```\n */\nexport function useFileHandling(): FileHandling {\n\tconst api = useApi();\n\tconst dialog = useDialog();\n\n\tconst extractFn = useCallback(\n\t\t(token?: string | null, fallbackText?: string): string => extractFileNameFromToken(token, fallbackText),\n\t\t[]\n\t);\n\n\tconst exportFile = useCallback((response: JudoRestResponse<Blob>): void => {\n\t\tconst fileName = parseFileNameFromContentDisposition(response.headers.get(\"content-disposition\")) ?? \"download\";\n\t\tconst contentType = response.headers.get(\"content-type\");\n\t\tconst blob = contentType ? new Blob([response.data], { type: contentType }) : response.data;\n\t\tconst url = URL.createObjectURL(blob);\n\t\ttriggerBrowserDownload(url, fileName);\n\t\tURL.revokeObjectURL(url);\n\t}, []);\n\n\tconst downloadFile = useCallback(\n\t\tasync (\n\t\t\tdata: Record<string, unknown>,\n\t\t\tattributeName: string,\n\t\t\tdisposition: \"inline\" | \"attachment\"\n\t\t): Promise<void> => {\n\t\t\tconst token = data[attributeName];\n\t\t\tif (typeof token !== \"string\") {\n\t\t\t\tthrow new Error(`No download token found for attribute \"${attributeName}\"`);\n\t\t\t}\n\n\t\t\tconst response = await api.downloadFile(token, disposition);\n\n\t\t\tconst contentDisposition = response.headers.get(\"content-disposition\");\n\t\t\tconst contentType = response.headers.get(\"content-type\");\n\t\t\tconst fileName =\n\t\t\t\tparseFileNameFromContentDisposition(contentDisposition) ?? extractFileNameFromToken(token, \"download\");\n\n\t\t\tconst blob = contentType ? new Blob([response.data], { type: contentType }) : response.data;\n\t\t\tconst url = URL.createObjectURL(blob);\n\n\t\t\tif (disposition === \"inline\") {\n\t\t\t\ttry {\n\t\t\t\t\tawait dialog.open<void, InlinePreviewDialogProps>({\n\t\t\t\t\t\tcomponent: InlinePreviewDialog,\n\t\t\t\t\t\tprops: { url, fileName },\n\t\t\t\t\t\tsize: \"lg\",\n\t\t\t\t\t\tfullWidth: true,\n\t\t\t\t\t\tdisableBackdropClick: true,\n\t\t\t\t\t});\n\t\t\t\t} finally {\n\t\t\t\t\tURL.revokeObjectURL(url);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttriggerBrowserDownload(url, fileName);\n\t\t\t\tURL.revokeObjectURL(url);\n\t\t\t}\n\t\t},\n\t\t[api, dialog]\n\t);\n\n\tconst uploadFile = useCallback(\n\t\tasync (attributePath: string, file: File): Promise<unknown> => {\n\t\t\tconst response = await api.uploadFile(attributePath, file);\n\t\t\treturn response.data;\n\t\t},\n\t\t[api]\n\t);\n\n\treturn {\n\t\tdownloadFile,\n\t\tuploadFile,\n\t\textractFileNameFromToken: extractFn,\n\t\texportFile,\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;AAuBA,IAAa,yBAAb,cAA4C,UAA2D;CACtG,QAA4B;EAC3B,UAAU;EACV,OAAO;EACP,WAAW;EACX,aAAa;EACb;CAED,OAAO,yBAAyB,GAA2C;AAC1E,SAAO;GAAE,UAAU;GAAM;GAAO;;CAGjC,kBAAkB,GAAc,GAA4B;AAG3D,EAFA,KAAK,SAAS,EAAE,cAAW,CAAC,EAE5B,QAAQ,MAAM,2BAA2B,GAAO,EAAU;;CAG3D,sBAA4B;AAC3B,OAAK,UAAU,OAAU,EAAE,aAAa,CAAC,EAAK,aAAa,EAAE;;CAM9D,cAAsB,GAAsB;EAC3C,IAAM,oBAAO,IAAI,SAAS;AAC1B,SAAO,KAAK,UACX,IACC,GAAK,MAAU;AACf,OAAI,OAAO,KAAU,YAAY,GAAgB;AAChD,QAAI,EAAK,IAAI,EAAM,CAClB,QAAO;AAER,MAAK,IAAI,EAAM;;AAEhB,UAAO;KAER,EACA;;CAGF,SAAS;AACR,MAAI,KAAK,MAAM,UAAU;GACxB,IAAM,EAAE,kBAAe,eAAY,KAAK,OAClC,EAAE,UAAO,cAAW,mBAAgB,KAAK;AAE/C,UACC,oBAAC,KAAA;IAAI,GAAG;IAAG,eAAa,mBAAmB,EAAc,aAAa;cACrE,qBAAC,OAAA;KAAM,UAAS;;MACf,qBAAC,YAAA,EAAA,UAAA,CAAY,GAAc,mBAAA,EAAA,CAA6B;MACxD,qBAAC,YAAA;OAAW,SAAQ;;QAAQ;QACT,EAAc,aAAa;QAAC;QAC7C,KAAW,iBAAiB,EAAQ;;QACzB;MAEb,qBAAC,KAAA;OAAI,IAAI;kBACR,oBAAC,YAAA;QACA,MAAK;QACL,SAAS,KAAK;QACd,eAAY;QACZ,cAAY,IAAc,iBAAiB;kBAE5B,IAAd,IAAe,iBAAqB,gBAArB,EAAA,CAAsC;SAC1C,EACb,qBAAC,YAAA;QAAW,SAAQ;QAAU,WAAU;mBACtC,IAAc,SAAS,QAAO,WAAA;SACnB,CAAA;QACR;MAEN,oBAAC,UAAA;OAAS,IAAI;iBACb,qBAAC,KAAA;QAAI,IAAI;QAAG,GAAG;QAAG,IAAI;SAAE,SAAS;SAAY,cAAc;SAAG;QAAE,eAAY;;SAC3E,oBAAC,YAAA;UAAW,SAAQ;oBAAY;WAAmB;SACnD,oBAAC,YAAA;UAAW,SAAQ;UAAQ,YAAW;UAAY,eAAY;oBAC7D,GAAO;WACI;SAEZ,KACA,qBAAA,UAAA,EAAA,UAAA;UACC,oBAAC,YAAA;WAAW,SAAQ;WAAY,IAAI;qBAAG;YAE1B;UACb,oBAAC,YAAA;WAAW,SAAQ;WAAQ,YAAW;WAAY,eAAY;qBAC7D,EAAQ,YAAY,EAAQ;YACjB;UAEb,oBAAC,YAAA;WAAW,SAAQ;WAAY,IAAI;qBAAG;YAE1B;UACb,oBAAC,KAAA;WACA,WAAU;WACV,UAAS;WACT,UAAS;WACT,WAAW;WACX,eAAY;qBAEX,KAAK,cAAc,EAAQ;YACvB;aACJ;SAGH,KACA,qBAAA,UAAA,EAAA,UAAA,CACC,oBAAC,YAAA;UAAW,SAAQ;UAAY,IAAI;oBAAG;WAE1B,EACb,oBAAC,KAAA;UACA,WAAU;UACV,UAAS;UACT,UAAS;UACT,WAAW;UACX,eAAY;oBAEX,EAAU;WACN,CAAA,EAAA,CACJ;;SAEC;QACI;;MACJ;KACH;;AAIR,SAAO,KAAK,MAAM;;;AAKpB,SAAgB,4BAA4B,EAAE,aAAU,cAA6D;AACpH,QACC,oBAAC,wBAAA;EAAuB,eAAc;EAAiB;EACrD;GACuB;;AAI3B,SAAgB,2BAA2B,EAAE,aAAU,cAA6D;AACnH,QACC,oBAAC,wBAAA;EAAuB,eAAc;EAAgB;EACpD;GACuB;;AAI3B,SAAgB,2BAA2B,EAAE,aAAU,cAA6D;AACnH,QACC,oBAAC,wBAAA;EAAuB,eAAc;EAAgB;EACpD;GACuB;;ACjK3B,SAAgB,qBAAqB,GAA6C;AAMjF,QAJI,EAAU,OACN,EAAU,OAGX,kBAAkB;;ACT1B,IAAM,6BAA6B,WAAW,OAAO,wCAA4B,EAC3E,4BAA4B,WAAW,OAAO,uCAA2B,EACzE,4BAA4B,WAAW,OAAO,uCAA2B;AAS/E,SAAgB,aAAa,EAAE,WAA2B;CAEzD,IAAM,IAAY,EAAK;AACvB,KAAI,OAAO,KAAc,SACxB,QACC,qBAAC,KAAA;EAAI,GAAG;EAAG,eAAa,kBAAkB,EAAK,KAAK;aAAe,sCAC/B,EAAA;GAC9B;CAIR,IAAM,IAAgB,qBAAqB,EAAU,EAG/C,IAAU,EAAK,aAAa,EAAK,QAAQ,gBAEzC,IACL,oBAAC,KAAA;EAAI,SAAQ;EAAO,gBAAe;EAAS,GAAG;EAAG,eAAY;YAC7D,oBAAC,kBAAA,EAAA,CAAmB;GACf;AAGP,SAAQ,GAAR;EACC,KAAK,kBAAkB,MACtB,QACC,oBAAC,6BAAA;GAA4B,SAAS;aACrC,oBAAC,UAAA;IAAS,UAAU;cACnB,oBAAC,4BAAA,EAAiC,SAAA,CAAQ;KAChC;KAH0C,EAIxB;EAGhC,KAAK,kBAAkB,KACtB,QACC,oBAAC,4BAAA;GAA2B,SAAS;aACpC,oBAAC,UAAA;IAAS,UAAU;cACnB,oBAAC,2BAAA,EAAgC,SAAA,CAAQ;KAC/B;KAHyC,EAIxB;EAG/B,QACC,QACC,oBAAC,4BAAA;GAA2B,SAAS;aACpC,oBAAC,UAAA;IAAS,UAAU;cACnB,oBAAC,2BAAA,EAAgC,SAAA,CAAQ;KAC/B;KAHyC,EAIxB;;;AChBjC,SAAS,iBAAiB,GAAwC;CACjE,IAAM,IAAQ,EAAM,MAAM,IAAI;AAC9B,KAAI,EAAM,WAAW,EAAG,OAAU,MAAM,qBAAqB;CAE7D,IAAM,IAAS,EAAM,GAAG,QAAQ,MAAM,IAAI,CAAC,QAAQ,MAAM,IAAI;AAC7D,QAAO,KAAK,MAAM,KAAK,EAAO,CAAC;;AAahC,SAAgB,yBAAyB,GAAuB,GAA+B;AAC9F,KAAI,CAAC,EAAO,QAAO,KAAgB;AACnC,KAAI;AAEH,SADgB,iBAAiB,EAAM,CACxB,YAAY,KAAgB;SACpC;AAEP,SADA,QAAQ,MAAM,qCAAqC,IAAQ,EACpD,KAAgB;;;AAQzB,SAAS,oCAAoC,GAA2C;AAClF,OAEL,QADc,EAAO,MAAM,kBAAkB,GAC9B;;AAMhB,SAAS,uBAAuB,GAAa,GAAwB;CACpE,IAAM,IAAO,SAAS,cAAc,IAAI;AAKxC,CAJA,EAAK,OAAO,GACZ,EAAK,WAAW,GAChB,SAAS,KAAK,YAAY,EAAK,EAC/B,EAAK,OAAO,EACZ,SAAS,KAAK,YAAY,EAAK;;AAmBhC,SAAgB,oBAAoB,EAAE,YAAS,QAAK,eAAsC;CACzF,IAAM,EAAE,SAAM,gBAAgB;AAC9B,QACC,qBAAA,UAAA,EAAA,UAAA;EACC,qBAAC,aAAA,EAAA,UAAA,CACC,GACD,oBAAC,YAAA;GACA,eAAY;GACZ,cAAW;GACX,eAAe,GAAS;GACxB,IAAI;IACH,UAAU;IACV,OAAO;IACP,KAAK;IACL,QAAQ,MAAU,EAAM,QAAQ,KAAK;IACrC;aAED,oBAAC,WAAA,EAAA,CAAY;IACD,CAAA,EAAA,CACA;EACd,oBAAC,eAAA;GAAc,UAAA;aACd,oBAAC,KAAA,EAAA,UACA,oBAAC,UAAA;IACA,KAAK;IACL,OAAO;IACP,SAAQ;IACR,OAAM;IACN,QAAQ,OAAO,WAAa,MAAc,SAAS,KAAK,eAAe,KAAM;IAC7E,OAAO,EAAE,QAAQ,GAAG;KACnB,EAAA,CACG;IACS;EAChB,oBAAC,eAAA,EAAA,UACA,oBAAC,QAAA;GAAO,eAAY;GAAoC,SAAQ;GAAO,eAAe,GAAS;aAC7F,EAAE,6BAA6B,EAAE,cAAc,SAAS,CAAC;IAClD,EAAA,CACM;KACd;;AAiCL,SAAgB,kBAAgC;CAC/C,IAAM,IAAM,QAAQ,EACd,IAAS,WAAW,EAEpB,IAAY,aAChB,GAAuB,MAAkC,yBAAyB,GAAO,EAAa,EACvG,EAAE,CACF,EAEK,IAAa,aAAa,MAA2C;EAC1E,IAAM,IAAW,oCAAoC,EAAS,QAAQ,IAAI,sBAAsB,CAAC,IAAI,YAC/F,IAAc,EAAS,QAAQ,IAAI,eAAe,EAClD,IAAO,IAAc,IAAI,KAAK,CAAC,EAAS,KAAK,EAAE,EAAE,MAAM,GAAa,CAAC,GAAG,EAAS,MACjF,IAAM,IAAI,gBAAgB,EAAK;AAErC,EADA,uBAAuB,GAAK,EAAS,EACrC,IAAI,gBAAgB,EAAI;IACtB,EAAE,CAAC;AAmDN,QAAO;EACN,cAlDoB,YACpB,OACC,GACA,GACA,MACmB;GACnB,IAAM,IAAQ,EAAK;AACnB,OAAI,OAAO,KAAU,SACpB,OAAU,MAAM,0CAA0C,EAAc,GAAG;GAG5E,IAAM,IAAW,MAAM,EAAI,aAAa,GAAO,EAAY,EAErD,IAAqB,EAAS,QAAQ,IAAI,sBAAsB,EAChE,IAAc,EAAS,QAAQ,IAAI,eAAe,EAClD,IACL,oCAAoC,EAAmB,IAAI,yBAAyB,GAAO,WAAW,EAEjG,IAAO,IAAc,IAAI,KAAK,CAAC,EAAS,KAAK,EAAE,EAAE,MAAM,GAAa,CAAC,GAAG,EAAS,MACjF,IAAM,IAAI,gBAAgB,EAAK;AAErC,OAAI,MAAgB,SACnB,KAAI;AACH,UAAM,EAAO,KAAqC;KACjD,WAAW;KACX,OAAO;MAAE;MAAK;MAAU;KACxB,MAAM;KACN,WAAW;KACX,sBAAsB;KACtB,CAAC;aACO;AACT,QAAI,gBAAgB,EAAI;;OAIzB,CADA,uBAAuB,GAAK,EAAS,EACrC,IAAI,gBAAgB,EAAI;KAG1B,CAAC,GAAK,EAAO,CACb;EAYA,YAVkB,YAClB,OAAO,GAAuB,OACZ,MAAM,EAAI,WAAW,GAAe,EAAK,EAC1C,MAEjB,CAAC,EAAI,CACL;EAKA,0BAA0B;EAC1B;EACA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BinaryTypeInput, Input } from '@judo/model-api';
|
|
2
|
+
export interface BinaryInputComponentProps {
|
|
3
|
+
element: BinaryTypeInput | Input;
|
|
4
|
+
readOnly?: boolean;
|
|
5
|
+
value?: string | null;
|
|
6
|
+
onChange?: (value: string | null) => void;
|
|
7
|
+
error?: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
fileName?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Binary/file input component.
|
|
13
|
+
*/
|
|
14
|
+
export declare function BinaryInputComponent({ element, readOnly, value: _value, onChange, error, disabled, fileName, }: BinaryInputComponentProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
//# sourceMappingURL=BinaryInputComponent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BinaryInputComponent.d.ts","sourceRoot":"","sources":["../../src/inputs/BinaryInputComponent.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAO9D,MAAM,WAAW,yBAAyB;IACzC,OAAO,EAAE,eAAe,GAAG,KAAK,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EACpC,OAAO,EACP,QAAQ,EACR,KAAK,EAAE,MAAM,EACb,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,QAAQ,GACR,EAAE,yBAAyB,2CAyD3B"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Checkbox as CheckboxElement, Input } from '@judo/model-api';
|
|
2
|
+
export interface CheckboxComponentProps {
|
|
3
|
+
element: CheckboxElement | Input;
|
|
4
|
+
readOnly?: boolean;
|
|
5
|
+
value?: boolean;
|
|
6
|
+
onChange?: (value: boolean) => void;
|
|
7
|
+
error?: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Checkbox input component.
|
|
12
|
+
*/
|
|
13
|
+
export declare function CheckboxComponent({ element, readOnly, value, onChange, error, disabled, }: CheckboxComponentProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=CheckboxComponent.d.ts.map
|