@strato-admin/cloudscape 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 +21 -0
- package/README.md +3 -0
- package/dist/Admin.d.ts +17 -0
- package/dist/Admin.js +69 -0
- package/dist/RecordLink.d.ts +9 -0
- package/dist/RecordLink.js +43 -0
- package/dist/__mocks__/strato-core.js +50 -0
- package/dist/__mocks__to__delete/strato-core.js +50 -0
- package/dist/button/BulkDeleteButton.d.ts +7 -0
- package/dist/button/BulkDeleteButton.js +17 -0
- package/dist/button/Button.d.ts +6 -0
- package/dist/button/Button.js +6 -0
- package/dist/button/CreateButton.d.ts +6 -0
- package/dist/button/CreateButton.js +24 -0
- package/dist/button/EditButton.d.ts +8 -0
- package/dist/button/EditButton.js +24 -0
- package/dist/button/SaveButton.d.ts +6 -0
- package/dist/button/SaveButton.js +8 -0
- package/dist/button/index.d.ts +5 -0
- package/dist/button/index.js +5 -0
- package/dist/collection-hooks/index.d.ts +2 -0
- package/dist/collection-hooks/index.js +2 -0
- package/dist/collection-hooks/interfaces.d.ts +93 -0
- package/dist/collection-hooks/interfaces.js +1 -0
- package/dist/collection-hooks/useCollection.d.ts +3 -0
- package/dist/collection-hooks/useCollection.js +102 -0
- package/dist/create/Create.d.ts +40 -0
- package/dist/create/Create.js +34 -0
- package/dist/create/CreateHeader.d.ts +7 -0
- package/dist/create/CreateHeader.js +18 -0
- package/dist/create/index.d.ts +2 -0
- package/dist/create/index.js +2 -0
- package/dist/detail/KeyValuePairs.d.ts +36 -0
- package/dist/detail/KeyValuePairs.js +58 -0
- package/dist/detail/Show.d.ts +39 -0
- package/dist/detail/Show.js +40 -0
- package/dist/detail/ShowHeader.d.ts +7 -0
- package/dist/detail/ShowHeader.js +19 -0
- package/dist/detail/index.d.ts +3 -0
- package/dist/detail/index.js +3 -0
- package/dist/edit/Edit.d.ts +42 -0
- package/dist/edit/Edit.js +38 -0
- package/dist/edit/EditHeader.d.ts +7 -0
- package/dist/edit/EditHeader.js +18 -0
- package/dist/edit/index.d.ts +2 -0
- package/dist/edit/index.js +2 -0
- package/dist/field/ArrayField.d.ts +29 -0
- package/dist/field/ArrayField.js +30 -0
- package/dist/field/BadgeField.d.ts +12 -0
- package/dist/field/BadgeField.js +15 -0
- package/dist/field/BooleanField.d.ts +18 -0
- package/dist/field/BooleanField.js +14 -0
- package/dist/field/CurrencyField.d.ts +19 -0
- package/dist/field/CurrencyField.js +23 -0
- package/dist/field/DateField.d.ts +14 -0
- package/dist/field/DateField.js +17 -0
- package/dist/field/IdField.d.ts +17 -0
- package/dist/field/IdField.js +21 -0
- package/dist/field/NumberField.d.ts +14 -0
- package/dist/field/NumberField.js +18 -0
- package/dist/field/ReferenceField.d.ts +16 -0
- package/dist/field/ReferenceField.js +23 -0
- package/dist/field/ReferenceManyField.d.ts +55 -0
- package/dist/field/ReferenceManyField.js +19 -0
- package/dist/field/StatusIndicatorField.d.ts +56 -0
- package/dist/field/StatusIndicatorField.js +48 -0
- package/dist/field/TextField.d.ts +5 -0
- package/dist/field/TextField.js +11 -0
- package/dist/field/index.d.ts +23 -0
- package/dist/field/index.js +23 -0
- package/dist/field/types.d.ts +56 -0
- package/dist/field/types.js +1 -0
- package/dist/form/Form.d.ts +13 -0
- package/dist/form/Form.js +33 -0
- package/dist/form/index.d.ts +2 -0
- package/dist/form/index.js +2 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +22 -0
- package/dist/input/AttributeEditor.d.ts +25 -0
- package/dist/input/AttributeEditor.js +80 -0
- package/dist/input/AutocompleteInput.d.ts +10 -0
- package/dist/input/AutocompleteInput.js +67 -0
- package/dist/input/FieldTitle.d.ts +8 -0
- package/dist/input/FieldTitle.js +29 -0
- package/dist/input/FormField.d.ts +7 -0
- package/dist/input/FormField.js +35 -0
- package/dist/input/FormFieldContext.d.ts +6 -0
- package/dist/input/FormFieldContext.js +3 -0
- package/dist/input/NumberInput.d.ts +7 -0
- package/dist/input/NumberInput.js +27 -0
- package/dist/input/ReferenceInput.d.ts +3 -0
- package/dist/input/ReferenceInput.js +25 -0
- package/dist/input/SelectInput.d.ts +15 -0
- package/dist/input/SelectInput.js +47 -0
- package/dist/input/SliderInput.d.ts +6 -0
- package/dist/input/SliderInput.js +25 -0
- package/dist/input/TextAreaInput.d.ts +6 -0
- package/dist/input/TextAreaInput.js +23 -0
- package/dist/input/TextInput.d.ts +7 -0
- package/dist/input/TextInput.js +23 -0
- package/dist/input/index.d.ts +11 -0
- package/dist/input/index.js +11 -0
- package/dist/input/types.d.ts +6 -0
- package/dist/input/types.js +1 -0
- package/dist/layout/AppLayout.d.ts +8 -0
- package/dist/layout/AppLayout.js +38 -0
- package/dist/layout/TopNavigation.d.ts +6 -0
- package/dist/layout/TopNavigation.js +53 -0
- package/dist/layout/index.d.ts +2 -0
- package/dist/layout/index.js +2 -0
- package/dist/list/Cards.d.ts +11 -0
- package/dist/list/Cards.js +27 -0
- package/dist/list/List.d.ts +43 -0
- package/dist/list/List.js +28 -0
- package/dist/list/Table.d.ts +112 -0
- package/dist/list/Table.examples.d.ts +1 -0
- package/dist/list/Table.examples.js +3 -0
- package/dist/list/Table.js +218 -0
- package/dist/list/TableHeader.d.ts +7 -0
- package/dist/list/TableHeader.js +22 -0
- package/dist/list/index.d.ts +4 -0
- package/dist/list/index.js +4 -0
- package/dist/preferences/index.d.ts +0 -0
- package/dist/preferences/index.js +1 -0
- package/dist/theme/ThemeManager.d.ts +2 -0
- package/dist/theme/ThemeManager.js +11 -0
- package/dist/theme/index.d.ts +2 -0
- package/dist/theme/index.js +2 -0
- package/package.json +73 -0
- package/src/Admin.test.tsx +32 -0
- package/src/Admin.tsx +123 -0
- package/src/RecordLink.stories.tsx +56 -0
- package/src/RecordLink.tsx +67 -0
- package/src/__mocks__/strato-core.tsx +52 -0
- package/src/button/BulkDeleteButton.stories.tsx +59 -0
- package/src/button/BulkDeleteButton.test.tsx +64 -0
- package/src/button/BulkDeleteButton.tsx +41 -0
- package/src/button/Button.stories.tsx +31 -0
- package/src/button/Button.tsx +12 -0
- package/src/button/CreateButton.stories.tsx +42 -0
- package/src/button/CreateButton.tsx +38 -0
- package/src/button/EditButton.stories.tsx +29 -0
- package/src/button/EditButton.tsx +38 -0
- package/src/button/SaveButton.stories.tsx +35 -0
- package/src/button/SaveButton.tsx +19 -0
- package/src/button/index.ts +5 -0
- package/src/collection-hooks/index.ts +2 -0
- package/src/collection-hooks/interfaces.ts +80 -0
- package/src/collection-hooks/useCollection.test.ts +413 -0
- package/src/collection-hooks/useCollection.ts +125 -0
- package/src/create/Create.test.tsx +63 -0
- package/src/create/Create.tsx +93 -0
- package/src/create/CreateHeader.tsx +34 -0
- package/src/create/index.ts +2 -0
- package/src/detail/KeyValuePairs.test.tsx +98 -0
- package/src/detail/KeyValuePairs.tsx +107 -0
- package/src/detail/Show.test.tsx +96 -0
- package/src/detail/Show.tsx +104 -0
- package/src/detail/ShowHeader.test.tsx +80 -0
- package/src/detail/ShowHeader.tsx +35 -0
- package/src/detail/index.ts +3 -0
- package/src/edit/Edit.test.tsx +91 -0
- package/src/edit/Edit.tsx +102 -0
- package/src/edit/EditHeader.tsx +34 -0
- package/src/edit/index.ts +2 -0
- package/src/field/ArrayField.tsx +51 -0
- package/src/field/BadgeField.tsx +33 -0
- package/src/field/BooleanField.stories.tsx +56 -0
- package/src/field/BooleanField.test.tsx +63 -0
- package/src/field/BooleanField.tsx +42 -0
- package/src/field/CurrencyField.stories.tsx +67 -0
- package/src/field/CurrencyField.tsx +45 -0
- package/src/field/DateField.stories.tsx +67 -0
- package/src/field/DateField.tsx +33 -0
- package/src/field/IdField.test.tsx +88 -0
- package/src/field/IdField.tsx +40 -0
- package/src/field/NumberField.stories.tsx +75 -0
- package/src/field/NumberField.tsx +35 -0
- package/src/field/ReferenceField.test.tsx +88 -0
- package/src/field/ReferenceField.tsx +64 -0
- package/src/field/ReferenceManyField.test.tsx +41 -0
- package/src/field/ReferenceManyField.tsx +73 -0
- package/src/field/StatusIndicatorField.stories.tsx +93 -0
- package/src/field/StatusIndicatorField.test.tsx +143 -0
- package/src/field/StatusIndicatorField.tsx +119 -0
- package/src/field/TextField.stories.tsx +45 -0
- package/src/field/TextField.tsx +17 -0
- package/src/field/index.ts +23 -0
- package/src/field/types.ts +58 -0
- package/src/form/Form.test.tsx +55 -0
- package/src/form/Form.tsx +66 -0
- package/src/form/index.ts +2 -0
- package/src/index.ts +25 -0
- package/src/input/AttributeEditor.test.tsx +147 -0
- package/src/input/AttributeEditor.tsx +185 -0
- package/src/input/AutocompleteInput.test.tsx +178 -0
- package/src/input/AutocompleteInput.tsx +116 -0
- package/src/input/FieldTitle.tsx +53 -0
- package/src/input/FormField.tsx +87 -0
- package/src/input/FormFieldContext.ts +9 -0
- package/src/input/NumberInput.tsx +56 -0
- package/src/input/ReferenceInput.test.tsx +35 -0
- package/src/input/ReferenceInput.tsx +36 -0
- package/src/input/SelectInput.tsx +91 -0
- package/src/input/SliderInput.test.tsx +103 -0
- package/src/input/SliderInput.tsx +49 -0
- package/src/input/TextAreaInput.tsx +48 -0
- package/src/input/TextInput.test.tsx +91 -0
- package/src/input/TextInput.tsx +51 -0
- package/src/input/index.ts +11 -0
- package/src/input/types.ts +14 -0
- package/src/layout/AppLayout.test.tsx +87 -0
- package/src/layout/AppLayout.tsx +60 -0
- package/src/layout/TopNavigation.test.tsx +78 -0
- package/src/layout/TopNavigation.tsx +84 -0
- package/src/layout/index.ts +2 -0
- package/src/list/Cards.tsx +58 -0
- package/src/list/List.tsx +76 -0
- package/src/list/Table.examples.tsx +11 -0
- package/src/list/Table.stories.tsx +73 -0
- package/src/list/Table.test.tsx +255 -0
- package/src/list/Table.tsx +438 -0
- package/src/list/TableHeader.test.tsx +114 -0
- package/src/list/TableHeader.tsx +44 -0
- package/src/list/index.ts +4 -0
- package/src/preferences/index.ts +0 -0
- package/src/stories/Button.stories.ts +54 -0
- package/src/stories/Button.tsx +31 -0
- package/src/stories/Configure.mdx +369 -0
- package/src/stories/Header.stories.ts +34 -0
- package/src/stories/Header.tsx +47 -0
- package/src/stories/Page.stories.ts +33 -0
- package/src/stories/Page.tsx +71 -0
- package/src/stories/RaStoryDecorator.tsx +38 -0
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +1 -0
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +1 -0
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +1 -0
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +1 -0
- package/src/stories/assets/youtube.svg +1 -0
- package/src/stories/button.css +30 -0
- package/src/stories/header.css +32 -0
- package/src/stories/page.css +68 -0
- package/src/theme/ThemeManager.tsx +15 -0
- package/src/theme/index.ts +2 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AutosuggestProps as CloudscapeAutosuggestProps } from '@cloudscape-design/components/autosuggest';
|
|
2
|
+
import { InputProps } from './types';
|
|
3
|
+
export interface AutocompleteInputProps extends Omit<CloudscapeAutosuggestProps, 'onChange' | 'value' | 'options' | 'onBlur'>, InputProps {
|
|
4
|
+
choices?: Array<{
|
|
5
|
+
id: string | number;
|
|
6
|
+
[key: string]: any;
|
|
7
|
+
}>;
|
|
8
|
+
}
|
|
9
|
+
export declare const AutocompleteInput: (props: AutocompleteInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export default AutocompleteInput;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useState, useEffect, useMemo } from 'react';
|
|
3
|
+
import { useInput, useResourceContext, useChoicesContext, useGetRecordRepresentation, } from '@strato-admin/core';
|
|
4
|
+
import CloudscapeAutosuggest from '@cloudscape-design/components/autosuggest';
|
|
5
|
+
import { FormField } from './FormField';
|
|
6
|
+
import { FormFieldContext, useFormFieldContext } from './FormFieldContext';
|
|
7
|
+
export const AutocompleteInput = (props) => {
|
|
8
|
+
const { label, source, defaultValue, validate, choices: choicesProp, ...rest } = props;
|
|
9
|
+
const resource = useResourceContext();
|
|
10
|
+
const { allChoices, isPending, setFilters } = useChoicesContext(props);
|
|
11
|
+
const getRecordRepresentation = useGetRecordRepresentation(resource);
|
|
12
|
+
const context = useFormFieldContext();
|
|
13
|
+
const inputState = context ??
|
|
14
|
+
useInput({
|
|
15
|
+
source,
|
|
16
|
+
defaultValue,
|
|
17
|
+
validate,
|
|
18
|
+
...rest,
|
|
19
|
+
});
|
|
20
|
+
const { id, field } = inputState;
|
|
21
|
+
const choices = choicesProp || allChoices || [];
|
|
22
|
+
const selectedChoice = useMemo(() => choices.find((c) => String(c.id) === String(field.value)), [choices, field.value]);
|
|
23
|
+
const [filterValue, setFilterValue] = useState('');
|
|
24
|
+
// Keep track of the last value we synced from the field
|
|
25
|
+
const lastSyncedValue = React.useRef(undefined);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (selectedChoice) {
|
|
28
|
+
setFilterValue(String(getRecordRepresentation(selectedChoice)));
|
|
29
|
+
lastSyncedValue.current = field.value;
|
|
30
|
+
}
|
|
31
|
+
else if (!field.value) {
|
|
32
|
+
setFilterValue('');
|
|
33
|
+
lastSyncedValue.current = field.value;
|
|
34
|
+
}
|
|
35
|
+
else if (field.value !== lastSyncedValue.current) {
|
|
36
|
+
// If we have a value but no choice yet, and we are not loading,
|
|
37
|
+
// we show the ID as a last resort.
|
|
38
|
+
if (!isPending) {
|
|
39
|
+
setFilterValue(String(field.value));
|
|
40
|
+
lastSyncedValue.current = field.value;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}, [field.value, selectedChoice, getRecordRepresentation, isPending]);
|
|
44
|
+
const options = useMemo(() => choices.map((choice) => ({
|
|
45
|
+
label: String(getRecordRepresentation(choice)),
|
|
46
|
+
value: String(choice.id),
|
|
47
|
+
})), [choices, getRecordRepresentation]);
|
|
48
|
+
const handleChange = ({ detail }) => {
|
|
49
|
+
setFilterValue(detail.value);
|
|
50
|
+
if (setFilters) {
|
|
51
|
+
setFilters(detail.value);
|
|
52
|
+
}
|
|
53
|
+
// If the user cleared the input, we clear the field value
|
|
54
|
+
if (detail.value === '') {
|
|
55
|
+
field.onChange(null);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const handleSelect = ({ detail }) => {
|
|
59
|
+
field.onChange(detail.value);
|
|
60
|
+
};
|
|
61
|
+
const inner = (_jsx(CloudscapeAutosuggest, { ...rest, id: id, options: options, value: filterValue, statusType: isPending ? 'loading' : 'finished', expandToViewport: true, onChange: handleChange, onSelect: handleSelect, onBlur: () => field.onBlur() }));
|
|
62
|
+
if (context) {
|
|
63
|
+
return inner;
|
|
64
|
+
}
|
|
65
|
+
return (_jsx(FormFieldContext.Provider, { value: inputState, children: _jsx(FormField, { ...props, children: inner }) }));
|
|
66
|
+
};
|
|
67
|
+
export default AutocompleteInput;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useTranslate, useResourceDefinitions } from '@strato-admin/core';
|
|
4
|
+
import { humanize } from 'inflection';
|
|
5
|
+
export const FieldTitle = (props) => {
|
|
6
|
+
const { resource, source, label, isRequired } = props;
|
|
7
|
+
const translate = useTranslate();
|
|
8
|
+
const definitions = useResourceDefinitions();
|
|
9
|
+
const labelString = React.useMemo(() => {
|
|
10
|
+
if (label !== undefined) {
|
|
11
|
+
return translate(label, { _: label });
|
|
12
|
+
}
|
|
13
|
+
if (!resource || !source) {
|
|
14
|
+
return source ? humanize(source) : '';
|
|
15
|
+
}
|
|
16
|
+
const definition = definitions[resource];
|
|
17
|
+
const fieldDefinition = definition?.fields?.[source];
|
|
18
|
+
const defaultLabel = fieldDefinition?.label
|
|
19
|
+
? translate(fieldDefinition.label, { _: fieldDefinition.label })
|
|
20
|
+
: source
|
|
21
|
+
? humanize(source)
|
|
22
|
+
: '';
|
|
23
|
+
return translate(`resources.${resource}.fields.${source}`, {
|
|
24
|
+
_: defaultLabel,
|
|
25
|
+
});
|
|
26
|
+
}, [label, translate, resource, source, definitions]);
|
|
27
|
+
return (_jsxs("span", { children: [labelString, !isRequired && (_jsx("span", { style: { color: '#687078', fontWeight: 'normal', fontStyle: 'italic', fontSize: '12px', marginLeft: '4px' }, children: "(optional)" }))] }));
|
|
28
|
+
};
|
|
29
|
+
export default FieldTitle;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { InputProps } from './types';
|
|
3
|
+
export interface FormFieldProps extends InputProps {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
}
|
|
6
|
+
export declare const FormField: (props: FormFieldProps) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export default FormField;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useInput, useResourceContext, ValidationError } from '@strato-admin/core';
|
|
4
|
+
import CloudscapeFormField from '@cloudscape-design/components/form-field';
|
|
5
|
+
import { FieldTitle } from './FieldTitle';
|
|
6
|
+
import { FormFieldContext, useFormFieldContext } from './FormFieldContext';
|
|
7
|
+
export const FormField = (props) => {
|
|
8
|
+
const { children, label, source, defaultValue, validate, description, constraintText, info, secondaryControl, stretch, i18nStrings, ...rest } = props;
|
|
9
|
+
const resource = useResourceContext();
|
|
10
|
+
const context = useFormFieldContext();
|
|
11
|
+
const inputState = context ??
|
|
12
|
+
useInput({
|
|
13
|
+
source,
|
|
14
|
+
defaultValue,
|
|
15
|
+
validate,
|
|
16
|
+
...rest,
|
|
17
|
+
});
|
|
18
|
+
const contextValue = React.useMemo(() => {
|
|
19
|
+
if (!inputState)
|
|
20
|
+
return undefined;
|
|
21
|
+
return {
|
|
22
|
+
...inputState,
|
|
23
|
+
source: source || context?.source || '',
|
|
24
|
+
};
|
|
25
|
+
}, [inputState, source, context?.source]);
|
|
26
|
+
const { id, fieldState: { isTouched, invalid, error }, formState: { isSubmitted }, isRequired, } = inputState;
|
|
27
|
+
const errorToProcess = error?.message || error?.root?.message;
|
|
28
|
+
const errorText = (isTouched || isSubmitted) && invalid && typeof errorToProcess === 'string' ? (_jsx(ValidationError, { error: errorToProcess })) : undefined;
|
|
29
|
+
const content = (_jsx(CloudscapeFormField, { id: id, label: label === false ? undefined : (_jsx(FieldTitle, { label: label, source: source, resource: resource, isRequired: isRequired })), description: description, constraintText: constraintText, info: info, secondaryControl: secondaryControl, stretch: stretch, i18nStrings: i18nStrings, errorText: errorText, children: children }));
|
|
30
|
+
if (context) {
|
|
31
|
+
return content;
|
|
32
|
+
}
|
|
33
|
+
return _jsx(FormFieldContext.Provider, { value: contextValue, children: content });
|
|
34
|
+
};
|
|
35
|
+
export default FormField;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { UseInputValue } from '@strato-admin/core';
|
|
2
|
+
export interface FormFieldContextValue extends UseInputValue {
|
|
3
|
+
source?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const FormFieldContext: import("react").Context<FormFieldContextValue | undefined>;
|
|
6
|
+
export declare const useFormFieldContext: () => FormFieldContextValue | undefined;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { InputProps as CloudscapeInputProps } from '@cloudscape-design/components/input';
|
|
2
|
+
import { InputProps } from './types';
|
|
3
|
+
export interface NumberInputProps extends Omit<CloudscapeInputProps, 'onChange' | 'value' | 'onBlur' | 'type'>, InputProps {
|
|
4
|
+
type?: CloudscapeInputProps['type'];
|
|
5
|
+
}
|
|
6
|
+
export declare const NumberInput: (props: NumberInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export default NumberInput;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useInput } from '@strato-admin/core';
|
|
3
|
+
import CloudscapeInput from '@cloudscape-design/components/input';
|
|
4
|
+
import { FormField } from './FormField';
|
|
5
|
+
import { FormFieldContext, useFormFieldContext } from './FormFieldContext';
|
|
6
|
+
export const NumberInput = (props) => {
|
|
7
|
+
const { label, source, defaultValue, validate, type = 'number', ...rest } = props;
|
|
8
|
+
const context = useFormFieldContext();
|
|
9
|
+
const inputState = context ??
|
|
10
|
+
useInput({
|
|
11
|
+
source,
|
|
12
|
+
defaultValue,
|
|
13
|
+
validate,
|
|
14
|
+
...rest,
|
|
15
|
+
});
|
|
16
|
+
const { id, field } = inputState;
|
|
17
|
+
const handleChange = (value) => {
|
|
18
|
+
const floatValue = parseFloat(value);
|
|
19
|
+
field.onChange(isNaN(floatValue) ? null : floatValue);
|
|
20
|
+
};
|
|
21
|
+
const inner = (_jsx(CloudscapeInput, { ...rest, ...field, id: id, type: type, value: field.value?.toString() || '', onChange: (event) => handleChange(event.detail.value), onBlur: () => field.onBlur() }));
|
|
22
|
+
if (context) {
|
|
23
|
+
return inner;
|
|
24
|
+
}
|
|
25
|
+
return (_jsx(FormFieldContext.Provider, { value: inputState, children: _jsx(FormField, { ...props, children: inner }) }));
|
|
26
|
+
};
|
|
27
|
+
export default NumberInput;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { ReferenceInputBase } from '@strato-admin/core';
|
|
4
|
+
import { useFormFieldContext } from './FormFieldContext';
|
|
5
|
+
import { AutocompleteInput } from './AutocompleteInput';
|
|
6
|
+
export const ReferenceInput = (props) => {
|
|
7
|
+
const { children, source: sourceProp, reference, ...rest } = props;
|
|
8
|
+
const context = useFormFieldContext();
|
|
9
|
+
// If we have a context, we use the source from it.
|
|
10
|
+
const source = sourceProp || context?.source;
|
|
11
|
+
if (!source) {
|
|
12
|
+
throw new Error('ReferenceInput requires a source prop or a parent FormField Master');
|
|
13
|
+
}
|
|
14
|
+
const finalChildren = children || _jsx(AutocompleteInput, { source: source });
|
|
15
|
+
const inner = (_jsx(ReferenceInputBase, { source: source, reference: reference, ...rest, children: React.isValidElement(finalChildren)
|
|
16
|
+
? React.cloneElement(finalChildren, {
|
|
17
|
+
source,
|
|
18
|
+
})
|
|
19
|
+
: finalChildren }));
|
|
20
|
+
// ReferenceInput is unique because it's a wrapper.
|
|
21
|
+
// It doesn't use FormFieldContext for its state directly (ReferenceInputBase does),
|
|
22
|
+
// but it needs to ensure its children can consume the state it provides via ReferenceInputBase.
|
|
23
|
+
return inner;
|
|
24
|
+
};
|
|
25
|
+
export default ReferenceInput;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SelectProps as CloudscapeSelectProps } from '@cloudscape-design/components/select';
|
|
2
|
+
import { InputProps } from './types';
|
|
3
|
+
export interface SelectInputProps extends Omit<CloudscapeSelectProps, 'onChange' | 'selectedOption' | 'options' | 'onBlur'>, InputProps {
|
|
4
|
+
choices?: Array<{
|
|
5
|
+
id: string | number;
|
|
6
|
+
[key: string]: any;
|
|
7
|
+
}>;
|
|
8
|
+
/**
|
|
9
|
+
* The text to display for the empty option when isRequired is false.
|
|
10
|
+
* @default "-"
|
|
11
|
+
*/
|
|
12
|
+
emptyText?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare const SelectInput: (props: SelectInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export default SelectInput;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useInput, useResourceContext, useChoicesContext, useGetRecordRepresentation, } from '@strato-admin/core';
|
|
4
|
+
import CloudscapeSelect from '@cloudscape-design/components/select';
|
|
5
|
+
import { FormField } from './FormField';
|
|
6
|
+
import { FormFieldContext, useFormFieldContext } from './FormFieldContext';
|
|
7
|
+
export const SelectInput = (props) => {
|
|
8
|
+
const { label, source, defaultValue, validate, choices: choicesProp, emptyText = '-', ...rest } = props;
|
|
9
|
+
const resource = useResourceContext();
|
|
10
|
+
const { allChoices, isPending } = useChoicesContext(props);
|
|
11
|
+
const getRecordRepresentation = useGetRecordRepresentation(resource);
|
|
12
|
+
const context = useFormFieldContext();
|
|
13
|
+
const inputState = context ??
|
|
14
|
+
useInput({
|
|
15
|
+
source,
|
|
16
|
+
defaultValue,
|
|
17
|
+
validate,
|
|
18
|
+
...rest,
|
|
19
|
+
});
|
|
20
|
+
const { id, field, isRequired } = inputState;
|
|
21
|
+
const choices = choicesProp || allChoices || [];
|
|
22
|
+
const options = React.useMemo(() => {
|
|
23
|
+
const opts = choices.map((choice) => ({
|
|
24
|
+
label: String(getRecordRepresentation(choice)),
|
|
25
|
+
value: String(choice.id),
|
|
26
|
+
}));
|
|
27
|
+
if (!isRequired) {
|
|
28
|
+
opts.unshift({ label: emptyText, value: '__EMPTY__' });
|
|
29
|
+
}
|
|
30
|
+
return opts;
|
|
31
|
+
}, [choices, getRecordRepresentation, isRequired, emptyText]);
|
|
32
|
+
const selectedOption = options.find((option) => {
|
|
33
|
+
if (!field.value) {
|
|
34
|
+
return option.value === '__EMPTY__';
|
|
35
|
+
}
|
|
36
|
+
return option.value === String(field.value);
|
|
37
|
+
}) || null;
|
|
38
|
+
const inner = (_jsx(CloudscapeSelect, { ...rest, id: id, options: options, selectedOption: selectedOption, statusType: isPending ? 'loading' : 'finished', expandToViewport: true, onChange: ({ detail }) => {
|
|
39
|
+
const value = detail.selectedOption.value === '__EMPTY__' ? null : detail.selectedOption.value;
|
|
40
|
+
field.onChange(value);
|
|
41
|
+
}, onBlur: () => field.onBlur() }));
|
|
42
|
+
if (context) {
|
|
43
|
+
return inner;
|
|
44
|
+
}
|
|
45
|
+
return (_jsx(FormFieldContext.Provider, { value: inputState, children: _jsx(FormField, { ...props, children: inner }) }));
|
|
46
|
+
};
|
|
47
|
+
export default SelectInput;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SliderProps as CloudscapeSliderProps } from '@cloudscape-design/components/slider';
|
|
2
|
+
import { InputProps } from './types';
|
|
3
|
+
export interface SliderInputProps extends Omit<CloudscapeSliderProps, 'onChange' | 'value' | 'i18nStrings'>, InputProps {
|
|
4
|
+
}
|
|
5
|
+
export declare const SliderInput: (props: SliderInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export default SliderInput;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useInput } from '@strato-admin/core';
|
|
3
|
+
import CloudscapeSlider from '@cloudscape-design/components/slider';
|
|
4
|
+
import { FormField } from './FormField';
|
|
5
|
+
import { FormFieldContext, useFormFieldContext } from './FormFieldContext';
|
|
6
|
+
export const SliderInput = (props) => {
|
|
7
|
+
const { label, source, defaultValue, validate, ...rest } = props;
|
|
8
|
+
const context = useFormFieldContext();
|
|
9
|
+
const inputState = context ??
|
|
10
|
+
useInput({
|
|
11
|
+
source,
|
|
12
|
+
defaultValue,
|
|
13
|
+
validate,
|
|
14
|
+
...rest,
|
|
15
|
+
});
|
|
16
|
+
const { id, field } = inputState;
|
|
17
|
+
// Cloudscape Slider requires a number value
|
|
18
|
+
const value = typeof field.value === 'number' ? field.value : props.min ?? 0;
|
|
19
|
+
const inner = (_jsx(CloudscapeSlider, { ...rest, id: id, value: value, onChange: (event) => field.onChange(event.detail.value) }));
|
|
20
|
+
if (context) {
|
|
21
|
+
return inner;
|
|
22
|
+
}
|
|
23
|
+
return (_jsx(FormFieldContext.Provider, { value: inputState, children: _jsx(FormField, { ...props, children: inner }) }));
|
|
24
|
+
};
|
|
25
|
+
export default SliderInput;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TextareaProps as CloudscapeTextareaProps } from '@cloudscape-design/components/textarea';
|
|
2
|
+
import { InputProps } from './types';
|
|
3
|
+
export interface TextAreaInputProps extends Omit<CloudscapeTextareaProps, 'onChange' | 'value' | 'onBlur'>, InputProps {
|
|
4
|
+
}
|
|
5
|
+
export declare const TextAreaInput: (props: TextAreaInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export default TextAreaInput;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useInput } from '@strato-admin/core';
|
|
3
|
+
import CloudscapeTextarea from '@cloudscape-design/components/textarea';
|
|
4
|
+
import { FormField } from './FormField';
|
|
5
|
+
import { FormFieldContext, useFormFieldContext } from './FormFieldContext';
|
|
6
|
+
export const TextAreaInput = (props) => {
|
|
7
|
+
const { label, source, defaultValue, validate, ...rest } = props;
|
|
8
|
+
const context = useFormFieldContext();
|
|
9
|
+
const inputState = context ??
|
|
10
|
+
useInput({
|
|
11
|
+
source,
|
|
12
|
+
defaultValue,
|
|
13
|
+
validate,
|
|
14
|
+
...rest,
|
|
15
|
+
});
|
|
16
|
+
const { id, field } = inputState;
|
|
17
|
+
const inner = (_jsx(CloudscapeTextarea, { ...rest, ...field, id: id, value: field.value || '', onChange: (event) => field.onChange(event.detail.value), onBlur: () => field.onBlur() }));
|
|
18
|
+
if (context) {
|
|
19
|
+
return inner;
|
|
20
|
+
}
|
|
21
|
+
return (_jsx(FormFieldContext.Provider, { value: inputState, children: _jsx(FormField, { ...props, children: inner }) }));
|
|
22
|
+
};
|
|
23
|
+
export default TextAreaInput;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { InputProps as CloudscapeInputProps } from '@cloudscape-design/components/input';
|
|
2
|
+
import { InputProps } from './types';
|
|
3
|
+
export interface TextInputProps extends Omit<CloudscapeInputProps, 'onChange' | 'value' | 'onBlur' | 'type'>, InputProps {
|
|
4
|
+
type?: CloudscapeInputProps['type'];
|
|
5
|
+
}
|
|
6
|
+
export declare const TextInput: (props: TextInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export default TextInput;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useInput } from '@strato-admin/core';
|
|
3
|
+
import CloudscapeInput from '@cloudscape-design/components/input';
|
|
4
|
+
import { FormField } from './FormField';
|
|
5
|
+
import { FormFieldContext, useFormFieldContext } from './FormFieldContext';
|
|
6
|
+
export const TextInput = (props) => {
|
|
7
|
+
const { label, source, defaultValue, validate, type = 'text', ...rest } = props;
|
|
8
|
+
const context = useFormFieldContext();
|
|
9
|
+
const inputState = context ??
|
|
10
|
+
useInput({
|
|
11
|
+
source,
|
|
12
|
+
defaultValue,
|
|
13
|
+
validate,
|
|
14
|
+
...rest,
|
|
15
|
+
});
|
|
16
|
+
const { id, field } = inputState;
|
|
17
|
+
const inner = (_jsx(CloudscapeInput, { ...rest, ...field, id: id, type: type, value: field.value || '', onChange: (event) => field.onChange(event.detail.value), onBlur: () => field.onBlur() }));
|
|
18
|
+
if (context) {
|
|
19
|
+
return inner;
|
|
20
|
+
}
|
|
21
|
+
return (_jsx(FormFieldContext.Provider, { value: inputState, children: _jsx(FormField, { ...props, children: inner }) }));
|
|
22
|
+
};
|
|
23
|
+
export default TextInput;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './types';
|
|
2
|
+
export * from './TextInput';
|
|
3
|
+
export * from './TextAreaInput';
|
|
4
|
+
export * from './NumberInput';
|
|
5
|
+
export * from './AttributeEditor';
|
|
6
|
+
export * from './SelectInput';
|
|
7
|
+
export * from './AutocompleteInput';
|
|
8
|
+
export * from './ReferenceInput';
|
|
9
|
+
export * from './SliderInput';
|
|
10
|
+
export * from './FormFieldContext';
|
|
11
|
+
export * from './FormField';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './types';
|
|
2
|
+
export * from './TextInput';
|
|
3
|
+
export * from './TextAreaInput';
|
|
4
|
+
export * from './NumberInput';
|
|
5
|
+
export * from './AttributeEditor';
|
|
6
|
+
export * from './SelectInput';
|
|
7
|
+
export * from './AutocompleteInput';
|
|
8
|
+
export * from './ReferenceInput';
|
|
9
|
+
export * from './SliderInput';
|
|
10
|
+
export * from './FormFieldContext';
|
|
11
|
+
export * from './FormField';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { InputProps as InputPropsBase } from '@strato-admin/core';
|
|
2
|
+
import { FormFieldProps as CloudscapeFormFieldProps } from '@cloudscape-design/components/form-field';
|
|
3
|
+
export interface StratoInputProps<T = any> extends Omit<InputPropsBase<T>, 'label'>, Pick<CloudscapeFormFieldProps, 'description' | 'constraintText' | 'info' | 'secondaryControl' | 'stretch' | 'i18nStrings'> {
|
|
4
|
+
label?: string | false;
|
|
5
|
+
}
|
|
6
|
+
export type InputProps<T = any> = StratoInputProps<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface AppLayoutProps {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
header?: React.ReactNode;
|
|
5
|
+
title?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const AppLayout: ({ children, header, title }: AppLayoutProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export default AppLayout;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import CloudscapeAppLayout from '@cloudscape-design/components/app-layout';
|
|
4
|
+
import SideNavigation from '@cloudscape-design/components/side-navigation';
|
|
5
|
+
import { useResourceDefinitions, useDefaultTitle, useGetResourceLabel } from '@strato-admin/core';
|
|
6
|
+
import { useNavigate } from 'react-router-dom';
|
|
7
|
+
import { TopNavigation } from './TopNavigation';
|
|
8
|
+
import ThemeManager from '../theme/ThemeManager';
|
|
9
|
+
export const AppLayout = ({ children, header, title }) => {
|
|
10
|
+
const resources = useResourceDefinitions();
|
|
11
|
+
const getResourceLabel = useGetResourceLabel();
|
|
12
|
+
const navigate = useNavigate();
|
|
13
|
+
const defaultTitle = useDefaultTitle();
|
|
14
|
+
const [navigationOpen, setNavigationOpen] = useState(true);
|
|
15
|
+
const appTitle = title ?? (typeof defaultTitle === 'string' ? defaultTitle : '');
|
|
16
|
+
const items = Object.values(resources).map((resource) => ({
|
|
17
|
+
type: 'link',
|
|
18
|
+
text: getResourceLabel(resource.name),
|
|
19
|
+
href: `/${resource.name}`,
|
|
20
|
+
}));
|
|
21
|
+
return (_jsxs(_Fragment, { children: [_jsx(ThemeManager, {}), header || _jsx(TopNavigation, { identity: { title: appTitle, href: '/' } }), _jsx(CloudscapeAppLayout, { headerSelector: "#header", navigationOpen: navigationOpen, onNavigationChange: ({ detail }) => setNavigationOpen(detail.open), navigation: _jsx(SideNavigation
|
|
22
|
+
//header={{
|
|
23
|
+
// href: '/',
|
|
24
|
+
// text: 'Dashboard',
|
|
25
|
+
//}}
|
|
26
|
+
, {
|
|
27
|
+
//header={{
|
|
28
|
+
// href: '/',
|
|
29
|
+
// text: 'Dashboard',
|
|
30
|
+
//}}
|
|
31
|
+
items: items, onFollow: (event) => {
|
|
32
|
+
if (!event.detail.external) {
|
|
33
|
+
event.preventDefault();
|
|
34
|
+
navigate(event.detail.href);
|
|
35
|
+
}
|
|
36
|
+
} }), content: _jsx("div", { children: children }) })] }));
|
|
37
|
+
};
|
|
38
|
+
export default AppLayout;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TopNavigationProps } from '@cloudscape-design/components/top-navigation';
|
|
2
|
+
export interface MyTopNavigationProps extends Omit<TopNavigationProps, 'identity'> {
|
|
3
|
+
identity?: TopNavigationProps.Identity;
|
|
4
|
+
}
|
|
5
|
+
export declare const TopNavigation: ({ utilities: providedUtilities, identity, ...props }: MyTopNavigationProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export default TopNavigation;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import CloudscapeTopNavigation from '@cloudscape-design/components/top-navigation';
|
|
3
|
+
import { useLocale, useSetLocale, useLocales, useTranslate, useAuthProvider, useStore } from '@strato-admin/core';
|
|
4
|
+
const LightModeIcon = (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 16 16", focusable: "false", children: [_jsx("path", { d: "M8 1.5v13a6.5 6.5 0 0 0 0-13z", fill: "currentColor" }), _jsx("circle", { cx: "8", cy: "8", r: "7", fill: "none", stroke: "currentColor", "stroke-width": "1.5" })] }));
|
|
5
|
+
const DarkModeIcon = (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 16 16", focusable: "false", children: [_jsx("path", { d: "M8 1.5v13a6.5 6.5 0 0 1 0-13z", fill: "currentColor" }), _jsx("circle", { cx: "8", cy: "8", r: "7", fill: "none", stroke: "currentColor", "stroke-width": "1.5" })] }));
|
|
6
|
+
export const TopNavigation = ({ utilities: providedUtilities, identity, ...props }) => {
|
|
7
|
+
const locale = useLocale();
|
|
8
|
+
const setLocale = useSetLocale();
|
|
9
|
+
const locales = useLocales();
|
|
10
|
+
const translate = useTranslate();
|
|
11
|
+
const authProvider = useAuthProvider();
|
|
12
|
+
const [theme, setTheme] = useStore('theme', 'light');
|
|
13
|
+
let utilities = providedUtilities;
|
|
14
|
+
if (!utilities) {
|
|
15
|
+
const autoUtilities = [];
|
|
16
|
+
autoUtilities.push({
|
|
17
|
+
type: 'button',
|
|
18
|
+
iconSvg: theme === 'light' ? LightModeIcon : DarkModeIcon,
|
|
19
|
+
onClick: () => {
|
|
20
|
+
setTheme(theme === 'dark' ? 'light' : 'dark');
|
|
21
|
+
},
|
|
22
|
+
ariaLabel: translate('strato.action.toggle_theme', { _: 'Toggle theme' }),
|
|
23
|
+
});
|
|
24
|
+
if (locales && locales.length > 1) {
|
|
25
|
+
autoUtilities.push({
|
|
26
|
+
type: 'menu-dropdown',
|
|
27
|
+
text: locales.find((l) => l.locale === locale)?.name || locale,
|
|
28
|
+
iconName: 'globe',
|
|
29
|
+
onItemClick: (event) => {
|
|
30
|
+
setLocale(event.detail.id);
|
|
31
|
+
},
|
|
32
|
+
items: locales.map((l) => ({
|
|
33
|
+
id: l.locale,
|
|
34
|
+
text: l.name,
|
|
35
|
+
})),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
if (authProvider) {
|
|
39
|
+
autoUtilities.push({
|
|
40
|
+
type: 'menu-dropdown',
|
|
41
|
+
text: translate('ra.auth.user_menu', { _: 'User' }),
|
|
42
|
+
iconName: 'user-profile',
|
|
43
|
+
items: [
|
|
44
|
+
{ id: 'profile', text: translate('ra.auth.profile', { _: 'Profile' }) },
|
|
45
|
+
{ id: 'signout', text: translate('ra.auth.logout', { _: 'Sign out' }) },
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
utilities = autoUtilities;
|
|
50
|
+
}
|
|
51
|
+
return (_jsx("div", { id: "header", children: _jsx(CloudscapeTopNavigation, { identity: identity || { title: 'Strato Admin', href: '/' }, utilities: utilities, ...props }) }));
|
|
52
|
+
};
|
|
53
|
+
export default TopNavigation;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { CardsProps } from '@cloudscape-design/components/cards';
|
|
3
|
+
import { RaRecord } from '@strato-admin/core';
|
|
4
|
+
export interface ListCardsProps<T extends RaRecord = any> extends Omit<CardsProps<T>, 'items' | 'cardDefinition'> {
|
|
5
|
+
renderItem?: (item: T) => React.ReactNode;
|
|
6
|
+
include?: string[];
|
|
7
|
+
exclude?: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare const ListCards: <T extends RaRecord = any>({ renderItem, include, exclude, ...props }: ListCardsProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export declare const Cards: <T extends RaRecord = any>({ renderItem, include, exclude, ...props }: ListCardsProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export default ListCards;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import CloudscapeCards from '@cloudscape-design/components/cards';
|
|
3
|
+
import Pagination from '@cloudscape-design/components/pagination';
|
|
4
|
+
import { RecordContextProvider, useFieldSchema } from '@strato-admin/core';
|
|
5
|
+
import { useCollection } from '../collection-hooks';
|
|
6
|
+
import KeyValuePairs from '../detail/KeyValuePairs';
|
|
7
|
+
export const ListCards = ({ renderItem, include, exclude, ...props }) => {
|
|
8
|
+
const { items, paginationProps, collectionProps } = useCollection({
|
|
9
|
+
filtering: {},
|
|
10
|
+
pagination: {},
|
|
11
|
+
sorting: {},
|
|
12
|
+
});
|
|
13
|
+
const schemaChildren = useFieldSchema();
|
|
14
|
+
const defaultRenderItem = (_item) => (_jsx(KeyValuePairs, { include: include, exclude: exclude, children: schemaChildren }));
|
|
15
|
+
const finalRenderItem = renderItem || defaultRenderItem;
|
|
16
|
+
const cardDefinition = {
|
|
17
|
+
sections: [
|
|
18
|
+
{
|
|
19
|
+
id: 'main',
|
|
20
|
+
content: (item) => _jsx(RecordContextProvider, { value: item, children: finalRenderItem(item) }),
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
return (_jsx(CloudscapeCards, { ...collectionProps, ...props, items: items || [], cardDefinition: cardDefinition, pagination: _jsx(Pagination, { ...paginationProps }) }));
|
|
25
|
+
};
|
|
26
|
+
export const Cards = ListCards;
|
|
27
|
+
export default ListCards;
|