@navikt/ds-react 0.16.15 → 0.16.18

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 (46) hide show
  1. package/cjs/button/Button.js +3 -3
  2. package/cjs/form/checkbox/useCheckbox.js +3 -4
  3. package/cjs/table/ColumnHeader.js +58 -0
  4. package/cjs/table/DataCell.js +4 -2
  5. package/cjs/table/HeaderCell.js +4 -2
  6. package/cjs/table/Table.js +4 -2
  7. package/esm/button/Button.d.ts +1 -1
  8. package/esm/button/Button.js +3 -3
  9. package/esm/button/Button.js.map +1 -1
  10. package/esm/form/checkbox/Checkbox.d.ts +1 -1
  11. package/esm/form/checkbox/CheckboxGroup.d.ts +6 -6
  12. package/esm/form/checkbox/CheckboxGroup.js.map +1 -1
  13. package/esm/form/checkbox/useCheckbox.js +3 -4
  14. package/esm/form/checkbox/useCheckbox.js.map +1 -1
  15. package/esm/form/radio/Radio.d.ts +1 -1
  16. package/esm/form/radio/RadioGroup.d.ts +6 -6
  17. package/esm/menu/Menu.js.map +1 -1
  18. package/esm/table/ColumnHeader.d.ts +17 -0
  19. package/esm/table/ColumnHeader.js +35 -0
  20. package/esm/table/ColumnHeader.js.map +1 -0
  21. package/esm/table/DataCell.d.ts +5 -0
  22. package/esm/table/DataCell.js +4 -2
  23. package/esm/table/DataCell.js.map +1 -1
  24. package/esm/table/HeaderCell.d.ts +6 -1
  25. package/esm/table/HeaderCell.js +4 -2
  26. package/esm/table/HeaderCell.js.map +1 -1
  27. package/esm/table/Table.d.ts +16 -0
  28. package/esm/table/Table.js +4 -2
  29. package/esm/table/Table.js.map +1 -1
  30. package/package.json +4 -3
  31. package/src/button/Button.tsx +7 -3
  32. package/src/button/button.stories.tsx +8 -0
  33. package/src/form/checkbox/Checkbox.tsx +1 -1
  34. package/src/form/checkbox/CheckboxGroup.tsx +8 -10
  35. package/src/form/checkbox/useCheckbox.ts +3 -5
  36. package/src/form/radio/Radio.tsx +1 -1
  37. package/src/form/radio/RadioGroup.tsx +6 -6
  38. package/src/menu/Menu.tsx +9 -9
  39. package/src/table/ColumnHeader.tsx +70 -0
  40. package/src/table/DataCell.tsx +11 -3
  41. package/src/table/HeaderCell.tsx +11 -3
  42. package/src/table/Table.tsx +30 -2
  43. package/src/table/stories/people.json +822 -0
  44. package/src/table/stories/table-async.stories.tsx +169 -0
  45. package/src/table/stories/table-hot.stories.tsx +376 -0
  46. package/src/table/stories/table.stories.tsx +35 -2
@@ -23,7 +23,7 @@ export interface CheckboxProps
23
23
  /**
24
24
  * The value of the HTML element.
25
25
  */
26
- value?: string | number | boolean;
26
+ value?: any;
27
27
  /**
28
28
  * Specify whether the Checkbox is in an indeterminate state
29
29
  * @default false
@@ -3,9 +3,9 @@ import cl from "classnames";
3
3
  import { Fieldset, FieldsetProps, FieldsetContext } from "..";
4
4
 
5
5
  export interface CheckboxGroupState {
6
- readonly defaultValue?: ReadonlyArray<string | number | boolean>;
7
- readonly value?: ReadonlyArray<string | number | boolean>;
8
- toggleValue(value: string | number | boolean): void;
6
+ readonly defaultValue?: readonly any[];
7
+ readonly value?: readonly any[];
8
+ toggleValue(value: any): void;
9
9
  }
10
10
 
11
11
  export const CheckboxGroupContext = createContext<CheckboxGroupState | null>(
@@ -24,15 +24,15 @@ export interface CheckboxGroupProps
24
24
  /**
25
25
  * Controlled state for group
26
26
  */
