annotate-kit 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/LICENSE +21 -0
- package/README.md +307 -0
- package/backend/firebase/firestore.indexes.json +22 -0
- package/backend/firebase/firestore.rules +84 -0
- package/backend/firebase/storage.rules +37 -0
- package/backend/supabase/migration.sql +245 -0
- package/dist/adapter-Cyqfwj6F.d.ts +40 -0
- package/dist/annotate-kit.css +2 -0
- package/dist/chunk-G44KPHPN.js +107 -0
- package/dist/delivery.d.ts +31 -0
- package/dist/delivery.js +48 -0
- package/dist/firebase.d.ts +34 -0
- package/dist/firebase.js +200 -0
- package/dist/idb.d.ts +18 -0
- package/dist/idb.js +202 -0
- package/dist/index.d.ts +290 -0
- package/dist/index.js +1856 -0
- package/dist/local.d.ts +18 -0
- package/dist/local.js +115 -0
- package/dist/prompt.d.ts +54 -0
- package/dist/prompt.js +8 -0
- package/dist/rest.d.ts +27 -0
- package/dist/rest.js +63 -0
- package/dist/supabase.d.ts +31 -0
- package/dist/supabase.js +143 -0
- package/dist/types-BLXmj4Oi.d.ts +93 -0
- package/package.json +143 -0
- package/src/Annotate.tsx +1043 -0
- package/src/ScreenshotEditor.tsx +195 -0
- package/src/adapter.ts +31 -0
- package/src/adapters/firebase.ts +197 -0
- package/src/adapters/idb.ts +181 -0
- package/src/adapters/local.ts +114 -0
- package/src/adapters/rest.ts +98 -0
- package/src/adapters/supabase.ts +185 -0
- package/src/constants.ts +35 -0
- package/src/delivery.ts +63 -0
- package/src/index.ts +20 -0
- package/src/prompt.ts +109 -0
- package/src/snapshot.ts +21 -0
- package/src/styles/annotate.css +211 -0
- package/src/types.ts +71 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/* annotate-kit — self-contained stylesheet.
|
|
2
|
+
The overlay keeps HRMS's Tailwind class names; this file compiles JUST the utilities it uses,
|
|
3
|
+
with the design tokens given concrete values. Tailwind's global reset (preflight) is deliberately
|
|
4
|
+
NOT imported — instead a tiny reset scoped to [data-annot-ui] runs, so dropping this CSS into ANY
|
|
5
|
+
app (Tailwind or not, tokens or not) styles the widget correctly and touches nothing else. */
|
|
6
|
+
|
|
7
|
+
@layer theme, base, components, utilities;
|
|
8
|
+
@import "tailwindcss/theme.css" layer(theme);
|
|
9
|
+
@import "tailwindcss/utilities.css" layer(utilities);
|
|
10
|
+
|
|
11
|
+
/* Only scan the widget's own source for class names. */
|
|
12
|
+
@source "../Annotate.tsx";
|
|
13
|
+
@source "../constants.ts";
|
|
14
|
+
|
|
15
|
+
/* ── Design tokens (values lifted verbatim from the HRMS "Trust Enterprise Light" system) ── */
|
|
16
|
+
@theme {
|
|
17
|
+
--color-canvas: #f6f8fb;
|
|
18
|
+
--color-surface: #ffffff;
|
|
19
|
+
--color-elevated: #ffffff;
|
|
20
|
+
--color-sunken: #f1f5f9;
|
|
21
|
+
--color-sidebar: #fbfcfe;
|
|
22
|
+
--color-table-head: #f3f6fa;
|
|
23
|
+
--color-row-alt: #fafbfd;
|
|
24
|
+
|
|
25
|
+
--color-fg: #0f172a;
|
|
26
|
+
--color-fg-secondary: #334155;
|
|
27
|
+
--color-fg-muted: #64748b;
|
|
28
|
+
--color-fg-disabled: #94a3b8;
|
|
29
|
+
--color-ink-hover: #334155;
|
|
30
|
+
|
|
31
|
+
--color-line: #e9eef5;
|
|
32
|
+
--color-line-strong: #d8e0ea;
|
|
33
|
+
--color-line-brand: #e0e3ff;
|
|
34
|
+
|
|
35
|
+
--color-brand: #6366f1;
|
|
36
|
+
--color-brand-strong: #4f46e5;
|
|
37
|
+
--color-brand-deep: #4338ca;
|
|
38
|
+
--color-brand-2: #8b5cf6;
|
|
39
|
+
--color-brand-tint: #eef0ff;
|
|
40
|
+
--color-brand-hairline: #e0e3ff;
|
|
41
|
+
|
|
42
|
+
--color-accent: #f59e0b;
|
|
43
|
+
--color-accent-text: #b45309;
|
|
44
|
+
--color-accent-tint: #fffbeb;
|
|
45
|
+
--color-accent-hairline: #fde68a;
|
|
46
|
+
|
|
47
|
+
--color-success: #059669;
|
|
48
|
+
--color-success-text: #047857;
|
|
49
|
+
--color-success-tint: #ecfdf5;
|
|
50
|
+
--color-success-hairline: #a7f3d0;
|
|
51
|
+
--color-warning: #f59e0b;
|
|
52
|
+
--color-warning-text: #b45309;
|
|
53
|
+
--color-warning-tint: #fffbeb;
|
|
54
|
+
--color-warning-hairline: #fde68a;
|
|
55
|
+
--color-danger: #dc2626;
|
|
56
|
+
--color-danger-text: #b91c1c;
|
|
57
|
+
--color-danger-tint: #fef2f2;
|
|
58
|
+
--color-danger-hairline: #fecaca;
|
|
59
|
+
--color-info: #2563eb;
|
|
60
|
+
--color-info-text: #1d4ed8;
|
|
61
|
+
--color-info-tint: #eff6ff;
|
|
62
|
+
--color-info-hairline: #bfdbfe;
|
|
63
|
+
--color-neutral-tint: #f1f5f9;
|
|
64
|
+
|
|
65
|
+
--radius-input: 0.625rem;
|
|
66
|
+
--radius-control: 0.625rem;
|
|
67
|
+
--radius-card: 0.875rem;
|
|
68
|
+
--radius-modal: 1.25rem;
|
|
69
|
+
|
|
70
|
+
--shadow-e1: 0 1px 2px rgba(16, 24, 40, 0.05);
|
|
71
|
+
--shadow-e2: 0 1px 3px rgba(16, 24, 40, 0.08), 0 1px 2px rgba(16, 24, 40, 0.06);
|
|
72
|
+
--shadow-e3: 0 8px 24px -6px rgba(16, 24, 40, 0.12);
|
|
73
|
+
--shadow-e4: 0 20px 48px -16px rgba(16, 24, 40, 0.28);
|
|
74
|
+
--shadow-brand: 0 10px 28px -10px rgba(99, 102, 241, 0.45);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* ── Scoped reset — replaces preflight, ONLY inside the overlay ──────────────────────────────
|
|
78
|
+
Re-pinning the token vars here means the widget looks identical even if the host app happens to
|
|
79
|
+
define its own --color-surface / --color-fg-* etc. at :root. */
|
|
80
|
+
[data-annot-ui] {
|
|
81
|
+
box-sizing: border-box;
|
|
82
|
+
font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
|
|
83
|
+
line-height: 1.4;
|
|
84
|
+
-webkit-font-smoothing: antialiased;
|
|
85
|
+
color: var(--color-fg-secondary); /* base text colour — inputs inherit this, so typed text stays readable in every theme */
|
|
86
|
+
|
|
87
|
+
--color-canvas: #f6f8fb;
|
|
88
|
+
--color-surface: #ffffff;
|
|
89
|
+
--color-sunken: #f1f5f9;
|
|
90
|
+
--color-row-alt: #fafbfd;
|
|
91
|
+
--color-fg: #0f172a;
|
|
92
|
+
--color-fg-secondary: #334155;
|
|
93
|
+
--color-fg-muted: #64748b;
|
|
94
|
+
--color-fg-disabled: #94a3b8;
|
|
95
|
+
--color-ink-hover: #334155;
|
|
96
|
+
--color-line: #e9eef5;
|
|
97
|
+
--color-line-strong: #d8e0ea;
|
|
98
|
+
--color-brand: #6366f1;
|
|
99
|
+
--color-brand-strong: #4f46e5;
|
|
100
|
+
--color-brand-tint: #eef0ff;
|
|
101
|
+
--color-brand-hairline: #e0e3ff;
|
|
102
|
+
--color-success: #059669;
|
|
103
|
+
--color-success-text: #047857;
|
|
104
|
+
--color-success-tint: #ecfdf5;
|
|
105
|
+
--color-success-hairline: #a7f3d0;
|
|
106
|
+
--color-warning: #f59e0b;
|
|
107
|
+
--color-warning-text: #b45309;
|
|
108
|
+
--color-warning-tint: #fffbeb;
|
|
109
|
+
--color-warning-hairline: #fde68a;
|
|
110
|
+
--color-danger: #dc2626;
|
|
111
|
+
--color-danger-text: #b91c1c;
|
|
112
|
+
--color-danger-tint: #fef2f2;
|
|
113
|
+
--color-danger-hairline: #fecaca;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* ── Dark theme — overrides the token vars when data-annot-theme="dark" (or "auto" + OS is dark).
|
|
117
|
+
--color-fg stays dark ON PURPOSE: it backs the inverted chrome (dock header, tooltips, scrims),
|
|
118
|
+
which keep white text in both themes. Text tokens (fg-secondary/muted) flip to light. ────────── */
|
|
119
|
+
[data-annot-ui][data-annot-theme="dark"],
|
|
120
|
+
[data-annot-theme="dark"] [data-annot-ui] {
|
|
121
|
+
--color-canvas: #0b1120;
|
|
122
|
+
--color-surface: #1e293b;
|
|
123
|
+
--color-sunken: #0f172a;
|
|
124
|
+
--color-row-alt: #263449;
|
|
125
|
+
--color-fg-secondary: #e2e8f0;
|
|
126
|
+
--color-fg-muted: #94a3b8;
|
|
127
|
+
--color-fg-disabled: #64748b;
|
|
128
|
+
--color-line: #334155;
|
|
129
|
+
--color-line-strong: #475569;
|
|
130
|
+
--color-brand-strong: #a5b4fc;
|
|
131
|
+
--color-brand-tint: #312e81;
|
|
132
|
+
--color-brand-hairline: #4338ca;
|
|
133
|
+
--color-success-text: #6ee7b7;
|
|
134
|
+
--color-success-tint: #064e3b;
|
|
135
|
+
--color-success-hairline: #065f46;
|
|
136
|
+
--color-warning-text: #fcd34d;
|
|
137
|
+
--color-warning-tint: #422006;
|
|
138
|
+
--color-warning-hairline: #78350f;
|
|
139
|
+
--color-danger-text: #fca5a5;
|
|
140
|
+
--color-danger-tint: #450a0a;
|
|
141
|
+
--color-danger-hairline: #7f1d1d;
|
|
142
|
+
}
|
|
143
|
+
@media (prefers-color-scheme: dark) {
|
|
144
|
+
[data-annot-ui][data-annot-theme="auto"],
|
|
145
|
+
[data-annot-theme="auto"] [data-annot-ui] {
|
|
146
|
+
--color-canvas: #0b1120;
|
|
147
|
+
--color-surface: #1e293b;
|
|
148
|
+
--color-sunken: #0f172a;
|
|
149
|
+
--color-row-alt: #263449;
|
|
150
|
+
--color-fg-secondary: #e2e8f0;
|
|
151
|
+
--color-fg-muted: #94a3b8;
|
|
152
|
+
--color-fg-disabled: #64748b;
|
|
153
|
+
--color-line: #334155;
|
|
154
|
+
--color-line-strong: #475569;
|
|
155
|
+
--color-brand-strong: #a5b4fc;
|
|
156
|
+
--color-brand-tint: #312e81;
|
|
157
|
+
--color-brand-hairline: #4338ca;
|
|
158
|
+
--color-success-text: #6ee7b7;
|
|
159
|
+
--color-success-tint: #064e3b;
|
|
160
|
+
--color-success-hairline: #065f46;
|
|
161
|
+
--color-warning-text: #fcd34d;
|
|
162
|
+
--color-warning-tint: #422006;
|
|
163
|
+
--color-warning-hairline: #78350f;
|
|
164
|
+
--color-danger-text: #fca5a5;
|
|
165
|
+
--color-danger-tint: #450a0a;
|
|
166
|
+
--color-danger-hairline: #7f1d1d;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
[data-annot-ui] *,
|
|
170
|
+
[data-annot-ui] *::before,
|
|
171
|
+
[data-annot-ui] *::after {
|
|
172
|
+
box-sizing: border-box;
|
|
173
|
+
}
|
|
174
|
+
[data-annot-ui] button {
|
|
175
|
+
margin: 0;
|
|
176
|
+
padding: 0;
|
|
177
|
+
border: 0;
|
|
178
|
+
background: none;
|
|
179
|
+
font: inherit;
|
|
180
|
+
color: inherit;
|
|
181
|
+
line-height: inherit;
|
|
182
|
+
cursor: pointer;
|
|
183
|
+
}
|
|
184
|
+
[data-annot-ui] button:disabled {
|
|
185
|
+
cursor: default;
|
|
186
|
+
}
|
|
187
|
+
[data-annot-ui] input,
|
|
188
|
+
[data-annot-ui] textarea,
|
|
189
|
+
[data-annot-ui] select {
|
|
190
|
+
font: inherit;
|
|
191
|
+
color: inherit;
|
|
192
|
+
margin: 0;
|
|
193
|
+
}
|
|
194
|
+
[data-annot-ui] textarea {
|
|
195
|
+
line-height: 1.4;
|
|
196
|
+
}
|
|
197
|
+
[data-annot-ui] p,
|
|
198
|
+
[data-annot-ui] pre {
|
|
199
|
+
margin: 0;
|
|
200
|
+
}
|
|
201
|
+
[data-annot-ui] svg {
|
|
202
|
+
display: inline-block;
|
|
203
|
+
vertical-align: middle;
|
|
204
|
+
flex-shrink: 0;
|
|
205
|
+
}
|
|
206
|
+
[data-annot-ui] a {
|
|
207
|
+
color: inherit;
|
|
208
|
+
}
|
|
209
|
+
[data-annot-ui] kbd {
|
|
210
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
211
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Data shapes for a single annotation. Kept identical to the HRMS "Live Annotate" model so rows
|
|
2
|
+
// migrate 1:1, but with zero backend/framework coupling — this file is pure types.
|
|
3
|
+
|
|
4
|
+
export type AnnType = 'change' | 'add' | 'remove' | 'bug' | 'style' | 'question'
|
|
5
|
+
export type AnnPriority = 'low' | 'med' | 'high'
|
|
6
|
+
export type AnnStatus = 'open' | 'in_progress' | 'done' | 'dismissed'
|
|
7
|
+
export type AnnKind = 'pin' | 'shape'
|
|
8
|
+
export type AnnShape = 'rect' | 'arrow' | 'circle' | 'freehand'
|
|
9
|
+
export type AnnVisibility = 'public' | 'private'
|
|
10
|
+
|
|
11
|
+
export type AnnReply = { note: string; author?: string; at?: string }
|
|
12
|
+
export type AnnPoint = { x: number; y: number }
|
|
13
|
+
export type AnnMeta = { browser?: string; os?: string; device?: string; viewport?: string; screen?: string; dpr?: number; url?: string; ua?: string }
|
|
14
|
+
export type AnnLog = { level: string; text: string; at?: string }
|
|
15
|
+
export type AnnNetLog = { method: string; url: string; status?: number; ms?: number; ok?: boolean; at?: string }
|
|
16
|
+
|
|
17
|
+
export type Annotation = {
|
|
18
|
+
id: number
|
|
19
|
+
page_route: string
|
|
20
|
+
page_title: string
|
|
21
|
+
target_selector: string
|
|
22
|
+
target_text: string
|
|
23
|
+
pos_x: number
|
|
24
|
+
pos_y: number
|
|
25
|
+
viewport_w: number
|
|
26
|
+
viewport_h: number
|
|
27
|
+
note: string
|
|
28
|
+
type: AnnType
|
|
29
|
+
priority: AnnPriority
|
|
30
|
+
status: AnnStatus
|
|
31
|
+
screenshot_path?: string | null
|
|
32
|
+
screenshot_url?: string | null
|
|
33
|
+
replies?: AnnReply[]
|
|
34
|
+
created_by?: string
|
|
35
|
+
created_at?: string
|
|
36
|
+
updated_at?: string
|
|
37
|
+
// shapes + visibility + author snapshot + captured element styles
|
|
38
|
+
kind?: AnnKind
|
|
39
|
+
shape_type?: AnnShape | null
|
|
40
|
+
x2?: number | null
|
|
41
|
+
y2?: number | null
|
|
42
|
+
points?: AnnPoint[] | null
|
|
43
|
+
color?: string | null
|
|
44
|
+
visibility?: AnnVisibility
|
|
45
|
+
created_by_role?: string | null
|
|
46
|
+
created_by_name?: string | null
|
|
47
|
+
styles?: Record<string, string> | null
|
|
48
|
+
el_context?: string[] | null
|
|
49
|
+
// auto technical context + captured console/JS errors (reproducible bug reports)
|
|
50
|
+
meta?: AnnMeta | null
|
|
51
|
+
console_logs?: AnnLog[] | null
|
|
52
|
+
network_logs?: AnnNetLog[] | null
|
|
53
|
+
dom_snapshot?: string | null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// What the overlay hands the adapter to persist a new mark (server assigns id/timestamps/author).
|
|
57
|
+
export type NewAnnotation = Omit<Annotation, 'id' | 'status' | 'created_at' | 'updated_at' | 'screenshot_url' | 'created_by' | 'created_by_role' | 'created_by_name'> & {
|
|
58
|
+
screenshot_path?: string | null
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// A partial edit (status / note / type / priority) applied by id.
|
|
62
|
+
export type AnnotationPatch = { id: number } & Partial<Pick<Annotation, 'note' | 'status' | 'type' | 'priority'>>
|
|
63
|
+
|
|
64
|
+
// The current viewer + their permission envelope, resolved by the adapter.
|
|
65
|
+
export type AnnotateAccess = {
|
|
66
|
+
enabled: boolean // global toggle: is the tool shown to all users, or ADMIN-only?
|
|
67
|
+
isAdmin: boolean // can flip the global toggle + clear-resolved
|
|
68
|
+
canUse: boolean // may see/use the tool at all (enabled || isAdmin)
|
|
69
|
+
seeAll: boolean // sees everyone's marks + can edit them (else own + public only)
|
|
70
|
+
me?: { email?: string; name?: string; role?: string }
|
|
71
|
+
}
|