Compare commits

...

2 Commits

37 changed files with 2981 additions and 171 deletions

View File

@ -11,6 +11,7 @@ import SbLayout from '@schlechtenburg/layout';
import SbHeading from '@schlechtenburg/heading';
import SbParagraph from '@schlechtenburg/paragraph';
import SbImage from '@schlechtenburg/image';
import SbItalicTool from '@schlechtenburg/italic';
import exampleData from './example-data';
@ -38,6 +39,9 @@ export default defineComponent({
SbImage,
SbParagraph,
]}
availableInlineTools={[
SbItalicTool,
]}
mode={activeTab.value as SbMode}
eventUpdate={(data:IBlockData<any>) => {
block.id = data.id;

View File

@ -21,3 +21,7 @@ export default {
view: defineAsyncComponent(() => import('./view')),
} as IBlockDefinition<any>;
```
## Go by example
As Schlechtenburg is still in active development, it's good to check out the official blocks to see what they look like.

View File

@ -13,6 +13,7 @@ export default defineConfig({
'@schlechtenburg/heading': join(__dirname, '../packages/heading/lib/index.ts'),
'@schlechtenburg/image': join(__dirname, '../packages/image/lib/index.ts'),
'@schlechtenburg/layout': join(__dirname, '../packages/layout/lib/index.ts'),
'@schlechtenburg/italic': join(__dirname, '../packages/italic/lib/index.ts'),
},
},
});

View File

@ -164,6 +164,7 @@ export const SbBlock = defineComponent({
eventRemoveSelf={props.eventRemoveSelf}
eventActivatePrevious={props.eventActivatePrevious}
eventActivateNext={props.eventActivateNext}
data-sb-block--content
{...{
onClick: ($event: MouseEvent) => {

View File

@ -5,6 +5,10 @@
background-color: var(--grey-0);
border: 1px solid var(--grey-2);
&_active {
box-shadow: inset 5px 5px 5px 5px black;
}
&:hover {
border: 1px solid var(--interact);
}

View File

@ -2,6 +2,7 @@ import {
defineComponent,
provide,
shallowReactive,
shallowRef,
ref,
watch,
computed,
@ -15,6 +16,8 @@ import {
IBlockLibrary,
ITreeNode,
OnUpdateBlockCb,
IFormattingTool,
IFormattingToolLibrary,
} from '../types';
import { model } from '../block-helpers';
import { SymMode, SbMode } from '../mode';
@ -26,12 +29,20 @@ import {
} from '../use-block-tree';
import { SymEditorDimensions, useResizeObserver } from '../use-resize-observer';
import { SymActiveBlock } from '../use-activation';
import { SymRootElement } from '../use-root-element';
import {
SbFormattingToolbar,
SymFormattingToolLibrary,
SymFormattingToolbarClients,
SymFormattingToolbarActiveClient,
} from '../rich-text';
import { SbMainMenu } from './MainMenu';
import { SbBlock } from './Block';
export interface ISbMainProps {
availableBlocks: IBlockDefinition<any>[];
availableFormattingTools: IFormattingTool[];
block: IBlockData<any>;
eventUpdate: OnUpdateBlockCb;
mode: SbMode;
@ -49,6 +60,10 @@ export const SbMain = defineComponent({
type: Array as PropType<IBlockDefinition<any>[]>,
default: () => [],
},
availableFormattingTools: {
type: Array as PropType<IFormattingTool[]>,
default: () => [],
},
block: {
type: Object as PropType<IBlockData<any>>,
required: true,
@ -72,6 +87,12 @@ export const SbMain = defineComponent({
setup(props: ISbMainProps) {
const el: Ref<null|HTMLElement> = ref(null);
useResizeObserver(el, SymEditorDimensions);
provide(SymRootElement, el);
const inlineClients = shallowRef([]);
provide(SymFormattingToolbarClients, inlineClients);
provide(SymFormattingToolbarActiveClient, ref(null));
const mode = ref(props.mode);
provide(SymMode, mode);
@ -99,9 +120,16 @@ export const SbMain = defineComponent({
{},
),
});
provide(SymBlockLibrary, blockLibrary);
const inlineToolLibrary: IFormattingToolLibrary = shallowReactive({
...props.availableFormattingTools.reduce(
(tools: IFormattingToolLibrary, tool: IFormattingTool) => ({ ...tools, [tool.name]: tool }),
{},
),
});
provide(SymFormattingToolLibrary, inlineToolLibrary);
return () => (
<div
class={classes.value}
@ -123,6 +151,7 @@ export const SbMain = defineComponent({
block={props.block}
eventUpdate={props.eventUpdate}
/>
<SbFormattingToolbar />
</div>
);
},

View File

@ -1,6 +1,8 @@
export * from './mode';
export * from './types';
export * from './rich-text';
export * from './block-helpers';
export * from './use-activation';
@ -8,10 +10,12 @@ export * from './use-dynamic-blocks';
export * from './use-resize-observer';
export * from './components/Main';
export * from './components/Block';
export * from './components/BlockPicker';
export * from './components/BlockOrdering';
export * from './components/BlockPlaceholder';
export * from './components/Toolbar';
export * from './components/Button';
export * from './components/Select';

View File

@ -0,0 +1,12 @@
.sb-inline-toolbar {
position: absolute;
background-color: var(--bg);
height: 2rem;
min-width: 2rem;
display: flex;
z-index: var(--z-toolbar);
&_hidden {
display: none;
}
}

View File

@ -0,0 +1,124 @@
import {
ref,
Ref,
onMounted,
onBeforeUnmount,
defineComponent,
computed,
} from 'vue';
import debounce from 'lodash/debounce';
import { useRootElement } from '../use-root-element';
import { useFormattingToolbar } from './use-formatting-toolbar';
import {
getSelection,
getAnchorElementForSelection,
getRangeFromSelection,
getRect,
} from './selection';
import './FormattingToolbar.scss';
export const SbFormattingToolbar = defineComponent({
name: 'sb-inlinetoolbar',
setup() {
const { rootElement } = useRootElement();
const {
activeClient,
setActiveClient,
clients,
getAllTools,
} = useFormattingToolbar();
const allTools = computed(() => getAllTools());
const selection: Ref<Selection|null>= ref(null);
const selectionRect: Ref<DOMRect|null>= ref(null);
const updateSelectionRect = () => {
selectionRect.value = getRect(selection.value!);
};
const showing: Ref<boolean> = ref(false);
const show = () => {
showing.value = true;
updateSelectionRect();
};
const hide = () => {
showing.value = false;
setActiveClient(null);
};
const style = computed(() => {
const rootRect = rootElement.value?.getBoundingClientRect();
const x = (selectionRect.value?.x || 0)
- (rootRect?.left || 0);
const y = (selectionRect.value?.y || 0)
+ (selectionRect.value?.height || 0)
- (rootRect?.top || 0);
return {
left: Math.floor(x) + 'px',
top: Math.floor(y) + 'px',
};
});
const classes = computed(() => ({
'sb-inline-toolbar': true,
}));
const onSelectionChanged = debounce(() => {
selection.value = getSelection();
if (!selection.value) {
console.warn('Could not get selection');
return
}
const range = getRangeFromSelection(selection.value);
// If we're not selecting anything, bail
if (!range || range.endOffset === range.startOffset) {
hide();
return;
}
const focusedElement = document.activeElement;
if (!focusedElement) {
hide();
return;
}
// If new selection is not in registered clients, close it
if (!clients.value.find(client => client === focusedElement)) {
hide();
return;
}
setActiveClient(document.activeElement as HTMLElement|null);
show();
}, 50);
onMounted(() => {
rootElement.value?.addEventListener('click', close);
document.addEventListener('selectionchange', onSelectionChanged, true);
});
onBeforeUnmount(() => {
rootElement.value?.removeEventListener('click', close);
document.removeEventListener('selectionchange', onSelectionChanged);
});
return () => (allTools.value.length && showing.value)
? <div
style={style.value}
class={classes.value}
onClick={(event:MouseEvent) => { event.stopPropagation(); }}
>{allTools.value.map((tool) => {
const ToolUI = tool.ui as any;
return <ToolUI
activeClient={activeClient}
selection={selection.value}
></ToolUI>;
})}</div>
: null;
},
});

View File

@ -0,0 +1,69 @@
import {
ref,
Ref,
h,
defineComponent,
onMounted,
onBeforeUnmount,
PropType,
computed,
watchEffect,
} from 'vue';
import { useFormattingToolbar } from './use-formatting-toolbar';
export const SbRichText = defineComponent({
name: 'sb-rich-text',
props: {
inputRef: {
type: (null as unknown) as PropType<Ref<HTMLElement|null>>,
default: ref(null),
},
tag: { type: String, default: 'p' },
value: { type: String, default: '' },
onValueChange: {
type: (null as unknown) as PropType<(value: string) => void>,
default: (_:string) => {},
},
},
setup(props) {
const {
registerClient,
unregisterClient,
} = useFormattingToolbar();
const onKeydown = (event: KeyboardEvent) => {
if (['Delete', 'Backspace'].indexOf(event.key) < 0) {
return;
}
if (props.inputRef.value?.textContent === '') {
props.inputRef.value.innerHTML = '';
}
};
onMounted(() => {
registerClient(props.inputRef.value!);
});
onBeforeUnmount(() => {
unregisterClient(props.inputRef.value!);
});
return () => h(
props.tag,
{
class: 'sb-contenteditable',
contenteditable: 'true',
ref: props.inputRef,
onKeydown,
onInput: () => {
props.onValueChange(props.inputRef.value?.innerHTML || '');
},
},
);
},
});

View File

@ -0,0 +1,37 @@
/*
* Copyright notice:
*
* Large parts of this file are heavily inspired if not downright copied from editor.js,
* copyright MIT.
* https://editorjs.io/
*/
/**
* Check if object is DOM node
*
* @param {*} node - object to check
* @returns {boolean}
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isElement = (node: any): node is Element => {
if (node instanceof Number) {
return false;
}
return node && node.nodeType && node.nodeType === Node.ELEMENT_NODE;
}
/**
* Check if object is DocumentFragment node
*
* @param {object} node - object to check
* @returns {boolean}
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isFragment = (node: any): node is DocumentFragment => {
if (node instanceof Number) {
return false;
}
return node && node.nodeType && node.nodeType === Node.DOCUMENT_FRAGMENT_NODE;
}

View File

@ -0,0 +1,5 @@
export * from './FormattingToolbar';
export * from './RichText';
export * from './use-formatting-toolbar';
export * from './selection';
export * from './dom';

View File

@ -0,0 +1,93 @@
/*
* Copyright notice:
*
* Large parts of this file are heavily inspired if not downright copied from editor.js,
* copyright MIT.
* https://editorjs.io/
*/
import { isElement } from './dom';
export const getSelection = globalThis.getSelection ? globalThis.getSelection : () => null;
/**
* Returns range from passed Selection object
*
* @param selection - Selection object to get Range from
*/
export const getRangeFromSelection = (selection: Selection): Range|null => {
return selection && selection.rangeCount ? selection.getRangeAt(0) : null;
}
/**
* Returns selected anchor element
*
* @returns {Element|null}
*/
export const getAnchorElementForSelection = (selection: Selection): Element | null => {
const anchorNode = selection.anchorNode;
if (!anchorNode) {
return null;
}
if (!isElement(anchorNode)) {
return anchorNode.parentElement;
} else {
return anchorNode;
}
}
/**
* Calculates position and size of selected text
*
* @returns {DOMRect}
*/
export const getRect = (selection: Selection): DOMRect => {
const defaultRect = {
x: 0,
y: 0,
width: 0,
height: 0,
} as DOMRect;
if (selection.rangeCount === null || isNaN(selection.rangeCount)) {
console.warn('Method SelectionUtils.rangeCount is not supported');
return defaultRect;
}
if (selection.rangeCount === 0) {
return defaultRect;
}
const range = selection.getRangeAt(0).cloneRange() as Range;
let rect = { ...defaultRect };
if (range.getBoundingClientRect) {
rect = range.getBoundingClientRect() as DOMRect;
}
// Fall back to inserting a temporary element
if (rect.x === 0 && rect.y === 0) {
const span = document.createElement('span');
if (span.getBoundingClientRect) {
// Ensure span has dimensions and position by
// adding a zero-width space character
span.appendChild(document.createTextNode('\u200b'));
range.insertNode(span);
rect = span.getBoundingClientRect() as DOMRect;
const spanParent = span.parentNode;
if (spanParent) {
spanParent.removeChild(span);
// Glue any broken text nodes back together
spanParent.normalize();
}
}
}
return rect;
};

View File

@ -0,0 +1,58 @@
import {
ref,
Ref,
inject,
reactive,
} from 'vue';
import { IFormattingToolLibrary } from '../types';
export const SymFormattingToolbarActiveClient = Symbol('Schlechtenburg inline active client');
export const SymFormattingToolbarClients = Symbol('Schlechtenburg inline toolbar client elements');
export const SymFormattingToolLibrary = Symbol('Schlechtenburg inline tool library');
export const useFormattingToolbar = () => {
const clients: Ref<HTMLElement[]> = inject(SymFormattingToolbarClients, ref([]));
const activeClient: Ref<HTMLElement|null> = inject(SymFormattingToolbarActiveClient, ref(null));
const setActiveClient = (client: HTMLElement|null) => {
activeClient.value = client;
};
const setClients = (newClients: HTMLElement[]) => {
clients.value = newClients;
};
const clientIsRegistered = (el: HTMLElement) => !!clients.value.find(cl => cl === el);
const registerClient = (el: HTMLElement) => {
if (clientIsRegistered(el)) {
console.warn('Not reregistering toolbar client that is already registered:', el);
return;
}
setClients([
...clients.value,
el,
]);
};
const unregisterClient = (el: HTMLElement) => {
setClients(clients.value.filter(cl => cl !== el));
};
const tools: IFormattingToolLibrary = inject(SymFormattingToolLibrary, reactive({}));
const getTool = (name: string) => tools[name];
const getAllTools = () => Object.keys(tools).map(name => tools[name]);
return {
clients,
activeClient,
setActiveClient,
registerClient,
unregisterClient,
tools,
getTool,
getAllTools,
};
};

View File

@ -0,0 +1,254 @@
import defaultTo from 'lodash/defaultTo';
import { IFormattingTool } from '../types';
export interface IRichTextFormat {
type: string;
}
export interface IRichTextValue {
text: string;
formats: IRichTextFormat[][];
start: number|null;
end: number|null;
}
export const findToolForElement = (
tools: IFormattingTool[],
element: Element,
): IFormattingTool|null => tools.find(tool => {
if (tool.tagName && element.tagName !== tool.tagName) {
return false;
}
if (tool.className && !element.classList.contains(tool.className)) {
return false;
}
return true;
}) || null;
export const createFromString = (
value: string = '',
formats: IRichTextFormat[] = [],
): IRichTextValue => ({
text: value,
formats: (new Array(value.length)).fill([...formats]),
start: null,
end: null,
});
const createFromDOMNodeRecursively = (
tools: IFormattingTool[],
node: ChildNode,
formats: IRichTextFormat[] = [],
): IRichTextValue => {
if (node.nodeType === node.TEXT_NODE) {
return createFromString(node.textContent || '', formats);
}
if (node.nodeType === node.ELEMENT_NODE) {
return createFromDOMElement(tools, node as Element, formats);
}
return createFromString('', []);
};
export const createFromDOMElement = (
tools: IFormattingTool[],
element: Element,
formats: IRichTextFormat[] = [],
): IRichTextValue => {
const tool = findToolForElement(tools, element);
const subFormats = tool
? [
...formats.filter(f => f.type !== tool.name),
{ type: tool.name },
]
: [ ...formats ];
const nodes = Array.from(element.childNodes);
return concat(...nodes.map(node => createFromDOMNodeRecursively(tools, node, subFormats)));
};
export const createFromDOMString = (
tools: IFormattingTool[],
value: string,
formats: IRichTextFormat[] = [],
): IRichTextValue => {
const div = document.createElement('div');
div.innerHTML = value;
return createFromDOMElement(tools, div, formats);
};
export const create = (
tools: IFormattingTool[],
value: Element|string = '',
): IRichTextValue => {
if (typeof value === 'string') {
return createFromDOMString(tools, value);
}
return createFromDOMElement(tools, value);
}
export const toHTMLString = (
tools: IFormattingTool[],
value: IRichTextValue,
) => {
const tools = [...tools].sort((a, b) => {
const tensionA = defaultTo(a.surfaceTension, Infinity);
const tensionB = defaultTo(b.surfaceTension, Infinity);
return tensionA - tensionB;
});
const elementTree = [];
const string = '';
for (let i = 0; i < value.text.length; i++) {
const c = value.text[i];
const formats = value.formats[i];
const activeFormats = value.formats[i - 1] || [];
const removedFormats = activeFormats
.filter(a => !formats
.find(f => f.type === a.type
&& JSON.stringify(f) === JSON.stringify(a)));
const addedFormats = formats
.filter(f => !activeFormats
.find(a => a.type === f.type
&& JSON.stringify(a) === JSON.stringify(f)));
console.log(c);
for (
}
return string;
}
export const getActiveFormats = (richTextValue: IRichTextValue): IRichTextFormat[] =>
richTextValue.start !== null
? richTextValue.formats[richTextValue.start]
: [];
export const applyFormat = (
value: IRichTextValue,
format: IRichTextFormat,
startIndex?: number,
endIndex?: number,
): IRichTextValue => {
const start = defaultTo(defaultTo(startIndex, value.start), 0);
const end = defaultTo(defaultTo(endIndex, value.end), value.text.length);
return {
...value,
formats: [
...value.formats.slice(0, start),
...value.formats.slice(start, end).map(letterFormatList => [
...letterFormatList.filter(letterFormat => letterFormat.type === format.type),
format,
]),
...value.formats.slice(end),
],
}
};
export const removeFormat = (
value: IRichTextValue,
format: IRichTextFormat,
startIndex?: number,
endIndex?: number,
): IRichTextValue => {
const start = defaultTo(defaultTo(startIndex, value.start), 0);
const end = defaultTo(defaultTo(endIndex, value.end), value.text.length);
return {
...value,
formats: [
...value.formats.slice(0, start),
...value.formats.slice(start, end)
.map(letterFormatList => letterFormatList.filter(letterFormat => letterFormat.type === format.type)),
...value.formats.slice(end),
],
};
}
export const toggleFormat = (
value: IRichTextValue,
format: IRichTextFormat,
): IRichTextValue => {
const activeFormats = getActiveFormats(value);
if (activeFormats.find(f => f.type === format.type)) {
return removeFormat(value, format);
}
return applyFormat(value, format);
}
export const concat = (...richTextValues:IRichTextValue[]): IRichTextValue => richTextValues
.reduce((newValue, value) => ({
text: newValue.text + value.text,
formats: [
...newValue.formats,
...value.formats,
],
start: newValue.start !== null ? newValue.start : value.start,
end: value.end !== null ? value.end : newValue.end,
}), { text: '', formats: [], start: null, end: null });
export const join = (
richTextValues:IRichTextValue[],
separator?: string|IRichTextValue,
): IRichTextValue => richTextValues
.reduce((total, value) => concat(
total,
...(separator
? [typeof separator === 'string' ? createFromString(separator) : separator]
: []),
value,
), createFromString());
export const slice = (
value: IRichTextValue,
startIndex?: number,
endIndex?: number,
): IRichTextValue => {
const start = defaultTo(defaultTo(startIndex, value.start), 0);
const end = defaultTo(defaultTo(endIndex, value.end), value.text.length);
return {
text: value.text.slice(start, end),
formats: value.formats.slice(start, end),
start: value.start !== null ? (value.start >= start ? value.start - start : null) : null,
end: value.end !== null ? (value.end <= end ? end - value.end : null) : null,
};
};
export const insert = (
value: IRichTextValue,
valueToInsert: IRichTextValue|string,
startIndex?: number,
endIndex?: number,
) => {
const start = defaultTo(defaultTo(startIndex, value.start), value.text.length);
const end = defaultTo(defaultTo(endIndex, value.end), value.text.length);
return concat(
slice(value, 0, start),
typeof valueToInsert === 'string' ? createFromString(valueToInsert) : valueToInsert,
slice(value, end, value.text.length),
);
}
export const split = (
value: IRichTextValue,
valueToInsert: IRichTextValue|string,
startIndex?: number,
endIndex?: number,
) => {
const start = defaultTo(defaultTo(startIndex, value.start), value.text.length);
const end = defaultTo(defaultTo(endIndex, value.end), value.text.length);
return concat(
slice(value, 0, start),
typeof valueToInsert === 'string' ? createFromString(valueToInsert) : valueToInsert,
slice(value, end, value.text.length),
);
}

View File

@ -170,3 +170,21 @@ export interface IBlockDefinition<T> {
export interface IBlockLibrary {
[name: string]: IBlockDefinition<any>;
}
export interface IFormattingTool {
name: string;
icon: string;
tagName?: string;
className?: string;
edit: Component;
surfaceTension?: number;
}
/**
* Schlechtenburg maintains a library of formatting tools that are available
*
* @internal
*/
export interface IFormattingToolLibrary {
[name: string]: IFormattingTool;
}

View File

@ -7,7 +7,7 @@ import {
} from 'vue';
export const SymActiveBlock = Symbol('Schlechtenburg active block');
export function useActivation(currentBlockId: string|null = null) {
export const useActivation = (currentBlockId: string|null = null) => {
const activeBlockId: Ref<string|null> = inject(SymActiveBlock, ref(null));
const isActive = computed(() => activeBlockId.value === currentBlockId);
@ -46,4 +46,4 @@ export function useActivation(currentBlockId: string|null = null) {
deactivate,
requestActivation,
};
}
};

View File

@ -10,14 +10,12 @@ import {
ITreeNode,
IBlockData,
} from './types';
import { useDynamicBlocks } from './use-dynamic-blocks';
import { SbMode } from './mode';
export const SymBlockTree= Symbol('Schlechtenburg block tree');
export const SymBlockTreeRegister = Symbol('Schlechtenburg block tree register');
export const SymBlockTreeUnregister = Symbol('Schlechtenburg block tree unregister');
export function useBlockTree() {
export const useBlockTree = () => {
const blockTree: Ref<ITreeNode|null> = inject(SymBlockTree, ref(null));
const registerWithParent = inject(SymBlockTreeRegister, (_b: ITreeNode, _i: number) => {});
const unregisterWithParent = inject(SymBlockTreeUnregister, (_b: ITreeNode) => {});
@ -52,8 +50,6 @@ export function useBlockTree() {
self.children = self.children.filter((child: ITreeNode) => child.id !== id);
});
const { mode } = useDynamicBlocks();
const register = (block: IBlockData<any>, index: number = 0) => {
if (!block.id) {
throw new Error(`Cannot register a block without an id: ${JSON.stringify(block)}`);
@ -77,4 +73,4 @@ export function useBlockTree() {
blockTree,
register,
};
}
};

View File

@ -16,7 +16,7 @@ interface BlockRect {
export const SymBlockDimensions = Symbol('Schlechtenburg block dimensions');
export const SymEditorDimensions = Symbol('Schlechtenburg editor dimensions');
export function useResizeObserver(el: Ref<null|HTMLElement>, symbol: symbol) {
export const useResizeObserver = (el: Ref<null|HTMLElement>, symbol: symbol) => {
const dimensions: Ref<null|BlockRect> = ref(null);
provide(symbol, dimensions);
const triggerSizeCalculation = () => {
@ -47,7 +47,7 @@ export function useResizeObserver(el: Ref<null|HTMLElement>, symbol: symbol) {
})
return { triggerSizeCalculation, dimensions };
}
};
export function useBlockSizing() {
const editorDimensions: Ref<BlockRect|null> = inject(SymEditorDimensions, ref(null));

View File

@ -0,0 +1,11 @@
import {
Ref,
ref,
inject,
} from 'vue';
export const SymRootElement = Symbol('Schlechtenburg root element');
export const useRootElement = () => {
const rootElement: Ref<HTMLElement|null> = inject(SymRootElement, ref(null));
return { rootElement };
};

View File

@ -173,6 +173,14 @@
"integrity": "sha512-nEUfRiARCcaVo3ny3ZQjURjHQZUo/JkEw7rLlSZy/psWGnvwXFtPcr6jb7Yb41DVW5LTe6KRq9LGleRNsg1Frw==",
"dev": true
},
"@babel/runtime": {
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz",
"integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==",
"requires": {
"regenerator-runtime": "^0.13.11"
}
},
"@babel/template": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
@ -420,6 +428,33 @@
"tslib": "^1.9.3"
}
},
"@tannin/compile": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@tannin/compile/-/compile-1.1.0.tgz",
"integrity": "sha512-n8m9eNDfoNZoxdvWiTfW/hSPhehzLJ3zW7f8E7oT6mCROoMNWCB4TYtv041+2FMAxweiE0j7i1jubQU4MEC/Gg==",
"requires": {
"@tannin/evaluate": "^1.2.0",
"@tannin/postfix": "^1.1.0"
}
},
"@tannin/evaluate": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@tannin/evaluate/-/evaluate-1.2.0.tgz",
"integrity": "sha512-3ioXvNowbO/wSrxsDG5DKIMxC81P0QrQTYai8zFNY+umuoHWRPbQ/TuuDEOju9E+jQDXmj6yI5GyejNuh8I+eg=="
},
"@tannin/plural-forms": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@tannin/plural-forms/-/plural-forms-1.1.0.tgz",
"integrity": "sha512-xl9R2mDZO/qiHam1AgMnAES6IKIg7OBhcXqy6eDsRCdXuxAFPcjrej9HMjyCLE0DJ/8cHf0i5OQTstuBRhpbHw==",
"requires": {
"@tannin/compile": "^1.1.0"
}
},
"@tannin/postfix": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@tannin/postfix/-/postfix-1.1.0.tgz",
"integrity": "sha512-oocsqY7g0cR+Gur5jRQLSrX2OtpMLMse1I10JQBm8CdGMrDkh1Mg2gjsiquMHRtBs4Qwu5wgEp5GgIYHk4SNPw=="
},
"@types/braces": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/braces/-/braces-3.0.1.tgz",
@ -450,12 +485,73 @@
"@types/braces": "*"
}
},
"@types/mousetrap": {
"version": "1.6.11",
"resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.11.tgz",
"integrity": "sha512-F0oAily9Q9QQpv9JKxKn0zMKfOo36KHCW7myYsmUyf2t0g+sBTbG3UleTPoguHdE1z3GLFr3p7/wiOio52QFjQ=="
},
"@types/prop-types": {
"version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
},
"@types/react": {
"version": "18.0.26",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz",
"integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==",
"requires": {
"@types/prop-types": "*",
"@types/scheduler": "*",
"csstype": "^3.0.2"
},
"dependencies": {
"csstype": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
}
}
},
"@types/react-dom": {
"version": "18.0.10",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz",
"integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==",
"requires": {
"@types/react": "*"
}
},
"@types/scheduler": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
},
"@types/uuid": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz",
"integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==",
"dev": true
},
"@types/wordpress__data": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@types/wordpress__data/-/wordpress__data-6.0.1.tgz",
"integrity": "sha512-jTLl9mbw54rUq4wuTEmg9bBUaV66MIbg7vVoutpf3Etdnk+kwsuucAdoW+mJTzKEVkGQB5LDIZ/vohd6QrtQ2w==",
"dev": true,
"requires": {
"@types/react": "*",
"redux": "^4.1.0"
}
},
"@types/wordpress__rich-text": {
"version": "3.4.6",
"resolved": "https://registry.npmjs.org/@types/wordpress__rich-text/-/wordpress__rich-text-3.4.6.tgz",
"integrity": "sha512-MeLSATBHrcN3fp8cVylbpx+BKRJ1aootPNtbTblcUAHcuRo6avKu1kaDLxIZb/8YbsD+/3Wm8d1uldeNz9/lhw==",
"dev": true,
"requires": {
"@types/react": "*",
"@types/wordpress__data": "*",
"@types/wordpress__rich-text": "*"
}
},
"@vue/compiler-core": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.0.7.tgz",
@ -842,6 +938,183 @@
"vscode-uri": "^2.1.2"
}
},
"@wordpress/a11y": {
"version": "3.23.0",
"resolved": "https://registry.npmjs.org/@wordpress/a11y/-/a11y-3.23.0.tgz",
"integrity": "sha512-RgnnmI2u6DnechTYr8368LrQy2C/1HtFzXqnDjw9zzT+8kkL8Qa1W2l2JTzz0yHG/n/nR/UXZWXq0FSbnknKlw==",
"requires": {
"@babel/runtime": "^7.16.0",
"@wordpress/dom-ready": "^3.23.0",
"@wordpress/i18n": "^4.23.0"
}
},
"@wordpress/compose": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@wordpress/compose/-/compose-6.0.0.tgz",
"integrity": "sha512-7VPoISTbhIw5bWT7CmIr3XjX86gtI5mhwDrmHAW4Gdt7cd0wRjcJVT45R/PPbZwmAfxjeqVVFh1qTmfz/PxlYg==",
"requires": {
"@babel/runtime": "^7.16.0",
"@types/mousetrap": "^1.6.8",
"@wordpress/deprecated": "^3.23.0",
"@wordpress/dom": "^3.23.0",
"@wordpress/element": "^5.0.0",
"@wordpress/is-shallow-equal": "^4.23.0",
"@wordpress/keycodes": "^3.23.0",
"@wordpress/priority-queue": "^2.23.0",
"change-case": "^4.1.2",
"clipboard": "^2.0.8",
"mousetrap": "^1.6.5",
"use-memo-one": "^1.1.1"
}
},
"@wordpress/data": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@wordpress/data/-/data-8.0.0.tgz",
"integrity": "sha512-1O6DDp7cyHw5x9+M2Y3LZf/dAsVuz4+6PtIRf1EE3VVifDA60cd6lCMs87ljBYFn2hOWgfXL9SwcObfUXtW51g==",
"requires": {
"@babel/runtime": "^7.16.0",
"@wordpress/compose": "^6.0.0",
"@wordpress/deprecated": "^3.23.0",
"@wordpress/element": "^5.0.0",
"@wordpress/is-shallow-equal": "^4.23.0",
"@wordpress/priority-queue": "^2.23.0",
"@wordpress/redux-routine": "^4.23.0",
"equivalent-key-map": "^0.2.2",
"is-plain-object": "^5.0.0",
"is-promise": "^4.0.0",
"lodash": "^4.17.21",
"redux": "^4.1.2",
"turbo-combine-reducers": "^1.0.2",
"use-memo-one": "^1.1.1"
}
},
"@wordpress/deprecated": {
"version": "3.23.0",
"resolved": "https://registry.npmjs.org/@wordpress/deprecated/-/deprecated-3.23.0.tgz",
"integrity": "sha512-dyliFqGFwaUueG9SLu8ugJ6Gr6eaXHiKg188udZjNt4J8WhC/nC03en4gmtCf38C9nTKbZZOzBAdijw5fdJh7g==",
"requires": {
"@babel/runtime": "^7.16.0",
"@wordpress/hooks": "^3.23.0"
}
},
"@wordpress/dom": {
"version": "3.23.0",
"resolved": "https://registry.npmjs.org/@wordpress/dom/-/dom-3.23.0.tgz",
"integrity": "sha512-w1Fkb2K3ODBnZze5iZ7AX3h9QRryO0up7dTUAFKMuRQSFgLKHzhzF78bteA1EV0DDNdiNMzvxr5mSnE1vl1cpg==",
"requires": {
"@babel/runtime": "^7.16.0",
"@wordpress/deprecated": "^3.23.0"
}
},
"@wordpress/dom-ready": {
"version": "3.23.0",
"resolved": "https://registry.npmjs.org/@wordpress/dom-ready/-/dom-ready-3.23.0.tgz",
"integrity": "sha512-wJndB3ER9yn9Z//kc6VB1fu86m7ETwrU5P4uXslyqpGGGpgghWNhwtr0GU2gXguBIRSeAWhwcjYl30wciy6f+w==",
"requires": {
"@babel/runtime": "^7.16.0"
}
},
"@wordpress/element": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@wordpress/element/-/element-5.0.0.tgz",
"integrity": "sha512-u1DhVIdb6VEe8wzxKCrLfRWbeFLrlhYTFSOY6yrtl2z9vr9bCdlLp9aAppTxLNUs8cFcdoCEMpakVRYFyfZwTQ==",
"requires": {
"@babel/runtime": "^7.16.0",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"@wordpress/escape-html": "^2.23.0",
"change-case": "^4.1.2",
"is-plain-object": "^5.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
},
"@wordpress/escape-html": {
"version": "2.23.0",
"resolved": "https://registry.npmjs.org/@wordpress/escape-html/-/escape-html-2.23.0.tgz",
"integrity": "sha512-QmMGJVEoVu3+s46Ya7saYZI8D1jPOKN18eFJX21y59/99tAVvmcWWz0k0uTO5bciDQ7R6ACm9AJS6RiZycODkg==",
"requires": {
"@babel/runtime": "^7.16.0"
}
},
"@wordpress/hooks": {
"version": "3.23.0",
"resolved": "https://registry.npmjs.org/@wordpress/hooks/-/hooks-3.23.0.tgz",
"integrity": "sha512-EYv8xXY0BEJVWu8YPv5LobxEMddFtdbuUVKSryPWHcLjSMrSYRT6j8qzjq8EP/UQolVOxs3THdOoMDySKsJT9g==",
"requires": {
"@babel/runtime": "^7.16.0"
}
},
"@wordpress/i18n": {
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-4.23.0.tgz",
"integrity": "sha512-SF9aJ2gajHtYDLMA9nhnMPerLmKJofUM4qQypwrW5AYwi5JS7jxvZHNETIqqYq5UdhRwsubPjAUfFosIonmfnA==",
"requires": {
"@babel/runtime": "^7.16.0",
"@wordpress/hooks": "^3.23.0",
"gettext-parser": "^1.3.1",
"memize": "^1.1.0",
"sprintf-js": "^1.1.1",
"tannin": "^1.2.0"
}
},
"@wordpress/is-shallow-equal": {
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@wordpress/is-shallow-equal/-/is-shallow-equal-4.23.0.tgz",
"integrity": "sha512-uA1RauILRs85Q864x5xrBfN588Pg0xDrbp4DYs3ktzBL9Jm4igI7+Say7fHpqGBVc8+ZuAEhGeoLt4gUfAJzKg==",
"requires": {
"@babel/runtime": "^7.16.0"
}
},
"@wordpress/keycodes": {
"version": "3.23.0",
"resolved": "https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-3.23.0.tgz",
"integrity": "sha512-CfvxhqwgVU2c3f2B1F09i8E+1/HMkgf4gmmf+0dyKFMmYesByY4GKuvOvKw5dklFWp96qECz6Jf+L2F4vw7//w==",
"requires": {
"@babel/runtime": "^7.16.0",
"@wordpress/i18n": "^4.23.0",
"change-case": "^4.1.2",
"lodash": "^4.17.21"
}
},
"@wordpress/priority-queue": {
"version": "2.23.0",
"resolved": "https://registry.npmjs.org/@wordpress/priority-queue/-/priority-queue-2.23.0.tgz",
"integrity": "sha512-5jf2EK2C/EzXjw7uQ5DwLxDuWP+TyrGdJzcjKXWwAm89H/tdgS6qbRkL6T7ZhARNkm1po88xmCvMarYzceXnBg==",
"requires": {
"@babel/runtime": "^7.16.0",
"requestidlecallback": "^0.3.0"
}
},
"@wordpress/redux-routine": {
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@wordpress/redux-routine/-/redux-routine-4.23.0.tgz",
"integrity": "sha512-uPWlYT28qsPKL1DOLcjU2hUZNsNb3uTSP5rPRD6rwZHtezQLYtg1jFM+HG6TAm0hPjnqMbcULmDNI+FA2fSdHg==",
"requires": {
"@babel/runtime": "^7.16.0",
"is-plain-object": "^5.0.0",
"is-promise": "^4.0.0",
"rungen": "^0.3.2"
}
},
"@wordpress/rich-text": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@wordpress/rich-text/-/rich-text-6.0.0.tgz",
"integrity": "sha512-vzEzUn4VtYdnf3i96HPaIwxYvebw1t+Pubwma6TfBYa2pBI2Q8L6E+LaWkFtjv6Pw8pCv/+5m9sQPnUPo0K7zw==",
"requires": {
"@babel/runtime": "^7.16.0",
"@wordpress/a11y": "^3.23.0",
"@wordpress/compose": "^6.0.0",
"@wordpress/data": "^8.0.0",
"@wordpress/deprecated": "^3.23.0",
"@wordpress/element": "^5.0.0",
"@wordpress/escape-html": "^2.23.0",
"@wordpress/i18n": "^4.23.0",
"@wordpress/keycodes": "^3.23.0",
"memize": "^1.1.0",
"rememo": "^4.0.0"
}
},
"agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@ -881,6 +1154,39 @@
"fill-range": "^7.0.1"
}
},
"camel-case": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
"integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
"requires": {
"pascal-case": "^3.1.2",
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"capital-case": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz",
"integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==",
"requires": {
"no-case": "^3.0.4",
"tslib": "^2.0.3",
"upper-case-first": "^2.0.2"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@ -932,6 +1238,32 @@
}
}
},
"change-case": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz",
"integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==",
"requires": {
"camel-case": "^4.1.2",
"capital-case": "^1.0.4",
"constant-case": "^3.0.4",
"dot-case": "^3.0.4",
"header-case": "^2.0.4",
"no-case": "^3.0.4",
"param-case": "^3.0.4",
"pascal-case": "^3.1.2",
"path-case": "^3.0.4",
"sentence-case": "^3.0.4",
"snake-case": "^3.0.4",
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"cli-highlight": {
"version": "2.1.11",
"resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz",
@ -946,6 +1278,16 @@
"yargs": "^16.0.0"
}
},
"clipboard": {
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz",
"integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
"requires": {
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^2.0.0"
}
},
"cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
@ -978,6 +1320,23 @@
"integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
"dev": true
},
"constant-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz",
"integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==",
"requires": {
"no-case": "^3.0.4",
"tslib": "^2.0.3",
"upper-case": "^2.0.2"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"cookie": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
@ -1005,12 +1364,46 @@
"ms": "2.1.2"
}
},
"delegate": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
},
"dot-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
"integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
"requires": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"encoding": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
"requires": {
"iconv-lite": "^0.6.2"
}
},
"equivalent-key-map": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/equivalent-key-map/-/equivalent-key-map-0.2.2.tgz",
"integrity": "sha512-xvHeyCDbZzkpN4VHQj/n+j2lOwL0VWszG30X4cOrc9Y7Tuo2qCdZK/0AMod23Z5dCtNUbaju6p0rwOhHUk05ew=="
},
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@ -1066,6 +1459,15 @@
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true
},
"gettext-parser": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.4.0.tgz",
"integrity": "sha512-sedZYLHlHeBop/gZ1jdg59hlUEcpcZJofLq2JFwJT1zTqAU3l2wFv6IsuwFHGqbiT9DWzMUW4/em2+hspnmMMA==",
"requires": {
"encoding": "^0.1.12",
"safe-buffer": "^5.1.1"
}
},
"glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
@ -1081,6 +1483,14 @@
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true
},
"good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
"integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
"requires": {
"delegate": "^3.1.2"
}
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@ -1093,6 +1503,22 @@
"integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==",
"dev": true
},
"header-case": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz",
"integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==",
"requires": {
"capital-case": "^1.0.4",
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"highlight.js": {
"version": "10.7.3",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
@ -1109,6 +1535,14 @@
"debug": "4"
}
},
"iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@ -1136,11 +1570,20 @@
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
},
"is-promise": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"jsesc": {
"version": "2.5.2",
@ -1162,6 +1605,29 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"requires": {
"js-tokens": "^3.0.0 || ^4.0.0"
}
},
"lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
"requires": {
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@ -1186,6 +1652,11 @@
"sourcemap-codec": "^1.4.8"
}
},
"memize": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/memize/-/memize-1.1.0.tgz",
"integrity": "sha512-K4FcPETOMTwe7KL2LK0orMhpOmWD2wRGwWWpbZy0fyArwsyIKR8YJVz8+efBAh3BO4zPqlSICu4vsLTRRqtFAg=="
},
"merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@ -1208,6 +1679,11 @@
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
},
"mousetrap": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz",
"integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA=="
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -1231,6 +1707,22 @@
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
"dev": true
},
"no-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
"requires": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"node-unique-machine-id": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/node-unique-machine-id/-/node-unique-machine-id-1.1.0.tgz",
@ -1254,6 +1746,22 @@
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"dev": true
},
"param-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
"integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
"requires": {
"dot-case": "^3.0.4",
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"parse5": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
@ -1277,6 +1785,38 @@
}
}
},
"pascal-case": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
"requires": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"path-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz",
"integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==",
"requires": {
"dot-case": "^3.0.4",
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@ -1312,6 +1852,46 @@
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
"dev": true
},
"react": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"requires": {
"loose-envify": "^1.1.0"
}
},
"react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
"requires": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.0"
}
},
"redux": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz",
"integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
"requires": {
"@babel/runtime": "^7.9.2"
}
},
"regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
"rememo": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/rememo/-/rememo-4.0.2.tgz",
"integrity": "sha512-NVfSP9NstE3QPNs/TnegQY0vnJnstKQSpcrsI2kBTB3dB2PkdfKdTa+abbjMIDqpc63fE5LfjLgfMst0ULMFxQ=="
},
"requestidlecallback": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/requestidlecallback/-/requestidlecallback-0.3.0.tgz",
"integrity": "sha512-TWHFkT7S9p7IxLC5A1hYmAYQx2Eb9w1skrXmQ+dS1URyvR8tenMLl4lHbqEOUnpEYxNKpkVMXUgknVpBZWXXfQ=="
},
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@ -1339,6 +1919,67 @@
"queue-microtask": "^1.2.2"
}
},
"rungen": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/rungen/-/rungen-0.3.2.tgz",
"integrity": "sha512-zWl10xu2D7zoR8zSC2U6bg5bYF6T/Wk7rxwp8IPaJH7f0Ge21G03kNHVgHR7tyVkSSfAOG0Rqf/Cl38JftSmtw=="
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"scheduler": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
"requires": {
"loose-envify": "^1.1.0"
}
},
"select": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
"integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
},
"sentence-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz",
"integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==",
"requires": {
"no-case": "^3.0.4",
"tslib": "^2.0.3",
"upper-case-first": "^2.0.2"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"snake-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
"integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
"requires": {
"dot-case": "^3.0.4",
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@ -1357,6 +1998,11 @@
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"dev": true
},
"sprintf-js": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
"integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
},
"string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
@ -1386,6 +2032,14 @@
"has-flag": "^3.0.0"
}
},
"tannin": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/tannin/-/tannin-1.2.0.tgz",
"integrity": "sha512-U7GgX/RcSeUETbV7gYgoz8PD7Ni4y95pgIP/Z6ayI3CfhSujwKEBlGFTCRN+Aqnuyf4AN2yHL+L8x+TCGjb9uA==",
"requires": {
"@tannin/plural-forms": "^1.1.0"
}
},
"thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
@ -1404,6 +2058,11 @@
"thenify": ">= 3.1.0 < 4"
}
},
"tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
},
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@ -1425,12 +2084,52 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
},
"turbo-combine-reducers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/turbo-combine-reducers/-/turbo-combine-reducers-1.0.2.tgz",
"integrity": "sha512-gHbdMZlA6Ym6Ur5pSH/UWrNQMIM9IqTH6SoL1DbHpqEdQ8i+cFunSmSlFykPt0eGQwZ4d/XTHOl74H0/kFBVWw=="
},
"typescript": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz",
"integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==",
"dev": true
},
"upper-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz",
"integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==",
"requires": {
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"upper-case-first": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz",
"integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==",
"requires": {
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
}
},
"use-memo-one": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz",
"integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ=="
},
"uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",

View File

@ -27,6 +27,7 @@
},
"dependencies": {
"@schlechtenburg/style": "^0.0.0",
"@wordpress/rich-text": "^6.0.0",
"lodash": "^4.17.21",
"uuid": "^8.3.2"
},
@ -36,6 +37,7 @@
"devDependencies": {
"@types/lodash-es": "^4.17.4",
"@types/uuid": "^8.3.0",
"@types/wordpress__rich-text": "^3.4.6",
"@vuedx/typecheck": "^0.6.3",
"@vuedx/typescript-plugin-vue": "^0.6.3",
"vue": "^3.2.31"

View File

@ -43,7 +43,7 @@ body {
box-sizing: border-box;
}
&--admin-nav {
&--edit-nav {
z-index: 100;
position: fixed;
top: 0;
@ -62,7 +62,7 @@ body {
@media screen and (min-width: 1000px) {
--ex-nav-width: var(--ex-nav-expanded-width);
&--admin-nav {
&--edit-nav {
position: unset;
width: unset;
flex-basis: var(--ex-nav-width);

View File

@ -3,14 +3,14 @@ import { NuxtPage } from '#components';
import './app.scss';
const AdminNav = defineAsyncComponent(() => import('~~/components/admin/Nav'));
const AdminNav = defineAsyncComponent(() => import('~~/components/_/Nav'));
export default defineComponent({
setup() {
const { me } = useMe();
return () => (
<div class="ex-app">
{me.value ? <AdminNav class="ex-app--admin-nav" /> : null}
{me.value ? <AdminNav class="ex-app--edit-nav" /> : null}
<NuxtPage class="ex-app--page" />
</div>
);

View File

@ -1,10 +1,14 @@
.ex-admin-nav {
.ex-edit-nav {
background-color: white;
width: var(--ex-nav-width);
display: flex;
flex-direction: column;
align-items: stretch;
transition: width 0.2s ease;
.icon {
height: 1.5rem;
width: 1.5rem;
}
&_expanded {
width: 300px;
@ -54,24 +58,17 @@
width: calc(100% - 60px);
overflow: hidden;
margin: 0px;
margin-left: 16px;
transition: opacity 0.1s ease;
}
&-icon {
position: absolute;
left: calc((var(--ex-nav-width) / 2) - 8px);
right: 0;
}
}
&_expanded &--menu-item {
&-title {
//width: calc(100% - (32px + 24px));
opacity: 1;
&-action {
justify-content: flex-start;
}
&-icon {
&-title {
opacity: 1;
margin-left: 16px;
}
}

View File

@ -0,0 +1,67 @@
import { defineComponent } from 'vue';
import { NuxtLink } from '#components';
import './Nav.scss';
export default defineComponent({
setup() {
const { setMe } = useMe();
const expanded = useState(() => false);
const toggle = () => {
expanded.value = !expanded.value;
};
const classes = computed(() => ({
'ex-edit-nav': true,
'ex-edit-nav_expanded': expanded.value,
}));
const logout = () => {
setMe(null);
useGqlToken({
token: null,
config: { type: 'Bearer' },
});
};
return () => (
<nav class={classes.value}>
<button
class="ex-edit-nav--toggle"
type="button"
onClick={() => toggle()}
aria-label="Toggle"
>
{expanded.value
? <Icon name="icon-park-solid:expand-right" class="ex-edit-nav--menu-item-icon" />
: <Icon name="icon-park-solid:expand-left" class="ex-edit-nav--menu-item-icon" />}
</button>
<ul class="ex-edit-nav--menu">
<li class="ex-edit-nav--menu-item">
<NuxtLink
class="ex-edit-nav--menu-item-action"
to="/"
>
<Icon name="mdi:web" class="ex-edit-nav--menu-item-icon" />
<span class="ex-edit-nav--menu-item-title">Website</span>
</NuxtLink>
</li>
<li class="ex-edit-nav--menu-spacer"></li>
<li class="ex-edit-nav--menu-item">
<button
type="button"
class="ex-edit-nav--menu-item-action"
onClick={() => logout()}
>
<Icon name="mdi:logout" class="ex-edit-nav--menu-item-icon" />
<span class="ex-edit-nav--menu-item-title">Logout</span>
</button>
</li>
</ul>
</nav>
);
},
});

View File

@ -1,73 +0,0 @@
import { defineComponent } from 'vue';
import { NuxtLink } from '#components';
import './Nav.scss';
export default defineComponent({
setup() {
const { setMe } = useMe();
const expanded = useState(() => false);
const toggle = () => {
expanded.value = !expanded.value;
};
const classes = computed(() => ({
'ex-admin-nav': true,
'ex-admin-nav_expanded': expanded.value,
}));
const logout = () => {
setMe(null);
useGqlToken({
token: null,
config: { type: 'Bearer' },
});
};
return () => (
<nav class={classes.value}>
<button
class="ex-admin-nav--toggle"
type="button"
onClick={() => toggle()}
aria-label="Toggle"
>
<font-awesome-icon
icon={`fa-solid fa-arrow-${expanded.value ? 'left' : 'right'}`}
/>
</button>
<ul class="ex-admin-nav--menu">
<li class="ex-admin-nav--menu-item">
<NuxtLink
class="ex-admin-nav--menu-item-action"
to="/"
>
<font-awesome-icon
class="ex-admin-nav--menu-item-icon"
icon="fa-solid fa-home"
/>
<span class="ex-admin-nav--menu-item-title">Website</span>
</NuxtLink>
</li>
<li class="ex-admin-nav--menu-spacer"></li>
<li class="ex-admin-nav--menu-item">
<button
type="button"
class="ex-admin-nav--menu-item-action"
onClick={() => logout()}
>
<font-awesome-icon
class="ex-admin-nav--menu-item-icon"
icon="fa-solid fa-right-from-bracket"
/>
<span class="ex-admin-nav--menu-item-title">Logout</span>
</button>
</li>
</ul>
</nav>
);
},
});

View File

@ -3,6 +3,7 @@ import { defineNuxtConfig } from 'nuxt/config';
export default defineNuxtConfig({
modules: [
'nuxt-graphql-client',
'nuxt-icon',
],
runtimeConfig: {

View File

@ -812,32 +812,6 @@
"dev": true,
"optional": true
},
"@fortawesome/fontawesome-common-types": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.2.1.tgz",
"integrity": "sha512-Sz07mnQrTekFWLz5BMjOzHl/+NooTdW8F8kDQxjWwbpOJcnoSg4vUDng8d/WR1wOxM0O+CY9Zw0nR054riNYtQ=="
},
"@fortawesome/fontawesome-svg-core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.2.1.tgz",
"integrity": "sha512-HELwwbCz6C1XEcjzyT1Jugmz2NNklMrSPjZOWMlc+ZsHIVk+XOvOXLGGQtFBwSyqfJDNgRq4xBCwWOaZ/d9DEA==",
"requires": {
"@fortawesome/fontawesome-common-types": "6.2.1"
}
},
"@fortawesome/free-solid-svg-icons": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.2.1.tgz",
"integrity": "sha512-oKuqrP5jbfEPJWTij4sM+/RvgX+RMFwx3QZCZcK9PrBDgxC35zuc7AOFsyMjMd/PIFPeB2JxyqDr5zs/DZFPPw==",
"requires": {
"@fortawesome/fontawesome-common-types": "6.2.1"
}
},
"@fortawesome/vue-fontawesome": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.2.tgz",
"integrity": "sha512-xHVtVY8ASUeEvgcA/7vULUesENhD+pi/EirRHdMBqooHlXBqK+yrV6d8tUye1m5UKQKVgYAHMhUBfOnoiwvc8Q=="
},
"@graphql-codegen/cli": {
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-2.16.1.tgz",
@ -2033,6 +2007,19 @@
"resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
"integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="
},
"@iconify/types": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
"integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="
},
"@iconify/vue": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@iconify/vue/-/vue-4.0.2.tgz",
"integrity": "sha512-LRp+mYh8N0bcX4lustHtI5o1aEoio9HN3/19uIzVOvI78qopKBjzsDK5hkEZYDSc6+LKG8hfLxTxpW8CejXGZg==",
"requires": {
"@iconify/types": "^2.0.0"
}
},
"@ioredis/commands": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
@ -2165,7 +2152,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.0.0.tgz",
"integrity": "sha512-7ZsOLt5s9a0ZleAIzmoD70JwkZf5ti6bDdxl6f8ew7Huxz+ni/oRfTPTX9TrORXsgW5CvDt6Q9M7IJNPkAN/Iw==",
"dev": true,
"requires": {
"@nuxt/schema": "3.0.0",
"c12": "^1.0.1",
@ -6713,6 +6699,15 @@
}
}
},
"nuxt-icon": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/nuxt-icon/-/nuxt-icon-0.1.8.tgz",
"integrity": "sha512-oPFlLOZCy80MN+hf49+mBkOIHWVF3sOqZREQZw3qD0N6wGlR15QeRQtKQC8qGeQcc+xvpLQm0GvrdJ8FxFOPYg==",
"requires": {
"@iconify/vue": "^4.0.1",
"@nuxt/kit": "^3.0.0"
}
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",

View File

@ -13,9 +13,6 @@
"nuxt": "3.0.0"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.2.1",
"@fortawesome/free-solid-svg-icons": "^6.2.1",
"@fortawesome/vue-fontawesome": "^3.0.2",
"@graphql-codegen/cli": "^2.16.1",
"@schlechtenburg/core": "^0.0.0",
"@schlechtenburg/heading": "^0.0.0",
@ -24,6 +21,7 @@
"@schlechtenburg/paragraph": "^0.0.0",
"@schlechtenburg/style": "^0.0.0",
"event-target-polyfill": "^0.0.3",
"nuxt-graphql-client": "^0.2.23"
"nuxt-graphql-client": "^0.2.23",
"nuxt-icon": "^0.1.8"
}
}

View File

@ -1,19 +0,0 @@
import { library } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import {
faRightFromBracket,
faHome,
faArrowRight,
faArrowLeft,
} from '@fortawesome/free-solid-svg-icons';
/* add icons to the library */
library.add(faRightFromBracket);
library.add(faArrowRight);
library.add(faArrowLeft);
library.add(faHome);
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.component('font-awesome-icon', FontAwesomeIcon);
})

View File

@ -0,0 +1,38 @@
import {
defineComponent,
computed,
PropType,
} from 'vue';
import {
SbButton,
getSelection,
getRangeFromSelection,
} from '@schlechtenburg/core';
export default defineComponent({
props: {
isActive: {
type: (null as unknown) as PropType<HTMLElement|null>,
default: null,
},
eventChange: {
type: (null as unknown) as PropType<Selection|null>,
default: null,
},
value: {
type: (null as unknown) as PropType<Range|null>,
default: null,
},
},
setup(props) {
return () => <SbButton
type="button"
class={{ 'sb-button_active': isActive.value }}
onClick={() => {
}}
>i</SbButton>;
},
});

View File

@ -0,0 +1,11 @@
import { defineAsyncComponent } from 'vue';
import { IFormattingTool } from '@schlechtenburg/core';
export const name = '@schechtenburg/italic';
export default {
name,
title: 'Italic',
icon: 'I',
edit: defineAsyncComponent(() => import('./edit')),
} as IFormattingTool;

1334
packages/italic/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
{
"name": "@schlechtenburg/italic",
"version": "0.0.0",
"description": "> TODO: description",
"author": "Benjamin Bädorf <hello@benjaminbaedorf.eu>",
"homepage": "",
"license": "GPL-3.0-or-later",
"main": "lib/index.ts",
"scripts": {
"typecheck": "vuedx-typecheck --no-pretty ./lib",
"test": "echo \"Error: run tests from root\" && exit 1"
},
"directories": {
"lib": "lib",
"test": "__tests__"
},
"files": [
"lib",
"docs"
],
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git@git.b12f.io:b12f/schlechtenburg.git"
},
"dependencies": {
"@schlechtenburg/core": "^0.0.0"
},
"devDependencies": {
"@vuedx/typecheck": "^0.6.3",
"@vuedx/typescript-plugin-vue": "^0.6.3",
"vue": "^3.2.31"
}
}

View File

@ -14,6 +14,8 @@ import {
SbToolbar,
SbSelect,
generateBlockId,
SbRichText,
getSelection,
} from '@schlechtenburg/core';
import { isEmptyContentEditable } from './contenteditable';
import {
@ -77,21 +79,11 @@ export default defineComponent({
}
};
onMounted(() => {
focusInput();
if (inputEl.value) {
inputEl.value.innerHTML = localData.value;
}
});
watch(isActive, focusInput);
watch(() => props.data, () => {
localData.value = props.data.value;
localData.align = props.data.align;
if (inputEl.value) {
inputEl.value.innerHTML = localData.value;
}
});
const onTextUpdate = ($event: Event) => {
@ -136,7 +128,7 @@ export default defineComponent({
activate(id);
$event.preventDefault();
}
}window
};
const onKeyup = ($event: KeyboardEvent) => {
@ -144,7 +136,7 @@ export default defineComponent({
props.eventRemoveSelf();
}
const selection = window.getSelection();
const selection = getSelection();
const node = selection?.focusNode;
const childNodes = Array.from(inputEl?.value?.childNodes || []);
const index = node ? childNodes.indexOf(node as ChildNode) : -1;
@ -174,16 +166,24 @@ export default defineComponent({
<option>right</option>
</SbSelect>
</SbToolbar>
<p
<SbRichText
tag="p"
class="sb-paragraph__input"
ref={inputEl}
contenteditable
onInput={onTextUpdate}
inputRef={inputEl}
value={localData.value}
onValueChange={(value: string) => {
localData.value = value;
}}
{/*
onFocus={onFocus}
onBlur={onBlur}
onKeydown={onKeydown}
onKeyup={onKeyup}
></p>
*/...{}}
></SbRichText>
</div>
);
},