Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions docs/api-reference/annotation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# @interactive-os/json-document-annotation API

**Owner:** Hands

Annotation Hand interaction과 SVG projection의 public entrypoint입니다. 아래 항목은 package root에서 import할 수 있는 안정된 public API이며 internal 경로는 계약이 아닙니다.

> 이 문서는 `packages/json-document-annotation/src/index.ts`에서 생성됩니다. API를 변경한 뒤 `npm run docs:api`를 실행하세요.

## `AnnotationHand`

```ts
AnnotationHand(props: AnnotationHandProps): import("<repository>/node_modules/@types/react/jsx-runtime").JSX.Element
```
## `AnnotationHandClassNames`

```ts
interface AnnotationHandClassNames {
readonly frame?: string;
readonly stage?: string;
readonly canvas?: string;
readonly commentCard?: string;
readonly commentInput?: string;
readonly commentPreview?: string;
readonly sendButton?: string;
readonly toolDock?: string;
readonly dockButton?: string;
readonly dockDivider?: string;
}
```
## `AnnotationHandLabels`

```ts
interface AnnotationHandLabels {
readonly canvas?: string;
readonly tools?: string;
readonly instruction?: string;
readonly instructionPlaceholder?: string;
readonly sendComment?: string;
readonly deleteAnnotation?: string;
readonly downloadImage?: string;
}
```
## `AnnotationHandProps`

```ts
interface AnnotationHandProps {
readonly editor: AnnotationEditor;
readonly sourceUrl: string;
readonly createId: () => string;
readonly classNames?: AnnotationHandClassNames;
readonly enabledTools?: ReadonlyArray<AnnotationTool>;
readonly labels?: AnnotationHandLabels;
readonly rasterStyle: WebAnnotationRasterStyle;
readonly onAnnouncement?: (message: string) => void;
}
```
## `AnnotationTool`

```ts
type AnnotationTool = "select" | "comment" | "draw" | "arrow" | "like" | "dislike";
```
## `annotationTools`

