lynx-console 0.0.1 → 0.1.1

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.
Files changed (26) hide show
  1. package/dist/assets/src/components/{BottomSheet.css.ts.vanilla-D-1A77Ik.css → BottomSheet.css.ts.vanilla-CulwSDhG.css} +2 -2
  2. package/dist/assets/src/components/ConsolePanel.css.ts.vanilla-DWdhFBJq.css +337 -0
  3. package/dist/assets/src/components/FadeList.css.ts.vanilla-sppTKMZj.css +12 -0
  4. package/dist/assets/src/components/{FloatingButton.css.ts.vanilla-rPj35oLW.css → FloatingButton.css.ts.vanilla-BaG0OI6p.css} +15 -3
  5. package/dist/assets/src/components/{NetworkPanel.css.ts.vanilla-DFMduT0T.css → NetworkPanel.css.ts.vanilla-BSE4s40D.css} +2 -5
  6. package/dist/assets/src/components/{PerformancePanel.css.ts.vanilla-D35LuXlW.css → PerformancePanel.css.ts.vanilla-Bb3zG5G8.css} +2 -2
  7. package/dist/index.cjs +743 -84
  8. package/dist/index.mjs +743 -84
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +1 -1
  11. package/src/components/BottomSheet.css.ts +2 -2
  12. package/src/components/ConsolePanel.css.ts +104 -16
  13. package/src/components/ConsolePanel.tsx +2 -1
  14. package/src/components/FadeList.css.ts +16 -0
  15. package/src/components/FadeList.tsx +76 -0
  16. package/src/components/FloatingButton.css.ts +15 -4
  17. package/src/components/FloatingButton.tsx +46 -10
  18. package/src/components/LogPanel.tsx +128 -15
  19. package/src/components/NetworkPanel.css.ts +2 -5
  20. package/src/components/NetworkPanel.tsx +4 -4
  21. package/src/components/PerformancePanel.css.ts +2 -2
  22. package/src/components/PerformancePanel.tsx +5 -5
  23. package/src/components/Tabs.tsx +3 -0
  24. package/src/hooks/useLongPressDrag.ts +95 -0
  25. package/src/index.tsx +1 -1
  26. package/dist/assets/src/components/ConsolePanel.css.ts.vanilla-B3avfSlI.css +0 -246
@@ -1,6 +1,7 @@
1
1
  import { useState } from "@lynx-js/react";
2
2
  import { stringify } from "javascript-stringify";
3
3
  import type { PerformanceEntryData } from "../types";
4
+ import { FadeList } from "./FadeList";
4
5
  import * as css from "./PerformancePanel.css";
5
6
 
