Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@bpmn-io/form-js-viewer

Package Overview
Dependencies
Maintainers
9
Versions
100
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@bpmn-io/form-js-viewer - npm Package Compare versions

Comparing version 0.7.2 to 0.8.0-alpha.0

dist/types/render/components/form-fields/Checklist.d.ts

546

dist/index.es.js

@@ -5,6 +5,7 @@ import Ids from 'ids';

import { jsx, jsxs } from 'preact/jsx-runtime';
import { useContext, useState, useCallback } from 'preact/hooks';
import { useContext, useState, useEffect, useRef, useMemo, useCallback } from 'preact/hooks';
import { createContext, createElement, Fragment, render } from 'preact';
import React, { createPortal } from 'preact/compat';
import classNames from 'classnames';
import Markup from 'preact-markup';
import { createPortal } from 'preact/compat';
import { Injector } from 'didi';

@@ -811,15 +812,22 @@

_path,
type
} = formField;
type,
valuesKey
} = formField; // get values defined via valuesKey
if (!_path) {
return importedData;
} // (1) try to get value from data
// (2) try to get default value from form field
// (3) get empty value from form field
if (valuesKey) {
importedData = { ...importedData,
[valuesKey]: get(data, [valuesKey])
};
} // try to get value from data
// if unavailable - try to get default value from form field
// if unavailable - get empty value from form field
return { ...importedData,
[_path[0]]: get(data, _path, isUndefined(defaultValue) ? this._formFields.get(type).emptyValue : defaultValue)
};
if (_path) {
importedData = { ...importedData,
[_path[0]]: get(data, _path, isUndefined(defaultValue) ? this._formFields.get(type).emptyValue : defaultValue)
};
}
return importedData;
}, {});

@@ -985,3 +993,3 @@ }

