@ansible/ansible-ui-framework 0.0.232 → 0.0.234

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. package/cjs/BulkActionDialog.js +2 -2
  2. package/cjs/PageBody.js +1 -1
  3. package/cjs/PageDataList.js +1 -2
  4. package/cjs/PageHeader.js +2 -2
  5. package/cjs/PageTable.js +32 -8
  6. package/cjs/PageTableCard.js +87 -0
  7. package/cjs/PageTableCards.js +38 -0
  8. package/cjs/PageTableList.js +79 -0
  9. package/cjs/PageTableViewType.js +9 -0
  10. package/cjs/PageToolbar.js +25 -1
  11. package/cjs/TypedActions/TypedActions.js +13 -4
  12. package/cjs/components/Details.js +2 -1
  13. package/cjs/components/patternfly-colors.js +11 -1
  14. package/cjs/index.js +1 -1
  15. package/mjs/BulkActionDialog.js +2 -2
  16. package/mjs/PageBody.d.ts +1 -0
  17. package/mjs/PageBody.js +1 -1
  18. package/mjs/PageDataList.js +1 -2
  19. package/mjs/PageHeader.d.ts +1 -0
  20. package/mjs/PageHeader.js +2 -2
  21. package/mjs/PageTable.d.ts +10 -1
  22. package/mjs/PageTable.js +28 -7
  23. package/mjs/PageTableCard.d.ts +33 -0
  24. package/mjs/PageTableCard.js +69 -0
  25. package/mjs/PageTableCards.d.ts +4 -0
  26. package/mjs/PageTableCards.js +23 -0
  27. package/mjs/PageTableList.d.ts +6 -0
  28. package/mjs/PageTableList.js +62 -0
  29. package/mjs/PageTableViewType.d.ts +6 -0
  30. package/mjs/PageTableViewType.js +6 -0
  31. package/mjs/PageToolbar.d.ts +3 -0
  32. package/mjs/PageToolbar.js +27 -3
  33. package/mjs/TypedActions/TypedActions.d.ts +3 -0
  34. package/mjs/TypedActions/TypedActions.js +14 -5
  35. package/mjs/components/Details.d.ts +1 -1
  36. package/mjs/components/Details.js +2 -2
  37. package/mjs/components/patternfly-colors.d.ts +10 -0
  38. package/mjs/components/patternfly-colors.js +10 -0
  39. package/mjs/index.d.ts +1 -1
  40. package/mjs/index.js +1 -1
  41. package/package.json +1 -1
  42. package/cjs/PageCatalog.js +0 -178
  43. package/mjs/PageCatalog.d.ts +0 -113
  44. package/mjs/PageCatalog.js +0 -140
