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 authored and GitHub committed 2026-08-10 23:51:28 +08:00
1 parent 749c83cd8e
commit 0c7b20dc18
291 files changed
+3371 -2865

No files matched your search

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