@sphereon/ui-components.ssi-react 0.1.3-next.119 → 0.1.3-next.124

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.
@@ -2,9 +2,10 @@ import { FC, MouseEventHandler } from 'react';
2
2
  import { ButtonIcon } from '@sphereon/ui-components.core';
3
3
  type Props = {
4
4
  icon: ButtonIcon;
5
+ caption?: string;
5
6
  onClick: MouseEventHandler;
6
7
  disabled?: boolean;
7
- color?: string;
8
+ iconColor?: string;
8
9
  };
9
10
  declare const SSIIconButton: FC<Props>;
10
11
  export default SSIIconButton;
@@ -1,14 +1,14 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ButtonIcon, fontColors } from '@sphereon/ui-components.core';
3
3
  import SSIAddIcon from '../../assets/icons/SSIAddIcon';
4
4
  import SSIFilterIcon from '../../assets/icons/SSIFilterIcon';
5
5
  import SSIArrowDownIcon from '../../assets/icons/SSIArrowDownIcon';
6
- import { SSIIconButtonContainerStyled as Container } from '../../../styles';
6
+ import { SSIIconButtonContainerStyled as Container, SSITextH3Styled as Caption } from '../../../styles';
7
7
  import MeatBallsIcon from '../../assets/icons/MeatBallsIcon';
8
8
  import DeleteIcon from '../../assets/icons/DeleteIcon';
9
9
  const SSIIconButton = (props) => {
10
- const { icon, onClick, disabled = false, color = fontColors.dark } = props;
11
- return _jsx(Container, { onClick: onClick, children: getIcon(icon, color) });
10
+ const { caption, icon, onClick, disabled = false, iconColor = fontColors.dark } = props;
11
+ return _jsxs(Container, { onClick: onClick, children: [getIcon(icon, iconColor), caption && _jsx(Caption, { children: caption })] });
12
12
  };