package/mjs/PageHeader.js CHANGED
@@ -59,7 +59,7 @@ export function PageHeader(props) {
59
59
  borderTop: settings.theme !== 'light' && settings.borders
60
60
  ? 'thin solid var(--pf-global--BorderColor--100)'
61
61
  : undefined,
62
- borderBottom: settings.borders
62
+ borderBottom: !props.disableBorderBottom && settings.borders
63
63
  ? 'thin solid var(--pf-global--BorderColor--100)'
64
64
  : undefined,
65
65
  backgroundColor: 'var(--pf-global--BackgroundColor--100)',
@@ -69,7 +69,7 @@ export function PageHeader(props) {
69
69
  borderTop: !navigation && settings.theme !== 'light' && settings.borders
70
70
  ? 'thin solid var(--pf-global--BorderColor--100)'
71
71
  : undefined,
72
- borderBottom: settings.borders
72
+ borderBottom: !props.disableBorderBottom && settings.borders
73
73
  ? 'thin solid var(--pf-global--BorderColor--100)'
74
74
  : undefined,
75
75
  backgroundColor: settings.theme === 'dark'
@@ -1,5 +1,6 @@
1
1
  import { Dispatch, ReactNode, SetStateAction } from 'react';
2
2
  import { PageHeaderProps } from './PageHeader';
3
+ import { PageTableViewType } from './PageTableViewType';
3
4
  import { IToolbarFilter } from './PageToolbar';
4
5
  import { ITypedAction } from './TypedActions';
5
6
  export declare type TablePageProps<T extends object> = PageHeaderProps & PageTableProps<T> & {
@@ -43,7 +44,12 @@ export declare type PageTableProps<T extends object> = {
43
44
  emptyStateButtonClick?: () => void;
44
45
  t?: (t: string) => string;
45
46
  showSelect?: boolean;
46
- ColumnManagement?: boolean;
47
+ disableTableView?: boolean;
48
+ disableListView?: boolean;
49
+ disableCardView?: boolean;
50
+ defaultTableView?: PageTableViewType;
51
+ disableBodyPadding?: boolean;
52
+ defaultCardSubtitle?: ReactNode;
47
53
  };
48
54
  export declare function PageTable<T extends object>(props: PageTableProps<T>): JSX.Element;
49
55
  declare type CellFn<T extends object> = (item: T) => ReactNode;
@@ -64,5 +70,8 @@ export interface ITableColumn<T extends object> {
64
70
  * @deprecated The method should not be used
65
71
  */
66
72
  sortFn?: (l: T, r: T) => number;
73
+ card?: 'description' | 'hidden';
74
+ list?: 'primary' | 'secondary';
75
+ hideLabel?: boolean;
67
76
  }
68
77
  export {};
package/mjs/PageTable.js CHANGED
@@ -4,19 +4,41 @@ import { ExclamationCircleIcon, PlusCircleIcon, SearchIcon } from '@patternfly/r
4
4
  import { ActionsColumn, TableComposable, Tbody, Td, Th, Thead, Tr, } from '@patternfly/react-table';
5
5
  import useResizeObserver from '@react-hook/resize-observer';
6
6
  import { Fragment, useCallback, useEffect, useRef, useState, } from 'react';
7
+ import { Scrollable } from './components/Scrollable';
7
8
  import { useBreakpoint } from './components/useBreakPoint';
8
9
  import { PageBody } from './PageBody';
9
10
  import { useColumnModal } from './PageColumnModal';
10
11
  import { PageHeader } from './PageHeader';
11
12
  import { PageLayout } from './PageLayout';
12
13
  import { PagePagination } from './PagePagination';
14
+ import { PageTableCards } from './PageTableCards';
15
+ import { PageTableList } from './PageTableList';
16
+ import { PageTableViewTypeE } from './PageTableViewType';
13
17
  import { PageTableToolbar } from './PageToolbar';
14
18
  import { useSettings } from './Settings';
15
19
  import { TypedActionType, useTypedActionsToTableActions } from './TypedActions';
16
20
  export function TablePage(props) {
17
- return (_jsx(_Fragment, { children: _jsxs(PageLayout, { children: [_jsx(PageHeader, { ...props }), _jsx(PageBody, { children: _jsx(PageTable, { ...props }) })] }) }));
21
+ return (_jsxs(PageLayout, { children: [_jsx(PageHeader, { ...props }), _jsx(PageTable, { ...props })] }));
18
22
  }
19
23
  export function PageTable(props) {
24
+ let { disableBodyPadding } = props;
25
+ disableBodyPadding = true;
26
+ const { toolbarActions } = props;
27
+ const { openColumnModal, columnModal, managedColumns } = useColumnModal(props.tableColumns);
28
+ const showSelect = toolbarActions?.find((toolbarAction) => TypedActionType.bulk === toolbarAction.type) !==
29
+ undefined;
30
+ const hasTableViewType = !props.disableTableView;
31
+ const hasListViewType = !props.disableListView;
32
+ // const hasCardViewType = !props.disableCardView
33
+ const [viewType, setViewType] = useState(() => props.defaultTableView ??
34
+ (hasTableViewType
35
+ ? PageTableViewTypeE.Table
36
+ : hasListViewType
37
+ ? PageTableViewTypeE.List
38
+ : PageTableViewTypeE.Cards));
39
+ return (_jsxs(_Fragment, { children: [_jsx(PageTableToolbar, { ...props, openColumnModal: openColumnModal, showSelect: showSelect, viewType: viewType, setViewType: setViewType }), viewType === PageTableViewTypeE.Table && (_jsx(PageBody, { disablePadding: disableBodyPadding, children: _jsx(PageTableView, { ...props, tableColumns: managedColumns }) })), viewType === PageTableViewTypeE.List && (_jsx(PageBody, { disablePadding: true, children: _jsx(Scrollable, { children: _jsx(PageTableList, { ...props, showSelect: showSelect }) }) })), viewType === PageTableViewTypeE.Cards && (_jsx(Scrollable, { children: _jsx(PageTableCards, { ...props, showSelect: showSelect }) })), (!props.autoHidePagination || (props.itemCount ?? 0) > props.perPage) && (_jsx(PagePagination, { ...props })), columnModal] }));
40
+ }
41
+ function PageTableView(props) {
20
42
  const { tableColumns, pageItems, selectItem, unselectItem, isSelected, keyFn, rowActions, toolbarActions, itemCount, perPage, clearAllFilters, filters, error, onSelect, unselectAll, } = props;
21
43
  let { t } = props;
22
44
  t = t ? t : (t) => t;
@@ -44,7 +66,6 @@ export function PageTable(props) {
44
66
  useResizeObserver(containerRef, () => updateScroll(containerRef.current));
45
67
  useEffect(() => updateScroll(containerRef.current), [updateScroll]);
46
68
  const settings = useSettings();
47
- const { openColumnModal, columnModal, managedColumns } = useColumnModal(tableColumns);
48
69
  if (error) {
49
70
  return (_jsx("div", { style: {
50
71
  backgroundColor: settings.theme === 'dark' ? 'var(--pf-global--BackgroundColor--300)' : undefined,
@@ -56,11 +77,11 @@ export function PageTable(props) {
56
77
  if (itemCount === 0 && Object.keys(filters ?? {}).length === 0) {
57
78
  return (_jsxs(EmptyState, { variant: EmptyStateVariant.large, style: { paddingTop: 64 }, children: [_jsx(EmptyStateIcon, { icon: PlusCircleIcon }), _jsx(Title, { headingLevel: "h4", size: "lg", children: props.emptyStateTitle }), props.emptyStateDescription && (_jsx(EmptyStateBody, { children: props.emptyStateDescription })), props.emptyStateButtonClick && (_jsx(Button, { variant: "primary", onClick: props.emptyStateButtonClick, children: props.emptyStateButtonText }))] }));
58
79
  }
59
- return (_jsxs(Fragment, { children: [columnModal, _jsx(PageTableToolbar, { ...props, openColumnModal: openColumnModal, showSelect: showSelect }), _jsxs("div", { className: "pf-c-scroll-inner-wrapper", style: { height: '100%' }, ref: containerRef, onScroll: onScroll, children: [_jsxs(TableComposable, { "aria-label": "Simple table", variant: props.compact ? 'compact' : settings.tableLayout === 'compact' ? 'compact' : undefined, gridBreakPoint: "", isStickyHeader: true, children: [itemCount === undefined ? (_jsx(Thead, { children: _jsx(Tr, { children: _jsx(Th, { children: _jsx(Skeleton, {}) }) }) })) : (_jsx(TableHead, { ...props, showSelect: showSelect, scrollLeft: scroll.left > 0, scrollRight: scroll.right > 1, tableColumns: managedColumns, onSelect: onSelect })), _jsx(Tbody, { children: itemCount === undefined
60
- ? new Array(perPage).fill(0).map((_, index) => (_jsx(Tr, { children: _jsx(Td, { children: _jsx("div", { style: { paddingTop: 5, paddingBottom: 5 }, children: _jsx(Skeleton, { height: "27px" }) }) }) }, index)))
61
- : pageItems === undefined
62
- ? new Array(Math.min(perPage, itemCount)).fill(0).map((_, index) => (_jsxs(Tr, { children: [showSelect && _jsx(Td, {}), _jsx(Td, { colSpan: managedColumns.length, children: _jsx("div", { style: { paddingTop: 5, paddingBottom: 5 }, children: _jsx(Skeleton, { height: "27px" }) }) })] }, index)))
63
- : pageItems?.map((item, rowIndex) => (_jsx(TableRow, { columns: managedColumns, item: item, isItemSelected: isSelected?.(item), selectItem: selectItem, unselectItem: unselectItem, rowActions: rowActions, rowIndex: rowIndex, showSelect: showSelect, scrollLeft: scroll.left > 0, scrollRight: scroll.right > 1, unselectAll: unselectAll, onSelect: onSelect }, keyFn ? keyFn(item) : rowIndex))) })] }), itemCount === 0 && (_jsx("div", { style: { margin: 'auto' }, children: _jsxs(EmptyState, { children: [_jsx(EmptyStateIcon, { icon: SearchIcon }), _jsx(Title, { headingLevel: "h2", size: "lg", children: t('No results found') }), _jsx(EmptyStateBody, { children: t('No results match this filter criteria. Adjust your filters and try again.') }), clearAllFilters && (_jsx(EmptyStateSecondaryActions, { children: _jsx(Button, { variant: "link", onClick: clearAllFilters, children: t('Clear all filters') }) }))] }) }))] }), (!props.autoHidePagination || (itemCount ?? 0) > perPage) && _jsx(PagePagination, { ...props })] }));
80
+ return (_jsxs("div", { className: "pf-c-scroll-inner-wrapper", style: { height: '100%', marginBottom: -1 }, ref: containerRef, onScroll: onScroll, children: [_jsxs(TableComposable, { "aria-label": "Simple table", variant: props.compact ? 'compact' : settings.tableLayout === 'compact' ? 'compact' : undefined, gridBreakPoint: "", isStickyHeader: true, children: [itemCount === undefined ? (_jsx(Thead, { children: _jsx(Tr, { children: _jsx(Th, { children: _jsx(Skeleton, {}) }) }) })) : (_jsx(TableHead, { ...props, showSelect: showSelect, scrollLeft: scroll.left > 0, scrollRight: scroll.right > 1, tableColumns: tableColumns, onSelect: onSelect })), _jsx(Tbody, { children: itemCount === undefined
81
+ ? new Array(perPage).fill(0).map((_, index) => (_jsx(Tr, { children: _jsx(Td, { children: _jsx("div", { style: { paddingTop: 5, paddingBottom: 5 }, children: _jsx(Skeleton, { height: "27px" }) }) }) }, index)))
82
+ : pageItems === undefined
83
+ ? new Array(Math.min(perPage, itemCount)).fill(0).map((_, index) => (_jsxs(Tr, { children: [showSelect && _jsx(Td, {}), _jsx(Td, { colSpan: tableColumns.length, children: _jsx("div", { style: { paddingTop: 5, paddingBottom: 5 }, children: _jsx(Skeleton, { height: "27px" }) }) })] }, index)))
84
+ : pageItems?.map((item, rowIndex) => (_jsx(TableRow, { columns: tableColumns, item: item, isItemSelected: isSelected?.(item), selectItem: selectItem, unselectItem: unselectItem, rowActions: rowActions, rowIndex: rowIndex, showSelect: showSelect, scrollLeft: scroll.left > 0, scrollRight: scroll.right > 1, unselectAll: unselectAll, onSelect: onSelect }, keyFn ? keyFn(item) : rowIndex))) })] }), itemCount === 0 && (_jsx("div", { style: { margin: 'auto' }, children: _jsxs(EmptyState, { children: [_jsx(EmptyStateIcon, { icon: SearchIcon }), _jsx(Title, { headingLevel: "h2", size: "lg", children: t('No results found') }), _jsx(EmptyStateBody, { children: t('No results match this filter criteria. Adjust your filters and try again.') }), clearAllFilters && (_jsx(EmptyStateSecondaryActions, { children: _jsx(Button, { variant: "link", onClick: clearAllFilters, children: t('Clear all filters') }) }))] }) }))] }));
64
85
  }
65
86
  function TableHead(props) {
66
87
  const { tableColumns: columns, rowActions: itemActions, sort, setSort, sortDirection, setSortDirection, showSelect, onSelect, } = props;
@@ -0,0 +1,33 @@
1
+ import { ReactNode } from 'react';
2
+ import { LabelColor } from './components/patternfly-colors';
3
+ import { ITableColumn } from './PageTable';
4
+ import { ITypedAction } from './TypedActions';
5
+ export interface IPageTableCard {
6
+ id: string | number;
7
+ icon?: ReactNode;
8
+ title: ReactNode;
9
+ description?: ReactNode;
10
+ cardBody: ReactNode;
11
+ labels?: {
12
+ label: string;
13
+ color?: LabelColor;
14
+ }[];
15
+ badge?: string;
16
+ badgeColor?: LabelColor;
17
+ badgeTooltip?: string;
18
+ badgeTooltipTitle?: string;
19
+ alertTitle?: string;
20
+ alertContent?: ReactNode;
21
+ alertVariant?: 'success' | 'danger' | 'warning' | 'info' | 'default';
22
+ }
23
+ export declare function PageTableCard<T extends object>(props: {
24
+ item: T;
25
+ itemToCardFn: (item: T) => IPageTableCard;
26
+ isSelected?: (item: T) => boolean;
27
+ selectItem?: (item: T) => void;
28
+ unselectItem?: (item: T) => void;
29
+ itemActions?: ITypedAction<T>[];
30
+ showSelect?: boolean;
31
+ defaultCardSubtitle?: ReactNode;
32
+ }): JSX.Element;
33
+ export declare function useColumnsToTableCardFn<T extends object>(columns: ITableColumn<T>[], keyFn: (item: T) => string | number): (item: T) => IPageTableCard;
@@ -0,0 +1,69 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
3
+ /* eslint-disable @typescript-eslint/no-empty-function */
4
+ import { Alert, Card, CardActions, CardBody, CardFooter, CardHeader, CardTitle, Checkbox, DescriptionList, DropdownPosition, Label, LabelGroup, Popover, Split, SplitItem, Stack, Text, Truncate, } from '@patternfly/react-core';
5
+ import { useCallback, useMemo } from 'react';
6
+ import { Detail } from './components/Details';
7
+ import { IconWrapper } from './components/IconWrapper';
8
+ import { TypedActions } from './TypedActions';
9
+ export function PageTableCard(props) {
10
+ const { item, itemToCardFn, isSelected, selectItem, unselectItem, itemActions, showSelect, defaultCardSubtitle, } = props;
11
+ const card = useMemo(() => itemToCardFn(item), [item, itemToCardFn]);
12
+ const isItemSelected = !!isSelected?.(item);
13
+ const onSelectClick = useCallback(() => {
14
+ if (isSelected?.(item)) {
15
+ unselectItem?.(item);
16
+ }
17
+ else {
18
+ selectItem?.(item);
19
+ }
20
+ }, [isSelected, item, selectItem, unselectItem]);
21
+ const showDropdown = itemActions !== undefined && itemActions.length > 0;
22
+ const showActions = showSelect || showDropdown;
23
+ return (_jsxs(Card, { id: card.id, isFlat: true, isLarge: true, isRounded: true, isSelectable: isItemSelected, isSelected: isItemSelected, style: {
24
+ transition: 'box-shadow 0.25s',
25
+ cursor: 'default',
26
+ }, children: [_jsxs(CardHeader, { children: [_jsxs(Split, { hasGutter: true, style: { width: '100%' }, children: [_jsx(SplitItem, { isFilled: true, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [card.icon && (_jsx("div", { style: {
27
+ display: 'flex',
28
+ height: 40,
29
+ width: 40,
30
+ marginTop: -20,
31
+ marginBottom: -20,
32
+ marginRight: 12,
33
+ alignItems: 'center',
34
+ justifyItems: 'stretch',
35
+ }, children: _jsx(IconWrapper, { size: "lg", children: card.icon }) })), _jsxs(Stack, { children: [_jsx(CardTitle, { children: card.title }), card.description ? (_jsx(Text, { component: "small", style: { opacity: 0.7 }, children: card.description })) : (defaultCardSubtitle && _jsx(Text, { component: "small", children: defaultCardSubtitle }))] })] }) }), card.badge && card.badgeTooltip && (_jsx(SplitItem, { children: _jsx("div", { onClick: (e) => e.stopPropagation(), children: _jsx(Popover, { headerContent: card.badgeTooltipTitle, bodyContent: card.badgeTooltip, removeFindDomNode: true, children: _jsx(Label, { color: card.badgeColor, children: card.badge }) }) }) })), card.badge && !card.badgeTooltip && (_jsx(SplitItem, { children: _jsx(Label, { color: card.badgeColor, children: card.badge }) }))] }), showActions && (_jsxs(CardActions, { children: [itemActions && itemActions.length && (_jsx(TypedActions, { actions: itemActions, position: DropdownPosition.right, selectedItem: item })), showSelect && (_jsx(Checkbox, { isChecked: isSelected?.(item), onChange: onSelectClick,
36
+ // aria-label="card checkbox example"
37
+ id: "check-1" }))] }))] }), card.cardBody, card.labels && (_jsx(CardFooter, { children: _jsx("div", { style: {
38
+ display: 'flex',
39
+ flexDirection: 'row',
40
+ alignItems: 'end',
41
+ gap: 16,
42
+ }, children: _jsx("div", { style: { flexGrow: 1 }, children: card.labels && (_jsx(LabelGroup, { children: card.labels.map((item) => (_jsx(Label, { color: item.color, children: _jsx(Truncate, { content: item.label, style: { minWidth: 0 } }) }, item.label))) })) }) }) })), card.alertTitle && (_jsx(Alert, { title: card.alertTitle, isInline: true, variant: card.alertVariant, children: card.alertContent }))] }, card.id ?? card.title));
43
+ }
44
+ export function useColumnsToTableCardFn(columns, keyFn) {
45
+ const cardData = useMemo(() => {
46
+ let cols = columns.filter((column) => column.card !== 'hidden');
47
+ const nameColumn = cols.shift();
48
+ const descriptionColumn = cols.find((column) => column.card === 'description');
49
+ if (descriptionColumn) {
50
+ cols = cols.filter((column) => column !== descriptionColumn);
51
+ }
52
+ return {
53
+ nameColumn: nameColumn,
54
+ descriptionColumn: descriptionColumn,
55
+ columns: cols,
56
+ };
57
+ }, [columns]);
58
+ return useMemo(() => {
59
+ return (item) => {
60
+ const pageTableCard = {
61
+ id: keyFn(item),
62
+ title: cardData.nameColumn?.cell(item),
63
+ description: cardData.descriptionColumn?.cell(item),
64
+ cardBody: (_jsx(CardBody, { children: _jsx(DescriptionList, { isCompact: true, children: cardData.columns.map((column) => (_jsx(Detail, { label: column.hideLabel ? undefined : column.header, children: column.cell(item) }, column.id))) }) })),
65
+ };
66
+ return pageTableCard;
67
+ };
68
+ }, [cardData.columns, cardData.descriptionColumn, cardData.nameColumn, keyFn]);
69
+ }
@@ -0,0 +1,4 @@
1
+ /// <reference types="react" />
2
+ import { PageTableProps } from './PageTable';
3
+ export declare type PageTableCardsProps<T extends object> = PageTableProps<T>;
4
+ export declare function PageTableCards<T extends object>(props: PageTableCardsProps<T>): JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { PageSection } from '@patternfly/react-core';
3
+ import { useMemo } from 'react';
4
+ import { Grid } from './components/Grid';
5
+ import { PageTableCard, useColumnsToTableCardFn } from './PageTableCard';
6
+ export function PageTableCards(props) {
7
+ const { keyFn, pageItems: items, tableColumns, isSelected, selectItem, unselectItem, rowActions, showSelect, defaultCardSubtitle, } = props;
8
+ const itemToCardFn = useColumnsToTableCardFn(tableColumns, keyFn);
9
+ const catalogCards = useMemo(() => {
10
+ return (_jsx(Grid, { size: 470, children: items?.map((item) => (_jsx(PageTableCard, { item: item, itemToCardFn: itemToCardFn, isSelected: isSelected, selectItem: selectItem, unselectItem: unselectItem, itemActions: rowActions, showSelect: showSelect, defaultCardSubtitle: defaultCardSubtitle }, keyFn(item)))) }));
11
+ }, [
12
+ items,
13
+ keyFn,
14
+ itemToCardFn,
15
+ isSelected,
16
+ selectItem,
17
+ unselectItem,
18
+ rowActions,
19
+ showSelect,
20
+ defaultCardSubtitle,
21
+ ]);
22
+ return _jsx(PageSection, { style: { flexGrow: 1 }, children: catalogCards });
23
+ }
@@ -0,0 +1,6 @@
1
+ import { ReactNode } from 'react';
2
+ import { ITableColumn, PageTableProps } from './PageTable';
3
+ import { ITypedAction } from './TypedActions';
4
+ export declare type PageTableListProps<T extends object> = PageTableProps<T>;
5
+ export declare function PageTableList<T extends object>(props: PageTableListProps<T>): JSX.Element;
6
+ export declare function useColumnsToDataList<T extends object>(tableColumns: ITableColumn<T>[], keyFn: (item: T) => string | number, isSelected?: (item: T) => boolean, selectItem?: (item: T) => void, unselectItem?: (item: T) => void, rowActions?: ITypedAction<T>[], defaultCardSubtitle?: ReactNode, showSelect?: boolean): (item: T) => ReactNode;
@@ -0,0 +1,62 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { DataList, DataListAction, DataListCell, DataListCheck, DataListItem, DataListItemCells, DataListItemRow, DescriptionList, DescriptionListDescription, DescriptionListGroup, DescriptionListTerm, DropdownPosition, Flex, Stack, Text, Title, } from '@patternfly/react-core';
3
+ import { useCallback, useMemo } from 'react';
4
+ import { TypedActions } from './TypedActions';
5
+ export function PageTableList(props) {
6
+ const { keyFn, pageItems, tableColumns, isSelected, selectItem, unselectItem, rowActions, defaultCardSubtitle, showSelect, } = props;
7
+ const columnsToDataList = useColumnsToDataList(tableColumns, keyFn, isSelected, selectItem, unselectItem, rowActions, defaultCardSubtitle, showSelect);
8
+ return (_jsx(DataList, { "aria-label": "TODO", style: { marginTop: -1 }, children: pageItems?.map(columnsToDataList) }));
9
+ }
10
+ export function useColumnsToDataList(tableColumns, keyFn, isSelected, selectItem, unselectItem, rowActions, defaultCardSubtitle, showSelect) {
11
+ const data = useMemo(() => {
12
+ let cols = tableColumns.filter((column) => column.card !== 'hidden');
13
+ const nameColumn = cols.shift();
14
+ const descriptionColumn = cols.find((column) => column.card === 'description');
15
+ if (descriptionColumn) {
16
+ cols = cols.filter((column) => column !== descriptionColumn);
17
+ }
18
+ return {
19
+ nameColumn: nameColumn,
20
+ descriptionColumn: descriptionColumn,
21
+ columns: cols.filter((column) => column.list !== 'secondary'),
22
+ secondary: cols.filter((column) => column.list === 'secondary'),
23
+ };
24
+ }, [tableColumns]);
25
+ const onSelectClick = useCallback((item) => {
26
+ if (isSelected?.(item)) {
27
+ unselectItem?.(item);
28
+ }
29
+ else {
30
+ selectItem?.(item);
31
+ }
32
+ }, [isSelected, selectItem, unselectItem]);
33
+ return useCallback((item) => {
34
+ const key = keyFn(item);
35
+ const isItemSelected = isSelected?.(item);
36
+ return (_jsx(DataListItem, { "aria-labelledby": `data-list-${key}`, isExpanded: isItemSelected, children: _jsxs(DataListItemRow, { children: [showSelect && (_jsx(DataListCheck, { "aria-labelledby": `data-list-check-${key}`, name: `data-list-check-${key}`, isChecked: isSelected?.(item), onClick: () => onSelectClick(item) })), _jsx(DataListItemCells, { dataListCells: [
37
+ _jsx(DataListCell, { children: _jsx(Flex, { children: _jsxs(Stack, { hasGutter: true, children: [_jsxs(Stack, { children: [_jsx(Title, { headingLevel: "h2", style: { marginTop: -4 }, children: _jsx("span", { id: `data-list-${key}`, children: data.nameColumn?.cell(item) }) }), data.descriptionColumn ? (_jsx(Text, { component: "small", style: { opacity: 0.7 }, children: data.descriptionColumn.cell(item) })) : (defaultCardSubtitle && (_jsx(Text, { component: "small", style: { opacity: 0.7 }, children: defaultCardSubtitle })))] }), _jsx(DescriptionList, { isCompact: true, children: data.columns.map((column) => {
38
+ const value = column.cell(item);
39
+ if (!value)
40
+ return _jsx(_Fragment, {});
41
+ return (_jsxs(DescriptionListGroup, { children: [!column.hideLabel && (_jsx(DescriptionListTerm, { children: _jsx(Text, { component: "small", style: { opacity: 0.7 }, children: column.header }) })), _jsx(DescriptionListDescription, { children: column.cell(item) })] }, column.header));
42
+ }) })] }) }) }, "primary"),
43
+ _jsx(DataListCell, { children: _jsx(Flex, { children: _jsx(DescriptionList, { isCompact: true, children: data.secondary.map((column) => {
44
+ const value = column.cell(item);
45
+ if (!value)
46
+ return _jsx(_Fragment, {});
47
+ return (_jsxs(DescriptionListGroup, { children: [!column.hideLabel && (_jsx(DescriptionListTerm, { children: _jsx(Text, { component: "small", style: { opacity: 0.7 }, children: column.header }) })), _jsx(DescriptionListDescription, { children: column.cell(item) })] }, column.header));
48
+ }) }) }) }, "secondary"),
49
+ ] }), rowActions && (_jsx(DataListAction, { "aria-labelledby": "check-action-item1 check-action-action1", id: "check-action-action1", "aria-label": "Actions", isPlainButtonAction: true, style: { whiteSpace: 'nowrap' }, children: _jsx(TypedActions, { actions: rowActions, position: DropdownPosition.right, selectedItem: item }) }))] }) }, key));
50
+ }, [
51
+ data.columns,
52
+ data.descriptionColumn,
53
+ data.nameColumn,
54
+ data.secondary,
55
+ defaultCardSubtitle,
56
+ isSelected,
57
+ keyFn,
58
+ onSelectClick,
59
+ rowActions,
60
+ showSelect,
61
+ ]);
62
+ }
@@ -0,0 +1,6 @@
1
+ export declare enum PageTableViewTypeE {
2
+ Table = "table",
3
+ List = "list",
4
+ Cards = "cards"
5
+ }
6
+ export declare type PageTableViewType = 'table' | 'list' | 'cards';
@@ -0,0 +1,6 @@
1
+ export var PageTableViewTypeE;
2
+ (function (PageTableViewTypeE) {
3
+ PageTableViewTypeE["Table"] = "table";
4
+ PageTableViewTypeE["List"] = "list";
5
+ PageTableViewTypeE["Cards"] = "cards";
6
+ })(PageTableViewTypeE || (PageTableViewTypeE = {}));
@@ -1,4 +1,5 @@
1
1
  import { Dispatch, SetStateAction } from 'react';
2
+ import { PageTableViewType } from './PageTableViewType';
2
3
  import { ITypedAction } from './TypedActions';
3
4
  export interface IItemFilter<T extends object> {
4
5
  label: string;
@@ -53,5 +54,7 @@ export declare type PagetableToolbarProps<T extends object> = {
53
54
  onSelect?: (item: T) => void;
54
55
  disableBorderBottom?: boolean;
55
56
  showSelect?: boolean;
57
+ viewType: PageTableViewType;
58
+ setViewType: (viewType: PageTableViewType) => void;
56
59
  };
57
60
  export declare function PageTableToolbar<T extends object>(props: PagetableToolbarProps<T>): JSX.Element;
@@ -1,11 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Button, Flex, FlexItem, InputGroup, Pagination, PaginationVariant, Select, SelectOption, SelectVariant, Skeleton, TextInputGroup, TextInputGroupMain, TextInputGroupUtilities, Toolbar, ToolbarContent, ToolbarFilter, ToolbarGroup, ToolbarItem, ToolbarToggleGroup, Tooltip, } from '@patternfly/react-core';
3
- import { ArrowRightIcon, ColumnsIcon, FilterIcon, TimesIcon } from '@patternfly/react-icons';
2
+ import { Button, Flex, FlexItem, InputGroup, Pagination, PaginationVariant, Select, SelectOption, SelectVariant, Skeleton, TextInputGroup, TextInputGroupMain, TextInputGroupUtilities, ToggleGroup, ToggleGroupItem, Toolbar, ToolbarContent, ToolbarFilter, ToolbarGroup, ToolbarItem, ToolbarToggleGroup, Tooltip, } from '@patternfly/react-core';
3
+ import { ArrowRightIcon, ColumnsIcon, FilterIcon, ListIcon, TableIcon, ThLargeIcon, TimesIcon, } from '@patternfly/react-icons';
4
4
  import { Fragment, useCallback, useState } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import { BulkSelector } from './components/BulkSelector';
7
7
  import { SingleSelect2 } from './components/SingleSelect';
8
8
  import { useBreakpoint } from './components/useBreakPoint';
9
+ import { PageTableViewTypeE } from './PageTableViewType';
9
10
  import { useSettings } from './Settings';
10
11
  import { TypedActions, TypedActionType } from './TypedActions';
11
12
  export function toolbarActionsHaveBulkActions(actions) {
@@ -20,6 +21,7 @@ export function toolbarActionsHaveBulkActions(actions) {
20
21
  export function PageTableToolbar(props) {
21
22
  const { itemCount, page, perPage, setPage, setPerPage, toolbarFilters, selectedItems, filters, setFilters, clearAllFilters, openColumnModal, disableBorderBottom, } = props;
22
23
  const sm = useBreakpoint('md');
24
+ const { viewType, setViewType } = props;
23
25
  let { toolbarActions } = props;
24
26
  toolbarActions = toolbarActions ?? [];
25
27
  const onSetPage = useCallback((_event, page) => setPage(page), [setPage]);
@@ -96,7 +98,29 @@ export function PageTableToolbar(props) {
96
98
  return newState;
97
99
  });
98
100
  }, showToolbarItem: false, children: _jsx(_Fragment, {}) }, filter.label));
99
- })] }) })), _jsx(ToolbarGroup, { variant: "button-group", style: { zIndex: 302 }, children: _jsx(ToolbarItem, { children: _jsx(TypedActions, { actions: toolbarActions, selectedItems: selectedItems, wrapper: ToolbarItem }) }) }), _jsx(ToolbarGroup, { variant: "button-group", style: { zIndex: 302 }, children: openColumnModal && (_jsx(ToolbarItem, { children: _jsx(Tooltip, { content: 'Manage columns', children: _jsx(Button, { variant: "plain", icon: _jsx(ColumnsIcon, {}), onClick: openColumnModal }) }) })) }), _jsx(ToolbarItem, { variant: "pagination", visibility: { default: 'hidden', '2xl': 'visible' }, children: _jsx(Pagination, { variant: PaginationVariant.top, isCompact: true, itemCount: itemCount, perPage: perPage, page: page, onSetPage: onSetPage, onPerPageSelect: onPerPageSelect, style: { marginTop: -8, marginBottom: -8 } }) })] }) }));
101
+ })] }) })), _jsx(ToolbarGroup, { variant: "button-group", style: { zIndex: 302 }, children: _jsx(ToolbarItem, { children: _jsx(TypedActions, { actions: toolbarActions, selectedItems: selectedItems, wrapper: ToolbarItem }) }) }), _jsx("div", { style: { flexGrow: 1 } }), _jsxs(ToolbarGroup, { variant: "button-group", style: { zIndex: 302 }, children: [openColumnModal && viewType === 'table' && (_jsx(ToolbarItem, { children: _jsx(Tooltip, { content: 'Manage columns', children: _jsx(Button, { variant: "plain", icon: _jsx(ColumnsIcon, {}), onClick: openColumnModal }) }) })), _jsx(ToolbarItem, { children: _jsx(ToggleGroup, { children: [PageTableViewTypeE.Table, PageTableViewTypeE.List, PageTableViewTypeE.Cards]
102
+ // .filter((vt) => {
103
+ // switch (vt) {
104
+ // case PageTableViewTypeE.Cards:
105
+ // return props.itemToCardFn !== undefined
106
+ // case PageTableViewTypeE.list:
107
+ // return false
108
+ // case PageTableViewTypeE.table:
109
+ // return props.tableColumns !== undefined
110
+ // default:
111
+ // return false
112
+ // }
113
+ // })
114
+ .map((vt) => {
115
+ switch (vt) {
116
+ case PageTableViewTypeE.Cards:
117
+ return (_jsx(Tooltip, { content: 'Card view', position: "top-end", enableFlip: false, children: _jsx(ToggleGroupItem, { icon: _jsx(ThLargeIcon, {}), isSelected: viewType === PageTableViewTypeE.Cards, onClick: () => setViewType?.(PageTableViewTypeE.Cards) }) }, vt));
118
+ case PageTableViewTypeE.List:
119
+ return (_jsx(Tooltip, { content: 'List view', position: "top-end", enableFlip: false, children: _jsx(ToggleGroupItem, { icon: _jsx(ListIcon, {}), isSelected: viewType === PageTableViewTypeE.List, onClick: () => setViewType?.(PageTableViewTypeE.List) }) }));
120
+ case PageTableViewTypeE.Table:
121
+ return (_jsx(Tooltip, { content: 'Table view', position: "top-end", enableFlip: false, children: _jsx(ToggleGroupItem, { icon: _jsx(TableIcon, {}), isSelected: viewType === PageTableViewTypeE.Table, onClick: () => setViewType?.(PageTableViewTypeE.Table) }) }));
122
+ }
123
+ }) }) })] }), _jsx(ToolbarItem, { visibility: { default: 'hidden', '2xl': 'visible' }, children: _jsx(Pagination, { variant: PaginationVariant.top, isCompact: true, itemCount: itemCount, perPage: perPage, page: page, onSetPage: onSetPage, onPerPageSelect: onPerPageSelect, style: { marginTop: -8, marginBottom: -8 } }) })] }) }));
100
124
  }
