@sito/dashboard-app 0.0.47 → 0.0.48
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 +98 -2
- package/dist/components/Buttons/IconButton.stories.d.ts +17 -0
- package/dist/components/Buttons/ToTop.d.ts +12 -1
- package/dist/components/Buttons/ToTop.stories.d.ts +4 -1
- package/dist/components/Buttons/ToTop.test.d.ts +1 -0
- package/dist/components/Clock/Clock.stories.d.ts +10 -0
- package/dist/components/Dialog/ConfirmationDialog.stories.d.ts +1 -0
- package/dist/components/Dialog/DialogActions.stories.d.ts +17 -0
- package/dist/components/Dialog/FormDialog.stories.d.ts +10 -3
- package/dist/components/Dialog/ImportDialog/ImportDialog.stories.d.ts +13 -1
- package/dist/components/Dialog/ImportDialog/ImportDialog.test.d.ts +1 -0
- package/dist/components/Dialog/ImportDialog/types.d.ts +2 -0
- package/dist/components/Empty/Empty.stories.d.ts +2 -0
- package/dist/components/Form/FormContainer.stories.d.ts +19 -0
- package/dist/components/Form/ParagraphInput.stories.d.ts +4 -1
- package/dist/components/Loading/SplashScreen.stories.d.ts +1 -0
- package/dist/components/Notification/Notification.stories.d.ts +1 -0
- package/dist/components/Onboarding/Onboarding.stories.d.ts +1 -0
- package/dist/components/Onboarding/Step.stories.d.ts +17 -0
- package/dist/components/Page/Page.stories.d.ts +11 -0
- package/dist/components/PrettyGrid/PrettyGrid.stories.d.ts +2 -0
- package/dist/components/PrettyGrid/PrettyGrid.test.d.ts +1 -0
- package/dist/components/PrettyGrid/types.d.ts +6 -0
- package/dist/components/TabsLayout/Tab.stories.d.ts +19 -0
- package/dist/components/TabsLayout/TabsLayout.stories.d.ts +1 -0
- package/dist/dashboard-app.cjs +1 -1
- package/dist/dashboard-app.js +1549 -1469
- package/dist/hooks/dialogs/types.d.ts +1 -0
- package/dist/hooks/dialogs/useImportDialog.test.d.ts +1 -0
- package/dist/lib/api/IndexedDBClient.d.ts +4 -1
- package/dist/main.css +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ pnpm add @sito/dashboard-app
|
|
|
24
24
|
|
|
25
25
|
## Core exports
|
|
26
26
|
|
|
27
|
-
- Layout and navigation: `Page`, `Navbar`, `Drawer`, `TabsLayout`, `PrettyGrid`
|
|
27
|
+
- Layout and navigation: `Page`, `Navbar`, `Drawer`, `TabsLayout`, `PrettyGrid`, `ToTop`
|
|
28
28
|
- Actions and menus: `Actions`, `Action`, `Dropdown`, button components
|
|
29
29
|
- Dialogs and forms: `Dialog`, `FormDialog`, `ImportDialog`, form inputs
|
|
30
30
|
- Feedback: `Notification`, `Loading`, `Empty`, `Error`, `Onboarding`
|
|
@@ -100,6 +100,93 @@ import { Onboarding } from "@sito/dashboard-app";
|
|
|
100
100
|
|
|
101
101
|
The action buttons still use the package's internal accessibility/button translation keys.
|
|
102
102
|
|
|
103
|
+
### ImportDialog custom preview
|
|
104
|
+
|
|
105
|
+
`ImportDialog` supports optional custom preview rendering via `renderCustomPreview`.
|
|
106
|
+
If provided, it receives current parsed `previewItems` and replaces the default JSON preview.
|
|
107
|
+
If omitted, the default preview remains unchanged.
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
import { ImportDialog } from "@sito/dashboard-app";
|
|
111
|
+
|
|
112
|
+
<ImportDialog<ProductImportPreviewDto>
|
|
113
|
+
open={open}
|
|
114
|
+
title="Import products"
|
|
115
|
+
handleClose={close}
|
|
116
|
+
handleSubmit={submit}
|
|
117
|
+
fileProcessor={parseFile}
|
|
118
|
+
renderCustomPreview={(items) => <ProductsPreviewTable items={items ?? []} />}
|
|
119
|
+
/>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`useImportDialog` also accepts and forwards `renderCustomPreview`:
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
import { useImportDialog } from "@sito/dashboard-app";
|
|
126
|
+
|
|
127
|
+
const importDialog = useImportDialog<ProductDto, ProductImportPreviewDto>({
|
|
128
|
+
queryKey: ["products"],
|
|
129
|
+
entity: "products",
|
|
130
|
+
mutationFn: api.products.import,
|
|
131
|
+
fileProcessor: parseFile,
|
|
132
|
+
renderCustomPreview: (items) => <ProductsPreviewTable items={items ?? []} />,
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### PrettyGrid infinite scroll
|
|
137
|
+
|
|
138
|
+
`PrettyGrid` supports optional infinite loading with `IntersectionObserver`.
|
|
139
|
+
Current usage without infinite props keeps the same behavior.
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
import { PrettyGrid, Loading } from "@sito/dashboard-app";
|
|
143
|
+
|
|
144
|
+
<PrettyGrid<ProductDto>
|
|
145
|
+
data={products}
|
|
146
|
+
loading={isLoading}
|
|
147
|
+
renderComponent={(item) => <ProductCard item={item} />}
|
|
148
|
+
hasMore={hasMore}
|
|
149
|
+
loadingMore={isFetchingNextPage}
|
|
150
|
+
onLoadMore={fetchNextPage}
|
|
151
|
+
loadMoreComponent={<Loading className="!w-auto" loaderClass="w-5 h-5" />}
|
|
152
|
+
/>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Defaults:
|
|
156
|
+
|
|
157
|
+
- `hasMore = false`
|
|
158
|
+
- `loadingMore = false`
|
|
159
|
+
- `loadMoreComponent = null`
|
|
160
|
+
- `observerRootMargin = "0px 0px 200px 0px"`
|
|
161
|
+
- `observerThreshold = 0`
|
|
162
|
+
|
|
163
|
+
### ToTop customization
|
|
164
|
+
|
|
165
|
+
`ToTop` is now customizable while preserving current defaults.
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
import { ToTop } from "@sito/dashboard-app";
|
|
169
|
+
|
|
170
|
+
<ToTop
|
|
171
|
+
threshold={120}
|
|
172
|
+
tooltip="Back to top"
|
|
173
|
+
variant="outlined"
|
|
174
|
+
color="secondary"
|
|
175
|
+
className="right-8 bottom-8"
|
|
176
|
+
scrollTop={0}
|
|
177
|
+
scrollLeft={0}
|
|
178
|
+
/>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Main optional props:
|
|
182
|
+
|
|
183
|
+
- `threshold?: number` (default `200`)
|
|
184
|
+
- `scrollTop?: number` / `scrollLeft?: number` (default `0` / `0`)
|
|
185
|
+
- `icon?: IconDefinition`
|
|
186
|
+
- `tooltip?: string`
|
|
187
|
+
- `scrollOnClick?: boolean` (default `true`)
|
|
188
|
+
- `onClick?: () => void`
|
|
189
|
+
|
|
103
190
|
## Initial setup example
|
|
104
191
|
|
|
105
192
|
Wrap your app with the providers to enable navigation, React Query integration, auth context, and notifications.
|
|
@@ -183,7 +270,7 @@ export function App() {
|
|
|
183
270
|
|
|
184
271
|
## Offline-first / IndexedDB fallback
|
|
185
272
|
|
|
186
|
-
`IndexedDBClient` is a drop-in offline alternative to `BaseClient`. It exposes the
|
|
273
|
+
`IndexedDBClient` is a drop-in offline alternative to `BaseClient`. It exposes the same method surface (`insert`, `insertMany`, `update`, `get`, `getById`, `export`, `import`, `commonGet`, `softDelete`, `restore`) but stores data locally in the browser's IndexedDB instead of calling a remote API.
|
|
187
274
|
|
|
188
275
|
### When to use it
|
|
189
276
|
|
|
@@ -263,6 +350,15 @@ function useProductsClient() {
|
|
|
263
350
|
|
|
264
351
|
> **Note:** `IndexedDBClient` requires a browser environment. It will not work in SSR/Node contexts.
|
|
265
352
|
|
|
353
|
+
Contract and filtering notes:
|
|
354
|
+
|
|
355
|
+
- Preferred update contract is `update(value)` (aligned with `BaseClient.update(value)`).
|
|
356
|
+
- Legacy `update(id, value)` remains temporarily supported for backward compatibility.
|
|
357
|
+
- Filtering uses strict equality for regular keys.
|
|
358
|
+
- `deletedAt` also supports boolean filtering:
|
|
359
|
+
- `deletedAt: true` => deleted rows (`deletedAt` not null/undefined)
|
|
360
|
+
- `deletedAt: false` => active rows (`deletedAt` null/undefined)
|
|
361
|
+
|
|
266
362
|
## Tests
|
|
267
363
|
|
|
268
364
|
Automated tests are configured with `Vitest` + `@testing-library/react`.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StoryObj } from '@storybook/react';
|
|
2
|
+
declare const meta: {
|
|
3
|
+
title: string;
|
|
4
|
+
component: ({ icon, ...rest }: import('./IconButton').IconButtonPropsLocalType) => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
tags: string[];
|
|
6
|
+
args: {
|
|
7
|
+
icon: import('@fortawesome/fontawesome-common-types').IconDefinition;
|
|
8
|
+
type: "button";
|
|
9
|
+
name: string;
|
|
10
|
+
"aria-label": string;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof meta>;
|
|
15
|
+
export declare const Basic: Story;
|
|
16
|
+
export declare const Outlined: Story;
|
|
17
|
+
export declare const Disabled: Story;
|
|
@@ -1 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
|
|
2
|
+
import { IconButtonPropsLocalType } from './IconButton';
|
|
3
|
+
export type ToTopPropsType = Omit<IconButtonPropsLocalType, "icon" | "onClick"> & {
|
|
4
|
+
icon?: IconDefinition;
|
|
5
|
+
threshold?: number;
|
|
6
|
+
scrollTop?: number;
|
|
7
|
+
scrollLeft?: number;
|
|
8
|
+
tooltip?: string;
|
|
9
|
+
scrollOnClick?: boolean;
|
|
10
|
+
onClick?: () => void;
|
|
11
|
+
};
|
|
12
|
+
export declare const ToTop: (props: ToTopPropsType) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { StoryObj } from '@storybook/react';
|
|
2
2
|
declare const meta: {
|
|
3
3
|
title: string;
|
|
4
|
-
component: () => import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
component: (props: import('./ToTop').ToTopPropsType) => import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
tags: string[];
|
|
6
6
|
};
|
|
7
7
|
export default meta;
|
|
8
8
|
type Story = StoryObj<typeof meta>;
|
|
9
9
|
export declare const Basic: Story;
|
|
10
|
+
export declare const Customized: Story;
|
|
11
|
+
export declare const CustomIcon: Story;
|
|
12
|
+
export declare const WithoutAutoScroll: Story;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { StoryObj } from '@storybook/react';
|
|
2
|
+
declare const meta: {
|
|
3
|
+
title: string;
|
|
4
|
+
component: () => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
tags: string[];
|
|
6
|
+
};
|
|
7
|
+
export default meta;
|
|
8
|
+
type Story = StoryObj<typeof meta>;
|
|
9
|
+
export declare const Basic: Story;
|
|
10
|
+
export declare const InNarrowContainer: Story;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StoryObj } from '@storybook/react';
|
|
2
|
+
declare const meta: {
|
|
3
|
+
title: string;
|
|
4
|
+
component: (props: import('./types').DialogActionsProps) => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
tags: string[];
|
|
6
|
+
args: {
|
|
7
|
+
primaryText: string;
|
|
8
|
+
cancelText: string;
|
|
9
|
+
onPrimaryClick: () => void;
|
|
10
|
+
onCancel: () => void;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof meta>;
|
|
15
|
+
export declare const Basic: Story;
|
|
16
|
+
export declare const Loading: Story;
|
|
17
|
+
export declare const AlignedEnd: Story;
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { StoryObj } from '@storybook/react';
|
|
2
|
-
|
|
2
|
+
type FormDialogStoryProps = {
|
|
3
|
+
title?: string;
|
|
4
|
+
isLoading?: boolean;
|
|
5
|
+
buttonEnd?: boolean;
|
|
6
|
+
};
|
|
3
7
|
declare const meta: {
|
|
4
8
|
title: string;
|
|
5
|
-
component:
|
|
9
|
+
component: ({ title, isLoading, buttonEnd, }: FormDialogStoryProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
10
|
tags: string[];
|
|
7
11
|
args: {
|
|
8
12
|
title: string;
|
|
9
|
-
|
|
13
|
+
isLoading: false;
|
|
14
|
+
buttonEnd: true;
|
|
10
15
|
};
|
|
11
16
|
};
|
|
12
17
|
export default meta;
|
|
13
18
|
type Story = StoryObj<typeof meta>;
|
|
14
19
|
export declare const Basic: Story;
|
|
20
|
+
export declare const Loading: Story;
|
|
21
|
+
export declare const ButtonsAlignedStart: Story;
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import { StoryObj } from '@storybook/react';
|
|
2
|
+
import { ImportPreviewDto } from '../../../lib';
|
|
3
|
+
import { ImportDialogPropsType } from './types';
|
|
4
|
+
type ImportDialogStoryProps = {
|
|
5
|
+
title?: string;
|
|
6
|
+
helperText?: string;
|
|
7
|
+
fileProcessor?: ImportDialogPropsType<ImportPreviewDto>["fileProcessor"];
|
|
8
|
+
renderCustomPreview?: ImportDialogPropsType<ImportPreviewDto>["renderCustomPreview"];
|
|
9
|
+
};
|
|
2
10
|
declare const meta: {
|
|
3
11
|
title: string;
|
|
4
|
-
component:
|
|
12
|
+
component: ({ title, helperText, fileProcessor, renderCustomPreview, }: ImportDialogStoryProps) => import("react/jsx-runtime").JSX.Element;
|
|
5
13
|
tags: string[];
|
|
6
14
|
args: {
|
|
7
15
|
title: string;
|
|
16
|
+
helperText: string;
|
|
8
17
|
};
|
|
9
18
|
};
|
|
10
19
|
export default meta;
|
|
11
20
|
type Story = StoryObj<typeof meta>;
|
|
12
21
|
export declare const Basic: Story;
|
|
22
|
+
export declare const WithAsyncPreview: Story;
|
|
23
|
+
export declare const WithParseError: Story;
|
|
24
|
+
export declare const WithCustomPreview: Story;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
1
2
|
import { ImportPreviewDto } from '../../../lib';
|
|
2
3
|
import { DialogPropsType } from '../..';
|
|
3
4
|
export interface ImportDialogPropsType<EntityDto extends ImportPreviewDto> extends DialogPropsType {
|
|
@@ -7,5 +8,6 @@ export interface ImportDialogPropsType<EntityDto extends ImportPreviewDto> exten
|
|
|
7
8
|
override?: boolean;
|
|
8
9
|
}) => Promise<EntityDto[]>;
|
|
9
10
|
onFileProcessed?: (items: EntityDto[]) => void;
|
|
11
|
+
renderCustomPreview?: (items?: EntityDto[] | null) => ReactNode;
|
|
10
12
|
onOverrideChange?: (override: boolean) => void;
|
|
11
13
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { StoryObj } from '@storybook/react';
|
|
2
|
+
type FormContainerStoryProps = {
|
|
3
|
+
isLoading?: boolean;
|
|
4
|
+
buttonEnd?: boolean;
|
|
5
|
+
};
|
|
6
|
+
declare const meta: {
|
|
7
|
+
title: string;
|
|
8
|
+
component: ({ isLoading, buttonEnd, }: FormContainerStoryProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
tags: string[];
|
|
10
|
+
args: {
|
|
11
|
+
isLoading: false;
|
|
12
|
+
buttonEnd: true;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export default meta;
|
|
16
|
+
type Story = StoryObj<typeof meta>;
|
|
17
|
+
export declare const Basic: Story;
|
|
18
|
+
export declare const Loading: Story;
|
|
19
|
+
export declare const ButtonsAlignedStart: Story;
|
|
@@ -16,7 +16,7 @@ declare const meta: {
|
|
|
16
16
|
control: {
|
|
17
17
|
type: "select";
|
|
18
18
|
};
|
|
19
|
-
options:
|
|
19
|
+
options: State[];
|
|
20
20
|
};
|
|
21
21
|
};
|
|
22
22
|
};
|
|
@@ -24,3 +24,6 @@ export default meta;
|
|
|
24
24
|
type Story = StoryObj<typeof meta>;
|
|
25
25
|
export declare const Basic: Story;
|
|
26
26
|
export declare const ErrorState: Story;
|
|
27
|
+
export declare const GoodState: Story;
|
|
28
|
+
export declare const Disabled: Story;
|
|
29
|
+
export declare const Uncontrolled: Story;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StoryObj } from '@storybook/react';
|
|
2
|
+
declare const meta: {
|
|
3
|
+
title: string;
|
|
4
|
+
component: (props: import('./types').StepPropsType) => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
tags: string[];
|
|
6
|
+
args: {
|
|
7
|
+
title: string;
|
|
8
|
+
body: string;
|
|
9
|
+
onClickNext: () => void;
|
|
10
|
+
final: false;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof meta>;
|
|
15
|
+
export declare const Basic: Story;
|
|
16
|
+
export declare const WithImageAndContent: Story;
|
|
17
|
+
export declare const FinalStep: Story;
|
|
@@ -3,6 +3,17 @@ declare const meta: {
|
|
|
3
3
|
title: string;
|
|
4
4
|
component: <TEntity extends import('../../lib').BaseEntityDto>(props: import('./types').PagePropsType<TEntity>) => import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
tags: string[];
|
|
6
|
+
decorators: ((Story: import('@storybook/core/csf').PartialStoryFn<import('@storybook/react').ReactRenderer, {
|
|
7
|
+
title?: string | undefined;
|
|
8
|
+
children: import('react').ReactNode;
|
|
9
|
+
isLoading?: boolean | undefined;
|
|
10
|
+
addOptions?: import('./types').PageAddOptions<import('../../lib').BaseEntityDto> | undefined;
|
|
11
|
+
filterOptions?: Partial<import('@sito/dashboard').ActionType<import('../../lib').BaseEntityDto>> | undefined;
|
|
12
|
+
isAnimated?: boolean | undefined;
|
|
13
|
+
actions?: import('@sito/dashboard').ActionType<import('../../lib').BaseEntityDto>[] | undefined;
|
|
14
|
+
showBackButton?: boolean | undefined;
|
|
15
|
+
queryKey?: string[] | undefined;
|
|
16
|
+
}>) => import("react/jsx-runtime").JSX.Element)[];
|
|
6
17
|
args: {
|
|
7
18
|
title: string;
|
|
8
19
|
showBackButton: true;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -8,4 +8,10 @@ export type PrettyGridPropsType<TDto extends BaseEntityDto> = {
|
|
|
8
8
|
loading?: boolean;
|
|
9
9
|
className?: string;
|
|
10
10
|
itemClassName?: string;
|
|
11
|
+
hasMore?: boolean;
|
|
12
|
+
loadingMore?: boolean;
|
|
13
|
+
onLoadMore?: () => void | Promise<void>;
|
|
14
|
+
loadMoreComponent?: ReactNode;
|
|
15
|
+
observerRootMargin?: string;
|
|
16
|
+
observerThreshold?: number;
|
|
11
17
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { StoryObj } from '@storybook/react';
|
|
2
|
+
declare const meta: {
|
|
3
|
+
title: string;
|
|
4
|
+
component: (props: import('./types').TabPropsType) => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
tags: string[];
|
|
6
|
+
args: {
|
|
7
|
+
id: string;
|
|
8
|
+
to: string;
|
|
9
|
+
active: true;
|
|
10
|
+
useLinks: true;
|
|
11
|
+
onClick: () => void;
|
|
12
|
+
children: string;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export default meta;
|
|
16
|
+
type Story = StoryObj<typeof meta>;
|
|
17
|
+
export declare const AsLink: Story;
|
|
18
|
+
export declare const AsButton: Story;
|
|
19
|
+
export declare const ToggleExample: Story;
|