got a basic working text area
This commit is contained in:
parent
2dfbc08788
commit
d914db1c1d
9 changed files with 888 additions and 58 deletions
144
package-lock.json
generated
144
package-lock.json
generated
|
@ -9,14 +9,20 @@
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@editorjs/editorjs": "^2.30.7",
|
||||||
"@lit/localize": "^0.12.2",
|
"@lit/localize": "^0.12.2",
|
||||||
"@shoelace-style/shoelace": "^2.18.0",
|
"@shoelace-style/shoelace": "^2.18.0",
|
||||||
"@thepassle/app-tools": "^0.9.12",
|
"@thepassle/app-tools": "^0.9.12",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"express": "^4.21.1",
|
"express": "^4.21.1",
|
||||||
|
"lazy.js": "^0.5.1",
|
||||||
"lit": "^3.2.1",
|
"lit": "^3.2.1",
|
||||||
"nostr-tools": "^2.10.1",
|
"nostr-tools": "^2.10.1",
|
||||||
|
"prosemirror-markdown": "^1.13.1",
|
||||||
|
"prosemirror-model": "^1.24.1",
|
||||||
|
"prosemirror-state": "^1.4.3",
|
||||||
|
"prosemirror-view": "^1.37.1",
|
||||||
"urlpattern-polyfill": "^10.0.0",
|
"urlpattern-polyfill": "^10.0.0",
|
||||||
"workbox-build": "^7.3.0",
|
"workbox-build": "^7.3.0",
|
||||||
"workbox-core": "^7.3.0",
|
"workbox-core": "^7.3.0",
|
||||||
|
@ -1505,6 +1511,11 @@
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@editorjs/editorjs": {
|
||||||
|
"version": "2.30.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@editorjs/editorjs/-/editorjs-2.30.7.tgz",
|
||||||
|
"integrity": "sha512-FfdeUqrgcKWC+Cy2GW6Dxup6s2TaRKokR4FL+HKXshu6h9Y//rrx4SQkURgkZOCSbV77t9btbmAXdFXWGB+diw=="
|
||||||
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.21.5",
|
"version": "0.21.5",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
||||||
|
@ -2464,6 +2475,25 @@
|
||||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/linkify-it": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q=="
|
||||||
|
},
|
||||||
|
"node_modules/@types/markdown-it": {
|
||||||
|
"version": "14.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz",
|
||||||
|
"integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/linkify-it": "^5",
|
||||||
|
"@types/mdurl": "^2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/mdurl": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="
|
||||||
|
},
|
||||||
"node_modules/@types/prop-types": {
|
"node_modules/@types/prop-types": {
|
||||||
"version": "15.7.13",
|
"version": "15.7.13",
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
|
||||||
|
@ -2558,6 +2588,11 @@
|
||||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/argparse": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||||
|
},
|
||||||
"node_modules/array-buffer-byte-length": {
|
"node_modules/array-buffer-byte-length": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
|
||||||
|
@ -3203,6 +3238,17 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/entities": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/es-abstract": {
|
"node_modules/es-abstract": {
|
||||||
"version": "1.23.3",
|
"version": "1.23.3",
|
||||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz",
|
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz",
|
||||||
|
@ -4302,6 +4348,11 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lazy.js": {
|
||||||
|
"version": "0.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lazy.js/-/lazy.js-0.5.1.tgz",
|
||||||
|
"integrity": "sha512-p9v24vaKrzS2mEx3yuzva/3M6I3+HwvXd0pB1Xf/IvsFIMdhQgmym7JBO0e7c0OZmKTo07sCuiCIm6jazSWFNw=="
|
||||||
|
},
|
||||||
"node_modules/leven": {
|
"node_modules/leven": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||||
|
@ -4311,6 +4362,14 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/linkify-it": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"uc.micro": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lit": {
|
"node_modules/lit": {
|
||||||
"version": "3.2.1",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/lit/-/lit-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/lit/-/lit-3.2.1.tgz",
|
||||||
|
@ -4378,6 +4437,27 @@
|
||||||
"sourcemap-codec": "^1.4.8"
|
"sourcemap-codec": "^1.4.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/markdown-it": {
|
||||||
|
"version": "14.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
|
||||||
|
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
|
||||||
|
"dependencies": {
|
||||||
|
"argparse": "^2.0.1",
|
||||||
|
"entities": "^4.4.0",
|
||||||
|
"linkify-it": "^5.0.0",
|
||||||
|
"mdurl": "^2.0.0",
|
||||||
|
"punycode.js": "^2.3.1",
|
||||||
|
"uc.micro": "^2.1.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"markdown-it": "bin/markdown-it.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mdurl": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="
|
||||||
|
},
|
||||||
"node_modules/media-typer": {
|
"node_modules/media-typer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
|
@ -4580,6 +4660,11 @@
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/orderedmap": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g=="
|
||||||
|
},
|
||||||
"node_modules/parseurl": {
|
"node_modules/parseurl": {
|
||||||
"version": "1.3.3",
|
"version": "1.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||||
|
@ -4677,6 +4762,52 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prosemirror-markdown": {
|
||||||
|
"version": "1.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.1.tgz",
|
||||||
|
"integrity": "sha512-Sl+oMfMtAjWtlcZoj/5L/Q39MpEnVZ840Xo330WJWUvgyhNmLBLN7MsHn07s53nG/KImevWHSE6fEj4q/GihHw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/markdown-it": "^14.0.0",
|
||||||
|
"markdown-it": "^14.0.0",
|
||||||
|
"prosemirror-model": "^1.20.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-model": {
|
||||||
|
"version": "1.24.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.24.1.tgz",
|
||||||
|
"integrity": "sha512-YM053N+vTThzlWJ/AtPtF1j0ebO36nvbmDy4U7qA2XQB8JVaQp1FmB9Jhrps8s+z+uxhhVTny4m20ptUvhk0Mg==",
|
||||||
|
"dependencies": {
|
||||||
|
"orderedmap": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-state": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz",
|
||||||
|
"integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.0.0",
|
||||||
|
"prosemirror-transform": "^1.0.0",
|
||||||
|
"prosemirror-view": "^1.27.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-transform": {
|
||||||
|
"version": "1.10.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.10.2.tgz",
|
||||||
|
"integrity": "sha512-2iUq0wv2iRoJO/zj5mv8uDUriOHWzXRnOTVgCzSXnktS/2iQRa3UUQwVlkBlYZFtygw6Nh1+X4mGqoYBINn5KQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.21.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prosemirror-view": {
|
||||||
|
"version": "1.37.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.37.1.tgz",
|
||||||
|
"integrity": "sha512-MEAnjOdXU1InxEmhjgmEzQAikaS6lF3hD64MveTPpjOGNTl87iRLA1HupC/DEV6YuK7m4Q9DHFNTjwIVtqz5NA==",
|
||||||
|
"dependencies": {
|
||||||
|
"prosemirror-model": "^1.20.0",
|
||||||
|
"prosemirror-state": "^1.0.0",
|
||||||
|
"prosemirror-transform": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/proxy-addr": {
|
"node_modules/proxy-addr": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||||
|
@ -4703,6 +4834,14 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/punycode.js": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/qr-creator": {
|
"node_modules/qr-creator": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/qr-creator/-/qr-creator-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/qr-creator/-/qr-creator-1.0.0.tgz",
|
||||||
|
@ -5534,6 +5673,11 @@
|
||||||
"node": ">=14.17"
|
"node": ">=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/uc.micro": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="
|
||||||
|
},
|
||||||
"node_modules/unbox-primitive": {
|
"node_modules/unbox-primitive": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
||||||
|
|
|
@ -15,14 +15,20 @@
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@editorjs/editorjs": "^2.30.7",
|
||||||
"@lit/localize": "^0.12.2",
|
"@lit/localize": "^0.12.2",
|
||||||
"@shoelace-style/shoelace": "^2.18.0",
|
"@shoelace-style/shoelace": "^2.18.0",
|
||||||
"@thepassle/app-tools": "^0.9.12",
|
"@thepassle/app-tools": "^0.9.12",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"express": "^4.21.1",
|
"express": "^4.21.1",
|
||||||
|
"lazy.js": "^0.5.1",
|
||||||
"lit": "^3.2.1",
|
"lit": "^3.2.1",
|
||||||
"nostr-tools": "^2.10.1",
|
"nostr-tools": "^2.10.1",
|
||||||
|
"prosemirror-markdown": "^1.13.1",
|
||||||
|
"prosemirror-model": "^1.24.1",
|
||||||
|
"prosemirror-state": "^1.4.3",
|
||||||
|
"prosemirror-view": "^1.37.1",
|
||||||
"urlpattern-polyfill": "^10.0.0",
|
"urlpattern-polyfill": "^10.0.0",
|
||||||
"workbox-build": "^7.3.0",
|
"workbox-build": "^7.3.0",
|
||||||
"workbox-core": "^7.3.0",
|
"workbox-core": "^7.3.0",
|
||||||
|
|
40
src/components/menu-plugin.ts
Normal file
40
src/components/menu-plugin.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import { Plugin } from 'prosemirror-state';
|
||||||
|
|
||||||
|
export const plusButtonPlugin = new Plugin({
|
||||||
|
view(editorView) {
|
||||||
|
const button = document.createElement('button');
|
||||||
|
button.textContent = '+';
|
||||||
|
button.className = 'plus-button'
|
||||||
|
|
||||||
|
button.style.position = 'absolute';
|
||||||
|
button.style.zIndex = '10';
|
||||||
|
button.style.display = 'none'; // Hide initially
|
||||||
|
|
||||||
|
editorView.dom.appendChild(button);
|
||||||
|
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
console.log('Plus button clicked');
|
||||||
|
// Add logic to open dropdown or execute commands
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
update(view) {
|
||||||
|
const { $from } = view.state.selection;
|
||||||
|
|
||||||
|
// Only show the button when the cursor is in a text block with no content
|
||||||
|
if ($from.parent.isTextblock && $from.parent.content.size === 0) {
|
||||||
|
const coords = view.coordsAtPos($from.pos);
|
||||||
|
// Position the button relative to the cursor
|
||||||
|
button.style.top = `${coords.top + window.scrollY}px`; // Added scroll offset for better positioning
|
||||||
|
button.style.left = `${coords.left + window.scrollX - 30}px`; // Added scroll offset
|
||||||
|
button.style.display = 'block'; // Make the button visible
|
||||||
|
} else {
|
||||||
|
button.style.display = 'none'; // Hide the button when not in valid position
|
||||||
|
}
|
||||||
|
},
|
||||||
|
destroy() {
|
||||||
|
button.remove(); // Cleanup on destroy
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,12 +1,9 @@
|
||||||
import { LitElement, html, css } from 'lit';
|
import { LitElement, html, css } from 'lit';
|
||||||
import { customElement } from 'lit/decorators.js';
|
import { customElement } from 'lit/decorators.js';
|
||||||
|
|
||||||
// You can also import styles from another file
|
|
||||||
// if you prefer to keep your CSS seperate from your component
|
|
||||||
import { styles } from './about-styles';
|
import { styles } from './about-styles';
|
||||||
|
|
||||||
import { styles as sharedStyles } from '../../styles/shared-styles'
|
import { styles as sharedStyles } from '../../styles/shared-styles'
|
||||||
|
|
||||||
import '@shoelace-style/shoelace/dist/components/card/card.js';
|
import '@shoelace-style/shoelace/dist/components/card/card.js';
|
||||||
|
|
||||||
@customElement('app-about')
|
@customElement('app-about')
|
||||||
|
@ -16,29 +13,6 @@ export class AppAbout extends LitElement {
|
||||||
styles,
|
styles,
|
||||||
css`
|
css`
|
||||||
|
|
||||||
#welcomeBar {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#welcomeCard,
|
|
||||||
#infoCard {
|
|
||||||
padding: 18px;
|
|
||||||
padding-top: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
sl-card::part(footer) {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media(min-width: 750px) {
|
|
||||||
sl-card {
|
|
||||||
width: 70vw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
`
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -74,7 +48,8 @@ export class AppAbout extends LitElement {
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://www.npmjs.com/package/nostr-tools?activeTab=dependencies">Nostr Tools</a>
|
I am using <a href="https://www.npmjs.com/package/nostr-tools?activeTab=dependencies">Nostr Tools</a> to implement an extension
|
||||||
|
sign in and pull notes from my personal relay.
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
|
|
|
@ -4,11 +4,13 @@ import { resolveRouterPath } from '../router';
|
||||||
import { Relay } from 'nostr-tools';
|
import { Relay } from 'nostr-tools';
|
||||||
import { WindowNostr } from 'nostr-tools/nip07';
|
import { WindowNostr } from 'nostr-tools/nip07';
|
||||||
|
|
||||||
|
|
||||||
import '@shoelace-style/shoelace/dist/components/card/card.js';
|
import '@shoelace-style/shoelace/dist/components/card/card.js';
|
||||||
import '@shoelace-style/shoelace/dist/components/button/button.js';
|
import '@shoelace-style/shoelace/dist/components/button/button.js';
|
||||||
|
|
||||||
import { styles } from '../styles/shared-styles';
|
import { styles } from '../styles/shared-styles';
|
||||||
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
nostr?: WindowNostr;
|
nostr?: WindowNostr;
|
||||||
|
@ -31,29 +33,7 @@ export class AppHome extends LitElement {
|
||||||
static styles = [
|
static styles = [
|
||||||
styles,
|
styles,
|
||||||
css`
|
css`
|
||||||
#welcomeBar {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#welcomeCard,
|
|
||||||
#infoCard {
|
|
||||||
padding: 18px;
|
|
||||||
padding-top: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
sl-card::part(footer) {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media(min-width: 750px) {
|
|
||||||
sl-card {
|
|
||||||
width: 70vw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@media (horizontal-viewport-segments: 2) {
|
@media (horizontal-viewport-segments: 2) {
|
||||||
|
@ -209,16 +189,16 @@ Profile Picture Container
|
||||||
<div id="welcomeBar">
|
<div id="welcomeBar">
|
||||||
<sl-card id="welcomeCard">
|
<sl-card id="welcomeCard">
|
||||||
<div slot="header">
|
<div slot="header">
|
||||||
<h2>Find me on any nostr client by searching ${this.nostrAddy || 'Guest'}</h2>
|
<h2>Welcome to ${this.nostrAddy || 'Guest'}'s Profile</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
You can use the Nostr protocol to transform your personal website into
|
You can use the Nostr protocol to transform your personal website into
|
||||||
a micro social media client. It eliminates the need to use a corporate
|
a micro blog client. You can compose a note and post it to your social
|
||||||
social media account. I am using nostr-tools to implement an extension
|
network.
|
||||||
sign in and pull notes from my personal relay.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
<div class="profile-picture-container">
|
<div class="profile-picture-container">
|
||||||
<img class="profile-pic" src="${this.profilePic || '/assets/img/default_pfp.png'}" alt="Profile Picture" width="200px" height="200px">
|
<img class="profile-pic" src="${this.profilePic || '/assets/img/default_pfp.png'}" alt="Profile Picture" width="200px" height="200px">
|
||||||
|
|
||||||
|
@ -237,7 +217,9 @@ Profile Picture Container
|
||||||
|
|
||||||
<sl-button href="${resolveRouterPath('about')}" variant="primary">Navigate to About</sl-button>
|
<sl-button href="${resolveRouterPath('about')}" variant="primary">Navigate to About</sl-button>
|
||||||
<sl-button href="${resolveRouterPath('note-wall')}" variant="primary">Navigate to Note Wall</sl-button>
|
<sl-button href="${resolveRouterPath('note-wall')}" variant="primary">Navigate to Note Wall</sl-button>
|
||||||
</div>
|
<sl-button href="${resolveRouterPath('write')}" variant="primary">Navigate to Note Compose</sl-button>
|
||||||
|
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
242
src/pages/app-write/app-write.ts
Normal file
242
src/pages/app-write/app-write.ts
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
import { LitElement, css, html } from 'lit';
|
||||||
|
import { property, customElement, query } from 'lit/decorators.js';
|
||||||
|
|
||||||
|
import '@shoelace-style/shoelace/dist/components/card/card.js';
|
||||||
|
|
||||||
|
import '@shoelace-style/shoelace/dist/components/button/button.js';
|
||||||
|
|
||||||
|
import { styles } from '../../styles/shared-styles';
|
||||||
|
|
||||||
|
import {EditorState} from 'prosemirror-state'
|
||||||
|
import { Transaction } from 'prosemirror-state';
|
||||||
|
import { EditorView } from 'prosemirror-view';
|
||||||
|
import { Schema } from 'prosemirror-model';
|
||||||
|
import { keymap } from 'prosemirror-keymap';
|
||||||
|
import { toggleMark } from 'prosemirror-commands';
|
||||||
|
import {undo, redo, history} from 'prosemirror-history'
|
||||||
|
import { baseKeymap } from 'prosemirror-commands';
|
||||||
|
|
||||||
|
import { plusButtonPlugin } from '../../components/menu-plugin';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const customSchema = new Schema({
|
||||||
|
nodes: {
|
||||||
|
text: {
|
||||||
|
group: 'inline',
|
||||||
|
},
|
||||||
|
star: {
|
||||||
|
inline: true,
|
||||||
|
group: 'inline',
|
||||||
|
toDOM() {
|
||||||
|
return ['star', '⭐'];
|
||||||
|
},
|
||||||
|
parseDOM: [{ tag: 'star' }],
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
group: 'block',
|
||||||
|
content: 'inline*',
|
||||||
|
toDOM() {
|
||||||
|
return ['p', 0];
|
||||||
|
},
|
||||||
|
parseDOM: [{ tag: 'p' }],
|
||||||
|
},
|
||||||
|
boring_paragraph: {
|
||||||
|
group: 'block',
|
||||||
|
content: 'text*',
|
||||||
|
marks: '',
|
||||||
|
toDOM() {
|
||||||
|
return ['p', { class: 'boring' }, 0];
|
||||||
|
},
|
||||||
|
parseDOM: [{ tag: 'p.boring', priority: 60 }],
|
||||||
|
},
|
||||||
|
doc: {
|
||||||
|
content: 'block+',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
marks: {
|
||||||
|
shouting: {
|
||||||
|
toDOM() {
|
||||||
|
return ['shouting', 0];
|
||||||
|
},
|
||||||
|
parseDOM: [{ tag: 'shouting' }],
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
attrs: { href: {} },
|
||||||
|
toDOM(node) {
|
||||||
|
return ['a', { href: node.attrs.href }, 0];
|
||||||
|
},
|
||||||
|
parseDOM: [
|
||||||
|
{
|
||||||
|
tag: 'a',
|
||||||
|
getAttrs(dom) {
|
||||||
|
return { href: dom };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
inclusive: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Commands
|
||||||
|
function insertStar(state: EditorState, dispatch?: (tr: Transaction) => void): boolean {
|
||||||
|
const type = customSchema.nodes.star;
|
||||||
|
const { $from } = state.selection;
|
||||||
|
|
||||||
|
// If the parent cannot replace with the 'star' node, return false
|
||||||
|
if (!$from.parent.canReplaceWith($from.index(), $from.index(), type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If dispatch is provided, apply the transaction
|
||||||
|
if (dispatch) {
|
||||||
|
dispatch(state.tr.replaceSelectionWith(type.create()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always return true if insertion conditions are met
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleLink(state: EditorState, dispatch?: (tr: Transaction) => void): boolean {
|
||||||
|
let {doc, selection} = state
|
||||||
|
if (selection.empty) return false
|
||||||
|
let attrs = null
|
||||||
|
if (!doc.rangeHasMark(selection.from, selection.to, customSchema.marks.link)) {
|
||||||
|
attrs = {href: prompt("Link to where?", "")}
|
||||||
|
if (!attrs.href) return false
|
||||||
|
}
|
||||||
|
return toggleMark(customSchema.marks.link, attrs)(state, dispatch)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Keymap
|
||||||
|
const customKeymap = keymap({
|
||||||
|
'Ctrl-Space': insertStar,
|
||||||
|
"Ctrl-b": (state, dispatch) => {
|
||||||
|
console.log("Ctrl-b pressed, toggling shouting mark...");
|
||||||
|
return toggleMark(customSchema.marks.shouting)(state, dispatch);
|
||||||
|
},
|
||||||
|
'Ctrl-q': (state, dispatch) => {
|
||||||
|
console.log("you should have just gotten an alert");
|
||||||
|
return toggleLink(state, dispatch);
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
@customElement('app-write')
|
||||||
|
export class AppWrite extends LitElement {
|
||||||
|
@property({ type: String }) placeholder: string = 'Compose your note...';
|
||||||
|
@property({ type: String }) public value?: string;
|
||||||
|
|
||||||
|
// Reference to the ProseMirror container
|
||||||
|
@query('#editor') editorContainer!: HTMLElement;
|
||||||
|
|
||||||
|
private editorView!: EditorView
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static styles = [
|
||||||
|
styles, css`
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
shouting {
|
||||||
|
all: unset; /* Remove inherited or conflicting styles */
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: red; /* Add a visible color for debugging */
|
||||||
|
}
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
protected async firstUpdated() {
|
||||||
|
console.log("Welcome to the compose page");
|
||||||
|
await this.updateComplete;
|
||||||
|
this.initializeEditor()
|
||||||
|
|
||||||
|
}
|
||||||
|
private initializeEditor() {
|
||||||
|
if (!this.editorContainer) {
|
||||||
|
console.error('Editor container not here');
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const state = EditorState.create({
|
||||||
|
schema: customSchema,
|
||||||
|
plugins: [
|
||||||
|
|
||||||
|
history(),
|
||||||
|
keymap({
|
||||||
|
'Mod-z': undo,
|
||||||
|
'Mod-y': redo,
|
||||||
|
}),
|
||||||
|
keymap(baseKeymap),
|
||||||
|
// Add the plus-button plugin here
|
||||||
|
plusButtonPlugin
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
let view = new EditorView(this.editorContainer, {
|
||||||
|
state,
|
||||||
|
dispatchTransaction(transaction) {
|
||||||
|
console.log('Document size went from', transaction.before.content.size, "to",
|
||||||
|
transaction.doc.content.size
|
||||||
|
)
|
||||||
|
let newState = view.state.apply(transaction)
|
||||||
|
view.updateState(newState)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.editorView = view;
|
||||||
|
console.log('editor initialized')
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnectedCallback(): void {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
if (this.editorView) {
|
||||||
|
this.editorView.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
return html`
|
||||||
|
<app-header ?enableBack="${true}"></app-header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div id="welcomeBar">
|
||||||
|
|
||||||
|
<sl-card id="welcomeCard">
|
||||||
|
<div slot="header">
|
||||||
|
<h2>Editor Demo</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Aren't you tired of distracting interfaces on mainstream blogging platforms?
|
||||||
|
So many buttons and advertising makes a single task very draining. This is
|
||||||
|
a platform-agnostic browser application that is installable to any homescreen! </p>
|
||||||
|
<p>
|
||||||
|
You can use a protocol to transform your personal website into
|
||||||
|
a micro blog client. Using WYSIWYG style editor builders like
|
||||||
|
ProseMirror, you can render a simple rich text editor for visitors to compose
|
||||||
|
notes with. You can type out a note and post it to a set of relays.
|
||||||
|
</p>
|
||||||
|
<h3>Basic Intructions</h3>
|
||||||
|
<p>click inside the white text area to place your curson there.
|
||||||
|
You can type and press enter to go to the next line down.
|
||||||
|
<br>
|
||||||
|
Click and hold down to select a piece of text, then CTRL+X to cut and
|
||||||
|
CTRL+V to paste.</p>
|
||||||
|
|
||||||
|
</sl-card>
|
||||||
|
<sl-card>
|
||||||
|
<div id="editor" class="ProseMirror"></div>
|
||||||
|
</sl-card>
|
||||||
|
</main>
|
||||||
|
`}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ import { title } from '@thepassle/app-tools/router/plugins/title.js';
|
||||||
|
|
||||||
import './pages/app-home.js';
|
import './pages/app-home.js';
|
||||||
|
|
||||||
|
|
||||||
const baseURL: string = (import.meta as any).env.BASE_URL;
|
const baseURL: string = (import.meta as any).env.BASE_URL;
|
||||||
|
|
||||||
export const router = new Router({
|
export const router = new Router({
|
||||||
|
@ -35,7 +36,15 @@ export const router = new Router({
|
||||||
path: resolveRouterPath('note-wall'),
|
path: resolveRouterPath('note-wall'),
|
||||||
title: 'Note Wall',
|
title: 'Note Wall',
|
||||||
render: () => html`<note-wall></note-wall>`
|
render: () => html`<note-wall></note-wall>`
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
path: resolveRouterPath('write'),
|
||||||
|
title: 'Write',
|
||||||
|
plugins: [
|
||||||
|
lazy(() => import('./pages/app-write/app-write.js')),
|
||||||
|
],
|
||||||
|
render: () => html`<app-write><app-write>`
|
||||||
|
},
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,439 @@ export const styles = css`
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
margin-top: 34px;
|
margin-top: 70px;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ProseMirror {
|
||||||
|
position: relative;
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
-webkit-font-variant-ligatures: none;
|
||||||
|
font-variant-ligatures: none;
|
||||||
|
padding: 1rem;
|
||||||
|
line-height: 1.2;
|
||||||
|
outline: none;
|
||||||
|
font-family: var(
|
||||||
|
--markdown-editor-typography-font-family,
|
||||||
|
var(--mdc-typography-font-family, Montserrat, sans-serif)
|
||||||
|
);
|
||||||
|
font-size: var(
|
||||||
|
--markdown-editor-typography-font-size,
|
||||||
|
var(--mdc-typography-subtitle1-font-size, 1rem)
|
||||||
|
);
|
||||||
|
font-weight: var(
|
||||||
|
--markdown-editor-typography-font-weight,
|
||||||
|
var(--mdc-typography-subtitle1-font-weight, 400)
|
||||||
|
);
|
||||||
|
letter-spacing: var(
|
||||||
|
--markdown-editor-typography-letter-spacing,
|
||||||
|
var(--mdc-typography-subtitle1-letter-spacing, 0.009375em)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror pre {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror li {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror p:first-child,
|
||||||
|
.ProseMirror h1:first-child,
|
||||||
|
.ProseMirror h2:first-child,
|
||||||
|
.ProseMirror h3:first-child,
|
||||||
|
.ProseMirror h4:first-child,
|
||||||
|
.ProseMirror h5:first-child,
|
||||||
|
.ProseMirror h6:first-child {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror a {
|
||||||
|
color: var(--markdown-editor-typography-anchor-color, -webkit-link);
|
||||||
|
text-decoration: var(--markdown-editor-typography-anchor-text-decoration);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror p {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-hideselection {
|
||||||
|
caret-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-hideselection *::selection,
|
||||||
|
.ProseMirror-hideselection *::-moz-selection {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-selectednode {
|
||||||
|
outline: 2px solid #8cf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure li selections wrap around markers */
|
||||||
|
li.ProseMirror-selectednode {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
li.ProseMirror-selectednode:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: -32px;
|
||||||
|
right: -2px;
|
||||||
|
top: -2px;
|
||||||
|
bottom: -2px;
|
||||||
|
border: 2px solid #8cf;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-textblock-dropdown {
|
||||||
|
min-width: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu {
|
||||||
|
margin: 0 -4px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-tooltip .ProseMirror-menu {
|
||||||
|
width: -webkit-fit-content;
|
||||||
|
width: fit-content;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menuitem {
|
||||||
|
margin: 0.25rem 0.25rem 0.25rem 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.ProseMirror-menuitem:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menuseparator {
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-dropdown,
|
||||||
|
.ProseMirror-menu-dropdown-menu {
|
||||||
|
font-size: 90%;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-dropdown {
|
||||||
|
vertical-align: 1px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-dropdown-wrap {
|
||||||
|
padding: 1px 0 1px 4px;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-dropdown:after {
|
||||||
|
content: '';
|
||||||
|
border-left: 4px solid transparent;
|
||||||
|
border-right: 4px solid transparent;
|
||||||
|
border-top: 4px solid currentColor;
|
||||||
|
opacity: 0.6;
|
||||||
|
position: absolute;
|
||||||
|
right: 4px;
|
||||||
|
top: calc(50% - 2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-dropdown-menu,
|
||||||
|
.ProseMirror-menu-submenu {
|
||||||
|
position: absolute;
|
||||||
|
background: white;
|
||||||
|
color: #666;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-dropdown-menu {
|
||||||
|
z-index: 1;
|
||||||
|
min-width: 6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-dropdown-item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-dropdown-item:hover {
|
||||||
|
background: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-dropdown-item > div {
|
||||||
|
padding: 0.375rem 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-submenu-wrap {
|
||||||
|
position: relative;
|
||||||
|
margin-right: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-submenu-label:after {
|
||||||
|
content: '';
|
||||||
|
border-top: 4px solid transparent;
|
||||||
|
border-bottom: 4px solid transparent;
|
||||||
|
border-left: 4px solid currentColor;
|
||||||
|
opacity: 0.6;
|
||||||
|
position: absolute;
|
||||||
|
right: 4px;
|
||||||
|
top: calc(50% - 4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-submenu {
|
||||||
|
display: none;
|
||||||
|
min-width: 4em;
|
||||||
|
left: 100%;
|
||||||
|
top: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-active {
|
||||||
|
background: #eee;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-submenu-wrap:hover .ProseMirror-menu-submenu,
|
||||||
|
.ProseMirror-menu-submenu-wrap-active .ProseMirror-menu-submenu {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menubar {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
position: relative;
|
||||||
|
background: white;
|
||||||
|
min-height: 1em;
|
||||||
|
overflow: visible;
|
||||||
|
z-index: 2;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
color: #666;
|
||||||
|
padding: 1px 6px;
|
||||||
|
border-top-left-radius: inherit;
|
||||||
|
border-top-right-radius: inherit;
|
||||||
|
border-bottom: 1px solid
|
||||||
|
var(--markdown-editor-outline-idle-border-color, rgba(0, 0, 0, 0.38));
|
||||||
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-icon {
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 0.8;
|
||||||
|
vertical-align: -2px;
|
||||||
|
/* Compensate for padding */
|
||||||
|
padding: 2px 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-disabled {
|
||||||
|
color: rgba(0,0,0,0.37);
|
||||||
|
background-color: rgba(0,0,0,0.12);
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-menu-disabled.ProseMirror-icon {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-icon svg {
|
||||||
|
fill: currentColor;
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-icon span {
|
||||||
|
vertical-align: text-top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-gapcursor {
|
||||||
|
display: none;
|
||||||
|
pointer-events: none;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-gapcursor:after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: -2px;
|
||||||
|
width: 20px;
|
||||||
|
border-top: 1px solid black;
|
||||||
|
animation: ProseMirror-cursor-blink 1.1s steps(2, start) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes ProseMirror-cursor-blink {
|
||||||
|
to {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-focused .ProseMirror-gapcursor {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add space around the hr to make clicking it easier */
|
||||||
|
.ProseMirror-example-setup-style hr {
|
||||||
|
padding: 2px 10px;
|
||||||
|
border: none;
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-example-setup-style hr:after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
height: 1px;
|
||||||
|
background-color: silver;
|
||||||
|
line-height: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror ul,
|
||||||
|
.ProseMirror ol {
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror blockquote {
|
||||||
|
padding-left: 1em;
|
||||||
|
border-left: 3px solid #eee;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-example-setup-style img {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror-invalid {
|
||||||
|
background: #ffc;
|
||||||
|
border: 1px solid #cc7;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
position: absolute;
|
||||||
|
min-width: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror h1.title.empty-node::before,
|
||||||
|
.ProseMirror h2.instructional-prompt.empty-node::before,
|
||||||
|
.ProseMirror h3.mechanical-promp.empty-node::before {
|
||||||
|
content: 'Enter title here...';
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror div.passage-subtitle.empty-node:first-child::before {
|
||||||
|
content: 'Enter subtitle here...';
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror div.passage-author.empty-node:first-child::before,
|
||||||
|
.ProseMirror div.passage-cast-title.empty-node:first-child::before,
|
||||||
|
.ProseMirror div.passage-act-title.empty-node:first-child::before,
|
||||||
|
.ProseMirror div.passage-scene-title.empty-node:first-child::before,
|
||||||
|
.ProseMirror div.passage-verse.empty-node:first-child::before,
|
||||||
|
.ProseMirror div.passage-footnotes.empty-node:first-child::before,
|
||||||
|
.ProseMirror div.paragraph.empty-node:first-child::before {
|
||||||
|
content: 'Enter text here...';
|
||||||
|
}
|
||||||
|
|
||||||
|
div[contenteditable]:focus h1.title.empty-node::before,
|
||||||
|
div[contenteditable]:focus h2.instructional-prompt.empty-node::before,
|
||||||
|
div[contenteditable]:focus h3.mechanical-promp.empty-node::before,
|
||||||
|
div[contenteditable]:focus
|
||||||
|
div.passage-subtitle.empty-node:first-child::before,
|
||||||
|
div[contenteditable]:focus div.passage-author.empty-node:first-child::before,
|
||||||
|
div[contenteditable]:focus
|
||||||
|
div.passage-cast-title.empty-node:first-child::before,
|
||||||
|
div[contenteditable]:focus
|
||||||
|
div.passage-act-title.empty-node:first-child::before,
|
||||||
|
div[contenteditable]:focus
|
||||||
|
div.passage-scene-title.empty-node:first-child::before,
|
||||||
|
div[contenteditable]:focus div.passage-verse.empty-node:first-child::before,
|
||||||
|
div[contenteditable]:focus
|
||||||
|
div.passage-footnotes.empty-node:first-child::before,
|
||||||
|
div[contenteditable]:focus div.paragraph.empty-node:first-child::before {
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
.ProseMirror .empty-node::before {
|
||||||
|
position: absolute;
|
||||||
|
color: #aaa;
|
||||||
|
cursor: text;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor, .editor {
|
||||||
|
background: white;
|
||||||
|
color: black;
|
||||||
|
background-clip: padding-box;
|
||||||
|
padding: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor[disabled] .ProseMirror-menubar {
|
||||||
|
display: none!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
drop-down-editor rich-text .inline-component-button,
|
||||||
|
expand-collapse rich-text .inline-component-button,
|
||||||
|
flip-reveal rich-text .inline-component-button,
|
||||||
|
hint-list rich-text .inline-component-button,
|
||||||
|
option-list rich-text .inline-component-button,
|
||||||
|
plankton-passage rich-text .inline-component-button {
|
||||||
|
pointer-events: none;
|
||||||
|
color: lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ProseMirror-icon-collection path {
|
||||||
|
fill-rule: evenodd;
|
||||||
|
}
|
||||||
|
#welcomeBar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#welcomeCard,
|
||||||
|
#infoCard {
|
||||||
|
padding: 18px;
|
||||||
|
padding-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
sl-card::part(footer) {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media(min-width: 750px) {
|
||||||
|
sl-card {
|
||||||
|
width: 70vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.boring {
|
||||||
|
background: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plus {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
padding: 8px;
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: red;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plus:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
|
||||||
`;
|
`;
|
|
@ -23,6 +23,6 @@
|
||||||
"vite/client"
|
"vite/client"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "router.d.ts"],
|
"include": ["src/**/*.ts", "router.d.ts", "src/pages/app-write"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue