@seeqdev/qomponents 0.0.183 → 0.0.185
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/README.md +5 -19
- package/dist/example/.eslintrc.cjs +2 -6
- package/dist/example/README.md +0 -3
- package/dist/example/src/Example.tsx +7 -7
- package/dist/example/tsconfig.json +2 -8
- package/dist/example/tsconfig.node.json +1 -3
- package/dist/example/vite.config.ts +1 -1
- package/dist/index.esm.js +784 -523
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +781 -520
- package/dist/index.js.map +1 -1
- package/dist/src/Accordion/Accordion.js +8 -0
- package/dist/src/Accordion/Accordion.stories.js +96 -0
- package/dist/src/Accordion/Accordion.test.js +54 -0
- package/dist/src/Accordion/Accordion.types.js +1 -0
- package/dist/src/Accordion/index.js +1 -0
- package/dist/src/Alert/Alert.js +33 -0
- package/dist/src/Alert/Alert.stories.d.ts +13 -5
- package/dist/src/Alert/Alert.stories.js +72 -0
- package/dist/src/Alert/Alert.test.js +49 -0
- package/dist/src/Alert/Alert.types.js +1 -0
- package/dist/src/Alert/index.js +1 -0
- package/dist/src/Button/Button.js +107 -0
- package/dist/src/Button/Button.stories.js +74 -0
- package/dist/src/Button/Button.test.js +65 -0
- package/dist/src/Button/Button.types.d.ts +4 -4
- package/dist/src/Button/Button.types.js +4 -0
- package/dist/src/Button/index.d.ts +1 -1
- package/dist/src/Button/index.js +1 -0
- package/dist/src/ButtonGroup/ButtonGroup.js +34 -0
- package/dist/src/ButtonGroup/ButtonGroup.stories.js +328 -0
- package/dist/src/ButtonGroup/ButtonGroup.test.js +65 -0
- package/dist/src/ButtonGroup/ButtonGroup.types.js +1 -0
- package/dist/src/ButtonGroup/index.js +1 -0
- package/dist/src/ButtonWithDropdown/ButtonWithDropdown.js +46 -0
- package/dist/src/ButtonWithDropdown/ButtonWithDropdown.stories.js +119 -0
- package/dist/src/ButtonWithDropdown/ButtonWithDropdown.test.js +92 -0
- package/dist/src/ButtonWithDropdown/ButtonWithDropdown.types.js +1 -0
- package/dist/src/ButtonWithDropdown/index.js +1 -0
- package/dist/src/ButtonWithPopover/ButtonWithPopover.js +54 -0
- package/dist/src/ButtonWithPopover/ButtonWithPopover.stories.js +51 -0
- package/dist/src/ButtonWithPopover/ButtonWithPopover.test.js +80 -0
- package/dist/src/ButtonWithPopover/ButtonWithPopover.types.js +1 -0
- package/dist/src/ButtonWithPopover/index.js +1 -0
- package/dist/src/Carousel/Carousel.js +80 -0
- package/dist/src/Carousel/Carousel.stories.js +100 -0
- package/dist/src/Carousel/Carousel.test.js +47 -0
- package/dist/src/Carousel/Carousel.types.js +1 -0
- package/dist/src/Carousel/index.js +1 -0
- package/dist/src/Checkbox/Checkbox.js +24 -0
- package/dist/src/Checkbox/Checkbox.stories.js +21 -0
- package/dist/src/Checkbox/Checkbox.test.js +93 -0
- package/dist/src/Checkbox/Checkbox.types.js +1 -0
- package/dist/src/Checkbox/index.js +1 -0
- package/dist/src/Collapse/Collapse.js +16 -0
- package/dist/src/Collapse/Collapse.stories.js +28 -0
- package/dist/src/Collapse/Collapse.test.js +16 -0
- package/dist/src/Collapse/Collapse.types.js +1 -0
- package/dist/src/Collapse/index.js +1 -0
- package/dist/src/Icon/Icon.js +55 -0
- package/dist/src/Icon/Icon.stories.js +31 -0
- package/dist/src/Icon/Icon.test.js +54 -0
- package/dist/src/Icon/Icon.types.d.ts +1 -1
- package/dist/src/Icon/Icon.types.js +15 -0
- package/dist/src/Icon/index.js +1 -0
- package/dist/src/InputGroup/InputGroup.js +33 -0
- package/dist/src/InputGroup/InputGroup.stories.js +144 -0
- package/dist/src/InputGroup/InputGroup.test.js +41 -0
- package/dist/src/InputGroup/InputGroup.types.js +1 -0
- package/dist/src/InputGroup/index.js +1 -0
- package/dist/src/Modal/Modal.js +86 -0
- package/dist/src/Modal/Modal.stories.js +79 -0
- package/dist/src/Modal/Modal.test.js +107 -0
- package/dist/src/Modal/Modal.types.js +1 -0
- package/dist/src/Modal/index.js +1 -0
- package/dist/src/ProgressBar/ProgressBar.js +71 -0
- package/dist/src/ProgressBar/ProgressBar.stories.js +46 -0
- package/dist/src/ProgressBar/ProgressBar.test.js +42 -0
- package/dist/src/ProgressBar/ProgressBar.types.js +1 -0
- package/dist/src/ProgressBar/index.js +1 -0
- package/dist/src/SeeqActionDropdown/SeeqActionDropdown.js +41 -0
- package/dist/src/SeeqActionDropdown/SeeqActionDropdown.stories.js +73 -0
- package/dist/src/SeeqActionDropdown/SeeqActionDropdown.test.js +72 -0
- package/dist/src/SeeqActionDropdown/SeeqActionDropdown.types.d.ts +0 -5
- package/dist/src/SeeqActionDropdown/SeeqActionDropdown.types.js +1 -0
- package/dist/src/SeeqActionDropdown/index.js +1 -0
- package/dist/src/SeeqActionDropdown/variants.js +34 -0
- package/dist/src/Select/Select.js +171 -0
- package/dist/src/Select/Select.stories.js +50 -0
- package/dist/src/Select/Select.test.js +176 -0
- package/dist/src/Select/Select.types.js +1 -0
- package/dist/src/Select/index.js +2 -0
- package/dist/src/Slider/Slider.js +11 -0
- package/dist/src/Slider/Slider.stories.js +37 -0
- package/dist/src/Slider/Slider.test.js +31 -0
- package/dist/src/Slider/Slider.types.js +1 -0
- package/dist/src/Slider/index.js +1 -0
- package/dist/src/SvgIcon/SvgIcon.js +27 -0
- package/dist/src/SvgIcon/SvgIcon.stories.js +26 -0
- package/dist/src/SvgIcon/SvgIcon.test.js +40 -0
- package/dist/src/SvgIcon/SvgIcon.types.d.ts +1 -1
- package/dist/src/SvgIcon/SvgIcon.types.js +2 -0
- package/dist/src/SvgIcon/index.js +1 -0
- package/dist/src/Tabs/Tabs.js +18 -0
- package/dist/src/Tabs/Tabs.stories.js +83 -0
- package/dist/src/Tabs/Tabs.test.js +91 -0
- package/dist/src/Tabs/Tabs.types.js +1 -0
- package/dist/src/Tabs/index.js +1 -0
- package/dist/src/TextArea/TextArea.js +54 -0
- package/dist/src/TextArea/TextArea.stories.js +21 -0
- package/dist/src/TextArea/TextArea.test.js +129 -0
- package/dist/src/TextArea/TextArea.types.js +1 -0
- package/dist/src/TextArea/index.js +1 -0
- package/dist/src/TextField/TextField.js +85 -0
- package/dist/src/TextField/TextField.stories.js +30 -0
- package/dist/src/TextField/TextField.test.js +40 -0
- package/dist/src/TextField/TextField.types.js +1 -0
- package/dist/src/TextField/index.js +1 -0
- package/dist/src/ToolbarButton/ToolbarButton.js +58 -0
- package/dist/src/ToolbarButton/ToolbarButton.stories.js +63 -0
- package/dist/src/ToolbarButton/ToolbarButton.test.js +89 -0
- package/dist/src/ToolbarButton/ToolbarButton.types.d.ts +1 -1
- package/dist/src/ToolbarButton/ToolbarButton.types.js +1 -0
- package/dist/src/ToolbarButton/index.js +1 -0
- package/dist/src/Tooltip/QTip.stories.js +22 -0
- package/dist/src/Tooltip/QTip.types.js +1 -0
- package/dist/src/Tooltip/QTipPerformance.stories.js +27 -0
- package/dist/src/Tooltip/Qtip.js +168 -0
- package/dist/src/Tooltip/Tooltip.js +34 -0
- package/dist/src/Tooltip/Tooltip.stories.js +20 -0
- package/dist/src/Tooltip/Tooltip.types.d.ts +1 -1
- package/dist/src/Tooltip/Tooltip.types.js +2 -0
- package/dist/src/Tooltip/TooltipPerformance.stories.js +25 -0
- package/dist/src/Tooltip/index.js +2 -0
- package/dist/src/Tooltip/qTip.utilities.js +10 -0
- package/dist/src/index.js +47 -0
- package/dist/src/setupTests.js +5 -0
- package/dist/src/types.js +25 -0
- package/dist/src/utils/browserId.d.ts +3 -3
- package/dist/src/utils/browserId.js +28 -0
- package/dist/src/utils/svg.js +19 -0
- package/dist/src/utils/validateStyleDimension.js +13 -0
- package/dist/src/utils/validateStyleDimension.test.js +19 -0
- package/dist/styles.css +3410 -2791
- package/package.json +22 -17
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import userEvent from '@testing-library/user-event';
|
|
5
|
+
import ButtonWithDropdown from './ButtonWithDropdown';
|
|
6
|
+
import Icon from '../Icon';
|
|
7
|
+
describe('ButtonWithDropdown', () => {
|
|
8
|
+
const mockOnClick = jest.fn();
|
|
9
|
+
const testId = 'trigger-icon';
|
|
10
|
+
const tooltip = 'This is a small dropdown.';
|
|
11
|
+
const itemTooltip = 'This is an item from the dropdown.';
|
|
12
|
+
class Context {
|
|
13
|
+
props = {
|
|
14
|
+
triggerIcon: (_jsx(Icon, { icon: "fc-more", type: "text", testId: testId, extraClassNames: "tw-text-sq-text-color dark:tw-text-sq-white tw-w-[18px]" })),
|
|
15
|
+
containerTestId: 'basic-dropdown1',
|
|
16
|
+
tooltip,
|
|
17
|
+
tooltipDelay: 0,
|
|
18
|
+
tooltipPlacement: 'top',
|
|
19
|
+
isHtmlTooltip: false,
|
|
20
|
+
dropdownItems: [
|
|
21
|
+
{ label: 'Orange', icon: 'fc-data-file', onClick: mockOnClick },
|
|
22
|
+
{ label: 'Mango', icon: 'fc-user-community', onClick: mockOnClick },
|
|
23
|
+
{ label: 'Guava', icon: 'fc-user-community', onClick: mockOnClick },
|
|
24
|
+
{
|
|
25
|
+
label: 'Banana',
|
|
26
|
+
icon: 'fc-user-community',
|
|
27
|
+
onClick: mockOnClick,
|
|
28
|
+
tooltip: itemTooltip,
|
|
29
|
+
tooltipPlacement: 'top',
|
|
30
|
+
tooltipDelay: 0,
|
|
31
|
+
isHtmlTooltip: false,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
let tc;
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
tc = new Context();
|
|
39
|
+
jest.clearAllMocks();
|
|
40
|
+
});
|
|
41
|
+
const renderButtonWithDropdown = (props) => render(_jsx(ButtonWithDropdown, { ...props }));
|
|
42
|
+
const openDropdown = async () => {
|
|
43
|
+
const popover = screen.getByTestId(testId);
|
|
44
|
+
await userEvent.click(popover);
|
|
45
|
+
};
|
|
46
|
+
test('renders trigger and opens dropdown content on trigger click', async () => {
|
|
47
|
+
renderButtonWithDropdown(tc.props);
|
|
48
|
+
expect(screen.getByTestId('trigger-icon')).toBeInTheDocument();
|
|
49
|
+
await openDropdown();
|
|
50
|
+
expect(screen.getByText('Orange')).toBeInTheDocument();
|
|
51
|
+
});
|
|
52
|
+
test('renders dividers correctly', async () => {
|
|
53
|
+
tc.props.dropdownItems[1].hasDivider = true;
|
|
54
|
+
renderButtonWithDropdown(tc.props);
|
|
55
|
+
expect(screen.getByTestId('trigger-icon')).toBeInTheDocument();
|
|
56
|
+
await openDropdown();
|
|
57
|
+
expect(screen.getByText('Orange')).toBeInTheDocument();
|
|
58
|
+
expect(screen.getByTestId('dropdown-divider-1')).toBeInTheDocument();
|
|
59
|
+
});
|
|
60
|
+
test('calls onClick handler when dropdown item is selected', async () => {
|
|
61
|
+
renderButtonWithDropdown(tc.props);
|
|
62
|
+
await openDropdown();
|
|
63
|
+
const item1 = screen.getByText('Orange');
|
|
64
|
+
await userEvent.click(item1);
|
|
65
|
+
expect(mockOnClick).toHaveBeenCalledTimes(1);
|
|
66
|
+
});
|
|
67
|
+
test('closes dropdown when item is clicked', async () => {
|
|
68
|
+
renderButtonWithDropdown(tc.props);
|
|
69
|
+
await openDropdown();
|
|
70
|
+
const item1 = screen.getByText('Orange');
|
|
71
|
+
await userEvent.click(item1);
|
|
72
|
+
expect(mockOnClick).toHaveBeenCalledTimes(1);
|
|
73
|
+
expect(screen.queryByText('Orange')).not.toBeInTheDocument();
|
|
74
|
+
});
|
|
75
|
+
test('does not open when disabled', async () => {
|
|
76
|
+
tc.props.disabled = true;
|
|
77
|
+
renderButtonWithDropdown(tc.props);
|
|
78
|
+
await openDropdown();
|
|
79
|
+
expect(screen.queryByText('Orange')).not.toBeInTheDocument();
|
|
80
|
+
});
|
|
81
|
+
test('renders button tooltip correctly', async () => {
|
|
82
|
+
renderButtonWithDropdown(tc.props);
|
|
83
|
+
const tooltipText = document.querySelector(`[data-qtip-text="${tooltip}"]`);
|
|
84
|
+
expect(tooltipText).toBeInTheDocument();
|
|
85
|
+
});
|
|
86
|
+
test('renders dropdown item tooltip correctly', async () => {
|
|
87
|
+
renderButtonWithDropdown(tc.props);
|
|
88
|
+
await openDropdown();
|
|
89
|
+
const tooltipText = document.querySelector(`[data-qtip-text="${itemTooltip}"]`);
|
|
90
|
+
expect(tooltipText).toBeInTheDocument();
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './ButtonWithDropdown';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { useRef } from 'react';
|
|
4
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
5
|
+
import { getQTipData } from '../Tooltip/qTip.utilities';
|
|
6
|
+
const bgStyles = ['tw-bg-sq-white', 'dark:tw-bg-sq-dark-background'].join(' ');
|
|
7
|
+
const borderStyles = [
|
|
8
|
+
'tw-border-solid',
|
|
9
|
+
'tw-border',
|
|
10
|
+
'tw-rounded-popover',
|
|
11
|
+
'tw-border-sq-disabled-gray',
|
|
12
|
+
'dark:tw-border-gray-500',
|
|
13
|
+
].join(' ');
|
|
14
|
+
const disabledClasses = ['tw-opacity-50', 'tw-cursor-not-allowed'].join(' ');
|
|
15
|
+
const ButtonWithPopover = ({ children, trigger, id, hasArrow, extraTriggerClassNames, extraPopoverClassNames, containerTestId, onInteractOutside, onPointerDownOutside, isTriggerAsChild = false, shouldTriggerFullWidth = false, disabled = false, align = 'end', alignOffset = -35, placement = 'bottom', placementOffset = 2, isHoverEnabled = false, hoverOpenDelay = 300, onOpenChange, isOpen, isCloseOnContentClick = false, isPortal = false, ...tooltipProps }) => {
|
|
16
|
+
const tooltipData = getQTipData(tooltipProps);
|
|
17
|
+
const timeout = useRef(null);
|
|
18
|
+
const [isHoveredOpen, setIsHoveredOpen] = React.useState(false);
|
|
19
|
+
const clearHoverTimeout = () => {
|
|
20
|
+
if (timeout.current) {
|
|
21
|
+
clearTimeout(timeout.current);
|
|
22
|
+
timeout.current = null;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const onHoverStart = () => {
|
|
26
|
+
if (isHoverEnabled) {
|
|
27
|
+
clearHoverTimeout();
|
|
28
|
+
timeout.current = setTimeout(() => {
|
|
29
|
+
setIsHoveredOpen(true);
|
|
30
|
+
onOpenChange && onOpenChange(true);
|
|
31
|
+
}, hoverOpenDelay);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const onHoverEnd = () => {
|
|
35
|
+
if (isHoverEnabled) {
|
|
36
|
+
clearHoverTimeout();
|
|
37
|
+
timeout.current = setTimeout(() => {
|
|
38
|
+
setIsHoveredOpen(false);
|
|
39
|
+
onOpenChange && onOpenChange(false);
|
|
40
|
+
}, 200);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
React.useEffect(() => clearHoverTimeout, []);
|
|
44
|
+
const renderContent = () => {
|
|
45
|
+
return (_jsx(PopoverPrimitive.Content, { sideOffset: placementOffset, align: align, side: placement, onInteractOutside: onInteractOutside, onPointerDownOutside: onPointerDownOutside, alignOffset: isHoverEnabled ? -10 : alignOffset, asChild: true, onClick: () => isCloseOnContentClick && onOpenChange && onOpenChange(false), className: "focus-visible:tw-outline-none tw-outline-none tw-w-full tw-h-full", children: _jsxs("div", { "data-testid": containerTestId, className: `${bgStyles} ${borderStyles} tw-relative tw-z-[1200] tw-min-w-6 focus-visible:tw-outline-none tw-outline-none data-[state=open]:tw-animate-in data-[state=closed]:tw-animate-out
|
|
46
|
+
data-[side=top]:tw-animate-slideDownAndFade data-[side=right]:tw-animate-slideLeftAndFade data-[side=bottom]:tw-animate-slideUpAndFade data-[side=left]:tw-animate-slideRightAndFade tw-text-sq-text-color
|
|
47
|
+
${extraPopoverClassNames || ''}`, children: [hasArrow && (_jsx(PopoverPrimitive.Arrow, { asChild: true, children: _jsx("div", { className: "tw-fill-transparent tw-bg-white tw-w-[15px] tw-h-[15px] tw-mt-[-7px] tw-rotate-45 dark:tw-bg-sq-dark-background tw-border-b tw-border-r tw-border-sq-disabled-gray dark:tw-border-gray-500" }) })), children] }) }));
|
|
48
|
+
};
|
|
49
|
+
const renderPopover = (popoverOpenState) => {
|
|
50
|
+
return (_jsxs(PopoverPrimitive.Root, { open: popoverOpenState, defaultOpen: false, onOpenChange: onOpenChange, children: [trigger ? (_jsx(PopoverPrimitive.Trigger, { id: id, asChild: isTriggerAsChild, className: `focus-visible:tw-outline-none tw-outline-none ${shouldTriggerFullWidth ? 'tw-w-full tw-h-full' : ''}`, disabled: disabled, children: _jsx("div", { ...tooltipData, onMouseOver: onHoverStart, onMouseOut: onHoverEnd, className: `tw-bg-transparent focus-visible:tw-outline-none tw-outline-none ${disabled ? disabledClasses : ''} ${shouldTriggerFullWidth ? 'tw-flex tw-flex-col tw-items-center tw-justify-center' : 'tw-inline'} ${extraTriggerClassNames || ''}`, children: trigger }) })) : (_jsx(PopoverPrimitive.Trigger, { asChild: true, children: _jsx("div", {}) })), isPortal ? _jsx(PopoverPrimitive.Portal, { children: renderContent() }) : renderContent()] }));
|
|
51
|
+
};
|
|
52
|
+
return isHoverEnabled ? renderPopover(isHoveredOpen) : renderPopover(isOpen);
|
|
53
|
+
};
|
|
54
|
+
export default ButtonWithPopover;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import ButtonWithPopover from './ButtonWithPopover';
|
|
4
|
+
import Icon from '../Icon';
|
|
5
|
+
import { QTip } from '../Tooltip/Qtip';
|
|
6
|
+
export default {
|
|
7
|
+
title: 'Button with Popover',
|
|
8
|
+
};
|
|
9
|
+
export const AllButtonWithPopoverVariants = () => {
|
|
10
|
+
const options = ['Chocolate', 'Strawberry', 'Vanilla', 'Rocky Road', 'Crazy Cow', 'Almond Joy'];
|
|
11
|
+
const renderFlavours = () => (_jsxs("div", { className: "tw-text-sm dark:tw-text-white tw-w-72 tw-p-4", children: [
|
|
12
|
+
_jsx("p", { className: "tw-font-bold", children: "Flavors" }), _jsx("div", { className: "tw-w-full tw-flex tw-flex-wrap tw-gap-1", children: options.map((option) => (_jsxs("div", { className: "tw-flex tw-items-center tw-px-2 tw-py-1 tw-mt-2 tw tw-rounded-full tw-border-sq-color-dark-dark tw-border", children: [
|
|
13
|
+
_jsx(Icon, { type: "color", color: "rgb(var(--sq-color-dark-dark))", icon: "fc-check", extraClassNames: "tw-mr-2" }), _jsx("span", { children: option })
|
|
14
|
+
] }, option))) })
|
|
15
|
+
] }));
|
|
16
|
+
const renderInputFields = () => {
|
|
17
|
+
const [name, setName] = React.useState('');
|
|
18
|
+
const [email, setEmail] = React.useState('');
|
|
19
|
+
return (_jsx("div", { className: "tw-w-72 tw-p-4", children: _jsxs("div", { className: "tw-flex tw-flex-col tw-gap-2", children: [
|
|
20
|
+
_jsx("input", { type: "text", value: name, onChange: (e) => setName(e.target.value), placeholder: "Enter your name", className: "tw-p-2 tw-rounded tw-border tw-border-sq-color-dark-dark dark:tw-border-sq-dark-background tw-bg-transparent" }), _jsx("input", { type: "text", value: email, onChange: (e) => setEmail(e.target.value), placeholder: "Enter your email", className: "tw-p-2 tw-rounded tw-border tw-border-sq-color-dark-dark dark:tw-border-sq-dark-background tw-bg-transparent" }), _jsx("button", { className: "tw-p-2 tw-rounded tw-border tw-border-sq-color-dark-dark dark:tw-border-sq-dark-background tw-bg-transparent tw-text-sq-color", children: "Submit" })
|
|
21
|
+
] }) }));
|
|
22
|
+
};
|
|
23
|
+
const [openPopver, setOpenPopover] = React.useState('');
|
|
24
|
+
const iconRef = React.useRef(null);
|
|
25
|
+
const allButtonWithPopovers = (isDark = false, topic) => (_jsxs("div", { className: isDark ? 'tw-dark tw-bg-sq-dark-background ' : '', children: [
|
|
26
|
+
_jsx("div", { className: "tw-p-5 ", children: _jsx(ButtonWithPopover, { trigger: _jsx(Icon, { type: "color", color: "rgb(var(--sq-color-dark-dark))", icon: "fc-more" }), containerTestId: `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-1`, tooltip: "This is a small popover.", tooltipDelay: 0, tooltipPlacement: "top", isHtmlTooltip: false, children: renderFlavours() }) }), _jsx("div", { className: "tw-p-5 ", children: _jsx(ButtonWithPopover, { trigger: _jsx(Icon, { type: "color", color: "rgb(var(--sq-color-dark-dark))", icon: "fc-more" }), containerTestId: `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-2`, isOpen: openPopver === `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-2`, onOpenChange: (isOpen) => setOpenPopover(isOpen ? `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-2` : ''), tooltip: "This is a normal popover.", tooltipDelay: 0, tooltipPlacement: "top", isHtmlTooltip: false, children: renderFlavours() }) }), _jsxs("div", { className: "tw-p-5 ", children: [
|
|
27
|
+
_jsx("p", { className: "dark:tw-text-sq-white tw-text-sm tw-mb-4", children: "Close popover on content click" }), _jsx(ButtonWithPopover, { trigger: _jsx(Icon, { type: "color", color: "rgb(var(--sq-color-dark-dark))", icon: "fc-more" }), containerTestId: `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-3`, isOpen: openPopver === `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-3`, onOpenChange: (isOpen) => setOpenPopover(isOpen ? `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-3` : ''), tooltip: "This is a normal popover.", tooltipDelay: 0, tooltipPlacement: "top", isCloseOnContentClick: true, isHtmlTooltip: false, children: renderFlavours() })
|
|
28
|
+
] }), _jsx("div", { className: "tw-p-5 ", children: _jsx(ButtonWithPopover, { trigger: _jsx(Icon, { type: "color", color: "rgb(var(--sq-color-dark-dark))", icon: "fc-more" }), containerTestId: `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-4`, isOpen: openPopver === `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-4`, onOpenChange: (isOpen) => setOpenPopover(isOpen ? `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-4` : ''), tooltip: "This is a disabled popover.", tooltipDelay: 0, tooltipPlacement: "top", isHtmlTooltip: false, disabled: true, children: renderFlavours() }) }), _jsxs("div", { className: "tw-p-5 ", children: [
|
|
29
|
+
_jsx("div", { className: "dark:tw-text-white tw-text-xs", children: "Popover with arrow" }), _jsx(ButtonWithPopover, { trigger: _jsx(Icon, { type: "color", color: "rgb(var(--sq-color-dark-dark))", icon: "fc-more" }), containerTestId: `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-5`, isOpen: openPopver === `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-5`, onOpenChange: (isOpen) => setOpenPopover(isOpen ? `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-5` : ''), tooltip: "This is a normal popover with arrow.", tooltipDelay: 0, tooltipPlacement: "top", hasArrow: true, isHtmlTooltip: false, children: renderFlavours() })
|
|
30
|
+
] }), _jsxs("div", { className: "tw-p-5 ", children: [
|
|
31
|
+
_jsx("div", { className: "dark:tw-text-white tw-text-xs", children: "Popover aligned at center" }), _jsx(ButtonWithPopover, { trigger: _jsx(Icon, { type: "color", color: "rgb(var(--sq-color-dark-dark))", icon: "fc-more" }), containerTestId: `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-6`, isOpen: openPopver === `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-6`, onOpenChange: (isOpen) => setOpenPopover(isOpen ? `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-6` : ''), tooltip: "This is a normal popover with arrow.", tooltipDelay: 0, tooltipPlacement: "top", align: "center", hasArrow: true, isHtmlTooltip: false, children: renderFlavours() })
|
|
32
|
+
] }), _jsxs("div", { className: "tw-p-5 ", children: [
|
|
33
|
+
_jsx("div", { className: "dark:tw-text-white tw-text-xs", children: "Popover aligned at start" }), _jsx(ButtonWithPopover, { trigger: _jsx(Icon, { type: "color", color: "rgb(var(--sq-color-dark-dark))", icon: "fc-more" }), containerTestId: `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-7`, isOpen: openPopver === `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-7`, onOpenChange: (isOpen) => setOpenPopover(isOpen ? `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-7` : ''), tooltip: "This is a normal popover with arrow.", tooltipDelay: 0, align: "start", tooltipPlacement: "top", hasArrow: true, isHtmlTooltip: false, children: renderFlavours() })
|
|
34
|
+
] }), _jsxs("div", { className: "tw-p-5 ", children: [
|
|
35
|
+
_jsx("div", { className: "dark:tw-text-white tw-text-xs", children: "Popover triggered by hover" }), _jsx(ButtonWithPopover, { trigger: _jsx(Icon, { type: "color", color: "rgb(var(--sq-color-dark-dark))", icon: "fc-more" }), containerTestId: `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-8`, isOpen: openPopver === `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-8`, onOpenChange: (isOpen) => setOpenPopover(isOpen ? `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-8` : ''), isHoverEnabled: true, align: "start", tooltipPlacement: "top", hasArrow: true, isHtmlTooltip: false, children: renderFlavours() })
|
|
36
|
+
] }), _jsxs("div", { className: "tw-p-5 ", children: [
|
|
37
|
+
_jsx(ButtonWithPopover, { trigger: _jsx("div", { className: "dark:tw-text-white tw-text-xs", children: "Popover triggered by another element" }), containerTestId: `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-9`, isOpen: openPopver === `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-9`, onInteractOutside: () => setOpenPopover(''), align: "start", tooltipPlacement: "top", hasArrow: true, isHtmlTooltip: false, children: renderFlavours() }), openPopver != `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-9` && (_jsx("div", { ref: iconRef, onClick: () => {
|
|
38
|
+
setOpenPopover(`basic-popover-${isDark ? 'dark' : 'light'}-${topic}-9`);
|
|
39
|
+
}, children: _jsx(Icon, { type: "text", icon: "fc-all-items" }) }))] }), _jsxs("div", { className: "tw-p-5 ", children: [
|
|
40
|
+
_jsx("div", { className: "dark:tw-text-white tw-text-xs", children: "Popover with input fields" }), _jsx(ButtonWithPopover, { trigger: _jsx(Icon, { type: "color", color: "rgb(var(--sq-color-dark-dark))", icon: "fc-more" }), containerTestId: `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-10`, isOpen: openPopver === `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-10`, onOpenChange: (isOpen) => setOpenPopover(isOpen ? `basic-popover-${isDark ? 'dark' : 'light'}-${topic}-10` : ''), tooltip: "This is a normal popover with arrow.", tooltipDelay: 0, tooltipPlacement: "top", align: "center", hasArrow: true, isHtmlTooltip: false, children: renderInputFields() })
|
|
41
|
+
] })
|
|
42
|
+
] }));
|
|
43
|
+
const renderAllVariations = (color) => (_jsxs("div", { className: "tw-grid tw-grid-cols-2 tw-gap-4 tw-p-4", children: [allButtonWithPopovers(false, color), allButtonWithPopovers(true, color)] }));
|
|
44
|
+
return (_jsxs("div", { className: "tw-grid tw-grid-cols-4 tw-gap-4", children: [
|
|
45
|
+
_jsx(QTip, {}), _jsxs("div", { className: "color_topic", children: [
|
|
46
|
+
_jsx("b", { children: "Topic Colors" }), renderAllVariations('topic')] }), _jsxs("div", { className: "color_analysis", children: [
|
|
47
|
+
_jsx("b", { children: "Analysis Colors" }), renderAllVariations('analysis')] }), _jsxs("div", { className: "color_datalab", children: [
|
|
48
|
+
_jsx("b", { children: "Datalab Colors" }), renderAllVariations('datalab')] }), _jsxs("div", { className: "color_vantage", children: [
|
|
49
|
+
_jsx("b", { children: "Vantage Colors" }), renderAllVariations('vantage')] })
|
|
50
|
+
] }));
|
|
51
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
4
|
+
import userEvent from '@testing-library/user-event';
|
|
5
|
+
import ButtonWithPopover from './ButtonWithPopover';
|
|
6
|
+
import Icon from '../Icon';
|
|
7
|
+
describe('ButtonWithPopover', () => {
|
|
8
|
+
const mockOnClick = jest.fn();
|
|
9
|
+
const testId = 'trigger-icon';
|
|
10
|
+
class Context {
|
|
11
|
+
props = {
|
|
12
|
+
trigger: (_jsx(Icon, { icon: "fc-more", type: "text", testId: testId, extraClassNames: "tw-text-sq-text-color dark:tw-text-sq-white tw-w-[18px]" })),
|
|
13
|
+
onOpenChange: mockOnClick,
|
|
14
|
+
containerTestId: 'basic-Popover1',
|
|
15
|
+
tooltip: 'This is a small Popover.',
|
|
16
|
+
tooltipDelay: 0,
|
|
17
|
+
tooltipPlacement: 'top',
|
|
18
|
+
isHtmlTooltip: false,
|
|
19
|
+
hoverOpenDelay: 0,
|
|
20
|
+
children: _jsx("div", { children: "Popover content" }),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
let tc;
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
tc = new Context();
|
|
26
|
+
jest.clearAllMocks();
|
|
27
|
+
});
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
global.ResizeObserver = undefined;
|
|
30
|
+
});
|
|
31
|
+
const renderButtonWithPopover = (props) => render(_jsx("div", { "data-testid": "container", className: "tw-w-10 tw-h-10", children: _jsx(ButtonWithPopover, { ...props }) }));
|
|
32
|
+
const openPopover = async () => {
|
|
33
|
+
const popover = screen.getByTestId(testId);
|
|
34
|
+
await userEvent.click(popover);
|
|
35
|
+
};
|
|
36
|
+
const closePopover = async () => {
|
|
37
|
+
const container = screen.getByTestId('container');
|
|
38
|
+
await userEvent.click(container);
|
|
39
|
+
};
|
|
40
|
+
test('renders trigger and opens Popover content on trigger click', async () => {
|
|
41
|
+
renderButtonWithPopover(tc.props);
|
|
42
|
+
expect(screen.getByTestId('trigger-icon')).toBeInTheDocument();
|
|
43
|
+
await openPopover();
|
|
44
|
+
expect(screen.getByText('Popover content')).toBeInTheDocument();
|
|
45
|
+
await closePopover();
|
|
46
|
+
expect(screen.queryByText('Popover content')).not.toBeInTheDocument();
|
|
47
|
+
});
|
|
48
|
+
test('renders trigger and opens Popover content on trigger hover', async () => {
|
|
49
|
+
tc.props.isHoverEnabled = true;
|
|
50
|
+
renderButtonWithPopover(tc.props);
|
|
51
|
+
expect(screen.getByTestId('trigger-icon')).toBeInTheDocument();
|
|
52
|
+
const popover = screen.getByTestId(testId);
|
|
53
|
+
await userEvent.hover(popover);
|
|
54
|
+
await waitFor(() => {
|
|
55
|
+
expect(screen.getByText('Popover content')).toBeInTheDocument();
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
test('closes popover when content is clicked and is set in props', async () => {
|
|
59
|
+
tc.props.isCloseOnContentClick = true;
|
|
60
|
+
renderButtonWithPopover(tc.props);
|
|
61
|
+
await openPopover();
|
|
62
|
+
const item1 = screen.getByText('Popover content');
|
|
63
|
+
await userEvent.click(item1);
|
|
64
|
+
expect(mockOnClick).toHaveBeenCalledTimes(2);
|
|
65
|
+
});
|
|
66
|
+
test('leaves popover open when content is clicked and is set in props', async () => {
|
|
67
|
+
tc.props.isCloseOnContentClick = false;
|
|
68
|
+
renderButtonWithPopover(tc.props);
|
|
69
|
+
await openPopover();
|
|
70
|
+
const item1 = screen.getByText('Popover content');
|
|
71
|
+
await userEvent.click(item1);
|
|
72
|
+
expect(mockOnClick).toHaveBeenCalledTimes(1);
|
|
73
|
+
});
|
|
74
|
+
test('does not open when disabled', async () => {
|
|
75
|
+
tc.props.disabled = true;
|
|
76
|
+
renderButtonWithPopover(tc.props);
|
|
77
|
+
await openPopover();
|
|
78
|
+
expect(screen.queryByText('Popover content')).not.toBeInTheDocument();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './ButtonWithPopover';
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { motion } from 'framer-motion';
|
|
4
|
+
import Button from '../Button/Button';
|
|
5
|
+
/**
|
|
6
|
+
* Carousel:
|
|
7
|
+
* - Easily create a carousel with custom slides.
|
|
8
|
+
* - Supports automatic sliding, navigation arrows, and slide indicators.
|
|
9
|
+
*/
|
|
10
|
+
const Carousel = ({ testId = 'carousel-id', activeIndex = 0, extraClassNames = '', onSlide = () => { }, autoSlide, showIndicators = true, continuous = true, interval = 4000, prevIcon = 'fc-arrow-dropdown tw-rotate-90', nextIcon = 'fc-arrow-dropdown -tw-rotate-90', showArrows = true, iconExtraClassNames = '', carouselItems = [], }) => {
|
|
11
|
+
const [currentIndex, setCurrentIndex] = useState(activeIndex);
|
|
12
|
+
const changeSlide = (nextIndex) => {
|
|
13
|
+
const newIndex = (nextIndex + carouselItems.length) % carouselItems.length;
|
|
14
|
+
setCurrentIndex(newIndex);
|
|
15
|
+
onSlide(newIndex, newIndex > currentIndex ? 'right' : 'left');
|
|
16
|
+
};
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (autoSlide) {
|
|
19
|
+
const slideInterval = setInterval(() => {
|
|
20
|
+
if (continuous || currentIndex < carouselItems.length - 1) {
|
|
21
|
+
changeSlide(currentIndex + 1);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
clearInterval(slideInterval);
|
|
25
|
+
}
|
|
26
|
+
}, interval);
|
|
27
|
+
return () => clearInterval(slideInterval);
|
|
28
|
+
}
|
|
29
|
+
}, [autoSlide, currentIndex, continuous, interval, carouselItems.length]);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (activeIndex !== currentIndex) {
|
|
32
|
+
setCurrentIndex(activeIndex);
|
|
33
|
+
}
|
|
34
|
+
}, [activeIndex]);
|
|
35
|
+
const onBackClick = () => {
|
|
36
|
+
if (currentIndex === 0 && !continuous) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
let prevIndex = currentIndex - 1;
|
|
40
|
+
if (prevIndex < 0) {
|
|
41
|
+
prevIndex = carouselItems.length - 1;
|
|
42
|
+
}
|
|
43
|
+
changeSlide(prevIndex);
|
|
44
|
+
};
|
|
45
|
+
const onForwardClick = () => {
|
|
46
|
+
if (currentIndex === carouselItems.length - 1) {
|
|
47
|
+
if (!continuous) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
changeSlide(0);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
changeSlide(currentIndex + 1);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const springTransition = {
|
|
57
|
+
type: 'spring',
|
|
58
|
+
damping: 20,
|
|
59
|
+
stiffness: 100,
|
|
60
|
+
};
|
|
61
|
+
const slideVariants = {
|
|
62
|
+
initial: (direction) => ({
|
|
63
|
+
x: direction > 0 ? '100%' : '-100%',
|
|
64
|
+
opacity: 0,
|
|
65
|
+
}),
|
|
66
|
+
animate: {
|
|
67
|
+
x: 0,
|
|
68
|
+
opacity: 1,
|
|
69
|
+
transition: springTransition,
|
|
70
|
+
},
|
|
71
|
+
exit: (direction) => ({
|
|
72
|
+
x: direction > 0 ? '-100%' : '100%',
|
|
73
|
+
opacity: 0,
|
|
74
|
+
transition: springTransition,
|
|
75
|
+
}),
|
|
76
|
+
};
|
|
77
|
+
return (_jsxs("div", { "data-testid": testId, className: `tw-flex tw-flex-col tw-items-center tw-justify-center tw-w-full tw-overflow-hidden ${extraClassNames}`, children: [
|
|
78
|
+
_jsxs("div", { className: "tw-flex tw-items-center tw-w-full tw-h-max tw-gap-1", children: [showArrows && (_jsx(Button, { icon: prevIcon, size: "lg", variant: "no-border", testId: "carousel-prev", extraClassNames: `${currentIndex === 0 && !continuous ? 'tw-invisible' : ''} ${iconExtraClassNames} tw-animate-fadeIn`, onClick: onBackClick })), _jsx("div", { className: "tw-h-full tw-w-full tw-overflow-hidden", children: _jsx(motion.div, { custom: 1, initial: "initial", animate: "animate", exit: "exit", variants: slideVariants, className: "tw-w-full", children: carouselItems[currentIndex] }, currentIndex) }), showArrows && (_jsx(Button, { icon: nextIcon, testId: "carousel-next", size: "lg", variant: "no-border", extraClassNames: `${currentIndex === carouselItems.length - 1 && !continuous ? 'tw-invisible' : ''} ${iconExtraClassNames} tw-animate-fadeIn`, onClick: onForwardClick }))] }), showIndicators && (_jsx("div", { className: "tw-flex tw-gap-1 tw-mt-2", children: carouselItems.map((_, i) => (_jsx("div", { className: `tw-w-2 tw-h-2 tw-rounded-full tw-cursor-pointer ${i === currentIndex ? 'tw-bg-sq-color-dark' : 'tw-bg-sq-darkish-gray'}`, onClick: () => changeSlide(i) }, i))) }))] }));
|
|
79
|
+
};
|
|
80
|
+
export default Carousel;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { QTip } from '../Tooltip/Qtip';
|
|
4
|
+
import Carousel from './Carousel';
|
|
5
|
+
import Button from '../Button';
|
|
6
|
+
export default {
|
|
7
|
+
title: 'Carousel',
|
|
8
|
+
};
|
|
9
|
+
export const AllCarousels = () => {
|
|
10
|
+
const [value, setValue] = React.useState(0);
|
|
11
|
+
const renderChild = (text, extraClass) => (_jsxs("div", { className: 'tw-p-4 tw-text-sq-color-gray dark:tw-text-sq-white tw-h-[200px] ' + extraClass, children: [
|
|
12
|
+
_jsx("p", { className: "tw-mb-5 tw-text-[0.9375rem] tw-leading-normal", children: text }), _jsx(Button, { variant: "outline", label: "Save data" })
|
|
13
|
+
] }));
|
|
14
|
+
const renderAllVariations = () => (_jsxs(_Fragment, { children: [
|
|
15
|
+
_jsxs("div", { className: "light", children: [
|
|
16
|
+
_jsxs("div", { className: "tw-p-4", children: [
|
|
17
|
+
_jsx("p", { children: "Controlled" }), _jsx(Carousel, { carouselItems: [
|
|
18
|
+
renderChild('First of her name, the Queen to be, long may she reign', 'tw-bg-yellow-500'),
|
|
19
|
+
renderChild('Second of her home, but her love conquers all', 'tw-bg-green-500'),
|
|
20
|
+
renderChild('Third is a wonder, the embodiment of hope and faith', 'tw-bg-gray-500'),
|
|
21
|
+
], activeIndex: value, onSlide: (index) => setValue(index) })
|
|
22
|
+
] }), _jsxs("div", { className: "tw-p-4", children: [
|
|
23
|
+
_jsx("p", { children: "Uncontrolled" }), _jsx(Carousel, { carouselItems: [
|
|
24
|
+
renderChild('First of her name, the Queen to be, long may she reign', 'tw-bg-yellow-500'),
|
|
25
|
+
renderChild('Second of her home, but her love conquers all', 'tw-bg-green-500'),
|
|
26
|
+
renderChild('Third is a wonder, the embodiment of hope and faith', 'tw-bg-gray-500'),
|
|
27
|
+
], autoSlide: true, continuous: true, showArrows: false })
|
|
28
|
+
] }), _jsxs("div", { className: "tw-p-4", children: [
|
|
29
|
+
_jsx("p", { children: "Custom side buttons" }), _jsx(Carousel, { carouselItems: [
|
|
30
|
+
renderChild('First of her name, the Queen to be, long may she reign', 'tw-bg-yellow-500'),
|
|
31
|
+
renderChild('Second of her home, but her love conquers all', 'tw-bg-green-500'),
|
|
32
|
+
renderChild('Third is a wonder, the embodiment of hope and faith', 'tw-bg-gray-500'),
|
|
33
|
+
], activeIndex: value, onSlide: (index) => setValue(index), nextIcon: "fc-more", prevIcon: "fc-y-axis" })
|
|
34
|
+
] }), _jsxs("div", { className: "tw-p-4", children: [
|
|
35
|
+
_jsx("p", { children: "Continuous" }), _jsx(Carousel, { carouselItems: [
|
|
36
|
+
renderChild('First of her name, the Queen to be, long may she reign', 'tw-bg-yellow-500'),
|
|
37
|
+
renderChild('Second of her home, but her love conquers all', 'tw-bg-green-500'),
|
|
38
|
+
renderChild('Third is a wonder, the embodiment of hope and faith', 'tw-bg-gray-500'),
|
|
39
|
+
], activeIndex: value, onSlide: (index) => setValue(index), continuous: true })
|
|
40
|
+
] }), _jsxs("div", { className: "tw-p-4", children: [
|
|
41
|
+
_jsx("p", { children: "Non continuous" }), _jsx(Carousel, { carouselItems: [
|
|
42
|
+
renderChild('First of her name, the Queen to be, long may she reign', 'tw-bg-yellow-500'),
|
|
43
|
+
renderChild('Second of her home, but her love conquers all', 'tw-bg-green-500'),
|
|
44
|
+
renderChild('Third is a wonder, the embodiment of hope and faith', 'tw-bg-gray-500'),
|
|
45
|
+
], activeIndex: value, onSlide: (index) => setValue(index), showArrows: true, continuous: false })
|
|
46
|
+
] }), _jsxs("div", { className: "tw-p-4", children: [
|
|
47
|
+
_jsx("p", { children: "Without indicators" }), _jsx(Carousel, { carouselItems: [
|
|
48
|
+
renderChild('First of her name, the Queen to be, long may she reign', 'tw-bg-yellow-500'),
|
|
49
|
+
renderChild('Second of her home, but her love conquers all', 'tw-bg-green-500'),
|
|
50
|
+
renderChild('Third is a wonder, the embodiment of hope and faith', 'tw-bg-gray-500'),
|
|
51
|
+
], activeIndex: value, onSlide: (index) => setValue(index), showArrows: true, continuous: true, showIndicators: false })
|
|
52
|
+
] })
|
|
53
|
+
] }), _jsxs("div", { className: "tw-dark tw-bg-sq-dark-background", children: [
|
|
54
|
+
_jsxs("div", { className: "tw-p-4", children: [
|
|
55
|
+
_jsx("p", { children: "Controlled" }), _jsx(Carousel, { carouselItems: [
|
|
56
|
+
renderChild('First of her name, the Queen to be, long may she reign', 'tw-bg-yellow-500'),
|
|
57
|
+
renderChild('Second of her home, but her love conquers all', 'tw-bg-green-500'),
|
|
58
|
+
renderChild('Third is a wonder, the embodiment of hope and faith', 'tw-bg-gray-500'),
|
|
59
|
+
], activeIndex: value, onSlide: (index) => setValue(index) })
|
|
60
|
+
] }), _jsxs("div", { className: "tw-p-4", children: [
|
|
61
|
+
_jsx("p", { children: "Uncontrolled" }), _jsx(Carousel, { carouselItems: [
|
|
62
|
+
renderChild('First of her name, the Queen to be, long may she reign', 'tw-bg-yellow-500'),
|
|
63
|
+
renderChild('Second of her home, but her love conquers all', 'tw-bg-green-500'),
|
|
64
|
+
renderChild('Third is a wonder, the embodiment of hope and faith', 'tw-bg-gray-500'),
|
|
65
|
+
], autoSlide: true, continuous: true, showArrows: false })
|
|
66
|
+
] }), _jsxs("div", { className: "tw-p-4", children: [
|
|
67
|
+
_jsx("p", { children: "Custom side buttons" }), _jsx(Carousel, { carouselItems: [
|
|
68
|
+
renderChild('First of her name, the Queen to be, long may she reign', 'tw-bg-yellow-500'),
|
|
69
|
+
renderChild('Second of her home, but her love conquers all', 'tw-bg-green-500'),
|
|
70
|
+
renderChild('Third is a wonder, the embodiment of hope and faith', 'tw-bg-gray-500'),
|
|
71
|
+
], activeIndex: value, onSlide: (index) => setValue(index), nextIcon: "fc-more", prevIcon: "fc-y-axis" })
|
|
72
|
+
] }), _jsxs("div", { className: "tw-p-4", children: [
|
|
73
|
+
_jsx("p", { children: "Continuous" }), _jsx(Carousel, { carouselItems: [
|
|
74
|
+
renderChild('First of her name, the Queen to be, long may she reign', 'tw-bg-yellow-500'),
|
|
75
|
+
renderChild('Second of her home, but her love conquers all', 'tw-bg-green-500'),
|
|
76
|
+
renderChild('Third is a wonder, the embodiment of hope and faith', 'tw-bg-gray-500'),
|
|
77
|
+
], activeIndex: value, onSlide: (index) => setValue(index), continuous: true })
|
|
78
|
+
] }), _jsxs("div", { className: "tw-p-4", children: [
|
|
79
|
+
_jsx("p", { children: "Non continuous" }), _jsx(Carousel, { carouselItems: [
|
|
80
|
+
renderChild('First of her name, the Queen to be, long may she reign', 'tw-bg-yellow-500'),
|
|
81
|
+
renderChild('Second of her home, but her love conquers all', 'tw-bg-green-500'),
|
|
82
|
+
renderChild('Third is a wonder, the embodiment of hope and faith', 'tw-bg-gray-500'),
|
|
83
|
+
], activeIndex: value, onSlide: (index) => setValue(index), showArrows: true, continuous: false })
|
|
84
|
+
] }), _jsxs("div", { className: "tw-p-4", children: [
|
|
85
|
+
_jsx("p", { children: "Without indicators" }), _jsx(Carousel, { carouselItems: [
|
|
86
|
+
renderChild('First of her name, the Queen to be, long may she reign', 'tw-bg-yellow-500'),
|
|
87
|
+
renderChild('Second of her home, but her love conquers all', 'tw-bg-green-500'),
|
|
88
|
+
renderChild('Third is a wonder, the embodiment of hope and faith', 'tw-bg-gray-500'),
|
|
89
|
+
], activeIndex: value, onSlide: (index) => setValue(index), showArrows: true, continuous: true, showIndicators: false })
|
|
90
|
+
] })
|
|
91
|
+
] })
|
|
92
|
+
] }));
|
|
93
|
+
return (_jsxs("div", { className: "tw-grid tw-grid-cols-4 tw-gap-4", children: [
|
|
94
|
+
_jsx(QTip, {}), _jsxs("div", { className: "color_topic", children: [
|
|
95
|
+
_jsx("b", { children: "Topic Colors" }), renderAllVariations()] }), _jsxs("div", { className: "color_analysis", children: [
|
|
96
|
+
_jsx("b", { children: "Analysis Colors" }), renderAllVariations()] }), _jsxs("div", { className: "color_datalab", children: [
|
|
97
|
+
_jsx("b", { children: "Datalab Colors" }), renderAllVariations()] }), _jsxs("div", { className: "color_vantage", children: [
|
|
98
|
+
_jsx("b", { children: "Vantage Colors" }), renderAllVariations()] })
|
|
99
|
+
] }));
|
|
100
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { act, render, fireEvent, screen } from '@testing-library/react';
|
|
4
|
+
import Carousel from './Carousel';
|
|
5
|
+
describe('Carousel Component', () => {
|
|
6
|
+
const mockOnSlide = jest.fn();
|
|
7
|
+
const carouselItems = [_jsx("div", { children: "Slide 1" }, "1"), _jsx("div", { children: "Slide 2" }, "2"), _jsx("div", { children: "Slide 3" }, "3")];
|
|
8
|
+
it('renders correctly', () => {
|
|
9
|
+
render(_jsx(Carousel, { testId: "carousel", carouselItems: carouselItems }));
|
|
10
|
+
expect(screen.getByTestId('carousel')).toBeInTheDocument();
|
|
11
|
+
});
|
|
12
|
+
it('shows the correct initial slide', () => {
|
|
13
|
+
render(_jsx(Carousel, { testId: "carousel", carouselItems: carouselItems, activeIndex: 1 }));
|
|
14
|
+
expect(screen.getByText('Slide 2')).toBeInTheDocument();
|
|
15
|
+
});
|
|
16
|
+
it('calls onSlide when next button is clicked', () => {
|
|
17
|
+
render(_jsx(Carousel, { testId: "carousel", carouselItems: carouselItems, onSlide: mockOnSlide }));
|
|
18
|
+
const nextButton = screen.getByTestId('carousel-next');
|
|
19
|
+
fireEvent.click(nextButton);
|
|
20
|
+
expect(mockOnSlide).toHaveBeenCalledWith(1, 'right');
|
|
21
|
+
});
|
|
22
|
+
it('calls onSlide when previous button is clicked', () => {
|
|
23
|
+
render(_jsx(Carousel, { testId: "carousel", carouselItems: carouselItems, onSlide: mockOnSlide, activeIndex: 1 }));
|
|
24
|
+
const prevButton = screen.getByTestId('carousel-prev');
|
|
25
|
+
fireEvent.click(prevButton);
|
|
26
|
+
expect(mockOnSlide).toHaveBeenCalledWith(0, 'left');
|
|
27
|
+
});
|
|
28
|
+
it('does not move past the last slide', () => {
|
|
29
|
+
render(_jsx(Carousel, { testId: "carousel", carouselItems: carouselItems, activeIndex: 2, continuous: false }));
|
|
30
|
+
const nextButton = screen.queryByTestId('carousel-next');
|
|
31
|
+
expect(nextButton).toHaveClass('tw-invisible');
|
|
32
|
+
});
|
|
33
|
+
it('autoSlides correctly', async () => {
|
|
34
|
+
jest.useFakeTimers();
|
|
35
|
+
render(_jsx(Carousel, { testId: "carousel", carouselItems: carouselItems, autoSlide: true, interval: 1000 }));
|
|
36
|
+
expect(screen.getByText('Slide 1')).toBeInTheDocument();
|
|
37
|
+
act(() => {
|
|
38
|
+
jest.advanceTimersByTime(1000);
|
|
39
|
+
});
|
|
40
|
+
expect(screen.getByText('Slide 2')).toBeInTheDocument();
|
|
41
|
+
act(() => {
|
|
42
|
+
jest.advanceTimersByTime(1000);
|
|
43
|
+
});
|
|
44
|
+
expect(screen.getByText('Slide 3')).toBeInTheDocument();
|
|
45
|
+
jest.useRealTimers();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './Carousel';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import '../styles.css';
|
|
3
|
+
import { getQTipData } from '../Tooltip/qTip.utilities';
|
|
4
|
+
const alignment = 'tw-flex';
|
|
5
|
+
const labelClasses = 'tw-ml-1.5 tw-text-sm tw--mt-0.5';
|
|
6
|
+
const baseClasses = 'tw-border-1 tw-h-3.5 tw-w-3.5 focus:tw-ring-0 focus:tw-ring-offset-0 tw-outline-none focus:tw-outline-none' +
|
|
7
|
+
' dark:tw-bg-sq-dark-background dark:tw-border-sq-dark-text dark:hover:tw-bg-sq-dark-background' +
|
|
8
|
+
' checked:tw-text-white checked:tw-border-sq-text-color checked:hover:tw-border-sq-color-dark' +
|
|
9
|
+
' checked:active:tw-border-sq-color-dark checked:focus:tw-border-sq-color-dark disabled:tw-border-sq-disabled-gray' +
|
|
10
|
+
' dark:disabled:tw-border-sq-fairly-dark-gray dark:checked:focus:tw-bg-sq-dark-background';
|
|
11
|
+
const checkboxClasses = `tw-form-checkbox tw-rounded ${baseClasses}`;
|
|
12
|
+
const radioClasses = `tw-form-radio ${baseClasses}`;
|
|
13
|
+
/**
|
|
14
|
+
* Checkbox and Radio Box Component.
|
|
15
|
+
*/
|
|
16
|
+
export const Checkbox = (props) => {
|
|
17
|
+
const { type = 'checkbox', value, disabled = false, label, onChange, onClick, onKeyDown, checked, defaultChecked, id, name, extraClassNames, extraLabelClassNames, testId, ...tooltipProps } = props;
|
|
18
|
+
const assignedId = id ?? 'checkbox_' + Math.random();
|
|
19
|
+
const tooltipData = getQTipData(tooltipProps);
|
|
20
|
+
return (_jsxs("span", { className: `${alignment} ${extraClassNames}`, children: [
|
|
21
|
+
_jsx("input", { value: value, type: type, "data-testid": testId, name: name, id: assignedId, readOnly: !onChange, checked: checked, defaultChecked: defaultChecked, className: `${type === 'checkbox' ? checkboxClasses : radioClasses} ${disabled ? 'tw-cursor-not-allowed' : 'tw-cursor-pointer'}`, disabled: disabled, onClick: onClick, onChange: onChange, onKeyDown: onKeyDown, ...tooltipData }), label && (_jsx("label", { htmlFor: assignedId, className: `${labelClasses} ${extraLabelClassNames} ${disabled
|
|
22
|
+
? 'tw-cursor-not-allowed dark:tw-text-sq-fairly-dark-gray tw-text-sq-fairly-dark-gray'
|
|
23
|
+
: 'tw-cursor-pointer tw-text-sq-text-color dark:tw-text-sq-dark-text'}`, children: label }))] }));
|
|
24
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Checkbox } from './Checkbox';
|
|
3
|
+
import { QTip } from '../Tooltip';
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Checkbox',
|
|
6
|
+
};
|
|
7
|
+
export const AllCheckboxes = () => {
|
|
8
|
+
const getDisplay = (type) => (_jsxs(_Fragment, { children: [
|
|
9
|
+
_jsx(QTip, {}), _jsx("div", { className: "tw-p-4", children: _jsx(Checkbox, { value: "a", type: type, checked: true, label: 'with Label', tooltip: "Checkbox Tooltip" }) }), _jsx("div", { className: "tw-p-4", children: _jsx(Checkbox, { value: "d", type: type, checked: false, disabled: true, label: _jsxs("div", { children: ["Disabled",
|
|
10
|
+
_jsx("br", {}),
|
|
11
|
+
"multi-Line"] }), tooltip: "Checkbox Tooltip" }) }), _jsx("div", { className: "tw-p-4", children: _jsx(Checkbox, { value: "d", type: type, checked: true, disabled: true, label: "Disabled", tooltip: "Checkbox Tooltip" }) }), _jsx("div", { className: "tw-p-4", children: _jsx(Checkbox, { value: "b", type: type, checked: true, tooltip: "Checkbox Tooltip" }) }), _jsx("div", { className: "tw-p-4", children: _jsx(Checkbox, { value: "c", type: type, checked: false, tooltip: "Checkbox Tooltip" }) })
|
|
12
|
+
] }));
|
|
13
|
+
const renderAllVariations = (type) => (_jsxs(_Fragment, { children: [
|
|
14
|
+
_jsx("div", { className: "tw-p-4 light", children: getDisplay(type) }), _jsx("div", { className: "tw-p-4 tw-dark tw-bg-sq-dark-background", children: getDisplay(type) })
|
|
15
|
+
] }));
|
|
16
|
+
return (_jsxs("div", { className: "tw-grid tw-grid-cols-2 tw-gap-4", children: [
|
|
17
|
+
_jsxs("div", { children: [
|
|
18
|
+
_jsx("b", { children: "Checkbox" }), renderAllVariations('checkbox')] }), _jsxs("div", { children: [
|
|
19
|
+
_jsx("b", { children: "Radios" }), renderAllVariations('radio')] })
|
|
20
|
+
] }));
|
|
21
|
+
};
|