annotation-kit 0.0.0-stage → 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.
Files changed (121) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +75 -0
  3. package/README.md +114 -2
  4. package/README.zh-CN.md +112 -0
  5. package/dist/annotation-kit.css +157 -0
  6. package/dist/chunks/references-ukB-tSle.js +1126 -0
  7. package/dist/chunks/references-ukB-tSle.js.map +1 -0
  8. package/dist/electron/element-context.cjs +72 -0
  9. package/dist/electron/guest-preload.cjs +327 -0
  10. package/dist/electron.js +394 -0
  11. package/dist/electron.js.map +1 -0
  12. package/dist/index.js +910 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/react.js +2256 -0
  15. package/dist/react.js.map +1 -0
  16. package/dist/styles.d.ts +2 -0
  17. package/dist/types/address.d.ts +53 -0
  18. package/dist/types/address.d.ts.map +1 -0
  19. package/dist/types/client/Workbench.d.ts +11 -0
  20. package/dist/types/client/Workbench.d.ts.map +1 -0
  21. package/dist/types/client/composer/PacketPreview.d.ts +12 -0
  22. package/dist/types/client/composer/PacketPreview.d.ts.map +1 -0
  23. package/dist/types/client/composer/ReferenceCard.d.ts +12 -0
  24. package/dist/types/client/composer/ReferenceCard.d.ts.map +1 -0
  25. package/dist/types/client/composer/attachments.d.ts +10 -0
  26. package/dist/types/client/composer/attachments.d.ts.map +1 -0
  27. package/dist/types/client/composer/commit.d.ts +4 -0
  28. package/dist/types/client/composer/commit.d.ts.map +1 -0
  29. package/dist/types/client/composer/packets.d.ts +53 -0
  30. package/dist/types/client/composer/packets.d.ts.map +1 -0
  31. package/dist/types/client/composer/reference-presentation.d.ts +4 -0
  32. package/dist/types/client/composer/reference-presentation.d.ts.map +1 -0
  33. package/dist/types/client/error-copy.d.ts +69 -0
  34. package/dist/types/client/error-copy.d.ts.map +1 -0
  35. package/dist/types/client/errors.d.ts +10 -0
  36. package/dist/types/client/errors.d.ts.map +1 -0
  37. package/dist/types/client/files/FileSelectionAction.d.ts +7 -0
  38. package/dist/types/client/files/FileSelectionAction.d.ts.map +1 -0
  39. package/dist/types/client/files/SelectionCard.d.ts +14 -0
  40. package/dist/types/client/files/SelectionCard.d.ts.map +1 -0
  41. package/dist/types/client/files/document-workflow.d.ts +34 -0
  42. package/dist/types/client/files/document-workflow.d.ts.map +1 -0
  43. package/dist/types/client/files/pages/DocumentChrome.d.ts +30 -0
  44. package/dist/types/client/files/pages/DocumentChrome.d.ts.map +1 -0
  45. package/dist/types/client/files/pages/PageSelectionAction.d.ts +7 -0
  46. package/dist/types/client/files/pages/PageSelectionAction.d.ts.map +1 -0
  47. package/dist/types/client/files/pages/batches.d.ts +21 -0
  48. package/dist/types/client/files/pages/batches.d.ts.map +1 -0
  49. package/dist/types/client/files/pages/geometry.d.ts +16 -0
  50. package/dist/types/client/files/pages/geometry.d.ts.map +1 -0
  51. package/dist/types/client/files/pages/image-store.d.ts +8 -0
  52. package/dist/types/client/files/pages/image-store.d.ts.map +1 -0
  53. package/dist/types/client/files/pages/images.d.ts +41 -0
  54. package/dist/types/client/files/pages/images.d.ts.map +1 -0
  55. package/dist/types/client/files/pages/interaction.d.ts +55 -0
  56. package/dist/types/client/files/pages/interaction.d.ts.map +1 -0
  57. package/dist/types/client/files/pages/selection.d.ts +25 -0
  58. package/dist/types/client/files/pages/selection.d.ts.map +1 -0
  59. package/dist/types/client/files/pages/snapshot.d.ts +31 -0
  60. package/dist/types/client/files/pages/snapshot.d.ts.map +1 -0
  61. package/dist/types/client/files/references.d.ts +80 -0
  62. package/dist/types/client/files/references.d.ts.map +1 -0
  63. package/dist/types/client/files/selection.d.ts +11 -0
  64. package/dist/types/client/files/selection.d.ts.map +1 -0
  65. package/dist/types/client/files/sheets/SheetRecovery.d.ts +12 -0
  66. package/dist/types/client/files/sheets/SheetRecovery.d.ts.map +1 -0
  67. package/dist/types/client/files/sheets/SheetSurface.d.ts +27 -0
  68. package/dist/types/client/files/sheets/SheetSurface.d.ts.map +1 -0
  69. package/dist/types/client/files/sheets/geometry.d.ts +30 -0
  70. package/dist/types/client/files/sheets/geometry.d.ts.map +1 -0
  71. package/dist/types/client/files/sheets/navigation.d.ts +4 -0
  72. package/dist/types/client/files/sheets/navigation.d.ts.map +1 -0
  73. package/dist/types/client/files/sheets/snapshot.d.ts +45 -0
  74. package/dist/types/client/files/sheets/snapshot.d.ts.map +1 -0
  75. package/dist/types/client/locales.d.ts +148 -0
  76. package/dist/types/client/locales.d.ts.map +1 -0
  77. package/dist/types/client/messages/SentAnnotations.d.ts +18 -0
  78. package/dist/types/client/messages/SentAnnotations.d.ts.map +1 -0
  79. package/dist/types/client/messages/presentation.d.ts +39 -0
  80. package/dist/types/client/messages/presentation.d.ts.map +1 -0
  81. package/dist/types/client/model.d.ts +68 -0
  82. package/dist/types/client/model.d.ts.map +1 -0
  83. package/dist/types/client/quoted-context.d.ts +3 -0
  84. package/dist/types/client/quoted-context.d.ts.map +1 -0
  85. package/dist/types/client/responses/ResponseCard.d.ts +12 -0
  86. package/dist/types/client/responses/ResponseCard.d.ts.map +1 -0
  87. package/dist/types/client/responses/ResponseOverlay.d.ts +7 -0
  88. package/dist/types/client/responses/ResponseOverlay.d.ts.map +1 -0
  89. package/dist/types/client/responses/composer.d.ts +11 -0
  90. package/dist/types/client/responses/composer.d.ts.map +1 -0
  91. package/dist/types/client/responses/controller.d.ts +39 -0
  92. package/dist/types/client/responses/controller.d.ts.map +1 -0
  93. package/dist/types/client/responses/references.d.ts +62 -0
  94. package/dist/types/client/responses/references.d.ts.map +1 -0
  95. package/dist/types/client/responses/selection.d.ts +43 -0
  96. package/dist/types/client/responses/selection.d.ts.map +1 -0
  97. package/dist/types/electron/bridge.d.mts +45 -0
  98. package/dist/types/electron/bridge.d.mts.map +1 -0
  99. package/dist/types/electron/build-preload.d.mts +4 -0
  100. package/dist/types/electron/build-preload.d.mts.map +1 -0
  101. package/dist/types/electron/element-context.d.cts +7 -0
  102. package/dist/types/electron/element-context.d.cts.map +1 -0
  103. package/dist/types/electron/guest-preload.d.cts +2 -0
  104. package/dist/types/electron/guest-preload.d.cts.map +1 -0
  105. package/dist/types/electron/index.d.ts +5 -0
  106. package/dist/types/electron/index.d.ts.map +1 -0
  107. package/dist/types/host-contracts.d.ts +104 -0
  108. package/dist/types/host-contracts.d.ts.map +1 -0
  109. package/dist/types/index.d.ts +32 -0
  110. package/dist/types/index.d.ts.map +1 -0
  111. package/dist/types/react.d.ts +14 -0
  112. package/dist/types/react.d.ts.map +1 -0
  113. package/dist/types/shared/desktop.d.ts +75 -0
  114. package/dist/types/shared/desktop.d.ts.map +1 -0
  115. package/dist/types/shared/surface.d.ts +11 -0
  116. package/dist/types/shared/surface.d.ts.map +1 -0
  117. package/dist/types/ui/icons.d.ts +11 -0
  118. package/dist/types/ui/icons.d.ts.map +1 -0
  119. package/dist/types/ui/regions.d.ts +28 -0
  120. package/dist/types/ui/regions.d.ts.map +1 -0
  121. package/package.json +82 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 annotation-kit contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE ADDED
