@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 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 { CountingMode } from './components/CountingMode';
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 { CappingCountingMode, CappingTypes } from './types';
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(CountingMode, {
130
- countingMode: capping.countingMode ?? CappingCountingMode.ROLLING,
131
- timezone: capping.timezone ?? '',
117
+ }), cappingOption === CappingTypes.CUSTOM && !isDisabled && timezoneOptions !== undefined && _jsx(CountingModeControl, {
118
+ capping: capping,
132
119
  timezoneOptions: timezoneOptions,
133
- onCountingModeChange: onCountingModeChange,
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,2 @@
1
+ export { SplitButton } from './SplitButton';
2
+ export type { SplitButtonProps } from './types';
@@ -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';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushwoosh/dumb-components",
3
- "version": "1.1.205",
3
+ "version": "1.1.207",
4
4
  "description": "React components to build Pushwoosh products",
5
5
  "main": "index.js",
6
6
  "module": "index.js",