@llumi/design-system 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 ADDED
@@ -0,0 +1,210 @@
1
+ # @llumi/design-system
2
+
3
+ Framework-agnostic Web Components (built with [Lit](https://lit.dev)) for the llumi
4
+ review experience. Wrap any content in `<llumi-review>` and let users attach comments to
5
+ whole elements or to text selections, add an overall comment, and submit an approval or a
6
+ set of comments.
7
+
8
+ - **Hybrid DOM** — your content stays in the light DOM (so text selection, `Range`s, and
9
+ the CSS Custom Highlight API work normally); the review chrome (toolbar, dialogs) renders
10
+ in Shadow DOM with its styles encapsulated.
11
+ - **Drop-in** — works in plain HTML or any framework that can render custom elements.
12
+ - **Per-component** — each component is imported on its own (`@llumi/design-system/review`).
13
+ - **Three builds per component** — ESM (the default import), plus single-file UMD and IIFE
14
+ bundles for `<script>` / CDN use.
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ bun add @llumi/design-system
20
+ # or: npm install @llumi/design-system
21
+ ```
22
+
23
+ `lit` is pulled in automatically as a dependency — no peer install required.
24
+
25
+ ## Quick start (ESM)
26
+
27
+ ```ts
28
+ // Registers <llumi-review> and all of its chrome elements.
29
+ // The light-DOM highlight styles are injected automatically on first use —
30
+ // no separate CSS import is required.
31
+ import "@llumi/design-system/review";
32
+ ```
33
+
34
+ ```html
35
+ <llumi-review default-mode="annotating" bar-position="bottom-center">
36
+ <article>
37
+ <h1 data-review-id="title">Project Proposal</h1>
38
+ <p data-review-selectable="intro">
39
+ Select any of this text to leave a comment on the selection…
40
+ </p>
41
+ </article>
42
+ </llumi-review>
43
+
44
+ <script type="module">
45
+ const review = document.querySelector("llumi-review");
46
+ review.addEventListener("llumi-review-submit", (e) => {
47
+ console.log(e.detail); // ReviewResult
48
+ });
49
+ </script>
50
+ ```
51
+
52
+ ### `<script>` tag (no bundler)
53
+
54
+ ```html
55
+ <!-- unpkg / jsDelivr both resolve the IIFE subpath via the package `exports` field -->
56
+ <script src="https://unpkg.com/@llumi/design-system/review.js"></script>
57
+ <!-- jsDelivr can also take the explicit file path -->
58
+ <script src="https://cdn.jsdelivr.net/npm/@llumi/design-system/dist/review.js"></script>
59
+ ```
60
+
61
+ This single file bundles Lit, registers the `<llumi-review>` element, and exposes a `Llumi`
62
+ global. A `require()`-safe UMD/CJS build is also published at `@llumi/design-system/review.cjs`.
63
+
64
+ ## Marking up content
65
+
66
+ Inside `<llumi-review>`, annotate the elements you want to be reviewable:
67
+
68
+ | Attribute | Meaning |
69
+ | --- | --- |
70
+ | `data-review-id="<id>"` | A **whole-element** comment target. Clicking it (in annotate mode) opens a comment dialog and shows a badge when commented. |
71
+ | `data-review-selectable="<id>"` | A region whose **text can be selected** to leave a selection-scoped comment. |
72
+
73
+ An element may carry both attributes. The `<id>` values are yours; they are echoed back in
74
+ each comment's `targetId`.
75
+
76
+ ## Component API
77
+
78
+ ### Attributes
79
+
80
+ | Attribute | Type | Default | Description |
81
+ | --- | --- | --- | --- |
82
+ | `bar-position` | `top-left` \| `top-center` \| `top-right` \| `bottom-left` \| `bottom-center` \| `bottom-right` | `bottom-center` | Initial corner for the floating toolbar (which is also draggable). |
83
+ | `shortcut` | string ([tinykeys](https://github.com/jamiebuilds/tinykeys) syntax) | `$mod+Shift+M` | Keyboard shortcut that toggles annotate mode. |
84
+ | `default-mode` | `idle` \| `annotating` | `idle` | Whether annotate mode is on at mount. |
85
+
86
+ ### Properties (set in JS — complex values)
87
+
88
+ | Property | Type | Description |
89
+ | --- | --- | --- |
90
+ | `initialData` | `ReviewResult` | Pre-populate existing comments / overall comment. |
91
+ | `customTargets` | `CustomTarget[]` | Resolve comment targets from arbitrary selectors (advanced). |
92
+
93
+ ```ts
94
+ const review = document.querySelector("llumi-review");
95
+ review.initialData = {
96
+ status: "commented",
97
+ comments: [{ commentId: "c1", targetId: "title", content: "Tighten this", createdAt: new Date().toISOString() }],
98
+ };
99
+ ```
100
+
101
+ ### Events
102
+
103
+ Both are `CustomEvent<ReviewResult>` and bubble (composed):
104
+
105
+ | Event | Fires |
106
+ | --- | --- |
107
+ | `llumi-review-change` | On every edit (comment added/edited/deleted, overall comment changed). |
108
+ | `llumi-review-submit` | When the user clicks Submit / Approve. |
109
+
110
+ ```ts
111
+ type ReviewResult =
112
+ | { status: "approved" }
113
+ | { status: "commented"; comments: ReviewComment[]; overallComment?: string };
114
+
115
+ interface ReviewComment {
116
+ commentId: string;
117
+ targetId: string; // the data-review-id / data-review-selectable value
118
+ content: string;
119
+ createdAt: string; // ISO timestamp
120
+ selection?: { // present for text-selection comments
121
+ startOffset: number;
122
+ endOffset: number;
123
+ selectedText: string;
124
+ matchIndex: number;
125
+ };
126
+ }
127
+ ```
128
+
129
+ Comments in the result are ordered by their position in the document.
130
+
131
+ ### Keyboard shortcuts
132
+
133
+ | Keys | Action |
134
+ | --- | --- |
135
+ | `$mod+Shift+M` (configurable) | Toggle annotate mode |
136
+ | Hold `Alt` | Temporarily reveal all targets while held |
137
+ | `Escape` / `$mod+Enter` | Close the open dialog |
138
+ | `$mod+Shift+Backspace` | Delete the comment being edited |
139
+
140
+ (`$mod` is ⌘ on macOS, Ctrl elsewhere.)
141
+
142
+ ## Custom comment editor
143
+
144
+ The default editor is an auto-growing textarea. To supply your own, slot an element into
145
+ the comment dialog's `editor` slot. Your element receives the current text via a `value`
146
+ property and must emit these `CustomEvent`s (bubbling + composed):
147
+
148
+ - `change` — `detail` is the new string value
149
+ - `cancel` — request to close the dialog
150
+ - `delete` — request to delete the comment
151
+
152
+ ```html
153
+ <llumi-comment-dialog>
154
+ <my-rich-editor slot="editor"></my-rich-editor>
155
+ </llumi-comment-dialog>
156
+ ```
157
+
158
+ ## Styling & customization
159
+
160
+ No CSS setup is required. The chrome (toolbar, dialogs) ships its Tailwind styles inside
161
+ each element's Shadow DOM, and the light-DOM highlight styles are injected into the
162
+ document automatically when a `<llumi-review>` connects.
163
+
164
+ To theme the highlight outlines, selection colors, and z-index, override these CSS custom
165
+ properties. Set them on `llumi-review` (or any ancestor of your content) so they reliably
166
+ override the injected defaults via inheritance:
167
+
168
+ ```css
169
+ llumi-review {
170
+ /* whole-element outlines */
171
+ --review-highlight-commented-color: oklch(0.7 0 0 / 0.3);
172
+ --review-highlight-editing-color: oklch(0.6 0 0 / 0.7);
173
+ /* text-selection highlights */
174
+ --review-selection-commented-color: oklch(0.85 0.08 250 / 0.4);
175
+ --review-selection-editing-color: oklch(0.75 0.12 250 / 0.6);
176
+ --review-selection-hover-color: oklch(0.8 0.1 250 / 0.5);
177
+ /* stacking */
178
+ --review-z-index: 9998;
179
+ }
180
+ ```
181
+
182
+ All `--review-*` variables defined in the injected stylesheet are overridable this way.
183
+
184
+ ## Package exports
185
+
186
+ | Specifier | Build |
187
+ | --- | --- |
188
+ | `@llumi/design-system/review` | The review component — resolves to ESM on `import`, CJS on `require` (the default entry) |
189
+ | `@llumi/design-system/review.mjs` | ESM bundle (explicit) |
190
+ | `@llumi/design-system/review.cjs` | UMD / CJS bundle, `require()`-safe (Lit included) |
191
+ | `@llumi/design-system/review.js` | IIFE bundle, `Llumi` global (Lit included) |
192
+ | `@llumi/design-system/review.css` | Light-DOM highlight styles — optional; only needed to preload them (e.g. SSR / avoid a first-paint flash), since they're otherwise auto-injected |
193
+
194
+ ## Known limitation
195
+
196
+ Selection highlights use the document-global CSS Custom Highlight API with fixed names, so
197
+ only one active `<llumi-review>` paints selection highlights on the page at a time (this
198
+ matches the original React component). Whole-element highlights and everything else work
199
+ with multiple instances.
200
+
201
+ ## Development
202
+
203
+ ```bash
204
+ bun install
205
+ bun run storybook # interactive dev/docs harness
206
+ bun test # logic tests (XState machine, utilities)
207
+ bun run test:browser # component/DOM tests (Vitest + Playwright)
208
+ bun run build # ESM + UMD + IIFE
209
+ bun run ci # full gate: lint, types, tests, manifest, build
210
+ ```