@x-plat/design-system 0.7.1 → 0.8.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/components/AutoResizeTextArea/index.css +3 -1
- package/dist/components/Button/index.css +2 -1
- package/dist/components/Button/index.d.cts +6 -0
- package/dist/components/Button/index.d.ts +6 -0
- package/dist/components/Chart/index.cjs +8 -1
- package/dist/components/Chart/index.js +8 -1
- package/dist/components/ChatInput/index.css +6 -2
- package/dist/components/DatePicker/index.css +5 -2
- package/dist/components/Input/index.css +3 -1
- package/dist/components/Link/index.cjs +64 -0
- package/dist/components/Link/index.css +25 -0
- package/dist/components/Link/index.d.cts +27 -0
- package/dist/components/Link/index.d.ts +27 -0
- package/dist/components/Link/index.js +37 -0
- package/dist/components/LinkButton/index.cjs +64 -0
- package/dist/components/LinkButton/index.css +106 -0
- package/dist/components/LinkButton/index.d.cts +28 -0
- package/dist/components/LinkButton/index.d.ts +28 -0
- package/dist/components/LinkButton/index.js +37 -0
- package/dist/components/Select/index.css +4 -2
- package/dist/components/TextArea/index.css +3 -1
- package/dist/components/Tooltip/index.cjs +77 -32
- package/dist/components/Tooltip/index.d.cts +10 -2
- package/dist/components/Tooltip/index.d.ts +10 -2
- package/dist/components/Tooltip/index.js +77 -32
- package/dist/components/index.cjs +247 -153
- package/dist/components/index.css +44 -7
- package/dist/components/index.d.cts +2 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +222 -130
- package/dist/index.cjs +266 -172
- package/dist/index.css +44 -7
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +239 -147
- package/guidelines/AGENT_PROMPT.md +2 -2
- package/guidelines/Guidelines.md +2 -1
- package/guidelines/components/button.md +54 -0
- package/guidelines/components/card.md +15 -19
- package/guidelines/components/link.md +35 -0
- package/guidelines/components/overlay.md +30 -1
- package/package.json +1 -1
|
@@ -70,13 +70,15 @@ var clsx_default = clsx;
|
|
|
70
70
|
// src/components/Tooltip/Tooltip.tsx
|
|
71
71
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
72
72
|
var OFFSET = 12;
|
|
73
|
+
var GAP = 8;
|
|
73
74
|
var SHOW_DELAY = 300;
|
|
74
75
|
var Tooltip = (props) => {
|
|
75
76
|
const {
|
|
76
|
-
|
|
77
|
+
children,
|
|
77
78
|
title,
|
|
78
79
|
description,
|
|
79
|
-
|
|
80
|
+
type = "dark",
|
|
81
|
+
follow = false,
|
|
80
82
|
disabled = false
|
|
81
83
|
} = props;
|
|
82
84
|
const triggerRef = import_react2.default.useRef(null);
|
|
@@ -84,49 +86,91 @@ var Tooltip = (props) => {
|
|
|
84
86
|
const [visible, setVisible] = import_react2.default.useState(false);
|
|
85
87
|
const [pos, setPos] = import_react2.default.useState({ left: 0, top: 0 });
|
|
86
88
|
const delayTimer = import_react2.default.useRef(0);
|
|
87
|
-
const
|
|
89
|
+
const rafRef = import_react2.default.useRef(0);
|
|
90
|
+
const cursor = import_react2.default.useRef(null);
|
|
91
|
+
const clamp = import_react2.default.useCallback((left, top, w, h) => {
|
|
92
|
+
const vw = window.innerWidth;
|
|
93
|
+
const vh = window.innerHeight;
|
|
94
|
+
return {
|
|
95
|
+
left: Math.min(Math.max(GAP, left), Math.max(GAP, vw - w - GAP)),
|
|
96
|
+
top: Math.min(Math.max(GAP, top), Math.max(GAP, vh - h - GAP))
|
|
97
|
+
};
|
|
98
|
+
}, []);
|
|
99
|
+
const placeAtCursor = import_react2.default.useCallback((x, y) => {
|
|
88
100
|
const el = tooltipRef.current;
|
|
89
101
|
if (!el) return;
|
|
90
102
|
const w = el.offsetWidth;
|
|
91
103
|
const h = el.offsetHeight;
|
|
92
|
-
|
|
93
|
-
let
|
|
94
|
-
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
104
|
+
let left = x + OFFSET;
|
|
105
|
+
let top = y - h - OFFSET;
|
|
106
|
+
if (left + w > window.innerWidth - GAP) left = x - w - OFFSET;
|
|
107
|
+
if (top < GAP) top = y + OFFSET;
|
|
108
|
+
setPos(clamp(left, top, w, h));
|
|
109
|
+
}, [clamp]);
|
|
110
|
+
const placeAtTrigger = import_react2.default.useCallback(() => {
|
|
111
|
+
const el = tooltipRef.current;
|
|
112
|
+
const trigger = triggerRef.current;
|
|
113
|
+
if (!el || !trigger) return;
|
|
114
|
+
const w = el.offsetWidth;
|
|
115
|
+
const h = el.offsetHeight;
|
|
116
|
+
const rect = trigger.getBoundingClientRect();
|
|
117
|
+
let top = rect.top - h - GAP;
|
|
118
|
+
if (top < GAP) top = rect.bottom + GAP;
|
|
119
|
+
const left = rect.left + rect.width / 2 - w / 2;
|
|
120
|
+
setPos(clamp(left, top, w, h));
|
|
121
|
+
}, [clamp]);
|
|
122
|
+
const reposition = import_react2.default.useCallback(() => {
|
|
123
|
+
if (follow && cursor.current) {
|
|
124
|
+
placeAtCursor(cursor.current.x, cursor.current.y);
|
|
125
|
+
} else {
|
|
126
|
+
placeAtTrigger();
|
|
127
|
+
}
|
|
128
|
+
}, [follow, placeAtCursor, placeAtTrigger]);
|
|
129
|
+
const handleMouseEnter = import_react2.default.useCallback((e) => {
|
|
101
130
|
if (disabled) return;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}, SHOW_DELAY);
|
|
131
|
+
cursor.current = { x: e.clientX, y: e.clientY };
|
|
132
|
+
delayTimer.current = window.setTimeout(() => setVisible(true), SHOW_DELAY);
|
|
105
133
|
}, [disabled]);
|
|
106
134
|
const handleMouseMove = import_react2.default.useCallback((e) => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}, []);
|
|
114
|
-
const
|
|
135
|
+
cursor.current = { x: e.clientX, y: e.clientY };
|
|
136
|
+
if (!visible || !follow) return;
|
|
137
|
+
cancelAnimationFrame(rafRef.current);
|
|
138
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
139
|
+
if (cursor.current) placeAtCursor(cursor.current.x, cursor.current.y);
|
|
140
|
+
});
|
|
141
|
+
}, [visible, follow, placeAtCursor]);
|
|
142
|
+
const close = import_react2.default.useCallback(() => {
|
|
115
143
|
window.clearTimeout(delayTimer.current);
|
|
144
|
+
cancelAnimationFrame(rafRef.current);
|
|
116
145
|
setVisible(false);
|
|
117
146
|
}, []);
|
|
147
|
+
const handleMouseLeave = import_react2.default.useCallback(() => {
|
|
148
|
+
cursor.current = null;
|
|
149
|
+
close();
|
|
150
|
+
}, [close]);
|
|
118
151
|
const handleFocus = import_react2.default.useCallback(() => {
|
|
119
152
|
if (disabled) return;
|
|
153
|
+
cursor.current = null;
|
|
120
154
|
setVisible(true);
|
|
121
155
|
}, [disabled]);
|
|
122
|
-
const handleBlur = import_react2.default.useCallback(() => {
|
|
123
|
-
setVisible(false);
|
|
124
|
-
}, []);
|
|
125
156
|
import_react2.default.useLayoutEffect(() => {
|
|
126
|
-
if (!visible
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
157
|
+
if (!visible) return;
|
|
158
|
+
reposition();
|
|
159
|
+
}, [visible, reposition]);
|
|
160
|
+
import_react2.default.useEffect(() => {
|
|
161
|
+
if (!visible || follow) return;
|
|
162
|
+
const onChange = () => placeAtTrigger();
|
|
163
|
+
window.addEventListener("scroll", onChange, true);
|
|
164
|
+
window.addEventListener("resize", onChange);
|
|
165
|
+
return () => {
|
|
166
|
+
window.removeEventListener("scroll", onChange, true);
|
|
167
|
+
window.removeEventListener("resize", onChange);
|
|
168
|
+
};
|
|
169
|
+
}, [visible, follow, placeAtTrigger]);
|
|
170
|
+
import_react2.default.useEffect(() => () => {
|
|
171
|
+
window.clearTimeout(delayTimer.current);
|
|
172
|
+
cancelAnimationFrame(rafRef.current);
|
|
173
|
+
}, []);
|
|
130
174
|
if (!title && !description) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
|
|
131
175
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
132
176
|
"div",
|
|
@@ -136,15 +180,16 @@ var Tooltip = (props) => {
|
|
|
136
180
|
onMouseEnter: handleMouseEnter,
|
|
137
181
|
onMouseMove: handleMouseMove,
|
|
138
182
|
onMouseLeave: handleMouseLeave,
|
|
139
|
-
onClick:
|
|
183
|
+
onClick: close,
|
|
140
184
|
onFocus: handleFocus,
|
|
141
|
-
onBlur:
|
|
185
|
+
onBlur: close,
|
|
142
186
|
children: [
|
|
143
187
|
children,
|
|
144
188
|
visible && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
145
189
|
"div",
|
|
146
190
|
{
|
|
147
191
|
ref: tooltipRef,
|
|
192
|
+
role: "tooltip",
|
|
148
193
|
className: clsx_default("lib-xplat-tooltip", type),
|
|
149
194
|
style: { position: "fixed", left: pos.left, top: pos.top },
|
|
150
195
|
children: [
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
interface TooltipProps {
|
|
4
|
-
|
|
4
|
+
children: React.ReactNode;
|
|
5
5
|
title?: React.ReactNode;
|
|
6
6
|
description?: React.ReactNode;
|
|
7
|
-
|
|
7
|
+
type?: "dark" | "light";
|
|
8
|
+
/**
|
|
9
|
+
* 커서를 따라다닌다. 기본값은 `false` — 트리거 요소 기준으로 고정된다
|
|
10
|
+
* (PopOver/Dropdown/Select 와 같은 방식).
|
|
11
|
+
*
|
|
12
|
+
* 넓은 영역 안에서 **가리키는 지점**이 의미를 가질 때만 켠다. 버튼이나
|
|
13
|
+
* 아이콘처럼 대상이 작은 경우는 고정이 읽기 편하다.
|
|
14
|
+
*/
|
|
15
|
+
follow?: boolean;
|
|
8
16
|
disabled?: boolean;
|
|
9
17
|
}
|
|
10
18
|
declare const Tooltip: React.FC<TooltipProps>;
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
interface TooltipProps {
|
|
4
|
-
|
|
4
|
+
children: React.ReactNode;
|
|
5
5
|
title?: React.ReactNode;
|
|
6
6
|
description?: React.ReactNode;
|
|
7
|
-
|
|
7
|
+
type?: "dark" | "light";
|
|
8
|
+
/**
|
|
9
|
+
* 커서를 따라다닌다. 기본값은 `false` — 트리거 요소 기준으로 고정된다
|
|
10
|
+
* (PopOver/Dropdown/Select 와 같은 방식).
|
|
11
|
+
*
|
|
12
|
+
* 넓은 영역 안에서 **가리키는 지점**이 의미를 가질 때만 켠다. 버튼이나
|
|
13
|
+
* 아이콘처럼 대상이 작은 경우는 고정이 읽기 편하다.
|
|
14
|
+
*/
|
|
15
|
+
follow?: boolean;
|
|
8
16
|
disabled?: boolean;
|
|
9
17
|
}
|
|
10
18
|
declare const Tooltip: React.FC<TooltipProps>;
|
|
@@ -34,13 +34,15 @@ var clsx_default = clsx;
|
|
|
34
34
|
// src/components/Tooltip/Tooltip.tsx
|
|
35
35
|
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
36
36
|
var OFFSET = 12;
|
|
37
|
+
var GAP = 8;
|
|
37
38
|
var SHOW_DELAY = 300;
|
|
38
39
|
var Tooltip = (props) => {
|
|
39
40
|
const {
|
|
40
|
-
|
|
41
|
+
children,
|
|
41
42
|
title,
|
|
42
43
|
description,
|
|
43
|
-
|
|
44
|
+
type = "dark",
|
|
45
|
+
follow = false,
|
|
44
46
|
disabled = false
|
|
45
47
|
} = props;
|
|
46
48
|
const triggerRef = React2.useRef(null);
|
|
@@ -48,49 +50,91 @@ var Tooltip = (props) => {
|
|
|
48
50
|
const [visible, setVisible] = React2.useState(false);
|
|
49
51
|
const [pos, setPos] = React2.useState({ left: 0, top: 0 });
|
|
50
52
|
const delayTimer = React2.useRef(0);
|
|
51
|
-
const
|
|
53
|
+
const rafRef = React2.useRef(0);
|
|
54
|
+
const cursor = React2.useRef(null);
|
|
55
|
+
const clamp = React2.useCallback((left, top, w, h) => {
|
|
56
|
+
const vw = window.innerWidth;
|
|
57
|
+
const vh = window.innerHeight;
|
|
58
|
+
return {
|
|
59
|
+
left: Math.min(Math.max(GAP, left), Math.max(GAP, vw - w - GAP)),
|
|
60
|
+
top: Math.min(Math.max(GAP, top), Math.max(GAP, vh - h - GAP))
|
|
61
|
+
};
|
|
62
|
+
}, []);
|
|
63
|
+
const placeAtCursor = React2.useCallback((x, y) => {
|
|
52
64
|
const el = tooltipRef.current;
|
|
53
65
|
if (!el) return;
|
|
54
66
|
const w = el.offsetWidth;
|
|
55
67
|
const h = el.offsetHeight;
|
|
56
|
-
|
|
57
|
-
let
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
let left = x + OFFSET;
|
|
69
|
+
let top = y - h - OFFSET;
|
|
70
|
+
if (left + w > window.innerWidth - GAP) left = x - w - OFFSET;
|
|
71
|
+
if (top < GAP) top = y + OFFSET;
|
|
72
|
+
setPos(clamp(left, top, w, h));
|
|
73
|
+
}, [clamp]);
|
|
74
|
+
const placeAtTrigger = React2.useCallback(() => {
|
|
75
|
+
const el = tooltipRef.current;
|
|
76
|
+
const trigger = triggerRef.current;
|
|
77
|
+
if (!el || !trigger) return;
|
|
78
|
+
const w = el.offsetWidth;
|
|
79
|
+
const h = el.offsetHeight;
|
|
80
|
+
const rect = trigger.getBoundingClientRect();
|
|
81
|
+
let top = rect.top - h - GAP;
|
|
82
|
+
if (top < GAP) top = rect.bottom + GAP;
|
|
83
|
+
const left = rect.left + rect.width / 2 - w / 2;
|
|
84
|
+
setPos(clamp(left, top, w, h));
|
|
85
|
+
}, [clamp]);
|
|
86
|
+
const reposition = React2.useCallback(() => {
|
|
87
|
+
if (follow && cursor.current) {
|
|
88
|
+
placeAtCursor(cursor.current.x, cursor.current.y);
|
|
89
|
+
} else {
|
|
90
|
+
placeAtTrigger();
|
|
91
|
+
}
|
|
92
|
+
}, [follow, placeAtCursor, placeAtTrigger]);
|
|
93
|
+
const handleMouseEnter = React2.useCallback((e) => {
|
|
65
94
|
if (disabled) return;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}, SHOW_DELAY);
|
|
95
|
+
cursor.current = { x: e.clientX, y: e.clientY };
|
|
96
|
+
delayTimer.current = window.setTimeout(() => setVisible(true), SHOW_DELAY);
|
|
69
97
|
}, [disabled]);
|
|
70
98
|
const handleMouseMove = React2.useCallback((e) => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}, []);
|
|
78
|
-
const
|
|
99
|
+
cursor.current = { x: e.clientX, y: e.clientY };
|
|
100
|
+
if (!visible || !follow) return;
|
|
101
|
+
cancelAnimationFrame(rafRef.current);
|
|
102
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
103
|
+
if (cursor.current) placeAtCursor(cursor.current.x, cursor.current.y);
|
|
104
|
+
});
|
|
105
|
+
}, [visible, follow, placeAtCursor]);
|
|
106
|
+
const close = React2.useCallback(() => {
|
|
79
107
|
window.clearTimeout(delayTimer.current);
|
|
108
|
+
cancelAnimationFrame(rafRef.current);
|
|
80
109
|
setVisible(false);
|
|
81
110
|
}, []);
|
|
111
|
+
const handleMouseLeave = React2.useCallback(() => {
|
|
112
|
+
cursor.current = null;
|
|
113
|
+
close();
|
|
114
|
+
}, [close]);
|
|
82
115
|
const handleFocus = React2.useCallback(() => {
|
|
83
116
|
if (disabled) return;
|
|
117
|
+
cursor.current = null;
|
|
84
118
|
setVisible(true);
|
|
85
119
|
}, [disabled]);
|
|
86
|
-
const handleBlur = React2.useCallback(() => {
|
|
87
|
-
setVisible(false);
|
|
88
|
-
}, []);
|
|
89
120
|
React2.useLayoutEffect(() => {
|
|
90
|
-
if (!visible
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
121
|
+
if (!visible) return;
|
|
122
|
+
reposition();
|
|
123
|
+
}, [visible, reposition]);
|
|
124
|
+
React2.useEffect(() => {
|
|
125
|
+
if (!visible || follow) return;
|
|
126
|
+
const onChange = () => placeAtTrigger();
|
|
127
|
+
window.addEventListener("scroll", onChange, true);
|
|
128
|
+
window.addEventListener("resize", onChange);
|
|
129
|
+
return () => {
|
|
130
|
+
window.removeEventListener("scroll", onChange, true);
|
|
131
|
+
window.removeEventListener("resize", onChange);
|
|
132
|
+
};
|
|
133
|
+
}, [visible, follow, placeAtTrigger]);
|
|
134
|
+
React2.useEffect(() => () => {
|
|
135
|
+
window.clearTimeout(delayTimer.current);
|
|
136
|
+
cancelAnimationFrame(rafRef.current);
|
|
137
|
+
}, []);
|
|
94
138
|
if (!title && !description) return /* @__PURE__ */ jsx2(Fragment, { children });
|
|
95
139
|
return /* @__PURE__ */ jsxs(
|
|
96
140
|
"div",
|
|
@@ -100,15 +144,16 @@ var Tooltip = (props) => {
|
|
|
100
144
|
onMouseEnter: handleMouseEnter,
|
|
101
145
|
onMouseMove: handleMouseMove,
|
|
102
146
|
onMouseLeave: handleMouseLeave,
|
|
103
|
-
onClick:
|
|
147
|
+
onClick: close,
|
|
104
148
|
onFocus: handleFocus,
|
|
105
|
-
onBlur:
|
|
149
|
+
onBlur: close,
|
|
106
150
|
children: [
|
|
107
151
|
children,
|
|
108
152
|
visible && /* @__PURE__ */ jsx2(Portal_default, { children: /* @__PURE__ */ jsxs(
|
|
109
153
|
"div",
|
|
110
154
|
{
|
|
111
155
|
ref: tooltipRef,
|
|
156
|
+
role: "tooltip",
|
|
112
157
|
className: clsx_default("lib-xplat-tooltip", type),
|
|
113
158
|
style: { position: "fixed", left: pos.left, top: pos.top },
|
|
114
159
|
children: [
|