@loj-lang/rdsl-runtime 0.5.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/README.md +19 -0
- package/dist/components/Badge.d.ts +6 -0
- package/dist/components/Badge.d.ts.map +1 -0
- package/dist/components/Badge.js +5 -0
- package/dist/components/ConfirmDialog.d.ts +8 -0
- package/dist/components/ConfirmDialog.d.ts.map +1 -0
- package/dist/components/ConfirmDialog.js +11 -0
- package/dist/components/DataTable.d.ts +34 -0
- package/dist/components/DataTable.d.ts.map +1 -0
- package/dist/components/DataTable.js +58 -0
- package/dist/components/FilterBar.d.ts +13 -0
- package/dist/components/FilterBar.d.ts.map +1 -0
- package/dist/components/FilterBar.js +41 -0
- package/dist/components/FormField.d.ts +22 -0
- package/dist/components/FormField.d.ts.map +1 -0
- package/dist/components/FormField.js +66 -0
- package/dist/components/GroupedDataTable.d.ts +26 -0
- package/dist/components/GroupedDataTable.d.ts.map +1 -0
- package/dist/components/GroupedDataTable.js +67 -0
- package/dist/components/Pagination.d.ts +7 -0
- package/dist/components/Pagination.d.ts.map +1 -0
- package/dist/components/Pagination.js +12 -0
- package/dist/components/PivotDataTable.d.ts +25 -0
- package/dist/components/PivotDataTable.d.ts.map +1 -0
- package/dist/components/PivotDataTable.js +72 -0
- package/dist/components/Tag.d.ts +6 -0
- package/dist/components/Tag.d.ts.map +1 -0
- package/dist/components/Tag.js +5 -0
- package/dist/components/WorkflowSummary.d.ts +5 -0
- package/dist/components/WorkflowSummary.d.ts.map +1 -0
- package/dist/components/WorkflowSummary.js +17 -0
- package/dist/hooks/navigation.d.ts +20 -0
- package/dist/hooks/navigation.d.ts.map +1 -0
- package/dist/hooks/navigation.js +135 -0
- package/dist/hooks/resourceClient.d.ts +36 -0
- package/dist/hooks/resourceClient.d.ts.map +1 -0
- package/dist/hooks/resourceClient.js +259 -0
- package/dist/hooks/resourceStore.d.ts +25 -0
- package/dist/hooks/resourceStore.d.ts.map +1 -0
- package/dist/hooks/resourceStore.js +164 -0
- package/dist/hooks/resourceTarget.d.ts +2 -0
- package/dist/hooks/resourceTarget.d.ts.map +1 -0
- package/dist/hooks/resourceTarget.js +22 -0
- package/dist/hooks/useAuth.d.ts +16 -0
- package/dist/hooks/useAuth.d.ts.map +1 -0
- package/dist/hooks/useAuth.js +20 -0
- package/dist/hooks/useCollectionView.d.ts +28 -0
- package/dist/hooks/useCollectionView.d.ts.map +1 -0
- package/dist/hooks/useCollectionView.js +73 -0
- package/dist/hooks/useDocumentMetadata.d.ts +13 -0
- package/dist/hooks/useDocumentMetadata.d.ts.map +1 -0
- package/dist/hooks/useDocumentMetadata.js +111 -0
- package/dist/hooks/useGroupedCollectionView.d.ts +26 -0
- package/dist/hooks/useGroupedCollectionView.d.ts.map +1 -0
- package/dist/hooks/useGroupedCollectionView.js +82 -0
- package/dist/hooks/useReadModel.d.ts +16 -0
- package/dist/hooks/useReadModel.d.ts.map +1 -0
- package/dist/hooks/useReadModel.js +104 -0
- package/dist/hooks/useResource.d.ts +36 -0
- package/dist/hooks/useResource.d.ts.map +1 -0
- package/dist/hooks/useResource.js +69 -0
- package/dist/hooks/useToast.d.ts +18 -0
- package/dist/hooks/useToast.d.ts.map +1 -0
- package/dist/hooks/useToast.js +31 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/policies/can.d.ts +15 -0
- package/dist/policies/can.d.ts.map +1 -0
- package/dist/policies/can.js +160 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @loj-lang/rdsl-runtime
|
|
2
|
+
|
|
3
|
+
Runtime package for generated frontend-family React output.
|
|
4
|
+
|
|
5
|
+
Current surface includes:
|
|
6
|
+
|
|
7
|
+
- data-table and form components
|
|
8
|
+
- `useResource`
|
|
9
|
+
- auth and toast hooks
|
|
10
|
+
- policy evaluation helpers
|
|
11
|
+
|
|
12
|
+
This package is consumed by generated output from `@loj-lang/rdsl-compiler`.
|
|
13
|
+
|
|
14
|
+
Local workspace commands:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm run build --workspace=@loj-lang/rdsl-runtime
|
|
18
|
+
npm run test --workspace=@loj-lang/rdsl-runtime
|
|
19
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../src/components/Badge.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,wBAAgB,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,eAOlD"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export function Badge({ value, colors }) {
|
|
3
|
+
const color = colors[value] ?? 'gray';
|
|
4
|
+
return (React.createElement("span", { className: "rdsl-badge", style: { border: `1px solid ${color}`, color, padding: '0.125rem 0.5rem', borderRadius: '0.375rem' } }, value));
|
|
5
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface ConfirmDialogProps {
|
|
2
|
+
open: boolean;
|
|
3
|
+
message: string;
|
|
4
|
+
onConfirm: () => void | Promise<void>;
|
|
5
|
+
onCancel: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function ConfirmDialog({ open, message, onConfirm, onCancel }: ConfirmDialogProps): JSX.Element | null;
|
|
8
|
+
//# sourceMappingURL=ConfirmDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfirmDialog.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmDialog.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,kBAAkB,sBAkBvF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export function ConfirmDialog({ open, message, onConfirm, onCancel }) {
|
|
3
|
+
if (!open)
|
|
4
|
+
return null;
|
|
5
|
+
return (React.createElement("div", { className: "rdsl-dialog-backdrop", role: "presentation" },
|
|
6
|
+
React.createElement("div", { className: "rdsl-dialog", role: "dialog", "aria-modal": "true", "aria-label": "Confirmation dialog" },
|
|
7
|
+
React.createElement("p", null, message),
|
|
8
|
+
React.createElement("div", { className: "rdsl-dialog-actions" },
|
|
9
|
+
React.createElement("button", { type: "button", className: "rdsl-btn rdsl-btn-secondary", onClick: onCancel }, "Cancel"),
|
|
10
|
+
React.createElement("button", { type: "button", className: "rdsl-btn rdsl-btn-danger", onClick: () => void onConfirm() }, "Confirm")))));
|
|
11
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface DataTableColumn<T> {
|
|
2
|
+
key: string;
|
|
3
|
+
label: string;
|
|
4
|
+
sortable?: boolean;
|
|
5
|
+
format?: 'date';
|
|
6
|
+
render?: (value: unknown, record: T) => React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export interface DataTableAction<T> {
|
|
9
|
+
label: string;
|
|
10
|
+
href?: (row: T) => string;
|
|
11
|
+
onClick?: (row: T) => void | Promise<void>;
|
|
12
|
+
variant?: 'default' | 'danger';
|
|
13
|
+
}
|
|
14
|
+
export interface SortState {
|
|
15
|
+
field: string;
|
|
16
|
+
direction: 'asc' | 'desc';
|
|
17
|
+
}
|
|
18
|
+
export interface DataTableProps<T extends {
|
|
19
|
+
id: string;
|
|
20
|
+
}> {
|
|
21
|
+
columns: readonly DataTableColumn<T>[];
|
|
22
|
+
data: T[];
|
|
23
|
+
loading?: boolean;
|
|
24
|
+
sort?: SortState | null;
|
|
25
|
+
onSortChange?: (next: SortState | null) => void;
|
|
26
|
+
actions?: readonly DataTableAction<T>[];
|
|
27
|
+
selectedRowId?: string | null;
|
|
28
|
+
onSelectRow?: (row: T) => void;
|
|
29
|
+
selectionName?: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function DataTable<T extends {
|
|
32
|
+
id: string;
|
|
33
|
+
}>({ columns, data, loading, sort, onSortChange, actions, selectedRowId, onSelectRow, selectionName, }: DataTableProps<T>): JSX.Element;
|
|
34
|
+
//# sourceMappingURL=DataTable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../src/components/DataTable.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;CACzD;AAED,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CAChC;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,KAAK,GAAG,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;IACtD,OAAO,EAAE,SAAS,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IACvC,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,OAAO,CAAC,EAAE,SAAS,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IACxC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAmBD,wBAAgB,SAAS,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,EAClD,OAAO,EACP,IAAI,EACJ,OAAe,EACf,IAAW,EACX,YAAY,EACZ,OAAY,EACZ,aAAoB,EACpB,WAAW,EACX,aAAsC,GACvC,EAAE,cAAc,CAAC,CAAC,CAAC,eAmGnB"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
function formatValue(value, format) {
|
|
3
|
+
if (value === null || value === undefined || value === '')
|
|
4
|
+
return '—';
|
|
5
|
+
if (format !== 'date')
|
|
6
|
+
return String(value);
|
|
7
|
+
const date = new Date(String(value));
|
|
8
|
+
return Number.isNaN(date.getTime()) ? String(value) : date.toLocaleString();
|
|
9
|
+
}
|
|
10
|
+
function nextSortState(current, field) {
|
|
11
|
+
if (!current || current.field !== field) {
|
|
12
|
+
return { field, direction: 'asc' };
|
|
13
|
+
}
|
|
14
|
+
if (current.direction === 'asc') {
|
|
15
|
+
return { field, direction: 'desc' };
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
export function DataTable({ columns, data, loading = false, sort = null, onSortChange, actions = [], selectedRowId = null, onSelectRow, selectionName = 'rdsl-table-selection', }) {
|
|
20
|
+
const hasSelection = Boolean(onSelectRow);
|
|
21
|
+
return (React.createElement("div", { className: "rdsl-data-table" },
|
|
22
|
+
React.createElement("table", null,
|
|
23
|
+
React.createElement("thead", null,
|
|
24
|
+
React.createElement("tr", null,
|
|
25
|
+
hasSelection ? React.createElement("th", null, "Select") : null,
|
|
26
|
+
columns.map((column) => {
|
|
27
|
+
const sortable = Boolean(column.sortable && onSortChange);
|
|
28
|
+
const activeSort = sort?.field === column.key ? sort.direction : null;
|
|
29
|
+
return (React.createElement("th", { key: column.key }, sortable ? (React.createElement("button", { type: "button", className: "rdsl-table-sort", onClick: () => onSortChange?.(nextSortState(sort, column.key)) },
|
|
30
|
+
column.label,
|
|
31
|
+
activeSort ? ` ${activeSort === 'asc' ? '↑' : '↓'}` : '')) : (column.label)));
|
|
32
|
+
}),
|
|
33
|
+
actions.length > 0 ? React.createElement("th", null, "Actions") : null)),
|
|
34
|
+
React.createElement("tbody", null,
|
|
35
|
+
loading ? (React.createElement("tr", null,
|
|
36
|
+
React.createElement("td", { colSpan: columns.length + (actions.length > 0 ? 1 : 0) + (hasSelection ? 1 : 0) }, "Loading..."))) : null,
|
|
37
|
+
!loading && data.length === 0 ? (React.createElement("tr", null,
|
|
38
|
+
React.createElement("td", { colSpan: columns.length + (actions.length > 0 ? 1 : 0) + (hasSelection ? 1 : 0) }, "No records"))) : null,
|
|
39
|
+
!loading
|
|
40
|
+
? data.map((record) => (React.createElement("tr", { key: record.id },
|
|
41
|
+
hasSelection ? (React.createElement("td", null,
|
|
42
|
+
React.createElement("input", { type: "radio", name: selectionName, checked: selectedRowId === String(record.id), onChange: () => onSelectRow?.(record) }))) : null,
|
|
43
|
+
columns.map((column) => {
|
|
44
|
+
const value = record[column.key];
|
|
45
|
+
return (React.createElement("td", { key: column.key }, column.render ? column.render(value, record) : formatValue(value, column.format)));
|
|
46
|
+
}),
|
|
47
|
+
actions.length > 0 ? (React.createElement("td", null,
|
|
48
|
+
React.createElement("div", { className: "rdsl-table-actions" }, actions.map((action) => {
|
|
49
|
+
const className = action.variant === 'danger'
|
|
50
|
+
? 'rdsl-btn rdsl-btn-danger'
|
|
51
|
+
: 'rdsl-btn rdsl-btn-secondary';
|
|
52
|
+
if (action.href) {
|
|
53
|
+
return (React.createElement("a", { key: action.label, className: className, href: action.href(record) }, action.label));
|
|
54
|
+
}
|
|
55
|
+
return (React.createElement("button", { key: action.label, type: "button", className: className, onClick: () => action.onClick?.(record) }, action.label));
|
|
56
|
+
})))) : null)))
|
|
57
|
+
: null))));
|
|
58
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface FilterField {
|
|
2
|
+
key: string;
|
|
3
|
+
label: string;
|
|
4
|
+
type: 'text' | 'select';
|
|
5
|
+
options?: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
export interface FilterBarProps {
|
|
8
|
+
fields: readonly FilterField[];
|
|
9
|
+
values: Record<string, string>;
|
|
10
|
+
onChange: (nextValues: Record<string, string>) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function FilterBar({ fields, values, onChange }: FilterBarProps): JSX.Element;
|
|
13
|
+
//# sourceMappingURL=FilterBar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterBar.d.ts","sourceRoot":"","sources":["../../src/components/FilterBar.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;CACxD;AAED,wBAAgB,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,cAAc,eAoErE"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export function FilterBar({ fields, values, onChange }) {
|
|
3
|
+
const [draftValues, setDraftValues] = React.useState(values);
|
|
4
|
+
const composingFieldKeyRef = React.useRef(null);
|
|
5
|
+
React.useEffect(() => {
|
|
6
|
+
if (composingFieldKeyRef.current) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
setDraftValues(values);
|
|
10
|
+
}, [values]);
|
|
11
|
+
const commitChange = React.useCallback((fieldKey, value) => {
|
|
12
|
+
onChange({
|
|
13
|
+
...values,
|
|
14
|
+
[fieldKey]: value,
|
|
15
|
+
});
|
|
16
|
+
}, [onChange, values]);
|
|
17
|
+
const updateDraftValue = React.useCallback((fieldKey, value) => {
|
|
18
|
+
setDraftValues((previous) => ({
|
|
19
|
+
...previous,
|
|
20
|
+
[fieldKey]: value,
|
|
21
|
+
}));
|
|
22
|
+
}, []);
|
|
23
|
+
return (React.createElement("div", { className: "rdsl-filter-bar" }, fields.map((field) => (React.createElement("label", { key: field.key, className: "rdsl-filter-field" },
|
|
24
|
+
React.createElement("span", null, field.label),
|
|
25
|
+
field.type === 'select' ? (React.createElement("select", { value: values[field.key] ?? '', onChange: (event) => commitChange(field.key, String(event?.target?.value ?? '')) },
|
|
26
|
+
React.createElement("option", { value: "" }, "All"),
|
|
27
|
+
(field.options ?? []).map((option) => (React.createElement("option", { key: option, value: option }, option))))) : (React.createElement("input", { type: "text", value: draftValues[field.key] ?? values[field.key] ?? '', onCompositionStart: () => {
|
|
28
|
+
composingFieldKeyRef.current = field.key;
|
|
29
|
+
}, onCompositionEnd: (event) => {
|
|
30
|
+
const nextValue = String(event?.target?.value ?? '');
|
|
31
|
+
composingFieldKeyRef.current = null;
|
|
32
|
+
updateDraftValue(field.key, nextValue);
|
|
33
|
+
commitChange(field.key, nextValue);
|
|
34
|
+
}, onChange: (event) => {
|
|
35
|
+
const nextValue = String(event?.target?.value ?? '');
|
|
36
|
+
updateDraftValue(field.key, nextValue);
|
|
37
|
+
if (composingFieldKeyRef.current !== field.key) {
|
|
38
|
+
commitChange(field.key, nextValue);
|
|
39
|
+
}
|
|
40
|
+
} })))))));
|
|
41
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface FieldSchema {
|
|
2
|
+
required?: true;
|
|
3
|
+
pattern?: RegExp;
|
|
4
|
+
minLength?: number;
|
|
5
|
+
unique?: true;
|
|
6
|
+
}
|
|
7
|
+
export interface SelectOption {
|
|
8
|
+
value: string;
|
|
9
|
+
label: string;
|
|
10
|
+
}
|
|
11
|
+
export interface FormFieldProps {
|
|
12
|
+
label: string;
|
|
13
|
+
name: string;
|
|
14
|
+
type: 'text' | 'number' | 'checkbox' | 'datetime' | 'select';
|
|
15
|
+
value: unknown;
|
|
16
|
+
onChange: (value: unknown) => void;
|
|
17
|
+
schema?: FieldSchema;
|
|
18
|
+
options?: readonly (string | SelectOption)[];
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function FormField({ label, name, type, value, onChange, schema, options, disabled, }: FormFieldProps): JSX.Element;
|
|
22
|
+
//# sourceMappingURL=FormField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormField.d.ts","sourceRoot":"","sources":["../../src/components/FormField.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,IAAI,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC7D,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,YAAY,CAAC,EAAE,CAAC;IAC7C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAsBD,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,MAAM,EACN,OAAO,EACP,QAAgB,GACjB,EAAE,cAAc,eA2EhB"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
function coerceValue(type, event) {
|
|
3
|
+
const target = event?.target;
|
|
4
|
+
if (type === 'checkbox')
|
|
5
|
+
return Boolean(target?.checked);
|
|
6
|
+
if (type === 'number') {
|
|
7
|
+
const nextValue = String(target?.value ?? '').trim();
|
|
8
|
+
return nextValue === '' ? '' : Number(nextValue);
|
|
9
|
+
}
|
|
10
|
+
return target?.value ?? '';
|
|
11
|
+
}
|
|
12
|
+
function describeSchema(schema) {
|
|
13
|
+
if (!schema)
|
|
14
|
+
return null;
|
|
15
|
+
const hints = [];
|
|
16
|
+
if (schema.required)
|
|
17
|
+
hints.push('Required');
|
|
18
|
+
if (typeof schema.minLength === 'number')
|
|
19
|
+
hints.push(`Min length ${schema.minLength}`);
|
|
20
|
+
if (schema.pattern)
|
|
21
|
+
hints.push('Pattern validated');
|
|
22
|
+
if (schema.unique)
|
|
23
|
+
hints.push('Must be unique');
|
|
24
|
+
return hints.length > 0 ? hints.join(' • ') : null;
|
|
25
|
+
}
|
|
26
|
+
export function FormField({ label, name, type, value, onChange, schema, options, disabled = false, }) {
|
|
27
|
+
const hint = describeSchema(schema);
|
|
28
|
+
const isTextLikeInput = type === 'text';
|
|
29
|
+
const externalValue = String(value ?? '');
|
|
30
|
+
const [draftValue, setDraftValue] = React.useState(externalValue);
|
|
31
|
+
const isComposingRef = React.useRef(false);
|
|
32
|
+
React.useEffect(() => {
|
|
33
|
+
if (!isTextLikeInput || isComposingRef.current) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
setDraftValue(externalValue);
|
|
37
|
+
}, [externalValue, isTextLikeInput]);
|
|
38
|
+
return (React.createElement("label", { className: "rdsl-form-field" },
|
|
39
|
+
React.createElement("span", null, label),
|
|
40
|
+
type === 'select' ? (React.createElement("select", { name: name, value: String(value ?? ''), disabled: disabled, onChange: (event) => onChange(event?.target?.value ?? '') },
|
|
41
|
+
React.createElement("option", { value: "" }, "Select..."),
|
|
42
|
+
(options ?? []).map((option) => {
|
|
43
|
+
const normalized = typeof option === 'string'
|
|
44
|
+
? { value: option, label: option }
|
|
45
|
+
: option;
|
|
46
|
+
return (React.createElement("option", { key: normalized.value, value: normalized.value }, normalized.label));
|
|
47
|
+
}))) : type === 'checkbox' ? (React.createElement("input", { name: name, type: "checkbox", checked: Boolean(value), disabled: disabled, onChange: (event) => onChange(coerceValue(type, event)) })) : (React.createElement("input", { name: name, type: type === 'datetime' ? 'datetime-local' : type, value: isTextLikeInput ? draftValue : type === 'number' ? String(value ?? '') : String(value ?? ''), disabled: disabled, onCompositionStart: isTextLikeInput ? (() => {
|
|
48
|
+
isComposingRef.current = true;
|
|
49
|
+
}) : undefined, onCompositionEnd: isTextLikeInput ? ((event) => {
|
|
50
|
+
const nextValue = String(event?.target?.value ?? '');
|
|
51
|
+
isComposingRef.current = false;
|
|
52
|
+
setDraftValue(nextValue);
|
|
53
|
+
onChange(nextValue);
|
|
54
|
+
}) : undefined, onChange: (event) => {
|
|
55
|
+
if (!isTextLikeInput) {
|
|
56
|
+
onChange(coerceValue(type, event));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const nextValue = String(event?.target?.value ?? '');
|
|
60
|
+
setDraftValue(nextValue);
|
|
61
|
+
if (!isComposingRef.current) {
|
|
62
|
+
onChange(nextValue);
|
|
63
|
+
}
|
|
64
|
+
} })),
|
|
65
|
+
hint ? React.createElement("small", { className: "rdsl-form-hint" }, hint) : null));
|
|
66
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { DataTableAction, DataTableColumn, SortState } from './DataTable.js';
|
|
2
|
+
export interface GroupedDataTableGroup<T extends {
|
|
3
|
+
id: string;
|
|
4
|
+
}> {
|
|
5
|
+
id: string;
|
|
6
|
+
values: Record<string, unknown>;
|
|
7
|
+
rows: T[];
|
|
8
|
+
}
|
|
9
|
+
export interface GroupedDataTableProps<T extends {
|
|
10
|
+
id: string;
|
|
11
|
+
}> {
|
|
12
|
+
columns: readonly DataTableColumn<T>[];
|
|
13
|
+
groupBy: readonly string[];
|
|
14
|
+
groups: Array<GroupedDataTableGroup<T>>;
|
|
15
|
+
loading?: boolean;
|
|
16
|
+
sort?: SortState | null;
|
|
17
|
+
onSortChange?: (next: SortState | null) => void;
|
|
18
|
+
actions?: readonly DataTableAction<T>[];
|
|
19
|
+
selectedRowId?: string | null;
|
|
20
|
+
onSelectRow?: (row: T) => void;
|
|
21
|
+
selectionName?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function GroupedDataTable<T extends {
|
|
24
|
+
id: string;
|
|
25
|
+
}>({ columns, groupBy, groups, loading, sort, onSortChange, actions, selectedRowId, onSelectRow, selectionName, }: GroupedDataTableProps<T>): JSX.Element;
|
|
26
|
+
//# sourceMappingURL=GroupedDataTable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GroupedDataTable.d.ts","sourceRoot":"","sources":["../../src/components/GroupedDataTable.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAElF,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;IAC7D,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,IAAI,EAAE,CAAC,EAAE,CAAC;CACX;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;IAC7D,OAAO,EAAE,SAAS,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IACvC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,MAAM,EAAE,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,OAAO,CAAC,EAAE,SAAS,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IACxC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAmBD,wBAAgB,gBAAgB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,EACzD,OAAO,EACP,OAAO,EACP,MAAM,EACN,OAAe,EACf,IAAW,EACX,YAAY,EACZ,OAAY,EACZ,aAAoB,EACpB,WAAW,EACX,aAA8C,GAC/C,EAAE,qBAAqB,CAAC,CAAC,CAAC,eA+G1B"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
function formatValue(value, format) {
|
|
3
|
+
if (value === null || value === undefined || value === '')
|
|
4
|
+
return '—';
|
|
5
|
+
if (format !== 'date')
|
|
6
|
+
return String(value);
|
|
7
|
+
const date = new Date(String(value));
|
|
8
|
+
return Number.isNaN(date.getTime()) ? String(value) : date.toLocaleString();
|
|
9
|
+
}
|
|
10
|
+
function nextSortState(current, field) {
|
|
11
|
+
if (!current || current.field !== field) {
|
|
12
|
+
return { field, direction: 'asc' };
|
|
13
|
+
}
|
|
14
|
+
if (current.direction === 'asc') {
|
|
15
|
+
return { field, direction: 'desc' };
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
export function GroupedDataTable({ columns, groupBy, groups, loading = false, sort = null, onSortChange, actions = [], selectedRowId = null, onSelectRow, selectionName = 'rdsl-grouped-table-selection', }) {
|
|
20
|
+
const groupColumns = columns.filter((column) => groupBy.includes(column.key));
|
|
21
|
+
const rowColumns = columns.filter((column) => !groupBy.includes(column.key));
|
|
22
|
+
const hasSelection = Boolean(onSelectRow);
|
|
23
|
+
return (React.createElement("div", { className: "rdsl-grouped-data-table" },
|
|
24
|
+
loading ? React.createElement("div", { className: "rdsl-empty" }, "Loading...") : null,
|
|
25
|
+
!loading && groups.length === 0 ? React.createElement("div", { className: "rdsl-empty" }, "No records") : null,
|
|
26
|
+
!loading
|
|
27
|
+
? groups.map((group) => {
|
|
28
|
+
const firstRow = group.rows[0];
|
|
29
|
+
return (React.createElement("section", { key: group.id, className: "rdsl-grouped-data-table-group" },
|
|
30
|
+
React.createElement("div", { className: "rdsl-grouped-data-table-summary" }, groupColumns.map((column) => {
|
|
31
|
+
const value = group.values[column.key];
|
|
32
|
+
return (React.createElement("div", { key: column.key, className: "rdsl-grouped-data-table-summary-item" },
|
|
33
|
+
React.createElement("strong", null, column.label),
|
|
34
|
+
React.createElement("span", null, column.render ? column.render(value, firstRow) : formatValue(value, column.format))));
|
|
35
|
+
})),
|
|
36
|
+
React.createElement("table", null,
|
|
37
|
+
React.createElement("thead", null,
|
|
38
|
+
React.createElement("tr", null,
|
|
39
|
+
hasSelection ? React.createElement("th", null, "Select") : null,
|
|
40
|
+
rowColumns.map((column) => {
|
|
41
|
+
const sortable = Boolean(column.sortable && onSortChange);
|
|
42
|
+
const activeSort = sort?.field === column.key ? sort.direction : null;
|
|
43
|
+
return (React.createElement("th", { key: column.key }, sortable ? (React.createElement("button", { type: "button", className: "rdsl-table-sort", onClick: () => onSortChange?.(nextSortState(sort, column.key)) },
|
|
44
|
+
column.label,
|
|
45
|
+
activeSort ? ` ${activeSort === 'asc' ? '↑' : '↓'}` : '')) : (column.label)));
|
|
46
|
+
}),
|
|
47
|
+
actions.length > 0 ? React.createElement("th", null, "Actions") : null)),
|
|
48
|
+
React.createElement("tbody", null, group.rows.map((record) => (React.createElement("tr", { key: record.id },
|
|
49
|
+
hasSelection ? (React.createElement("td", null,
|
|
50
|
+
React.createElement("input", { type: "radio", name: selectionName, checked: selectedRowId === String(record.id), onChange: () => onSelectRow?.(record) }))) : null,
|
|
51
|
+
rowColumns.map((column) => {
|
|
52
|
+
const value = record[column.key];
|
|
53
|
+
return (React.createElement("td", { key: column.key }, column.render ? column.render(value, record) : formatValue(value, column.format)));
|
|
54
|
+
}),
|
|
55
|
+
actions.length > 0 ? (React.createElement("td", null,
|
|
56
|
+
React.createElement("div", { className: "rdsl-table-actions" }, actions.map((action) => {
|
|
57
|
+
const className = action.variant === 'danger'
|
|
58
|
+
? 'rdsl-btn rdsl-btn-danger'
|
|
59
|
+
: 'rdsl-btn rdsl-btn-secondary';
|
|
60
|
+
if (action.href) {
|
|
61
|
+
return (React.createElement("a", { key: action.label, className: className, href: action.href(record) }, action.label));
|
|
62
|
+
}
|
|
63
|
+
return (React.createElement("button", { key: action.label, type: "button", className: className, onClick: () => action.onClick?.(record) }, action.label));
|
|
64
|
+
})))) : null)))))));
|
|
65
|
+
})
|
|
66
|
+
: null));
|
|
67
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../src/components/Pagination.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAMD,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,eAAe,eAyBvE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
function clampPage(page, total) {
|
|
3
|
+
return Math.min(Math.max(page, 1), Math.max(total, 1));
|
|
4
|
+
}
|
|
5
|
+
export function Pagination({ current, total, onChange }) {
|
|
6
|
+
const totalPages = Math.max(total, 1);
|
|
7
|
+
const currentPage = clampPage(current, totalPages);
|
|
8
|
+
return (React.createElement("nav", { className: "rdsl-pagination", "aria-label": "Pagination" },
|
|
9
|
+
React.createElement("button", { type: "button", disabled: currentPage <= 1, onClick: () => onChange(currentPage - 1) }, "Previous"),
|
|
10
|
+
Array.from({ length: totalPages }, (_, index) => index + 1).map((page) => (React.createElement("button", { key: page, type: "button", "aria-current": page === currentPage ? 'page' : undefined, disabled: page === currentPage, onClick: () => onChange(page) }, page))),
|
|
11
|
+
React.createElement("button", { type: "button", disabled: currentPage >= totalPages, onClick: () => onChange(currentPage + 1) }, "Next")));
|
|
12
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DataTableAction, DataTableColumn } from './DataTable.js';
|
|
2
|
+
export interface PivotDataTableGroup<T extends {
|
|
3
|
+
id: string;
|
|
4
|
+
}> {
|
|
5
|
+
id: string;
|
|
6
|
+
values: Record<string, unknown>;
|
|
7
|
+
rows: T[];
|
|
8
|
+
}
|
|
9
|
+
export interface PivotDataTableProps<T extends {
|
|
10
|
+
id: string;
|
|
11
|
+
}> {
|
|
12
|
+
columns: readonly DataTableColumn<T>[];
|
|
13
|
+
groupBy: readonly string[];
|
|
14
|
+
pivotBy: string;
|
|
15
|
+
groups: Array<PivotDataTableGroup<T>>;
|
|
16
|
+
loading?: boolean;
|
|
17
|
+
actions?: readonly DataTableAction<T>[];
|
|
18
|
+
selectedRowId?: string | null;
|
|
19
|
+
onSelectRow?: (row: T) => void;
|
|
20
|
+
selectionName?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function PivotDataTable<T extends {
|
|
23
|
+
id: string;
|
|
24
|
+
}>({ columns, groupBy, pivotBy, groups, loading, actions, selectedRowId, onSelectRow, selectionName, }: PivotDataTableProps<T>): JSX.Element;
|
|
25
|
+
//# sourceMappingURL=PivotDataTable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PivotDataTable.d.ts","sourceRoot":"","sources":["../../src/components/PivotDataTable.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEvE,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;IAC3D,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,IAAI,EAAE,CAAC,EAAE,CAAC;CACX;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;IAC3D,OAAO,EAAE,SAAS,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IACvC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,SAAS,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IACxC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA0BD,wBAAgB,cAAc,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,EACvD,OAAO,EACP,OAAO,EACP,OAAO,EACP,MAAM,EACN,OAAe,EACf,OAAY,EACZ,aAAoB,EACpB,WAAW,EACX,aAA4C,GAC7C,EAAE,mBAAmB,CAAC,CAAC,CAAC,eA+GxB"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
function formatValue(value, format) {
|
|
3
|
+
if (value === null || value === undefined || value === '')
|
|
4
|
+
return '—';
|
|
5
|
+
if (format !== 'date')
|
|
6
|
+
return String(value);
|
|
7
|
+
const date = new Date(String(value));
|
|
8
|
+
return Number.isNaN(date.getTime()) ? String(value) : date.toLocaleString();
|
|
9
|
+
}
|
|
10
|
+
function collectPivotValues(groups, pivotBy) {
|
|
11
|
+
const values = [];
|
|
12
|
+
for (const group of groups) {
|
|
13
|
+
for (const row of group.rows) {
|
|
14
|
+
const value = row[pivotBy];
|
|
15
|
+
const key = value == null ? '—' : String(value);
|
|
16
|
+
if (!values.includes(key)) {
|
|
17
|
+
values.push(key);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return values;
|
|
22
|
+
}
|
|
23
|
+
export function PivotDataTable({ columns, groupBy, pivotBy, groups, loading = false, actions = [], selectedRowId = null, onSelectRow, selectionName = 'rdsl-pivot-table-selection', }) {
|
|
24
|
+
const groupColumns = columns.filter((column) => groupBy.includes(column.key));
|
|
25
|
+
const pivotColumns = columns.filter((column) => !groupBy.includes(column.key) && column.key !== pivotBy);
|
|
26
|
+
const pivotValues = React.useMemo(() => collectPivotValues(groups, pivotBy), [groups, pivotBy]);
|
|
27
|
+
const hasSelection = Boolean(onSelectRow);
|
|
28
|
+
return (React.createElement("div", { className: "rdsl-pivot-data-table" },
|
|
29
|
+
loading ? React.createElement("div", { className: "rdsl-empty" }, "Loading...") : null,
|
|
30
|
+
!loading && groups.length === 0 ? React.createElement("div", { className: "rdsl-empty" }, "No records") : null,
|
|
31
|
+
!loading
|
|
32
|
+
? groups.map((group) => {
|
|
33
|
+
const firstRow = group.rows[0];
|
|
34
|
+
return (React.createElement("section", { key: group.id, className: "rdsl-pivot-data-table-group" },
|
|
35
|
+
React.createElement("div", { className: "rdsl-pivot-data-table-summary" }, groupColumns.map((column) => {
|
|
36
|
+
const value = group.values[column.key];
|
|
37
|
+
return (React.createElement("div", { key: column.key, className: "rdsl-pivot-data-table-summary-item" },
|
|
38
|
+
React.createElement("strong", null, column.label),
|
|
39
|
+
React.createElement("span", null, column.render ? column.render(value, firstRow) : formatValue(value, column.format))));
|
|
40
|
+
})),
|
|
41
|
+
React.createElement("table", null,
|
|
42
|
+
React.createElement("thead", null,
|
|
43
|
+
React.createElement("tr", null, pivotValues.map((value) => (React.createElement("th", { key: value }, value))))),
|
|
44
|
+
React.createElement("tbody", null,
|
|
45
|
+
React.createElement("tr", null, pivotValues.map((value) => {
|
|
46
|
+
const rows = group.rows.filter((row) => {
|
|
47
|
+
const rowValue = row[pivotBy];
|
|
48
|
+
return (rowValue == null ? '—' : String(rowValue)) === value;
|
|
49
|
+
});
|
|
50
|
+
return (React.createElement("td", { key: value }, rows.length === 0 ? (React.createElement("div", { className: "rdsl-empty" }, "\u2014")) : (React.createElement("div", { className: "rdsl-pivot-data-table-cell" }, rows.map((record) => (React.createElement("div", { key: record.id, className: "rdsl-pivot-data-table-entry" },
|
|
51
|
+
hasSelection ? (React.createElement("label", { className: "rdsl-pivot-data-table-entry-field" },
|
|
52
|
+
React.createElement("strong", null, "Select"),
|
|
53
|
+
React.createElement("input", { type: "radio", name: selectionName, checked: selectedRowId === String(record.id), onChange: () => onSelectRow?.(record) }))) : null,
|
|
54
|
+
pivotColumns.map((column) => {
|
|
55
|
+
const columnValue = record[column.key];
|
|
56
|
+
return (React.createElement("div", { key: column.key, className: "rdsl-pivot-data-table-entry-field" },
|
|
57
|
+
React.createElement("strong", null, column.label),
|
|
58
|
+
React.createElement("span", null, column.render ? column.render(columnValue, record) : formatValue(columnValue, column.format))));
|
|
59
|
+
}),
|
|
60
|
+
actions.length > 0 ? (React.createElement("div", { className: "rdsl-table-actions" }, actions.map((action) => {
|
|
61
|
+
const className = action.variant === 'danger'
|
|
62
|
+
? 'rdsl-btn rdsl-btn-danger'
|
|
63
|
+
: 'rdsl-btn rdsl-btn-secondary';
|
|
64
|
+
if (action.href) {
|
|
65
|
+
return (React.createElement("a", { key: action.label, className: className, href: action.href(record) }, action.label));
|
|
66
|
+
}
|
|
67
|
+
return (React.createElement("button", { key: action.label, type: "button", className: className, onClick: () => action.onClick?.(record) }, action.label));
|
|
68
|
+
}))) : null)))))));
|
|
69
|
+
}))))));
|
|
70
|
+
})
|
|
71
|
+
: null));
|
|
72
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tag.d.ts","sourceRoot":"","sources":["../../src/components/Tag.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,wBAAgB,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,eAO9C"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export function Tag({ value, colors }) {
|
|
3
|
+
const color = colors[value] ?? 'gray';
|
|
4
|
+
return (React.createElement("span", { className: "rdsl-tag", style: { backgroundColor: color, color: 'white', padding: '0.125rem 0.5rem', borderRadius: '999px' } }, value));
|
|
5
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { WorkflowProgressDescriptor, WorkflowSummaryStepDescriptor } from '@loj-lang/shared-contracts';
|
|
2
|
+
export type WorkflowSummaryStep = WorkflowSummaryStepDescriptor;
|
|
3
|
+
export type WorkflowSummaryProps = WorkflowProgressDescriptor;
|
|
4
|
+
export declare function WorkflowSummary({ stateHeading, stateLabel, currentStepName, nextStepName, steps, }: WorkflowSummaryProps): JSX.Element;
|
|
5
|
+
//# sourceMappingURL=WorkflowSummary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowSummary.d.ts","sourceRoot":"","sources":["../../src/components/WorkflowSummary.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AAE5G,MAAM,MAAM,mBAAmB,GAAG,6BAA6B,CAAC;AAChE,MAAM,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAE9D,wBAAgB,eAAe,CAAC,EAC9B,YAAY,EACZ,UAAU,EACV,eAAe,EACf,YAAY,EACZ,KAAK,GACN,EAAE,oBAAoB,GAAG,GAAG,CAAC,OAAO,CA6BpC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export function WorkflowSummary({ stateHeading, stateLabel, currentStepName, nextStepName, steps, }) {
|
|
3
|
+
return (React.createElement("section", { className: "rdsl-workflow-summary" },
|
|
4
|
+
React.createElement("div", { className: "rdsl-read-actions" },
|
|
5
|
+
React.createElement("strong", null, stateHeading),
|
|
6
|
+
React.createElement("span", { className: "rdsl-btn rdsl-btn-secondary" }, stateLabel)),
|
|
7
|
+
React.createElement("div", { className: "rdsl-read-actions" },
|
|
8
|
+
React.createElement("strong", null, "Current step"),
|
|
9
|
+
React.createElement("span", null, currentStepName ?? '—')),
|
|
10
|
+
nextStepName ? (React.createElement("div", { className: "rdsl-read-actions" },
|
|
11
|
+
React.createElement("strong", null, "Next step"),
|
|
12
|
+
React.createElement("span", null, nextStepName))) : null,
|
|
13
|
+
steps.length > 0 ? (React.createElement("ol", { className: "rdsl-related-list" }, steps.map((step) => (React.createElement("li", { key: step.name },
|
|
14
|
+
React.createElement("strong", null, step.name),
|
|
15
|
+
' ',
|
|
16
|
+
React.createElement("span", null, step.status)))))) : null));
|
|
17
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare function normalizeAppBasePath(value: string | null | undefined): string;
|
|
2
|
+
export declare function configureAppBasePath(value: string | null | undefined): void;
|
|
3
|
+
export declare function getConfiguredAppBasePath(): string;
|
|
4
|
+
export declare function prefixAppBasePath(path: string): string;
|
|
5
|
+
export declare function stripAppBasePath(pathname: string): string;
|
|
6
|
+
export declare function getCurrentAppPathname(): string;
|
|
7
|
+
export declare function getCurrentAppHref(): string;
|
|
8
|
+
export declare function getLocationSearchParams(): URLSearchParams | null;
|
|
9
|
+
export declare function shiftDateInputValue(value: string, days: number): string;
|
|
10
|
+
export declare function getLocationSearchValues<T extends Record<string, string>>(defaultValues: T, options?: {
|
|
11
|
+
prefix?: string;
|
|
12
|
+
searchParams?: URLSearchParams | null;
|
|
13
|
+
}): T;
|
|
14
|
+
export declare function replaceLocationSearchValues(values: Record<string, string>, options?: {
|
|
15
|
+
prefix?: string;
|
|
16
|
+
keys?: readonly string[];
|
|
17
|
+
}): void;
|
|
18
|
+
export declare function sanitizeAppLocalHref(candidate: string | null | undefined): string | null;
|
|
19
|
+
export declare function getSanitizedReturnTo(searchParams?: URLSearchParams | null): string | null;
|
|
20
|
+
//# sourceMappingURL=navigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/hooks/navigation.ts"],"names":[],"mappings":"AAEA,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAU7E;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAE3E;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAetD;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAazD;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAG9C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C;AAED,wBAAgB,uBAAuB,IAAI,eAAe,GAAG,IAAI,CAGhE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CA2BvE;AAMD,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACtE,aAAa,EAAE,CAAC,EAChB,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CAClC,GACL,CAAC,CAUH;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACrB,GACL,IAAI,CAuBN;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAGxF;AAED,wBAAgB,oBAAoB,CAAC,YAAY,CAAC,EAAE,eAAe,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAGzF"}
|