@pautena/react-design-system 0.1.4 → 0.3.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.
Files changed (61) hide show
  1. package/dist/cjs/index.js +13 -4
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/types/components/value-displays/index.d.ts +1 -0
  4. package/dist/cjs/types/components/value-displays/value-datetime/index.d.ts +1 -0
  5. package/dist/cjs/types/components/value-displays/value-datetime/value-datetime.d.ts +18 -0
  6. package/dist/cjs/types/generators/generators.mock.d.ts +9 -5
  7. package/dist/cjs/types/generators/generators.model.d.ts +25 -1
  8. package/dist/cjs/types/generators/model-router/index.d.ts +1 -0
  9. package/dist/cjs/types/generators/model-router/screens/add-screen.d.ts +1 -1
  10. package/dist/cjs/types/generators/model-router/screens/list-screen.d.ts +1 -1
  11. package/dist/cjs/types/generators/model-router/screens/screens.types.d.ts +20 -0
  12. package/dist/cjs/types/generators/model-router/screens/update-screen.d.ts +1 -1
  13. package/dist/cjs/types/index.d.ts +1 -0
  14. package/dist/esm/index.js +13 -4
  15. package/dist/esm/index.js.map +1 -1
  16. package/dist/esm/types/components/value-displays/index.d.ts +1 -0
  17. package/dist/esm/types/components/value-displays/value-datetime/index.d.ts +1 -0
  18. package/dist/esm/types/components/value-displays/value-datetime/value-datetime.d.ts +18 -0
  19. package/dist/esm/types/generators/generators.mock.d.ts +9 -5
  20. package/dist/esm/types/generators/generators.model.d.ts +25 -1
  21. package/dist/esm/types/generators/model-router/index.d.ts +1 -0
  22. package/dist/esm/types/generators/model-router/screens/add-screen.d.ts +1 -1
  23. package/dist/esm/types/generators/model-router/screens/list-screen.d.ts +1 -1
  24. package/dist/esm/types/generators/model-router/screens/screens.types.d.ts +20 -0
  25. package/dist/esm/types/generators/model-router/screens/update-screen.d.ts +1 -1
  26. package/dist/esm/types/index.d.ts +1 -0
  27. package/dist/index.d.ts +98 -4
  28. package/package.json +6 -2
  29. package/src/components/header/header.test.tsx +2 -12
  30. package/src/components/tab/tab-card/tab-card.tsx +2 -2
  31. package/src/components/table-list/table-list.test.tsx +8 -1
  32. package/src/components/table-list/table-list.tsx +3 -3
  33. package/src/components/value-displays/index.ts +1 -0
  34. package/src/components/value-displays/value-datetime/index.ts +1 -0
  35. package/src/components/value-displays/value-datetime/value-datetime.stories.tsx +21 -0
  36. package/src/components/value-displays/value-datetime/value-datetime.test.tsx +23 -0
  37. package/src/components/value-displays/value-datetime/value-datetime.tsx +40 -0
  38. package/src/components/value-displays/value-text/{value-test.test.tsx → value-text.test.tsx} +0 -0
  39. package/src/generators/generators.mock.ts +56 -17
  40. package/src/generators/generators.model.ts +39 -1
  41. package/src/generators/model-form/model-form.stories.tsx +2 -2
  42. package/src/generators/model-form/model-form.test.tsx +39 -22
  43. package/src/generators/model-form/model-form.tsx +220 -33
  44. package/src/generators/model-router/index.ts +1 -0
  45. package/src/generators/model-router/model-router.test.tsx +264 -57
  46. package/src/generators/model-router/model-router.tsx +4 -3
  47. package/src/generators/model-router/screens/add-screen.tsx +2 -1
  48. package/src/generators/model-router/screens/list-screen.tsx +41 -26
  49. package/src/generators/model-router/screens/screens.types.ts +25 -0
  50. package/src/generators/model-router/screens/update-screen.tsx +2 -1
  51. package/src/generators/model-router/stories/list-screen.stories.tsx +51 -0
  52. package/src/generators/model-router/stories/model-router.stories.tsx +66 -3
  53. package/src/generators/object-details/object-details.tsx +5 -4
  54. package/src/index.ts +1 -0
  55. package/src/layouts/app-bar-with-drawer-layout/app-bar-with-drawer-layout.stories.tsx +1 -1
  56. package/src/layouts/app-bar-with-drawer-layout/app-bar-with-drawer-layout.tsx +1 -1
  57. package/src/storybook.tsx +10 -0
  58. package/src/tests/actions.ts +43 -0
  59. package/src/tests/assertions.ts +70 -1
  60. package/src/tests/index.ts +1 -0
  61. package/src/tests/testing-library.tsx +5 -1
