eddev 2.0.0-beta.116 → 2.0.0-beta.118
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/editor-styles.css +4 -0
- package/dist/app/lib/blocks/EditableText.d.ts +14 -1
- package/dist/app/lib/blocks/EditableText.js +8 -2
- package/dist/app/lib/blocks/InnerBlocks.d.ts +9 -5
- package/dist/app/lib/blocks/InnerBlocks.js +66 -27
- package/dist/app/lib/blocks/defineBlock.d.ts +3 -0
- package/dist/app/lib/blocks/defineBlock.js +7 -0
- package/dist/app/lib/blocks/editor/EditorHighlights.js +43 -9
- package/dist/app/lib/blocks/editor/EditorSupport.js +13 -7
- package/dist/app/lib/blocks/editor/block-templates.d.ts +6 -0
- package/dist/app/lib/blocks/editor/block-templates.js +64 -0
- package/dist/app/lib/blocks/editor/create-block.d.ts +9 -0
- package/dist/app/lib/blocks/editor/create-block.js +13 -0
- package/dist/app/lib/blocks/editor/editor-config.d.ts +38 -3
- package/dist/app/lib/blocks/editor/editor-config.js +3 -63
- package/dist/app/lib/blocks/editor/installGutenbergHooks.d.ts +3 -0
- package/dist/app/lib/blocks/editor/installGutenbergHooks.js +68 -1
- package/dist/app/lib/blocks/index.d.ts +5 -4
- package/dist/app/lib/blocks/index.js +5 -4
- package/dist/app/lib/blocks/inline-editing.d.ts +8 -0
- package/dist/app/lib/devtools/hooks/useTailwind.d.ts +5 -5
- package/dist/node/cli/version.d.ts +1 -1
- package/dist/node/cli/version.js +1 -1
- package/dist/node/compiler/get-vite-config.d.ts +5 -1
- package/dist/node/compiler/get-vite-config.js +48 -6
- package/dist/node/types/block-type.d.ts +2 -2
- package/package.json +2 -2
- package/types.meta.d.ts +105 -0
package/css/editor-styles.css
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
import { ElementType } from "react";
|
|
2
2
|
import { InlineValueStore } from "./inline-editing.js";
|
|
3
3
|
export type InlineTextValueStore = InlineValueStore<string>;
|
|
4
|
+
type BuiltinFormats = "core/bold" | "core/code" | "core/italic" | "core/link" | "core/strikethrough" | "core/underline" | "core/subscript" | "core/superscript" | "core/unknown" | "core/non-breaking-space" | "core/footnote";
|
|
4
5
|
type Props<T extends ElementType> = {
|
|
5
6
|
/** Specify a tag name or React component */
|
|
6
7
|
as?: T;
|
|
7
8
|
/** Prevents this text element from being multi-line */
|
|
8
9
|
disableLineBreaks?: boolean;
|
|
9
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Specify which formatting options are allowed in this text element (bold, italics etc).
|
|
12
|
+
*
|
|
13
|
+
* By default, all options are enabled.
|
|
14
|
+
*
|
|
15
|
+
* Set to an empty array to disable formatting options.
|
|
16
|
+
*
|
|
17
|
+
* You can register new formats in `_editor.tsx` using the `defineEditorConfig` function.
|
|
18
|
+
**/
|
|
19
|
+
allowedFormats?: (BuiltinFormats | (string & {}))[];
|
|
20
|
+
/**
|
|
21
|
+
* @deprecated use `allowedFormats` instead
|
|
22
|
+
*/
|
|
10
23
|
inlineToolbar?: boolean;
|
|
11
24
|
/** Specify default content to use on the frontend if nothing has been entered */
|
|
12
25
|
defaultValue?: string;
|
|
@@ -6,8 +6,13 @@ export function EditableText({ id, as, appendOnEnter, store, ...props }) {
|
|
|
6
6
|
const readOnly = useBlockContext()?.readonly;
|
|
7
7
|
if (!readOnly) {
|
|
8
8
|
const [value, setValue] = useValueStore(store ?? id);
|
|
9
|
+
// const defaultFormats = wp.data.useSelect((select) => {
|
|
10
|
+
// const formats = (select(wp.richText.store) as any).getFormatTypes()
|
|
11
|
+
// console.log("U", formats)
|
|
12
|
+
// return formats.map((f: any) => f.name)
|
|
13
|
+
// }, [])
|
|
9
14
|
const appendBlocks = useBlockAppender();
|
|
10
|
-
return (_jsx(wp.blockEditor.RichText, { ...props, placeholder: props.placeholder ?? props.defaultValue, tagName: as, value: value || "", onChange: setValue, inlineToolbar: props.
|
|
15
|
+
return (_jsx(wp.blockEditor.RichText, { ...props, placeholder: props.placeholder ?? props.defaultValue, tagName: as, value: value || "", onChange: setValue, allowedFormats: props.inlineToolbar === false ? [] : props.allowedFormats, disableLineBreaks: props.disableLineBreaks, "data-allowed-formats": props.allowedFormats?.join(" "), onKeyDownCapture: (e) => {
|
|
11
16
|
if (e.key === "Enter" && appendOnEnter && appendBlocks) {
|
|
12
17
|
appendBlocks([
|
|
13
18
|
wp.blocks.createBlock(typeof appendOnEnter === "string" ? appendOnEnter : "core/paragraph"),
|
|
@@ -21,11 +26,12 @@ export function EditableText({ id, as, appendOnEnter, store, ...props }) {
|
|
|
21
26
|
let [value] = useValueStore(store ?? id);
|
|
22
27
|
const handleClickEvent = useRouter((r) => r.handleClickEvent);
|
|
23
28
|
const otherProps = { ...props };
|
|
24
|
-
delete otherProps.inlineToolbar;
|
|
25
29
|
delete otherProps.disableLineBreaks;
|
|
26
30
|
delete otherProps.id;
|
|
27
31
|
otherProps.as = otherProps.asProp ?? undefined;
|
|
28
32
|
delete otherProps.asProp;
|
|
33
|
+
delete otherProps.allowedFormats;
|
|
34
|
+
delete otherProps.disableLineBreaks;
|
|
29
35
|
delete otherProps.placeholder;
|
|
30
36
|
if (value === "" || typeof value !== "string") {
|
|
31
37
|
if (props.defaultValue) {
|
|
@@ -2,7 +2,7 @@ import { FunctionComponent } from "react";
|
|
|
2
2
|
import { ContentBlockLayoutProps } from "./ContentBlocks.js";
|
|
3
3
|
import { BlockTemplate } from "./editor/block-templates.js";
|
|
4
4
|
type AppenderConfig = {
|
|
5
|
-
type: "default" | "button" | CustomBlockAppender;
|
|
5
|
+
type: "default" | "button" | "simple" | CustomBlockAppender;
|
|
6
6
|
className?: string;
|
|
7
7
|
};
|
|
8
8
|
export type CustomBlockAppender = FunctionComponent<{
|
|
@@ -26,9 +26,13 @@ type InnerBlocksProps = {
|
|
|
26
26
|
* NOTE: This will have no effect on the frontend, since no wrapper div is created on the frontend.
|
|
27
27
|
**/
|
|
28
28
|
adminClassName?: string;
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
/** The default blocks to insert when there are no (non-templated) blocks */
|
|
30
|
+
defaultBlocks?: BlockTemplate;
|
|
31
|
+
/** Blocks to ensure are inserted at the top of the page */
|
|
32
|
+
headerTemplate?: BlockTemplate;
|
|
33
|
+
/** Blocks to ensure are inserted at the bottom of the page */
|
|
34
|
+
footerTemplate?: BlockTemplate;
|
|
35
|
+
/** A full-page block template */
|
|
32
36
|
template?: BlockTemplate;
|
|
33
37
|
/**
|
|
34
38
|
* `false` allows all operations
|
|
@@ -41,7 +45,7 @@ type InnerBlocksProps = {
|
|
|
41
45
|
* @default false
|
|
42
46
|
*
|
|
43
47
|
*/
|
|
44
|
-
templateLock?: "all" | "insert" | "contentOnly" | false;
|
|
48
|
+
templateLock?: "all" | "insert" | "contentOnly" | "none" | false;
|
|
45
49
|
appender?: AppenderConfig;
|
|
46
50
|
prioritizedInserterBlocks?: ChildBlockTypeName[];
|
|
47
51
|
} & ContentBlockLayoutProps;
|
|
@@ -1,25 +1,58 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo } from "react";
|
|
2
3
|
import { ContentBlocks } from "./ContentBlocks.js";
|
|
3
|
-
import { transformBlockTemplate } from "./editor/block-templates.js";
|
|
4
|
+
import { applyTemplateBlocks, transformBlockTemplate } from "./editor/block-templates.js";
|
|
4
5
|
import { blocksByTag } from "./editor/blocks-by-tag.js";
|
|
5
6
|
import { useBlockContext, useInnerBlocks } from "./inline-editing.js";
|
|
6
|
-
|
|
7
|
+
import { hash } from "object-code";
|
|
8
|
+
const Appender = ({ config, ...props }) => {
|
|
7
9
|
const clientId = useBlockContext()?.block[1].clientId;
|
|
8
|
-
if (
|
|
9
|
-
return _jsx(wp.blockEditor.ButtonBlockAppender, {
|
|
10
|
+
if (config?.type === "button") {
|
|
11
|
+
return _jsx(wp.blockEditor.ButtonBlockAppender, { ...props, rootClientId: clientId, className: config.className });
|
|
10
12
|
}
|
|
11
|
-
else if (
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
else if (config?.type === "simple") {
|
|
14
|
+
return (_jsx(wp.blockEditor.ButtonBlockAppender, { ...props, rootClientId: clientId, className: (props.className || "") + " block-editor-inserter__toggle has-icon simple-appender" }));
|
|
15
|
+
}
|
|
16
|
+
else if (typeof config?.type === "function") {
|
|
17
|
+
const Type = config?.type;
|
|
18
|
+
return (_jsx(wp.blockEditor.Inserter, { rootClientId: clientId, renderToggle: (p) => {
|
|
14
19
|
return _jsx(Type, { ...p });
|
|
15
|
-
},
|
|
20
|
+
}, isAppender: true,
|
|
21
|
+
// @ts-ignore
|
|
22
|
+
__experimentalIsQuick: true }));
|
|
23
|
+
// } else if (config?.type === "simple") {
|
|
24
|
+
// return (
|
|
25
|
+
// <wp.blockEditor.Inserter
|
|
26
|
+
// clientId={clientId}
|
|
27
|
+
// rootClientId={clientId}
|
|
28
|
+
// renderToggle={(p: any) => {
|
|
29
|
+
// return (
|
|
30
|
+
// <button
|
|
31
|
+
// className="simple-appender components-button block-editor-inserter__toggle !inline-flex has-icon"
|
|
32
|
+
// onClick={() => p.onToggle()}
|
|
33
|
+
// >
|
|
34
|
+
// <svg
|
|
35
|
+
// xmlns="http://www.w3.org/2000/svg"
|
|
36
|
+
// viewBox="0 0 24 24"
|
|
37
|
+
// width="24"
|
|
38
|
+
// height="24"
|
|
39
|
+
// aria-hidden="true"
|
|
40
|
+
// focusable="false"
|
|
41
|
+
// >
|
|
42
|
+
// <path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z"></path>
|
|
43
|
+
// </svg>
|
|
44
|
+
// </button>
|
|
45
|
+
// )
|
|
46
|
+
// }}
|
|
47
|
+
// isAppender
|
|
48
|
+
// // @ts-ignore
|
|
49
|
+
// __experimentalIsQuick
|
|
50
|
+
// />
|
|
51
|
+
// )
|
|
16
52
|
}
|
|
17
53
|
else {
|
|
18
|
-
return (_jsx(wp.blockEditor.DefaultBlockAppender
|
|
19
54
|
// @ts-ignore
|
|
20
|
-
, {
|
|
21
|
-
// @ts-ignore
|
|
22
|
-
className: props.className, rootClientId: clientId, lastBlockClientId: clientId }));
|
|
55
|
+
return _jsx(wp.blockEditor.InnerBlocks.DefaultBlockAppender, { ...props });
|
|
23
56
|
}
|
|
24
57
|
};
|
|
25
58
|
export function createAppender(comp) {
|
|
@@ -33,29 +66,35 @@ export function createAppender(comp) {
|
|
|
33
66
|
export function InnerBlocks(props) {
|
|
34
67
|
if (env.admin) {
|
|
35
68
|
const inlineContext = useBlockContext();
|
|
69
|
+
const appender = useMemo(() => {
|
|
70
|
+
return (p) => _jsx(Appender, { config: props.appender, ...p });
|
|
71
|
+
}, [props.appender]);
|
|
36
72
|
if (!inlineContext?.readonly) {
|
|
37
73
|
const innerBlocksProps = wp.blockEditor.useInnerBlocksProps({}, {
|
|
38
74
|
orientation: props.orientation ?? "vertical",
|
|
39
75
|
allowedBlocks: props.allowedBlocks ? blocksByTag.expand(props.allowedBlocks) : undefined,
|
|
40
76
|
prioritizedInserterBlocks: props.prioritizedInserterBlocks,
|
|
41
|
-
renderAppender:
|
|
42
|
-
|
|
43
|
-
: wp.blockEditor.InnerBlocks.ButtonBlockAppender,
|
|
44
|
-
templateLock: props.templateLock ?? false,
|
|
77
|
+
renderAppender: appender,
|
|
78
|
+
templateLock: props.templateLock === "none" ? false : (props.templateLock ?? false),
|
|
45
79
|
template: props.template ? transformBlockTemplate(props.template) : undefined,
|
|
46
80
|
});
|
|
81
|
+
/**
|
|
82
|
+
* A little bit experimental
|
|
83
|
+
*
|
|
84
|
+
* Adds support for headerTemplate/defaultBlocks/footerTemplate, which was first introduced in `_editor.tsx` for generate templates.
|
|
85
|
+
*/
|
|
86
|
+
const blockId = inlineContext?.block[1].clientId;
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (props.defaultBlocks || props.headerTemplate || props.footerTemplate) {
|
|
89
|
+
const newBlocks = applyTemplateBlocks(inlineContext?.innerBlocks ?? [], props);
|
|
90
|
+
wp.data.dispatch(wp.blockEditor.store).replaceInnerBlocks(blockId, newBlocks);
|
|
91
|
+
}
|
|
92
|
+
}, [
|
|
93
|
+
hash(inlineContext?.innerBlocks.map((b) => [b.blockName, b.clientId])),
|
|
94
|
+
hash([props.template, props.defaultBlocks, props.headerTemplate, props.footerTemplate]),
|
|
95
|
+
blockId,
|
|
96
|
+
]);
|
|
47
97
|
return (_jsx("div", { ...innerBlocksProps, className: [innerBlocksProps.className, props.adminClassName].filter(Boolean).join(" ") }));
|
|
48
|
-
// return (
|
|
49
|
-
// <wp.blockEditor.InnerBlocks
|
|
50
|
-
// // @ts-ignore
|
|
51
|
-
// orientation={props.orientation}
|
|
52
|
-
// prioritizedInserterBlocks={props.prioritizedInserterBlocks}
|
|
53
|
-
// allowedBlocks={props.allowedBlocks ? blocksByTag.expand(props.allowedBlocks) : undefined}
|
|
54
|
-
// renderAppender={props.appender ? () => <Appender {...props.appender!} /> : undefined}
|
|
55
|
-
// templateLock={(props.templateLock as any) ?? false}
|
|
56
|
-
// template={props.template ? transformBlockTemplate(props.template) : undefined}
|
|
57
|
-
// />
|
|
58
|
-
// )
|
|
59
98
|
}
|
|
60
99
|
}
|
|
61
100
|
const blocks = useInnerBlocks();
|
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
import { ComponentType, ReactNode } from "react";
|
|
2
2
|
export declare function defineBlock<TName extends keyof BlockProps>(name: TName, component: (props: BlockProps[TName]) => ReactNode): ComponentType<BlockProps[TName]>;
|
|
3
|
+
export declare namespace defineBlock {
|
|
4
|
+
var meta: (name: string, meta: any) => void;
|
|
5
|
+
}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import { blockMetaDescriptors } from "./editor/installGutenbergHooks";
|
|
2
|
+
import { resolveAcfBlockName } from "./editor/block-templates";
|
|
1
3
|
export function defineBlock(name, component) {
|
|
2
4
|
return component;
|
|
3
5
|
}
|
|
6
|
+
defineBlock.meta = (name, meta) => {
|
|
7
|
+
if (env.admin) {
|
|
8
|
+
blockMetaDescriptors.set(resolveAcfBlockName(name), meta);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect,
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
3
|
export function EditorHighlights(props) {
|
|
4
|
-
const
|
|
4
|
+
const [element, setElement] = useState(null);
|
|
5
5
|
const [controller, setController] = useState(null);
|
|
6
6
|
// wp.data.select('core/editor').isBlockSelected
|
|
7
7
|
// const isSelected = wp.data.useSelect(
|
|
@@ -9,12 +9,12 @@ export function EditorHighlights(props) {
|
|
|
9
9
|
// [props.clientId]
|
|
10
10
|
// )
|
|
11
11
|
useEffect(() => {
|
|
12
|
-
if (!props.enabled)
|
|
12
|
+
if (!props.enabled || !element)
|
|
13
13
|
return;
|
|
14
|
-
const controller = new HighlightController(
|
|
14
|
+
const controller = new HighlightController(element);
|
|
15
15
|
setController(controller);
|
|
16
16
|
return () => controller.teardown();
|
|
17
|
-
}, [props.enabled]);
|
|
17
|
+
}, [props.enabled, element]);
|
|
18
18
|
useEffect(() => {
|
|
19
19
|
if (controller) {
|
|
20
20
|
controller.isSelected = false;
|
|
@@ -22,7 +22,38 @@ export function EditorHighlights(props) {
|
|
|
22
22
|
controller.update();
|
|
23
23
|
}
|
|
24
24
|
}, [controller, false]);
|
|
25
|
-
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const element = document.getElementById(`block-${props.clientId}`);
|
|
27
|
+
if (element) {
|
|
28
|
+
setElement(element);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
setElement(null);
|
|
32
|
+
}
|
|
33
|
+
}, [props.clientId]);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (controller && element) {
|
|
36
|
+
const onPointerEnter = () => controller.enable();
|
|
37
|
+
const onPointerLeave = () => controller.disable();
|
|
38
|
+
element.addEventListener("pointerenter", onPointerEnter);
|
|
39
|
+
element.addEventListener("pointerleave", onPointerLeave);
|
|
40
|
+
return () => {
|
|
41
|
+
element.removeEventListener("pointerenter", onPointerEnter);
|
|
42
|
+
element.removeEventListener("pointerleave", onPointerLeave);
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}, [element, controller]);
|
|
46
|
+
return _jsx(_Fragment, { children: props.children });
|
|
47
|
+
// return (
|
|
48
|
+
// <div
|
|
49
|
+
// ref={ref}
|
|
50
|
+
// style={{ display: "contents" }}
|
|
51
|
+
// // onPointerEnter={() => controller?.enable()}
|
|
52
|
+
// // onPointerLeave={() => controller?.disable()}
|
|
53
|
+
// >
|
|
54
|
+
// {props.children}
|
|
55
|
+
// </div>
|
|
56
|
+
// )
|
|
26
57
|
}
|
|
27
58
|
class HighlightController {
|
|
28
59
|
root;
|
|
@@ -40,7 +71,7 @@ class HighlightController {
|
|
|
40
71
|
let editables = Array.from(this.root.querySelectorAll("[contenteditable=true], .editable-slot"));
|
|
41
72
|
let childBlocks = Array.from(this.root.querySelectorAll(".wp-block"));
|
|
42
73
|
const childIsSelected = this.root.querySelectorAll(".editor-highlighter-root-selected").length > 0;
|
|
43
|
-
this.block =
|
|
74
|
+
this.block = this.root;
|
|
44
75
|
childBlocks = childBlocks.slice(1);
|
|
45
76
|
editables = childIsSelected
|
|
46
77
|
? []
|
|
@@ -96,7 +127,10 @@ class HighlightController {
|
|
|
96
127
|
el.style.position = "absolute";
|
|
97
128
|
el.style.pointerEvents = "none";
|
|
98
129
|
el.style.zIndex = "20";
|
|
99
|
-
el.
|
|
130
|
+
el.classList.add("editor-highlight");
|
|
131
|
+
if (target.getAttribute("data-editor-higlight-class")) {
|
|
132
|
+
el.classList.add(target.getAttribute("data-editor-higlight-class"));
|
|
133
|
+
}
|
|
100
134
|
this.block.appendChild(el);
|
|
101
135
|
return el;
|
|
102
136
|
}
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { createContext, Suspense, useContext } from "react";
|
|
2
|
+
import { createContext, Suspense, useContext, useEffect } from "react";
|
|
3
3
|
import { blockManifestReader } from "../../internal/read-block-manifest.js";
|
|
4
4
|
import { APIProvider } from "../../../utils/APIProvider.js";
|
|
5
5
|
import { ErrorBoundaryEditor } from "./ErrorBoundaryEditor.js";
|
|
6
6
|
export const BlockContext = createContext(undefined);
|
|
7
7
|
export function EditableBlock({ payload }) {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
if (!env.admin)
|
|
9
|
+
throw new Error("`EditableBlock` can only be used in the admin environment");
|
|
10
|
+
const info = useContext(BlockContext);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
const block = wp.data.select("core/block-editor").getBlock(info?.props.clientId);
|
|
13
|
+
if (block && block.attributes) {
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
block.attributes.props = payload;
|
|
16
|
+
}
|
|
17
|
+
}, [payload, info?.props.clientId]);
|
|
18
|
+
if (!info)
|
|
10
19
|
return null;
|
|
11
|
-
const
|
|
12
|
-
return blockManifestReader.value[block.name];
|
|
13
|
-
};
|
|
14
|
-
const BlockComponent = getBlock();
|
|
20
|
+
const BlockComponent = blockManifestReader.value[info.name];
|
|
15
21
|
if (!BlockComponent)
|
|
16
22
|
return _jsx("div", { children: "Unable to load block component" });
|
|
17
23
|
return (_jsx(ErrorBoundaryEditor, { children: _jsx(APIProvider, { children: _jsx(Suspense, { children: _jsx(BlockComponent, { ...payload }) }) }) }));
|
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
export type BlockTemplate = [name: ChildBlockTypeName, props: any, children?: BlockTemplate][];
|
|
2
2
|
export declare function resolveAcfBlockName(name: string): string;
|
|
3
3
|
export declare function transformBlockTemplate(template: BlockTemplate): BlockTemplate;
|
|
4
|
+
export declare function applyTemplateBlocks(currentBlocks: any[], config: {
|
|
5
|
+
defaultBlocks?: BlockTemplate;
|
|
6
|
+
headerTemplate?: BlockTemplate;
|
|
7
|
+
footerTemplate?: BlockTemplate;
|
|
8
|
+
}): any[];
|
|
9
|
+
export declare function transformTemplateToBlocks(template: BlockTemplate, locked?: boolean, isFromTemplate?: boolean): any;
|
|
@@ -7,3 +7,67 @@ export function transformBlockTemplate(template) {
|
|
|
7
7
|
return [resolveAcfBlockName(name), props, children ? transformBlockTemplate(children) : undefined];
|
|
8
8
|
});
|
|
9
9
|
}
|
|
10
|
+
export function applyTemplateBlocks(currentBlocks, config) {
|
|
11
|
+
const templateBlocks = currentBlocks.filter((block) => block.attributes.isFromTemplate);
|
|
12
|
+
let header = config.headerTemplate ? syncBlocks(transformTemplateToBlocks(config.headerTemplate)) : [];
|
|
13
|
+
let footer = config.footerTemplate ? syncBlocks(transformTemplateToBlocks(config.footerTemplate)) : [];
|
|
14
|
+
let blocks = currentBlocks.filter((block) => !header.includes(block) && !footer.includes(block));
|
|
15
|
+
blocks.forEach((block) => {
|
|
16
|
+
delete block.attributes.lock;
|
|
17
|
+
delete block.isFromTemplate;
|
|
18
|
+
});
|
|
19
|
+
// const blocksToDelete = currentBlocks.filter((block: any) => {
|
|
20
|
+
// return !header.includes(block) && !footer.includes(block) && !blocks.includes(block)
|
|
21
|
+
// })
|
|
22
|
+
// blocksToDelete.forEach((block: any) => {
|
|
23
|
+
// delete block.attributes.lock
|
|
24
|
+
// delete block.isFromTemplate
|
|
25
|
+
// })
|
|
26
|
+
// blocks = [...blocks, ...blocksToDelete]
|
|
27
|
+
// console.log("blocks", blocks)
|
|
28
|
+
// console.log("blocksToDelete", blocksToDelete)
|
|
29
|
+
if (!blocks.length && config.defaultBlocks) {
|
|
30
|
+
blocks = transformTemplateToBlocks(config.defaultBlocks, false, false);
|
|
31
|
+
}
|
|
32
|
+
let newBlocks = [...header, ...blocks, ...footer];
|
|
33
|
+
function syncBlocks(blocks) {
|
|
34
|
+
return blocks.map((block) => {
|
|
35
|
+
const matched = templateBlocks.find((templateBlock) => templateBlock.name === block.name);
|
|
36
|
+
templateBlocks.splice(templateBlocks.indexOf(matched), 1);
|
|
37
|
+
if (matched) {
|
|
38
|
+
matched.attributes.lock = block.attributes.lock;
|
|
39
|
+
return matched;
|
|
40
|
+
}
|
|
41
|
+
return block;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return newBlocks;
|
|
45
|
+
}
|
|
46
|
+
export function transformTemplateToBlocks(template, locked = true, isFromTemplate = true) {
|
|
47
|
+
return template.map(([name, props, children]) => {
|
|
48
|
+
const attributes = {
|
|
49
|
+
data: {},
|
|
50
|
+
inline: {},
|
|
51
|
+
isFromTemplate: isFromTemplate,
|
|
52
|
+
lock: undefined,
|
|
53
|
+
};
|
|
54
|
+
if (props.locked === false) {
|
|
55
|
+
attributes.lock = { move: false, remove: false };
|
|
56
|
+
}
|
|
57
|
+
else if (locked || props.locked === true || props.locked === "all") {
|
|
58
|
+
attributes.lock = { move: true, remove: true };
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
attributes.lock = props.lock;
|
|
62
|
+
}
|
|
63
|
+
Object.assign(attributes, props);
|
|
64
|
+
return {
|
|
65
|
+
clientId: "block-" + Math.random().toString(36),
|
|
66
|
+
name: resolveAcfBlockName(name),
|
|
67
|
+
attributes: attributes,
|
|
68
|
+
innerBlocks: children ? transformTemplateToBlocks(children, false, isFromTemplate) : [],
|
|
69
|
+
isValid: true,
|
|
70
|
+
validationIssues: [],
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BlockInstance } from "../inline-editing";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a block instance for the editor. This doesn't add the block to the editor on it's own.
|
|
4
|
+
* @param name The name of the block
|
|
5
|
+
* @param attributes
|
|
6
|
+
* @param innerBlocks
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
export declare function createBlock(name: ChildBlockTypeName, attributes?: Record<string, any>, innerBlocks?: BlockInstance[]): BlockInstance;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a block instance for the editor. This doesn't add the block to the editor on it's own.
|
|
3
|
+
* @param name The name of the block
|
|
4
|
+
* @param attributes
|
|
5
|
+
* @param innerBlocks
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export function createBlock(name, attributes = {}, innerBlocks = []) {
|
|
9
|
+
if (!env.admin) {
|
|
10
|
+
throw new Error("`createBlock` can only be used in the admin environment");
|
|
11
|
+
}
|
|
12
|
+
return wp.blocks.createBlock(name, attributes, innerBlocks);
|
|
13
|
+
}
|
|
@@ -44,7 +44,6 @@ export declare const editorConfigStore: {
|
|
|
44
44
|
currentBlocksConfig: EditorConfigItem;
|
|
45
45
|
};
|
|
46
46
|
export declare function configureEditorBlocks(config: EditorConfigItem): void;
|
|
47
|
-
export declare function transformTemplateToBlocks(template: BlockTemplate, locked?: boolean, isFromTemplate?: boolean): any;
|
|
48
47
|
type PostInfo = {
|
|
49
48
|
type: PostTypeName;
|
|
50
49
|
isPattern: false;
|
|
@@ -72,9 +71,45 @@ type Matcher = {
|
|
|
72
71
|
/** Configuration for the editor, when the post type and template match */
|
|
73
72
|
config: EditorConfigItem | ((post: PostInfo) => EditorConfigItem);
|
|
74
73
|
};
|
|
74
|
+
export type BlockTransform = {
|
|
75
|
+
from: ChildBlockTypeName[];
|
|
76
|
+
to: ChildBlockTypeName;
|
|
77
|
+
};
|
|
78
|
+
export type CustomRichTextFormat = {
|
|
79
|
+
/** The ID of the format, eg. `"custom/fancy"` */
|
|
80
|
+
id: string;
|
|
81
|
+
/** The title of the format, shown on the tooltip */
|
|
82
|
+
title: string;
|
|
83
|
+
/**
|
|
84
|
+
* The HTML tag name to use.
|
|
85
|
+
* @default `"span"`
|
|
86
|
+
**/
|
|
87
|
+
tagName?: string;
|
|
88
|
+
/**
|
|
89
|
+
* The class name to apply to the element.
|
|
90
|
+
* @default `undefined`
|
|
91
|
+
**/
|
|
92
|
+
className?: string;
|
|
93
|
+
/**
|
|
94
|
+
* The icon to use in the toolbar.
|
|
95
|
+
*/
|
|
96
|
+
icon?: string;
|
|
97
|
+
/**
|
|
98
|
+
* Whether format makes content interactive or not.
|
|
99
|
+
* @default `false`
|
|
100
|
+
*/
|
|
101
|
+
interactive?: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Whether to disable this format by default. If `true`, you must pass the format ID to `allowedFormats` on a `EditableText` component.
|
|
104
|
+
*
|
|
105
|
+
* @default `false`
|
|
106
|
+
*/
|
|
107
|
+
disabledByDefault?: boolean;
|
|
108
|
+
};
|
|
75
109
|
type EditorConfig = {
|
|
76
|
-
|
|
77
|
-
matchers
|
|
110
|
+
customRichTextFormats?: CustomRichTextFormat[];
|
|
111
|
+
/** A list of template/post type matchers, and resulting editor config that they will apply */
|
|
112
|
+
matchers?: Matcher[];
|
|
78
113
|
};
|
|
79
114
|
/**
|
|
80
115
|
* This call should be placed in blocks/_editor.tsx
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { proxy } from "valtio";
|
|
2
|
-
import { resolveAcfBlockName, transformBlockTemplate } from "./block-templates.js";
|
|
2
|
+
import { applyTemplateBlocks, resolveAcfBlockName, transformBlockTemplate, transformTemplateToBlocks, } from "./block-templates.js";
|
|
3
3
|
export const editorConfigStore = proxy({
|
|
4
4
|
config: null,
|
|
5
5
|
currentBlocksConfig: {},
|
|
@@ -26,68 +26,8 @@ export function configureEditorBlocks(config) {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
const currentBlocks = wp.data.select("core/block-editor").getBlocks();
|
|
29
|
-
const
|
|
30
|
-
let header = config.headerTemplate ? syncBlocks(transformTemplateToBlocks(config.headerTemplate)) : [];
|
|
31
|
-
let footer = config.footerTemplate ? syncBlocks(transformTemplateToBlocks(config.footerTemplate)) : [];
|
|
32
|
-
let blocks = currentBlocks.filter((block) => !header.includes(block) && !footer.includes(block));
|
|
33
|
-
blocks.forEach((block) => {
|
|
34
|
-
delete block.attributes.lock;
|
|
35
|
-
delete block.isFromTemplate;
|
|
36
|
-
});
|
|
37
|
-
// const blocksToDelete = currentBlocks.filter((block: any) => {
|
|
38
|
-
// return !header.includes(block) && !footer.includes(block) && !blocks.includes(block)
|
|
39
|
-
// })
|
|
40
|
-
// blocksToDelete.forEach((block: any) => {
|
|
41
|
-
// delete block.attributes.lock
|
|
42
|
-
// delete block.isFromTemplate
|
|
43
|
-
// })
|
|
44
|
-
// blocks = [...blocks, ...blocksToDelete]
|
|
45
|
-
// console.log("blocks", blocks)
|
|
46
|
-
// console.log("blocksToDelete", blocksToDelete)
|
|
47
|
-
if (!blocks.length && config.defaultBlocks) {
|
|
48
|
-
blocks = transformTemplateToBlocks(config.defaultBlocks, false, false);
|
|
49
|
-
}
|
|
50
|
-
let newBlocks = [...header, ...blocks, ...footer];
|
|
29
|
+
const newBlocks = applyTemplateBlocks(currentBlocks, config);
|
|
51
30
|
wp.data.dispatch("core/block-editor").resetBlocks(newBlocks);
|
|
52
|
-
function syncBlocks(blocks) {
|
|
53
|
-
return blocks.map((block) => {
|
|
54
|
-
const matched = templateBlocks.find((templateBlock) => templateBlock.name === block.name);
|
|
55
|
-
templateBlocks.splice(templateBlocks.indexOf(matched), 1);
|
|
56
|
-
if (matched) {
|
|
57
|
-
matched.attributes.lock = block.attributes.lock;
|
|
58
|
-
return matched;
|
|
59
|
-
}
|
|
60
|
-
return block;
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
export function transformTemplateToBlocks(template, locked = true, isFromTemplate = true) {
|
|
65
|
-
return template.map(([name, props, children]) => {
|
|
66
|
-
const attributes = {
|
|
67
|
-
data: {},
|
|
68
|
-
inline: {},
|
|
69
|
-
isFromTemplate: isFromTemplate,
|
|
70
|
-
lock: undefined,
|
|
71
|
-
};
|
|
72
|
-
if (props.locked === false) {
|
|
73
|
-
attributes.lock = { move: false, remove: false };
|
|
74
|
-
}
|
|
75
|
-
else if (locked || props.locked === true || props.locked === "all") {
|
|
76
|
-
attributes.lock = { move: true, remove: true };
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
attributes.lock = props.lock;
|
|
80
|
-
}
|
|
81
|
-
Object.assign(attributes, props);
|
|
82
|
-
return {
|
|
83
|
-
clientId: "block-" + Math.random().toString(36),
|
|
84
|
-
name: resolveAcfBlockName(name),
|
|
85
|
-
attributes: attributes,
|
|
86
|
-
innerBlocks: children ? transformTemplateToBlocks(children, false, isFromTemplate) : [],
|
|
87
|
-
isValid: true,
|
|
88
|
-
validationIssues: [],
|
|
89
|
-
};
|
|
90
|
-
});
|
|
91
31
|
}
|
|
92
32
|
/**
|
|
93
33
|
* This call should be placed in blocks/_editor.tsx
|
|
@@ -125,7 +65,7 @@ export function updateTemplateConfig() {
|
|
|
125
65
|
const editorConfig = editorConfigStore.config;
|
|
126
66
|
if (!editorConfig)
|
|
127
67
|
return;
|
|
128
|
-
const matched = editorConfig.matchers
|
|
68
|
+
const matched = editorConfig.matchers?.find((matcher) => {
|
|
129
69
|
return matcher.match(postInfo);
|
|
130
70
|
});
|
|
131
71
|
if (matched) {
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
+
export declare const blockMetaDescriptors: Map<string, BlockMeta> & {
|
|
2
|
+
$$valtioSnapshot: Omit<Map<string, BlockMeta>, "set" | "clear" | "delete">;
|
|
3
|
+
};
|
|
1
4
|
export declare function whenEditorIsReady(): Promise<void>;
|
|
2
5
|
export declare function installEDGutenbergHooks(): void;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect } from "react";
|
|
3
|
-
import { useSnapshot } from "valtio";
|
|
3
|
+
import { subscribe, useSnapshot } from "valtio";
|
|
4
|
+
import { proxyMap } from "valtio/utils";
|
|
4
5
|
import { getBlockMetadata } from "../block-utils.js";
|
|
5
6
|
import { InlineEditingContextProvider } from "../inline-editing.js";
|
|
6
7
|
import { EditorHighlights } from "./EditorHighlights.js";
|
|
7
8
|
import { BlockContext, EditableBlock } from "./EditorSupport.js";
|
|
9
|
+
import { resolveAcfBlockName } from "./block-templates.js";
|
|
8
10
|
import { blocksByTag } from "./blocks-by-tag.js";
|
|
9
11
|
import { editorConfigStore, getEditingPostInfo, watchEditorTemplate } from "./editor-config.js";
|
|
10
12
|
import { rootBlocks } from "./root-blocks.js";
|
|
@@ -21,6 +23,7 @@ function listenForHandleResize() {
|
|
|
21
23
|
}
|
|
22
24
|
}, 100);
|
|
23
25
|
}
|
|
26
|
+
export const blockMetaDescriptors = proxyMap();
|
|
24
27
|
export function whenEditorIsReady() {
|
|
25
28
|
return new Promise((resolve) => {
|
|
26
29
|
let ready = false;
|
|
@@ -57,6 +60,45 @@ export function installEDGutenbergHooks() {
|
|
|
57
60
|
};
|
|
58
61
|
}, "withClientIdClassName");
|
|
59
62
|
wp.hooks.addFilter("editor.BlockListBlock", "ed", withClientIdClassName);
|
|
63
|
+
// Manage custom rich text formats
|
|
64
|
+
setTimeout(() => {
|
|
65
|
+
subscribe(editorConfigStore, () => {
|
|
66
|
+
const formats = editorConfigStore.config?.customRichTextFormats;
|
|
67
|
+
if (formats) {
|
|
68
|
+
const activeFormats = wp.data.select("core/rich-text").getFormatTypes();
|
|
69
|
+
formats.forEach((format) => {
|
|
70
|
+
if (activeFormats.some((f) => f.name === format.id)) {
|
|
71
|
+
wp.richText.unregisterFormatType(format.id);
|
|
72
|
+
}
|
|
73
|
+
const EditComponent = (props) => {
|
|
74
|
+
if (format.disabledByDefault) {
|
|
75
|
+
const explicitlyEnabled = props.contentRef.current
|
|
76
|
+
?.getAttribute("data-allowed-formats")
|
|
77
|
+
?.includes(format.id);
|
|
78
|
+
if (!explicitlyEnabled) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return (_jsx(wp.components.Fill, { name: "BlockFormatControls", children: _jsx(wp.components.ToolbarButton, { icon: format.icon, title: format.title, onClick: () => {
|
|
83
|
+
props.onChange(wp.richText.toggleFormat(props.value, {
|
|
84
|
+
type: format.id,
|
|
85
|
+
}));
|
|
86
|
+
}, isActive: props.isActive }) }));
|
|
87
|
+
};
|
|
88
|
+
wp.richText.registerFormatType(format.id, {
|
|
89
|
+
name: format.id,
|
|
90
|
+
title: format.title,
|
|
91
|
+
tagName: format.tagName ?? "span",
|
|
92
|
+
className: format.className,
|
|
93
|
+
interactive: false,
|
|
94
|
+
edit: EditComponent,
|
|
95
|
+
// @ts-ignore
|
|
96
|
+
disabledByDefault: format.disabledByDefault,
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
60
102
|
listenForHandleResize();
|
|
61
103
|
// Remove unwanted formatting options
|
|
62
104
|
// https://developer.wordpress.org/block-editor/how-to-guides/format-api/
|
|
@@ -81,7 +123,19 @@ export function installEDGutenbergHooks() {
|
|
|
81
123
|
item.attributes.inline = { type: "object" };
|
|
82
124
|
item.attributes.values = { type: "object" };
|
|
83
125
|
item.attributes.isFromTemplate = { type: "boolean" };
|
|
126
|
+
item.supports.mode = false;
|
|
84
127
|
item.supports.customClassName = false;
|
|
128
|
+
// item.transforms = {
|
|
129
|
+
// to: [
|
|
130
|
+
// {
|
|
131
|
+
// type: "block",
|
|
132
|
+
// blocks: ["core/paragraph"],
|
|
133
|
+
// transform: (attributes: any) => {
|
|
134
|
+
// return wp.blocks.createBlock("core/paragraph", { content: JSON.stringify(attributes) })
|
|
135
|
+
// },
|
|
136
|
+
// },
|
|
137
|
+
// ],
|
|
138
|
+
// }
|
|
85
139
|
item.edit = function (props) {
|
|
86
140
|
const self = this;
|
|
87
141
|
useEffect(() => {
|
|
@@ -127,6 +181,19 @@ export function installEDGutenbergHooks() {
|
|
|
127
181
|
return undefined;
|
|
128
182
|
return blocksByTag.expand([...(item.parent ?? []), ...(isRootBlock ? ["core/post-content"] : [])]);
|
|
129
183
|
},
|
|
184
|
+
get transforms() {
|
|
185
|
+
const result = {
|
|
186
|
+
from: item.transforms?.from ?? [],
|
|
187
|
+
to: item.transforms?.to ?? [],
|
|
188
|
+
ungroup: item.transforms?.ungroup,
|
|
189
|
+
};
|
|
190
|
+
const meta = blockMetaDescriptors.get(resolveAcfBlockName(name));
|
|
191
|
+
if (meta?.transforms) {
|
|
192
|
+
result.from = [...(result.from ?? []), ...(meta.transforms.from ?? [])];
|
|
193
|
+
result.to = [...(result.to ?? []), ...(meta.transforms.to ?? [])];
|
|
194
|
+
}
|
|
195
|
+
return result;
|
|
196
|
+
},
|
|
130
197
|
get ancestor() {
|
|
131
198
|
if (name === "core/block")
|
|
132
199
|
return undefined;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
export * from "./block-utils.js";
|
|
1
2
|
export * from "./ContentBlocks.js";
|
|
2
|
-
export * from "./EditableText.js";
|
|
3
|
-
export * from "./InnerBlocks.js";
|
|
4
3
|
export * from "./defineBlock.js";
|
|
4
|
+
export * from "./EditableText.js";
|
|
5
5
|
export * from "./editor/controls.js";
|
|
6
|
-
export * from "./editor/
|
|
7
|
-
export * from "./block-utils.js";
|
|
6
|
+
export * from "./editor/create-block.js";
|
|
8
7
|
export { defineEditorConfig } from "./editor/editor-config.js";
|
|
8
|
+
export * from "./editor/usePostEditor.js";
|
|
9
9
|
export { useBlockContext, useInlineEditableValue, useInnerBlocks, useTemplate } from "./inline-editing.js";
|
|
10
|
+
export * from "./InnerBlocks.js";
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
export * from "./block-utils.js";
|
|
1
2
|
export * from "./ContentBlocks.js";
|
|
2
|
-
export * from "./EditableText.js";
|
|
3
|
-
export * from "./InnerBlocks.js";
|
|
4
3
|
export * from "./defineBlock.js";
|
|
4
|
+
export * from "./EditableText.js";
|
|
5
5
|
export * from "./editor/controls.js";
|
|
6
|
-
export * from "./editor/
|
|
7
|
-
export * from "./block-utils.js";
|
|
6
|
+
export * from "./editor/create-block.js";
|
|
8
7
|
export { defineEditorConfig } from "./editor/editor-config.js";
|
|
8
|
+
export * from "./editor/usePostEditor.js";
|
|
9
9
|
export { useBlockContext, useInlineEditableValue, useInnerBlocks, useTemplate } from "./inline-editing.js";
|
|
10
|
+
export * from "./InnerBlocks.js";
|
|
@@ -2,6 +2,14 @@ import { ContentBlock } from "./ContentBlocks.js";
|
|
|
2
2
|
import { PropsWithChildren } from "react";
|
|
3
3
|
type Attributes = Record<string, any>;
|
|
4
4
|
export type InlineValueStore<T> = [value: T, setValue: (value: T) => void];
|
|
5
|
+
export type BlockInstance = {
|
|
6
|
+
attributes: any;
|
|
7
|
+
clientId: string;
|
|
8
|
+
innerBlocks: BlockInstance[];
|
|
9
|
+
isValid: boolean;
|
|
10
|
+
name: string;
|
|
11
|
+
originalContent?: string | undefined;
|
|
12
|
+
};
|
|
5
13
|
type InlineEditingContext = {
|
|
6
14
|
values: Attributes;
|
|
7
15
|
innerBlocks: ContentBlock[];
|
|
@@ -915,8 +915,8 @@ export declare function useTailwindConfig(): {
|
|
|
915
915
|
readonly flex?: boolean | undefined;
|
|
916
916
|
readonly blur?: boolean | undefined;
|
|
917
917
|
readonly resize?: boolean | undefined;
|
|
918
|
-
readonly position?: boolean | undefined;
|
|
919
918
|
readonly columns?: boolean | undefined;
|
|
919
|
+
readonly position?: boolean | undefined;
|
|
920
920
|
readonly preflight?: boolean | undefined;
|
|
921
921
|
readonly container?: boolean | undefined;
|
|
922
922
|
readonly accessibility?: boolean | undefined;
|
|
@@ -1960,8 +1960,8 @@ export declare function useTailwindConfig(): {
|
|
|
1960
1960
|
readonly flex?: boolean | undefined;
|
|
1961
1961
|
readonly blur?: boolean | undefined;
|
|
1962
1962
|
readonly resize?: boolean | undefined;
|
|
1963
|
-
readonly position?: boolean | undefined;
|
|
1964
1963
|
readonly columns?: boolean | undefined;
|
|
1964
|
+
readonly position?: boolean | undefined;
|
|
1965
1965
|
readonly preflight?: boolean | undefined;
|
|
1966
1966
|
readonly container?: boolean | undefined;
|
|
1967
1967
|
readonly accessibility?: boolean | undefined;
|
|
@@ -2980,8 +2980,8 @@ export declare function useTailwindConfig(): {
|
|
|
2980
2980
|
readonly flex?: boolean | undefined;
|
|
2981
2981
|
readonly blur?: boolean | undefined;
|
|
2982
2982
|
readonly resize?: boolean | undefined;
|
|
2983
|
-
readonly position?: boolean | undefined;
|
|
2984
2983
|
readonly columns?: boolean | undefined;
|
|
2984
|
+
readonly position?: boolean | undefined;
|
|
2985
2985
|
readonly preflight?: boolean | undefined;
|
|
2986
2986
|
readonly container?: boolean | undefined;
|
|
2987
2987
|
readonly accessibility?: boolean | undefined;
|
|
@@ -4051,8 +4051,8 @@ export declare function useTailwindConfig(): {
|
|
|
4051
4051
|
readonly flex?: boolean | undefined;
|
|
4052
4052
|
readonly blur?: boolean | undefined;
|
|
4053
4053
|
readonly resize?: boolean | undefined;
|
|
4054
|
-
readonly position?: boolean | undefined;
|
|
4055
4054
|
readonly columns?: boolean | undefined;
|
|
4055
|
+
readonly position?: boolean | undefined;
|
|
4056
4056
|
readonly preflight?: boolean | undefined;
|
|
4057
4057
|
readonly container?: boolean | undefined;
|
|
4058
4058
|
readonly accessibility?: boolean | undefined;
|
|
@@ -5069,8 +5069,8 @@ export declare function useTailwindConfig(): {
|
|
|
5069
5069
|
readonly flex?: boolean | undefined;
|
|
5070
5070
|
readonly blur?: boolean | undefined;
|
|
5071
5071
|
readonly resize?: boolean | undefined;
|
|
5072
|
-
readonly position?: boolean | undefined;
|
|
5073
5072
|
readonly columns?: boolean | undefined;
|
|
5073
|
+
readonly position?: boolean | undefined;
|
|
5074
5074
|
readonly preflight?: boolean | undefined;
|
|
5075
5075
|
readonly container?: boolean | undefined;
|
|
5076
5076
|
readonly accessibility?: boolean | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "2.0.0-beta.
|
|
1
|
+
export declare const VERSION = "2.0.0-beta.118";
|
package/dist/node/cli/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = "2.0.0-beta.
|
|
1
|
+
export const VERSION = "2.0.0-beta.118";
|
|
@@ -11,7 +11,10 @@ export type Args = {
|
|
|
11
11
|
client: boolean;
|
|
12
12
|
};
|
|
13
13
|
export declare function envPlugin(args: Args): PluginOption;
|
|
14
|
-
|
|
14
|
+
type ReactPluginArgs = {
|
|
15
|
+
retainBlockMeta?: boolean;
|
|
16
|
+
};
|
|
17
|
+
export declare function reactPlugin(args?: ReactPluginArgs): PluginOption[];
|
|
15
18
|
/**
|
|
16
19
|
* Turns on SSR module proxying,
|
|
17
20
|
*/
|
|
@@ -19,3 +22,4 @@ export declare function ssrPlugin(): PluginOption;
|
|
|
19
22
|
export declare function corePlugins(args: Args): PluginOption[];
|
|
20
23
|
export declare function storybookVitePlugins(args: Args): PluginOption[];
|
|
21
24
|
export declare function getViteConfig(args: Args): InlineConfig;
|
|
25
|
+
export {};
|
|
@@ -34,14 +34,35 @@ export function envPlugin(args) {
|
|
|
34
34
|
preventAssignment: true,
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
|
-
export function reactPlugin() {
|
|
37
|
+
export function reactPlugin(args = {}) {
|
|
38
|
+
let currentFile = null;
|
|
38
39
|
return react({
|
|
39
40
|
babel: {
|
|
40
41
|
overrides: [{ test: /types\./, compact: true }],
|
|
41
42
|
plugins: [
|
|
42
43
|
{
|
|
43
44
|
visitor: {
|
|
44
|
-
|
|
45
|
+
Program: {
|
|
46
|
+
enter: (path, state) => {
|
|
47
|
+
const filename = state.file.opts.filename;
|
|
48
|
+
if (filename.match(/.\/blocks\/.+\.tsx/)) {
|
|
49
|
+
currentFile = { type: "block", id: filename.replace(/.*\/blocks\/(.+)\.tsx/, "$1") };
|
|
50
|
+
}
|
|
51
|
+
else if (filename.match(/.\/views\/.+\.tsx/)) {
|
|
52
|
+
currentFile = { type: "view", id: filename.replace(/.*\/views\/(.+)\.tsx/, "$1") };
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
currentFile = null;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
exit: (path, state) => {
|
|
59
|
+
currentFile = null;
|
|
60
|
+
// console.log("Exiting", state.file.opts.filename)
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
ExportNamedDeclaration: (path, state) => {
|
|
64
|
+
if (!currentFile)
|
|
65
|
+
return;
|
|
45
66
|
const decl = path.node.declaration;
|
|
46
67
|
if (decl?.type !== "VariableDeclaration")
|
|
47
68
|
return;
|
|
@@ -49,11 +70,20 @@ export function reactPlugin() {
|
|
|
49
70
|
if (!t.isIdentifier(id))
|
|
50
71
|
return;
|
|
51
72
|
if (id.name === "meta") {
|
|
52
|
-
|
|
73
|
+
if (args.retainBlockMeta && currentFile?.type === "block") {
|
|
74
|
+
// Adds a defineBlock.meta("name", meta) call, which can be used by the editor
|
|
75
|
+
path.replaceWith(t.callExpression(t.memberExpression(t.identifier("defineBlock"), t.identifier("meta")), [
|
|
76
|
+
t.stringLiteral(currentFile.id),
|
|
77
|
+
decl.declarations[0].init,
|
|
78
|
+
]));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
path.remove();
|
|
82
|
+
}
|
|
53
83
|
}
|
|
54
84
|
},
|
|
55
85
|
ExportDefaultDeclaration: (path) => {
|
|
56
|
-
if (!
|
|
86
|
+
if (!currentFile)
|
|
57
87
|
return;
|
|
58
88
|
if (path.node.declaration.type === "CallExpression") {
|
|
59
89
|
const call = path.node.declaration;
|
|
@@ -145,7 +175,12 @@ function buildStatusPlugin(console) {
|
|
|
145
175
|
};
|
|
146
176
|
}
|
|
147
177
|
export function corePlugins(args) {
|
|
148
|
-
return [
|
|
178
|
+
return [
|
|
179
|
+
args.serverless && ssrPlugin(),
|
|
180
|
+
envPlugin(args),
|
|
181
|
+
tsconfigPaths(),
|
|
182
|
+
reactPlugin({ retainBlockMeta: args.target === "cms" }),
|
|
183
|
+
].flat();
|
|
149
184
|
}
|
|
150
185
|
export function storybookVitePlugins(args) {
|
|
151
186
|
return [args.serverless && ssrPlugin(), envPlugin(args), tsconfigPaths()].flat();
|
|
@@ -176,7 +211,14 @@ export function getViteConfig(args) {
|
|
|
176
211
|
define: {
|
|
177
212
|
"process.env.NODE_ENV": JSON.stringify(args.mode),
|
|
178
213
|
},
|
|
179
|
-
plugins: [
|
|
214
|
+
plugins: [
|
|
215
|
+
tsconfigPaths(),
|
|
216
|
+
envPlugin(args),
|
|
217
|
+
reactPlugin({
|
|
218
|
+
retainBlockMeta: args.target === "cms",
|
|
219
|
+
}),
|
|
220
|
+
buildStatusPlugin(console),
|
|
221
|
+
],
|
|
180
222
|
build: {
|
|
181
223
|
manifest: true,
|
|
182
224
|
sourcemap: true,
|
|
@@ -40,8 +40,8 @@ export declare const BlockMetaSchema: z.ZodObject<{
|
|
|
40
40
|
slug: string;
|
|
41
41
|
tags: string[];
|
|
42
42
|
flags: Record<string, any>;
|
|
43
|
-
category: string;
|
|
44
43
|
parent: string[];
|
|
44
|
+
category: string;
|
|
45
45
|
acfName: string;
|
|
46
46
|
fileName: string;
|
|
47
47
|
graphqlFieldName: string;
|
|
@@ -72,9 +72,9 @@ export declare const BlockMetaSchema: z.ZodObject<{
|
|
|
72
72
|
mode?: "both" | "edit" | "preview" | undefined;
|
|
73
73
|
tags?: string[] | undefined;
|
|
74
74
|
flags?: Record<string, any> | undefined;
|
|
75
|
+
parent?: string[] | undefined;
|
|
75
76
|
icon?: string | undefined;
|
|
76
77
|
category?: string | undefined;
|
|
77
|
-
parent?: string[] | undefined;
|
|
78
78
|
description?: string | undefined;
|
|
79
79
|
keywords?: string[] | undefined;
|
|
80
80
|
templates?: string[] | null | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eddev",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.118",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
},
|
|
136
136
|
"peerDependencies": {
|
|
137
137
|
"react": "^18.3.1",
|
|
138
|
-
"react-dom": "^
|
|
138
|
+
"react-dom": "^18.3.1",
|
|
139
139
|
"tailwindcss": "^3.4.4"
|
|
140
140
|
}
|
|
141
141
|
}
|
package/types.meta.d.ts
CHANGED
|
@@ -153,6 +153,14 @@ declare global {
|
|
|
153
153
|
* Set to `false` for blocks which should not be added manually, such as deprecated blocks, or blocks which are added automatically using template locks.
|
|
154
154
|
*/
|
|
155
155
|
inserter?: boolean
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Transforms
|
|
159
|
+
*/
|
|
160
|
+
transforms?: {
|
|
161
|
+
from?: AnyBlockTransform[]
|
|
162
|
+
to?: AnyBlockTransform[]
|
|
163
|
+
}
|
|
156
164
|
}
|
|
157
165
|
}
|
|
158
166
|
type BlockIcon =
|
|
@@ -316,4 +324,101 @@ type BlockIcon =
|
|
|
316
324
|
| "lightbulb"
|
|
317
325
|
| "smiley"
|
|
318
326
|
|
|
327
|
+
type TransformRawSchema = {
|
|
328
|
+
[k in keyof HTMLElementTagNameMap | "#text"]?: {
|
|
329
|
+
attributes?: string[] | undefined
|
|
330
|
+
require?: Array<keyof HTMLElementTagNameMap> | undefined
|
|
331
|
+
classes?: Array<string | RegExp> | undefined
|
|
332
|
+
children?: TransformRawSchema | undefined
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
interface TransformBlock<T extends Record<string, any>> {
|
|
337
|
+
type: "block"
|
|
338
|
+
priority?: number | undefined
|
|
339
|
+
blocks: string[]
|
|
340
|
+
isMatch?(attributes: T, block: string | string[]): boolean
|
|
341
|
+
isMultiBlock?: boolean | undefined
|
|
342
|
+
transform(attributes: T): BlockInstance<Partial<T>>
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
interface TransformEnter<T extends Record<string, any>> {
|
|
346
|
+
type: "enter"
|
|
347
|
+
priority?: number | undefined
|
|
348
|
+
regExp: RegExp
|
|
349
|
+
transform(): BlockInstance<Partial<T>>
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
interface TransformFiles<T extends Record<string, any>> {
|
|
353
|
+
type: "files"
|
|
354
|
+
priority?: number | undefined
|
|
355
|
+
isMatch?(files: FileList): boolean
|
|
356
|
+
transform(files: FileList, onChange?: (id: string, attrs: T) => void): BlockInstance<Partial<T>>
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
interface TransformPrefix<T extends Record<string, any>> {
|
|
360
|
+
type: "prefix"
|
|
361
|
+
priority?: number | undefined
|
|
362
|
+
prefix: string
|
|
363
|
+
transform(content: string): BlockInstance<Partial<T>>
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
interface TransformRaw<T extends Record<string, any>> {
|
|
367
|
+
type: "raw"
|
|
368
|
+
priority?: number | undefined
|
|
369
|
+
/**
|
|
370
|
+
* Comma-separated list of selectors, no spaces.
|
|
371
|
+
*
|
|
372
|
+
* @example 'p,div,h1,.css-class,#id'
|
|
373
|
+
*/
|
|
374
|
+
selector?: string | undefined
|
|
375
|
+
schema?: TransformRawSchema | undefined
|
|
376
|
+
isMatch?(node: Node): boolean
|
|
377
|
+
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
|
378
|
+
transform?(node: Node): BlockInstance<Partial<T>> | void
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
interface TransformShortcode<T extends Record<string, any>> {
|
|
382
|
+
type: "shortcode"
|
|
383
|
+
priority?: number | undefined
|
|
384
|
+
tag: string
|
|
385
|
+
transform?(attributes: any, match: ShortcodeMatch): BlockInstance<T>
|
|
386
|
+
attributes?: any // TODO: add stronger types here.
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
type AnyBlockTransform<T extends Record<string, any> = Record<string, any>> =
|
|
390
|
+
| TransformBlock<T>
|
|
391
|
+
| TransformEnter<T>
|
|
392
|
+
| TransformFiles<T>
|
|
393
|
+
| TransformPrefix<T>
|
|
394
|
+
| TransformRaw<T>
|
|
395
|
+
| TransformShortcode<T>
|
|
396
|
+
|
|
397
|
+
type BlockInstance<T extends Record<string, any> = { [k: string]: any }> = {
|
|
398
|
+
/**
|
|
399
|
+
* Attributes for the block.
|
|
400
|
+
*/
|
|
401
|
+
readonly attributes: T
|
|
402
|
+
/**
|
|
403
|
+
* Unique ID registered to the block.
|
|
404
|
+
*/
|
|
405
|
+
readonly clientId: string
|
|
406
|
+
/**
|
|
407
|
+
* Array of inner blocks, if the block has any.
|
|
408
|
+
*/
|
|
409
|
+
readonly innerBlocks: BlockInstance[]
|
|
410
|
+
/**
|
|
411
|
+
* Indicates whether or not the block is valid.
|
|
412
|
+
*/
|
|
413
|
+
readonly isValid: boolean
|
|
414
|
+
/**
|
|
415
|
+
* The block's registered name.
|
|
416
|
+
*/
|
|
417
|
+
readonly name: string
|
|
418
|
+
/**
|
|
419
|
+
* The parsed HTML content of the block.
|
|
420
|
+
*/
|
|
421
|
+
readonly originalContent?: string | undefined
|
|
422
|
+
}
|
|
423
|
+
|
|
319
424
|
export {}
|