diff --git a/.scripts/fetch-examples.ts b/.scripts/fetch-examples.ts index efbcc1d964..56dc7536a8 100644 --- a/.scripts/fetch-examples.ts +++ b/.scripts/fetch-examples.ts @@ -66,6 +66,36 @@ export default function Editor() { return } ` + +const litEntry = ( + story: string, +) => `import { registerLitEditor } from './components/editor/examples/${story}' +import { LitElement, html } from 'lit' +import { customElement } from 'lit/decorators.js' + +registerLitEditor() + +@customElement('my-editor') +export class MyEditor extends LitElement { + createRenderRoot() { + return this + } + + render() { + return html\`\` + } +} +` + +const vanillaEntry = ( + story: string, +) => `import { setupVanillaEditor } from './components/editor/examples/${story}' + +export function renderEditor() { + return setupVanillaEditor().render() +} +` + const createSvelteEntry = (componentsPath: string) => (story: string) => ` + diff --git a/.templates/template-vanilla/main.js b/.templates/template-vanilla/main.js deleted file mode 100644 index 117581fd42..0000000000 --- a/.templates/template-vanilla/main.js +++ /dev/null @@ -1,2 +0,0 @@ -import './src/app.css' -import './src/index' diff --git a/.templates/template-vanilla/package.json b/.templates/template-vanilla/package.json index 220a7b9270..eb7413ebea 100644 --- a/.templates/template-vanilla/package.json +++ b/.templates/template-vanilla/package.json @@ -16,6 +16,7 @@ "postcss": "^8.5.6", "tailwindcss": "^4.1.18", "tw-animate-css": "^1.4.0", + "typescript": "~5.9.3", "vite": "7.3.1" } } diff --git a/.templates/template-vanilla/src/editor.ts b/.templates/template-vanilla/src/editor.ts new file mode 100644 index 0000000000..e5596caad2 --- /dev/null +++ b/.templates/template-vanilla/src/editor.ts @@ -0,0 +1,3 @@ +export function renderEditor() { + return document.createElement('div') +} diff --git a/.templates/template-vanilla/src/index.js b/.templates/template-vanilla/src/index.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/.templates/template-vanilla/src/main.ts b/.templates/template-vanilla/src/main.ts new file mode 100644 index 0000000000..a4945ae00c --- /dev/null +++ b/.templates/template-vanilla/src/main.ts @@ -0,0 +1,11 @@ +import './app.css' +import { renderEditor } from './editor' + +let container = document.querySelector('#app') +if (!container) { + container = document.createElement('div') + container.id = 'app' + document.body.appendChild(container) +} + +container.replaceChildren(renderEditor()) diff --git a/.templates/template-vanilla/tsconfig.json b/.templates/template-vanilla/tsconfig.json new file mode 100644 index 0000000000..4ba8dd95cf --- /dev/null +++ b/.templates/template-vanilla/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "types": ["vite/client"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/lit-minimal/.gitignore b/lit-minimal/.gitignore new file mode 100644 index 0000000000..5d6225c6df --- /dev/null +++ b/lit-minimal/.gitignore @@ -0,0 +1,4 @@ +node_modules +dist +.next +.svelte-kit diff --git a/lit-minimal/README.md b/lit-minimal/README.md new file mode 100644 index 0000000000..954cc8c15d --- /dev/null +++ b/lit-minimal/README.md @@ -0,0 +1,15 @@ +# lit-minimal + +A [ProseKit](https://prosekit.dev) example. + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/prosekit/examples/tree/master/lit-minimal) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/prosekit/examples/tree/master/lit-minimal) + +Run the example locally with: + +```bash +npx degit prosekit/examples/lit-minimal lit-minimal +cd lit-minimal +npm install +npm run dev +``` diff --git a/lit-minimal/index.html b/lit-minimal/index.html new file mode 100644 index 0000000000..9637b16269 --- /dev/null +++ b/lit-minimal/index.html @@ -0,0 +1,13 @@ + + + + + + ProseKit + Lit + + + + + + + diff --git a/lit-minimal/package.json b/lit-minimal/package.json new file mode 100644 index 0000000000..29be21bd5b --- /dev/null +++ b/lit-minimal/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-lit-minimal", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "tsc && vite build", + "dev": "vite", + "preview": "vite preview" + }, + "dependencies": { + "lit": "^3.3.2", + "prosekit": "^0.17.1" + }, + "devDependencies": { + "@egoist/tailwindcss-icons": "^1.9.0", + "@iconify-json/lucide": "^1.2.84", + "@tailwindcss/vite": "^4.1.18", + "postcss": "^8.5.6", + "tailwindcss": "^4.1.18", + "tw-animate-css": "^1.4.0", + "typescript": "5.9.3", + "vite": "7.3.1" + } +} diff --git a/lit-minimal/src/app.css b/lit-minimal/src/app.css new file mode 100644 index 0000000000..5d0567ecf8 --- /dev/null +++ b/lit-minimal/src/app.css @@ -0,0 +1,13 @@ +@import 'tailwindcss'; +@import 'tw-animate-css'; + +@plugin "@egoist/tailwindcss-icons"; + +body { + height: 100svh; + display: grid; + max-width: 900px; + padding: 16px; + margin-left: auto; + margin-right: auto; +} diff --git a/lit-minimal/src/app.ts b/lit-minimal/src/app.ts new file mode 100644 index 0000000000..3cbf14f94d --- /dev/null +++ b/lit-minimal/src/app.ts @@ -0,0 +1,18 @@ +import './app.css' +import './editor' + +import { LitElement, html } from 'lit' +import { customElement } from 'lit/decorators.js' + +@customElement('my-app') +export class MyApp extends LitElement { + createRenderRoot() { + return this + } + + render() { + return html` + + ` + } +} diff --git a/lit-minimal/src/components/editor/examples/minimal/editor.ts b/lit-minimal/src/components/editor/examples/minimal/editor.ts new file mode 100644 index 0000000000..122b4ad8f6 --- /dev/null +++ b/lit-minimal/src/components/editor/examples/minimal/editor.ts @@ -0,0 +1,59 @@ +import 'prosekit/basic/style.css' +import 'prosekit/basic/typography.css' + +import { + html, + LitElement, + type PropertyDeclaration, + type PropertyValues, +} from 'lit' +import { createRef, ref, type Ref } from 'lit/directives/ref.js' +import { defineBasicExtension } from 'prosekit/basic' +import type { Editor } from 'prosekit/core' +import { createEditor } from 'prosekit/core' + +export class LitEditor extends LitElement { + static override properties = { + editor: { + state: true, + attribute: false, + } satisfies PropertyDeclaration, + } + + private editor: Editor + private ref: Ref + + constructor() { + super() + + const extension = defineBasicExtension() + this.editor = createEditor({ extension }) + this.ref = createRef() + } + + override createRenderRoot() { + return this + } + + override updated(changedProperties: PropertyValues) { + super.updated(changedProperties) + this.editor.mount(this.ref.value) + } + + override render() { + return html` +
+ ` + } +} + +export function registerLitEditor() { + if (customElements.get('lit-editor-example-minimal')) return + customElements.define('lit-editor-example-minimal', LitEditor) +} + +declare global { + interface HTMLElementTagNameMap { + 'lit-editor-example-minimal': LitEditor + } +} diff --git a/lit-minimal/src/components/editor/examples/minimal/index.ts b/lit-minimal/src/components/editor/examples/minimal/index.ts new file mode 100644 index 0000000000..9eeecbbc50 --- /dev/null +++ b/lit-minimal/src/components/editor/examples/minimal/index.ts @@ -0,0 +1 @@ +export { LitEditor as ExampleEditor, registerLitEditor } from './editor' diff --git a/lit-minimal/src/editor.ts b/lit-minimal/src/editor.ts new file mode 100644 index 0000000000..63bc2902d8 --- /dev/null +++ b/lit-minimal/src/editor.ts @@ -0,0 +1,18 @@ +import { registerLitEditor } from './components/editor/examples/minimal' +import { LitElement, html } from 'lit' +import { customElement } from 'lit/decorators.js' + +registerLitEditor() + +@customElement('my-editor') +export class MyEditor extends LitElement { + createRenderRoot() { + return this + } + + render() { + return html` + + ` + } +} diff --git a/lit-minimal/tsconfig.json b/lit-minimal/tsconfig.json new file mode 100644 index 0000000000..1de5d357aa --- /dev/null +++ b/lit-minimal/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2022", + "experimentalDecorators": true, + "useDefineForClassFields": false, + "module": "ESNext", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/lit-minimal/vite.config.ts b/lit-minimal/vite.config.ts new file mode 100644 index 0000000000..fb0cdf00b5 --- /dev/null +++ b/lit-minimal/vite.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from 'vite' +import tailwindcss from '@tailwindcss/vite' + +export default defineConfig({ + plugins: [tailwindcss()], +}) diff --git a/lit-slash-menu/.gitignore b/lit-slash-menu/.gitignore new file mode 100644 index 0000000000..5d6225c6df --- /dev/null +++ b/lit-slash-menu/.gitignore @@ -0,0 +1,4 @@ +node_modules +dist +.next +.svelte-kit diff --git a/lit-slash-menu/README.md b/lit-slash-menu/README.md new file mode 100644 index 0000000000..1a4d660037 --- /dev/null +++ b/lit-slash-menu/README.md @@ -0,0 +1,15 @@ +# lit-slash-menu + +A [ProseKit](https://prosekit.dev) example. + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/prosekit/examples/tree/master/lit-slash-menu) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/prosekit/examples/tree/master/lit-slash-menu) + +Run the example locally with: + +```bash +npx degit prosekit/examples/lit-slash-menu lit-slash-menu +cd lit-slash-menu +npm install +npm run dev +``` diff --git a/lit-slash-menu/index.html b/lit-slash-menu/index.html new file mode 100644 index 0000000000..9637b16269 --- /dev/null +++ b/lit-slash-menu/index.html @@ -0,0 +1,13 @@ + + + + + + ProseKit + Lit + + + + + + + diff --git a/lit-slash-menu/package.json b/lit-slash-menu/package.json new file mode 100644 index 0000000000..620651a3a5 --- /dev/null +++ b/lit-slash-menu/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-lit-slash-menu", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "tsc && vite build", + "dev": "vite", + "preview": "vite preview" + }, + "dependencies": { + "lit": "^3.3.2", + "prosekit": "^0.17.1" + }, + "devDependencies": { + "@egoist/tailwindcss-icons": "^1.9.0", + "@iconify-json/lucide": "^1.2.84", + "@tailwindcss/vite": "^4.1.18", + "postcss": "^8.5.6", + "tailwindcss": "^4.1.18", + "tw-animate-css": "^1.4.0", + "typescript": "5.9.3", + "vite": "7.3.1" + } +} diff --git a/lit-slash-menu/src/app.css b/lit-slash-menu/src/app.css new file mode 100644 index 0000000000..5d0567ecf8 --- /dev/null +++ b/lit-slash-menu/src/app.css @@ -0,0 +1,13 @@ +@import 'tailwindcss'; +@import 'tw-animate-css'; + +@plugin "@egoist/tailwindcss-icons"; + +body { + height: 100svh; + display: grid; + max-width: 900px; + padding: 16px; + margin-left: auto; + margin-right: auto; +} diff --git a/lit-slash-menu/src/app.ts b/lit-slash-menu/src/app.ts new file mode 100644 index 0000000000..3cbf14f94d --- /dev/null +++ b/lit-slash-menu/src/app.ts @@ -0,0 +1,18 @@ +import './app.css' +import './editor' + +import { LitElement, html } from 'lit' +import { customElement } from 'lit/decorators.js' + +@customElement('my-app') +export class MyApp extends LitElement { + createRenderRoot() { + return this + } + + render() { + return html` + + ` + } +} diff --git a/lit-slash-menu/src/components/editor/examples/slash-menu/editor.ts b/lit-slash-menu/src/components/editor/examples/slash-menu/editor.ts new file mode 100644 index 0000000000..b706136311 --- /dev/null +++ b/lit-slash-menu/src/components/editor/examples/slash-menu/editor.ts @@ -0,0 +1,75 @@ +import 'prosekit/basic/style.css' +import 'prosekit/basic/typography.css' + +import { + html, + LitElement, + type PropertyDeclaration, + type PropertyValues, +} from 'lit' +import { createRef, ref, type Ref } from 'lit/directives/ref.js' +import type { Editor } from 'prosekit/core' +import { createEditor } from 'prosekit/core' + +import { defineExtension } from './extension' + +import '../../ui/slash-menu/index' + +export class LitEditor extends LitElement { + static override properties = { + editor: { + state: true, + attribute: false, + } satisfies PropertyDeclaration, + } + + private editor: Editor + private ref: Ref + + constructor() { + super() + + const extension = defineExtension() + this.editor = createEditor({ extension }) + this.ref = createRef() + } + + override createRenderRoot() { + return this + } + + override updated(changedProperties: PropertyValues) { + super.updated(changedProperties) + this.editor.mount(this.ref.value) + } + + override render() { + return html` +
+
+
+ +
+
+ ` + } +} + +export function registerLitEditor() { + if (customElements.get('lit-editor-example-slash-menu')) return + customElements.define('lit-editor-example-slash-menu', LitEditor) +} + +declare global { + interface HTMLElementTagNameMap { + 'lit-editor-example-slash-menu': LitEditor + } +} diff --git a/lit-slash-menu/src/components/editor/examples/slash-menu/extension.ts b/lit-slash-menu/src/components/editor/examples/slash-menu/extension.ts new file mode 100644 index 0000000000..0edda60136 --- /dev/null +++ b/lit-slash-menu/src/components/editor/examples/slash-menu/extension.ts @@ -0,0 +1,12 @@ +import { defineBasicExtension } from 'prosekit/basic' +import { union } from 'prosekit/core' +import { definePlaceholder } from 'prosekit/extensions/placeholder' + +export function defineExtension() { + return union( + defineBasicExtension(), + definePlaceholder({ placeholder: 'Press / for commands...' }), + ) +} + +export type EditorExtension = ReturnType diff --git a/lit-slash-menu/src/components/editor/examples/slash-menu/index.ts b/lit-slash-menu/src/components/editor/examples/slash-menu/index.ts new file mode 100644 index 0000000000..9eeecbbc50 --- /dev/null +++ b/lit-slash-menu/src/components/editor/examples/slash-menu/index.ts @@ -0,0 +1 @@ +export { LitEditor as ExampleEditor, registerLitEditor } from './editor' diff --git a/lit-slash-menu/src/components/editor/ui/slash-menu/index.ts b/lit-slash-menu/src/components/editor/ui/slash-menu/index.ts new file mode 100644 index 0000000000..6b2bff17a8 --- /dev/null +++ b/lit-slash-menu/src/components/editor/ui/slash-menu/index.ts @@ -0,0 +1,3 @@ +import './slash-menu' +import './slash-menu-item' +import './slash-menu-empty' diff --git a/lit-slash-menu/src/components/editor/ui/slash-menu/slash-menu-empty.ts b/lit-slash-menu/src/components/editor/ui/slash-menu/slash-menu-empty.ts new file mode 100644 index 0000000000..8b31ad9f46 --- /dev/null +++ b/lit-slash-menu/src/components/editor/ui/slash-menu/slash-menu-empty.ts @@ -0,0 +1,21 @@ +import 'prosekit/lit/autocomplete' + +import { html, LitElement } from 'lit' + +class SlashMenuEmptyElement extends LitElement { + override createRenderRoot() { + return this + } + + override render() { + return html` + + No results + + ` + } +} + +customElements.define('lit-editor-slash-menu-empty', SlashMenuEmptyElement) diff --git a/lit-slash-menu/src/components/editor/ui/slash-menu/slash-menu-item.ts b/lit-slash-menu/src/components/editor/ui/slash-menu/slash-menu-item.ts new file mode 100644 index 0000000000..a87cd0db39 --- /dev/null +++ b/lit-slash-menu/src/components/editor/ui/slash-menu/slash-menu-item.ts @@ -0,0 +1,48 @@ +import 'prosekit/lit/autocomplete' + +import { html, LitElement } from 'lit' +import type { AutocompleteItemEvents } from 'prosekit/web/autocomplete' + +class SlashMenuItemElement extends LitElement { + static override properties = { + label: { type: String }, + kbd: { type: String }, + } + + label: string + kbd: string + + constructor() { + super() + this.label = '' + this.kbd = '' + } + + override createRenderRoot() { + return this + } + + handleSelect = (event: AutocompleteItemEvents['select']) => { + this.dispatchEvent(new CustomEvent('select', { detail: event.detail })) + } + + override render() { + return html` + + ${this.label} + ${this.kbd + ? html` + + ${this.kbd} + + ` + : ''} + + ` + } +} + +customElements.define('lit-editor-slash-menu-item', SlashMenuItemElement) diff --git a/lit-slash-menu/src/components/editor/ui/slash-menu/slash-menu.ts b/lit-slash-menu/src/components/editor/ui/slash-menu/slash-menu.ts new file mode 100644 index 0000000000..6716185a16 --- /dev/null +++ b/lit-slash-menu/src/components/editor/ui/slash-menu/slash-menu.ts @@ -0,0 +1,114 @@ +import 'prosekit/lit/autocomplete' + +import { html, LitElement, type PropertyDeclaration } from 'lit' +import type { BasicExtension } from 'prosekit/basic' +import type { Editor } from 'prosekit/core' +import { canUseRegexLookbehind } from 'prosekit/core' + +// Match inputs like "/", "/table", "/heading 1" etc. Do not match "/ heading". +const regex = canUseRegexLookbehind() ? /(?, + } + + editor?: Editor + + override createRenderRoot() { + return this + } + + override render() { + const editor = this.editor + if (!editor) { + return html`` + } + + return html` + + + editor.commands.setParagraph()} + > + editor.commands.setHeading({ level: 1 })} + > + editor.commands.setHeading({ level: 2 })} + > + editor.commands.setHeading({ level: 3 })} + > + editor.commands.wrapInList({ kind: 'bullet' })} + > + editor.commands.wrapInList({ kind: 'ordered' })} + > + editor.commands.wrapInList({ kind: 'task' })} + > + editor.commands.wrapInList({ kind: 'toggle' })} + > + editor.commands.setBlockquote()} + > + editor.commands.insertTable({ row: 3, col: 3 })} + > + editor.commands.insertHorizontalRule()} + > + editor.commands.setCodeBlock()} + > + + + + ` + } +} + +customElements.define('lit-editor-slash-menu', SlashMenuElement) diff --git a/lit-slash-menu/src/editor.ts b/lit-slash-menu/src/editor.ts new file mode 100644 index 0000000000..7ea7548ab0 --- /dev/null +++ b/lit-slash-menu/src/editor.ts @@ -0,0 +1,18 @@ +import { registerLitEditor } from './components/editor/examples/slash-menu' +import { LitElement, html } from 'lit' +import { customElement } from 'lit/decorators.js' + +registerLitEditor() + +@customElement('my-editor') +export class MyEditor extends LitElement { + createRenderRoot() { + return this + } + + render() { + return html` + + ` + } +} diff --git a/lit-slash-menu/tsconfig.json b/lit-slash-menu/tsconfig.json new file mode 100644 index 0000000000..1de5d357aa --- /dev/null +++ b/lit-slash-menu/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2022", + "experimentalDecorators": true, + "useDefineForClassFields": false, + "module": "ESNext", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/lit-slash-menu/vite.config.ts b/lit-slash-menu/vite.config.ts new file mode 100644 index 0000000000..fb0cdf00b5 --- /dev/null +++ b/lit-slash-menu/vite.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from 'vite' +import tailwindcss from '@tailwindcss/vite' + +export default defineConfig({ + plugins: [tailwindcss()], +}) diff --git a/vanilla-minimal/.gitignore b/vanilla-minimal/.gitignore new file mode 100644 index 0000000000..5d6225c6df --- /dev/null +++ b/vanilla-minimal/.gitignore @@ -0,0 +1,4 @@ +node_modules +dist +.next +.svelte-kit diff --git a/vanilla-minimal/README.md b/vanilla-minimal/README.md new file mode 100644 index 0000000000..6937f9ae91 --- /dev/null +++ b/vanilla-minimal/README.md @@ -0,0 +1,15 @@ +# vanilla-minimal + +A [ProseKit](https://prosekit.dev) example. + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/prosekit/examples/tree/master/vanilla-minimal) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/prosekit/examples/tree/master/vanilla-minimal) + +Run the example locally with: + +```bash +npx degit prosekit/examples/vanilla-minimal vanilla-minimal +cd vanilla-minimal +npm install +npm run dev +``` diff --git a/vanilla-minimal/index.html b/vanilla-minimal/index.html new file mode 100644 index 0000000000..2d9080a6a4 --- /dev/null +++ b/vanilla-minimal/index.html @@ -0,0 +1,11 @@ + + + + + + ProseKit + Vanilla TypeScript + + + + + diff --git a/vanilla-minimal/package.json b/vanilla-minimal/package.json new file mode 100644 index 0000000000..3c3923301c --- /dev/null +++ b/vanilla-minimal/package.json @@ -0,0 +1,24 @@ +{ + "name": "example-vanilla-minimal", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "vite build", + "dev": "vite", + "preview": "vite preview" + }, + "dependencies": { + "prosekit": "^0.17.1" + }, + "devDependencies": { + "@egoist/tailwindcss-icons": "^1.9.0", + "@iconify-json/lucide": "^1.2.84", + "@tailwindcss/vite": "^4.1.18", + "postcss": "^8.5.6", + "tailwindcss": "^4.1.18", + "tw-animate-css": "^1.4.0", + "typescript": "~5.9.3", + "vite": "7.3.1" + } +} diff --git a/vanilla-minimal/src/app.css b/vanilla-minimal/src/app.css new file mode 100644 index 0000000000..5d0567ecf8 --- /dev/null +++ b/vanilla-minimal/src/app.css @@ -0,0 +1,13 @@ +@import 'tailwindcss'; +@import 'tw-animate-css'; + +@plugin "@egoist/tailwindcss-icons"; + +body { + height: 100svh; + display: grid; + max-width: 900px; + padding: 16px; + margin-left: auto; + margin-right: auto; +} diff --git a/vanilla-minimal/src/components/editor/examples/minimal/editor.ts b/vanilla-minimal/src/components/editor/examples/minimal/editor.ts new file mode 100644 index 0000000000..a8ca847e52 --- /dev/null +++ b/vanilla-minimal/src/components/editor/examples/minimal/editor.ts @@ -0,0 +1,22 @@ +import 'prosekit/basic/style.css' +import 'prosekit/basic/typography.css' + +import { defineBasicExtension } from 'prosekit/basic' +import { createEditor } from 'prosekit/core' + +export function setupVanillaEditor() { + const extension = defineBasicExtension() + const editor = createEditor({ extension }) + + return { + render: () => { + const element = document.createElement('div') + element.className = 'outline-solid p-4' + editor.mount(element) + return element + }, + destroy: () => { + editor.unmount() + }, + } +} diff --git a/vanilla-minimal/src/components/editor/examples/minimal/index.ts b/vanilla-minimal/src/components/editor/examples/minimal/index.ts new file mode 100644 index 0000000000..e54daaa4f4 --- /dev/null +++ b/vanilla-minimal/src/components/editor/examples/minimal/index.ts @@ -0,0 +1 @@ +export { setupVanillaEditor } from './editor' diff --git a/vanilla-minimal/src/editor.ts b/vanilla-minimal/src/editor.ts new file mode 100644 index 0000000000..3ea03142c5 --- /dev/null +++ b/vanilla-minimal/src/editor.ts @@ -0,0 +1,5 @@ +import { setupVanillaEditor } from './components/editor/examples/minimal' + +export function renderEditor() { + return setupVanillaEditor().render() +} diff --git a/vanilla-minimal/src/main.ts b/vanilla-minimal/src/main.ts new file mode 100644 index 0000000000..a4945ae00c --- /dev/null +++ b/vanilla-minimal/src/main.ts @@ -0,0 +1,11 @@ +import './app.css' +import { renderEditor } from './editor' + +let container = document.querySelector('#app') +if (!container) { + container = document.createElement('div') + container.id = 'app' + document.body.appendChild(container) +} + +container.replaceChildren(renderEditor()) diff --git a/vanilla-minimal/tsconfig.json b/vanilla-minimal/tsconfig.json new file mode 100644 index 0000000000..4ba8dd95cf --- /dev/null +++ b/vanilla-minimal/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "types": ["vite/client"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/vanilla-minimal/vite.config.ts b/vanilla-minimal/vite.config.ts new file mode 100644 index 0000000000..fb0cdf00b5 --- /dev/null +++ b/vanilla-minimal/vite.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from 'vite' +import tailwindcss from '@tailwindcss/vite' + +export default defineConfig({ + plugins: [tailwindcss()], +})