@@ -1,4 +1,5 @@
1
1
  export * from "./value-text";
2
2
  export * from "./value-card";
3
3
  export * from "./value-boolean";
4
+ export * from "./value-datetime";
4
5
  export * from "./group-value-card";
@@ -0,0 +1 @@
1
+ export * from "./value-datetime";
@@ -0,0 +1,18 @@
1
+ export interface ValueDatetimeProps {
2
+ /**
3
+ * Name of the displayed value
4
+ */
5
+ label: string;
6
+ /**
7
+ * Value displayed
8
+ */
9
+ value: Date;
10
+ /**
11
+ * Datetime format
12
+ */
13
+ format: string;
14
+ }
15
+ /**
16
+ * Displays a formated datetime with a label
17
+ */
18
+ export declare const ValueDatetime: ({ label, value, format: fmt }: ValueDatetimeProps) => JSX.Element;
@@ -1,4 +1,7 @@
1
- import { Model } from "./generators.model";
1
+ import { BasicModelInstance, Model } from "./generators.model";
2
+ export declare const BirthDateFormat = "dd/MM/yyyy";
3
+ export declare const ReturnTimeFormat = "HH:mm";
4
+ export declare const TradeDateFormat = "dd/MM/yyyy HH:mm";
2
5
  export declare const mockModel: Model;