const type$6 = 'button';
const type$8 = 'button';
function Button(props) {

@@ -996,3 +1004,3 @@ const {

return jsx("div", {
class: formFieldClasses(type$6),
class: formFieldClasses(type$8),
children: jsx("button", {

@@ -1014,3 +1022,3 @@ class: "fjs-button",

Button.type = type$6;
Button.type = type$8;
Button.label = 'Button';

@@ -1097,3 +1105,3 @@ Button.keyed = true;

const type$5 = 'checkbox';
const type$7 = 'checkbox';
function Checkbox(props) {

@@ -1125,3 +1133,3 @@ const {

return jsxs("div", {
class: formFieldClasses(type$5, errors),
class: formFieldClasses(type$7, errors),
children: [jsx(Label, {

@@ -1152,3 +1160,3 @@ id: prefixId(id, formId),

Checkbox.type = type$5;
Checkbox.type = type$7;
Checkbox.label = 'Checkbox';

@@ -1165,2 +1173,148 @@ Checkbox.keyed = true;

/**
* @enum { String }
*/
const LOAD_STATES = {
LOADING: 'loading',
LOADED: 'loaded',
ERROR: 'error'
};
/**
* @typedef {Object} ValuesGetter
* @property {Object[]} values - The values data
* @property {(LOAD_STATES)} state - The values data's loading state, to use for conditional rendering
*/
/**
* A hook to load values for single and multiselect components.
*
* @param {Object} field - The form field to handle values for
* @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
*/
function useValuesAsync (field) {
const {
valuesKey,
values: staticValues
} = field;
const [valuesGetter, setValuesGetter] = useState({
values: [],
error: undefined,
state: LOAD_STATES.LOADING
});
const initialData = useService('form')._getState().initialData;
useEffect(() => {
let values = [];
if (valuesKey !== undefined) {
const keyedValues = (initialData || {})[valuesKey];
if (keyedValues && Array.isArray(keyedValues)) {
values = keyedValues;
}
} else if (staticValues !== undefined) {
values = Array.isArray(staticValues) ? staticValues : [];
} else {
setValuesGetter(getErrorState('No values source defined in the form definition'));
return;
}
setValuesGetter(buildLoadedState(values));
}, [valuesKey, staticValues, initialData]);
return valuesGetter;
}
const getErrorState = error => ({
values: [],
error,
state: LOAD_STATES.ERROR
});
const buildLoadedState = values => ({
values,
error: undefined,
state: LOAD_STATES.LOADED
});
const type$6 = 'checklist';
function Checklist(props) {
const {
disabled,
errors = [],
field,
value = []
} = props;
const {
description,
id,
label
} = field;
const toggleCheckbox = v => {
let newValue = [...value];
if (!newValue.includes(v)) {
newValue.push(v);
} else {
newValue = newValue.filter(x => x != v);
}
props.onChange({
field,
value: newValue
});
};
const {
state: loadState,
values: options
} = useValuesAsync(field);
const {
formId
} = useContext(FormContext);
return jsxs("div", {
class: formFieldClasses(type$6, errors),
children: [jsx(Label, {
label: label
}), loadState == LOAD_STATES.LOADED && options.map((v, index) => {
return jsx(Label, {
id: prefixId(`${id}-${index}`, formId),
label: v.label,
required: false,
children: jsx("input", {
checked: value.includes(v.value),
class: "fjs-input",
disabled: disabled,
id: prefixId(`${id}-${index}`, formId),
type: "checkbox",
onClick: () => toggleCheckbox(v.value)
})
}, `${id}-${index}`);
}), jsx(Description, {
description: description
}), jsx(Errors, {
errors: errors
})]
});
}
Checklist.create = function (options = {}) {
if (options.valuesKey) return options;
return {
values: [{
label: 'Value',
value: 'value'
}],
...options
};
};
Checklist.type = type$6;
Checklist.label = 'Checklist';
Checklist.keyed = true;
Checklist.emptyValue = [];
const noop$1 = () => false;

@@ -1374,3 +1528,3 @@

const type$4 = 'number';
const type$5 = 'number';
function Number(props) {

@@ -1407,3 +1561,3 @@ const {

return jsxs("div", {
class: formFieldClasses(type$4, errors),
class: formFieldClasses(type$5, errors),
children: [jsx(Label, {

@@ -1433,3 +1587,3 @@ id: prefixId(id, formId),

Number.type = type$4;
Number.type = type$5;
Number.keyed = true;

@@ -1439,3 +1593,3 @@ Number.label = 'Number';

const type$3 = 'radio';
const type$4 = 'radio';
function Radio(props) {

@@ -1452,4 +1606,3 @@ const {

label,
validate = {},
values
validate = {}
} = field;

@@ -1468,16 +1621,20 @@ const {

const {
state: loadState,
values: options
} = useValuesAsync(field);
const {
formId
} = useContext(FormContext);
return jsxs("div", {
class: formFieldClasses(type$3, errors),
class: formFieldClasses(type$4, errors),
children: [jsx(Label, {
label: label,
required: required
}), values.map((v, index) => {
}), loadState == LOAD_STATES.LOADED && options.map((option, index) => {
return jsx(Label, {
id: prefixId(`${id}-${index}`, formId),
label: v.label,
label: option.label,
required: false,
children: jsx("input", {
checked: v.value === value,
checked: option.value === value,
class: "fjs-input",

@@ -1487,3 +1644,3 @@ disabled: disabled,

type: "radio",
onClick: () => onChange(v.value)
onClick: () => onChange(option.value)
})

@@ -1500,2 +1657,3 @@ }, `${id}-${index}`);

Radio.create = function (options = {}) {
if (options.valuesKey) return options;
return {

@@ -1510,3 +1668,3 @@ values: [{

Radio.type = type$3;
Radio.type = type$4;
Radio.label = 'Radio';

@@ -1516,3 +1674,3 @@ Radio.keyed = true;

const type$2 = 'select';
const type$3 = 'select';
function Select(props) {

@@ -1529,4 +1687,3 @@ const {

label,
validate = {},
values
validate = {}
} = field;

@@ -1547,6 +1704,10 @@ const {

const {
state: loadState,
values: options
} = useValuesAsync(field);
const {
formId
} = useContext(FormContext);
return jsxs("div", {
class: formFieldClasses(type$2, errors),
class: formFieldClasses(type$3, errors),
children: [jsx(Label, {

@@ -1564,6 +1725,6 @@ id: prefixId(id, formId),

value: ""
}), values.map((v, index) => {
}), loadState == LOAD_STATES.LOADED && options.map((option, index) => {
return jsx("option", {
value: v.value,
children: v.label
value: option.value,
children: option.label
}, `${id}-${index}`);

@@ -1580,2 +1741,3 @@ })]

Select.create = function (options = {}) {
if (options.valuesKey) return options;
return {

@@ -1590,3 +1752,3 @@ values: [{

Select.type = type$2;
Select.type = type$3;
Select.label = 'Select';

@@ -1596,2 +1758,304 @@ Select.keyed = true;

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
var CloseIcon = (({
styles = {},
...props
}) => /*#__PURE__*/React.createElement("svg", _extends({
width: "16",
height: "16",
fill: "none",
xmlns: "http://www.w3.org/2000/svg"
}, props), /*#__PURE__*/React.createElement("path", {
fillRule: "evenodd",
clipRule: "evenodd",
d: "M12 4.7l-.7-.7L8 7.3 4.7 4l-.7.7L7.3 8 4 11.3l.7.7L8 8.7l3.3 3.3.7-.7L8.7 8 12 4.7z",
fill: "#000"
})));
function useKeyDownAction(targetKey, action, listenerElement = window) {
function downHandler({
key
}) {
if (key === targetKey) {
action();
}
}
useEffect(() => {
listenerElement.addEventListener('keydown', downHandler);
return () => {
listenerElement.removeEventListener('keydown', downHandler);
};
});
}
const DEFAULT_LABEL_GETTER = value => value;
const NOOP = () => {};
function DropdownList(props) {
const {
keyEventsListener = window,
values = [],
getLabel = DEFAULT_LABEL_GETTER,
onValueSelected = NOOP,
height = 235,
emptyListMessage = 'No results'
} = props;
const [mouseControl, setMouseControl] = useState(true);
const [focusedValueIndex, setFocusedValueIndex] = useState(0);
const dropdownContainer = useRef();
const mouseScreenPos = useRef();
const focusedItem = useMemo(() => values.length ? values[focusedValueIndex] : null, [focusedValueIndex, values]);
const changeFocusedValueIndex = useCallback(delta => {
setFocusedValueIndex(x => Math.min(Math.max(0, x + delta), values.length - 1));
}, [values.length]);
useEffect(() => {
if (focusedValueIndex === 0) return;
if (!focusedValueIndex || !values.length) {
setFocusedValueIndex(0);
} else if (focusedValueIndex >= values.length) {
setFocusedValueIndex(values.length - 1);
}
}, [focusedValueIndex, values.length]);
useKeyDownAction('ArrowUp', () => {
if (values.length) {
changeFocusedValueIndex(-1);
setMouseControl(false);
}
}, keyEventsListener);
useKeyDownAction('ArrowDown', () => {
if (values.length) {
changeFocusedValueIndex(1);
setMouseControl(false);
}
}, keyEventsListener);
useKeyDownAction('Enter', () => {
if (focusedItem) {
onValueSelected(focusedItem);
}
}, keyEventsListener);
useEffect(() => {
const individualEntries = dropdownContainer.current.children;
if (individualEntries.length && !mouseControl) {
individualEntries[focusedValueIndex].scrollIntoView({
block: 'nearest',
inline: 'nearest'
});
}
}, [focusedValueIndex, mouseControl]);
const mouseMove = (e, i) => {
const userMoved = !mouseScreenPos.current || mouseScreenPos.current.x !== e.screenX && mouseScreenPos.current.y !== e.screenY;
if (userMoved) {
mouseScreenPos.current = {
x: e.screenX,
y: e.screenY
};
if (!mouseControl) {
setMouseControl(true);
setFocusedValueIndex(i);
}
}
};
return jsxs("div", {
ref: dropdownContainer,
tabIndex: -1,
class: "fjs-dropdownlist",
style: {
maxHeight: height
},
children: [!!values.length && values.map((v, i) => {
return jsx("div", {
class: 'fjs-dropdownlist-item' + (focusedValueIndex === i ? ' focused' : ''),
onMouseMove: e => mouseMove(e, i),
onMouseEnter: mouseControl ? () => setFocusedValueIndex(i) : undefined,
onMouseDown: e => {
e.preventDefault();
onValueSelected(v);
},
children: getLabel(v)
});
}), !values.length && jsx("div", {
class: "fjs-dropdownlist-empty",
children: emptyListMessage
})]
});
}
const type$2 = 'taglist';
function Taglist(props) {
const {
disabled,
errors = [],
field,
value: values = []
} = props;
const {
description,
id,
label
} = field;
const {
formId
} = useContext(FormContext);
const [filter, setFilter] = useState('');
const [selectedValues, setSelectedValues] = useState([]);
const [filteredValues, setFilteredValues] = useState([]);
const [isDropdownExpanded, setIsDropdownExpanded] = useState(false);
const [hasValuesLeft, setHasValuesLeft] = useState(true);
const [isEscapeClosed, setIsEscapeClose] = useState(false);
const searchbarRef = useRef();
const {
state: loadState,
values: options
} = useValuesAsync(field); // Usage of stringify is necessary here because we want this effect to only trigger when there is a value change to the array
useEffect(() => {
if (loadState === LOAD_STATES.LOADED) {
const selectedValues = values.map(v => options.find(o => o.value === v)).filter(v => v !== undefined);
setSelectedValues(selectedValues);
} else {
setSelectedValues([]);
}
}, [JSON.stringify(values), options, loadState]);
useEffect(() => {
if (loadState === LOAD_STATES.LOADED) {
setFilteredValues(options.filter(o => o.label && o.label.toLowerCase().includes(filter.toLowerCase()) && !values.includes(o.value)));
} else {
setFilteredValues([]);
}
}, [filter, JSON.stringify(values), options]);
useEffect(() => {
setHasValuesLeft(selectedValues.length < options.length);
}, [selectedValues.length, options.length]);
const onFilterChange = ({
target
}) => {
setIsEscapeClose(false);
setFilter(target.value);
};
const selectValue = option => {
setFilter('');
props.onChange({
value: [...values, option.value],
field
});
};
const deselectValue = option => {
props.onChange({
value: values.filter(v => v != option.value),
field
});
};
const onInputKeyDown = e => {
switch (e.key) {
case 'ArrowUp':
case 'ArrowDown':
// We do not want the cursor to seek in the search field when we press up and down
e.preventDefault();
break;
case 'Backspace':
if (!filter && selectedValues.length) {
deselectValue(selectedValues[selectedValues.length - 1]);
}
break;
case 'Escape':
setIsEscapeClose(true);
break;
case 'Enter':
if (isEscapeClosed) {
setIsEscapeClose(false);
}
break;
}
};
return jsxs("div", {
class: formFieldClasses(type$2, errors),
children: [jsx(Label, {
label: label,
id: prefixId(id, formId)
}), jsxs("div", {
class: classNames('fjs-taglist', {
'disabled': disabled
}),
children: [!disabled && loadState === LOAD_STATES.LOADED && selectedValues.map(sv => {
return jsxs("div", {
class: "fjs-taglist-tag",
onMouseDown: e => e.preventDefault(),
children: [jsx("span", {
class: "fjs-taglist-tag-label",
children: sv.label
}), jsx("span", {
class: "fjs-taglist-tag-remove",
onMouseDown: () => deselectValue(sv),
children: jsx(CloseIcon, {})
})]
});
}), jsx("input", {
disabled: disabled,
class: "fjs-taglist-input",
ref: searchbarRef,
id: prefixId(`${id}-search`, formId),
onChange: onFilterChange,
type: "text",
value: filter,
placeholder: 'Search',
autoComplete: "off",
onKeyDown: e => onInputKeyDown(e),
onMouseDown: () => setIsEscapeClose(false),
onFocus: () => setIsDropdownExpanded(true),
onBlur: () => {
setIsDropdownExpanded(false);
setFilter('');
}
})]
}), jsx("div", {
class: "fjs-taglist-anchor",
children: !disabled && loadState === LOAD_STATES.LOADED && isDropdownExpanded && !isEscapeClosed && jsx(DropdownList, {
values: filteredValues,
getLabel: v => v.label,
onValueSelected: v => selectValue(v),
emptyListMessage: hasValuesLeft ? 'No results' : 'All values selected',
listenerElement: searchbarRef.current
})
}), jsx(Description, {
description: description
}), jsx(Errors, {
errors: errors
})]
});
}
Taglist.create = function (options = {}) {
if (options.valuesKey) return options;
return {
values: [{
label: 'Value',
value: 'value'
}],
...options
};
};
Taglist.type = type$2;
Taglist.label = 'Taglist';
Taglist.keyed = true;
Taglist.emptyValue = [];
const type$1 = 'text';

@@ -1685,3 +2149,3 @@ function Text(props) {

const formFields = [Button, Checkbox, Default, Number, Radio, Select, Text, Textfield];
const formFields = [Button, Checkbox, Checklist, Default, Number, Radio, Select, Taglist, Text, Textfield];

@@ -2173,3 +2637,3 @@ class FormFields {

const schemaVersion = 4;
const schemaVersion = 5;
/**

@@ -2199,3 +2663,3 @@ * @typedef { import('./types').CreateFormOptions } CreateFormOptions

export { Button, Checkbox, Default, Form, FormComponent, FormContext, FormFieldRegistry, FormFields, FormRenderContext, Number, Radio, Select, Text, Textfield, clone, createForm, createFormContainer, createInjector, findErrors, formFields, generateIdForType, generateIndexForType, isRequired, pathParse, pathStringify, pathsEqual, schemaVersion };
export { Button, Checkbox, Checklist, Default, Form, FormComponent, FormContext, FormFieldRegistry, FormFields, FormRenderContext, Number, Radio, Select, Taglist, Text, Textfield, clone, createForm, createFormContainer, createInjector, findErrors, formFields, generateIdForType, generateIndexForType, isRequired, pathParse, pathStringify, pathsEqual, schemaVersion };
//# sourceMappingURL=index.es.js.map

2

dist/types/index.d.ts

@@ -17,3 +17,3 @@ /**

import Form from "./Form";
export const schemaVersion: 4;
export const schemaVersion: 5;
export { Form };
declare function Radio(props: any): import("preact").JSX.Element;
declare namespace Radio {
export function create(options?: {}): {
values: {
label: string;
value: string;
}[];
};
export function create(options?: {}): {};
export { type };

@@ -10,0 +5,0 @@ export const label: string;

declare function Select(props: any): import("preact").JSX.Element;
declare namespace Select {
export function create(options?: {}): {
values: {
label: string;
value: string;
}[];
};
export function create(options?: {}): {};
export { type };

@@ -10,0 +5,0 @@ export const label: string;

export const formFields: (typeof Button | typeof Default | typeof Number | typeof Text)[];
import Button from "./form-fields/Button";
import Checkbox from "./form-fields/Checkbox";
import Checklist from "./form-fields/Checklist";
import Default from "./form-fields/Default";

@@ -9,4 +10,5 @@ import FormComponent from "./FormComponent";

import Select from "./form-fields/Select";
import Taglist from "./form-fields/Taglist";
import Text from "./form-fields/Text";
import Textfield from "./form-fields/Textfield";
export { Button, Checkbox, Default, FormComponent, Number, Radio, Select, Text, Textfield };
export { Button, Checkbox, Checklist, Default, FormComponent, Number, Radio, Select, Taglist, Text, Textfield };
{
"name": "@bpmn-io/form-js-viewer",
"version": "0.7.2",
"version": "0.8.0-alpha.0",
"description": "View forms - powered by bpmn.io",

@@ -23,3 +23,3 @@ "exports": {

"start": "SINGLE_START=basic npm run dev",
"bundle": "rollup -c",
"bundle": "rollup -c --failAfterWarnings",
"bundle:watch": "rollup -c -w",

@@ -43,2 +43,3 @@ "dev": "npm test -- --auto-watch --no-single-run",

"@bpmn-io/snarkdown": "^2.1.0",
"classnames": "^2.3.1",
"didi": "^5.2.1",

@@ -56,3 +57,3 @@ "ids": "^1.0.0",

],
"gitHead": "46631f707eea5537cbeb81aa05423fd9be71a3c0"
"gitHead": "ffc5f0cedcf0b9a923b34ff56e7f63a34c362cf9"
}

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

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