@plaudit/gutenberg-api-extensions 2.94.2 → 2.96.0

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.
Files changed (103) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/lib/useful-types.d.ts +1 -4
  3. package/package.json +4 -4
  4. package/src/blocks/MoveError.ts +0 -7
  5. package/src/blocks/PathError.ts +0 -18
  6. package/src/blocks/SNPFlexibleItemsListComponent.tsx +0 -30
  7. package/src/blocks/SNPGroupComponent.tsx +0 -38
  8. package/src/blocks/SNPListComponent.tsx +0 -25
  9. package/src/blocks/SNPTreeContext.tsx +0 -13
  10. package/src/blocks/basic-custom-block-bindings-support.tsx +0 -248
  11. package/src/blocks/common-native-property-constructors.tsx +0 -927
  12. package/src/blocks/conditions.ts +0 -261
  13. package/src/blocks/csnp-api.ts +0 -221
  14. package/src/blocks/data-controller/actions.ts +0 -20
  15. package/src/blocks/data-controller/reducer.ts +0 -146
  16. package/src/blocks/data-controller/trigger-handlers.ts +0 -150
  17. package/src/blocks/data-controller/utils.ts +0 -415
  18. package/src/blocks/data-controller-manager.ts +0 -50
  19. package/src/blocks/data-controller.ts +0 -165
  20. package/src/blocks/hooks/built-in-suspendable-option-protocols/select.ts +0 -51
  21. package/src/blocks/hooks/built-in-suspendable-option-protocols/settings.ts +0 -70
  22. package/src/blocks/hooks/useSuspendableOptions.ts +0 -122
  23. package/src/blocks/index.ts +0 -23
  24. package/src/blocks/layered-styles-api.ts +0 -142
  25. package/src/blocks/layered-styles-impl.ts +0 -95
  26. package/src/blocks/layout/LaidOutProperty.tsx +0 -72
  27. package/src/blocks/layout/LaidOutPropertyRow.tsx +0 -28
  28. package/src/blocks/layout/NodeContext.tsx +0 -54
  29. package/src/blocks/layout/PanelRoot.tsx +0 -30
  30. package/src/blocks/layout/TabsRoot.tsx +0 -56
  31. package/src/blocks/layout/ToolsPanelContext.tsx +0 -22
  32. package/src/blocks/problematic-blocks-blocker.ts +0 -24
  33. package/src/blocks/problematic-variations-blocker.ts +0 -32
  34. package/src/blocks/shared-exportable-types.ts +0 -6
  35. package/src/blocks/shared-internal-types.ts +0 -18
  36. package/src/blocks/simple-block.tsx +0 -74
  37. package/src/blocks/simple-native-property-api.ts +0 -173
  38. package/src/blocks/simple-native-property-impl.tsx +0 -335
  39. package/src/blocks/simple-native-property-internal-shared.ts +0 -19
  40. package/src/blocks/snp-api.ts +0 -5
  41. package/src/blocks/snp-data-store.ts +0 -72
  42. package/src/blocks/utilities.ts +0 -66
  43. package/src/controls/AsynchronousFormTokenField.tsx +0 -86
  44. package/src/controls/BaseSortableItemsControl.tsx +0 -84
  45. package/src/controls/ExtendedFormTokenField.tsx +0 -144
  46. package/src/controls/ExtendedPostPicker.ts +0 -57
  47. package/src/controls/ExtendedRadioControl.tsx +0 -107
  48. package/src/controls/ExtendedTaxonomyPicker.tsx +0 -100
  49. package/src/controls/ExtendedTermPicker.tsx +0 -61
  50. package/src/controls/ExtendedTextareaControl.tsx +0 -65
  51. package/src/controls/ExtendedUserPicker.ts +0 -56
  52. package/src/controls/FileControl.tsx +0 -48
  53. package/src/controls/FullSizeToggleControl.tsx +0 -95
  54. package/src/controls/ImageControl.tsx +0 -143
  55. package/src/controls/InspectorPanel.tsx +0 -37
  56. package/src/controls/LazySuggestionsComboboxControl.tsx +0 -64
  57. package/src/controls/MultiSelectControl.tsx +0 -59
  58. package/src/controls/PickOne.tsx +0 -88
  59. package/src/controls/PromisableComponent.tsx +0 -56
  60. package/src/controls/ProperLinkControl.tsx +0 -98
  61. package/src/controls/SimpleToggle.tsx +0 -9
  62. package/src/controls/SortableFlexibleItemsControl.tsx +0 -37
  63. package/src/controls/SortableItemsControl.tsx +0 -22
  64. package/src/controls/basicNumericallyIdedItemPicker.tsx +0 -75
  65. package/src/controls/hooks/useImprovedTokenManager.ts +0 -163
  66. package/src/controls/hooks/useMultiSingleConversionLayer.ts +0 -17
  67. package/src/controls/hooks/useNonRenderingCounter.ts +0 -6
  68. package/src/controls/hooks/useOutputMemoizingFilter.ts +0 -16
  69. package/src/controls/hooks/useSortableItemsModel.ts +0 -196
  70. package/src/controls/hooks/useSuggestions.ts +0 -91
  71. package/src/controls/hooks/useTokenManager.ts +0 -177
  72. package/src/controls/index.ts +0 -24
  73. package/src/controls/shared.ts +0 -50
  74. package/src/controls/types.ts +0 -18
  75. package/src/editor/insert-sibling-or-child-block-shortcut.tsx +0 -60
  76. package/src/editor/install-insert-sole-allowed-block-shortcut-support.tsx +0 -51
  77. package/src/editor/simple-gutenberg-endpoints-api.ts +0 -31
  78. package/src/editor/simple-gutenberg-endpoints-impl.ts +0 -126
  79. package/src/index.ts +0 -30
  80. package/src/lib/compat-types.ts +0 -21
  81. package/src/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.ts +0 -35
  82. package/src/lib/gutenberg-api-extensions-state/general-logic.ts +0 -41
  83. package/src/lib/gutenberg-api-extensions-state/layered-block-styles-logic.ts +0 -43
  84. package/src/lib/gutenberg-api-extensions-state/snp-logic.ts +0 -240
  85. package/src/lib/gutenberg-api-extensions-state.ts +0 -69
  86. package/src/lib/helpers.ts +0 -115
  87. package/src/lib/modified-fast-deep-equals.ts +0 -91
  88. package/src/lib/plaudit-icons/column-1.tsx +0 -6
  89. package/src/lib/plaudit-icons/column-2.tsx +0 -6
  90. package/src/lib/plaudit-icons/column-3.tsx +0 -6
  91. package/src/lib/plaudit-icons/placement-center.tsx +0 -3
  92. package/src/lib/plaudit-icons/placement-end.tsx +0 -3
  93. package/src/lib/plaudit-icons/placement-start.tsx +0 -3
  94. package/src/lib/plaudit-icons/placement-stretch.tsx +0 -3
  95. package/src/lib/plaudit-icons/plaudit-icon.tsx +0 -4
  96. package/src/lib/plaudit-icons/reusable-block-marker.tsx +0 -3
  97. package/src/lib/plaudit-icons.ts +0 -13
  98. package/src/lib/sectioned-cache-store.ts +0 -120
  99. package/src/lib/suspense/promise-handlers.ts +0 -72
  100. package/src/lib/suspense.tsx +0 -18
  101. package/src/lib/useful-types.ts +0 -82
  102. package/src/schemas/README.md +0 -1
  103. package/src/schemas/plaudit-block-schema.json +0 -818
