@sito/dashboard-app 0.0.46 → 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 (35) hide show
  1. package/README.md +125 -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 +10 -1
  19. package/dist/components/Onboarding/Onboarding.test.d.ts +1 -0
  20. package/dist/components/Onboarding/Step.stories.d.ts +17 -0
  21. package/dist/components/Onboarding/types.d.ts +9 -4
  22. package/dist/components/Page/Page.stories.d.ts +11 -0
  23. package/dist/components/PrettyGrid/PrettyGrid.stories.d.ts +2 -0
  24. package/dist/components/PrettyGrid/PrettyGrid.test.d.ts +1 -0
  25. package/dist/components/PrettyGrid/types.d.ts +6 -0
  26. package/dist/components/TabsLayout/Tab.stories.d.ts +19 -0
  27. package/dist/components/TabsLayout/TabsLayout.stories.d.ts +1 -0
  28. package/dist/components/TabsLayout/types.d.ts +2 -0
  29. package/dist/dashboard-app.cjs +1 -1
  30. package/dist/dashboard-app.js +1202 -1107
  31. package/dist/hooks/dialogs/types.d.ts +1 -0
  32. package/dist/hooks/dialogs/useImportDialog.test.d.ts +1 -0
  33. package/dist/lib/api/IndexedDBClient.d.ts +3 -0
  34. package/dist/main.css +1 -1
  35. 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`
@@ -73,6 +73,120 @@ import { TabsLayout } from "@sito/dashboard-app";
73
73
 
74
74
  `tabButtonProps` lets you customize each tab button style/behavior (except `onClick` and `children`, which are controlled by `TabsLayout`).
75
75
 
76
+ ### Onboarding
77
+
78
+ `Onboarding` accepts structured steps instead of translation keys. Each step provides required `title` and `body`, plus optional `content`, `image`, and `alt`.
79
+ Step copy is provided by the consumer app, so any i18n for the step itself should be resolved before rendering `Onboarding`.
80
+
81
+ ```tsx
82
+ import { Onboarding } from "@sito/dashboard-app";
83
+
84
+ <Onboarding
85
+ steps={[
86
+ {
87
+ title: "Welcome",
88
+ body: "This flow explains the main features.",
89
+ },
90
+ {
91
+ title: "Almost done",
92
+ body: "Add custom content when a step needs extra UI.",
93
+ content: <MyStepContent />,
94
+ image: "/images/setup.png",
95
+ alt: "Setup preview",
96
+ },
97
+ ]}
98
+ />
99
+ ```
100
+
101
+ The action buttons still use the package's internal accessibility/button translation keys.
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
+
76
190
  ## Initial setup example
77
191
 
78
192
  Wrap your app with the providers to enable navigation, React Query integration, auth context, and notifications.
@@ -156,7 +270,7 @@ export function App() {
156
270
 
157
271
  ## Offline-first / IndexedDB fallback
158
272
 
159
- `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.
160
274
 
161
275
  ### When to use it
162
276
 
@@ -236,6 +350,15 @@ function useProductsClient() {
236
350
 
237
351
  > **Note:** `IndexedDBClient` requires a browser environment. It will not work in SSR/Node contexts.
238
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
+
239
362
  ## Tests
240
363
 
241
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;
@@ -4,9 +4,18 @@ declare const meta: {
4
4
  component: (props: import('./types').OnboardingPropsType) => import("react/jsx-runtime").JSX.Element;
5
5
  tags: string[];
6
6
  args: {
7
- steps: string[];
7
+ steps: ({
8
+ title: string;
9
+ body: string;
10
+ content?: undefined;
11
+ } | {
12
+ title: string;
13
+ body: string;
14
+ content: import("react/jsx-runtime").JSX.Element;
15
+ })[];
8
16
  };
9
17
  };
10
18
  export default meta;
11
19
  type Story = StoryObj<typeof meta>;
12
20
  export declare const Basic: Story;
21
+ export declare const WithStepImages: Story;
@@ -0,0 +1 @@
1
+ export {};
@@ -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;
@@ -1,10 +1,15 @@
1
- export type StepPropsType = {
2
- translation: string;
3
- onClickNext: () => void;
1
+ import { ReactNode } from 'react';
2
+ export type OnboardingStepType = {
3
+ title: ReactNode;
4
+ body: ReactNode;
5
+ content?: ReactNode;
4
6
  image?: string;
5
7
  alt?: string;
8
+ };
9
+ export type StepPropsType = OnboardingStepType & {
10
+ onClickNext: () => void;
6
11
  final?: boolean;
7
12
  };
8
13
  export type OnboardingPropsType = {
9
- steps: string[];
14
+ steps: OnboardingStepType[];
10
15
  };
@@ -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;
@@ -4,6 +4,8 @@ export type TabButtonPropsType = Omit<ButtonPropsType, "children" | "onClick" |
4
4
  export type TabsLayoutPropsType = {
5
5
  tabs: TabsType[];
6
6
  defaultTab?: number;
7
+ currentTab?: number;
8
+ onTabChange?: (id: number | string) => void;
7
9
  className?: string;
8
10
  tabsContainerClassName?: string;
9
11
  useLinks?: boolean;