chore: migrate oxlint & oxfmt (#15464)

#### PR Dependency Tree


* **PR #15464** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Replaced the project’s formatting and linting workflow with Oxfmt and
Oxlint.
* Added shared formatting and linting configuration, editor integration,
and updated automated checks.
* Updated generated files, scripts, and lint guidance to use the new
tooling.

* **Style**
* Reformatted templates, source code, examples, and configuration files
for consistent readability.
  * No user-facing functionality or rendering behavior changed.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-08-10 23:51:28 +08:00
committed by GitHub
parent 749c83cd8e
commit 0c7b20dc18
292 changed files with 3372 additions and 2866 deletions
+1 -5
View File
@@ -17,11 +17,7 @@
// Configure tool-specific properties.
"customizations": {
"vscode": {
"extensions": [
"ms-playwright.playwright",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint"
]
"extensions": ["ms-playwright.playwright", "oxc.oxc-vscode"]
}
},
"updateContentCommand": "bash ./.devcontainer/build.sh",
+1 -1
View File
@@ -13,7 +13,7 @@
{
"rangeStrategy": "replace",
"groupName": "linter",
"matchPackageNames": ["/^eslint/", "/^@typescript-eslint/"]
"matchPackageNames": ["/^eslint-plugin/"]
},
{
"matchDepNames": ["oxlint"],
+2 -4
View File
@@ -91,13 +91,11 @@ jobs:
run: yarn lint:ox
- name: Run i18n codegen
run: yarn affine @affine/i18n build
- name: Run ESLint
run: yarn lint:eslint --max-warnings=0
- name: Run Prettier
- name: Run Oxfmt
# Set nmMode in `actions/setup-node` will modify the .yarnrc.yml
run: |
git checkout .yarnrc.yml
yarn lint:prettier
yarn lint:format
- name: Yarn Dedupe
run: yarn dedupe --check
-1
View File
@@ -73,7 +73,6 @@ playwright/.cache
download
# Cache
.eslintcache
next-env.d.ts
.rollup.cache
+10
View File
@@ -0,0 +1,10 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"printWidth": 80,
"singleQuote": true,
"trailingComma": "es5",
"tabWidth": 2,
"arrowParens": "avoid",
"sortPackageJson": false,
"ignorePatterns": ["**/*.toml"]
}
+92 -1
View File
@@ -3,9 +3,27 @@
"jsPlugins": [
"eslint-plugin-simple-import-sort",
"eslint-plugin-sonarjs",
"eslint-plugin-lit"
"eslint-plugin-lit",
{
"name": "import-x-js",
"specifier": "eslint-plugin-import-x"
},
{
"name": "react-js",
"specifier": "eslint-plugin-react"
},
{
"name": "react-hooks-js",
"specifier": "eslint-plugin-react-hooks"
}
],
"plugins": ["import", "react", "typescript", "unicorn", "promise"],
"settings": {
"_comment": "TODO: Restore rxjs/finnish when Oxlint JS plugins support type-aware rules.",
"react": {
"version": "19.2.1"
}
},
"categories": {
"correctness": "error",
"perf": "error"
@@ -66,8 +84,19 @@
"no-unused-private-class-members": "error",
"no-useless-backreference": "error",
"react/display-name": "error",
"react-js/no-deprecated": "error",
"react/rules-of-hooks": "error",
"react/exhaustive-deps": "warn",
"react-hooks-js/component-hook-factories": "error",
"react-hooks-js/preserve-manual-memoization": "error",
"react-hooks-js/incompatible-library": "warn",
"react-hooks-js/globals": "error",
"react-hooks-js/error-boundaries": "error",
"react-hooks-js/purity": "error",
"react-hooks-js/set-state-in-render": "error",
"react-hooks-js/unsupported-syntax": "warn",
"react-hooks-js/config": "error",
"react-hooks-js/gating": "error",
"typescript/prefer-for-of": "error",
"typescript/no-unsafe-function-type": "error",
"typescript/no-wrapper-object-types": "error",
@@ -162,6 +191,7 @@
"no-useless-catch": "error",
"no-async-promise-executor": "error",
"no-unreachable": "error",
"no-unreachable-loop": "error",
"no-duplicate-case": "error",
"no-empty-pattern": "error",
"no-unused-labels": "error",
@@ -399,6 +429,67 @@
"lit/binding-positions": "off",
"lit/no-invalid-html": "off"
}
},
{
"files": [
"packages/**/*.{ts,tsx}",
"tools/**/*.{ts,tsx}",
"blocksuite/**/*.{ts,tsx}"
],
"rules": {
"import-x-js/no-extraneous-dependencies": [
"error",
{
"includeInternal": true
}
]
}
},
{
"files": ["packages/frontend/admin/**/*"],
"rules": {
"import-x-js/no-extraneous-dependencies": [
"error",
{
"includeInternal": true,
"whitelist": ["@affine/admin"]
}
]
}
},
{
"files": ["packages/frontend/core/**/*"],
"rules": {
"import-x-js/no-extraneous-dependencies": [
"error",
{
"includeInternal": true,
"whitelist": ["@affine/core"]
}
]
}
},
{
"files": ["packages/frontend/component/**/*"],
"rules": {
"import-x-js/no-extraneous-dependencies": [
"error",
{
"includeInternal": true,
"whitelist": ["@affine/component"]
}
]
}
},
{
"files": [
"packages/frontend/apps/electron/scripts/**/*",
"tests/blocksuite/**/*.{ts,tsx}",
"blocksuite/**/__tests__/**/*.{ts,tsx}"
],
"rules": {
"import-x-js/no-extraneous-dependencies": "off"
}
}
]
}
+1 -1
View File
@@ -1,4 +1,4 @@
# we will make this file shared by prettier|eslint|oxlint
# shared by oxfmt|oxlint
**/node_modules
.yarn
.github/helm
-6
View File
@@ -1,6 +0,0 @@
{
"singleQuote": true,
"trailingComma": "es5",
"tabWidth": 2,
"arrowParens": "avoid"
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"recommendations": [
"ms-playwright.playwright",
"esbenp.prettier-vscode",
"oxc.oxc-vscode",
"deepscan.vscode-deepscan",
"streetsidesoftware.code-spell-checker"
]
+4 -6
View File
@@ -1,6 +1,6 @@
{
"prisma.pinToPrisma6": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.formatOnSave": true,
"editor.formatOnSaveMode": "file",
"cSpell.words": [
@@ -17,10 +17,10 @@
"explorer.fileNesting.enabled": true,
"explorer.fileNesting.patterns": {
"*.js": "${capture}.js.map, ${capture}.min.js, ${capture}.d.ts, ${capture}.d.ts.map",
"package.json": ".browserslist*, .circleci*, .codecov, .commitlint*, .cz-config.js, .czrc, .dlint.json, .dprint.json, .editorconfig, .eslint*, eslint.*, .firebase*, .flowconfig, .github*, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .lighthouserc.*, .lintstagedrc*, .markdownlint*, .mocha*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, api-extractor.json, apollo.config.*, appveyor*, ava.config.*, azure-pipelines*, bower.json, build.config.*, commitlint*, dangerfile*, dlint.json, dprint.json, firebase.json, grunt*, gulp*, histoire.config.*, jasmine.*, jenkins*, jest.config.*, jsconfig.*, karma*, lerna*, lighthouserc.*, lint-staged*, nest-cli.*, netlify*, nodemon*, nx.*, package-lock.json, package.nls*.json, phpcs.xml, playwright.config.*, pm2.*, pnpm*, prettier*, pullapprove*, puppeteer.config.*, pyrightconfig.json, release-tasks.sh, renovate*, rollup.config.*, stylelint*, tsconfig.*, tsdoc.*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, vitest.*, webpack*, workspace.json, xo.config.*, yarn*, babel.*, .babelrc, project.json, .oxlintrc.json, oxlint.json, nyc.config.*",
"package.json": ".browserslist*, .circleci*, .codecov, .commitlint*, .cz-config.js, .czrc, .dlint.json, .dprint.json, .editorconfig, .firebase*, .flowconfig, .github*, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .lighthouserc.*, .lintstagedrc*, .markdownlint*, .mocha*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, api-extractor.json, apollo.config.*, appveyor*, ava.config.*, azure-pipelines*, bower.json, build.config.*, commitlint*, dangerfile*, dlint.json, dprint.json, firebase.json, grunt*, gulp*, histoire.config.*, jasmine.*, jenkins*, jest.config.*, jsconfig.*, karma*, lerna*, lighthouserc.*, lint-staged*, nest-cli.*, netlify*, nodemon*, nx.*, package-lock.json, package.nls*.json, phpcs.xml, playwright.config.*, pm2.*, pnpm*, prettier*, pullapprove*, puppeteer.config.*, pyrightconfig.json, release-tasks.sh, renovate*, rollup.config.*, stylelint*, tsconfig.*, tsdoc.*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, vitest.*, webpack*, workspace.json, xo.config.*, yarn*, babel.*, .babelrc, project.json, .oxlintrc.json, oxlint.json, nyc.config.*",
"Cargo.toml": "Cargo.lock, rust-toolchain*, rustfmt.toml, .taplo.toml",
"README.md": "LICENSE*, CHANGELOG.md, CODE_OF_CONDUCT.md, CONTRIBUTING.md, SECURITY.md, README.*",
".gitignore": ".gitattributes, .dockerignore, .eslintignore, .prettierignore, .stylelintignore, .tslintignore, .yarnignore"
".gitignore": ".gitattributes, .dockerignore, .prettierignore, .stylelintignore, .tslintignore, .yarnignore"
},
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer"
@@ -29,11 +29,9 @@
"editor.defaultFormatter": "tamasfe.even-better-toml"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"vitest.include": ["packages/**/*.spec.ts", "packages/**/*.spec.tsx"],
"eslint.runtime": "node",
"eslint.execArgv": ["--max_old_space_size=16384"],
"rust-analyzer.check.extraEnv": {
"DATABASE_URL": "sqlite:affine.db"
},
@@ -0,0 +1,26 @@
diff --git a/dist/frameworks/i18next/generator/react-hooks.js b/dist/frameworks/i18next/generator/react-hooks.js
index ae1953ca1baceb09e587eda931567c8d8c5d671e..3bc918f6ff4f378e297d1fe927dcc90cf20c821e 100644
--- a/dist/frameworks/i18next/generator/react-hooks.js
+++ b/dist/frameworks/i18next/generator/react-hooks.js
@@ -99,7 +99,7 @@ export function i18NextReactHooksGenerator(gen) {
// Codegen
const printedSourceFile = [
gen.generatorOptions?.emitTS && '// @ts-nocheck',
- '/* eslint-disable */',
+ '/* oxlint-disable */',
printer.printFile(factory.createSourceFile(statements, factory.createToken(SyntaxKind.EndOfFileToken), NodeFlags.Synthesized)),
]
.filter(Boolean)
diff --git a/src/frameworks/i18next/generator/react-hooks.ts b/src/frameworks/i18next/generator/react-hooks.ts
index bbaf10a2b482e6118e786e634d15abab31c7ba32..a2dfd09ad422cb24c986d1a4ee3458197e70d5c2 100644
--- a/src/frameworks/i18next/generator/react-hooks.ts
+++ b/src/frameworks/i18next/generator/react-hooks.ts
@@ -203,7 +203,7 @@ export function i18NextReactHooksGenerator(gen: GenType) {
// Codegen
const printedSourceFile = [
gen.generatorOptions?.emitTS && '// @ts-nocheck',
- '/* eslint-disable */',
+ '/* oxlint-disable */',
printer.printFile(
factory.createSourceFile(statements, factory.createToken(SyntaxKind.EndOfFileToken), NodeFlags.Synthesized),
),
@@ -234,22 +234,26 @@ export class CalloutBlockComponent extends CaptionedBlockComponent<CalloutBlockM
backgroundColor: backgroundColor ?? 'transparent',
})}
>
${iconContent
? html`
<div
@click=${this._toggleIconPicker}
contenteditable="false"
class="${calloutEmojiContainerStyles}"
style=${styleMap({
marginTop: this._getEmojiMarginTop(),
})}
>
<span class="${calloutEmojiStyles}" data-testid="callout-emoji"
>${iconContent}</span
${
iconContent
? html`
<div
@click=${this._toggleIconPicker}
contenteditable="false"
class="${calloutEmojiContainerStyles}"
style=${styleMap({
marginTop: this._getEmojiMarginTop(),
})}
>
</div>
`
: ''}
<span
class="${calloutEmojiStyles}"
data-testid="callout-emoji"
>${iconContent}</span
>
</div>
`
: ''
}
<div class="${calloutChildrenStyles}">
${this.renderChildren(this.model)}
</div>
@@ -489,9 +489,11 @@ export class CodeBlockComponent extends CaptionedBlockComponent<CodeBlockModel>
}}
>
</rich-text>
${collapsed
? html`<div class="code-collapsed-fade" aria-hidden="true"></div>`
: nothing}
${
collapsed
? html`<div class="code-collapsed-fade" aria-hidden="true"></div>`
: nothing
}
<div
style=${styleMap({
display: shouldRenderPreview && !collapsed ? undefined : 'none',
@@ -132,32 +132,36 @@ export class LinkCell extends BaseCellRenderer<string, string> {
return html`
<div>
<div class="${linkContainerStyle}">
${isDoc
? html`<span class="${linkedDocStyle}" @click="${this.openDoc}"
>${docName}</span
>`
: isValidUrl(linkText)
? html`<a
data-testid="property-link-a"
class="${inlineLinkNodeStyle}"
href="${linkText}"
rel="noopener noreferrer"
target="_blank"
>${linkText}</a
${
isDoc
? html`<span class="${linkedDocStyle}" @click="${this.openDoc}"
>${docName}</span
>`
: html`<span class="${normalTextStyle}">${linkText}</span>`}
: isValidUrl(linkText)
? html`<a
data-testid="property-link-a"
class="${inlineLinkNodeStyle}"
href="${linkText}"
rel="noopener noreferrer"
target="_blank"
>${linkText}</a
>`
: html`<span class="${normalTextStyle}">${linkText}</span>`
}
</div>
${hasLink
? html` <div class="${linkIconContainerStyle} ${showLinkIconStyle}">
<div
class="${linkIconStyle}"
data-testid="edit-link-button"
@click="${this._onEdit}"
>
${EditIcon()}
</div>
</div>`
: nothing}
${
hasLink
? html` <div class="${linkIconContainerStyle} ${showLinkIconStyle}">
<div
class="${linkIconStyle}"
data-testid="edit-link-button"
@click="${this._onEdit}"
>
${EditIcon()}
</div>
</div>`
: nothing
}
</div>
`;
}
@@ -427,33 +427,37 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
`
)
)}
${isError
? html`
<div class="affine-embed-linked-doc-card-content-reload">
<div
class="affine-embed-linked-doc-card-content-reload-button"
@click=${this.refreshData}
>
${ResetIcon()} <span>Reload</span>
${
isError
? html`
<div class="affine-embed-linked-doc-card-content-reload">
<div
class="affine-embed-linked-doc-card-content-reload-button"
@click=${this.refreshData}
>
${ResetIcon()} <span>Reload</span>
</div>
</div>
</div>
`
: html`
<div class="affine-embed-linked-doc-content-date">
<span>Updated</span>
`
: html`
<div class="affine-embed-linked-doc-content-date">
<span>Updated</span>
<span>${dateText}</span>
</div>
`}
<span>${dateText}</span>
</div>
`
}
</div>
${showDefaultBanner
? html`
<div class="affine-embed-linked-doc-banner default">
${defaultBanner}
</div>
`
: nothing}
${
showDefaultBanner
? html`
<div class="affine-embed-linked-doc-banner default">
${defaultBanner}
</div>
`
: nothing
}
</div>
`
);
@@ -202,42 +202,48 @@ export class EmbedSyncedDocCard extends WithDisposable(ShadowlessElement) {
</div>
</div>
${showDefaultNoteContent
? html`<div class="affine-embed-synced-doc-content-note default">
${defaultNoteContent}
</div>`
: nothing}
${
showDefaultNoteContent
? html`<div class="affine-embed-synced-doc-content-note default">
${defaultNoteContent}
</div>`
: nothing
}
<div class="affine-embed-synced-doc-content-note render"></div>
${error
? html`
<div class="affine-embed-synced-doc-card-content-reload">
<div
class="affine-embed-synced-doc-card-content-reload-button"
@click=${() => this.block.refreshData()}
>
${ResetIcon()} <span>Reload</span>
${
error
? html`
<div class="affine-embed-synced-doc-card-content-reload">
<div
class="affine-embed-synced-doc-card-content-reload-button"
@click=${() => this.block.refreshData()}
>
${ResetIcon()} <span>Reload</span>
</div>
</div>
</div>
`
: html`
<div class="affine-embed-synced-doc-card-content-date">
<span>Updated</span>
`
: html`
<div class="affine-embed-synced-doc-card-content-date">
<span>Updated</span>
<span>${dateText}</span>
</div>
`}
<span>${dateText}</span>
</div>
`
}
</div>
<div class="affine-embed-synced-doc-card-banner render"></div>
${showDefaultBanner
? html`
<div class="affine-embed-synced-doc-card-banner default">
${defaultBanner}
</div>
`
: nothing}
${
showDefaultBanner
? html`
<div class="affine-embed-synced-doc-card-banner default">
${defaultBanner}
</div>
`
: nothing
}
</div>
`;
}
@@ -123,15 +123,17 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
${header}
</div>
<div class="affine-embed-synced-doc-editor">
${this.isPageMode && this._isEmptySyncedDoc
? html`
<div class="affine-embed-synced-doc-editor-empty">
<span>
This is a linked doc, you can add content here.
</span>
</div>
`
: guard([editorMode, syncedDoc], renderEditor)}
${
this.isPageMode && this._isEmptySyncedDoc
? html`
<div class="affine-embed-synced-doc-editor-empty">
<span>
This is a linked doc, you can add content here.
</span>
</div>
`
: guard([editorMode, syncedDoc], renderEditor)
}
</div>
<div class="affine-embed-synced-doc-editor-overlay"></div>
</div>
@@ -242,18 +242,20 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
?data-scale=${undefined}
>
<div class="affine-embed-synced-doc-editor">
${isPageMode && this._isEmptySyncedDoc
? html`
<div class="affine-embed-synced-doc-editor-empty">
<span>
This is a linked doc, you can add content here.
</span>
</div>
`
: guard(
[editorMode, syncedDoc, appTheme, edgelessTheme],
renderEditor
)}
${
isPageMode && this._isEmptySyncedDoc
? html`
<div class="affine-embed-synced-doc-editor-empty">
<span>
This is a linked doc, you can add content here.
</span>
</div>
`
: guard(
[editorMode, syncedDoc, appTheme, edgelessTheme],
renderEditor
)
}
</div>
<div
class=${classMap({
@@ -108,11 +108,13 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent<EmbedFigmaMode
</div>
</div>
${description
? html`<div class="affine-embed-figma-content-description">
${description}
</div>`
: nothing}
${
description
? html`<div class="affine-embed-figma-content-description">
${description}
</div>`
: nothing
}
<div class="affine-embed-figma-content-url" @click=${this.open}>
<span>www.figma.com</span>
@@ -183,21 +183,23 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent<
${titleIcon}
</div>
${status && statusText
? html`<div
class=${classMap({
'affine-embed-github-content-title-status-icon': true,
[githubType]: true,
[status]: true,
success: statusReason === 'completed',
failure: statusReason === 'not_planned',
})}
>
${statusIcon}
${
status && statusText
? html`<div
class=${classMap({
'affine-embed-github-content-title-status-icon': true,
[githubType]: true,
[status]: true,
success: statusReason === 'completed',
failure: statusReason === 'not_planned',
})}
>
${statusIcon}
<span>${statusText}</span>
</div>`
: nothing}
<span>${statusText}</span>
</div>`
: nothing
}
</div>
<div class="affine-embed-github-content-title-text">
@@ -209,50 +211,56 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent<
${descriptionText}
</div>
${githubType === 'issue' && assignees
? html`
<div class="affine-embed-github-content-assignees">
<div
class="affine-embed-github-content-assignees-text label"
>
Assignees
</div>
${
githubType === 'issue' && assignees
? html`
<div class="affine-embed-github-content-assignees">
<div
class="affine-embed-github-content-assignees-text label"
>
Assignees
</div>
<div
class="affine-embed-github-content-assignees-text users"
>
${assignees.length === 0
? html`<span
class="affine-embed-github-content-assignees-text-users placeholder"
>No one</span
>`
: repeat(
assignees,
assignee => assignee,
(assignee, index) =>
html`<span
class="affine-embed-github-content-assignees-text-users user"
@click=${() =>
this._handleAssigneeClick(assignee)}
>${`@${assignee}`}</span
>
${index === assignees.length - 1 ? '' : `, `}`
)}
<div
class="affine-embed-github-content-assignees-text users"
>
${
assignees.length === 0
? html`<span
class="affine-embed-github-content-assignees-text-users placeholder"
>No one</span
>`
: repeat(
assignees,
assignee => assignee,
(assignee, index) =>
html`<span
class="affine-embed-github-content-assignees-text-users user"
@click=${() =>
this._handleAssigneeClick(assignee)}
>${`@${assignee}`}</span
>
${index === assignees.length - 1 ? '' : `, `}`
)
}
</div>
</div>
</div>
`
: nothing}
`
: nothing
}
<div class="affine-embed-github-content-url" @click=${this.open}>
<span class="affine-embed-github-content-repo"
>${`${owner}/${repo} |`}</span
>
${createdAt
? html`<span class="affine-embed-github-content-date"
>${dateText} |</span
>`
: nothing}
${
createdAt
? html`<span class="affine-embed-github-content-date"
>${dateText} |</span
>`
: nothing
}
<span>github.com</span>
<div class="affine-embed-github-content-url-icon">
@@ -252,16 +252,18 @@ export class EmbedIframeErrorCard extends WithDisposable(LitElement) {
${this.error?.message || 'Failed to load embedded content'}
</div>
<div class="error-info">
${this.readonly
? nothing
: html`
<div class="button edit" @click=${this._toggleEdit}>
<span class="icon"
>${EditIcon({ width: '16px', height: '16px' })}</span
>
<span class="text">Edit</span>
</div>
`}
${
this.readonly
? nothing
: html`
<div class="button edit" @click=${this._toggleEdit}>
<span class="icon"
>${EditIcon({ width: '16px', height: '16px' })}</span
>
<span class="text">Edit</span>
</div>
`
}
<div class="button retry" @click=${this._handleRetry}>
<span class="icon"
>${ResetIcon({ width: '16px', height: '16px' })}</span
@@ -244,13 +244,15 @@ export class EmbedIframeLinkInputPopup extends EmbedIframeLinkInputBase {
return html`
<div class=${modalMainWrapperClass}>
${showCloseButton
? html`
<div class="popup-close-button" @click=${this._onClose}>
${CloseIcon({ width: '20', height: '20' })}
</div>
`
: nothing}
${
showCloseButton
? html`
<div class="popup-close-button" @click=${this._onClose}>
${CloseIcon({ width: '20', height: '20' })}
</div>
`
: nothing
}
<div class="link-input-popup-content-wrapper">
<div class="title">${title}</div>
<div class="description">${description}</div>
@@ -392,9 +392,11 @@ export class EmbedIframeBlockComponent extends CaptionedBlockComponent<EmbedIfra
scrolling=${ifDefined(scrolling)}
style=${ifDefined(style)}
></iframe>
${sourceHost
? html`<div class="affine-embed-iframe-source">${sourceHost}</div>`
: nothing}`;
${
sourceHost
? html`<div class="affine-embed-iframe-source">${sourceHost}</div>`
: nothing
}`;
};
private readonly _isIframeUrlAllowed = (iframeUrl: string) => {
@@ -118,28 +118,30 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
@dblclick=${this._handleDoubleClick}
>
<div class="affine-embed-loom-video">
${videoId
? html`
<div class="affine-embed-loom-video-iframe-container">
<iframe
src=${`https://www.loom.com/embed/${videoId}?hide_title=true`}
frameborder="0"
allow="fullscreen; autoplay; clipboard-write; encrypted-media; picture-in-picture; web-share"
sandbox="allow-scripts allow-same-origin allow-presentation"
loading="lazy"
credentialless
></iframe>
${
videoId
? html`
<div class="affine-embed-loom-video-iframe-container">
<iframe
src=${`https://www.loom.com/embed/${videoId}?hide_title=true`}
frameborder="0"
allow="fullscreen; autoplay; clipboard-write; encrypted-media; picture-in-picture; web-share"
sandbox="allow-scripts allow-same-origin allow-presentation"
loading="lazy"
credentialless
></iframe>
<!-- overlay to prevent the iframe from capturing pointer events -->
<div
class=${classMap({
'affine-embed-loom-video-iframe-overlay': true,
hide: !this.showOverlay$.value,
})}
></div>
</div>
`
: bannerImage}
<!-- overlay to prevent the iframe from capturing pointer events -->
<div
class=${classMap({
'affine-embed-loom-video-iframe-overlay': true,
hide: !this.showOverlay$.value,
})}
></div>
</div>
`
: bannerImage
}
</div>
<div class="affine-embed-loom-content">
<div class="affine-embed-loom-content-header">
@@ -134,40 +134,42 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
@dblclick=${this._handleDoubleClick}
>
<div class="affine-embed-youtube-video">
${videoId
? html`
<div class="affine-embed-youtube-video-iframe-container">
<iframe
id="ytplayer"
type="text/html"
src=${`https://www.youtube.com/embed/${videoId}`}
frameborder="0"
allow="fullscreen; autoplay; clipboard-write; encrypted-media; picture-in-picture; web-share"
sandbox="allow-scripts allow-same-origin allow-presentation"
loading="lazy"
credentialless
></iframe>
${
videoId
? html`
<div class="affine-embed-youtube-video-iframe-container">
<iframe
id="ytplayer"
type="text/html"
src=${`https://www.youtube.com/embed/${videoId}`}
frameborder="0"
allow="fullscreen; autoplay; clipboard-write; encrypted-media; picture-in-picture; web-share"
sandbox="allow-scripts allow-same-origin allow-presentation"
loading="lazy"
credentialless
></iframe>
<!-- overlay to prevent the iframe from capturing pointer events -->
<div
class=${classMap({
'affine-embed-youtube-video-iframe-overlay': true,
hide: !this.showOverlay$.value,
})}
></div>
<img
class=${classMap({
'affine-embed-youtube-video-iframe-overlay': true,
'media-print': true,
hide: !this._showImage,
})}
src=${`https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`}
alt="YouTube Video"
loading="lazy"
/>
</div>
`
: bannerImage}
<!-- overlay to prevent the iframe from capturing pointer events -->
<div
class=${classMap({
'affine-embed-youtube-video-iframe-overlay': true,
hide: !this.showOverlay$.value,
})}
></div>
<img
class=${classMap({
'affine-embed-youtube-video-iframe-overlay': true,
'media-print': true,
hide: !this._showImage,
})}
src=${`https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`}
alt="YouTube Video"
loading="lazy"
/>
</div>
`
: bannerImage
}
</div>
<div class="affine-embed-youtube-content">
<div class="affine-embed-youtube-content-header">
@@ -188,15 +190,17 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
</div>
</div>
${loading
? html`<div
class="affine-embed-youtube-content-description"
></div>`
: descriptionText
? html`<div class="affine-embed-youtube-content-description">
${descriptionText}
</div>`
: nothing}
${
loading
? html`<div
class="affine-embed-youtube-content-description"
></div>`
: descriptionText
? html`<div class="affine-embed-youtube-content-description">
${descriptionText}
</div>`
: nothing
}
<div class="affine-embed-youtube-content-url" @click=${this.open}>
<span>www.youtube.com</span>
@@ -25,12 +25,14 @@ export class EdgelessFrameToolButton extends QuickToolMixin(LitElement) {
return html`
<edgeless-tool-icon-button
class="edgeless-frame-button"
.tooltip=${this.popper
? ''
: html`<affine-tooltip-content-with-shortcut
data-tip="${'Frame'}"
data-shortcut="${'F'}"
></affine-tooltip-content-with-shortcut>`}
.tooltip=${
this.popper
? ''
: html`<affine-tooltip-content-with-shortcut
data-tip="${'Frame'}"
data-shortcut="${'F'}"
></affine-tooltip-content-with-shortcut>`
}
.tooltipOffset=${17}
.iconSize=${'24px'}
.active=${type === 'frame'}
@@ -407,15 +407,17 @@ export class PresentationToolbar extends EdgelessToolbarToolMixin(
</edgeless-tool-icon-button>
<div class="edgeless-frame-navigator ${this.dense ? 'dense' : ''}">
${this.dense
? nothing
: html`<span
style="color: ${cssVar('textPrimaryColor')}"
class="edgeless-frame-navigator-title"
@click=${() => this._moveToCurrentFrame()}
>
${frame?.props.title ?? 'no frame'}
</span>`}
${
this.dense
? nothing
: html`<span
style="color: ${cssVar('textPrimaryColor')}"
class="edgeless-frame-navigator-title"
@click=${() => this._moveToCurrentFrame()}
>
${frame?.props.title ?? 'no frame'}
</span>`
}
<span class="edgeless-frame-navigator-count">
${frames.length === 0 ? 0 : current + 1} / ${frames.length}
@@ -435,9 +437,11 @@ export class PresentationToolbar extends EdgelessToolbarToolMixin(
<div class="config-buttons">
<edgeless-tool-icon-button
.tooltip=${document.fullscreenElement
? 'Exit Full Screen'
: 'Enter Full Screen'}
.tooltip=${
document.fullscreenElement
? 'Exit Full Screen'
: 'Enter Full Screen'
}
@click=${() => this._toggleFullScreen()}
.iconContainerPadding=${0}
.iconContainerWidth=${'24px'}
@@ -446,14 +450,16 @@ export class PresentationToolbar extends EdgelessToolbarToolMixin(
${document.fullscreenElement ? ExpandCloseIcon() : ExpandFullIcon()}
</edgeless-tool-icon-button>
${this.dense
? nothing
: html`<edgeless-frame-order-button
.popperShow=${this.frameMenuShow}
.setPopperShow=${this.setFrameMenuShow}
.edgeless=${this.edgeless}
>
</edgeless-frame-order-button>`}
${
this.dense
? nothing
: html`<edgeless-frame-order-button
.popperShow=${this.frameMenuShow}
.setPopperShow=${this.setFrameMenuShow}
.edgeless=${this.edgeless}
>
</edgeless-frame-order-button>`
}
<edgeless-navigator-setting-button
.edgeless=${this.edgeless}
@@ -218,9 +218,9 @@ export class EdgelessFrameOrderMenu extends SignalWatcher(
return html`
<div
class="edgeless-frame-order-items-container ${this.embed
? 'embed'
: ''}"
class="edgeless-frame-order-items-container ${
this.embed ? 'embed' : ''
}"
@click=${(e: MouseEvent) => e.stopPropagation()}
>
${repeat(
@@ -235,11 +235,13 @@ export class EdgelessFrameOrderMenu extends SignalWatcher(
)}
<div class="indicator-line"></div>
<div class="clone item">
${frame
? html`<div class="drag-indicator"></div>
<div class="index">${this._curIndex + 1}</div>
<div class="title">${frame.props.title.toString()}</div>`
: nothing}
${
frame
? html`<div class="drag-indicator"></div>
<div class="index">${this._curIndex + 1}</div>
<div class="title">${frame.props.title.toString()}</div>`
: nothing
}
</div>
</div>
`;
@@ -150,17 +150,19 @@ export class EdgelessNavigatorSettingButton extends WithDisposable(LitElement) {
</toggle-switch>
</div>
${this.includeFrameOrder
? html` <div class="divider"></div>
<div class="item-container header">
<div class="text title">Frame Order</div>
</div>
${
this.includeFrameOrder
? html` <div class="divider"></div>
<div class="item-container header">
<div class="text title">Frame Order</div>
</div>
<edgeless-frame-order-menu
.edgeless=${this.edgeless}
.embed=${true}
></edgeless-frame-order-menu>`
: nothing}
<edgeless-frame-order-menu
.edgeless=${this.edgeless}
.embed=${true}
></edgeless-frame-order-menu>`
: nothing
}
</div>
`;
}
+19 -17
View File
@@ -174,23 +174,25 @@ export class ListBlockComponent extends CaptionedBlockComponent<ListBlockModel>
[TOGGLE_BUTTON_PARENT_CLASS]: true,
})}
>
${this.model.children.length > 0
? html`
<blocksuite-toggle-button
.collapsed=${collapsed}
.updateCollapsed=${(value: boolean) => {
if (this.store.readonly) {
this._readonlyCollapsed = value;
} else {
this.store.captureSync();
this.store.updateBlock(this.model, {
collapsed: value,
});
}
}}
></blocksuite-toggle-button>
`
: nothing}
${
this.model.children.length > 0
? html`
<blocksuite-toggle-button
.collapsed=${collapsed}
.updateCollapsed=${(value: boolean) => {
if (this.store.readonly) {
this._readonlyCollapsed = value;
} else {
this.store.captureSync();
this.store.updateBlock(this.model, {
collapsed: value,
});
}
}}
></blocksuite-toggle-button>
`
: nothing
}
${listIcon}
<rich-text
.yText=${this.model.props.text.yText}
@@ -58,9 +58,11 @@ export function getListIcon(
class=${`affine-list-block__prefix affine-list-block__todo-prefix ${model.store.readonly ? 'readonly' : ''}`}
@click=${onClick}
>
${model.props.checked
? CheckBoxCheckSolidIcon({ style: 'color: #1E96EB' })
: CheckBoxUnIcon()}
${
model.props.checked
? CheckBoxCheckSolidIcon({ style: 'color: #1E96EB' })
: CheckBoxUnIcon()
}
</div>`;
case 'toggle':
return html`<div
@@ -322,25 +322,27 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
.editing=${this._editing}
></edgeless-note-mask>
${isCollapsable &&
tool.currentToolName$.value !== 'frameNavigator' &&
(!this.model.isPageBlock() || !hasHeader)
? html`<div
class="${classMap({
[styles.collapseButton]: true,
flip: isCollapseArrowUp,
})}"
style=${styleMap({
bottom: this._editing ? `${-extra}px` : '0',
})}
data-testid="edgeless-note-collapse-button"
@mousedown=${stopPropagation}
@mouseup=${stopPropagation}
@click=${this._setCollapse}
>
${MoreIndicator}
</div>`
: nothing}
${
isCollapsable &&
tool.currentToolName$.value !== 'frameNavigator' &&
(!this.model.isPageBlock() || !hasHeader)
? html`<div
class="${classMap({
[styles.collapseButton]: true,
flip: isCollapseArrowUp,
})}"
style=${styleMap({
bottom: this._editing ? `${-extra}px` : '0',
})}
data-testid="edgeless-note-collapse-button"
@mousedown=${stopPropagation}
@mouseup=${stopPropagation}
@click=${this._setCollapse}
>
${MoreIndicator}
</div>`
: nothing
}
${this._collapsedContent()}
</div>
`;
@@ -304,38 +304,42 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<ParagraphBl
[TOGGLE_BUTTON_PARENT_CLASS]: true,
})}
>
${this.model.props.type$.value.startsWith('h')
? html`
<affine-paragraph-heading-icon
.model=${this.model}
></affine-paragraph-heading-icon>
`
: nothing}
${this.model.props.type$.value.startsWith('h') &&
collapsedSiblings.length > 0
? html`
<blocksuite-toggle-button
.collapsed=${collapsed}
.updateCollapsed=${(value: boolean) => {
if (this.store.readonly) {
this._readonlyCollapsed = value;
} else {
this.store.captureSync();
this.store.updateBlock(this.model, {
collapsed: value,
});
}
${
this.model.props.type$.value.startsWith('h')
? html`
<affine-paragraph-heading-icon
.model=${this.model}
></affine-paragraph-heading-icon>
`
: nothing
}
${
this.model.props.type$.value.startsWith('h') &&
collapsedSiblings.length > 0
? html`
<blocksuite-toggle-button
.collapsed=${collapsed}
.updateCollapsed=${(value: boolean) => {
if (this.store.readonly) {
this._readonlyCollapsed = value;
} else {
this.store.captureSync();
this.store.updateBlock(this.model, {
collapsed: value,
});
}
if (this.hasCitationSiblings) {
this.citationService.trackEvent('Expand', {
control: 'Source Button',
type: value ? 'Hide' : 'Show',
});
}
}}
></blocksuite-toggle-button>
`
: nothing}
if (this.hasCitationSiblings) {
this.citationService.trackEvent('Expand', {
control: 'Source Button',
type: value ? 'Hide' : 'Show',
});
}
}}
></blocksuite-toggle-button>
`
: nothing
}
<rich-text
.yText=${this.model.props.text.yText}
.inlineEventSource=${this.topContenteditableElement ?? nothing}
@@ -351,19 +355,21 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<ParagraphBl
.verticalScrollContainerGetter=${() =>
getViewportElement(this.host)}
></rich-text>
${this.inEdgelessText
? nothing
: html`
<div
contenteditable="false"
class=${classMap({
'affine-paragraph-placeholder': true,
visible: this._displayPlaceholder.value,
})}
>
${this._placeholder}
</div>
`}
${
this.inEdgelessText
? nothing
: html`
<div
contenteditable="false"
class=${classMap({
'affine-paragraph-placeholder': true,
visible: this._displayPlaceholder.value,
})}
>
${this._placeholder}
</div>
`
}
</div>
${children} ${widgets}
@@ -544,7 +544,7 @@ export class EdgelessClipboardController extends PageClipboard {
}
});
// oxlint-disable-next-line @typescript-eslint/prefer-for-of
// oxlint-disable-next-line typescript/prefer-for-of
for (let i = 0; i < blocksInsideFrame.length; i++) {
const element = blocksInsideFrame[i];
await _drawTopLevelBlock(element, true);
@@ -645,7 +645,7 @@ export class EdgelessClipboardController extends PageClipboard {
);
});
} else {
// oxlint-disable-next-line @typescript-eslint/prefer-for-of
// oxlint-disable-next-line typescript/prefer-for-of
for (let index = 0; index < content.length; index++) {
const blockSnapshot = content[index];
if (blockSnapshot.flavour === 'affine:note') {
@@ -99,24 +99,30 @@ export class SurfaceRefPlaceHolder extends SignalWatcher(
'not-found': modelNotFound,
})}
>
${modelNotFound
? html`<div class="surface-ref-not-found-background">
${notFoundBackground}
</div>`
: nothing}
${
modelNotFound
? html`<div class="surface-ref-not-found-background">
${notFoundBackground}
</div>`
: nothing
}
<div class="surface-ref-placeholder-heading">
${modelNotFound ? DeleteIcon() : matchedType.icon}
<span class="surface-ref-title">
${modelNotFound
? `This ${matchedType.name} not available`
: `${title}`}
${
modelNotFound
? `This ${matchedType.name} not available`
: `${title}`
}
</span>
</div>
<div class="surface-ref-placeholder-body">
<span class="surface-ref-text">
${modelNotFound
? `The ${matchedType.name.toLowerCase()} is deleted or not in this doc.`
: `The ${matchedType.name.toLowerCase()} is inserted but cannot display in edgeless mode. Switch to page mode to view the block.`}
${
modelNotFound
? `The ${matchedType.name.toLowerCase()} is deleted or not in this doc.`
: `The ${matchedType.name.toLowerCase()} is inserted but cannot display in edgeless mode. Switch to page mode to view the block.`
}
</span>
</div>
</div>
@@ -1,4 +1,4 @@
// oxlint-disable-next-line @typescript-eslint/triple-slash-reference
// oxlint-disable-next-line typescript/triple-slash-reference
/// <reference path="./effects.ts" />
export * from './consts.js';
export { GRID_GAP_MAX, GRID_GAP_MIN } from './consts.js';
@@ -281,7 +281,7 @@ export class DefaultTool extends BaseTool {
}
}
// oxlint-disable-next-line @typescript-eslint/no-misused-promises
// oxlint-disable-next-line typescript/no-misused-promises
override async dragStart(e: PointerEventState) {
const { preventDefaultState, handledByView } =
this.interactivity?.dispatchEvent('dragstart', e) ?? {};
@@ -153,7 +153,7 @@ export class AStarRunner {
}
const neighbors = this._neighbors(current);
// oxlint-disable-next-line @typescript-eslint/prefer-for-of
// oxlint-disable-next-line typescript/prefer-for-of
for (let i = 0; i < neighbors.length; i++) {
const next = neighbors[i];
const curCosts = this._costSoFar.get(current);
@@ -268,12 +268,14 @@ export class TableBlockComponent extends CaptionedBlockComponent<TableBlockModel
}
)}
</tbody>
${IS_MOBILE || this.dataManager.readonly$.value
? nothing
: html`<affine-table-add-button
style="display: contents;"
.dataManager=${this.dataManager}
></affine-table-add-button>`}
${
IS_MOBILE || this.dataManager.readonly$.value
? nothing
: html`<affine-table-add-button
style="display: contents;"
.dataManager=${this.dataManager}
></affine-table-add-button>`
}
${html`<affine-table-selection-layer
style="display: contents;"
.selectionController=${this.selectionController}
@@ -138,9 +138,9 @@ export class TableCell extends SignalWatcher(
].map(item =>
menu.action({
prefix: html`<div
style="color: ${item.color ??
cssVarV2.layer.background
.primary};display: flex;align-items: center;justify-content: center;"
style="color: ${
item.color ?? cssVarV2.layer.background.primary
};display: flex;align-items: center;justify-content: center;"
>
${TextBackgroundDuotoneIcon}
</div>`,
@@ -264,9 +264,9 @@ export class TableCell extends SignalWatcher(
].map(item =>
menu.action({
prefix: html`<div
style="color: ${item.color ??
cssVarV2.layer.background
.primary};display: flex;align-items: center;justify-content: center;"
style="color: ${
item.color ?? cssVarV2.layer.background.primary
};display: flex;align-items: center;justify-content: center;"
>
${TextBackgroundDuotoneIcon}
</div>`,
@@ -376,9 +376,9 @@ export class TableCell extends SignalWatcher(
items: [{ name: 'Default', color: undefined }, ...colorList].map(item =>
menu.action({
prefix: html`<div
style="color: ${item.color ??
cssVarV2.layer.background
.primary};display: flex;align-items: center;justify-content: center;"
style="color: ${
item.color ?? cssVarV2.layer.background.primary
};display: flex;align-items: center;justify-content: center;"
>
${TextBackgroundDuotoneIcon}
</div>`,
@@ -418,7 +418,7 @@ export class TableCell extends SignalWatcher(
name: 'Paste',
prefix: PasteIcon(),
select: () => {
// oxlint-disable-next-line @typescript-eslint/no-floating-promises
// oxlint-disable-next-line typescript/no-floating-promises
navigator.clipboard.readText().then(text => {
this.selectionController.doPaste(text, selected);
});
@@ -501,12 +501,16 @@ export class TableCell extends SignalWatcher(
return nothing;
}
return html`
${this.rowIndex === 0
? this.renderColumnOptions(this.column, this.columnIndex)
: nothing}
${this.columnIndex === 0
? this.renderRowOptions(this.row, this.rowIndex)
: nothing}
${
this.rowIndex === 0
? this.renderColumnOptions(this.column, this.columnIndex)
: nothing
}
${
this.columnIndex === 0
? this.renderRowOptions(this.row, this.rowIndex)
: nothing
}
`;
}
@@ -53,19 +53,25 @@ export class CaptionedBlockComponent<
})}
>
${content}
${this.useCaptionEditor
? html`<block-caption-editor
${ref(this._captionEditorRef)}
></block-caption-editor>`
: nothing}
${this.selectedStyle === SelectedStyle.Background
? html`<affine-block-selection
.selected=${watch(this.selected$)}
></affine-block-selection>`
: null}
${this.useZeroWidth && !this.store.readonly
? html`<block-zero-width .block=${this}></block-zero-width>`
: nothing}
${
this.useCaptionEditor
? html`<block-caption-editor
${ref(this._captionEditorRef)}
></block-caption-editor>`
: nothing
}
${
this.selectedStyle === SelectedStyle.Background
? html`<affine-block-selection
.selected=${watch(this.selected$)}
></affine-block-selection>`
: null
}
${
this.useZeroWidth && !this.store.readonly
? html`<block-zero-width .block=${this}></block-zero-width>`
: nothing
}
</div>`;
}
@@ -126,19 +126,23 @@ export class CitationCard extends SignalWatcher(WithDisposable(LitElement)) {
@dblclick=${this.onDoubleClickCallback}
>
<div class="citation-header">
${this.icon
? html`<div class="citation-icon">
${this._IconTemplate(this.icon)}
</div>`
: nothing}
${
this.icon
? html`<div class="citation-icon">
${this._IconTemplate(this.icon)}
</div>`
: nothing
}
<div class="citation-title">${this.citationTitle}</div>
<div class=${citationIdentifierClasses}>
${this.citationIdentifier}
</div>
</div>
${this.citationContent
? html`<div class="citation-content">${this.citationContent}</div>`
: nothing}
${
this.citationContent
? html`<div class="citation-content">${this.citationContent}</div>`
: nothing
}
</div>
`;
}
@@ -250,9 +250,11 @@ export const menuButtonItems = {
}
const data: MenuButtonData = {
content: () => html`
${config.checked.value
? CheckBoxCheckSolidIcon({ style: `color:#1E96EB` })
: CheckBoxUnIcon()}
${
config.checked.value
? CheckBoxCheckSolidIcon({ style: `color:#1E96EB` })
: CheckBoxUnIcon()
}
<div class="affine-menu-action-text">
${config.label?.() ?? config.name}
</div>
@@ -24,11 +24,13 @@ export const menuGroupItems = {
${items}
</div>`;
}
const result: TemplateResult = html` ${index === 0
? ''
: html` <div
style="height: 0.5px;background-color: var(--affine-divider-color);margin: 4px 0"
></div>`}
const result: TemplateResult = html` ${
index === 0
? ''
: html` <div
style="height: 0.5px;background-color: var(--affine-divider-color);margin: 4px 0"
></div>`
}
<div style="display: flex;flex-direction: column;gap:4px">${items}</div>`;
return result;
},
@@ -165,9 +165,11 @@ export class MenuComponent
return html`
${this.renderTitle()} ${this.renderSearch()}
<div class="affine-menu-body">
${result.length === 0 && this.menu.enableSearch
? html` <div class="no-results">No Results</div>`
: ''}
${
result.length === 0 && this.menu.enableSearch
? html` <div class="no-results">No Results</div>`
: ''
}
${result}
</div>
`;
@@ -213,35 +215,39 @@ export class MenuComponent
style="display:flex;align-items:center;gap: 4px;padding:3px 4px 3px 2px"
@mouseenter="${() => this.menu.closeSubMenu()}"
>
${title.onBack
? html` <div
@click="${() => {
const result = title.onBack?.(this.menu);
if (result !== false) {
this.menu.close();
}
}}"
class="dv-icon-20 dv-hover dv-pd-2 dv-round-4"
style="display:flex;"
>
${ArrowLeftBigIcon()}
</div>`
: nothing}
${
title.onBack
? html` <div
@click="${() => {
const result = title.onBack?.(this.menu);
if (result !== false) {
this.menu.close();
}
}}"
class="dv-icon-20 dv-hover dv-pd-2 dv-round-4"
style="display:flex;"
>
${ArrowLeftBigIcon()}
</div>`
: nothing
}
<div
style="flex:1;font-weight:500;font-size: 14px;line-height: 22px;color: var(--affine-text-primary-color)"
>
${title.text}
</div>
${title.postfix?.()}
${title.onClose
? html` <div
@click="${title.onClose}"
class="dv-icon-20 dv-hover dv-pd-2 dv-round-4"
style="display:flex;"
>
${CloseIcon()}
</div>`
: nothing}
${
title.onClose
? html` <div
@click="${title.onClose}"
class="dv-icon-20 dv-hover dv-pd-2 dv-round-4"
style="display:flex;"
>
${CloseIcon()}
</div>`
: nothing
}
</div>
`;
}
@@ -323,21 +329,23 @@ export class MobileMenuComponent
@mouseenter="${() => this.menu.closeSubMenu()}"
>
<div style="width: 50px;flex-shrink: 0;margin-left: 10px;">
${title?.onBack
? html` <div
@click="${() => {
title.onBack?.(this.menu);
this.menu.close();
}}"
style="
${
title?.onBack
? html` <div
@click="${() => {
title.onBack?.(this.menu);
this.menu.close();
}}"
style="
display:flex;
font-size: 24px;
align-items:center;
"
>
${ArrowLeftSmallIcon()}
</div>`
: nothing}
>
${ArrowLeftSmallIcon()}
</div>`
: nothing
}
</div>
<div
style="
@@ -149,7 +149,7 @@ export class Menu {
renderItems(items: MenuConfig[]) {
const result = [];
// oxlint-disable-next-line @typescript-eslint/prefer-for-of
// oxlint-disable-next-line typescript/prefer-for-of
for (let i = 0; i < items.length; i++) {
const item = items[i];
const template = item(this, result.length);
@@ -178,18 +178,20 @@ export class DatePicker extends WithDisposable(LitElement) {
</div>`
)}
</div>
${this.onClear
? html`<div class="date-picker-footer">
<button
tabindex="0"
aria-label="clear"
class="footer-button interactive"
@click=${() => this.onClear?.()}
>
Clear
</button>
</div>`
: nothing}`;
${
this.onClear
? html`<div class="date-picker-footer">
<button
tabindex="0"
aria-label="clear"
class="footer-button interactive"
@click=${() => this.onClear?.()}
>
Clear
</button>
</div>`
: nothing
}`;
}
/** Week header */
@@ -40,9 +40,8 @@ export const LoadingIcon = ({
stroke="${strokeColor}"
stroke-width="4"
stroke-linecap="round"
stroke-dasharray="${2 * Math.PI * 8 * progress} ${2 *
Math.PI *
8 *
(1 - progress)}"
stroke-dasharray="${2 * Math.PI * 8 * progress} ${
2 * Math.PI * 8 * (1 - progress)
}"
/>
</svg>`;
@@ -40,7 +40,7 @@ export interface PeekViewService {
* @returns A promise that resolves when the peek view is closed.
*/
peek(
// oxlint-disable-next-line @typescript-eslint/unified-signatures
// oxlint-disable-next-line typescript/unified-signatures
element: { target: HTMLElement; template?: TemplateResult },
options?: PeekOptions
): Promise<void>;
@@ -161,8 +161,9 @@ export class SizeDropdownMenu extends SignalWatcher(
.labelHeight="${'20px'}"
.iconContainerWidth="${icon ? 'unset' : '65px'}"
>
${icon ??
html`<span class="label">${format?.(size) ?? size}</span>`}
${
icon ?? html`<span class="label">${format?.(size) ?? size}</span>`
}
${EditorChevronDown}
</editor-icon-button>
`}
@@ -151,9 +151,11 @@ export class Slider extends WithDisposable(LitElement) {
<div class="drag-handle"></div>
<div class="bottom-line"></div>
<div class="slider-selected-overlay"></div>
${this.tooltip
? html`<affine-tooltip .offset=${8}>${this.tooltip}</affine-tooltip>`
: nothing}
${
this.tooltip
? html`<affine-tooltip .offset=${8}>${this.tooltip}</affine-tooltip>`
: nothing
}
</div>`;
}
}
@@ -83,9 +83,11 @@ export function renderActions(
?disabled=${item.disabled}
@click=${item.action ? item.action : () => action?.(item)}
>
${item.icon}${item.label
? html`<span class="label">${item.label}</span>`
: nothing}
${item.icon}${
item.label
? html`<span class="label">${item.label}</span>`
: nothing
}
</editor-menu-action>
`
)
@@ -237,13 +237,15 @@ export class Tooltip extends LitElement {
${unsafeCSS(this.style.cssText)}
}
${this.allowInteractive
? css``
: css`
:host {
pointer-events: none;
}
`}
${
this.allowInteractive
? css``
: css`
:host {
pointer-events: none;
}
`
}
${this.tooltipStyle}
`;
@@ -29,9 +29,11 @@ export const typeConfig = (property: Property) => {
style="color: var(--affine-text-secondary-color);gap:4px;font-size: 14px;"
>
${renderUniLit(property.icon)}
${property.view.propertyMetas$.value.find(
v => v.type === property.type$.value
)?.config.name}
${
property.view.propertyMetas$.value.find(
v => v.type === property.type$.value
)?.config.name
}
</div>`,
options: {
title: {
@@ -361,11 +361,13 @@ export class MultiTagSelect extends SignalWatcher(
});
return html` <div class="${tagContainerStyle}" style=${style}>
<div data-testid="tag-name" class="${tagTextStyle}">${name}</div>
${onDelete
? html` <div class="${tagDeleteIconStyle}" @click="${onDelete}">
${CloseIcon()}
</div>`
: nothing}
${
onDelete
? html` <div class="${tagDeleteIconStyle}" @click="${onDelete}">
${CloseIcon()}
</div>`
: nothing
}
</div>`;
}
@@ -402,27 +404,31 @@ export class MultiTagSelect extends SignalWatcher(
@click="${select.select}"
>
<div class="${selectOptionContentStyle}">
${select.isCreate
? html` <div class="${selectOptionNewIconStyle}">
Create
</div>`
: html`
<div
${dragHandler(select.id)}
class="${selectOptionDragHandlerStyle}"
></div>
`}
${
select.isCreate
? html` <div class="${selectOptionNewIconStyle}">
Create
</div>`
: html`
<div
${dragHandler(select.id)}
class="${selectOptionDragHandlerStyle}"
></div>
`
}
${this.renderTag(select.value, select.color)}
</div>
${!select.isCreate
? html` <div
class="${selectOptionIconStyle}"
@click="${clickOption}"
data-testid="option-more"
>
${MoreHorizontalIcon()}
</div>`
: null}
${
!select.isCreate
? html` <div
class="${selectOptionIconStyle}"
@click="${clickOption}"
data-testid="option-more"
>
${MoreHorizontalIcon()}
</div>`
: null
}
</div>
`;
}
@@ -586,9 +592,13 @@ const popMobileTagSelect = (target: PopupTarget, ops: TagSelectOptions) => {
});
return html`
<div style="display: flex; align-items:center;">
${option.isCreate
? html` <div style="margin-right: 8px;">Create</div>`
: ''}
${
option.isCreate
? html` <div style="margin-right: 8px;">
Create
</div>`
: ''
}
<div class="${tagContainerStyle}" style=${style}>
<div class="${tagTextStyle}">${option.value}</div>
</div>
@@ -256,15 +256,17 @@ export class RecordDetail extends SignalWatcher(
);
}
)}
${!this.readonly
? html` <div
class="add-property"
@click="${this._clickAddProperty}"
>
<div class="icon">${PlusIcon()}</div>
Add Property
</div>`
: nothing}
${
!this.readonly
? html` <div
class="add-property"
@click="${this._clickAddProperty}"
>
<div class="icon">${PlusIcon()}</div>
Add Property
</div>`
: nothing
}
</div>
${keyed(this.rowId, this.renderNote())}
</div>
@@ -96,16 +96,18 @@ const GroupTitleMobile = (
${icon} ${renderUniLit(groupData.view, props)} ${columnName}
${GroupHeaderCount(groupData)}
</div>
${ops.readonly
? nothing
: html` <div class="group-header-ops">
<div @click="${ops.clickAdd}" class="group-header-op add-card">
${PlusIcon()}
</div>
<div @click="${ops.clickOps}" class="group-header-op">
${MoreHorizontalIcon()}
</div>
</div>`}
${
ops.readonly
? nothing
: html` <div class="group-header-ops">
<div @click="${ops.clickAdd}" class="group-header-op add-card">
${PlusIcon()}
</div>
<div @click="${ops.clickOps}" class="group-header-op">
${MoreHorizontalIcon()}
</div>
</div>`
}
`;
};
@@ -211,15 +213,17 @@ export const GroupTitle = (
${icon} ${renderUniLit(groupData.view, props)} ${columnName}
${GroupHeaderCount(groupData)}
</div>
${ops.readonly
? nothing
: html` <div class="group-header-ops">
<div @click="${ops.clickAdd}" class="group-header-op add-card">
${PlusIcon()}
</div>
<div @click="${ops.clickOps}" class="group-header-op">
${MoreHorizontalIcon()}
</div>
</div>`}
${
ops.readonly
? nothing
: html` <div class="group-header-ops">
<div @click="${ops.clickAdd}" class="group-header-op add-card">
${PlusIcon()}
</div>
<div @click="${ops.clickOps}" class="group-header-op">
${MoreHorizontalIcon()}
</div>
</div>`
}
`;
};
@@ -25,9 +25,11 @@ export class BooleanGroupView extends BaseGroup<boolean, NonNullable<unknown>> {
}
return html` <div class="data-view-group-title-boolean-view">
${this.value
? CheckBoxCheckSolidIcon({ style: `color:#1E96EB` })
: CheckBoxUnIcon()}
${
this.value
? CheckBoxCheckSolidIcon({ style: `color:#1E96EB` })
: CheckBoxUnIcon()
}
</div>`;
}
}
@@ -224,9 +224,9 @@ export class GroupSetting extends SignalWatcher(
<div
${sortable(g.key)}
${dragHandler(g.key)}
class="dv-hover dv-round-4 group-item ${g.hide$.value
? 'group-hidden'
: ''}"
class="dv-hover dv-round-4 group-item ${
g.hide$.value ? 'group-hidden' : ''
}"
>
<div class="group-item-drag-bar"></div>
<div
@@ -376,27 +376,28 @@ export const buildGroupSettingItems = (
['Month', 'date-month'],
['Year', 'date-year'],
] as [string, string][]
).map(
([label, key]): MenuConfig =>
menu.action({
name: label,
label: () => {
const isSelected =
group.groupInfo$.value?.config.name === key;
return html`<span
style="font-size:14px;color:${isSelected
).map(([label, key]): MenuConfig =>
menu.action({
name: label,
label: () => {
const isSelected =
group.groupInfo$.value?.config.name === key;
return html`<span
style="font-size:14px;color:${
isSelected
? 'var(--affine-text-emphasis-color)'
: 'var(--affine-text-secondary-color)'}"
>${label}</span
>`;
},
isSelected:
group.groupInfo$.value?.config.name === key,
select: () => {
group.changeGroupMode(key);
return false;
},
})
: 'var(--affine-text-secondary-color)'
}"
>${label}</span
>`;
},
isSelected:
group.groupInfo$.value?.config.name === key,
select: () => {
group.changeGroupMode(key);
return false;
},
})
)
),
],
@@ -417,10 +418,12 @@ export const buildGroupSettingItems = (
<div
style="display:flex;align-items:center;gap:4px;font-size:14px;line-height:20px;color:var(--affine-text-secondary-color);margin-left:8px;"
>
${group.groupInfo$.value?.config.name ===
'date-week-mon'
? 'Monday'
: 'Sunday'}
${
group.groupInfo$.value?.config.name ===
'date-week-mon'
? 'Monday'
: 'Sunday'
}
</div>
`,
options: {
@@ -439,9 +442,11 @@ export const buildGroupSettingItems = (
group.groupInfo$.value?.config.name ===
key;
return html`<span
style="font-size:14px;color:${isSelected
? 'var(--affine-text-emphasis-color)'
: 'var(--affine-text-secondary-color)'}"
style="font-size:14px;color:${
isSelected
? 'var(--affine-text-emphasis-color)'
: 'var(--affine-text-secondary-color)'
}"
>${label}</span
>`;
},
@@ -485,9 +490,11 @@ export const buildGroupSettingItems = (
label: () => {
const isSelected = group.sortAsc$.value;
return html`<span
style="font-size:14px;color:${isSelected
? 'var(--affine-text-emphasis-color)'
: 'var(--affine-text-secondary-color)'}"
style="font-size:14px;color:${
isSelected
? 'var(--affine-text-emphasis-color)'
: 'var(--affine-text-secondary-color)'
}"
>Oldest first</span
>`;
},
@@ -502,9 +509,11 @@ export const buildGroupSettingItems = (
label: () => {
const isSelected = !group.sortAsc$.value;
return html`<span
style="font-size:14px;color:${isSelected
? 'var(--affine-text-emphasis-color)'
: 'var(--affine-text-secondary-color)'}"
style="font-size:14px;color:${
isSelected
? 'var(--affine-text-emphasis-color)'
: 'var(--affine-text-secondary-color)'
}"
>Newest first</span
>`;
},
@@ -131,15 +131,17 @@ export class ProgressCell extends BaseCellRenderer<number, number> {
style=${bgStyles}
>
<div class="${progressFgStyle}" style=${fgStyles}></div>
${this.isEditing$.value
? html` <div
class="${progressDragHandleStyle}"
data-testid="progress-drag-handle"
style=${styleMap({
left: `calc(${progress}% - 3px)`,
})}
></div>`
: ''}
${
this.isEditing$.value
? html` <div
class="${progressDragHandleStyle}"
data-testid="progress-drag-handle"
style=${styleMap({
left: `calc(${progress}% - 3px)`,
})}
></div>`
: ''
}
</div>
</div>
<span class="${progressNumberStyle}" data-testid="progress"
@@ -65,20 +65,28 @@ export const openCalendarEntry = (
<span class="calendar-event-popover-icon">${DateTimeIcon()}</span>
<span>${formatEntryTime(entry)}</span>
</div>
${entry.location
? html`<div class="calendar-event-popover-row">
<span class="calendar-event-popover-icon">${PinIcon()}</span>
<span>${entry.location}</span>
</div>`
: ''}
${entry.description
? html`<div class="calendar-event-popover-row">
<span class="calendar-event-popover-icon">${TextIcon()}</span>
<span class="calendar-event-popover-description"
>${entry.description}</span
>
</div>`
: ''}
${
entry.location
? html`<div class="calendar-event-popover-row">
<span class="calendar-event-popover-icon"
>${PinIcon()}</span
>
<span>${entry.location}</span>
</div>`
: ''
}
${
entry.description
? html`<div class="calendar-event-popover-row">
<span class="calendar-event-popover-icon"
>${TextIcon()}</span
>
<span class="calendar-event-popover-description"
>${entry.description}</span
>
</div>`
: ''
}
</div>
`,
],
@@ -416,10 +416,12 @@ export class CalendarViewUILogic extends DataViewUILogicBase<CalendarSingleView>
postfix: html`<div
style="font-size:14px;color:var(--affine-text-secondary-color);"
>
${this.view.startDateMapping$.value.status === 'ready'
? this.view.propertyGetOrCreate(selectedStart ?? '').name$
.value
: ''}
${
this.view.startDateMapping$.value.status === 'ready'
? this.view.propertyGetOrCreate(selectedStart ?? '').name$
.value
: ''
}
</div>
${ArrowRightSmallIcon()}`,
select: () => {
@@ -448,9 +450,11 @@ export class CalendarViewUILogic extends DataViewUILogicBase<CalendarSingleView>
postfix: html`<div
style="font-size:14px;color:var(--affine-text-secondary-color);"
>
${selectedEnd
? this.view.propertyGetOrCreate(selectedEnd).name$.value
: 'None'}
${
selectedEnd
? this.view.propertyGetOrCreate(selectedEnd).name$.value
: 'None'
}
</div>
${ArrowRightSmallIcon()}`,
select: () => {
@@ -726,10 +730,9 @@ export class CalendarViewUI extends DataViewUIBase<CalendarViewUILogic> {
return html`
<div
${ref(element => this.logic.bindEntryDraggable(dndKey, entry, element))}
class="calendar-entry ${entry.kind} ${segmentClass} ${this.logic
.selectedEntryId === entry.id
? 'selected'
: ''}"
class="calendar-entry ${entry.kind} ${segmentClass} ${
this.logic.selectedEntryId === entry.id ? 'selected' : ''
}"
role="button"
tabindex="0"
aria-label=${entry.title || 'Untitled'}
@@ -744,31 +747,37 @@ export class CalendarViewUI extends DataViewUIBase<CalendarViewUILogic> {
this.logic.handleEntryKeydown(entry, event);
}}
>
${showLeftHandle
? html`<span
class="calendar-resize-handle left"
@pointerdown=${(event: PointerEvent) =>
this.logic.startResize(entry, 'start', event)}
></span>`
: nothing}
${
showLeftHandle
? html`<span
class="calendar-resize-handle left"
@pointerdown=${(event: PointerEvent) =>
this.logic.startResize(entry, 'start', event)}
></span>`
: nothing
}
${this.renderEntryTitle(entry)}
${entry.kind === 'row' && entry.cardProperties.length
? html`<span class="calendar-entry-properties">
${entry.cardProperties.map(
property =>
html`<span class="calendar-entry-property"
>${property.value}</span
>`
)}
</span>`
: nothing}
${showRightHandle
? html`<span
class="calendar-resize-handle right"
@pointerdown=${(event: PointerEvent) =>
this.logic.startResize(entry, 'end', event)}
></span>`
: nothing}
${
entry.kind === 'row' && entry.cardProperties.length
? html`<span class="calendar-entry-properties">
${entry.cardProperties.map(
property =>
html`<span class="calendar-entry-property"
>${property.value}</span
>`
)}
</span>`
: nothing
}
${
showRightHandle
? html`<span
class="calendar-resize-handle right"
@pointerdown=${(event: PointerEvent) =>
this.logic.startResize(entry, 'end', event)}
></span>`
: nothing
}
</div>
`;
}
@@ -785,16 +794,18 @@ export class CalendarViewUI extends DataViewUIBase<CalendarViewUILogic> {
${entry.titleSegments.map(
segment =>
html`<span
class="calendar-entry-title-segment ${segment.linkedDoc
? 'linked-doc-segment'
: ''}"
class="calendar-entry-title-segment ${
segment.linkedDoc ? 'linked-doc-segment' : ''
}"
>
${segment.linkedDoc ? LinkedPageIcon() : nothing}
${segment.text
? html`<span class="calendar-entry-title-text"
>${segment.text}</span
>`
: nothing}
${
segment.text
? html`<span class="calendar-entry-title-text"
>${segment.text}</span
>`
: nothing
}
</span>`
)}
</span>`;
@@ -895,11 +906,12 @@ export class CalendarViewUI extends DataViewUIBase<CalendarViewUILogic> {
if (!preview) return nothing;
return html`<div
class="calendar-entry-preview ${preview.continuesLeft
? 'continues-left'
: ''} ${preview.continuesRight ? 'continues-right' : ''}"
style="grid-column:${preview.sIdx +
1} / span ${preview.span};grid-row:${preview.slot + 1};"
class="calendar-entry-preview ${
preview.continuesLeft ? 'continues-left' : ''
} ${preview.continuesRight ? 'continues-right' : ''}"
style="grid-column:${
preview.sIdx + 1
} / span ${preview.span};grid-row:${preview.slot + 1};"
>
${preview.title}
</div>`;
@@ -919,17 +931,19 @@ export class CalendarViewUI extends DataViewUIBase<CalendarViewUILogic> {
</span>
</div>
<div class="calendar-empty-month-hint-actions">
${this.logic.view.readonly$.value
? nothing
: html`<button
class="calendar-empty-month-hint-action"
@click=${() =>
this.logic.createRowOnDate(
getDefaultCreateDate(this.logic.currentMonth)
)}
>
${PlusIcon()}<span>New row</span>
</button>`}
${
this.logic.view.readonly$.value
? nothing
: html`<button
class="calendar-empty-month-hint-action"
@click=${() =>
this.logic.createRowOnDate(
getDefaultCreateDate(this.logic.currentMonth)
)}
>
${PlusIcon()}<span>New row</span>
</button>`
}
<button
class="calendar-empty-month-hint-close"
aria-label="Dismiss"
@@ -963,14 +977,16 @@ export class CalendarViewUI extends DataViewUIBase<CalendarViewUILogic> {
${monthFormatter.format(new Date(this.logic.currentMonth))}
</div>
<div class="calendar-nav">
${this.logic.isCurrentMonth()
? nothing
: html`<button
class="calendar-today-button"
@click=${() => this.logic.goToday()}
>
<span>Today</span>
</button>`}
${
this.logic.isCurrentMonth()
? nothing
: html`<button
class="calendar-today-button"
@click=${() => this.logic.goToday()}
>
<span>Today</span>
</button>`
}
<button
class="calendar-icon-button"
aria-label="Previous month"
@@ -1022,13 +1038,13 @@ export class CalendarViewUI extends DataViewUIBase<CalendarViewUILogic> {
return html`
<div
data-date=${day.date}
class="calendar-day ${day.inMonth
? ''
: 'is-outside'} ${day.date === today
? 'is-today'
: ''} ${this.logic.isDayInPreview(day.date)
? 'is-drop-target'
: ''}"
class="calendar-day ${
day.inMonth ? '' : 'is-outside'
} ${day.date === today ? 'is-today' : ''} ${
this.logic.isDayInPreview(day.date)
? 'is-drop-target'
: ''
}"
style="--calendar-segment-slots:${getCalendarDaySegmentSlots(
day,
movingEntryId
@@ -1044,17 +1060,19 @@ export class CalendarViewUI extends DataViewUIBase<CalendarViewUILogic> {
${this.renderDayPreview(day.date)}
${this.renderPreviewSpacer(day, preview, dayIndex)}
</div>
${canReserveNewRow
? html`<button
class="calendar-new-row"
aria-label="+ New row"
?disabled=${this.logic.isInteracting}
@click=${() =>
this.logic.createRowOnDate(day.date)}
>
${PlusIcon()}<span>New row</span>
</button>`
: nothing}
${
canReserveNewRow
? html`<button
class="calendar-new-row"
aria-label="+ New row"
?disabled=${this.logic.isInteracting}
@click=${() =>
this.logic.createRowOnDate(day.date)}
>
${PlusIcon()}<span>New row</span>
</button>`
: nothing
}
</div>
`;
}
@@ -1083,25 +1101,31 @@ export class CalendarViewUI extends DataViewUIBase<CalendarViewUILogic> {
override render(): TemplateResult {
const setup = this.logic.view.dateMapping$.value.status === 'setup';
return html`
${this.logic.headerWidget
? renderUniLit(this.logic.headerWidget, {
dataViewLogic: this.logic,
})
: nothing}
${
this.logic.headerWidget
? renderUniLit(this.logic.headerWidget, {
dataViewLogic: this.logic,
})
: nothing
}
<div class=${setup ? 'calendar-setup-wrap' : ''}>
<div class="calendar-scroll" @wheel="${this.logic.onWheel}">
${this.renderCalendar(setup)}
</div>
${setup
? html`<div class="calendar-setup">
<button
@click=${(event: MouseEvent) =>
this.logic.openSetupMenu(event.currentTarget as HTMLElement)}
>
${TodayIcon()}<span>Select or create date property</span>
</button>
</div>`
: nothing}
${
setup
? html`<div class="calendar-setup">
<button
@click=${(event: MouseEvent) =>
this.logic.openSetupMenu(
event.currentTarget as HTMLElement
)}
>
${TodayIcon()}<span>Select or create date property</span>
</button>
</div>`
: nothing
}
</div>
`;
}
@@ -121,16 +121,18 @@ export class MobileKanbanGroup extends SignalWatcher(
`;
}
)}
${this.view.readonly$.value
? nothing
: html` <div class="mobile-add-card" @click="${this.clickAddCard}">
<div
style="margin-right: 4px;width: 16px;height: 16px;display:flex;align-items:center;"
>
${AddCursorIcon()}
</div>
Add
</div>`}
${
this.view.readonly$.value
? nothing
: html` <div class="mobile-add-card" @click="${this.clickAddCard}">
<div
style="margin-right: 4px;width: 16px;height: 16px;display:flex;align-items:center;"
>
${AddCursorIcon()}
</div>
Add
</div>`
}
</div>
`;
}
@@ -179,16 +179,18 @@ export class KanbanGroup extends SignalWatcher(
`;
}
)}
${this.view.readonly$.value
? nothing
: html`<div class="add-card" @click="${this.clickAddCard}">
<div
style="margin-right: 4px;width: 16px;height: 16px;display:flex;align-items:center;"
>
${AddCursorIcon()}
</div>
Add
</div>`}
${
this.view.readonly$.value
? nothing
: html`<div class="add-card" @click="${this.clickAddCard}">
<div
style="margin-right: 4px;width: 16px;height: 16px;display:flex;align-items:center;"
>
${AddCursorIcon()}
</div>
Add
</div>`
}
</div>
`;
}
@@ -148,9 +148,9 @@ export class MobileTableGroup extends SignalWatcher(
class=${`group-toggle-btn ${this.collapsed$.value ? '' : 'expanded'}`}
role="button"
aria-expanded=${this.collapsed$.value ? 'false' : 'true'}
aria-label=${this.collapsed$.value
? 'Expand group'
: 'Collapse group'}
aria-label=${
this.collapsed$.value ? 'Expand group' : 'Collapse group'
}
tabindex="0"
@click=${this._toggleCollapse}
@keydown=${(e: KeyboardEvent) => {
@@ -160,9 +160,11 @@ export class MobileTableGroup extends SignalWatcher(
}
}}
>
${this.collapsed$.value
? ToggleRightIcon({ width: '16px', height: '16px' })
: ToggleDownIcon({ width: '16px', height: '16px' })}
${
this.collapsed$.value
? ToggleRightIcon({ width: '16px', height: '16px' })
: ToggleDownIcon({ width: '16px', height: '16px' })
}
</div>
${GroupTitle(this.group, {
@@ -198,20 +200,22 @@ export class MobileTableGroup extends SignalWatcher(
}
)}
</div>
${this.view.readonly$.value
? null
: html` <div
class="data-view-table-group-add-row dv-hover"
@click="${this.clickAddRow}"
>
<div
class="data-view-table-group-add-row-button dv-icon-16"
data-test-id="affine-database-add-row-button"
role="button"
${
this.view.readonly$.value
? null
: html` <div
class="data-view-table-group-add-row dv-hover"
@click="${this.clickAddRow}"
>
${PlusIcon()}<span style="font-size: 12px">New Record</span>
</div>
</div>`}
<div
class="data-view-table-group-add-row-button dv-icon-16"
data-test-id="affine-database-add-row-button"
role="button"
>
${PlusIcon()}<span style="font-size: 12px">New Record</span>
</div>
</div>`
}
`;
}
@@ -109,19 +109,23 @@ export class MobileTableRow extends SignalWatcher(
</mobile-table-cell>
<div class="${cellDivider}"></div>
</div>
${!column.readonly$.value &&
column.view.mainProperties$.value.titleColumn === column.id
? html` <div class="mobile-row-ops">
<div class="mobile-row-op" @click="${clickDetail}">
${CenterPeekIcon()}
</div>
${!view.readonly$.value
? html` <div class="mobile-row-op" @click="${openMenu}">
${MoreHorizontalIcon()}
</div>`
: nothing}
</div>`
: nothing}
${
!column.readonly$.value &&
column.view.mainProperties$.value.titleColumn === column.id
? html` <div class="mobile-row-ops">
<div class="mobile-row-op" @click="${clickDetail}">
${CenterPeekIcon()}
</div>
${
!view.readonly$.value
? html` <div class="mobile-row-op" @click="${openMenu}">
${MoreHorizontalIcon()}
</div>`
: nothing
}
</div>`
: nothing
}
`;
}
)}
@@ -74,24 +74,26 @@ export class TableGroupFooter extends WithDisposable(ShadowlessElement) {
override render() {
return html`
${this.tableViewManager.readonly$.value
? null
: html`
<div
class="${styles.addRowWrapper} dv-hover"
@click="${this.clickAddRow}"
>
${
this.tableViewManager.readonly$.value
? null
: html`
<div
class="${styles.addRowButton} dv-icon-16"
data-test-id="affine-database-add-row-button"
role="button"
class="${styles.addRowWrapper} dv-hover"
@click="${this.clickAddRow}"
>
${PlusIcon()}<span class="${styles.addRowText}"
>New Record</span
<div
class="${styles.addRowButton} dv-icon-16"
data-test-id="affine-database-add-row-button"
role="button"
>
${PlusIcon()}<span class="${styles.addRowText}"
>New Record</span
>
</div>
</div>
</div>
`}
`
}
<affine-database-virtual-column-stats
.view="${this.tableViewManager}"
.group="${this.group$.value}"
@@ -225,12 +225,14 @@ export class VirtualDatabaseColumnStatsCell extends SignalWatcher(
class="stats-cell"
>
<div class="content">
${!this.statsResult$.value
? html`Calculate ${ArrowDownSmallIcon()}`
: html`
<span class="label">${this.statsResult$.value.name}</span>
<span class="value">${this.statsResult$.value.value} </span>
`}
${
!this.statsResult$.value
? html`Calculate ${ArrowDownSmallIcon()}`
: html`
<span class="label">${this.statsResult$.value.name}</span>
<span class="value">${this.statsResult$.value.value} </span>
`
}
</div>
</div>`;
}
@@ -64,15 +64,17 @@ export const GroupTitle = (
${icon} ${renderUniLit(view, props)} ${columnName}
${GroupHeaderCount(groupData)}
</div>
${!ops.readonly
? html` <div class="${opsClass}">
<div @click="${ops.clickAdd}" class="${groupHeaderOp}">
${PlusIcon()}
</div>
<div @click="${ops.clickOps}" class="${groupHeaderOp}">
${MoreHorizontalIcon()}
</div>
</div>`
: nothing}
${
!ops.readonly
? html` <div class="${opsClass}">
<div @click="${ops.clickAdd}" class="${groupHeaderOp}">
${PlusIcon()}
</div>
<div @click="${ops.clickOps}" class="${groupHeaderOp}">
${MoreHorizontalIcon()}
</div>
</div>`
: nothing
}
`;
};
@@ -428,14 +428,16 @@ export class DatabaseHeaderColumn extends SignalWatcher(
${draggable(column.id)}
${droppable(column.id)}
>
${this.readonly
? null
: html` <button class="${classes}">
<div class="hover-trigger"></div>
<div class="control-h"></div>
<div class="control-l"></div>
<div class="control-r"></div>
</button>`}
${
this.readonly
? null
: html` <button class="${classes}">
<div class="hover-trigger"></div>
<div class="control-h"></div>
<div class="control-l"></div>
<div class="control-r"></div>
</button>`
}
<div class="affine-database-column-text ${column.type$.value}">
<div
class="affine-database-column-type-icon dv-hover"
@@ -84,9 +84,11 @@ export class TableRowHeader extends SignalWatcher(
return html`
<div @click=${this.selectRow} class="${styles.checkboxWrapper}">
<div class="${classString}">
${this.rowSelected$.value
? CheckBoxCheckSolidIcon({ style: `color:#1E96EB` })
: CheckBoxUnIcon()}
${
this.rowSelected$.value
? CheckBoxCheckSolidIcon({ style: `color:#1E96EB` })
: CheckBoxUnIcon()
}
</div>
</div>
`;
@@ -206,9 +206,9 @@ export class TableGroup extends SignalWatcher(
class=${`group-toggle-btn ${this.collapsed$.value ? '' : 'expanded'}`}
role="button"
aria-expanded=${this.collapsed$.value ? 'false' : 'true'}
aria-label=${this.collapsed$.value
? 'Expand group'
: 'Collapse group'}
aria-label=${
this.collapsed$.value ? 'Expand group' : 'Collapse group'
}
tabindex="0"
@click=${this._toggleCollapse}
@keydown=${(e: KeyboardEvent) => {
@@ -218,9 +218,11 @@ export class TableGroup extends SignalWatcher(
}
}}
>
${this.collapsed$.value
? ToggleRightIcon({ width: '16px', height: '16px' })
: ToggleDownIcon({ width: '16px', height: '16px' })}
${
this.collapsed$.value
? ToggleRightIcon({ width: '16px', height: '16px' })
: ToggleDownIcon({ width: '16px', height: '16px' })
}
</div>
${GroupTitle(this.group, {
@@ -344,20 +346,22 @@ export class TableGroup extends SignalWatcher(
}
)}
</div>
${this.view.readonly$.value
? null
: html` <div
class="data-view-table-group-add-row dv-hover"
@click="${this.clickAddRow}"
>
<div
class="data-view-table-group-add-row-button dv-icon-16"
data-test-id="affine-database-add-row-button"
role="button"
${
this.view.readonly$.value
? null
: html` <div
class="data-view-table-group-add-row dv-hover"
@click="${this.clickAddRow}"
>
${PlusIcon()}<span style="font-size: 12px">New Record</span>
</div>
</div>`}
<div
class="data-view-table-group-add-row-button dv-icon-16"
data-test-id="affine-database-add-row-button"
role="button"
>
${PlusIcon()}<span style="font-size: 12px">New Record</span>
</div>
</div>`
}
<affine-database-column-stats
.tableViewLogic="${this.tableViewLogic}"
.group="${this.group}"
@@ -87,9 +87,11 @@ export class DatabaseColumnHeader extends SignalWatcher(
return html`
${this.renderGroupHeader?.()}
<div class="affine-database-column-header database-row">
${this.readonly
? nothing
: html`<div class="${tableStyle.leftToolBarStyle}"></div>`}
${
this.readonly
? nothing
: html`<div class="${tableStyle.leftToolBarStyle}"></div>`
}
${repeat(
this.tableViewManager.properties$.value,
column => column.id,
@@ -431,14 +431,16 @@ export class DatabaseHeaderColumn extends SignalWatcher(
${draggable(column.id)}
${droppable(column.id)}
>
${this.readonly
? null
: html` <button class="${classes}">
<div class="hover-trigger"></div>
<div class="control-h"></div>
<div class="control-l"></div>
<div class="control-r"></div>
</button>`}
${
this.readonly
? null
: html` <button class="${classes}">
<div class="hover-trigger"></div>
<div class="control-h"></div>
<div class="control-l"></div>
<div class="control-r"></div>
</button>`
}
<div class="affine-database-column-text ${column.type$.value}">
<div
class="affine-database-column-type-icon dv-hover"
@@ -71,9 +71,11 @@ export class RowSelectCheckbox extends SignalWatcher(
});
return html`
<div class="${classString}">
${this.isSelected$.value
? CheckBoxCheckSolidIcon({ style: `color:#1E96EB` })
: CheckBoxUnIcon()}
${
this.isSelected$.value
? CheckBoxCheckSolidIcon({ style: `color:#1E96EB` })
: CheckBoxUnIcon()
}
</div>
`;
}
@@ -177,28 +177,30 @@ export class TableRowView extends SignalWatcher(
protected override render(): unknown {
const view = this.view;
return html`
${view.readonly$.value
? nothing
: html`<div class="data-view-table-left-bar" style="height: 34px">
<div style="display: flex;">
<div
class="data-view-table-view-drag-handler show-on-hover-row row-selected-bg"
@click=${this._clickDragHandler}
>
${
view.readonly$.value
? nothing
: html`<div class="data-view-table-left-bar" style="height: 34px">
<div style="display: flex;">
<div
style="width: 4px;
class="data-view-table-view-drag-handler show-on-hover-row row-selected-bg"
@click=${this._clickDragHandler}
>
<div
style="width: 4px;
border-radius: 2px;
height: 12px;
background-color: var(--affine-placeholder-color);"
></div>
></div>
</div>
<row-select-checkbox
.tableViewLogic="${this.tableViewLogic}"
.rowId="${this.rowId}"
.groupKey="${this.groupKey}"
></row-select-checkbox>
</div>
<row-select-checkbox
.tableViewLogic="${this.tableViewLogic}"
.rowId="${this.rowId}"
.groupKey="${this.groupKey}"
></row-select-checkbox>
</div>
</div>`}
</div>`
}
${repeat(
view.properties$.value,
v => v.id,
@@ -265,19 +267,23 @@ export class TableRowView extends SignalWatcher(
</dv-table-view-cell-container>
<div class="${cellDivider}"></div>
</div>
${!column.readonly$.value &&
column.view.mainProperties$.value.titleColumn === column.id
? html`<div class="row-ops show-on-hover-row">
<div class="row-op" @click="${clickDetail}">
${CenterPeekIcon()}
</div>
${!view.readonly$.value
? html`<div class="row-op" @click="${openMenu}">
${MoreHorizontalIcon()}
</div>`
: nothing}
</div>`
: nothing}
${
!column.readonly$.value &&
column.view.mainProperties$.value.titleColumn === column.id
? html`<div class="row-ops show-on-hover-row">
<div class="row-op" @click="${clickDetail}">
${CenterPeekIcon()}
</div>
${
!view.readonly$.value
? html`<div class="row-op" @click="${openMenu}">
${MoreHorizontalIcon()}
</div>`
: nothing
}
</div>`
: nothing
}
`;
}
)}
@@ -191,11 +191,13 @@ export class TableViewUI extends DataViewUIBase<TableViewUILogic> {
paddingRight: `${vPadding}px`,
});
return html`
${this.logic.headerWidget
? renderUniLit(this.logic.headerWidget, {
dataViewLogic: this.logic,
})
: ''}
${
this.logic.headerWidget
? renderUniLit(this.logic.headerWidget, {
dataViewLogic: this.logic,
})
: ''
}
<div class="${tableWrapperStyle}" style="${wrapperStyle}">
<div
${ref(this.logic.scrollContainer$)}
@@ -207,11 +209,13 @@ export class TableViewUI extends DataViewUIBase<TableViewUILogic> {
class="affine-database-table-container"
style="${containerStyle}"
>
${this.logic.view.groupTrait.allHidden$.value
? html`<div class="${groupsHiddenMessageStyle}">
All groups are hidden
</div>`
: this.renderTable()}
${
this.logic.view.groupTrait.allHidden$.value
? html`<div class="${groupsHiddenMessageStyle}">
All groups are hidden
</div>`
: this.renderTable()
}
</div>
</div>
</div>
@@ -225,12 +225,14 @@ export class DatabaseColumnStatsCell extends SignalWatcher(
class="stats-cell"
>
<div class="content">
${!this.statsResult$.value
? html`Calculate ${ArrowDownSmallIcon()}`
: html`
<span class="label">${this.statsResult$.value.name}</span>
<span class="value">${this.statsResult$.value.value} </span>
`}
${
!this.statsResult$.value
? html`Calculate ${ArrowDownSmallIcon()}`
: html`
<span class="label">${this.statsResult$.value.name}</span>
<span class="value">${this.statsResult$.value.value} </span>
`
}
</div>
</div>`;
}
@@ -374,25 +374,27 @@ export class FilterGroupView extends SignalWatcher(ShadowlessElement) {
<div
style="flex:1;display:flex;align-items:start;justify-content: space-between;gap: 8px;"
>
${filter.type === 'filter'
? html`
<filter-condition-view
.vars="${this.vars}"
.index="${i}"
.value="${this.conditions$}"
.onChange="${this.setConditions}"
></filter-condition-view>
`
: html`
<filter-group-view
class="${groupClassList}"
style="width: 100%;"
.depth="${this.depth + 1}"
.onChange="${(v: Filter) => this._setFilter(i, v)}"
.vars="${this.vars}"
.filterGroup="${computed(() => filter)}"
></filter-group-view>
`}
${
filter.type === 'filter'
? html`
<filter-condition-view
.vars="${this.vars}"
.index="${i}"
.value="${this.conditions$}"
.onChange="${this.setConditions}"
></filter-condition-view>
`
: html`
<filter-group-view
class="${groupClassList}"
style="width: 100%;"
.depth="${this.depth + 1}"
.onChange="${(v: Filter) => this._setFilter(i, v)}"
.vars="${this.vars}"
.filterGroup="${computed(() => filter)}"
></filter-group-view>
`
}
<div class="filter-group-item-ops" @click="${clickOps}">
${MoreHorizontalIcon()}
</div>
@@ -37,13 +37,15 @@ export const widgetQuickSettingBar = defineUniComponent(
>
${barList.map((bar, index) => {
return html`
${index !== 0
? html` <div
style="width: 1px;height:27px;background-color: ${unsafeCSSVarV2(
'layer/insideBorder/border'
)}"
></div>`
: nothing}
${
index !== 0
? html` <div
style="width: 1px;height:27px;background-color: ${unsafeCSSVarV2(
'layer/insideBorder/border'
)}"
></div>`
: nothing
}
${bar}
`;
})}
@@ -36,9 +36,11 @@ export class DataViewHeaderToolsAddRow extends WidgetBase {
class="affine-database-toolbar-item new-record"
.onClick="${this.onAddNewRecord}"
.icon="${PlusIcon()}"
.text="${IS_MOBILE
? html`<span style="font-weight: 500">New</span>`
: html`<span style="font-weight: 500">New Record</span>`}"
.text="${
IS_MOBILE
? html`<span style="font-weight: 500">New</span>`
: html`<span style="font-weight: 500">New Record</span>`
}"
>
</data-view-component-button>`;
}
@@ -440,11 +440,13 @@ export const popViewOptions = (
closeOnSelect: false,
postfix: html`
<div style="font-size: 14px;">
${filterCount === 0
? ''
: filterCount === 1
? '1 active'
: `${filterCount} active`}
${
filterCount === 0
? ''
: filterCount === 1
? '1 active'
: `${filterCount} active`
}
</div>
${ArrowRightSmallIcon()}
`,
@@ -466,11 +468,13 @@ export const popViewOptions = (
closeOnSelect: false,
postfix: html`
<div style="font-size: 14px;">
${sortCount === 0
? ''
: sortCount === 1
? '1 active'
: `${sortCount} active`}
${
sortCount === 0
? ''
: sortCount === 1
? '1 active'
: `${sortCount} active`
}
</div>
${ArrowRightSmallIcon()}
`,
+16 -4
View File
@@ -11,7 +11,10 @@ import { BaseExtensionProvider } from '@blocksuite/affine-ext-loader';
import { z } from 'zod';
// Create a custom provider with options
class MyProvider extends BaseExtensionProvider<'my-scope', { enabled: boolean }> {
class MyProvider extends BaseExtensionProvider<
'my-scope',
{ enabled: boolean }
> {
name = 'MyProvider';
schema = z.object({
@@ -28,7 +31,10 @@ class MyProvider extends BaseExtensionProvider<'my-scope', { enabled: boolean }>
### Store Extensions
```typescript
import { StoreExtensionProvider, StoreExtensionManager } from '@blocksuite/affine-ext-loader';
import {
StoreExtensionProvider,
StoreExtensionManager,
} from '@blocksuite/affine-ext-loader';
import { z } from 'zod';
// Create a store provider with custom options
@@ -39,7 +45,10 @@ class MyStoreProvider extends StoreExtensionProvider<{ cacheSize: number }> {
cacheSize: z.number().min(0),
});
override setup(context: StoreExtensionContext, options?: { cacheSize: number }) {
override setup(
context: StoreExtensionContext,
options?: { cacheSize: number }
) {
super.setup(context, options);
context.register([Ext1, Ext2, Ext3]);
}
@@ -54,7 +63,10 @@ const extensions = manager.get('store');
### View Extensions
```typescript
import { ViewExtensionProvider, ViewExtensionManager } from '@blocksuite/affine-ext-loader';
import {
ViewExtensionProvider,
ViewExtensionManager,
} from '@blocksuite/affine-ext-loader';
import { z } from 'zod';
// Create a view provider with custom options
@@ -134,13 +134,15 @@ export class AdapterPanelBody extends SignalWatcher(LitElement) {
private _renderHtmlPanel() {
return html`
${this.isHtmlPreview
? html`<iframe
class="html-preview-container"
.srcdoc=${this.htmlContent}
sandbox="allow-same-origin"
></iframe>`
: html`<div class="html-panel-content">${this.htmlContent}</div>`}
${
this.isHtmlPreview
? html`<iframe
class="html-preview-container"
.srcdoc=${this.htmlContent}
sandbox="allow-same-origin"
></iframe>`
: html`<div class="html-panel-content">${this.htmlContent}</div>`
}
<div class="html-panel-footer">
<div class="html-toggle-container">
<span
@@ -213,9 +213,9 @@ export class DocTitle extends WithDisposable(ShadowlessElement) {
return html`
<div
class="doc-title-container ${isEmpty
? 'doc-title-container-empty'
: ''}"
class="doc-title-container ${
isEmpty ? 'doc-title-container-empty' : ''
}"
data-block-is-title="true"
>
<rich-text
@@ -268,11 +268,13 @@ export class FramePanelBody extends SignalWatcher(
.std=${this.editorHost.std}
.cardIndex=${cardIndex}
.frameIndex=${frameIndex}
.status=${selectedFrames.has(frame.id)
? this._dragging
? 'placeholder'
: 'selected'
: 'none'}
.status=${
selectedFrames.has(frame.id)
? this._dragging
? 'placeholder'
: 'selected'
: 'none'
}
@select=${this._selectFrame}
@fitview=${this._fitToElement}
@drag=${this._drag}
@@ -281,12 +283,14 @@ export class FramePanelBody extends SignalWatcher(
})}`;
const frameList = html` <div class="frame-list-container">
${this.insertIndex !== undefined
? html`<div
class="insert-indicator"
style=${`transform: translateY(${this._indicatorTranslateY}px)`}
></div>`
: nothing}
${
this.insertIndex !== undefined
? html`<div
class="insert-indicator"
style=${`transform: translateY(${this._indicatorTranslateY}px)`}
></div>`
: nothing
}
${frameCards}
</div>`;
return frameList;
@@ -385,9 +389,11 @@ export class FramePanelBody extends SignalWatcher(
override render() {
this._updateFrameItems();
return html` ${this._frameItems.length
? this._renderFrameList()
: this._renderEmptyContent()}`;
return html` ${
this._frameItems.length
? this._renderFrameList()
: this._renderEmptyContent()
}`;
}
override updated(_changedProperties: PropertyValues) {
@@ -193,24 +193,28 @@ export class FrameCard extends WithDisposable(ShadowlessElement) {
class="frame-card-container ${this.status ?? ''}"
style=${containerStyle}
>
${this.status === 'dragging'
? nothing
: html`<affine-frame-card-title
.cardIndex=${this.cardIndex}
.frame=${this.frame}
></affine-frame-card-title>`}
${
this.status === 'dragging'
? nothing
: html`<affine-frame-card-title
.cardIndex=${this.cardIndex}
.frame=${this.frame}
></affine-frame-card-title>`
}
<div
class="frame-card-body"
@click=${this._dispatchSelectEvent}
@dblclick=${this._dispatchFitViewEvent}
@mousedown=${this._dispatchDragEvent}
>
${this.status === 'dragging' && stackOrder !== 0
? nothing
: html`<frame-preview
.frame=${this.frame}
.std=${this.std}
></frame-preview>`}
${
this.status === 'dragging' && stackOrder !== 0
? nothing
: html`<frame-preview
.frame=${this.frame}
.std=${this.std}
></frame-preview>`
}
${this._DraggingCardNumber()}
</div>
</div>`;
@@ -191,9 +191,9 @@ export class FramePanelHeader extends WithDisposable(LitElement) {
<div class="all-frames-setting">
<span class="all-frames-setting-label">All frames</span>
<edgeless-tool-icon-button
class="all-frames-setting-button ${this._settingPopperShow
? 'active'
: ''}"
class="all-frames-setting-button ${
this._settingPopperShow ? 'active' : ''
}"
.tooltip=${this._settingPopperShow ? '' : 'All Frames Settings'}
.tipPosition=${'top'}
.active=${this._settingPopperShow}
@@ -412,11 +412,13 @@ export class OutlinePanelBody extends SignalWatcher(
index=${index}
.note=${note}
.activeHeadingId=${this._activeHeadingId$.value}
.status=${this._allSelectedNotes$.value.includes(note)
? this._dragging$.value
? 'dragging'
: 'selected'
: 'normal'}
.status=${
this._allSelectedNotes$.value.includes(note)
? this._dragging$.value
? 'dragging'
: 'selected'
: 'normal'
}
@fitview=${this._fitToElement}
@select=${this._selectNote}
@displaymodechange=${this._handleDisplayModeChange}
@@ -101,11 +101,13 @@ export class OutlineBlockPreview extends SignalWatcher(
class="${styles.text} ${styles.textGeneral} ${headingClass}"
>${previewText}</span
>
${this._context.showIcons$.value
? html`<span class=${iconClass}
>${previewIconMap[block.props.type]}</span
>`
: nothing}`;
${
this._context.showIcons$.value
? html`<span class=${iconClass}
>${previewIconMap[block.props.type]}</span
>`
: nothing
}`;
}
override render() {
@@ -148,15 +150,17 @@ export class OutlineBlockPreview extends SignalWatcher(
assertType<BookmarkBlockModel>(block);
return html`
<span class="${styles.text} ${styles.textGeneral}"
>${block.props.title ||
block.props.url ||
placeholderMap['bookmark']}</span
>${
block.props.title || block.props.url || placeholderMap['bookmark']
}</span
>
${showPreviewIcon
? html`<span class=${iconClass}
>${previewIconMap['bookmark']}</span
>`
: nothing}
${
showPreviewIcon
? html`<span class=${iconClass}
>${previewIconMap['bookmark']}</span
>`
: nothing
}
`;
case 'affine:code':
assertType<CodeBlockModel>(block);
@@ -164,47 +168,61 @@ export class OutlineBlockPreview extends SignalWatcher(
<span class="${styles.text} ${styles.textGeneral}"
>${block.props.language ?? placeholderMap['code']}</span
>
${showPreviewIcon
? html`<span class=${iconClass}>${previewIconMap['code']}</span>`
: nothing}
${
showPreviewIcon
? html`<span class=${iconClass}>${previewIconMap['code']}</span>`
: nothing
}
`;
case 'affine:database':
assertType<DatabaseBlockModel>(block);
return html`
<span class="${styles.text} ${styles.textGeneral}"
>${block.props.title.toString().length
? block.props.title.toString()
: placeholderMap['database']}</span
>${
block.props.title.toString().length
? block.props.title.toString()
: placeholderMap['database']
}</span
>
${showPreviewIcon
? html`<span class=${iconClass}>${previewIconMap['table']}</span>`
: nothing}
${
showPreviewIcon
? html`<span class=${iconClass}>${previewIconMap['table']}</span>`
: nothing
}
`;
case 'affine:image':
assertType<ImageBlockModel>(block);
return html`
<span class="${styles.text} ${styles.textGeneral}"
>${block.props.caption?.length
? block.props.caption
: placeholderMap['image']}</span
>${
block.props.caption?.length
? block.props.caption
: placeholderMap['image']
}</span
>
${showPreviewIcon
? html`<span class=${iconClass}>${previewIconMap['image']}</span>`
: nothing}
${
showPreviewIcon
? html`<span class=${iconClass}>${previewIconMap['image']}</span>`
: nothing
}
`;
case 'affine:attachment':
assertType<AttachmentBlockModel>(block);
return html`
<span class="${styles.text} ${styles.textGeneral}"
>${block.props.name?.length
? block.props.name
: placeholderMap['attachment']}</span
>${
block.props.name?.length
? block.props.name
: placeholderMap['attachment']
}</span
>
${showPreviewIcon
? html`<span class=${iconClass}
>${previewIconMap['attachment']}</span
>`
: nothing}
${
showPreviewIcon
? html`<span class=${iconClass}
>${previewIconMap['attachment']}</span
>`
: nothing
}
`;
default:
return nothing;
@@ -963,7 +963,7 @@ export class ConnectionOverlay extends Overlay {
this._clearRect();
let result: Connection | null = null;
// oxlint-disable-next-line @typescript-eslint/prefer-for-of
// oxlint-disable-next-line typescript/prefer-for-of
for (let i = 0; i < connectables.length; i++) {
const connectable = connectables[i];
// first check if in excluedIds
@@ -357,22 +357,26 @@ export class EdgelessConnectorLabelEditor extends WithDisposable(
<rich-text
.yText=${connector.text}
.enableFormat=${false}
style=${isEmpty
? styleMap({
position: 'absolute',
left: 0,
top: 0,
padding: `${VERTICAL_PADDING}px ${HORIZONTAL_PADDING}px`,
})
: nothing}
style=${
isEmpty
? styleMap({
position: 'absolute',
left: 0,
top: 0,
padding: `${VERTICAL_PADDING}px ${HORIZONTAL_PADDING}px`,
})
: nothing
}
></rich-text>
${isEmpty
? html`
<span class="edgeless-connector-label-editor-placeholder">
Add text
</span>
`
: nothing}
${
isEmpty
? html`
<span class="edgeless-connector-label-editor-placeholder">
Add text
</span>
`
: nothing
}
</div>
`;
}
@@ -53,12 +53,14 @@ export class EdgelessConnectorToolButton extends QuickToolMixin(
return html`
<edgeless-tool-icon-button
class="edgeless-connector-button"
.tooltip=${this.popper
? ''
: html`<affine-tooltip-content-with-shortcut
data-tip="${getConnectorModeName(mode)}"
data-shortcut="${'C'}"
></affine-tooltip-content-with-shortcut>`}
.tooltip=${
this.popper
? ''
: html`<affine-tooltip-content-with-shortcut
data-tip="${getConnectorModeName(mode)}"
data-shortcut="${'C'}"
></affine-tooltip-content-with-shortcut>`
}
.tooltipOffset=${17}
.active=${active}
.iconContainerPadding=${6}
@@ -278,14 +278,16 @@ export class EdgelessMindmapMenu extends EdgelessToolbarToolMixin(
return html`<edgeless-slide-menu .height=${'64px'}>
<div class="text-and-mindmap">
<div class="media-item">
${isDraggingMedia
? html`<button
class="next"
style="transform: translateY(${showNextText ? 0 : 64}px)"
>
${mediaItem.icon}
</button>`
: nothing}
${
isDraggingMedia
? html`<button
class="next"
style="transform: translateY(${showNextText ? 0 : 64}px)"
>
${mediaItem.icon}
</button>`
: nothing
}
<button
style="opacity: ${isDraggingMedia ? 0 : 1}"
@mousedown=${(e: MouseEvent) =>
@@ -309,14 +311,16 @@ export class EdgelessMindmapMenu extends EdgelessToolbarToolMixin(
</div>
<div class="thin-divider"></div>
<div class="text-item">
${isDraggingText
? html`<button
class="next"
style="transform: translateY(${showNextText ? 0 : 64}px)"
>
${textItem.icon}
</button>`
: nothing}
${
isDraggingText
? html`<button
class="next"
style="transform: translateY(${showNextText ? 0 : 64}px)"
>
${textItem.icon}
</button>`
: nothing
}
<button
style="opacity: ${isDraggingText ? 0 : 1}"
@mousedown=${(e: MouseEvent) =>
@@ -350,14 +354,16 @@ export class EdgelessMindmapMenu extends EdgelessToolbarToolMixin(
const isActive = this._style$.value === mindMap.style;
return html`
<div class="mindmap-item" data-is-active=${isActive}>
${isBeingDragged
? html`<button
style="transform: translateY(${showNext ? 0 : 64}px)"
class="next"
>
${mindMap.icon}
</button>`
: nothing}
${
isBeingDragged
? html`<button
style="transform: translateY(${showNext ? 0 : 64}px)"
class="next"
>
${mindMap.icon}
</button>`
: nothing
}
<button
style="opacity: ${isBeingDragged ? 0 : 1}"
@mousedown=${(e: MouseEvent) => {
@@ -387,11 +393,13 @@ export class EdgelessMindmapMenu extends EdgelessToolbarToolMixin(
</div>
`;
})}
${this.std.store
.get(FeatureFlagService)
.getFlag('enable_mind_map_import')
? this._importMindMapEntry()
: nothing}
${
this.std.store
.get(FeatureFlagService)
.getFlag('enable_mind_map_import')
? this._importMindMapEntry()
: nothing
}
</div>
</edgeless-slide-menu>`;
}
@@ -374,18 +374,20 @@ export class EdgelessMindmapToolButton extends EdgelessToolbarToolMixin(
pointerEvents: draggingElement ? 'none' : 'auto',
});
return html`${isBeingDragged
? html`<div
class=${classMap({
'basket-tool-item': true,
next: true,
coming: !!dragOut && !cancelled,
})}
style=${nextStyle}
>
${tool.icon}
</div>`
: nothing}
return html`${
isBeingDragged
? html`<div
class=${classMap({
'basket-tool-item': true,
next: true,
coming: !!dragOut && !cancelled,
})}
style=${nextStyle}
>
${tool.icon}
</div>`
: nothing
}
<div
style=${currentStyle}
@@ -99,9 +99,11 @@ export class EdgelessNoteShadowPanel extends WithDisposable(LitElement) {
(shadow, index) =>
html`<style>
.item-icon svg rect:first-of-type {
fill: ${this.background.startsWith('--')
? `var(${this.background})`
: this.background};
fill: ${
this.background.startsWith('--')
? `var(${this.background})`
: this.background
};
}
</style>
<div
@@ -184,12 +184,14 @@ export class EdgelessNoteSeniorButton extends EdgelessToolbarToolMixin(
return html`<edgeless-toolbar-button
class="edgeless-note-button"
.tooltip=${this.popper
? ''
: html`<affine-tooltip-content-with-shortcut
data-tip="${'Note'}"
data-shortcut="${'N'}"
></affine-tooltip-content-with-shortcut>`}
.tooltip=${
this.popper
? ''
: html`<affine-tooltip-content-with-shortcut
data-tip="${'Note'}"
data-shortcut="${'N'}"
></affine-tooltip-content-with-shortcut>`
}
.tooltipOffset=${5}
>
<div
@@ -89,12 +89,14 @@ export class EdgelessNoteToolButton extends QuickToolMixin(LitElement) {
return html`
<edgeless-tool-icon-button
class="edgeless-note-button"
.tooltip=${this._noteMenu
? ''
: html`<affine-tooltip-content-with-shortcut
data-tip="${'Note'}"
data-shortcut="${'N'}"
></affine-tooltip-content-with-shortcut>`}
.tooltip=${
this._noteMenu
? ''
: html`<affine-tooltip-content-with-shortcut
data-tip="${'Note'}"
data-shortcut="${'N'}"
></affine-tooltip-content-with-shortcut>`
}
.tooltipOffset=${17}
.active=${active}
.iconContainerPadding=${6}
@@ -47,9 +47,9 @@ export class EdgelessShapePanel extends LitElement {
this._onSelect(name);
}}
>
${this.shapeStyle === ShapeStyle.General
? generalIcon
: scribbledIcon}
${
this.shapeStyle === ShapeStyle.General ? generalIcon : scribbledIcon
}
</edgeless-tool-icon-button>`
);
}
@@ -308,18 +308,20 @@ export class EdgelessToolbarShapeDraggable extends EdgelessToolbarToolMixin(
opacity: isBeingDragged ? 0 : 1,
});
const nextStyle = styleMap(baseStyle);
return html`${isBeingDragged
? html`<div
style=${nextStyle}
class=${classMap({
shape: true,
next: true,
coming: !!dragOut && !cancelled,
})}
>
${shape.svg}
</div>`
: nothing}
return html`${
isBeingDragged
? html`<div
style=${nextStyle}
class=${classMap({
shape: true,
next: true,
coming: !!dragOut && !cancelled,
})}
>
${shape.svg}
</div>`
: nothing
}
<div
style=${currStyle}
class=${classMap({

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