@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.
Files changed (32) hide show
  1. package/README.md +98 -2
  2. package/dist/components/Buttons/IconButton.stories.d.ts +17 -0
  3. package/dist/components/Buttons/ToTop.d.ts +12 -1
  4. package/dist/components/Buttons/ToTop.stories.d.ts +4 -1
  5. package/dist/components/Buttons/ToTop.test.d.ts +1 -0
  6. package/dist/components/Clock/Clock.stories.d.ts +10 -0
  7. package/dist/components/Dialog/ConfirmationDialog.stories.d.ts +1 -0
  8. package/dist/components/Dialog/DialogActions.stories.d.ts +17 -0
  9. package/dist/components/Dialog/FormDialog.stories.d.ts +10 -3
  10. package/dist/components/Dialog/ImportDialog/ImportDialog.stories.d.ts +13 -1
  11. package/dist/components/Dialog/ImportDialog/ImportDialog.test.d.ts +1 -0
  12. package/dist/components/Dialog/ImportDialog/types.d.ts +2 -0
  13. package/dist/components/Empty/Empty.stories.d.ts +2 -0
  14. package/dist/components/Form/FormContainer.stories.d.ts +19 -0
  15. package/dist/components/Form/ParagraphInput.stories.d.ts +4 -1
  16. package/dist/components/Loading/SplashScreen.stories.d.ts +1 -0
  17. package/dist/components/Notification/Notification.stories.d.ts +1 -0
  18. package/dist/components/Onboarding/Onboarding.stories.d.ts +1 -0
  19. package/dist/components/Onboarding/Step.stories.d.ts +17 -0
  20. package/dist/components/Page/Page.stories.d.ts +11 -0
  21. package/dist/components/PrettyGrid/PrettyGrid.stories.d.ts +2 -0
  22. package/dist/components/PrettyGrid/PrettyGrid.test.d.ts +1 -0
  23. package/dist/components/PrettyGrid/types.d.ts +6 -0
  24. package/dist/components/TabsLayout/Tab.stories.d.ts +19 -0
  25. package/dist/components/TabsLayout/TabsLayout.stories.d.ts +1 -0
  26. package/dist/dashboard-app.cjs +1 -1
  27. package/dist/dashboard-app.js +1549 -1469
  28. package/dist/hooks/dialogs/types.d.ts +1 -0
  29. package/dist/hooks/dialogs/useImportDialog.test.d.ts +1 -0
  30. package/dist/lib/api/IndexedDBClient.d.ts +4 -1
  31. package/dist/main.css +1 -1
  32. 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 exact 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.
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
- export declare const ToTop: () => import("react/jsx-runtime").JSX.Element;
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;
@@ -10,3 +10,4 @@ declare const meta: {
10
10
  export default meta;
11
11
  type Story = StoryObj<typeof meta>;
12
12
  export declare const Basic: Story;
13
+ export declare const Loading: 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
- import { FieldValues } from 'react-hook-form';
2
+ type FormDialogStoryProps = {
3
+ title?: string;
4
+ isLoading?: boolean;
5
+ buttonEnd?: boolean;
6
+ };
3
7
  declare const meta: {
4
8
  title: string;
5
- component: <TInput extends FieldValues>(props: import('./types').FormDialogPropsType<TInput>) => import("react/jsx-runtime").JSX.Element;
9
+ component: ({ title, isLoading, buttonEnd, }: FormDialogStoryProps) => import("react/jsx-runtime").JSX.Element;
6
10
  tags: string[];
7
11
  args: {
8
12
  title: string;
9
- open: true;
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: <EntityDto extends import('../../../lib').ImportPreviewDto>(props: import('./types').ImportDialogPropsType<EntityDto>) => import("react/jsx-runtime").JSX.Element;
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;
@@ -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
  }
@@ -12,3 +12,5 @@ export default meta;
12
12
  type Story = StoryObj<typeof meta>;
13
13
  export declare const Basic: Story;
14
14
  export declare const CustomMessage: Story;
15
+ export declare const WithAction: Story;
16
+ export declare const WithIcon: Story;
@@ -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: string[];
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;
@@ -8,3 +8,4 @@ declare const meta: {
8
8
  export default meta;
9
9
  type Story = StoryObj<typeof meta>;
10
10
  export declare const Basic: Story;
11
+ export declare const CustomSizeAndColor: Story;
@@ -8,3 +8,4 @@ declare const meta: {
8
8
  export default meta;
9
9
  type Story = StoryObj<typeof meta>;
10
10
  export declare const Basic: Story;
11
+ export declare const StackAndDismiss: Story;
@@ -18,3 +18,4 @@ declare const meta: {
18
18
  export default meta;
19
19
  type Story = StoryObj<typeof meta>;
20
20
  export declare const Basic: Story;
21
+ export declare const WithStepImages: 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;
@@ -16,3 +16,5 @@ export default meta;
16
16
  type Story = StoryObj<typeof meta>;
17
17
  export declare const Basic: Story;
18
18
  export declare const Empty: Story;
19
+ export declare const Loading: Story;
20
+ export declare const InfiniteScroll: Story;
@@ -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;
@@ -16,3 +16,4 @@ type Story = StoryObj<typeof meta>;
16
16
  export declare const Basic: Story;
17
17
  export declare const WithoutLinks: Story;
18
18
  export declare const WithCustomTabButton: Story;
19
+ export declare const Controlled: Story;