From 79e8fec838b46534c266f1ec2c8d2d5bdc945b48 Mon Sep 17 00:00:00 2001 From: Sharon Stratsianis Date: Mon, 26 Oct 2026 10:59:30 +1100 Subject: [PATCH 1/2] move preferred pane function to be used by solid panes and folder pane --- package-lock.json | 4 +- package.json | 2 +- src/lib/file-explorer/relevant-panes.ts | 23 ++++++++ .../unit/file-explorer/relevant-panes.test.ts | 52 ++++++++++++++++++- test/unit/index.test.ts | 1 + 5 files changed, 78 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index b8f909a95..62ae55402 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "solid-ui", - "version": "5.0.2-3", + "version": "5.0.2-4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "solid-ui", - "version": "5.0.2-3", + "version": "5.0.2-4", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 0a97bd893..25d596ca8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "solid-ui", - "version": "5.0.2-3", + "version": "5.0.2-4", "description": "UI library for Solid applications", "main": "dist/index.cjs.js", "types": "dist/index.d.ts", diff --git a/src/lib/file-explorer/relevant-panes.ts b/src/lib/file-explorer/relevant-panes.ts index a8cf10af1..375aaaa02 100644 --- a/src/lib/file-explorer/relevant-panes.ts +++ b/src/lib/file-explorer/relevant-panes.ts @@ -1,6 +1,7 @@ import type { DataBrowserContext, PaneDefinition } from 'pane-registry' import type { NamedNode } from 'rdflib' import { filterAvailablePanes } from '@/login/login' +import ns from '@/lib/ns' export type RelevantPaneOptions = { excludedPaneNames?: readonly string[] @@ -43,3 +44,25 @@ export async function getRelevantPanes ( ? [relevantPanes[0]].concat(filteredPanes) : filteredPanes } + +/** + * Chooses the default pane from the relevant panes for a resource. + * + * A resource's `ui:mintClass` is an explicit declaration of the pane that + * created it, so it takes precedence over panes that merely request focus. + */ +export function getPreferredPane ( + subject: NamedNode, + context: DataBrowserContext, + relevantPanes: PaneDefinition[] +): PaneDefinition | undefined { + const store = context.session.store + const mintClass = store.any(subject, ns.ui('mintClass'), undefined, subject.doc()) || + store.any(subject.doc(), ns.ui('mintClass'), undefined, subject.doc()) + if (mintClass) { + const mintClassPane = relevantPanes.find(pane => pane.mintClass?.sameTerm(mintClass)) + if (mintClassPane) return mintClassPane + } + + return relevantPanes.find(pane => pane.shouldGetFocus?.(subject)) || relevantPanes[0] +} diff --git a/test/unit/file-explorer/relevant-panes.test.ts b/test/unit/file-explorer/relevant-panes.test.ts index 5dbca9b73..89ff4e301 100644 --- a/test/unit/file-explorer/relevant-panes.test.ts +++ b/test/unit/file-explorer/relevant-panes.test.ts @@ -3,7 +3,8 @@ import type { DataBrowserContext, PaneDefinition } from 'pane-registry' import { sym } from 'rdflib' import { solidLogicSingleton } from 'solid-logic' import { filterAvailablePanes } from '../../../src/login/login' -import { getRelevantPanes } from '../../../src/lib/file-explorer/relevant-panes' +import ns from '../../../src/lib/ns' +import { getPreferredPane, getRelevantPanes } from '../../../src/lib/file-explorer/relevant-panes' vi.mock('../../../src/login/login', () => ({ filterAvailablePanes: vi.fn() @@ -128,3 +129,52 @@ describe('getRelevantPanes', () => { await expect(getRelevantPanes(subject, createContext([createPane('first')]))).rejects.toBe(error) }) }) + +describe('getPreferredPane', () => { + function contextWithMintClass (mintClass?: string): DataBrowserContext { + const store = Object.create(solidLogicSingleton.store) + store.any = vi.fn((candidate, predicate) => { + if (mintClass && candidate.sameTerm(subject) && predicate.sameTerm(ns.ui('mintClass'))) { + return sym(mintClass) + } + return undefined + }) + return { + dom: document, + getOutliner: () => undefined, + session: { + logic: solidLogicSingleton, + store, + paneRegistry: { + list: [], + paneForIcon: {}, + paneForPredicate: {}, + register: vi.fn(), + byName: () => null + } + } + } + } + + it('prefers the pane matching a resource mint class over a focus request', () => { + const mintClass = sym('https://schema.example/PhotoAlbum') + const focus = createPane('focus', { shouldGetFocus: () => true }) + const minted = createPane('album', { mintClass }) + + expect(getPreferredPane(subject, contextWithMintClass(mintClass.uri), [focus, minted])).toBe(minted) + }) + + it('uses a focus request when no relevant pane matches the mint class', () => { + const focus = createPane('focus', { shouldGetFocus: () => true }) + const other = createPane('other', { mintClass: sym('https://schema.example/Other') }) + + expect(getPreferredPane(subject, contextWithMintClass('https://schema.example/PhotoAlbum'), [other, focus])).toBe(focus) + }) + + it('falls back to registry order when no pane requests focus', () => { + const first = createPane('first') + const second = createPane('second') + + expect(getPreferredPane(subject, contextWithMintClass(), [first, second])).toBe(first) + }) +}) diff --git a/test/unit/index.test.ts b/test/unit/index.test.ts index 33bf40ebb..b030f2526 100644 --- a/test/unit/index.test.ts +++ b/test/unit/index.test.ts @@ -37,6 +37,7 @@ describe('Index', () => { 'dom', 'fileExplorerContext', 'generateId', + 'getPreferredPane', 'getRelevantPanes', 'icons', 'infiniteMessageArea', From 8c0fea5235616f2e4eb6d09a99cb6758f6be51cd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 26 Oct 2026 00:13:36 +0000 Subject: [PATCH 2/2] chore: update solidos dependencies (dev: solid-logic@6.0.1-4 pane-registry@5.0.2-1) (latest: rdflib@2.4.1) --- package-lock.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 62ae55402..538c41d44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3478,9 +3478,9 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.5.tgz", - "integrity": "sha512-HshSvXzmBxNzqejd3k/KemgQ3hdREUYFRRrgxOZ+gPljDIsO2SDZrVZMd4Z/HsxudQbE62OVyVFE8z9BCurfjA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.6.tgz", + "integrity": "sha512-mRyDmEw9/fCDXCGfL1sbgIw/GUK0PVxRW4YwgPN61F3LQ+fSyoBFarJVzgGyhF6kRzEQZ0FejDqm4WLXSeqQmw==", "dev": true, "license": "MIT", "optional": true, @@ -3495,8 +3495,8 @@ "url": "https://github.com/sponsors/Brooooooklyn" }, "peerDependencies": { - "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", - "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + "@emnapi/core": "^1.7.1 || 2.0.0-beta.2", + "@emnapi/runtime": "^1.7.1 || 2.0.0-beta.2" } }, "node_modules/@nicolo-ribaudo/chokidar-2": { @@ -6762,9 +6762,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.11.32", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.32.tgz", - "integrity": "sha512-UvuxFU9P3hM29LrQdwu0cD6w6/+SFr+UlB9s/knI7+O2rK9xFxKUwSDWxGdbbqQ9/V7BJ5s0NI5nQAE4uJp3gQ==", + "version": "2.11.33", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.33.tgz", + "integrity": "sha512-yiVKDX+qCMRKBE084lXvq9EcwFUhKZ2nU8TK1EQQuOgPNR/lmbGxXOeDdlGUqC2Zz11Cs9rk1d/8NfgBmlkt0w==", "dev": true, "license": "Apache-2.0", "bin": {