@pushwoosh/dumb-components 0.0.17 → 0.0.18

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.
@@ -0,0 +1 @@
1
+ export declare const minimalWidth = 12;
@@ -0,0 +1 @@
1
+ export const minimalWidth = 12; // pixels
@@ -0,0 +1,3 @@
1
+ import { type ReactElement } from 'react';
2
+ import type { AutosizeInputProps } from './AutosizeInput.types';
3
+ export declare function AutosizeInput(props: AutosizeInputProps): ReactElement;
@@ -0,0 +1,37 @@
1
+ import React, { useRef, useState, useEffect } from 'react';
2
+ import { minimalWidth } from './AutosizeInput.constants';
3
+ import { Hidden } from './AutosizeInput.styled';
4
+ import { InputStyled } from './styled';
5
+ export function AutosizeInput(props) {
6
+ const {
7
+ value,
8
+ placeholder,
9
+ isDisabled,
10
+ onChange,
11
+ onKeyUp,
12
+ onKeyDown,
13
+ onBlur
14
+ } = props;
15
+ const hiddenRef = useRef(null);
16
+ const [width, setWidth] = useState(minimalWidth);
17
+ useEffect(() => {
18
+ const {
19
+ offsetWidth: hiddenWidth
20
+ } = hiddenRef.current;
21
+ setWidth(hiddenWidth + minimalWidth);
22
+ }, [value]);
23
+ return React.createElement(React.Fragment, null, React.createElement(InputStyled, {
24
+ style: {
25
+ width
26
+ },
27
+ value: value,
28
+ placeholder: placeholder,
29
+ disabled: isDisabled,
30
+ onChange: onChange,
31
+ onKeyUp: onKeyUp,
32
+ onKeyDown: onKeyDown,
33
+ onBlur: onBlur
34
+ }), React.createElement(Hidden, {
35
+ ref: hiddenRef
36
+ }, value || placeholder));
37
+ }
@@ -0,0 +1 @@
1
+ export declare const Hidden: import("styled-components").StyledComponent<"span", any, {}, never>;
@@ -0,0 +1,5 @@
1
+ import styled from 'styled-components';
2
+ export const Hidden = styled.span.withConfig({
3
+ displayName: "Hidden",
4
+ componentId: "sc-dce14p-0"
5
+ })(["position:absolute;visibility:hidden;"]);
@@ -0,0 +1,10 @@
1
+ import type { ChangeEvent, KeyboardEvent, FocusEvent } from 'react';
2
+ export interface AutosizeInputProps {
3
+ value: string;
4
+ placeholder?: string;
5
+ isDisabled?: boolean;
6
+ onChange: (event: ChangeEvent<HTMLInputElement>) => void;
7
+ onKeyUp: (event: KeyboardEvent<HTMLInputElement>) => void;
8
+ onKeyDown: (event: KeyboardEvent<HTMLInputElement>) => void;
9
+ onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
10
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { type ReactElement } from 'react';
2
+ import type { NumberPickerProps } from './types';
3
+ export declare function NumberPicker(props: NumberPickerProps): ReactElement;
@@ -0,0 +1,126 @@
1
+ import React, { useRef, useState, useEffect } from 'react';
2
+ import { Vertical, useMount, usePersistentFunction } from '@pushwoosh/kit-helpers';
3
+ import { ChevronIcon } from '@pushwoosh/kit-icons';
4
+ import { AutosizeInput } from './AutosizeInput';
5
+ import { intVal, isStringInteger } from './helpers';
6
+ import { Hint, SingleInputFrame, InputStyled } from './styled';
7
+ export function NumberPicker(props) {
8
+ const {
9
+ value,
10
+ hint,
11
+ step = 1,
12
+ placeholder,
13
+ focusOnMount,
14
+ minValue,
15
+ maxValue,
16
+ autoSize,
17
+ isDisabled,
18
+ onChange,
19
+ onSubmit
20
+ } = props;
21
+ const ref = useRef(null);
22
+ const [autoDiff, setAutoDiff] = useState(0);
23
+ const [localValue, setLocalValue] = useState('');
24
+ const onChangeDiff = usePersistentFunction(diff => {
25
+ const newValue = intVal(value) + diff;
26
+ const minValueValid = minValue === undefined || newValue >= minValue;
27
+ const maxValueValid = maxValue === undefined || newValue <= maxValue;
28
+ if (minValueValid && maxValueValid) {
29
+ onChange(newValue);
30
+ }
31
+ });
32
+ useEffect(() => {
33
+ setLocalValue(value !== undefined ? value.toString() : '');
34
+ }, [value]);
35
+ useEffect(() => {
36
+ if (!autoDiff) {
37
+ return;
38
+ }
39
+ const interval = setInterval(() => {
40
+ onChangeDiff(autoDiff);
41
+ }, 250);
42
+ return () => clearInterval(interval);
43
+ }, [autoDiff, onChangeDiff]);
44
+ useMount(() => {
45
+ if (focusOnMount && ref.current) {
46
+ ref.current.children[0].focus();
47
+ }
48
+ });
49
+ const handleChange = event => {
50
+ const val = event.target.value;
51
+ if (val === '' || val === '-') {
52
+ setLocalValue(val);
53
+ return;
54
+ }
55
+ const parsedValue = intVal(val);
56
+ if (parsedValue === 0 && val !== '0') {
57
+ return;
58
+ }
59
+ setLocalValue(val);
60
+ const minValueValid = minValue === undefined || parsedValue >= minValue;
61
+ const maxValueValid = maxValue === undefined || parsedValue <= maxValue;
62
+ if (isStringInteger(val) && minValueValid && maxValueValid) {
63
+ onChange(parsedValue);
64
+ }
65
+ };
66
+ const handleKeyDown = event => {
67
+ if (onSubmit && event.key === 'Enter' && isStringInteger(localValue)) {
68
+ onSubmit();
69
+ }
70
+ if (event.key === 'ArrowUp') {
71
+ onChangeDiff(1);
72
+ setAutoDiff(1);
73
+ }
74
+ if (event.key === 'ArrowDown') {
75
+ onChangeDiff(-1);
76
+ setAutoDiff(-1);
77
+ }
78
+ };
79
+ const resetAutoDiff = () => setAutoDiff(0);
80
+ const InputComponent = autoSize ? AutosizeInput : InputStyled;
81
+ return React.createElement(SingleInputFrame, {
82
+ ref: ref,
83
+ "$hasHint": !!hint,
84
+ "$isDisabled": isDisabled
85
+ }, React.createElement(InputComponent, {
86
+ value: localValue,
87
+ placeholder: placeholder,
88
+ isDisabled: isDisabled,
89
+ onChange: handleChange,
90
+ onKeyDown: handleKeyDown,
91
+ onKeyUp: resetAutoDiff,
92
+ onBlur: event => {
93
+ if (!event.target.value && value === undefined) {
94
+ return;
95
+ }
96
+ let blurValue = intVal(event.target.value);
97
+ const minValueValid = minValue === undefined || blurValue >= minValue;
98
+ const maxValueValid = maxValue === undefined || blurValue <= maxValue;
99
+ if (!maxValueValid) {
100
+ blurValue = maxValue;
101
+ } else if (!minValueValid) {
102
+ blurValue = minValue;
103
+ }
104
+ onChange(blurValue);
105
+ setLocalValue(`${blurValue}`);
106
+ }
107
+ }), hint && React.createElement(Hint, null, hint), React.createElement(Vertical, {
108
+ "$gap": 1
109
+ }, React.createElement("div", null, React.createElement(ChevronIcon, {
110
+ direction: "up",
111
+ size: "small",
112
+ "aria-disabled": "true",
113
+ onClick: () => onChangeDiff(step),
114
+ onMouseDown: () => setAutoDiff(step),
115
+ onMouseUp: resetAutoDiff,
116
+ onMouseLeave: resetAutoDiff
117
+ })), React.createElement("div", null, React.createElement(ChevronIcon, {
118
+ size: "small",
119
+ direction: "down",
120
+ "aria-disabled": isDisabled,
121
+ onClick: () => onChangeDiff(-1 * step),
122
+ onMouseDown: () => setAutoDiff(-1 * step),
123
+ onMouseUp: resetAutoDiff,
124
+ onMouseLeave: resetAutoDiff
125
+ }))));
126
+ }
@@ -0,0 +1,2 @@
1
+ export declare const intVal: (value: any) => number;
2
+ export declare const isStringInteger: (value: string) => boolean;
@@ -0,0 +1,5 @@
1
+ export const intVal = value => {
2
+ const num = parseInt(value, 10);
3
+ return Number.isNaN(num) ? 0 : num;
4
+ };
5
+ export const isStringInteger = value => /^-?\d+$/.test(value);
@@ -0,0 +1 @@
1
+ export { NumberPicker } from './NumberPicker';
@@ -0,0 +1 @@
1
+ export { NumberPicker } from './NumberPicker';
@@ -0,0 +1,10 @@
1
+ export declare const InputStyled: import("styled-components").StyledComponent<"input", any, {
2
+ type: "text";
3
+ }, "type">;
4
+ export declare const Hint: import("styled-components").StyledComponent<"div", any, {}, never>;
5
+ export declare const SingleInputFrame: import("styled-components").StyledComponent<"div", any, {
6
+ $empty?: boolean;
7
+ $error?: boolean;
8
+ $hasHint: boolean;
9
+ $isDisabled?: boolean;
10
+ }, never>;
@@ -0,0 +1,26 @@
1
+ import styled from 'styled-components';
2
+ import { Color, ShapeRadius, Spacing, UnitSize } from '@pushwoosh/kit-constants';
3
+ export const InputStyled = styled.input.attrs({
4
+ type: 'text'
5
+ }).withConfig({
6
+ displayName: "InputStyled",
7
+ componentId: "sc-6ibrwh-0"
8
+ })(["&:disabled{background-color:", ";}"], Color.FROZEN);
9
+ export const Hint = styled.div.withConfig({
10
+ displayName: "Hint",
11
+ componentId: "sc-6ibrwh-1"
12
+ })(["display:flex;align-items:center;font-size:100%;line-height:initial;padding-right:", ";color:", ";pointer-events:none;"], Spacing.S3, Color.PHANTOM);
13
+ export const SingleInputFrame = styled.div.withConfig({
14
+ displayName: "SingleInputFrame",
15
+ componentId: "sc-6ibrwh-2"
16
+ })(["display:inline-grid;grid-template-columns:", ";box-sizing:border-box;align-items:center;height:", ";position:relative;padding-left:", ";color:", ";border:1px solid ", ";border-radius:", ";background-color:", ";cursor:pointer;pointer-events:", ";&:focus-within{border-color:", ";}& > input{color:", ";height:34px;border:none;padding:0;outline:none;line-height:140%;}& > div:last-of-type{height:34px;padding-left:1px;background-color:", ";border-radius:0 ", " ", " 0;& > div{display:flex;justify-content:center;align-items:center;color:", ";background-color:", ";cursor:pointer;&:hover > *{transform:scale(1.3);}&:first-of-type{border-top-right-radius:", ";}&:last-of-type{border-bottom-right-radius:", ";}}}"], ({
17
+ $hasHint
18
+ }) => $hasHint ? '1fr max-content 21px' : '1fr 21px', UnitSize.FIELD_HEIGHT, Spacing.S4, ({
19
+ $empty
20
+ }) => $empty ? Color.BRIGHT : Color.MAIN, ({
21
+ $error
22
+ }) => $error ? Color.DANGER : Color.FORM, ShapeRadius.CONTROL, ({
23
+ $isDisabled
24
+ }) => $isDisabled ? Color.FROZEN : Color.CLEAR, ({
25
+ $isDisabled
26
+ }) => $isDisabled ? 'none' : 'auto', Color.BRIGHT, Color.MAIN, Color.FORM, ShapeRadius.CONTROL, ShapeRadius.CONTROL, Color.MAIN, Color.FROZEN, ShapeRadius.CONTROL, ShapeRadius.CONTROL);
@@ -0,0 +1,13 @@
1
+ export interface NumberPickerProps {
2
+ value: number | undefined;
3
+ hint?: string;
4
+ step?: number;
5
+ placeholder?: string;
6
+ focusOnMount?: boolean;
7
+ minValue?: number;
8
+ maxValue?: number;
9
+ autoSize?: boolean;
10
+ isDisabled?: boolean;
11
+ onChange: (value: number) => void;
12
+ onSubmit?: () => void;
13
+ }
@@ -0,0 +1 @@
1
+ export {};
package/index.d.ts CHANGED
@@ -5,3 +5,4 @@ export { EmailTemplatePreview, NoEmailTemplatePreview, } from './EmailTemplatePr
5
5
  export { PushPreview } from './PushPreview';
6
6
  export { ExportResult } from './ExportResult';
7
7
  export { NativeInput, NativeTextarea, NativeSelect, } from './native';
8
+ export { NumberPicker } from './NumberPicker';
package/index.js CHANGED
@@ -4,4 +4,5 @@ export { StatisticCard } from './StatisticCard';
4
4
  export { EmailTemplatePreview, NoEmailTemplatePreview } from './EmailTemplatePreview';
5
5
  export { PushPreview } from './PushPreview';
6
6
  export { ExportResult } from './ExportResult';
7
- export { NativeInput, NativeTextarea, NativeSelect } from './native';
7
+ export { NativeInput, NativeTextarea, NativeSelect } from './native';
8
+ export { NumberPicker } from './NumberPicker';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushwoosh/dumb-components",
3
- "version": "0.0.17",
3
+ "version": "0.0.18",
4
4
  "description": "React components to build Pushwoosh products",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "pre-commit": "check",
18
18
  "devDependencies": {
19
- "@pushwoosh/frontend-builder-engine": "^1.0.8",
19
+ "@pushwoosh/frontend-builder-engine": "^1.0.11",
20
20
  "@pushwoosh/kit-constants": "^1.6.7",
21
21
  "@pushwoosh/kit-dropdown-menu": "^1.6.8",
22
22
  "@types/lodash": "^4.17.13",