@ansible/ansible-ui-framework 0.0.190

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/cjs/framework/BulkActionDialog.js +217 -0
  3. package/cjs/framework/BulkProgressDialog.js +240 -0
  4. package/cjs/framework/FilterDrawer.js +64 -0
  5. package/cjs/framework/PageBody.js +47 -0
  6. package/cjs/framework/PageCatalog.js +178 -0
  7. package/cjs/framework/PageCells.js +141 -0
  8. package/cjs/framework/PageColumnModal.js +130 -0
  9. package/cjs/framework/PageDataList.js +61 -0
  10. package/cjs/framework/PageDialog.js +28 -0
  11. package/cjs/framework/PageForm.js +376 -0
  12. package/cjs/framework/PageFramework.js +11 -0
  13. package/cjs/framework/PageHeader.js +96 -0
  14. package/cjs/framework/PageLayout.js +41 -0
  15. package/cjs/framework/PagePagination.js +28 -0
  16. package/cjs/framework/PageTable.js +205 -0
  17. package/cjs/framework/PageTabs.js +82 -0
  18. package/cjs/framework/PageToolbar.js +209 -0
  19. package/cjs/framework/Settings.js +122 -0
  20. package/cjs/framework/TypedActions.js +303 -0
  21. package/cjs/framework/components/BulkSelector.js +89 -0
  22. package/cjs/framework/components/Collapse.js +22 -0
  23. package/cjs/framework/components/DetailInfo.js +23 -0
  24. package/cjs/framework/components/Details.js +88 -0
  25. package/cjs/framework/components/Dotted.js +19 -0
  26. package/cjs/framework/components/DropdownControlled.js +28 -0
  27. package/cjs/framework/components/ErrorBoundary.js +45 -0
  28. package/cjs/framework/components/Grid.js +64 -0
  29. package/cjs/framework/components/Help.js +24 -0
  30. package/cjs/framework/components/IconWrapper.js +55 -0
  31. package/cjs/framework/components/LoadingPage.js +14 -0
  32. package/cjs/framework/components/Masonry.js +113 -0
  33. package/cjs/framework/components/Scrollable.js +87 -0
  34. package/cjs/framework/components/SingleSelect.js +70 -0
  35. package/cjs/framework/components/patternfly-colors.js +32 -0
  36. package/cjs/framework/components/useBreakPoint.js +145 -0
  37. package/cjs/framework/components/useOpen.js +36 -0
  38. package/cjs/framework/components/useWindowLocation.js +70 -0
  39. package/cjs/framework/index.js +39 -0
  40. package/cjs/framework/useFrameworkTranslations.js +38 -0
  41. package/cjs/framework/useSelectDialog.js +81 -0
  42. package/cjs/framework/useSelectMultipleDialog.js +62 -0
  43. package/cjs/framework/useTableItems.js +485 -0
  44. package/cjs/framework/useView.js +155 -0
  45. package/cjs/framework/utils/compare.js +59 -0
  46. package/cjs/framework/utils/download-file.js +23 -0
  47. package/cjs/framework/utils/random-string.js +17 -0
  48. package/cjs/frontend/controller/access/organizations/Organization.js +2 -0
  49. package/mjs/framework/BulkActionDialog.d.ts +25 -0
  50. package/mjs/framework/BulkActionDialog.js +104 -0
  51. package/mjs/framework/BulkProgressDialog.d.ts +20 -0
  52. package/mjs/framework/BulkProgressDialog.js +131 -0
  53. package/mjs/framework/FilterDrawer.d.ts +8 -0
  54. package/mjs/framework/FilterDrawer.js +24 -0
  55. package/mjs/framework/PageBody.d.ts +4 -0
  56. package/mjs/framework/PageBody.js +29 -0
  57. package/mjs/framework/PageCatalog.d.ts +113 -0
  58. package/mjs/framework/PageCatalog.js +140 -0
  59. package/mjs/framework/PageCells.d.ts +35 -0
  60. package/mjs/framework/PageCells.js +102 -0
  61. package/mjs/framework/PageColumnModal.d.ts +7 -0
  62. package/mjs/framework/PageColumnModal.js +64 -0
  63. package/mjs/framework/PageDataList.d.ts +46 -0
  64. package/mjs/framework/PageDataList.js +45 -0
  65. package/mjs/framework/PageDialog.d.ts +10 -0
  66. package/mjs/framework/PageDialog.js +12 -0
  67. package/mjs/framework/PageForm.d.ts +147 -0
  68. package/mjs/framework/PageForm.js +316 -0
  69. package/mjs/framework/PageFramework.d.ts +4 -0
  70. package/mjs/framework/PageFramework.js +7 -0
  71. package/mjs/framework/PageHeader.d.ts +45 -0
  72. package/mjs/framework/PageHeader.js +80 -0
  73. package/mjs/framework/PageLayout.d.ts +15 -0
  74. package/mjs/framework/PageLayout.js +23 -0
  75. package/mjs/framework/PagePagination.d.ts +10 -0
  76. package/mjs/framework/PagePagination.js +22 -0
  77. package/mjs/framework/PageTable.d.ts +68 -0
  78. package/mjs/framework/PageTable.js +170 -0
  79. package/mjs/framework/PageTabs.d.ts +15 -0
  80. package/mjs/framework/PageTabs.js +45 -0
  81. package/mjs/framework/PageToolbar.d.ts +57 -0
  82. package/mjs/framework/PageToolbar.js +148 -0
  83. package/mjs/framework/Settings.d.ts +19 -0
  84. package/mjs/framework/Settings.js +87 -0
  85. package/mjs/framework/TypedActions.d.ts +80 -0
  86. package/mjs/framework/TypedActions.js +251 -0
  87. package/mjs/framework/components/BulkSelector.d.ts +11 -0
  88. package/mjs/framework/components/BulkSelector.js +56 -0
  89. package/mjs/framework/components/Collapse.d.ts +5 -0
  90. package/mjs/framework/components/Collapse.js +7 -0
  91. package/mjs/framework/components/DetailInfo.d.ts +5 -0
  92. package/mjs/framework/components/DetailInfo.js +8 -0
  93. package/mjs/framework/components/Details.d.ts +38 -0
  94. package/mjs/framework/components/Details.js +68 -0
  95. package/mjs/framework/components/Dotted.d.ts +4 -0
  96. package/mjs/framework/components/Dotted.js +4 -0
  97. package/mjs/framework/components/DropdownControlled.d.ts +4 -0
  98. package/mjs/framework/components/DropdownControlled.js +8 -0
  99. package/mjs/framework/components/ErrorBoundary.d.ts +15 -0
  100. package/mjs/framework/components/ErrorBoundary.js +25 -0
  101. package/mjs/framework/components/Grid.d.ts +6 -0
  102. package/mjs/framework/components/Grid.js +27 -0
  103. package/mjs/framework/components/Help.d.ts +5 -0
  104. package/mjs/framework/components/Help.js +9 -0
  105. package/mjs/framework/components/IconWrapper.d.ts +8 -0
  106. package/mjs/framework/components/IconWrapper.js +40 -0
  107. package/mjs/framework/components/LoadingPage.d.ts +6 -0
  108. package/mjs/framework/components/LoadingPage.js +9 -0
  109. package/mjs/framework/components/Masonry.d.ts +6 -0
  110. package/mjs/framework/components/Masonry.js +69 -0
  111. package/mjs/framework/components/Scrollable.d.ts +7 -0
  112. package/mjs/framework/components/Scrollable.js +60 -0
  113. package/mjs/framework/components/SingleSelect.d.ts +18 -0
  114. package/mjs/framework/components/SingleSelect.js +37 -0
  115. package/mjs/framework/components/patternfly-colors.d.ts +13 -0
  116. package/mjs/framework/components/patternfly-colors.js +28 -0
  117. package/mjs/framework/components/useBreakPoint.d.ts +5 -0
  118. package/mjs/framework/components/useBreakPoint.js +118 -0
  119. package/mjs/framework/components/useOpen.d.ts +4 -0
  120. package/mjs/framework/components/useOpen.js +16 -0
  121. package/mjs/framework/components/useWindowLocation.d.ts +6 -0
  122. package/mjs/framework/components/useWindowLocation.js +48 -0
  123. package/mjs/framework/index.d.ts +23 -0
  124. package/mjs/framework/index.js +23 -0
  125. package/mjs/framework/useFrameworkTranslations.d.ts +17 -0
  126. package/mjs/framework/useFrameworkTranslations.js +22 -0
  127. package/mjs/framework/useSelectDialog.d.ts +30 -0
  128. package/mjs/framework/useSelectDialog.js +49 -0
  129. package/mjs/framework/useSelectMultipleDialog.d.ts +21 -0
  130. package/mjs/framework/useSelectMultipleDialog.js +29 -0
  131. package/mjs/framework/useTableItems.d.ts +76 -0
  132. package/mjs/framework/useTableItems.js +371 -0
  133. package/mjs/framework/useView.d.ts +15 -0
  134. package/mjs/framework/useView.js +108 -0
  135. package/mjs/framework/utils/compare.d.ts +3 -0
  136. package/mjs/framework/utils/compare.js +53 -0
  137. package/mjs/framework/utils/download-file.d.ts +2 -0
  138. package/mjs/framework/utils/download-file.js +18 -0
  139. package/mjs/framework/utils/random-string.d.ts +1 -0
  140. package/mjs/framework/utils/random-string.js +12 -0
  141. package/mjs/frontend/controller/access/organizations/Organization.d.ts +44 -0
  142. package/mjs/frontend/controller/access/organizations/Organization.js +1 -0
  143. package/package.json +39 -0
