Skip to content

Commit

Permalink
bum
Browse files Browse the repository at this point in the history
  • Loading branch information
aidenybai committed Dec 27, 2024
1 parent a7a3abe commit 5a630db
Show file tree
Hide file tree
Showing 8 changed files with 280 additions and 160 deletions.
1 change: 1 addition & 0 deletions kitchen-sink/src/index.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import ReactDOM from "react-dom/client";
import "./main.css";

const PROJECT = "mini-react-scan";

Expand Down
180 changes: 111 additions & 69 deletions kitchen-sink/src/mini-react-scan.jsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
import { instrument, getNearestHostFiber, createFiberVisitor } from "bippy"; // must be imported BEFORE react
import React, { useState } from "react";
import React, { useState, createContext } from "react";
import * as BippyScan from "bippy/dist/scan/index";

const highlightFiber = (fiber) => {
if (!(fiber.stateNode instanceof HTMLElement)) return;

const rect = fiber.stateNode.getBoundingClientRect();
const highlight = document.createElement("div");
highlight.style.border = "1px solid red";
highlight.style.position = "fixed";
highlight.style.top = `${rect.top}px`;
highlight.style.left = `${rect.left}px`;
highlight.style.width = `${rect.width}px`;
highlight.style.height = `${rect.height}px`;
highlight.style.zIndex = 999999999;
document.documentElement.appendChild(highlight);
setTimeout(() => {
document.documentElement.removeChild(highlight);
}, 100);
};

// const visit = createFiberVisitor({
// onRender(fiber) {
// // const hostFiber = getNearestHostFiber(fiber);
Expand All @@ -36,61 +17,122 @@ const highlightFiber = (fiber) => {

console.log(BippyScan);

export default function TodoList() {
const [todos, setTodos] = useState([]);
const [input, setInput] = useState("");
const TooltipContext = createContext({ tooltip: "" });

const addTodo = () => {
setTodos([...todos, { text: input, completed: false }]);
setInput("");
};
export const App = () => {
const [tasks, setTasks] = useState([]);

const toggleComplete = (index) => {
setTodos(
todos.map((todo, i) =>
i === index ? { ...todo, completed: !todo.completed } : todo,
),
);
};
return (
<TooltipContext.Provider value={{ tooltip: "Hello" }}>
<div className="p-16 text-xs">
<div className="main-content">
<nav className="navbar">
<a href="/" className="navbar-brand">
<h3>
<strong style={{ fontFamily: "Geist Mono, monospace" }}>
React Scan
</strong>
</h3>
</a>
</nav>

const deleteTodo = (index) => {
setTodos(todos.filter((_, i) => i !== index));
};
<div className="task-section">
<AddTaskBar
onCreate={(value) => {
if (!value) return;
setTasks([...tasks, value]);
}}
/>
<TaskList
tasks={tasks}
onDelete={(value) =>
setTasks(tasks.filter((task) => task !== value))
}
/>
</div>
</div>
</div>
</TooltipContext.Provider>
);
};

React.useEffect(() => {
console.log("useEffect");
}, []);
export const TaskList = ({ tasks, onDelete }) => {
return (
<ul className="mt-4 list-disc pl-4">
{tasks.map((task) => (
<TaskItem key={task} task={task} onDelete={onDelete} />
))}
</ul>
);
};

export const TaskItem = ({ task, onDelete }) => {
const { tooltip } = React.useContext(TooltipContext);
return (
<div>
<h2>Todo List</h2>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && addTodo()}
<li className="task-item" tooltip={tooltip}>
{task}
<Button onClick={() => onDelete(task)}>Delete</Button>
</li>
);
};

export const Text = ({ children }) => {
return <span>{children}</span>;
};

export const Button = ({ onClick, children }) => {
return (
<button
type="button"
className="ml-2 border border-gray-300 bg-black text-white rounded-md p-2"
onClick={onClick}
>
<Text>{children}</Text>
</button>
);
};

export const AddTaskBar = ({ onCreate }) => {
const [value, setValue] = useState("");
const [id, setId] = useState(0);
return (
<div className="add-task-container flex">
<Input
onChange={(value) => setValue(value)}
onEnter={(value) => {
onCreate(`${value} (${id})`);
setValue("");
setId(id + 1);
}}
value={value}
/>
<button type="button" onClick={addTodo}>
Add Todo
</button>
<ul>
{todos.map((todo, index) => (
<li key={todo.id}>
<span
onClick={() => toggleComplete(index)}
onKeyDown={(e) => e.key === "Enter" && toggleComplete(index)}
style={{
textDecoration: todo.completed ? "line-through" : "none",
cursor: "pointer",
}}
>
{todo.text}
</span>
<button type="button" onClick={() => deleteTodo(index)}>
Delete
</button>
</li>
))}
</ul>
<Button
onClick={() => {
onCreate(value);
setValue("");
}}
>
Add Task
</Button>
</div>
);
}
};

export const Input = ({ onChange, onEnter, value }) => {
return (
<input
type="text"
className="border border-gray-300 rounded-md p-2"
placeholder="Today I will..."
onChange={(e) => onChange(e.target.value)}
onKeyDown={(e) => {
if (e.key === "Enter") {
onEnter(e.target.value);
}
}}
value={value}
/>
);
};

export default App;
24 changes: 12 additions & 12 deletions src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,20 +517,20 @@ export const getNearestHostFiber = (fiber: Fiber, ascending = false) => {
*/
export const getNearestHostFibers = (fiber: Fiber) => {
const hostFibers: Fiber[] = [];
const stack: Fiber[] = [fiber];

const traverse = (node: Fiber | null) => {
let currentNode = node;
while (currentNode) {
if (isHostFiber(currentNode)) {
hostFibers.push(currentNode);
} else if (currentNode.child) {
traverse(currentNode.child);
}
currentNode = currentNode.sibling;
while (stack.length) {
const currentNode = stack.pop();
if (!currentNode) break;
if (isHostFiber(currentNode)) {
hostFibers.push(currentNode);
} else if (currentNode.child) {
stack.push(currentNode.child);
}
};

traverse(fiber);
if (currentNode.sibling) {
stack.push(currentNode.sibling);
}
}

return hostFibers;
};
Expand Down
20 changes: 20 additions & 0 deletions src/scan/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# react scan v1 architecture

- `bippy`
- `@react-scan/web-instrumentation`: web instrumentation, export API for renders, types of renders, FPS, CWV
- `react-scan`:
- web highlighting overlay
- web toolbar
- `@react-scan/playwright`:
- playwright plugin (... for each testing lib)
- `@react-scan/sdk`:
- observability sdk
- `@react-scan/native-instrumentation`: native instrumentation, export API for renders, types of renders, FPS, CWV
- `@react-scan/native`:
- native highlighting overlay
- native toolbar

## todo

- [ ] backwards compatibility (for worker, offscreen canvas)
- [ ] feature compat with existing version (core, instrumentation, highlighting)
Loading

0 comments on commit 5a630db

Please sign in to comment.