3
6
  export interface MockInstance {
4
7
  id: string;
@@ -7,18 +10,19 @@ export interface MockInstance {
7
10
  lastName: string;
8
11
  gender: string;
9
12
  age: number;
10
- birthDate: string;
13
+ birthDate: Date;
11
14
  car: {
12
15
  model: string;
13
16
  manufacturer: string;
14
17
  color: string;
15
- type: string;
18
+ type: string[];
16
19
  vin: string;
17
20
  vrm: string;
21
+ returnTime: Date;
18
22
  };
19
23
  quantity: number;
20
24
  available: boolean;
21
25
  currency: string;
22
- tradeDate: string;
26
+ tradeDate: Date;
23
27
  }
24
- export declare const createModelInstance: <T extends BasicData>(model: Model, seed?: number) => T;
28
+ export declare const createModelInstance: <T extends BasicModelInstance>(model: Model, seed?: number) => T;
@@ -20,7 +20,30 @@ declare type NumberField = {
20
20
  declare type BooleanField = {
21
21
  type: "boolean";
22
22
  };
23
- declare type SingleFields = StringField | NumberField | BooleanField;
23
+ declare type EnumField = {
24
+ type: "enum";
25
+ value: string[];
26
+ };
27
+ declare type MultiEnumField = {
28
+ type: "multienum";
29
+ value: string[];
30
+ };
31
+ declare type DateField = {
32
+ type: "date";
33
+ format: string;
34
+ default: any;
35
+ };
36
+ declare type TimeField = {
37
+ type: "time";
38
+ format: string;
39
+ default: any;
40
+ };
41
+ declare type DatetimeField = {
42
+ type: "datetime";
43
+ format: string;
44
+ default: any;
45
+ };
46
+ declare type SingleFields = StringField | NumberField | BooleanField | EnumField | MultiEnumField | DateField | TimeField | DatetimeField;
24
47
  export declare type GroupField = {
25
48
  type: "group";
26
49
  value: (Base & Breakpoints & SingleFields)[];
@@ -34,4 +57,5 @@ export interface BasicModelInstance {
34
57
  id: string;
35
58
  [key: string]: any;
36
59
  }
60
+ export declare type ModelFieldTypes = "string" | "number" | "boolean" | "enum" | "multienum";
37
61
  export {};
@@ -1 +1,2 @@
1
1
  export * from "./model-router";
2
+ export * from "./model-router.types";
@@ -13,4 +13,4 @@ export interface AddScreenProps<T extends BasicModelInstance> extends BaseScreen
13
13
  */
14
14
  newItemRequest: RequestState;
15
15
  }
16
- export declare const AddScreen: <T extends BasicModelInstance>({ model, modelName, onSubmitNewItem, newItemRequest, }: AddScreenProps<T>) => JSX.Element;
16
+ export declare const AddScreen: <T extends BasicModelInstance>({ model, modelName, basePath, onSubmitNewItem, newItemRequest, }: AddScreenProps<T>) => JSX.Element;
@@ -27,4 +27,4 @@ export interface ListScreenProps<T extends BasicModelInstance> extends BaseScree
27
27
  */
28
28
  deleteRequest: RequestState;
29
29
  }
30
- export declare const ListScreen: <T extends BasicModelInstance>({ model, modelName, listData, onRequestList, onClickDeleteItem, listRequest, deleteRequest, }: ListScreenProps<T>) => JSX.Element;
30
+ export declare const ListScreen: <T extends BasicModelInstance>({ model, modelName, listData, listRequest, deleteRequest, basePath, deleteFeature, updateFeature, addFeature, detailsFeature, onRequestList, onClickDeleteItem, }: ListScreenProps<T>) => JSX.Element;
@@ -8,4 +8,24 @@ export interface BaseScreenProps {
8
8
  * Structure that represents the fields of the model
9
9
  */
10
10
  model: Model;
11
+ /**
12
+ * Path to attach before each internal ModelRouter path
13
+ */
14
+ basePath?: string;
15
+ /**
16
+ * If true delete features are enabled
17
+ */
18
+ deleteFeature?: boolean;
19
+ /**
20
+ * If true update features are enabled
21
+ */
22
+ updateFeature?: boolean;
23
+ /**
24
+ * If true add features are enabled
25
+ */
26
+ addFeature?: boolean;
27
+ /**
28
+ * If true details features are enabled
29
+ */
30
+ detailsFeature?: boolean;
11
31
  }
@@ -26,4 +26,4 @@ export interface UpdateScreenProps<T extends BasicModelInstance> extends BaseScr
26
26
  */
27
27
  updateItem?: T;
28
28
  }
29
- export declare const UpdateScreen: <T extends BasicModelInstance>({ model, modelName, submitUpdateItemRequest, updateItemRequest, updateItem, onSubmitUpdateItem, onRequestUpdateItem, }: UpdateScreenProps<T>) => JSX.Element;
29
+ export declare const UpdateScreen: <T extends BasicModelInstance>({ model, modelName, basePath, submitUpdateItemRequest, updateItemRequest, updateItem, onSubmitUpdateItem, onRequestUpdateItem, }: UpdateScreenProps<T>) => JSX.Element;
@@ -2,3 +2,4 @@ export * from "./components";
2
2
  export * from "./utils";
3
3
  export * from "./layouts";
4
4
  export * from "./generators";
5
+ export * from "./providers";
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  /// <reference types="react" />
2
2
  import * as _mui_material from '@mui/material';
3
- import { PropTypes, LinkProps as LinkProps$1, AppBarProps as AppBarProps$1, DrawerProps as DrawerProps$1, SxProps, Theme, GridProps, Color } from '@mui/material';
3
+ import { PropTypes, LinkProps as LinkProps$1, AppBarProps as AppBarProps$1, DrawerProps as DrawerProps$1, SxProps, Theme, GridProps, Color, AlertColor } from '@mui/material';
4
4
  import * as React from 'react';
