uikit-react-public 0.49.6 → 0.50.1
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/dist/components/Button/Button.d.ts +8 -4
- package/dist/components/Button/Button.stories.d.ts +11 -2
- package/dist/components/Button/style/buttonPrimarySubtleStyle.d.ts +1 -1
- package/dist/components/Button/style/buttonSecondaryStyle.d.ts +1 -1
- package/dist/components/Button/style/buttonSecondarySubtleStyle.d.ts +1 -1
- package/dist/components/Button/style/buttonTertiaryDestructiveNoPaddingStyle.d.ts +4 -0
- package/dist/components/Button/style/buttonTertiaryDestructiveStyle.d.ts +1 -1
- package/dist/components/Button/style/buttonTertiaryNoPaddingStyle.d.ts +1 -1
- package/dist/components/Button/style/buttonTertiaryStyle.d.ts +1 -1
- package/dist/components/Filters/Filter.d.ts +20 -0
- package/dist/components/Filters/FilterPanel.d.ts +16 -0
- package/dist/components/Filters/Filters.context.d.ts +8 -0
- package/dist/components/Filters/Filters.d.ts +30 -0
- package/dist/components/Filters/Filters.stories.d.ts +17 -0
- package/dist/components/Filters/QuickFilter.d.ts +8 -0
- package/dist/components/Filters/__tests__/Filters.test.d.ts +1 -0
- package/dist/components/Filters/index.d.ts +6 -0
- package/dist/components/Overlay/Overlay.d.ts +1 -0
- package/dist/components/Overlay/Overlay.stories.d.ts +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/index.js +8807 -8141
- package/lib/components/Button/Button.mdx +12 -0
- package/lib/components/Button/Button.stories.tsx +46 -0
- package/lib/components/Button/Button.tsx +48 -25
- package/lib/components/Button/__tests__/Button.test.tsx +120 -1
- package/lib/components/Button/__tests__/__snapshots__/Button.test.tsx.snap +11 -11
- package/lib/components/Button/style/buttonAccentStyle.ts +2 -0
- package/lib/components/Button/style/buttonPrimaryDestructiveStyle.ts +2 -0
- package/lib/components/Button/style/buttonPrimaryStyle.ts +2 -0
- package/lib/components/Button/style/buttonPrimarySubtleStyle.ts +10 -11
- package/lib/components/Button/style/buttonPrimaryWarningStyle.ts +2 -0
- package/lib/components/Button/style/buttonSecondaryDestructiveStyle.ts +13 -7
- package/lib/components/Button/style/buttonSecondaryStyle.ts +49 -16
- package/lib/components/Button/style/buttonSecondarySubtleStyle.ts +15 -13
- package/lib/components/Button/style/buttonTertiaryDestructiveNoPaddingStyle.ts +34 -0
- package/lib/components/Button/style/buttonTertiaryDestructiveStyle.ts +9 -8
- package/lib/components/Button/style/buttonTertiaryNoPaddingStyle.ts +13 -15
- package/lib/components/Button/style/buttonTertiaryStyle.ts +10 -9
- package/lib/components/Filters/Filter.tsx +327 -0
- package/lib/components/Filters/FilterPanel.tsx +152 -0
- package/lib/components/Filters/Filters.context.ts +12 -0
- package/lib/components/Filters/Filters.mdx +75 -0
- package/lib/components/Filters/Filters.stories.tsx +354 -0
- package/lib/components/Filters/Filters.tsx +316 -0
- package/lib/components/Filters/QuickFilter.tsx +89 -0
- package/lib/components/Filters/__tests__/Filters.test.tsx +230 -0
- package/lib/components/Filters/index.ts +6 -0
- package/lib/components/Overlay/Overlay.tsx +9 -4
- package/lib/components/Overlay/__tests__/Overlay.test.tsx +39 -0
- package/lib/components/Table/subcomponents/Cell/__tests__/__snapshots__/Cell.test.tsx.snap +1 -1
- package/lib/components/index.ts +8 -0
- package/package.json +1 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { ButtonHTMLAttributes, memo } from 'react';
|
|
2
|
+
import { css, cx } from '@emotion/css';
|
|
3
|
+
import { useTheme } from '../../theme';
|
|
4
|
+
import { useFiltersContext } from './Filters.context';
|
|
5
|
+
|
|
6
|
+
export const NAME = 'ucl-uikit-quick-filter';
|
|
7
|
+
|
|
8
|
+
export interface QuickFilterProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
9
|
+
selected?: boolean;
|
|
10
|
+
testId?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const QuickFilter = ({
|
|
14
|
+
selected = false,
|
|
15
|
+
disabled = false,
|
|
16
|
+
testId = NAME,
|
|
17
|
+
className,
|
|
18
|
+
children,
|
|
19
|
+
type = 'button',
|
|
20
|
+
...props
|
|
21
|
+
}: QuickFilterProps) => {
|
|
22
|
+
const [theme] = useTheme();
|
|
23
|
+
const filtersContext = useFiltersContext();
|
|
24
|
+
const isDesktop = filtersContext?.isDesktop ?? true;
|
|
25
|
+
const typography = isDesktop
|
|
26
|
+
? theme.typography.body.sm
|
|
27
|
+
: theme.typography.body.smSemibold;
|
|
28
|
+
|
|
29
|
+
const baseStyle = css`
|
|
30
|
+
min-height: ${isDesktop ? '28px' : '32px'};
|
|
31
|
+
padding: ${theme.padding.p4}
|
|
32
|
+
${isDesktop ? theme.padding.p8 : theme.padding.p16};
|
|
33
|
+
border: ${theme.border.b1} solid ${theme.colour.border.brand};
|
|
34
|
+
border-radius: ${isDesktop ? theme.radius.r4 : theme.radius.r16};
|
|
35
|
+
box-sizing: border-box;
|
|
36
|
+
background-color: ${theme.colour.fill.default};
|
|
37
|
+
color: ${theme.colour.text.brand};
|
|
38
|
+
font-family: ${typography.fontFamily};
|
|
39
|
+
font-feature-settings: ${typography.fontSettings};
|
|
40
|
+
font-size: ${typography.fontSize}px;
|
|
41
|
+
font-weight: ${typography.fontWeight};
|
|
42
|
+
line-height: ${typography.lineHeight}%;
|
|
43
|
+
cursor: pointer;
|
|
44
|
+
|
|
45
|
+
&:hover {
|
|
46
|
+
background-color: ${theme.colour.fill.brandSubtleHover};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&:focus-visible {
|
|
50
|
+
outline: none;
|
|
51
|
+
box-shadow: ${theme.boxShadow.focus};
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
const selectedStyle = css`
|
|
56
|
+
background-color: ${theme.colour.fill.brandSubtleSelected};
|
|
57
|
+
color: ${theme.colour.text.brandHover};
|
|
58
|
+
`;
|
|
59
|
+
|
|
60
|
+
const disabledStyle = css`
|
|
61
|
+
border-color: ${theme.colour.border.disabled};
|
|
62
|
+
background-color: ${theme.colour.fill.disabled};
|
|
63
|
+
color: ${theme.colour.text.disabled};
|
|
64
|
+
cursor: not-allowed;
|
|
65
|
+
`;
|
|
66
|
+
|
|
67
|
+
const style = cx(
|
|
68
|
+
NAME,
|
|
69
|
+
baseStyle,
|
|
70
|
+
selected && selectedStyle,
|
|
71
|
+
disabled && disabledStyle,
|
|
72
|
+
className
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<button
|
|
77
|
+
type={type}
|
|
78
|
+
className={style}
|
|
79
|
+
disabled={disabled}
|
|
80
|
+
aria-pressed={selected}
|
|
81
|
+
data-testid={testId}
|
|
82
|
+
{...props}
|
|
83
|
+
>
|
|
84
|
+
{children}
|
|
85
|
+
</button>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export default memo(QuickFilter);
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { afterEach, describe, expect, test, vi } from 'vitest';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import userEvent from '@testing-library/user-event';
|
|
5
|
+
import { ThemeContextProvider } from '../../../theme';
|
|
6
|
+
import Filters from '../Filters';
|
|
7
|
+
import Filter from '../Filter';
|
|
8
|
+
import QuickFilter from '../QuickFilter';
|
|
9
|
+
|
|
10
|
+
const setDesktopViewport = (matches: boolean) => {
|
|
11
|
+
vi.stubGlobal(
|
|
12
|
+
'matchMedia',
|
|
13
|
+
vi.fn().mockImplementation(() => ({
|
|
14
|
+
matches,
|
|
15
|
+
media: '',
|
|
16
|
+
onchange: null,
|
|
17
|
+
addEventListener: vi.fn(),
|
|
18
|
+
removeEventListener: vi.fn(),
|
|
19
|
+
addListener: vi.fn(),
|
|
20
|
+
removeListener: vi.fn(),
|
|
21
|
+
dispatchEvent: vi.fn(),
|
|
22
|
+
}))
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const renderFilters = (component: React.ReactNode) =>
|
|
27
|
+
render(<ThemeContextProvider>{component}</ThemeContextProvider>);
|
|
28
|
+
|
|
29
|
+
const StatefulMobileFilters = () => {
|
|
30
|
+
const [value, setValue] = useState('');
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Filters
|
|
34
|
+
onOpenChange={() => {}}
|
|
35
|
+
onApply={() => {}}
|
|
36
|
+
>
|
|
37
|
+
<Filter
|
|
38
|
+
label='Search'
|
|
39
|
+
defaultOpen
|
|
40
|
+
>
|
|
41
|
+
<input
|
|
42
|
+
aria-label='Search records'
|
|
43
|
+
value={value}
|
|
44
|
+
onChange={(event) => setValue(event.target.value)}
|
|
45
|
+
/>
|
|
46
|
+
</Filter>
|
|
47
|
+
</Filters>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
describe('Filters', () => {
|
|
52
|
+
afterEach(() => {
|
|
53
|
+
vi.unstubAllGlobals();
|
|
54
|
+
vi.restoreAllMocks();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('opens a desktop panel in an Overlay and closes on Apply', async () => {
|
|
58
|
+
setDesktopViewport(true);
|
|
59
|
+
const user = userEvent.setup();
|
|
60
|
+
const onApply = vi.fn();
|
|
61
|
+
|
|
62
|
+
const result = renderFilters(
|
|
63
|
+
<Filters>
|
|
64
|
+
<Filter
|
|
65
|
+
label='File type'
|
|
66
|
+
onApply={onApply}
|
|
67
|
+
>
|
|
68
|
+
Panel controls
|
|
69
|
+
</Filter>
|
|
70
|
+
</Filters>
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const trigger = result.getByRole('button', { name: 'File type' });
|
|
74
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
75
|
+
|
|
76
|
+
await user.click(trigger);
|
|
77
|
+
|
|
78
|
+
const panel = result.getByRole('dialog', { name: 'File type filter' });
|
|
79
|
+
expect(panel.parentElement).toHaveClass('ucl-overlay');
|
|
80
|
+
expect(panel).toHaveTextContent('Panel controls');
|
|
81
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
82
|
+
|
|
83
|
+
await user.click(result.getByRole('button', { name: 'Apply' }));
|
|
84
|
+
|
|
85
|
+
expect(onApply).toHaveBeenCalledOnce();
|
|
86
|
+
expect(
|
|
87
|
+
result.queryByRole('dialog', { name: 'File type filter' })
|
|
88
|
+
).not.toBeInTheDocument();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('closes a desktop filter on Escape and restores trigger focus', async () => {
|
|
92
|
+
setDesktopViewport(true);
|
|
93
|
+
const user = userEvent.setup();
|
|
94
|
+
|
|
95
|
+
const result = renderFilters(
|
|
96
|
+
<Filters>
|
|
97
|
+
<Filter label='Status'>Panel controls</Filter>
|
|
98
|
+
</Filters>
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const trigger = result.getByRole('button', { name: 'Status' });
|
|
102
|
+
await user.click(trigger);
|
|
103
|
+
await user.keyboard('{Escape}');
|
|
104
|
+
|
|
105
|
+
expect(result.queryByText('Panel controls')).not.toBeInTheDocument();
|
|
106
|
+
expect(trigger).toHaveFocus();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('renders mobile filters in a bottom sheet and expands a filter inline', async () => {
|
|
110
|
+
setDesktopViewport(false);
|
|
111
|
+
const user = userEvent.setup();
|
|
112
|
+
const onApply = vi.fn();
|
|
113
|
+
const onReset = vi.fn();
|
|
114
|
+
|
|
115
|
+
const result = renderFilters(
|
|
116
|
+
<Filters
|
|
117
|
+
appliedCount={2}
|
|
118
|
+
onApply={onApply}
|
|
119
|
+
onReset={onReset}
|
|
120
|
+
>
|
|
121
|
+
<Filter
|
|
122
|
+
label='File type'
|
|
123
|
+
appliedCount={2}
|
|
124
|
+
>
|
|
125
|
+
Panel controls
|
|
126
|
+
</Filter>
|
|
127
|
+
</Filters>
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const groupTrigger = result.getByRole('button', {
|
|
131
|
+
name: 'Filters, 2 applied',
|
|
132
|
+
});
|
|
133
|
+
expect(groupTrigger).toHaveTextContent('');
|
|
134
|
+
await user.click(groupTrigger);
|
|
135
|
+
|
|
136
|
+
expect(result.getByRole('dialog', { name: 'Filters' })).toBeInTheDocument();
|
|
137
|
+
expect(result.getByTestId('ucl-blanket')).toBeInTheDocument();
|
|
138
|
+
expect(result.queryByText('Panel controls')).not.toBeInTheDocument();
|
|
139
|
+
|
|
140
|
+
await user.click(result.getByRole('button', { name: /File type/ }));
|
|
141
|
+
expect(result.getByText('Panel controls')).toBeInTheDocument();
|
|
142
|
+
|
|
143
|
+
await user.click(result.getByRole('button', { name: 'Reset all' }));
|
|
144
|
+
expect(onReset).toHaveBeenCalledOnce();
|
|
145
|
+
|
|
146
|
+
await user.click(result.getByRole('button', { name: 'Apply filters' }));
|
|
147
|
+
expect(onApply).toHaveBeenCalledOnce();
|
|
148
|
+
expect(
|
|
149
|
+
result.queryByRole('dialog', { name: 'Filters' })
|
|
150
|
+
).not.toBeInTheDocument();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test('preserves focus when an inline open callback changes identity', async () => {
|
|
154
|
+
setDesktopViewport(false);
|
|
155
|
+
const user = userEvent.setup();
|
|
156
|
+
const result = renderFilters(<StatefulMobileFilters />);
|
|
157
|
+
|
|
158
|
+
await user.click(result.getByRole('button', { name: 'Filters' }));
|
|
159
|
+
|
|
160
|
+
const input = result.getByRole('textbox', { name: 'Search records' });
|
|
161
|
+
await user.click(input);
|
|
162
|
+
await user.type(input, 'report');
|
|
163
|
+
|
|
164
|
+
expect(input).toHaveFocus();
|
|
165
|
+
expect(input).toHaveValue('report');
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test('supports controlled open state', async () => {
|
|
169
|
+
setDesktopViewport(true);
|
|
170
|
+
const user = userEvent.setup();
|
|
171
|
+
const onOpenChange = vi.fn();
|
|
172
|
+
|
|
173
|
+
const result = renderFilters(
|
|
174
|
+
<Filters>
|
|
175
|
+
<Filter
|
|
176
|
+
label='Status'
|
|
177
|
+
open={false}
|
|
178
|
+
onOpenChange={onOpenChange}
|
|
179
|
+
>
|
|
180
|
+
Panel controls
|
|
181
|
+
</Filter>
|
|
182
|
+
</Filters>
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
await user.click(result.getByRole('button', { name: 'Status' }));
|
|
186
|
+
|
|
187
|
+
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
188
|
+
expect(result.queryByText('Panel controls')).not.toBeInTheDocument();
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test('keeps only one filter open at a time', async () => {
|
|
192
|
+
setDesktopViewport(true);
|
|
193
|
+
const user = userEvent.setup();
|
|
194
|
+
|
|
195
|
+
const result = renderFilters(
|
|
196
|
+
<Filters>
|
|
197
|
+
<Filter label='File type'>File controls</Filter>
|
|
198
|
+
<Filter label='Status'>Status controls</Filter>
|
|
199
|
+
</Filters>
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
await user.click(result.getByRole('button', { name: 'File type' }));
|
|
203
|
+
expect(result.getByText('File controls')).toBeInTheDocument();
|
|
204
|
+
|
|
205
|
+
await user.click(result.getByRole('button', { name: 'Status' }));
|
|
206
|
+
expect(result.queryByText('File controls')).not.toBeInTheDocument();
|
|
207
|
+
expect(result.getByText('Status controls')).toBeInTheDocument();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test('QuickFilter exposes its selected state', async () => {
|
|
211
|
+
setDesktopViewport(true);
|
|
212
|
+
const user = userEvent.setup();
|
|
213
|
+
const onClick = vi.fn();
|
|
214
|
+
|
|
215
|
+
const result = renderFilters(
|
|
216
|
+
<QuickFilter
|
|
217
|
+
selected
|
|
218
|
+
onClick={onClick}
|
|
219
|
+
>
|
|
220
|
+
Last 30 days
|
|
221
|
+
</QuickFilter>
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
const quickFilter = result.getByRole('button', { name: 'Last 30 days' });
|
|
225
|
+
expect(quickFilter).toHaveAttribute('aria-pressed', 'true');
|
|
226
|
+
|
|
227
|
+
await user.click(quickFilter);
|
|
228
|
+
expect(onClick).toHaveBeenCalledOnce();
|
|
229
|
+
});
|
|
230
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default } from './Filters';
|
|
2
|
+
export { default as Filter } from './Filter';
|
|
3
|
+
export { default as QuickFilter } from './QuickFilter';
|
|
4
|
+
export type { FiltersProps, FiltersSubComponents } from './Filters';
|
|
5
|
+
export type { FilterProps } from './Filter';
|
|
6
|
+
export type { QuickFilterProps } from './QuickFilter';
|
|
@@ -44,6 +44,7 @@ export type OverlaySize = {
|
|
|
44
44
|
|
|
45
45
|
export interface OverlayProps extends HTMLAttributes<HTMLDivElement> {
|
|
46
46
|
reference: RefObject<HTMLElement | null>;
|
|
47
|
+
positioning?: 'reference' | 'viewport';
|
|
47
48
|
placement?: Placement;
|
|
48
49
|
strategy?: Strategy;
|
|
49
50
|
blanket?: boolean;
|
|
@@ -63,6 +64,7 @@ const Overlay = forwardRef<Ref, OverlayProps>(
|
|
|
63
64
|
(
|
|
64
65
|
{
|
|
65
66
|
reference,
|
|
67
|
+
positioning = 'reference',
|
|
66
68
|
placement = 'bottom',
|
|
67
69
|
strategy = 'absolute',
|
|
68
70
|
blanket = false,
|
|
@@ -146,6 +148,7 @@ const Overlay = forwardRef<Ref, OverlayProps>(
|
|
|
146
148
|
|
|
147
149
|
const overlayPlacement = currentPlacement.split('-')[0] as
|
|
148
150
|
'left' | 'right' | 'top' | 'bottom';
|
|
151
|
+
const isReferencePositioned = positioning === 'reference';
|
|
149
152
|
|
|
150
153
|
useLayoutEffect(() => {
|
|
151
154
|
refs.setReference(reference.current);
|
|
@@ -237,11 +240,13 @@ const Overlay = forwardRef<Ref, OverlayProps>(
|
|
|
237
240
|
className={style}
|
|
238
241
|
style={{
|
|
239
242
|
...(inlineStyle as CSSProperties),
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
+
...(isReferencePositioned && {
|
|
244
|
+
position: strategy,
|
|
245
|
+
left: x ?? 0,
|
|
246
|
+
top: y ?? 0,
|
|
247
|
+
}),
|
|
243
248
|
visibility:
|
|
244
|
-
x === null || y === null
|
|
249
|
+
isReferencePositioned && (x === null || y === null)
|
|
245
250
|
? 'hidden'
|
|
246
251
|
: (inlineStyle as CSSProperties | undefined)?.visibility,
|
|
247
252
|
}}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { afterEach, describe, expect, test, vi } from 'vitest';
|
|
2
2
|
import { useRef } from 'react';
|
|
3
3
|
import { render, waitFor } from '@testing-library/react';
|
|
4
|
+
import { css } from '@emotion/css';
|
|
4
5
|
import Overlay from '../Overlay';
|
|
5
6
|
|
|
6
7
|
describe('Overlay', () => {
|
|
@@ -78,4 +79,42 @@ describe('Overlay', () => {
|
|
|
78
79
|
});
|
|
79
80
|
});
|
|
80
81
|
});
|
|
82
|
+
|
|
83
|
+
test('allows viewport positioning to be defined by className', async () => {
|
|
84
|
+
const TestOverlay = () => {
|
|
85
|
+
const reference = useRef<HTMLButtonElement>(null);
|
|
86
|
+
const viewportStyle = css`
|
|
87
|
+
position: fixed;
|
|
88
|
+
inset: auto 0 0;
|
|
89
|
+
`;
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<>
|
|
93
|
+
<button
|
|
94
|
+
ref={reference}
|
|
95
|
+
type='button'
|
|
96
|
+
>
|
|
97
|
+
Anchor
|
|
98
|
+
</button>
|
|
99
|
+
<Overlay
|
|
100
|
+
reference={reference}
|
|
101
|
+
positioning='viewport'
|
|
102
|
+
className={viewportStyle}
|
|
103
|
+
>
|
|
104
|
+
Content
|
|
105
|
+
</Overlay>
|
|
106
|
+
</>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const result = render(<TestOverlay />);
|
|
111
|
+
const overlay = result.container.querySelector('.ucl-overlay');
|
|
112
|
+
|
|
113
|
+
await waitFor(() => {
|
|
114
|
+
expect(overlay).toHaveStyle({
|
|
115
|
+
position: 'fixed',
|
|
116
|
+
inset: 'auto 0 0',
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
});
|
|
81
120
|
});
|
package/lib/components/index.ts
CHANGED
|
@@ -37,6 +37,14 @@ export type { BlanketProps } from './Blanket';
|
|
|
37
37
|
export { default as Overlay } from './Overlay';
|
|
38
38
|
export type { OverlayProps } from './Overlay';
|
|
39
39
|
|
|
40
|
+
export { default as Filters, Filter, QuickFilter } from './Filters';
|
|
41
|
+
export type {
|
|
42
|
+
FiltersProps,
|
|
43
|
+
FiltersSubComponents,
|
|
44
|
+
FilterProps,
|
|
45
|
+
QuickFilterProps,
|
|
46
|
+
} from './Filters';
|
|
47
|
+
|
|
40
48
|
export { default as Snackbar } from './Snackbar';
|
|
41
49
|
export { Snackbars } from './Snackbar';
|
|
42
50
|
export type {
|