@devtron-labs/devtron-fe-common-lib 0.0.56 → 0.0.58-beta-3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/.eslintignore +96 -0
  2. package/.eslintrc.js +84 -16
  3. package/.github/pull_request_template.md +25 -0
  4. package/.github/workflows/ci.yml +31 -0
  5. package/.github/workflows/release-package.yml +2 -3
  6. package/.husky/pre-commit +5 -0
  7. package/.lintstagedrc +3 -0
  8. package/.nvmrc +1 -0
  9. package/dist/Common/Common.service.d.ts +2 -2
  10. package/dist/Common/Constants.d.ts +0 -8
  11. package/dist/Common/CustomInput/CustomInput.d.ts +1 -1
  12. package/dist/Common/CustomInput/Types.d.ts +0 -1
  13. package/dist/Common/DebouncedSearch/DebouncedSearch.d.ts +2 -0
  14. package/dist/Common/EmptyState/GenericEmptyState.d.ts +1 -1
  15. package/dist/Common/Helper.d.ts +8 -1
  16. package/dist/Common/Pagination/PageSizeSelector.d.ts +4 -0
  17. package/dist/Common/Pagination/Pagination.d.ts +5 -0
  18. package/dist/Common/Pagination/constants.d.ts +5 -0
  19. package/dist/Common/Pagination/index.d.ts +1 -0
  20. package/dist/Common/Pagination/types.d.ts +51 -0
  21. package/dist/Common/Pagination/utils.d.ts +6 -0
  22. package/dist/Common/SearchBar/SearchBar.component.d.ts +39 -0
  23. package/dist/Common/SearchBar/index.d.ts +2 -0
  24. package/dist/Common/SearchBar/types.d.ts +35 -0
  25. package/dist/Common/Types.d.ts +15 -3
  26. package/dist/Common/index.d.ts +2 -0
  27. package/dist/index.js +462 -229
  28. package/package.json +19 -2
  29. package/src/Assets/Icon/ic-search.svg +6 -0
  30. package/src/Common/Constants.ts +0 -9
  31. package/src/Common/CustomInput/CustomInput.tsx +2 -3
  32. package/src/Common/CustomInput/Types.ts +0 -1
  33. package/src/Common/DebouncedSearch/DebouncedSearch.tsx +2 -0
  34. package/src/Common/EmptyState/GenericEmptyState.tsx +13 -45
  35. package/src/Common/Helper.tsx +45 -16
  36. package/src/Common/Pagination/PageSizeSelector.tsx +78 -0
  37. package/src/Common/Pagination/Pagination.tsx +127 -0
  38. package/src/Common/Pagination/constants.ts +6 -0
  39. package/src/Common/Pagination/index.tsx +3 -0
  40. package/src/Common/Pagination/pagination.scss +123 -0
  41. package/src/Common/Pagination/types.ts +55 -0
  42. package/src/Common/Pagination/utils.tsx +24 -0
  43. package/src/Common/SearchBar/SearchBar.component.tsx +120 -0
  44. package/src/Common/SearchBar/index.ts +2 -0
  45. package/src/Common/SearchBar/searchBar.scss +31 -0
  46. package/src/Common/SearchBar/types.ts +36 -0
  47. package/src/Common/Types.ts +15 -3
  48. package/src/Common/index.ts +2 -0
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "@devtron-labs/devtron-fe-common-lib",
3
- "version": "0.0.56",
3
+ "version": "0.0.58-beta-3",
4
4
  "description": "Supporting common component library",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
7
+ "prepare": "node -e \"try { require('husky').install() } catch (e) {}\"",
8
+ "lint": "tsc --noEmit && eslint 'src/**/*.{js,jsx,ts,tsx}' --max-warnings 0",
9
+ "lint-fix": "eslint 'src/**/*.{js,jsx,ts,tsx}' --fix",
7
10
  "test": "exit 0",
8
11
  "build-lib": "rollup -c --bundleConfigAsCjs",
9
- "build-watch": "rollup -c --bundleConfigAsCjs -w"
12
+ "build-watch": "rollup -c --bundleConfigAsCjs -w",
13
+ "lint-staged": "lint-staged"
10
14
  },
