@sito/dashboard-app 0.0.47 → 0.0.49
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 +195 -27
- 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/components/index.d.ts +1 -1
- package/dist/dashboard-app.cjs +1 -1
- package/dist/dashboard-app.js +1655 -1487
- 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 +6 -7
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ pnpm add @sito/dashboard-app
|
|
|
14
14
|
|
|
15
15
|
## Requirements
|
|
16
16
|
|
|
17
|
-
- Node.js `
|
|
17
|
+
- Node.js `20.x` (see `.nvmrc`)
|
|
18
18
|
- React `18.3.1`
|
|
19
19
|
- React DOM `18.3.1`
|
|
20
20
|
- `@tanstack/react-query` `5.83.0`
|
|
@@ -22,14 +22,30 @@ pnpm add @sito/dashboard-app
|
|
|
22
22
|
- `@sito/dashboard` `^0.0.68`
|
|
23
23
|
- Font Awesome + Emotion peers defined in `package.json`
|
|
24
24
|
|
|
25
|
+
Install all peers in consumer apps:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install \
|
|
29
|
+
react@18.3.1 react-dom@18.3.1 \
|
|
30
|
+
@sito/dashboard@^0.0.68 \
|
|
31
|
+
@emotion/css@11.13.5 \
|
|
32
|
+
@tanstack/react-query@5.83.0 \
|
|
33
|
+
react-hook-form@7.61.1 \
|
|
34
|
+
@fortawesome/fontawesome-svg-core@7.0.0 \
|
|
35
|
+
@fortawesome/free-solid-svg-icons@7.0.0 \
|
|
36
|
+
@fortawesome/free-regular-svg-icons@7.0.0 \
|
|
37
|
+
@fortawesome/free-brands-svg-icons@7.0.0 \
|
|
38
|
+
@fortawesome/react-fontawesome@0.2.3
|
|
39
|
+
```
|
|
40
|
+
|
|
25
41
|
## Core exports
|
|
26
42
|
|
|
27
|
-
- Layout and navigation: `Page`, `Navbar`, `Drawer`, `TabsLayout`, `PrettyGrid`
|
|
43
|
+
- Layout and navigation: `Page`, `Navbar`, `Drawer`, `TabsLayout`, `PrettyGrid`, `ToTop`
|
|
28
44
|
- Actions and menus: `Actions`, `Action`, `Dropdown`, button components
|
|
29
45
|
- Dialogs and forms: `Dialog`, `FormDialog`, `ImportDialog`, form inputs
|
|
30
46
|
- Feedback: `Notification`, `Loading`, `Empty`, `Error`, `Onboarding`
|
|
31
47
|
- Hooks: `useImportDialog`, `useDeleteDialog`, `usePostForm`, `useDeleteAction`, `useNavbar`, and more — all action hooks ship with default `sticky`, `multiple`, `id`, `icon`, and `tooltip` values so only `onClick` is required
|
|
32
|
-
- Providers and utilities: `ConfigProvider`, `ManagerProvider`, `AuthProvider`, `NotificationProvider`, `NavbarProvider`, DTOs, API clients
|
|
48
|
+
- Providers and utilities: `ConfigProvider`, `ManagerProvider`, `AuthProvider`, `NotificationProvider`, `DrawerMenuProvider`, `NavbarProvider`, DTOs, API clients
|
|
33
49
|
|
|
34
50
|
## Component usage patterns
|
|
35
51
|
|
|
@@ -68,7 +84,7 @@ import { TabsLayout } from "@sito/dashboard-app";
|
|
|
68
84
|
useLinks={false}
|
|
69
85
|
tabButtonProps={{ variant: "outlined", color: "secondary" }}
|
|
70
86
|
tabs={tabs}
|
|
71
|
-
|
|
87
|
+
/>;
|
|
72
88
|
```
|
|
73
89
|
|
|
74
90
|
`tabButtonProps` lets you customize each tab button style/behavior (except `onClick` and `children`, which are controlled by `TabsLayout`).
|
|
@@ -95,44 +111,170 @@ import { Onboarding } from "@sito/dashboard-app";
|
|
|
95
111
|
alt: "Setup preview",
|
|
96
112
|
},
|
|
97
113
|
]}
|
|
98
|
-
|
|
114
|
+
/>;
|
|
99
115
|
```
|
|
100
116
|
|
|
101
117
|
The action buttons still use the package's internal accessibility/button translation keys.
|
|
102
118
|
|
|
119
|
+
### ImportDialog custom preview
|
|
120
|
+
|
|
121
|
+
`ImportDialog` supports optional custom preview rendering via `renderCustomPreview`.
|
|
122
|
+
If provided, it receives current parsed `previewItems` and replaces the default JSON preview.
|
|
123
|
+
If omitted, the default preview remains unchanged.
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
import { ImportDialog } from "@sito/dashboard-app";
|
|
127
|
+
|
|
128
|
+
<ImportDialog<ProductImportPreviewDto>
|
|
129
|
+
open={open}
|
|
130
|
+
title="Import products"
|
|
131
|
+
handleClose={close}
|
|
132
|
+
handleSubmit={submit}
|
|
133
|
+
fileProcessor={parseFile}
|
|
134
|
+
renderCustomPreview={(items) => <ProductsPreviewTable items={items ?? []} />}
|
|
135
|
+
/>;
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`useImportDialog` also accepts and forwards `renderCustomPreview`:
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
import { useImportDialog } from "@sito/dashboard-app";
|
|
142
|
+
|
|
143
|
+
const importDialog = useImportDialog<ProductDto, ProductImportPreviewDto>({
|
|
144
|
+
queryKey: ["products"],
|
|
145
|
+
entity: "products",
|
|
146
|
+
mutationFn: api.products.import,
|
|
147
|
+
fileProcessor: parseFile,
|
|
148
|
+
renderCustomPreview: (items) => <ProductsPreviewTable items={items ?? []} />,
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### PrettyGrid infinite scroll
|
|
153
|
+
|
|
154
|
+
`PrettyGrid` supports optional infinite loading with `IntersectionObserver`.
|
|
155
|
+
Current usage without infinite props keeps the same behavior.
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
import { PrettyGrid, Loading } from "@sito/dashboard-app";
|
|
159
|
+
|
|
160
|
+
<PrettyGrid<ProductDto>
|
|
161
|
+
data={products}
|
|
162
|
+
loading={isLoading}
|
|
163
|
+
renderComponent={(item) => <ProductCard item={item} />}
|
|
164
|
+
hasMore={hasMore}
|
|
165
|
+
loadingMore={isFetchingNextPage}
|
|
166
|
+
onLoadMore={fetchNextPage}
|
|
167
|
+
loadMoreComponent={<Loading className="!w-auto" loaderClass="w-5 h-5" />}
|
|
168
|
+
/>;
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Defaults:
|
|
172
|
+
|
|
173
|
+
- `hasMore = false`
|
|
174
|
+
- `loadingMore = false`
|
|
175
|
+
- `loadMoreComponent = null`
|
|
176
|
+
- `observerRootMargin = "0px 0px 200px 0px"`
|
|
177
|
+
- `observerThreshold = 0`
|
|
178
|
+
|
|
179
|
+
### ToTop customization
|
|
180
|
+
|
|
181
|
+
`ToTop` is now customizable while preserving current defaults.
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
import { ToTop } from "@sito/dashboard-app";
|
|
185
|
+
|
|
186
|
+
<ToTop
|
|
187
|
+
threshold={120}
|
|
188
|
+
tooltip="Back to top"
|
|
189
|
+
variant="outlined"
|
|
190
|
+
color="secondary"
|
|
191
|
+
className="right-8 bottom-8"
|
|
192
|
+
scrollTop={0}
|
|
193
|
+
scrollLeft={0}
|
|
194
|
+
/>;
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Main optional props:
|
|
198
|
+
|
|
199
|
+
- `threshold?: number` (default `200`)
|
|
200
|
+
- `scrollTop?: number` / `scrollLeft?: number` (default `0` / `0`)
|
|
201
|
+
- `icon?: IconDefinition`
|
|
202
|
+
- `tooltip?: string`
|
|
203
|
+
- `scrollOnClick?: boolean` (default `true`)
|
|
204
|
+
- `onClick?: () => void`
|
|
205
|
+
|
|
103
206
|
## Initial setup example
|
|
104
207
|
|
|
105
|
-
Wrap your app with
|
|
208
|
+
Wrap your app with providers in this order to enable routing integration, React Query, auth, notifications, and drawer/navbar state.
|
|
106
209
|
|
|
107
210
|
```tsx
|
|
108
211
|
import type { ReactNode } from "react";
|
|
109
|
-
import {
|
|
212
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
213
|
+
import {
|
|
214
|
+
BrowserRouter,
|
|
215
|
+
Link,
|
|
216
|
+
useLocation,
|
|
217
|
+
useNavigate,
|
|
218
|
+
} from "react-router-dom";
|
|
110
219
|
import {
|
|
111
220
|
AuthProvider,
|
|
112
221
|
ConfigProvider,
|
|
222
|
+
DrawerMenuProvider,
|
|
113
223
|
IManager,
|
|
114
224
|
ManagerProvider,
|
|
225
|
+
NavbarProvider,
|
|
115
226
|
NotificationProvider,
|
|
116
227
|
} from "@sito/dashboard-app";
|
|
117
228
|
|
|
118
|
-
const
|
|
229
|
+
const queryClient = new QueryClient();
|
|
230
|
+
|
|
231
|
+
const authStorageKeys = {
|
|
232
|
+
user: "user",
|
|
233
|
+
remember: "remember",
|
|
234
|
+
refreshTokenKey: "refreshToken",
|
|
235
|
+
accessTokenExpiresAtKey: "accessTokenExpiresAt",
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const manager = new IManager(
|
|
239
|
+
import.meta.env.VITE_API_URL,
|
|
240
|
+
authStorageKeys.user,
|
|
241
|
+
{
|
|
242
|
+
rememberKey: authStorageKeys.remember,
|
|
243
|
+
refreshTokenKey: authStorageKeys.refreshTokenKey,
|
|
244
|
+
accessTokenExpiresAtKey: authStorageKeys.accessTokenExpiresAtKey,
|
|
245
|
+
},
|
|
246
|
+
);
|
|
119
247
|
|
|
120
248
|
function AppProviders({ children }: { children: ReactNode }) {
|
|
121
249
|
const go = useNavigate();
|
|
122
250
|
const location = useLocation();
|
|
123
251
|
|
|
124
252
|
return (
|
|
125
|
-
<
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
253
|
+
<QueryClientProvider client={queryClient}>
|
|
254
|
+
<ConfigProvider
|
|
255
|
+
location={location}
|
|
256
|
+
navigate={(route) => {
|
|
257
|
+
if (typeof route === "number") go(route);
|
|
258
|
+
else go(route);
|
|
259
|
+
}}
|
|
260
|
+
linkComponent={Link}
|
|
261
|
+
>
|
|
262
|
+
<ManagerProvider manager={manager}>
|
|
263
|
+
<AuthProvider
|
|
264
|
+
user={authStorageKeys.user}
|
|
265
|
+
remember={authStorageKeys.remember}
|
|
266
|
+
refreshTokenKey={authStorageKeys.refreshTokenKey}
|
|
267
|
+
accessTokenExpiresAtKey={authStorageKeys.accessTokenExpiresAtKey}
|
|
268
|
+
>
|
|
269
|
+
<NotificationProvider>
|
|
270
|
+
<DrawerMenuProvider>
|
|
271
|
+
<NavbarProvider>{children}</NavbarProvider>
|
|
272
|
+
</DrawerMenuProvider>
|
|
273
|
+
</NotificationProvider>
|
|
274
|
+
</AuthProvider>
|
|
275
|
+
</ManagerProvider>
|
|
276
|
+
</ConfigProvider>
|
|
277
|
+
</QueryClientProvider>
|
|
136
278
|
);
|
|
137
279
|
}
|
|
138
280
|
|
|
@@ -145,6 +287,21 @@ export function App() {
|
|
|
145
287
|
}
|
|
146
288
|
```
|
|
147
289
|
|
|
290
|
+
Notes:
|
|
291
|
+
|
|
292
|
+
- Keep `ManagerProvider` above `AuthProvider`.
|
|
293
|
+
- `NavbarProvider` is required when using `Navbar` or `useNavbar`; otherwise it can be omitted.
|
|
294
|
+
- If you customize auth storage keys in `AuthProvider`, pass the same keys to `IManager`/`BaseClient` auth config.
|
|
295
|
+
|
|
296
|
+
## Built-in auth refresh behavior
|
|
297
|
+
|
|
298
|
+
`APIClient` and `BaseClient` already include refresh/retry behavior for secured requests:
|
|
299
|
+
|
|
300
|
+
- If `accessTokenExpiresAt` is close to expiry, a refresh runs before sending the request.
|
|
301
|
+
- If a secured request returns `401`, the client attempts one refresh and retries once.
|
|
302
|
+
- Concurrent refresh calls are deduplicated with a shared in-flight promise.
|
|
303
|
+
- If refresh fails, local session keys are cleared (`user`, `remember`, `refreshToken`, `accessTokenExpiresAt`).
|
|
304
|
+
|
|
148
305
|
## Local development (step-by-step)
|
|
149
306
|
|
|
150
307
|
1. Clone the repository:
|
|
@@ -183,7 +340,7 @@ export function App() {
|
|
|
183
340
|
|
|
184
341
|
## Offline-first / IndexedDB fallback
|
|
185
342
|
|
|
186
|
-
`IndexedDBClient` is a drop-in offline alternative to `BaseClient`. It exposes the
|
|
343
|
+
`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
344
|
|
|
188
345
|
### When to use it
|
|
189
346
|
|
|
@@ -224,9 +381,9 @@ interface ProductFilterDto extends BaseFilterDto {
|
|
|
224
381
|
class ProductsIndexedDBClient extends IndexedDBClient<
|
|
225
382
|
"products",
|
|
226
383
|
ProductDto,
|
|
227
|
-
ProductDto,
|
|
384
|
+
ProductDto, // TCommonDto
|
|
228
385
|
Omit<ProductDto, "id" | "createdAt" | "updatedAt" | "deletedAt">,
|
|
229
|
-
ProductDto,
|
|
386
|
+
ProductDto, // TUpdateDto (extends DeleteDto via BaseEntityDto)
|
|
230
387
|
ProductFilterDto,
|
|
231
388
|
ImportPreviewDto
|
|
232
389
|
> {
|
|
@@ -242,17 +399,19 @@ class ProductsIndexedDBClient extends IndexedDBClient<
|
|
|
242
399
|
import { useState, useEffect } from "react";
|
|
243
400
|
|
|
244
401
|
function useProductsClient() {
|
|
245
|
-
const [client, setClient] = useState(
|
|
246
|
-
|
|
402
|
+
const [client, setClient] = useState(() =>
|
|
403
|
+
navigator.onLine
|
|
404
|
+
? new ProductsClient(apiUrl)
|
|
405
|
+
: new ProductsIndexedDBClient(),
|
|
247
406
|
);
|
|
248
407
|
|
|
249
408
|
useEffect(() => {
|
|
250
|
-
const goOnline
|
|
409
|
+
const goOnline = () => setClient(new ProductsClient(apiUrl));
|
|
251
410
|
const goOffline = () => setClient(new ProductsIndexedDBClient());
|
|
252
|
-
window.addEventListener("online",
|
|
411
|
+
window.addEventListener("online", goOnline);
|
|
253
412
|
window.addEventListener("offline", goOffline);
|
|
254
413
|
return () => {
|
|
255
|
-
window.removeEventListener("online",
|
|
414
|
+
window.removeEventListener("online", goOnline);
|
|
256
415
|
window.removeEventListener("offline", goOffline);
|
|
257
416
|
};
|
|
258
417
|
}, []);
|
|
@@ -263,6 +422,15 @@ function useProductsClient() {
|
|
|
263
422
|
|
|
264
423
|
> **Note:** `IndexedDBClient` requires a browser environment. It will not work in SSR/Node contexts.
|
|
265
424
|
|
|
425
|
+
Contract and filtering notes:
|
|
426
|
+
|
|
427
|
+
- Preferred update contract is `update(value)` (aligned with `BaseClient.update(value)`).
|
|
428
|
+
- Legacy `update(id, value)` remains temporarily supported for backward compatibility.
|
|
429
|
+
- Filtering uses strict equality for regular keys.
|
|
430
|
+
- `deletedAt` also supports boolean filtering:
|
|
431
|
+
- `deletedAt: true` => deleted rows (`deletedAt` not null/undefined)
|
|
432
|
+
- `deletedAt: false` => active rows (`deletedAt` null/undefined)
|
|
433
|
+
|
|
266
434
|
## Tests
|
|
267
435
|
|
|
268
436
|
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;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Action, Actions, ActionsDropdown } from '@sito/dashboard';
|
|
2
|
-
export type { ActionPropsType, ActionsContainerPropsType } from '@sito/dashboard';
|
|
2
|
+
export type { ActionPropsType, ActionsContainerPropsType, } from '@sito/dashboard';
|
|
3
3
|
export * from './Form';
|
|
4
4
|
export * from './Dialog';
|
|
5
5
|
export * from './Drawer';
|