@pushwoosh/dumb-components 1.1.205 → 1.1.207
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/Button/styles.js +3 -3
- package/FrequencyCapping/FrequencyCappingEdit.js +5 -19
- package/FrequencyCapping/FrequencyCappingInApps.js +7 -1
- package/FrequencyCapping/components/CountingMode/CountingModeControl.d.ts +15 -0
- package/FrequencyCapping/components/CountingMode/CountingModeControl.js +31 -0
- package/FrequencyCapping/types.d.ts +6 -0
- package/SplitButton/SplitButton.d.ts +5 -0
- package/SplitButton/SplitButton.js +63 -0
- package/SplitButton/index.d.ts +2 -0
- package/SplitButton/index.js +1 -0
- package/SplitButton/styles.d.ts +7 -0
- package/SplitButton/styles.js +28 -0
- package/SplitButton/types.d.ts +26 -0
- package/SplitButton/types.js +1 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +1 -1
package/Button/styles.js
CHANGED
|
@@ -40,7 +40,7 @@ const dangerShapeColors = createColors(colors.danger.shape);
|
|
|
40
40
|
export const ButtonBoxDangerShapeCompact = styled(ButtonBox).withConfig({
|
|
41
41
|
displayName: "ButtonBoxDangerShapeCompact",
|
|
42
42
|
componentId: "sc-qltvdl-6"
|
|
43
|
-
})(["height:28px;padding:0 calc(6px - 1px);font-size:", ";font-weight:", ";text-transform:uppercase;", ";"], FontSize.SMALL, FontWeight.BOLD, /* sc-custom "display: none;" */dangerShapeColors);
|
|
43
|
+
})(["height:28px;padding:0 calc(6px - 1px);font-size:", ";line-height:", ";font-weight:", ";text-transform:uppercase;", ";"], FontSize.SMALL, LineHeight.SMALL, FontWeight.BOLD, /* sc-custom "display: none;" */dangerShapeColors);
|
|
44
44
|
export const ButtonBoxDangerShapeField = styled(ButtonBox).withConfig({
|
|
45
45
|
displayName: "ButtonBoxDangerShapeField",
|
|
46
46
|
componentId: "sc-qltvdl-7"
|
|
@@ -50,7 +50,7 @@ const primaryShapeColors = createColors(colors.primary.shape);
|
|
|
50
50
|
export const ButtonBoxPrimaryShapeCompact = styled(ButtonBox).withConfig({
|
|
51
51
|
displayName: "ButtonBoxPrimaryShapeCompact",
|
|
52
52
|
componentId: "sc-qltvdl-8"
|
|
53
|
-
})(["height:28px;padding:0 calc(6px - 1px);font-size:", ";font-weight:", ";text-transform:uppercase;", ";"], FontSize.SMALL, FontWeight.BOLD, /* sc-custom "display: none;" */primaryShapeColors);
|
|
53
|
+
})(["height:28px;padding:0 calc(6px - 1px);font-size:", ";line-height:", ";font-weight:", ";text-transform:uppercase;", ";"], FontSize.SMALL, LineHeight.SMALL, FontWeight.BOLD, /* sc-custom "display: none;" */primaryShapeColors);
|
|
54
54
|
export const ButtonBoxPrimaryShapeField = styled(ButtonBox).withConfig({
|
|
55
55
|
displayName: "ButtonBoxPrimaryShapeField",
|
|
56
56
|
componentId: "sc-qltvdl-9"
|
|
@@ -80,7 +80,7 @@ const secondaryShapeColors = createColors(colors.secondary.shape);
|
|
|
80
80
|
export const ButtonBoxSecondaryShapeCompact = styled(ButtonBox).withConfig({
|
|
81
81
|
displayName: "ButtonBoxSecondaryShapeCompact",
|
|
82
82
|
componentId: "sc-qltvdl-14"
|
|
83
|
-
})(["height:28px;padding:0 calc(6px - 1px);font-size:", ";font-weight:", ";text-transform:uppercase;", ";"], FontSize.SMALL, FontWeight.MEDIUM, /* sc-custom "display: none;" */secondaryShapeColors);
|
|
83
|
+
})(["height:28px;padding:0 calc(6px - 1px);font-size:", ";line-height:", ";font-weight:", ";text-transform:uppercase;", ";"], FontSize.SMALL, LineHeight.SMALL, FontWeight.MEDIUM, /* sc-custom "display: none;" */secondaryShapeColors);
|
|
84
84
|
export const ButtonBoxSecondaryShapeField = styled(ButtonBox).withConfig({
|
|
85
85
|
displayName: "ButtonBoxSecondaryShapeField",
|
|
86
86
|
componentId: "sc-qltvdl-15"
|
|
@@ -3,12 +3,12 @@ import { useCallback } from 'react';
|
|
|
3
3
|
import { Color } from '@pushwoosh/kit-constants';
|
|
4
4
|
import { Vertical } from '@pushwoosh/kit-helpers';
|
|
5
5
|
import { OpenIcon } from '@pushwoosh/kit-icons';
|
|
6
|
-
import {
|
|
6
|
+
import { CountingModeControl } from './components/CountingMode/CountingModeControl';
|
|
7
7
|
import { Description } from './components/Description';
|
|
8
8
|
import { EditCappingSettings } from './components/Settings';
|
|
9
9
|
import { getCappingOption } from './helpers/getCappingOption';
|
|
10
10
|
import { getGlobalCappingLinkText } from './helpers/getGlobalCappingLinkText';
|
|
11
|
-
import {
|
|
11
|
+
import { CappingTypes } from './types';
|
|
12
12
|
import { FieldBox } from '../FieldBox';
|
|
13
13
|
import { Link } from '../Link';
|
|
14
14
|
import { Select } from '../Select';
|
|
@@ -75,18 +75,6 @@ export function FrequencyCappingEdit({
|
|
|
75
75
|
days
|
|
76
76
|
});
|
|
77
77
|
}, [capping, onChange]);
|
|
78
|
-
const onCountingModeChange = useCallback(countingMode => {
|
|
79
|
-
onChange({
|
|
80
|
-
...capping,
|
|
81
|
-
countingMode
|
|
82
|
-
});
|
|
83
|
-
}, [capping, onChange]);
|
|
84
|
-
const onTimezoneChange = useCallback(timezone => {
|
|
85
|
-
onChange({
|
|
86
|
-
...capping,
|
|
87
|
-
timezone
|
|
88
|
-
});
|
|
89
|
-
}, [capping, onChange]);
|
|
90
78
|
return _jsx(Container, {
|
|
91
79
|
"$padding": 16,
|
|
92
80
|
"$bgColor": Color.SOFT_LIGHT,
|
|
@@ -126,12 +114,10 @@ export function FrequencyCappingEdit({
|
|
|
126
114
|
messages: messages,
|
|
127
115
|
days: days,
|
|
128
116
|
onChange: onSettingsChange
|
|
129
|
-
}), cappingOption === CappingTypes.CUSTOM && !isDisabled && timezoneOptions !== undefined && _jsx(
|
|
130
|
-
|
|
131
|
-
timezone: capping.timezone ?? '',
|
|
117
|
+
}), cappingOption === CappingTypes.CUSTOM && !isDisabled && timezoneOptions !== undefined && _jsx(CountingModeControl, {
|
|
118
|
+
capping: capping,
|
|
132
119
|
timezoneOptions: timezoneOptions,
|
|
133
|
-
|
|
134
|
-
onTimezoneChange: onTimezoneChange
|
|
120
|
+
onChange: onChange
|
|
135
121
|
})]
|
|
136
122
|
})
|
|
137
123
|
});
|
|
@@ -3,6 +3,7 @@ import { useCallback } from 'react';
|
|
|
3
3
|
import { Color } from '@pushwoosh/kit-constants';
|
|
4
4
|
import { Vertical } from '@pushwoosh/kit-helpers';
|
|
5
5
|
import { OpenIcon } from '@pushwoosh/kit-icons';
|
|
6
|
+
import { CountingModeControl } from './components/CountingMode/CountingModeControl';
|
|
6
7
|
import { Description } from './components/Description';
|
|
7
8
|
import { EditInAppCappingSettings } from './components/Settings';
|
|
8
9
|
import { getCappingOption } from './helpers/getCappingOption';
|
|
@@ -29,7 +30,8 @@ export function FrequencyCappingInApps(props) {
|
|
|
29
30
|
editGlobalClicked,
|
|
30
31
|
applicationCode,
|
|
31
32
|
isInJourney = false,
|
|
32
|
-
isDisabled = false
|
|
33
|
+
isDisabled = false,
|
|
34
|
+
timezoneOptions
|
|
33
35
|
} = props;
|
|
34
36
|
const lang = useLang();
|
|
35
37
|
const cappingOptions = getCappingOptions(lang);
|
|
@@ -105,6 +107,10 @@ export function FrequencyCappingInApps(props) {
|
|
|
105
107
|
}), cappingOption === CappingTypes.CUSTOM && !isDisabled && _jsx(EditInAppCappingSettings, {
|
|
106
108
|
capping: capping,
|
|
107
109
|
onChange: onSettingsChange
|
|
110
|
+
}), cappingOption === CappingTypes.CUSTOM && !isDisabled && timezoneOptions !== undefined && _jsx(CountingModeControl, {
|
|
111
|
+
capping: capping,
|
|
112
|
+
timezoneOptions: timezoneOptions,
|
|
113
|
+
onChange: onChange
|
|
108
114
|
})]
|
|
109
115
|
})
|
|
110
116
|
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ReactElement } from 'react';
|
|
2
|
+
import type { SelectOption } from '../../../Select';
|
|
3
|
+
import { CappingCountingMode } from '../../types';
|
|
4
|
+
type WindowCapping = {
|
|
5
|
+
countingMode?: CappingCountingMode;
|
|
6
|
+
timezone?: string;
|
|
7
|
+
};
|
|
8
|
+
type CountingModeControlProps<T extends WindowCapping> = {
|
|
9
|
+
capping: T;
|
|
10
|
+
timezoneOptions: SelectOption[];
|
|
11
|
+
onChange: (newCappingState: T) => void;
|
|
12
|
+
};
|
|
13
|
+
/** Controlled {@link CountingMode} bound to a capping config with optional window fields. */
|
|
14
|
+
export declare function CountingModeControl<T extends WindowCapping>(props: CountingModeControlProps<T>): ReactElement;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
import { CappingCountingMode } from '../../types';
|
|
4
|
+
import { CountingMode } from './index';
|
|
5
|
+
/** Controlled {@link CountingMode} bound to a capping config with optional window fields. */
|
|
6
|
+
export function CountingModeControl(props) {
|
|
7
|
+
const {
|
|
8
|
+
capping,
|
|
9
|
+
timezoneOptions,
|
|
10
|
+
onChange
|
|
11
|
+
} = props;
|
|
12
|
+
const onCountingModeChange = useCallback(countingMode => {
|
|
13
|
+
onChange({
|
|
14
|
+
...capping,
|
|
15
|
+
countingMode
|
|
16
|
+
});
|
|
17
|
+
}, [capping, onChange]);
|
|
18
|
+
const onTimezoneChange = useCallback(timezone => {
|
|
19
|
+
onChange({
|
|
20
|
+
...capping,
|
|
21
|
+
timezone
|
|
22
|
+
});
|
|
23
|
+
}, [capping, onChange]);
|
|
24
|
+
return _jsx(CountingMode, {
|
|
25
|
+
countingMode: capping.countingMode ?? CappingCountingMode.ROLLING,
|
|
26
|
+
timezone: capping.timezone ?? '',
|
|
27
|
+
timezoneOptions: timezoneOptions,
|
|
28
|
+
onCountingModeChange: onCountingModeChange,
|
|
29
|
+
onTimezoneChange: onTimezoneChange
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -46,6 +46,10 @@ export type CappingInAppBase = {
|
|
|
46
46
|
enabled: boolean;
|
|
47
47
|
/** Ignore the account-wide global cap. */
|
|
48
48
|
ignoreGlobalCapping: boolean;
|
|
49
|
+
/** Anchoring of the perDays/leastDays windows; missing means {@link CappingCountingMode.ROLLING}, the lifetime total ignores it. */
|
|
50
|
+
countingMode?: CappingCountingMode;
|
|
51
|
+
/** IANA timezone midnight is calculated in, for {@link CappingCountingMode.CALENDAR_DAY}; empty means UTC. */
|
|
52
|
+
timezone?: string;
|
|
49
53
|
/** Lifetime total limit. */
|
|
50
54
|
total?: {
|
|
51
55
|
count: number;
|
|
@@ -120,4 +124,6 @@ export type FrequencyCappingInAppsProps = {
|
|
|
120
124
|
isInJourney?: boolean;
|
|
121
125
|
/** Disable editing. */
|
|
122
126
|
isDisabled?: boolean;
|
|
127
|
+
/** IANA timezones for the calendar-day mode; supplying them enables the counting-mode selector. */
|
|
128
|
+
timezoneOptions?: SelectOption[];
|
|
123
129
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type FC } from 'react';
|
|
2
|
+
import { type SplitButtonProps } from './types';
|
|
3
|
+
/** Main action button joined with a chevron half that opens a {@link DropdownMenu} of secondary actions;
|
|
4
|
+
* the menu defaults to `bottom-end`, so it opens leftwards from the chevron. */
|
|
5
|
+
export declare const SplitButton: FC<SplitButtonProps>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ChevronIcon } from '@pushwoosh/kit-icons';
|
|
3
|
+
import { SplitButtonAction, SplitButtonBox, SplitButtonMenuHandler } from './styles';
|
|
4
|
+
import { DropdownMenu } from '../DropdownMenu';
|
|
5
|
+
/** Main action button joined with a chevron half that opens a {@link DropdownMenu} of secondary actions;
|
|
6
|
+
* the menu defaults to `bottom-end`, so it opens leftwards from the chevron. */
|
|
7
|
+
export const SplitButton = ({
|
|
8
|
+
label,
|
|
9
|
+
color,
|
|
10
|
+
size = 'field',
|
|
11
|
+
icon,
|
|
12
|
+
className,
|
|
13
|
+
isDisabled,
|
|
14
|
+
isMenuDisabled,
|
|
15
|
+
isLoading,
|
|
16
|
+
menuAriaLabel = 'More actions',
|
|
17
|
+
onClick,
|
|
18
|
+
isScrollable,
|
|
19
|
+
openOnMount,
|
|
20
|
+
menuZIndex,
|
|
21
|
+
menuPlacement = 'bottom-end',
|
|
22
|
+
onClose,
|
|
23
|
+
children
|
|
24
|
+
}) => {
|
|
25
|
+
return _jsxs(SplitButtonBox, {
|
|
26
|
+
className: className,
|
|
27
|
+
"$color": color,
|
|
28
|
+
"$size": size,
|
|
29
|
+
children: [_jsx(SplitButtonAction, {
|
|
30
|
+
color: color,
|
|
31
|
+
size: size,
|
|
32
|
+
icon: icon,
|
|
33
|
+
isDisabled: isDisabled,
|
|
34
|
+
isLoading: isLoading,
|
|
35
|
+
onClick: onClick,
|
|
36
|
+
children: label
|
|
37
|
+
}), _jsx(DropdownMenu, {
|
|
38
|
+
isScrollable: isScrollable,
|
|
39
|
+
openOnMount: openOnMount,
|
|
40
|
+
menuZIndex: menuZIndex,
|
|
41
|
+
menuPlacement: menuPlacement,
|
|
42
|
+
onClose: onClose,
|
|
43
|
+
renderHandler: ({
|
|
44
|
+
ref,
|
|
45
|
+
onClick: onToggle,
|
|
46
|
+
isOpen
|
|
47
|
+
}) => _jsx(SplitButtonMenuHandler, {
|
|
48
|
+
color: color,
|
|
49
|
+
size: size,
|
|
50
|
+
"aria-label": menuAriaLabel,
|
|
51
|
+
icon: _jsx(ChevronIcon, {
|
|
52
|
+
direction: isOpen ? 'up' : 'down',
|
|
53
|
+
size: "small"
|
|
54
|
+
}),
|
|
55
|
+
isDisabled: isDisabled || isMenuDisabled,
|
|
56
|
+
isOpen: isOpen,
|
|
57
|
+
boxRef: ref,
|
|
58
|
+
onClick: onToggle
|
|
59
|
+
}),
|
|
60
|
+
children: children
|
|
61
|
+
})]
|
|
62
|
+
});
|
|
63
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SplitButton } from './SplitButton';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Button } from '../Button';
|
|
2
|
+
export declare const SplitButtonBox: import("styled-components").StyledComponent<"div", any, {
|
|
3
|
+
$color: "primary" | "secondary";
|
|
4
|
+
$size: "field" | "compact";
|
|
5
|
+
}, never>;
|
|
6
|
+
export declare const SplitButtonAction: typeof Button;
|
|
7
|
+
export declare const SplitButtonMenuHandler: typeof Button;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
import { Color } from '@pushwoosh/kit-constants';
|
|
3
|
+
import { Button } from '../Button';
|
|
4
|
+
const dividerColorByColor = {
|
|
5
|
+
primary: Color.CLEAR,
|
|
6
|
+
secondary: Color.FORM
|
|
7
|
+
};
|
|
8
|
+
const menuHandlerPaddingBySize = {
|
|
9
|
+
field: 'calc(6px - 1px)',
|
|
10
|
+
compact: '2px'
|
|
11
|
+
};
|
|
12
|
+
export const SplitButtonBox = styled.div.withConfig({
|
|
13
|
+
displayName: "SplitButtonBox",
|
|
14
|
+
componentId: "sc-19s68pa-0"
|
|
15
|
+
})(["display:inline-flex;align-items:stretch;--split-button-divider-color:", ";--split-button-menu-padding:", ";"], ({
|
|
16
|
+
$color
|
|
17
|
+
}) => dividerColorByColor[$color], ({
|
|
18
|
+
$size
|
|
19
|
+
}) => menuHandlerPaddingBySize[$size]);
|
|
20
|
+
export const SplitButtonAction = styled(Button).withConfig({
|
|
21
|
+
displayName: "SplitButtonAction",
|
|
22
|
+
componentId: "sc-19s68pa-1"
|
|
23
|
+
})(["&,&:hover:not([disabled]),&:active:not([disabled]),&:disabled{border-top-right-radius:0;border-bottom-right-radius:0;border-right-width:0;}"]);
|
|
24
|
+
export const SplitButtonMenuHandler = styled(Button).withConfig({
|
|
25
|
+
displayName: "SplitButtonMenuHandler",
|
|
26
|
+
componentId: "sc-19s68pa-2"
|
|
27
|
+
})(["&,&:hover:not([disabled]),&:active:not([disabled]),&:disabled{border-top-left-radius:0;border-bottom-left-radius:0;border-left-color:var(--split-button-divider-color);padding:0 var(--split-button-menu-padding);}"]);
|
|
28
|
+
SplitButtonBox.displayName = 'SplitButtonBox';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type RequiredButtonProps } from '../Button';
|
|
3
|
+
import { type DropdownMenuProps } from '../DropdownMenu/components/DropdownMenu/types';
|
|
4
|
+
/** Props of {@link SplitButton} — a main action button joined with a chevron that opens a {@link DropdownMenu}. */
|
|
5
|
+
export type SplitButtonProps = Pick<DropdownMenuProps, 'isScrollable' | 'openOnMount' | 'menuZIndex' | 'menuPlacement' | 'onClose' | 'children'> & {
|
|
6
|
+
/** Label of the main action button. */
|
|
7
|
+
label?: ReactNode;
|
|
8
|
+
/** Visual intent of both halves: `primary` or `secondary`. */
|
|
9
|
+
color: 'primary' | 'secondary';
|
|
10
|
+
/** Height preset of both halves. */
|
|
11
|
+
size?: RequiredButtonProps['size'];
|
|
12
|
+
/** Icon before the label; use kit-icons `size="medium"` for `field` and `size="small"` for `compact`. */
|
|
13
|
+
icon?: RequiredButtonProps['icon'];
|
|
14
|
+
/** Extra CSS class applied to the group element. */
|
|
15
|
+
className?: string;
|
|
16
|
+
/** Disable both halves. */
|
|
17
|
+
isDisabled?: boolean;
|
|
18
|
+
/** Disable only the chevron half. */
|
|
19
|
+
isMenuDisabled?: boolean;
|
|
20
|
+
/** Show the loading state on the main action button. */
|
|
21
|
+
isLoading?: boolean;
|
|
22
|
+
/** Accessible label of the chevron half. */
|
|
23
|
+
menuAriaLabel?: string;
|
|
24
|
+
/** Fires when the main action button is clicked. */
|
|
25
|
+
onClick: () => void;
|
|
26
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export { RadioCard } from './RadioCard';
|
|
|
21
21
|
export { ReCaptcha, useRecaptcha, asyncScriptLoad } from './ReCaptcha';
|
|
22
22
|
export { Spinner } from './Spinner';
|
|
23
23
|
export { SortButton, type SortButtonParams } from './SortButton';
|
|
24
|
+
export { SplitButton, type SplitButtonProps } from './SplitButton';
|
|
24
25
|
export { Select, SelectAsync, SelectComponents, CLASS_NAME_PREFIX, type SelectBase, type SelectOption, type MultiSelectOptions, type SingleValue, type MultiValue, } from './Select';
|
|
25
26
|
export { Combobox, type ComboboxProps, type ComboboxChangeSource, type ComboboxChangeMeta, type FreeComboboxProps, type SelectComboboxProps, } from './Combobox';
|
|
26
27
|
export { ComboboxMulti, type ComboboxMultiProps } from './ComboboxMulti';
|
package/index.js
CHANGED
|
@@ -21,6 +21,7 @@ export { RadioCard } from './RadioCard';
|
|
|
21
21
|
export { ReCaptcha, useRecaptcha, asyncScriptLoad } from './ReCaptcha';
|
|
22
22
|
export { Spinner } from './Spinner';
|
|
23
23
|
export { SortButton } from './SortButton';
|
|
24
|
+
export { SplitButton } from './SplitButton';
|
|
24
25
|
export { Select, SelectAsync, SelectComponents, CLASS_NAME_PREFIX } from './Select';
|
|
25
26
|
export { Combobox } from './Combobox';
|
|
26
27
|
export { ComboboxMulti } from './ComboboxMulti';
|