Compare commits

..

78 Commits

Author SHA1 Message Date
zzj3720 b15a2a9638 fix(editor): adjust the style of the table block 2025-02-21 17:10:06 +08:00
Saul-Mirone f3218ab3bc refactor(editor): rename presets to integration test (#10340) 2025-02-21 06:26:03 +00:00
L-Sun f79324b6a1 chore(editor): update shadow of ask-ai-panel (#10336)
Close [PD-2343](https://linear.app/affine-design/issue/PD-2343/[ui]-ai-面板-shadow-改为-overlaypanelshadow)
2025-02-21 06:12:05 +00:00
Saul-Mirone adcc6b578c refactor(editor): move editor components to frontend core (#10335)
### TL;DR
Moved editor components from BlockSuite presets to AFFiNE core and updated imports accordingly.

### What changed?
- Relocated `EdgelessEditor` and `PageEditor` components from BlockSuite presets to AFFiNE core
- Removed basic editor examples from playground
- Updated import paths across the codebase to reference new component locations
- Added editor effects registration in AFFiNE core
- Removed editor exports from BlockSuite presets

### How to test?
1. Launch the application
2. Verify both page and edgeless editors load correctly
3. Confirm editor functionality remains intact including:
   - Document editing
   - Mode switching
   - Editor toolbars and controls
   - Multiple editor instances

### Why make this change?
This change better aligns with AFFiNE's architecture by moving editor components closer to where they are used. It reduces coupling with BlockSuite presets and gives AFFiNE more direct control over editor customization and implementation.
2025-02-21 04:28:54 +00:00
fengmk2 7f833f8c15 fix(server): don't sync blob meta on workspace deleted event (#10334)
close CLOUD-128
2025-02-21 04:11:57 +00:00
JimmFly 785951bbfa fix(core): adjust copy link button styles (#10337)
close PD-2344
![CleanShot 2025-02-21 at 11 22 32@2x](https://github.com/user-attachments/assets/97d1052b-c900-47df-89ba-476787a28587)
![CleanShot 2025-02-21 at 11 22 08@2x](https://github.com/user-attachments/assets/2b455797-dfc8-4572-95ac-3ee8b33b0528)
2025-02-21 03:58:03 +00:00
fundon 19e9f970f4 fix(editor): block selected style in note under edgeless (#10326)
Related to: https://github.com/toeverything/AFFiNE/pull/9849

Currently missing selected style in note under edgeless.
<img width="860" alt="Screenshot 2025-02-20 at 20 51 12" src="https://github.com/user-attachments/assets/77d68cfb-13d0-4e09-a567-f2a30ba72db1" />
2025-02-21 03:43:54 +00:00
doodlewind c362737441 perf(editor): reduce dom ops in viewport update (#10333) 2025-02-21 03:30:10 +00:00
EYHN 618042812b fix(nbstore): fix cloud awareness (#10320) 2025-02-21 11:11:10 +08:00
fengmk2 0ff7c5f897 fix(server): gen new request id on websocket event request (#10330)
After

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/hTwOityLamd4hitrae7M/22431b9a-30e8-48a3-8db6-de377671f9b7.png)
2025-02-21 02:00:58 +00:00
Saul-Mirone b8dcb85007 refactor: move outline fragment to separate package (#10331)
### TL;DR

Moved outline functionality into a dedicated fragment package and updated vanilla-extract CSS dependency.

### What changed?

- Created new `@blocksuite/affine-fragment-outline` package
- Relocated outline-related code from presets to the new fragment package
- Updated imports across affected files to reference the new package location
- Upgraded `@vanilla-extract/css` dependency from 1.14.0/1.16.1 to 1.17.0
- Added necessary package configuration and TypeScript setup for the new fragment

### How to test?

1. Verify outline functionality works as expected in both desktop and mobile views
2. Check that outline panel, viewer, and mobile menu components render correctly
3. Ensure outline navigation and interactions continue to work
4. Confirm no regressions in outline-related features

### Why make this change?

This change improves code organization by isolating outline functionality into a dedicated package, following the modular architecture pattern. This makes the codebase more maintainable and allows for better separation of concerns. The vanilla-extract CSS upgrade ensures consistency across packages and provides access to the latest features and fixes.
2025-02-20 15:59:13 +00:00
Saul-Mirone 5ac15f12e6 refactor: replace editor container with editor host (#10328)
### TL;DR
Refactored editor access to use `EditorHost` instead of `AffineEditorContainer` and updated mode access through `DocModeProvider`.

### What changed?
- Changed editor property types from `AffineEditorContainer` to `EditorHost` across multiple components
- Updated mode access to use `DocModeProvider` service instead of direct editor mode access
- Modified editor references to use `editor.host` where appropriate
- Updated scroll and highlight utilities to work with `EditorHost`

### How to test?
1. Open a document in both page and edgeless modes
2. Verify outline panel functionality works as expected
3. Test outline viewer navigation and highlighting
4. Confirm mobile outline menu operates correctly
5. Check that frame panel and TOC features work in all modes

### Why make this change?
This change improves architectural consistency by using `EditorHost` directly and accessing mode through the proper service provider. This makes the code more maintainable and follows better dependency practices by using the correct abstraction levels.
2025-02-20 14:20:32 +00:00
akumatus efe36161e8 fix(core): remove candidate doc chip suggestions (#10327)
Fix issue [AF-2247](https://linear.app/affine-design/issue/AF-2247).
2025-02-20 14:01:00 +00:00
akumatus 126677d7ad fix(core): no pop-ups if user click discard menu item (#10317)
Fix issue [BS-2628](https://linear.app/affine-design/issue/BS-2628).
2025-02-20 13:29:28 +00:00
Saul-Mirone 007bbabce4 refactor: move frame manager and panel to separate packages (#10324)
### TL;DR
Moved frame management functionality from `blocksuite/blocks` to `@blocksuite/affine-block-frame` package.

### What changed?
- Relocated `frame-manager.ts` from `blocksuite/blocks` to `@blocksuite/affine-block-frame`
- Added new dependencies to block-frame package: `@blocksuite/affine-block-surface` and `yjs`
- Updated imports across multiple components to reference frame manager from its new location
- Moved utility functions `areSetsEqual` and `isFrameBlock` into frame-manager file
- Replaced direct EdgelessRootService references with GfxController in frame panel components

### How to test?
1. Verify frame functionality works in edgeless mode
2. Test frame creation, selection, and manipulation
3. Confirm frame navigation and presentation modes operate correctly
4. Check that frame panel and toolbar interactions remain functional

### Why make this change?
This refactoring improves code organization by consolidating frame-related functionality into a dedicated package, making the codebase more modular and easier to maintain. It also reduces dependencies between packages and provides clearer boundaries for frame-related features.
2025-02-20 13:06:40 +00:00
doodlewind 64cc99354e refactor(editor): add zoom threshold for dom rendering fallback (#10322) 2025-02-20 11:45:19 +00:00
Saul-Mirone 1516903c77 refactor: move doc-title and ai-chat-block components (#10316)
### TL;DR
Moved doc title and AI chat block components to more appropriate locations while removing unused backlink functionality.

### What changed?
- Relocated doc title component from presets to affine-components
- Moved AI chat block from presets/blocks to blocks directory
- Removed unused backlink-related code and components
- Updated imports across files to reference new component locations
- Consolidated AI-related exports through a single entry point

### How to test?
1. Verify doc title still renders correctly in documents
2. Confirm AI chat functionality works as expected
3. Check that no backlink-related features are accessible
4. Ensure all AI features continue to work through the new import paths

### Why make this change?
This reorganization improves code organization by:
- Placing components closer to their related functionality
- Removing dead/unused code around backlinks
- Simplifying the import structure for AI-related features
- Making the codebase more maintainable by consolidating related components
2025-02-20 10:45:47 +00:00
EYHN 4f831732e1 fix(core): fix throw if aborted polyfill (#10321) 2025-02-20 10:32:02 +00:00
zzj3720 ef28e36441 fix(editor): data in the database will be completely overwritten in some cases (#10318) 2025-02-20 10:17:57 +00:00
doodlewind 7b1dfb7ee8 refactor(editor): reduce dom query per refresh (#10319) 2025-02-20 10:01:13 +00:00
Hwang 5fcc402280 style: update ios dark icon (#10312) 2025-02-20 08:01:32 +00:00
DarkSky fa86f71853 feat(server): client version check (#9205)
Co-authored-by: forehalo <forehalo@gmail.com>
2025-02-20 15:50:22 +08:00
L-Sun 4fee2a9c4b chore(editor): update some widget styles (#10311) 2025-02-20 15:39:48 +08:00
fengmk2 b4097aef8e refactor(server): move bin content parser to doc reader (#10302) 2025-02-20 07:19:48 +00:00
Saul-Mirone 9f4311f654 refactor(editor): remove AbstractEditor type and feature flags in test (#10308) 2025-02-20 07:05:35 +00:00
darkskygit 13f1859cdf feat: allow retry with new message (#10307)
fix AF-1630
2025-02-20 06:07:53 +00:00
Flrande 50820482df fix(editor): auto focus after add inline latex (#10309)
https://github.com/user-attachments/assets/09e713ee-e600-464c-8614-d874d343cfb0

Close #10208
2025-02-20 05:52:06 +00:00
forehalo ec67d30b27 chore(server): race condition during fixing doc owner (#10303) 2025-02-20 05:34:55 +00:00
forehalo fd5897dbe6 chore(server): disable nightly subscriptions expirasion check (#10298) 2025-02-20 05:34:54 +00:00
liuyi d490e767eb fix(server): wrong previous subscription check (#10306) 2025-02-20 13:33:49 +08:00
fundon adc003862b fix(editor): image size and xywh when converting attachment to image (#10200)
In Edgeless, the image size should be read when converting attachment to image:

* fix `size`
* fix `xywh`
2025-02-20 05:16:21 +00:00
fengmk2 ff0ce1a962 fix(server): remove job on complete (#10305) 2025-02-20 04:39:05 +00:00
EYHN 5042d9f644 fix(nbstore): check before save empty update (#10304) 2025-02-20 04:24:50 +00:00
JimmFly 1d339c682b fix(core): adjust share menu and upgrade-to-team page style (#10299)
close PD-2330 PD-2331 AF-2238
2025-02-20 04:10:52 +00:00
doodlewind b38abcb59c perf(editor): avoid recreation of Intl.Segmenter (#10295)
<img width="537" alt="image" src="https://github.com/user-attachments/assets/43e54d94-6228-4c26-b3d0-cf4725b251e4" />
2025-02-20 03:55:57 +00:00
Saul-Mirone c3fc0a0d88 chore(editor): fix imports in legacy tests (#10300) 2025-02-20 03:30:05 +00:00
fengmk2 e0b2b2b33c fix(server): convert error type to lower case (#10301) 2025-02-20 03:04:21 +00:00
zzj3720 ba91b36cc3 feat(editor): add block creation tracking (#10294)
fix: PD-2090
2025-02-20 02:25:29 +00:00
github-actions[bot] a0e3f9909c chore(i18n): sync translations (#10184)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-20 02:25:19 +00:00
EYHN 8f6ce2c3b4 fix(nbstore): fix doc clock comparison (#10296) 2025-02-20 10:10:17 +08:00
zzj3720 d8435421d2 fix(editor): improve table selection in edgeless mode (#10293)
fix: BS-2614, BS-2560
2025-02-20 01:50:40 +00:00
doodlewind 676ccc9094 refactor(editor): allow force refresh in worker renderer (#10289) 2025-02-19 14:23:45 +00:00
Saul-Mirone 091ba7bb51 chore: remove createEmptyEditor legacy test misc (#10291) 2025-02-19 21:38:00 +08:00
donteatfriedrice 2b11941c0e chore: bump theme (#10290) 2025-02-19 11:37:19 +00:00
forehalo 02f567f2c0 chore(core): better doc action error message (#10288) 2025-02-19 10:38:38 +00:00
donteatfriedrice 54b7515167 fix(editor): log when export blob failed (#10287) 2025-02-19 10:06:50 +00:00
CatsJuice e726df9a1b fix(core): prevent all-docs header from overlapping scrollbar (#10270) 2025-02-19 09:24:49 +00:00
CatsJuice 926b35c91f chore(core): temporarily hide editor starter-bar on mobile (#10237) 2025-02-19 09:10:26 +00:00
JimmFly b456feee63 fix(core): unexpected redirect to expired page after accepting invitation (#10257)
Co-authored-by: EYHN <cneyhn@gmail.com>
2025-02-19 09:10:12 +00:00
JimmFly 487158b9ca fix(core): incorrect permissions displayed in member management (#10269) 2025-02-19 16:58:06 +08:00
EYHN 5b768d9091 fix(nbstore): close full blob sync for iOS (#10286) 2025-02-19 16:57:32 +08:00
Saul-Mirone 90b0982dd3 fix(editor): hide edgeless only note in synced doc block (#10277)
Closes: [BS-2616](https://linear.app/affine-design/issue/BS-2616/embed-view-%E5%B1%95%E7%A4%BA%E4%B8%8D%E8%AF%A5%E5%87%BA%E7%8E%B0%E7%9A%84-note-%E5%86%85%E5%AE%B9)
2025-02-19 08:40:26 +00:00
JimmFly e5a1595980 feat(core): add tracking events to doc role management (#10221) 2025-02-19 16:39:50 +08:00
Flrande bc34516e6c fix(editor): embed sync doc theme not reactive (#10283) 2025-02-19 16:38:05 +08:00
liuyi 521ee9d374 fix(server): doc owner and default role permission (#10281) 2025-02-19 08:29:46 +00:00
L-Sun 61ee5531f4 fix(core): incorrect root config identifier (#10285) 2025-02-19 08:20:22 +00:00
EYHN 0f770093b0 fix(nbstore): better diff function for doc update (#10284) 2025-02-19 08:06:51 +00:00
Cats Juice 2d9162b3c4 style(core): adjust ai icon color in starter-bar (#10280) 2025-02-19 16:05:34 +08:00
EYHN c39a93e1fd fix(nbstore): fix v1 doc storage timestamp (#10282) 2025-02-19 16:04:37 +08:00
EYHN 53cada4640 fix(core): throttle sync progress update (#10278) 2025-02-19 07:45:46 +00:00
EYHN 60a9572c88 fix(core): remove crypto randomuuid api (#10268) 2025-02-19 07:32:01 +00:00
Yifeng Wang e5315087cb chore(editor): allow remote debug in presets dev entry (#10279) 2025-02-19 15:15:48 +08:00
donteatfriedrice 319d909ac8 fix(editor): paste surface-ref block to another doc as embed-linked-doc block (#10274)
[BS-2155](https://linear.app/affine-design/issue/BS-2155/复制-insert-frame-group-粘贴后,应当变为-block-ref-link)
2025-02-19 07:02:27 +00:00
JimmFly 751f229e30 fix(core): unexpectedly jump to price plan when selfhosting (#10247) 2025-02-19 07:01:54 +00:00
EYHN c0cc4224bb feat(core): close popup after oauth login (#10273) 2025-02-19 14:44:02 +08:00
liuyi b50e507fc5 fix(core): wrong i18n key used (#10275) 2025-02-19 14:43:39 +08:00
liuyi 294002101d fix(server): wrong queue options for worker executor (#10267) 2025-02-19 04:44:23 +00:00
fengmk2 320875425c fix: replace all CRLF in email token (#10271) 2025-02-19 04:07:43 +00:00
doouding dad39d1129 fix: handle unsupported image upload (#10272) 2025-02-19 03:47:48 +00:00
CatsJuice 35f7f5a01b chore(mobile): adjust setting dialog swipe gesture trigger size (#10236) 2025-02-19 02:41:41 +00:00
pengx17 29f8a627b6 fix(core): center peek doc view circular deps (#10253) 2025-02-19 02:23:53 +00:00
EYHN 5a7ab880c1 fix(core): fix ios blob upload (#10263) 2025-02-19 10:07:46 +08:00
Oleg b20d316d60 fix(editor): ui bugs in linked document embed view (#10105)
Co-authored-by: Mirone <Saul-Mirone@outlook.com>
2025-02-18 23:29:58 +08:00
renovate dc7e7cfc75 chore: bump up all non-major dependencies (#10132)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@aws-sdk/client-s3](https://redirect.github.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3) ([source](https://redirect.github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3)) | [`3.744.0` -> `3.750.0`](https://renovatebot.com/diffs/npm/@aws-sdk%2fclient-s3/3.744.0/3.750.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@aws-sdk%2fclient-s3/3.750.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@aws-sdk%2fclient-s3/3.750.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@aws-sdk%2fclient-s3/3.744.0/3.750.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@aws-sdk%2fclient-s3/3.744.0/3.750.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@capgo/inappbrowser](https://redirect.github.com/Cap-go/capacitor-inappbrowser) | [`7.1.6` -> `7.2.16`](https://renovatebot.com/diffs/npm/@capgo%2finappbrowser/7.1.6/7.2.16) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@capgo%2finappbrowser/7.2.16?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@capgo%2finappbrowser/7.2.16?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@capgo%2finappbrowser/7.1.6/7.2.16?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capgo%2finappbrowser/7.1.6/7.2.16?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@graphql-codegen/cli](https://redirect.github.com/dotansimha/graphql-code-generator) ([source](https://redirect.github.com/dotansimha/graphql-code-generator/tree/HEAD/packages/graphql-codegen-cli)) | [`5.0.4` -> `5.0.5`](https://renovatebot.com/diffs/npm/@graphql-codegen%2fcli/5.0.4/5.0.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@graphql-codegen%2fcli/5.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@graphql-codegen%2fcli/5.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@graphql-codegen%2fcli/5.0.4/5.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@graphql-codegen%2fcli/5.0.4/5.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@lit/context](https://lit.dev/) ([source](https://redirect.github.com/lit/lit/tree/HEAD/packages/context)) | [`1.1.3` -> `1.1.4`](https://renovatebot.com/diffs/npm/@lit%2fcontext/1.1.3/1.1.4) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@lit%2fcontext/1.1.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@lit%2fcontext/1.1.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@lit%2fcontext/1.1.3/1.1.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@lit%2fcontext/1.1.3/1.1.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@opentelemetry/exporter-prometheus](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-prometheus) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`0.57.1` -> `0.57.2`](https://renovatebot.com/diffs/npm/@opentelemetry%2fexporter-prometheus/0.57.1/0.57.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2fexporter-prometheus/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2fexporter-prometheus/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2fexporter-prometheus/0.57.1/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2fexporter-prometheus/0.57.1/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@opentelemetry/instrumentation](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`0.57.1` -> `0.57.2`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation/0.57.1/0.57.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2finstrumentation/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2finstrumentation/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2finstrumentation/0.57.1/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2finstrumentation/0.57.1/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@opentelemetry/instrumentation-http](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-http) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`0.57.1` -> `0.57.2`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation-http/0.57.1/0.57.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2finstrumentation-http/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2finstrumentation-http/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2finstrumentation-http/0.57.1/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2finstrumentation-http/0.57.1/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@opentelemetry/sdk-node](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-sdk-node) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`0.57.1` -> `0.57.2`](https://renovatebot.com/diffs/npm/@opentelemetry%2fsdk-node/0.57.1/0.57.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2fsdk-node/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2fsdk-node/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2fsdk-node/0.57.1/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2fsdk-node/0.57.1/0.57.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@sentry/react](https://redirect.github.com/getsentry/sentry-javascript/tree/master/packages/react) ([source](https://redirect.github.com/getsentry/sentry-javascript)) | [`8.54.0` -> `8.55.0`](https://renovatebot.com/diffs/npm/@sentry%2freact/8.54.0/8.55.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2freact/8.55.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2freact/8.55.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2freact/8.54.0/8.55.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2freact/8.54.0/8.55.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@storybook/addon-essentials](https://redirect.github.com/storybookjs/storybook/tree/next/code/addons/essentials) ([source](https://redirect.github.com/storybookjs/storybook/tree/HEAD/code/addons/essentials)) | [`8.5.4` -> `8.5.6`](https://renovatebot.com/diffs/npm/@storybook%2faddon-essentials/8.5.4/8.5.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@storybook%2faddon-essentials/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@storybook%2faddon-essentials/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@storybook%2faddon-essentials/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@storybook%2faddon-essentials/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@storybook/addon-interactions](https://redirect.github.com/storybookjs/storybook/tree/next/code/addons/interactions) ([source](https://redirect.github.com/storybookjs/storybook/tree/HEAD/code/addons/interactions)) | [`8.5.4` -> `8.5.6`](https://renovatebot.com/diffs/npm/@storybook%2faddon-interactions/8.5.4/8.5.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@storybook%2faddon-interactions/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@storybook%2faddon-interactions/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@storybook%2faddon-interactions/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@storybook%2faddon-interactions/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@storybook/addon-links](https://redirect.github.com/storybookjs/storybook/tree/next/code/addons/links) ([source](https://redirect.github.com/storybookjs/storybook/tree/HEAD/code/addons/links)) | [`8.5.4` -> `8.5.6`](https://renovatebot.com/diffs/npm/@storybook%2faddon-links/8.5.4/8.5.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@storybook%2faddon-links/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@storybook%2faddon-links/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@storybook%2faddon-links/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@storybook%2faddon-links/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@storybook/addon-mdx-gfm](https://redirect.github.com/storybookjs/storybook/tree/next/code/addons/gfm) ([source](https://redirect.github.com/storybookjs/storybook/tree/HEAD/code/addons/gfm)) | [`8.5.4` -> `8.5.6`](https://renovatebot.com/diffs/npm/@storybook%2faddon-mdx-gfm/8.5.4/8.5.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@storybook%2faddon-mdx-gfm/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@storybook%2faddon-mdx-gfm/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@storybook%2faddon-mdx-gfm/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@storybook%2faddon-mdx-gfm/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@storybook/react](https://redirect.github.com/storybookjs/storybook/tree/next/code/renderers/react) ([source](https://redirect.github.com/storybookjs/storybook/tree/HEAD/code/renderers/react)) | [`8.5.4` -> `8.5.6`](https://renovatebot.com/diffs/npm/@storybook%2freact/8.5.4/8.5.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@storybook%2freact/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@storybook%2freact/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@storybook%2freact/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@storybook%2freact/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@storybook/react-vite](https://redirect.github.com/storybookjs/storybook/tree/next/code/frameworks/react-vite) ([source](https://redirect.github.com/storybookjs/storybook/tree/HEAD/code/frameworks/react-vite)) | [`8.5.4` -> `8.5.6`](https://renovatebot.com/diffs/npm/@storybook%2freact-vite/8.5.4/8.5.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@storybook%2freact-vite/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@storybook%2freact-vite/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@storybook%2freact-vite/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@storybook%2freact-vite/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@swc/core](https://swc.rs) ([source](https://redirect.github.com/swc-project/swc)) | [`1.10.15` -> `1.10.17`](https://renovatebot.com/diffs/npm/@swc%2fcore/1.10.15/1.10.17) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@swc%2fcore/1.10.17?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@swc%2fcore/1.10.17?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@swc%2fcore/1.10.15/1.10.17?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@swc%2fcore/1.10.15/1.10.17?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | [`22.13.1` -> `22.13.4`](https://renovatebot.com/diffs/npm/@types%2fnode/22.13.1/22.13.4) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/22.13.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/22.13.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/22.13.1/22.13.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/22.13.1/22.13.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@types/react](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react) ([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react)) | [`19.0.8` -> `19.0.10`](https://renovatebot.com/diffs/npm/@types%2freact/19.0.8/19.0.10) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact/19.0.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact/19.0.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact/19.0.8/19.0.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact/19.0.8/19.0.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@types/react-dom](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-dom) ([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom)) | [`19.0.3` -> `19.0.4`](https://renovatebot.com/diffs/npm/@types%2freact-dom/19.0.3/19.0.4) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact-dom/19.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact-dom/19.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact-dom/19.0.3/19.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact-dom/19.0.3/19.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@vitest/browser](https://redirect.github.com/vitest-dev/vitest/tree/main/packages/browser#readme) ([source](https://redirect.github.com/vitest-dev/vitest/tree/HEAD/packages/browser)) | [`3.0.5` -> `3.0.6`](https://renovatebot.com/diffs/npm/@vitest%2fbrowser/3.0.5/3.0.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@vitest%2fbrowser/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vitest%2fbrowser/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vitest%2fbrowser/3.0.5/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vitest%2fbrowser/3.0.5/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@vitest/coverage-istanbul](https://redirect.github.com/vitest-dev/vitest/tree/main/packages/coverage-istanbul#readme) ([source](https://redirect.github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-istanbul)) | [`3.0.5` -> `3.0.6`](https://renovatebot.com/diffs/npm/@vitest%2fcoverage-istanbul/3.0.5/3.0.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@vitest%2fcoverage-istanbul/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vitest%2fcoverage-istanbul/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vitest%2fcoverage-istanbul/3.0.5/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vitest%2fcoverage-istanbul/3.0.5/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@vitest/ui](https://redirect.github.com/vitest-dev/vitest/tree/main/packages/ui#readme) ([source](https://redirect.github.com/vitest-dev/vitest/tree/HEAD/packages/ui)) | [`3.0.5` -> `3.0.6`](https://renovatebot.com/diffs/npm/@vitest%2fui/3.0.5/3.0.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@vitest%2fui/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vitest%2fui/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vitest%2fui/3.0.5/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vitest%2fui/3.0.5/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [bullmq](https://bullmq.io/) ([source](https://redirect.github.com/taskforcesh/bullmq)) | [`5.40.2` -> `5.41.2`](https://renovatebot.com/diffs/npm/bullmq/5.40.2/5.41.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/bullmq/5.41.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/bullmq/5.41.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/bullmq/5.40.2/5.41.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/bullmq/5.40.2/5.41.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [electron](https://redirect.github.com/electron/electron) | [`34.1.1` -> `34.2.0`](https://renovatebot.com/diffs/npm/electron/34.1.1/34.2.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/electron/34.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/electron/34.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/electron/34.1.1/34.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/electron/34.1.1/34.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [electron-updater](https://redirect.github.com/electron-userland/electron-builder) ([source](https://redirect.github.com/electron-userland/electron-builder/tree/HEAD/packages/electron-updater)) | [`6.5.0` -> `6.6.0`](https://renovatebot.com/diffs/npm/electron-updater/6.5.0/6.6.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/electron-updater/6.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/electron-updater/6.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/electron-updater/6.5.0/6.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/electron-updater/6.5.0/6.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [fast-xml-parser](https://redirect.github.com/NaturalIntelligence/fast-xml-parser) | [`4.5.1` -> `4.5.2`](https://renovatebot.com/diffs/npm/fast-xml-parser/4.5.1/4.5.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/fast-xml-parser/4.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/fast-xml-parser/4.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/fast-xml-parser/4.5.1/4.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/fast-xml-parser/4.5.1/4.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [html-validate](https://html-validate.org) ([source](https://gitlab.com/html-validate/html-validate)) | [`9.2.2` -> `9.3.0`](https://renovatebot.com/diffs/npm/html-validate/9.2.2/9.3.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/html-validate/9.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/html-validate/9.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/html-validate/9.2.2/9.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/html-validate/9.2.2/9.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [inquirer](https://redirect.github.com/SBoudrias/Inquirer.js/blob/main/packages/inquirer/README.md) ([source](https://redirect.github.com/SBoudrias/Inquirer.js)) | [`12.4.1` -> `12.4.2`](https://renovatebot.com/diffs/npm/inquirer/12.4.1/12.4.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/inquirer/12.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/inquirer/12.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/inquirer/12.4.1/12.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/inquirer/12.4.1/12.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [jotai](https://redirect.github.com/pmndrs/jotai) | [`2.12.0` -> `2.12.1`](https://renovatebot.com/diffs/npm/jotai/2.12.0/2.12.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/jotai/2.12.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/jotai/2.12.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/jotai/2.12.0/2.12.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/jotai/2.12.0/2.12.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [nanoid](https://redirect.github.com/ai/nanoid) | [`5.0.9` -> `5.1.0`](https://renovatebot.com/diffs/npm/nanoid/5.0.9/5.1.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/nanoid/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nanoid/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nanoid/5.0.9/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nanoid/5.0.9/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [nestjs-cls](https://papooch.github.io/nestjs-cls/) ([source](https://redirect.github.com/Papooch/nestjs-cls)) | [`5.2.0` -> `5.4.0`](https://renovatebot.com/diffs/npm/nestjs-cls/5.2.0/5.4.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/nestjs-cls/5.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nestjs-cls/5.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nestjs-cls/5.2.0/5.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nestjs-cls/5.2.0/5.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [openai](https://redirect.github.com/openai/openai-node) | [`4.83.0` -> `4.85.1`](https://renovatebot.com/diffs/npm/openai/4.83.0/4.85.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/openai/4.85.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/openai/4.85.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/openai/4.83.0/4.85.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/openai/4.83.0/4.85.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [prettier](https://prettier.io) ([source](https://redirect.github.com/prettier/prettier)) | [`3.5.0` -> `3.5.1`](https://renovatebot.com/diffs/npm/prettier/3.5.0/3.5.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/prettier/3.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prettier/3.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prettier/3.5.0/3.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prettier/3.5.0/3.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [react-i18next](https://redirect.github.com/i18next/react-i18next) | [`15.4.0` -> `15.4.1`](https://renovatebot.com/diffs/npm/react-i18next/15.4.0/15.4.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-i18next/15.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-i18next/15.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-i18next/15.4.0/15.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-i18next/15.4.0/15.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [shiki](https://redirect.github.com/shikijs/shiki) ([source](https://redirect.github.com/shikijs/shiki/tree/HEAD/packages/shiki)) | [`2.3.2` -> `2.5.0`](https://renovatebot.com/diffs/npm/shiki/2.3.2/2.5.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/shiki/2.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/shiki/2.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/shiki/2.3.2/2.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/shiki/2.3.2/2.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [storybook](https://redirect.github.com/storybookjs/storybook/tree/next/code/lib/cli) ([source](https://redirect.github.com/storybookjs/storybook/tree/HEAD/code/lib/cli)) | [`8.5.4` -> `8.5.6`](https://renovatebot.com/diffs/npm/storybook/8.5.4/8.5.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/storybook/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/storybook/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/storybook/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/storybook/8.5.4/8.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [typescript-eslint](https://typescript-eslint.io/packages/typescript-eslint) ([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint)) | [`8.24.0` -> `8.24.1`](https://renovatebot.com/diffs/npm/typescript-eslint/8.24.0/8.24.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/typescript-eslint/8.24.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/typescript-eslint/8.24.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/typescript-eslint/8.24.0/8.24.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/typescript-eslint/8.24.0/8.24.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [vitest](https://redirect.github.com/vitest-dev/vitest) ([source](https://redirect.github.com/vitest-dev/vitest/tree/HEAD/packages/vitest)) | [`3.0.5` -> `3.0.6`](https://renovatebot.com/diffs/npm/vitest/3.0.5/3.0.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/vitest/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vitest/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vitest/3.0.5/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vitest/3.0.5/3.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [webpack](https://redirect.github.com/webpack/webpack) | [`5.97.1` -> `5.98.0`](https://renovatebot.com/diffs/npm/webpack/5.97.1/5.98.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/webpack/5.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/webpack/5.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/webpack/5.97.1/5.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/webpack/5.97.1/5.98.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [com.android.library](https://developer.android.com/studio/build) ([source](https://android.googlesource.com/platform/tools/base)) | `8.8.0` -> `8.8.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.android.library:com.android.library.gradle.plugin/8.8.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.android.library:com.android.library.gradle.plugin/8.8.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.android.library:com.android.library.gradle.plugin/8.8.0/8.8.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.android.library:com.android.library.gradle.plugin/8.8.0/8.8.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [com.android.application](https://developer.android.com/studio/build) ([source](https://android.googlesource.com/platform/tools/base)) | `8.8.0` -> `8.8.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.android.application:com.android.application.gradle.plugin/8.8.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.android.application:com.android.application.gradle.plugin/8.8.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.android.application:com.android.application.gradle.plugin/8.8.0/8.8.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.android.application:com.android.application.gradle.plugin/8.8.0/8.8.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [com.android.tools.build:gradle](https://developer.android.com/studio/build) ([source](https://android.googlesource.com/platform/tools/base)) | `8.8.0` -> `8.8.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.android.tools.build:gradle/8.8.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.android.tools.build:gradle/8.8.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.android.tools.build:gradle/8.8.0/8.8.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.android.tools.build:gradle/8.8.0/8.8.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>aws/aws-sdk-js-v3 (@&#8203;aws-sdk/client-s3)</summary>

### [`v3.750.0`](https://redirect.github.com/aws/aws-sdk-js-v3/blob/HEAD/clients/client-s3/CHANGELOG.md#37500-2025-02-17)

[Compare Source](https://redirect.github.com/aws/aws-sdk-js-v3/compare/v3.749.0...v3.750.0)

**Note:** Version bump only for package [@&#8203;aws-sdk/client-s3](https://redirect.github.com/aws-sdk/client-s3)

### [`v3.749.0`](https://redirect.github.com/aws/aws-sdk-js-v3/blob/HEAD/clients/client-s3/CHANGELOG.md#37490-2025-02-14)

[Compare Source](https://redirect.github.com/aws/aws-sdk-js-v3/compare/v3.744.0...v3.749.0)

##### Features

-   **client-s3:** Added support for Content-Range header in HeadObject response. ([5b15ad8](https://redirect.github.com/aws/aws-sdk-js-v3/commit/5b15ad8260c5d20adf77b35d1762982827c9266b))

</details>

<details>
<summary>Cap-go/capacitor-inappbrowser (@&#8203;capgo/inappbrowser)</summary>

### [`v7.2.16`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#7216-2025-02-10)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.2.15...7.2.16)

### [`v7.2.15`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#7215-2025-02-10)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.2.14...7.2.15)

### [`v7.2.14`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#7214-2025-02-09)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.2.13...7.2.14)

### [`v7.2.13`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#7213-2025-02-09)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.2.9...7.2.13)

### [`v7.2.9`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#729-2025-02-08)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.2.8...7.2.9)

### [`v7.2.8`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#728-2025-02-08)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.2.7...7.2.8)

### [`v7.2.7`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#727-2025-02-08)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.2.6...7.2.7)

### [`v7.2.6`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#726-2025-02-08)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.2.5...7.2.6)

### [`v7.2.5`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#725-2025-02-08)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.2.4...7.2.5)

### [`v7.2.4`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#724-2025-02-08)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.2.3...7.2.4)

### [`v7.2.3`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#723-2025-02-08)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.2.2...7.2.3)

### [`v7.2.2`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#722-2025-02-08)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.2.1...7.2.2)

### [`v7.2.1`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#7216-2025-02-10)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.2.0...7.2.1)

### [`v7.2.0`](https://redirect.github.com/Cap-go/capacitor-inappbrowser/blob/HEAD/CHANGELOG.md#720-2025-02-08)

[Compare Source](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.1.6...7.2.0)

##### Features

-   add ability to close webview from javascript on ios ([5034997](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/50349975e5a0b81595f6f91ea0747910cf9c7aeb))
-   add close function to unified javascript interface ([c3d9079](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/c3d9079cabf4b5c6ea6f6b722cd487cf47e74fa1))
-   close webview with window.AndroidInterface.close() from within ([c5eae97](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/c5eae97a6aa207c9e36121e61530c395a28fffa8))

##### Bug Fixes

-   add better doc for 2 way com ([171ea27](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/171ea27931b36b358c6e34ee80ed89380e0c0fb7))
-   add warning ([84470ae](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/84470ae1c32dbdbcea0ab206367227c270f1b75d))
-   allow inline video ([1368f2a](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/1368f2a4f0eb2b8cb95a91f7c5b23430ae129bce))
-   better definition ([588cc88](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/588cc8843845b2d5c29212d8b767908109264555))
-   CICD ([ee7ef04](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/ee7ef0430ae4b092717f825098db18a86ed07930))
-   order of doc ([71d8923](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/71d892399685d4e67b67a02ee056c51c8f1d912f))
-   versions ([941aabe](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/941aabee33049624f20030ae044a1fde20f8afb7))

##### [7.1.6](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.1.5...7.1.6) (2025-02-02)

##### Bug Fixes

-   lint ([d3df47c](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/d3df47cfef62a89da4f96e0db9d0010a5a4aa6ef))

##### [7.1.5](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.1.4...7.1.5) (2025-02-01)

##### Bug Fixes

-   build ([89cd832](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/89cd832f9699e449e0df684fd2949e41991020f2))

##### [7.1.4](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.1.3...7.1.4) (2025-02-01)

##### Bug Fixes

-   remove READ_MEDIA_IMAGES ([e30874e](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/e30874ebe18d44e39aef60c66bbdf61ad87a0608))

##### [7.1.3](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.1.2...7.1.3) (2025-02-01)

##### Bug Fixes

-   async thread ([df0bb19](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/df0bb198a62cd776925b1622287760845560a7df))

##### [7.1.2](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.1.1...7.1.2) (2025-02-01)

##### Bug Fixes

-   Fixed back_arrow being displayed correctly instead of close_icon ([0516043](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/05160433128222187fff8b12632b711cb7a99b12))
-   openWebView has stopped hiding the phone's status bar. ([465a035](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/465a03561ff8b39b94a9d25396771bbdecf42bc3))
-   openWebView has stopped hiding the phone's status bar. ([6154e54](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/6154e5422c470786d1402c45e432217675347742))
-   openWebView has stopped hiding the phone's status bar. ([ec6a9c2](https://redirect.github.com/Cap-go/capacitor-inappbrowser/commit/ec6a9c220580db66777f0a3886a29eba5d9d7aa4))

##### [7.1.1](https://redirect.github.com/Cap-go/capacitor-inappbrowser/compare/7.1.0...7.1.1) (2025-01-27)

</details>

<details>
<summary>dotansimha/graphql-code-generator (@&#8203;graphql-codegen/cli)</summary>

### [`v5.0.5`](https://redirect.github.com/dotansimha/graphql-code-generator/blob/HEAD/packages/graphql-codegen-cli/CHANGELOG.md#505)

[Compare Source](https://redirect.github.com/dotansimha/graphql-code-generator/compare/@graphql-codegen/cli@5.0.4...@graphql-codegen/cli@5.0.5)

##### Patch Changes

-   [#&#8203;10282](https://redirect.github.com/dotansimha/graphql-code-generator/pull/10282) [`7d7760d`](https://redirect.github.com/dotansimha/graphql-code-generator/commit/7d7760d55c21a99417c38ce5e77a6de22b5effcc) Thanks [@&#8203;oprypkhantc](https://redirect.github.com/oprypkhantc)! - Fix watcher watching project root when schema URL is used

</details>

<details>
<summary>lit/lit (@&#8203;lit/context)</summary>

### [`v1.1.4`](https://redirect.github.com/lit/lit/blob/HEAD/packages/context/CHANGELOG.md#114)

[Compare Source](https://redirect.github.com/lit/lit/compare/@lit/context@1.1.3...7db8eadb285c2a55fe4aa78c491585e1e90d3b1c)

##### Patch Changes

-   [#&#8203;4734](https://redirect.github.com/lit/lit/pull/4734) [`0f535d48`](https://redirect.github.com/lit/lit/commit/0f535d483ba32c57e49ffaa7f7e4ce70a9f6f26d) Thanks [@&#8203;sorin-davidoi](https://redirect.github.com/sorin-davidoi)! - Avoid calling Event.composedPath() when it is not needed

</details>

<details>
<summary>open-telemetry/opentelemetry-js (@&#8203;opentelemetry/exporter-prometheus)</summary>

### [`v0.57.2`](https://redirect.github.com/open-telemetry/opentelemetry-js/compare/cbc912d67bda462ca00449d7ce7b80052c20a4fc...ac8641a5dbb5df1169bd5ed25a6667a6a6f730ca)

[Compare Source](https://redirect.github.com/open-telemetry/opentelemetry-js/compare/cbc912d67bda462ca00449d7ce7b80052c20a4fc...ac8641a5dbb5df1169bd5ed25a6667a6a6f730ca)

</details>

<details>
<summary>getsentry/sentry-javascript (@&#8203;sentry/react)</summary>

### [`v8.55.0`](https://redirect.github.com/getsentry/sentry-javascript/releases/tag/8.55.0)

[Compare Source](https://redirect.github.com/getsentry/sentry-javascript/compare/8.54.0...8.55.0)

##### Important Changes

-   **chore(ci/v8): Switch lambda layer name to `SentryNodeServerlessSDKv8` ([#&#8203;15351](https://redirect.github.com/getsentry/sentry-javascript/pull/15351))**

The `SentryNodeServerlessSDK` AWS Lambda Layer will stop receiving updates.
If you intend to stay on `v8` and receive updates use `SentryNodeServerlessSDKv8` instead.

##### Other Changes

-   feat(flags/v8): add Statsig browser integration ([#&#8203;15347](https://redirect.github.com/getsentry/sentry-javascript/pull/15347))
-   feat(v8/node): Add missing `vercelAIIntegration` export ([#&#8203;15339](https://redirect.github.com/getsentry/sentry-javascript/pull/15339))
-   feat(v8/nuxt): Add `enabled` to disable Sentry module ([#&#8203;15337](https://redirect.github.com/getsentry/sentry-javascript/pull/15337)) ([#&#8203;15381](https://redirect.github.com/getsentry/sentry-javascript/issues/15381))
-   feat(v8/vue): Support Pinia v3 ([#&#8203;15384](https://redirect.github.com/getsentry/sentry-javascript/pull/15384))
-   fix(astro): Add vue to `registerEsmLoaderHooks` ([#&#8203;15352](https://redirect.github.com/getsentry/sentry-javascript/pull/15352))
-   fix(react/v8): Support lazy-loaded routes and components ([#&#8203;15281](https://redirect.github.com/getsentry/sentry-javascript/pull/15281))
-   fix(v8/nuxt): Detect Azure Function runtime for flushing with timeout ([#&#8203;15297](https://redirect.github.com/getsentry/sentry-javascript/pull/15297))
-   fix(v8/solidstart): Do not copy release-injection map file ([#&#8203;15304](https://redirect.github.com/getsentry/sentry-javascript/pull/15304))
-   fix(v8/svelte): Guard component tracking `beforeUpdate` call ([#&#8203;15262](https://redirect.github.com/getsentry/sentry-javascript/pull/15262))

Work in this release was contributed by [@&#8203;aryanvdesh](https://redirect.github.com/aryanvdesh). Thank you for your contribution!

##### Bundle size 📦

| Path                                                             | Size              |
| ---------------------------------------------------------------- | ----------------- |
| [@&#8203;sentry/browser](https://redirect.github.com/sentry/browser)                                                  | 23.3 KB   |
| [@&#8203;sentry/browser](https://redirect.github.com/sentry/browser) - with treeshaking flags                         | 23.17 KB  |
| [@&#8203;sentry/browser](https://redirect.github.com/sentry/browser) (incl. Tracing)                                  | 35.9 KB   |
| [@&#8203;sentry/browser](https://redirect.github.com/sentry/browser) (incl. Tracing, Replay)                          | 73.27 KB  |
| [@&#8203;sentry/browser](https://redirect.github.com/sentry/browser) (incl. Tracing, Replay) - with treeshaking flags | 66.71 KB  |
| [@&#8203;sentry/browser](https://redirect.github.com/sentry/browser) (incl. Tracing, Replay with Canvas)              | 77.57 KB  |
| [@&#8203;sentry/browser](https://redirect.github.com/sentry/browser) (incl. Tracing, Replay, Feedback)                | 89.5 KB   |
| [@&#8203;sentry/browser](https://redirect.github.com/sentry/browser) (incl. Feedback)                                 | 39.51 KB  |
| [@&#8203;sentry/browser](https://redirect.github.com/sentry/browser) (incl. sendFeedback)                             | 27.91 KB  |
| [@&#8203;sentry/browser](https://redirect.github.com/sentry/browser) (incl. FeedbackAsync)                            | 32.71 KB  |
| [@&#8203;sentry/react](https://redirect.github.com/sentry/react)                                                    | 25.98 KB  |
| [@&#8203;sentry/react](https://redirect.github.com/sentry/react) (incl. Tracing)                                    | 38.71 KB  |
| [@&#8203;sentry/vue](https://redirect.github.com/sentry/vue)                                                      | 27.58 KB  |
| [@&#8203;sentry/vue](https://redirect.github.com/sentry/vue) (incl. Tracing)                                      | 37.75 KB  |
| [@&#8203;sentry/svelte](https://redirect.github.com/sentry/svelte)                                                   | 23.46 KB  |
| CDN Bundle                                                       | 24.49 KB  |
| CDN Bundle (incl. Tracing)                                       | 37.6 KB   |
| CDN Bundle (incl. Tracing, Replay)                               | 72.9 KB   |
| CDN Bundle (incl. Tracing, Replay, Feedback)                     | 78.23 KB  |
| CDN Bundle - uncompressed                                        | 71.92 KB  |
| CDN Bundle (incl. Tracing) - uncompressed                        | 111.52 KB |
| CDN Bundle (incl. Tracing, Replay) - uncompressed                | 225.78 KB |
| CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed      | 238.88 KB |
| [@&#8203;sentry/nextjs](https://redirect.github.com/sentry/nextjs) (client)                                          | 38.96 KB  |
| [@&#8203;sentry/sveltekit](https://redirect.github.com/sentry/sveltekit) (client)                                       | 36.4 KB   |
| [@&#8203;sentry/node](https://redirect.github.com/sentry/node)                                                     | 162.85 KB |
| [@&#8203;sentry/node](https://redirect.github.com/sentry/node) - without tracing                                   | 99.14 KB  |
| [@&#8203;sentry/aws-serverless](https://redirect.github.com/sentry/aws-serverless)                                           | 131.23 KB |

</details>

<details>
<summary>storybookjs/storybook (@&#8203;storybook/addon-essentials)</summary>

### [`v8.5.6`](https://redirect.github.com/storybookjs/storybook/blob/HEAD/CHANGELOG.md#856)

[Compare Source](https://redirect.github.com/storybookjs/storybook/compare/v8.5.5...v8.5.6)

-   Builder-Vite: Fix defaulting to allowing all hosts - [#&#8203;30523](https://redirect.github.com/storybookjs/storybook/pull/30523), thanks [@&#8203;JReinhold](https://redirect.github.com/JReinhold)!
-   UI: Fix tags sort for browser back-compat - [#&#8203;30547](https://redirect.github.com/storybookjs/storybook/pull/30547), thanks [@&#8203;shilman](https://redirect.github.com/shilman)!

### [`v8.5.5`](https://redirect.github.com/storybookjs/storybook/blob/HEAD/CHANGELOG.md#855)

[Compare Source](https://redirect.github.com/storybookjs/storybook/compare/v8.5.4...v8.5.5)

-   Builder-Vite: Fix Turbosnap - [#&#8203;30522](https://redirect.github.com/storybookjs/storybook/pull/30522), thanks [@&#8203;valentinpalkovic](https://redirect.github.com/valentinpalkovic)!

</details>

<details>
<summary>swc-project/swc (@&#8203;swc/core)</summary>

### [`v1.10.17`](https://redirect.github.com/swc-project/swc/blob/HEAD/CHANGELOG.md#11017---2025-02-18)

[Compare Source](https://redirect.github.com/swc-project/swc/compare/v1.10.16...v1.10.17)

##### Bug Fixes

-   **(deps)** Update cargo (patch) ([#&#8203;10021](https://redirect.github.com/swc-project/swc/issues/10021)) ([ffb7734](https://redirect.github.com/swc-project/swc/commit/ffb77342d977722c6afa93ac5c8959e2152ea11c))

-   **(typescript)** Improve type inferring for undefined and null ([#&#8203;10038](https://redirect.github.com/swc-project/swc/issues/10038)) ([5059ece](https://redirect.github.com/swc-project/swc/commit/5059ece95a2bf941779213e34dd18997d16a7140))

-   **(typescript)** Remove the usages of private members ([#&#8203;10037](https://redirect.github.com/swc-project/swc/issues/10037)) ([8410b59](https://redirect.github.com/swc-project/swc/commit/8410b596218bfea290751ed40e29fcea8626d0dc))

##### Performance

-   **(hstr)** Use thin arc for hash and length ([#&#8203;10033](https://redirect.github.com/swc-project/swc/issues/10033)) ([2bea793](https://redirect.github.com/swc-project/swc/commit/2bea793bf39c53a5c36b8ccdd274ca93bf1ff1ed))

-   **(hstr)** Skip interning if the text is long enough ([#&#8203;10035](https://redirect.github.com/swc-project/swc/issues/10035)) ([2622e4e](https://redirect.github.com/swc-project/swc/commit/2622e4e1d0263a6a10b6cd47cba3f4e50d697c32))

##### Testing

-   **(hstr)** Add tests ([#&#8203;10043](https://redirect.github.com/swc-project/swc/issues/10043)) ([32b58f0](https://redirect.github.com/swc-project/swc/commit/32b58f0b21bba8c32ea21d3c03d068c7fe260669))

-   **(ts/fast-strip)** Add tests for `declare module` error cases ([#&#8203;10040](https://redirect.github.com/swc-project/swc/issues/10040)) ([37672e0](https://redirect.github.com/swc-project/swc/commit/37672e024e340b1509f4d8f70414bc132a8337bf))

### [`v1.10.16`](https://redirect.github.com/swc-project/swc/blob/HEAD/CHANGELOG.md#11016---2025-02-13)

[Compare Source](https://redirect.github.com/swc-project/swc/compare/v1.10.15...v1.10.16)

##### Bug Fixes

-   **(es/minifier)** Check assign target before merge assign cond ([#&#8203;10020](https://redirect.github.com/swc-project/swc/issues/10020)) ([6dab49a](https://redirect.github.com/swc-project/swc/commit/6dab49a07c5f0853fd6200a7ee153e66a7b8dcdc))

-   **(es/parser)** Preserve comment positions with leading semicolon ([#&#8203;10019](https://redirect.github.com/swc-project/swc/issues/10019)) ([c9937b6](https://redirect.github.com/swc-project/swc/commit/c9937b65bfdaeb2ad9b8fe72943053ac5fe767c5))

-   **(swc_common)** Fix panic with non-narrow chars with width != 2 ([#&#8203;10011](https://redirect.github.com/swc-project/swc/issues/10011)) ([f9f4cac](https://redirect.github.com/swc-project/swc/commit/f9f4cac0e5ae586f0d3cbd3c8f4db8f79ff67e17))

-   **(ts/fast-strip)** Handle unsupported `module` keyword ([#&#8203;10022](https://redirect.github.com/swc-project/swc/issues/10022)) ([308f5d0](https://redirect.github.com/swc-project/swc/commit/308f5d03c735649ec81d73ec6b785cd68345a04c))

##### Performance

-   **(es/codegen)** Reduce allocation using `compact_str` ([#&#8203;10008](https://redirect.github.com/swc-project/swc/issues/10008)) ([7d7319f](https://redirect.github.com/swc-project/swc/commit/7d7319f248afe10f33da2a7201c1a90ec58a441c))

</details>

<details>
<summary>vitest-dev/vitest (@&#8203;vitest/browser)</summary>

### [`v3.0.6`](https://redirect.github.com/vitest-dev/vitest/releases/tag/v3.0.6)

[Compare Source](https://redirect.github.com/vitest-dev/vitest/compare/v3.0.5...v3.0.6)

#####    🐞 Bug Fixes

-   Fix `getMockedSystemTime` for `useFakeTimer`  -  by [@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in [https://github.com/vitest-dev/vitest/issues/7405](https://redirect.github.com/vitest-dev/vitest/issues/7405) [<samp>(03912)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/03912b43)
-   Compat for jest-image-snapshot  -  by [@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in [https://github.com/vitest-dev/vitest/issues/7390](https://redirect.github.com/vitest-dev/vitest/issues/7390) [<samp>(9542b)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/9542b699)
-   Ensure project names are readable in dark terminals  -  by [@&#8203;rgrove](https://redirect.github.com/rgrove) in [https://github.com/vitest-dev/vitest/issues/7371](https://redirect.github.com/vitest-dev/vitest/issues/7371) [<samp>(bb94c)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/bb94c19f)
-   Exclude `queueMicrotask` from default fake timers to not break node fetch  -  by [@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in [https://github.com/vitest-dev/vitest/issues/7505](https://redirect.github.com/vitest-dev/vitest/issues/7505) [<samp>(167a9)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/167a98d7)
-   **browser**:
    -   Fix mocking modules out of root  -  by [@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in [https://github.com/vitest-dev/vitest/issues/7415](https://redirect.github.com/vitest-dev/vitest/issues/7415) [<samp>(d3acb)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/d3acbd8b)
    -   Fix `toHaveClass` typing  -  by [@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in [https://github.com/vitest-dev/vitest/issues/7383](https://redirect.github.com/vitest-dev/vitest/issues/7383) [<samp>(7ef23)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/7ef238c0)
    -   Relax locator selectors methods  -  by [@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/7422](https://redirect.github.com/vitest-dev/vitest/issues/7422) [<samp>(1b8c5)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/1b8c5c9e)
    -   Resolve thread count from `maxWorkers`  -  by [@&#8203;AriPerkkio](https://redirect.github.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/7483](https://redirect.github.com/vitest-dev/vitest/issues/7483) [<samp>(adbb2)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/adbb25ab)
    -   Cleanup timeout on resolve and give more information in the error  -  by [@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/7487](https://redirect.github.com/vitest-dev/vitest/issues/7487) [<samp>(5a45a)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/5a45a7ca)
-   **coverage**:
    -   `vite-node` to pass correct execution wrapper offset  -  by [@&#8203;AriPerkkio](https://redirect.github.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/7417](https://redirect.github.com/vitest-dev/vitest/issues/7417) [<samp>(1f2e5)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/1f2e5552)
    -   Preserve moduleExecutionInfo in non-isolated runs  -  by [@&#8203;AriPerkkio](https://redirect.github.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/7486](https://redirect.github.com/vitest-dev/vitest/issues/7486) [<samp>(f31a0)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/f31a07bb)
-   **deps**:
    -   Update all non-major dependencies  -  by [@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa)
2025-02-18 15:14:03 +00:00
Saul-Mirone 2f04e3180c refactor: move utils and cleanup test helpers (#10261) 2025-02-18 14:03:51 +00:00
Saul-Mirone faf6e2c79f refactor(editor): optimize store map (#10246) 2025-02-18 13:30:09 +00:00
donteatfriedrice 15e9acefc2 fix(editor): paste when select multiple block texts (#10227)
[BS-2512](https://linear.app/affine-design/issue/BS-2512/选中多段粘贴,多段只有第一段会被replace,这个bug还在)
2025-02-18 12:13:55 +00:00
darkskygit 176e0a1950 fix: raw body limit (#10254) 2025-02-18 11:34:58 +00:00
640 changed files with 9494 additions and 4317 deletions
-5
View File
@@ -17,7 +17,6 @@
"@blocksuite/blocks": "workspace:*",
"@blocksuite/global": "workspace:*",
"@blocksuite/inline": "workspace:*",
"@blocksuite/presets": "workspace:*",
"@blocksuite/store": "workspace:*",
"@blocksuite/sync": "workspace:*"
},
@@ -37,7 +36,6 @@
"./inline": "./src/inline/index.ts",
"./inline/consts": "./src/inline/consts.ts",
"./inline/types": "./src/inline/types.ts",
"./presets": "./src/presets/index.ts",
"./blocks": "./src/blocks/index.ts",
"./blocks/schemas": "./src/blocks/schemas.ts",
"./sync": "./src/sync/index.ts"
@@ -83,9 +81,6 @@
"inline/types": [
"dist/inline/types.d.ts"
],
"presets": [
"dist/presets/index.d.ts"
],
"blocks": [
"dist/blocks/index.d.ts"
],
-2
View File
@@ -1,7 +1,5 @@
import { effects as blocksEffects } from '@blocksuite/blocks/effects';
import { effects as presetsEffects } from '@blocksuite/presets/effects';
export function effects() {
blocksEffects();
presetsEffects();
}
@@ -1 +0,0 @@
export * from '@blocksuite/presets';
-1
View File
@@ -11,7 +11,6 @@
{ "path": "../../blocks" },
{ "path": "../../framework/global" },
{ "path": "../../framework/inline" },
{ "path": "../../presets" },
{ "path": "../../framework/store" },
{ "path": "../../framework/sync" }
]
@@ -26,7 +26,7 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"file-type": "^20.0.0",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
@@ -38,8 +38,6 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<Attachment
protected _isResizing = false;
protected _isSelected = false;
protected _whenHover: HoverController | null = new HoverController(
this,
({ abortController }) => {
@@ -35,7 +35,7 @@ export class AttachmentEdgelessBlockComponent extends toGfxBlockComponent(
this.slots.elementResizeEnd.on(() => {
this._isResizing = false;
this._showOverlay =
this._isResizing || this._isDragging || !this._isSelected;
this._isResizing || this._isDragging || !this.selected$.peek();
})
);
}
+46 -11
View File
@@ -1,20 +1,25 @@
import type {
AttachmentBlockModel,
ImageBlockProps,
import {
type AttachmentBlockModel,
type ImageBlockProps,
MAX_IMAGE_WIDTH,
} from '@blocksuite/affine-model';
import { FileSizeLimitService } from '@blocksuite/affine-shared/services';
import {
readImageSize,
transformModel,
withTempBlobData,
} from '@blocksuite/affine-shared/utils';
import { type BlockStdScope, StdIdentifier } from '@blocksuite/block-std';
import type { Container } from '@blocksuite/global/di';
import { createIdentifier } from '@blocksuite/global/di';
import { Bound } from '@blocksuite/global/utils';
import type { ExtensionType } from '@blocksuite/store';
import { Extension } from '@blocksuite/store';
import type { TemplateResult } from 'lit';
import { html } from 'lit';
import { getAttachmentBlob } from './utils';
export type AttachmentEmbedConfig = {
name: string;
/**
@@ -24,7 +29,10 @@ export type AttachmentEmbedConfig = {
/**
* The action will be executed when the 「Turn into embed view」 button is clicked.
*/
action?: (model: AttachmentBlockModel) => Promise<void> | void;
action?: (
model: AttachmentBlockModel,
std: BlockStdScope
) => Promise<void> | void;
/**
* The template will be used to render the embed view.
*/
@@ -89,11 +97,11 @@ export class AttachmentEmbedService extends Extension {
// Converts to embed view.
convertTo(model: AttachmentBlockModel, maxFileSize = this._maxFileSize) {
const config = this.values.find(config => config.check(model, maxFileSize));
if (!config || !config.action) {
if (!config?.action) {
model.doc.updateBlock(model, { embed: true });
return;
}
config.action(model)?.catch(console.error);
config.action(model, this.std)?.catch(console.error);
}
embedded(model: AttachmentBlockModel, maxFileSize = this._maxFileSize) {
@@ -123,7 +131,12 @@ const embedConfig: AttachmentEmbedConfig[] = [
check: model =>
model.doc.schema.flavourSchemaMap.has('affine:image') &&
model.type.startsWith('image/'),
action: model => turnIntoImageBlock(model),
async action(model, std) {
const component = std.view.getBlock(model.id);
if (!component) return;
await turnIntoImageBlock(model);
},
},
{
name: 'pdf',
@@ -171,7 +184,7 @@ const embedConfig: AttachmentEmbedConfig[] = [
/**
* Turn the attachment block into an image block.
*/
export function turnIntoImageBlock(model: AttachmentBlockModel) {
export async function turnIntoImageBlock(model: AttachmentBlockModel) {
if (!model.doc.schema.flavourSchemaMap.has('affine:image')) {
console.error('The image flavour is not supported!');
return;
@@ -183,15 +196,37 @@ export function turnIntoImageBlock(model: AttachmentBlockModel) {
const { saveAttachmentData, getImageData } = withTempBlobData();
saveAttachmentData(sourceId, { name: model.name });
const imageConvertData = model.sourceId
? getImageData(model.sourceId)
let imageSize = model.sourceId ? getImageData(model.sourceId) : undefined;
const bounds = model.xywh
? Bound.fromXYWH(model.deserializedXYWH)
: undefined;
if (bounds) {
if (!imageSize?.width || !imageSize?.height) {
const blob = await getAttachmentBlob(model);
if (blob) {
imageSize = await readImageSize(blob);
}
}
if (imageSize?.width && imageSize?.height) {
const p = imageSize.height / imageSize.width;
imageSize.width = Math.min(imageSize.width, MAX_IMAGE_WIDTH);
imageSize.height = imageSize.width * p;
bounds.w = imageSize.width;
bounds.h = imageSize.height;
}
}
const others = bounds ? { xywh: bounds.serialize() } : undefined;
const imageProp: Partial<ImageBlockProps> = {
sourceId,
caption: model.caption,
size: model.size,
...imageConvertData,
...imageSize,
...others,
};
transformModel(model, 'affine:image', imageProp);
}
@@ -97,7 +97,7 @@ export async function uploadAttachmentBlob(
}
}
async function getAttachmentBlob(model: AttachmentBlockModel) {
export async function getAttachmentBlob(model: AttachmentBlockModel) {
const sourceId = model.sourceId;
if (!sourceId) {
return null;
@@ -25,7 +25,7 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
"zod": "^3.23.8"
@@ -4,9 +4,10 @@ import {
} from '@blocksuite/affine-components/caption';
import type { BookmarkBlockModel } from '@blocksuite/affine-model';
import { DocModeProvider } from '@blocksuite/affine-shared/services';
import { computed, type ReadonlySignal } from '@preact/signals-core';
import { html } from 'lit';
import { property, query } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { type ClassInfo, classMap } from 'lit/directives/class-map.js';
import { type StyleInfo, styleMap } from 'lit/directives/style-map.js';
import { refreshBookmarkUrlData } from './utils.js';
@@ -14,6 +15,12 @@ import { refreshBookmarkUrlData } from './utils.js';
export const BOOKMARK_MIN_WIDTH = 450;
export class BookmarkBlockComponent extends CaptionedBlockComponent<BookmarkBlockModel> {
selectedStyle$: ReadonlySignal<ClassInfo> | null = computed<ClassInfo>(
() => ({
'selected-style': this.selected$.value,
})
);
private _fetchAbortController?: AbortController;
blockDraggable = true;
@@ -69,16 +76,12 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent<BookmarkBloc
}
override renderBlock() {
const selected = this.selected$.value;
const isInEdgeless =
this.std.get(DocModeProvider).getEditorMode() === 'edgeless';
return html`
<div
draggable="${this.blockDraggable ? 'true' : 'false'}"
class=${classMap({
'affine-bookmark-container': true,
'selected-style': selected && !isInEdgeless,
...this.selectedStyle$?.value,
})}
style=${this.containerStyleMap}
>
@@ -10,6 +10,8 @@ import { BookmarkBlockComponent } from './bookmark-block.js';
export class BookmarkEdgelessBlockComponent extends toGfxBlockComponent(
BookmarkBlockComponent
) {
override selectedStyle$ = null;
override blockDraggable = false;
override getRenderingRect() {
+1 -1
View File
@@ -24,7 +24,7 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"@types/mdast": "^4.0.4",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
@@ -26,7 +26,7 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"@types/mdast": "^4.0.4",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
@@ -26,7 +26,7 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"@types/mdast": "^4.0.4",
"date-fns": "^4.0.0",
"lit": "^3.2.0",
@@ -34,8 +34,6 @@ import {
} from './properties/index.js';
import {
addProperty,
applyCellsUpdate,
applyPropertyUpdate,
copyCellsByProperty,
deleteRows,
deleteView,
@@ -169,7 +167,6 @@ export class DatabaseBlockDataSource extends DataSourceBase {
columnId: propertyId,
value: newValue,
});
applyCellsUpdate(this._model);
}
}
@@ -199,7 +196,6 @@ export class DatabaseBlockDataSource extends DataSourceBase {
insertToPosition,
property.create(this.newPropertyName())
);
applyPropertyUpdate(this._model);
return result;
}
@@ -283,7 +279,6 @@ export class DatabaseBlockDataSource extends DataSourceBase {
propertyDataSet(propertyId: string, data: Record<string, unknown>): void {
this._runCapture();
this.updateProperty(propertyId, () => ({ data }));
applyPropertyUpdate(this._model);
}
propertyDataTypeGet(propertyId: string): TypeInstance | undefined {
@@ -337,7 +332,6 @@ export class DatabaseBlockDataSource extends DataSourceBase {
schema
);
copyCellsByProperty(this._model, copyId, id);
applyPropertyUpdate(this._model);
return id;
}
@@ -366,7 +360,6 @@ export class DatabaseBlockDataSource extends DataSourceBase {
propertyNameSet(propertyId: string, name: string): void {
this.doc.captureSync();
this.updateProperty(propertyId, () => ({ name }));
applyPropertyUpdate(this._model);
}
override propertyReadonlyGet(propertyId: string): boolean {
@@ -421,7 +414,6 @@ export class DatabaseBlockDataSource extends DataSourceBase {
}
});
updateCells(this._model, propertyId, cells);
applyPropertyUpdate(this._model);
}
rowAdd(insertPosition: InsertToPosition | number): string {
@@ -37,24 +37,6 @@ export function addProperty(
return id;
}
export function applyCellsUpdate(model: DatabaseBlockModel) {
model.doc.updateBlock(model, {
cells: model.cells,
});
}
export function applyPropertyUpdate(model: DatabaseBlockModel) {
model.doc.updateBlock(model, {
columns: model.columns,
});
}
export function applyViewsUpdate(model: DatabaseBlockModel) {
model.doc.updateBlock(model, {
views: model.views,
});
}
export function copyCellsByProperty(
model: DatabaseBlockModel,
fromId: Column['id'],
@@ -156,7 +138,6 @@ export function moveViewTo(
arr => insertPositionToIndex(position, arr)
);
});
applyViewsUpdate(model);
}
export function updateCell(
@@ -255,6 +236,5 @@ export const updateView = <ViewData extends ViewBasicDataType>(
return { ...v, ...update(v as ViewData) };
});
});
applyViewsUpdate(model);
};
export const DATABASE_CONVERT_WHITE_LIST = ['affine:list', 'affine:paragraph'];
+1 -1
View File
@@ -23,7 +23,7 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"@types/mdast": "^4.0.4",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
@@ -25,7 +25,7 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
"zod": "^3.23.8"
+2 -2
View File
@@ -25,14 +25,14 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
"yjs": "^13.6.21",
"zod": "^3.23.8"
},
"devDependencies": {
"vitest": "3.0.5"
"vitest": "3.0.6"
},
"exports": {
".": "./src/index.ts",
@@ -12,10 +12,11 @@ import { DocModeProvider } from '@blocksuite/affine-shared/services';
import type { BlockService } from '@blocksuite/block-std';
import type { GfxCompatibleProps } from '@blocksuite/block-std/gfx';
import type { BlockModel } from '@blocksuite/store';
import { computed, type ReadonlySignal } from '@preact/signals-core';
import type { TemplateResult } from 'lit';
import { html } from 'lit';
import { query } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { type ClassInfo, classMap } from 'lit/directives/class-map.js';
import { type StyleInfo, styleMap } from 'lit/directives/style-map.js';
export class EmbedBlockComponent<
@@ -23,6 +24,12 @@ export class EmbedBlockComponent<
Service extends BlockService = BlockService,
WidgetName extends string = string,
> extends CaptionedBlockComponent<Model, Service, WidgetName> {
selectedStyle$: ReadonlySignal<ClassInfo> | null = computed<ClassInfo>(
() => ({
'selected-style': this.selected$.value,
})
);
private _fetchAbortController = new AbortController();
_cardStyle: EmbedCardStyle = 'horizontal';
@@ -43,10 +50,6 @@ export class EmbedBlockComponent<
protected embedContainerStyle: StyleInfo = {};
renderEmbed = (content: () => TemplateResult) => {
const selected = this.selected$.value;
const isInEdgeless =
this.std.get(DocModeProvider).getEditorMode() === 'edgeless';
if (
this._cardStyle === 'horizontal' ||
this._cardStyle === 'horizontalThin' ||
@@ -54,7 +57,7 @@ export class EmbedBlockComponent<
) {
this.style.display = 'block';
if (isInEdgeless) {
if (this.std.get(DocModeProvider).getEditorMode() === 'edgeless') {
this.style.minWidth = `${EMBED_CARD_MIN_WIDTH}px`;
}
}
@@ -64,7 +67,7 @@ export class EmbedBlockComponent<
draggable="${this.blockDraggable ? 'true' : 'false'}"
class=${classMap({
'embed-block-container': true,
'selected-style': selected && !isInEdgeless,
...this.selectedStyle$?.value,
})}
style=${styleMap({
height: `${this._cardHeight}px`,
@@ -404,7 +404,6 @@ export function createLinkedDocFromSlice(
snapshots: BlockSnapshot[],
docTitle?: string
) {
// const modelsWithChildren = (list:BlockModel[]):BlockModel[]=>list.flatMap(model=>[model,...modelsWithChildren(model.children)])
const linkedDoc = doc.workspace.createDoc({});
linkedDoc.load(() => {
const rootId = linkedDoc.addBlock('affine:page', {
@@ -22,6 +22,8 @@ export function toEdgelessEmbedBlock<
B extends typeof EmbedBlockComponent<Model, Service, WidgetName>,
>(block: B) {
return class extends toGfxBlockComponent(block) {
override selectedStyle$ = null;
_isDragging = false;
_isResizing = false;
@@ -246,7 +246,9 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
}
get linkedDoc() {
return this.std.workspace.getDoc(this.model.pageId);
return this.std.workspace.getDoc(this.model.pageId, {
id: this.model.pageId,
});
}
private _handleDoubleClick(event: MouseEvent) {
@@ -164,7 +164,7 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
this.cardStyleMap = {
display: 'block',
width: `${EMBED_CARD_WIDTH[style]}px`,
height: `${EMBED_CARD_WIDTH[style]}px`,
height: `${EMBED_CARD_HEIGHT[style]}px`,
transform: `scale(${bound.w / EMBED_CARD_WIDTH[style]}, ${bound.h / EMBED_CARD_HEIGHT[style]})`,
transformOrigin: '0 0',
};
@@ -245,7 +245,10 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
</span>
</div>
`
: guard([editorMode, syncedDoc], renderEditor)}
: guard(
[editorMode, syncedDoc, appTheme, edgelessTheme],
renderEditor
)}
</div>
<div
class=${classMap({
@@ -57,6 +57,7 @@ export const blockStyles = css`
}
.affine-embed-synced-doc-container {
border: 1px solid var(--affine-border-color);
border-radius: 8px;
overflow: hidden;
}
@@ -69,12 +70,6 @@ export const blockStyles = css`
width: 100%;
height: calc(${EMBED_CARD_HEIGHT.syncedDoc}px + 36px);
}
.affine-embed-synced-doc-container:hover.light {
box-shadow: 0px 0px 0px 2px rgba(0, 0, 0, 0.08);
}
.affine-embed-synced-doc-container:hover.dark {
box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.14);
}
.affine-embed-synced-doc-header-wrapper {
position: absolute;
top: 0;
@@ -127,9 +122,6 @@ export const blockStyles = css`
z-index: 1;
cursor: pointer;
}
.affine-embed-synced-doc-editor-overlay:hover {
background: var(--affine-hover-color);
}
.affine-embed-synced-doc-editor-empty {
display: flex;
+3 -1
View File
@@ -13,6 +13,7 @@
"author": "toeverything",
"license": "MIT",
"dependencies": {
"@blocksuite/affine-block-surface": "workspace:*",
"@blocksuite/affine-components": "workspace:*",
"@blocksuite/affine-model": "workspace:*",
"@blocksuite/affine-shared": "workspace:*",
@@ -23,10 +24,11 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"@types/mdast": "^4.0.4",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
"yjs": "^13.6.21",
"zod": "^3.23.8"
},
"exports": {
@@ -21,14 +21,13 @@ import {
type IVec,
type SerializedXYWH,
} from '@blocksuite/global/utils';
import { Text } from '@blocksuite/store';
import { type BlockModel, Text } from '@blocksuite/store';
import * as Y from 'yjs';
import { areSetsEqual } from './utils/misc.js';
import { isFrameBlock } from './utils/query.js';
const FRAME_PADDING = 40;
export type NavigatorMode = 'fill' | 'fit';
export class FrameOverlay extends Overlay {
static override overlayName: string = 'frame';
@@ -461,3 +460,13 @@ export class EdgelessFrameManager extends GfxExtension {
this._disposable.dispose();
}
}
function areSetsEqual<T>(setA: Set<T>, setB: Set<T>) {
if (setA.size !== setB.size) return false;
for (const a of setA) if (!setB.has(a)) return false;
return true;
}
export function isFrameBlock(element: unknown): element is FrameBlockModel {
return !!element && (element as BlockModel).flavour === 'affine:frame';
}
@@ -1,2 +1,3 @@
export * from './frame-block.js';
export * from './frame-manager.js';
export * from './frame-spec.js';
@@ -7,6 +7,7 @@
},
"include": ["./src"],
"references": [
{ "path": "../block-surface" },
{ "path": "../components" },
{ "path": "../model" },
{ "path": "../shared" },
+1 -1
View File
@@ -26,7 +26,7 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"file-type": "^20.0.0",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
@@ -40,17 +40,18 @@ export const ImageDropOption = FileDropConfigExtension({
if (isInsideEdgelessEditor(std.host)) {
const gfx = std.get(GfxControllerIdentifier);
point = gfx.viewport.toViewCoordFromClientCoord(point);
addImages(std, files, { point, maxWidth: MAX_IMAGE_WIDTH }).catch(
console.error
);
addImages(std, files, { point, maxWidth: MAX_IMAGE_WIDTH })
.then(() => {
std.getOptional(TelemetryProvider)?.track('CanvasElementAdded', {
control: 'canvas:drop',
page: 'whiteboard editor',
module: 'toolbar',
segment: 'toolbar',
type: 'image',
});
})
.catch(console.error);
std.getOptional(TelemetryProvider)?.track('CanvasElementAdded', {
control: 'canvas:drop',
page: 'whiteboard editor',
module: 'toolbar',
segment: 'toolbar',
type: 'image',
});
return true;
}
@@ -33,4 +33,4 @@ export const ImageBlockSpec: ExtensionType[] = [
ImageBlockAdapterExtensions,
].flat();
export const ImageStoreSpec: ExtensionType[] = [ImageProxyService].flat();
export const ImageStoreSpec: ExtensionType[] = [ImageProxyService];
+10 -22
View File
@@ -12,6 +12,7 @@ import {
import {
downloadBlob,
humanFileSize,
readImageSize,
transformModel,
withTempBlobData,
} from '@blocksuite/affine-shared/utils';
@@ -425,27 +426,6 @@ export async function turnImageIntoCardView(
transformModel(model, 'affine:attachment', attachmentProp);
}
export function readImageSize(file: File | Blob) {
return new Promise<{ width: number; height: number }>(resolve => {
const size = { width: 0, height: 0 };
const img = new Image();
img.onload = () => {
size.width = img.width;
size.height = img.height;
URL.revokeObjectURL(img.src);
resolve(size);
};
img.onerror = () => {
URL.revokeObjectURL(img.src);
resolve(size);
};
img.src = URL.createObjectURL(file);
});
}
export async function addImages(
std: BlockStdScope,
files: File[],
@@ -512,9 +492,17 @@ export async function addImages(
// upload image data and update the image model
const uploadPromises = imageFiles.map(async (file, index) => {
const { point, blockId } = dropInfos[index];
const block = std.store.getBlock(blockId);
const imageSize = await readImageSize(file);
if (!imageSize.width || !imageSize.height) {
std.store.deleteBlock(block!.model);
toast(std.host, 'Failed to read image size, please try another image');
throw new Error('Failed to read image size');
}
const sourceId = await std.store.blobSync.set(file);
const imageSize = await readImageSize(file);
const center = Vec.toVec(point);
// If maxWidth is provided, limit the width of the image to maxWidth
+1 -1
View File
@@ -24,7 +24,7 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"@types/katex": "^0.16.7",
"@types/mdast": "^4.0.4",
"katex": "^0.16.11",
+2 -2
View File
@@ -23,14 +23,14 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"@types/mdast": "^4.0.4",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
"zod": "^3.23.8"
},
"devDependencies": {
"vitest": "3.0.5"
"vitest": "3.0.6"
},
"exports": {
".": "./src/index.ts",
+1 -1
View File
@@ -26,7 +26,7 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"@types/mdast": "^4.0.4",
"@vanilla-extract/css": "^1.17.0",
"lit": "^3.2.0",
@@ -23,7 +23,7 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"@types/mdast": "^4.0.4",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
@@ -24,7 +24,7 @@
"@blocksuite/store": "workspace:*",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"fractional-indexing": "^3.2.0",
"lit": "^3.2.0",
"lodash.chunk": "^4.2.0",
+2 -2
View File
@@ -22,7 +22,7 @@
"@blocksuite/store": "workspace:*",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"fractional-indexing": "^3.2.0",
"html2canvas": "^1.4.1",
"lit": "^3.2.0",
@@ -34,7 +34,7 @@
},
"devDependencies": {
"@types/lodash.chunk": "^4.2.9",
"vitest": "3.0.5"
"vitest": "3.0.6"
},
"exports": {
".": "./src/index.ts",
+1 -1
View File
@@ -24,7 +24,7 @@
"@blocksuite/store": "workspace:*",
"@floating-ui/dom": "^1.6.10",
"@preact/signals-core": "^1.8.0",
"@vanilla-extract/css": "^1.14.0",
"@vanilla-extract/css": "^1.17.0",
"lit": "^3.2.0",
"yjs": "^13.6.21",
"zod": "^3.24.1"
@@ -43,6 +43,10 @@ export class SelectionController implements ReactiveController {
private get clipboard() {
return this.host.std.clipboard;
}
private get scale() {
return this.host.getScale();
}
widthAdjust(dragHandle: HTMLElement, event: MouseEvent) {
event.preventDefault();
event.stopPropagation();
@@ -50,6 +54,7 @@ export class SelectionController implements ReactiveController {
const currentWidth =
dragHandle.closest('td')?.getBoundingClientRect().width ??
DefaultColumnWidth;
const adjustedWidth = currentWidth / this.scale;
const columnId = dragHandle.dataset['widthAdjustColumnId'];
if (!columnId) {
return;
@@ -60,7 +65,7 @@ export class SelectionController implements ReactiveController {
columnId,
width: Math.max(
ColumnMinWidth,
event.clientX - initialX + currentWidth
(event.clientX - initialX) / this.scale + adjustedWidth
),
};
};
@@ -68,6 +68,7 @@ export class SelectionLayer extends SignalWatcher(
display: 'none',
});
const border = '2px solid var(--affine-primary-color)';
return styleMap({
position: 'absolute',
pointerEvents: 'none',
@@ -2,8 +2,7 @@ import { style } from '@vanilla-extract/css';
export const tableContainer = style({
display: 'block',
backgroundColor: 'var(--affine-background-primary-color)',
padding: '10px 0 18px',
padding: '10px 0 18px 10px',
overflowX: 'auto',
overflowY: 'visible',
selectors: {
@@ -54,6 +54,12 @@ export class TableBlockComponent extends CaptionedBlockComponent<TableBlockModel
table$ = signal<HTMLTableElement>();
public getScale(): number {
const table = this.table$.value;
if (!table) return 1;
return table.getBoundingClientRect().width / table.offsetWidth;
}
private readonly getRootRect = () => {
const table = this.table$.value;
if (!table) return;
@@ -65,11 +71,12 @@ export class TableBlockComponent extends CaptionedBlockComponent<TableBlockModel
const rootRect = this.getRootRect();
if (!row || !rootRect) return;
const rect = row.getBoundingClientRect();
const scale = this.getScale();
return {
top: rect.top - rootRect.top,
left: rect.left - rootRect.left,
width: rect.width,
height: rect.height,
top: (rect.top - rootRect.top) / scale,
left: (rect.left - rootRect.left) / scale,
width: rect.width / scale,
height: rect.height / scale,
};
};
@@ -80,11 +87,12 @@ export class TableBlockComponent extends CaptionedBlockComponent<TableBlockModel
const firstRect = columns.item(0)?.getBoundingClientRect();
const lastRect = columns.item(columns.length - 1)?.getBoundingClientRect();
if (!firstRect || !lastRect) return;
const scale = this.getScale();
return {
top: firstRect.top - rootRect.top,
left: firstRect.left - rootRect.left,
width: firstRect.width,
height: lastRect.bottom - firstRect.top,
top: (firstRect.top - rootRect.top) / scale,
left: (firstRect.left - rootRect.left) / scale,
width: firstRect.width / scale,
height: (lastRect.bottom - firstRect.top) / scale,
};
};
@@ -99,19 +107,22 @@ export class TableBlockComponent extends CaptionedBlockComponent<TableBlockModel
const startRow = rows.item(rowStartIndex);
const endRow = rows.item(rowEndIndex);
if (!startRow || !endRow || !rootRect) return;
const columns = startRow.querySelectorAll('td');
const startColumn = columns.item(columnStartIndex);
const endColumn = columns.item(columnEndIndex);
if (!startColumn || !endColumn) return;
const startRect = startRow.getBoundingClientRect();
const endRect = endRow.getBoundingClientRect();
const startColumnRect = startColumn.getBoundingClientRect();
const endColumnRect = endColumn.getBoundingClientRect();
const startCells = startRow.querySelectorAll('td');
const endCells = endRow.querySelectorAll('td');
const startCell = startCells.item(columnStartIndex);
const endCell = endCells.item(columnEndIndex);
if (!startCell || !endCell) return;
const startRect = startCell.getBoundingClientRect();
const endRect = endCell.getBoundingClientRect();
const scale = this.getScale();
return {
top: startRect.top - rootRect.top,
left: startColumnRect.left - rootRect.left,
width: endColumnRect.right - startColumnRect.left,
height: endRect.bottom - startRect.top,
top: (startRect.top - rootRect.top) / scale,
left: (startRect.left - rootRect.left) / scale,
width: (endRect.right - startRect.left) / scale,
height: (endRect.bottom - startRect.top) / scale,
};
};
@@ -124,7 +135,7 @@ export class TableBlockComponent extends CaptionedBlockComponent<TableBlockModel
contenteditable="false"
class=${tableContainer}
style=${styleMap({
marginLeft: `-${virtualPadding}px`,
marginLeft: `-${virtualPadding + 10}px`,
marginRight: `-${virtualPadding}px`,
position: 'relative',
})}
@@ -4,7 +4,8 @@ import { createVar, style } from '@vanilla-extract/css';
export const cellContainerStyle = style({
position: 'relative',
alignItems: 'center',
border: '1px solid var(--affine-border-color)',
border: '1px solid',
borderColor: cssVarV2.table.border,
borderCollapse: 'collapse',
isolation: 'auto',
textAlign: 'start',
+1 -1
View File
@@ -24,7 +24,7 @@
"@lit/context": "^1.1.2",
"@lottiefiles/dotlottie-wc": "^0.4.0",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"@types/hast": "^3.0.4",
"@types/mdast": "^4.0.4",
"collapse-white-space": "^2.1.0",
@@ -229,6 +229,10 @@ export class AffineLatexNode extends SignalWatcher(
latex,
}
);
this.editor.setInlineRange({
index: this.endOffset,
length: 0,
});
}
},
{ once: true }
+1 -1
View File
@@ -23,7 +23,7 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"date-fns": "^4.0.0",
"lit": "^3.2.0",
"yjs": "^13.6.21",
@@ -0,0 +1,45 @@
{
"name": "@blocksuite/affine-fragment-frame-panel",
"description": "Frame panel fragment for BlockSuite.",
"type": "module",
"scripts": {
"build": "tsc",
"test:unit": "nx vite:test --run --passWithNoTests",
"test:unit:coverage": "nx vite:test --run --coverage",
"test:e2e": "playwright test"
},
"sideEffects": false,
"keywords": [],
"author": "toeverything",
"license": "MIT",
"dependencies": {
"@blocksuite/affine-block-frame": "workspace:*",
"@blocksuite/affine-block-surface": "workspace:*",
"@blocksuite/affine-components": "workspace:*",
"@blocksuite/affine-model": "workspace:*",
"@blocksuite/affine-shared": "workspace:*",
"@blocksuite/block-std": "workspace:*",
"@blocksuite/global": "workspace:*",
"@blocksuite/icons": "^2.2.1",
"@blocksuite/inline": "workspace:*",
"@blocksuite/store": "workspace:*",
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.11",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
"zod": "^3.23.8"
},
"exports": {
".": "./src/index.ts",
"./effects": "./src/effects.ts"
},
"files": [
"src",
"dist",
"!src/__tests__",
"!dist/__tests__"
],
"version": "0.19.0"
}
@@ -1,12 +1,14 @@
import { type EditorHost, ShadowlessElement } from '@blocksuite/block-std';
import { generateKeyBetweenV2 } from '@blocksuite/block-std/gfx';
import { EdgelessFrameManager } from '@blocksuite/affine-block-frame';
import type { FrameBlockModel } from '@blocksuite/affine-model';
import {
DocModeProvider,
EdgelessFrameManager,
EdgelessRootService,
EditPropsStore,
type FrameBlockModel,
} from '@blocksuite/blocks';
} from '@blocksuite/affine-shared/services';
import { type EditorHost, ShadowlessElement } from '@blocksuite/block-std';
import {
generateKeyBetweenV2,
GfxControllerIdentifier,
} from '@blocksuite/block-std/gfx';
import {
Bound,
DisposableGroup,
@@ -110,7 +112,7 @@ export class FramePanelBody extends SignalWatcher(
}
this._selected = [];
this._edgelessRootService?.selection.set({
this._gfx.selection.set({
elements: this._selected,
editing: false,
});
@@ -126,6 +128,10 @@ export class FramePanelBody extends SignalWatcher(
private _lastEdgelessRootId = '';
private get _gfx() {
return this.editorHost.std.get(GfxControllerIdentifier);
}
private readonly _selectFrame = (e: SelectEvent) => {
const { selected, id, multiselect } = e.detail;
@@ -138,7 +144,7 @@ export class FramePanelBody extends SignalWatcher(
this._selected = [id];
}
this._edgelessRootService?.selection.set({
this._gfx.selection.set({
elements: this._selected,
editing: false,
});
@@ -152,10 +158,6 @@ export class FramePanelBody extends SignalWatcher(
}));
};
get _edgelessRootService() {
return this.editorHost.std.getOptional(EdgelessRootService);
}
get frames() {
const frames = this.editorHost.doc
.getBlocksByFlavour('affine:frame')
@@ -229,8 +231,9 @@ export class FramePanelBody extends SignalWatcher(
private _fitToElement(e: FitViewEvent) {
const { block } = e.detail;
const bound = Bound.deserialize(block.xywh);
const docModeProvider = this.editorHost.std.get(DocModeProvider);
if (!this._edgelessRootService) {
if (docModeProvider.getEditorMode() !== 'edgeless') {
// When click frame card in page mode
// Should switch to edgeless mode and set viewport to the frame
const viewport = {
@@ -242,11 +245,7 @@ export class FramePanelBody extends SignalWatcher(
this.editorHost.std.get(EditPropsStore).setStorage('viewport', viewport);
this.editorHost.std.get(DocModeProvider).setEditorMode('edgeless');
} else {
this._edgelessRootService.viewport.setViewportByBound(
bound,
this.viewportPadding,
true
);
this._gfx.viewport.setViewportByBound(bound, this.viewportPadding, true);
}
}
@@ -398,7 +397,7 @@ export class FramePanelBody extends SignalWatcher(
this._setDocDisposables(this.editorHost.doc);
// after switch to edgeless mode, should update the selection
if (this.editorHost.doc.id === this._lastEdgelessRootId) {
this._edgelessRootService?.selection.set({
this._gfx.selection.set({
elements: this._selected,
editing: false,
});
@@ -1,5 +1,6 @@
import type { RichText } from '@blocksuite/affine-components/rich-text';
import type { FrameBlockModel } from '@blocksuite/affine-model';
import { ShadowlessElement } from '@blocksuite/block-std';
import type { FrameBlockModel, RichText } from '@blocksuite/blocks';
import { WithDisposable } from '@blocksuite/global/utils';
import { css, html } from 'lit';
import { property, query } from 'lit/decorators.js';
@@ -1,5 +1,5 @@
import type { FrameBlockModel } from '@blocksuite/affine-model';
import { ShadowlessElement } from '@blocksuite/block-std';
import type { FrameBlockModel } from '@blocksuite/blocks';
import { DisposableGroup, WithDisposable } from '@blocksuite/global/utils';
import { css, html, type PropertyValues } from 'lit';
import { property, query } from 'lit/decorators.js';
@@ -1,5 +1,6 @@
import type { FrameBlockModel } from '@blocksuite/affine-model';
import { on, once } from '@blocksuite/affine-shared/utils';
import { ShadowlessElement } from '@blocksuite/block-std';
import { type FrameBlockModel, on, once } from '@blocksuite/blocks';
import { WithDisposable } from '@blocksuite/global/utils';
import { css, html, nothing } from 'lit';
import { property, query } from 'lit/decorators.js';
@@ -0,0 +1,32 @@
import {
AFFINE_FRAME_PANEL_BODY,
FramePanelBody,
} from './body/frame-panel-body';
import { AFFINE_FRAME_CARD, FrameCard } from './card/frame-card';
import {
AFFINE_FRAME_CARD_TITLE,
FrameCardTitle,
} from './card/frame-card-title';
import {
AFFINE_FRAME_TITLE_EDITOR,
FrameCardTitleEditor,
} from './card/frame-card-title-editor';
import { AFFINE_FRAME_PANEL, FramePanel } from './frame-panel';
import {
AFFINE_FRAME_PANEL_HEADER,
FramePanelHeader,
} from './header/frame-panel-header';
import {
AFFINE_FRAMES_SETTING_MENU,
FramesSettingMenu,
} from './header/frames-setting-menu';
export function effects() {
customElements.define(AFFINE_FRAME_PANEL, FramePanel);
customElements.define(AFFINE_FRAME_TITLE_EDITOR, FrameCardTitleEditor);
customElements.define(AFFINE_FRAME_CARD, FrameCard);
customElements.define(AFFINE_FRAME_CARD_TITLE, FrameCardTitle);
customElements.define(AFFINE_FRAME_PANEL_BODY, FramePanelBody);
customElements.define(AFFINE_FRAME_PANEL_HEADER, FramePanelHeader);
customElements.define(AFFINE_FRAMES_SETTING_MENU, FramesSettingMenu);
}
@@ -1,12 +1,12 @@
import type { EditorHost } from '@blocksuite/block-std';
import type { NavigatorMode } from '@blocksuite/affine-block-frame';
import { EdgelessLegacySlotIdentifier } from '@blocksuite/affine-block-surface';
import {
createButtonPopper,
DocModeProvider,
EdgelessLegacySlotIdentifier,
EdgelessRootService,
EditPropsStore,
type NavigatorMode,
} from '@blocksuite/blocks';
} from '@blocksuite/affine-shared/services';
import { createButtonPopper } from '@blocksuite/affine-shared/utils';
import type { EditorHost } from '@blocksuite/block-std';
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
import { DisposableGroup, WithDisposable } from '@blocksuite/global/utils';
import { PresentationIcon, SettingsIcon } from '@blocksuite/icons/lit';
import { css, html, LitElement, type PropertyValues } from 'lit';
@@ -112,13 +112,18 @@ export class FramePanelHeader extends WithDisposable(LitElement) {
private _edgelessDisposables: DisposableGroup | null = null;
private get _gfx() {
return this.editorHost.std.get(GfxControllerIdentifier);
}
private readonly _enterPresentationMode = () => {
if (!this._edgelessRootService) {
const docModeProvider = this.editorHost.std.get(DocModeProvider);
if (docModeProvider.getEditorMode() !== 'edgeless') {
this.editorHost.std.get(DocModeProvider).setEditorMode('edgeless');
}
setTimeout(() => {
this._edgelessRootService?.gfx.tool.setTool({
this._gfx.tool.setTool({
type: 'frameNavigator',
mode: this._navigatorMode,
});
@@ -132,8 +137,6 @@ export class FramePanelHeader extends WithDisposable(LitElement) {
private _navigatorMode: NavigatorMode = 'fit';
private readonly _setEdgelessDisposables = () => {
if (!this._edgelessRootService) return;
const slots = this.editorHost.std.get(EdgelessLegacySlotIdentifier);
this._clearEdgelessDisposables();
@@ -145,10 +148,6 @@ export class FramePanelHeader extends WithDisposable(LitElement) {
);
};
private get _edgelessRootService() {
return this.editorHost.std.getOptional(EdgelessRootService);
}
private _tryLoadNavigatorStateLocalRecord() {
this._navigatorMode = this.editorHost.std
.get(EditPropsStore)
@@ -219,7 +218,8 @@ export class FramePanelHeader extends WithDisposable(LitElement) {
override updated(_changedProperties: PropertyValues) {
if (_changedProperties.has('editorHost')) {
if (this._edgelessRootService) {
const docModeProvider = this.editorHost.std.get(DocModeProvider);
if (docModeProvider.getEditorMode() === 'edgeless') {
this._setEdgelessDisposables();
} else {
this._clearEdgelessDisposables();
@@ -1,9 +1,9 @@
import type { EditorHost } from '@blocksuite/block-std';
import { EdgelessLegacySlotIdentifier } from '@blocksuite/affine-block-surface';
import {
EdgelessLegacySlotIdentifier,
EdgelessRootService,
DocModeProvider,
EditPropsStore,
} from '@blocksuite/blocks';
} from '@blocksuite/affine-shared/services';
import type { EditorHost } from '@blocksuite/block-std';
import { WithDisposable } from '@blocksuite/global/utils';
import { css, html, LitElement, type PropertyValues } from 'lit';
import { property, state } from 'lit/decorators.js';
@@ -103,10 +103,6 @@ export class FramesSettingMenu extends WithDisposable(LitElement) {
this._editPropsStore.setStorage('presentHideToolbar', this.hideToolbar);
};
private get _edgelessRootService() {
return this.editorHost.std.getOptional(EdgelessRootService);
}
private get _editPropsStore() {
return this.editorHost.std.get(EditPropsStore);
}
@@ -176,7 +172,8 @@ export class FramesSettingMenu extends WithDisposable(LitElement) {
override updated(_changedProperties: PropertyValues) {
if (_changedProperties.has('editorHost')) {
if (this._edgelessRootService) {
const docModeProvider = this.editorHost.std.get(DocModeProvider);
if (docModeProvider.getEditorMode() === 'edgeless') {
this.disposables.add(
this.slots.navigatorSettingUpdated.on(
({ blackBackground, hideToolbar }) => {
@@ -0,0 +1,2 @@
export * from './frame-panel';
export * from './tool';
@@ -1,7 +1,6 @@
import type { NavigatorMode } from '@blocksuite/affine-block-frame';
import { BaseTool } from '@blocksuite/block-std/gfx';
import type { NavigatorMode } from '../../../_common/edgeless/frame/consts.js';
type PresentToolOption = {
mode?: NavigatorMode;
};
@@ -1,4 +1,5 @@
import { type FrameBlockModel, on, once } from '@blocksuite/blocks';
import type { FrameBlockModel } from '@blocksuite/affine-model';
import { on, once } from '@blocksuite/affine-shared/utils';
import type { FramePanelBody } from '../body/frame-panel-body.js';
import { FrameCard } from '../card/frame-card.js';
@@ -0,0 +1,20 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
"tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo"
},
"include": ["./src"],
"references": [
{ "path": "../block-frame" },
{ "path": "../block-surface" },
{ "path": "../components" },
{ "path": "../model" },
{ "path": "../shared" },
{ "path": "../../framework/block-std" },
{ "path": "../../framework/global" },
{ "path": "../../framework/inline" },
{ "path": "../../framework/store" }
]
}
@@ -0,0 +1,45 @@
{
"name": "@blocksuite/affine-fragment-outline",
"description": "Outline fragment for BlockSuite.",
"type": "module",
"scripts": {
"build": "tsc",
"test:unit": "nx vite:test --run --passWithNoTests",
"test:unit:coverage": "nx vite:test --run --coverage",
"test:e2e": "playwright test"
},
"sideEffects": false,
"keywords": [],
"author": "toeverything",
"license": "MIT",
"dependencies": {
"@blocksuite/affine-block-note": "workspace:*",
"@blocksuite/affine-components": "workspace:*",
"@blocksuite/affine-model": "workspace:*",
"@blocksuite/affine-shared": "workspace:*",
"@blocksuite/block-std": "workspace:*",
"@blocksuite/global": "workspace:*",
"@blocksuite/icons": "^2.2.1",
"@blocksuite/inline": "workspace:*",
"@blocksuite/store": "workspace:*",
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.11",
"@vanilla-extract/css": "^1.17.0",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
"zod": "^3.23.8"
},
"exports": {
".": "./src/index.ts",
"./effects": "./src/effects.ts"
},
"files": [
"src",
"dist",
"!src/__tests__",
"!dist/__tests__"
],
"version": "0.19.0"
}
@@ -1,17 +1,10 @@
import { effects } from '@blocksuite/affine-block-note/effects';
import { changeNoteDisplayMode } from '@blocksuite/affine-block-note';
import { NoteBlockModel, NoteDisplayMode } from '@blocksuite/affine-model';
import { DocModeProvider } from '@blocksuite/affine-shared/services';
import { matchModels } from '@blocksuite/affine-shared/utils';
import { ShadowlessElement, SurfaceSelection } from '@blocksuite/block-std';
import {
changeNoteDisplayMode,
matchModels,
NoteBlockModel,
NoteDisplayMode,
} from '@blocksuite/blocks';
import {
Bound,
noop,
SignalWatcher,
WithDisposable,
} from '@blocksuite/global/utils';
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
import { Bound, SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
import type { BlockModel } from '@blocksuite/store';
import { consume } from '@lit/context';
import { effect, signal } from '@preact/signals-core';
@@ -21,8 +14,6 @@ import { classMap } from 'lit/directives/class-map.js';
import { repeat } from 'lit/directives/repeat.js';
import { when } from 'lit/directives/when.js';
noop(effects);
import { type TocContext, tocContext } from '../config';
import type {
ClickBlockEvent,
@@ -78,10 +69,6 @@ export class OutlinePanelBody extends SignalWatcher(
return this.editor.doc;
}
private get edgeless() {
return this.editor.querySelector('affine-edgeless-root');
}
get viewportPadding(): [number, number, number, number] {
const fitPadding = this._context.fitPadding$.value;
return fitPadding.length === 4
@@ -92,9 +79,9 @@ export class OutlinePanelBody extends SignalWatcher(
}
private _deSelectNoteInEdgelessMode(note: NoteBlockModel) {
if (!this.edgeless) return;
const gfx = this.editor.std.get(GfxControllerIdentifier);
const selection = gfx.selection;
const { selection } = this.edgeless.service;
if (!selection.has(note.id)) return;
const selectedIds = selection.selectedIds.filter(id => id !== note.id);
selection.set({
@@ -115,18 +102,12 @@ export class OutlinePanelBody extends SignalWatcher(
}
private _fitToElement(e: FitViewEvent) {
const edgeless = this.edgeless;
if (!edgeless) return;
const gfx = this.editor.std.get(GfxControllerIdentifier);
const { block } = e.detail;
const bound = Bound.deserialize(block.xywh);
edgeless.service.viewport.setViewportByBound(
bound,
this.viewportPadding,
true
);
gfx.viewport.setViewportByBound(bound, this.viewportPadding, true);
}
// when display mode change to page only, we should de-select the note if it is selected in edgeless mode
@@ -199,6 +180,8 @@ export class OutlinePanelBody extends SignalWatcher(
private _selectNote(e: SelectEvent) {
const { selected, id, multiselect } = e.detail;
const gfx = this.editor.std.get(GfxControllerIdentifier);
const editorMode = this.editor.std.get(DocModeProvider).getEditorMode();
const note = this.doc.getBlock(id)?.model;
if (!note || !matchModels(note, [NoteBlockModel])) return;
@@ -212,8 +195,8 @@ export class OutlinePanelBody extends SignalWatcher(
selectedNotes = [note];
}
if (this.edgeless) {
this.edgeless?.service.selection.set({
if (editorMode === 'edgeless') {
gfx.selection.set({
elements: selectedNotes.map(({ id }) => id),
editing: false,
});
@@ -224,7 +207,9 @@ export class OutlinePanelBody extends SignalWatcher(
private _watchSelectedNotes() {
return effect(() => {
const { std, doc, mode } = this.editor;
const { std, doc } = this.editor;
const docModeService = this.editor.std.get(DocModeProvider);
const mode = docModeService.getEditorMode();
if (mode !== 'edgeless') return;
const currSelectedNotes = std.selection
@@ -1,9 +1,6 @@
import { type NoteBlockModel, NoteDisplayMode } from '@blocksuite/affine-model';
import { createButtonPopper } from '@blocksuite/affine-shared/utils';
import { ShadowlessElement } from '@blocksuite/block-std';
import {
createButtonPopper,
type NoteBlockModel,
NoteDisplayMode,
} from '@blocksuite/blocks';
import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
import { ArrowDownSmallIcon, InvisibleIcon } from '@blocksuite/icons/lit';
import type { BlockModel } from '@blocksuite/store';
@@ -1,16 +1,16 @@
import type {
AttachmentBlockModel,
BookmarkBlockModel,
CodeBlockModel,
DatabaseBlockModel,
ImageBlockModel,
ListBlockModel,
ParagraphBlockModel,
RootBlockModel,
} from '@blocksuite/affine-model';
import { DocDisplayMetaProvider } from '@blocksuite/affine-shared/services';
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
import { ShadowlessElement } from '@blocksuite/block-std';
import {
type AttachmentBlockModel,
type BookmarkBlockModel,
type CodeBlockModel,
type DatabaseBlockModel,
DocDisplayMetaProvider,
type ImageBlockModel,
type ListBlockModel,
type ParagraphBlockModel,
type RootBlockModel,
} from '@blocksuite/blocks';
import { noop, SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
import { LinkedPageIcon } from '@blocksuite/icons/lit';
import type { DeltaInsert } from '@blocksuite/inline';
@@ -1,4 +1,5 @@
import type { ParagraphBlockModel, Signal } from '@blocksuite/blocks';
import type { ParagraphBlockModel } from '@blocksuite/affine-model';
import type { EditorHost } from '@blocksuite/block-std';
import {
AttachmentIcon,
BlockIcon,
@@ -20,10 +21,9 @@ import {
TextIcon,
} from '@blocksuite/icons/lit';
import { createContext } from '@lit/context';
import type { Signal } from '@preact/signals-core';
import type { TemplateResult } from 'lit';
import type { AffineEditorContainer } from '../../editors/editor-container.js';
const _16px = { width: '16px', height: '16px' };
const paragraphIconMap: Record<
@@ -85,7 +85,7 @@ export const headingKeys = new Set(
export const outlineSettingsKey = 'outlinePanelSettings';
export type TocContext = {
editor$: Signal<AffineEditorContainer>;
editor$: Signal<EditorHost>;
enableSorting$: Signal<boolean>;
showIcons$: Signal<boolean>;
fitPadding$: Signal<number[]>;
@@ -0,0 +1,39 @@
import { AFFINE_OUTLINE_NOTICE, OutlineNotice } from './body/outline-notice';
import {
AFFINE_OUTLINE_PANEL_BODY,
OutlinePanelBody,
} from './body/outline-panel-body';
import { AFFINE_OUTLINE_NOTE_CARD, OutlineNoteCard } from './card/outline-card';
import {
AFFINE_OUTLINE_BLOCK_PREVIEW,
OutlineBlockPreview,
} from './card/outline-preview';
import {
AFFINE_OUTLINE_PANEL_HEADER,
OutlinePanelHeader,
} from './header/outline-panel-header';
import {
AFFINE_OUTLINE_NOTE_PREVIEW_SETTING_MENU,
OutlineNotePreviewSettingMenu,
} from './header/outline-setting-menu';
import {
AFFINE_MOBILE_OUTLINE_MENU,
MobileOutlineMenu,
} from './mobile-outline-panel';
import { AFFINE_OUTLINE_PANEL, OutlinePanel } from './outline-panel';
import { AFFINE_OUTLINE_VIEWER, OutlineViewer } from './outline-viewer';
export function effects() {
customElements.define(
AFFINE_OUTLINE_NOTE_PREVIEW_SETTING_MENU,
OutlineNotePreviewSettingMenu
);
customElements.define(AFFINE_OUTLINE_NOTICE, OutlineNotice);
customElements.define(AFFINE_OUTLINE_PANEL, OutlinePanel);
customElements.define(AFFINE_OUTLINE_PANEL_HEADER, OutlinePanelHeader);
customElements.define(AFFINE_OUTLINE_NOTE_CARD, OutlineNoteCard);
customElements.define(AFFINE_OUTLINE_VIEWER, OutlineViewer);
customElements.define(AFFINE_MOBILE_OUTLINE_MENU, MobileOutlineMenu);
customElements.define(AFFINE_OUTLINE_BLOCK_PREVIEW, OutlineBlockPreview);
customElements.define(AFFINE_OUTLINE_PANEL_BODY, OutlinePanelBody);
}
@@ -1,5 +1,5 @@
import { createButtonPopper } from '@blocksuite/affine-shared/utils';
import { ShadowlessElement } from '@blocksuite/block-std';
import { createButtonPopper } from '@blocksuite/blocks';
import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
import { SettingsIcon, SortIcon } from '@blocksuite/icons/lit';
import { consume } from '@lit/context';
@@ -1,11 +1,16 @@
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
import { PropTypes, requiredProperties } from '@blocksuite/block-std';
import {
matchModels,
NoteDisplayMode,
ParagraphBlockModel,
RootBlockModel,
} from '@blocksuite/blocks';
} from '@blocksuite/affine-model';
import { DocModeProvider } from '@blocksuite/affine-shared/services';
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
import { matchModels } from '@blocksuite/affine-shared/utils';
import {
type EditorHost,
PropTypes,
requiredProperties,
} from '@blocksuite/block-std';
import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
import type { BlockModel } from '@blocksuite/store';
import { signal } from '@preact/signals-core';
@@ -14,7 +19,6 @@ import { property } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { repeat } from 'lit/directives/repeat.js';
import type { AffineEditorContainer } from '../../editors/editor-container.js';
import { getHeadingBlocksFromDoc } from './utils/query.js';
import {
observeActiveHeadingDuringScroll,
@@ -162,8 +166,9 @@ export class MobileOutlineMenu extends SignalWatcher(
};
override render() {
if (this.editor.doc.root === null || this.editor.mode === 'edgeless')
return nothing;
const docModeService = this.editor.std.get(DocModeProvider);
const mode = docModeService.getEditorMode();
if (this.editor.doc.root === null || mode === 'edgeless') return nothing;
const headingBlocks = getHeadingBlocksFromDoc(
this.editor.doc,
@@ -182,7 +187,7 @@ export class MobileOutlineMenu extends SignalWatcher(
}
@property({ attribute: false })
accessor editor!: AffineEditorContainer;
accessor editor!: EditorHost;
}
declare global {
@@ -1,4 +1,6 @@
import { DocModeProvider } from '@blocksuite/affine-shared/services';
import {
type EditorHost,
PropTypes,
requiredProperties,
ShadowlessElement,
@@ -9,7 +11,6 @@ import { effect, signal } from '@preact/signals-core';
import { html, type PropertyValues } from 'lit';
import { property } from 'lit/decorators.js';
import type { AffineEditorContainer } from '../../editors/editor-container.js';
import { outlineSettingsKey, type TocContext, tocContext } from './config.js';
import * as styles from './outline-panel.css';
@@ -21,6 +22,12 @@ export const AFFINE_OUTLINE_PANEL = 'affine-outline-panel';
export class OutlinePanel extends SignalWatcher(
WithDisposable(ShadowlessElement)
) {
private _getEditorMode(host: EditorHost) {
const docModeService = host.std.get(DocModeProvider);
const mode = docModeService.getEditorMode();
return mode;
}
private _setContext() {
this._context = {
editor$: signal(this.editor),
@@ -39,7 +46,7 @@ export class OutlinePanel extends SignalWatcher(
}
const editor = this._context.editor$.value;
if (editor.mode === 'edgeless') {
if (this._getEditorMode(editor) === 'edgeless') {
this._context.enableSorting$.value = true;
} else if (settings) {
this._context.enableSorting$.value = settings.enableSorting;
@@ -51,7 +58,8 @@ export class OutlinePanel extends SignalWatcher(
private _watchSettingsChange() {
this.disposables.add(
effect(() => {
if (this._context.editor$.value.mode === 'edgeless') return;
if (this._getEditorMode(this._context.editor$.value) === 'edgeless')
return;
const showPreviewIcon = this._context.showIcons$.value;
const enableNotesSorting = this._context.enableSorting$.value;
@@ -84,7 +92,7 @@ export class OutlinePanel extends SignalWatcher(
}
override render() {
if (!this.editor.host) return;
if (!this.editor) return;
return html`
<affine-outline-panel-header></affine-outline-panel-header>
@@ -97,7 +105,7 @@ export class OutlinePanel extends SignalWatcher(
private accessor _context!: TocContext;
@property({ attribute: false })
accessor editor!: AffineEditorContainer;
accessor editor!: EditorHost;
@property({ attribute: false })
accessor fitPadding!: number[];
@@ -1,9 +1,12 @@
import { NoteDisplayMode } from '@blocksuite/affine-model';
import { DocModeProvider } from '@blocksuite/affine-shared/services';
import { scrollbarStyle } from '@blocksuite/affine-shared/styles';
import {
type EditorHost,
PropTypes,
requiredProperties,
ShadowlessElement,
} from '@blocksuite/block-std';
import { NoteDisplayMode, scrollbarStyle } from '@blocksuite/blocks';
import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
import { TocIcon } from '@blocksuite/icons/lit';
import { provide } from '@lit/context';
@@ -13,7 +16,6 @@ import { property, query, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { repeat } from 'lit/directives/repeat.js';
import type { AffineEditorContainer } from '../../editors/editor-container.js';
import { type TocContext, tocContext } from './config.js';
import { getHeadingBlocksFromDoc } from './utils/query.js';
import {
@@ -219,8 +221,9 @@ export class OutlineViewer extends SignalWatcher(
}
override render() {
if (this.editor.doc.root === null || this.editor.mode === 'edgeless')
return nothing;
const docModeService = this.editor.std.get(DocModeProvider);
const mode = docModeService.getEditorMode();
if (this.editor.doc.root === null || mode === 'edgeless') return nothing;
const headingBlocks = getHeadingBlocksFromDoc(
this.editor.doc,
@@ -308,7 +311,7 @@ export class OutlineViewer extends SignalWatcher(
private accessor _showViewer: boolean = false;
@property({ attribute: false })
accessor editor!: AffineEditorContainer;
accessor editor!: EditorHost;
@property({ attribute: false })
accessor toggleOutlinePanel: (() => void) | null = null;
@@ -1,4 +1,4 @@
import type { NoteBlockModel, NoteDisplayMode } from '@blocksuite/blocks';
import type { NoteBlockModel, NoteDisplayMode } from '@blocksuite/affine-model';
export type ReorderEvent = CustomEvent<{
currentNumber: number;
@@ -1,11 +1,10 @@
import {
BlocksUtils,
matchModels,
NoteBlockModel,
NoteDisplayMode,
ParagraphBlockModel,
RootBlockModel,
} from '@blocksuite/blocks';
} from '@blocksuite/affine-model';
import { matchModels } from '@blocksuite/affine-shared/utils';
import type { BlockModel, Store } from '@blocksuite/store';
import { headingKeys } from '../config.js';
@@ -35,14 +34,14 @@ export function getNotesFromDoc(
}
export function isRootBlock(block: BlockModel): block is RootBlockModel {
return BlocksUtils.matchModels(block, [RootBlockModel]);
return matchModels(block, [RootBlockModel]);
}
export function isHeadingBlock(
block: BlockModel
): block is ParagraphBlockModel {
return (
BlocksUtils.matchModels(block, [ParagraphBlockModel]) &&
matchModels(block, [ParagraphBlockModel]) &&
headingKeys.has(block.type$.value)
);
}
@@ -1,16 +1,18 @@
import { getDocTitleByEditorHost } from '@blocksuite/affine-components/doc-title';
import { NoteDisplayMode } from '@blocksuite/affine-model';
import { DocModeProvider } from '@blocksuite/affine-shared/services';
import type { Viewport } from '@blocksuite/affine-shared/types';
import type { EditorHost } from '@blocksuite/block-std';
import { NoteDisplayMode } from '@blocksuite/blocks';
import { clamp, DisposableGroup } from '@blocksuite/global/utils';
import type { AffineEditorContainer } from '../../../editors/editor-container.js';
import { getDocTitleByEditorHost } from '../../doc-title/index.js';
import { getHeadingBlocksFromDoc } from './query.js';
export function scrollToBlock(editor: AffineEditorContainer, blockId: string) {
const { host, mode } = editor;
if (mode === 'edgeless' || !host) return;
export function scrollToBlock(host: EditorHost, blockId: string) {
const docModeService = host.std.get(DocModeProvider);
const mode = docModeService.getEditorMode();
if (mode === 'edgeless') return;
if (editor.doc.root?.id === blockId) {
if (host.doc.root?.id === blockId) {
const docTitle = getDocTitleByEditorHost(host);
if (!docTitle) return;
@@ -50,12 +52,11 @@ export function isBlockBeforeViewportCenter(
}
export const observeActiveHeadingDuringScroll = (
getEditor: () => AffineEditorContainer, // workaround for editor changed
getEditor: () => EditorHost, // workaround for editor changed
update: (activeHeading: string | null) => void
) => {
const handler = () => {
const { host } = getEditor();
if (!host) return;
const host = getEditor();
const headings = getHeadingBlocksFromDoc(
host.doc,
@@ -82,15 +83,14 @@ export const observeActiveHeadingDuringScroll = (
let highlightMask: HTMLDivElement | null = null;
let highlightTimeoutId: ReturnType<typeof setTimeout> | null = null;
function highlightBlock(editor: AffineEditorContainer, blockId: string) {
function highlightBlock(host: EditorHost, blockId: string) {
const emptyClear = () => {};
const { host } = editor;
if (!host) return emptyClear;
if (host.doc.root?.id === blockId) return emptyClear;
if (editor.doc.root?.id === blockId) return emptyClear;
const rootComponent = host.querySelector('affine-page-root');
const rootComponent = host.querySelector<
HTMLElement & { viewport: Viewport }
>('affine-page-root');
if (!rootComponent) return emptyClear;
if (!rootComponent.viewport) {
@@ -153,11 +153,11 @@ function highlightBlock(editor: AffineEditorContainer, blockId: string) {
// this function is useful when the scroll need smooth animation
let highlightIntervalId: ReturnType<typeof setInterval> | null = null;
export async function scrollToBlockWithHighlight(
editor: AffineEditorContainer,
host: EditorHost,
blockId: string,
timeout = 3000
) {
scrollToBlock(editor, blockId);
scrollToBlock(host, blockId);
let timeCount = 0;
@@ -174,10 +174,9 @@ export async function scrollToBlockWithHighlight(
return;
}
const { host } = editor;
const block = host?.view.getBlock(blockId);
const block = host.view.getBlock(blockId);
if (!host || !block || timeCount > timeout) {
if (!block || timeCount > timeout) {
clearInterval(highlightIntervalId);
resolve(() => {});
return;
@@ -195,7 +194,7 @@ export async function scrollToBlockWithHighlight(
clearInterval(highlightIntervalId);
// highlight block
resolve(highlightBlock(editor, blockId));
resolve(highlightBlock(host, blockId));
}, 100);
});
}
@@ -0,0 +1,19 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
"tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo"
},
"include": ["./src"],
"references": [
{ "path": "../block-note" },
{ "path": "../components" },
{ "path": "../model" },
{ "path": "../shared" },
{ "path": "../../framework/block-std" },
{ "path": "../../framework/global" },
{ "path": "../../framework/inline" },
{ "path": "../../framework/store" }
]
}
+1 -1
View File
@@ -17,7 +17,7 @@
"@blocksuite/global": "workspace:*",
"@blocksuite/inline": "workspace:*",
"@blocksuite/store": "workspace:*",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"fractional-indexing": "^3.2.0",
"yjs": "^13.6.21",
"zod": "^3.23.8"
+3 -2
View File
@@ -22,9 +22,10 @@
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.7",
"@toeverything/theme": "^1.1.11",
"@types/hast": "^3.0.4",
"@types/mdast": "^4.0.4",
"dompurify": "^3.2.4",
"fractional-indexing": "^3.2.0",
"lit": "^3.2.0",
"lodash.clonedeep": "^4.5.0",
@@ -74,7 +75,7 @@
"devDependencies": {
"@types/lodash.clonedeep": "^4.5.9",
"@types/lodash.mergewith": "^4",
"vitest": "3.0.5"
"vitest": "3.0.6"
},
"version": "0.19.0"
}
@@ -1,3 +1,4 @@
export * from './code';
export * from './copy';
export * from './paste';
export * from './surface-ref-to-embed';
@@ -17,12 +17,16 @@ export const surfaceRefToEmbed =
payload.snapshot.flavour === 'affine:surface-ref' &&
!std.store.hasBlock(payload.snapshot.id)
) {
const id = payload.snapshot.id;
// The blockId of the original surface-ref block
const blockId = payload.snapshot.id;
payload.snapshot.id = std.workspace.idGenerator();
payload.snapshot.flavour = 'affine:embed-linked-doc';
payload.snapshot.props = {
blockId: id,
pageId,
params: {
mode: 'page',
blockIds: [blockId],
},
};
}
});
+1 -1
View File
@@ -29,7 +29,7 @@ export const EMBED_CARD_WIDTH: Record<EmbedCardStyle, number> = {
video: 752,
figma: 752,
html: 752,
syncedDoc: 752,
syncedDoc: 800,
pdf: 537 + 24 + 2,
};
@@ -5,6 +5,7 @@ import type { LinkToolbarEvents } from './link.js';
import type { NoteEvents } from './note.js';
import type {
AttachmentUploadedEvent,
BlockCreationEvent,
DocCreatedEvent,
ElementCreationEvent,
ElementLockEvent,
@@ -24,6 +25,7 @@ export type TelemetryEventMap = OutDatabaseAllEvents &
EdgelessElementLocked: ElementLockEvent;
ExpandedAndCollapsed: MindMapCollapseEvent;
AttachmentUploadedEvent: AttachmentUploadedEvent;
BlockCreated: BlockCreationEvent;
};
export interface TelemetryService {
@@ -51,6 +51,10 @@ export interface ElementLockEvent extends TelemetryEvent {
control: 'lock' | 'unlock' | 'group-lock';
}
export interface BlockCreationEvent extends TelemetryEvent {
blockType: string;
}
export interface MindMapCollapseEvent extends TelemetryEvent {
page: 'whiteboard editor';
segment: 'mind map';
@@ -0,0 +1,6 @@
/**
* Return `true` if the element has class name in the class list.
*/
export function hasClassNameInList(element: Element, classList: string[]) {
return classList.some(className => element.classList.contains(className));
}
@@ -1,4 +1,5 @@
export * from './checker.js';
export * from './has-classname-in-list.js';
export * from './point-to-block.js';
export * from './point-to-range.js';
export * from './query.js';
@@ -0,0 +1,28 @@
import DOMPurify from 'dompurify';
export function readImageSize(file: File | Blob) {
return new Promise<{ width: number; height: number }>(resolve => {
const size = { width: 0, height: 0 };
if (!file.type.startsWith('image/')) {
resolve(size);
return;
}
const img = new Image();
img.onload = () => {
size.width = img.width;
size.height = img.height;
URL.revokeObjectURL(img.src);
resolve(size);
};
img.onerror = () => {
URL.revokeObjectURL(img.src);
resolve(size);
};
const sanitizedURL = DOMPurify.sanitize(URL.createObjectURL(file));
img.src = sanitizedURL;
});
}
@@ -8,6 +8,7 @@ export * from './edgeless';
export * from './event';
export * from './file';
export * from './fractional-indexing';
export * from './image';
export * from './insert';
export * from './is-abort-error';
export * from './math';
@@ -1,8 +1,12 @@
import type { Viewport } from '@blocksuite/block-std/gfx';
import {
GfxControllerIdentifier,
type Viewport,
} from '@blocksuite/block-std/gfx';
import { Pane } from 'tweakpane';
import { getSentenceRects, segmentSentences } from './text-utils.js';
import type { ParagraphLayout, SectionLayout } from './types.js';
import type { ParagraphLayout, ViewportLayout } from './types.js';
import type { ViewportTurboRendererExtension } from './viewport-renderer.js';
export function syncCanvasSize(canvas: HTMLCanvasElement, host: HTMLElement) {
const hostRect = host.getBoundingClientRect();
@@ -17,30 +21,30 @@ export function syncCanvasSize(canvas: HTMLCanvasElement, host: HTMLElement) {
canvas.style.pointerEvents = 'none';
}
export function getSectionLayout(
export function getViewportLayout(
host: HTMLElement,
viewport: Viewport
): SectionLayout {
): ViewportLayout {
const paragraphBlocks = host.querySelectorAll(
'.affine-paragraph-rich-text-wrapper [data-v-text="true"]'
);
const zoom = viewport.zoom;
let sectionMinX = Infinity;
let sectionMinY = Infinity;
let sectionMaxX = -Infinity;
let sectionMaxY = -Infinity;
let layoutMinX = Infinity;
let layoutMinY = Infinity;
let layoutMaxX = -Infinity;
let layoutMaxY = -Infinity;
const paragraphs: ParagraphLayout[] = Array.from(paragraphBlocks).map(p => {
const sentences = segmentSentences(p.textContent || '');
const sentenceLayouts = sentences.map(sentence => {
const rects = getSentenceRects(p, sentence);
rects.forEach(({ rect }) => {
sectionMinX = Math.min(sectionMinX, rect.x);
sectionMinY = Math.min(sectionMinY, rect.y);
sectionMaxX = Math.max(sectionMaxX, rect.x + rect.w);
sectionMaxY = Math.max(sectionMaxY, rect.y + rect.h);
layoutMinX = Math.min(layoutMinX, rect.x);
layoutMinY = Math.min(layoutMinY, rect.y);
layoutMaxX = Math.max(layoutMaxX, rect.x + rect.w);
layoutMaxY = Math.max(layoutMaxY, rect.y + rect.h);
});
return {
text: sentence,
@@ -68,42 +72,59 @@ export function getSectionLayout(
};
});
const sectionModelCoord = viewport.toModelCoordFromClientCoord([
sectionMinX,
sectionMinY,
const layoutModelCoord = viewport.toModelCoordFromClientCoord([
layoutMinX,
layoutMinY,
]);
const w = (sectionMaxX - sectionMinX) / zoom / viewport.viewScale;
const h = (sectionMaxY - sectionMinY) / zoom / viewport.viewScale;
const section: SectionLayout = {
const w = (layoutMaxX - layoutMinX) / zoom / viewport.viewScale;
const h = (layoutMaxY - layoutMinY) / zoom / viewport.viewScale;
const layout: ViewportLayout = {
paragraphs,
rect: {
x: sectionModelCoord[0],
y: sectionModelCoord[1],
x: layoutModelCoord[0],
y: layoutModelCoord[1],
w: Math.max(w, 0),
h: Math.max(h, 0),
},
};
return section;
return layout;
}
export function initTweakpane(
viewportElement: HTMLElement,
onStateChange: (value: boolean) => void
renderer: ViewportTurboRendererExtension,
viewportElement: HTMLElement
) {
const debugPane = new Pane({ container: viewportElement });
const paneElement = debugPane.element;
paneElement.style.position = 'absolute';
paneElement.style.top = '10px';
paneElement.style.left = '10px';
paneElement.style.right = '10px';
paneElement.style.width = '250px';
debugPane.title = 'Viewport Turbo Renderer';
const params = { enabled: true };
debugPane
.addBinding(params, 'enabled', {
label: 'Enable',
.addBinding({ paused: true }, 'paused', {
label: 'Paused',
})
.on('change', ({ value }) => {
onStateChange(value);
renderer.state = value ? 'paused' : 'monitoring';
});
debugPane
.addBinding({ keepDOM: true }, 'keepDOM', {
label: 'Keep DOM',
})
.on('change', ({ value }) => {
const container = viewportElement.querySelector('gfx-viewport')!;
(container as HTMLElement).style.display = value ? 'block' : 'none';
});
debugPane.addButton({ title: 'Fit Viewport' }).on('click', () => {
const gfx = renderer.std.get(GfxControllerIdentifier);
gfx.fitToScreen();
});
debugPane.addButton({ title: 'Force Refresh' }).on('click', () => {
renderer.refresh(true).catch(console.error);
});
}

Some files were not shown because too many files have changed in this diff Show More