@hyperion-framework/react-vault
TypeScript icon, indicating that this package has built-in type declarations

2.0.0-alpha.0 • Public • Published

React vault

React bindings for Hyperion vault.

Road map

Technical proof of concepts

  • Retrieval hooks
  • Selectors that have dependencies on other selectors (typed)
  • memoization of selectors
  • possible move to react-redux-hooks

Set of proof of concept Vault bindings/hooks/contexts for:

  • Collections
  • Manifest
  • Canvas
  • Annotation
  • Image service
  • VaultContext

Complete the base hooks implementation for setting up contexts and selectors and build up hook collection

  • AnnotationContext
  • AnnotationPageContext
  • CanvasContext
  • CollectionContext
  • ManifestContext
  • useAnnotation
  • useAnnotationPage
  • useCanvas
  • useCollection
  • useDispatch
  • useExternalAnnotationList
  • useExternalCollection
  • useExternalManifest
  • useManifest
  • useVault
  • useVaultEffect

Create viewer abstractions

  • SimpleViewerContext
  • SingleCanvasContext

Canvas clock implementation

  • useAnnotationsAtTime
  • useCanvasClock
  • useCanvasTimeline

Other helpers

  • RangeContext
  • usePaintingAnnotations
  • useRange
  • useSearchService
  • useVirtualCanvas

New hooks

useRenderingStrategy

There are many ways that a canvas can be rendered, some are easier than others. A hook that breaks these down into easier to render chunks will make iteratively supporting features easier.

This hook will return a type, some data and some actions. The types may be something like:

  • Single image - A single image or image service.
  • Composite image - A composition of more than one image or image service.
  • Choice - A choice that needs to be given to the user (with functions to make choice)
  • Audio - A single audio file, or sequential audio files
  • Video - A single video file, or sequential video files
  • Complex timeline - A composite of either multiple audio, video and composite images on a timeline.

This gives implementations a goal, and can easily let users know that they don't support the given canvas without an error.

The data models returned from this strategy should be similar to each other. A single image should have a way to load an image service, generate tiles or fixed sizes. Composite image should be the same as single image but with multiple. A choice should be available from the hook regardless of the type, to support a menu-like system for choices even after a choice is made. Audio and video should use a similar interface with controls. Complex timeline should be very similar to audio/video with the same controls but with additional structure similar to composite image.

type UseRenderingStrategy = {
  type: 'single-image' | 'composite-image' | 'audio' | 'video' | 'complex-timeline';
  image: { type: 'fixed-size' } | { type: 'image-service' } | null;
  images: [];
  media: { type: 'audio' } | { type: 'video' } | { type: 'sequence' };
  duration: number;
  choice: {} | null;
}

Querying and indexing

// Builds a memoized query
const filter = useFilter(() => {
  type: 'Canvas',
  id: id => id.startsWidth(`https://${myDomain}/`),
}, [myDomain]);

// The first time this is called it will build an index based on your query. (label + $contains)
const search = useVaultSearch([filter, { label: { $contains: `my-query` } }]);

//
search.results // now contains the results.

// Imperative example.
// For this filter to work, it must match reference equality.
const myFilterObject = vault.createFilter({
  type: 'Canvas',
  id: id => id.startsWidth('https://mydomain/'),
});

const myIndex = vault.createIndex({
  name: 'My index',
  refresh: true,
  filter: myFilterObject,
  indexes: ['viewingHint'],
});

// This is roughly what would be stored.
const state = {
  indexes: [
    {
      filter: myFilterObject,
      index: {
        viewingHint: {
          individuals: ['http://manifest-1/canvas-1.json'], 
          paged: ['http://manifest-1/canvas-2.json', 'http://manifest-1/canvas-3.json'],
        }
      }
    }
  ]
};

// And this is how it would be used.
const results = vault.query([myFilterObject, { 
  // This would be pre-filtered by the index.
  viewingHint: 'individuals',
  // Then this would be executed against the found objects.
  title: { $contains: 'Test' },
}]);

Vault event manager

// desired API:

const annotation = getAnnotationFromSomwehere();
const manager = useEventManager();

useEffect(() => {
  const lastAnnotation = annotation;
  const clickHandler = (e, anno) => {
    // ...
  };
  
  manager.select(lastAnnotation, 'optional-label').addEventListener('click', clickHandler);

  return () => {
    manager.select(lastAnnotation).removeEventListener('click', clickHandler);
  }
}, [annotation]);

// ...

<MyAnnotationComponent {...mananger.eventsFor(annotation)} />

// .. or

const annotationEvents = useEvents(annotation, 'optional-label');

<MyAnnotationComponent {...annotationEvents} />

// .. or

const div = useRef();

useBindEvents(div, annotation, 'optional-label');

<MyAnnotationComponent ref={div} />

Storing annotation pages

  • Annotation pages on canvases
  • Annotation pages on manifests
  • Annotation pages with manifestId in meta
  • Annotation pages with canvasId in meta

Meta

Example state:

const state = {
  meta: {
    'https://example.org/annotation-list/1': {
      annotationListManager: {
        isActive: true,
        resources: ['https://example.org/manifest-1'],
      }
    },
  }
};

Readme

Keywords

none

Package Sidebar

Install

npm i @hyperion-framework/react-vault

Weekly Downloads

2

Version

2.0.0-alpha.0

License

MIT

Unpacked Size

272 kB

Total Files

60

Last publish

Collaborators

  • stephenwf