101
125
  function ToolbarFilterInput(props) {
102
126
  const { filter } = props;
@@ -45,17 +45,20 @@ export declare function TypedActionsDropdown<T extends object>(props: {
45
45
  label?: string;
46
46
  isPrimary?: boolean;
47
47
  selectedItems?: T[];
48
+ selectedItem?: T;
48
49
  position?: DropdownPosition;
49
50
  }): JSX.Element;
50
51
  export declare function DropdownActionItem<T extends object>(props: {
51
52
  action: ITypedAction<T>;
52
53
  selectedItems: T[];
54
+ selectedItem?: T;
53
55
  hasIcons: boolean;
54
56
  index: number;
55
57
  }): JSX.Element;
56
58
  export declare function TypedActions<T extends object>(props: {
57
59
  actions: ITypedAction<T>[];
58
60
  selectedItems?: T[];
61
+ selectedItem?: T;
59
62
  wrapper?: ComponentClass | FunctionComponent;
60
63
  collapse?: WindowSize;
61
64
  noPrimary?: boolean;
@@ -3,7 +3,7 @@ import { ButtonVariant, Dropdown, DropdownItem, DropdownSeparator, DropdownToggl
3
3
  import { CircleIcon } from '@patternfly/react-icons';
4
4
  import { useCallback, useMemo, useState } from 'react';
5
5
  import { useBreakpoint } from '../components/useBreakPoint';
6
- import { TypedActionsButtons, TypedActionButton } from './TypedActionsButtons';
6
+ import { TypedActionButton, TypedActionsButtons } from './TypedActionsButtons';
7
7
  export var TypedActionType;
8
8
  (function (TypedActionType) {
9
9
  TypedActionType["seperator"] = "seperator";
@@ -13,7 +13,7 @@ export var TypedActionType;
13
13
  TypedActionType["dropdown"] = "dropdown";
14
14
  })(TypedActionType || (TypedActionType = {}));
15
15
  export function TypedActionsDropdown(props) {
16
- const { actions, label, isPrimary = false, selectedItems } = props;
16
+ const { actions, label, isPrimary = false, selectedItems, selectedItem } = props;
17
17
  const [dropdownOpen, setDropdownOpen] = useState(false);
18
18
  const hasItemActions = useMemo(() => !actions.every((action) => action.type !== TypedActionType.bulk), [actions]);
19
19
  const hasIcons = useMemo(() => actions.find((action) => action.type !== TypedActionType.seperator && action.icon !== undefined) !== undefined, [actions]);
@@ -24,12 +24,21 @@ export function TypedActionsDropdown(props) {
24
24
  ? {
25
25
  color: 'var(--pf-global--Color--light-100)',
26
26
  }
27
- : {}, children: label }), isOpen: dropdownOpen, isPlain: !label, dropdownItems: actions.map((action, index) => (_jsx(DropdownActionItem, { action: action, selectedItems: selectedItems ?? [], hasIcons: hasIcons, index: index }, 'label' in action ? action.label : `action-${index}`))), position: props.position, style: { zIndex: 201 } }));
27
+ : {}, children: label }), isOpen: dropdownOpen, isPlain: !label, dropdownItems: actions.map((action, index) => (_jsx(DropdownActionItem, { action: action, selectedItems: selectedItems ?? [], selectedItem: selectedItem, hasIcons: hasIcons, index: index }, 'label' in action ? action.label : `action-${index}`))), position: props.position, style: { zIndex: 201 } }));
28
28
  }
