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

@eeacms/volto-accordion-block

Package Overview
Dependencies
Maintainers
7
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@eeacms/volto-accordion-block - npm Package Compare versions

Comparing version 1.0.0 to 2.0.0

cypress.json

2

.release-it.json
{
"npm": {
"publish": false
"publish": true
},

@@ -5,0 +5,0 @@ "git": {

@@ -7,4 +7,43 @@ ### Changelog

#### [1.0.0](https://github.com/eea/volto-accordion-block/compare/0.1.0...1.0.0)
#### [2.0.0](https://github.com/eea/volto-accordion-block/compare/1.0.0...2.0.0)
- retain one child block after delete [`#8`](https://github.com/eea/volto-accordion-block/pull/8)
- style accordion panel ( background color, title size) and editing panels [`#7`](https://github.com/eea/volto-accordion-block/pull/7)
- edit parent accordion section [`#6`](https://github.com/eea/volto-accordion-block/pull/6)
- Restructure add-on [`0fd79ed`](https://github.com/eea/volto-accordion-block/commit/0fd79edfa170a97c50ecfc5bbb3c13538c4c7de7)
- [JENKINS] - Add cypress integration tests [`8726ab8`](https://github.com/eea/volto-accordion-block/commit/8726ab8c615f709a3cda8820fca5de3d2d9be300)
- Cleanup HTML and fix accordion heading [`57bd046`](https://github.com/eea/volto-accordion-block/commit/57bd04664480baca39c89b146e893322cce80878)
- Cleanup unused icons and panels [`2556218`](https://github.com/eea/volto-accordion-block/commit/25562182acff7b3ced29c9371e5f5adaa10b8504)
- add new icons for panel chooser [`3ee30e0`](https://github.com/eea/volto-accordion-block/commit/3ee30e0c87b9127584d7d5ffd171d33b9be14a27)
- Remove unusied EditBlockWrapper, rename column to panel [`793055b`](https://github.com/eea/volto-accordion-block/commit/793055b5499a7577dea77492a9f512fe7db1da08)
- Cleanup and headings for Accordion titles [`144c667`](https://github.com/eea/volto-accordion-block/commit/144c66760fc92193b74673216434a02ea40d2117)
- styles: background color in panels [`22995fd`](https://github.com/eea/volto-accordion-block/commit/22995fdcb6b8d14aec119baf5f7743349aaaa2a2)
- Add support DX Layout [`ab50789`](https://github.com/eea/volto-accordion-block/commit/ab50789964e15240061044e0458f269341e58a3f)
- remove colorPicker Widget [`61c0a12`](https://github.com/eea/volto-accordion-block/commit/61c0a12fbde7e507e5ec04562a305df04d42bead)
- combined settings in parent accordion block [`2d5fa42`](https://github.com/eea/volto-accordion-block/commit/2d5fa42d84540c7d351d39aa43acc2c2dd14b29d)
- Fix heading sizes; Add more cypress tests [`e1430f4`](https://github.com/eea/volto-accordion-block/commit/e1430f4db5d47b0f31ce9ff730494da66d18bc22)
- prevent deleting first accordion block child [`f99fd66`](https://github.com/eea/volto-accordion-block/commit/f99fd66fe63bf2f28fe0b8e8ebabee6f9244caa1)
- decorate, stlying edit,View [`dc521e5`](https://github.com/eea/volto-accordion-block/commit/dc521e54cc06c7782c6b1921c7df3a3fc114bcec)
- style: panel title font size [`ba33d9a`](https://github.com/eea/volto-accordion-block/commit/ba33d9ad87271c9aad36ff92945fce58d2e86378)
- Better heading component [`8389892`](https://github.com/eea/volto-accordion-block/commit/838989200cfe2b007309960d0c99a0df3bdbfaf4)
- use h2-h6 font sizes in accordion title [`0e5845d`](https://github.com/eea/volto-accordion-block/commit/0e5845dc860cd47763e48777adb49d9e38f87428)
- rotate right accordion arrow [`7f13476`](https://github.com/eea/volto-accordion-block/commit/7f134760ee970792a2be0a716c7f4851dc5b7f0f)
- move title to one level up in the panel layout [`0eb32d3`](https://github.com/eea/volto-accordion-block/commit/0eb32d3e93e087fe9f7084e7905c46ef50739a79)
- Render non empty panels in View [`7dca60c`](https://github.com/eea/volto-accordion-block/commit/7dca60c28b548e796b624d506e8dac88ea23bb8b)
- JENKINS: replace duplicate values with predefined vars [`3630a04`](https://github.com/eea/volto-accordion-block/commit/3630a044de5781161133b60e5165a6b05397a8bb)
- move accordion title in blocks_layout [`421845d`](https://github.com/eea/volto-accordion-block/commit/421845d98ecebe0880806ebdf0d92285ef90d860)
- JENKINS: fix missing deps [`fd18f3a`](https://github.com/eea/volto-accordion-block/commit/fd18f3afc6245cf2f218ec76077cf0814254e67f)
- JENKINS: fix useEffect deps [`c032943`](https://github.com/eea/volto-accordion-block/commit/c03294383a7e9863c8846f45b20fb51081de119b)
- fix console warnings and jenkins [`f0b68f9`](https://github.com/eea/volto-accordion-block/commit/f0b68f96311dad690b5ea461ef00fae74f92e4e3)
- JENKINS: fix useEffect deps [`b7f81f0`](https://github.com/eea/volto-accordion-block/commit/b7f81f060496238a0e018dd7aba40a18aa5478b6)
- Fix column title [`d190c26`](https://github.com/eea/volto-accordion-block/commit/d190c267bd54bdc1125804131af4fee3fbe55088)
- fix z-index of block-toolbar [`5adb193`](https://github.com/eea/volto-accordion-block/commit/5adb193ffa689e85bc958c5c3da6f8baa5a6d700)
- [JENKINS] - Fix style [`8bc3f4e`](https://github.com/eea/volto-accordion-block/commit/8bc3f4e55fbe833cf926aa65746087c450be460c)
- remove optional chaining in blockProps [`39741af`](https://github.com/eea/volto-accordion-block/commit/39741aff08a0f551ce10aae68e96dcb22bc61865)
- fix jenkins [`8a7ec73`](https://github.com/eea/volto-accordion-block/commit/8a7ec737be1cec1559bc9dc206147f41c7fb1986)
### [1.0.0](https://github.com/eea/volto-accordion-block/compare/0.1.0...1.0.0)
> 17 November 2020
- add panels via sidebar [`#3`](https://github.com/eea/volto-accordion-block/pull/3)

@@ -17,2 +56,3 @@ - Accordion title using semantic ui Input [`#5`](https://github.com/eea/volto-accordion-block/pull/5)

- yarn prettier [`afc2d37`](https://github.com/eea/volto-accordion-block/commit/afc2d379490cc4bdd4e2c2296229fac5d549d6a1)
- Release 1.0.0 [`80d83c1`](https://github.com/eea/volto-accordion-block/commit/80d83c1369cea5cff33c5a51a783b3f0d4a4e96f)
- Update package metadata [`602e871`](https://github.com/eea/volto-accordion-block/commit/602e871ab4b4cc5113fd927aee566722c6e0dddf)

@@ -19,0 +59,0 @@ - fix tests: stylelint [`00f503e`](https://github.com/eea/volto-accordion-block/commit/00f503e72429fc6aaa9385fb1a5fea50a0e58573)

{
"name": "@eeacms/volto-accordion-block",
"version": "1.0.0",
"version": "2.0.0",
"description": "volto-accordion-block: Volto group block to add accordions",

@@ -35,4 +35,6 @@ "main": "src/index.js",

"lint": "../../../node_modules/eslint/bin/eslint.js --max-warnings=0 'src/**/*.{js,jsx}'",
"lint:fix": "../../../node_modules/eslint/bin/eslint.js --fix 'src/**/*.{js,jsx}'"
"lint:fix": "../../../node_modules/eslint/bin/eslint.js --fix 'src/**/*.{js,jsx}'",
"cypress:run": "../../../node_modules/cypress/bin/cypress run",
"cypress:open": "../../../node_modules/cypress/bin/cypress open"
}
}

@@ -1,5 +0,4 @@

export AccordionBlockEdit from './manage/Blocks/Accordion/Edit';
export AccordionBlockView from './manage/Blocks/Accordion/View';
export AccordionBlockSchema from './manage/Blocks/Accordion/Schema';
export { options } from './manage/Blocks/Accordion/layout';
export AccordionLayoutSchema from '@eeacms/volto-accordion-block/components/manage/Blocks/Accordion/LayoutSchema';
export AccordionBlockEdit from '@eeacms/volto-accordion-block/components/manage/Blocks/Accordion/Edit';
export AccordionBlockView from '@eeacms/volto-accordion-block/components/manage/Blocks/Accordion/View';
export PanelsWidget from '@eeacms/volto-accordion-block/components/manage/Widgets/PanelsWidget';

@@ -10,10 +10,11 @@ import React from 'react';

import AnimateHeight from 'react-animate-height';
export default ({
children,
coldata,
handleTitleChange,
colId,
column,
data,
}) => {
export default (props) => {
const {
children,
handleTitleChange,
handleTitleClick,
uid,
panel,
data,
} = props;
const [activeIndex, setActiveIndex] = React.useState(0);

@@ -28,49 +29,52 @@ function handleClick(e, titleProps) {

return (
<div>
<Accordion fluid styled>
<React.Fragment>
<Accordion.Title
active={activeIndex === 0}
index={0}
onClick={handleClick}
className="accordion-title"
<Accordion fluid styled>
<React.Fragment>
<Accordion.Title
as={data.title_size}
active={activeIndex === 0}
index={0}
onClick={handleClick}
className={cx('accordion-title', {
'align-arrow-left': !props?.data?.right_arrows,
'align-arrow-right': props?.data?.right_arrows,
})}
>
{activeIndex === 0 ? (
<Icon name={downSVG} size="24px" />
) : (
<Icon
size="24px"
name={rightSVG}
className={cx({ 'rotate-arrow': data?.right_arrows })}
/>
)}
{!data.readOnlyTitles ? (
<Input
fluid
className="input-accordion-title"
transparent
placeholder="Enter Title"
value={panel?.title}
onClick={(e) => {
handleTitleClick();
e.stopPropagation();
}}
onChange={(e) => handleTitleChange(e, [uid, panel])}
/>
) : (
<span>{panel?.title}</span>
)}
</Accordion.Title>
<Accordion.Content active={activeIndex === 0}>
<AnimateHeight
animateOpacity
duration={500}
height={activeIndex === 0 ? 'auto' : 0}
>
<div
className={cx('align-arrow-left', {
'align-arrow-right': data.arrow_select,
})}
>
{activeIndex === 0 ? (
<Icon name={downSVG} size="20px" />
) : (
<Icon name={rightSVG} size="20px" />
)}
<Input
fluid
className="input-accordion-title"
transparent
placeholder="Enter Title"
value={column?.blocks?.acc_title}
onClick={(e) => e.stopPropagation()}
onChange={(e) => handleTitleChange(e, [colId, column])}
/>
</div>
</Accordion.Title>
<div>
<Accordion.Content active={activeIndex === 0}>
<div style={{ margin: '1em' }}>
<AnimateHeight
animateOpacity
duration={500}
height={activeIndex === 0 ? 'auto' : 0}
>
{children}
</AnimateHeight>
</div>
</Accordion.Content>
</div>
</React.Fragment>
</Accordion>
</div>
{children}
</AnimateHeight>
</Accordion.Content>
</React.Fragment>
</Accordion>
);
};

@@ -9,44 +9,48 @@ import React, { useState } from 'react';

import AccordionEdit from './AccordionEdit';
import Layout from './Layout.jsx';
import { empty, getColumns } from './util';
import { options } from './layout';
import { emptyAccordion, getPanels } from './util';
import './editor.less';
const Edit = (props) => {
const {
block,
data,
onChangeBlock,
pathname,
selected,
manage,
data: { display },
} = props;
const { block, data, onChangeBlock, pathname, selected, manage } = props;
const metadata = props.metadata || props.properties;
const properties = isEmpty(data?.data?.blocks)
? emptyBlocksForm()
? emptyAccordion(3)
: data.data;
const [selectedBlock, setSelectedBlock] = useState({});
React.useEffect(() => {
properties.blocks_layout.items.map((item) => {
if (isEmpty(properties.blocks[item].blocks)) {
return onChangeBlock(block, {
...data,
data: {
...properties,
blocks: {
...properties.blocks,
[item]: emptyBlocksForm(),
},
},
});
}
return undefined;
});
}, [
onChangeBlock,
properties,
selectedBlock,
block,
data,
properties.blocks,
]);
const createPanes = (initialData) => {
const { count } = initialData;
return {
data: empty(count),
};
};
const blockState = {};
const coldata = properties;
const columnList = getColumns(coldata);
const panelData = properties;
const panels = getPanels(panelData);
const handleTitleChange = (e, value) => {
const [colId, column] = value;
const [uid, panel] = value;
const modifiedBlock = {
...column,
blocks: {
...column.blocks,
acc_title: e.target.value,
},
...panel,
title: e.target.value,
};

@@ -56,6 +60,6 @@ onChangeBlock(block, {

data: {
...coldata,
...panelData,
blocks: {
...coldata.blocks,
[colId]: modifiedBlock,
...panelData.blocks,
[uid]: modifiedBlock,
},

@@ -67,96 +71,76 @@ },

return (
<section className="section-block">
{!display && Object.keys(data).length === 1 ? (
<Layout
variants={options}
<div className="accordion-block">
{panels.map(([uid, panel], index) => (
<AccordionEdit
uid={uid}
panel={panel}
panelData={panelData}
handleTitleChange={handleTitleChange}
handleTitleClick={() => setSelectedBlock({})}
data={data}
onChange={(initialData) => {
onChangeBlock(block, {
...data,
...createPanes(initialData),
});
}}
/>
) : display && Object.keys(data).length === 2 ? (
<Layout
variants={options}
data={data}
onChange={(initialData) => {
onChangeBlock(block, {
...data,
...createPanes(initialData),
});
}}
/>
) : (
<div>
{columnList.map(([colId, column], index) => (
<AccordionEdit
colId={colId}
column={column}
coldata={coldata}
handleTitleChange={handleTitleChange}
data={data}
>
<BlocksForm
key={colId}
metadata={metadata}
properties={isEmpty(column) ? emptyBlocksForm() : column}
manage={manage}
selectedBlock={selected ? selectedBlock[colId] : null}
description={data?.instructions?.data}
onSelectBlock={(id) =>
setSelectedBlock({
[colId]: id,
})
}
onChangeFormData={(newFormData) => {
onChangeBlock(block, {
...data,
data: {
...coldata,
blocks: {
...coldata.blocks,
[colId]: newFormData,
},
},
});
}}
onChangeField={(id, value) => {
if (['blocks', 'blocks_layout'].indexOf(id) > -1) {
blockState[id] = value;
onChangeBlock(block, {
...data,
data: {
...coldata,
blocks: {
...coldata.blocks,
[colId]: {
...coldata.blocks?.[colId],
...blockState,
},
},
},
});
}
}}
pathname={pathname}
/>
</AccordionEdit>
))}
</div>
)}
{Object.keys(selectedBlock).length === 0 ? (
<SidebarPortal selected={true}>
<InlineForm
schema={accordionBlockSchema()}
title="Accordion block"
onChangeField={(id, value) => {
key={index}
>
<BlocksForm
key={uid}
title={data.placeholder}
description={data?.instructions?.data}
manage={manage}
allowedBlocks={data.allowedBlocks}
metadata={metadata}
properties={isEmpty(panel) ? emptyBlocksForm() : panel}
selectedBlock={selected ? selectedBlock[uid] : null}
onSelectBlock={(id) =>
setSelectedBlock({
[uid]: id,
})
}
onChangeFormData={(newFormData) => {
onChangeBlock(block, {
...data,
[id]: value,
data: {
...panelData,
blocks: {
...panelData.blocks,
[uid]: newFormData,
},
},
});
}}
formData={data}
onChangeField={(id, value) => {
if (['blocks', 'blocks_layout'].indexOf(id) > -1) {
blockState[id] = value;
onChangeBlock(block, {
...data,
data: {
...panelData,
blocks: {
...panelData.blocks,
[uid]: {
...panelData.blocks?.[uid],
...blockState,
},
},
},
});
}
}}
pathname={pathname}
/>
</AccordionEdit>
))}
{Object.keys(selectedBlock).length === 0 && !data.readOnlySettings ? (
<SidebarPortal selected={true}>
<>
<InlineForm
schema={accordionBlockSchema()}
title="Accordion block"
onChangeField={(id, value) => {
onChangeBlock(block, {
...data,
[id]: value,
});
}}
formData={data}
/>
</>
</SidebarPortal>

@@ -166,3 +150,3 @@ ) : (

)}
</section>
</div>
);

@@ -169,0 +153,0 @@ };

@@ -1,78 +0,1 @@

const Schema = {
title: 'Accordion block settings',
fieldsets: [
{
id: 'default',
title: 'Default',
fields: [
'placeholder',
'instructions',
'allowedBlocks',
'as',
'required',
'fixed',
'disableNewBlocks',
'readOnly',
],
},
],
properties: {
allowedBlocks: {
title: 'Allowed blocks',
description: 'Allow only the following blocks types',
type: 'array',
items: {
choices: [],
},
},
placeholder: {
title: 'Helper text',
description:
'A short hint that describes the expected value within this block',
type: 'string',
},
instructions: {
title: 'Instructions',
description: 'Detailed expected value within this block',
type: 'string',
widget: 'richtext',
},
as: {
title: 'HTML5 element',
description: 'Select HTML5 element to be used for this block',
type: 'string',
factory: 'Choice',
default: 'div',
choices: [
['div', 'div'],
['section', 'section'],
['article', 'article'],
['aside', 'aside'],
['details', 'details'],
],
},
required: {
title: 'Required',
description: "Don't allow deletion of this block",
type: 'boolean',
},
fixed: {
title: 'Fixed position',
description: 'Disable drag & drop on this block',
type: 'boolean',
},
disableNewBlocks: {
title: 'Disable new blocks',
description: 'Disable creation of new blocks after this block',
type: 'boolean',
},
readOnly: {
title: 'Read-only',
description: 'Disable editing on this block',
type: 'boolean',
},
},
required: [],
};
export const AccordionSchema = {

@@ -101,10 +24,11 @@ title: 'Accordion',

title: 'Default',
fields: ['data', 'arrow_select'], // 'nrColumns', 'block_title'
fields: ['data'],
},
{
id: 'style',
title: 'Style',
fields: ['title_size', 'right_arrows'],
},
],
properties: {
block_title: {
title: 'Block title',
default: 'Panels',
},
data: {

@@ -115,5 +39,19 @@ title: 'Accordion',

},
arrow_select: {
title: 'Align arrow to right',
title_size: {
title: 'Title size',
description: 'Accordion Title size',
type: 'string',
factory: 'Choice',
choices: [
['h2', 'Heading 2'],
['h3', 'Heading 3'],
['h4', 'Heading 4'],
['h5', 'Heading 5'],
['h6', 'Heading 6'],
],
},
right_arrows: {
title: 'Arrows on the right',
type: 'boolean',
default: false,
},

@@ -123,3 +61,1 @@ },

});
export default Schema;
import { v4 as uuid } from 'uuid';
import { emptyBlocksForm } from '@eeacms/volto-blocks-form/helpers';
import { map } from 'lodash';
import {

@@ -10,3 +11,3 @@ getBlocksFieldname,

export const empty = (count) => {
export const emptyAccordion = (count) => {
const blocks = {};

@@ -28,3 +29,3 @@ const items = [];

export const getColumns = (data) => {
export const getPanels = (data) => {
return (data?.blocks_layout?.items || []).map((id) => [

@@ -36,3 +37,3 @@ id,

export const GroupblockHasValue = (content) => {
export const accordionBlockHasValue = (content) => {
const blocksFieldname = getBlocksFieldname(content);

@@ -44,3 +45,4 @@ const blocksLayoutFieldname = getBlocksLayoutFieldname(content);

});
return blockValue.length === 1 ? blockValue[0] : true;
if (content.hasOwnProperty('title') && content?.title.length > 0) return true;
return blockValue.some((item) => item === true);
};
import React from 'react';
import { RenderBlocks } from '@eeacms/volto-blocks-form/components';
import { getColumns, GroupblockHasValue } from './util';
import { getPanels, accordionBlockHasValue } from './util';
import { Accordion } from 'semantic-ui-react';

@@ -15,6 +15,4 @@

const View = (props) => {
const {
data: { data = {} },
} = props;
const columnList = getColumns(data);
const { data } = props;
const panels = getPanels(data.data);
const metadata = props.metadata || props.properties;

@@ -25,47 +23,46 @@ const [activeIndex, setActiveIndex] = React.useState(0);

const newIndex = activeIndex === index ? -1 : index;
setActiveIndex(newIndex);
}
return (
<div>
{columnList.map(([id, column], index) => {
return GroupblockHasValue(column) ? (
<Accordion fluid styled>
<div className="accordion-block">
{panels.map(([id, panel], index) => {
return accordionBlockHasValue(panel) ? (
<Accordion fluid styled key={id}>
<React.Fragment>
<Accordion.Title
as={data.title_size}
active={activeIndex === index}
index={index}
onClick={handleClick}
className="accordion-title"
className={cx('accordion-title', {
'align-arrow-left': !props?.data?.right_arrows,
'align-arrow-right': props?.data?.right_arrows,
})}
>
<div
className={cx('align-arrow-left', {
'align-arrow-right': props.data.arrow_select,
})}
{activeIndex === index ? (
<Icon name={downSVG} size="24px" />
) : (
<Icon
name={rightSVG}
size="24px"
className={cx({
'rotate-arrow': props?.data?.right_arrows,
})}
/>
)}
<span>{panel?.title}</span>
</Accordion.Title>
<Accordion.Content active={activeIndex === index}>
<AnimateHeight
animateOpacity
duration={500}
height={activeIndex === index ? 'auto' : 0}
>
{activeIndex === index ? (
<Icon name={downSVG} size="20px" />
) : (
<Icon name={rightSVG} size="20px" />
)}
<p>{column?.blocks?.acc_title}</p>
</div>
</Accordion.Title>
<div>
<Accordion.Content active={activeIndex === index}>
<div>
<AnimateHeight
animateOpacity
duration={500}
height={activeIndex === index ? 'auto' : 0}
>
<RenderBlocks
{...props}
metadata={metadata}
content={column}
/>
</AnimateHeight>
</div>
</Accordion.Content>
</div>
<RenderBlocks
{...props}
metadata={metadata}
content={panel}
/>
</AnimateHeight>
</Accordion.Content>
</React.Fragment>

@@ -72,0 +69,0 @@ </Accordion>

@@ -1,11 +0,10 @@

import circleBottomSVG from '@plone/volto/icons/circle-bottom.svg';
import accordionSVG from '@plone/volto/icons/list-arrows.svg';
import {
AccordionBlockEdit,
AccordionBlockView,
AccordionBlockSchema,
AccordionLayoutSchema,
} from './components';
import { PanelWidget } from './Widgets';
import { options } from '@eeacms/volto-accordion-block/components';
import { PanelsWidget } from '@eeacms/volto-accordion-block/components';
const applyConfig = (config) => {
const extendedSchema = (config) => {
const choices = Object.keys(config.blocks.blocksConfig)

@@ -24,8 +23,8 @@ .map((key) => {

const schema = {
...AccordionBlockSchema,
return {
...AccordionLayoutSchema,
properties: {
...AccordionBlockSchema.properties,
...AccordionLayoutSchema.properties,
allowedBlocks: {
...AccordionBlockSchema.properties.allowedBlocks,
...AccordionLayoutSchema.properties.allowedBlocks,
items: {

@@ -37,15 +36,17 @@ choices: choices,

};
};
const applyConfig = (config) => {
config.blocks.blocksConfig.accordion = {
id: 'accordion',
title: 'Accordion',
icon: circleBottomSVG,
icon: accordionSVG,
group: 'common',
view: AccordionBlockView,
edit: AccordionBlockEdit,
schema: schema,
restricted: false,
options,
mostUsed: false,
blockHasOwnFocusManagement: true,
sidebarTab: 1,
schema: extendedSchema(config),
security: {

@@ -56,3 +57,3 @@ addPermission: [],

};
config.widgets.type.panels = PanelWidget;
config.widgets.type.panels = PanelsWidget;
return config;

@@ -59,0 +60,0 @@ };

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