11
15
  "repository": {
12
16
  "type": "git",
@@ -30,7 +34,20 @@
30
34
  "@types/react": "17.0.39",
31
35
  "@types/react-dom": "17.0.13",
32
36
  "@types/react-router-dom": "^5.3.3",
37
+ "@typescript-eslint/eslint-plugin": "^6.17.0",
38
+ "@typescript-eslint/parser": "^6.17.0",
39
+ "eslint": "^8.56.0",
40
+ "eslint-config-airbnb": "^19.0.4",
41
+ "eslint-config-prettier": "^9.1.0",
42
+ "eslint-plugin-import": "^2.29.1",
43
+ "eslint-plugin-jsx-a11y": "^6.8.0",
44
+ "eslint-plugin-prettier": "^5.1.2",
45
+ "eslint-plugin-react": "^7.33.2",
46
+ "eslint-plugin-react-hooks": "^4.6.0",
47
+ "husky": "^7.0.4",
48
+ "lint-staged": "^12.5.0",
33
49
  "moment": "^2.29.4",
50
+ "prettier": "^3.1.1",
34
51
  "react-select": "5.2.2",
35
52
  "react-toastify": "^8.2.0",
36
53
  "rollup": "^3.10.0",
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <path d="M0 0h24v24H0z"/>
4
+ <path fill="#959BA1" d="M10 2a8 8 0 0 1 6.32 12.905l5.044 5.045a1 1 0 1 1-1.414 1.414l-5.045-5.043A8 8 0 1 1 10 2zm0 2a6 6 0 1 0 0 12 6 6 0 0 0 0-12z"/>
5
+ </g>
6
+ </svg>
@@ -242,13 +242,4 @@ export const RepositoryAction = {
242
242
  CHART_PUSH: "CHART_PUSH"
243
243
  }
244
244
 
245
- export enum APPROVAL_MODAL_TYPE {
246
- CONFIG = 'CONFIG',
247
- DEPLOYMENT = 'DEPLOYMENT',
248
- }
249
245
  export const MAX_Z_INDEX = 2147483647
250
-
251
- export const SELECTED_APPROVAL_TAB_STATE = {
252
- APPROVAL: 'approval',
253
- PENDING: 'pending',
254
- }
@@ -28,8 +28,7 @@ export function CustomInput({
28
28
  defaultValue,
29
29
  onKeyDown,
30
30
  required,
31
- additionalErrorInfo,
32
- inputWrapClassName = '',
31
+ additionalErrorInfo
33
32
  }: CustomInputProps) {
34
33
 
35
34
  function handleError(error: any): any[] {
@@ -93,7 +92,7 @@ export function CustomInput({
93
92
  }
94
93
 
95
94
  return (
96
- <div className={`flex column left top ${inputWrapClassName}`}>
95
+ <div className="flex column left top">
97
96
  {renderInputLabel()}
98
97
  <input
99
98
  data-testid={dataTestid}
@@ -27,5 +27,4 @@ export interface CustomInputProps {
27
27
  onKeyDown?: (e) => void
28
28
  required?: boolean
29
29
  additionalErrorInfo?: React.ReactNode
30
- inputWrapClassName?: string
31
30
  }
@@ -4,6 +4,8 @@ import { ReactComponent as ICClear } from '../../Assets/Icon/ic-error-cross.svg'
4
4
  import { DebouncedSearchProps } from './Types'
5
5
 
6
6
  /**
7
+ * @deprecated Use `SearchBar` component instead.
8
+ *
7
9
  * @param onSearch - Callback function to be called on search
8
10
  * @param Icon - (Optional) Icon to be shown before the input
9
11
  * @param iconClass - (Optional) Class for the icon
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React from 'react';
2
2
  import AppNotDeployed from '../../Assets/Img/app-not-deployed.png'
3
3
  import { GenericEmptyStateType, ImageType } from '../Types'
4
4
 
@@ -19,56 +19,24 @@ function GenericEmptyState({
19
19
  SvgImage,
20
20
  noImage,
21
21
  layout = 'column',
22
- contentClassName = '',
23
- imageStyles = {},
22
+ contentClassName = ''
24
23
  }: GenericEmptyStateType): JSX.Element {
25
- const isRowLayout = layout === 'row'
26
-
27
- const getImageSize = () => {
28
- switch (imageType) {
29
- case ImageType.Large:
30
- return { width: '250px', height: '200px' }
31
- default:
32
- return { width: '200px', height: '160px' }
33
- }
34
- }
35
-
24
+ const isRowLayout = layout === 'row';
25
+
36
26
  return (
37
27
  <div
38
- className={`flex ${isRowLayout ? 'dc__gap-32' : 'column dc__gap-20'} empty-state ${
39
- classname ? classname : ''
40
- }`}
28
+ className={`flex ${isRowLayout ? 'dc__gap-32' : 'column dc__gap-20'} empty-state ${classname ? classname : ''}`}
41
29
  style={styles}
42
30
  data-testid="generic-empty-state"
43
31
  {...(heightToDeduct >= 0 && { style: { ...styles, height: `calc(100vh - ${heightToDeduct}px)` } })}
44
- >
45
- {!SvgImage ? (
46
- !noImage && (
47
- <img
48
- className={imageClassName ? imageClassName : ''}
49
- src={image || AppNotDeployed}
50
- style={{
51
- ...imageStyles,
52
- width: `${getImageSize().width}`,
53
- height: `${getImageSize().height}`,
54
- }}
55
- alt="empty-state"
56
- />
57
- )
58
- ) : (
59
- <SvgImage
60
- style={{
61
- ...imageStyles,
62
- width: `${getImageSize().width}`,
63
- height: `${getImageSize().height}`,
64
- }}
65
- />
66
- )}
67
- <div
68
- className={`flex column dc__gap-10 dc__mxw-300 ${
69
- isRowLayout ? 'dc__align-start' : ''
70
- } ${contentClassName}`}
71
- >
32
+ >
33
+ {!SvgImage ? !noImage && <img className={imageClassName ? imageClassName : ''}
34
+ src={image || AppNotDeployed}
35
+ width={imageType === ImageType.Medium ? '200' : '250'}
36
+ height={imageType === ImageType.Medium ? '160' : '200'}
37
+ alt="empty-state"
38
+ /> : <SvgImage />}
39
+ <div className={`flex column dc__gap-10 dc__mxw-300 ${isRowLayout ? 'dc__align-start' : ''} ${contentClassName}`}>
72
40
  <h4 className="title fw-6 cn-9 mt-0 mb-0">{title}</h4>
73
41
  {subTitle && <p className={`subtitle ${isRowLayout ? 'subtitle--text-start' : ''}`}>{subTitle}</p>}
74
42
  {isButtonAvailable && renderButton()}
@@ -499,18 +499,27 @@ export const getFilteredChartVersions = (charts, selectedChartType) => {
499
499
  chartRefId: item.chartRefId,
500
500
  }))
501
501
  }
502
- function removeEmptyObjectKeysAndNullValues(obj) {
503
- // It recursively removes empty object keys and array values that are null
502
+
503
+ function removeEmptyObjectKeysAndNullValues(obj, originaljsonCopy) {
504
+ // It recursively removes empty object keys and empty array keys
504
505
  for (let key in obj) {
505
506
  if (Array.isArray(obj[key])) {
506
- if (obj[key].length === 0) continue
507
- obj[key] = obj[key].filter((item) => item !== null)
508
507
  // Check if the array is empty
509
- if (obj[key].length === 0) {
510
- delete obj[key] // Delete the key if the array is empty
508
+ if (obj[key].length !== 0) {
509
+ obj[key].forEach((element, index) => {
510
+ if (element === null || (typeof element === 'object' && Object.keys(element).length === 0))
511
+ obj[key].splice(index, 1)
512
+ else removeEmptyObjectKeysAndNullValues(element, originaljsonCopy[key][index])
513
+ })
514
+ }
515
+ if (obj[key].length === 0 && originaljsonCopy[key].length !== 0) {
516
+ delete obj[key]
511
517
  }
512
518
  } else if (obj[key] && typeof obj[key] === 'object') {
513
- if (removeEmptyObjectKeysAndNullValues(obj[key])) {
519
+ if (
520
+ removeEmptyObjectKeysAndNullValues(obj[key], originaljsonCopy[key]) &&
521
+ Object.keys(originaljsonCopy[key]).length !== 0
522
+ ) {
514
523
  delete obj[key]
515
524
  }
516
525
  } else if (obj[key] === undefined) {
@@ -520,20 +529,25 @@ function removeEmptyObjectKeysAndNullValues(obj) {
520
529
  return Object.keys(obj).length === 0
521
530
  }
522
531
 
523
- export function getUnlockedJSON(json, jsonPathArray) {
532
+ export function getUnlockedJSON(json, jsonPathArray, removeParentKeysAndEmptyArrays = false) {
533
+ if (!jsonPathArray.length) return { newDocument: json, removedPatches: [] }
534
+
524
535
  const jsonCopy = JSON.parse(JSON.stringify(json))
536
+ const originaljsonCopy = JSON.parse(JSON.stringify(json))
537
+ let removedPatches = []
525
538
  let patches = jsonPathArray.flatMap((jsonPath) => {
526
539
  const pathsToRemove = JSONPath({ path: jsonPath, json: jsonCopy, resultType: 'all' })
527
- return pathsToRemove.map((result) =>
528
- Array.isArray(result.parent)
529
- ? { op: 'replace', path: result.pointer, value: null }
530
- : { op: 'remove', path: result.pointer },
531
- )
540
+ //reversing patches to handle correct array index deletion
541
+ pathsToRemove.reverse()
542
+ return pathsToRemove.map((result) => {
543
+ //storing removed patches to have functionality of undo
544
+ removedPatches.push({ op: 'add', path: result.pointer, value: result.value })
545
+ return { op: 'remove', path: result.pointer }
546
+ })
532
547
  })
533
548
  let newDocument = jsonpatch.applyPatch(jsonCopy, patches).newDocument
534
-
535
- removeEmptyObjectKeysAndNullValues(newDocument)
536
- return newDocument
549
+ if (removeParentKeysAndEmptyArrays) removeEmptyObjectKeysAndNullValues(newDocument, originaljsonCopy)
550
+ return { newDocument, removedPatches: removedPatches.reverse() }
537
551
  }
538
552
 
539
553
  export function getLockedJSON(json, jsonPathArray: string[]) {
@@ -559,3 +573,18 @@ export function getLockedJSON(json, jsonPathArray: string[]) {
559
573
  return resultJson['$']
560
574
  }
561
575
 
576
+ /**
577
+ * Returns a debounced variant of the function
578
+ */
579
+ export const debounce = (func, timeout = 500) => {
580
+ let timer
581
+
582
+ return function (this, ...args) {
583
+ const context = this
584
+ if (timer) clearTimeout(timer)
585
+ timer = setTimeout(() => {
586
+ timer = null
587
+ func.apply(context, args)
588
+ }, timeout)
589
+ }
590
+ }
@@ -0,0 +1,78 @@
1
+ import { useRef, useState } from 'react'
2
+ import { PageSizeItemsProps, PageSizeOption, PageSizeSelectorProps } from './types'
3
+ import { useClickOutside } from '../Hooks'
4
+ import { getDefaultPageValueOptions } from './utils'
5
+
6
+ const PageSizeItems = ({
7
+ optionValue,
8
+ options,
9
+ setOptions,
10
+ handleCloseDropdown,
11
+ changePageSize,
12
+ }: PageSizeItemsProps) => {
13
+ const handlePageSizeSelect = () => {
14
+ const newOptions = options.map((_option) => ({
15
+ value: _option.value,
16
+ selected: _option.value === optionValue,
17
+ }))
18
+ setOptions([...newOptions])
19
+ handleCloseDropdown()
20
+ changePageSize(optionValue)
21
+ }
22
+
23
+ return (
24
+ <div key={optionValue} className="select__item" onClick={handlePageSizeSelect}>
25
+ {optionValue}
26
+ </div>
27
+ )
28
+ }
29
+
30
+ const PageSizeSelector = ({ pageSizeOptions, pageSize, changePageSize }: PageSizeSelectorProps) => {
31
+ const defaultOptions = getDefaultPageValueOptions(pageSizeOptions).map((option) => ({
32
+ value: option.value,
33
+ selected: option.value === pageSize,
34
+ }))
35
+
36
+ const [isDropdownOpen, setIsDropdownOpen] = useState<boolean>(false)
37
+ const [options, setOptions] = useState<PageSizeOption[]>(defaultOptions)
38
+
39
+ const handleCloseDropdown = () => {
40
+ setIsDropdownOpen(false)
41
+ }
42
+
43
+ const handleDropdownToggle = () => {
44
+ setIsDropdownOpen(!isDropdownOpen)
45
+ }
46
+
47
+ const dropdownRef = useRef<HTMLDivElement>(null)
48
+ useClickOutside(dropdownRef, handleCloseDropdown)
49
+
50
+ const selectedOption = options.find((option) => option.selected)
51
+ const font = isDropdownOpen ? 'fa fa-caret-up' : 'fa fa-caret-down'
52
+ return (
53
+ <div ref={dropdownRef}>
54
+ {isDropdownOpen && (
55
+ <div className="pagination__select-menu">
56
+ {options.map((_option) => (
57
+ <PageSizeItems
58
+ optionValue={_option.value}
59
+ options={options}
60
+ setOptions={setOptions}
61
+ handleCloseDropdown={handleCloseDropdown}
62
+ changePageSize={changePageSize}
63
+ />
64
+ ))}
65
+ </div>
66
+ )}
67
+
68
+ <button type="button" className="select__button" onClick={handleDropdownToggle}>
69
+ <span>{selectedOption ? selectedOption.value : ''}</span>
70
+ <span className="select__icon">
71
+ <i className={font} />
72
+ </span>
73
+ </button>
74
+ </div>
75
+ )
76
+ }
77
+
78
+ export default PageSizeSelector
@@ -0,0 +1,127 @@
1
+ import { useEffect, useState } from 'react'
2
+ import PageSizeSelector from './PageSizeSelector'
3
+ import { Page, PageValueItemProps, PaginationProps } from './types'
4
+ import { createPageArr } from './utils'
5
+ import './pagination.scss'
6
+
7
+ const PageValueItem = ({ value, isSelected, selectPage }: PageValueItemProps) => {
8
+ const classes = isSelected ? 'page__button page__button--selected' : 'page__button'
9
+ const handlePageSelection = () => {
10
+ selectPage(value)
11
+ }
12
+
13
+ return (
14
+ <li className="page">
15
+ <button className={classes} onClick={handlePageSelection} type="button">
16
+ {value}
17
+ </button>
18
+ </li>
19
+ )
20
+ }
21
+
22
+ // NOTE: This component will heavily benefit from data normalization
23
+ const Pagination = ({
24
+ size,
25
+ pageSize,
26
+ offset,
27
+ changePage,
28
+ changePageSize,
29
+ isPageSizeFix,
30
+ pageSizeOptions,
31
+ rootClassName,
32
+ }: PaginationProps) => {
33
+ const [pages, setPages] = useState<Page[]>([])
34
+
35
+ useEffect(() => {
36
+ const _pages = createPageArr({ size, pageSize, selectedPageNo: 1 })
37
+ setPages(_pages)
38
+ }, [size, pageSize])
39
+
40
+ useEffect(() => {
41
+ const selectedPageNo = 1 + Math.floor(offset / pageSize)
42
+ const _pages = createPageArr({ size, pageSize, selectedPageNo })
43
+ setPages(_pages)
44
+ }, [offset])
45
+
46
+ const selectPage = (selectedPageNo: number): void => {
47
+ const _pages = createPageArr({ size, pageSize, selectedPageNo })
48
+ setPages(_pages)
49
+ changePage(selectedPageNo)
50
+ }
51
+
52
+ const selectPreviousPage = (): void => {
53
+ const currPage = pages.find((page) => page.selected)
54
+ const selectedPageNo = currPage.value - 1
55
+ selectPage(selectedPageNo)
56
+ }
57
+
58
+ const selectNextPage = (): void => {
59
+ const currPage = pages.find((page) => page.selected)
60
+ const selectedPageNo = currPage.value + 1
61
+ selectPage(selectedPageNo)
62
+ }
63
+
64
+ const lastPageNo = offset + pageSize < size ? offset + pageSize : size
65
+ const pageNoIndex = pages.findIndex((page) => page.selected)
66
+ const visiblePages = pages.filter((page) => page.isVisible)
67
+ return (
68
+ // TODO: Remove pagination-wrapper from dashboard
69
+ <div className={rootClassName || ''}>
70
+ <div className="page-number">
71
+ {offset + 1} - {lastPageNo} of {size}
72
+ </div>
73
+
74
+ <ul className="pagination">
75
+ <li className="page">
76
+ <button
77
+ className="page__button page__button--icon"
78
+ disabled={!pageNoIndex}
79
+ onClick={selectPreviousPage}
80
+ type="button"
81
+ aria-label="Previous page"
82
+ >
83
+ <span className="left-icon">
84
+ <i className="fa fa-chevron-left" />
85
+ </span>
86
+ </button>
87
+ </li>
88
+
89
+ {visiblePages.map((page) => (
90
+ <PageValueItem
91
+ value={page.value}
92
+ isSelected={page.selected}
93
+ key={page.value}
94
+ selectPage={selectPage}
95
+ />
96
+ ))}
97
+
98
+ <li className="page">
99
+ <button
100
+ className="page__button page__button--icon"
101
+ disabled={pageNoIndex === pages.length - 1}
102
+ onClick={selectNextPage}
103
+ type="button"
104
+ aria-label="Next page"
105
+ >
106
+ <span className="left-icon">
107
+ <i className="fa fa-chevron-right" />
108
+ </span>
109
+ </button>
110
+ </li>
111
+ </ul>
112
+
113
+ {!isPageSizeFix && (
114
+ <div className="select">
115
+ <span className="select__placeholder">Rows per page</span>
116
+ <PageSizeSelector
117
+ pageSizeOptions={pageSizeOptions}
118
+ pageSize={pageSize}
119
+ changePageSize={changePageSize}
120
+ />
121
+ </div>
122
+ )}
123
+ </div>
124
+ )
125
+ }
126
+
127
+ export default Pagination
@@ -0,0 +1,6 @@
1
+ export const VISIBLE_PAGES_LIMIT = 5
2
+ export const FALLBACK_PAGE_SIZE_OPTIONS = [
3
+ { value: 20, selected: true },
4
+ { value: 40, selected: false },
5
+ { value: 50, selected: false },
6
+ ]
@@ -0,0 +1,3 @@
1
+ /* eslint-disable import/prefer-default-export */
2
+ // Disabling since might need to export types as well
3
+ export { default as Pagination } from './Pagination'
@@ -0,0 +1,123 @@
1
+ .pagination-wrapper {
2
+ display: flex;
3
+ align-items: center;
4
+ padding: 0px 24px;
5
+ justify-content: space-between;
6
+ margin: 0px;
7
+ background-color: var(--white);
8
+ }
9
+
10
+ .pagination {
11
+ margin-top: 16px;
12
+ margin-bottom: 16px;
13
+ padding: 0px;
14
+ }
15
+
16
+ .select {
17
+ display: flex;
18
+ align-items: center;
19
+ position: relative;
20
+ }
21
+
22
+ .select__placeholder {
23
+ font-size: 12px;
24
+ font-weight: normal;
25
+ font-style: normal;
26
+ font-stretch: normal;
27
+ line-height: 1.5;
28
+ letter-spacing: normal;
29
+ color: var(--N700);
30
+ margin-right: 8px;
31
+ }
32
+
33
+ .pagination__select-menu {
34
+ padding: 0px;
35
+ list-style: none;
36
+ overflow: hidden;
37
+ border: solid 1px var(--N200);
38
+ border-radius: 4px;
39
+ width: 64px;
40
+ position: absolute;
41
+ bottom: 31px;
42
+ background-color: var(--white);;
43
+ }
44
+
45
+ .select__button {
46
+ width: 64px;
47
+ background-color: transparent;
48
+ border-radius: 4px;
49
+ border: solid 1px var(--N200);
50
+ padding: 5px 10px;
51
+ text-align: left;
52
+ }
53
+
54
+ .select__item {
55
+ padding: 5px 10px;
56
+ cursor: pointer;
57
+ }
58
+
59
+ .select__icon {
60
+ margin-left: 18px;
61
+ }
62
+
63
+ .page {
64
+ margin: 0px 8px;
65
+ display: inline-block;
66
+ }
67
+
68
+ .page-number {
69
+ font-size: 12px;
70
+ font-weight: normal;
71
+ font-style: normal;
72
+ font-stretch: normal;
73
+ line-height: 1.5;
74
+ letter-spacing: normal;
75
+ color: var(--N700);
76
+ }
77
+
78
+ .page__button {
79
+ width: 24px;
80
+ height: 24px;
81
+ border-radius: 8px;
82
+ color: var(--B500);
83
+ background-color: var(--white);
84
+ padding: 0px;
85
+ user-select: none;
86
+ }
87
+
88
+ .page__button--icon {
89
+ background-color: var(--white);
90
+ color: var(--B500);
91
+ }
92
+
93
+ /* MODIFIERS */
94
+
95
+ .page__button--selected {
96
+ color: var(--white);
97
+ background-color: var(--B500);
98
+ }
99
+
100
+ /* States and Selectorys */
101
+
102
+ .page__button:disabled {
103
+ opacity: 0.5;
104
+ }
105
+
106
+ .select__item:hover {
107
+ background-color: var(--N50);
108
+ }
109
+
110
+ .page__button:hover ~ :disabled {
111
+ background-color: var(--B100);
112
+ }
113
+
114
+ .page__button--selected:hover {
115
+ color: var(--white);
116
+ background-color: var(--B500);
117
+ }
118
+
119
+ @media (min-width: 1024px) {
120
+ .pagination {
121
+ margin: 16px auto;
122
+ }
123
+ }
@@ -0,0 +1,55 @@
1
+ export interface PageSizeOption {
2
+ value: number
3
+ selected: boolean
4
+ }
5
+ export interface PaginationProps {
6
+ /**
7
+ * number of items
8
+ */
9
+ size: number
10
+ /**
11
+ * pageSize
12
+ */
13
+ pageSize: number
14
+ offset: number
15
+ changePage: (pageNo: number) => void
16
+ changePageSize?: (pageSize: number) => void
17
+ /**
18
+ * If true will not show page size selector
19
+ */
20
+ isPageSizeFix?: boolean
21
+ /**
22
+ * If given would show these options in page size selector else [20,40,50] with 20 as selected
23
+ */
24
+ pageSizeOptions?: PageSizeOption[]
25
+ /**
26
+ * class for wrapper
27
+ */
28
+ rootClassName?: string
29
+ }
30
+
31
+ export interface Page {
32
+ value: number
33
+ selected: boolean
34
+ isVisible: boolean
35
+ }
36
+
37
+ export interface CreatePageArrType extends Pick<PaginationProps, 'size' | 'pageSize'> {
38
+ selectedPageNo: number
39
+ }
40
+
41
+ export interface PageSizeSelectorProps
42
+ extends Pick<PaginationProps, 'pageSizeOptions' | 'pageSize' | 'changePageSize'> {}
43
+
44
+ export interface PageSizeItemsProps extends Pick<PageSizeSelectorProps, 'changePageSize'> {
45
+ optionValue: PageSizeOption['value']
46
+ options: PageSizeOption[]
47
+ setOptions: React.Dispatch<React.SetStateAction<PageSizeOption[]>>
48
+ handleCloseDropdown: () => void
49
+ }
50
+
51
+ export interface PageValueItemProps {
52
+ value: PageSizeOption['value']
53
+ isSelected: PageSizeOption['selected']
54
+ selectPage: (selectedPageNo: number) => void
55
+ }