skema-core 0.1.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/README.md +116 -0
- package/dist/cli.js +37 -0
- package/dist/index.d.mts +356 -0
- package/dist/index.d.ts +356 -0
- package/dist/index.js +2334 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2307 -0
- package/dist/index.mjs.map +1 -0
- package/dist/server.d.mts +260 -0
- package/dist/server.d.ts +260 -0
- package/dist/server.js +476 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +465 -0
- package/dist/server.mjs.map +1 -0
- package/package.json +76 -0
package/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Skema
|
|
2
|
+
|
|
3
|
+
A drawing-based website development tool that transforms how you annotate and communicate design changes.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Skema is a React component that provides a tldraw-powered drawing overlay for annotating and manipulating DOM elements visually. It sits on top of your localhost website, allowing developers to annotate, draw, and select DOM elements directly on the live page.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Drawing Overlay**: Use tldraw's powerful drawing tools directly on your website
|
|
12
|
+
- **DOM Picker**: Select any element on the page to capture its selector, bounding box, and context
|
|
13
|
+
- **Annotation Export**: Export all annotations in a structured JSON format optimized for AI agents
|
|
14
|
+
- **Non-Invasive**: Transparent overlay that doesn't interfere with your page when not in use
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
### 1. Install the package
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
bun add skema-core
|
|
22
|
+
# or
|
|
23
|
+
npm install skema-core
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Create the API route
|
|
27
|
+
|
|
28
|
+
Run the init command to create the Gemini API route in your Next.js App Router project:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
bunx skema init
|
|
32
|
+
# or
|
|
33
|
+
npx skema init
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
This creates `app/api/gemini/route.ts` (or `src/app/api/gemini/route.ts`) which handles annotation processing.
|
|
37
|
+
|
|
38
|
+
### 3. Set up your Gemini API key
|
|
39
|
+
|
|
40
|
+
Add your [Google AI API key](https://aistudio.google.com/apikey) to your `.env` file:
|
|
41
|
+
|
|
42
|
+
```env
|
|
43
|
+
GEMINI_API_KEY=your_api_key_here
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 4. Add Skema to your app
|
|
47
|
+
|
|
48
|
+
Wrap your app with the Skema component (development only):
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
import { Skema } from 'skema-core';
|
|
52
|
+
|
|
53
|
+
export default function Page() {
|
|
54
|
+
return (
|
|
55
|
+
<>
|
|
56
|
+
{/* Your page content */}
|
|
57
|
+
<main>...</main>
|
|
58
|
+
|
|
59
|
+
{/* Skema overlay - only in development */}
|
|
60
|
+
{process.env.NODE_ENV === 'development' && <Skema />}
|
|
61
|
+
</>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
That's it! Press **⌘⇧E** (Cmd+Shift+E) to toggle the Skema overlay.
|
|
67
|
+
|
|
68
|
+
## Keyboard Shortcuts
|
|
69
|
+
|
|
70
|
+
- **⌘⇧E** (Cmd+Shift+E / Ctrl+Shift+E): Toggle Skema overlay
|
|
71
|
+
- **P**: Activate DOM Picker tool
|
|
72
|
+
|
|
73
|
+
## Export Format
|
|
74
|
+
|
|
75
|
+
When you export annotations, Skema generates a JSON structure like this:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"version": "1.0.0",
|
|
80
|
+
"timestamp": "2024-01-24T12:00:00Z",
|
|
81
|
+
"viewport": {
|
|
82
|
+
"width": 1920,
|
|
83
|
+
"height": 1080,
|
|
84
|
+
"scrollX": 0,
|
|
85
|
+
"scrollY": 150
|
|
86
|
+
},
|
|
87
|
+
"pathname": "/",
|
|
88
|
+
"annotations": [
|
|
89
|
+
{
|
|
90
|
+
"type": "dom_selection",
|
|
91
|
+
"id": "dom-1706097600000-abc123",
|
|
92
|
+
"selector": ".hero-section > button.cta-primary",
|
|
93
|
+
"tagName": "button",
|
|
94
|
+
"elementPath": ".hero-section > button",
|
|
95
|
+
"text": "Get Started",
|
|
96
|
+
"boundingBox": { "x": 100, "y": 200, "width": 150, "height": 40 },
|
|
97
|
+
"timestamp": 1706097600000,
|
|
98
|
+
"pathname": "/"
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Props
|
|
105
|
+
|
|
106
|
+
| Prop | Type | Default | Description |
|
|
107
|
+
|------|------|---------|-------------|
|
|
108
|
+
| `enabled` | `boolean` | `true` | Whether Skema overlay is enabled |
|
|
109
|
+
| `onAnnotationsChange` | `(annotations: Annotation[]) => void` | - | Callback when annotations change |
|
|
110
|
+
| `toggleShortcut` | `string` | `'mod+shift+e'` | Keyboard shortcut to toggle Skema |
|
|
111
|
+
| `initialAnnotations` | `Annotation[]` | `[]` | Initial annotations to load |
|
|
112
|
+
| `zIndex` | `number` | `99999` | Z-index for the overlay |
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var fs = require('fs');
|
|
5
|
+
var path = require('path');
|
|
6
|
+
|
|
7
|
+
var ROUTE_CONTENT = `export { POST, DELETE } from 'skema-core/server';
|
|
8
|
+
`;
|
|
9
|
+
function init() {
|
|
10
|
+
const cwd = process.cwd();
|
|
11
|
+
const appDir = fs.existsSync(path.join(cwd, "app")) ? path.join(cwd, "app") : fs.existsSync(path.join(cwd, "src/app")) ? path.join(cwd, "src/app") : null;
|
|
12
|
+
if (!appDir) {
|
|
13
|
+
console.error("\u274C Could not find app/ or src/app/ directory.");
|
|
14
|
+
console.error(" Make sure you run this from a Next.js App Router project root.");
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
const apiDir = path.join(appDir, "api", "gemini");
|
|
18
|
+
const routePath = path.join(apiDir, "route.ts");
|
|
19
|
+
if (fs.existsSync(routePath)) {
|
|
20
|
+
console.log("\u2713 API route already exists at", routePath.replace(cwd, "."));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (!fs.existsSync(apiDir)) {
|
|
24
|
+
fs.mkdirSync(apiDir, { recursive: true });
|
|
25
|
+
console.log("\u2713 Created", apiDir.replace(cwd, "."));
|
|
26
|
+
}
|
|
27
|
+
fs.writeFileSync(routePath, ROUTE_CONTENT);
|
|
28
|
+
console.log("\u2713 Created", routePath.replace(cwd, "."));
|
|
29
|
+
console.log("");
|
|
30
|
+
console.log("\u{1F389} Skema is ready! The Gemini CLI integration is now set up.");
|
|
31
|
+
console.log("");
|
|
32
|
+
console.log("Usage:");
|
|
33
|
+
console.log(" 1. Add <Skema /> to your page");
|
|
34
|
+
console.log(" 2. Press Cmd+Shift+E to toggle the overlay");
|
|
35
|
+
console.log(" 3. Annotate elements and Gemini CLI will make the changes");
|
|
36
|
+
}
|
|
37
|
+
init();
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents a single DOM element in a selection
|
|
5
|
+
*/
|
|
6
|
+
interface DOMElement {
|
|
7
|
+
selector: string;
|
|
8
|
+
tagName: string;
|
|
9
|
+
elementPath: string;
|
|
10
|
+
text: string;
|
|
11
|
+
boundingBox: BoundingBox;
|
|
12
|
+
cssClasses?: string;
|
|
13
|
+
attributes?: Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Represents a DOM element selection (can contain one or more elements)
|
|
17
|
+
*/
|
|
18
|
+
interface DOMSelection {
|
|
19
|
+
id: string;
|
|
20
|
+
selector: string;
|
|
21
|
+
tagName: string;
|
|
22
|
+
elementPath: string;
|
|
23
|
+
text: string;
|
|
24
|
+
boundingBox: BoundingBox;
|
|
25
|
+
timestamp: number;
|
|
26
|
+
pathname: string;
|
|
27
|
+
cssClasses?: string;
|
|
28
|
+
attributes?: Record<string, string>;
|
|
29
|
+
/** User annotation comment */
|
|
30
|
+
comment?: string;
|
|
31
|
+
/** Whether this is a multi-element selection */
|
|
32
|
+
isMultiSelect?: boolean;
|
|
33
|
+
/** Individual elements when this is a grouped selection */
|
|
34
|
+
elements?: DOMElement[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Pending annotation state for the popup
|
|
38
|
+
*/
|
|
39
|
+
interface PendingAnnotation {
|
|
40
|
+
/** Screen X position (percentage of viewport width) */
|
|
41
|
+
x: number;
|
|
42
|
+
/** Screen Y position (pixels from top of document) */
|
|
43
|
+
y: number;
|
|
44
|
+
/** Y position relative to viewport (for popup positioning) */
|
|
45
|
+
clientY: number;
|
|
46
|
+
/** Element identifier string */
|
|
47
|
+
element: string;
|
|
48
|
+
/** CSS selector path */
|
|
49
|
+
elementPath: string;
|
|
50
|
+
/** Selected text content if any */
|
|
51
|
+
selectedText?: string;
|
|
52
|
+
/** Bounding box of selected element(s) */
|
|
53
|
+
boundingBox?: BoundingBox;
|
|
54
|
+
/** Whether this is a multi-element selection */
|
|
55
|
+
isMultiSelect?: boolean;
|
|
56
|
+
/** The DOM selection(s) being annotated */
|
|
57
|
+
selections?: DOMSelection[];
|
|
58
|
+
/** Type of annotation */
|
|
59
|
+
annotationType: 'dom_selection' | 'drawing';
|
|
60
|
+
/** Drawing shape IDs if annotating drawings */
|
|
61
|
+
shapeIds?: string[];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Bounding box for element positioning
|
|
65
|
+
*/
|
|
66
|
+
interface BoundingBox {
|
|
67
|
+
x: number;
|
|
68
|
+
y: number;
|
|
69
|
+
width: number;
|
|
70
|
+
height: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Viewport information for coordinate calculations
|
|
74
|
+
*/
|
|
75
|
+
interface ViewportInfo {
|
|
76
|
+
width: number;
|
|
77
|
+
height: number;
|
|
78
|
+
scrollX: number;
|
|
79
|
+
scrollY: number;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Computed styles for an element
|
|
83
|
+
*/
|
|
84
|
+
interface ElementStyles {
|
|
85
|
+
fontFamily?: string;
|
|
86
|
+
fontSize?: string;
|
|
87
|
+
fontWeight?: string;
|
|
88
|
+
lineHeight?: string;
|
|
89
|
+
letterSpacing?: string;
|
|
90
|
+
textAlign?: string;
|
|
91
|
+
color?: string;
|
|
92
|
+
padding?: string;
|
|
93
|
+
margin?: string;
|
|
94
|
+
gap?: string;
|
|
95
|
+
display?: string;
|
|
96
|
+
flexDirection?: string;
|
|
97
|
+
alignItems?: string;
|
|
98
|
+
justifyContent?: string;
|
|
99
|
+
backgroundColor?: string;
|
|
100
|
+
borderRadius?: string;
|
|
101
|
+
border?: string;
|
|
102
|
+
boxShadow?: string;
|
|
103
|
+
width?: string;
|
|
104
|
+
height?: string;
|
|
105
|
+
maxWidth?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Nearby element with style context for AI
|
|
109
|
+
*/
|
|
110
|
+
interface NearbyElement {
|
|
111
|
+
selector: string;
|
|
112
|
+
tagName: string;
|
|
113
|
+
text?: string;
|
|
114
|
+
className?: string;
|
|
115
|
+
styles?: ElementStyles;
|
|
116
|
+
tailwindClasses?: string[];
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Project-level style context
|
|
120
|
+
*/
|
|
121
|
+
interface ProjectStyleContext {
|
|
122
|
+
cssFramework?: 'tailwind' | 'bootstrap' | 'material-ui' | 'chakra' | 'vanilla' | 'css-modules' | 'styled-components' | 'unknown';
|
|
123
|
+
cssVariables?: Record<string, string>;
|
|
124
|
+
colorPalette?: string[];
|
|
125
|
+
baseFontFamily?: string;
|
|
126
|
+
baseFontSize?: string;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Drawing annotation from tldraw
|
|
130
|
+
*/
|
|
131
|
+
interface DrawingAnnotation {
|
|
132
|
+
id: string;
|
|
133
|
+
type: 'drawing';
|
|
134
|
+
tool: string;
|
|
135
|
+
shapes: unknown[];
|
|
136
|
+
boundingBox: BoundingBox;
|
|
137
|
+
relatedTo?: string;
|
|
138
|
+
timestamp: number;
|
|
139
|
+
/** User annotation comment describing what to build */
|
|
140
|
+
comment?: string;
|
|
141
|
+
/** SVG representation of the drawing for AI processing */
|
|
142
|
+
drawingSvg?: string;
|
|
143
|
+
/** Base64 PNG image of the drawing for vision AI */
|
|
144
|
+
drawingImage?: string;
|
|
145
|
+
/** Extracted text content from text shapes in the drawing */
|
|
146
|
+
extractedText?: string;
|
|
147
|
+
/** Grid configuration used for positioning reference */
|
|
148
|
+
gridConfig?: {
|
|
149
|
+
color: string;
|
|
150
|
+
size: number;
|
|
151
|
+
labels: boolean;
|
|
152
|
+
};
|
|
153
|
+
/** Viewport info for relative sizing context */
|
|
154
|
+
viewport?: ViewportInfo;
|
|
155
|
+
/** Project-level style context */
|
|
156
|
+
projectStyles?: ProjectStyleContext;
|
|
157
|
+
/** Nearby DOM elements that the drawing may relate to */
|
|
158
|
+
nearbyElements?: NearbyElement[];
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Gesture action annotation
|
|
162
|
+
*/
|
|
163
|
+
interface GestureAnnotation {
|
|
164
|
+
id: string;
|
|
165
|
+
type: 'gesture';
|
|
166
|
+
gesture: 'scribble_delete' | 'circle' | 'rectangle' | 'arrow';
|
|
167
|
+
target?: string;
|
|
168
|
+
boundingBox: BoundingBox;
|
|
169
|
+
timestamp: number;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Union type for all annotation types
|
|
173
|
+
*/
|
|
174
|
+
type Annotation = {
|
|
175
|
+
type: 'dom_selection';
|
|
176
|
+
} & DOMSelection | DrawingAnnotation | GestureAnnotation;
|
|
177
|
+
/**
|
|
178
|
+
* Complete export format for annotations
|
|
179
|
+
*/
|
|
180
|
+
interface AnnotationExport {
|
|
181
|
+
version: string;
|
|
182
|
+
timestamp: string;
|
|
183
|
+
viewport: ViewportInfo;
|
|
184
|
+
pathname: string;
|
|
185
|
+
annotations: Annotation[];
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Skema component props
|
|
189
|
+
*/
|
|
190
|
+
interface SkemaProps {
|
|
191
|
+
/** Whether Skema overlay is enabled */
|
|
192
|
+
enabled?: boolean;
|
|
193
|
+
/** Callback when annotations change */
|
|
194
|
+
onAnnotationsChange?: (annotations: Annotation[]) => void;
|
|
195
|
+
/** Callback when a single annotation is submitted - for real-time integrations like Gemini */
|
|
196
|
+
onAnnotationSubmit?: (annotation: Annotation, comment: string) => void;
|
|
197
|
+
/** Callback when an annotation is deleted - for reverting changes */
|
|
198
|
+
onAnnotationDelete?: (annotationId: string) => void;
|
|
199
|
+
/** Keyboard shortcut to toggle Skema (default: Cmd/Ctrl + Shift + E) */
|
|
200
|
+
toggleShortcut?: string;
|
|
201
|
+
/** Initial annotations to load */
|
|
202
|
+
initialAnnotations?: Annotation[];
|
|
203
|
+
/** Z-index for the overlay (default: 99999) */
|
|
204
|
+
zIndex?: number;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Skema mode - determines what tools are available
|
|
208
|
+
*/
|
|
209
|
+
type SkemaMode = 'select' | 'draw';
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Main Skema component - renders tldraw as a transparent overlay
|
|
213
|
+
*/
|
|
214
|
+
declare const Skema: React.FC<SkemaProps>;
|
|
215
|
+
|
|
216
|
+
interface AnnotationPopupProps {
|
|
217
|
+
/** Element name/description to display in header */
|
|
218
|
+
element: string;
|
|
219
|
+
/** Optional selected/highlighted text */
|
|
220
|
+
selectedText?: string;
|
|
221
|
+
/** Placeholder text for the textarea */
|
|
222
|
+
placeholder?: string;
|
|
223
|
+
/** Initial value for textarea (for edit mode) */
|
|
224
|
+
initialValue?: string;
|
|
225
|
+
/** Label for submit button (default: "Add") */
|
|
226
|
+
submitLabel?: string;
|
|
227
|
+
/** Called when annotation is submitted with text */
|
|
228
|
+
onSubmit: (text: string) => void;
|
|
229
|
+
/** Called when popup is cancelled/dismissed */
|
|
230
|
+
onCancel: () => void;
|
|
231
|
+
/** Position styles (left, top) */
|
|
232
|
+
style?: React.CSSProperties;
|
|
233
|
+
/** Custom accent color (hex) */
|
|
234
|
+
accentColor?: string;
|
|
235
|
+
/** External exit state (parent controls exit animation) */
|
|
236
|
+
isExiting?: boolean;
|
|
237
|
+
/** Whether this is a multi-select annotation */
|
|
238
|
+
isMultiSelect?: boolean;
|
|
239
|
+
}
|
|
240
|
+
interface AnnotationPopupHandle {
|
|
241
|
+
/** Shake the popup (e.g., when user clicks outside) */
|
|
242
|
+
shake: () => void;
|
|
243
|
+
}
|
|
244
|
+
declare const AnnotationPopup: React.ForwardRefExoticComponent<AnnotationPopupProps & React.RefAttributes<AnnotationPopupHandle>>;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Generates a unique CSS selector for an element
|
|
248
|
+
*/
|
|
249
|
+
declare function generateSelector(element: HTMLElement): string;
|
|
250
|
+
/**
|
|
251
|
+
* Gets a readable path for an element (e.g., "article > section > p")
|
|
252
|
+
*/
|
|
253
|
+
declare function getElementPath(target: HTMLElement, maxDepth?: number): string;
|
|
254
|
+
/**
|
|
255
|
+
* Identifies an element and returns a human-readable name
|
|
256
|
+
*/
|
|
257
|
+
declare function identifyElement(target: HTMLElement): string;
|
|
258
|
+
/**
|
|
259
|
+
* Gets bounding box for an element in document coordinates (includes scroll offset)
|
|
260
|
+
*/
|
|
261
|
+
declare function getBoundingBox(element: HTMLElement): BoundingBox;
|
|
262
|
+
/**
|
|
263
|
+
* Gets CSS class names from an element (cleaned of module hashes)
|
|
264
|
+
*/
|
|
265
|
+
declare function getElementClasses(target: HTMLElement): string;
|
|
266
|
+
/**
|
|
267
|
+
* Creates a DOMSelection from an element
|
|
268
|
+
*/
|
|
269
|
+
declare function createDOMSelection(element: HTMLElement): DOMSelection;
|
|
270
|
+
/**
|
|
271
|
+
* Checks if an element should be ignored for DOM picking
|
|
272
|
+
*/
|
|
273
|
+
declare function shouldIgnoreElement(element: HTMLElement): boolean;
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Gets current viewport information
|
|
277
|
+
*/
|
|
278
|
+
declare function getViewportInfo(): ViewportInfo;
|
|
279
|
+
/**
|
|
280
|
+
* Converts viewport-relative coordinates to document coordinates
|
|
281
|
+
*/
|
|
282
|
+
declare function viewportToDocument(x: number, y: number, viewport?: ViewportInfo): {
|
|
283
|
+
x: number;
|
|
284
|
+
y: number;
|
|
285
|
+
};
|
|
286
|
+
/**
|
|
287
|
+
* Converts document coordinates to viewport-relative coordinates
|
|
288
|
+
*/
|
|
289
|
+
declare function documentToViewport(x: number, y: number, viewport?: ViewportInfo): {
|
|
290
|
+
x: number;
|
|
291
|
+
y: number;
|
|
292
|
+
};
|
|
293
|
+
/**
|
|
294
|
+
* Converts a bounding box from viewport to document coordinates
|
|
295
|
+
*/
|
|
296
|
+
declare function bboxViewportToDocument(bbox: BoundingBox, viewport?: ViewportInfo): BoundingBox;
|
|
297
|
+
/**
|
|
298
|
+
* Converts a bounding box from document to viewport coordinates
|
|
299
|
+
*/
|
|
300
|
+
declare function bboxDocumentToViewport(bbox: BoundingBox, viewport?: ViewportInfo): BoundingBox;
|
|
301
|
+
/**
|
|
302
|
+
* Checks if two bounding boxes intersect
|
|
303
|
+
*/
|
|
304
|
+
declare function bboxIntersects(a: BoundingBox, b: BoundingBox): boolean;
|
|
305
|
+
/**
|
|
306
|
+
* Checks if point is inside bounding box
|
|
307
|
+
*/
|
|
308
|
+
declare function pointInBbox(x: number, y: number, bbox: BoundingBox): boolean;
|
|
309
|
+
/**
|
|
310
|
+
* Gets the center point of a bounding box
|
|
311
|
+
*/
|
|
312
|
+
declare function bboxCenter(bbox: BoundingBox): {
|
|
313
|
+
x: number;
|
|
314
|
+
y: number;
|
|
315
|
+
};
|
|
316
|
+
/**
|
|
317
|
+
* Expands a bounding box by a padding amount
|
|
318
|
+
*/
|
|
319
|
+
declare function expandBbox(bbox: BoundingBox, padding: number): BoundingBox;
|
|
320
|
+
/**
|
|
321
|
+
* Creates a bounding box from two points
|
|
322
|
+
*/
|
|
323
|
+
declare function bboxFromPoints(x1: number, y1: number, x2: number, y2: number): BoundingBox;
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Convert a Blob to a base64 string
|
|
327
|
+
*/
|
|
328
|
+
declare function blobToBase64(blob: Blob): Promise<string>;
|
|
329
|
+
/**
|
|
330
|
+
* Add a labeled grid overlay to an SVG string
|
|
331
|
+
* Grid uses A/B/C column labels and 0/1/2 row numbers for positioning reference
|
|
332
|
+
* @param svgString - The SVG markup to add grid to
|
|
333
|
+
* @param opts - Grid options (color, cell size, whether to show labels)
|
|
334
|
+
* @returns SVG string with grid overlay added
|
|
335
|
+
*/
|
|
336
|
+
declare function addGridToSvg(svgString: string, opts?: {
|
|
337
|
+
color?: string;
|
|
338
|
+
size?: number;
|
|
339
|
+
labels?: boolean;
|
|
340
|
+
}): string;
|
|
341
|
+
/**
|
|
342
|
+
* Get the grid cell reference (e.g., "B2") for a given position
|
|
343
|
+
* @param x - X coordinate in pixels
|
|
344
|
+
* @param y - Y coordinate in pixels
|
|
345
|
+
* @param gridSize - Size of each grid cell (default 100px)
|
|
346
|
+
* @returns Grid cell reference string (e.g., "B2")
|
|
347
|
+
*/
|
|
348
|
+
declare function getGridCellReference(x: number, y: number, gridSize?: number): string;
|
|
349
|
+
/**
|
|
350
|
+
* Extract text content from tldraw shapes
|
|
351
|
+
* @param shapes - Array of tldraw shapes
|
|
352
|
+
* @returns Combined text content from text and note shapes
|
|
353
|
+
*/
|
|
354
|
+
declare function extractTextFromShapes(shapes: unknown[]): string;
|
|
355
|
+
|
|
356
|
+
export { type Annotation, type AnnotationExport, AnnotationPopup, type AnnotationPopupHandle, type AnnotationPopupProps, type BoundingBox, type DOMElement, type DOMSelection, type DrawingAnnotation, type ElementStyles, type GestureAnnotation, type NearbyElement, type PendingAnnotation, type ProjectStyleContext, Skema, type SkemaMode, type SkemaProps, type ViewportInfo, addGridToSvg, bboxCenter, bboxDocumentToViewport, bboxFromPoints, bboxIntersects, bboxViewportToDocument, blobToBase64, createDOMSelection, Skema as default, documentToViewport, expandBbox, extractTextFromShapes, generateSelector, getBoundingBox, getElementClasses, getElementPath, getGridCellReference, getViewportInfo, identifyElement, pointInBbox, shouldIgnoreElement, viewportToDocument };
|