@orangesk/orange-design-system 2.0.0-beta.28 → 2.0.0-beta.29
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/build/components/Carousel/style.css +1 -1
- package/build/components/Carousel/style.css.map +1 -1
- package/build/components/Megamenu/style.css +1 -1
- package/build/components/Megamenu/style.css.map +1 -1
- package/build/components/index.js +1 -1
- package/build/components/index.js.map +1 -1
- package/build/components/tsconfig.tsbuildinfo +1 -1
- package/build/components/types/index.d.ts +8 -0
- package/build/components/types/src/components/Carousel/Carousel.static.d.ts +7 -0
- package/build/components/types/src/components/Forms/File/File.d.ts +2 -0
- package/build/components/types/src/components/Forms/Group/Group.d.ts +2 -0
- package/build/components/types/src/components/Forms/InputStepper/InputStepper.d.ts +2 -0
- package/build/components/types/src/components/Forms/RangeSlider/RangeSlider.d.ts +2 -0
- package/build/lib/components.css +1 -1
- package/build/lib/components.css.map +1 -1
- package/build/lib/megamenu.css +1 -1
- package/build/lib/megamenu.css.map +1 -1
- package/build/lib/scripts.js +1 -1
- package/build/lib/scripts.js.map +1 -1
- package/build/lib/style.css +1 -1
- package/build/lib/style.css.map +1 -1
- package/build/lib/tsconfig.tsbuildinfo +1 -1
- package/build/search-index.json +1 -1
- package/package.json +6 -6
- package/src/components/Carousel/Carousel.static.ts +45 -7
- package/src/components/Carousel/styles/mixins.scss +0 -5
- package/src/components/Forms/Checkbox/styles/config.scss +6 -3
- package/src/components/Forms/Field/Control.tsx +49 -46
- package/src/components/Forms/Field/styles/config.scss +1 -1
- package/src/components/Forms/Field/tests/Group.Field.conformance.test.js +35 -11
- package/src/components/Forms/File/File.tsx +7 -2
- package/src/components/Forms/Group/Group.tsx +17 -8
- package/src/components/Forms/InputStepper/InputStepper.tsx +3 -0
- package/src/components/Forms/InputStepper/styles/style.scss +39 -44
- package/src/components/Forms/Message/styles/config.scss +2 -1
- package/src/components/Forms/Radio/styles/config.scss +6 -3
- package/src/components/Forms/RangeSlider/RangeSlider.tsx +3 -0
- package/src/components/Forms/styles/config.scss +5 -4
- package/src/components/PromoBanner/PromoBanner.tsx +52 -50
- package/src/components/PromoBanner/tests/PromoBanner.conformance.test.js +4 -2
- package/src/components/PromoBanner/tests/PromoBanner.unit.test.js +5 -1
|
@@ -30,6 +30,33 @@ export interface ControlProps {
|
|
|
30
30
|
className?: string;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
const getControlElement = (type: string) => {
|
|
34
|
+
switch (type) {
|
|
35
|
+
case "autocomplete":
|
|
36
|
+
return Autocomplete;
|
|
37
|
+
case "checkbox":
|
|
38
|
+
return Checkbox;
|
|
39
|
+
case "datepicker":
|
|
40
|
+
return DatePicker;
|
|
41
|
+
case "file":
|
|
42
|
+
return File;
|
|
43
|
+
case "group":
|
|
44
|
+
return Group;
|
|
45
|
+
case "radio":
|
|
46
|
+
return Radio;
|
|
47
|
+
case "range":
|
|
48
|
+
return RangeSlider;
|
|
49
|
+
case "select":
|
|
50
|
+
return Select;
|
|
51
|
+
case "input-stepper":
|
|
52
|
+
return InputStepper;
|
|
53
|
+
case "textarea":
|
|
54
|
+
return TextArea;
|
|
55
|
+
default:
|
|
56
|
+
return TextInput;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
33
60
|
const Control: React.FC<ControlProps> = ({ className }) => {
|
|
34
61
|
const context = React.useContext(FieldContext);
|
|
35
62
|
const fieldsetContext = React.useContext(FieldsetContext);
|
|
@@ -46,66 +73,42 @@ const Control: React.FC<ControlProps> = ({ className }) => {
|
|
|
46
73
|
type,
|
|
47
74
|
control: innerControl,
|
|
48
75
|
renderControl,
|
|
76
|
+
prefix,
|
|
77
|
+
suffix,
|
|
78
|
+
id: controlConfigId,
|
|
49
79
|
...controlProps
|
|
50
80
|
} = control;
|
|
51
81
|
|
|
52
82
|
const describedby = getDescribedBy(hint, messages, tooltip, controlId);
|
|
53
83
|
const renderWrapper = isRadioCheck || type === "autocomplete";
|
|
54
84
|
|
|
55
|
-
const ControlElement = (
|
|
56
|
-
switch (type) {
|
|
57
|
-
case "autocomplete":
|
|
58
|
-
return <Autocomplete {...props} />;
|
|
59
|
-
case "checkbox":
|
|
60
|
-
return <Checkbox {...props} />;
|
|
61
|
-
case "datepicker":
|
|
62
|
-
return <DatePicker {...props} />;
|
|
63
|
-
case "file":
|
|
64
|
-
return <File {...props} />;
|
|
65
|
-
case "group":
|
|
66
|
-
return <Group {...props} />;
|
|
67
|
-
case "radio":
|
|
68
|
-
return <Radio {...props} />;
|
|
69
|
-
case "range":
|
|
70
|
-
return <RangeSlider {...props} />;
|
|
71
|
-
case "select":
|
|
72
|
-
return <Select {...props} />;
|
|
73
|
-
case "input-stepper":
|
|
74
|
-
return <InputStepper {...props} />;
|
|
75
|
-
case "textarea":
|
|
76
|
-
return <TextArea {...props} />;
|
|
77
|
-
default:
|
|
78
|
-
return <TextInput {...props} />;
|
|
79
|
-
}
|
|
80
|
-
};
|
|
85
|
+
const ControlElement = getControlElement(type ?? "text");
|
|
81
86
|
|
|
82
87
|
const { isInvalid, isValid } = controlProps;
|
|
83
88
|
|
|
84
|
-
const
|
|
89
|
+
const hasValidationError =
|
|
85
90
|
isInvalid ??
|
|
86
91
|
((fieldsetMessages.some((msg: any) => msg.isMain) ||
|
|
87
92
|
messages.some((msg: any) => msg.type === "error")) &&
|
|
88
93
|
!isValid);
|
|
89
94
|
|
|
90
|
-
const props =
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
control: {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
};
|
|
108
|
-
})();
|
|
95
|
+
const props = {
|
|
96
|
+
...controlProps,
|
|
97
|
+
...(type !== "group" && { id: controlId }),
|
|
98
|
+
...(describedby.length && { "aria-describedby": describedby }),
|
|
99
|
+
...(type === "file" && { "aria-labelledby": `${controlId}-label` }),
|
|
100
|
+
isInvalid: hasValidationError,
|
|
101
|
+
...(type === "group" &&
|
|
102
|
+
innerControl && {
|
|
103
|
+
addonPrefix: prefix,
|
|
104
|
+
addonSuffix: suffix,
|
|
105
|
+
control: {
|
|
106
|
+
...innerControl,
|
|
107
|
+
id: controlId,
|
|
108
|
+
isInvalid: hasValidationError,
|
|
109
|
+
},
|
|
110
|
+
}),
|
|
111
|
+
};
|
|
109
112
|
|
|
110
113
|
if (renderControl) {
|
|
111
114
|
return renderControl(props);
|
|
@@ -4,25 +4,49 @@ import { axe } from "jest-axe";
|
|
|
4
4
|
import { Button } from "../../../Button";
|
|
5
5
|
import { Field } from "..";
|
|
6
6
|
|
|
7
|
-
const controlConfig = {
|
|
8
|
-
type: "group",
|
|
9
|
-
prefix: "€",
|
|
10
|
-
suffix: ["kg", <Button key="test">Send</Button>],
|
|
11
|
-
control: { type: "text" },
|
|
12
|
-
};
|
|
13
|
-
|
|
14
7
|
const example = (
|
|
15
8
|
<>
|
|
16
|
-
<Field
|
|
17
|
-
|
|
9
|
+
<Field
|
|
10
|
+
label="Field Label"
|
|
11
|
+
control={{
|
|
12
|
+
type: "group",
|
|
13
|
+
id: "group-field-1",
|
|
14
|
+
prefix: "€",
|
|
15
|
+
suffix: ["kg", <Button key="test">Send</Button>],
|
|
16
|
+
control: { type: "text", id: "text-field-1" },
|
|
17
|
+
}}
|
|
18
|
+
/>
|
|
19
|
+
<Field
|
|
20
|
+
label="Field Label"
|
|
21
|
+
control={{
|
|
22
|
+
type: "group",
|
|
23
|
+
id: "group-field-2",
|
|
24
|
+
prefix: "€",
|
|
25
|
+
suffix: ["kg", <Button key="test">Send</Button>],
|
|
26
|
+
control: { type: "text", id: "text-field-2" },
|
|
27
|
+
}}
|
|
28
|
+
tooltip="info tooltip"
|
|
29
|
+
/>
|
|
18
30
|
<Field
|
|
19
31
|
label="Field Label"
|
|
20
32
|
hint="Field hint with long text"
|
|
21
|
-
control={
|
|
33
|
+
control={{
|
|
34
|
+
type: "group",
|
|
35
|
+
id: "group-field-3",
|
|
36
|
+
prefix: "€",
|
|
37
|
+
suffix: ["kg", <Button key="test">Send</Button>],
|
|
38
|
+
control: { type: "text", id: "text-field-3" },
|
|
39
|
+
}}
|
|
22
40
|
/>
|
|
23
41
|
<Field
|
|
24
42
|
label="Field Label"
|
|
25
|
-
control={
|
|
43
|
+
control={{
|
|
44
|
+
type: "group",
|
|
45
|
+
id: "group-field-4",
|
|
46
|
+
prefix: "€",
|
|
47
|
+
suffix: ["kg", <Button key="test">Send</Button>],
|
|
48
|
+
control: { type: "text", id: "text-field-4" },
|
|
49
|
+
}}
|
|
26
50
|
messages={[
|
|
27
51
|
{ type: "info", text: "Info message with lorem ipsum long text ipsum" },
|
|
28
52
|
]}
|
|
@@ -11,12 +11,16 @@ const CLASS_ROOT = "file-input";
|
|
|
11
11
|
export type FileSize = "default" | "large";
|
|
12
12
|
|
|
13
13
|
// Omit native 'size' prop to avoid conflict
|
|
14
|
-
export interface FileProps
|
|
15
|
-
|
|
14
|
+
export interface FileProps extends Omit<
|
|
15
|
+
React.InputHTMLAttributes<HTMLInputElement>,
|
|
16
|
+
"size"
|
|
17
|
+
> {
|
|
16
18
|
/** Html id attribute. Generated automatically if omitted. */
|
|
17
19
|
id?: string;
|
|
18
20
|
/** Disabled state. */
|
|
19
21
|
isDisabled?: boolean;
|
|
22
|
+
/** Invalid state */
|
|
23
|
+
isInvalid?: boolean;
|
|
20
24
|
/** Input name. */
|
|
21
25
|
name?: string;
|
|
22
26
|
/** Size of element. */
|
|
@@ -29,6 +33,7 @@ const defaultSize: FileSize = "default";
|
|
|
29
33
|
const File: FC<FileProps> = ({
|
|
30
34
|
id,
|
|
31
35
|
isDisabled,
|
|
36
|
+
isInvalid,
|
|
32
37
|
name,
|
|
33
38
|
size = defaultSize,
|
|
34
39
|
className,
|
|
@@ -19,6 +19,8 @@ interface GroupProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
19
19
|
size?: "large";
|
|
20
20
|
addonSuffix?: ReactNode | ReactNode[];
|
|
21
21
|
className?: string;
|
|
22
|
+
/** Invalid state */
|
|
23
|
+
isInvalid?: boolean;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
const Group: React.FC<GroupProps> = ({
|
|
@@ -27,6 +29,7 @@ const Group: React.FC<GroupProps> = ({
|
|
|
27
29
|
addonSuffix,
|
|
28
30
|
size,
|
|
29
31
|
className,
|
|
32
|
+
isInvalid,
|
|
30
33
|
...other
|
|
31
34
|
}) => {
|
|
32
35
|
const { type, ...controlProps } = control;
|
|
@@ -42,20 +45,26 @@ const Group: React.FC<GroupProps> = ({
|
|
|
42
45
|
|
|
43
46
|
const renderItems = (items: ReactNode | ReactNode[] | undefined) =>
|
|
44
47
|
React.Children.map(items, (item) => {
|
|
45
|
-
if (
|
|
46
|
-
typeof item === "string" ||
|
|
47
|
-
(item && typeof (item as any).type === "string")
|
|
48
|
-
) {
|
|
48
|
+
if (typeof item === "string") {
|
|
49
49
|
return <Item size={size}>{item}</Item>;
|
|
50
50
|
} else if (React.isValidElement(item)) {
|
|
51
|
+
const itemType = (item as any).type;
|
|
52
|
+
const isNativeElement = typeof itemType === "string";
|
|
53
|
+
const isButtonElement =
|
|
54
|
+
isNativeElement && (itemType === "button" || itemType === "a");
|
|
55
|
+
|
|
56
|
+
// Wrap native HTML elements (span, p, div) but NOT buttons or links
|
|
57
|
+
// Don't wrap React components (Button, etc.)
|
|
58
|
+
if (isNativeElement && !isButtonElement) {
|
|
59
|
+
return <Item size={size}>{item}</Item>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// For buttons, links, and React components, clone with size prop if needed
|
|
51
63
|
const propsToAdd =
|
|
52
64
|
item.props && typeof item.props === "object" && "size" in item.props
|
|
53
65
|
? {}
|
|
54
66
|
: { size };
|
|
55
|
-
return React.cloneElement(item,
|
|
56
|
-
...(item.props || {}),
|
|
57
|
-
...propsToAdd,
|
|
58
|
-
});
|
|
67
|
+
return React.cloneElement(item, propsToAdd);
|
|
59
68
|
}
|
|
60
69
|
return item;
|
|
61
70
|
});
|
|
@@ -22,6 +22,8 @@ export interface InputStepperProps {
|
|
|
22
22
|
id: string;
|
|
23
23
|
inputClassName?: string;
|
|
24
24
|
isDisabled?: boolean;
|
|
25
|
+
/** Invalid state */
|
|
26
|
+
isInvalid?: boolean;
|
|
25
27
|
name?: string;
|
|
26
28
|
nonEditableInput?: boolean;
|
|
27
29
|
className?: string;
|
|
@@ -34,6 +36,7 @@ const InputStepper: React.FC<InputStepperProps> = ({
|
|
|
34
36
|
id,
|
|
35
37
|
config,
|
|
36
38
|
isDisabled,
|
|
39
|
+
isInvalid,
|
|
37
40
|
nonEditableInput = false,
|
|
38
41
|
...other
|
|
39
42
|
}) => {
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
appearance: none;
|
|
26
26
|
}
|
|
27
27
|
&:disabled {
|
|
28
|
-
color: var(--color-
|
|
29
|
-
-webkit-text-fill-color: var(--color-
|
|
30
|
-
background-color: color
|
|
28
|
+
color: var(--color-text-disabled) !important;
|
|
29
|
+
-webkit-text-fill-color: var(--color-text-disabled) !important;
|
|
30
|
+
background-color: var(--color-fill-primary);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
&__number {
|
|
@@ -40,11 +40,12 @@
|
|
|
40
40
|
padding: space.get("xsmall") space.get("xsmall") convert.to-rem(8px)
|
|
41
41
|
space.get("xsmall");
|
|
42
42
|
text-align: center;
|
|
43
|
-
border: 2px solid var(--color-
|
|
43
|
+
border: 2px solid var(--color-border-strong);
|
|
44
44
|
border-left: 0;
|
|
45
45
|
border-right: 0;
|
|
46
46
|
margin-bottom: 0;
|
|
47
47
|
line-height: 1.5;
|
|
48
|
+
background-color: var(--color-fill-primary);
|
|
48
49
|
}
|
|
49
50
|
&__button {
|
|
50
51
|
position: relative;
|
|
@@ -53,14 +54,11 @@
|
|
|
53
54
|
width: 40px;
|
|
54
55
|
border-top: 2px solid;
|
|
55
56
|
border-bottom: 2px solid;
|
|
56
|
-
border-color: var(--color-
|
|
57
|
+
border-color: var(--color-border-strong);
|
|
57
58
|
|
|
58
59
|
&::before {
|
|
59
60
|
content: "";
|
|
60
61
|
position: absolute;
|
|
61
|
-
background-size: cover;
|
|
62
|
-
background-repeat: no-repeat;
|
|
63
|
-
background-position: center center;
|
|
64
62
|
top: 50%;
|
|
65
63
|
left: 50%;
|
|
66
64
|
transform: translate(-50%, -50%);
|
|
@@ -70,24 +68,40 @@
|
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
&__button--minus {
|
|
73
|
-
border-left: 2px solid var(--color-
|
|
71
|
+
border-left: 2px solid var(--color-border-strong);
|
|
74
72
|
border-top-left-radius: convert.to-rem(5px);
|
|
75
73
|
border-bottom-left-radius: convert.to-rem(5px);
|
|
76
|
-
background-color: color
|
|
74
|
+
background-color: var(--color-fill-primary);
|
|
77
75
|
|
|
78
76
|
&::before {
|
|
79
|
-
background:
|
|
77
|
+
background-color: var(--color-text-default);
|
|
78
|
+
mask: url('data:image/svg+xml,<svg width="38" height="36" viewBox="0 0 38 36" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M11 17V19H25V17H11Z"/></svg>');
|
|
79
|
+
mask-size: cover;
|
|
80
|
+
mask-repeat: no-repeat;
|
|
81
|
+
mask-position: center center;
|
|
82
|
+
-webkit-mask: url('data:image/svg+xml,<svg width="38" height="36" viewBox="0 0 38 36" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M11 17V19H25V17H11Z"/></svg>');
|
|
83
|
+
-webkit-mask-size: cover;
|
|
84
|
+
-webkit-mask-repeat: no-repeat;
|
|
85
|
+
-webkit-mask-position: center center;
|
|
80
86
|
}
|
|
81
87
|
}
|
|
82
88
|
|
|
83
89
|
&__button--plus {
|
|
84
|
-
border-right: 2px solid var(--color-
|
|
90
|
+
border-right: 2px solid var(--color-border-strong);
|
|
85
91
|
border-top-right-radius: convert.to-rem(5px);
|
|
86
92
|
border-bottom-right-radius: convert.to-rem(5px);
|
|
87
|
-
background-color: color
|
|
93
|
+
background-color: var(--color-fill-primary);
|
|
88
94
|
|
|
89
95
|
&::before {
|
|
90
|
-
background:
|
|
96
|
+
background-color: var(--color-text-default);
|
|
97
|
+
mask: url('data:image/svg+xml,<svg width="38" height="36" viewBox="0 0 38 36" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M19 11H21V17H27V19H21V25H19V19H13V17H19V11Z"/></svg>');
|
|
98
|
+
mask-size: cover;
|
|
99
|
+
mask-repeat: no-repeat;
|
|
100
|
+
mask-position: center center;
|
|
101
|
+
-webkit-mask: url('data:image/svg+xml,<svg width="38" height="36" viewBox="0 0 38 36" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M19 11H21V17H27V19H21V25H19V19H13V17H19V11Z"/></svg>');
|
|
102
|
+
-webkit-mask-size: cover;
|
|
103
|
+
-webkit-mask-repeat: no-repeat;
|
|
104
|
+
-webkit-mask-position: center center;
|
|
91
105
|
}
|
|
92
106
|
}
|
|
93
107
|
|
|
@@ -95,50 +109,31 @@
|
|
|
95
109
|
z-index: 1;
|
|
96
110
|
}
|
|
97
111
|
|
|
98
|
-
&__button--minus:disabled
|
|
99
|
-
&::before {
|
|
100
|
-
background: url('data:image/svg+xml,<svg width="38" height="36" viewBox="0 0 38 36" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M11 17V19H25V17H11Z" fill="%23CCCCCC"/></svg>');
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
112
|
+
&__button--minus:disabled,
|
|
104
113
|
&__button--plus:disabled {
|
|
105
114
|
&::before {
|
|
106
|
-
background:
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
&__button:hover:not(:disabled) {
|
|
111
|
-
background-color: color.$black;
|
|
112
|
-
border-color: color.$black;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
&__button--minus:hover:not(:disabled) {
|
|
116
|
-
&::before {
|
|
117
|
-
background: url('data:image/svg+xml,<svg width="38" height="36" viewBox="0 0 38 36" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M11 17V19H25V17H11Z" fill="white"/></svg>');
|
|
115
|
+
background-color: var(--color-border-strong);
|
|
118
116
|
}
|
|
119
117
|
}
|
|
120
118
|
|
|
119
|
+
&__button--minus:hover:not(:disabled),
|
|
121
120
|
&__button--plus:hover:not(:disabled) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
}
|
|
121
|
+
background-color: var(--color-fill-contrast);
|
|
122
|
+
border-color: var(--color-fill-contrast);
|
|
126
123
|
|
|
127
|
-
&__button--minus:active:not(:disabled) {
|
|
128
124
|
&::before {
|
|
129
|
-
background:
|
|
125
|
+
background-color: var(--color-fill-primary);
|
|
130
126
|
}
|
|
131
127
|
}
|
|
132
128
|
|
|
129
|
+
&__button--minus:active:not(:disabled),
|
|
133
130
|
&__button--plus:active:not(:disabled) {
|
|
131
|
+
background-color: var(--color-fill-tertiary);
|
|
132
|
+
border-color: var(--color-border-accent);
|
|
133
|
+
|
|
134
134
|
&::before {
|
|
135
|
-
background:
|
|
135
|
+
background-color: color.$white;
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
|
-
|
|
139
|
-
&__button:active:not(:disabled) {
|
|
140
|
-
background-color: color.$orange-dark;
|
|
141
|
-
border-color: color.$orange-dark;
|
|
142
|
-
}
|
|
143
138
|
}
|
|
144
139
|
}
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
@use "../../styles/config" as commonConfig;
|
|
3
3
|
|
|
4
4
|
$checked-bg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='4' fill='%23fff'/%3E%3C/svg%3E");
|
|
5
|
-
$invalid-checked-bg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='4' fill='%
|
|
5
|
+
$invalid-checked-bg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='4' fill='%23ffffff'/%3E%3C/svg%3E");
|
|
6
6
|
|
|
7
7
|
$states: (
|
|
8
8
|
default: commonConfig.$default,
|
|
9
|
-
focus:
|
|
9
|
+
focus: (
|
|
10
|
+
outline: 2px solid var(--color-border-contrast),
|
|
11
|
+
outline-offset: 2px,
|
|
12
|
+
),
|
|
10
13
|
checked: (
|
|
11
14
|
border-color: var(--color-border-accent),
|
|
12
15
|
background-color: var(--color-surface-tertiary),
|
|
@@ -17,7 +20,7 @@ $states: (
|
|
|
17
20
|
disabled-checked: commonConfig.$disabled-checked,
|
|
18
21
|
invalid: commonConfig.$invalid,
|
|
19
22
|
invalid-checked: (
|
|
20
|
-
background-color: color
|
|
23
|
+
background-color: var(--color-icon-negative),
|
|
21
24
|
background-image: $invalid-checked-bg,
|
|
22
25
|
),
|
|
23
26
|
);
|
|
@@ -40,6 +40,8 @@ export interface RangeSliderProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
40
40
|
hasDataAttr?: boolean;
|
|
41
41
|
/** element id. required by RangeSlider.static.js and generated automatically in React environment. */
|
|
42
42
|
id?: string;
|
|
43
|
+
/** Invalid state */
|
|
44
|
+
isInvalid?: boolean;
|
|
43
45
|
/** width of the element */
|
|
44
46
|
width?: RangeSliderWidth;
|
|
45
47
|
/** Additional CSS classes */
|
|
@@ -58,6 +60,7 @@ const RangeSlider: React.FC<RangeSliderProps> = ({
|
|
|
58
60
|
config,
|
|
59
61
|
elementBefore,
|
|
60
62
|
elementAfter,
|
|
63
|
+
isInvalid,
|
|
61
64
|
width = defaultProps.width,
|
|
62
65
|
...other
|
|
63
66
|
}) => {
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
@use "../../../styles/tokens/space";
|
|
4
4
|
|
|
5
5
|
$default: (
|
|
6
|
-
background-color: color
|
|
7
|
-
border: 2px solid var(--color-
|
|
6
|
+
background-color: var(--color-fill-primary),
|
|
7
|
+
border: 2px solid var(--color-border-strong),
|
|
8
|
+
color: var(--color-text-default),
|
|
8
9
|
);
|
|
9
10
|
|
|
10
11
|
$focus: (
|
|
@@ -15,12 +16,12 @@ $focus: (
|
|
|
15
16
|
|
|
16
17
|
$disabled: (
|
|
17
18
|
background-color: var(--color-surface-subtle),
|
|
18
|
-
border-color: var(--color-
|
|
19
|
+
border-color: var(--color-border-strong),
|
|
19
20
|
color: var(--color-text-secondary),
|
|
20
21
|
);
|
|
21
22
|
|
|
22
23
|
$disabled-checked: (
|
|
23
|
-
background-color: var(--color-
|
|
24
|
+
background-color: var(--color-border-strong),
|
|
24
25
|
);
|
|
25
26
|
|
|
26
27
|
$readonly: (
|
|
@@ -30,64 +30,66 @@ export const PromoBanner = ({
|
|
|
30
30
|
}: PromoBannerProps) => {
|
|
31
31
|
const classes = cx(CLASS_ROOT, className);
|
|
32
32
|
return (
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<GridCol
|
|
52
|
-
size={
|
|
53
|
-
variant === "vertical"
|
|
54
|
-
? { xs: 12, sm: 10, md: 8, lg: 6 }
|
|
55
|
-
: { xs: 12, md: image ? 6 : 7 }
|
|
56
|
-
}
|
|
57
|
-
className={cx(
|
|
58
|
-
`${CLASS_ROOT}__item`,
|
|
59
|
-
{
|
|
60
|
-
"align-items-center align-center align-self-center":
|
|
61
|
-
variant === "vertical",
|
|
62
|
-
},
|
|
63
|
-
itemClassName,
|
|
33
|
+
<div className={classes}>
|
|
34
|
+
<Grid columnGapSize="large">
|
|
35
|
+
{variant === "reverse" && image && (
|
|
36
|
+
<GridCol
|
|
37
|
+
size={{ xs: 12, md: 6 }}
|
|
38
|
+
className={cx(
|
|
39
|
+
`${CLASS_ROOT}__image`,
|
|
40
|
+
"align-center align-md-left",
|
|
41
|
+
imageClassName,
|
|
42
|
+
)}
|
|
43
|
+
>
|
|
44
|
+
<Image
|
|
45
|
+
src={image}
|
|
46
|
+
alt="Obrázok"
|
|
47
|
+
className={cx("mb-none", { fullwidth: imageFullWidth })}
|
|
48
|
+
/>
|
|
49
|
+
</GridCol>
|
|
64
50
|
)}
|
|
65
|
-
>
|
|
66
|
-
{children}
|
|
67
|
-
</GridCol>
|
|
68
51
|
|
|
69
|
-
{image && variant !== "reverse" && (
|
|
70
52
|
<GridCol
|
|
71
|
-
size={
|
|
53
|
+
size={
|
|
54
|
+
variant === "vertical"
|
|
55
|
+
? { xs: 12, sm: 10, md: 8, lg: 6 }
|
|
56
|
+
: { xs: 12, md: image ? 6 : 7 }
|
|
57
|
+
}
|
|
72
58
|
className={cx(
|
|
73
|
-
`${CLASS_ROOT}
|
|
59
|
+
`${CLASS_ROOT}__item`,
|
|
74
60
|
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"pt-none": alignImage === "top",
|
|
78
|
-
"pb-none": alignImage === "bottom",
|
|
79
|
-
"align-center": variant === "vertical",
|
|
61
|
+
"align-items-center align-center align-self-center":
|
|
62
|
+
variant === "vertical",
|
|
80
63
|
},
|
|
81
|
-
|
|
64
|
+
itemClassName,
|
|
82
65
|
)}
|
|
83
66
|
>
|
|
84
|
-
|
|
85
|
-
src={image}
|
|
86
|
-
alt="Obrázok"
|
|
87
|
-
className={cx("mb-none", { fullwidth: imageFullWidth })}
|
|
88
|
-
/>
|
|
67
|
+
{children}
|
|
89
68
|
</GridCol>
|
|
90
|
-
|
|
91
|
-
|
|
69
|
+
|
|
70
|
+
{image && variant !== "reverse" && (
|
|
71
|
+
<GridCol
|
|
72
|
+
size={variant === "vertical" ? { xs: 12 } : { xs: 12, md: 6 }}
|
|
73
|
+
className={cx(
|
|
74
|
+
`${CLASS_ROOT}__image`,
|
|
75
|
+
{
|
|
76
|
+
[`${CLASS_ROOT}__image--bleed-right`]: bleedImage,
|
|
77
|
+
[`align-self-${alignImage}`]: alignImage,
|
|
78
|
+
"pt-none": alignImage === "top",
|
|
79
|
+
"pb-none": alignImage === "bottom",
|
|
80
|
+
"align-center": variant === "vertical",
|
|
81
|
+
},
|
|
82
|
+
imageClassName,
|
|
83
|
+
)}
|
|
84
|
+
>
|
|
85
|
+
<Image
|
|
86
|
+
src={image}
|
|
87
|
+
alt="Obrázok"
|
|
88
|
+
className={cx("mb-none", { fullwidth: imageFullWidth })}
|
|
89
|
+
/>
|
|
90
|
+
</GridCol>
|
|
91
|
+
)}
|
|
92
|
+
</Grid>
|
|
93
|
+
</div>
|
|
92
94
|
);
|
|
93
95
|
};
|
|
@@ -714,10 +714,12 @@ describe("PromoBanner Component Conformance Tests", () => {
|
|
|
714
714
|
</PromoBanner>,
|
|
715
715
|
);
|
|
716
716
|
|
|
717
|
-
const
|
|
717
|
+
const banner = container.querySelector(".promo-banner");
|
|
718
|
+
const grid = banner.querySelector(".grid");
|
|
718
719
|
const gridCol = container.querySelector(".grid__col");
|
|
719
720
|
|
|
720
|
-
expect(
|
|
721
|
+
expect(banner).toHaveClass("promo-banner", "test-grid");
|
|
722
|
+
expect(grid).toHaveClass("grid");
|
|
721
723
|
expect(gridCol).toHaveClass("grid__col");
|
|
722
724
|
});
|
|
723
725
|
|