diff --git a/package-lock.json b/package-lock.json index e98d7db9..5e600704 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@solid/better-simple-slideshow": "^0.1.0", "activitystreams-pane": "2.0.0-0", "chat-pane": "4.0.0-0", - "contacts-pane": "3.2.1-6", + "contacts-pane": "4.0.0-0", "dompurify": "^3.4.4", "folder-pane": "4.0.0-0", "issue-pane": "4.0.0-0", @@ -21,12 +21,12 @@ "meeting-pane": "4.0.0-0", "mime-types": "^3.0.2", "pane-registry": "5.0.0-0", - "profile-pane": "3.2.3-4", + "profile-pane": "4.0.0-0", "rdflib": "2.4.0", "solid-logic": "6.0.0-0", "solid-namespace": "^0.5.4", "solid-ui": "5.0.0-0", - "source-pane": "3.1.1-7" + "source-pane": "4.0.0-0" }, "devDependencies": { "@iconify/json": "2.2.494", @@ -123,9 +123,9 @@ "license": "MIT" }, "node_modules/@awesome.me/webawesome": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/@awesome.me/webawesome/-/webawesome-3.11.0.tgz", - "integrity": "sha512-WM8kyP+AdAT3/zwNpc/YzN3Nu5pRD6ksREFZAct/DIn6KMnQs8lPVfiPbJrOpKMk8OaSnQX19iiwFGjoswXVXw==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@awesome.me/webawesome/-/webawesome-3.12.0.tgz", + "integrity": "sha512-cO/vSvlyZqiki1upynxpk9q2N48U2+nflIj40OtCKYOs6ZXa4zXhW6+asXKOfeNw1AnD4nzsSIdZSt/Ti9QONA==", "license": "MIT", "dependencies": { "@ctrl/tinycolor": "4.1.0", @@ -2977,9 +2977,9 @@ } }, "node_modules/@marijn/find-cluster-break": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.3.tgz", - "integrity": "sha512-FY+MKLBoTsLNJF/eLWaOsXGdz6uh3Iu1axjPf6TUq92IYumcTcXWHoS747JARLkcdlJ/Waiaxc5wQfFO8jC6NA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.4.tgz", + "integrity": "sha512-Wy0V7+SGUjnF9/TkiM1hKVDPj7jKXduPNboMVtHTA8dySMURWqfg/JZ9E2Sq8JgSJmkl7k7Qe9FLeMSrSraWmQ==", "license": "MIT" }, "node_modules/@noble/curves": { @@ -3988,9 +3988,9 @@ } }, "node_modules/@xmldom/xmldom": { - "version": "0.9.11", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.11.tgz", - "integrity": "sha512-tW8bcK3hsG0/uqSnNz6TK4BkcuZSezoU7DlnYssILmZDktPnSHHuDJJFM0AJv+13gz2r0iGdrj6qqKeUnxXEDg==", + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.12.tgz", + "integrity": "sha512-5AXjrcMClTryPe9LgZrygpB1lj7s0S9E0+W+AHaVKAVyHanafK86iPSvG5xHVSp/jC+VH1UXu0TAEmY279xH7A==", "license": "MIT", "engines": { "node": ">=14.6" @@ -4409,9 +4409,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.11.16", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.16.tgz", - "integrity": "sha512-H/bNPUFHewJHyCTdjn1n3Pit5+2GmWT6mmeHImPX+8MA9NA6b67jO4gYmi4jTbCJb2otq34KMZnovndDPqJwhQ==", + "version": "2.11.18", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.18.tgz", + "integrity": "sha512-1iEmLEYSiE1SeBoAfPo/Mnx3PzfzHUkDK61ASkCpuk3YXugYLH5DYK1SzqV55F8FMI6s0F+/tCP7Polz1QRjxw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4734,13 +4734,17 @@ "license": "MIT" }, "node_modules/contacts-pane": { - "version": "3.2.1-6", - "resolved": "https://registry.npmjs.org/contacts-pane/-/contacts-pane-3.2.1-6.tgz", - "integrity": "sha512-Mf8OCx5Jp4bgTOI0QdDp/Ecs0Pl2SWqriqM/HSnVJ1Q69WOi081pBymR6shL4cP0hv2SHEBy7sjABTXEqjqMrg==", + "version": "4.0.0-0", + "resolved": "https://registry.npmjs.org/contacts-pane/-/contacts-pane-4.0.0-0.tgz", + "integrity": "sha512-gGrXVp3w0bgSxu51WWrrmGZgXm361E9AM/0qLsOwfpqdTV3oLYga6WGpuMBeiuBps8Ya3Go3bzDY2D1FyDGDLA==", "license": "MIT", "dependencies": { "@lit/context": "^1.1.6", - "lit": "^3.3.3" + "lit": "^3.3.3", + "pane-registry": "5.0.0-0", + "rdflib": "2.4.0", + "solid-logic": "6.0.0-0", + "solid-ui": "5.0.0-0" } }, "node_modules/convert-source-map": { @@ -5158,9 +5162,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.411", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.411.tgz", - "integrity": "sha512-gglkxzokjHfawpGxq75XdBV2/l3BAPzrsMs70qgaZdTW5rpV1tC4MdgJVP9fN126bODA4ZJQkn1wryEzJyQXIg==", + "version": "1.5.412", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.412.tgz", + "integrity": "sha512-z4rMe3esBzlzovKHj4gxJnsCGZRK5l4baUvm+gCGJBPE+gsyUMKsuU9tnEUtI1dOebXz1ytAPGjvXhmQ7rIPwA==", "dev": true, "license": "ISC" }, @@ -9231,89 +9235,26 @@ "license": "MIT" }, "node_modules/profile-pane": { - "version": "3.2.3-4", - "resolved": "https://registry.npmjs.org/profile-pane/-/profile-pane-3.2.3-4.tgz", - "integrity": "sha512-mtbOfS37mFazMu+3h0YaUP4BMqVvzAB4Mvlt9jivl41XQIBxulKP+xhKw2GSI6A4wGs9SIMa8JB7ykQJqiC1bg==", + "version": "4.0.0-0", + "resolved": "https://registry.npmjs.org/profile-pane/-/profile-pane-4.0.0-0.tgz", + "integrity": "sha512-Pl9VFKRACkAwMOkJO6CWTpWkvJLMRacdy9P1ODhkaD5wN84ABNzFooqq6RoKFoHlVOUzzmac3fkLVxzmPO0wXw==", "license": "MIT", "dependencies": { "@solid-data-modules/contacts-rdflib": "^0.7.1", - "chat-pane": "3.0.4-3", + "chat-pane": "4.0.0-0", "lit-html": "^3.3.3", - "pane-registry": "3.1.2-2", + "pane-registry": "5.0.0-0", "patch-package": "^8.0.1", "qrcode": "^1.5.4", "rdflib": "2.4.0", - "solid-logic": "4.0.8-1", - "solid-ui": "3.1.3-13", + "solid-logic": "6.0.0-0", + "solid-ui": "5.0.0-0", "validate-color": "^2.2.4", "vite": "^8.0.16", "vitest": "^4.0.18", "vitest-axe": "^0.1.0" } }, - "node_modules/profile-pane/node_modules/chat-pane": { - "version": "3.0.4-3", - "resolved": "https://registry.npmjs.org/chat-pane/-/chat-pane-3.0.4-3.tgz", - "integrity": "sha512-m099X1Lb1qaOtaYNAaJ+NfqD/TMRnhX3Gfx5Xgb2HoZYllaxn1xN3Y5Am4Un21k6tLoPaiq1OIkBe09/gHN/sw==", - "license": "MIT", - "dependencies": { - "pane-registry": "3.1.2-2", - "patch-package": "^8.0.1", - "rdflib": "^2.3.9", - "solid-logic": "^4.0.8-0", - "solid-ui": "3.1.3-13", - "vite": "^8.0.16", - "vitest": "^4.0.18", - "vitest-axe": "^0.1.0" - } - }, - "node_modules/profile-pane/node_modules/pane-registry": { - "version": "3.1.2-2", - "resolved": "https://registry.npmjs.org/pane-registry/-/pane-registry-3.1.2-2.tgz", - "integrity": "sha512-w+pCan1Umj+pLm5/uNlBMLw0YOKbKhHn5Qh62oqlKlbFrSHj4H3gNOXcKnI47liQFPQYepw5UPssP3aPdiowvA==", - "license": "MIT", - "dependencies": { - "rdflib": "2.4.0", - "solid-logic": "4.0.8-1" - } - }, - "node_modules/profile-pane/node_modules/solid-logic": { - "version": "4.0.8-1", - "resolved": "https://registry.npmjs.org/solid-logic/-/solid-logic-4.0.8-1.tgz", - "integrity": "sha512-9Vtg9ukEaDTIvBPqECORWRtEJ3nTlEvInJzUCJZDp1qjN9VIdJG0mSiPTIP9RXOEOSAA+Q+cP3d7BzsNyI/RVA==", - "license": "MIT", - "dependencies": { - "@uvdsl/solid-oidc-client-browser": "^0.2.3", - "solid-namespace": "^0.5.4" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/profile-pane/node_modules/solid-ui": { - "version": "3.1.3-13", - "resolved": "https://registry.npmjs.org/solid-ui/-/solid-ui-3.1.3-13.tgz", - "integrity": "sha512-0meJycoMXoelTD06W9A0S9Q4vg0I8BDSsui4BfwocfwFIpEZ02FBFZZf1LcanP7NNpAOs0So6HOQp4QlwSJE3w==", - "license": "MIT", - "dependencies": { - "@awesome.me/webawesome": "^3.9.0", - "@lit/context": "^1.1.6", - "@lit/task": "^1.0.3", - "@noble/curves": "^2.2.0", - "@noble/hashes": "^2.2.0", - "escape-html": "^1.0.3", - "lit": "^3.3.3", - "mime-types": "^3.0.2", - "pane-registry": "3.1.2-2", - "rdflib": "2.4.0", - "solid-logic": "4.0.8-1", - "solid-namespace": "^0.5.4", - "uuid": "^14.0.0" - }, - "optionalDependencies": { - "fsevents": "*" - } - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -10230,97 +10171,23 @@ } }, "node_modules/source-pane": { - "version": "3.1.1-7", - "resolved": "https://registry.npmjs.org/source-pane/-/source-pane-3.1.1-7.tgz", - "integrity": "sha512-fssbKBXlm16/YA8S/5W/YNUZILlR54DeC71CIr5j0FJx/R8Ts2b7ClMtdpFput39vW7+WCpSH1NkBW+k97157w==", + "version": "4.0.0-0", + "resolved": "https://registry.npmjs.org/source-pane/-/source-pane-4.0.0-0.tgz", + "integrity": "sha512-kjo/pMUyN0JsOyVmNYNxwm+SId0cgHXETx+gIyjCIbGoxknH4BHUkTyCz2KTkS71QZXk2QLG2VmCCaUAehUOpA==", "license": "MIT", "dependencies": { "@lit/context": "^1.1.6", "@typescript-eslint/parser": "^8.63.0", "lit": "^3.3.3", - "pane-registry": "3.1.2-2", + "pane-registry": "5.0.0-0", "rdflib": "2.4.0", - "solid-logic": "4.0.8-3", - "solid-ui": "3.1.3-17", + "solid-logic": "6.0.0-0", + "solid-ui": "5.0.0-0", "vite": "^8.0.16", "vitest": "^4.0.18", "vitest-axe": "^0.1.0" } }, - "node_modules/source-pane/node_modules/pane-registry": { - "version": "3.1.2-2", - "resolved": "https://registry.npmjs.org/pane-registry/-/pane-registry-3.1.2-2.tgz", - "integrity": "sha512-w+pCan1Umj+pLm5/uNlBMLw0YOKbKhHn5Qh62oqlKlbFrSHj4H3gNOXcKnI47liQFPQYepw5UPssP3aPdiowvA==", - "license": "MIT", - "dependencies": { - "rdflib": "2.4.0", - "solid-logic": "4.0.8-1" - } - }, - "node_modules/source-pane/node_modules/pane-registry/node_modules/solid-logic": { - "version": "4.0.8-1", - "resolved": "https://registry.npmjs.org/solid-logic/-/solid-logic-4.0.8-1.tgz", - "integrity": "sha512-9Vtg9ukEaDTIvBPqECORWRtEJ3nTlEvInJzUCJZDp1qjN9VIdJG0mSiPTIP9RXOEOSAA+Q+cP3d7BzsNyI/RVA==", - "license": "MIT", - "dependencies": { - "@uvdsl/solid-oidc-client-browser": "^0.2.3", - "solid-namespace": "^0.5.4" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/source-pane/node_modules/solid-logic": { - "version": "4.0.8-3", - "resolved": "https://registry.npmjs.org/solid-logic/-/solid-logic-4.0.8-3.tgz", - "integrity": "sha512-0HKcZJb5ZF2MvFzOid26LMilgL6jD1zaRpix5nb2fB1h3H9WB0kquyD/297L6jIiUTIYSMlVb7ivpvkiVNTTNQ==", - "license": "MIT", - "dependencies": { - "@uvdsl/solid-oidc-client-browser": "^0.2.3", - "solid-namespace": "^0.5.4", - "vite": "^8.0.16", - "vitest": "^4.1.9" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/source-pane/node_modules/solid-ui": { - "version": "3.1.3-17", - "resolved": "https://registry.npmjs.org/solid-ui/-/solid-ui-3.1.3-17.tgz", - "integrity": "sha512-XVnz8u3lhW0AhmywMlEOif23lYkQcCmWiL5NUf8A5kmz3Ixw3E/qGiqmPpJ8VAOPZhEsj8+G7u+Y6pUDmhrLeA==", - "license": "MIT", - "dependencies": { - "@awesome.me/webawesome": "^3.9.0", - "@codemirror/commands": "^6.10.0", - "@codemirror/lang-css": "^6.3.1", - "@codemirror/lang-html": "^6.4.11", - "@codemirror/lang-javascript": "^6.2.5", - "@codemirror/lang-json": "^6.0.2", - "@codemirror/lang-markdown": "^6.3.1", - "@codemirror/lang-xml": "^6.1.0", - "@codemirror/language": "^6.12.3", - "@codemirror/legacy-modes": "^6.5.3", - "@codemirror/state": "^6.6.0", - "@codemirror/view": "^6.43.0", - "@lit/context": "^1.1.6", - "@lit/task": "^1.0.3", - "@noble/curves": "^2.2.0", - "@noble/hashes": "^2.2.0", - "@uiw/codemirror-theme-vscode": "^4.25.10", - "escape-html": "^1.0.3", - "lit": "^3.3.3", - "mime-types": "^3.0.2", - "pane-registry": "3.1.2-2", - "rdflib": "2.4.0", - "solid-logic": "4.0.8-3", - "solid-namespace": "^0.5.4", - "uuid": "^14.0.0" - }, - "optionalDependencies": { - "fsevents": "*" - } - }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", diff --git a/package.json b/package.json index cad7d4ac..4b199aec 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "@solid/better-simple-slideshow": "^0.1.0", "activitystreams-pane": "2.0.0-0", "chat-pane": "4.0.0-0", - "contacts-pane": "3.2.1-6", + "contacts-pane": "4.0.0-0", "dompurify": "^3.4.4", "folder-pane": "4.0.0-0", "issue-pane": "4.0.0-0", @@ -68,12 +68,12 @@ "meeting-pane": "4.0.0-0", "mime-types": "^3.0.2", "pane-registry": "5.0.0-0", - "profile-pane": "3.2.3-4", + "profile-pane": "4.0.0-0", "rdflib": "2.4.0", "solid-logic": "6.0.0-0", "solid-namespace": "^0.5.4", "solid-ui": "5.0.0-0", - "source-pane": "3.1.1-7" + "source-pane": "4.0.0-0" }, "overrides": { "rdflib": "$rdflib" diff --git a/src/RDFXMLPane.css b/src/RDFXMLPane.css index eb43c5e7..e642331e 100644 --- a/src/RDFXMLPane.css +++ b/src/RDFXMLPane.css @@ -1,74 +1,6 @@ .rdfxml-pane { - padding: 1rem; width: 100%; min-width: 0; - border-top: solid 2px var(--color-data-pane-border-top, black); - border-left: solid 2px var(--color-data-pane-border-top, black); - border-bottom: solid 2px var(--color-data-pane-border-side, #777); - border-right: solid 2px var(--color-data-pane-border-side, #777); - color: var(--color-text-brown, #440); + border: 1px solid var(--solid-ui-color-slate-200, #E2E8F0); box-sizing: border-box; } - -.rdfxml-pane__source { - overflow-x: auto; - max-width: 100%; - min-width: 0; - box-sizing: border-box; - font-family: monospace; - font-size: 120%; - margin: 0; - white-space: pre; -} - -.rdfxml-pane__line { - display: grid; - grid-template-columns: var(--rdfxml-indent, 0) minmax(0, 1fr); - align-items: start; - min-width: 0; -} - -.rdfxml-pane__line-indent { - display: block; - width: var(--rdfxml-indent, 0); -} - -.rdfxml-pane__line-content { - white-space: pre; -} - -.rdfxml-pane[data-layout='mobile'] .rdfxml-pane__source { - overflow-wrap: anywhere; - word-break: break-word; - white-space: normal; -} - -.rdfxml-pane[data-layout='mobile'] .rdfxml-pane__line { - grid-template-columns: var(--rdfxml-indent, 0) minmax(0, 1fr); -} - -.rdfxml-pane[data-layout='mobile'] .rdfxml-pane__line-content { - white-space: pre-wrap; - overflow-wrap: anywhere; - word-break: break-word; - min-width: 0; -} - -@media (max-width: 576px) { - .rdfxml-pane__source { - overflow-wrap: anywhere; - word-break: break-word; - white-space: normal; - } - - .rdfxml-pane__line { - grid-template-columns: var(--rdfxml-indent, 0) minmax(0, 1fr); - } - - .rdfxml-pane__line-content { - white-space: pre-wrap; - overflow-wrap: anywhere; - word-break: break-word; - min-width: 0; - } -} diff --git a/src/RDFXMLPane.ts b/src/RDFXMLPane.ts index cee48c77..0617deeb 100644 --- a/src/RDFXMLPane.ts +++ b/src/RDFXMLPane.ts @@ -5,13 +5,11 @@ ** in generated N3 syntax. */ -import * as UI from 'solid-ui' -import * as $rdf from 'rdflib' -import type { DataBrowserContext, RenderEnvironment } from 'pane-registry' -import type { NamedNode, Statement } from 'rdflib' +import { ns, icons } from 'solid-ui' +import type { DataBrowserContext } from 'pane-registry' +import { Serializer, type NamedNode, type Statement } from 'rdflib' import './RDFXMLPane.css' - -const ns = UI.ns +import './components/editor-card' type RDFXMLPaneDefinition = { icon: string @@ -21,32 +19,8 @@ type RDFXMLPaneDefinition = { render: (subject: NamedNode, context: DataBrowserContext) => HTMLDivElement } -function leadingIndentWidth (line: string): number { - if (line.trim().length === 0) { - return 0 - } - - let width = 0 - for (const character of line) { - if (character === ' ') { - width += 1 - continue - } - if (character === '\t') { - width += 2 - continue - } - break - } - return Math.max(width, 2) -} - -function trimLeadingIndent (line: string): string { - return line.replace(/^[ \t]+/, '') -} - export const RDFXMLPane: RDFXMLPaneDefinition = { - icon: UI.icons.originalIconBase + '22-text-xml4.png', + icon: icons.originalIconBase + '22-text-xml4.png', name: 'RDFXML', @@ -74,60 +48,30 @@ export const RDFXMLPane: RDFXMLPaneDefinition = { const myDocument = context.dom const kb = context.session.store - function applyEnvironmentAttributes (element: HTMLDivElement): void { - const environment = (context.environment ?? {}) as Partial - element.dataset.layout = environment.layout ?? 'desktop' - } - const div = myDocument.createElement('div') div.setAttribute('class', 'rdfxml-pane') - applyEnvironmentAttributes(div) // Because of smushing etc, this will not be a copy of the original source // We could instead either fetch and re-parse the source, // or we could keep all the pre-smushed triples. - const sts = kb.statementsMatching( + const statements = kb.statementsMatching( undefined, undefined, undefined, subject - ) as Statement[] // @@ slow with current store! - /* - var kludge = kb.formula([]) // No features - for (var i=0; i< sts.length; i++) { - s = sts[i] - kludge.add(s.subject, s.predicate, s.object) - } - */ - const sz = $rdf.Serializer(kb) + ) as Statement[] + + const sz = Serializer(kb) sz.suggestNamespaces(kb.namespaces) sz.setBase(subject.uri) - const str = sz.statementsToXML(sts) - const source = myDocument.createElement('div') - source.classList.add('rdfxml-pane__source') - - str.split('\n').forEach(line => { - const lineElement = myDocument.createElement('div') - const indentElement = myDocument.createElement('span') - const contentElement = myDocument.createElement('span') - const indentWidth = leadingIndentWidth(line) - - lineElement.classList.add('rdfxml-pane__line') - lineElement.style.setProperty('--rdfxml-indent', `${indentWidth}ch`) - - indentElement.classList.add('rdfxml-pane__line-indent') - indentElement.setAttribute('aria-hidden', 'true') - - contentElement.classList.add('rdfxml-pane__line-content') - contentElement.textContent = line.length > 0 ? trimLeadingIndent(line) : ' ' - - lineElement.appendChild(indentElement) - lineElement.appendChild(contentElement) - source.appendChild(lineElement) - }) + const serializedContent = sz.statementsToXML(statements) + const source = myDocument.createElement('solid-panes-editor-card') as HTMLElement & { + contentType?: string + content?: string + } + source.contentType = 'application/rdf+xml' + source.content = serializedContent div.appendChild(source) return div } } - -// ends diff --git a/src/components/editor-card/EditorCard.styles.css b/src/components/editor-card/EditorCard.styles.css new file mode 100644 index 00000000..a537c8bd --- /dev/null +++ b/src/components/editor-card/EditorCard.styles.css @@ -0,0 +1,27 @@ +:host { + display: block; + width: 100%; + height: 100%; + + section { + display: flex; + flex-direction: column; + width: 100%; + height: 100%; + min-height: 0; + margin: 0; + padding: 0px 40px 25px; + } + + .editor { + flex: 1 1 auto; + width: 100%; + min-height: 0; + } + + @media (max-width: 768px) { + section { + padding: 0px 0px 25px; + } + } +} diff --git a/src/components/editor-card/EditorCard.ts b/src/components/editor-card/EditorCard.ts new file mode 100644 index 00000000..d3dd4300 --- /dev/null +++ b/src/components/editor-card/EditorCard.ts @@ -0,0 +1,78 @@ +import { html } from 'lit' +import { customElement, property, query } from 'lit/decorators.js' +import { WebComponent, type CodeEditor } from 'solid-ui' +import styles from './EditorCard.styles.css' + +@customElement('solid-panes-editor-card') +export default class EditorCard extends WebComponent { + static styles = styles + + private _editor?: CodeEditor + private _initializing = false + + @query('.editor') + accessor _editorMount: HTMLDivElement | null = null + + @property() + accessor contentType: string | undefined + + @property() + accessor content: string | undefined + + getEditor () { + return this._editor + } + + setReadOnly (readOnly: boolean) { + this._editor?.setReadOnly(readOnly) + } + + private async _initializeEditor () { + if (this._editor || this._initializing) return + this._initializing = true + const editorDiv = this._editorMount + + if (!editorDiv) { + this._initializing = false + return + } + + try { + const { CodeEditor } = await import('solid-ui') + this._editor = new CodeEditor() + try { + await this._editor.initialize(editorDiv, this.content ?? '', this.contentType ?? '', 'dark') + } catch (err) { + throw new Error(`Error initializing code editor: ${err instanceof Error ? err.message : String(err)}`) + } + this._editor?.setReadOnly(true) + } catch (err) { + // TODO: Bring in error handling and debug + console.log('Error loading CodeEditor module:', err) + } finally { + this._initializing = false + } + } + + async firstUpdated () { + await this._initializeEditor() + } + + disconnectedCallback () { + super.disconnectedCallback() + if (this._editor) { + this._editor.destroy() + this._editor = undefined + } + + this._initializing = false + } + + render () { + return html` +
+
+
+ ` + } +} diff --git a/src/components/editor-card/index.ts b/src/components/editor-card/index.ts new file mode 100644 index 00000000..94218f92 --- /dev/null +++ b/src/components/editor-card/index.ts @@ -0,0 +1,4 @@ +import EditorCard from './EditorCard' + +export { EditorCard } +export default EditorCard diff --git a/src/n3Pane.css b/src/n3Pane.css index df359447..7c67b1b8 100644 --- a/src/n3Pane.css +++ b/src/n3Pane.css @@ -1,52 +1,6 @@ .n3-pane { - padding: 1rem; width: 100%; min-width: 0; - border-top: solid 1px var(--color-data-pane-border-top, black); - border-left: solid 1px var(--color-data-pane-border-top, black); - border-bottom: solid 1px var(--color-data-pane-border-side, #777); - border-right: solid 1px var(--color-data-pane-border-side, #777); - color: var(--color-text-blue, #004); + border: 1px solid var(--solid-ui-color-slate-200, #E2E8F0); box-sizing: border-box; } - -.n3-pane__source { - overflow-x: auto; - max-width: 100%; - min-width: 0; - box-sizing: border-box; - font-family: monospace; - font-size: 120%; - margin: 0; - white-space: pre; -} - -.n3-pane__line { - white-space: pre; -} - -.n3-pane[data-layout='mobile'] .n3-pane__source { - overflow-wrap: anywhere; - word-break: break-word; - white-space: normal; -} - -.n3-pane[data-layout='mobile'] .n3-pane__line { - white-space: pre-wrap; - padding-left: var(--n3-indent, 0); - text-indent: calc(-1 * var(--n3-indent, 0)); -} - -@media (max-width: 576px) { - .n3-pane__source { - overflow-wrap: anywhere; - word-break: break-word; - white-space: normal; - } - - .n3-pane__line { - white-space: pre-wrap; - padding-left: var(--n3-indent, 0); - text-indent: calc(-1 * var(--n3-indent, 0)); - } -} \ No newline at end of file diff --git a/src/n3Pane.ts b/src/n3Pane.ts index 6e40fdf7..db76751b 100644 --- a/src/n3Pane.ts +++ b/src/n3Pane.ts @@ -6,9 +6,10 @@ */ import * as UI from 'solid-ui' import * as $rdf from 'rdflib' -import type { DataBrowserContext, RenderEnvironment } from 'pane-registry' +import type { DataBrowserContext } from 'pane-registry' import type { NamedNode, Statement } from 'rdflib' import './n3Pane.css' +import './components/editor-card' const ns = UI.ns @@ -20,26 +21,6 @@ type N3PaneLike = { render: (subject: NamedNode, context: DataBrowserContext) => HTMLDivElement } -function leadingIndentWidth (line: string): number { - if (line.trim().length === 0) { - return 0 - } - - let width = 0 - for (const character of line) { - if (character === ' ') { - width += 1 - continue - } - if (character === '\t') { - width += 2 - continue - } - break - } - return Math.max(width, 2) -} - export const n3Pane: N3PaneLike = { icon: UI.icons.originalIconBase + 'w3c/n3_smaller.png', @@ -68,45 +49,28 @@ export const n3Pane: N3PaneLike = { const myDocument = context.dom const kb = context.session.store - function applyEnvironmentAttributes (element: HTMLDivElement): void { - const environment = (context.environment ?? {}) as Partial - element.dataset.layout = environment.layout ?? 'desktop' - } - const div = myDocument.createElement('div') div.setAttribute('class', 'n3-pane') - applyEnvironmentAttributes(div) // Because of smushing etc, this will not be a copy of the original source // We could instead either fetch and re-parse the source, // or we could keep all the pre-smushed triples. - const sts = kb.statementsMatching( + const statements = kb.statementsMatching( undefined, undefined, undefined, subject ) as Statement[] // @@ slow with current store! - /* - var kludge = kb.formula([]) // No features - for (var i=0; i< sts.length; i++) { - s = sts[i] - kludge.add(s.subject, s.predicate, s.object) - } - */ + const sz = $rdf.Serializer(kb) sz.suggestNamespaces(kb.namespaces) sz.setBase(subject.uri) - const str = sz.statementsToN3(sts) - const source = myDocument.createElement('div') - source.classList.add('n3-pane__source') - - str.split('\n').forEach(line => { - const lineElement = myDocument.createElement('div') - const indentWidth = leadingIndentWidth(line) - lineElement.classList.add('n3-pane__line') - lineElement.style.setProperty('--n3-indent', `${indentWidth}ch`) - lineElement.textContent = line.length > 0 ? line : ' ' - source.appendChild(lineElement) - }) + const serializedContent = sz.statementsToN3(statements) + const source = myDocument.createElement('solid-panes-editor-card') as HTMLElement & { + contentType?: string + content?: string + } + source.contentType = 'text/n3' + source.content = serializedContent div.appendChild(source) return div