@lidofinance/lido-app-ui 1.7.0 → 1.9.0
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/dist/cjs/button/Button.cjs +11 -3
- package/dist/cjs/button/Button.cjs.map +1 -1
- package/dist/cjs/counter/Counter.module.css.cjs +1 -1
- package/dist/cjs/counter/CounterSlot.cjs +22 -0
- package/dist/cjs/counter/CounterSlot.cjs.map +1 -0
- package/dist/cjs/counter/CounterSlot.module.css.cjs +6 -0
- package/dist/cjs/counter/CounterSlot.module.css.cjs.map +1 -0
- package/dist/cjs/disclaimer/Disclaimer.cjs +33 -0
- package/dist/cjs/disclaimer/Disclaimer.cjs.map +1 -0
- package/dist/cjs/disclaimer/Disclaimer.module.css.cjs +6 -0
- package/dist/cjs/disclaimer/Disclaimer.module.css.cjs.map +1 -0
- package/dist/cjs/error-page/ErrorPage.cjs +64 -0
- package/dist/cjs/error-page/ErrorPage.cjs.map +1 -0
- package/dist/cjs/error-page/ErrorPage.module.css.cjs +6 -0
- package/dist/cjs/error-page/ErrorPage.module.css.cjs.map +1 -0
- package/dist/cjs/footer/Footer.cjs +30 -0
- package/dist/cjs/footer/Footer.cjs.map +1 -0
- package/dist/cjs/footer/Footer.module.css.cjs +6 -0
- package/dist/cjs/footer/Footer.module.css.cjs.map +1 -0
- package/dist/cjs/icon-button/IconButton.cjs +8 -3
- package/dist/cjs/icon-button/IconButton.cjs.map +1 -1
- package/dist/cjs/icons/TokenIcon.cjs +9 -1
- package/dist/cjs/icons/TokenIcon.cjs.map +1 -1
- package/dist/cjs/icons/components/base/IconEtherscan.cjs +25 -0
- package/dist/cjs/icons/components/base/IconEtherscan.cjs.map +1 -0
- package/dist/cjs/icons/components/base/IconNumber.cjs +28 -0
- package/dist/cjs/icons/components/base/IconNumber.cjs.map +1 -0
- package/dist/cjs/icons/components/base/iconsMap.cjs +5 -1
- package/dist/cjs/icons/components/base/iconsMap.cjs.map +1 -1
- package/dist/cjs/identicon/Identicon.cjs +35 -3
- package/dist/cjs/identicon/Identicon.cjs.map +1 -1
- package/dist/cjs/index.cjs +12 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.css +3 -3
- package/dist/cjs/notification/Notification.cjs +29 -36
- package/dist/cjs/notification/Notification.cjs.map +1 -1
- package/dist/cjs/notification/Notification.module.css.cjs +1 -1
- package/dist/cjs/rich-input/RichInput.cjs +28 -25
- package/dist/cjs/rich-input/RichInput.cjs.map +1 -1
- package/dist/cjs/rich-input/RichInput.module.css.cjs +1 -1
- package/dist/cjs/skeleton/Skeleton.cjs +40 -0
- package/dist/cjs/skeleton/Skeleton.cjs.map +1 -0
- package/dist/cjs/skeleton/Skeleton.module.css.cjs +6 -0
- package/dist/cjs/skeleton/Skeleton.module.css.cjs.map +1 -0
- package/dist/cjs/tag/Tag.cjs +12 -8
- package/dist/cjs/tag/Tag.cjs.map +1 -1
- package/dist/cjs/tag/Tag.module.css.cjs +1 -1
- package/dist/cjs/token-selector/TokenSelector.cjs +6 -6
- package/dist/cjs/token-selector/TokenSelector.cjs.map +1 -1
- package/dist/cjs/tooltip/Tooltip.cjs +85 -48
- package/dist/cjs/tooltip/Tooltip.cjs.map +1 -1
- package/dist/cjs/tooltip/Tooltip.module.css.cjs +1 -1
- package/dist/cjs/tx-status/TxStatus.cjs +2 -2
- package/dist/cjs/tx-status/TxStatus.cjs.map +1 -1
- package/dist/esm/button/Button.mjs +11 -3
- package/dist/esm/button/Button.mjs.map +1 -1
- package/dist/esm/counter/Counter.module.css.mjs +1 -1
- package/dist/esm/counter/CounterSlot.mjs +18 -0
- package/dist/esm/counter/CounterSlot.mjs.map +1 -0
- package/dist/esm/counter/CounterSlot.module.css.mjs +4 -0
- package/dist/esm/counter/CounterSlot.module.css.mjs.map +1 -0
- package/dist/esm/disclaimer/Disclaimer.mjs +29 -0
- package/dist/esm/disclaimer/Disclaimer.mjs.map +1 -0
- package/dist/esm/disclaimer/Disclaimer.module.css.mjs +4 -0
- package/dist/esm/disclaimer/Disclaimer.module.css.mjs.map +1 -0
- package/dist/esm/error-page/ErrorPage.mjs +60 -0
- package/dist/esm/error-page/ErrorPage.mjs.map +1 -0
- package/dist/esm/error-page/ErrorPage.module.css.mjs +4 -0
- package/dist/esm/error-page/ErrorPage.module.css.mjs.map +1 -0
- package/dist/esm/footer/Footer.mjs +26 -0
- package/dist/esm/footer/Footer.mjs.map +1 -0
- package/dist/esm/footer/Footer.module.css.mjs +4 -0
- package/dist/esm/footer/Footer.module.css.mjs.map +1 -0
- package/dist/esm/icon-button/IconButton.mjs +9 -4
- package/dist/esm/icon-button/IconButton.mjs.map +1 -1
- package/dist/esm/icons/TokenIcon.mjs +9 -1
- package/dist/esm/icons/TokenIcon.mjs.map +1 -1
- package/dist/esm/icons/components/base/IconEtherscan.mjs +21 -0
- package/dist/esm/icons/components/base/IconEtherscan.mjs.map +1 -0
- package/dist/esm/icons/components/base/IconNumber.mjs +24 -0
- package/dist/esm/icons/components/base/IconNumber.mjs.map +1 -0
- package/dist/esm/icons/components/base/iconsMap.mjs +5 -1
- package/dist/esm/icons/components/base/iconsMap.mjs.map +1 -1
- package/dist/esm/identicon/Identicon.mjs +15 -2
- package/dist/esm/identicon/Identicon.mjs.map +1 -1
- package/dist/esm/index.css +3 -3
- package/dist/esm/index.mjs +7 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/notification/Notification.mjs +31 -37
- package/dist/esm/notification/Notification.mjs.map +1 -1
- package/dist/esm/notification/Notification.module.css.mjs +1 -1
- package/dist/esm/rich-input/RichInput.mjs +28 -25
- package/dist/esm/rich-input/RichInput.mjs.map +1 -1
- package/dist/esm/rich-input/RichInput.module.css.mjs +1 -1
- package/dist/esm/skeleton/Skeleton.mjs +36 -0
- package/dist/esm/skeleton/Skeleton.mjs.map +1 -0
- package/dist/esm/skeleton/Skeleton.module.css.mjs +4 -0
- package/dist/esm/skeleton/Skeleton.module.css.mjs.map +1 -0
- package/dist/esm/tag/Tag.mjs +13 -9
- package/dist/esm/tag/Tag.mjs.map +1 -1
- package/dist/esm/tag/Tag.module.css.mjs +1 -1
- package/dist/esm/token-selector/TokenSelector.mjs +6 -6
- package/dist/esm/token-selector/TokenSelector.mjs.map +1 -1
- package/dist/esm/tooltip/Tooltip.mjs +87 -50
- package/dist/esm/tooltip/Tooltip.mjs.map +1 -1
- package/dist/esm/tooltip/Tooltip.module.css.mjs +1 -1
- package/dist/esm/tx-status/TxStatus.mjs +2 -2
- package/dist/esm/tx-status/TxStatus.mjs.map +1 -1
- package/dist/index.css +3 -3
- package/dist/styles/typography-mixins.css +8 -0
- package/dist/types/button/Button.d.ts +14 -2
- package/dist/types/button/Button.d.ts.map +1 -1
- package/dist/types/counter/CounterSlot.d.ts +8 -0
- package/dist/types/counter/CounterSlot.d.ts.map +1 -0
- package/dist/types/disclaimer/Disclaimer.d.ts +9 -0
- package/dist/types/disclaimer/Disclaimer.d.ts.map +1 -0
- package/dist/types/disclaimer/index.d.ts +3 -0
- package/dist/types/disclaimer/index.d.ts.map +1 -0
- package/dist/types/error-page/ErrorPage.d.ts +20 -0
- package/dist/types/error-page/ErrorPage.d.ts.map +1 -0
- package/dist/types/error-page/index.d.ts +3 -0
- package/dist/types/error-page/index.d.ts.map +1 -0
- package/dist/types/footer/Footer.d.ts +7 -0
- package/dist/types/footer/Footer.d.ts.map +1 -0
- package/dist/types/footer/index.d.ts +3 -0
- package/dist/types/footer/index.d.ts.map +1 -0
- package/dist/types/icon-button/IconButton.d.ts +4 -1
- package/dist/types/icon-button/IconButton.d.ts.map +1 -1
- package/dist/types/icons/TokenIcon.d.ts +1 -1
- package/dist/types/icons/TokenIcon.d.ts.map +1 -1
- package/dist/types/icons/components/base/IconEtherscan.d.ts +3 -0
- package/dist/types/icons/components/base/IconEtherscan.d.ts.map +1 -0
- package/dist/types/icons/components/base/IconNumber.d.ts +3 -0
- package/dist/types/icons/components/base/IconNumber.d.ts.map +1 -0
- package/dist/types/icons/components/base/iconsMap.d.ts +2 -0
- package/dist/types/icons/components/base/iconsMap.d.ts.map +1 -1
- package/dist/types/icons/components/base/index.d.ts +2 -0
- package/dist/types/icons/components/base/index.d.ts.map +1 -1
- package/dist/types/identicon/Identicon.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/notification/Notification.d.ts +5 -11
- package/dist/types/notification/Notification.d.ts.map +1 -1
- package/dist/types/notification/index.d.ts +2 -2
- package/dist/types/notification/index.d.ts.map +1 -1
- package/dist/types/rich-input/RichInput.d.ts +4 -2
- package/dist/types/rich-input/RichInput.d.ts.map +1 -1
- package/dist/types/skeleton/Skeleton.d.ts +9 -0
- package/dist/types/skeleton/Skeleton.d.ts.map +1 -0
- package/dist/types/skeleton/index.d.ts +2 -0
- package/dist/types/skeleton/index.d.ts.map +1 -0
- package/dist/types/tag/Tag.d.ts +4 -1
- package/dist/types/tag/Tag.d.ts.map +1 -1
- package/dist/types/tooltip/Tooltip.d.ts +1 -1
- package/dist/types/tooltip/Tooltip.d.ts.map +1 -1
- package/dist/types/tx-status/TxStatus.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -10,15 +10,19 @@ const jsxRuntime = require('react/jsx-runtime');
|
|
|
10
10
|
|
|
11
11
|
// Minimal distance between the tooltip and the viewport edge.
|
|
12
12
|
const VIEWPORT_MARGIN = 16;
|
|
13
|
-
//
|
|
14
|
-
const
|
|
13
|
+
// Visual gap between the anchor and the content.
|
|
14
|
+
const MAIN_GAP = 8;
|
|
15
|
+
const CORNER_GAP = 2;
|
|
16
|
+
// Extra buffer used only to decide whether a position still "fits" — bigger
|
|
17
|
+
// than the visual gap so a flip triggers before the bubble visually crowds the edge.
|
|
18
|
+
const FIT_BUFFER = 15;
|
|
15
19
|
const clampValue = (value, min, max) => Math.min(Math.max(value, min), Math.max(max, min));
|
|
16
20
|
const getMaxWidth = width => `min(${width}px, calc(100vw - ${VIEWPORT_MARGIN * 2}px))`;
|
|
17
21
|
|
|
18
|
-
// Measures the anchor and the
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
const getAdjustment = (position, anchor,
|
|
22
|
+
// Measures the anchor and the content, then picks a position that keeps the
|
|
23
|
+
// bubble inside the viewport — flipping sides when there isn't room, sliding
|
|
24
|
+
// along the cross axis otherwise — and resolves it to fixed-position coordinates.
|
|
25
|
+
const getAdjustment = (position, anchor, contentWidth, contentHeight) => {
|
|
22
26
|
const viewportWidth = document.documentElement.clientWidth;
|
|
23
27
|
const viewportHeight = document.documentElement.clientHeight;
|
|
24
28
|
const spaceTop = anchor.top - VIEWPORT_MARGIN;
|
|
@@ -26,12 +30,12 @@ const getAdjustment = (position, anchor, content) => {
|
|
|
26
30
|
const spaceLeft = anchor.left - VIEWPORT_MARGIN;
|
|
27
31
|
const spaceRight = viewportWidth - anchor.right - VIEWPORT_MARGIN;
|
|
28
32
|
let [main, corner] = position.split('-');
|
|
29
|
-
const
|
|
33
|
+
const fitGap = corner ? 0 : FIT_BUFFER;
|
|
30
34
|
|
|
31
35
|
// Side positions: flip to the other side, or fall back to a vertical
|
|
32
36
|
// position when the content doesn't fit horizontally on either side.
|
|
33
37
|
if (main === 'left' || main === 'right') {
|
|
34
|
-
const needed =
|
|
38
|
+
const needed = contentWidth + fitGap;
|
|
35
39
|
if (needed > spaceLeft && needed > spaceRight) {
|
|
36
40
|
main = spaceBottom >= spaceTop ? 'bottom' : 'top';
|
|
37
41
|
} else if (main === 'right' && needed > spaceRight) {
|
|
@@ -45,7 +49,7 @@ const getAdjustment = (position, anchor, content) => {
|
|
|
45
49
|
if (main === 'top' || main === 'bottom') {
|
|
46
50
|
const space = main === 'top' ? spaceTop : spaceBottom;
|
|
47
51
|
const opposite = main === 'top' ? spaceBottom : spaceTop;
|
|
48
|
-
if (
|
|
52
|
+
if (contentHeight + fitGap > space && opposite > space) {
|
|
49
53
|
main = main === 'top' ? 'bottom' : 'top';
|
|
50
54
|
}
|
|
51
55
|
}
|
|
@@ -55,25 +59,33 @@ const getAdjustment = (position, anchor, content) => {
|
|
|
55
59
|
if (corner) {
|
|
56
60
|
const space = corner === 'left' ? spaceLeft : spaceRight;
|
|
57
61
|
const opposite = corner === 'left' ? spaceRight : spaceLeft;
|
|
58
|
-
if (
|
|
62
|
+
if (contentWidth > space && opposite > space) {
|
|
59
63
|
corner = corner === 'left' ? 'right' : 'left';
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
|
-
|
|
63
|
-
let
|
|
66
|
+
const resolvedPosition = corner ? `${main}-${corner}` : main;
|
|
67
|
+
let left;
|
|
68
|
+
let top;
|
|
64
69
|
if (main === 'left' || main === 'right') {
|
|
65
|
-
const idealTop = anchor.top + anchor.height / 2 -
|
|
66
|
-
|
|
70
|
+
const idealTop = anchor.top + anchor.height / 2 - contentHeight / 2;
|
|
71
|
+
top = clampValue(idealTop, VIEWPORT_MARGIN, viewportHeight - VIEWPORT_MARGIN - contentHeight);
|
|
72
|
+
left = main === 'right' ? anchor.right + MAIN_GAP : anchor.left - MAIN_GAP - contentWidth;
|
|
67
73
|
} else {
|
|
68
|
-
const idealLeft = !corner ? anchor.left + anchor.width / 2 -
|
|
69
|
-
|
|
74
|
+
const idealLeft = !corner ? anchor.left + anchor.width / 2 - contentWidth / 2 : corner === 'left' ? anchor.left - contentWidth - CORNER_GAP : anchor.right + CORNER_GAP;
|
|
75
|
+
left = clampValue(idealLeft, VIEWPORT_MARGIN, viewportWidth - VIEWPORT_MARGIN - contentWidth);
|
|
76
|
+
const gap = corner ? CORNER_GAP : MAIN_GAP;
|
|
77
|
+
top = main === 'top' ? anchor.top - gap - contentHeight : anchor.bottom + gap;
|
|
70
78
|
}
|
|
71
79
|
return {
|
|
72
|
-
position:
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
position: resolvedPosition,
|
|
81
|
+
left,
|
|
82
|
+
top
|
|
75
83
|
};
|
|
76
84
|
};
|
|
85
|
+
|
|
86
|
+
// Rendered into document.body so a clipping ancestor (overflow: clip/hidden, or a
|
|
87
|
+
// transform/filter/backdrop-filter that would otherwise capture position: fixed)
|
|
88
|
+
// can't cut the bubble off — it sits outside that ancestor's DOM subtree entirely.
|
|
77
89
|
const Tooltip = _ref => {
|
|
78
90
|
let {
|
|
79
91
|
content,
|
|
@@ -82,62 +94,87 @@ const Tooltip = _ref => {
|
|
|
82
94
|
className,
|
|
83
95
|
children,
|
|
84
96
|
onMouseEnter,
|
|
97
|
+
onMouseLeave,
|
|
85
98
|
onFocus,
|
|
99
|
+
onBlur,
|
|
86
100
|
dataTestId,
|
|
87
101
|
...rest
|
|
88
102
|
} = _ref;
|
|
89
|
-
const
|
|
103
|
+
const anchorRef = react.useRef(null);
|
|
90
104
|
const contentRef = react.useRef(null);
|
|
91
|
-
const [
|
|
105
|
+
const [open, setOpen] = react.useState(false);
|
|
106
|
+
const tooltipId = react.useId();
|
|
92
107
|
const updatePosition = react.useCallback(() => {
|
|
93
|
-
const
|
|
108
|
+
const anchor = anchorRef.current;
|
|
94
109
|
const contentEl = contentRef.current;
|
|
95
|
-
if (!
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
110
|
+
if (!anchor || !contentEl) return;
|
|
111
|
+
const {
|
|
112
|
+
left,
|
|
113
|
+
top,
|
|
114
|
+
position: resolved
|
|
115
|
+
} = getAdjustment(position, anchor.getBoundingClientRect(), contentEl.offsetWidth, contentEl.offsetHeight);
|
|
116
|
+
contentEl.style.left = `${left}px`;
|
|
117
|
+
contentEl.style.top = `${top}px`;
|
|
118
|
+
contentEl.dataset.position = resolved;
|
|
119
|
+
contentEl.dataset.placed = 'true';
|
|
105
120
|
}, [position]);
|
|
121
|
+
react.useLayoutEffect(() => {
|
|
122
|
+
if (!open) return;
|
|
123
|
+
updatePosition();
|
|
124
|
+
window.addEventListener('scroll', updatePosition, true);
|
|
125
|
+
window.addEventListener('resize', updatePosition);
|
|
126
|
+
return () => {
|
|
127
|
+
window.removeEventListener('scroll', updatePosition, true);
|
|
128
|
+
window.removeEventListener('resize', updatePosition);
|
|
129
|
+
};
|
|
130
|
+
}, [open, updatePosition]);
|
|
131
|
+
|
|
132
|
+
// A hover-opened tooltip has no focus to catch the key, so Escape is heard document-wide.
|
|
106
133
|
react.useEffect(() => {
|
|
107
|
-
|
|
108
|
-
|
|
134
|
+
if (!open) return;
|
|
135
|
+
const handleKeyDown = event => {
|
|
136
|
+
if (event.key === 'Escape') setOpen(false);
|
|
109
137
|
};
|
|
110
|
-
|
|
111
|
-
return () =>
|
|
112
|
-
}, [
|
|
138
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
139
|
+
return () => document.removeEventListener('keydown', handleKeyDown);
|
|
140
|
+
}, [open]);
|
|
113
141
|
const handleMouseEnter = event => {
|
|
114
|
-
updatePosition();
|
|
115
142
|
onMouseEnter?.(event);
|
|
143
|
+
setOpen(true);
|
|
144
|
+
};
|
|
145
|
+
const handleMouseLeave = event => {
|
|
146
|
+
onMouseLeave?.(event);
|
|
147
|
+
setOpen(false);
|
|
116
148
|
};
|
|
117
149
|
const handleFocus = event => {
|
|
118
|
-
updatePosition();
|
|
119
150
|
onFocus?.(event);
|
|
151
|
+
setOpen(true);
|
|
152
|
+
};
|
|
153
|
+
const handleBlur = event => {
|
|
154
|
+
onBlur?.(event);
|
|
155
|
+
setOpen(false);
|
|
120
156
|
};
|
|
121
|
-
const effectivePosition = adjustment?.position ?? position;
|
|
122
157
|
return /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
123
|
-
ref:
|
|
158
|
+
ref: anchorRef,
|
|
124
159
|
className: cn(Tooltip_module.wrapper, className),
|
|
160
|
+
"aria-describedby": open ? tooltipId : undefined,
|
|
125
161
|
onMouseEnter: handleMouseEnter,
|
|
162
|
+
onMouseLeave: handleMouseLeave,
|
|
126
163
|
onFocus: handleFocus,
|
|
164
|
+
onBlur: handleBlur,
|
|
127
165
|
"data-testid": dataTestId?.root,
|
|
128
166
|
...rest,
|
|
129
|
-
children: [children, /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
167
|
+
children: [children, open ? /*#__PURE__*/reactDom.createPortal(/*#__PURE__*/jsxRuntime.jsx("span", {
|
|
130
168
|
ref: contentRef,
|
|
131
|
-
|
|
169
|
+
id: tooltipId,
|
|
170
|
+
role: "tooltip",
|
|
171
|
+
className: Tooltip_module.content,
|
|
132
172
|
style: {
|
|
133
|
-
'--local-tooltip-width': getMaxWidth(width)
|
|
134
|
-
'--local-tooltip-shift-x': `${adjustment?.shiftX ?? 0}px`,
|
|
135
|
-
'--local-tooltip-shift-y': `${adjustment?.shiftY ?? 0}px`
|
|
173
|
+
'--local-tooltip-width': getMaxWidth(width)
|
|
136
174
|
},
|
|
137
|
-
role: "tooltip",
|
|
138
175
|
"data-testid": dataTestId?.content,
|
|
139
176
|
children: content
|
|
140
|
-
})]
|
|
177
|
+
}), document.body) : null]
|
|
141
178
|
});
|
|
142
179
|
};
|
|
143
180
|
Tooltip.displayName = 'Tooltip';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.cjs","sources":["../../../src/tooltip/Tooltip.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type CSSProperties,\n type FocusEvent,\n type MouseEvent,\n type ReactNode,\n} from 'react'\nimport { flushSync } from 'react-dom'\n\nimport cn from 'classnames'\n\nimport styles from './Tooltip.module.css'\n\nexport type TooltipPosition =\n | 'top'\n | 'right'\n | 'bottom'\n | 'left'\n | 'top-left'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-right'\n\nexport type TooltipDataTestId = {\n root?: string\n content?: string\n}\n\nexport type TooltipProps = Omit<ComponentPropsWithoutRef<'span'>, 'content'> & {\n content: ReactNode\n position?: TooltipPosition\n width?: number\n dataTestId?: TooltipDataTestId\n}\n\n// Minimal distance between the tooltip and the viewport edge.\nconst VIEWPORT_MARGIN = 16\n// Distance between the anchor and the content for main (non-corner) positions.\nconst POSITION_GAP = 15\n\ntype TooltipAdjustment = {\n position: TooltipPosition\n shiftX: number\n shiftY: number\n}\n\nconst clampValue = (value: number, min: number, max: number) =>\n Math.min(Math.max(value, min), Math.max(max, min))\n\nconst getMaxWidth = (width: number) =>\n `min(${width}px, calc(100vw - ${VIEWPORT_MARGIN * 2}px))`\n\n// Measures the anchor and the (hidden but laid-out) content, then picks a\n// position/shift that keeps the bubble inside the viewport — flipping sides\n// when there isn't room, sliding along the cross axis otherwise.\nconst getAdjustment = (\n position: TooltipPosition,\n anchor: DOMRect,\n content: DOMRect,\n): TooltipAdjustment => {\n const viewportWidth = document.documentElement.clientWidth\n const viewportHeight = document.documentElement.clientHeight\n\n const spaceTop = anchor.top - VIEWPORT_MARGIN\n const spaceBottom = viewportHeight - anchor.bottom - VIEWPORT_MARGIN\n const spaceLeft = anchor.left - VIEWPORT_MARGIN\n const spaceRight = viewportWidth - anchor.right - VIEWPORT_MARGIN\n\n let [main, corner] = position.split('-')\n const gap = corner ? 0 : POSITION_GAP\n\n // Side positions: flip to the other side, or fall back to a vertical\n // position when the content doesn't fit horizontally on either side.\n if (main === 'left' || main === 'right') {\n const needed = content.width + gap\n if (needed > spaceLeft && needed > spaceRight) {\n main = spaceBottom >= spaceTop ? 'bottom' : 'top'\n } else if (main === 'right' && needed > spaceRight) {\n main = 'left'\n } else if (main === 'left' && needed > spaceLeft) {\n main = 'right'\n }\n }\n\n // Vertical positions: flip when the content doesn't fit and there is more room on the other side.\n if (main === 'top' || main === 'bottom') {\n const space = main === 'top' ? spaceTop : spaceBottom\n const opposite = main === 'top' ? spaceBottom : spaceTop\n if (content.height + gap > space && opposite > space) {\n main = main === 'top' ? 'bottom' : 'top'\n }\n }\n\n // A corner's cut-off edge has to meet the anchor, and sliding breaks that\n // join — so mirror to the other side first and only slide as a last resort.\n if (corner) {\n const space = corner === 'left' ? spaceLeft : spaceRight\n const opposite = corner === 'left' ? spaceRight : spaceLeft\n if (content.width > space && opposite > space) {\n corner = corner === 'left' ? 'right' : 'left'\n }\n }\n\n let shiftX = 0\n let shiftY = 0\n if (main === 'left' || main === 'right') {\n const idealTop = anchor.top + anchor.height / 2 - content.height / 2\n shiftY =\n clampValue(\n idealTop,\n VIEWPORT_MARGIN,\n viewportHeight - VIEWPORT_MARGIN - content.height,\n ) - idealTop\n } else {\n const idealLeft = !corner\n ? anchor.left + anchor.width / 2 - content.width / 2\n : corner === 'left'\n ? anchor.left - content.width\n : anchor.right\n shiftX =\n clampValue(\n idealLeft,\n VIEWPORT_MARGIN,\n viewportWidth - VIEWPORT_MARGIN - content.width,\n ) - idealLeft\n }\n\n return {\n position: (corner ? `${main}-${corner}` : main) as TooltipPosition,\n shiftX,\n shiftY,\n }\n}\n\nexport const Tooltip = ({\n content,\n position = 'top',\n width = 320,\n className,\n children,\n onMouseEnter,\n onFocus,\n dataTestId,\n ...rest\n}: TooltipProps) => {\n const rootRef = useRef<HTMLSpanElement>(null)\n const contentRef = useRef<HTMLSpanElement>(null)\n const [adjustment, setAdjustment] = useState<TooltipAdjustment | null>(null)\n\n const updatePosition = useCallback(() => {\n const root = rootRef.current\n const contentEl = contentRef.current\n if (!root || !contentEl) return\n\n // React treats mouseenter as a continuous-priority event and would defer\n // the update past the next paint, flashing the tooltip at the old position.\n flushSync(() => {\n setAdjustment(\n getAdjustment(\n position,\n root.getBoundingClientRect(),\n contentEl.getBoundingClientRect(),\n ),\n )\n })\n }, [position])\n\n useEffect(() => {\n setAdjustment(null)\n }, [position])\n\n useEffect(() => {\n const handleResize = () => {\n if (rootRef.current?.matches(':hover')) updatePosition()\n }\n\n window.addEventListener('resize', handleResize)\n return () => window.removeEventListener('resize', handleResize)\n }, [updatePosition])\n\n const handleMouseEnter = (event: MouseEvent<HTMLSpanElement>) => {\n updatePosition()\n onMouseEnter?.(event)\n }\n\n const handleFocus = (event: FocusEvent<HTMLSpanElement>) => {\n updatePosition()\n onFocus?.(event)\n }\n\n const effectivePosition = adjustment?.position ?? position\n\n return (\n <span\n ref={rootRef}\n className={cn(styles.wrapper, className)}\n onMouseEnter={handleMouseEnter}\n onFocus={handleFocus}\n data-testid={dataTestId?.root}\n {...rest}\n >\n {children}\n <span\n ref={contentRef}\n className={cn(styles.content, styles[`position-${effectivePosition}`])}\n style={\n {\n '--local-tooltip-width': getMaxWidth(width),\n '--local-tooltip-shift-x': `${adjustment?.shiftX ?? 0}px`,\n '--local-tooltip-shift-y': `${adjustment?.shiftY ?? 0}px`,\n } as CSSProperties\n }\n role='tooltip'\n data-testid={dataTestId?.content}\n >\n {content}\n </span>\n </span>\n )\n}\n\nTooltip.displayName = 'Tooltip'\n"],"names":["VIEWPORT_MARGIN","POSITION_GAP","clampValue","value","min","max","Math","getMaxWidth","width","getAdjustment","position","anchor","content","viewportWidth","document","documentElement","clientWidth","viewportHeight","clientHeight","spaceTop","top","spaceBottom","bottom","spaceLeft","left","spaceRight","right","main","corner","split","gap","needed","space","opposite","height","shiftX","shiftY","idealTop","idealLeft","Tooltip","_ref","className","children","onMouseEnter","onFocus","dataTestId","rest","rootRef","useRef","contentRef","adjustment","setAdjustment","useState","updatePosition","useCallback","root","current","contentEl","flushSync","getBoundingClientRect","useEffect","handleResize","matches","window","addEventListener","removeEventListener","handleMouseEnter","event","handleFocus","effectivePosition","_jsxs","ref","cn","styles","wrapper","_jsx","style","role","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Tooltip.cjs","sources":["../../../src/tooltip/Tooltip.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type CSSProperties,\n type FocusEvent,\n type MouseEvent,\n type ReactNode,\n} from 'react'\nimport { createPortal } from 'react-dom'\n\nimport cn from 'classnames'\n\nimport styles from './Tooltip.module.css'\n\nexport type TooltipPosition =\n | 'top'\n | 'right'\n | 'bottom'\n | 'left'\n | 'top-left'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-right'\n\nexport type TooltipDataTestId = {\n root?: string\n content?: string\n}\n\nexport type TooltipProps = Omit<ComponentPropsWithoutRef<'span'>, 'content'> & {\n content: ReactNode\n position?: TooltipPosition\n width?: number\n dataTestId?: TooltipDataTestId\n}\n\n// Minimal distance between the tooltip and the viewport edge.\nconst VIEWPORT_MARGIN = 16\n// Visual gap between the anchor and the content.\nconst MAIN_GAP = 8\nconst CORNER_GAP = 2\n// Extra buffer used only to decide whether a position still \"fits\" — bigger\n// than the visual gap so a flip triggers before the bubble visually crowds the edge.\nconst FIT_BUFFER = 15\n\ntype Adjustment = {\n position: TooltipPosition\n left: number\n top: number\n}\n\nconst clampValue = (value: number, min: number, max: number) =>\n Math.min(Math.max(value, min), Math.max(max, min))\n\nconst getMaxWidth = (width: number) =>\n `min(${width}px, calc(100vw - ${VIEWPORT_MARGIN * 2}px))`\n\n// Measures the anchor and the content, then picks a position that keeps the\n// bubble inside the viewport — flipping sides when there isn't room, sliding\n// along the cross axis otherwise — and resolves it to fixed-position coordinates.\nconst getAdjustment = (\n position: TooltipPosition,\n anchor: DOMRect,\n contentWidth: number,\n contentHeight: number,\n): Adjustment => {\n const viewportWidth = document.documentElement.clientWidth\n const viewportHeight = document.documentElement.clientHeight\n\n const spaceTop = anchor.top - VIEWPORT_MARGIN\n const spaceBottom = viewportHeight - anchor.bottom - VIEWPORT_MARGIN\n const spaceLeft = anchor.left - VIEWPORT_MARGIN\n const spaceRight = viewportWidth - anchor.right - VIEWPORT_MARGIN\n\n let [main, corner] = position.split('-') as [string, string | undefined]\n const fitGap = corner ? 0 : FIT_BUFFER\n\n // Side positions: flip to the other side, or fall back to a vertical\n // position when the content doesn't fit horizontally on either side.\n if (main === 'left' || main === 'right') {\n const needed = contentWidth + fitGap\n if (needed > spaceLeft && needed > spaceRight) {\n main = spaceBottom >= spaceTop ? 'bottom' : 'top'\n } else if (main === 'right' && needed > spaceRight) {\n main = 'left'\n } else if (main === 'left' && needed > spaceLeft) {\n main = 'right'\n }\n }\n\n // Vertical positions: flip when the content doesn't fit and there is more room on the other side.\n if (main === 'top' || main === 'bottom') {\n const space = main === 'top' ? spaceTop : spaceBottom\n const opposite = main === 'top' ? spaceBottom : spaceTop\n if (contentHeight + fitGap > space && opposite > space) {\n main = main === 'top' ? 'bottom' : 'top'\n }\n }\n\n // A corner's cut-off edge has to meet the anchor, and sliding breaks that\n // join — so mirror to the other side first and only slide as a last resort.\n if (corner) {\n const space = corner === 'left' ? spaceLeft : spaceRight\n const opposite = corner === 'left' ? spaceRight : spaceLeft\n if (contentWidth > space && opposite > space) {\n corner = corner === 'left' ? 'right' : 'left'\n }\n }\n\n const resolvedPosition = (\n corner ? `${main}-${corner}` : main\n ) as TooltipPosition\n\n let left: number\n let top: number\n\n if (main === 'left' || main === 'right') {\n const idealTop = anchor.top + anchor.height / 2 - contentHeight / 2\n top = clampValue(\n idealTop,\n VIEWPORT_MARGIN,\n viewportHeight - VIEWPORT_MARGIN - contentHeight,\n )\n left =\n main === 'right'\n ? anchor.right + MAIN_GAP\n : anchor.left - MAIN_GAP - contentWidth\n } else {\n const idealLeft = !corner\n ? anchor.left + anchor.width / 2 - contentWidth / 2\n : corner === 'left'\n ? anchor.left - contentWidth - CORNER_GAP\n : anchor.right + CORNER_GAP\n left = clampValue(\n idealLeft,\n VIEWPORT_MARGIN,\n viewportWidth - VIEWPORT_MARGIN - contentWidth,\n )\n const gap = corner ? CORNER_GAP : MAIN_GAP\n top =\n main === 'top' ? anchor.top - gap - contentHeight : anchor.bottom + gap\n }\n\n return { position: resolvedPosition, left, top }\n}\n\n// Rendered into document.body so a clipping ancestor (overflow: clip/hidden, or a\n// transform/filter/backdrop-filter that would otherwise capture position: fixed)\n// can't cut the bubble off — it sits outside that ancestor's DOM subtree entirely.\nexport const Tooltip = ({\n content,\n position = 'top',\n width = 320,\n className,\n children,\n onMouseEnter,\n onMouseLeave,\n onFocus,\n onBlur,\n dataTestId,\n ...rest\n}: TooltipProps) => {\n const anchorRef = useRef<HTMLSpanElement>(null)\n const contentRef = useRef<HTMLSpanElement>(null)\n const [open, setOpen] = useState(false)\n const tooltipId = useId()\n\n const updatePosition = useCallback(() => {\n const anchor = anchorRef.current\n const contentEl = contentRef.current\n if (!anchor || !contentEl) return\n const {\n left,\n top,\n position: resolved,\n } = getAdjustment(\n position,\n anchor.getBoundingClientRect(),\n contentEl.offsetWidth,\n contentEl.offsetHeight,\n )\n contentEl.style.left = `${left}px`\n contentEl.style.top = `${top}px`\n contentEl.dataset.position = resolved\n contentEl.dataset.placed = 'true'\n }, [position])\n\n useLayoutEffect(() => {\n if (!open) return\n updatePosition()\n window.addEventListener('scroll', updatePosition, true)\n window.addEventListener('resize', updatePosition)\n return () => {\n window.removeEventListener('scroll', updatePosition, true)\n window.removeEventListener('resize', updatePosition)\n }\n }, [open, updatePosition])\n\n // A hover-opened tooltip has no focus to catch the key, so Escape is heard document-wide.\n useEffect(() => {\n if (!open) return\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') setOpen(false)\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [open])\n\n const handleMouseEnter = (event: MouseEvent<HTMLSpanElement>) => {\n onMouseEnter?.(event)\n setOpen(true)\n }\n\n const handleMouseLeave = (event: MouseEvent<HTMLSpanElement>) => {\n onMouseLeave?.(event)\n setOpen(false)\n }\n\n const handleFocus = (event: FocusEvent<HTMLSpanElement>) => {\n onFocus?.(event)\n setOpen(true)\n }\n\n const handleBlur = (event: FocusEvent<HTMLSpanElement>) => {\n onBlur?.(event)\n setOpen(false)\n }\n\n return (\n <span\n ref={anchorRef}\n className={cn(styles.wrapper, className)}\n aria-describedby={open ? tooltipId : undefined}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onFocus={handleFocus}\n onBlur={handleBlur}\n data-testid={dataTestId?.root}\n {...rest}\n >\n {children}\n {open\n ? createPortal(\n <span\n ref={contentRef}\n id={tooltipId}\n role='tooltip'\n className={styles.content}\n style={\n { '--local-tooltip-width': getMaxWidth(width) } as CSSProperties\n }\n data-testid={dataTestId?.content}\n >\n {content}\n </span>,\n document.body,\n )\n : null}\n </span>\n )\n}\n\nTooltip.displayName = 'Tooltip'\n"],"names":["VIEWPORT_MARGIN","MAIN_GAP","CORNER_GAP","FIT_BUFFER","clampValue","value","min","max","Math","getMaxWidth","width","getAdjustment","position","anchor","contentWidth","contentHeight","viewportWidth","document","documentElement","clientWidth","viewportHeight","clientHeight","spaceTop","top","spaceBottom","bottom","spaceLeft","left","spaceRight","right","main","corner","split","fitGap","needed","space","opposite","resolvedPosition","idealTop","height","idealLeft","gap","Tooltip","_ref","content","className","children","onMouseEnter","onMouseLeave","onFocus","onBlur","dataTestId","rest","anchorRef","useRef","contentRef","open","setOpen","useState","tooltipId","useId","updatePosition","useCallback","current","contentEl","resolved","getBoundingClientRect","offsetWidth","offsetHeight","style","dataset","placed","useLayoutEffect","window","addEventListener","removeEventListener","useEffect","handleKeyDown","event","key","handleMouseEnter","handleMouseLeave","handleFocus","handleBlur","_jsxs","ref","cn","styles","wrapper","undefined","root","createPortal","_jsx","id","role","body","displayName"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const styles = {"wrapper":"Tooltip-module_wrapper__-h7ZD","content":"Tooltip-module_content__Yqdc-"
|
|
3
|
+
const styles = {"wrapper":"Tooltip-module_wrapper__-h7ZD","content":"Tooltip-module_content__Yqdc-"};
|
|
4
4
|
|
|
5
5
|
module.exports = styles;
|
|
6
6
|
//# sourceMappingURL=Tooltip.module.css.cjs.map
|
|
@@ -5,13 +5,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
5
5
|
const cn = require('classnames');
|
|
6
6
|
const TxStatus_module = require('./TxStatus.module.css.cjs');
|
|
7
7
|
const jsxRuntime = require('react/jsx-runtime');
|
|
8
|
-
const IconSpinner = require('../icons/components/base/IconSpinner.cjs');
|
|
9
8
|
const IconExclamation = require('../icons/components/base/IconExclamation.cjs');
|
|
9
|
+
const IconLoaderCircle = require('../icons/components/base/IconLoaderCircle.cjs');
|
|
10
10
|
const IconCheck = require('../icons/components/base/IconCheck.cjs');
|
|
11
11
|
const IconCross = require('../icons/components/base/IconCross.cjs');
|
|
12
12
|
|
|
13
13
|
const graphicByStatus = {
|
|
14
|
-
loading: /*#__PURE__*/jsxRuntime.jsx(
|
|
14
|
+
loading: /*#__PURE__*/jsxRuntime.jsx(IconLoaderCircle.IconLoaderCircle, {
|
|
15
15
|
className: TxStatus_module.spinner
|
|
16
16
|
}),
|
|
17
17
|
success: /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TxStatus.cjs","sources":["../../../src/tx-status/TxStatus.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ReactNode } from 'react'\n\nimport {
|
|
1
|
+
{"version":3,"file":"TxStatus.cjs","sources":["../../../src/tx-status/TxStatus.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ReactNode } from 'react'\n\nimport {\n IconCheck,\n IconCross,\n IconExclamation,\n IconLoaderCircle,\n} from '../icons'\nimport cn from 'classnames'\n\nimport styles from './TxStatus.module.css'\n\nexport type TxStatusVariant = 'loading' | 'success' | 'error' | 'warning'\n\nexport type TxStatusDataTestId = {\n root?: string\n title?: string\n amount?: string\n message?: string\n footer?: string\n}\n\nexport type TxStatusProps = Omit<ComponentPropsWithoutRef<'div'>, 'title'> & {\n status: TxStatusVariant\n title: ReactNode\n amount?: ReactNode\n message?: ReactNode\n footer?: ReactNode\n dataTestId?: TxStatusDataTestId\n}\n\nconst graphicByStatus: Record<TxStatusVariant, ReactNode> = {\n loading: <IconLoaderCircle className={styles.spinner} />,\n success: (\n <span className={cn(styles.circle, styles.circleSuccess)}>\n <IconCheck className={styles.circleIcon} />\n </span>\n ),\n error: (\n <span className={cn(styles.circle, styles.circleError)}>\n <IconCross className={styles.circleIcon} />\n </span>\n ),\n warning: (\n <span className={cn(styles.circle, styles.circleWarning)}>\n <IconExclamation className={styles.circleIcon} />\n </span>\n ),\n}\n\nexport const TxStatus = ({\n status,\n title,\n amount,\n message,\n footer,\n className,\n dataTestId,\n ...rest\n}: TxStatusProps) => (\n <div\n className={cn(styles.root, className)}\n data-testid={dataTestId?.root}\n {...rest}\n >\n <div className={styles.graphicGroup}>\n <span className={styles.graphic}>{graphicByStatus[status]}</span>\n <div className={styles.textGroup}>\n <span className={styles.title} data-testid={dataTestId?.title}>\n {title}\n </span>\n {amount ? (\n <div className={styles.amount} data-testid={dataTestId?.amount}>\n {amount}\n </div>\n ) : null}\n {message ? (\n <div className={styles.message} data-testid={dataTestId?.message}>\n {message}\n </div>\n ) : null}\n </div>\n </div>\n {footer ? (\n <div className={styles.footer} data-testid={dataTestId?.footer}>\n {footer}\n </div>\n ) : null}\n </div>\n)\n"],"names":["graphicByStatus","loading","_jsx","IconLoaderCircle","className","styles","spinner","success","cn","circle","circleSuccess","children","IconCheck","circleIcon","error","circleError","IconCross","warning","circleWarning","IconExclamation","TxStatus","_ref","status","title","amount","message","footer","dataTestId","rest","_jsxs","root","graphicGroup","graphic","textGroup"],"mappings":"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"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { forwardRef } from 'react';
|
|
1
2
|
import cn from 'classnames';
|
|
3
|
+
import { CounterSlot } from '../counter/CounterSlot.mjs';
|
|
2
4
|
import styles from './Button.module.css.mjs';
|
|
3
5
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
6
|
import { IconLoaderCircle } from '../icons/components/base/IconLoaderCircle.mjs';
|
|
5
7
|
|
|
6
|
-
const Button = _ref => {
|
|
8
|
+
const Button = /*#__PURE__*/forwardRef((_ref, ref) => {
|
|
7
9
|
let {
|
|
8
10
|
className,
|
|
9
11
|
children,
|
|
@@ -14,10 +16,12 @@ const Button = _ref => {
|
|
|
14
16
|
disabled = false,
|
|
15
17
|
iconLeft,
|
|
16
18
|
iconRight,
|
|
19
|
+
counter,
|
|
17
20
|
dataTestId,
|
|
18
21
|
...rest
|
|
19
22
|
} = _ref;
|
|
20
23
|
return /*#__PURE__*/jsxs("button", {
|
|
24
|
+
ref: ref,
|
|
21
25
|
type: type,
|
|
22
26
|
disabled: disabled || loading,
|
|
23
27
|
"aria-busy": loading || undefined,
|
|
@@ -41,9 +45,13 @@ const Button = _ref => {
|
|
|
41
45
|
"aria-hidden": "true",
|
|
42
46
|
"data-testid": dataTestId?.iconRight,
|
|
43
47
|
children: iconRight
|
|
44
|
-
}) : null
|
|
48
|
+
}) : null, /*#__PURE__*/jsx(CounterSlot, {
|
|
49
|
+
dataTestId: dataTestId?.counter,
|
|
50
|
+
children: counter
|
|
51
|
+
})]
|
|
45
52
|
});
|
|
46
|
-
};
|
|
53
|
+
});
|
|
54
|
+
Button.displayName = 'Button';
|
|
47
55
|
|
|
48
56
|
export { Button };
|
|
49
57
|
//# sourceMappingURL=Button.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.mjs","sources":["../../../src/button/Button.tsx"],"sourcesContent":["import type
|
|
1
|
+
{"version":3,"file":"Button.mjs","sources":["../../../src/button/Button.tsx"],"sourcesContent":["import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from 'react'\n\nimport cn from 'classnames'\n\nimport { CounterSlot } from '../counter/CounterSlot'\nimport { IconLoaderCircle } from '../icons'\nimport styles from './Button.module.css'\n\nexport type ButtonVariant = 'primary' | 'outline' | 'subtle' | 'ghost' | 'error'\n\nexport type ButtonSize = 'big' | 'small'\n\nexport type ButtonDataTestId = {\n root?: string\n iconLeft?: string\n iconRight?: string\n content?: string\n counter?: string\n}\n\nexport type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n variant?: ButtonVariant\n size?: ButtonSize\n loading?: boolean\n iconLeft?: ReactNode\n iconRight?: ReactNode\n /** Corner slot, aria-hidden: put the count into `aria-label`. */\n counter?: ReactNode\n dataTestId?: ButtonDataTestId\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n children,\n type = 'button',\n variant = 'primary',\n size = 'big',\n loading = false,\n disabled = false,\n iconLeft,\n iconRight,\n counter,\n dataTestId,\n ...rest\n },\n ref,\n ) => (\n <button\n ref={ref}\n type={type}\n disabled={disabled || loading}\n aria-busy={loading || undefined}\n className={cn(\n styles.button,\n styles[variant],\n styles[size],\n loading && styles.loading,\n className,\n )}\n data-testid={dataTestId?.root}\n {...rest}\n >\n {loading ? (\n <IconLoaderCircle className={styles.spinner} aria-hidden='true' />\n ) : (\n iconLeft != null && (\n <span\n className={styles.icon}\n aria-hidden='true'\n data-testid={dataTestId?.iconLeft}\n >\n {iconLeft}\n </span>\n )\n )}\n <span className={styles.content} data-testid={dataTestId?.content}>\n {children}\n </span>\n {!loading && iconRight != null ? (\n <span\n className={styles.icon}\n aria-hidden='true'\n data-testid={dataTestId?.iconRight}\n >\n {iconRight}\n </span>\n ) : null}\n <CounterSlot dataTestId={dataTestId?.counter}>{counter}</CounterSlot>\n </button>\n ),\n)\n\nButton.displayName = 'Button'\n"],"names":["Button","forwardRef","_ref","ref","className","children","type","variant","size","loading","disabled","iconLeft","iconRight","counter","dataTestId","rest","_jsxs","undefined","cn","styles","button","root","_jsx","IconLoaderCircle","spinner","icon","content","CounterSlot","displayName"],"mappings":";;;;;;;AA+BO,MAAMA,MAAM,gBAAGC,UAAU,CAC9B,CAAAC,IAAA,EAeEC,GAAG,KAAA;EAAA,IAdH;IACEC,SAAS;IACTC,QAAQ;AACRC,IAAAA,IAAI,GAAG,QAAQ;AACfC,IAAAA,OAAO,GAAG,SAAS;AACnBC,IAAAA,IAAI,GAAG,KAAK;AACZC,IAAAA,OAAO,GAAG,KAAK;AACfC,IAAAA,QAAQ,GAAG,KAAK;IAChBC,QAAQ;IACRC,SAAS;IACTC,OAAO;IACPC,UAAU;IACV,GAAGC,IAAAA;AACL,GAAC,GAAAb,IAAA,CAAA;AAAA,EAAA,oBAGDc,IAAA,CAAA,QAAA,EAAA;AACEb,IAAAA,GAAG,EAAEA,GAAI;AACTG,IAAAA,IAAI,EAAEA,IAAK;IACXI,QAAQ,EAAEA,QAAQ,IAAID,OAAQ;IAC9B,WAAWA,EAAAA,OAAO,IAAIQ,SAAU;IAChCb,SAAS,EAAEc,EAAE,CACXC,MAAM,CAACC,MAAM,EACbD,MAAM,CAACZ,OAAO,CAAC,EACfY,MAAM,CAACX,IAAI,CAAC,EACZC,OAAO,IAAIU,MAAM,CAACV,OAAO,EACzBL,SACF,CAAE;IACF,aAAaU,EAAAA,UAAU,EAAEO,IAAK;AAAA,IAAA,GAC1BN,IAAI;AAAAV,IAAAA,QAAA,EAEPI,CAAAA,OAAO,gBACNa,GAAA,CAACC,gBAAgB,EAAA;MAACnB,SAAS,EAAEe,MAAM,CAACK,OAAQ;MAAC,aAAY,EAAA,MAAA;AAAM,KAAE,CAAC,GAElEb,QAAQ,IAAI,IAAI,iBACdW,GAAA,CAAA,MAAA,EAAA;MACElB,SAAS,EAAEe,MAAM,CAACM,IAAK;AACvB,MAAA,aAAA,EAAY,MAAM;MAClB,aAAaX,EAAAA,UAAU,EAAEH,QAAS;AAAAN,MAAAA,QAAA,EAEjCM,QAAAA;KACG,CAET,eACDW,GAAA,CAAA,MAAA,EAAA;MAAMlB,SAAS,EAAEe,MAAM,CAACO,OAAQ;MAAC,aAAaZ,EAAAA,UAAU,EAAEY,OAAQ;AAAArB,MAAAA,QAAA,EAC/DA,QAAAA;KACG,CAAC,EACN,CAACI,OAAO,IAAIG,SAAS,IAAI,IAAI,gBAC5BU,GAAA,CAAA,MAAA,EAAA;MACElB,SAAS,EAAEe,MAAM,CAACM,IAAK;AACvB,MAAA,aAAA,EAAY,MAAM;MAClB,aAAaX,EAAAA,UAAU,EAAEF,SAAU;AAAAP,MAAAA,QAAA,EAElCO,SAAAA;AAAS,KACN,CAAC,GACL,IAAI,eACRU,GAAA,CAACK,WAAW,EAAA;MAACb,UAAU,EAAEA,UAAU,EAAED,OAAQ;AAAAR,MAAAA,QAAA,EAAEQ,OAAAA;AAAO,KAAc,CAAC,CAAA;AAAA,GAC/D,CAAC,CAAA;AAAA,CAEb,EAAC;AAEDb,MAAM,CAAC4B,WAAW,GAAG,QAAQ;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const styles = {"counter":"Counter-module_counter__qutVl","neutral":"Counter-module_neutral__Z5iCI","error":"Counter-module_error__srNOJ","warning":"Counter-module_warning__5OY4o","action":"Counter-module_action__ywkeX","active":"Counter-module_active__AZ4oD"};
|
|
1
|
+
const styles = {"counter":"Counter-module_counter__qutVl","neutral":"Counter-module_neutral__Z5iCI","default":"Counter-module_default__W0-pw","error":"Counter-module_error__srNOJ","warning":"Counter-module_warning__5OY4o","action":"Counter-module_action__ywkeX","active":"Counter-module_active__AZ4oD"};
|
|
2
2
|
|
|
3
3
|
export { styles as default };
|
|
4
4
|
//# sourceMappingURL=Counter.module.css.mjs.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import styles from './CounterSlot.module.css.mjs';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
const CounterSlot = _ref => {
|
|
5
|
+
let {
|
|
6
|
+
children,
|
|
7
|
+
dataTestId
|
|
8
|
+
} = _ref;
|
|
9
|
+
return children == null || children === false ? null : /*#__PURE__*/jsx("span", {
|
|
10
|
+
className: styles.slot,
|
|
11
|
+
"aria-hidden": "true",
|
|
12
|
+
"data-testid": dataTestId,
|
|
13
|
+
children: children
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export { CounterSlot };
|
|
18
|
+
//# sourceMappingURL=CounterSlot.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CounterSlot.mjs","sources":["../../../src/counter/CounterSlot.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\n\nimport styles from './CounterSlot.module.css'\n\ntype CounterSlotProps = {\n children?: ReactNode\n dataTestId?: string\n}\n\nexport const CounterSlot = ({ children, dataTestId }: CounterSlotProps) =>\n children == null || children === false ? null : (\n <span className={styles.slot} aria-hidden='true' data-testid={dataTestId}>\n {children}\n </span>\n )\n"],"names":["CounterSlot","_ref","children","dataTestId","_jsx","className","styles","slot"],"mappings":";;;AASO,MAAMA,WAAW,GAAGC,IAAA,IAAA;EAAA,IAAC;IAAEC,QAAQ;AAAEC,IAAAA,UAAAA;AAA6B,GAAC,GAAAF,IAAA,CAAA;EAAA,OACpEC,QAAQ,IAAI,IAAI,IAAIA,QAAQ,KAAK,KAAK,GAAG,IAAI,gBAC3CE,GAAA,CAAA,MAAA,EAAA;IAAMC,SAAS,EAAEC,MAAM,CAACC,IAAK;AAAC,IAAA,aAAA,EAAY,MAAM;AAAC,IAAA,aAAA,EAAaJ,UAAW;AAAAD,IAAAA,QAAA,EACtEA,QAAAA;AAAQ,GACL,CACP,CAAA;AAAA;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CounterSlot.module.css.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import cn from 'classnames';
|
|
2
|
+
import styles from './Disclaimer.module.css.mjs';
|
|
3
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import { TextLink } from '../text-link/TextLink.mjs';
|
|
5
|
+
|
|
6
|
+
const defaultContent = /*#__PURE__*/jsxs(Fragment, {
|
|
7
|
+
children: ["Your privacy matters. We use cookieless analytics and collect only anonymized data for improvements. Cookies are used for functionality only. For more info read", ' ', /*#__PURE__*/jsx(TextLink, {
|
|
8
|
+
href: "https://lido.fi/privacy-notice",
|
|
9
|
+
external: true,
|
|
10
|
+
children: "Privacy Notice"
|
|
11
|
+
}), "."]
|
|
12
|
+
});
|
|
13
|
+
const Disclaimer = _ref => {
|
|
14
|
+
let {
|
|
15
|
+
className,
|
|
16
|
+
children = defaultContent,
|
|
17
|
+
dataTestId,
|
|
18
|
+
...rest
|
|
19
|
+
} = _ref;
|
|
20
|
+
return /*#__PURE__*/jsx("p", {
|
|
21
|
+
className: cn(styles.root, className),
|
|
22
|
+
"data-testid": dataTestId?.root,
|
|
23
|
+
...rest,
|
|
24
|
+
children: children
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export { Disclaimer };
|
|
29
|
+
//# sourceMappingURL=Disclaimer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Disclaimer.mjs","sources":["../../../src/disclaimer/Disclaimer.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef } from 'react'\n\nimport cn from 'classnames'\n\nimport { TextLink } from '../text-link'\nimport styles from './Disclaimer.module.css'\n\nexport type DisclaimerDataTestId = {\n root?: string\n}\n\nexport type DisclaimerProps = ComponentPropsWithoutRef<'p'> & {\n dataTestId?: DisclaimerDataTestId\n}\n\nconst defaultContent = (\n <>\n Your privacy matters. We use cookieless analytics and collect only\n anonymized data for improvements. Cookies are used for functionality only.\n For more info read{' '}\n <TextLink href='https://lido.fi/privacy-notice' external>\n Privacy Notice\n </TextLink>\n .\n </>\n)\n\nexport const Disclaimer = ({\n className,\n children = defaultContent,\n dataTestId,\n ...rest\n}: DisclaimerProps) => (\n <p\n className={cn(styles.root, className)}\n data-testid={dataTestId?.root}\n {...rest}\n >\n {children}\n </p>\n)\n"],"names":["defaultContent","_jsxs","_Fragment","children","_jsx","TextLink","href","external","Disclaimer","_ref","className","dataTestId","rest","cn","styles","root"],"mappings":";;;;;AAeA,MAAMA,cAAc,gBAClBC,IAAA,CAAAC,QAAA,EAAA;AAAAC,EAAAA,QAAA,GAAE,kKAGkB,EAAC,GAAG,eACtBC,GAAA,CAACC,QAAQ,EAAA;AAACC,IAAAA,IAAI,EAAC,gCAAgC;IAACC,QAAQ,EAAA,IAAA;AAAAJ,IAAAA,QAAA,EAAC,gBAAA;AAEzD,GAAU,CAAC,EAEb,GAAA,CAAA;AAAA,CAAE,CACH,CAAA;AAEM,MAAMK,UAAU,GAAGC,IAAA,IAAA;EAAA,IAAC;IACzBC,SAAS;AACTP,IAAAA,QAAQ,GAAGH,cAAc;IACzBW,UAAU;IACV,GAAGC,IAAAA;AACY,GAAC,GAAAH,IAAA,CAAA;AAAA,EAAA,oBAChBL,GAAA,CAAA,GAAA,EAAA;IACEM,SAAS,EAAEG,EAAE,CAACC,MAAM,CAACC,IAAI,EAAEL,SAAS,CAAE;IACtC,aAAaC,EAAAA,UAAU,EAAEI,IAAK;AAAA,IAAA,GAC1BH,IAAI;AAAAT,IAAAA,QAAA,EAEPA,QAAAA;AAAQ,GACR,CAAC,CAAA;AAAA;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Disclaimer.module.css.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import cn from 'classnames';
|
|
2
|
+
import styles from './ErrorPage.module.css.mjs';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
const presets = {
|
|
6
|
+
'404': {
|
|
7
|
+
title: 'Page not found',
|
|
8
|
+
description: 'The page you’re looking for doesn’t exist or has been moved. Check the URL or return to your dashboard.'
|
|
9
|
+
},
|
|
10
|
+
'500': {
|
|
11
|
+
title: 'Something went wrong',
|
|
12
|
+
description: 'We’re having trouble loading this page. Please try again in a moment.'
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const isPresetCode = code => code === '404' || code === '500';
|
|
16
|
+
const ErrorPage = _ref => {
|
|
17
|
+
let {
|
|
18
|
+
code,
|
|
19
|
+
title,
|
|
20
|
+
description,
|
|
21
|
+
action,
|
|
22
|
+
className,
|
|
23
|
+
dataTestId,
|
|
24
|
+
...rest
|
|
25
|
+
} = _ref;
|
|
26
|
+
const preset = isPresetCode(code) ? presets[code] : undefined;
|
|
27
|
+
const resolvedTitle = title !== undefined ? title : preset?.title;
|
|
28
|
+
const resolvedDescription = description !== undefined ? description : preset?.description;
|
|
29
|
+
return /*#__PURE__*/jsx("div", {
|
|
30
|
+
className: cn(styles.root, className),
|
|
31
|
+
"data-testid": dataTestId?.root,
|
|
32
|
+
...rest,
|
|
33
|
+
children: /*#__PURE__*/jsxs("div", {
|
|
34
|
+
className: styles.inner,
|
|
35
|
+
children: [code != null ? /*#__PURE__*/jsx("div", {
|
|
36
|
+
className: styles.code,
|
|
37
|
+
"data-testid": dataTestId?.code,
|
|
38
|
+
children: code
|
|
39
|
+
}) : null, /*#__PURE__*/jsxs("div", {
|
|
40
|
+
className: styles.text,
|
|
41
|
+
children: [resolvedTitle != null ? /*#__PURE__*/jsx("h1", {
|
|
42
|
+
className: styles.title,
|
|
43
|
+
"data-testid": dataTestId?.title,
|
|
44
|
+
children: resolvedTitle
|
|
45
|
+
}) : null, resolvedDescription != null ? /*#__PURE__*/jsx("p", {
|
|
46
|
+
className: styles.description,
|
|
47
|
+
"data-testid": dataTestId?.description,
|
|
48
|
+
children: resolvedDescription
|
|
49
|
+
}) : null]
|
|
50
|
+
}), action != null ? /*#__PURE__*/jsx("div", {
|
|
51
|
+
className: styles.action,
|
|
52
|
+
"data-testid": dataTestId?.action,
|
|
53
|
+
children: action
|
|
54
|
+
}) : null]
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export { ErrorPage };
|
|
60
|
+
//# sourceMappingURL=ErrorPage.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorPage.mjs","sources":["../../../src/error-page/ErrorPage.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from 'react'\n\nimport cn from 'classnames'\n\nimport styles from './ErrorPage.module.css'\n\nexport type ErrorPageCode = '404' | '500'\n\nexport type ErrorPageDataTestId = {\n root?: string\n code?: string\n title?: string\n description?: string\n action?: string\n}\n\nexport type ErrorPageProps = Omit<HTMLAttributes<HTMLDivElement>, 'title'> & {\n /** `'404'` / `'500'` fill default title and description. */\n code?: ErrorPageCode | (string & {})\n title?: ReactNode\n description?: ReactNode\n /** Slot below the text, usually a `Button`. */\n action?: ReactNode\n dataTestId?: ErrorPageDataTestId\n}\n\nconst presets: Record<ErrorPageCode, { title: string; description: string }> = {\n '404': {\n title: 'Page not found',\n description:\n 'The page you’re looking for doesn’t exist or has been moved. Check the URL or return to your dashboard.',\n },\n '500': {\n title: 'Something went wrong',\n description:\n 'We’re having trouble loading this page. Please try again in a moment.',\n },\n}\n\nconst isPresetCode = (code?: string): code is ErrorPageCode =>\n code === '404' || code === '500'\n\nexport const ErrorPage = ({\n code,\n title,\n description,\n action,\n className,\n dataTestId,\n ...rest\n}: ErrorPageProps) => {\n const preset = isPresetCode(code) ? presets[code] : undefined\n const resolvedTitle = title !== undefined ? title : preset?.title\n const resolvedDescription =\n description !== undefined ? description : preset?.description\n\n return (\n <div\n className={cn(styles.root, className)}\n data-testid={dataTestId?.root}\n {...rest}\n >\n <div className={styles.inner}>\n {code != null ? (\n <div className={styles.code} data-testid={dataTestId?.code}>\n {code}\n </div>\n ) : null}\n <div className={styles.text}>\n {resolvedTitle != null ? (\n <h1 className={styles.title} data-testid={dataTestId?.title}>\n {resolvedTitle}\n </h1>\n ) : null}\n {resolvedDescription != null ? (\n <p\n className={styles.description}\n data-testid={dataTestId?.description}\n >\n {resolvedDescription}\n </p>\n ) : null}\n </div>\n {action != null ? (\n <div className={styles.action} data-testid={dataTestId?.action}>\n {action}\n </div>\n ) : null}\n </div>\n </div>\n )\n}\n"],"names":["presets","title","description","isPresetCode","code","ErrorPage","_ref","action","className","dataTestId","rest","preset","undefined","resolvedTitle","resolvedDescription","_jsx","cn","styles","root","children","_jsxs","inner","text"],"mappings":";;;;AA0BA,MAAMA,OAAsE,GAAG;AAC7E,EAAA,KAAK,EAAE;AACLC,IAAAA,KAAK,EAAE,gBAAgB;AACvBC,IAAAA,WAAW,EACT,yGAAA;GACH;AACD,EAAA,KAAK,EAAE;AACLD,IAAAA,KAAK,EAAE,sBAAsB;AAC7BC,IAAAA,WAAW,EACT,uEAAA;AACJ,GAAA;AACF,CAAC,CAAA;AAED,MAAMC,YAAY,GAAIC,IAAa,IACjCA,IAAI,KAAK,KAAK,IAAIA,IAAI,KAAK,KAAK,CAAA;AAErBC,MAAAA,SAAS,GAAGC,IAAA,IAQH;EAAA,IARI;IACxBF,IAAI;IACJH,KAAK;IACLC,WAAW;IACXK,MAAM;IACNC,SAAS;IACTC,UAAU;IACV,GAAGC,IAAAA;AACW,GAAC,GAAAJ,IAAA,CAAA;AACf,EAAA,MAAMK,MAAM,GAAGR,YAAY,CAACC,IAAI,CAAC,GAAGJ,OAAO,CAACI,IAAI,CAAC,GAAGQ,SAAS,CAAA;EAC7D,MAAMC,aAAa,GAAGZ,KAAK,KAAKW,SAAS,GAAGX,KAAK,GAAGU,MAAM,EAAEV,KAAK,CAAA;EACjE,MAAMa,mBAAmB,GACvBZ,WAAW,KAAKU,SAAS,GAAGV,WAAW,GAAGS,MAAM,EAAET,WAAW,CAAA;AAE/D,EAAA,oBACEa,GAAA,CAAA,KAAA,EAAA;IACEP,SAAS,EAAEQ,EAAE,CAACC,MAAM,CAACC,IAAI,EAAEV,SAAS,CAAE;IACtC,aAAaC,EAAAA,UAAU,EAAES,IAAK;AAAA,IAAA,GAC1BR,IAAI;AAAAS,IAAAA,QAAA,eAERC,IAAA,CAAA,KAAA,EAAA;MAAKZ,SAAS,EAAES,MAAM,CAACI,KAAM;AAAAF,MAAAA,QAAA,EAC1Bf,CAAAA,IAAI,IAAI,IAAI,gBACXW,GAAA,CAAA,KAAA,EAAA;QAAKP,SAAS,EAAES,MAAM,CAACb,IAAK;QAAC,aAAaK,EAAAA,UAAU,EAAEL,IAAK;AAAAe,QAAAA,QAAA,EACxDf,IAAAA;AAAI,OACF,CAAC,GACJ,IAAI,eACRgB,IAAA,CAAA,KAAA,EAAA;QAAKZ,SAAS,EAAES,MAAM,CAACK,IAAK;AAAAH,QAAAA,QAAA,EACzBN,CAAAA,aAAa,IAAI,IAAI,gBACpBE,GAAA,CAAA,IAAA,EAAA;UAAIP,SAAS,EAAES,MAAM,CAAChB,KAAM;UAAC,aAAaQ,EAAAA,UAAU,EAAER,KAAM;AAAAkB,UAAAA,QAAA,EACzDN,aAAAA;SACC,CAAC,GACH,IAAI,EACPC,mBAAmB,IAAI,IAAI,gBAC1BC,GAAA,CAAA,GAAA,EAAA;UACEP,SAAS,EAAES,MAAM,CAACf,WAAY;UAC9B,aAAaO,EAAAA,UAAU,EAAEP,WAAY;AAAAiB,UAAAA,QAAA,EAEpCL,mBAAAA;SACA,CAAC,GACF,IAAI,CAAA;AAAA,OACL,CAAC,EACLP,MAAM,IAAI,IAAI,gBACbQ,GAAA,CAAA,KAAA,EAAA;QAAKP,SAAS,EAAES,MAAM,CAACV,MAAO;QAAC,aAAaE,EAAAA,UAAU,EAAEF,MAAO;AAAAY,QAAAA,QAAA,EAC5DZ,MAAAA;OACE,CAAC,GACJ,IAAI,CAAA;KACL,CAAA;AAAC,GACH,CAAC,CAAA;AAEV;;;;"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
const styles = {"root":"ErrorPage-module_root__sdAsZ","inner":"ErrorPage-module_inner__rf3pT","code":"ErrorPage-module_code__sXtwL","text":"ErrorPage-module_text__SIHr-","title":"ErrorPage-module_title__1gYNN","description":"ErrorPage-module_description__VILdD","action":"ErrorPage-module_action__euwDk"};
|
|
2
|
+
|
|
3
|
+
export { styles as default };
|
|
4
|
+
//# sourceMappingURL=ErrorPage.module.css.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorPage.module.css.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import cn from 'classnames';
|
|
2
|
+
import styles from './Footer.module.css.mjs';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
const Footer = _ref => {
|
|
6
|
+
let {
|
|
7
|
+
children,
|
|
8
|
+
aside,
|
|
9
|
+
className,
|
|
10
|
+
...rest
|
|
11
|
+
} = _ref;
|
|
12
|
+
return /*#__PURE__*/jsxs("footer", {
|
|
13
|
+
className: cn(styles.footer, className),
|
|
14
|
+
...rest,
|
|
15
|
+
children: [/*#__PURE__*/jsx("div", {
|
|
16
|
+
className: styles.content,
|
|
17
|
+
children: children
|
|
18
|
+
}), aside != null ? /*#__PURE__*/jsx("div", {
|
|
19
|
+
className: styles.aside,
|
|
20
|
+
children: aside
|
|
21
|
+
}) : null]
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export { Footer };
|
|
26
|
+
//# sourceMappingURL=Footer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Footer.mjs","sources":["../../../src/footer/Footer.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ReactNode } from 'react'\n\nimport cn from 'classnames'\n\nimport styles from './Footer.module.css'\n\nexport type FooterProps = ComponentPropsWithoutRef<'footer'> & {\n /** Right slot, e.g. version tag. */\n aside?: ReactNode\n}\n\nexport const Footer = ({\n children,\n aside,\n className,\n ...rest\n}: FooterProps) => (\n <footer className={cn(styles.footer, className)} {...rest}>\n <div className={styles.content}>{children}</div>\n {aside != null ? <div className={styles.aside}>{aside}</div> : null}\n </footer>\n)\n"],"names":["Footer","_ref","children","aside","className","rest","_jsxs","cn","styles","footer","_jsx","content"],"mappings":";;;;AAWO,MAAMA,MAAM,GAAGC,IAAA,IAAA;EAAA,IAAC;IACrBC,QAAQ;IACRC,KAAK;IACLC,SAAS;IACT,GAAGC,IAAAA;AACQ,GAAC,GAAAJ,IAAA,CAAA;AAAA,EAAA,oBACZK,IAAA,CAAA,QAAA,EAAA;IAAQF,SAAS,EAAEG,EAAE,CAACC,MAAM,CAACC,MAAM,EAAEL,SAAS,CAAE;AAAA,IAAA,GAAKC,IAAI;AAAAH,IAAAA,QAAA,gBACvDQ,GAAA,CAAA,KAAA,EAAA;MAAKN,SAAS,EAAEI,MAAM,CAACG,OAAQ;AAAAT,MAAAA,QAAA,EAAEA,QAAAA;AAAQ,KAAM,CAAC,EAC/CC,KAAK,IAAI,IAAI,gBAAGO,GAAA,CAAA,KAAA,EAAA;MAAKN,SAAS,EAAEI,MAAM,CAACL,KAAM;AAAAD,MAAAA,QAAA,EAAEC,KAAAA;KAAW,CAAC,GAAG,IAAI,CAAA;AAAA,GAC7D,CAAC,CAAA;AAAA;;;;"}
|