@truedat/dd 8.13.1 → 8.13.3
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dd",
|
|
3
|
-
"version": "8.13.
|
|
3
|
+
"version": "8.13.3",
|
|
4
4
|
"description": "Truedat Web Data Dictionary",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"module": "src/index.js",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
]
|
|
47
47
|
},
|
|
48
48
|
"transformIgnorePatterns": [
|
|
49
|
-
"/node_modules/(?!marked|turndown|@tiptap|react-router|cookie-es)/"
|
|
49
|
+
"/node_modules/(?!(marked|turndown|@tiptap|react-router|cookie-es|query-string|decode-uri-component|split-on-first|filter-obj)/)"
|
|
50
50
|
]
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"@testing-library/jest-dom": "^6.6.3",
|
|
55
55
|
"@testing-library/react": "^16.3.0",
|
|
56
56
|
"@testing-library/user-event": "^14.6.1",
|
|
57
|
-
"@truedat/test": "8.13.
|
|
57
|
+
"@truedat/test": "8.13.3",
|
|
58
58
|
"identity-obj-proxy": "^3.0.0",
|
|
59
59
|
"jest": "^29.7.0",
|
|
60
60
|
"redux-saga-test-plan": "^4.0.6"
|
|
@@ -90,5 +90,5 @@
|
|
|
90
90
|
"svg-pan-zoom": "^3.6.2",
|
|
91
91
|
"swr": "^2.3.3"
|
|
92
92
|
},
|
|
93
|
-
"gitHead": "
|
|
93
|
+
"gitHead": "f02b46c12aeac48b129806b2c6a23cb0c87dcc94"
|
|
94
94
|
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import { connect } from "react-redux";
|
|
4
|
+
import { useIntl } from "react-intl";
|
|
5
|
+
import { Link } from "react-router";
|
|
6
|
+
import { Menu, Icon, Label } from "semantic-ui-react";
|
|
7
|
+
import routes from "@truedat/core/routes";
|
|
8
|
+
|
|
9
|
+
export const GrantCartMenu = ({ cartCount = 0 }) => {
|
|
10
|
+
const { formatMessage } = useIntl();
|
|
11
|
+
const [cartAnimation, setCartAnimation] = useState({
|
|
12
|
+
count: cartCount,
|
|
13
|
+
revision: 0,
|
|
14
|
+
direction: undefined,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
if (cartAnimation.count !== cartCount) {
|
|
18
|
+
const direction =
|
|
19
|
+
cartCount > cartAnimation.count ? "cart-added" : "cart-removed";
|
|
20
|
+
const visibleDirection =
|
|
21
|
+
cartAnimation.count === 0 ? "cart-enter" : direction;
|
|
22
|
+
const nextDirection = cartCount === 0 ? "cart-exit" : visibleDirection;
|
|
23
|
+
const continuingBatch =
|
|
24
|
+
cartCount > 0 &&
|
|
25
|
+
(cartAnimation.direction === nextDirection ||
|
|
26
|
+
(cartAnimation.direction === "cart-enter" &&
|
|
27
|
+
direction === "cart-added"));
|
|
28
|
+
setCartAnimation({
|
|
29
|
+
count: cartCount,
|
|
30
|
+
revision: cartAnimation.revision + (continuingBatch ? 0 : 1),
|
|
31
|
+
direction: continuingBatch ? cartAnimation.direction : nextDirection,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (!cartAnimation.direction) return;
|
|
37
|
+
const timeout = setTimeout(
|
|
38
|
+
() => {
|
|
39
|
+
setCartAnimation((current) => ({ ...current, direction: undefined }));
|
|
40
|
+
},
|
|
41
|
+
cartAnimation.direction === "cart-added" ? 600 : 460,
|
|
42
|
+
);
|
|
43
|
+
return () => clearTimeout(timeout);
|
|
44
|
+
}, [cartCount, cartAnimation.direction, cartAnimation.revision]);
|
|
45
|
+
|
|
46
|
+
return cartCount > 0 || cartAnimation.direction === "cart-exit" ? (
|
|
47
|
+
<Menu.Item
|
|
48
|
+
className="grant-cart-menu"
|
|
49
|
+
as={cartCount > 0 ? Link : "div"}
|
|
50
|
+
aria-disabled={cartCount === 0 || undefined}
|
|
51
|
+
aria-label={formatMessage(
|
|
52
|
+
{
|
|
53
|
+
id: "navigation.grant_cart",
|
|
54
|
+
defaultMessage: "Checkout ({count})",
|
|
55
|
+
},
|
|
56
|
+
{ count: cartCount },
|
|
57
|
+
)}
|
|
58
|
+
to={cartCount > 0 ? routes.GRANTS_REQUESTS_CHECKOUT : undefined}
|
|
59
|
+
>
|
|
60
|
+
<Icon
|
|
61
|
+
key={cartAnimation.revision}
|
|
62
|
+
name="shopping cart"
|
|
63
|
+
flipped="horizontally"
|
|
64
|
+
className={cartAnimation.direction}
|
|
65
|
+
/>
|
|
66
|
+
{(cartAnimation.direction === "cart-added" ||
|
|
67
|
+
cartAnimation.direction === "cart-removed") && (
|
|
68
|
+
<Icon
|
|
69
|
+
key={`incoming-${cartAnimation.revision}`}
|
|
70
|
+
name="shopping cart"
|
|
71
|
+
className={
|
|
72
|
+
cartAnimation.direction === "cart-added"
|
|
73
|
+
? "cart-incoming"
|
|
74
|
+
: "cart-outgoing"
|
|
75
|
+
}
|
|
76
|
+
aria-hidden="true"
|
|
77
|
+
/>
|
|
78
|
+
)}
|
|
79
|
+
{cartCount > 0 && (
|
|
80
|
+
<Label
|
|
81
|
+
circular
|
|
82
|
+
color="red"
|
|
83
|
+
size="mini"
|
|
84
|
+
className="top-menu-cart-counter"
|
|
85
|
+
aria-live="polite"
|
|
86
|
+
>
|
|
87
|
+
<span
|
|
88
|
+
key={cartAnimation.revision}
|
|
89
|
+
className={
|
|
90
|
+
cartAnimation.direction === "cart-added"
|
|
91
|
+
? "cart-counter-added"
|
|
92
|
+
: undefined
|
|
93
|
+
}
|
|
94
|
+
>
|
|
95
|
+
{cartCount > 99 ? "99+" : cartCount}
|
|
96
|
+
</span>
|
|
97
|
+
</Label>
|
|
98
|
+
)}
|
|
99
|
+
</Menu.Item>
|
|
100
|
+
) : null;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
GrantCartMenu.propTypes = { cartCount: PropTypes.number };
|
|
104
|
+
|
|
105
|
+
const mapStateToProps = ({ grantRequestsCart }) => ({
|
|
106
|
+
cartCount: grantRequestsCart?.structures?.length ?? 0,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
export default connect(mapStateToProps)(GrantCartMenu);
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import React, { act } from "react";
|
|
2
|
+
import { render, waitForLoad } from "@truedat/test/render";
|
|
3
|
+
import ConnectedGrantCartMenu, { GrantCartMenu } from "../GrantCartMenu";
|
|
4
|
+
|
|
5
|
+
describe("<GrantCartMenu />", () => {
|
|
6
|
+
const storeState = {};
|
|
7
|
+
it("reads the real cart count from Redux", async () => {
|
|
8
|
+
const rendered = render(<ConnectedGrantCartMenu />, {
|
|
9
|
+
state: { grantRequestsCart: { structures: [{ id: 1 }, { id: 2 }] } },
|
|
10
|
+
});
|
|
11
|
+
await waitForLoad(rendered);
|
|
12
|
+
expect(
|
|
13
|
+
rendered.getByRole("link", { name: "Checkout (2)" }),
|
|
14
|
+
).toHaveTextContent("2");
|
|
15
|
+
});
|
|
16
|
+
it.each([
|
|
17
|
+
[0, ""],
|
|
18
|
+
[1, "1"],
|
|
19
|
+
[30, "30"],
|
|
20
|
+
[99, "99"],
|
|
21
|
+
[100, "99+"],
|
|
22
|
+
[230, "99+"],
|
|
23
|
+
])(
|
|
24
|
+
"shows capped cart count %i and hides empty cart",
|
|
25
|
+
async (count, badge) => {
|
|
26
|
+
const rendered = render(<GrantCartMenu cartCount={count} />, {
|
|
27
|
+
state: storeState,
|
|
28
|
+
});
|
|
29
|
+
await waitForLoad(rendered);
|
|
30
|
+
const cart = rendered.queryByRole("link", {
|
|
31
|
+
name: `Checkout (${count})`,
|
|
32
|
+
});
|
|
33
|
+
if (count === 0) expect(cart).not.toBeInTheDocument();
|
|
34
|
+
else expect(cart).toHaveTextContent(badge);
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
it("animates additions and removals, including batches above 99", async () => {
|
|
39
|
+
const rendered = render(<GrantCartMenu cartCount={99} />, {
|
|
40
|
+
state: storeState,
|
|
41
|
+
});
|
|
42
|
+
await waitForLoad(rendered);
|
|
43
|
+
const initialIcon = rendered.container.querySelector(".shopping.cart.icon");
|
|
44
|
+
expect(initialIcon).not.toHaveClass("cart-added");
|
|
45
|
+
|
|
46
|
+
rendered.rerender(<GrantCartMenu cartCount={100} />);
|
|
47
|
+
const addedIcon = rendered.container.querySelector(".shopping.cart.icon");
|
|
48
|
+
expect(addedIcon).toHaveClass("cart-added");
|
|
49
|
+
expect(addedIcon).not.toBe(initialIcon);
|
|
50
|
+
|
|
51
|
+
act(() => jest.advanceTimersByTime(600));
|
|
52
|
+
rendered.rerender(<GrantCartMenu cartCount={230} />);
|
|
53
|
+
const batchIcon = rendered.container.querySelector(".shopping.cart.icon");
|
|
54
|
+
expect(batchIcon).not.toBe(addedIcon);
|
|
55
|
+
expect(batchIcon).toHaveClass("cart-added");
|
|
56
|
+
|
|
57
|
+
rendered.rerender(<GrantCartMenu cartCount={229} />);
|
|
58
|
+
const removedIcon = rendered.container.querySelector(".shopping.cart.icon");
|
|
59
|
+
expect(removedIcon).not.toBe(batchIcon);
|
|
60
|
+
expect(removedIcon).toHaveClass("cart-removed");
|
|
61
|
+
rendered.rerender(<GrantCartMenu cartCount={229} />);
|
|
62
|
+
expect(rendered.container.querySelector(".shopping.cart.icon")).toBe(
|
|
63
|
+
removedIcon,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
rendered.rerender(<GrantCartMenu cartCount={0} />);
|
|
67
|
+
expect(rendered.container.querySelector(".shopping.cart.icon")).toHaveClass(
|
|
68
|
+
"cart-exit",
|
|
69
|
+
);
|
|
70
|
+
expect(
|
|
71
|
+
rendered.container.querySelector(".top-menu-cart-counter"),
|
|
72
|
+
).toBeNull();
|
|
73
|
+
expect(rendered.queryByRole("link")).not.toBeInTheDocument();
|
|
74
|
+
act(() => jest.advanceTimersByTime(460));
|
|
75
|
+
expect(rendered.container.querySelector(".shopping.cart.icon")).toBeNull();
|
|
76
|
+
rendered.rerender(<GrantCartMenu cartCount={1} />);
|
|
77
|
+
expect(rendered.container.querySelector(".shopping.cart.icon")).toHaveClass(
|
|
78
|
+
"cart-enter",
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("exits directly from one to zero even during a removal pulse", async () => {
|
|
83
|
+
const rendered = render(<GrantCartMenu cartCount={2} />);
|
|
84
|
+
await waitForLoad(rendered);
|
|
85
|
+
rendered.rerender(<GrantCartMenu cartCount={1} />);
|
|
86
|
+
expect(rendered.container.querySelector(".shopping.cart.icon")).toHaveClass(
|
|
87
|
+
"cart-removed",
|
|
88
|
+
);
|
|
89
|
+
rendered.rerender(<GrantCartMenu cartCount={0} />);
|
|
90
|
+
const icon = rendered.container.querySelector(".shopping.cart.icon");
|
|
91
|
+
expect(icon).toHaveClass("cart-exit");
|
|
92
|
+
expect(icon).not.toHaveClass("cart-removed");
|
|
93
|
+
expect(
|
|
94
|
+
rendered.container.querySelector(".top-menu-cart-counter"),
|
|
95
|
+
).toBeNull();
|
|
96
|
+
act(() => jest.advanceTimersByTime(460));
|
|
97
|
+
expect(icon).not.toBeInTheDocument();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it.each([1, 5])(
|
|
101
|
+
"enters from an empty cart when adding %i requests",
|
|
102
|
+
async (count) => {
|
|
103
|
+
const rendered = render(<GrantCartMenu cartCount={0} />);
|
|
104
|
+
await waitForLoad(rendered);
|
|
105
|
+
expect(
|
|
106
|
+
rendered.container.querySelector(".shopping.cart.icon"),
|
|
107
|
+
).toBeNull();
|
|
108
|
+
rendered.rerender(<GrantCartMenu cartCount={count} />);
|
|
109
|
+
const icon = rendered.container.querySelector(".shopping.cart.icon");
|
|
110
|
+
expect(icon).toHaveClass("cart-enter");
|
|
111
|
+
expect(icon).not.toHaveClass("cart-added");
|
|
112
|
+
act(() => jest.advanceTimersByTime(460));
|
|
113
|
+
rendered.rerender(<GrantCartMenu cartCount={count + 1} />);
|
|
114
|
+
expect(
|
|
115
|
+
rendered.container.querySelector(".shopping.cart.icon"),
|
|
116
|
+
).toHaveClass("cart-added");
|
|
117
|
+
},
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
it("cancels the pending exit when new requests are added", async () => {
|
|
121
|
+
const rendered = render(<GrantCartMenu cartCount={3} />);
|
|
122
|
+
await waitForLoad(rendered);
|
|
123
|
+
rendered.rerender(<GrantCartMenu cartCount={0} />);
|
|
124
|
+
act(() => jest.advanceTimersByTime(200));
|
|
125
|
+
rendered.rerender(<GrantCartMenu cartCount={2} />);
|
|
126
|
+
act(() => jest.advanceTimersByTime(460));
|
|
127
|
+
expect(
|
|
128
|
+
rendered.getByRole("link", { name: "Checkout (2)" }),
|
|
129
|
+
).toHaveTextContent("2");
|
|
130
|
+
expect(
|
|
131
|
+
rendered.container.querySelector(".shopping.cart.icon"),
|
|
132
|
+
).not.toHaveClass("cart-exit");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it.each([0, 10])(
|
|
136
|
+
"animates a burst of 30 additions once starting at %i",
|
|
137
|
+
async (initial) => {
|
|
138
|
+
const rendered = render(<GrantCartMenu cartCount={initial} />);
|
|
139
|
+
await waitForLoad(rendered);
|
|
140
|
+
rendered.rerender(<GrantCartMenu cartCount={initial + 1} />);
|
|
141
|
+
const icon = rendered.container.querySelector(".shopping.cart.icon");
|
|
142
|
+
const incoming = rendered.container.querySelector(".cart-incoming");
|
|
143
|
+
const number = rendered.container.querySelector(
|
|
144
|
+
".top-menu-cart-counter > span",
|
|
145
|
+
);
|
|
146
|
+
Array.from({ length: 29 }, (_, index) => initial + index + 2).forEach(
|
|
147
|
+
(count) => {
|
|
148
|
+
act(() => jest.advanceTimersByTime(40));
|
|
149
|
+
rendered.rerender(<GrantCartMenu cartCount={count} />);
|
|
150
|
+
expect(rendered.container.querySelector(".shopping.cart.icon")).toBe(
|
|
151
|
+
icon,
|
|
152
|
+
);
|
|
153
|
+
expect(rendered.container.querySelector(".cart-incoming")).toBe(
|
|
154
|
+
incoming,
|
|
155
|
+
);
|
|
156
|
+
expect(
|
|
157
|
+
rendered.container.querySelector(".top-menu-cart-counter > span"),
|
|
158
|
+
).toBe(number);
|
|
159
|
+
},
|
|
160
|
+
);
|
|
161
|
+
expect(number).toHaveTextContent(String(initial + 30));
|
|
162
|
+
act(() => jest.advanceTimersByTime(600));
|
|
163
|
+
rendered.rerender(<GrantCartMenu cartCount={initial + 31} />);
|
|
164
|
+
expect(rendered.container.querySelector(".shopping.cart.icon")).not.toBe(
|
|
165
|
+
icon,
|
|
166
|
+
);
|
|
167
|
+
},
|
|
168
|
+
);
|
|
169
|
+
});
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
.ui.menu .item.grant-cart-menu {
|
|
2
|
+
position: relative;
|
|
3
|
+
|
|
4
|
+
&:hover {
|
|
5
|
+
background: rgba(0, 0, 0, 0.03);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.ui.menu .item > .icon.cart-added {
|
|
10
|
+
transform-origin: center;
|
|
11
|
+
animation: cart-added-pulse 460ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
12
|
+
animation-delay: 140ms;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.ui.menu .item > .icon.cart-removed {
|
|
16
|
+
transform-origin: center;
|
|
17
|
+
animation: cart-removed-pulse 460ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.ui.menu .item.grant-cart-menu[aria-disabled="true"] {
|
|
21
|
+
cursor: default;
|
|
22
|
+
pointer-events: none;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.ui.menu .item > .icon.cart-exit {
|
|
26
|
+
animation: cart-exit 460ms cubic-bezier(0.55, 0, 1, 0.45) forwards;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.ui.menu .item > .icon.cart-enter {
|
|
30
|
+
animation: cart-enter 460ms cubic-bezier(0, 0.55, 0.45, 1) backwards;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@keyframes cart-enter {
|
|
34
|
+
from {
|
|
35
|
+
transform: translateX(48px) scaleX(-1);
|
|
36
|
+
opacity: 0;
|
|
37
|
+
}
|
|
38
|
+
to {
|
|
39
|
+
transform: translateX(0) scaleX(-1);
|
|
40
|
+
opacity: 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@keyframes cart-enter-fade {
|
|
45
|
+
from {
|
|
46
|
+
opacity: 0;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@keyframes cart-exit {
|
|
51
|
+
from {
|
|
52
|
+
transform: translateX(0) scaleX(-1);
|
|
53
|
+
opacity: 1;
|
|
54
|
+
}
|
|
55
|
+
to {
|
|
56
|
+
transform: translateX(-48px) scaleX(-1);
|
|
57
|
+
opacity: 0;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@keyframes cart-exit-fade {
|
|
62
|
+
to {
|
|
63
|
+
opacity: 0;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@keyframes cart-removed-pulse {
|
|
68
|
+
0%,
|
|
69
|
+
100% {
|
|
70
|
+
transform: scaleX(-1);
|
|
71
|
+
}
|
|
72
|
+
38% {
|
|
73
|
+
color: @primaryColor;
|
|
74
|
+
transform: scale(-0.72, 0.72);
|
|
75
|
+
}
|
|
76
|
+
74% {
|
|
77
|
+
transform: scale(-1.03, 1.03);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@keyframes cart-added-pulse {
|
|
82
|
+
0%,
|
|
83
|
+
100% {
|
|
84
|
+
transform: scaleX(-1);
|
|
85
|
+
}
|
|
86
|
+
38% {
|
|
87
|
+
color: @red;
|
|
88
|
+
transform: scale(-1.28, 1.28);
|
|
89
|
+
}
|
|
90
|
+
74% {
|
|
91
|
+
transform: scale(-0.97, 0.97);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.top-menu-cart-counter > span {
|
|
96
|
+
display: inline-block;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.top-menu-cart-counter > .cart-counter-added {
|
|
100
|
+
transform-origin: center;
|
|
101
|
+
animation: cart-counter-added-pulse 460ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
102
|
+
animation-delay: 140ms;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@keyframes cart-counter-added-pulse {
|
|
106
|
+
0%,
|
|
107
|
+
100% {
|
|
108
|
+
transform: scale(1);
|
|
109
|
+
}
|
|
110
|
+
38% {
|
|
111
|
+
transform: scale(1.28);
|
|
112
|
+
}
|
|
113
|
+
74% {
|
|
114
|
+
transform: scale(0.97);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.ui.menu .item.grant-cart-menu > .icon {
|
|
119
|
+
position: relative;
|
|
120
|
+
left: 4px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.ui.menu .item.grant-cart-menu > .icon.cart-incoming,
|
|
124
|
+
.ui.menu .item.grant-cart-menu > .icon.cart-outgoing {
|
|
125
|
+
position: absolute;
|
|
126
|
+
left: calc(50% + 2px);
|
|
127
|
+
top: 50%;
|
|
128
|
+
margin: 0;
|
|
129
|
+
pointer-events: none;
|
|
130
|
+
color: @primaryColor;
|
|
131
|
+
animation: cart-merge 320ms cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.ui.menu .item.grant-cart-menu > .icon.cart-outgoing {
|
|
135
|
+
animation: cart-separate 460ms cubic-bezier(0.55, 0, 1, 0.45) both;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@keyframes cart-separate {
|
|
139
|
+
0% {
|
|
140
|
+
transform: translate(-50%, -50%) scale(-1, 1);
|
|
141
|
+
opacity: 0;
|
|
142
|
+
}
|
|
143
|
+
20% {
|
|
144
|
+
opacity: 0.7;
|
|
145
|
+
}
|
|
146
|
+
100% {
|
|
147
|
+
transform: translate(calc(-50% + 32px), -50%) scale(-1, 1);
|
|
148
|
+
opacity: 0;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@keyframes cart-merge {
|
|
153
|
+
0% {
|
|
154
|
+
transform: translate(calc(-50% + 32px), -50%) scale(-1, 1);
|
|
155
|
+
opacity: 0;
|
|
156
|
+
}
|
|
157
|
+
25% {
|
|
158
|
+
opacity: 0.7;
|
|
159
|
+
}
|
|
160
|
+
75% {
|
|
161
|
+
opacity: 0.5;
|
|
162
|
+
}
|
|
163
|
+
100% {
|
|
164
|
+
transform: translate(-50%, -50%) scale(-1, 1);
|
|
165
|
+
opacity: 0;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.ui.menu .item.grant-cart-menu .ui.label.top-menu-cart-counter {
|
|
170
|
+
position: absolute;
|
|
171
|
+
left: -3px;
|
|
172
|
+
top: 10px;
|
|
173
|
+
z-index: 1;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@media (prefers-reduced-motion: reduce) {
|
|
177
|
+
.ui.menu .item > .icon.cart-enter {
|
|
178
|
+
animation: cart-enter-fade 160ms ease-out backwards;
|
|
179
|
+
}
|
|
180
|
+
.ui.menu .item > .icon.cart-exit {
|
|
181
|
+
animation: cart-exit-fade 160ms ease-out forwards;
|
|
182
|
+
}
|
|
183
|
+
.ui.menu .item > .icon.cart-added,
|
|
184
|
+
.ui.menu .item > .icon.cart-removed,
|
|
185
|
+
.top-menu-cart-counter > .cart-counter-added {
|
|
186
|
+
animation: none;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.ui.menu .item.grant-cart-menu > .icon.cart-incoming,
|
|
190
|
+
.ui.menu .item.grant-cart-menu > .icon.cart-outgoing {
|
|
191
|
+
display: none;
|
|
192
|
+
animation: none;
|
|
193
|
+
}
|
|
194
|
+
}
|