27
- value?: Array<string | number | boolean>;
27
+ value?: any[];
28
28
  /**
29
29
  * Default checked checkboxes on render
30
30
  */
31
- defaultValue?: Array<string | number | boolean>;
31
+ defaultValue?: any[];
32
32
  /**
33
33
  * Returns current checked checkboxes in group
34
34
  */
35
- onChange?: (value: Array<string | number | boolean>) => void;
35
+ onChange?: (value: any[]) => void;
36
36
  }
37
37
 
38
38
  const CheckboxGroup = forwardRef<HTMLFieldSetElement, CheckboxGroupProps>(
@@ -42,11 +42,9 @@ const CheckboxGroup = forwardRef<HTMLFieldSetElement, CheckboxGroupProps>(
42
42
  ) => {
43
43
  const fieldset = useContext(FieldsetContext);
44
44
 
45
- const [state, setState] = useState<Array<string | number | boolean>>(
46
- defaultValue ?? []
47
- );
45
+ const [state, setState] = useState<any[]>(defaultValue ?? []);
48
46
 
49
- const toggleValue = (v: string | number | boolean) => {
47
+ const toggleValue = (v: any) => {
50
48
  const newValue = value ?? state;
51
49
  const newState = newValue.includes(v)
52
50
  ? newValue.filter((x) => x !== v)
@@ -28,21 +28,19 @@ const useCheckbox = ({ children, ...props }: CheckboxProps) => {
28
28
  }
29
29
  }
30
30
 
31
- const value = props.value as string | number | boolean;
32
-
33
31
  return {
34
32
  ...rest,
35
33
  inputProps: {
36
34
  ...inputProps,
37
35
  checked: checkboxGroup?.value
38
- ? checkboxGroup.value.includes(value)
36
+ ? checkboxGroup.value.includes(props.value)
39
37
  : props.checked,
40
38
  defaultChecked: checkboxGroup?.defaultValue
41
- ? checkboxGroup.defaultValue.includes(value)
39
+ ? checkboxGroup.defaultValue.includes(props.value)
42
40
  : props.defaultChecked,
43
41
  onChange: (e) => {
44
42
  props.onChange && props.onChange(e);
45
- checkboxGroup && checkboxGroup.toggleValue(value);
43
+ checkboxGroup && checkboxGroup.toggleValue(props.value);
46
44
  },
47
45
  },
48
46
  };
@@ -14,7 +14,7 @@ export interface RadioProps
14
14
  /**
15
15
  * The value of the HTML element
16
16
  */
17
- value: string | number | boolean;
17
+ value: any;
18
18
  }
19
19
 
20
20
  const Radio = forwardRef<HTMLInputElement, RadioProps>((props, ref) => {
@@ -5,9 +5,9 @@ import { useId } from "../..";
5
5
 
6
6
  export interface RadioGroupContextProps {
7
7
  name: string;
8
- defaultValue?: string | number | boolean;
9
- value?: string | number | boolean;
10
- onChange: (value: string | number | boolean) => void;
8
+ defaultValue?: any;
9
+ value?: any;
10
+ onChange: (value: any) => void;
11
11
  required?: boolean;
12
12
  }
13
13
 
@@ -31,15 +31,15 @@ export interface RadioGroupProps
31
31
  /**
32
32
  * Default checked radiobutton
33
33
  */
34
- defaultValue?: string | number | boolean;
34
+ defaultValue?: any;
35
35
  /**
36
36
  * Controlled state for Radiobutton
37
37
  */
38
- value?: string | number | boolean;
38
+ value?: any;
39
39
  /**
40
40
  * Returns current checked radiobutton in group
41
41
  */
42
- onChange?: (value: string | number | boolean) => void;
42
+ onChange?: (value: any) => void;
43
43
  /**
44
44
  * Tells Fieldset if group is required
45
45
  */
package/src/menu/Menu.tsx CHANGED
@@ -19,15 +19,15 @@ interface MenuComponent
19
19
 
20
20
  const Menu = forwardRef<HTMLElement, MenuProps>(
21
21
  ({ children, className, ...rest }, ref) => (
22
- <nav
23
- {...rest}
24
- role="navigation"
25
- ref={ref}
26
- className={cl("navds-menu", className)}
27
- >
28
- <MenuItems>{children}</MenuItems>
29
- </nav>
30
- )
22
+ <nav
23
+ {...rest}
24
+ role="navigation"
25
+ ref={ref}
26
+ className={cl("navds-menu", className)}
27
+ >
28
+ <MenuItems>{children}</MenuItems>
29
+ </nav>
30
+ )
31
31
  ) as MenuComponent;
32
32
 
33
33
  Menu.Collapse = Collapse;
@@ -0,0 +1,70 @@
1
+ import React, { forwardRef, useContext } from "react";
2
+ import { Down, Up } from "@navikt/ds-icons";
3
+ import { TableContext } from "..";
4
+ import HeaderCell, { HeaderCellProps } from "./HeaderCell";
5
+
6
+ interface ColumnHeaderProps extends HeaderCellProps {
7
+ /**
8
+ * Key to sort by
9
+ */
10
+ sortKey?: string;
11
+ /**
12
+ * Column is sortable
13
+ * @default false
14
+ */
15
+ sortable?: boolean;
16
+ }
17
+
18
+ export interface ColumnHeaderType
19
+ extends React.ForwardRefExoticComponent<
20
+ ColumnHeaderProps & React.RefAttributes<HTMLTableCellElement>
21
+ > {}
22
+
23
+ const ColumnHeader: ColumnHeaderType = forwardRef(
24
+ ({ className, children, sortable = false, sortKey, ...rest }, ref) => {
25
+ const context = useContext(TableContext);
26
+
27
+ if (sortable && !sortKey) {
28
+ console.warn("ColumnHeader with `sortable=true` must have a sortKey.");
29
+ }
30
+
31
+ return (
32
+ <HeaderCell
33
+ scope="col"
34
+ ref={ref}
35
+ className={className}
36
+ aria-sort={
37
+ sortable
38
+ ? context?.sort?.orderBy === sortKey
39
+ ? context?.sort?.direction
40
+ : "none"
41
+ : undefined
42
+ }
43
+ {...rest}
44
+ >
45
+ {sortable ? (
46
+ <button
47
+ className="navds-table__sort-button"
48
+ onClick={
49
+ sortable && sortKey
50
+ ? () => context?.onSortChange?.(sortKey)
51
+ : undefined
52
+ }
53
+ >
54
+ {children}
55
+ {context?.sort?.orderBy === sortKey &&
56
+ context?.sort?.direction === "descending" ? (
57
+ <Down aria-label="sorter synkende" />
58
+ ) : (
59
+ <Up aria-label="sorter stigende" />
60
+ )}
61
+ </button>
62
+ ) : (
63
+ children
64
+ )}
65
+ </HeaderCell>
66
+ );
67
+ }
68
+ );
69
+
70
+ export default ColumnHeader;
@@ -3,7 +3,13 @@ import cl from "classnames";
3
3
  import { BodyShort } from "..";
4
4
  import { TableContext } from ".";
5
5
 
6
- interface DataCellProps extends React.TdHTMLAttributes<HTMLTableCellElement> {}
6
+ interface DataCellProps extends React.TdHTMLAttributes<HTMLTableCellElement> {
7
+ /**
8
+ * Content alignment
9
+ * @default "left"
10
+ */
11
+ align?: "left" | "center" | "right";
12
+ }
7
13
 
8
14
  export interface DataCellType
9
15
  extends React.ForwardRefExoticComponent<
@@ -11,14 +17,16 @@ export interface DataCellType
11
17
  > {}
12
18
 
13
19
  const DataCell: DataCellType = forwardRef(
14
- ({ className, children = "", ...rest }, ref) => {
20
+ ({ className, children = "", align, ...rest }, ref) => {
15
21
  const context = useContext(TableContext);
16
22
 
17
23
  return (
18
24
  <BodyShort
19
25
  as="td"
20
26
  ref={ref}
21
- className={cl("navds-table__data-cell", className)}
27
+ className={cl("navds-table__data-cell", className, {
28
+ [`navds-table__data-cell--align-${align}`]: align,
29
+ })}
22
30
  size={context?.size}
23
31
  {...rest}
24
32
  >
@@ -2,8 +2,14 @@ import React, { forwardRef, useContext } from "react";
2
2
  import cl from "classnames";
3
3
  import { Label, TableContext } from "..";
4
4
 
5
- interface HeaderCellProps extends React.ThHTMLAttributes<HTMLTableCellElement> {
5
+ export interface HeaderCellProps
6
+ extends React.ThHTMLAttributes<HTMLTableCellElement> {
6
7
  scope?: string;
8
+ /**
9
+ * Content alignment
10
+ * @default "left"
11
+ */
12
+ align?: "left" | "center" | "right";
7
13
  }
8
14
 
9
15
  export interface HeaderCellType
@@ -12,14 +18,16 @@ export interface HeaderCellType
12
18
  > {}
13
19
 
14
20
  const HeaderCell: HeaderCellType = forwardRef(
15
- ({ className, children, ...rest }, ref) => {
21
+ ({ className, children, align, ...rest }, ref) => {
16
22
  const context = useContext(TableContext);
17
23
 
18
24
  return (
19
25
  <Label
20
26
  as="th"
21
27
  ref={ref}
22
- className={cl("navds-table__header-cell", className)}
28
+ className={cl("navds-table__header-cell", className, {
29
+ [`navds-table__header-cell--align-${align}`]: align,
30
+ })}
23
31
  size={context?.size}
24
32
  {...rest}
25
33
  >
@@ -3,9 +3,15 @@ import cl from "classnames";
3
3
  import Header, { HeaderType } from "./Header";
4
4
  import Body, { BodyType } from "./Body";
5
5
  import Row, { RowType } from "./Row";
6
+ import ColumnHeader, { ColumnHeaderType } from "./ColumnHeader";
6
7
  import HeaderCell, { HeaderCellType } from "./HeaderCell";
7
8
  import DataCell, { DataCellType } from "./DataCell";
8
9
 
10
+ export interface SortState {
11
+ orderBy: string;
12
+ direction: "ascending" | "descending";
13
+ }
14
+
9
15
  export interface TableProps
10
16
  extends React.TableHTMLAttributes<HTMLTableElement> {
11
17
  /**
@@ -18,6 +24,14 @@ export interface TableProps
18
24
  * @default false
19
25
  */
20
26
  zebraStripes?: boolean;
27
+ /**
28
+ * Sort state
29
+ */
30
+ sort?: SortState;
31
+ /**
32
+ * Callback whens sort state changes
33
+ */
34
+ onSortChange?: (sortKey?: string) => void;
21
35
  }
22
36
 
23
37
  export interface TableType
@@ -29,17 +43,30 @@ export interface TableType
29
43
  Row: RowType;
30
44
  DataCell: DataCellType;
31
45
  HeaderCell: HeaderCellType;
46
+ ColumnHeader: ColumnHeaderType;
32
47
  }
33
48
 
34
49
  export interface TableContextProps {
35
50
  size: "medium" | "small";
51
+ onSortChange?: (sortKey: string) => void;
52
+ sort?: SortState;
36
53
  }
37
54
 
38
55
  export const TableContext = createContext<TableContextProps | null>(null);
39
56
 
40
57
  const Table = forwardRef(
41
- ({ className, zebraStripes = false, size = "medium", ...rest }, ref) => (
42
- <TableContext.Provider value={{ size }}>
58
+ (
59
+ {
60
+ className,
61
+ zebraStripes = false,
62
+ size = "medium",
63
+ onSortChange,
64
+ sort,
65
+ ...rest
66
+ },
67
+ ref
68
+ ) => (
69
+ <TableContext.Provider value={{ size, onSortChange, sort }}>
43
70
  <table
44
71
  {...rest}
45
72
  ref={ref}
@@ -54,6 +81,7 @@ const Table = forwardRef(
54
81
  Table.Header = Header;
55
82
  Table.Body = Body;
56
83
  Table.Row = Row;
84
+ Table.ColumnHeader = ColumnHeader;
57
85
  Table.HeaderCell = HeaderCell;
58
86
  Table.DataCell = DataCell;
59
87