```ts
const annotationTools: readonly [{ readonly id: "select"; readonly label: "Select"; readonly shortcut: "V"; readonly icon: ForwardRefExoticComponent<Omit<LucideProps, "ref"> & RefAttributes<SVGSVGElement>>; }, ... 4 more ..., { ...; }]
```
27 changes: 27 additions & 0 deletions docs/api-reference/editing.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ interface Annotation extends Record<string, JSONValue> { readonly id: string; re
```ts
const ANNOTATION_PROFILE_V1: "urn:interactive-os:json-document:annotation:1"
```
## `AnnotationBounds`

```ts
interface AnnotationBounds extends AnnotationPoint { readonly width: number; readonly height: number }
```
## `AnnotationDocument`

```ts
Expand Down Expand Up @@ -57,6 +62,11 @@ type AnnotationPresentation =
| { readonly type: "stroke" }
| { readonly type: "arrow" };
```
## `annotationResizeHandle`

```ts
annotationResizeHandle(selector: AnnotationSelector): "end" | "south-east" | null
```
## `AnnotationSelection`

```ts
Expand All @@ -71,6 +81,18 @@ type AnnotationSelector =
| { readonly type: "path"; readonly points: ReadonlyArray<AnnotationPoint> }
| { readonly type: "arrow"; readonly from: AnnotationPoint; readonly to: AnnotationPoint };
```
## `annotationSelectorBounds`

```ts
annotationSelectorBounds(selector: AnnotationSelector): AnnotationBounds
```
## `AnnotationSelectorTransform`

```ts
type AnnotationSelectorTransform =
| { readonly type: "move"; readonly dx: number; readonly dy: number }
| { readonly type: "resize"; readonly handle: "end" | "south-east"; readonly dx: number; readonly dy: number };
```
## `AnnotationSource`

```ts
Expand Down Expand Up @@ -890,6 +912,11 @@ interface SheetSelection extends Record<string, JSONValue> {
```ts
type SheetTopology = GridTopology;
```
## `transformAnnotationSelector`

```ts
transformAnnotationSelector(selector: AnnotationSelector, transform: AnnotationSelectorTransform): AnnotationSelector | null
```
## `TreeClipboard`

```ts
Expand Down
1 change: 1 addition & 0 deletions docs/api-reference/packages.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const apiReferencePackages = [
["affordance", "@interactive-os/json-document-affordance", "packages/json-document-affordance/src/index.ts", "Affordance", "입력 문법과 interaction session"],
["ui-primitives-react", "@interactive-os/json-document-ui-primitives-react", "packages/json-document-ui-primitives-react/src/index.ts", "UI Primitives", "표준 React UI primitive"],
["database", "@interactive-os/json-document-database", "packages/json-document-database/src/index.ts", "Hands", "Database Hand domain 계약"],
["annotation", "@interactive-os/json-document-annotation", "packages/json-document-annotation/src/index.ts", "Hands", "Annotation Hand interaction과 SVG projection"],
["web", "@interactive-os/json-document-web", "packages/json-document-web/src/index.ts", "Adapter", "Web platform adapter"],
["contenteditable", "@interactive-os/json-document-contenteditable", "packages/json-document-contenteditable/src/index.ts", "Adapter", "contenteditable platform adapter"],
["rich-text", "@interactive-os/json-document-rich-text", "packages/json-document-rich-text/src/index.ts", "Editing", "Rich Text domain과 editing 계약"],
Expand Down
2 changes: 2 additions & 0 deletions docs/evaluate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ const surfaces = {
ajvReadme: read("packages/json-document-ajv/README.md"),
zodReadme: read("packages/json-document-zod/README.md"),
databaseReadme: read("packages/json-document-database/README.md"),
annotationReadme: read("packages/json-document-annotation/README.md"),
tanstackTableReadme: read("packages/json-document-tanstack-table/README.md"),
webReadme: read("packages/json-document-web/README.md"),
contenteditableReadme: read("packages/json-document-contenteditable/README.md"),
Expand Down Expand Up @@ -146,6 +147,7 @@ const activeCompanionPackages = new Set([
"@interactive-os/json-document-ui-primitives-react",
"@interactive-os/json-document-zod",
"@interactive-os/json-document-database",
"@interactive-os/json-document-annotation",
"@interactive-os/json-document-tanstack-table",
"@interactive-os/json-document-web",
"@interactive-os/json-document-contenteditable",
Expand Down
15 changes: 9 additions & 6 deletions docs/public/hands.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ editor.undo();
`AnnotationDocument`는 source와 selector geometry, presentation을 직렬화하고,
selection과 undo/redo는 editor snapshot에 둡니다. Point, rectangle, path와 arrow
selector는 geometry의 유일한 정본이며 presentation은 geometry를 반복하지
않습니다. SVG 좌표 변환, pointer gesture, Canvas rasterization과 comment UI는
Editing owner 밖에서 조합합니다.
않습니다. `@interactive-os/json-document-annotation`의 `AnnotationHand`가
도구, gesture-to-Intent, SVG projection, transient preview와 comment UI를
하나의 공개 surface로 제공합니다.

```ts
const gesture = createGestureSession<AnnotationGesture>();
const point = projectWebClientPointToSVG(clientPoint, viewport);
const raster = await readWebRasterFile(file);
const output = await renderWebAnnotationRaster({ document, sourceId, sourceURL, style });
<AnnotationHand
editor={editor}
sourceUrl={sourceURL}
createId={() => crypto.randomUUID()}
rasterStyle={style}
/>
```

Gesture는 Affordance가 input-independent lifecycle로 소유하고 Pointer capture는
Expand Down
35 changes: 35 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"packages/json-document-ui-primitives-react",
"packages/json-document-zod",
"packages/json-document-database",
"packages/json-document-annotation",
"packages/json-document-tanstack-table",
"packages/json-document-web",
"packages/json-document-contenteditable",
Expand Down
3 changes: 3 additions & 0 deletions packages/json-document-annotation/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MIT License

Copyright (c) Interactive OS contributors
21 changes: 21 additions & 0 deletions packages/json-document-annotation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# @interactive-os/json-document-annotation

`AnnotationHand` is the canonical React interaction surface for raster
annotations. Editing owns the persistent document and selector transforms;
the Hand owns tools, gesture-to-Intent orchestration, SVG projection,
transient previews, resize handles, and comment UI.

```tsx
import { AnnotationHand } from "@interactive-os/json-document-annotation";

<AnnotationHand
editor={editor}
sourceUrl={sourceUrl}
createId={() => crypto.randomUUID()}
rasterStyle={rasterStyle}
/>
```

The Host injects IDs, enabled tools, copy, class names, raster style, and the
concrete source URL. The serialized output remains an `AnnotationDocument`;
selection and history stay in the editor snapshot.
10 changes: 10 additions & 0 deletions packages/json-document-annotation/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "@interactive-os/json-document-annotation", "version": "0.1.0-rc.0", "description": "Official React Annotation Hand for json-document.", "type": "module", "license": "MIT", "sideEffects": false,
"main": "./dist/index.js", "types": "./dist/index.d.ts", "repository": { "type": "git", "url": "git+https://github.com/developer-1px/json-document.git", "directory": "packages/json-document-annotation" },
"publishConfig": { "access": "public", "provenance": true, "tag": "next" }, "files": ["dist", "!dist/.tsbuildinfo", "README.md", "LICENSE"],
"exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" } },
"scripts": { "clean": "rm -rf dist", "build": "npm run clean && tsc -b tsconfig.json", "test": "vitest run --config vitest.config.ts", "pretypecheck": "node ../../scripts/workspace-tasks.mjs build-dependencies", "typecheck": "tsc -p tsconfig.test.json --noEmit", "verify": "npm run typecheck && npm test && npm run build" },
"dependencies": { "@interactive-os/json-document-affordance": ">=0.1.0-rc.0 <1", "@interactive-os/json-document-editing": ">=0.1.0-rc.0 <1", "@interactive-os/json-document-ui-primitives-react": ">=0.1.0-rc.0 <1", "@interactive-os/json-document-web": ">=0.1.0-rc.0 <1", "lucide-react": "^1.33.0" },
"peerDependencies": { "react": "^18.0.0 || ^19.0.0" },
"devDependencies": { "@interactive-os/json-document-affordance": "*", "@interactive-os/json-document-editing": "*", "@interactive-os/json-document-ui-primitives-react": "*", "@interactive-os/json-document-web": "*", "@testing-library/react": "^16.3.2", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "jsdom": "^29.1.1", "react": "^19.2.5", "react-dom": "^19.2.5", "typescript": "^5.0.0", "vitest": "^4.1.7" }
}
Loading
Loading