@shiflo/ui 0.1.2 → 0.1.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.
@@ -1,35 +1,30 @@
1
- import { jsxs as k, jsx as c } from "@emotion/react/jsx-runtime";
2
- import { useState as l, useEffect as j } from "react";
1
+ import { jsxs as k, jsx as m } from "@emotion/react/jsx-runtime";
2
+ import { useState as f, useEffect as j } from "react";
3
3
  import { createPortal as v } from "react-dom";
4
4
  import { useTheme as x } from "@emotion/react";
5
5
  import r from "@emotion/styled";
6
- import { motion as a } from "motion/react";
7
- const C = r(a.div)`
6
+ import { motion as n } from "motion/react";
7
+ const C = r(n.div)`
8
8
  position: fixed;
9
9
  top: 0;
10
10
  left: 0;
11
11
  z-index: 1;
12
- `, A = r(a.div)`
12
+ `, A = r(n.div)`
13
13
  position: fixed;
14
14
  top: 0;
15
15
  left: 0;
16
16
  width: 100%;
17
17
  height: 100%;
18
- background-color: ${({
19
- theme: {
20
- palette: { common: e }
21
- }
22
- }) => e.overlay};
23
- `, w = r(a.div)`
18
+ `, w = r(n.div)`
24
19
  position: fixed;
25
20
  width: 100%;
26
21
  display: flex;
27
22
  justify-content: center;
28
23
  align-items: center;
29
24
 
