@indico-data/design-system 2.48.0 → 2.50.0
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.
- package/lib/components/table/Table.stories.d.ts +1 -0
- package/lib/components/table/components/HorizontalStickyHeader.d.ts +10 -0
- package/lib/components/table/components/__tests__/HorizontalStickyHeader.test.d.ts +1 -0
- package/lib/components/table/components/helpers.d.ts +6 -0
- package/lib/components/table/hooks/usePinnedColumnsManager.d.ts +8 -0
- package/lib/components/table/sampleData.d.ts +4 -0
- package/lib/components/table/types.d.ts +11 -1
- package/lib/components/table/utils/processColumns.d.ts +2 -0
- package/lib/index.css +188 -89
- package/lib/index.d.ts +12 -1
- package/lib/index.esm.css +188 -89
- package/lib/index.esm.js +238 -2
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +238 -2
- package/lib/index.js.map +1 -1
- package/lib/stylesAndAnimations/utilityClasses/UtilityClassesData.d.ts +7 -0
- package/lib/stylesAndAnimations/utilityClasses/UtilityClassesTable.d.ts +1 -0
- package/lib/stylesAndAnimations/utilityClasses/UtilityClassesTable.stories.d.ts +6 -0
- package/lib/utils/getPreviousHeadersWidth.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/table/Table.mdx +134 -0
- package/src/components/table/Table.stories.tsx +71 -2
- package/src/components/table/Table.tsx +16 -1
- package/src/components/table/components/HorizontalStickyHeader.tsx +57 -0
- package/src/components/table/components/__tests__/HorizontalStickyHeader.test.tsx +104 -0
- package/src/components/table/components/helpers.ts +90 -0
- package/src/components/table/hooks/usePinnedColumnsManager.ts +146 -0
- package/src/components/table/{sampleData.ts → sampleData.tsx} +156 -1
- package/src/components/table/styles/Table.scss +32 -15
- package/src/components/table/styles/_variables.scss +2 -0
- package/src/components/table/types.ts +13 -1
- package/src/components/table/utils/processColumns.tsx +35 -0
- package/src/setup/setupTests.ts +8 -0
- package/src/storybookDocs/Permafrost.mdx +22 -11
- package/src/styles/_borders.scss +2 -1
- package/src/stylesAndAnimations/borders/BorderColor.tsx +14 -6
- package/src/stylesAndAnimations/utilityClasses/UtilityClasses.mdx +24 -0
- package/src/stylesAndAnimations/utilityClasses/UtilityClassesData.ts +230 -0
- package/src/stylesAndAnimations/utilityClasses/UtilityClassesTable.stories.tsx +13 -0
- package/src/stylesAndAnimations/utilityClasses/UtilityClassesTable.tsx +146 -0
- package/src/utils/getPreviousHeadersWidth.ts +12 -0
package/src/setup/setupTests.ts
CHANGED
|
@@ -3,3 +3,11 @@ import { configure } from '@testing-library/react';
|
|
|
3
3
|
import './setupIcons';
|
|
4
4
|
|
|
5
5
|
configure({ testIdAttribute: 'data-testid' });
|
|
6
|
+
|
|
7
|
+
class ResizeObserverMock {
|
|
8
|
+
observe() {}
|
|
9
|
+
unobserve() {}
|
|
10
|
+
disconnect() {}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
global.ResizeObserver = ResizeObserverMock;
|
|
@@ -2,13 +2,16 @@ import { Meta } from '@storybook/addon-docs';
|
|
|
2
2
|
|
|
3
3
|
<Meta title="Getting Started" />
|
|
4
4
|
|
|
5
|
-
# Permafrost
|
|
5
|
+
# Permafrost
|
|
6
|
+
|
|
6
7
|
#### Permafrost is the name of our User Interface Design System and Component Library.
|
|
8
|
+
|
|
7
9
|
Permafrost is utilized in Indico's React projects to ensure a consistent look and feel across our products. It leverages many variables and components that are defined in our design system. We also wrap multiple libraries such as `react-day-picker` or `react-select` to ensure a consistent look and feel.
|
|
8
10
|
|
|
9
11
|
<div style={{ marginBottom: '3rem' }} />
|
|
10
12
|
|
|
11
13
|
## Installation
|
|
14
|
+
|
|
12
15
|
Indico serves Permafrost as a package on npm. In order to take advantage of it in your project, you can install it by adding the following to your `package.json`:
|
|
13
16
|
|
|
14
17
|
```json
|
|
@@ -16,16 +19,17 @@ Indico serves Permafrost as a package on npm. In order to take advantage of it i
|
|
|
16
19
|
"@indico-data/permafrost": "latest" // or the specific version you want
|
|
17
20
|
}
|
|
18
21
|
```
|
|
19
|
-
|
|
22
|
+
|
|
23
|
+
After adding the package, import the CSS file to apply Permafrost's styles to the components.
|
|
20
24
|
|
|
21
25
|
```css
|
|
22
|
-
@import
|
|
26
|
+
@import '@indico-data/permafrost/dist/index.css';
|
|
23
27
|
```
|
|
24
28
|
|
|
25
|
-
|
|
26
29
|
## Usage
|
|
27
30
|
|
|
28
31
|
### Overriding Variables
|
|
32
|
+
|
|
29
33
|
You are able to override any of the variables in the design system. We currently support `light` and `dark` themes. If you would like to override a variable in the dark theme, try this approach:
|
|
30
34
|
|
|
31
35
|
```css
|
|
@@ -37,7 +41,8 @@ You are able to override any of the variables in the design system. We currently
|
|
|
37
41
|
This pattern applies to all of our variables which you can find in the CSS variables directory in the project.
|
|
38
42
|
|
|
39
43
|
### Theming
|
|
40
|
-
|
|
44
|
+
|
|
45
|
+
In order to switch between the light and dark themes, you can simply add the `data-theme` attribute to the `html` element. _Note_ If no theme is provided, it will default to `:root` which is the dark theme.
|
|
41
46
|
|
|
42
47
|
```html
|
|
43
48
|
<html data-theme="light">
|
|
@@ -47,18 +52,22 @@ In order to switch between the light and dark themes, you can simply add the `da
|
|
|
47
52
|
|
|
48
53
|
In the example above, it will leverage the `light` theme to render our styles with the `light mode` variables. It is important to note that while Permafrost natively supports `light` and `dark` values for data-theme, these can be extended and even overridden by your project to support additional themes.
|
|
49
54
|
|
|
50
|
-
|
|
51
55
|
### Importing Components
|
|
56
|
+
|
|
52
57
|
Using components from Permafrost is as simple as importing them from the package and using them in your project.
|
|
53
58
|
|
|
54
59
|
```tsx
|
|
55
|
-
import {Icon} from '@indico-data/design-system';
|
|
60
|
+
import { Icon } from '@indico-data/design-system';
|
|
56
61
|
|
|
57
|
-
|
|
58
|
-
<Icon name="indico-o" />
|
|
62
|
+
<Icon name="indico-o" />;
|
|
59
63
|
```
|
|
60
64
|
|
|
65
|
+
### Utility Classes
|
|
66
|
+
|
|
67
|
+
Utility classes are pre-defined CSS classes that provide quick and easy styling options for common design patterns. They help maintain consistency and speed up development by offering ready-to-use styles for margins, typography, and more. For a complete list of available utility classes and their usage, see our [Utility Classes documentation](/docs/utility-classes-overview--docs).
|
|
68
|
+
|
|
61
69
|
### CSS Only
|
|
70
|
+
|
|
62
71
|
We have tried to provide as much support as possible for those who wish to implement Permafrost without using our React components. This is where the CSS only approach comes in. We have wrapped the components in a way that allows you to use the same styles with a different library. In order to use the CSS only approach, you can import the css file that sets the styles for the components.
|
|
63
72
|
|
|
64
73
|
You can do this by going into the project and running the following command:
|
|
@@ -70,11 +79,13 @@ yarn build
|
|
|
70
79
|
This will create an `index.css` file in the `dist` directory that you can then copy and import into your project.
|
|
71
80
|
|
|
72
81
|
#### SASS
|
|
82
|
+
|
|
73
83
|
If you prefer to use SASS, you can copy the entire `/styles` directory and import the `index.scss` file into your project.
|
|
74
84
|
|
|
75
85
|
**Note:** This will only give you the styling of our design system, none of the interactivity.
|
|
76
86
|
|
|
77
87
|
### CSS Only Usage
|
|
88
|
+
|
|
78
89
|
If you wish to do the CSS only approach, you can do so by applying the CSS classes to your components. For example, if you have an input you wish to have styled with our design system, you can do the following:
|
|
79
90
|
|
|
80
91
|
```tsx
|
|
@@ -83,10 +94,10 @@ If you wish to do the CSS only approach, you can do so by applying the CSS class
|
|
|
83
94
|
|
|
84
95
|
We are as generic as possible with our CSS classes, so you can easily override them if needed.
|
|
85
96
|
|
|
86
|
-
|
|
87
97
|
## Testing
|
|
98
|
+
|
|
88
99
|
All of our components have been tested with React Testing Library. You can view the tests for each component by looking in the `__tests__` directory in each component. To run them, you can simply run the following command:
|
|
89
100
|
|
|
90
101
|
```bash
|
|
91
102
|
yarn jest
|
|
92
|
-
```
|
|
103
|
+
```
|
package/src/styles/_borders.scss
CHANGED
|
@@ -3,7 +3,8 @@ $values: var(--pf-border-thin), var(--pf-border-sm), var(--pf-border-md), var(--
|
|
|
3
3
|
var(--pf-border-xl);
|
|
4
4
|
$directions: ('t', top), ('b', bottom), ('l', left), ('r', right);
|
|
5
5
|
$styles: dashed, dotted, double, solid;
|
|
6
|
-
$color-names: 'primary', 'secondary', '
|
|
6
|
+
$color-names: 'primary', 'secondary', 'tertiary', 'gray', 'red', 'orange', 'yellow', 'green',
|
|
7
|
+
'purple';
|
|
7
8
|
$color-grades: '100', '200', '300', '400', '500', '600', '700', '800', '900';
|
|
8
9
|
$radiusSizes: 0, sm, lg, md, xl, pill, circle, shaped;
|
|
9
10
|
$radiusValues: var(--pf-rounded-0), var(--pf-rounded-sm), var(--pf-rounded-md), var(--pf-rounded-lg),
|
|
@@ -18,12 +18,12 @@ export const BorderColor = () => {
|
|
|
18
18
|
<p className="text-align--center">border-secondary</p>
|
|
19
19
|
</div>
|
|
20
20
|
<div>
|
|
21
|
-
<div className="sb__square bg-gray-800 border border-lg border-
|
|
22
|
-
<p className="text-align--center">border-
|
|
21
|
+
<div className="sb__square bg-gray-800 border border-lg border-tertiary"></div>
|
|
22
|
+
<p className="text-align--center">border-tertiary</p>
|
|
23
23
|
</div>
|
|
24
24
|
<div>
|
|
25
|
-
<div className="sb__square bg-gray-800 border border-lg border-
|
|
26
|
-
<p className="text-align--center">border-
|
|
25
|
+
<div className="sb__square bg-gray-800 border border-lg border-gray"></div>
|
|
26
|
+
<p className="text-align--center">border-gray</p>
|
|
27
27
|
</div>
|
|
28
28
|
<div>
|
|
29
29
|
<div className="sb__square bg-gray-800 border border-lg border-red"></div>
|
|
@@ -34,8 +34,16 @@ export const BorderColor = () => {
|
|
|
34
34
|
<p className="text-align--center">border-orange</p>
|
|
35
35
|
</div>
|
|
36
36
|
<div>
|
|
37
|
-
<div className="sb__square bg-gray-800 border border-lg border-
|
|
38
|
-
<p className="text-align--center">border-
|
|
37
|
+
<div className="sb__square bg-gray-800 border border-lg border-yellow"></div>
|
|
38
|
+
<p className="text-align--center">border-yellow</p>
|
|
39
|
+
</div>
|
|
40
|
+
<div>
|
|
41
|
+
<div className="sb__square bg-gray-800 border border-lg border-green"></div>
|
|
42
|
+
<p className="text-align--center">border-green</p>
|
|
43
|
+
</div>
|
|
44
|
+
<div>
|
|
45
|
+
<div className="sb__square bg-gray-800 border border-lg border-purple"></div>
|
|
46
|
+
<p className="text-align--center">border-purple</p>
|
|
39
47
|
</div>
|
|
40
48
|
</div>
|
|
41
49
|
);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Meta, Canvas } from '@storybook/blocks';
|
|
2
|
+
import * as UtilityClassesStories from './UtilityClassesTable.stories';
|
|
3
|
+
|
|
4
|
+
<Meta title="Utility Classes/Overview" />
|
|
5
|
+
|
|
6
|
+
# Utility Classes Overview
|
|
7
|
+
|
|
8
|
+
Utility classes are designed to provide quick and easy styling options for common design patterns. They help maintain consistency and speed up development by offering predefined styles for borders, colors, typography, and more.
|
|
9
|
+
|
|
10
|
+
## Example Usage
|
|
11
|
+
|
|
12
|
+
Here's a brief example of how you can use utility classes in your project:
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
<div className="mb-4 text-uppercase">
|
|
16
|
+
This will have a bottom margin of 16px and the text will be uppercase
|
|
17
|
+
</div>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Note:** If you find yourself adding more than a few utility classes to a single element and it starts resembling Tailwind, consider using CSS (styled-components, SCSS, etc.) and leverage the design system variables directly.
|
|
21
|
+
|
|
22
|
+
## Utility Classes
|
|
23
|
+
|
|
24
|
+
<Canvas of={UtilityClassesStories.Default} />
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
export type UtilityClassData = {
|
|
2
|
+
className: string;
|
|
3
|
+
css: string;
|
|
4
|
+
category: string;
|
|
5
|
+
resolvedCss?: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const utilityClassesData: UtilityClassData[] = [
|
|
9
|
+
// Border Utilities
|
|
10
|
+
{
|
|
11
|
+
className: 'border-primary',
|
|
12
|
+
css: 'border-color: var(--pf-primary-color);',
|
|
13
|
+
category: 'Border',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
className: 'border-secondary',
|
|
17
|
+
css: 'border-color: var(--pf-secondary-color);',
|
|
18
|
+
category: 'Border',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
className: 'border-tertiary',
|
|
22
|
+
css: 'border-color: var(--pf-tertiary-color);',
|
|
23
|
+
category: 'Border',
|
|
24
|
+
},
|
|
25
|
+
{ className: 'border-gray', css: 'border-color: var(--pf-gray-color);', category: 'Border' },
|
|
26
|
+
{ className: 'border-red', css: 'border-color: var(--pf-red-color);', category: 'Border' },
|
|
27
|
+
{ className: 'border-orange', css: 'border-color: var(--pf-orange-color);', category: 'Border' },
|
|
28
|
+
{ className: 'border-yellow', css: 'border-color: var(--pf-yellow-color);', category: 'Border' },
|
|
29
|
+
{ className: 'border-green', css: 'border-color: var(--pf-green-color);', category: 'Border' },
|
|
30
|
+
{ className: 'border-purple', css: 'border-color: var(--pf-purple-color);', category: 'Border' },
|
|
31
|
+
{ className: 'border-thin', css: 'border-width: var(--pf-border-thin);', category: 'Border' },
|
|
32
|
+
{ className: 'border-sm', css: 'border-width: var(--pf-border-sm);', category: 'Border' },
|
|
33
|
+
{ className: 'border-md', css: 'border-width: var(--pf-border-md);', category: 'Border' },
|
|
34
|
+
{ className: 'border-lg', css: 'border-width: var(--pf-border-lg);', category: 'Border' },
|
|
35
|
+
{ className: 'border-xl', css: 'border-width: var(--pf-border-xl);', category: 'Border' },
|
|
36
|
+
{ className: 'border-dashed', css: 'border-style: dashed;', category: 'Border' },
|
|
37
|
+
{ className: 'border-dotted', css: 'border-style: dotted;', category: 'Border' },
|
|
38
|
+
{ className: 'border-double', css: 'border-style: double;', category: 'Border' },
|
|
39
|
+
{ className: 'border-solid', css: 'border-style: solid;', category: 'Border' },
|
|
40
|
+
{ className: 'rounded', css: 'border-radius: var(--pf-rounded);', category: 'Border' },
|
|
41
|
+
{ className: 'rounded-0', css: 'border-radius: var(--pf-rounded-0);', category: 'Border' },
|
|
42
|
+
{ className: 'rounded-sm', css: 'border-radius: var(--pf-rounded-sm);', category: 'Border' },
|
|
43
|
+
{ className: 'rounded-md', css: 'border-radius: var(--pf-rounded-md);', category: 'Border' },
|
|
44
|
+
{ className: 'rounded-lg', css: 'border-radius: var(--pf-rounded-lg);', category: 'Border' },
|
|
45
|
+
{ className: 'rounded-xl', css: 'border-radius: var(--pf-rounded-xl);', category: 'Border' },
|
|
46
|
+
{ className: 'rounded-pill', css: 'border-radius: var(--pf-rounded-pill);', category: 'Border' },
|
|
47
|
+
{
|
|
48
|
+
className: 'rounded-circle',
|
|
49
|
+
css: 'border-radius: var(--pf-rounded-circle);',
|
|
50
|
+
category: 'Border',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
className: 'rounded-shaped',
|
|
54
|
+
css: 'border-radius: var(--pf-rounded-shaped);',
|
|
55
|
+
category: 'Border',
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
// Color Utilities
|
|
59
|
+
{ className: 'color-primary', css: 'color: var(--pf-primary-color);', category: 'Color' },
|
|
60
|
+
{ className: 'color-secondary', css: 'color: var(--pf-secondary-color);', category: 'Color' },
|
|
61
|
+
{ className: 'color-tertiary', css: 'color: var(--pf-tertiary-color);', category: 'Color' },
|
|
62
|
+
{ className: 'color-gray', css: 'color: var(--pf-gray-color);', category: 'Color' },
|
|
63
|
+
{ className: 'color-red', css: 'color: var(--pf-red-color);', category: 'Color' },
|
|
64
|
+
{ className: 'color-orange', css: 'color: var(--pf-orange-color);', category: 'Color' },
|
|
65
|
+
{ className: 'color-yellow', css: 'color: var(--pf-yellow-color);', category: 'Color' },
|
|
66
|
+
{ className: 'color-green', css: 'color: var(--pf-green-color);', category: 'Color' },
|
|
67
|
+
{ className: 'color-purple', css: 'color: var(--pf-purple-color);', category: 'Color' },
|
|
68
|
+
{ className: 'color-success', css: 'color: var(--pf-success-color);', category: 'Color' },
|
|
69
|
+
{ className: 'color-info', css: 'color: var(--pf-info-color);', category: 'Color' },
|
|
70
|
+
{ className: 'color-neutral', css: 'color: var(--pf-neutral-color);', category: 'Color' },
|
|
71
|
+
{ className: 'color-warning', css: 'color: var(--pf-warning-color);', category: 'Color' },
|
|
72
|
+
{ className: 'color-error', css: 'color: var(--pf-error-color);', category: 'Color' },
|
|
73
|
+
{ className: 'color-brand', css: 'color: var(--pf-brand-color);', category: 'Color' },
|
|
74
|
+
|
|
75
|
+
// Typography Utilities
|
|
76
|
+
{
|
|
77
|
+
className: 'text-h1',
|
|
78
|
+
css: 'font-size: var(--pf-font-size-h1); font-weight: var(--pf-font-weight-bold);',
|
|
79
|
+
category: 'Typography',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
className: 'text-h2',
|
|
83
|
+
css: 'font-size: var(--pf-font-size-h2); font-weight: var(--pf-font-weight-bold);',
|
|
84
|
+
category: 'Typography',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
className: 'text-h3',
|
|
88
|
+
css: 'font-size: var(--pf-font-size-h3); font-weight: var(--pf-font-weight-bold);',
|
|
89
|
+
category: 'Typography',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
className: 'text-h4',
|
|
93
|
+
css: 'font-size: var(--pf-font-size-h4); font-weight: var(--pf-font-weight-bold);',
|
|
94
|
+
category: 'Typography',
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
className: 'text-h5',
|
|
98
|
+
css: 'font-size: var(--pf-font-size-h5); font-weight: var(--pf-font-weight-bold);',
|
|
99
|
+
category: 'Typography',
|
|
100
|
+
},
|
|
101
|
+
{ className: 'text-body', css: 'font-size: var(--pf-font-size-body);', category: 'Typography' },
|
|
102
|
+
{
|
|
103
|
+
className: 'text-body-2',
|
|
104
|
+
css: 'font-size: var(--pf-font-size-body2);',
|
|
105
|
+
category: 'Typography',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
className: 'subtitle',
|
|
109
|
+
css: 'font-size: var(--pf-font-size-subtitle);',
|
|
110
|
+
category: 'Typography',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
className: 'subtitle-2',
|
|
114
|
+
css: 'font-size: var(--pf-font-size-subtitle2);',
|
|
115
|
+
category: 'Typography',
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
className: 'text-caption',
|
|
119
|
+
css: 'font-size: var(--pf-font-size-caption);',
|
|
120
|
+
category: 'Typography',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
className: 'text-overline',
|
|
124
|
+
css: 'font-size: var(--pf-font-size-overline); text-transform: uppercase;',
|
|
125
|
+
category: 'Typography',
|
|
126
|
+
},
|
|
127
|
+
{ className: 'text-capitalize', css: 'text-transform: capitalize;', category: 'Typography' },
|
|
128
|
+
{ className: 'text-uppercase', css: 'text-transform: uppercase;', category: 'Typography' },
|
|
129
|
+
{ className: 'text-lowercase', css: 'text-transform: lowercase;', category: 'Typography' },
|
|
130
|
+
{ className: 'text-decoration--none', css: 'text-decoration: none;', category: 'Typography' },
|
|
131
|
+
{
|
|
132
|
+
className: 'text-decoration--underline',
|
|
133
|
+
css: 'text-decoration: underline;',
|
|
134
|
+
category: 'Typography',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
className: 'text-decoration--line-through',
|
|
138
|
+
css: 'text-decoration: line-through;',
|
|
139
|
+
category: 'Typography',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
className: 'text-decoration--overline',
|
|
143
|
+
css: 'text-decoration: overline;',
|
|
144
|
+
category: 'Typography',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
className: 'text-weight--thin',
|
|
148
|
+
css: 'font-weight: var(--pf-font-weight-thin);',
|
|
149
|
+
category: 'Typography',
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
className: 'text-weight--light',
|
|
153
|
+
css: 'font-weight: var(--pf-font-weight-light);',
|
|
154
|
+
category: 'Typography',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
className: 'text-weight--regular',
|
|
158
|
+
css: 'font-weight: var(--pf-font-weight-regular);',
|
|
159
|
+
category: 'Typography',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
className: 'text-weight--medium',
|
|
163
|
+
css: 'font-weight: var(--pf-font-weight-medium);',
|
|
164
|
+
category: 'Typography',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
className: 'text-weight--bold',
|
|
168
|
+
css: 'font-weight: var(--pf-font-weight-bold);',
|
|
169
|
+
category: 'Typography',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
className: 'text-weight--heavy',
|
|
173
|
+
css: 'font-weight: var(--pf-font-weight-heavy);',
|
|
174
|
+
category: 'Typography',
|
|
175
|
+
},
|
|
176
|
+
{ className: 'text-align--left', css: 'text-align: left;', category: 'Typography' },
|
|
177
|
+
{ className: 'text-align--center', css: 'text-align: center;', category: 'Typography' },
|
|
178
|
+
{ className: 'text-align--right', css: 'text-align: right;', category: 'Typography' },
|
|
179
|
+
{ className: 'text-opacity--0', css: 'opacity: 0;', category: 'Typography' },
|
|
180
|
+
{ className: 'text-opacity--50', css: 'opacity: 0.5;', category: 'Typography' },
|
|
181
|
+
{ className: 'text-opacity--100', css: 'opacity: 1;', category: 'Typography' },
|
|
182
|
+
{ className: 'text-break--word', css: 'overflow-wrap: break-word;', category: 'Typography' },
|
|
183
|
+
|
|
184
|
+
// Sizing Utilities
|
|
185
|
+
{ className: 'ma-auto', css: 'margin: auto;', category: 'Sizing' },
|
|
186
|
+
{ className: 'ma-0', css: 'margin: var(--pf-margin-0);', category: 'Sizing' },
|
|
187
|
+
{ className: 'ma-1', css: 'margin: var(--pf-margin-1);', category: 'Sizing' },
|
|
188
|
+
{ className: 'ma-2', css: 'margin: var(--pf-margin-2);', category: 'Sizing' },
|
|
189
|
+
{ className: 'ma-3', css: 'margin: var(--pf-margin-3);', category: 'Sizing' },
|
|
190
|
+
{ className: 'ma-4', css: 'margin: var(--pf-margin-4);', category: 'Sizing' },
|
|
191
|
+
{ className: 'ma-5', css: 'margin: var(--pf-margin-5);', category: 'Sizing' },
|
|
192
|
+
{ className: 'ma-6', css: 'margin: var(--pf-margin-6);', category: 'Sizing' },
|
|
193
|
+
{ className: 'ma-7', css: 'margin: var(--pf-margin-7);', category: 'Sizing' },
|
|
194
|
+
{ className: 'ma-8', css: 'margin: var(--pf-margin-8);', category: 'Sizing' },
|
|
195
|
+
{ className: 'ma-9', css: 'margin: var(--pf-margin-9);', category: 'Sizing' },
|
|
196
|
+
{ className: 'ma-10', css: 'margin: var(--pf-margin-10);', category: 'Sizing' },
|
|
197
|
+
{ className: 'ma-11', css: 'margin: var(--pf-margin-11);', category: 'Sizing' },
|
|
198
|
+
{ className: 'ma-12', css: 'margin: var(--pf-margin-12);', category: 'Sizing' },
|
|
199
|
+
{ className: 'ma-13', css: 'margin: var(--pf-margin-13);', category: 'Sizing' },
|
|
200
|
+
{ className: 'ma-14', css: 'margin: var(--pf-margin-14);', category: 'Sizing' },
|
|
201
|
+
{ className: 'ma-15', css: 'margin: var(--pf-margin-15);', category: 'Sizing' },
|
|
202
|
+
{ className: 'ma-16', css: 'margin: var(--pf-margin-16);', category: 'Sizing' },
|
|
203
|
+
{ className: 'pa-0', css: 'padding: var(--pf-padding-0);', category: 'Sizing' },
|
|
204
|
+
{ className: 'pa-1', css: 'padding: var(--pf-padding-1);', category: 'Sizing' },
|
|
205
|
+
{ className: 'pa-2', css: 'padding: var(--pf-padding-2);', category: 'Sizing' },
|
|
206
|
+
{ className: 'pa-3', css: 'padding: var(--pf-padding-3);', category: 'Sizing' },
|
|
207
|
+
{ className: 'pa-4', css: 'padding: var(--pf-padding-4);', category: 'Sizing' },
|
|
208
|
+
{ className: 'pa-5', css: 'padding: var(--pf-padding-5);', category: 'Sizing' },
|
|
209
|
+
{ className: 'pa-6', css: 'padding: var(--pf-padding-6);', category: 'Sizing' },
|
|
210
|
+
{ className: 'pa-7', css: 'padding: var(--pf-padding-7);', category: 'Sizing' },
|
|
211
|
+
{ className: 'pa-8', css: 'padding: var(--pf-padding-8);', category: 'Sizing' },
|
|
212
|
+
{ className: 'pa-9', css: 'padding: var(--pf-padding-9);', category: 'Sizing' },
|
|
213
|
+
{ className: 'pa-10', css: 'padding: var(--pf-padding-10);', category: 'Sizing' },
|
|
214
|
+
{ className: 'pa-11', css: 'padding: var(--pf-padding-11);', category: 'Sizing' },
|
|
215
|
+
{ className: 'pa-12', css: 'padding: var(--pf-padding-12);', category: 'Sizing' },
|
|
216
|
+
{ className: 'pa-13', css: 'padding: var(--pf-padding-13);', category: 'Sizing' },
|
|
217
|
+
{ className: 'pa-14', css: 'padding: var(--pf-padding-14);', category: 'Sizing' },
|
|
218
|
+
{ className: 'pa-15', css: 'padding: var(--pf-padding-15);', category: 'Sizing' },
|
|
219
|
+
{ className: 'pa-16', css: 'padding: var(--pf-padding-16);', category: 'Sizing' },
|
|
220
|
+
|
|
221
|
+
// Icon Sizes
|
|
222
|
+
{ className: 'icon-xs', css: 'font-size: var(--pf-icon-size-xs);', category: 'Icon' },
|
|
223
|
+
{ className: 'icon-sm', css: 'font-size: var(--pf-icon-size-sm);', category: 'Icon' },
|
|
224
|
+
{ className: 'icon-md', css: 'font-size: var(--pf-icon-size-md);', category: 'Icon' },
|
|
225
|
+
{ className: 'icon-lg', css: 'font-size: var(--pf-icon-size-lg);', category: 'Icon' },
|
|
226
|
+
{ className: 'icon-xl', css: 'font-size: var(--pf-icon-size-xl);', category: 'Icon' },
|
|
227
|
+
|
|
228
|
+
// Drop Shadows
|
|
229
|
+
{ className: 'dropshadow', css: 'box-shadow: var(--pf-dropshadow);', category: 'Effect' },
|
|
230
|
+
];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { UtilityClassesTable } from './UtilityClassesTable';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof UtilityClassesTable> = {
|
|
5
|
+
title: 'remove/Utility Classes/Table',
|
|
6
|
+
component: UtilityClassesTable,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export default meta;
|
|
10
|
+
|
|
11
|
+
type Story = StoryObj<typeof UtilityClassesTable>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { Table, Select, Input, Container, Row, Col } from '@/components';
|
|
3
|
+
import { MultiValue, SingleValue, ActionMeta } from 'react-select';
|
|
4
|
+
import { UtilityClassData, utilityClassesData } from './UtilityClassesData';
|
|
5
|
+
|
|
6
|
+
const categories = Array.from(new Set(utilityClassesData.map((item) => item.category)));
|
|
7
|
+
|
|
8
|
+
// Resolve CSS variables using getComputedStyle
|
|
9
|
+
const resolveCssVariables = (css: string): string => {
|
|
10
|
+
const tempElement = document.createElement('div');
|
|
11
|
+
document.body.appendChild(tempElement);
|
|
12
|
+
const style = getComputedStyle(tempElement);
|
|
13
|
+
|
|
14
|
+
const resolvedCss = css.replace(/var\((--pf-[\w-]+)\)/g, (_, variable) => {
|
|
15
|
+
return style.getPropertyValue(variable).trim() || variable;
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
document.body.removeChild(tempElement);
|
|
19
|
+
return resolvedCss;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const formatCss = (css: string): string => {
|
|
23
|
+
return css
|
|
24
|
+
.split(';')
|
|
25
|
+
.filter(Boolean)
|
|
26
|
+
.map((line) => line.trim() + ';')
|
|
27
|
+
.join('\n');
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const UtilityClassesTable = () => {
|
|
31
|
+
const [classNameSearch, setClassNameSearch] = useState('');
|
|
32
|
+
const [cssSearch, setCssSearch] = useState('');
|
|
33
|
+
const [selectedCategories, setSelectedCategories] = useState<string[]>([]);
|
|
34
|
+
const [rowData, setRowData] = useState<UtilityClassData[]>([]);
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const resolved = utilityClassesData.map((item) => ({
|
|
38
|
+
...item,
|
|
39
|
+
resolvedCss: resolveCssVariables(item.css),
|
|
40
|
+
}));
|
|
41
|
+
setRowData(resolved);
|
|
42
|
+
}, []);
|
|
43
|
+
|
|
44
|
+
const handleCategoryChange = (
|
|
45
|
+
newValue:
|
|
46
|
+
| MultiValue<{ value: string; label: string }>
|
|
47
|
+
| SingleValue<{ value: string; label: string }>,
|
|
48
|
+
) => {
|
|
49
|
+
setSelectedCategories(Array.isArray(newValue) ? newValue.map((option) => option.value) : []);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const filteredData = rowData.filter(
|
|
53
|
+
(item) =>
|
|
54
|
+
(selectedCategories.length === 0 || selectedCategories.includes(item.category)) &&
|
|
55
|
+
item.className.toLowerCase().includes(classNameSearch.toLowerCase()) &&
|
|
56
|
+
(item.css.toLowerCase().includes(cssSearch.toLowerCase()) ||
|
|
57
|
+
item.resolvedCss?.toLowerCase().includes(cssSearch.toLowerCase())),
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<Container>
|
|
62
|
+
<Row className="mb-4">
|
|
63
|
+
<Col sm={4}>
|
|
64
|
+
<Input
|
|
65
|
+
id="classNameSearch"
|
|
66
|
+
name="classNameSearch"
|
|
67
|
+
label="Class Name"
|
|
68
|
+
value={classNameSearch}
|
|
69
|
+
onChange={(e) => setClassNameSearch(e.target.value)}
|
|
70
|
+
/>
|
|
71
|
+
</Col>
|
|
72
|
+
<Col sm={4}>
|
|
73
|
+
<Input
|
|
74
|
+
id="cssSearch"
|
|
75
|
+
name="cssSearch"
|
|
76
|
+
label="CSS"
|
|
77
|
+
value={cssSearch}
|
|
78
|
+
onChange={(e) => setCssSearch(e.target.value)}
|
|
79
|
+
/>
|
|
80
|
+
</Col>
|
|
81
|
+
<Col sm={4}>
|
|
82
|
+
<div className="form-control">
|
|
83
|
+
<div data-testid={`category-label`} className={`form-label mb-2`}>
|
|
84
|
+
<label htmlFor={`categoryFilter`}>Category</label>
|
|
85
|
+
</div>
|
|
86
|
+
<Select
|
|
87
|
+
id="categoryFilter"
|
|
88
|
+
name="categoryFilter"
|
|
89
|
+
options={categories.map((category) => ({ value: category, label: category }))}
|
|
90
|
+
onChange={handleCategoryChange}
|
|
91
|
+
value={categories
|
|
92
|
+
.filter((category) => selectedCategories.includes(category))
|
|
93
|
+
.map((category) => ({ value: category, label: category }))}
|
|
94
|
+
placeholder=""
|
|
95
|
+
isMulti
|
|
96
|
+
isClearable
|
|
97
|
+
/>
|
|
98
|
+
</div>
|
|
99
|
+
</Col>
|
|
100
|
+
</Row>
|
|
101
|
+
|
|
102
|
+
<Table
|
|
103
|
+
columns={[
|
|
104
|
+
{ name: 'Class Name', selector: (row) => row.className, sortable: true, width: '225px' },
|
|
105
|
+
{
|
|
106
|
+
name: 'CSS Applied',
|
|
107
|
+
selector: (row) => formatCss(row.css),
|
|
108
|
+
sortable: true,
|
|
109
|
+
cell: (row) => (
|
|
110
|
+
<pre
|
|
111
|
+
style={{
|
|
112
|
+
fontFamily: 'monospace',
|
|
113
|
+
whiteSpace: 'pre-wrap',
|
|
114
|
+
fontSize: '12px',
|
|
115
|
+
}}
|
|
116
|
+
>
|
|
117
|
+
{formatCss(row.css)}
|
|
118
|
+
</pre>
|
|
119
|
+
),
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: 'Resolved CSS',
|
|
123
|
+
selector: (row) => formatCss(row.resolvedCss || ''),
|
|
124
|
+
sortable: true,
|
|
125
|
+
cell: (row) => (
|
|
126
|
+
<pre
|
|
127
|
+
style={{
|
|
128
|
+
fontFamily: 'monospace',
|
|
129
|
+
whiteSpace: 'pre-wrap',
|
|
130
|
+
fontSize: '12px',
|
|
131
|
+
}}
|
|
132
|
+
>
|
|
133
|
+
{formatCss(row.resolvedCss || '')}
|
|
134
|
+
</pre>
|
|
135
|
+
),
|
|
136
|
+
},
|
|
137
|
+
{ name: 'Category', selector: (row) => row.category, sortable: true, width: '114px' },
|
|
138
|
+
]}
|
|
139
|
+
data={filteredData}
|
|
140
|
+
dense
|
|
141
|
+
noDataComponent="-- No Classes Found --"
|
|
142
|
+
pagination={false}
|
|
143
|
+
/>
|
|
144
|
+
</Container>
|
|
145
|
+
);
|
|
146
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const getPreviousHeadersWidth = (position: number): number => {
|
|
2
|
+
// Get headers with positions less than current position
|
|
3
|
+
const previousHeaders = Array.from({ length: position }, (_, i) =>
|
|
4
|
+
document.querySelector(`[data-column-id="sticky-column-${i}"]`),
|
|
5
|
+
).filter((header): header is HTMLElement => header !== null);
|
|
6
|
+
|
|
7
|
+
// Sum up widths of previous headers
|
|
8
|
+
return previousHeaders.reduce((acc, header) => {
|
|
9
|
+
const width = header.offsetWidth;
|
|
10
|
+
return acc + width;
|
|
11
|
+
}, 0);
|
|
12
|
+
};
|