13
13
  const getIcon = (icon, color) => {
14
14
  switch (icon) {
@@ -19,7 +19,7 @@ const getIcon = (icon, color) => {
19
19
  case ButtonIcon.MEATBALLS:
20
20
  return _jsx(MeatBallsIcon, { color: color });
21
21
  case ButtonIcon.DELETE:
22
- return _jsx(DeleteIcon, { color: color });
22
+ return _jsx(DeleteIcon, { color: color, width: 15, height: 16 });
23
23
  case ButtonIcon.FILTER:
24
24
  return _jsx(SSIFilterIcon, { color: color });
25
25
  default:
@@ -1,6 +1,6 @@
1
1
  import { FC } from 'react';
2
- import { Button } from '../../../types';
3
2
  import { ButtonIcon } from '@sphereon/ui-components.core';
3
+ import { Button } from '../../../types';
4
4
  export type Props = {
5
5
  icon: ButtonIcon;
6
6
  buttons: Array<Button>;
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState, useRef, useEffect } from 'react';
3
- import { DropDownListContainerStyled as Container, DropDownContainerStyled as DropDownContainer, DropDownListButtonStyled as ListButton, } from '../../../styles/components';
4
- import DropDownListItem from '../DropDownListItem';
5
- import { SSIIconButton } from '../../../index';
6
3
  import { borderColors } from '@sphereon/ui-components.core';
4
+ import DropDownListItem from '../DropDownListItem';
5
+ import SSIIconButton from '../../buttons/SSIIconButton';
6
+ import { DropDownListContainerStyled as Container, DropDownContainerStyled as DropDownContainer, DropDownListButtonStyled as ListButton, } from '../../../styles/components';
7
7
  const DropDownList = (props) => {
8
8
  const { icon, buttons, showBorder = false } = props;
9
9
  const [showActionsMenu, setShowActionsMenu] = useState(false);
@@ -4,6 +4,7 @@ type Props = {
4
4
  enableFiltering?: boolean;
5
5
  enableMostRecent?: boolean;
6
6
  actions?: Array<Button>;
7
+ onDelete?: () => Promise<void>;
7
8
  };
8
9
  declare const SSITableViewHeader: React.FC<Props>;
9
10
  export default SSITableViewHeader;
@@ -1,10 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { ButtonIcon, Localization } from '@sphereon/ui-components.core';
2
+ import { ButtonIcon, Localization, statusColors } from '@sphereon/ui-components.core';
3
3
  import SSIIconButton from '../../../buttons/SSIIconButton';
4
4
  import SSIPrimaryButton from '../../../buttons/SSIPrimaryButton';
5
- import { SSITableViewHeaderActionsContainerStyled as ActionsContainer, SSITableViewHeaderContainerStyled as Container, SSITableViewHeaderContentContainerStyled as ContentContainer, SSITextH3Styled as FilterCaption, SSITableViewHeaderFilterContainerStyled as FilterContainer, } from '../../../../styles';
5
+ import { SSITableViewHeaderActionsContainerStyled as ActionsContainer, SSITableViewHeaderContainerStyled as Container, SSITableViewHeaderContentContainerStyled as ContentContainer, SSITextH3Styled as FilterCaption, SSITableViewHeaderFilterContainerStyled as FilterContainer, TableViewHeaderStaticActionsContainerStyled as StaticActionsContainer } from '../../../../styles';
6
6
  const SSITableViewHeader = (props) => {
7
- const { enableFiltering = false, enableMostRecent = false, actions = [] } = props;
8
- return (_jsx(Container, { children: _jsx(ContentContainer, { children: _jsxs(ActionsContainer, { children: [enableFiltering && (_jsxs(FilterContainer, { children: [_jsx(SSIIconButton, { icon: ButtonIcon.FILTER, onClick: async () => console.log('add filter clicked') }), _jsx(FilterCaption, { children: Localization.translate('action_filter_caption') })] })), actions.map((action, index) => (_jsx(SSIPrimaryButton, { caption: action.caption, onClick: action.onClick, icon: action.icon }, index)))] }) }) }));
7
+ const { enableFiltering = false, enableMostRecent = false, actions = [], onDelete } = props;
8
+ const onDeleteClick = async () => {
9
+ await onDelete?.();
10
+ };
11
+ return (_jsxs(Container, { children: [_jsx(StaticActionsContainer, { children: onDelete &&
12
+ _jsx(SSIIconButton, { caption: Localization.translate('action_delete_label'), icon: ButtonIcon.DELETE, iconColor: statusColors.error, onClick: onDeleteClick }) }), _jsx(ContentContainer, { style: { width: 'fit-content' }, children: _jsxs(ActionsContainer, { children: [enableFiltering && (_jsxs(FilterContainer, { children: [_jsx(SSIIconButton, { icon: ButtonIcon.FILTER, onClick: async () => console.log('add filter clicked') }), _jsx(FilterCaption, { children: Localization.translate('action_filter_caption') })] })), actions.map((action, index) => (_jsx(SSIPrimaryButton, { caption: action.caption, onClick: action.onClick, icon: action.icon }, index)))] }) })] }));
9
13
  };
10
14
  export default SSITableViewHeader;
@@ -5,6 +5,7 @@ type Props<T> = {
5
5
  data: Array<T>;
6
6
  columns: Array<ColumnHeader<T>>;
7
7
  onRowClick?: (data: Row<T>) => Promise<void>;
8
+ onDelete?: (rows: Array<T>) => Promise<void>;
8
9
  enableRowSelection?: boolean;
9
10
  enableFiltering?: boolean;
10
11
  enableMostRecent?: boolean;
@@ -1,13 +1,15 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from 'react';
3
- import { createColumnHelper, flexRender, getCoreRowModel, useReactTable, } from '@tanstack/react-table';
4
- import { ButtonIcon, Localization } from '@sphereon/ui-components.core';
3
+ import { createColumnHelper, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
4
+ import { ButtonIcon, Localization, selectionElementColors } from '@sphereon/ui-components.core';
5
5
  import SSITableViewHeader from './SSITableViewHeader';
6
6
  import SSITypeLabel from '../../labels/SSITypeLabel';
7
7
  import SSIHoverText from '../../fields/SSIHoverText';
8
- import { SSITableViewCellContainerStyled as CellContainer, SSITableViewContainerStyled as Container, SSITableViewHeaderCellContainerStyled as HeaderCellContainer, SSITableViewLabelCellStyled as LabelCell, SSITableViewResultCountCaptionStyled as ResultCountCaption, SSITableViewRowContainerStyled as RowContainer, SSITableViewTableContainerStyled as TableContainer, } from '../../../styles';
8
+ import SSIStatusLabel from '../../labels/SSIStatusLabel';
9
+ import CredentialMiniCardView from '../CredentialMiniCardView';
10
+ import DropDownList from '../../lists/DropDownList';
11
+ import { SSITableViewCellContainerStyled as CellContainer, SSITableViewContainerStyled as Container, SSITableViewHeaderCellContainerStyled as HeaderCellContainer, SSITableViewLabelCellStyled as LabelCell, SSITableViewResultCountCaptionStyled as ResultCountCaption, SSITableViewRowContainerStyled as RowContainer, SSITableViewTableContainerStyled as TableContainer, TableViewRowSelectionCheckboxContainerStyled as RowSelectionCheckboxContainer } from '../../../styles';
9
12
  import { TableCellType } from '../../../types';
10
- import { CredentialMiniCardView, DropDownList, SSIStatusLabel } from '../../../index';
11
13
  function IndeterminateCheckbox({ indeterminate, className = '', ...rest }) {
12
14
  const ref = React.useRef(null);
13
15
  React.useEffect(() => {
@@ -33,23 +35,28 @@ const getCellFormatting = (type, value, row, opts) => {
33
35
  return _jsx(CredentialMiniCardView, { ...value });
34
36
  }
35
37
  case TableCellType.ACTION_GROUP: {
36
- const { actionGroup } = opts ?? {};
37
- if (actionGroup) {
38
- const actions = actionGroup.actions.map(action => ({
39
- ...action,
40
- onClick: () => action.onClick(row),
41
- }));
42
- return _jsx(DropDownList, { icon: ButtonIcon.MEATBALLS, buttons: actions, showBorder: true });
43
- }
44
- return _jsx("div", {});
38
+ const { actionGroup = { actions: [] } } = opts ?? { actions: [] };
39
+ const actions = actionGroup.actions.map((action) => ({
40
+ ...action,
41
+ onClick: () => action.onClick(row),
42
+ }));
43
+ return _jsx(DropDownList, { icon: ButtonIcon.MEATBALLS, buttons: actions, showBorder: true });
45
44
  }
46
45
  default:
47
46
  return _jsx("div", {});
48
47
  }
49
48
  };
49
+ const toRowSelectionObject = (rows) => {
50
+ const rowSelectionObject = {};
51
+ rows.forEach((row) => {
52
+ rowSelectionObject[row.rowId] = true;
53
+ });
54
+ return rowSelectionObject;
55
+ };
50
56
  const SSITableView = (props) => {
51
- const { columns, data, enableRowSelection = false, enableFiltering = false, enableMostRecent = false, enableResultCount = false, columnResizeMode = 'onChange', actions = [], onRowClick, } = props;
52
- const [rowSelection, setRowSelection] = React.useState({});
57
+ const { columns, data, enableRowSelection = false, enableFiltering = false, enableMostRecent = false, enableResultCount = false, columnResizeMode = 'onChange', actions = [], onRowClick, onDelete } = props;
58
+ const [rowSelection, setRowSelection] = React.useState([]);
59
+ const [focusedRowId, setFocusedRowId] = React.useState();
53
60
  const columnHelper = createColumnHelper();
54
61
  let availableColumns = columns.map((header) => columnHelper.accessor(header.accessor, {
55
62
  id: header.accessor,
@@ -68,39 +75,54 @@ const SSITableView = (props) => {
68
75
  indeterminate: table.getIsSomeRowsSelected(),
69
76
  onChange: table.getToggleAllRowsSelectedHandler(),
70
77
  } })),
71
- cell: ({ row }) => (_jsx("div", { className: "px-1", children: _jsx(IndeterminateCheckbox, { ...{
72
- checked: row.getIsSelected(),
73
- disabled: !row.getCanSelect(),
74
- indeterminate: row.getIsSomeSelected(),
75
- onChange: row.getToggleSelectedHandler(),
76
- } }) })),
78
+ cell: ({ row }) => (_jsx(RowSelectionCheckboxContainer, { children: (row.id === focusedRowId || rowSelection.length > 0)
79
+ && _jsx(IndeterminateCheckbox, { ...{
80
+ checked: row.getIsSelected(),
81
+ disabled: !row.getCanSelect(),
82
+ indeterminate: row.getIsSomeSelected(),
83
+ onChange: row.getToggleSelectedHandler(),
84
+ } }) })),
77
85
  },
78
86
  ...availableColumns,
79
87
  ];
80
88
  }
89
+ const onFocusRow = (rowId) => {
90
+ setFocusedRowId(rowId);
91
+ };
92
+ const onRowSelectionChange = (updatedRowSelection) => {
93
+ const currentRowSelection = updatedRowSelection(toRowSelectionObject(rowSelection));
94
+ const selection = Object.keys(currentRowSelection).map((key) => {
95
+ return {
96
+ rowId: key,
97
+ rowData: data[Number(key)]
98
+ };
99
+ });
100
+ setRowSelection(selection);
101
+ };
81
102
  const table = useReactTable({
82
103
  defaultColumn: {
83
104
  size: 0,
84
105
  },
85
106
  state: {
86
- rowSelection,
107
+ rowSelection: toRowSelectionObject(rowSelection)
87
108
  },
88
109
  enableRowSelection,
89
- onRowSelectionChange: setRowSelection,
110
+ onRowSelectionChange: onRowSelectionChange,
90
111
  data,
91
112
  columns: availableColumns,
92
113
  columnResizeMode,
93
114
  getCoreRowModel: getCoreRowModel(),
94
115
  });
95
116
  const onRowClicked = async (row) => {
96
- if (onRowClick) {
97
- await onRowClick(row);
98
- }
117
+ await onRowClick?.(row);
118
+ };
119
+ const onDeleteClicked = async () => {
120
+ await onDelete?.(rowSelection.map((row) => row.rowData));
99
121
  };
100
122
  return (_jsx(Container, { children: _jsxs("div", { className: "overflow-x-auto", children: [enableResultCount && (_jsx(ResultCountCaption, { children: Localization.translate('result_count_label', {
101
123
  count: data.length,
102
124
  maxCount: data.length,
103
- }) })), (enableFiltering || enableMostRecent || actions.length > 0) && (_jsx(SSITableViewHeader, { actions: actions, enableFiltering: enableFiltering, enableMostRecent: enableMostRecent })), _jsxs(TableContainer, { children: [_jsx("thead", { children: table.getHeaderGroups().map((headerGroup) => (_jsx(RowContainer, { children: headerGroup.headers.map((header) => (_jsxs(HeaderCellContainer, { colSpan: header.colSpan, style: {
125
+ }) })), (enableFiltering || enableMostRecent || actions.length > 0) && (_jsx(SSITableViewHeader, { actions: actions, enableFiltering: enableFiltering, enableMostRecent: enableMostRecent, ...(onDelete && { onDelete: onDeleteClicked }) })), _jsxs(TableContainer, { children: [_jsx("thead", { children: table.getHeaderGroups().map((headerGroup) => (_jsx(RowContainer, { children: headerGroup.headers.map((header) => (_jsxs(HeaderCellContainer, { colSpan: header.colSpan, style: {
104
126
  ...(header.column.columnDef.minSize && { minWidth: header.column.columnDef.minSize }),
105
127
  ...(header.column.columnDef.maxSize && { maxWidth: header.column.columnDef.maxSize }),
106
128
  ...(header.column.columnDef.size !== 0 && { width: header.column.columnDef.size }),
@@ -108,7 +130,7 @@ const SSITableView = (props) => {
108
130
  transform: columnResizeMode === 'onEnd' && header.column.getIsResizing()
109
131
  ? `translateX(${table.getState().columnSizingInfo.deltaOffset}px)`
110
132
  : '',
111
- } })] }, header.id))) }, headerGroup.id))) }), _jsx("tbody", { children: table.getRowModel().rows.map((row) => (_jsx(RowContainer, { onClick: () => onRowClicked(row), children: row.getVisibleCells().map((cell) => (_jsx(CellContainer, { style: {
133
+ } })] }, header.id))) }, headerGroup.id))) }), _jsx("tbody", { children: table.getRowModel().rows.map((row) => (_jsx(RowContainer, { onClick: () => onRowClicked(row), onMouseEnter: () => onFocusRow(row.id), onMouseLeave: () => onFocusRow(), style: { ...(row.getIsSelected() && { backgroundColor: selectionElementColors.selectedRow }) }, children: row.getVisibleCells().map((cell) => (_jsx(CellContainer, { style: {
112
134
  ...(cell.column.columnDef.minSize && { minWidth: cell.column.columnDef.minSize }),
113
135
  ...(cell.column.columnDef.maxSize && { maxWidth: cell.column.columnDef.maxSize }),
114
136
  ...(cell.column.columnDef.size !== 0 && { width: cell.column.columnDef.size }),
@@ -1,7 +1,9 @@
1
1
  import styled from 'styled-components';
2
2
  export const SSIIconButtonContainerStyled = styled.div `
3
- width: 32px;
4
- aspect-ratio: 1;
3
+ gap: 8px;
4
+ height: 32px;
5
+ min-width: 32px;
6
+ flex-direction: row;
5
7
  display: flex;
6
8
  justify-content: center;
7
9
  align-items: center;
@@ -5,3 +5,4 @@ export declare const SSITableViewRowContainerStyled: import("styled-components")
5
5
  export declare const SSITableViewCellContainerStyled: import("styled-components").StyledComponent<"td", any, {}, never>;
6
6
  export declare const SSITableViewHeaderCellContainerStyled: import("styled-components").StyledComponent<"th", any, {}, never>;
7
7
  export declare const SSITableViewResultCountCaptionStyled: import("styled-components").StyledComponent<"div", any, {}, never>;
8
+ export declare const TableViewRowSelectionCheckboxContainerStyled: import("styled-components").StyledComponent<"div", any, {}, never>;
@@ -19,11 +19,15 @@ export const SSITableViewTableContainerStyled = styled.table `
19
19
  `;
20
20
  export const SSITableViewRowContainerStyled = styled.tr `
21
21
  border-bottom: 1px solid ${borderColors.lightGrey};
22
+ background-color: ${backgroundColors.primaryLight};
23
+
24
+ &:hover {
25
+ background-color: #ECECEC;
26
+ }
22
27
  `;
23
28
  export const SSITableViewCellContainerStyled = styled.td `
24
29
  ${SSITextH3Css};
25
30
  color: ${fontColors.dark};
26
- background-color: ${backgroundColors.primaryLight};
27
31
  padding: 20px 16px 20px 16px;
28
32
  text-align: left;
29
33
  //setting border-box makes padding be included in the width, otherwise content-box is used and then padding is excluded from the width
@@ -43,3 +47,7 @@ export const SSITableViewResultCountCaptionStyled = styled.div `
43
47
  ${SSITextH3Css};
44
48
  margin-left: 24px;
45
49
  `;
50
+ export const TableViewRowSelectionCheckboxContainerStyled = styled.div `
51
+ width: 20px;
52
+ height: 20px;
53
+ `;
@@ -3,3 +3,4 @@ export declare const SSITableViewHeaderContentContainerStyled: import("styled-co
3
3
  export declare const SSITableViewHeaderActionsContainerStyled: import("styled-components").StyledComponent<"div", any, {}, never>;
4
4
  export declare const SSITableViewHeaderFilterContainerStyled: import("styled-components").StyledComponent<"div", any, {}, never>;
5
5
  export declare const SSITableViewHeaderShowOptionContainerStyled: import("styled-components").StyledComponent<"div", any, {}, never>;
6
+ export declare const TableViewHeaderStaticActionsContainerStyled: import("styled-components").StyledComponent<"div", any, {}, never>;
@@ -27,3 +27,11 @@ export const SSITableViewHeaderShowOptionContainerStyled = styled.div `
27
27
  text-align: left;
28
28
  align-items: center;
29
29
  `;
30
+ export const TableViewHeaderStaticActionsContainerStyled = styled.div `
31
+ height: 48px;
32
+ flex-grow: 1;
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: center;
36
+ gap: 50px;
37
+ `;
@@ -20,7 +20,8 @@ export const SSITextH2SemiBoldStyled = styled.div `
20
20
  ${SSITextH2SemiBoldStyledCss}
21
21
  `;
22
22
  export const SSITextH3Styled = styled.div `
23
- ${SSITextH3Css}
23
+ ${SSITextH3Css};
24
+ color: ${fontColors.dark};
24
25
  `;
25
26
  export const SSITextH3LightStyled = styled(SSITextH3Styled) `
26
27
  color: ${fontColors.light};
@@ -25,3 +25,7 @@ export type TableColumnActionGroup = {
25
25
  label?: string;
26
26
  actions: Array<Button>;
27
27
  };
28
+ export type TableRowSelection = {
29
+ rowId: string;
30
+ rowData: any;
31
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sphereon/ui-components.ssi-react",
3
3
  "private": false,
4
- "version": "0.1.3-next.119+7efc6da",
4
+ "version": "0.1.3-next.124+7c978b9",
5
5
  "description": "SSI UI components for React",
6
6
  "repository": "git@github.com:Sphereon-Opensource/UI-Components.git",
7
7
  "author": "Sphereon <dev@sphereon.com>",
@@ -28,7 +28,7 @@
28
28
  "access": "public"
29
29
  },
30
30
  "dependencies": {
31
- "@sphereon/ui-components.core": "0.1.3-next.119+7efc6da",
31
+ "@sphereon/ui-components.core": "0.1.3-next.124+7c978b9",
32
32
  "@tanstack/react-table": "^8.9.3",
33
33
  "react-loader-spinner": "^5.4.5",
34
34
  "react-toastify": "^9.1.3",
@@ -42,5 +42,5 @@
42
42
  "peerDependencies": {
43
43
  "react": ">= 16.8.0"
44
44
  },
45
- "gitHead": "7efc6da3b8ccf4385f8ce733b7e47fcad76681d6"
45
+ "gitHead": "7c978b9e929d595e3e097b4a07e1d75de99ff352"
46
46
  }