30
- ${({ placement: e }) => {
25
+ ${({ placement: o }) => {
31
26
  const t = {};
32
- switch (e) {
27
+ switch (o) {
33
28
  case "top-left":
34
29
  Object.assign(t, {
35
30
  top: 0,
@@ -93,56 +88,56 @@ const C = r(a.div)`
93
88
  return t;
94
89
  }}
95
90
  `;
96
- function E({
97
- children: e,
91
+ function P({
92
+ children: o,
98
93
  open: t,
99
- onClose: m,
100
- transitionDuration: n = 0.2,
101
- placement: f,
94
+ onClose: p,
95
+ transitionDuration: a = 0.2,
96
+ placement: b,
102
97
  ref: I,
103
- onClick: p,
104
- hideOverlay: d,
105
- ...b
98
+ onClick: d,
99
+ hideOverlay: s,
100
+ ...g
106
101
  }) {
107
102
  const {
108
- palette: { common: u }
109
- } = x(), [g, s] = l(!0), [h, i] = l(!1), y = (o) => {
110
- m?.(), p?.(o);
103
+ palette: { common: i }
104
+ } = x(), [u, c] = f(!0), [h, l] = f(!1), y = (e) => {
105
+ p?.(), d?.(e);
111
106
  }, O = () => {
112
- t || s(!0);
107
+ t || c(!0);
113
108
  };
114
109
  return j(() => {
115
- let o;
116
- return t ? (s(!1), o = requestAnimationFrame(() => {
117
- i(!0);
118
- })) : i(!1), () => {
119
- o && cancelAnimationFrame(o);
110
+ let e;
111
+ return t ? (c(!1), e = requestAnimationFrame(() => {
112
+ l(!0);
113
+ })) : l(!1), () => {
114
+ e && cancelAnimationFrame(e);
120
115
  };
121
- }, [t, n]), g ? null : v(
116
+ }, [t, a]), u ? null : v(
122
117
  /* @__PURE__ */ k(C, { children: [
123
- /* @__PURE__ */ c(
118
+ /* @__PURE__ */ m(
124
119
  A,
125
120
  {
126
- initial: { opacity: 0 },
121
+ initial: { opacity: 0, backgroundColor: s ? "rgba(0, 0, 0, 0)" : i.overlay },
127
122
  animate: {
128
123
  opacity: h ? 1 : 0,
129
- backgroundColor: d ? "rgba(0, 0, 0, 0)" : u.overlay
124
+ backgroundColor: s ? "rgba(0, 0, 0, 0)" : i.overlay
130
125
  },
131
126
  transition: {
132
127
  type: "spring",
133
- duration: n,
128
+ duration: a,
134
129
  bounce: 0.2
135
130
  },
136
131
  onAnimationComplete: O,
137
132
  onClick: y,
138
- ...b
133
+ ...g
139
134
  }
140
135
  ),
141
- /* @__PURE__ */ c(w, { placement: f, children: e })
136
+ /* @__PURE__ */ m(w, { placement: b, children: o })
142
137
  ] }),
143
138
  document.body
144
139
  );
145
140
  }
146
141
  export {
147
- E as default
142
+ P as default
148
143
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shiflo/ui",
3
3
  "description": "Shiflo React UI Components",
4
- "version": "0.1.2",
4
+ "version": "0.1.3",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"
@@ -1,201 +0,0 @@
1
- import { jsxs as t, jsx as r } from "@emotion/react/jsx-runtime";
2
- import { useState as P, useRef as k, useEffect as A } from "react";
3
- import { useTheme as E } from "@emotion/react";
4
- import { motion as u, AnimatePresence as C } from "motion/react";
5
- import s from "../Box/Box.mjs";
6
- import { FPSChecker as I } from "./FPSMonitor.utils.mjs";
7
- import e from "../Typography/Typography.mjs";
8
- function J({
9
- trigger: R = !1,
10
- duration: g = 5e3,
11
- updateInterval: y = 10,
12
- threshold: p = 55,
13
- onComplete: v,
14
- on60FPSAchieved: b
15
- }) {
16
- const {
17
- palette: { neutral: x, primary: o, feedback: n, common: W, border: w, gradient: T },
18
- spacing: l,
19
- radius: d
20
- } = E(), [i, f] = P(null), [c, F] = P(null), h = k(!1), m = k(null);
21
- A(() => {
22
- if (!h.current)
23
- return h.current = !0, F(null), f(null), m.current = new I(
24
- { duration: g, callbackInterval: y },
25
- {
26
- onUpdate: (a) => {
27
- f(a);
28
- },
29
- onComplete: (a) => {
30
- h.current = !1, f(a), v?.(a);
31
- const S = a.averageFPS >= p;
32
- F(S), b?.(S);
33
- }
34
- }
35
- ), m.current.start(), () => {
36
- m.current && h.current && m.current.stop();
37
- };
38
- }, [R, g, y, p, b, v]);
39
- const $ = () => i ? i.averageFPS >= 60 ? o.main : i.averageFPS >= 30 ? o.light : n.error.main : x[500], B = () => i ? i.averageFPS >= 60 ? "60프레임 달성!" : i.averageFPS >= 30 ? "30프레임 이상" : "30프레임 미만" : "측정 대기 중", j = (a) => a >= 60 ? o.main : a >= 30 ? o.light : n.error.main, O = (a) => Math.min(a / 60 * 100, 100);
40
- return /* @__PURE__ */ t(
41
- u.div,
42
- {
43
- initial: { opacity: 0, y: 10 },
44
- animate: { opacity: 1, y: 0 },
45
- transition: { duration: 0.3, ease: "easeOut" },
46
- style: {
47
- padding: l[600],
48
- border: `1px solid ${w.light}`,
49
- borderRadius: d[600],
50
- backgroundColor: W.surface,
51
- boxShadow: `0 2px 8px ${x[100]}15`,
52
- position: "relative",
53
- overflow: "hidden"
54
- },
55
- children: [
56
- /* @__PURE__ */ r(
57
- "div",
58
- {
59
- style: {
60
- position: "absolute",
61
- top: 0,
62
- left: 0,
63
- right: 0,
64
- height: "2px",
65
- background: T.primaryToAccent,
66
- opacity: 0.6
67
- }
68
- }
69
- ),
70
- /* @__PURE__ */ r(s, { mb: "600", children: /* @__PURE__ */ r(e, { variant: "heading3", fontWeight: 700, color: "primary.main", mb: "400", children: "FPS 모니터" }) }),
71
- /* @__PURE__ */ r(C, { children: i && /* @__PURE__ */ r(
72
- u.div,
73
- {
74
- initial: { opacity: 0 },
75
- animate: { opacity: 1 },
76
- exit: { opacity: 0 },
77
- transition: { duration: 0.2 },
78
- children: /* @__PURE__ */ t(s, { mb: "600", children: [
79
- /* @__PURE__ */ t(
80
- e,
81
- {
82
- variant: "body1",
83
- fontWeight: 700,
84
- mb: "400",
85
- style: { color: $() },
86
- children: [
87
- "상태: ",
88
- B()
89
- ]
90
- }
91
- ),
92
- /* @__PURE__ */ t(s, { mb: "500", children: [
93
- /* @__PURE__ */ t(e, { variant: "small1", color: "text.secondary", mb: "300", children: [
94
- "현재 FPS: ",
95
- i.fps.toFixed(1)
96
- ] }),
97
- /* @__PURE__ */ r(
98
- s,
99
- {
100
- style: {
101
- height: "8px",
102
- backgroundColor: o.alpha[10],
103
- borderRadius: d[150],
104
- overflow: "hidden",
105
- position: "relative"
106
- },
107
- children: /* @__PURE__ */ r(
108
- u.div,
109
- {
110
- style: {
111
- height: "100%",
112
- backgroundColor: j(i.fps),
113
- borderRadius: d[150],
114
- position: "relative"
115
- },
116
- initial: { width: 0 },
117
- animate: { width: `${O(i.fps)}%` },
118
- transition: { duration: 0.4, ease: "easeOut" }
119
- }
120
- )
121
- }
122
- )
123
- ] }),
124
- /* @__PURE__ */ t(
125
- s,
126
- {
127
- mb: "600",
128
- style: {
129
- display: "grid",
130
- gridTemplateColumns: "1fr 1fr",
131
- gap: l[300],
132
- backgroundColor: o.alpha[5],
133
- padding: l[400],
134
- borderRadius: d[400],
135
- border: `1px solid ${o.alpha[20]}`
136
- },
137
- children: [
138
- /* @__PURE__ */ t("div", { children: [
139
- /* @__PURE__ */ r(e, { variant: "small1", color: "text.secondary", children: "평균 FPS" }),
140
- /* @__PURE__ */ r(e, { variant: "body1", fontWeight: 700, color: "text.primary", children: i.averageFPS.toFixed(1) })
141
- ] }),
142
- /* @__PURE__ */ t("div", { children: [
143
- /* @__PURE__ */ r(e, { variant: "small1", color: "text.secondary", children: "최소 FPS" }),
144
- /* @__PURE__ */ r(e, { variant: "body1", fontWeight: 700, color: "text.primary", children: i.minFPS.toFixed(1) })
145
- ] }),
146
- /* @__PURE__ */ t("div", { children: [
147
- /* @__PURE__ */ r(e, { variant: "small1", color: "text.secondary", children: "최대 FPS" }),
148
- /* @__PURE__ */ r(e, { variant: "body1", fontWeight: 700, color: "text.primary", children: i.maxFPS.toFixed(1) })
149
- ] }),
150
- /* @__PURE__ */ t("div", { children: [
151
- /* @__PURE__ */ r(e, { variant: "small1", color: "text.secondary", children: "프레임 수" }),
152
- /* @__PURE__ */ r(e, { variant: "body1", fontWeight: 700, color: "text.primary", children: i.frameCount })
153
- ] }),
154
- /* @__PURE__ */ t("div", { style: { gridColumn: "1 / -1" }, children: [
155
- /* @__PURE__ */ r(e, { variant: "small1", color: "text.secondary", children: "측정 시간" }),
156
- /* @__PURE__ */ t(e, { variant: "body1", fontWeight: 700, color: "text.primary", children: [
157
- (i.duration / 1e3).toFixed(1),
158
- "초"
159
- ] })
160
- ] })
161
- ]
162
- }
163
- )
164
- ] })
165
- }
166
- ) }),
167
- /* @__PURE__ */ r(C, { children: c !== null && /* @__PURE__ */ t(
168
- u.div,
169
- {
170
- initial: { opacity: 0 },
171
- animate: { opacity: 1 },
172
- exit: { opacity: 0 },
173
- transition: { duration: 0.2 },
174
- style: {
175
- width: "100%",
176
- marginTop: l[600],
177
- padding: l[400],
178
- backgroundColor: c ? o.alpha[10] : n.error.light,
179
- border: `1px solid ${c ? o.main : n.error.main}`,
180
- borderRadius: d[400],
181
- color: c ? o.main : n.error.dark,
182
- position: "relative",
183
- overflow: "hidden"
184
- },
185
- children: [
186
- /* @__PURE__ */ r(e, { variant: "body1", fontWeight: 700, children: c ? "60프레임 달성!" : "60프레임 미달성" }),
187
- /* @__PURE__ */ t(e, { variant: "small1", mt: "200", style: { opacity: 0.8 }, children: [
188
- "임계값: ",
189
- p,
190
- "fps"
191
- ] })
192
- ]
193
- }
194
- ) })
195
- ]
196
- }
197
- );
198
- }
199
- export {
200
- J as default
201
- };
@@ -1,116 +0,0 @@
1
- class u {
2
- startTime = 0;
3
- lastTime = 0;
4
- frameCount = 0;
5
- fpsHistory = [];
6
- animationId = null;
7
- isRunning = !1;
8
- options;
9
- onUpdate;
10
- onComplete;
11
- constructor(t = {}, e) {
12
- this.options = {
13
- duration: t.duration ?? 5e3,
14
- // 기본 5초
15
- sampleSize: t.sampleSize ?? 60,
16
- // 기본 60프레임 샘플
17
- callbackInterval: t.callbackInterval ?? 10
18
- // 기본 10프레임마다 콜백
19
- }, this.onUpdate = e?.onUpdate, this.onComplete = e?.onComplete;
20
- }
21
- /**
22
- * FPS 측정 시작
23
- */
24
- start() {
25
- if (this.isRunning) {
26
- console.warn("FPS 측정이 이미 실행 중입니다.");
27
- return;
28
- }
29
- this.isRunning = !0, this.startTime = performance.now(), this.lastTime = this.startTime, this.frameCount = 0, this.fpsHistory = [], this.animationId = requestAnimationFrame(this.measure.bind(this));
30
- }
31
- /**
32
- * FPS 측정 중지
33
- */
34
- stop() {
35
- if (!this.isRunning)
36
- throw new Error("FPS 측정이 실행 중이 아닙니다.");
37
- return this.isRunning = !1, this.animationId && (cancelAnimationFrame(this.animationId), this.animationId = null), this.getMetrics();
38
- }
39
- /**
40
- * 현재 측정 중인지 확인
41
- */
42
- get running() {
43
- return this.isRunning;
44
- }
45
- /**
46
- * 현재까지의 측정 결과 반환
47
- */
48
- getMetrics() {
49
- const e = performance.now() - this.startTime, i = this.frameCount > 0 ? this.frameCount / e * 1e3 : 0, h = this.fpsHistory.length > 0 ? this.fpsHistory.reduce((m, o) => m + o, 0) / this.fpsHistory.length : i, s = this.fpsHistory.length > 0 ? Math.min(...this.fpsHistory) : i, r = this.fpsHistory.length > 0 ? Math.max(...this.fpsHistory) : i;
50
- return {
51
- fps: i,
52
- averageFPS: h,
53
- minFPS: s,
54
- maxFPS: r,
55
- frameCount: this.frameCount,
56
- duration: e
57
- };
58
- }
59
- measure(t) {
60
- if (this.isRunning) {
61
- if (this.frameCount++, t - this.lastTime >= 1e3) {
62
- const e = this.frameCount / (t - this.startTime) * 1e3;
63
- this.fpsHistory.push(e), this.fpsHistory.length > this.options.sampleSize && this.fpsHistory.shift(), this.lastTime = t;
64
- }
65
- if (this.frameCount % this.options.callbackInterval === 0 && this.onUpdate?.(this.getMetrics()), t - this.startTime >= this.options.duration) {
66
- this.stop(), this.onComplete?.(this.getMetrics());
67
- return;
68
- }
69
- this.animationId = requestAnimationFrame(this.measure.bind(this));
70
- }
71
- }
72
- }
73
- function f(n = 5e3) {
74
- return new Promise((t) => {
75
- new u({ duration: n }, { onComplete: t }).start();
76
- });
77
- }
78
- function p(n, t = {}) {
79
- const e = new u(t, { onUpdate: n });
80
- return e.start(), e;
81
- }
82
- function l() {
83
- return new Promise((n, t) => {
84
- if (!("PerformanceObserver" in window)) {
85
- t(new Error("PerformanceObserver를 지원하지 않는 브라우저입니다."));
86
- return;
87
- }
88
- const e = new PerformanceObserver((i) => {
89
- const s = i.getEntries().filter((r) => r.entryType === "frame");
90
- if (s.length > 0) {
91
- const r = s.map((a) => a.duration), o = 1e3 / (r.reduce((a, c) => a + c, 0) / r.length);
92
- e.disconnect(), n({
93
- fps: o,
94
- averageFPS: o,
95
- minFPS: o,
96
- maxFPS: o,
97
- frameCount: s.length,
98
- duration: s[s.length - 1].startTime - s[0].startTime
99
- });
100
- }
101
- });
102
- try {
103
- e.observe({ entryTypes: ["frame"] }), setTimeout(() => {
104
- e.disconnect(), t(new Error("측정 시간이 초과되었습니다."));
105
- }, 3e3);
106
- } catch (i) {
107
- t(i);
108
- }
109
- });
110
- }
111
- export {
112
- u as FPSChecker,
113
- f as measureFPS,
114
- l as measureFPSWithPerformanceAPI,
115
- p as monitorFPS
116
- };
@@ -1,4 +0,0 @@
1
- import r from "./FPSMonitor.mjs";
2
- export {
3
- r as default
4
- };