5
- import React__default, { FunctionComponent, ReactElement, PropsWithChildren, ReactNode } from 'react';
5
+ import React__default, { FunctionComponent, ReactElement, PropsWithChildren, ReactNode, Dispatch, SetStateAction } from 'react';
6
6
  import * as _mui_material_OverridableComponent from '@mui/material/OverridableComponent';
7
7
  import { LinkProps } from 'react-router-dom';
8
8
  import * as _emotion_styled from '@emotion/styled';
@@ -418,6 +418,25 @@ interface ValueBooleanProps {
418
418
  */
419
419
  declare const ValueBoolean: ({ label, value }: ValueBooleanProps) => JSX.Element;
420
420
 
421
+ interface ValueDatetimeProps {
422
+ /**
423
+ * Name of the displayed value
424
+ */
425
+ label: string;
426
+ /**
427
+ * Value displayed
428
+ */
429
+ value: Date;
430
+ /**
431
+ * Datetime format
432
+ */
433
+ format: string;
434
+ }
435
+ /**
436
+ * Displays a formated datetime with a label
437
+ */
438
+ declare const ValueDatetime: ({ label, value, format: fmt }: ValueDatetimeProps) => JSX.Element;
439
+
421
440
  declare type GroupValueItemProps = PropsWithChildren<Omit<GridProps, "item" | "container">>;
422
441
  declare type GroupValueItemComponent = FunctionComponent<GroupValueItemProps>;
423
442
  declare type GroupValueItemElement = ReactElement<GroupValueItemProps, GroupValueItemComponent>;
@@ -482,7 +501,30 @@ declare type NumberField = {
482
501
  declare type BooleanField = {
483
502
  type: "boolean";
484
503
  };
485
- declare type SingleFields = StringField | NumberField | BooleanField;
504
+ declare type EnumField = {
505
+ type: "enum";
506
+ value: string[];
507
+ };
508
+ declare type MultiEnumField = {
509
+ type: "multienum";
510
+ value: string[];
511
+ };
512
+ declare type DateField = {
513
+ type: "date";
514
+ format: string;
515
+ default: any;
516
+ };
517
+ declare type TimeField = {
518
+ type: "time";
519
+ format: string;
520
+ default: any;
521
+ };
522
+ declare type DatetimeField = {
523
+ type: "datetime";
524
+ format: string;
525
+ default: any;
526
+ };
527
+ declare type SingleFields = StringField | NumberField | BooleanField | EnumField | MultiEnumField | DateField | TimeField | DatetimeField;
486
528
  declare type GroupField = {
487
529
  type: "group";
488
530
  value: (Base & Breakpoints & SingleFields)[];
@@ -496,6 +538,7 @@ interface BasicModelInstance {
496
538
  id: string;
497
539
  [key: string]: any;
498
540
  }
541
+ declare type ModelFieldTypes = "string" | "number" | "boolean" | "enum" | "multienum";
499
542
 
500
543
  interface ObjectDetailsProps<T extends BasicModelInstance> {
501
544
  model: Model;
@@ -509,6 +552,8 @@ interface RequestState {
509
552
  error?: string;
510
553
  success?: boolean;
511
554
  }
555
+ declare const IdleRequest: RequestState;
556
+ declare const LoadingRequest: RequestState;
512
557
 
513
558
  interface BaseScreenProps {
514
559
  /**
@@ -519,6 +564,26 @@ interface BaseScreenProps {
519
564
  * Structure that represents the fields of the model
520
565
  */
521
566
  model: Model;
567
+ /**
568
+ * Path to attach before each internal ModelRouter path
569
+ */
570
+ basePath?: string;
571
+ /**
572
+ * If true delete features are enabled
573
+ */
574
+ deleteFeature?: boolean;
575
+ /**
576
+ * If true update features are enabled
577
+ */
578
+ updateFeature?: boolean;
579
+ /**
580
+ * If true add features are enabled
581
+ */
582
+ addFeature?: boolean;
583
+ /**
584
+ * If true details features are enabled
585
+ */
586
+ detailsFeature?: boolean;
522
587
  }
523
588
 
524
589
  interface UpdateScreenProps<T extends BasicModelInstance$1> extends BaseScreenProps {
@@ -615,4 +680,33 @@ interface ModelFormProps<T extends BasicModelInstance> {
615
680
  }
616
681
  declare const ModelForm: <T extends BasicModelInstance>({ model, saveButtonText, onSubmit, initialValues, }: ModelFormProps<T>) => JSX.Element;
617
682
 
618
- export { AppBarComponent, AppBarElement, AppBarProfile, AppBarProps, AppBarWithDrawerLayout, AppBarWithDrawerLayoutProps, BasicModelInstance, Bullet, BulletProps, BulletVariant, CenterContainer, CenterContainerProps, Content, ContentComponent, ContentElement, ContentProps, Drawer, DrawerComponent, DrawerContent, DrawerContentComponent, DrawerContentElement, DrawerContentProps, DrawerContext, DrawerContextProps, DrawerElement, DrawerItem, DrawerItemProps, DrawerProps, DrawerProvider, DrawerSection, DrawerSectionProps, EnhancedRemoteTable, EnhancedTable, EnhancedTableHead, GroupField, GroupValueCard, GroupValueCardProps, GroupValueItem, GroupValueItemComponent, GroupValueItemElement, GroupValueItemProps, HeadCell, Header, HeaderAction, HeaderActionVariant, HeaderBreadcrumb, HeaderComponent, HeaderElement, HeaderLayout, HeaderPreset, HeaderProps, HeaderTab, Label, LabelProps, LabelVariant, Link, LinkBehaviour, MiniAppBar, MiniDrawer, Model, ModelField, ModelForm, ModelFormProps, ModelRouter, ModelRouterProps, Nav, NavItem, NavItemAvatar, NavItemBullet, NavItemLabel, NavSection, ObjectDetails, ObjectDetailsProps, Order, Placeholder, PlaceholderAction, PlaceholderIconArgs, PlaceholderProps, QueryContainer, QueryContainerError, QueryContainerProps, QueryContainerSuccess, SignIn, TabCard, TabPanel, TableList, TableListProps, TableRowOption, UndefinedProvider, ValueBoolean, ValueBooleanProps, ValueCard, ValueCardProps, ValueText, ValueTextProps, bulletClasses, getRandomItem, groupValueItemClasses, labelClasses, newArrayWithSize, useDrawer, useGetDefaultThemeColor };
683
+ declare type NotificationCenterProviderProps = PropsWithChildren<{
684
+ autoHideDuration?: number;
685
+ }>;
686
+ declare const NotificationCenterProvider: ({ children, autoHideDuration, }: NotificationCenterProviderProps) => JSX.Element;
687
+
688
+ declare const NotificationCenterProviderUndefinedError: Error;
689
+ declare type SnackbarContentType = React__default.ReactElement<any, any> | ((key: string) => React__default.ReactElement<any, any>);
690
+ declare type SnackbarActionType = React__default.ReactNode | ((key: string) => React__default.ReactNode);
691
+ interface Notification {
692
+ severity: AlertColor;
693
+ title?: string;
694
+ message: string;
695
+ }
696
+ interface NotificationCenterProps {
697
+ show(notification: Notification): void;
698
+ hide(): void;
699
+ }
700
+ declare const NotificationCenterContext: React__default.Context<NotificationCenterProps | undefined>;
701
+ declare const useNotificationCenter: () => NotificationCenterProps;
702
+
703
+ declare const TabContext: React.Context<[number, Dispatch<SetStateAction<number>>]>;
704
+ declare const TabContextProvider: React.Provider<[number, Dispatch<SetStateAction<number>>]>;
705
+ declare const useTab: () => [number, Dispatch<SetStateAction<number>>];
706
+
707
+ declare type TabProviderProps = PropsWithChildren<{
708
+ initialValue?: number;
709
+ }>;
710
+ declare const TabProvider: ({ children, initialValue }: TabProviderProps) => JSX.Element;
711
+
712
+ export { AppBarComponent, AppBarElement, AppBarProfile, AppBarProps, AppBarWithDrawerLayout, AppBarWithDrawerLayoutProps, BasicModelInstance, Bullet, BulletProps, BulletVariant, CenterContainer, CenterContainerProps, Content, ContentComponent, ContentElement, ContentProps, Drawer, DrawerComponent, DrawerContent, DrawerContentComponent, DrawerContentElement, DrawerContentProps, DrawerContext, DrawerContextProps, DrawerElement, DrawerItem, DrawerItemProps, DrawerProps, DrawerProvider, DrawerSection, DrawerSectionProps, EnhancedRemoteTable, EnhancedTable, EnhancedTableHead, GroupField, GroupValueCard, GroupValueCardProps, GroupValueItem, GroupValueItemComponent, GroupValueItemElement, GroupValueItemProps, HeadCell, Header, HeaderAction, HeaderActionVariant, HeaderBreadcrumb, HeaderComponent, HeaderElement, HeaderLayout, HeaderPreset, HeaderProps, HeaderTab, IdleRequest, Label, LabelProps, LabelVariant, Link, LinkBehaviour, LoadingRequest, MiniAppBar, MiniDrawer, Model, ModelField, ModelFieldTypes, ModelForm, ModelFormProps, ModelRouter, ModelRouterProps, Nav, NavItem, NavItemAvatar, NavItemBullet, NavItemLabel, NavSection, Notification, NotificationCenterContext, NotificationCenterProps, NotificationCenterProvider, NotificationCenterProviderProps, NotificationCenterProviderUndefinedError, ObjectDetails, ObjectDetailsProps, Order, Placeholder, PlaceholderAction, PlaceholderIconArgs, PlaceholderProps, QueryContainer, QueryContainerError, QueryContainerProps, QueryContainerSuccess, RequestState, SignIn, SnackbarActionType, SnackbarContentType, TabCard, TabContext, TabContextProvider, TabPanel, TabProvider, TableList, TableListProps, TableRowOption, UndefinedProvider, ValueBoolean, ValueBooleanProps, ValueCard, ValueCardProps, ValueDatetime, ValueDatetimeProps, ValueText, ValueTextProps, bulletClasses, getRandomItem, groupValueItemClasses, labelClasses, newArrayWithSize, useDrawer, useGetDefaultThemeColor, useNotificationCenter, useTab };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pautena/react-design-system",
3
- "version": "0.1.4",
3
+ "version": "0.3.0",
4
4
  "description": "My custom design system on top of MUI",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -35,11 +35,14 @@
35
35
  "@mui/lab": "^5.0.0-alpha.90",
36
36
  "@mui/material": "^5.9.0",
37
37
  "@mui/x-data-grid": "^5.13.0",
38
+ "@mui/x-date-pickers": "^5.0.0-beta.7",
39
+ "date-fns": "^2.29.2",
38
40
  "react": "^18.2.0",
39
41
  "react-dom": "^18.2.0",
40
42
  "react-router-dom": "^6.3.0"
41
43
  },
42
44
  "devDependencies": {
45
+ "@date-io/date-fns": "^2.15.0",
43
46
  "@babel/core": "^7.18.6",
44
47
  "@babel/preset-env": "^7.18.6",
45
48
  "@babel/preset-react": "^7.18.6",
@@ -99,7 +102,8 @@
99
102
  "@types/react": "^17.0.0 || ^18.0.0",
100
103
  "react": "^17.0.0 || ^18.0.0",
101
104
  "react-dom": "^17.0.0 || ^18.0.0",
102
- "react-router-dom": "^6.0.0"
105
+ "react-router-dom": "^6.0.0",
106
+ "date-fns": "^2.0.0"
103
107
  },
104
108
  "repository": {
105
109
  "type": "git",
@@ -33,8 +33,6 @@ function renderInstance({
33
33
  tabs?: HeaderTab[];
34
34
  selectedTab?: number;
35
35
  }) {
36
- const onChangeTab = jest.fn();
37
-
38
36
  const instance = render(
39
37
  <TabProvider initialValue={selectedTab}>
40
38
  <Header
@@ -49,7 +47,7 @@ function renderInstance({
49
47
  </TabProvider>,
50
48
  );
51
49
 
52
- return { ...instance, onChangeTab };
50
+ return { ...instance };
53
51
  }
54
52
 
55
53
  describe("Header", () => {
@@ -149,7 +147,7 @@ describe("Header", () => {
149
147
  });
150
148
 
151
149
  it("would change the selected tab when a tab is clicked", async () => {
152
- const { onChangeTab } = renderInstance({ tabs, selectedTab: 0 });
150
+ renderInstance({ tabs, selectedTab: 0 });
153
151
 
154
152
  await userEvent.click(screen.getByRole("tab", { name: /tab 3/i }));
155
153
 
@@ -157,13 +155,5 @@ describe("Header", () => {
157
155
  expect(screen.getByRole("tab", { name: /tab 2/i, selected: false })).toBeInTheDocument();
158
156
  expect(screen.getByRole("tab", { name: /tab 3/i, selected: true })).toBeInTheDocument();
159
157
  });
160
-
161
- it("wouldn't call onChangeTab when the clicked tab is the selectedTab", async () => {
162
- const { onChangeTab } = renderInstance({ tabs, selectedTab: 2 });
163
-
164
- await userEvent.click(screen.getByRole("tab", { name: /tab 3/i }));
165
-
166
- expect(onChangeTab).not.toHaveBeenCalled();
167
- });
168
158
  });
169
159
  });
@@ -1,6 +1,6 @@
1
1
  import { Paper, Tabs, Tab, styled, tabsClasses } from "@mui/material";
2
- import React, { PropsWithChildren, useState } from "react";
3
- import { TabProvider, useTab } from "~/providers";
2
+ import React, { PropsWithChildren } from "react";
3
+ import { useTab } from "~/providers";
4
4
 
5
5
  const StyledTabs = styled(Tabs)(({ theme }) => ({
6
6
  [`&.${tabsClasses.root}`]: {
@@ -76,13 +76,14 @@ describe("TableList", () => {
76
76
  defaultSort = "value",
77
77
  loading = false,
78
78
  options = undefined,
79
+ onClick = jest.fn(),
79
80
  }: {
80
81
  defaultSort?: string;
81
82
  loading?: boolean;
82
83
  search?: boolean;
83
84
  options?: TableRowOption<any>[];
85
+ onClick?: jest.Mock;
84
86
  } = {}) => {
85
- const onClick = jest.fn();
86
87
  const instance = render(
87
88
  <TableList
88
89
  search={search}
@@ -221,6 +222,12 @@ describe("TableList", () => {
221
222
  expect(onClick).toHaveBeenCalledWith(data[2]);
222
223
  });
223
224
 
225
+ it("would continue working if onClick is not defined and we click a row", async () => {
226
+ renderInstance({ onClick: undefined });
227
+
228
+ await userEvents.click(screen.getByRole("row", { name: /item 3/i }));
229
+ });
230
+
224
231
  describe("options menu", () => {
225
232
  it("would render a button to open the menu if doesn't have options", () => {
226
233
  renderInstance({ options: undefined });
@@ -27,7 +27,7 @@ export const TableList = <T extends BasicModelInstance>({
27
27
  columns: columnsProp,
28
28
  options,
29
29
  data,
30
- onClick = () => null,
30
+ onClick,
31
31
  search,
32
32
  defaultSort,
33
33
  defaultOrder,
@@ -62,10 +62,10 @@ export const TableList = <T extends BasicModelInstance>({
62
62
  return (
63
63
  <TableRow
64
64
  key={row.id}
65
- onClick={() => onClick(row)}
65
+ onClick={() => onClick && onClick(row)}
66
66
  role="row"
67
67
  aria-rowindex={i}
68
- sx={{ cursor: "pointer" }}
68
+ sx={{ cursor: onClick && "pointer" }}
69
69
  >
70
70
  {columns.map(({ id }, j) => (
71
71
  <TableCell role="cell" scope="row" key={id} aria-rowindex={i} aria-colindex={j}>
@@ -1,4 +1,5 @@
1
1
  export * from "./value-text";
2
2
  export * from "./value-card";
3
3
  export * from "./value-boolean";
4
+ export * from "./value-datetime";
4
5
  export * from "./group-value-card";
@@ -0,0 +1 @@
1
+ export * from "./value-datetime";
@@ -0,0 +1,21 @@
1
+ import { ComponentMeta } from "@storybook/react";
2
+ import { ValueDatetime } from "./value-datetime";
3
+ import { createTemplate, withContainer } from "../../../storybook";
4
+
5
+ export default {
6
+ title: "Value displays/ValueDate",
7
+ component: ValueDatetime,
8
+ decorators: [withContainer({ width: 200 })],
9
+ parameters: {
10
+ layout: "centered",
11
+ },
12
+ } as ComponentMeta<typeof ValueDatetime>;
13
+
14
+ const Template = createTemplate(ValueDatetime);
15
+
16
+ export const Default = Template.bind({});
17
+ Default.args = {
18
+ label: "Lorem",
19
+ value: new Date(2022, 8, 22),
20
+ format: "yyyy/MM/dd",
21
+ };
@@ -0,0 +1,23 @@
1
+ import React from "react";
2
+ import { render, screen } from "../../../tests";
3
+ import { ValueDatetime } from "./value-datetime";
4
+
5
+ describe("ValueDatetime", () => {
6
+ const renderComponent = () => {
7
+ return render(
8
+ <ValueDatetime label="Hello world" value={new Date(2022, 7, 10)} format="dd-MM-yyyy" />,
9
+ );
10
+ };
11
+
12
+ it("would render the label", () => {
13
+ renderComponent();
14
+
15
+ expect(screen.getByRole("label", { name: /hello world/i })).toBeInTheDocument();
16
+ });
17
+
18
+ it("would render the value", () => {
19
+ renderComponent();
20
+
21
+ expect(screen.getByText(/10-08-2022/i)).toBeInTheDocument();
22
+ });
23
+ });
@@ -0,0 +1,40 @@
1
+ import { Box, Tooltip, Typography } from "@mui/material";
2
+ import React from "react";
3
+ import { format } from "date-fns";
4
+
5
+ export interface ValueDatetimeProps {
6
+ /**
7
+ * Name of the displayed value
8
+ */
9
+ label: string;
10
+ /**
11
+ * Value displayed
12
+ */
13
+ value: Date;
14
+
15
+ /**
16
+ * Datetime format
17
+ */
18
+ format: string;
19
+ }
20
+
21
+ /**
22
+ * Displays a formated datetime with a label
23
+ */
24
+ export const ValueDatetime = ({ label, value, format: fmt }: ValueDatetimeProps) => {
25
+ const id = `label-${label.replace(/ /g, "-")}`;
26
+ const formatedValue = format(value, fmt);
27
+
28
+ return (
29
+ <Box>
30
+ <Typography variant="subtitle2" role="label" id={id}>
31
+ {label}
32
+ </Typography>
33
+ <Tooltip title={formatedValue} placement="top" enterDelay={2000}>
34
+ <Typography variant="h5" noWrap aria-labelledby={id}>
35
+ {formatedValue}
36
+ </Typography>
37
+ </Tooltip>
38
+ </Box>
39
+ );
40
+ };