Nautical Poseidon Mythology

    digirati-annotation-components

    1.0.0-rc.11 • Public • Published

    Annotation Studio Components

    Components

    • Composites
      • Canvas
      • Confirmation Form
      • Selector
      • Viewer (@todo)
      • Router
    • Domain
      • Validation
    • Inputs
      • DatePicker
      • Form
      • TextArea
      • TextBox
    • Navigation
      • Navigation Resource
    • Selectors
      • BoxSelector
      • WholeCanvasSelector
    • Viewers
      • StaticImageViewer
      • ScaledImageViewer
      • OpenSeadragonViewer

    Composites

    These are React components that are composed of other react components. They are still mostly pure components, handing off their state management to Redux. Some offer APIs for choosing between different components (like selectors) with the goal in the future to be smart and delegate based on different contexts to choose the best component for the job. (Think A/V IIIF content)

    Canvas

    This is the abstract concept of space occupied so far by Selectors, Viewers and drawn Regions or annotations.

    Prop types

    propType = {
       onUpdateSelector: PropTypes.func,
       onSaveSelector: PropTypes.func,
       selector: PropTypes.shape({
         type: PropTypes.string.isRequired,
         left: PropTypes.number,
         top: PropTypes.number,
         height: PropTypes.number,
         width: PropTypes.number,
       }),
       image: PropTypes.shape({
         src: PropTypes.string.isRequired,
         height: PropTypes.number.isRequired,
         width: PropTypes.number.isRequired,
       }).isRequired,
       displayWidth: PropTypes.number.isRequired,
    }

    Minimum example usage

    <Canvas image={{ src: '...', height: 100, width: 100 }} displayWidth={50}/>

    ConfirmationForm

    The confirmation form is a composite of form elements and display values. It adds a "preview" to forms to allow a better and customisable representation of the values.

    Prop types

    propTypes = {
      draft: PropTypes.shape({
        id: PropTypes.string.isRequired,
        isPreviewing: PropTypes.bool.isRequired,
        input: PropTypes.object.isRequired,
      }),
      bem: PropTypes.object,
      nextLabel: PropTypes.string,
      editLabel: PropTypes.string,
      saveLabel: PropTypes.string,
      updateField: PropTypes.func.isRequired,
      onEdit: PropTypes.func,
      onSave: PropTypes.func,
      previewDraft: PropTypes.func.isRequired,
    };

    Minimum example usage

    <ConfirmationForm 
        draft={{ id: 1, isPreviewing: this.state.previewing, input: { title: 'testing' } }} 
        updateField={e => console.log(e)}
        previewDraft={e => this.setState({ previewing: true })}
        onEdit={e => this.setState({ previewing: false })}
      />

    Selector

    This is the composite selector that will be most used in apps to get any selector that you require without duplicating code elsewhere.

    Prop Types

    propTypes = {
      type: PropTypes.string.isRequired,
      onSave: PropTypes.func.isRequired,
      onCancel: PropTypes.func,
      initialPosition: PropTypes.shape({
        left: PropTypes.number,
        top: PropTypes.number,
        height: PropTypes.number,
        width: PropTypes.number,
      }),
    }

    Minimum example usage

    <Selector type="WholeCanvasSelector"/>

    Router

    The router is a very basic routing component that will route in a similar way to a switch/case or if/elseif. You can define boolean logic to create complex flows through components, while remaining pure and quick.

    Prop types

    propTypes = {
      routes: PropTypes.arrayOf(
        PropTypes.shape({
          matches: PropTypes.func.isRequired,
          render: PropTypes.func.isRequired,
        }).isRequired
      ),
      state: PropTypes.any,
      renderNotFound: PropTypes.func,
    };

    Minimum example usage

    <Router 
        routes={[
          {
            matches: (state) => state.isFirst,
            render: () => <StepOne />
          },
          {
            matches: (state) =>  !state.isFinished && !state.isFirst,
            render: () => <StepTwo />
          },
          {
            matches: (state) => state.isFinished,
            render: () => <LastStep />
          }
        ]}
        state={{ isFirst: true }}
      />

    Domain

    Note: this is likely to be removed from this part of the library as it is not strictly a component.

    Validation

    This is a library that will try and validate a variety of JSON-LD fields and contexts.

    Usage

    import validation from 'digirati-annotation-components/es/domain/validation';
     
    const fields = [
        {context: 'https://schema.org/jobTitle', value: 'Some job title'},
        {context: 'https://schema.org/birthDate', value: '31st Feb 1990'},
    ];
     
    function validate(field) {
      if (validation[field.context]) {
        return validation[field.context](field.value);
      }
      return true;
    }
     
    function validateAll(fields) {
        return fields.reduce((acc, cur) => acc && validate(field))
    }
     
    const isValid = validateAll(fields); // False since 31st Feb is invalid.

    Inputs

    Inputs are combined by a unified input field, offering an easy to compose interface to render a variety of fields. In the future this will be expanded to be more smart when choosing which field to render. Currently we have 3 example fields.

    Date Picker

    The date picker is a wrapper around a 3rd-party React component that really was meant to show off how these interfaces can be driven and expanded without re-inventing various wheels.

    Prop types

    propTypes = {
      id: PropTypes.string.isRequired,
      value: PropTypes.string.isRequired,
      update: PropTypes.func.isRequired,
      metaData: PropTypes.shape({
        title: PropTypes.string.isRequired,
        description: PropTypes.string
      }).isRequired,
      preview: PropTypes.bool,
    };

    Minimum example usage

    <DatePicker
        id={123}
        value={this.state.value}
        update={(value) => this.setState({ value })}
        metaData={{ title: 'Pick a date' }}
      />

    BEM class customisation

    List of classes:

    • .input-text-box
      • .input-text-box__label
      • .input-text-box__description
      • .input-text-box__preview
      • .input-text-box__input
        • .input-text-box__input--datepicker

    Form

    The form is a composition of form elements, with associated meta data to drive both styling and display of elements. This will also be expanded to be more introspective of fields and perform "best guess" when choosing fields. Currently its all driven by type.

    Prop types

    propTypes = {
      draft: PropTypes.shape({
        id: PropTypes.string.isRequired,
        input: PropTypes.objectOf(PropTypes.string).isRequired,
        isPreviewing: PropTypes.bool
      }).isRequired,
      fields: PropTypes.arrayOf(PropTypes.shape({
        id: PropTypes.string.isRequired,
        inputType: PropTypes.oneOf(['madoc:textarea', 'madoc:datepicker', 'madoc:textbox']),
        metaData: PropTypes.shape({
          title: PropTypes.string.isRequired,
          description: PropTypes.string,
          conformsTo: PropTypes.shape({
            id: PropTypes.oneOf([
              'http://xmlns.com/foaf/name',
              'https://schema.org/birthDate',
              'https://schema.org/jobTitle',
              'http://dublincore.org/documents/dcmi-terms/#terms-description'
            ]),
            label: PropTypes.string.isRequired,
          }),
        }).isRequired,
      })).isRequired,
      updateField: PropTypes.func.isRequired,
    };

    Minimum example usage

    <Form 
        draft={{ id: 1, input: this.state.values || {name: '', familyName: ''} }}
        fields={[
            { id: 'name', inputType: 'madoc:textbox', metaData: {
                title: 'First name'
            }},
            { id: 'familyName', inputType: 'madoc:textbox', metaData: {
                title: 'Family name'
            }},
        ]}
        updateField={(field, value) => this.setState(s => s.values[field.id] = value)}
      />

    BEM class customisation

    List of classes:

    • .input-form
      • .input-form__error
        • .input-form__error--hidden

    TextArea

    The text area is one of the most basic components binding to the DOM.

    Prop Types

    propTypes = {
      id: PropTypes.string.isRequired,
      value: PropTypes.string.isRequired,
      update: PropTypes.func.isRequired,
      metaData: PropTypes.shape({
        title: PropTypes.string.isRequired,
        description: PropTypes.string
      }).isRequired,
      preview: PropTypes.bool,
    };

    Minimum example usage

    <TextArea
        id={123}
        value={this.state.value}
        update={(value) => this.setState({ value })}
        metaData={{ title: 'Tell a story' }}
      />

    BEM class customisation

    List of classes:

    • .input-text-box
      • .input-text-box__label
      • .input-text-box__description
      • .input-text-box__preview
      • .input-text-box__input
        • .input-text-box__input--textarea

    TextField

    The text area is one of the most basic components binding to the DOM.

    Prop Types

    propTypes = {
      id: PropTypes.string.isRequired,
      value: PropTypes.string.isRequired,
      update: PropTypes.func.isRequired,
      metaData: PropTypes.shape({
        title: PropTypes.string.isRequired,
        description: PropTypes.string
      }).isRequired,
      preview: PropTypes.bool,
    };

    Minimum example usage

    <TextArea
        id={123}
        value={this.state.value}
        update={(value) => this.setState({ value })}
        metaData={{ title: 'First name' }}
      />

    BEM class customisation

    List of classes:

    • .input-text-box
      • .input-text-box__label
      • .input-text-box__description
      • .input-text-box__preview
      • .input-text-box__input

    Navigation

    The navigation section is one of the latest additions.

    ResourceNavigator

    The resource navigator focuses on building a UI around navigating through state by providing a path similar to path1.path2.path3 in Object notation. It binds to a UI and logic, allowing for state to be changed and the user to navigate through and render various things based on the current "location" in the state.

    Prop Types

    propTypes = {
      selections: PropTypes.arrayOf(PropTypes.any).isRequired,
      bem: PropTypes.object,
      renderSelection: PropTypes.func,
      onSelect: PropTypes.func.isRequired,
    };
    

    Minimum example usage

    <ResourceNavigator 
        selections={['apples', 'oranges']}
        onSelect={selection => console.log(selection)}>
        Choose a fruit
    </ResourceNavigator>

    BEM class customisation

    List of classes:

    • .resource-navigator
      • .resource-navigator__selection

    Selectors

    Selectors are built around highlighting a section or region of an image using a variety of tools, and being able to generate W3C valid selectors. This includes the media frags selector and also the SVG selector specifications.

    BoxSelector

    The box selector is a draggable box that is initially placed on a canvas. It is dragged around and is responsible for relaying back the co-ordinates that it currently exists at on the canvas (relative to the view port, for OSD)

    Prop Types

    propTypes = {
      onSave: PropTypes.func.isRequired,
      onUpdate: PropTypes.func.isRequired,
      onCancel: PropTypes.func,
      initialPosition: PropTypes.shape({
        left: PropTypes.number,
        top: PropTypes.number,
        height: PropTypes.number,
        width: PropTypes.number,
      }),
    };

    Minimum example usage

    <BoxSelector 
      onSave={position => console.log(position)}
      onUpdate={position => console.log(position)}
    />

    Note: the box selector can be dragged around its parents bounds. Make sure you have an appropriate container for dragging the box around and that it matches the height and width of your content.

    BEM class customisation

    List of classes:

    • .box-selector
      • .box-selector__button

    WholeCanvasSelector

    The whole canvas selector is a unique component, as it doesn't require a UI to work. Its job is simply to conform to the interface of other selectors and provide a way for the onSave method to be called to let the application know that it needs to target the whole application.

    There is support for making the user confirm their selection before hand. You could envision cancel buttons being added at an application level too, if that fits with the user experience.

    Prop types

    propTypes = {
      skipConfirm: PropTypes.bool,
      onSave: PropTypes.func.isRequired,
      onCancel: PropTypes.func, // unused
    };

    Minimum example usage

    <WholeCanvasSelector onSave={() => console.log('called on render')} />

    Viewers

    Viewers are components that display various kinds of content that you might want to annotate or surface annotations on.

    Static Image Viewer

    This is the most basic viewer, it takes an image, and displays it full size.

    propTypes = {
      resource: PropTypes.string.isRequired,
      height: PropTypes.number.isRequired,
      width: PropTypes.number.isRequired,
      regions: PropTypes.arrayOf(
        PropTypes.shape({
          onClick: PropTypes.func,
          left: PropTypes.number.isRequired,
          top: PropTypes.number.isRequired,
          height: PropTypes.number.isRequired,
          width: PropTypes.number.isRequired,
          selected: PropTypes.bool.isRequired,
        })
      )
    }

    Minimum example usage

    <StaticImageViewer 
        resource="http://.../portrait.jpg"
        height={200}
        width={100}
      />

    Scaled Image Viewer

    This was the next iteration from the static image viewer, this component internally uses the static image viewer, but simply scales it down. You must specify a scale for this one to work. Note: because of the way react works, you can change the height, width and scale interactively and still achieve accurate positions of regions, this aids with responsive design

    Prop types

    propTypes = {
      resource: PropTypes.string.isRequired,
      height: PropTypes.number.isRequired,
      width: PropTypes.number.isRequired,
      regions: PropTypes.arrayOf(
        PropTypes.shape({
          onClick: PropTypes.func,
          left: PropTypes.number.isRequired,
          top: PropTypes.number.isRequired,
          height: PropTypes.number.isRequired,
          width: PropTypes.number.isRequired,
          selected: PropTypes.bool.isRequired,
        })
      ),
      scale: PropTypes.number.isRequired // this is unique to this component.
    }

    Minimum example usage

    <ScaledImageViewer 
        resource="http://.../portrait.jpg"
        height={400}
        width={200}
        scale={0.5}
      />

    This will display the image at half the size (i.e. 100x200). You can also scale up, if required.

    OpenSeadragonViewer

    This is the most common choice for viewer, it consumes IIIF resources and enables deep zoom functionality. Unfortunately, not all content is the same, so this viewer will fallback as often as it can if it cannot read the resource provided.

    Prop types

    propTypes = {
      resource: PropTypes.string.isRequired,
      height: PropTypes.number.isRequired,
      width: PropTypes.number.isRequired,
      regions: PropTypes.arrayOf(
        PropTypes.shape({
          onClick: PropTypes.func,
          left: PropTypes.number.isRequired,
          top: PropTypes.number.isRequired,
          height: PropTypes.number.isRequired,
          width: PropTypes.number.isRequired,
          selected: PropTypes.bool.isRequired,
        })
      ),
      scale: PropTypes.number.isRequired,
      canvas: PropTypes.object.isRequired, // this is the IIIF Canvas, fully loaded, not an ID.
      maxHeight: PropTypes.number // Defaults to height*scale
    }

    Minimum example usage

    <OpenSeadragonViewer
        resource="http://.../portrait.jpg" // this is required in case a fallback is required
        height={400}
        width={200}
        scale={0.5}
        canvas={{ '@id': '...', '@type': 'sc:Canvas', /*...*/ }}
      />

    Install

    npm i digirati-annotation-components

    DownloadsWeekly Downloads

    449

    Version

    1.0.0-rc.11

    License

    MIT

    Unpacked Size

    536 kB

    Total Files

    130

    Last publish

    Collaborators

    • stephenwf2
    • kelsieiona
    • stephenwf