bsky-richtext-react 1.0.2 → 2.0.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/CHANGELOG.md +68 -0
- package/README.md +38 -82
- package/dist/index.cjs +49 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -7
- package/dist/index.d.ts +11 -7
- package/dist/index.js +49 -46
- package/dist/index.js.map +1 -1
- package/package.json +27 -30
- package/dist/styles.css +0 -106
- package/dist/styles.css.map +0 -1
- package/dist/styles.d.cts +0 -2
- package/dist/styles.d.ts +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,74 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [2.0.0] — 2026-02-18
|
|
11
|
+
|
|
12
|
+
### Breaking Changes
|
|
13
|
+
|
|
14
|
+
- **Upgraded all `@tiptap/*` dependencies from v2 to v3** (`^3.20.0`). Consumers must update their installed `@tiptap/*` packages to v3.
|
|
15
|
+
- **Replaced `tippy.js` with `@floating-ui/dom`** for mention suggestion popup positioning, aligning with the tiptap v3 ecosystem. The `tippy.js` peer dependency has been removed.
|
|
16
|
+
- **Peer dependency requirements changed**: consumers must install `@tiptap/*@^3.20.0` and `@floating-ui/dom@^1.6.0`. The `tippy.js` peer dependency is no longer required.
|
|
17
|
+
|
|
18
|
+
### Why
|
|
19
|
+
|
|
20
|
+
- Fixes Turbopack build failures in Next.js 16+ when the consumer's dependency tree includes tiptap v3 packages (e.g., via `@tiptap/starter-kit@3.x`). Turbopack's strict static export analysis caught that `@tiptap/extension-list@3.x` imports symbols from `@tiptap/core` that don't exist in v2.
|
|
21
|
+
- Aligns with the tiptap v3 ecosystem (`tippy.js` → `@floating-ui/dom`).
|
|
22
|
+
|
|
23
|
+
### Migration
|
|
24
|
+
|
|
25
|
+
```diff
|
|
26
|
+
- "@tiptap/core": "^2.x.x",
|
|
27
|
+
+ "@tiptap/core": "^3.20.0",
|
|
28
|
+
// repeat for all @tiptap/* packages
|
|
29
|
+
|
|
30
|
+
- "tippy.js": "^6.x.x",
|
|
31
|
+
+ "@floating-ui/dom": "^1.6.0",
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## [2.0.0] — 2026-02-18
|
|
37
|
+
|
|
38
|
+
### Breaking Changes
|
|
39
|
+
|
|
40
|
+
- **tiptap upgraded from v2 to v3** — all `@tiptap/*` peer dependencies must be updated to `^3.20.0`.
|
|
41
|
+
- **`tippy.js` replaced with `@floating-ui/dom`** — the mention suggestion popup now uses `@floating-ui/dom` for positioning. Remove `tippy.js` from your dependencies and install `@floating-ui/dom` instead.
|
|
42
|
+
|
|
43
|
+
### Migration
|
|
44
|
+
|
|
45
|
+
```diff
|
|
46
|
+
- bun add @tiptap/core@^2 @tiptap/react@^2 ... tippy.js
|
|
47
|
+
+ bun add @tiptap/core@^3.20.0 @tiptap/react@^3.20.0 ... @floating-ui/dom
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Update all `@tiptap/*` peer dependencies to `^3.20.0` and replace `tippy.js` with `@floating-ui/dom`.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## [1.1.0] — 2026-02-17
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- **Default classNames now use Tailwind CSS utility classes** instead of the previous BEM-style class names (`bsky-editor`, `bsky-richtext`, etc.). All components have sensible out-of-the-box appearance as long as Tailwind is configured in the consumer's project — no extra setup needed.
|
|
59
|
+
- `defaultDisplayClassNames` — mentions, links, and tags are styled `text-blue-500 hover:underline`.
|
|
60
|
+
- `defaultEditorClassNames` — editor root is `block w-full relative`; mention chips and autolinks are `inline text-blue-500`.
|
|
61
|
+
- `defaultSuggestionClassNames` — dropdown has full visual defaults: `bg-white rounded-lg shadow-lg border`, hover states, avatar layout, truncated text columns.
|
|
62
|
+
- **`styles.css` removed from the published package.** The `bsky-richtext-react/styles.css` sub-export and the `./dist/styles.css` artefact no longer exist. Remove any `import 'bsky-richtext-react/styles.css'` from your app.
|
|
63
|
+
- **`sideEffects` set to `false`** — the package no longer has CSS side effects, enabling full tree-shaking.
|
|
64
|
+
- **Tailwind added as a `devDependency`** — used exclusively in Storybook for development/testing. Not bundled in or required by consumers.
|
|
65
|
+
- The `classNames` prop API and `generateClassNames()` are unchanged — all existing override patterns continue to work.
|
|
66
|
+
|
|
67
|
+
### Migration
|
|
68
|
+
|
|
69
|
+
```diff
|
|
70
|
+
- import 'bsky-richtext-react/styles.css'
|
|
71
|
+
import { RichTextEditor } from 'bsky-richtext-react'
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
If you were targeting the old BEM class names in your own CSS, replace them with the `classNames` prop or `generateClassNames()` to apply your own classes directly.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
10
78
|
## [1.0.2] — 2026-02-17
|
|
11
79
|
|
|
12
80
|
### Fixed
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
- **`<RichTextDisplay>`** — Render AT Protocol richtext records (`text` + `facets`) as interactive HTML. Handles @mentions, links, and #hashtags with fully customisable renderers and URL resolvers.
|
|
15
15
|
- **`<RichTextEditor>`** — TipTap-based editor with real-time @mention autocomplete (powered by the **Bluesky public API** by default — no auth required), stateless URL decoration, undo/redo, and an imperative ref API.
|
|
16
16
|
- **`generateClassNames()`** — Deep-merge utility for the `classNames` prop system. Pass an array of partial classNames objects and get one merged result, optionally using your own `cn()` / `clsx` / `tailwind-merge` utility.
|
|
17
|
-
- **
|
|
17
|
+
- **Tailwind defaults, fully overridable** — Default classNames use Tailwind utility classes out of the box. Override any part via the `classNames` prop — no stylesheet import needed.
|
|
18
18
|
- **Fully typed** — TypeScript-first with complete type definitions for all AT Protocol facet types.
|
|
19
19
|
- **Tree-shakeable** — ESM + CJS dual build via `tsup`.
|
|
20
20
|
|
|
@@ -36,7 +36,16 @@ pnpm add bsky-richtext-react
|
|
|
36
36
|
Peer dependencies (if not already installed):
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
bun add react react-dom
|
|
39
|
+
bun add react react-dom @floating-ui/dom \
|
|
40
|
+
@tiptap/core@^3.20.0 \
|
|
41
|
+
@tiptap/extension-document@^3.20.0 \
|
|
42
|
+
@tiptap/extension-hard-break@^3.20.0 \
|
|
43
|
+
@tiptap/extension-history@^3.20.0 \
|
|
44
|
+
@tiptap/extension-mention@^3.20.0 \
|
|
45
|
+
@tiptap/extension-paragraph@^3.20.0 \
|
|
46
|
+
@tiptap/extension-placeholder@^3.20.0 \
|
|
47
|
+
@tiptap/extension-text@^3.20.0 \
|
|
48
|
+
@tiptap/react@^3.20.0
|
|
40
49
|
```
|
|
41
50
|
|
|
42
51
|
---
|
|
@@ -47,7 +56,6 @@ bun add react react-dom
|
|
|
47
56
|
|
|
48
57
|
```tsx
|
|
49
58
|
import { RichTextDisplay } from 'bsky-richtext-react'
|
|
50
|
-
import 'bsky-richtext-react/styles.css'
|
|
51
59
|
|
|
52
60
|
// Pass raw fields from an app.bsky.feed.post record
|
|
53
61
|
export function Post({ post }) {
|
|
@@ -59,7 +67,6 @@ export function Post({ post }) {
|
|
|
59
67
|
|
|
60
68
|
```tsx
|
|
61
69
|
import { RichTextEditor } from 'bsky-richtext-react'
|
|
62
|
-
import 'bsky-richtext-react/styles.css'
|
|
63
70
|
|
|
64
71
|
export function Composer() {
|
|
65
72
|
return (
|
|
@@ -81,84 +88,13 @@ export function Composer() {
|
|
|
81
88
|
|
|
82
89
|
## Styling
|
|
83
90
|
|
|
84
|
-
|
|
91
|
+
The library ships **no CSS file**. All default styles are Tailwind utility classes applied through the `classNames` prop system. As long as Tailwind is configured in your project, components look good with zero extra setup.
|
|
85
92
|
|
|
86
|
-
|
|
87
|
-
import 'bsky-richtext-react/styles.css'
|
|
88
|
-
```
|
|
93
|
+
### 1. Defaults — Tailwind utility classes
|
|
89
94
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
### 2. Target the default class names
|
|
93
|
-
|
|
94
|
-
Every element rendered by the components carries a predictable CSS class that you can target directly:
|
|
95
|
-
|
|
96
|
-
#### `<RichTextDisplay>`
|
|
97
|
-
|
|
98
|
-
| Class | Element |
|
|
99
|
-
|-------|---------|
|
|
100
|
-
| `.bsky-richtext` | Root `<span>` |
|
|
101
|
-
| `.bsky-mention` | @mention `<a>` |
|
|
102
|
-
| `.bsky-link` | Link `<a>` |
|
|
103
|
-
| `.bsky-tag` | #hashtag `<a>` |
|
|
104
|
-
|
|
105
|
-
#### `<RichTextEditor>`
|
|
106
|
-
|
|
107
|
-
| Class | Element |
|
|
108
|
-
|-------|---------|
|
|
109
|
-
| `.bsky-editor` | Root wrapper `<div>` |
|
|
110
|
-
| `.bsky-editor-content` | ProseMirror wrapper |
|
|
111
|
-
| `.bsky-editor-mention` | Mention chip inside editor |
|
|
112
|
-
| `.autolink` | URL decoration span inside editor |
|
|
113
|
-
|
|
114
|
-
#### `<MentionSuggestionList>` (dropdown)
|
|
115
|
-
|
|
116
|
-
| Class | Element |
|
|
117
|
-
|-------|---------|
|
|
118
|
-
| `.bsky-suggestions` | Outer container |
|
|
119
|
-
| `.bsky-suggestion-item` | Each suggestion row (`<button>`) |
|
|
120
|
-
| `.bsky-suggestion-item-selected` | Currently highlighted row |
|
|
121
|
-
| `.bsky-suggestion-avatar` | Avatar wrapper |
|
|
122
|
-
| `.bsky-suggestion-avatar-img` | `<img>` element |
|
|
123
|
-
| `.bsky-suggestion-avatar-placeholder` | Initial-letter fallback |
|
|
124
|
-
| `.bsky-suggestion-text` | Text column (name + handle) |
|
|
125
|
-
| `.bsky-suggestion-name` | Display name |
|
|
126
|
-
| `.bsky-suggestion-handle` | `@handle` |
|
|
127
|
-
| `.bsky-suggestion-empty` | "No results" message |
|
|
128
|
-
|
|
129
|
-
```css
|
|
130
|
-
/* Example: style the editor */
|
|
131
|
-
.bsky-editor .ProseMirror {
|
|
132
|
-
padding: 12px 16px;
|
|
133
|
-
border: 1px solid #e1e4e8;
|
|
134
|
-
border-radius: 8px;
|
|
135
|
-
font-size: 16px;
|
|
136
|
-
line-height: 1.5;
|
|
137
|
-
min-height: 120px;
|
|
138
|
-
}
|
|
95
|
+
Every component has a set of default Tailwind classes applied out of the box (see `defaultEditorClassNames`, `defaultDisplayClassNames`, `defaultSuggestionClassNames`). No stylesheet import is required.
|
|
139
96
|
|
|
140
|
-
|
|
141
|
-
.bsky-mention {
|
|
142
|
-
color: #0085ff;
|
|
143
|
-
font-weight: 600;
|
|
144
|
-
text-decoration: none;
|
|
145
|
-
}
|
|
146
|
-
.bsky-mention:hover { text-decoration: underline; }
|
|
147
|
-
|
|
148
|
-
/* Example: style the suggestion dropdown */
|
|
149
|
-
.bsky-suggestions {
|
|
150
|
-
background: #fff;
|
|
151
|
-
border: 1px solid #e1e4e8;
|
|
152
|
-
border-radius: 8px;
|
|
153
|
-
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
|
|
154
|
-
min-width: 240px;
|
|
155
|
-
padding: 4px;
|
|
156
|
-
}
|
|
157
|
-
.bsky-suggestion-item { padding: 8px 10px; border-radius: 6px; }
|
|
158
|
-
.bsky-suggestion-item-selected { background: #f0f4ff; }
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
### 3. Use `generateClassNames()` for targeted overrides
|
|
97
|
+
### 2. Use `generateClassNames()` for targeted overrides
|
|
162
98
|
|
|
163
99
|
The `classNames` prop on each component accepts a nested object. Use `generateClassNames()` to cleanly layer your classes on top of the defaults without rewriting them from scratch:
|
|
164
100
|
|
|
@@ -205,7 +141,9 @@ Pass a plain object to skip the defaults entirely:
|
|
|
205
141
|
<RichTextDisplay classNames={{ root: 'my-text', mention: 'my-mention' }} />
|
|
206
142
|
```
|
|
207
143
|
|
|
208
|
-
###
|
|
144
|
+
### 3. Using `tailwind-merge` to deduplicate classes
|
|
145
|
+
|
|
146
|
+
When layering your own Tailwind classes on top of the defaults, use `tailwind-merge` as the `cn` argument to avoid conflicting class duplication:
|
|
209
147
|
|
|
210
148
|
```tsx
|
|
211
149
|
import { twMerge } from 'tailwind-merge'
|
|
@@ -295,7 +233,7 @@ import { RichTextEditor } from 'bsky-richtext-react'
|
|
|
295
233
|
| `onMentionQuery` | `(query: string) => Promise<MentionSuggestion[]>` | **Bluesky public API** | Custom mention search. Overrides the built-in search. |
|
|
296
234
|
| `mentionSearchDebounceMs` | `number` | `300` | Debounce delay (ms) for the built-in search. No effect when `onMentionQuery` is set. |
|
|
297
235
|
| `disableDefaultMentionSearch` | `boolean` | `false` | Disable the built-in Bluesky API search entirely |
|
|
298
|
-
| `renderMentionSuggestion` | `SuggestionOptions['render']` |
|
|
236
|
+
| `renderMentionSuggestion` | `SuggestionOptions['render']` | @floating-ui/dom popup | Custom TipTap suggestion renderer factory |
|
|
299
237
|
| `mentionSuggestionOptions` | `DefaultSuggestionRendererOptions` | — | Options forwarded to the default renderer |
|
|
300
238
|
| `editorRef` | `Ref<RichTextEditorRef>` | — | Imperative ref |
|
|
301
239
|
| `editable` | `boolean` | `true` | Toggle read-only mode |
|
|
@@ -352,7 +290,7 @@ The editor searches Bluesky actors **by default** when the user types `@`:
|
|
|
352
290
|
|
|
353
291
|
### `<MentionSuggestionList>`
|
|
354
292
|
|
|
355
|
-
The default suggestion dropdown rendered inside the
|
|
293
|
+
The default suggestion dropdown rendered inside the @floating-ui/dom popup. Exported so you can reuse or reference it in your own popup implementation.
|
|
356
294
|
|
|
357
295
|
```tsx
|
|
358
296
|
import { MentionSuggestionList } from 'bsky-richtext-react'
|
|
@@ -578,6 +516,24 @@ bun run format
|
|
|
578
516
|
|
|
579
517
|
---
|
|
580
518
|
|
|
519
|
+
## Migration
|
|
520
|
+
|
|
521
|
+
### v2.0.0 — tiptap v3 upgrade
|
|
522
|
+
|
|
523
|
+
**v2.0.0 upgrades tiptap from v2 to v3.** If you are upgrading from v1.x, you must:
|
|
524
|
+
|
|
525
|
+
1. Update all `@tiptap/*` peer dependencies to `^3.20.0`.
|
|
526
|
+
2. Replace `tippy.js` with `@floating-ui/dom`.
|
|
527
|
+
|
|
528
|
+
```diff
|
|
529
|
+
- bun add @tiptap/core@^2 @tiptap/react@^2 tippy.js
|
|
530
|
+
+ bun add @tiptap/core@^3.20.0 @tiptap/react@^3.20.0 @floating-ui/dom
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
See [CHANGELOG.md](./CHANGELOG.md) for the full list of changes.
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
581
537
|
## Changelog
|
|
582
538
|
|
|
583
539
|
See [CHANGELOG.md](./CHANGELOG.md).
|
package/dist/index.cjs
CHANGED
|
@@ -11,15 +11,11 @@ var extensionHardBreak = require('@tiptap/extension-hard-break');
|
|
|
11
11
|
var extensionPlaceholder = require('@tiptap/extension-placeholder');
|
|
12
12
|
var api = require('@atproto/api');
|
|
13
13
|
var extensionMention = require('@tiptap/extension-mention');
|
|
14
|
-
var
|
|
14
|
+
var dom = require('@floating-ui/dom');
|
|
15
15
|
var core = require('@tiptap/core');
|
|
16
16
|
var state = require('@tiptap/pm/state');
|
|
17
17
|
var view = require('@tiptap/pm/view');
|
|
18
18
|
|
|
19
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
20
|
-
|
|
21
|
-
var tippy__default = /*#__PURE__*/_interopDefault(tippy);
|
|
22
|
-
|
|
23
19
|
// src/components/RichTextDisplay/RichTextDisplay.tsx
|
|
24
20
|
|
|
25
21
|
// src/types/facets.ts
|
|
@@ -35,29 +31,28 @@ function isTagFeature(feature) {
|
|
|
35
31
|
|
|
36
32
|
// src/defaults/classNames.ts
|
|
37
33
|
var defaultDisplayClassNames = {
|
|
38
|
-
root: "
|
|
39
|
-
mention: "
|
|
40
|
-
link: "
|
|
41
|
-
tag: "
|
|
34
|
+
root: "inline break-words",
|
|
35
|
+
mention: "inline text-blue-500 hover:underline cursor-pointer",
|
|
36
|
+
link: "inline text-blue-500 hover:underline",
|
|
37
|
+
tag: "inline text-blue-500 hover:underline cursor-pointer"
|
|
42
38
|
};
|
|
43
39
|
var defaultSuggestionClassNames = {
|
|
44
|
-
root: "
|
|
45
|
-
item: "
|
|
46
|
-
itemSelected: "
|
|
47
|
-
avatar: "
|
|
48
|
-
avatarImg: "
|
|
49
|
-
avatarPlaceholder: "
|
|
50
|
-
text: "
|
|
51
|
-
name: "
|
|
52
|
-
handle: "
|
|
53
|
-
empty: "
|
|
40
|
+
root: "flex flex-col max-h-80 overflow-y-auto bg-white rounded-lg shadow-lg border border-gray-200 min-w-60",
|
|
41
|
+
item: "flex items-center gap-3 w-full px-3 py-2 text-left cursor-pointer border-none bg-transparent hover:bg-gray-100 select-none",
|
|
42
|
+
itemSelected: "bg-gray-100",
|
|
43
|
+
avatar: "flex-shrink-0 w-10 h-10 rounded-full overflow-hidden bg-gray-200 flex items-center justify-center",
|
|
44
|
+
avatarImg: "block w-full h-full object-cover",
|
|
45
|
+
avatarPlaceholder: "flex items-center justify-center w-full h-full text-gray-500 font-medium text-sm",
|
|
46
|
+
text: "flex flex-col flex-1 min-w-0 overflow-hidden",
|
|
47
|
+
name: "block truncate font-medium text-gray-900 text-sm",
|
|
48
|
+
handle: "block truncate text-xs text-gray-500",
|
|
49
|
+
empty: "block px-3 py-2 text-sm text-gray-500"
|
|
54
50
|
};
|
|
55
51
|
var defaultEditorClassNames = {
|
|
56
|
-
root: "
|
|
57
|
-
content: "
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
link: "autolink",
|
|
52
|
+
root: "block w-full relative",
|
|
53
|
+
content: "block w-full",
|
|
54
|
+
mention: "inline text-blue-500",
|
|
55
|
+
link: "inline text-blue-500",
|
|
61
56
|
suggestion: defaultSuggestionClassNames
|
|
62
57
|
};
|
|
63
58
|
|
|
@@ -372,13 +367,7 @@ function createDebouncedSearch(delayMs = 300) {
|
|
|
372
367
|
});
|
|
373
368
|
};
|
|
374
369
|
}
|
|
375
|
-
var MentionSuggestionList = react.forwardRef(function MentionSuggestionListImpl({
|
|
376
|
-
items,
|
|
377
|
-
command,
|
|
378
|
-
showAvatars = true,
|
|
379
|
-
noResultsText = "No results",
|
|
380
|
-
classNames: classNamesProp
|
|
381
|
-
}, ref) {
|
|
370
|
+
var MentionSuggestionList = react.forwardRef(function MentionSuggestionListImpl({ items, command, showAvatars = true, noResultsText = "No results", classNames: classNamesProp }, ref) {
|
|
382
371
|
const [selectedIndex, setSelectedIndex] = react.useState(0);
|
|
383
372
|
const cn = react.useMemo(
|
|
384
373
|
() => generateClassNames([defaultSuggestionClassNames, classNamesProp]),
|
|
@@ -462,12 +451,6 @@ function createDefaultSuggestionRenderer(options = {}) {
|
|
|
462
451
|
return () => {
|
|
463
452
|
let renderer;
|
|
464
453
|
let popup;
|
|
465
|
-
const destroy = () => {
|
|
466
|
-
popup?.[0]?.destroy();
|
|
467
|
-
renderer?.destroy();
|
|
468
|
-
renderer = void 0;
|
|
469
|
-
popup = void 0;
|
|
470
|
-
};
|
|
471
454
|
const buildProps = (props) => ({
|
|
472
455
|
...props,
|
|
473
456
|
showAvatars: options.showAvatars ?? true,
|
|
@@ -482,33 +465,49 @@ function createDefaultSuggestionRenderer(options = {}) {
|
|
|
482
465
|
});
|
|
483
466
|
if (!props.clientRect) return;
|
|
484
467
|
const clientRect = props.clientRect;
|
|
485
|
-
popup =
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
placement: "bottom-start"
|
|
468
|
+
popup = document.createElement("div");
|
|
469
|
+
popup.style.position = "fixed";
|
|
470
|
+
popup.style.zIndex = "9999";
|
|
471
|
+
popup.appendChild(renderer.element);
|
|
472
|
+
document.body.appendChild(popup);
|
|
473
|
+
const virtualEl = { getBoundingClientRect: () => clientRect?.() ?? new DOMRect() };
|
|
474
|
+
void dom.computePosition(virtualEl, popup, {
|
|
475
|
+
placement: "bottom-start",
|
|
476
|
+
middleware: [dom.offset(8), dom.flip(), dom.shift({ padding: 8 })]
|
|
477
|
+
}).then(({ x, y }) => {
|
|
478
|
+
if (popup) {
|
|
479
|
+
popup.style.left = `${x}px`;
|
|
480
|
+
popup.style.top = `${y}px`;
|
|
481
|
+
}
|
|
493
482
|
});
|
|
494
483
|
},
|
|
495
484
|
onUpdate(props) {
|
|
496
485
|
renderer?.updateProps(buildProps(props));
|
|
497
|
-
if (!props.clientRect) return;
|
|
486
|
+
if (!props.clientRect || !popup) return;
|
|
498
487
|
const clientRect = props.clientRect;
|
|
499
|
-
|
|
500
|
-
|
|
488
|
+
const virtualEl = { getBoundingClientRect: () => clientRect?.() ?? new DOMRect() };
|
|
489
|
+
void dom.computePosition(virtualEl, popup, {
|
|
490
|
+
placement: "bottom-start",
|
|
491
|
+
middleware: [dom.offset(8), dom.flip(), dom.shift({ padding: 8 })]
|
|
492
|
+
}).then(({ x, y }) => {
|
|
493
|
+
if (popup) {
|
|
494
|
+
popup.style.left = `${x}px`;
|
|
495
|
+
popup.style.top = `${y}px`;
|
|
496
|
+
}
|
|
501
497
|
});
|
|
502
498
|
},
|
|
503
499
|
onKeyDown(props) {
|
|
504
500
|
if (props.event.key === "Escape") {
|
|
505
|
-
popup
|
|
501
|
+
if (popup) popup.style.display = "none";
|
|
506
502
|
return true;
|
|
507
503
|
}
|
|
508
504
|
return renderer?.ref?.onKeyDown(props) ?? false;
|
|
509
505
|
},
|
|
510
506
|
onExit() {
|
|
511
|
-
|
|
507
|
+
popup?.remove();
|
|
508
|
+
renderer?.destroy();
|
|
509
|
+
popup = void 0;
|
|
510
|
+
renderer = void 0;
|
|
512
511
|
}
|
|
513
512
|
};
|
|
514
513
|
};
|