@@ -1,165 +0,0 @@
1
- import {useMemo} from "@wordpress/element";
2
-
3
- import {configureStore, type Middleware, Tuple} from "@reduxjs/toolkit";
4
-
5
- import type {Dispatch} from "redux";
6
-
7
- import {type Condition, resolveValueForCondition} from "./conditions";
8
- import {PathError, PathErrorType} from "./PathError";
9
- import type {DataController, DataStore, HydratedSimpleNativeProperty, NodePath} from "./simple-native-property-api";
10
-
11
- import {actions, type DataControllerActions} from "./data-controller/actions";
12
- import {buildReducer} from "./data-controller/reducer";
13
- import {getDataStore, getOptionalValue, type UUID, walkToNode} from "./data-controller/utils";
14
-
15
- type DescendantsWrapper = {[key: string]: DCNode}|DCNode[];
16
- export type DCNode = {
17
- backup?: UUID,
18
- rendered?: boolean,
19
- condition?: Condition,
20
- children?: DescendantsWrapper,
21
- definition?: HydratedSimpleNativeProperty<{uuid: UUID}>,
22
- validationError?: string
23
- };
24
- export type DCStoreState = {
25
- treeRoot: Omit<DCNode, 'children'>&{children: {[key: string]: DCNode}},
26
- dataStores: {byProperty: {[key: string]: DataStore}, list: DataStore[]},
27
- blockClientId: string,
28
- changedByManagedControl: boolean,
29
- rerenderTrigger: number,
30
- batchAddedPropertiesThatNeedWriteThrough: HydratedSimpleNativeProperty<{uuid: UUID}>[]
31
- };
32
-
33
- export function useDataController(blockClientId: string): DataController {
34
- return useMemo(() => {
35
- const reducer = buildReducer(blockClientId);
36
- const store = configureStore<DCStoreState, DataControllerActions, Tuple<ReadonlyArray<Middleware<{}, DCStoreState, Dispatch<DataControllerActions>>>>>({reducer});
37
- function getDataStoreImpl(property: string, required: true): DataStore;
38
- function getDataStoreImpl(property: string, required?: undefined|false): DataStore|undefined;
39
- function getDataStoreImpl(property: string, required?: boolean): DataStore|undefined {
40
- return getDataStore(property, store.getState(), required);
41
- }
42
- const dataController: DataController = {
43
- getDataStore: getDataStoreImpl,
44
- getAllDataStores() {
45
- return store.getState().dataStores.list;
46
- },
47
- makePropertyValueResolver(contextPath) {
48
- return propertyPath => resolveValueForCondition(propertyPath, contextPath, blockClientId, getDataStoreImpl)
49
- },
50
- getValue(path) {
51
- return getOptionalValue(path, store.getState());
52
- },
53
- setValue(path, value) {
54
- store.dispatch(actions.node.write({path, value}));
55
- },
56
- addProperties(properties, dataStore, inBatch) {
57
- store.dispatch(actions.addProperties({properties, dataStore}, inBatch));
58
- },
59
- addNode(path, value) {
60
- try {
61
- store.dispatch(actions.node.add({path, value}));
62
- } catch (e) {
63
- if (e instanceof PathError && e.errorType === PathErrorType.UNEXPECTED_LEAF) {
64
- for (let i = e.errorIndex; i < path.length - 1; i++) {
65
- store.dispatch(actions.node.add({path: path.slice(0, i) as NodePath, value}, true));
66
- }
67
- store.dispatch(actions.node.add({path, value}));
68
- }
69
- throw e;
70
- }
71
- },
72
- removeNode(path) {
73
- store.dispatch(actions.node.remove({path}));
74
- },
75
- moveNode(path, indices) {
76
- store.dispatch(actions.node.move({path, ...indices}));
77
- },
78
- validateNode(path) {
79
- store.dispatch(actions.node.validate({path}));
80
- },
81
- hasRenderedNode(properties) {
82
- const rootNodes = store.getState().treeRoot.children;
83
- for (const property of properties) {
84
- if (Array.isArray(property)) {
85
- for (const prop of property) {
86
- if (rootNodes[prop.name]?.rendered) {
87
- return true;
88
- }
89
- }
90
- } else if (rootNodes[property.name]?.rendered) {
91
- return true;
92
- }
93
- }
94
- return false;
95
- },
96
- hasValidationErrors(properties) {
97
- if (properties === undefined) {
98
- return testForValidationErrors(store.getState().treeRoot);
99
- }
100
- const rootNodes = store.getState().treeRoot.children;
101
- for (const property of properties) {
102
- if (Array.isArray(property)) {
103
- for (const prop of property) {
104
- if (testForValidationErrors(rootNodes[prop.name])) {
105
- return true;
106
- }
107
- }
108
- } else if (testForValidationErrors(rootNodes[property.name])) {
109
- return true;
110
- }
111
- }
112
- return false;
113
- },
114
- getIsRendered(path) {
115
- return walkToNode(store.getState().treeRoot, path).rendered ?? true;
116
- },
117
- getNode(path) {
118
- return walkToNode(store.getState().treeRoot, path);
119
- },
120
- getValidationError(path) {
121
- return walkToNode(store.getState().treeRoot, path).validationError;
122
- },
123
- getWasChangedByManagedControl() {
124
- return store.getState().changedByManagedControl;
125
- },
126
- markManagedControlChangeHandled() {
127
- store.dispatch(actions.markManagedControlChangeHandled({}));
128
- },
129
- checkConditions() {
130
- store.dispatch(actions.checkConditions({}));
131
- },
132
- validateNodes() {
133
- store.dispatch(actions.validateNodes({}));
134
- },
135
- commitBatchAddedProperties() {
136
- store.dispatch(actions.commitBatchAddedProperties({}));
137
- },
138
- blockClientId
139
- };
140
- return dataController;
141
- }, [blockClientId]);
142
- }
143
-
144
- function testForValidationErrors(node: DCNode|undefined) {
145
- if (!node || !node.rendered) {
146
- return false;
147
- } else if (node.validationError) {
148
- return true;
149
- } else if (Array.isArray(node.children)) {
150
- for (const child of node.children) {
151
- if (testForValidationErrors(child)) {
152
- return true;
153
- }
154
- }
155
- } else if (node.children !== undefined) {
156
- for (const child of Object.values(node.children)) {
157
- if (testForValidationErrors(child)) {
158
- return true;
159
- }
160
- }
161
- }
162
- return false;
163
- }
164
-
165
- export {walkToNodeInValue} from "./data-controller/utils";
@@ -1,51 +0,0 @@
1
- import {useSuspenseSelect} from "@wordpress/data";
2
- import {useMemo} from "@wordpress/element";
3
- import {addFilter} from "@wordpress/hooks";
4
-
5
- import {produce} from "immer";
6
-
7
- import {useNodeContext} from "../../layout/NodeContext";
8
-
9
- export default function() {
10
- addFilter(
11
- 'plaudit.gutenbergApiExtensions.simpleNativeProperties.suspendableOptions.resolve',
12
- 'plaudit/gutenberg-api-extensions/simple-native-properties/suspendable-options',
13
- (options: unknown | undefined, selectorInfo: URL, {attributes}: { attributes: Record<string, any> | null }) => {
14
- if (options !== undefined || selectorInfo.protocol !== "select:") {
15
- return options;
16
- }
17
- const nodeContext = useNodeContext("get contextual options");
18
- const trimmedAttributes = useMemo(() => {
19
- if (selectorInfo.searchParams.has("attributes")) {
20
- if (attributes === null) {
21
- return null;
22
- }
23
- return produce(attributes, draft => {
24
- let current = draft;
25
- for (const p of nodeContext.path.slice(0, nodeContext.path.length - 1)) {
26
- if (typeof p === 'string') {
27
- current = current.p;
28
- } else {
29
- current = current[p];
30
- }
31
- if (current === undefined) {
32
- return;
33
- }
34
- }
35
- const lastItem = nodeContext.path[nodeContext.path.length - 1]!;
36
- if (typeof lastItem === 'string') {
37
- delete current[lastItem];
38
- } else {
39
- current.splice(lastItem, 1);
40
- }
41
- });
42
- } else {
43
- return undefined;
44
- }
45
- }, [attributes, nodeContext]);
46
- return useSuspenseSelect(select => {
47
- return (select(selectorInfo.hostname + selectorInfo.pathname) as any).get(selectorInfo.username, trimmedAttributes);
48
- }, [selectorInfo, trimmedAttributes]);
49
- }, 100_000
50
- );
51
- }
@@ -1,70 +0,0 @@
1
- import {useSettings} from "@wordpress/block-editor";
2
- import {addFilter} from "@wordpress/hooks";
3
-
4
- export default function() {
5
- addFilter(
6
- 'plaudit.gutenbergApiExtensions.simpleNativeProperties.suspendableOptions.resolve',
7
- 'plaudit/gutenberg-api-extensions/simple-native-properties/suspendable-options',
8
- (options: unknown | undefined, selectorInfo: URL) => {
9
- return options === undefined && selectorInfo.protocol === "settings:" ? useSettings(selectorInfo.hostname)[0] : options;
10
- }, 100_000
11
- );
12
-
13
- addFilter(
14
- 'plaudit.gutenbergApiExtensions.simpleNativeProperties.suspendableOptions.postProcess',
15
- 'plaudit/gutenberg-api-extensions/simple-native-properties/suspendable-options',
16
- (options: unknown, selectorInfo: URL) => {
17
- if (selectorInfo.protocol !== "settings:") {
18
- return options;
19
- }
20
-
21
- if (!Array.isArray(options)) {
22
- console.error(`The "settings" protocol for CSNPs only supports array-formatted values. ${selectorInfo} did not resolve to an array`);
23
- return [];
24
- }
25
- const valueTransformer = getValueTransformer(selectorInfo);
26
- return options
27
- .filter((s): s is { name: string, slug: string } & ({ value: string | number, icon?: string } | { color: string }) => {
28
- if (typeof s === 'object' && s && typeof s["name"] === 'string' && typeof s["slug"] === 'string') {
29
- if (typeof s["value"] === 'string' || typeof s["value"] === 'number') {
30
- if ("color" in s) {
31
- console.error("Encountered an invalid setting value:", s);
32
- return false;
33
- }
34
- } else if (typeof s["color"] !== 'string' || "value" in s) {
35
- console.error("Encountered an invalid setting value:", s);
36
- return false;
37
- }
38
- return true;
39
- }
40
- return false;
41
- })
42
- .map(s => {
43
- const {slug, name: label, ...rest} = s;
44
- return {...rest, value: valueTransformer(slug), label};
45
- });
46
- });
47
-
48
- function getValueTransformer(selectorInfo: URL): (value: string) => string {
49
- const valuePattern = getValuePatternAccountingForLegacyCode(selectorInfo);
50
- if (!valuePattern) {
51
- return value => value;
52
- }
53
- if (!valuePattern.includes("$slug")) {
54
- throw new Error("Value patterns provided to the \"settings\" protocol MUST include '$slug'");
55
- }
56
- return value => valuePattern.replaceAll("$slug", value);
57
- }
58
-
59
- function getValuePatternAccountingForLegacyCode(selectorInfo: URL) {
60
- const res = selectorInfo.searchParams.get("value-pattern") || selectorInfo.searchParams.get("valuePattern");
61
- if (!res) {
62
- for (const key of selectorInfo.searchParams.keys()) {
63
- if (key.includes("$slug")) {
64
- return key;
65
- }
66
- }
67
- }
68
- return res;
69
- }
70
- }
@@ -1,122 +0,0 @@
1
- import {store as blockEditorStore} from "@wordpress/block-editor";
2
- import {MapSelect, useSelect} from "@wordpress/data";
3
- import {useMemo} from "@wordpress/element";
4
- import {applyFilters} from "@wordpress/hooks";
5
-
6
- import type {CSNPConfig, PromisablePickableOptions, SuspendablePromisablePickableOptions} from "../csnp-api";
7
- import type {PickableOptions} from "../../controls";
8
- import {useNodeContext} from "../layout/NodeContext";
9
- import {isPromise, use} from "../../lib/suspense/promise-handlers";
10
-
11
- type RefablePromisablePickableOptions<T> = T extends {options: PromisablePickableOptions<infer V, infer T>} ? PickableOptions<V, T> : never;
12
- export function isSuspendableOptions<V extends string|number, T extends object = {}>(thing: PromisablePickableOptions<V, T>|string): thing is SuspendablePromisablePickableOptions {
13
- return typeof thing === 'string' || thing instanceof URL;
14
- }
15
-
16
- export function useSuspendableOptions<T extends CSNPConfig&{options: PromisablePickableOptions<any>}>(config: T): RefablePromisablePickableOptions<T> {
17
- const rawOptions = isPromise(config.options) ? use(config.options) : config.options;
18
- if (isSuspendableOptions(rawOptions)) {
19
- const selectorInfo = toSuspendableOptionsURI(rawOptions);
20
- const nodeContext = useNodeContext("get contextual options");
21
- const blockClientId = nodeContext.dataController.blockClientId;
22
-
23
- const usesBlockAttributes = applyFilters('plaudit.gutenbergApiExtensions.simpleNativeProperties.suspendableOptions.usesBlockAttributes',
24
- selectorInfo.searchParams.has("attributes"), selectorInfo, blockClientId);
25
-
26
- // This if/else statement is present because actually passing attributes through to the selectors represents a SEVERE relative performance hit.
27
- // At a minimum, it causes at least one additional full execution pass, and, due to how data can be cached, that pass is almost guaranteed to turn into at least one full render.
28
- let mapSelect: (...args: Parameters<MapSelect>) => [Record<string, any>|null, string|null];
29
- if (usesBlockAttributes) {
30
- mapSelect = wrappedSelect => {
31
- const selected = wrappedSelect(blockEditorStore);
32
- return [selected.getBlockAttributes(blockClientId), selected.getBlockName(blockClientId)];
33
- };
34
- } else {
35
- mapSelect = wrappedSelect => [null, wrappedSelect(blockEditorStore).getBlockName(blockClientId)];
36
- }
37
- const [attributes, blockName] = useSelect(mapSelect, [blockClientId]);
38
-
39
- const potentiallyPromisedOptions = applyFilters('plaudit.gutenbergApiExtensions.simpleNativeProperties.suspendableOptions.resolve',
40
- undefined, selectorInfo, {attributes, blockName});
41
- if (potentiallyPromisedOptions === undefined) {
42
- throw new Error(`Encountered an unsupported suspendable option request: ${rawOptions}`);
43
- }
44
-
45
- // selectorInfo is guaranteed to be valid by virtue of the checks performed while getting the handler
46
- const options = potentiallyPromisedOptions && typeof potentiallyPromisedOptions === 'object' && 'then' in potentiallyPromisedOptions
47
- ? use(potentiallyPromisedOptions as Promise<unknown>) : potentiallyPromisedOptions;
48
-
49
- return useMemo(() => {
50
- return applyFilters('plaudit.gutenbergApiExtensions.simpleNativeProperties.suspendableOptions.postProcess', options, selectorInfo, {attributes, blockName});
51
- }, [options, selectorInfo, attributes, blockName]) as RefablePromisablePickableOptions<T>;
52
- } else {
53
- return rawOptions as RefablePromisablePickableOptions<T>;
54
- }
55
- }
56
-
57
- export type SuspendableOptionsHandler = (selectorInfo: URL, params: {attributes: Record<string, any>|null, blockName: string|null}) => any;
58
-
59
- function toSuspendableOptionsURI(rawOptions: string|URL) {
60
- if (rawOptions instanceof URL) {
61
- return rawOptions;
62
- }
63
-
64
- return useMemo(() => {
65
- try {
66
- const res = new URL(rawOptions);
67
- if (res.protocol === "select:") {
68
- if (res.username && res.hostname) {
69
- return res;
70
- }
71
- } else if (res.protocol === "setting:" || res.protocol === "settings:") {
72
- if (res.protocol === "setting:") {
73
- console.warn(`Encountered a Suspendable Option parameter using deprecated protocol:`, res.toString(), "\nThe \"setting\" protocol has been renamed to \"settings\"");
74
- res.protocol = "settings:";
75
- }
76
- if (res.hostname) {
77
- return res;
78
- }
79
- } else {
80
- return res;
81
- }
82
- } catch {
83
- // We're not throwing on an invalid URI here because we want a chance to run the deprecated-syntax handling logic
84
- }
85
-
86
- const selectorInfo = rawOptions.split(":") as [string, ...string[]];
87
- let correctedRawOptions: string;
88
- if (selectorInfo[0] === 'select') {
89
- if (selectorInfo.length < 3 || !selectorInfo[1] || !selectorInfo[2]) {
90
- throw new Error(`The "select" protocol for Suspendable Options must have at least 3 colon-delimited parts. Got: ${rawOptions}`);
91
- }
92
- // Deprecated: select:plaudit/simple-gutenberg-apis:plaudit-base.conditional-display.show-when-options:attributes
93
- // Corrected: select://plaudit-base.conditional-display.show-when-options@plaudit/simple-gutenberg-apis?attributes
94
- correctedRawOptions = `select://${selectorInfo[2]}@${selectorInfo[1]}`;
95
- if (selectorInfo[3]) {
96
- correctedRawOptions += "?" + selectorInfo[3];
97
- }
98
- } else if (selectorInfo[0] === 'setting' || selectorInfo[0] === 'settings') {
99
- if (!selectorInfo[1]) {
100
- throw new Error(`The "settings" protocol for Suspendable Options must have at least 2 colon-delimited parts. Got: ${rawOptions}`);
101
- }
102
- // Deprecated: setting:plaudit.markerDisplay:with-inherit
103
- // Corrected: settings://plaudit.markerDisplay?with-inherit
104
- correctedRawOptions = `settings://${selectorInfo[1]}`;
105
- if (selectorInfo.length > 2) {
106
- const query = selectorInfo.slice(2).join("&");
107
- if (query.replaceAll("&", "").length > 0) {
108
- correctedRawOptions += "?" + query;
109
- }
110
- }
111
- } else {
112
- throw new Error(`Encountered an invalid suspendable options value: ${rawOptions}. Suspendable option values MUST be URIs.`);
113
- }
114
- console.warn(`Encountered a Suspendable Option parameter using deprecated syntax:`, rawOptions, "\nIt should be replaced with:", correctedRawOptions);
115
- return new URL(correctedRawOptions);
116
- }, [rawOptions]);
117
- }
118
-
119
- import initSelectProtocol from "./built-in-suspendable-option-protocols/select";
120
- import initSettingsProtocol from "./built-in-suspendable-option-protocols/settings";
121
- initSelectProtocol();
122
- initSettingsProtocol();
@@ -1,23 +0,0 @@
1
- export * from "./layered-styles-api";
2
- export * from "./simple-block";
3
- export * from "./shared-exportable-types";
4
- export * from "./simple-native-property-api";
5
- export * from "./snp-data-store";
6
- export * from "./utilities";
7
-
8
- export * from "./problematic-blocks-blocker";
9
- export * from "./problematic-variations-blocker";
10
-
11
- export type {SuspendableOptionsHandler} from "./hooks/useSuspendableOptions";
12
-
13
- export {installCustomBlockBindingsSupport, registerCustomBlockBindingsSource} from "./basic-custom-block-bindings-support";
14
- export type {DbSource, BlockName} from "../lib/useful-types"; // This is for backwards compatibility
15
-
16
- import {installGutenbergExtensions} from "../index";
17
-
18
- /**
19
- * @deprecated use installGutenbergExtensions() instead
20
- */
21
- export function installGutenbergBlockExtensions() {
22
- installGutenbergExtensions();
23
- }
@@ -1,142 +0,0 @@
1
- import type {
2
- ColorPaletteCSNPConfig,
3
- CommonPropertyConfig,
4
- RadioPropertyCSNPConfig,
5
- SelectPropertyCSNPConfig,
6
- ToggleGroupPropertyCSNPConfig,
7
- TogglePropertyCSNPConfig
8
- } from "./csnp-api";
9
- import type {PickableOptions} from "../controls";
10
- import {installGutenbergExtensions} from "../index";
11
- import type {BlockName} from "../lib/useful-types";
12
- import {registerSimpleNativeProperties, SimpleNativeProperty} from "./simple-native-property-api";
13
-
14
- type BaseLayeredBlockStyleLayer = {
15
- name: string;
16
- title: string;
17
- default?: string|undefined;
18
- condition?: SimpleNativeProperty['condition']
19
- alwaysStore?: boolean|undefined;
20
- styleProperty?: string;
21
- }&Pick<CommonPropertyConfig<any, any, any, any>, 'help'>
22
-
23
- type LayeredBlockStyleColorLayer = BaseLayeredBlockStyleLayer&{
24
- picker: 'color'|'colorPalette';
25
- clearable?: boolean|undefined;
26
- options: PickableOptions<string, {color?: string}>|ColorPaletteCSNPConfig['options'];
27
- }
28
-
29
- type LayeredBlockStyleToggleLayer = BaseLayeredBlockStyleLayer&{picker: 'toggle'}&Pick<TogglePropertyCSNPConfig, 'switch'>
30
-
31
- type LayeredBlockStyleToggleGroupLayer = BaseLayeredBlockStyleLayer&{
32
- picker?: 'toggle-control'|'toggleGroup';
33
- clearable?: boolean|undefined;
34
- options: ToggleGroupPropertyCSNPConfig['options'];
35
- }
36
- type LayeredBlockStyleSelectOrRadioLayer = BaseLayeredBlockStyleLayer&{options: PickableOptions<string>}&({picker: 'select', clearable?: boolean|undefined}|{picker: 'radio'})
37
-
38
- export type LayeredBlockStyleLayer = LayeredBlockStyleColorLayer|LayeredBlockStyleToggleLayer|LayeredBlockStyleToggleGroupLayer|LayeredBlockStyleSelectOrRadioLayer;
39
-
40
- export interface LayeredBlockStylesConfig {
41
- block: BlockName[]|BlockName;
42
- layers: LayeredBlockStyleLayer[];
43
- }
44
-
45
- export function registerLayeredBlockStyles(config: LayeredBlockStylesConfig) {
46
- registerSimpleNativeProperties({
47
- block: config.block,
48
- properties: {
49
- group: 'layered-styles',
50
- title: "Layered Styles",
51
- properties: config.layers.map(layer => {
52
- const sharedProps = {
53
- name: layer.name,
54
- label: layer.title,
55
- condition: layer.condition,
56
- alwaysStore: layer.alwaysStore ?? ((layer.default ?? '') !== ''),
57
- styleProperty: layer.styleProperty
58
- };
59
-
60
- const clearable = "clearable" in layer && (layer.clearable ?? false);
61
- let defaultValue: string|undefined;
62
- if (clearable) {
63
- if (layer.default) {
64
- console.error(`Layered Style, "${layer.title}" on ${Array.isArray(config.block) ? config.block.join(', ') : config.block}`,
65
- "is improperly configured with both clearable and a non-empty default.");
66
- defaultValue = "";
67
- } else {
68
- defaultValue = layer.default;
69
- }
70
- } else {
71
- defaultValue = layer.default;
72
- }
73
-
74
- switch (layer.picker) {
75
- case undefined:
76
- case 'toggle-control':
77
- case 'toggleGroup':
78
- return {
79
- ...sharedProps,
80
- clearable,
81
- control: 'toggleGroup',
82
- default: defaultValue,
83
- options: layer.options,
84
- help: layer.help
85
- } as ToggleGroupPropertyCSNPConfig;
86
- case 'color':
87
- case 'colorPalette':
88
- return {
89
- ...sharedProps,
90
- allowCustom: false,
91
- clearable,
92
- control: 'colorPalette',
93
- default: defaultValue,
94
- options: layer.options,
95
- help: layer.help
96
- } as ColorPaletteCSNPConfig;
97
- case 'radio':
98
- return {
99
- ...sharedProps,
100
- control: 'radio',
101
- options: layer.options,
102
- default: layer.default,
103
- allowCustom: false,
104
- help: layer.help
105
- } as RadioPropertyCSNPConfig;
106
- case 'select':
107
- return {
108
- ...sharedProps,
109
- clearable,
110
- control: 'select',
111
- default: defaultValue,
112
- options: layer.options,
113
- help: layer.help
114
- } as SelectPropertyCSNPConfig;
115
- case 'toggle':
116
- return {
117
- ...sharedProps,
118
- control: 'toggle',
119
- default: defaultValue,
120
- switch: layer.switch ?? {small: true},
121
- help: layer.help,
122
- transformer: {
123
- to(input: unknown) {
124
- return input !== undefined && input !== null ? (typeof input === 'boolean' ? input : input?.toString().toLowerCase() === 'true') : undefined;
125
- },
126
- from(value: boolean|undefined) {
127
- return value?.toString();
128
- }
129
- }
130
- } as TogglePropertyCSNPConfig
131
- }
132
- })
133
- }
134
- });
135
- }
136
-
137
- /**
138
- * @deprecated use installGutenbergExtensions() instead.
139
- */
140
- export function installLayeredBlockStylesSupport() {
141
- installGutenbergExtensions();
142
- }
@@ -1,95 +0,0 @@
1
- import {select} from "@wordpress/data";
2
-
3
- import {store as gutenbergApiExtensionsStore} from "../lib/gutenberg-api-extensions-state";
4
- import type {ActualBlockEditProps} from "../lib/useful-types";
5
- import type {PDSimpleNativeProperty} from "./simple-native-property-api";
6
- import {makeHasPropClassName} from "./simple-native-property-impl";
7
- import {SNPDataStore} from "./snp-data-store";
8
-
9
- export class LayeredStylesDataStore extends SNPDataStore {
10
- getAttribute(name: string): any {
11
- if (name.startsWith("__plaudit/")) {
12
- return this.getRawBlockAttributes()[name];
13
- }
14
- const layer = select(gutenbergApiExtensionsStore).blockStylesLayer(this.blockName, name);
15
- if (layer === undefined) {
16
- return undefined;
17
- }
18
-
19
- return extractStyleLayerValueFromAttributes(this.getRawBlockAttributes(), layer.name) ?? layer.default;
20
- }
21
- setAttribute(name: string, rawValue: any) {
22
- if (name.startsWith("__plaudit/")) {
23
- this.setRawBlockAttributes({[name]: rawValue});
24
- return;
25
- }
26
- const layers = select(gutenbergApiExtensionsStore).blockStylesLayers(this.blockName);
27
- if (layers === undefined) {
28
- return;
29
- }
30
- const layer = layers[name];
31
- if (layer === undefined) {
32
- return;
33
- }
34
- const className = this.getRawBlockAttributes()['className'];
35
-
36
- const value = rawValue?.toString() || (layer.default ?? '');
37
- const currentLayerClassPrefix = `style-${name}-`;
38
- if (typeof className !== 'string' || !className) {
39
- if (value.length) {
40
- this.setRawBlockAttributes({
41
- className: "styleProperty" in layer && layer.styleProperty
42
- ? `${currentLayerClassPrefix}${value} ${makeHasPropClassName(layer.name)}`
43
- : `${currentLayerClassPrefix}${value}`
44
- });
45
- }
46
- return;
47
- }
48
- this.setRawBlockAttributes({className: this.incorporateLayerValue(Object.values(layers), layer, name, value, className)});
49
- }
50
-
51
- private incorporateLayerValue(layers: PDSimpleNativeProperty[], currentLayer: PDSimpleNativeProperty, name: string, value: string, className: string): string {
52
- const classNames = className.split(/\s+/);
53
- const layeredStyleClassPrefixes = layers.map(layer => `style-${layer.name}-`);
54
- const nonLayerClasses = classNames
55
- .filter(cn => !layeredStyleClassPrefixes.some(lc => cn.startsWith(lc)));
56
-
57
- const layerPrefixPairs = layers
58
- .filter(layer => layer.name !== name)
59
- .map<[PDSimpleNativeProperty, string]>(layer => [layer, `style-${layer.name}-`]);
60
- const layerClasses: string[] = [];
61
- for (const [layer, prefix] of layerPrefixPairs) {
62
- if (this.hasCachedValue(layer.name)) {
63
- const layerValue = this.getCachedValue(layer.name);
64
- if (layerValue) {
65
- layerClasses.push(`${prefix}${layerValue}`);
66
- }
67
- } else {
68
- const layerValueClass = classNames.find(cn => cn.startsWith(prefix));
69
- if (layerValueClass) {
70
- layerClasses.push(layerValueClass);
71
- }
72
- }
73
- }
74
- if (value) {
75
- layerClasses.push(`style-${name}-${value}`);
76
- if ('styleProperty' in currentLayer && currentLayer.styleProperty) {
77
- const hasPropClassName = makeHasPropClassName(currentLayer.name);
78
- if (!nonLayerClasses.includes(hasPropClassName)) {
79
- nonLayerClasses.push(hasPropClassName);
80
- }
81
- }
82
- }
83
- return [...nonLayerClasses, ...layerClasses.sort()].join(' ');
84
- }
85
- }
86
-
87
- export function extractStyleLayerValueFromAttributes(attributes: ActualBlockEditProps['attributes'], layerName: string) {
88
- const className = attributes['className'];
89
- if (typeof className !== 'string') {
90
- return undefined;
91
- }
92
-
93
- const currentLayerClassPrefix = `style-${layerName}-`;
94
- return attributes['className']?.split(/\s+/).find(className => className.startsWith(currentLayerClassPrefix))?.substring(currentLayerClassPrefix.length);
95
- }