The bottom handle bar is now dynamic. Fixed CP + FO handles, then one
handle per kind of sub-object the focused node has. "Kind" is the SLOT
part of the AST's SLOT.SUBTYPE namespace: sub-objects sharing a SLOT
(e.g. `line.stem_note` + `line.motif`, or `articles.<subtypeA>` +
`articles.<subtypeB>`) collapse into one pane; different SLOTs split.
Score-level kinds emit, in this order: TU (tuning), ST (stage cone +
voices), IN (instruments — linked ones listed read-only), AR (articles),
BA (bars). info metadata is folded into the FO pane (was previously
listed as a sub-object).
Handles are 2-letter labels for now, intended as alt-text for icons in
a later release.
- `subobject-kinds.js` new: `getKindGroups(node)` returns ordered
`[{ kind, items }]`; `KIND_LABEL` maps kind -> 2-letter label.
- `PaneSubObjects.js` now parameterized by `kind` prop; renders one group.
- `AppShell.js` builds the handle bar from `getKindGroups(focusedNode)`;
drops back to FO when the active sub-pane disappears after a focus change.
- `ObjectShort.js` accepts a `readOnly` flag (used for linked instruments).
40 lines
1.5 KiB
JavaScript
40 lines
1.5 KiB
JavaScript
import { h } from 'vue';
|
|
import { ObjectShort } from './ObjectShort.js';
|
|
import { getKindGroups } from '../subobject-kinds.js';
|
|
|
|
export const PaneSubObjects = {
|
|
props: ['store', 'kind', 'onFocusFO'],
|
|
setup(props) {
|
|
function focused() {
|
|
const fp = props.store.focusPath;
|
|
return fp.length ? fp[fp.length - 1] : props.store.scoreModel;
|
|
}
|
|
|
|
return () => {
|
|
const node = focused();
|
|
const groups = getKindGroups(node);
|
|
const group = props.kind
|
|
? groups.find(g => g.kind === props.kind)
|
|
: groups[0];
|
|
const items = group?.items ?? [];
|
|
|
|
if (!items.length) return h('div', null, h('em', null, 'No sub-objects'));
|
|
|
|
return h('div', null,
|
|
h('ul', { class: 'se-object-list' }, items.map((item, idx) =>
|
|
h(ObjectShort, {
|
|
key: idx,
|
|
label: item.label,
|
|
typeTag: item.kind,
|
|
focused: props.store.focusPath.includes(item.node),
|
|
hasChildren: item.hasChildren,
|
|
readOnly: item.readOnly ?? false,
|
|
onFocus: () => { props.store.pushFocus(item.node); props.onFocusFO?.(); },
|
|
onDrillDown: () => { props.store.pushFocus(item.node); props.onFocusFO?.(); },
|
|
})
|
|
))
|
|
);
|
|
};
|
|
},
|
|
};
|