Spaces:
Running
Running
added cleaner react view
Browse files- index.html +1 -1
- package.json +2 -2
- src/SelectionApp.tsx +67 -33
- src/main.tsx +9 -9
index.html
CHANGED
|
@@ -7,6 +7,6 @@
|
|
| 7 |
</head>
|
| 8 |
<body>
|
| 9 |
<div id="root"></div>
|
| 10 |
-
|
| 11 |
</body>
|
| 12 |
</html>
|
|
|
|
| 7 |
</head>
|
| 8 |
<body>
|
| 9 |
<div id="root"></div>
|
| 10 |
+
<script type="module" src="/src/main.tsx"></script>
|
| 11 |
</body>
|
| 12 |
</html>
|
package.json
CHANGED
|
@@ -10,8 +10,8 @@
|
|
| 10 |
"preview": "vite preview"
|
| 11 |
},
|
| 12 |
"dependencies": {
|
| 13 |
-
"react": "^19.
|
| 14 |
-
"react-dom": "^19.
|
| 15 |
},
|
| 16 |
"devDependencies": {
|
| 17 |
"@eslint/js": "^9.21.0",
|
|
|
|
| 10 |
"preview": "vite preview"
|
| 11 |
},
|
| 12 |
"dependencies": {
|
| 13 |
+
"react": "^19.1.1",
|
| 14 |
+
"react-dom": "^19.1.1"
|
| 15 |
},
|
| 16 |
"devDependencies": {
|
| 17 |
"@eslint/js": "^9.21.0",
|
src/SelectionApp.tsx
CHANGED
|
@@ -51,7 +51,7 @@ const SelectionApp: React.FC = () => {
|
|
| 51 |
const end = start + selectedText.length;
|
| 52 |
|
| 53 |
const newSpan: Span = { span_text: selectedText, start, end };
|
| 54 |
-
setSpans((prev) => [newSpan, ...prev]
|
| 55 |
};
|
| 56 |
|
| 57 |
const renderSpans = () => {
|
|
@@ -71,34 +71,56 @@ const SelectionApp: React.FC = () => {
|
|
| 71 |
};
|
| 72 |
|
| 73 |
return (
|
| 74 |
-
<div
|
| 75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
{/* Settings Panel */}
|
| 78 |
<div
|
| 79 |
style={{
|
| 80 |
-
marginBottom: "
|
| 81 |
-
padding: "
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
| 86 |
}}
|
| 87 |
>
|
| 88 |
-
<strong>
|
| 89 |
-
<br />
|
| 90 |
-
<br />
|
| 91 |
<label>
|
| 92 |
-
Span Text
|
| 93 |
-
<input
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
</label>
|
| 95 |
-
<label
|
| 96 |
-
Start
|
| 97 |
-
<input
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
</label>
|
| 99 |
-
<label
|
| 100 |
-
End
|
| 101 |
-
<input
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
</label>
|
| 103 |
</div>
|
| 104 |
|
|
@@ -108,23 +130,34 @@ const SelectionApp: React.FC = () => {
|
|
| 108 |
contentEditable
|
| 109 |
onInput={handleInput}
|
| 110 |
style={{
|
| 111 |
-
width: "
|
| 112 |
-
minHeight: "
|
| 113 |
-
maxHeight: "
|
| 114 |
border: "1px solid #ccc",
|
| 115 |
-
|
|
|
|
| 116 |
whiteSpace: "pre-wrap",
|
| 117 |
overflowWrap: "break-word",
|
| 118 |
-
overflowY: "auto",
|
| 119 |
-
resize: "vertical",
|
|
|
|
|
|
|
|
|
|
| 120 |
}}
|
| 121 |
-
>
|
| 122 |
-
Paste or type your text here...
|
| 123 |
-
</div>
|
| 124 |
|
| 125 |
<button
|
| 126 |
onClick={getSelectionIndices}
|
| 127 |
-
style={{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
>
|
| 129 |
Get Selection JSON
|
| 130 |
</button>
|
|
@@ -132,14 +165,15 @@ const SelectionApp: React.FC = () => {
|
|
| 132 |
{/* Display JSON */}
|
| 133 |
<pre
|
| 134 |
style={{
|
| 135 |
-
marginTop: "
|
| 136 |
fontFamily: "monospace",
|
| 137 |
background: "#f4f4f4",
|
| 138 |
-
padding: "
|
| 139 |
-
borderRadius: "
|
| 140 |
border: "1px solid #ddd",
|
| 141 |
whiteSpace: "pre-wrap",
|
| 142 |
userSelect: "text",
|
|
|
|
| 143 |
}}
|
| 144 |
>
|
| 145 |
{spans.length ? JSON.stringify(renderSpans(), null, 2) : ""}
|
|
|
|
| 51 |
const end = start + selectedText.length;
|
| 52 |
|
| 53 |
const newSpan: Span = { span_text: selectedText, start, end };
|
| 54 |
+
setSpans((prev) => [newSpan, ...prev]);
|
| 55 |
};
|
| 56 |
|
| 57 |
const renderSpans = () => {
|
|
|
|
| 71 |
};
|
| 72 |
|
| 73 |
return (
|
| 74 |
+
<div
|
| 75 |
+
style={{
|
| 76 |
+
maxWidth: "900px",
|
| 77 |
+
margin: "40px auto",
|
| 78 |
+
fontFamily: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif",
|
| 79 |
+
color: "#333",
|
| 80 |
+
}}
|
| 81 |
+
>
|
| 82 |
+
<h2 style={{ textAlign: "center", marginBottom: "25px", color: "#1a73e8" }}>
|
| 83 |
+
Span Annotation App
|
| 84 |
+
</h2>
|
| 85 |
|
| 86 |
{/* Settings Panel */}
|
| 87 |
<div
|
| 88 |
style={{
|
| 89 |
+
marginBottom: "20px",
|
| 90 |
+
padding: "15px 20px",
|
| 91 |
+
borderRadius: "10px",
|
| 92 |
+
background: "#f9f9f9",
|
| 93 |
+
boxShadow: "0 2px 6px rgba(0,0,0,0.1)",
|
| 94 |
+
display: "flex",
|
| 95 |
+
flexWrap: "wrap",
|
| 96 |
+
gap: "10px",
|
| 97 |
+
alignItems: "center",
|
| 98 |
}}
|
| 99 |
>
|
| 100 |
+
<strong>Key Names:</strong>
|
|
|
|
|
|
|
| 101 |
<label>
|
| 102 |
+
Span Text:
|
| 103 |
+
<input
|
| 104 |
+
value={keySpan}
|
| 105 |
+
onChange={(e) => setKeySpan(e.target.value)}
|
| 106 |
+
style={{ marginLeft: "5px", padding: "4px 8px", borderRadius: "4px", border: "1px solid #ccc" }}
|
| 107 |
+
/>
|
| 108 |
</label>
|
| 109 |
+
<label>
|
| 110 |
+
Start:
|
| 111 |
+
<input
|
| 112 |
+
value={keyStart}
|
| 113 |
+
onChange={(e) => setKeyStart(e.target.value)}
|
| 114 |
+
style={{ marginLeft: "5px", padding: "4px 8px", borderRadius: "4px", border: "1px solid #ccc" }}
|
| 115 |
+
/>
|
| 116 |
</label>
|
| 117 |
+
<label>
|
| 118 |
+
End:
|
| 119 |
+
<input
|
| 120 |
+
value={keyEnd}
|
| 121 |
+
onChange={(e) => setKeyEnd(e.target.value)}
|
| 122 |
+
style={{ marginLeft: "5px", padding: "4px 8px", borderRadius: "4px", border: "1px solid #ccc" }}
|
| 123 |
+
/>
|
| 124 |
</label>
|
| 125 |
</div>
|
| 126 |
|
|
|
|
| 130 |
contentEditable
|
| 131 |
onInput={handleInput}
|
| 132 |
style={{
|
| 133 |
+
width: "100%",
|
| 134 |
+
minHeight: "180px",
|
| 135 |
+
maxHeight: "450px",
|
| 136 |
border: "1px solid #ccc",
|
| 137 |
+
borderRadius: "10px",
|
| 138 |
+
padding: "12px",
|
| 139 |
whiteSpace: "pre-wrap",
|
| 140 |
overflowWrap: "break-word",
|
| 141 |
+
overflowY: "auto",
|
| 142 |
+
resize: "vertical",
|
| 143 |
+
boxShadow: "inset 0 2px 6px rgba(0,0,0,0.05)",
|
| 144 |
+
fontSize: "16px",
|
| 145 |
+
lineHeight: "1.5",
|
| 146 |
}}
|
| 147 |
+
></div>
|
|
|
|
|
|
|
| 148 |
|
| 149 |
<button
|
| 150 |
onClick={getSelectionIndices}
|
| 151 |
+
style={{
|
| 152 |
+
marginTop: "15px",
|
| 153 |
+
padding: "10px 20px",
|
| 154 |
+
backgroundColor: "#1a73e8",
|
| 155 |
+
color: "#fff",
|
| 156 |
+
border: "none",
|
| 157 |
+
borderRadius: "6px",
|
| 158 |
+
cursor: "pointer",
|
| 159 |
+
boxShadow: "0 2px 6px rgba(0,0,0,0.2)",
|
| 160 |
+
}}
|
| 161 |
>
|
| 162 |
Get Selection JSON
|
| 163 |
</button>
|
|
|
|
| 165 |
{/* Display JSON */}
|
| 166 |
<pre
|
| 167 |
style={{
|
| 168 |
+
marginTop: "20px",
|
| 169 |
fontFamily: "monospace",
|
| 170 |
background: "#f4f4f4",
|
| 171 |
+
padding: "15px",
|
| 172 |
+
borderRadius: "10px",
|
| 173 |
border: "1px solid #ddd",
|
| 174 |
whiteSpace: "pre-wrap",
|
| 175 |
userSelect: "text",
|
| 176 |
+
boxShadow: "inset 0 2px 4px rgba(0,0,0,0.05)",
|
| 177 |
}}
|
| 178 |
>
|
| 179 |
{spans.length ? JSON.stringify(renderSpans(), null, 2) : ""}
|
src/main.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
| 1 |
-
import
|
| 2 |
-
import
|
| 3 |
-
import
|
| 4 |
-
import App from './App.tsx'
|
| 5 |
|
| 6 |
-
createRoot(document.getElementById(
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
| 1 |
+
import React from "react";
|
| 2 |
+
import ReactDOM from "react-dom/client"; // important for React 18
|
| 3 |
+
import SelectionApp from "./SelectionApp";
|
|
|
|
| 4 |
|
| 5 |
+
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
|
| 6 |
+
root.render(
|
| 7 |
+
<React.StrictMode>
|
| 8 |
+
<SelectionApp />
|
| 9 |
+
</React.StrictMode>
|
| 10 |
+
);
|