Skip to content

Commit

Permalink
Update the struct view to define the setStructViewAnnotations act…
Browse files Browse the repository at this point in the history
…ion when using the new `setup()` method
  • Loading branch information
lahmatiy committed Nov 25, 2024
1 parent f0e87d9 commit f81de47
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 29 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Changed `ViewModel#setDataProgress()` to no longer change the context, despite accepting `context` argument
- Updated `ViewModel` to trigger a render when the `context` event is fired
- Added `Model#legacyPrepare` readonly property to indicate whether the legacy `prepare` method is used or the new `setup()` method
- Updated the `struct` view to define the `setStructViewAnnotations` action when using the new `setup()` method, allowing custom annotations to be specified across all `struct` views
- Added the `EmbedApp#publicApi.setLocationSync()` method to simplify sync between the embed app and the host location, preventing potential pitfalls
- Added `ViewModel#enforceScheduledRenders()` to immediately execute scheduled renders
- Changed `ViewModel#scheduleRender()` to use `setTimeout()` instead of `Promise.resolve()` to ensure proper processing of event loop tasks, eliminating unnecessary renders
Expand Down
24 changes: 18 additions & 6 deletions src/views/struct/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { hasOwn, objectToString } from '../../core/utils/object-utils.js';
import { createClickHandler } from './click-handler.js';
import { createValueActionsPopup } from './popup-value-actions.js';
import value2html, { stringifyIfNeeded } from './value-to-html.js';
import { getDefaultAnnotations, prepareAnnotations, renderAnnotations } from './render-annotations.js';
import { concatAnnotations, getDefaultAnnotations, prepareAnnotations, preprocessAnnotations, renderAnnotations } from './render-annotations.js';
import usage from './struct.usage.js';
import {
stringValueProto,
Expand Down Expand Up @@ -343,8 +343,9 @@ export default function(host) {
const elementContext = new WeakMap();
const elementOptions = new WeakMap();
const structViewRoots = new WeakSet();
const defaultAnnotations = getDefaultAnnotations(host);
const annotationsToRender = [];
const defaultAnnotations = getDefaultAnnotations(host);
let customAnnotations = defaultAnnotations;
let annotationsTimer = null;

const valueActionsPopup = createValueActionsPopup(host, elementData, elementContext, buildPathForElement);
Expand All @@ -362,6 +363,16 @@ export default function(host) {
// single event handler for all `struct` view instances
host.addHostElEventListener('click', clickHandler, false);

// define an action to set custom annotations
if (!host.legacyPrepare) {
host.action.define('setStructViewAnnotations', (newAnnotations) => {
customAnnotations = concatAnnotations(
defaultAnnotations,
preprocessAnnotations(newAnnotations)
);
});
}

host.view.define('struct', function(el, config, data, context) {
const {
annotations,
Expand All @@ -378,10 +389,11 @@ export default function(host) {
} = config;
const normalizedAnnotations = prepareAnnotations(
annotations,
defaultAnnotations ||
// FIXME: that's a fallback to work with legacy prepare,
// remove when discard model-legacy-extension-api
host.annotations
!host.legacyPrepare
? customAnnotations
// FIXME: that's a fallback to work with legacy prepare,
// remove when discard model-legacy-extension-api
: host.annotations
);

const options = {
Expand Down
57 changes: 34 additions & 23 deletions src/views/struct/render-annotations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,39 +36,50 @@ type RenderAnnotationConfig = {
const styles = ['none', 'default', 'badge'];
const annotationsElByEl = new WeakMap<HTMLElement, HTMLElement>();

export function getDefaultAnnotations(host: ViewModel) {
const annotations: ValueAnnotation[] = [];

for (const { name, lookup } of host.objectMarkers.values) {
annotations.push({
query(value: unknown, context: ValueAnnotationContext) {
const marker = lookup(value, true);

if (marker !== null && marker.object !== context.host) {
return {
place: 'before',
style: 'badge',
text: name,
href: marker.href
};
}
}
});
export function concatAnnotations(a: ValueAnnotation[] | false, b: ValueAnnotation[] | false) {
if (Array.isArray(a)) {
return Array.isArray(b)
? a.concat(b)
: a;
}

return annotations.length > 0 ? annotations : false;
return b;
}

export function prepareAnnotations(annotations: unknown[], hostAnnotations: ValueAnnotation[]) {
export function preprocessAnnotations(annotations: unknown[]) {
if (Array.isArray(annotations) && annotations.length > 0) {
return hostAnnotations.concat(annotations.map(annotation =>
return annotations.map((annotation) =>
typeof annotation === 'string' || typeof annotation === 'function'
? { query: annotation as Query }
: annotation as ValueAnnotation
));
);
}

return hostAnnotations;
return false;
}

export function getDefaultAnnotations(host: ViewModel) {
return preprocessAnnotations([...host.objectMarkers.values].map(({ name, lookup }) =>
(value: unknown, context: ValueAnnotationContext) => {
const marker = lookup(value, true);

if (marker !== null && marker.object !== context.host) {
return {
place: 'before',
style: 'badge',
text: name,
href: marker.href
};
}
}
));
}

export function prepareAnnotations(
viewAnnotations: unknown[],
customAnnotations: ValueAnnotation[]
) {
return concatAnnotations(customAnnotations, preprocessAnnotations(viewAnnotations));
}

function isValidStyle(value: unknown): value is RenderAnnotationConfig['style'] {
Expand Down

0 comments on commit f81de47

Please sign in to comment.