@@ -0,0 +1,170 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Button, EmptyState, EmptyStateBody, EmptyStateIcon, EmptyStateSecondaryActions, EmptyStateVariant, Skeleton, Title, } from '@patternfly/react-core';
3
+ import { ExclamationCircleIcon, PlusCircleIcon, SearchIcon } from '@patternfly/react-icons';
4
+ import { ActionsColumn, TableComposable, Tbody, Td, Th, Thead, Tr, } from '@patternfly/react-table';
5
+ import useResizeObserver from '@react-hook/resize-observer';
6
+ import { Fragment, useCallback, useEffect, useRef, useState, } from 'react';
7
+ import { useBreakpoint } from './components/useBreakPoint';
8
+ import { PageBody } from './PageBody';
9
+ import { useColumnModal } from './PageColumnModal';
10
+ import { PageHeader } from './PageHeader';
11
+ import { PageLayout } from './PageLayout';
12
+ import { PagePagination } from './PagePagination';
13
+ import { PageTableToolbar } from './PageToolbar';
14
+ import { useSettings } from './Settings';
15
+ import { TypedActionType, useTypedActionsToTableActions } from './TypedActions';
16
+ export function TablePage(props) {
17
+ return (_jsx(_Fragment, { children: _jsxs(PageLayout, { children: [_jsx(PageHeader, { ...props }), _jsx(PageBody, { children: _jsx(PageTable, { ...props }) })] }) }));
18
+ }
19
+ export function PageTable(props) {
20
+ const { tableColumns, pageItems, selectItem, unselectItem, isSelected, keyFn, rowActions, toolbarActions, itemCount, perPage, clearAllFilters, filters, error, onSelect, unselectAll, } = props;
21
+ let { t } = props;
22
+ t = t ? t : (t) => t;
23
+ const showSelect = props.showSelect ||
24
+ toolbarActions?.find((toolbarAction) => TypedActionType.bulk === toolbarAction.type) !==
25
+ undefined;
26
+ const containerRef = useRef(null);
27
+ const [scroll, setScroll] = useState({
28
+ left: 0,
29
+ right: 0,
30
+ top: 0,
31
+ bottom: 0,
32
+ });
33
+ const updateScroll = useCallback((div) => {
34
+ if (!div)
35
+ return;
36
+ setScroll({
37
+ top: div.scrollTop,
38
+ bottom: div.scrollHeight - div.clientHeight - div.scrollTop,
39
+ left: div.scrollLeft,
40
+ right: div.scrollWidth - div.clientWidth - div.scrollLeft,
41
+ });
42
+ }, []);
43
+ const onScroll = useCallback((event) => updateScroll(event.currentTarget), [updateScroll]);
44
+ useResizeObserver(containerRef, () => updateScroll(containerRef.current));
45
+ useEffect(() => updateScroll(containerRef.current), [updateScroll]);
46
+ const settings = useSettings();
47
+ const { openColumnModal, columnModal, managedColumns } = useColumnModal(tableColumns);
48
+ if (error) {
49
+ return (_jsx("div", { style: {
50
+ backgroundColor: settings.theme === 'dark' ? 'var(--pf-global--BackgroundColor--300)' : undefined,
51
+ height: '100%',
52
+ }, children: _jsxs(EmptyState, { variant: EmptyStateVariant.small, style: {
53
+ paddingTop: 64,
54
+ }, children: [_jsx(EmptyStateIcon, { icon: ExclamationCircleIcon, color: "var(--pf-global--danger-color--100)" }), _jsx(Title, { headingLevel: "h2", size: "lg", children: props.errorStateTitle }), _jsx(EmptyStateBody, { children: error.message })] }) }));
55
+ }
56
+ if (itemCount === 0 && Object.keys(filters ?? {}).length === 0) {
57
+ 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
+ }
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 })] }));
64
+ }
65
+ function TableHead(props) {
66
+ const { tableColumns: columns, rowActions: itemActions, sort, setSort, sortDirection, setSortDirection, showSelect, onSelect, } = props;
67
+ const settings = useSettings();
68
+ const getColumnSort = useCallback((columnIndex, column) => {
69
+ if (!column.sort)
70
+ return undefined;
71
+ return {
72
+ onSort: (_event, _columnIndex, sortByDirection) => {
73
+ if (column.sort) {
74
+ setSort?.(column.sort);
75
+ setSortDirection?.(sortByDirection);
76
+ }
77
+ },
78
+ sortBy: {
79
+ index: column.sort === sort ? columnIndex : undefined,
80
+ direction: column.sort === sort ? sortDirection : undefined,
81
+ defaultDirection: column.defaultSortDirection,
82
+ },
83
+ columnIndex,
84
+ };
85
+ }, [setSort, setSortDirection, sort, sortDirection]);
86
+ return (_jsx(Thead, { children: _jsxs(Tr, { children: [(showSelect || onSelect) && (_jsx(Th, { isStickyColumn: true, style: {
87
+ width: '0%',
88
+ backgroundColor: settings.theme === 'dark' ? 'var(--pf-global--BackgroundColor--300)' : undefined,
89
+ }, stickyMinWidth: "45px", hasRightBorder: props.scrollLeft, children: "\u00A0" })), columns
90
+ .filter((column) => column.enabled !== false)
91
+ .map((column, index) => {
92
+ return (_jsx(Th, { modifier: "fitContent", style: {
93
+ minWidth: column.minWidth,
94
+ maxWidth: column.maxWidth,
95
+ backgroundColor: settings.theme === 'dark'
96
+ ? 'var(--pf-global--BackgroundColor--300)'
97
+ : undefined,
98
+ }, sort: getColumnSort(index, column), children: column.header }, column.header));
99
+ }), itemActions !== undefined && (_jsx(Th, { style: {
100
+ paddingRight: 8,
101
+ paddingLeft: 0,
102
+ width: '0%',
103
+ right: 0,
104
+ backgroundColor: settings.theme === 'dark' ? 'var(--pf-global--BackgroundColor--300)' : undefined,
105
+ }, isStickyColumn: true, stickyMinWidth: "45px", className: props.scrollRight ? 'pf-m-border-left' : undefined, children: "\u00A0" }))] }) }));
106
+ }
107
+ function TableRow(props) {
108
+ const { columns, selectItem, unselectItem, unselectAll, isItemSelected, item, rowActions, rowIndex, showSelect, onSelect, } = props;
109
+ const md = useBreakpoint('xl');
110
+ return (_jsxs(Tr, { className: isItemSelected ? 'selected' : undefined,
111
+ // style={{ backgroundColor: theme === ThemeE.Dark ? 'transparent' : undefined }}
112
+ isRowSelected: isItemSelected, style: { boxShadow: 'unset' }, children: [showSelect && (_jsx(Th, { select: isItemSelected !== undefined
113
+ ? {
114
+ onSelect: (_event, isSelecting) => {
115
+ if (isSelecting) {
116
+ selectItem?.(item);
117
+ }
118
+ else {
119
+ unselectItem?.(item);
120
+ }
121
+ },
122
+ isSelected: isItemSelected,
123
+ }
124
+ : undefined, style: { width: '0%', paddingLeft: md ? undefined : 20, paddingRight: 16 }, isStickyColumn: true, stickyMinWidth: "0px", hasRightBorder: props.scrollLeft })), onSelect && (_jsx(Td, { select: {
125
+ rowIndex,
126
+ onSelect: () => {
127
+ unselectAll?.();
128
+ selectItem?.(item);
129
+ onSelect?.(item);
130
+ },
131
+ isSelected: isItemSelected ?? false,
132
+ // disable: !isRepoSelectable(repo),
133
+ variant: 'radio',
134
+ }, style: {
135
+ width: '0%',
136
+ paddingLeft: md ? undefined : 20,
137
+ position: 'sticky',
138
+ left: 0,
139
+ background: 'var(--pf-c-table__sticky-column--BackgroundColor)',
140
+ zIndex: 1,
141
+ } })), _jsx(TableCells, { rowIndex: rowIndex, columns: columns, item: item, rowActions: rowActions, scrollLeft: props.scrollLeft, scrollRight: props.scrollRight })] }));
142
+ }
143
+ function TableCells(props) {
144
+ const { columns, item, rowActions, rowIndex } = props;
145
+ const actions = useTypedActionsToTableActions({
146
+ actions: rowActions ?? [],
147
+ item,
148
+ collapse: 'xxl',
149
+ });
150
+ return (_jsxs(Fragment, { children: [columns
151
+ .filter((column) => column.enabled !== false)
152
+ .map((column) => {
153
+ return (_jsx(Td, { dataLabel: column.header, modifier: "nowrap", children: column.cell(item) }, column.header));
154
+ }), actions !== undefined && actions.length > 0 && (_jsx(Th
155
+ // isActionCell
156
+ , {
157
+ // isActionCell
158
+ style: {
159
+ zIndex: 100 - rowIndex,
160
+ paddingRight: 8,
161
+ paddingLeft: 8,
162
+ width: '0%',
163
+ right: 0,
164
+ // display: 'flex',
165
+ }, isStickyColumn: true, stickyMinWidth: "0px", className: props.scrollRight ? 'pf-m-border-left' : undefined, children: _jsx("div", { style: { display: 'flex' }, children: _jsx(ActionsColumn
166
+ // dropdownDirection="up" // TODO handle....
167
+ , {
168
+ // dropdownDirection="up" // TODO handle....
169
+ items: actions }) }) }))] }));
170
+ }
@@ -0,0 +1,15 @@
1
+ import { Dispatch, ReactNode, SetStateAction } from 'react';
2
+ export declare function PageTabs(props: {
3
+ children: ReactNode;
4
+ preComponents?: ReactNode;
5
+ postComponents?: ReactNode;
6
+ }): JSX.Element;
7
+ export declare function PageTab(props: {
8
+ title?: string;
9
+ children: ReactNode;
10
+ }): JSX.Element;
11
+ export declare function PageTabsOld(props: {
12
+ activeKey: string | number;
13
+ setActiveKey: Dispatch<SetStateAction<string | number>>;
14
+ children: ReactNode;
15
+ }): JSX.Element;
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Divider, Flex, FlexItem, PageSection, PageSectionTypes, Skeleton, Tab, Tabs, } from '@patternfly/react-core';
3
+ import { Children, isValidElement, useCallback, useState, } from 'react';
4
+ export function PageTabs(props) {
5
+ const [activeKey, setActiveKey] = useState(0);
6
+ const onSelect = useCallback((_, key) => setActiveKey(key), [setActiveKey]);
7
+ const children = Children.toArray(props.children);
8
+ const tabs = children.map((child, index) => {
9
+ if (isValidElement(child)) {
10
+ if (child.type === PageTab) {
11
+ const title = child.props.title;
12
+ return (_jsx(Tab, { title: title ? title : _jsx(Skeleton, { width: "60px" }), eventKey: index }, title ?? index));
13
+ }
14
+ }
15
+ return child;
16
+ });
17
+ const content = children[activeKey];
18
+ return (_jsxs(_Fragment, { children: [_jsx(PageSection, { type: PageSectionTypes.tabs, children: _jsxs(Flex, { spaceItems: { default: 'spaceItemsNone' }, children: [props.preComponents && (_jsxs(_Fragment, { children: [_jsx(FlexItem
19
+ // style={{ paddingLeft: 16 }}
20
+ , { children: props.preComponents }), _jsx(Divider, { orientation: { default: 'vertical' }, component: "div" })] })), _jsx(FlexItem, { grow: { default: 'grow' }, children: _jsx(Tabs, { activeKey: activeKey, onSelect: onSelect, inset: props.preComponents
21
+ ? undefined
22
+ : {
23
+ default: 'insetNone',
24
+ sm: 'insetNone',
25
+ md: 'insetNone',
26
+ lg: 'insetNone',
27
+ xl: 'insetSm',
28
+ ['2xl']: 'insetSm',
29
+ }, hasBorderBottom: false, children: tabs }) }), props.postComponents && (_jsxs(_Fragment, { children: [_jsx(Divider, { orientation: { default: 'vertical' } }), _jsx(FlexItem, { style: { paddingRight: 16 }, children: props.postComponents })] }))] }) }), _jsx(Divider, {}), content] }));
30
+ }
31
+ export function PageTab(props) {
32
+ return _jsx(_Fragment, { children: props.children });
33
+ }
34
+ export function PageTabsOld(props) {
35
+ const { activeKey, setActiveKey } = props;
36
+ const onSelect = useCallback((_, key) => setActiveKey(key), [setActiveKey]);
37
+ return (_jsx(PageSection, { type: PageSectionTypes.tabs, style: { flexGrow: 1 }, children: _jsx(Tabs, { activeKey: activeKey, onSelect: onSelect, inset: {
38
+ default: 'insetNone',
39
+ sm: 'insetNone',
40
+ md: 'insetNone',
41
+ lg: 'insetNone',
42
+ xl: 'insetSm',
43
+ ['2xl']: 'insetSm',
44
+ }, children: props.children }) }));
45
+ }
@@ -0,0 +1,57 @@
1
+ import { Dispatch, SetStateAction } from 'react';
2
+ import { ITypedAction } from './TypedActions';
3
+ export interface IItemFilter<T extends object> {
4
+ label: string;
5
+ type?: 'search' | 'filter';
6
+ options: {
7
+ label: string;
8
+ value: string;
9
+ }[];
10
+ filter: (item: T, values: string[]) => boolean;
11
+ }
12
+ export declare type SetFilterValues<T extends object> = (filter: IItemFilter<T>, values: string[]) => void;
13
+ export declare function toolbarActionsHaveBulkActions<T extends object>(actions?: ITypedAction<T>[]): boolean;
14
+ export interface IToolbarStringFilter {
15
+ key: string;
16
+ label: string;
17
+ type: 'string';
18
+ query: string;
19
+ placeholder?: string;
20
+ }
21
+ export interface IToolbarSelectFilter {
22
+ key: string;
23
+ label: string;
24
+ type: 'select';
25
+ options: {
26
+ label: string;
27
+ value: string;
28
+ }[];
29
+ query: string;
30
+ placeholder?: string;
31
+ }
32
+ export declare type IToolbarFilter = IToolbarStringFilter | IToolbarSelectFilter;
33
+ export declare type IFilterState = Record<string, string[] | undefined>;
34
+ export declare type PagetableToolbarProps<T extends object> = {
35
+ openColumnModal?: () => void;
36
+ keyFn: (item: T) => string | number;
37
+ itemCount?: number;
38
+ toolbarActions?: ITypedAction<T>[];
39
+ toolbarFilters?: IToolbarFilter[];
40
+ filters?: Record<string, string[]>;
41
+ setFilters?: Dispatch<SetStateAction<Record<string, string[]>>>;
42
+ clearAllFilters?: () => void;
43
+ page: number;
44
+ perPage: number;
45
+ setPage: (page: number) => void;
46
+ setPerPage: (perPage: number) => void;
47
+ isSelected?: (item: T) => boolean;
48
+ selectedItems?: T[];
49
+ selectItem?: (item: T) => void;
50
+ unselectItem?: (item: T) => void;
51
+ selectItems?: (items: T[]) => void;
52
+ unselectAll?: () => void;
53
+ onSelect?: (item: T) => void;
54
+ disableBorderBottom?: boolean;
55
+ showSelect?: boolean;
56
+ };
57
+ export declare function PageTableToolbar<T extends object>(props: PagetableToolbarProps<T>): JSX.Element;
@@ -0,0 +1,148 @@
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';
4
+ import { Fragment, useCallback, useState } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { BulkSelector } from './components/BulkSelector';
7
+ import { SingleSelect2 } from './components/SingleSelect';
8
+ import { useBreakpoint } from './components/useBreakPoint';
9
+ import { useSettings } from './Settings';
10
+ import { TypedActions, TypedActionType } from './TypedActions';
11
+ export function toolbarActionsHaveBulkActions(actions) {
12
+ if (!actions)
13
+ return false;
14
+ for (const action of actions) {
15
+ if (action.type === 'bulk')
16
+ return true;
17
+ }
18
+ return false;
19
+ }
20
+ export function PageTableToolbar(props) {
21
+ const { itemCount, page, perPage, setPage, setPerPage, toolbarFilters, selectedItems, filters, setFilters, clearAllFilters, openColumnModal, disableBorderBottom, } = props;
22
+ const sm = useBreakpoint('md');
23
+ let { toolbarActions } = props;
24
+ toolbarActions = toolbarActions ?? [];
25
+ const onSetPage = useCallback((_event, page) => setPage(page), [setPage]);
26
+ const onPerPageSelect = useCallback((_event, perPage) => setPerPage(perPage), [setPerPage]);
27
+ const showSearchAndFilters = toolbarFilters !== undefined;
28
+ const showToolbarActions = toolbarActions !== undefined && toolbarActions.length > 0;
29
+ const showSelect = props.showSelect === true ||
30
+ (selectedItems !== undefined &&
31
+ toolbarActions &&
32
+ toolbarActions.find((toolbarAction) => TypedActionType.bulk === toolbarAction.type));
33
+ const showToolbar = showSelect || showSearchAndFilters || showToolbarActions;
34
+ const [selectedFilter, setSeletedFilter] = useState(() => toolbarFilters ? (toolbarFilters?.length > 0 ? toolbarFilters[0].key : '') : '');
35
+ const settings = useSettings();
36
+ if (!showToolbar) {
37
+ return _jsx(Fragment, {});
38
+ }
39
+ if (itemCount === undefined) {
40
+ return (_jsx(Toolbar, { style: {
41
+ borderBottom: disableBorderBottom
42
+ ? undefined
43
+ : 'thin solid var(--pf-global--BorderColor--100)',
44
+ paddingBottom: sm ? undefined : 8,
45
+ paddingTop: sm ? undefined : 8,
46
+ backgroundColor: settings.theme === 'dark' ? 'var(--pf-global--BackgroundColor--300)' : undefined,
47
+ }, children: _jsx(ToolbarContent, { children: _jsx(ToolbarItem, { style: { width: '100%' }, children: _jsx(Skeleton, { height: "36px" }) }) }) }));
48
+ }
49
+ return (_jsx(Toolbar, { clearAllFilters: clearAllFilters, style: {
50
+ borderBottom: disableBorderBottom
51
+ ? undefined
52
+ : 'thin solid var(--pf-global--BorderColor--100)',
53
+ paddingBottom: sm ? undefined : 8,
54
+ paddingTop: sm ? undefined : 8,
55
+ backgroundColor: settings.theme === 'dark' ? 'var(--pf-global--BackgroundColor--300)' : undefined,
56
+ }, children: _jsxs(ToolbarContent, { children: [showSelect && (_jsx(ToolbarGroup, { children: _jsx(ToolbarItem, { variant: "bulk-select", children: _jsx(BulkSelector, { ...props }) }) })), toolbarFilters && toolbarFilters.length > 0 && (_jsx(ToolbarToggleGroup, { toggleIcon: _jsx(FilterIcon, {}), breakpoint: "md", style: { zIndex: 302 }, children: _jsxs(ToolbarGroup, { variant: "filter-group", children: [_jsx(ToolbarItem, { children: _jsx(SingleSelect2, { onChange: setSeletedFilter, value: selectedFilter, children: toolbarFilters.map((filter) => (_jsx(SelectOption, { value: filter.key, children: _jsxs(Flex, { spaceItems: { default: 'spaceItemsNone' }, alignItems: { default: 'alignItemsCenter' }, flexWrap: { default: 'nowrap' }, children: [_jsx(FlexItem, { style: { paddingLeft: 4, paddingRight: 8 }, children: _jsx(FilterIcon, {}) }), _jsx(FlexItem, { children: filter.label })] }) }, filter.key))) }) }), _jsx(ToolbarItem, { children: _jsx(ToolbarFilterInput, { filter: toolbarFilters.find((filter) => filter.key === selectedFilter), addFilter: (value) => {
57
+ let values = filters?.[selectedFilter];
58
+ if (!values)
59
+ values = [];
60
+ if (!values.includes(value))
61
+ values.push(value);
62
+ setFilters?.({ ...filters, [selectedFilter]: values });
63
+ }, removeFilter: (value) => {
64
+ let values = filters?.[selectedFilter];
65
+ if (!values)
66
+ values = [];
67
+ values = values.filter((v) => v !== value);
68
+ setFilters?.({ ...filters, [selectedFilter]: values });
69
+ }, values: filters?.[selectedFilter] ?? [] }) }), toolbarFilters.map((filter) => {
70
+ const values = filters?.[filter.key] ?? [];
71
+ return (_jsx(ToolbarFilter, { categoryName: filter.label, chips: values.map((value) => {
72
+ return 'options' in filter
73
+ ? filter.options.find((o) => o.value === value)?.label ?? value
74
+ : value;
75
+ }), deleteChip: (_group, value) => {
76
+ setFilters?.((filters) => {
77
+ //TODO bug here where value is actually select filter option label... need to map
78
+ const newState = { ...filters };
79
+ value = typeof value === 'string' ? value : value.key;
80
+ let values = filters[filter.key];
81
+ if (values) {
82
+ values = values.filter((v) => v !== value);
83
+ if (values.length === 0) {
84
+ delete newState[filter.key];
85
+ }
86
+ else {
87
+ newState[filter.key] = values;
88
+ }
89
+ }
90
+ return newState;
91
+ });
92
+ }, deleteChipGroup: () => {
93
+ setFilters?.((filters) => {
94
+ const newState = { ...filters };
95
+ delete newState[filter.key];
96
+ return newState;
97
+ });
98
+ }, showToolbarItem: false, children: _jsx(_Fragment, {}) }, filter.label));
99
+ })] }) })), _jsxs(ToolbarGroup, { variant: "button-group", style: { zIndex: 302 }, children: [_jsx(TypedActions, { actions: toolbarActions, selectedItems: selectedItems, wrapper: ToolbarItem }), 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 } }) })] }) }));
100
+ }
101
+ function ToolbarFilterInput(props) {
102
+ const { filter } = props;
103
+ switch (filter?.type) {
104
+ case 'string':
105
+ return _jsx(ToolbarTextFilter, { ...props, placeholder: filter.placeholder });
106
+ case 'select':
107
+ return (_jsx(ToolbarSelectFilter, { ...props, options: filter.options, placeholder: filter.placeholder }));
108
+ }
109
+ return _jsx(_Fragment, {});
110
+ }
111
+ function ToolbarTextFilter(props) {
112
+ const [value, setValue] = useState('');
113
+ return (_jsxs(InputGroup, { children: [_jsxs(TextInputGroup, { style: { minWidth: 220 }, children: [_jsx(TextInputGroupMain
114
+ // ref={ref}
115
+ , {
116
+ // ref={ref}
117
+ value: value, onChange: setValue, onKeyUp: (event) => {
118
+ if (value && event.key === 'Enter') {
119
+ props.addFilter(value);
120
+ setValue('');
121
+ // ref.current?.focus() // Does not work because PF does not expose ref
122
+ }
123
+ }, placeholder: props.placeholder }), value !== '' && (_jsx(TextInputGroupUtilities, { children: _jsx(Button, { variant: "plain", "aria-label": "add filter", onClick: () => setValue(''), style: { opacity: value ? undefined : 0 },
124
+ // tabIndex={value ? undefined : -1}
125
+ tabIndex: -1, children: _jsx(TimesIcon, {}) }) }))] }), !value ? (_jsx(_Fragment, {})) : (
126
+ // <Button variant={'control'} aria-label="add filter">
127
+ // <SearchIcon />
128
+ // </Button>
129
+ _jsx(Button, { variant: value ? 'primary' : 'control', "aria-label": "add filter", onClick: () => {
130
+ props.addFilter(value);
131
+ setValue('');
132
+ }, children: _jsx(ArrowRightIcon, {}) }))] }));
133
+ }
134
+ function ToolbarSelectFilter(props) {
135
+ const { t } = useTranslation();
136
+ const { addFilter, removeFilter, options, values } = props;
137
+ const [open, setOpen] = useState(false);
138
+ const onSelect = useCallback((e, value) => {
139
+ if (values.includes(value.toString())) {
140
+ removeFilter(value.toString());
141
+ }
142
+ else {
143
+ addFilter(value.toString());
144
+ }
145
+ }, [addFilter, removeFilter, values]);
146
+ const selections = values;
147
+ return (_jsx(_Fragment, { children: _jsx(Select, { variant: SelectVariant.checkbox, isOpen: open, onToggle: setOpen, selections: selections, onSelect: onSelect, placeholderText: values.length ? t('Selected') : _jsx("span", { style: { opacity: 0.7 }, children: props.placeholder }), children: options.map((option) => (_jsx(SelectOption, { id: option.value, value: option.value, children: option.label }, option.value))) }) }));
148
+ }
@@ -0,0 +1,19 @@
1
+ import { ReactNode } from 'react';
2
+ export interface Settings {
3
+ theme?: 'system' | 'light' | 'dark';
4
+ tableLayout?: 'compact' | 'comfortable';
5
+ formColumns?: 'single' | 'multiple';
6
+ formLayout?: 'vertical' | 'horizontal';
7
+ borders?: boolean;
8
+ }
9
+ export declare const SettingsContext: import("react").Context<[Settings, (settings: Settings) => void]>;
10
+ export declare function useSettings(): Settings;
11
+ export declare function SettingsProvider(props: {
12
+ children?: ReactNode;
13
+ }): JSX.Element;
14
+ export declare function useSettingsDialog(t: (t: string) => string): () => void;
15
+ export declare function SettingsDialog(props: {
16
+ open: boolean;
17
+ setOpen: (open: boolean) => void;
18
+ t: (t: string) => string;
19
+ }): JSX.Element;
@@ -0,0 +1,87 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, Form, Modal, ModalVariant, SelectOption } from '@patternfly/react-core';
3
+ import { createContext, useCallback, useContext, useEffect, useState } from 'react';
4
+ import { SingleSelect } from './components/SingleSelect';
5
+ import { usePageDialog } from './PageDialog';
6
+ export const SettingsContext = createContext([
7
+ {},
8
+ () => null,
9
+ ]);
10
+ export function useSettings() {
11
+ const [settings] = useContext(SettingsContext);
12
+ return settings;
13
+ }
14
+ export function SettingsProvider(props) {
15
+ const [settings, setSettingsState] = useState(() => {
16
+ const settings = {
17
+ theme: localStorage.getItem('theme'),
18
+ tableLayout: localStorage.getItem('tableLayout'),
19
+ formColumns: localStorage.getItem('formColumns'),
20
+ formLayout: localStorage.getItem('formLayout'),
21
+ borders: localStorage.getItem('borders') !== 'false',
22
+ };
23
+ const activeTheme = settings.theme !== 'dark' && settings.theme !== 'light'
24
+ ? window.matchMedia('(prefers-color-scheme: dark)').matches
25
+ ? 'dark'
26
+ : 'light'
27
+ : settings.theme;
28
+ if (activeTheme === 'dark') {
29
+ document.documentElement.classList.add('pf-theme-dark');
30
+ }
31
+ else {
32
+ document.documentElement.classList.remove('pf-theme-dark');
33
+ }
34
+ return settings;
35
+ });
36
+ const setSettings = useCallback((settings) => {
37
+ localStorage.setItem('theme', settings.theme ?? 'system');
38
+ localStorage.setItem('tableLayout', settings.tableLayout ?? 'comfortable');
39
+ localStorage.setItem('formColumns', settings.formColumns ?? 'multiple');
40
+ localStorage.setItem('formLayout', settings.formLayout ?? 'vertical');
41
+ localStorage.setItem('borders', settings.borders ? 'true' : 'false');
42
+ setSettingsState(settings);
43
+ const activeTheme = settings.theme === 'system'
44
+ ? window.matchMedia('(prefers-color-scheme: dark)').matches
45
+ ? 'dark'
46
+ : 'light'
47
+ : settings.theme;
48
+ if (activeTheme === 'dark') {
49
+ document.documentElement.classList.add('pf-theme-dark');
50
+ }
51
+ else {
52
+ document.documentElement.classList.remove('pf-theme-dark');
53
+ }
54
+ }, []);
55
+ return (_jsx(SettingsContext.Provider, { value: [settings, setSettings], children: props.children }));
56
+ }
57
+ export function useSettingsDialog(t) {
58
+ const [open, setOpen] = useState(false);
59
+ const openSetting = useCallback(() => setOpen(true), []);
60
+ const [_, setDialog] = usePageDialog();
61
+ useEffect(() => {
62
+ if (open) {
63
+ setDialog(_jsx(SettingsDialog, { open: open, setOpen: setOpen, t: t }));
64
+ }
65
+ else {
66
+ setDialog(undefined);
67
+ }
68
+ }, [open, setDialog, t]);
69
+ return openSetting;
70
+ }
71
+ export function SettingsDialog(props) {
72
+ const onClose = () => props.setOpen(false);
73
+ const [settings, setSettings] = useContext(SettingsContext);
74
+ const { t } = props;
75
+ return (_jsx(Modal, { title: "Settings", isOpen: props.open, onClose: onClose, variant: ModalVariant.medium, tabIndex: 0, actions: [
76
+ _jsx(Button, { variant: "primary", onClick: onClose, children: t('Close') }, "close"),
77
+ ], children: _jsxs(Form, { isHorizontal: settings.formLayout === 'horizontal', children: [_jsxs(SingleSelect, { label: "Theme", value: settings.theme ?? 'system', onChange: (theme) => setSettings({ ...settings, theme: theme }), children: [_jsx(SelectOption, { value: "system", children: t('System default') }), _jsx(SelectOption, { value: "light", children: t('Light') }), _jsx(SelectOption, { value: "dark", children: t('Dark') })] }), _jsxs(SingleSelect, { label: "Table Layout", value: settings.tableLayout ?? 'comfortable', onChange: (tableLayout) => setSettings({
78
+ ...settings,
79
+ tableLayout: tableLayout,
80
+ }), children: [_jsx(SelectOption, { value: "comfortable", children: t('Comfortable') }), _jsx(SelectOption, { value: "compact", children: t('Compact') })] }), _jsxs(SingleSelect, { label: "Form Columns", value: settings.formColumns ?? 'multiple', onChange: (formColumns) => setSettings({
81
+ ...settings,
82
+ formColumns: formColumns,
83
+ }), children: [_jsx(SelectOption, { value: "multiple", children: t('Multiple columns') }), _jsx(SelectOption, { value: "single", children: t('Single column') })] }), _jsxs(SingleSelect, { label: "Form Layout", value: settings.formLayout ?? 'vertical', onChange: (formLayout) => setSettings({
84
+ ...settings,
85
+ formLayout: formLayout,
86
+ }), children: [_jsx(SelectOption, { value: "vertical", children: t('Vertical labels') }), _jsx(SelectOption, { value: "horizontal", children: t('Horizontal labels') })] }), _jsxs(SingleSelect, { label: "Borders", value: settings.borders ? 'true' : 'false', onChange: (value) => setSettings({ ...settings, borders: value === 'true' }), style: { paddingBottom: 120 }, children: [_jsx(SelectOption, { value: "true", children: t('Yes') }), _jsx(SelectOption, { value: "false", children: t('No') })] })] }) }));
87
+ }
@@ -0,0 +1,80 @@
1
+ import { ButtonVariant, DropdownPosition } from '@patternfly/react-core';
2
+ import { IAction } from '@patternfly/react-table';
3
+ import { ComponentClass, FunctionComponent } from 'react';
4
+ import { WindowSize } from './components/useBreakPoint';
5
+ export declare enum TypedActionType {
6
+ seperator = "seperator",
7
+ button = "button",
8
+ single = "single",
9
+ bulk = "bulk",
10
+ dropdown = "dropdown"
11
+ }
12
+ export interface ITypedActionSeperator {
13
+ type: TypedActionType.seperator;
14
+ }
15
+ interface ITypedActionCommon {
16
+ icon?: ComponentClass;
17
+ label: string;
18
+ shortLabel?: string;
19
+ tooltip?: string;
20
+ isDanger?: boolean;
21
+ }
22
+ export declare type ITypedActionButton = ITypedActionCommon & {
23
+ type: TypedActionType.button;
24
+ variant?: ButtonVariant;
25
+ onClick: () => void;
26
+ };
27
+ export declare type ITypedBulkAction<T extends object> = ITypedActionCommon & {
28
+ type: TypedActionType.bulk;
29
+ variant?: ButtonVariant;
30
+ onClick: (selectedItems: T[]) => void;
31
+ };
32
+ export declare type ITypedSingleAction<T extends object> = ITypedActionCommon & {
33
+ type: TypedActionType.single;
34
+ variant?: ButtonVariant;
35
+ onClick: (item: T) => void;
36
+ };
37
+ export declare type ITypedDropdownAction<T extends object> = ITypedActionCommon & {
38
+ type: TypedActionType.dropdown;
39
+ variant?: ButtonVariant;
40
+ options: ITypedAction<T>[];
41
+ };
42
+ export declare type ITypedAction<T extends object> = ITypedActionSeperator | ITypedActionButton | ITypedBulkAction<T> | ITypedSingleAction<T> | ITypedDropdownAction<T>;
43
+ export declare function TypedActionsDropdown<T extends object>(props: {
44
+ actions: ITypedAction<T>[];
45
+ label?: string;
46
+ isPrimary?: boolean;
47
+ selectedItems?: T[];
48
+ position?: DropdownPosition;
49
+ }): JSX.Element;
50
+ export declare function TypedActionsButtons<T extends object>(props: {
51
+ actions: ITypedAction<T>[];
52
+ selectedItems?: T[];
53
+ wrapper?: ComponentClass | FunctionComponent;
54
+ noPrimary?: boolean;
55
+ }): JSX.Element;
56
+ export declare function TypedActionButton<T extends object>(props: {
57
+ action: ITypedAction<T>;
58
+ selectedItems?: T[];
59
+ selectedItem?: T;
60
+ wrapper?: ComponentClass | FunctionComponent;
61
+ noPrimary?: boolean;
62
+ iconOnly?: boolean;
63
+ }): JSX.Element;
64
+ export declare function TypedActions<T extends object>(props: {
65
+ actions: ITypedAction<T>[];
66
+ selectedItems?: T[];
67
+ wrapper?: ComponentClass | FunctionComponent;
68
+ collapse?: WindowSize;
69
+ noPrimary?: boolean;
70
+ position?: DropdownPosition;
71
+ }): JSX.Element;
72
+ export declare function useTypedActionsToTableActions<T extends object>(props: {
73
+ actions: ITypedAction<T>[];
74
+ item: T;
75
+ wrapper?: ComponentClass | FunctionComponent;
76
+ collapse?: WindowSize;
77
+ noPrimary?: boolean;
78
+ position?: DropdownPosition;
79
+ }): IAction[];
80
+ export {};