@@ -0,0 +1,75 @@
1
+ annotation-kit 0.1.0
2
+
3
+ Original annotations extracted from Aione by leung-alex.
4
+ The DSH URI codec and version-specific example adaptations derive from DeepSeek Harness.
5
+ Guest selection bundles react-grab 0.2.0 primitives. Spreadsheet types and the host adapter use FortuneSheet 1.0.4.
6
+
7
+ --- DeepSeek Harness ---
8
+ MIT License
9
+
10
+ Copyright (c) 2026 DeepSeek
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in all
20
+ copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
29
+
30
+ --- react-grab 0.2.0 ---
31
+ MIT License
32
+
33
+ Copyright (c) 2025 Aiden Bai
34
+
35
+ Permission is hereby granted, free of charge, to any person obtaining a copy
36
+ of this software and associated documentation files (the "Software"), to deal
37
+ in the Software without restriction, including without limitation the rights
38
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
39
+ copies of the Software, and to permit persons to whom the Software is
40
+ furnished to do so, subject to the following conditions:
41
+
42
+ The above copyright notice and this permission notice shall be included in all
43
+ copies or substantial portions of the Software.
44
+
45
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
47
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
48
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
49
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
50
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
51
+ SOFTWARE.
52
+
53
+ --- FortuneSheet 1.0.4 ---
54
+ MIT License
55
+
56
+ Copyright (c) 2022 Suzhou Ruilisi Technology Co., Ltd
57
+
58
+ Permission is hereby granted, free of charge, to any person obtaining a copy
59
+ of this software and associated documentation files (the "Software"), to deal
60
+ in the Software without restriction, including without limitation the rights
61
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
62
+ copies of the Software, and to permit persons to whom the Software is
63
+ furnished to do so, subject to the following conditions:
64
+
65
+ The above copyright notice and this permission notice shall be included in all
66
+ copies or substantial portions of the Software.
67
+
68
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
69
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
70
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
72
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
73
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
74
+ SOFTWARE.
75
+
package/README.md CHANGED
@@ -1,3 +1,115 @@
1
- # Temporary Holding Version
1
+ # annotation-kit
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Annotations for web pages, documents, spreadsheets, and conversation text. React 18 UI, immutable evidence, editable comments, and host-controlled submission.
4
+
5
+ [中文文档](README.zh-CN.md) · [Host integration](docs/host-integration.md) · [DSH rc.5 example](examples/dsh/README.md)
6
+
7
+ ![Select a web element and write a comment in the independent React example](docs/screenshots/web-react.png)
8
+
9
+ | Surface | What gets preserved | Save behavior |
10
+ | --- | --- | --- |
11
+ | Web element / region | URL, element context, geometry, original PNG | Adds to your application's draft |
12
+ | Code / text / Markdown | Original text and source location | Adds a text reference to the draft |
13
+ | PDF / Word / PowerPoint | Selected text, page anchors, or cropped page pixels | Saves an independent document batch |
14
+ | XLSX / CSV | Sheet identity, cells, displayed/raw values, formulas, range | Saves an independent document batch |
15
+ | Assistant reply | Stable message location, original quote, optional comment | Adds an editable reference to the draft |
16
+ | Sent message | Versioned card metadata plus original evidence | Remains readable after the source changes |
17
+
18
+ PowerPoint's plain-text quick request submits directly. Ordinary document and spreadsheet comments remain in their source batch until Send. A failed admission retains the pending content; session changes, navigation, cancellation and unload invalidate pending selections.
19
+
20
+ <details>
21
+ <summary>More screenshots</summary>
22
+
23
+ ![Text selection and its original source snapshot](docs/screenshots/text-react.png)
24
+ ![Assistant reply selection](docs/screenshots/assistant-react.png)
25
+ ![Persisted sent cards](docs/screenshots/sent-react.png)
26
+ ![PDF selection inside the patched DSH rc.5 application](docs/screenshots/pdf-dsh.png)
27
+ ![Spreadsheet selection and comment inside DSH rc.5](docs/screenshots/spreadsheet-dsh.png)
28
+
29
+ See [screenshot environments and verification](docs/verification.md) for the DSH PDF/Office and spreadsheet examples. Images are captured from the running extracted examples, using synthetic content.
30
+
31
+ </details>
32
+
33
+ ## Install
34
+
35
+ ```sh
36
+ npm install annotation-kit@0.1.0 react@18 react-dom@18
37
+ ```
38
+
39
+ ```tsx
40
+ import { en, type TextSnapshot } from 'annotation-kit'
41
+ import { SelectionCard } from 'annotation-kit/react'
42
+ import 'annotation-kit/styles.css'
43
+
44
+ const quote: TextSnapshot = {
45
+ version: 1, id: 'quote-1', kind: 'text',
46
+ address: 'memory://example/notes.txt', text: 'Keep the original evidence.',
47
+ startLine: 1, endLine: 1, startColumn: 1, endColumn: 28,
48
+ }
49
+
50
+ export function SavedQuote() {
51
+ return <SelectionCard items={[quote]} initiallyOpen t={key => en[key]} />
52
+ }
53
+ ```
54
+
55
+ Your application retains its React root. The package externalizes React and React DOM. Import the stylesheet once through your CSS-aware bundler; Vite consumers normally include `vite/client` in their type environment.
56
+
57
+ ## Run the independent React example
58
+
59
+ ```sh
60
+ git clone https://github.com/leung-alex/annotation-kit.git
61
+ cd annotation-kit
62
+ corepack pnpm install --frozen-lockfile
63
+ pnpm build
64
+ pnpm dev
65
+ ```
66
+
67
+ Open `http://127.0.0.1:4178`. Select a web element or region, add text or an assistant quote, edit the comment, and send the draft. The host event panel shows the received data. Sent messages survive a refresh. Browser image capture in this example uses same-document DOM rasterization; Electron hosts use native `capturePage`.
68
+
69
+ ## Entry points and host integration
70
+
71
+ | Entry | Responsibility |
72
+ | --- | --- |
73
+ | `annotation-kit` | Snapshots, codecs, selection readers, state, image and batch lifecycle |
74
+ | `annotation-kit/react` | Selection actions, comment editors, markers, batch controls and cards |
75
+ | `annotation-kit/electron` | Owned-guest selection/capture bridge and sandbox-compatible preload builder |
76
+
77
+ Implement `ComposerBridge` to connect the current session, draft insertion, independent batch submission and draft editing. Supply your own viewers, Markdown renderer, workbook and source navigation. The library does not ship an Office converter, PDF viewer, model service, DSH Context, or application runtime directory.
78
+
79
+ Read the [host contract and selection recipes](docs/host-integration.md). The independent [React host](examples/react/host.ts) and complete [DSH adapter](examples/dsh/plugin/src/client/index.ts) are working implementations.
80
+
81
+ ## DSH rc.5 example
82
+
83
+ ```sh
84
+ pnpm dsh:prepare
85
+ pnpm dsh:build
86
+ pnpm dsh:check
87
+ pnpm dsh:start
88
+ ```
89
+
90
+ The helper clones official **DSH 0.2.1-rc.5**, commit `b830ec950faba0a46dda564be3e2d854afed94f1`, under `.dsh/runtime`, checks its version and source state, and applies the [registered patch](examples/dsh/patches/dsh-0.2.1-rc.5.patch). Its data and Electron profile are isolated under `.dsh/`. It adds annotation seats, structured-reference presentation, image admission and an owned Electron bridge; it retains DSH's frame and normal browser policy.
91
+
92
+ The example includes a deterministic **local demo model**. Select “Annotation demo (local)” to exercise real DSH submission and persistence without a remote provider. This model does not inspect images or call tools. See the [complete instructions, sample files and revert command](examples/dsh/README.md).
93
+
94
+ This npm package is a library. The DSH example requires the documented source patch and a rebuilt desktop app; it does not claim installation into an unmodified DSH app through its plugin marketplace.
95
+
96
+ ## Environments and limitations
97
+
98
+ - React / React DOM 18; Node 22.19+ for development and Electron build tooling.
99
+ - Browser selection uses rendered DOM; PDF selection requires the viewer's text layer and page canvas. Markdown source locations are omitted when DOM/source parity cannot be established.
100
+ - Spreadsheet integration accepts the host's FortuneSheet 1.0.4 workbook. DSH's patched read-only workbook and parser remain host-owned.
101
+ - Electron image capture requires a visible, owned application window and an authorized guest main frame. Cross-origin frames and canvas use region selection.
102
+ - Storage namespaces and native IPC channel prefixes are configurable. The v1 reference codecs retain their historical `aione-*` wire identifiers so existing data can be read; these are format identifiers, not application dependencies.
103
+ - Current validation and platform scope are recorded in [verification](docs/verification.md). Platforms and versions not exercised there are unverified.
104
+
105
+ ## Development
106
+
107
+ ```sh
108
+ pnpm verify # types, behavior tests, build and external packed consumer
109
+ pnpm build:demo
110
+ pnpm test:demo # running demo + Microsoft Edge required on Windows
111
+ ```
112
+
113
+ `npm pack` contains built entry points, declarations, CSS, preloads, README files and license notices. DSH source, application data, logs, screenshots and example build caches are excluded from the npm tarball. Examples and screenshots live in this repository.
114
+
115
+ MIT © leung-alex. See [LICENSE](LICENSE) and [NOTICE](NOTICE) for third-party attribution, including DeepSeek Harness and react-grab.
@@ -0,0 +1,112 @@
1
+ # annotation-kit
2
+
3
+ 把网页、文档、表格和助手回复中的一段内容,保存为带评论的批注。提供 React 18 界面,保留选中时的原文和图片,由接入的应用负责草稿、会话和发送。
4
+
5
+ [English](README.md) · [接入接口](docs/host-integration.zh-CN.md) · [DSH 完整示例](examples/dsh/README.zh-CN.md)
6
+
7
+ ![独立 React 示例:选择网页元素并添加评论](docs/screenshots/web-react.png)
8
+
9
+ | 场景 | 保存的内容 | 保存后的去向 |
10
+ | --- | --- | --- |
11
+ | 网页元素、网页区域 | 页面地址、元素信息、位置、截图、评论 | 应用的输入草稿 |
12
+ | 代码、普通文本、Markdown | 原文、来源地址、可确定的行列位置 | 输入草稿中的结构化引用 |
13
+ | PDF、Word、PPT | 文本、页码、选区位置或页面局部截图 | 当前会话、当前文件的独立批次 |
14
+ | XLSX、CSV | 工作表、单元格范围、显示值、原始值、公式 | 当前会话、当前文件的独立批次 |
15
+ | 助手回复 | 原始引用、消息位置、可编辑评论 | 输入草稿 |
16
+ | 发送后卡片 | 版本化展示数据与原始证据 | 会话消息,可展开查看 |
17
+
18
+ PPT 普通文字的快捷请求直接提交;文档和表格的普通批注先保存,点击发送才提交。发送失败保留待处理内容,会话切换、网页导航、取消和卸载会中止过期操作。
19
+
20
+ ![原文选区](docs/screenshots/text-react.png)
21
+ ![助手回复选区](docs/screenshots/assistant-react.png)
22
+ ![发送后卡片](docs/screenshots/sent-react.png)
23
+ ![DSH rc.5:PDF 文字批注](docs/screenshots/pdf-dsh.png)
24
+ ![DSH rc.5:表格范围批注](docs/screenshots/spreadsheet-dsh.png)
25
+
26
+ PDF/Office、表格的 DSH 实际效果和各张图的环境说明见[验证记录](docs/verification.md)。全部使用生成的演示材料,从抽离后的运行示例重新截图。
27
+
28
+ ## 安装和最小示例
29
+
30
+ ```sh
31
+ npm install annotation-kit@0.1.0 react@18 react-dom@18
32
+ ```
33
+
34
+ ```tsx
35
+ import { zh, type TextSnapshot } from 'annotation-kit'
36
+ import { SelectionCard } from 'annotation-kit/react'
37
+ import 'annotation-kit/styles.css'
38
+
39
+ const snapshot: TextSnapshot = {
40
+ version: 1, id: 'quote-1', kind: 'text',
41
+ address: 'memory://example/notes.txt', text: '保留选中时的原文。',
42
+ startLine: 1, endLine: 1, startColumn: 1, endColumn: 10,
43
+ }
44
+
45
+ export function SavedQuote() {
46
+ return <SelectionCard items={[snapshot]} initiallyOpen t={key => zh[key]} />
47
+ }
48
+ ```
49
+
50
+ 宿主继续管理 React 根节点,库使用宿主的 React 和 React DOM,不打包第二份 React。样式通过支持 CSS 的构建工具加载一次;Vite 项目通常在类型配置中包含 `vite/client`。
51
+
52
+ ## 不安装 DSH 也能运行
53
+
54
+ ```sh
55
+ git clone https://github.com/leung-alex/annotation-kit.git
56
+ cd annotation-kit
57
+ corepack pnpm install --frozen-lockfile
58
+ pnpm build
59
+ pnpm dev
60
+ ```
61
+
62
+ 访问 `http://127.0.0.1:4178`。网页页签可以选择元素、拖选区域并评论;文字页签可以选中原文;助手页签可以引用回复并编辑评论;发送后可以在卡片页签查看结果,刷新后仍保留。右侧事件面板展示宿主接收到的操作。
63
+
64
+ 独立示例通过同一文档内的 DOM 栅格化生成图片,Electron 示例使用原生网页截图。两种宿主的截图方式会在截图说明中分别标明。
65
+
66
+ ## 库和应用如何分工
67
+
68
+ | 入口 | 提供的能力 |
69
+ | --- | --- |
70
+ | `annotation-kit` | 批注数据、锚点、原文快照、状态、图片和批次管理 |
71
+ | `annotation-kit/react` | 选区按钮、评论框、标记、批次工具条、预览和发送后卡片 |
72
+ | `annotation-kit/electron` | 网页选取与截图桥、沙箱预加载脚本生成 |
73
+
74
+ 应用实现 `ComposerBridge`,提供当前会话、加入输入草稿、独立批次发送和草稿编辑。PDF/Office 预览、Markdown 渲染、表格工作簿、打开来源、身份与权限仍由应用提供。库不依赖 Aione 服务、DSH 的 `Context` 或某个本地目录。
75
+
76
+ 完整的[宿主接口和各类选区用法](docs/host-integration.zh-CN.md)解释了具体参数、保存规则、错误处理、图片生命周期以及 Electron 接入。可直接参考[独立宿主代码](examples/react/host.ts)和 [DSH 接入代码](examples/dsh/plugin/src/client/index.ts)。
77
+
78
+ ## DSH 的补丁如何使用
79
+
80
+ ```sh
81
+ pnpm dsh:prepare
82
+ pnpm dsh:build
83
+ pnpm dsh:check
84
+ pnpm dsh:start
85
+ ```
86
+
87
+ 这些命令在 `.dsh/runtime` 创建干净的官方 **0.2.1-rc.5** 副本,固定提交 `b830ec950faba0a46dda564be3e2d854afed94f1`,校验后应用[配套补丁](examples/dsh/patches/dsh-0.2.1-rc.5.patch)。数据与 Electron 配置也在独立目录中。补丁提供浏览器插槽、助手正文入口、结构化引用展示、图片附件接入和截图桥;保留官方外壳与原有浏览器隔离规则。
88
+
89
+ 示例带有明确标注的本地演示模型。选择 “Annotation demo (local)” 即可演练实际提交和恢复,无需配置远程模型。它只返回固定演示文字,不识别图片、不调用工具。完整步骤、样例文件、检查与撤销见 [DSH 中文指南](examples/dsh/README.zh-CN.md)。
90
+
91
+ 这里发布的是一个普通 npm 库。DSH 示例需要应用补丁并重新构建桌面程序,不能直接在未经修改的 DSH 插件市场中安装。自己开发的 React/Electron 应用可以直接引用库,并自行实现宿主接口。
92
+
93
+ ## 环境、兼容和限制
94
+
95
+ - 使用 React / React DOM 18;开发及 Electron 构建工具需要 Node 22.19 或更高版本。
96
+ - 网页和文字选区依赖实际渲染的 DOM;PDF 需要预览器提供文字层和页面画布。Markdown 无法确定原文与 DOM 对应关系时,不编造行号。
97
+ - 表格由宿主提供 FortuneSheet 1.0.4 工作簿;DSH 的只读修复、解析器与文件转换仍由宿主管理。
98
+ - Electron 截图要求应用窗口可见,目标属于当前窗口且是受控网页的主框架;跨域 iframe、Canvas 可使用区域选取。
99
+ - 存储命名和 IPC 通道前缀可配置。为了继续读取历史数据,v1 引用格式保留原有 `aione-*` 标识;这些是数据格式标识,不是服务依赖。
100
+ - 已验证版本、平台和实际检查范围以[验证记录](docs/verification.md)为准。未实测的平台明确记为未验证。
101
+
102
+ ## 开发和许可证
103
+
104
+ ```sh
105
+ pnpm verify
106
+ pnpm build:demo
107
+ pnpm test:demo # 先运行 pnpm dev;Windows 示例检查使用 Microsoft Edge
108
+ ```
109
+
110
+ npm 包包含编译后的入口、类型、CSS、预加载脚本、README 和许可证。DSH 源码、应用数据、日志、截图、示例缓存均不进入 npm 包;示例与图片在 GitHub 仓库中提供。
111
+
112
+ 采用 MIT,版权归 leung-alex。第三方声明见 [NOTICE](NOTICE),包括 DeepSeek Harness、react-grab 等;完整许可见 [LICENSE](LICENSE)。
@@ -0,0 +1,157 @@
1
+ ._annotate_voyw3_1, ._comment_voyw3_1, ._notice_voyw3_1 { -webkit-app-region: no-drag; }
2
+ ._annotate_voyw3_1 { display: inline-flex; align-items: center; gap: 8px; flex: none; border: 0; border-radius: 22px; padding: 8px 14px; font: inherit; font-size: 14px; font-weight: 400; background: transparent; color: var(--color-text-primary); cursor: pointer; white-space: nowrap; }
3
+ ._annotate_voyw3_1:hover { background: var(--color-background-secondary-soft); }
4
+ ._annotate_voyw3_1[aria-pressed="true"] { color: #2563eb; background: #eaf0fa; }
5
+ ._annotate_voyw3_1:disabled { opacity: .45; cursor: default; }
6
+ ._marker_voyw3_6 { position: fixed; z-index: 1000; color: #3199f8; filter: drop-shadow(0 0 1px white); pointer-events: none; }
7
+ ._comment_voyw3_1 { position: fixed; z-index: 1001; box-sizing: border-box; margin: 0; border: 1px solid var(--color-border-subtle); border-radius: 22px; background: var(--color-surface, white); color: var(--color-text-primary); box-shadow: 0 2px 5px #00000014, 0 8px 24px #00000008; padding: 8px 10px; }
8
+ ._commentRow_voyw3_8 { display: flex; align-items: center; gap: 10px; min-height: 26px; }
9
+ ._comment_voyw3_1 textarea { display: block; flex: 1; min-width: 0; resize: none; border: 0; outline: 0; padding: 0; margin: 0; box-shadow: none; background: transparent; color: inherit; font: 400 12px/20px var(--font-sans, system-ui); max-height: 144px; }
10
+ ._comment_voyw3_1 textarea::placeholder { color: var(--color-text-tertiary, #aaa); }
11
+ ._icon_voyw3_11 { flex: none; width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: 50%; padding: 0; cursor: pointer; background: transparent; color: var(--color-text-secondary); }
12
+ ._icon_voyw3_11:hover { background: var(--color-background-secondary-soft); }
13
+ ._actions_voyw3_13 { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding-top: 8px; }
14
+ ._actions_voyw3_13 ._delete_voyw3_14 { margin-right: auto; }
15
+ ._cancel_voyw3_15, ._save_voyw3_15 { border-radius: 20px; padding: 5px 12px; font: inherit; font-size: 14px; border: 1px solid var(--color-border-subtle); cursor: pointer; }
16
+ ._cancel_voyw3_15 { background: transparent; color: inherit; }
17
+ ._save_voyw3_15 { background: var(--color-text-primary); color: var(--color-surface); border-color: transparent; }
18
+ ._save_voyw3_15:disabled { opacity: .4; cursor: default; }
19
+ ._comment_voyw3_1 button:focus-visible, ._annotate_voyw3_1:focus-visible { outline: 2px solid #1677ff; outline-offset: 3px; }
20
+ ._adjust_voyw3_20 { position: absolute; bottom: calc(100% + 8px); left: 0; padding: 6px; min-width: 168px; background: var(--color-surface); border: 1px solid var(--color-border-subtle); border-radius: 12px; box-shadow: 0 4px 20px #0002; }
21
+ ._adjust_voyw3_20 button { display: flex; align-items: center; gap: 8px; width: 100%; border: 0; padding: 8px 12px; border-radius: 8px; background: transparent; text-align: left; color: inherit; font: inherit; font-size: 14px; cursor: pointer; }
22
+ ._adjust_voyw3_20 button:hover { background: var(--color-background-secondary-soft); }
23
+ ._error_voyw3_23 { padding: 4px 8px 0; color: var(--color-text-danger, #c12a30); font-size: 12px; line-height: 18px; overflow-wrap: anywhere; }
24
+ ._notice_voyw3_1 { position: fixed; z-index: 1001; max-width: 340px; border: 1px solid var(--color-border-subtle); background: var(--color-surface); border-radius: 12px; padding: 12px; font-size: 13px; }
25
+ ._toolbar_voyw3_25 { position: fixed; z-index: 999; transform: translateX(-50%); display: flex; align-items: center; gap: 8px; background: #292929; color: white; border-radius: 16px; padding: 8px 12px; box-shadow: 0 4px 20px #0002; -webkit-app-region: no-drag; }
26
+ ._toolbar_voyw3_25 button { display: flex; align-items: center; justify-content: center; border: 0; border-radius: 10px; background: transparent; color: inherit; padding: 6px; font: 400 14px/20px system-ui; white-space: nowrap; cursor: pointer; }
27
+ ._toolbar_voyw3_25 button:hover { background: #ffffff18; }
28
+ ._toolbar_voyw3_25 ._send_voyw3_28 { background: #3986f6; padding: 6px 12px; }
29
+ ._outline_voyw3_29 { position: fixed; z-index: 998; border: 2px solid #1677ff; background: #1677ff09; pointer-events: none; }
30
+ ._savedMarker_voyw3_30 { position: fixed; z-index: 1000; display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; padding: 0; background: transparent; border: 0; color: #3199f8; cursor: pointer; filter: drop-shadow(0 0 1px white); -webkit-app-region: no-drag; }
31
+ ._savedMarker_voyw3_30 span { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: white; font: 700 12px/1 system-ui; }
32
+ ._host_ptdo8_1 { position: relative; width: 100%; box-sizing: border-box; padding: 4px 12px; -webkit-app-region: no-drag; color: var(--color-text-primary); }
33
+ ._chip_ptdo8_2 { display: inline-flex; border: 1px solid var(--color-border-subtle); border-radius: 12px; background: var(--color-surface); overflow: hidden; }
34
+ ._open_ptdo8_3 { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; line-height: 20px; background: transparent; color: inherit; border: 0; font: inherit; font-size: 14px; cursor: pointer; }
35
+ ._open_ptdo8_3 svg { color: var(--color-text-secondary); }
36
+ ._removeAll_ptdo8_5 { align-self: center; display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; margin-right: 4px; padding: 0; border: 0; border-radius: 50%; color: var(--color-text-secondary); background: transparent; cursor: pointer; }
37
+ ._removeAll_ptdo8_5:hover { background: var(--color-background-secondary-soft); }
38
+ ._packet_ptdo8_7 { position: absolute; z-index: 1002; left: 12px; bottom: calc(100% + 4px); box-sizing: border-box; width: calc(100% - 24px); min-width: 240px; max-height: min(420px, 55vh); overflow: auto; border: 1px solid var(--color-border-subtle); border-radius: 16px; background: var(--color-surface); box-shadow: 0 2px 5px #0000000d, 0 8px 24px #00000008; padding: 12px 16px; }
39
+ ._entry_ptdo8_8 + ._entry_ptdo8_8 { border-top: 1px solid var(--color-border-subtle); padding-top: 12px; margin-top: 12px; }
40
+ ._heading_ptdo8_9 { display: flex; align-items: center; gap: 10px; }
41
+ ._heading_ptdo8_9 code { font-size: 12px; line-height: 20px; padding: 0 7px; border-radius: 7px; background: var(--color-background-secondary-soft); color: var(--color-text-secondary); max-width: 60%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
42
+ ._thumbnail_ptdo8_11 { padding: 0; border: 0; background: transparent; cursor: pointer; }
43
+ ._thumbnail_ptdo8_11 img { display: block; width: 32px; height: 24px; object-fit: cover; border: 1px solid var(--color-border-subtle); border-radius: 6px; }
44
+ ._spacer_ptdo8_13 { flex: 1; }
45
+ ._icon_ptdo8_14 { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 26px; border: 0; padding: 0; background: transparent; color: var(--color-text-secondary); cursor: pointer; border-radius: 6px; }
46
+ ._icon_ptdo8_14:hover, ._open_ptdo8_3:hover { background: var(--color-background-secondary-soft); }
47
+ ._text_ptdo8_16 { margin: 8px 0 4px; white-space: pre-wrap; overflow-wrap: anywhere; font-size: 14px; line-height: 22px; }
48
+ ._image_ptdo8_17 { display: block; margin-top: 10px; width: 100%; height: 180px; object-fit: contain; }
49
+ ._packet_ptdo8_7 textarea { width: 100%; min-height: 72px; resize: vertical; padding: 8px; border: 1px solid var(--color-border-subtle); border-radius: 8px; background: transparent; color: inherit; margin-top: 8px; font: inherit; font-size: 14px; }
50
+ ._actions_ptdo8_19 { display: flex; justify-content: flex-end; gap: 8px; }
51
+ ._actions_ptdo8_19 button { border: 1px solid var(--color-border-subtle); background: transparent; border-radius: 18px; padding: 4px 10px; color: inherit; cursor: pointer; }
52
+ ._dismiss_ptdo8_21 { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
53
+ ._dismiss_ptdo8_21:focus-visible { position: static; width: 24px; height: 24px; clip-path: none; }
54
+ ._host_ptdo8_1 button:focus-visible { outline: 2px solid #1677ff; outline-offset: 2px; }
55
+ /* The editor owns serialization and undo; the attachment card owns presentation. */
56
+ [data-aione-annotation-owned] { display: none; }
57
+ [data-aione-annotation-only]::before { content: attr(data-placeholder); position: absolute; inset: 4px 8px auto 14px; color: var(--dsw-alias-label-caption); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; pointer-events: none; user-select: none; }
58
+ ._draft_ypxoz_1 { position: relative; width: 100%; padding: 4px 12px; box-sizing: border-box; -webkit-app-region: no-drag; }
59
+ ._sent_ypxoz_2 { margin-top: 8px; max-width: 100%; }
60
+ ._chip_ypxoz_3 { display: inline-flex; align-items: center; border: 1px solid var(--color-border-subtle); border-radius: 12px; background: var(--color-surface); color: var(--color-text-primary); }
61
+ ._summary_ypxoz_4 { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; background: transparent; border: 0; border-radius: 11px; color: inherit; font: inherit; font-size: 14px; font-weight: 400; line-height: 20px; cursor: pointer; }
62
+ ._summary_ypxoz_4 svg { color: var(--color-text-secondary); }
63
+ ._removeAll_ypxoz_6, ._remove_ypxoz_6 { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 50%; corner-shape: round; background: transparent; color: var(--color-text-secondary); cursor: pointer; }
64
+ ._removeAll_ypxoz_6 { margin-right: 4px; opacity: 0; }
65
+ ._chip_ypxoz_3:hover ._removeAll_ypxoz_6, ._chip_ypxoz_3:focus-within ._removeAll_ypxoz_6 { opacity: 1; }
66
+ ._summary_ypxoz_4:hover, ._remove_ypxoz_6:hover, ._removeAll_ypxoz_6:hover { background: var(--color-background-secondary-soft); }
67
+ ._popover_ypxoz_10, ._details_ypxoz_10 { box-sizing: border-box; border: 1px solid var(--color-border-subtle); border-radius: 14px; padding: 12px 16px; background: var(--color-surface); color: var(--color-text-primary); max-height: min(420px, 50vh); overflow: auto; }
68
+ ._popover_ypxoz_10 { position: absolute; z-index: 1002; left: 12px; bottom: calc(100% + 4px); width: min(440px, calc(100% - 24px)); max-height: min(420px, 50vh, var(--file-selection-space, 420px)); box-shadow: 0 2px 5px #0000000d, 0 8px 24px #00000012; }
69
+ ._details_ypxoz_10 { margin-top: 8px; }
70
+ ._entry_ypxoz_13 + ._entry_ypxoz_13 { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--color-border-subtle); }
71
+ ._heading_ypxoz_14 { display: flex; align-items: center; gap: 8px; }
72
+ ._source_ypxoz_15 { border: 0; padding: 0; margin-right: auto; background: transparent; color: var(--color-text-secondary); font: inherit; font-size: 12px; font-weight: 400; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
73
+ button._source_ypxoz_15 { cursor: pointer; }
74
+ button._source_ypxoz_15:hover { text-decoration: underline; }
75
+ ._quote_ypxoz_18 { border: 0; padding: 0; margin: 6px 0; white-space: pre-wrap; overflow-wrap: anywhere; font-size: 14px; font-weight: 400; line-height: 22px; }
76
+ ._hint_ypxoz_19 { margin: 8px 0 0; color: var(--color-text-secondary); font-size: 12px; font-weight: 400; line-height: 18px; }
77
+ ._tableScroll_ypxoz_20 { margin-top: 8px; overflow: auto; }
78
+ ._cells_ypxoz_21 { border-collapse: collapse; width: 100%; font-size: 14px; line-height: 22px; }
79
+ ._cells_ypxoz_21 th, ._cells_ypxoz_21 td { text-align: left; vertical-align: top; padding: 5px 8px; border-bottom: 1px solid var(--color-border-subtle); white-space: pre-wrap; overflow-wrap: anywhere; }
80
+ ._cells_ypxoz_21 th { font-weight: 700; }
81
+ ._cells_ypxoz_21 td:first-child { white-space: nowrap; }
82
+ ._cells_ypxoz_21 small { display: block; color: var(--color-text-secondary); font-size: 12px; font-weight: 400; }
83
+ ._draft_ypxoz_1 button:focus-visible, ._sent_ypxoz_2 button:focus-visible { outline: 2px solid var(--color-text-info, #1677ff); outline-offset: 2px; }
84
+ @media (hover: none) { ._removeAll_ypxoz_6 { opacity: 1; } }
85
+ ._overlay_1y8gz_1 { position: fixed; inset: 0; pointer-events: none; -webkit-app-region: initial; }
86
+ [data-annotation-window-interactive] { -webkit-app-region: no-drag; }
87
+ ._control_1hlpi_1 { display: inline-flex; }
88
+ ._toggle_1hlpi_2 { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 34px; padding: 0 12px; border: 1px solid var(--color-border-subtle); border-radius: 999px; corner-shape: round; background: var(--color-surface); color: var(--color-text-primary); font: inherit; font-size: 14px; font-weight: 400; white-space: nowrap; cursor: pointer; box-shadow: 0 2px 5px #00000005; }
89
+ ._toggle_1hlpi_2[aria-pressed="true"] { color: #3268ba; background: #e8effa; border-color: transparent; }
90
+ /* Electron applies app-region to the full layout box, even through clip-path
91
+ and pointer-events:none. Only the interactive panels may subtract dragging. */
92
+ ._chrome_1hlpi_6 { z-index: 1100; }
93
+ ._chrome_1hlpi_6 button, ._chrome_1hlpi_6 textarea { font: inherit; font-size: 14px; font-weight: 400; }
94
+ ._chrome_1hlpi_6 button { cursor: pointer; }
95
+ ._chrome_1hlpi_6 button:disabled, ._toggle_1hlpi_2:disabled { cursor: default; opacity: .45; }
96
+ ._chrome_1hlpi_6 button:focus-visible, ._toggle_1hlpi_2:focus-visible { outline: 2px solid #3884f5; outline-offset: 3px; }
97
+ ._outline_1hlpi_11 { position: fixed; box-sizing: border-box; border: 1px dashed #3977c4; background: #4188ed12; pointer-events: none; }
98
+ ._marker_1hlpi_12 { position: fixed; display: block; width: 26px; height: 26px; border: 1px solid white; border-radius: 50% 50% 50% 0; corner-shape: round; background: #3b82ef; box-shadow: 0 2px 4px #00000010; pointer-events: auto; padding: 0; }
99
+ span._marker_1hlpi_12 { pointer-events: none; }
100
+ ._ask_1hlpi_14 { position: fixed; display: flex; align-items: center; gap: 8px; padding: 7px 10px; border: 1px solid var(--color-border-subtle); border-radius: 10px; background: var(--color-surface); color: var(--color-text-primary); box-shadow: 0 4px 10px #00000012; pointer-events: auto; }
101
+ ._ask_1hlpi_14 kbd { color: var(--color-text-secondary); font: inherit; font-size: 11px; margin-left: 4px; }
102
+ ._comment_1hlpi_16 { position: fixed; box-sizing: border-box; border: 1px solid var(--color-border-subtle); border-radius: 24px; corner-shape: round; background: var(--color-surface); color: var(--color-text-primary); box-shadow: 0 2px 5px #00000009; padding: 7px 8px 7px 16px; pointer-events: auto; }
103
+ ._row_1hlpi_17 { display: flex; align-items: center; gap: 8px; min-height: 28px; }
104
+ ._comment_1hlpi_16 textarea { flex: 1; min-width: 0; width: 100%; padding: 3px 0; border: 0; outline: none; resize: none; box-shadow: none; background: transparent; color: inherit; line-height: 20px; overflow-y: auto; }
105
+ ._comment_1hlpi_16 textarea::placeholder { color: var(--color-text-tertiary); font-size: 12px; }
106
+ ._confirm_1hlpi_20 { flex: 0 0 28px; width: 28px; height: 28px; border: 0; padding: 0; display: grid; place-items: center; background: var(--color-text-primary); color: var(--color-surface); border-radius: 50%; corner-shape: round; }
107
+ ._expanded_1hlpi_21 { border-radius: 22px; padding: 12px; box-shadow: 0 4px 16px #0000000d; }
108
+ ._expanded_1hlpi_21 textarea { min-height: 48px; }
109
+ ._actions_1hlpi_23 { display: flex; align-items: center; gap: 6px; padding-top: 12px; }
110
+ ._actions_1hlpi_23 button { background: transparent; color: inherit; border: 1px solid var(--color-border-subtle); border-radius: 999px; corner-shape: round; padding: 7px 12px; }
111
+ ._actions_1hlpi_23 ._delete_1hlpi_25 { margin-right: auto; border: 0; padding: 6px; color: var(--color-text-secondary); }
112
+ ._actions_1hlpi_23 ._save_1hlpi_26 { background: var(--color-text-primary); color: var(--color-surface); border-color: transparent; }
113
+ ._batch_1hlpi_27 { position: fixed; display: flex; align-items: center; gap: 8px; transform: translateX(-50%); box-sizing: border-box; padding: 6px 6px 6px 10px; border-radius: 12px; background: #303030; color: #fff; pointer-events: auto; box-shadow: 0 3px 8px #00000012; white-space: nowrap; }
114
+ ._count_1hlpi_28 { font-size: 13px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; }
115
+ ._grip_1hlpi_29 { font-size: 16px; opacity: .5; cursor: grab; touch-action: none; user-select: none; }
116
+ ._grip_1hlpi_29:active { cursor: grabbing; }
117
+ ._batch_1hlpi_27 button { border: 0; border-radius: 7px; background: transparent; color: inherit; padding: 6px 8px; font-size: 13px; }
118
+ ._batch_1hlpi_27 ._count_1hlpi_28 { padding-right: 12px; border-right: 1px solid #ffffff35; border-radius: 0; font-weight: 700; }
119
+ [data-sheet-annotations] ._outline_1hlpi_11 { border-width: 2px; }
120
+ ._batch_1hlpi_27 ._send_1hlpi_34 { background: #4389f3; color: #fff; }
121
+ ._batch_1hlpi_27 button:hover { background: #ffffff20; }
122
+ ._batch_1hlpi_27 ._send_1hlpi_34:hover { background: #5897f5; }
123
+ ._error_1hlpi_37 { position: fixed; box-sizing: border-box; padding: 10px 14px; border: 1px solid var(--color-border-subtle); border-radius: 12px; background: var(--color-surface); color: var(--color-text-danger, #c53030); font-size: 13px; overflow-wrap: anywhere; pointer-events: auto; }
124
+ ._snapshotReview_1hlpi_38 { position: fixed; box-sizing: border-box; border-radius: 14px; padding: 12px; background: var(--color-surface); border: 1px solid var(--color-border-subtle); overflow: auto; pointer-events: auto; }
125
+ [data-page-region-selecting] [data-pdf-page] { cursor: crosshair; user-select: none; }
126
+ [data-theme="dark"] ._toggle_1hlpi_2[aria-pressed="true"] { color: #88b8ff; background: #234067; }
127
+ @media (prefers-reduced-motion: no-preference) { ._comment_1hlpi_16, ._batch_1hlpi_27 { animation: _enter_1hlpi_1 100ms ease-out; } @keyframes _enter_1hlpi_1 { from { opacity: 0; } to { opacity: 1; } } }
128
+ ._overlay_1izny_1 { z-index: 1120; }
129
+ ._source_1izny_2 { position: relative; }
130
+ ._markers_1izny_3 { position: absolute; inset: 0; pointer-events: none; z-index: 2; }
131
+ ._highlight_1izny_4 { position: absolute; background: #3496fb40; pointer-events: none; }
132
+ ._marker_1izny_3 { position: absolute; width: 20px; height: 20px; border-radius: 50%; corner-shape: round; color: #fff; font-size: 12px; font-weight: 400; line-height: 18px; text-align: center; }
133
+ ._overlay_1izny_1 ._ask_1izny_6 { justify-content: center; box-sizing: border-box; height: 28px; border-radius: 8px; font-size: 12px; font-weight: 400; line-height: 16px; white-space: nowrap; padding: 0 8px; }
134
+ [data-theme="dark"] ._highlight_1izny_4 { background: #459dff55; }
135
+ ._action_j93o2_1 { position: fixed; z-index: 1100; max-width: min(360px, calc(100vw - 24px)); padding: 4px; border: 1px solid var(--color-border-subtle); border-radius: 12px; background: var(--color-surface); color: var(--color-text-primary); box-shadow: 0 2px 6px #00000012, 0 8px 24px #0000000d; -webkit-app-region: no-drag; }
136
+ ._button_j93o2_2 { display: flex; align-items: center; gap: 6px; min-height: 30px; padding: 4px 8px; border: 0; border-radius: 8px; background: transparent; color: inherit; font: inherit; font-size: 14px; font-weight: 400; line-height: 20px; white-space: nowrap; cursor: pointer; }
137
+ ._button_j93o2_2:hover { background: var(--color-background-secondary-soft); }
138
+ ._button_j93o2_2:focus-visible { outline: 2px solid var(--color-text-info, #1677ff); outline-offset: 2px; }
139
+ ._button_j93o2_2:disabled { opacity: .5; cursor: default; }
140
+ ._error_j93o2_6 { display: block; max-width: 280px; padding: 4px 8px; color: var(--color-text-danger); font-size: 12px; line-height: 18px; }
141
+ ._card_y1yyl_1 { box-sizing: border-box; width: min(100%, 420px); border: 1px solid var(--color-border-subtle); border-radius: 16px; background: var(--color-surface); color: var(--color-text-primary); overflow: hidden; margin-top: 4px; }
142
+ ._summary_y1yyl_3 { display: flex; align-items: center; gap: 8px; width: 100%; border: 0; background: transparent; color: inherit; padding: 12px 14px; font: inherit; font-size: 14px; cursor: pointer; text-align: left; }
143
+ ._summary_y1yyl_3:hover { background: var(--color-background-secondary-soft); }
144
+ ._summary_y1yyl_3:focus-visible { outline: 2px solid var(--color-text-info); outline-offset: -3px; border-radius: 14px; }
145
+ ._toggle_y1yyl_9 { margin-left: auto; color: var(--color-text-secondary); font-size: 12px; }
146
+ ._entry_y1yyl_11 { padding: 10px 14px 12px; border-top: 1px solid var(--color-border-subtle); }
147
+ ._context_y1yyl_13 { display: flex; align-items: center; gap: 7px; color: var(--color-text-secondary); font-size: 12px; line-height: 20px; min-width: 0; }
148
+ ._context_y1yyl_13 > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
149
+ ._number_y1yyl_17 { flex: none; display: inline-grid; place-items: center; min-width: 18px; height: 18px; border-radius: 50%; background: var(--color-background-secondary-soft); }
150
+ ._comment_y1yyl_19 { margin: 5px 0 0; font-size: 14px; line-height: 22px; white-space: pre-wrap; overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
151
+ ._comment_y1yyl_19[data-expanded] { display: block; }
152
+ ._detail_y1yyl_23 { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; padding-top: 8px; }
153
+ ._url_y1yyl_25, ._detail_y1yyl_23 code { max-width: 100%; overflow-wrap: anywhere; font-size: 12px; color: var(--color-text-secondary); }
154
+ ._detail_y1yyl_23 code { padding: 2px 6px; border-radius: 5px; background: var(--color-background-secondary-soft); }
155
+ ._evidence_y1yyl_29 { padding: 10px 14px; border-top: 1px solid var(--color-border-subtle); font-size: 12px; color: var(--color-text-secondary); }
156
+ ._evidence_y1yyl_29 summary { cursor: pointer; }
157
+ ._evidence_y1yyl_29 pre { max-height: 260px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; }