@orangesk/orange-design-system 2.0.0-beta.27 → 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/components/types/src/components/Modal/Modal.static.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 +418 -0
- package/package.json +7 -7
- 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/Modal/Modal.static.ts +14 -3
- package/src/components/Modal/Modal.tsx +12 -3
- 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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orangesk/orange-design-system",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.29",
|
|
4
4
|
"private": false,
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.x"
|
|
@@ -49,12 +49,12 @@
|
|
|
49
49
|
"@orangesk/accessible-autocomplete": "^3.1.2",
|
|
50
50
|
"@popperjs/core": "^2.11.8",
|
|
51
51
|
"@types/mdx": "^2.0.13",
|
|
52
|
-
"a11y-dialog": "^8.1.
|
|
52
|
+
"a11y-dialog": "^8.1.5",
|
|
53
53
|
"classnames": "^2.5.1",
|
|
54
54
|
"daypickr": "^0.3.4",
|
|
55
55
|
"diff2html": "^3.4.56",
|
|
56
56
|
"dompurify": "^3.3.1",
|
|
57
|
-
"html-react-parser": "^5.2.
|
|
57
|
+
"html-react-parser": "^5.2.17",
|
|
58
58
|
"jest-environment-jsdom": "^30.2.0",
|
|
59
59
|
"lorem-ipsum": "^2.0.8",
|
|
60
60
|
"minisearch": "7.2.0",
|
|
@@ -94,17 +94,17 @@
|
|
|
94
94
|
"@testing-library/jest-dom": "^6.9.1",
|
|
95
95
|
"@testing-library/react": "^16.3.2",
|
|
96
96
|
"@testing-library/user-event": "^14.6.1",
|
|
97
|
-
"@types/node": "25.2.
|
|
98
|
-
"@types/react": "19.2.
|
|
97
|
+
"@types/node": "25.2.2",
|
|
98
|
+
"@types/react": "19.2.13",
|
|
99
99
|
"@types/react-dom": "19.2.3",
|
|
100
100
|
"@types/wnumb": "^1.2.3",
|
|
101
101
|
"babel-jest": "30.2.0",
|
|
102
102
|
"eslint": "latest",
|
|
103
103
|
"eslint-config-next": "16.1.6",
|
|
104
104
|
"eslint-config-prettier": "^10.1.8",
|
|
105
|
-
"eslint-plugin-unused-imports": "^4.
|
|
105
|
+
"eslint-plugin-unused-imports": "^4.4.1",
|
|
106
106
|
"fs-extra": "^11.3.3",
|
|
107
|
-
"glob": "13.0.
|
|
107
|
+
"glob": "13.0.1",
|
|
108
108
|
"html-validate": "10.7.0",
|
|
109
109
|
"husky": "^9.1.7",
|
|
110
110
|
"identity-obj-proxy": "^3.0.0",
|
|
@@ -309,11 +309,30 @@ export default class Carousel {
|
|
|
309
309
|
} else {
|
|
310
310
|
this.instance.disable();
|
|
311
311
|
}
|
|
312
|
+
|
|
313
|
+
this.applyTrackMarginCompensation();
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Apply negative margin-right to carousel track when slidesPerView is a whole number.
|
|
318
|
+
* This compensates for the 20px padding-right on each slide, ensuring proper grid alignment.
|
|
319
|
+
*/
|
|
320
|
+
private applyTrackMarginCompensation(): void {
|
|
321
|
+
if (!this.instance || !this.viewport) return;
|
|
322
|
+
|
|
323
|
+
const slidesPerView = Number(this.instance.params.slidesPerView) || 1;
|
|
324
|
+
|
|
325
|
+
if (Number.isInteger(slidesPerView)) {
|
|
326
|
+
this.viewport.style.setProperty("margin-right", "-20px", "important");
|
|
327
|
+
} else {
|
|
328
|
+
this.viewport.style.removeProperty("margin-right");
|
|
329
|
+
}
|
|
312
330
|
}
|
|
313
331
|
|
|
314
332
|
/**
|
|
315
333
|
* Calculate how much the carousel should extend beyond the container (bleed effect).
|
|
316
334
|
* On screens 2560px and wider, the bleed effect is disabled.
|
|
335
|
+
* Also disabled when slidesPerView is a whole number (integer).
|
|
317
336
|
*/
|
|
318
337
|
private calculateBleedAmount(container: HTMLElement): number {
|
|
319
338
|
const containerWidth = container.offsetWidth;
|
|
@@ -325,6 +344,12 @@ export default class Carousel {
|
|
|
325
344
|
bleedAmount = 0;
|
|
326
345
|
}
|
|
327
346
|
|
|
347
|
+
// Disable bleed when slidesPerView is a whole number (integer)
|
|
348
|
+
const slidesPerView = Number(this.instance?.params.slidesPerView) || 1;
|
|
349
|
+
if (Number.isInteger(slidesPerView)) {
|
|
350
|
+
bleedAmount = 0;
|
|
351
|
+
}
|
|
352
|
+
|
|
328
353
|
return Math.max(bleedAmount, 0);
|
|
329
354
|
}
|
|
330
355
|
|
|
@@ -358,6 +383,7 @@ export default class Carousel {
|
|
|
358
383
|
* Configure bleed-right carousel to extend beyond the container edge.
|
|
359
384
|
* Calculates the exact offset needed for the carousel to reach the viewport edge
|
|
360
385
|
* while keeping the last slide aligned with the container edge when scrolled to the end.
|
|
386
|
+
* When slidesPerView is a whole number (integer), the bleed effect is disabled.
|
|
361
387
|
*/
|
|
362
388
|
adjustConfigForBleedRight() {
|
|
363
389
|
requestAnimationFrame(() => {
|
|
@@ -369,14 +395,26 @@ export default class Carousel {
|
|
|
369
395
|
) as HTMLElement;
|
|
370
396
|
if (!viewportWrapper) return;
|
|
371
397
|
|
|
372
|
-
const
|
|
373
|
-
|
|
398
|
+
const updateBleedState = () => {
|
|
399
|
+
const slidesPerView = Number(this.instance?.params.slidesPerView) || 1;
|
|
400
|
+
const shouldDisableBleed = Number.isInteger(slidesPerView);
|
|
374
401
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
402
|
+
if (shouldDisableBleed) {
|
|
403
|
+
this.element.classList.remove(CLASS_BLEED_RIGHT);
|
|
404
|
+
} else {
|
|
405
|
+
this.element.classList.add(CLASS_BLEED_RIGHT);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const bleedAmount = this.calculateBleedAmount(container);
|
|
409
|
+
this.applyBleedOffset(viewportWrapper, bleedAmount);
|
|
410
|
+
|
|
411
|
+
// Update margin compensation on resize
|
|
412
|
+
this.applyTrackMarginCompensation();
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
updateBleedState();
|
|
416
|
+
|
|
417
|
+
this.instance.on("resize", updateBleedState);
|
|
380
418
|
});
|
|
381
419
|
}
|
|
382
420
|
|
|
@@ -6,7 +6,10 @@ $invalid-checked-bg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/200
|
|
|
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-surface-tertiary),
|
|
12
15
|
background-color: var(--color-surface-tertiary),
|
|
@@ -17,8 +20,8 @@ $states: (
|
|
|
17
20
|
disabled-checked: commonConfig.$disabled-checked,
|
|
18
21
|
invalid: commonConfig.$invalid,
|
|
19
22
|
invalid-checked: (
|
|
20
|
-
background-color: var(--color-
|
|
21
|
-
background-image: $
|
|
23
|
+
background-color: var(--color-icon-negative),
|
|
24
|
+
background-image: $checked-bg,
|
|
22
25
|
),
|
|
23
26
|
);
|
|
24
27
|
|
|
@@ -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
|
}) => {
|