Skip to content

Commit 79e8fec

Browse files
committed
move preferred pane function to be used by solid panes and folder pane
1 parent fa85928 commit 79e8fec

5 files changed

Lines changed: 78 additions & 4 deletions

File tree

‎package-lock.json‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "solid-ui",
3-
"version": "5.0.2-3",
3+
"version": "5.0.2-4",
44
"description": "UI library for Solid applications",
55
"main": "dist/index.cjs.js",
66
"types": "dist/index.d.ts",

‎src/lib/file-explorer/relevant-panes.ts‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { DataBrowserContext, PaneDefinition } from 'pane-registry'
22
import type { NamedNode } from 'rdflib'
33
import { filterAvailablePanes } from '@/login/login'
4+
import ns from '@/lib/ns'
45

56
export type RelevantPaneOptions = {
67
excludedPaneNames?: readonly string[]
@@ -43,3 +44,25 @@ export async function getRelevantPanes (
4344
? [relevantPanes[0]].concat(filteredPanes)
4445
: filteredPanes
4546
}
47+
48+
/**
49+
* Chooses the default pane from the relevant panes for a resource.
50+
*
51+
* A resource's `ui:mintClass` is an explicit declaration of the pane that
52+
* created it, so it takes precedence over panes that merely request focus.
53+
*/
54+
export function getPreferredPane (
55+
subject: NamedNode,
56+
context: DataBrowserContext,
57+
relevantPanes: PaneDefinition[]
58+
): PaneDefinition | undefined {
59+
const store = context.session.store
60+
const mintClass = store.any(subject, ns.ui('mintClass'), undefined, subject.doc()) ||
61+
store.any(subject.doc(), ns.ui('mintClass'), undefined, subject.doc())
62+
if (mintClass) {
63+
const mintClassPane = relevantPanes.find(pane => pane.mintClass?.sameTerm(mintClass))
64+
if (mintClassPane) return mintClassPane
65+
}
66+
67+
return relevantPanes.find(pane => pane.shouldGetFocus?.(subject)) || relevantPanes[0]
68+
}

‎test/unit/file-explorer/relevant-panes.test.ts‎

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import type { DataBrowserContext, PaneDefinition } from 'pane-registry'
33
import { sym } from 'rdflib'
44
import { solidLogicSingleton } from 'solid-logic'
55
import { filterAvailablePanes } from '../../../src/login/login'
6-
import { getRelevantPanes } from '../../../src/lib/file-explorer/relevant-panes'
6+
import ns from '../../../src/lib/ns'
7+
import { getPreferredPane, getRelevantPanes } from '../../../src/lib/file-explorer/relevant-panes'
78

89
vi.mock('../../../src/login/login', () => ({
910
filterAvailablePanes: vi.fn()
@@ -128,3 +129,52 @@ describe('getRelevantPanes', () => {
128129
await expect(getRelevantPanes(subject, createContext([createPane('first')]))).rejects.toBe(error)
129130
})
130131
})
132+
133+
describe('getPreferredPane', () => {
134+
function contextWithMintClass (mintClass?: string): DataBrowserContext {
135+
const store = Object.create(solidLogicSingleton.store)
136+
store.any = vi.fn((candidate, predicate) => {
137+
if (mintClass && candidate.sameTerm(subject) && predicate.sameTerm(ns.ui('mintClass'))) {
138+
return sym(mintClass)
139+
}
140+
return undefined
141+
})
142+
return {
143+
dom: document,
144+
getOutliner: () => undefined,
145+
session: {
146+
logic: solidLogicSingleton,
147+
store,
148+
paneRegistry: {
149+
list: [],
150+
paneForIcon: {},
151+
paneForPredicate: {},
152+
register: vi.fn(),
153+
byName: () => null
154+
}
155+
}
156+
}
157+
}
158+
159+
it('prefers the pane matching a resource mint class over a focus request', () => {
160+
const mintClass = sym('https://schema.example/PhotoAlbum')
161+
const focus = createPane('focus', { shouldGetFocus: () => true })
162+
const minted = createPane('album', { mintClass })
163+
164+
expect(getPreferredPane(subject, contextWithMintClass(mintClass.uri), [focus, minted])).toBe(minted)
165+
})
166+
167+
it('uses a focus request when no relevant pane matches the mint class', () => {
168+
const focus = createPane('focus', { shouldGetFocus: () => true })
169+
const other = createPane('other', { mintClass: sym('https://schema.example/Other') })
170+
171+
expect(getPreferredPane(subject, contextWithMintClass('https://schema.example/PhotoAlbum'), [other, focus])).toBe(focus)
172+
})
173+
174+
it('falls back to registry order when no pane requests focus', () => {
175+
const first = createPane('first')
176+
const second = createPane('second')
177+
178+
expect(getPreferredPane(subject, contextWithMintClass(), [first, second])).toBe(first)
179+
})
180+
})

‎test/unit/index.test.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ describe('Index', () => {
3737
'dom',
3838
'fileExplorerContext',
3939
'generateId',
40+
'getPreferredPane',
4041
'getRelevantPanes',
4142
'icons',
4243
'infiniteMessageArea',

0 commit comments

Comments
 (0)