6
7
  interface PerformancePanelProps {
@@ -65,7 +66,6 @@ export const PerformancePanel = ({
65
66
  clearPerformances,
66
67
  }: PerformancePanelProps) => {
67
68
  const [selectedId, setSelectedId] = useState<string | null>(null);
68
-
69
69
  if (performances.length === 0) {
70
70
  return (
71
71
  <view className={css.container}>
@@ -80,7 +80,7 @@ export const PerformancePanel = ({
80
80
  <text>Log</text>
81
81
  </view>
82
82
  <view bindtap={clearPerformances} className={css.clearButton}>
83
- <text className={css.clearButtonText}>Clear</text>
83
+ <text className={css.clearButtonText}>🗑</text>
84
84
  </view>
85
85
  </view>
86
86
  <view className={css.placeholder}>
@@ -97,11 +97,11 @@ export const PerformancePanel = ({
97
97
  <view className={css.header}>
98
98
  <text className={css.count}>{performances.length} entries</text>
99
99
  <view bindtap={clearPerformances} className={css.clearButton}>
100
- <text className={css.clearButtonText}>Clear</text>
100
+ <text className={css.clearButtonText}>🗑</text>
101
101
  </view>
102
102
  </view>
103
103
 
104
- <list className={css.list}>
104
+ <FadeList className={css.list}>
105
105
  {performances.map((perf) => {
106
106
  const isMetricFcp = isMetricFcpEntry(perf);
107
107
  const fcpMetrics = extractFcpMetrics(perf);
@@ -203,7 +203,7 @@ export const PerformancePanel = ({
203
203
  </list-item>
204
204
  );
205
205
  })}
206
- </list>
206
+ </FadeList>
207
207
  </view>
208
208
  );
209
209
  };
@@ -8,6 +8,7 @@ type TabsProps = {
8
8
  label: string;
9
9
  renderContent: () => ReactNode;
10
10
  }>;
11
+ onTabChange?: () => void;
11
12
  };
12
13
 
13
14
  export default function Tabs(props: TabsProps) {
@@ -23,6 +24,7 @@ export default function Tabs(props: TabsProps) {
23
24
  className={css.tabTriggerButton}
24
25
  bindtap={() => {
25
26
  setActiveIndex(i);
27
+ props.onTabChange?.();
26
28
 
27
29
  tabContentsRef.current
28
30
  ?.invoke({
@@ -59,6 +61,7 @@ export default function Tabs(props: TabsProps) {
59
61
  className={css.tabContents}
60
62
  scroll-orientation="horizontal"
61
63
  item-snap={{ factor: 0, offset: 0 }}
64
+ bindscroll={() => props.onTabChange?.()}
62
65
  bindsnap={(e: ListSnapEvent) => {
63
66
  setActiveIndex(e.detail.position);
64
67
  }}
@@ -0,0 +1,95 @@
1
+ import { useRef, useState } from "@lynx-js/react";
2
+ import type { BaseTouchEvent, Target } from "@lynx-js/types";
3
+
4
+ const LONG_PRESS_DURATION = 400;
5
+ const MOVE_THRESHOLD = 5;
6
+
7
+ const DEFAULT_RIGHT = 16;
8
+ const DEFAULT_BOTTOM = 84;
9
+
10
+ let savedRight = DEFAULT_RIGHT;
11
+ let savedBottom = DEFAULT_BOTTOM;
12
+
13
+ export function useLongPressDrag(onTap: () => void) {
14
+ const [right, setRight] = useState(savedRight);
15
+ const [bottom, setBottom] = useState(savedBottom);
16
+ const [phase, setPhase] = useState<"idle" | "dragging" | "releasing">("idle");
17
+ const [tempRight, setTempRight] = useState(savedRight);
18
+ const [tempBottom, setTempBottom] = useState(savedBottom);
19
+
20
+ const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
21
+ const draggingRef = useRef(false);
22
+ const startRef = useRef({ x: 0, y: 0, r: 0, b: 0 });
23
+
24
+ const clearTimer = () => {
25
+ if (timerRef.current) {
26
+ clearTimeout(timerRef.current);
27
+ timerRef.current = null;
28
+ }
29
+ };
30
+
31
+ const handleTouchStart = (e: BaseTouchEvent<Target>) => {
32
+ startRef.current = {
33
+ x: e.detail.x,
34
+ y: e.detail.y,
35
+ r: right,
36
+ b: bottom,
37
+ };
38
+ draggingRef.current = false;
39
+
40
+ timerRef.current = setTimeout(() => {
41
+ draggingRef.current = true;
42
+ setPhase("dragging");
43
+ setTempRight(right);
44
+ setTempBottom(bottom);
45
+ }, LONG_PRESS_DURATION);
46
+ };
47
+
48
+ const handleTouchMove = (e: BaseTouchEvent<Target>) => {
49
+ const dx = e.detail.x - startRef.current.x;
50
+ const dy = e.detail.y - startRef.current.y;
51
+
52
+ if (
53
+ !draggingRef.current &&
54
+ (Math.abs(dx) > MOVE_THRESHOLD || Math.abs(dy) > MOVE_THRESHOLD)
55
+ ) {
56
+ clearTimer();
57
+ }
58
+
59
+ if (!draggingRef.current) return;
60
+
61
+ // right/bottom 기준이므로 방향 반전
62
+ setTempRight(startRef.current.r - dx);
63
+ setTempBottom(startRef.current.b - dy);
64
+ };
65
+
66
+ const handleTouchEnd = () => {
67
+ clearTimer();
68
+
69
+ if (draggingRef.current) {
70
+ setRight(tempRight);
71
+ setBottom(tempBottom);
72
+ savedRight = tempRight;
73
+ savedBottom = tempBottom;
74
+ setPhase("releasing");
75
+ draggingRef.current = false;
76
+ setTimeout(() => setPhase("idle"), 300);
77
+ } else {
78
+ onTap();
79
+ }
80
+ };
81
+
82
+ const isDragging = phase === "dragging";
83
+
84
+ return {
85
+ phase,
86
+ right: isDragging ? tempRight : right,
87
+ bottom: isDragging ? tempBottom : bottom,
88
+ clearTimer,
89
+ handlers: {
90
+ catchtouchstart: handleTouchStart,
91
+ catchtouchmove: handleTouchMove,
92
+ catchtouchend: handleTouchEnd,
93
+ },
94
+ };
95
+ }
package/src/index.tsx CHANGED
@@ -85,7 +85,7 @@ const LynxConsole = forwardRef<LynxConsoleHandle, LynxConsoleProps>(
85
85
 
86
86
  return (
87
87
  <view className={themeClass}>
88
- <FloatingButton bindtap={handleOpenBottomSheet} isVisible={!isOpen}>
88
+ <FloatingButton bindtap={handleOpenBottomSheet}>
89
89
  <text className={floatingButtonCss.title}>LynxConsole</text>
90
90
  <text className={floatingButtonCss.subtitle}>
91
91
  {`${latestFcp?.name ?? "FCP"}: ${latestFcp?.duration ? latestFcp.duration.toFixed(2) : "--"}ms`}
@@ -1,246 +0,0 @@
1
- .ConsolePanel_container__db6kuu0 {
2
- display: flex;
3
- flex-direction: column;
4
- height: 100%;
5
- }
6
- .ConsolePanel_placeholder__db6kuu1 {
7
- display: flex;
8
- align-items: center;
9
- justify-content: center;
10
- height: 100%;
11
- }
12
- .ConsolePanel_placeholderText__db6kuu2 {
13
- font-size: 0.875rem;
14
- line-height: 1.1875rem;
15
- font-weight: var(--seed-font-weight-regular);
16
- color: var(--seed-color-fg-disabled);
17
- }
18
- .ConsolePanel_logContainer__db6kuu3 {
19
- display: flex;
20
- flex-direction: column;
21
- flex: 1;
22
- padding-top: 4px;
23
- }
24
- .ConsolePanel_logHeader__db6kuu4 {
25
- display: flex;
26
- flex-direction: row;
27
- align-items: center;
28
- justify-content: space-between;
29
- margin-bottom: 8px;
30
- padding-bottom: 4px;
31
- border-bottom-width: 1px;
32
- border-bottom-color: var(--seed-color-stroke-neutral-subtle);
33
- border-bottom-style: solid;
34
- }
35
- .ConsolePanel_logCount__db6kuu5 {
36
- font-size: 0.8125rem;
37
- line-height: 1.125rem;
38
- font-weight: var(--seed-font-weight-regular);
39
- color: var(--seed-color-fg-neutral-subtle);
40
- }
41
- .ConsolePanel_clearButton__db6kuu6 {
42
- padding: 6px 12px;
43
- background-color: var(--seed-color-bg-neutral-weak);
44
- border-radius: 4px;
45
- }
46
- .ConsolePanel_clearButtonText__db6kuu7 {
47
- font-size: 0.8125rem;
48
- line-height: 1.125rem;
49
- font-weight: var(--seed-font-weight-medium);
50
- color: var(--seed-color-fg-neutral);
51
- }
52
- .ConsolePanel_logList__db6kuu8 {
53
- flex: 1;
54
- }
55
- .ConsolePanel_logItem__db6kuu9 {
56
- padding: 8px;
57
- border-bottom-width: 1px;
58
- border-bottom-color: var(--seed-color-stroke-neutral-weak);
59
- border-bottom-style: solid;
60
- }
61
- .ConsolePanel_logItem_level_warn__db6kuuc {
62
- background-color: var(--seed-color-palette-yellow-100);
63
- }
64
- .ConsolePanel_logItem_level_error__db6kuud {
65
- background-color: var(--seed-color-palette-red-100);
66
- }
67
- .ConsolePanel_logItemHeader__db6kuue {
68
- display: flex;
69
- flex-direction: row;
70
- align-items: center;
71
- margin-bottom: 4px;
72
- }
73
- .ConsolePanel_logLevel__db6kuuf {
74
- font-size: 0.75rem;
75
- line-height: 1rem;
76
- font-weight: var(--seed-font-weight-bold);
77
- margin-right: 8px;
78
- }
79
- .ConsolePanel_logLevel_level_log__db6kuug {
80
- color: var(--seed-color-palette-green-600);
81
- }
82
- .ConsolePanel_logLevel_level_info__db6kuuh {
83
- color: var(--seed-color-palette-blue-600);
84
- }
85
- .ConsolePanel_logLevel_level_warn__db6kuui {
86
- color: var(--seed-color-palette-yellow-600);
87
- }
88
- .ConsolePanel_logLevel_level_error__db6kuuj {
89
- color: var(--seed-color-palette-red-600);
90
- }
91
- .ConsolePanel_logTime__db6kuuk {
92
- font-size: 0.75rem;
93
- line-height: 1rem;
94
- font-weight: var(--seed-font-weight-regular);
95
- color: var(--seed-color-fg-neutral-subtle);
96
- }
97
- .ConsolePanel_toggleIndicator__db6kuul {
98
- font-size: 0.75rem;
99
- line-height: 1rem;
100
- font-weight: var(--seed-font-weight-regular);
101
- color: var(--seed-color-fg-neutral-subtle);
102
- margin-left: 4px;
103
- align-self: flex-start;
104
- }
105
- .ConsolePanel_logMessage__db6kuum {
106
- font-size: 0.8125rem;
107
- line-height: 1.125rem;
108
- font-weight: var(--seed-font-weight-regular);
109
- color: var(--seed-color-fg-neutral);
110
- word-break: break-all;
111
- }
112
- .ConsolePanel_logArgsContainer__db6kuun {
113
- display: flex;
114
- flex-direction: row;
115
- flex-wrap: wrap;
116
- gap: 8px;
117
- }
118
- .ConsolePanel_logArgItem__db6kuuo {
119
- font-size: 0.8125rem;
120
- line-height: 1.125rem;
121
- font-weight: var(--seed-font-weight-regular);
122
- }
123
- .ConsolePanel_argNull__db6kuup {
124
- color: var(--seed-color-fg-neutral-subtle);
125
- }
126
- .ConsolePanel_argUndefined__db6kuuq {
127
- color: var(--seed-color-fg-neutral-subtle);
128
- }
129
- .ConsolePanel_argString__db6kuur {
130
- font-size: 0.8125rem;
131
- line-height: 1.125rem;
132
- font-weight: var(--seed-font-weight-regular);
133
- }
134
- .ConsolePanel_argString_level_log__db6kuus {
135
- color: var(--seed-color-fg-neutral);
136
- }
137
- .ConsolePanel_argString_level_info__db6kuut {
138
- color: var(--seed-color-fg-neutral);
139
- }
140
- .ConsolePanel_argString_level_warn__db6kuuu {
141
- color: var(--seed-color-palette-yellow-900);
142
- }
143
- .ConsolePanel_argString_level_error__db6kuuv {
144
- color: var(--seed-color-palette-red-900);
145
- }
146
- .ConsolePanel_argPrimitive__db6kuuw {
147
- font-size: 0.8125rem;
148
- line-height: 1.125rem;
149
- font-weight: var(--seed-font-weight-regular);
150
- }
151
- .ConsolePanel_argPrimitive_level_log__db6kuux {
152
- color: var(--seed-color-palette-blue-600);
153
- }
154
- .ConsolePanel_argPrimitive_level_info__db6kuuy {
155
- color: var(--seed-color-palette-blue-600);
156
- }
157
- .ConsolePanel_argPrimitive_level_warn__db6kuuz {
158
- color: var(--seed-color-palette-yellow-900);
159
- }
160
- .ConsolePanel_argPrimitive_level_error__db6kuu10 {
161
- color: var(--seed-color-palette-red-900);
162
- }
163
- .ConsolePanel_argObject__db6kuu11 {
164
- display: flex;
165
- flex-direction: column;
166
- }
167
- .ConsolePanel_argObjectHeader__db6kuu12 {
168
- display: flex;
169
- flex-direction: row;
170
- align-items: center;
171
- gap: 4px;
172
- }
173
- .ConsolePanel_argObjectPreview__db6kuu13 {
174
- font-size: 0.8125rem;
175
- line-height: 1.125rem;
176
- font-weight: var(--seed-font-weight-medium);
177
- color: var(--seed-color-fg-neutral);
178
- }
179
- .ConsolePanel_argObjectContent__db6kuu14 {
180
- margin-top: 4px;
181
- display: flex;
182
- flex-direction: column;
183
- gap: 4px;
184
- }
185
- .ConsolePanel_argObjectProperty__db6kuu15 {
186
- display: flex;
187
- flex-direction: row;
188
- align-items: flex-start;
189
- }
190
- .ConsolePanel_argObjectKey__db6kuu16 {
191
- font-size: 0.8125rem;
192
- line-height: 1.125rem;
193
- font-weight: var(--seed-font-weight-medium);
194
- color: var(--seed-color-palette-purple-600);
195
- }
196
- .ConsolePanel_argObjectJson__db6kuu17 {
197
- font-size: 0.8125rem;
198
- line-height: 1.125rem;
199
- font-weight: var(--seed-font-weight-regular);
200
- color: var(--seed-color-fg-neutral);
201
- }
202
- .ConsolePanel_replInputRow__db6kuu18 {
203
- display: flex;
204
- flex-direction: row;
205
- align-items: center;
206
- gap: 8px;
207
- padding-top: 8px;
208
- padding-bottom: 8px;
209
- margin-top: -1px;
210
- border-top-width: 1px;
211
- border-top-color: var(--seed-color-stroke-neutral-subtle);
212
- border-top-style: solid;
213
- background-image: linear-gradient(to bottom, transparent, var(--seed-color-bg-layer-default));
214
- background-size: 100% 32px;
215
- background-repeat: no-repeat;
216
- background-position: top;
217
- background-color: var(--seed-color-bg-layer-default);
218
- }
219
- .ConsolePanel_replPrompt__db6kuu19 {
220
- font-size: 1.625rem;
221
- line-height: 2.1875rem;
222
- font-weight: var(--seed-font-weight-medium);
223
- color: var(--seed-color-fg-placeholder);
224
- padding-bottom: 8px;
225
- }
226
- .ConsolePanel_replInput__db6kuu1a {
227
- flex: 1;
228
- font-size: 1rem;
229
- line-height: 1.375rem;
230
- font-weight: var(--seed-font-weight-regular);
231
- color: var(--seed-color-fg-neutral);
232
- caret-color: var(--seed-color-palette-green-600);
233
- padding-bottom: 8px;
234
- }
235
- .ConsolePanel_replRunButton__db6kuu1b {
236
- padding: 4px 10px;
237
- background-color: var(--seed-color-palette-green-100);
238
- border-radius: 4px;
239
- margin-bottom: 8px;
240
- }
241
- .ConsolePanel_replRunButtonText__db6kuu1c {
242
- font-size: 0.8125rem;
243
- line-height: 1.125rem;
244
- font-weight: var(--seed-font-weight-medium);
245
- color: var(--seed-color-palette-green-600);
246
- }