29
29
  export function DropdownActionItem(props) {
30
- const { action, selectedItems, hasIcons, index } = props;
31
- // TODO case TypedActionType.single?
30
+ const { action, selectedItems, selectedItem, hasIcons, index } = props;
32
31
  switch (action.type) {
32
+ case TypedActionType.single: {
33
+ let Icon = action.icon;
34
+ if (!Icon && hasIcons)
35
+ Icon = TransparentIcon;
36
+ const tooltip = action.tooltip;
37
+ const isDisabled = false;
38
+ return (_jsx(Tooltip, { content: tooltip, trigger: tooltip ? undefined : 'manual', children: _jsx(DropdownItem, { onClick: () => selectedItem && action.onClick(selectedItem), isAriaDisabled: isDisabled, icon: Icon ? (_jsx("span", { style: { paddingRight: 4 }, children: _jsx(Icon, {}) })) : undefined, style: {
39
+ color: action.isDanger && !isDisabled ? 'var(--pf-global--danger-color--100)' : undefined,
40
+ }, children: action.label }) }, action.label));
41
+ }
33
42
  case TypedActionType.button:
34
43
  case TypedActionType.bulk: {
35
44
  let Icon = action.icon;
@@ -32,7 +32,7 @@ export declare function DetailsList(props: {
32
32
  children?: ReactNode;
33
33
  }): JSX.Element;
34
34
  export declare function Detail(props: {
35
- label: string;
35
+ label?: string;
36
36
  children?: ReactNode;
37
37
  }): JSX.Element;
38
38
  export declare function DetailsSkeleton(): JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { DescriptionList, DescriptionListDescription, DescriptionListGroup, DescriptionListTerm, Skeleton, Split, SplitItem, Stack, } from '@patternfly/react-core';
2
+ import { DescriptionList, DescriptionListDescription, DescriptionListGroup, DescriptionListTerm, Skeleton, Split, SplitItem, Stack, Text, } from '@patternfly/react-core';
3
3
  import { Link } from 'react-router-dom';
4
4
  import { CopyCell, SinceCell } from '../PageCells';
5
5
  import { useSettings } from '../Settings';
@@ -61,7 +61,7 @@ export function DetailsList(props) {
61
61
  export function Detail(props) {
62
62
  if (!props.children)
63
63
  return _jsx(_Fragment, {});
64
- return (_jsxs(DescriptionListGroup, { children: [_jsx(DescriptionListTerm, { children: props.label }), _jsx(DescriptionListDescription, { id: props.label.toLowerCase().split(' ').join('-'), children: props.children })] }));
64
+ return (_jsxs(DescriptionListGroup, { children: [props.label && (_jsx(DescriptionListTerm, { children: _jsx(Text, { component: "small", style: { opacity: 0.7 }, children: props.label }) })), _jsx(DescriptionListDescription, { id: props.label?.toLowerCase().split(' ').join('-'), children: props.children })] }));
65
65
  }
66
66
  export function DetailsSkeleton() {
67
67
  return (_jsxs(Stack, { hasGutter: true, children: [_jsx(Skeleton, {}), _jsx(Skeleton, {}), _jsx(Skeleton, {}), _jsx(Skeleton, {})] }));
@@ -11,3 +11,13 @@ export declare const pfDanger = "var(--pf-global--danger-color--100)";
11
11
  export declare const pfWarning = "var(--pf-global--warning-color--100)";
12
12
  export declare const pfInfo = "var(--pf-global--info-color--100)";
13
13
  export declare const pfDisabled = "var(--pf-global--disabled-color--100)";
14
+ export declare enum LabelColorE {
15
+ blue = "blue",
16
+ cyan = "cyan",
17
+ green = "green",
18
+ orange = "orange",
19
+ purple = "purple",
20
+ red = "red",
21
+ grey = "grey"
22
+ }
23
+ export declare type LabelColor = 'blue' | 'cyan' | 'green' | 'orange' | 'purple' | 'red' | 'grey';
@@ -26,3 +26,13 @@ export const pfDanger = 'var(--pf-global--danger-color--100)';
26
26
  export const pfWarning = 'var(--pf-global--warning-color--100)';
27
27
  export const pfInfo = 'var(--pf-global--info-color--100)';
28
28
  export const pfDisabled = 'var(--pf-global--disabled-color--100)';
29
+ export var LabelColorE;
30
+ (function (LabelColorE) {
31
+ LabelColorE["blue"] = "blue";
32
+ LabelColorE["cyan"] = "cyan";
33
+ LabelColorE["green"] = "green";
34
+ LabelColorE["orange"] = "orange";
35
+ LabelColorE["purple"] = "purple";
36
+ LabelColorE["red"] = "red";
37
+ LabelColorE["grey"] = "grey";
38
+ })(LabelColorE || (LabelColorE = {}));
package/mjs/index.d.ts CHANGED
@@ -6,7 +6,6 @@ export * from './components/Help';
6
6
  export * from './components/patternfly-colors';
7
7
  export * from './components/useBreakPoint';
8
8
  export * from './PageBody';
9
- export * from './PageCatalog';
10
9
  export * from './PageCells';
11
10
  export * from './PageDataList';
12
11
  export * from './PageDialog';
@@ -15,6 +14,7 @@ export * from './PageFramework';
15
14
  export * from './PageHeader';
16
15
  export * from './PageLayout';
17
16
  export * from './PageTable';
17
+ export * from './PageTableCards';
18
18
  export * from './PageTabs';
19
19
  export * from './PageToolbar';
20
20
  export * from './TypedActions';
package/mjs/index.js CHANGED
@@ -6,7 +6,6 @@ export * from './components/Help';
6
6
  export * from './components/patternfly-colors';
7
7
  export * from './components/useBreakPoint';
8
8
  export * from './PageBody';
9
- export * from './PageCatalog';
10
9
  export * from './PageCells';
11
10
  export * from './PageDataList';
12
11
  export * from './PageDialog';
@@ -15,6 +14,7 @@ export * from './PageFramework';
15
14
  export * from './PageHeader';
16
15
  export * from './PageLayout';
17
16
  export * from './PageTable';
17
+ export * from './PageTableCards';
18
18
  export * from './PageTabs';
19
19
  export * from './PageToolbar';
20
20
  export * from './TypedActions';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ansible/ansible-ui-framework",
3
3
  "description": "Framework for building consistent responsive web applications using PatternFly.",
4
- "version": "0.0.232",
4
+ "version": "0.0.234",
5
5
  "author": "Red Hat",
6
6
  "license": "MIT",
7
7
  "repository": {