New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@recogito/recogito-client-core

Package Overview
Dependencies
Maintainers
1
Versions
64
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@recogito/recogito-client-core - npm Package Compare versions

Comparing version 0.1.9 to 0.2.0

src/editor/widgets/index.js

3

package.json
{
"name": "@recogito/recogito-client-core",
"version": "0.1.9",
"version": "0.2.0",
"description": "Core functions, classes and components for RecogitoJS",

@@ -34,2 +34,3 @@ "main": "src/index.js",

"mocha": "^7.1.1",
"node-forge": ">=0.10.0",
"node-sass": "^4.14.1",

@@ -36,0 +37,0 @@ "sass-loader": "^8.0.0",

import React from 'preact/compat';
import { useState, useRef, useEffect } from 'preact/hooks';
import Environment from '../Environment';
import { getWidget, DEFAULT_WIDGETS } from './widgets';
import setPosition from './setPosition';

@@ -141,2 +142,6 @@ import i18n from '../i18n';

// Use default comment + tag widget unless host app overrides
const widgets = props.config.widgets ?
props.config.widgets.map(getWidget) : DEFAULT_WIDGETS;
return (

@@ -146,16 +151,16 @@ <div ref={element} className="r6o-editor">

<div className="inner">
{React.Children.map(props.children, child =>
React.cloneElement(child, {
...child.props,
{widgets.map(widget =>
React.cloneElement(widget, {
annotation : currentAnnotation,
readOnly : props.readOnly,
onAppendBody : onAppendBody,
onUpdateBody : onUpdateBody,
onRemoveBody : onRemoveBody,
onSaveAndClose : onOk
}))
}
config: props.config,
onAppendBody,
onUpdateBody,
onRemoveBody,
onSaveAndClose: onOk
})
)}
{ props.readOnly ? (
<div className="footer">
<div className="r6o-footer">
<button

@@ -166,3 +171,3 @@ className="r6o-btn"

) : (
<div className="footer">
<div className="r6o-footer">
<button

@@ -169,0 +174,0 @@ className="r6o-btn outline"

@@ -1,2 +0,2 @@

import React, { useState, useEffect, useRef } from 'react'
import React, { useState, useRef } from 'react'
import { useCombobox } from 'downshift'

@@ -9,9 +9,5 @@

const [ inputItems, setInputItems ] = useState(props.vocabulary);
useEffect(() =>
element.current?.querySelector('input')?.focus(), []);
const onInputValueChange = ({ inputValue }) => {
if (inputValue.length > 0) {
// Set suggestions to prefix matches...
const prefixMatches = props.vocabulary.filter(item => {

@@ -68,2 +64,3 @@ return item.toLowerCase().startsWith(inputValue.toLowerCase());

{...getInputProps({ onKeyDown })}
onChange={evt => props.onChange && props.onChange(evt)}
placeholder={props.placeholder}

@@ -70,0 +67,0 @@ defaultValue={props.initialValue}

@@ -32,3 +32,3 @@ import React from 'preact/compat';

<div className="lastmodified">
<span className="lastmodified-by">{props.body.creator.name}</span>
<span className="lastmodified-by">{props.body.creator.name || props.body.creator.id}</span>
{ props.body.created &&

@@ -43,3 +43,3 @@ <span className="lastmodified-at">

<div className="r6o-widget comment">
<div className="value">{props.body.value}</div>
<div className="r6o-readonly-comment">{props.body.value}</div>
{ creatorInfo }

@@ -46,0 +46,0 @@ </div>

@@ -5,2 +5,3 @@ import React from 'preact/compat';

import i18n from '../../../i18n';
import Environment from '../../../Environment';

@@ -53,2 +54,27 @@ /**

// A comment should be read-only if:
// - the global read-only flag is set
// - the current rule is 'MINE_ONLY' and the creator ID differs
// The 'editable' config flag overrides the global setting, if any
const isReadOnly = body => {
if (props.editable === true)
return false;
if (props.editable === false)
return true;
if (props.editable === 'MINE_ONLY') {
// The original creator of the body
const creator = body.creator?.id;
// The current user
const me = Environment.user?.id;
return me !== creator;
}
// Global setting as last possible option
return props.readOnly;
}
return (

@@ -59,3 +85,3 @@ <>

key={idx}
readOnly={props.readOnly}
readOnly={isReadOnly(body)}
body={body}

@@ -62,0 +88,0 @@ onUpdate={props.onUpdateBody}

@@ -23,3 +23,3 @@ import React, { Component } from 'preact/compat';

if (ref && this.props.editable)
ref.focus();
setTimeout(() => ref.focus(), 1);
}

@@ -26,0 +26,0 @@

@@ -8,19 +8,30 @@ import React from 'preact/compat';

const getDraftTag = existingDraft =>
existingDraft ? existingDraft : {
type: 'TextualBody', value: '', purpose: 'tagging', draft: true
};
/** The basic freetext tag control from original Recogito **/
const TagWidget = props => {
// All tags (draft + non-draft)
const all = props.annotation ?
props.annotation.bodies.filter(b => b.type === 'TextualBody' && b.purpose === 'tagging') : [];
// Last draft tag goes into the input field
const draftTag = getDraftTag(all.slice().reverse().find(b => b.draft));
// All except draft tag
const tags = all.filter(b => b != draftTag);
const [ showDelete, setShowDelete ] = useState(false);
// Every body with a 'tagging' purpose is considered a tag
const tagBodies = props.annotation ?
props.annotation.bodies.filter(b => b.purpose === 'tagging') : [];
const toggle = tag => _ => {
if (showDelete === tag) // Removes delete button
setShowDelete(false);
else
else
setShowDelete(tag); // Sets delete button on a different tag
}
const onDelete = tag => evt => {
const onDelete = tag => evt => {
evt.stopPropagation();

@@ -30,4 +41,19 @@ props.onRemoveBody(tag);

const onDraftChange = evt => {
const prev = draftTag.value.trim();
const updated = evt.target.value.trim();
if (prev.length === 0 && updated.length > 0) {
props.onAppendBody({ ...draftTag, value: updated });
} else if (prev.length > 0 && updated.length === 0) {
props.onRemoveBody(draftTag);
} else {
props.onUpdateBody(draftTag, { ...draftTag, value: updated });
}
}
const onSubmit = tag => {
props.onAppendBody({ type: 'TextualBody', purpose: 'tagging', value: tag.trim() });
// Just 'undraft' the current draft tag
const { draft, ...undrafted } = draftTag;
props.onUpdateBody(draftTag, undrafted);
}

@@ -37,25 +63,29 @@

<div className="r6o-widget tag">
{ tagBodies.length > 0 &&
<ul className="r6o-taglist">
{ tagBodies.map(tag =>
<li key={tag.value} onClick={toggle(tag.value)}>
<span className="label">{tag.value}</span>
<div>
{ tags.length > 0 &&
<ul className="r6o-taglist">
{ tags.map(tag =>
<li key={tag.value} onClick={toggle(tag.value)}>
<span className="label">{tag.value}</span>
{!props.readOnly &&
<CSSTransition in={showDelete === tag.value} timeout={200} classNames="delete">
<span className="delete-wrapper" onClick={onDelete(tag)}>
<span className="delete">
<CloseIcon width={12} />
{!props.readOnly &&
<CSSTransition in={showDelete === tag.value} timeout={200} classNames="delete">
<span className="delete-wrapper" onClick={onDelete(tag)}>
<span className="delete">
<CloseIcon width={12} />
</span>
</span>
</span>
</CSSTransition>
}
</li>
)}
</ul>
}
</CSSTransition>
}
</li>
)}
</ul>
}
</div>
{ !props.readOnly &&
<Autocomplete
{!props.readOnly &&
<Autocomplete
placeholder={i18n.t('Add tag...')}
initialValue={draftTag.value}
onChange={onDraftChange}
onSubmit={onSubmit}

@@ -69,2 +99,2 @@ vocabulary={props.vocabulary || []} />

export default TagWidget;
export default TagWidget;

@@ -98,5 +98,5 @@ const TEXT = 3; // HTML DOM node type for text nodes

/**
* Forces a new ID on the given annotation (or annotation with the given ID).
* This method handles the ID update within the Highlighter ONLY. It's up to
* the application to keep the RelationsLayer in sync!
* Forces a new ID on the annotation with the given ID. This method handles
* the ID update within the Highlighter ONLY. It's up to the application to
* keep the RelationsLayer in sync!
*

@@ -103,0 +103,0 @@ * @returns the updated annotation for convenience

@@ -0,1 +1,2 @@

export { default as Editor } from './editor/Editor';
export { default as Environment } from './Environment';

@@ -6,3 +7,2 @@ export { default as I18n } from './i18n';

export * from './editor';
export * from './highlighter';

@@ -9,0 +9,0 @@ export * from './relations';

import { trimRange, rangeToSelection, enableTouch, getExactOverlaps } from './SelectionUtils';
import { isInternetExplorer } from '../utils';
import EventEmitter from 'tiny-emitter';

@@ -8,3 +7,3 @@

const IS_INTERNET_EXPLORER =
window?.navigator.userAgent.match(/(MSIE|Trident)/);
navigator?.userAgent.match(/(MSIE|Trident)/);

@@ -11,0 +10,0 @@ /** Tests whether maybeChildEl is contained in containerEl **/

@@ -7,6 +7,3 @@ import React, { Component } from 'preact/compat';

import RelationEditor from './relations/editor/RelationEditor';
import { addPolyfills } from './utils';
addPolyfills(); // For Microsoft Edge
/**

@@ -41,5 +38,5 @@ * Pulls the strings between the annotation highlight layer

componentDidMount() {
this.highlighter = new Highlighter(this.props.contentEl, this.props.formatter);
this.highlighter = new Highlighter(this.props.contentEl, this.props.config.formatter);
this.selectionHandler = new SelectionHandler(this.props.contentEl, this.highlighter, this.props.readOnly);
this.selectionHandler = new SelectionHandler(this.props.contentEl, this.highlighter, this.props.config.readOnly);
this.selectionHandler.on('select', this.handleSelect);

@@ -274,4 +271,3 @@

selectedElement={this.state.selectedDOMElement}
readOnly={this.props.readOnly}
headless={this.state.headless}
config={this.props.config}
applyTemplate={this.state.applyTemplate}

@@ -281,7 +277,3 @@ onAnnotationCreated={this.onCreateOrUpdateAnnotation('onAnnotationCreated')}

onAnnotationDeleted={this.onDeleteAnnotation}
onCancel={this.onCancelAnnotation}>
{this.props.children}
</Editor>
onCancel={this.onCancelAnnotation} />
}

@@ -288,0 +280,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc