@webiny/react-properties 6.0.0-rc.0 → 6.0.0-rc.2

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/Properties.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import React from "react";
2
+ import { PropertyStore } from "./domain/index.js";
2
3
  export interface ConnectToPropertiesProps {
3
4
  name: string;
4
5
  children: React.ReactNode;
@@ -16,10 +17,11 @@ export interface Property {
16
17
  interface AddPropertyOptions {
17
18
  after?: string;
18
19
  before?: string;
20
+ priority?: number;
19
21
  }
20
22
  interface PropertiesContext {
21
23
  name?: string;
22
- properties: Property[];
24
+ store: PropertyStore;
23
25
  getAncestor(name: string): PropertiesContext | undefined;
24
26
  getObject<T = unknown>(): T;
25
27
  addProperty(property: Property, options?: AddPropertyOptions): void;
package/Properties.js CHANGED
@@ -1,5 +1,7 @@
1
- import React, { createContext, useContext, useEffect, useMemo, useRef, useState } from "react";
1
+ import React, { createContext, useContext, useEffect, useMemo, useRef } from "react";
2
2
  import { getUniqueId, toObject } from "./utils.js";
3
+ import { PropertyStore } from "./domain/index.js";
4
+ import { usePropertyPriority } from "./PropertyPriority.js";
3
5
  const PropertiesTargetContext = /*#__PURE__*/createContext(undefined);
4
6
  export const ConnectToProperties = ({
5
7
  name,
@@ -9,49 +11,17 @@ export const ConnectToProperties = ({
9
11
  value: name
10
12
  }, children);
11
13
  };
12
- function removeByParent(id, properties) {
13
- return properties.filter(prop => prop.parent === id).reduce((acc, item) => {
14
- return removeByParent(item.id, acc.filter(prop => prop.id !== item.id));
15
- }, properties);
16
- }
17
- function putPropertyBefore(properties, property, before) {
18
- const existingIndex = properties.findIndex(prop => prop.id === property.id);
19
- if (existingIndex > -1) {
20
- const existingProperty = properties[existingIndex];
21
- const newProperties = properties.filter(p => p.id !== property.id);
22
- const targetIndex = before.endsWith("$first") ? 0 : newProperties.findIndex(prop => prop.id === before);
23
- return [...newProperties.slice(0, targetIndex), existingProperty, ...newProperties.slice(targetIndex)];
24
- }
25
- const targetIndex = properties.findIndex(prop => prop.id === before);
26
- return [...properties.slice(0, targetIndex), property, ...properties.slice(targetIndex)];
27
- }
28
- function putPropertyAfter(properties, property, after) {
29
- const existingIndex = properties.findIndex(prop => prop.id === property.id);
30
- if (existingIndex > -1) {
31
- const [removedProperty] = properties.splice(existingIndex, 1);
32
- const targetIndex = after.endsWith("$last") ? properties.length - 1 : properties.findIndex(prop => prop.id === after);
33
- return [...properties.slice(0, targetIndex + 1), removedProperty, ...properties.slice(targetIndex + 1)];
34
- }
35
- const targetIndex = properties.findIndex(prop => prop.id === after);
36
- return [...properties.slice(0, targetIndex + 1), property, ...properties.slice(targetIndex + 1)];
37
- }
38
- function mergeProperty(properties, property) {
39
- const index = properties.findIndex(prop => prop.id === property.id);
40
- if (index > -1) {
41
- return [...properties.slice(0, index), {
42
- ...properties[index],
43
- ...property
44
- }, ...properties.slice(index + 1)];
45
- }
46
- return properties;
47
- }
48
14
  const PropertiesContext = /*#__PURE__*/createContext(undefined);
49
15
  export const Properties = ({
50
16
  name,
51
17
  onChange,
52
18
  children
53
19
  }) => {
54
- const [properties, setProperties] = useState([]);
20
+ const storeRef = useRef(null);
21
+ if (!storeRef.current) {
22
+ storeRef.current = new PropertyStore();
23
+ }
24
+ const store = storeRef.current;
55
25
  let parent;
56
26
  try {
57
27
  parent = useProperties();
@@ -59,13 +29,19 @@ export const Properties = ({
59
29
  // Do nothing, if there's no parent.
60
30
  }
61
31
  useEffect(() => {
62
- if (onChange) {
63
- onChange(properties);
32
+ if (!onChange) {
33
+ return;
64
34
  }
65
- }, [properties]);
35
+ return store.subscribe(properties => {
36
+ onChange(properties);
37
+ });
38
+ }, [store, onChange]);
39
+
40
+ // Context value is stable — it never changes after mount.
41
+ // Children never re-render due to context changes.
66
42
  const context = useMemo(() => ({
67
43
  name,
68
- properties,
44
+ store,
69
45
  getAncestor(ancestorName) {
70
46
  if (!parent) {
71
47
  return undefined;
@@ -73,63 +49,31 @@ export const Properties = ({
73
49
  return parent && parent.name === ancestorName ? parent : parent.getAncestor(ancestorName);
74
50
  },
75
51
  getObject() {
76
- return toObject(properties);
52
+ return toObject(store.allProperties);
77
53
  },
78
54
  addProperty(property, options = {}) {
79
- setProperties(properties => {
80
- const index = properties.findIndex(prop => prop.id === property.id);
81
- if (index > -1) {
82
- const newProperties = mergeProperty(properties, property);
83
- if (options.after) {
84
- return putPropertyAfter(newProperties, property, options.after);
85
- }
86
- if (options.before) {
87
- return putPropertyBefore(newProperties, property, options.before);
88
- }
89
- return newProperties;
90
- }
91
- if (options.after) {
92
- return putPropertyAfter(properties, property, options.after);
93
- }
94
- if (options.before) {
95
- return putPropertyBefore(properties, property, options.before);
96
- }
97
- return [...properties, property];
98
- });
55
+ store.addProperty(property, options);
99
56
  },
100
57
  removeProperty(id) {
101
- setProperties(properties => {
102
- return removeByParent(id, properties.filter(prop => prop.id !== id));
103
- });
58
+ store.removeProperty(id);
104
59
  },
105
60
  replaceProperty(id, property) {
106
- setProperties(properties => {
107
- const toReplace = properties.findIndex(prop => prop.id === id);
108
- if (toReplace > -1) {
109
- // Replace the property and remove all remaining child properties.
110
- return removeByParent(id, [...properties.slice(0, toReplace), property, ...properties.slice(toReplace + 1)]);
111
- }
112
- return properties;
113
- });
61
+ store.replaceProperty(id, property);
114
62
  }
115
- }), [properties]);
63
+ }), [store]);
116
64
  return /*#__PURE__*/React.createElement(PropertiesContext.Provider, {
117
65
  value: context
118
66
  }, children);
119
67
  };
120
68
  export function useProperties() {
121
- const properties = useContext(PropertiesContext);
122
- if (!properties) {
69
+ const context = useContext(PropertiesContext);
70
+ if (!context) {
123
71
  throw Error("Properties context provider is missing!");
124
72
  }
125
- return properties;
73
+ return context;
126
74
  }
127
75
  export function useMaybeProperties() {
128
- const properties = useContext(PropertiesContext);
129
- if (!properties) {
130
- return undefined;
131
- }
132
- return properties;
76
+ return useContext(PropertiesContext);
133
77
  }
134
78
  export function useAncestorByName(name) {
135
79
  const parent = useMaybeProperties();
@@ -150,14 +94,15 @@ export function useParentProperty() {
150
94
  export function useAncestor(params) {
151
95
  const property = useParentProperty();
152
96
  const {
153
- properties
97
+ store
154
98
  } = useProperties();
155
99
  const matchOrGetAncestor = (property, params) => {
156
- const matchedProps = properties.filter(prop => prop.parent === property.id).filter(prop => prop.name in params && prop.value === params[prop.name]);
100
+ const children = store.getChildrenOf(property.id);
101
+ const matchedProps = children.filter(prop => prop.name in params && prop.value === params[prop.name]);
157
102
  if (matchedProps.length === Object.keys(params).length) {
158
103
  return property;
159
104
  }
160
- const newParent = property.parent ? properties.find(prop => prop.id === property.parent) : undefined;
105
+ const newParent = property.parent ? store.getById(property.parent) : undefined;
161
106
  return newParent ? matchOrGetAncestor(newParent, params) : undefined;
162
107
  };
163
108
  return property ? matchOrGetAncestor(property, params) : undefined;
@@ -181,6 +126,7 @@ export const Property = ({
181
126
  const immediateProperties = useProperties();
182
127
  const ancestorByName = useAncestorByName(targetName);
183
128
  const previousValue = useRef(value);
129
+ const priority = usePropertyPriority();
184
130
  const properties = targetName && ancestorByName ? ancestorByName : immediateProperties;
185
131
  if (!properties) {
186
132
  throw Error("<Properties> provider is missing higher in the hierarchy!");
@@ -188,7 +134,8 @@ export const Property = ({
188
134
  const {
189
135
  addProperty,
190
136
  removeProperty,
191
- replaceProperty
137
+ replaceProperty,
138
+ store: propertyStore
192
139
  } = properties;
193
140
  const parentId = parent ? parent : root ? "" : parentProperty?.id || "";
194
141
  const property = {
@@ -198,6 +145,11 @@ export const Property = ({
198
145
  parent: parentId,
199
146
  array
200
147
  };
148
+
149
+ // Register in the synchronous lookup during render so useAncestor can find this property.
150
+ if (!remove) {
151
+ propertyStore.registerLookup(property);
152
+ }
201
153
  useEffect(() => {
202
154
  if (remove) {
203
155
  removeProperty(uniqueId);
@@ -215,7 +167,8 @@ export const Property = ({
215
167
  $isLast
216
168
  }, {
217
169
  after,
218
- before
170
+ before,
171
+ priority
219
172
  });
220
173
  return () => {
221
174
  removeProperty(uniqueId);
package/Properties.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["React","createContext","useContext","useEffect","useMemo","useRef","useState","getUniqueId","toObject","PropertiesTargetContext","undefined","ConnectToProperties","name","children","createElement","Provider","value","removeByParent","id","properties","filter","prop","parent","reduce","acc","item","putPropertyBefore","property","before","existingIndex","findIndex","existingProperty","newProperties","p","targetIndex","endsWith","slice","putPropertyAfter","after","removedProperty","splice","length","mergeProperty","index","PropertiesContext","Properties","onChange","setProperties","useProperties","context","getAncestor","ancestorName","getObject","addProperty","options","removeProperty","replaceProperty","toReplace","Error","useMaybeProperties","useAncestorByName","PropertyContext","useParentProperty","useAncestor","params","matchOrGetAncestor","matchedProps","Object","keys","newParent","find","Property","replace","remove","array","root","targetName","uniqueId","parentProperty","immediateProperties","ancestorByName","previousValue","parentId","$isFirst","$isLast","current"],"sources":["Properties.tsx"],"sourcesContent":["import React, { createContext, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport { getUniqueId, toObject } from \"./utils.js\";\n\nconst PropertiesTargetContext = createContext<string | undefined>(undefined);\n\nexport interface ConnectToPropertiesProps {\n name: string;\n children: React.ReactNode;\n}\n\nexport const ConnectToProperties = ({ name, children }: ConnectToPropertiesProps) => {\n return (\n <PropertiesTargetContext.Provider value={name}>{children}</PropertiesTargetContext.Provider>\n );\n};\n\nexport interface Property {\n id: string;\n parent: string;\n name: string;\n value?: unknown;\n array?: boolean;\n $isFirst?: boolean;\n $isLast?: boolean;\n}\n\nfunction removeByParent(id: string, properties: Property[]): Property[] {\n return properties\n .filter(prop => prop.parent === id)\n .reduce((acc, item) => {\n return removeByParent(\n item.id,\n acc.filter(prop => prop.id !== item.id)\n );\n }, properties);\n}\n\ninterface AddPropertyOptions {\n after?: string;\n before?: string;\n}\n\ninterface PropertiesContext {\n name?: string;\n properties: Property[];\n getAncestor(name: string): PropertiesContext | undefined;\n getObject<T = unknown>(): T;\n addProperty(property: Property, options?: AddPropertyOptions): void;\n removeProperty(id: string): void;\n replaceProperty(id: string, property: Property): void;\n}\n\nfunction putPropertyBefore(properties: Property[], property: Property, before: string) {\n const existingIndex = properties.findIndex(prop => prop.id === property.id);\n if (existingIndex > -1) {\n const existingProperty = properties[existingIndex];\n const newProperties = properties.filter(p => p.id !== property.id);\n const targetIndex = before.endsWith(\"$first\")\n ? 0\n : newProperties.findIndex(prop => prop.id === before);\n return [\n ...newProperties.slice(0, targetIndex),\n existingProperty,\n ...newProperties.slice(targetIndex)\n ];\n }\n\n const targetIndex = properties.findIndex(prop => prop.id === before);\n\n return [...properties.slice(0, targetIndex), property, ...properties.slice(targetIndex)];\n}\n\nfunction putPropertyAfter(properties: Property[], property: Property, after: string) {\n const existingIndex = properties.findIndex(prop => prop.id === property.id);\n\n if (existingIndex > -1) {\n const [removedProperty] = properties.splice(existingIndex, 1);\n const targetIndex = after.endsWith(\"$last\")\n ? properties.length - 1\n : properties.findIndex(prop => prop.id === after);\n return [\n ...properties.slice(0, targetIndex + 1),\n removedProperty,\n ...properties.slice(targetIndex + 1)\n ];\n }\n\n const targetIndex = properties.findIndex(prop => prop.id === after);\n\n return [\n ...properties.slice(0, targetIndex + 1),\n property,\n ...properties.slice(targetIndex + 1)\n ];\n}\n\nfunction mergeProperty(properties: Property[], property: Property) {\n const index = properties.findIndex(prop => prop.id === property.id);\n if (index > -1) {\n return [\n ...properties.slice(0, index),\n { ...properties[index], ...property },\n ...properties.slice(index + 1)\n ];\n }\n return properties;\n}\n\nconst PropertiesContext = createContext<PropertiesContext | undefined>(undefined);\n\ninterface PropertiesProps {\n name?: string;\n onChange?(properties: Property[]): void;\n children: React.ReactNode;\n}\n\nexport const Properties = ({ name, onChange, children }: PropertiesProps) => {\n const [properties, setProperties] = useState<Property[]>([]);\n let parent: PropertiesContext;\n\n try {\n parent = useProperties();\n } catch {\n // Do nothing, if there's no parent.\n }\n\n useEffect(() => {\n if (onChange) {\n onChange(properties);\n }\n }, [properties]);\n\n const context: PropertiesContext = useMemo(\n () => ({\n name,\n properties,\n getAncestor(ancestorName: string) {\n if (!parent) {\n return undefined;\n }\n\n return parent && parent.name === ancestorName\n ? parent\n : parent.getAncestor(ancestorName);\n },\n getObject<T>() {\n return toObject(properties) as T;\n },\n addProperty(property, options = {}) {\n setProperties(properties => {\n const index = properties.findIndex(prop => prop.id === property.id);\n\n if (index > -1) {\n const newProperties = mergeProperty(properties, property);\n if (options.after) {\n return putPropertyAfter(newProperties, property, options.after);\n }\n if (options.before) {\n return putPropertyBefore(newProperties, property, options.before);\n }\n\n return newProperties;\n }\n\n if (options.after) {\n return putPropertyAfter(properties, property, options.after);\n }\n\n if (options.before) {\n return putPropertyBefore(properties, property, options.before);\n }\n\n return [...properties, property];\n });\n },\n removeProperty(id) {\n setProperties(properties => {\n return removeByParent(\n id,\n properties.filter(prop => prop.id !== id)\n );\n });\n },\n replaceProperty(id, property) {\n setProperties(properties => {\n const toReplace = properties.findIndex(prop => prop.id === id);\n\n if (toReplace > -1) {\n // Replace the property and remove all remaining child properties.\n return removeByParent(id, [\n ...properties.slice(0, toReplace),\n property,\n ...properties.slice(toReplace + 1)\n ]);\n }\n return properties;\n });\n }\n }),\n [properties]\n );\n\n return <PropertiesContext.Provider value={context}>{children}</PropertiesContext.Provider>;\n};\n\nexport function useProperties() {\n const properties = useContext(PropertiesContext);\n if (!properties) {\n throw Error(\"Properties context provider is missing!\");\n }\n\n return properties;\n}\n\nexport function useMaybeProperties() {\n const properties = useContext(PropertiesContext);\n if (!properties) {\n return undefined;\n }\n\n return properties;\n}\n\nexport function useAncestorByName(name: string | undefined) {\n const parent = useMaybeProperties();\n\n return useMemo(() => {\n if (!name || !parent) {\n return undefined;\n }\n\n if (parent.name === name) {\n return parent;\n }\n\n return parent.getAncestor(name);\n }, [name]);\n}\n\ninterface PropertyProps {\n id?: string;\n name: string;\n value?: unknown;\n array?: boolean;\n after?: string;\n before?: string;\n replace?: string;\n remove?: boolean;\n parent?: string;\n root?: boolean;\n children?: React.ReactNode;\n}\n\nconst PropertyContext = createContext<Property | undefined>(undefined);\n\nexport function useParentProperty() {\n return useContext(PropertyContext);\n}\n\ninterface AncestorMatch {\n [key: string]: string | boolean | number | null | undefined;\n}\n\nexport function useAncestor(params: AncestorMatch) {\n const property = useParentProperty();\n const { properties } = useProperties();\n\n const matchOrGetAncestor = (\n property: Property,\n params: AncestorMatch\n ): Property | undefined => {\n const matchedProps = properties\n .filter(prop => prop.parent === property.id)\n .filter(prop => prop.name in params && prop.value === params[prop.name]);\n\n if (matchedProps.length === Object.keys(params).length) {\n return property;\n }\n\n const newParent = property.parent\n ? properties.find(prop => prop.id === property.parent)\n : undefined;\n\n return newParent ? matchOrGetAncestor(newParent, params) : undefined;\n };\n\n return property ? matchOrGetAncestor(property, params) : undefined;\n}\n\nexport const Property = ({\n id,\n name,\n value,\n children,\n after = undefined,\n before = undefined,\n replace = undefined,\n remove = false,\n array = false,\n root = false,\n parent = undefined\n}: PropertyProps) => {\n const targetName = useContext(PropertiesTargetContext);\n const uniqueId = useMemo(() => id || getUniqueId(), []);\n const parentProperty = useParentProperty();\n const immediateProperties = useProperties();\n const ancestorByName = useAncestorByName(targetName);\n const previousValue = useRef(value);\n\n const properties = targetName && ancestorByName ? ancestorByName : immediateProperties;\n\n if (!properties) {\n throw Error(\"<Properties> provider is missing higher in the hierarchy!\");\n }\n\n const { addProperty, removeProperty, replaceProperty } = properties;\n const parentId = parent ? parent : root ? \"\" : parentProperty?.id || \"\";\n const property = { id: uniqueId, name, value, parent: parentId, array };\n\n useEffect(() => {\n if (remove) {\n removeProperty(uniqueId);\n return;\n }\n\n if (replace) {\n replaceProperty(replace, property);\n return;\n }\n\n const $isFirst = before === \"$first\";\n const $isLast = after === \"$last\";\n\n addProperty({ ...property, $isFirst, $isLast }, { after, before });\n\n return () => {\n removeProperty(uniqueId);\n };\n }, []);\n\n useEffect(() => {\n if (previousValue.current !== value) {\n previousValue.current = value;\n if (!remove && !replace) {\n replaceProperty(uniqueId, property);\n }\n }\n }, [value]);\n\n if (children) {\n return <PropertyContext.Provider value={property}>{children}</PropertyContext.Provider>;\n }\n\n return null;\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","createContext","useContext","useEffect","useMemo","useRef","getUniqueId","toObject","PropertyStore","usePropertyPriority","PropertiesTargetContext","undefined","ConnectToProperties","name","children","createElement","Provider","value","PropertiesContext","Properties","onChange","storeRef","current","store","parent","useProperties","subscribe","properties","context","getAncestor","ancestorName","getObject","allProperties","addProperty","property","options","removeProperty","id","replaceProperty","Error","useMaybeProperties","useAncestorByName","PropertyContext","useParentProperty","useAncestor","params","matchOrGetAncestor","getChildrenOf","matchedProps","filter","prop","length","Object","keys","newParent","getById","Property","after","before","replace","remove","array","root","targetName","uniqueId","parentProperty","immediateProperties","ancestorByName","previousValue","priority","propertyStore","parentId","registerLookup","$isFirst","$isLast"],"sources":["Properties.tsx"],"sourcesContent":["import React, { createContext, useContext, useEffect, useMemo, useRef } from \"react\";\nimport { getUniqueId, toObject } from \"./utils.js\";\nimport { PropertyStore } from \"./domain/index.js\";\nimport { usePropertyPriority } from \"./PropertyPriority.js\";\n\nconst PropertiesTargetContext = createContext<string | undefined>(undefined);\n\nexport interface ConnectToPropertiesProps {\n name: string;\n children: React.ReactNode;\n}\n\nexport const ConnectToProperties = ({ name, children }: ConnectToPropertiesProps) => {\n return (\n <PropertiesTargetContext.Provider value={name}>{children}</PropertiesTargetContext.Provider>\n );\n};\n\nexport interface Property {\n id: string;\n parent: string;\n name: string;\n value?: unknown;\n array?: boolean;\n $isFirst?: boolean;\n $isLast?: boolean;\n}\n\ninterface AddPropertyOptions {\n after?: string;\n before?: string;\n priority?: number;\n}\n\ninterface PropertiesContext {\n name?: string;\n store: PropertyStore;\n getAncestor(name: string): PropertiesContext | undefined;\n getObject<T = unknown>(): T;\n addProperty(property: Property, options?: AddPropertyOptions): void;\n removeProperty(id: string): void;\n replaceProperty(id: string, property: Property): void;\n}\n\nconst PropertiesContext = createContext<PropertiesContext | undefined>(undefined);\n\ninterface PropertiesProps {\n name?: string;\n onChange?(properties: Property[]): void;\n children: React.ReactNode;\n}\n\nexport const Properties = ({ name, onChange, children }: PropertiesProps) => {\n const storeRef = useRef<PropertyStore | null>(null);\n if (!storeRef.current) {\n storeRef.current = new PropertyStore();\n }\n const store = storeRef.current;\n\n let parent: PropertiesContext;\n\n try {\n parent = useProperties();\n } catch {\n // Do nothing, if there's no parent.\n }\n\n useEffect(() => {\n if (!onChange) {\n return;\n }\n\n return store.subscribe(properties => {\n onChange(properties);\n });\n }, [store, onChange]);\n\n // Context value is stable — it never changes after mount.\n // Children never re-render due to context changes.\n const context: PropertiesContext = useMemo(\n () => ({\n name,\n store,\n getAncestor(ancestorName: string) {\n if (!parent) {\n return undefined;\n }\n\n return parent && parent.name === ancestorName\n ? parent\n : parent.getAncestor(ancestorName);\n },\n getObject<T>() {\n return toObject(store.allProperties) as T;\n },\n addProperty(property, options = {}) {\n store.addProperty(property, options);\n },\n removeProperty(id) {\n store.removeProperty(id);\n },\n replaceProperty(id, property) {\n store.replaceProperty(id, property);\n }\n }),\n [store]\n );\n\n return <PropertiesContext.Provider value={context}>{children}</PropertiesContext.Provider>;\n};\n\nexport function useProperties() {\n const context = useContext(PropertiesContext);\n if (!context) {\n throw Error(\"Properties context provider is missing!\");\n }\n\n return context;\n}\n\nexport function useMaybeProperties() {\n return useContext(PropertiesContext);\n}\n\nexport function useAncestorByName(name: string | undefined) {\n const parent = useMaybeProperties();\n\n return useMemo(() => {\n if (!name || !parent) {\n return undefined;\n }\n\n if (parent.name === name) {\n return parent;\n }\n\n return parent.getAncestor(name);\n }, [name]);\n}\n\ninterface PropertyProps {\n id?: string;\n name: string;\n value?: unknown;\n array?: boolean;\n after?: string;\n before?: string;\n replace?: string;\n remove?: boolean;\n parent?: string;\n root?: boolean;\n children?: React.ReactNode;\n}\n\nconst PropertyContext = createContext<Property | undefined>(undefined);\n\nexport function useParentProperty() {\n return useContext(PropertyContext);\n}\n\ninterface AncestorMatch {\n [key: string]: string | boolean | number | null | undefined;\n}\n\nexport function useAncestor(params: AncestorMatch) {\n const property = useParentProperty();\n const { store } = useProperties();\n\n const matchOrGetAncestor = (\n property: Property,\n params: AncestorMatch\n ): Property | undefined => {\n const children = store.getChildrenOf(property.id);\n const matchedProps = children.filter(\n prop => prop.name in params && prop.value === params[prop.name]\n );\n\n if (matchedProps.length === Object.keys(params).length) {\n return property;\n }\n\n const newParent = property.parent ? store.getById(property.parent) : undefined;\n\n return newParent ? matchOrGetAncestor(newParent, params) : undefined;\n };\n\n return property ? matchOrGetAncestor(property, params) : undefined;\n}\n\nexport const Property = ({\n id,\n name,\n value,\n children,\n after = undefined,\n before = undefined,\n replace = undefined,\n remove = false,\n array = false,\n root = false,\n parent = undefined\n}: PropertyProps) => {\n const targetName = useContext(PropertiesTargetContext);\n const uniqueId = useMemo(() => id || getUniqueId(), []);\n const parentProperty = useParentProperty();\n const immediateProperties = useProperties();\n const ancestorByName = useAncestorByName(targetName);\n const previousValue = useRef(value);\n const priority = usePropertyPriority();\n\n const properties = targetName && ancestorByName ? ancestorByName : immediateProperties;\n\n if (!properties) {\n throw Error(\"<Properties> provider is missing higher in the hierarchy!\");\n }\n\n const { addProperty, removeProperty, replaceProperty, store: propertyStore } = properties;\n const parentId = parent ? parent : root ? \"\" : parentProperty?.id || \"\";\n const property = { id: uniqueId, name, value, parent: parentId, array };\n\n // Register in the synchronous lookup during render so useAncestor can find this property.\n if (!remove) {\n propertyStore.registerLookup(property);\n }\n\n useEffect(() => {\n if (remove) {\n removeProperty(uniqueId);\n return;\n }\n\n if (replace) {\n replaceProperty(replace, property);\n return;\n }\n\n const $isFirst = before === \"$first\";\n const $isLast = after === \"$last\";\n\n addProperty({ ...property, $isFirst, $isLast }, { after, before, priority });\n\n return () => {\n removeProperty(uniqueId);\n };\n }, []);\n\n useEffect(() => {\n if (previousValue.current !== value) {\n previousValue.current = value;\n if (!remove && !replace) {\n replaceProperty(uniqueId, property);\n }\n }\n }, [value]);\n\n if (children) {\n return <PropertyContext.Provider value={property}>{children}</PropertyContext.Provider>;\n }\n\n return null;\n};\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,aAAa,EAAEC,UAAU,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,QAAQ,OAAO;AACpF,SAASC,WAAW,EAAEC,QAAQ;AAC9B,SAASC,aAAa;AACtB,SAASC,mBAAmB;AAE5B,MAAMC,uBAAuB,gBAAGT,aAAa,CAAqBU,SAAS,CAAC;AAO5E,OAAO,MAAMC,mBAAmB,GAAGA,CAAC;EAAEC,IAAI;EAAEC;AAAmC,CAAC,KAAK;EACjF,oBACId,KAAA,CAAAe,aAAA,CAACL,uBAAuB,CAACM,QAAQ;IAACC,KAAK,EAAEJ;EAAK,GAAEC,QAA2C,CAAC;AAEpG,CAAC;AA4BD,MAAMI,iBAAiB,gBAAGjB,aAAa,CAAgCU,SAAS,CAAC;AAQjF,OAAO,MAAMQ,UAAU,GAAGA,CAAC;EAAEN,IAAI;EAAEO,QAAQ;EAAEN;AAA0B,CAAC,KAAK;EACzE,MAAMO,QAAQ,GAAGhB,MAAM,CAAuB,IAAI,CAAC;EACnD,IAAI,CAACgB,QAAQ,CAACC,OAAO,EAAE;IACnBD,QAAQ,CAACC,OAAO,GAAG,IAAId,aAAa,CAAC,CAAC;EAC1C;EACA,MAAMe,KAAK,GAAGF,QAAQ,CAACC,OAAO;EAE9B,IAAIE,MAAyB;EAE7B,IAAI;IACAA,MAAM,GAAGC,aAAa,CAAC,CAAC;EAC5B,CAAC,CAAC,MAAM;IACJ;EAAA;EAGJtB,SAAS,CAAC,MAAM;IACZ,IAAI,CAACiB,QAAQ,EAAE;MACX;IACJ;IAEA,OAAOG,KAAK,CAACG,SAAS,CAACC,UAAU,IAAI;MACjCP,QAAQ,CAACO,UAAU,CAAC;IACxB,CAAC,CAAC;EACN,CAAC,EAAE,CAACJ,KAAK,EAAEH,QAAQ,CAAC,CAAC;;EAErB;EACA;EACA,MAAMQ,OAA0B,GAAGxB,OAAO,CACtC,OAAO;IACHS,IAAI;IACJU,KAAK;IACLM,WAAWA,CAACC,YAAoB,EAAE;MAC9B,IAAI,CAACN,MAAM,EAAE;QACT,OAAOb,SAAS;MACpB;MAEA,OAAOa,MAAM,IAAIA,MAAM,CAACX,IAAI,KAAKiB,YAAY,GACvCN,MAAM,GACNA,MAAM,CAACK,WAAW,CAACC,YAAY,CAAC;IAC1C,CAAC;IACDC,SAASA,CAAA,EAAM;MACX,OAAOxB,QAAQ,CAACgB,KAAK,CAACS,aAAa,CAAC;IACxC,CAAC;IACDC,WAAWA,CAACC,QAAQ,EAAEC,OAAO,GAAG,CAAC,CAAC,EAAE;MAChCZ,KAAK,CAACU,WAAW,CAACC,QAAQ,EAAEC,OAAO,CAAC;IACxC,CAAC;IACDC,cAAcA,CAACC,EAAE,EAAE;MACfd,KAAK,CAACa,cAAc,CAACC,EAAE,CAAC;IAC5B,CAAC;IACDC,eAAeA,CAACD,EAAE,EAAEH,QAAQ,EAAE;MAC1BX,KAAK,CAACe,eAAe,CAACD,EAAE,EAAEH,QAAQ,CAAC;IACvC;EACJ,CAAC,CAAC,EACF,CAACX,KAAK,CACV,CAAC;EAED,oBAAOvB,KAAA,CAAAe,aAAA,CAACG,iBAAiB,CAACF,QAAQ;IAACC,KAAK,EAAEW;EAAQ,GAAEd,QAAqC,CAAC;AAC9F,CAAC;AAED,OAAO,SAASW,aAAaA,CAAA,EAAG;EAC5B,MAAMG,OAAO,GAAG1B,UAAU,CAACgB,iBAAiB,CAAC;EAC7C,IAAI,CAACU,OAAO,EAAE;IACV,MAAMW,KAAK,CAAC,yCAAyC,CAAC;EAC1D;EAEA,OAAOX,OAAO;AAClB;AAEA,OAAO,SAASY,kBAAkBA,CAAA,EAAG;EACjC,OAAOtC,UAAU,CAACgB,iBAAiB,CAAC;AACxC;AAEA,OAAO,SAASuB,iBAAiBA,CAAC5B,IAAwB,EAAE;EACxD,MAAMW,MAAM,GAAGgB,kBAAkB,CAAC,CAAC;EAEnC,OAAOpC,OAAO,CAAC,MAAM;IACjB,IAAI,CAACS,IAAI,IAAI,CAACW,MAAM,EAAE;MAClB,OAAOb,SAAS;IACpB;IAEA,IAAIa,MAAM,CAACX,IAAI,KAAKA,IAAI,EAAE;MACtB,OAAOW,MAAM;IACjB;IAEA,OAAOA,MAAM,CAACK,WAAW,CAAChB,IAAI,CAAC;EACnC,CAAC,EAAE,CAACA,IAAI,CAAC,CAAC;AACd;AAgBA,MAAM6B,eAAe,gBAAGzC,aAAa,CAAuBU,SAAS,CAAC;AAEtE,OAAO,SAASgC,iBAAiBA,CAAA,EAAG;EAChC,OAAOzC,UAAU,CAACwC,eAAe,CAAC;AACtC;AAMA,OAAO,SAASE,WAAWA,CAACC,MAAqB,EAAE;EAC/C,MAAMX,QAAQ,GAAGS,iBAAiB,CAAC,CAAC;EACpC,MAAM;IAAEpB;EAAM,CAAC,GAAGE,aAAa,CAAC,CAAC;EAEjC,MAAMqB,kBAAkB,GAAGA,CACvBZ,QAAkB,EAClBW,MAAqB,KACE;IACvB,MAAM/B,QAAQ,GAAGS,KAAK,CAACwB,aAAa,CAACb,QAAQ,CAACG,EAAE,CAAC;IACjD,MAAMW,YAAY,GAAGlC,QAAQ,CAACmC,MAAM,CAChCC,IAAI,IAAIA,IAAI,CAACrC,IAAI,IAAIgC,MAAM,IAAIK,IAAI,CAACjC,KAAK,KAAK4B,MAAM,CAACK,IAAI,CAACrC,IAAI,CAClE,CAAC;IAED,IAAImC,YAAY,CAACG,MAAM,KAAKC,MAAM,CAACC,IAAI,CAACR,MAAM,CAAC,CAACM,MAAM,EAAE;MACpD,OAAOjB,QAAQ;IACnB;IAEA,MAAMoB,SAAS,GAAGpB,QAAQ,CAACV,MAAM,GAAGD,KAAK,CAACgC,OAAO,CAACrB,QAAQ,CAACV,MAAM,CAAC,GAAGb,SAAS;IAE9E,OAAO2C,SAAS,GAAGR,kBAAkB,CAACQ,SAAS,EAAET,MAAM,CAAC,GAAGlC,SAAS;EACxE,CAAC;EAED,OAAOuB,QAAQ,GAAGY,kBAAkB,CAACZ,QAAQ,EAAEW,MAAM,CAAC,GAAGlC,SAAS;AACtE;AAEA,OAAO,MAAM6C,QAAQ,GAAGA,CAAC;EACrBnB,EAAE;EACFxB,IAAI;EACJI,KAAK;EACLH,QAAQ;EACR2C,KAAK,GAAG9C,SAAS;EACjB+C,MAAM,GAAG/C,SAAS;EAClBgD,OAAO,GAAGhD,SAAS;EACnBiD,MAAM,GAAG,KAAK;EACdC,KAAK,GAAG,KAAK;EACbC,IAAI,GAAG,KAAK;EACZtC,MAAM,GAAGb;AACE,CAAC,KAAK;EACjB,MAAMoD,UAAU,GAAG7D,UAAU,CAACQ,uBAAuB,CAAC;EACtD,MAAMsD,QAAQ,GAAG5D,OAAO,CAAC,MAAMiC,EAAE,IAAI/B,WAAW,CAAC,CAAC,EAAE,EAAE,CAAC;EACvD,MAAM2D,cAAc,GAAGtB,iBAAiB,CAAC,CAAC;EAC1C,MAAMuB,mBAAmB,GAAGzC,aAAa,CAAC,CAAC;EAC3C,MAAM0C,cAAc,GAAG1B,iBAAiB,CAACsB,UAAU,CAAC;EACpD,MAAMK,aAAa,GAAG/D,MAAM,CAACY,KAAK,CAAC;EACnC,MAAMoD,QAAQ,GAAG5D,mBAAmB,CAAC,CAAC;EAEtC,MAAMkB,UAAU,GAAGoC,UAAU,IAAII,cAAc,GAAGA,cAAc,GAAGD,mBAAmB;EAEtF,IAAI,CAACvC,UAAU,EAAE;IACb,MAAMY,KAAK,CAAC,2DAA2D,CAAC;EAC5E;EAEA,MAAM;IAAEN,WAAW;IAAEG,cAAc;IAAEE,eAAe;IAAEf,KAAK,EAAE+C;EAAc,CAAC,GAAG3C,UAAU;EACzF,MAAM4C,QAAQ,GAAG/C,MAAM,GAAGA,MAAM,GAAGsC,IAAI,GAAG,EAAE,GAAGG,cAAc,EAAE5B,EAAE,IAAI,EAAE;EACvE,MAAMH,QAAQ,GAAG;IAAEG,EAAE,EAAE2B,QAAQ;IAAEnD,IAAI;IAAEI,KAAK;IAAEO,MAAM,EAAE+C,QAAQ;IAAEV;EAAM,CAAC;;EAEvE;EACA,IAAI,CAACD,MAAM,EAAE;IACTU,aAAa,CAACE,cAAc,CAACtC,QAAQ,CAAC;EAC1C;EAEA/B,SAAS,CAAC,MAAM;IACZ,IAAIyD,MAAM,EAAE;MACRxB,cAAc,CAAC4B,QAAQ,CAAC;MACxB;IACJ;IAEA,IAAIL,OAAO,EAAE;MACTrB,eAAe,CAACqB,OAAO,EAAEzB,QAAQ,CAAC;MAClC;IACJ;IAEA,MAAMuC,QAAQ,GAAGf,MAAM,KAAK,QAAQ;IACpC,MAAMgB,OAAO,GAAGjB,KAAK,KAAK,OAAO;IAEjCxB,WAAW,CAAC;MAAE,GAAGC,QAAQ;MAAEuC,QAAQ;MAAEC;IAAQ,CAAC,EAAE;MAAEjB,KAAK;MAAEC,MAAM;MAAEW;IAAS,CAAC,CAAC;IAE5E,OAAO,MAAM;MACTjC,cAAc,CAAC4B,QAAQ,CAAC;IAC5B,CAAC;EACL,CAAC,EAAE,EAAE,CAAC;EAEN7D,SAAS,CAAC,MAAM;IACZ,IAAIiE,aAAa,CAAC9C,OAAO,KAAKL,KAAK,EAAE;MACjCmD,aAAa,CAAC9C,OAAO,GAAGL,KAAK;MAC7B,IAAI,CAAC2C,MAAM,IAAI,CAACD,OAAO,EAAE;QACrBrB,eAAe,CAAC0B,QAAQ,EAAE9B,QAAQ,CAAC;MACvC;IACJ;EACJ,CAAC,EAAE,CAACjB,KAAK,CAAC,CAAC;EAEX,IAAIH,QAAQ,EAAE;IACV,oBAAOd,KAAA,CAAAe,aAAA,CAAC2B,eAAe,CAAC1B,QAAQ;MAACC,KAAK,EAAEiB;IAAS,GAAEpB,QAAmC,CAAC;EAC3F;EAEA,OAAO,IAAI;AACf,CAAC","ignoreList":[]}
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ interface PropertyPriorityProviderProps {
3
+ priority: number;
4
+ children: React.ReactNode;
5
+ }
6
+ export declare const PropertyPriorityProvider: ({ priority, children }: PropertyPriorityProviderProps) => React.JSX.Element;
7
+ export declare function usePropertyPriority(): number;
8
+ export {};
@@ -0,0 +1,15 @@
1
+ import React, { createContext, useContext } from "react";
2
+ const PropertyPriorityContext = /*#__PURE__*/createContext(0);
3
+ export const PropertyPriorityProvider = ({
4
+ priority,
5
+ children
6
+ }) => {
7
+ return /*#__PURE__*/React.createElement(PropertyPriorityContext.Provider, {
8
+ value: priority
9
+ }, children);
10
+ };
11
+ export function usePropertyPriority() {
12
+ return useContext(PropertyPriorityContext);
13
+ }
14
+
15
+ //# sourceMappingURL=PropertyPriority.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","createContext","useContext","PropertyPriorityContext","PropertyPriorityProvider","priority","children","createElement","Provider","value","usePropertyPriority"],"sources":["PropertyPriority.tsx"],"sourcesContent":["import React, { createContext, useContext } from \"react\";\n\nconst PropertyPriorityContext = createContext(0);\n\ninterface PropertyPriorityProviderProps {\n priority: number;\n children: React.ReactNode;\n}\n\nexport const PropertyPriorityProvider = ({ priority, children }: PropertyPriorityProviderProps) => {\n return (\n <PropertyPriorityContext.Provider value={priority}>\n {children}\n </PropertyPriorityContext.Provider>\n );\n};\n\nexport function usePropertyPriority(): number {\n return useContext(PropertyPriorityContext);\n}\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,aAAa,EAAEC,UAAU,QAAQ,OAAO;AAExD,MAAMC,uBAAuB,gBAAGF,aAAa,CAAC,CAAC,CAAC;AAOhD,OAAO,MAAMG,wBAAwB,GAAGA,CAAC;EAAEC,QAAQ;EAAEC;AAAwC,CAAC,KAAK;EAC/F,oBACIN,KAAA,CAAAO,aAAA,CAACJ,uBAAuB,CAACK,QAAQ;IAACC,KAAK,EAAEJ;EAAS,GAC7CC,QAC6B,CAAC;AAE3C,CAAC;AAED,OAAO,SAASI,mBAAmBA,CAAA,EAAW;EAC1C,OAAOR,UAAU,CAACC,uBAAuB,CAAC;AAC9C","ignoreList":[]}
@@ -1,8 +1,8 @@
1
- import React, { useContext, useEffect, useMemo, useState } from "react";
1
+ import React, { useCallback, useContext, useEffect, useMemo, useState } from "react";
2
2
  import { Compose, makeDecoratable } from "@webiny/react-composition";
3
3
  import { Properties, toObject } from "./index.js";
4
4
  import { useDebugConfig } from "./useDebugConfig.js";
5
- import debounce from "lodash/debounce.js";
5
+ import { PropertyPriorityProvider } from "./PropertyPriority.js";
6
6
  const createHOC = newChildren => BaseComponent => {
7
7
  return function ConfigHOC({
8
8
  children
@@ -11,9 +11,6 @@ const createHOC = newChildren => BaseComponent => {
11
11
  };
12
12
  };
13
13
  export function createConfigurableComponent(name) {
14
- /**
15
- * This component is used when we want to mount all composed configs.
16
- */
17
14
  const ConfigApplyPrimary = makeDecoratable(`${name}ConfigApply<Primary>`, ({
18
15
  children
19
16
  }) => {
@@ -24,10 +21,6 @@ export function createConfigurableComponent(name) {
24
21
  }) => {
25
22
  return /*#__PURE__*/React.createElement(React.Fragment, null, children);
26
23
  });
27
-
28
- /**
29
- * This component is used to configure the component (it can be mounted many times).
30
- */
31
24
  const Config = ({
32
25
  priority = "primary",
33
26
  children
@@ -47,28 +40,46 @@ export function createConfigurableComponent(name) {
47
40
  properties: []
48
41
  };
49
42
  const ViewContext = /*#__PURE__*/React.createContext(defaultContext);
43
+
44
+ /**
45
+ * Memoized config subtree — ConfigApply components don't depend on WithConfig
46
+ * props, so they must not remount when the parent re-renders. Without this,
47
+ * every parent re-render causes Property components inside HOCs to unmount
48
+ * and remount, corrupting the config object.
49
+ */
50
+ const ConfigApplyTree = /*#__PURE__*/React.memo(function ConfigApplyTree() {
51
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ConfigApplyPrimary, null), /*#__PURE__*/React.createElement(PropertyPriorityProvider, {
52
+ priority: 1
53
+ }, /*#__PURE__*/React.createElement(ConfigApplySecondary, null)));
54
+ });
50
55
  const WithConfig = ({
51
56
  onProperties,
52
57
  children
53
58
  }) => {
54
- const [properties, setProperties] = useState([]);
55
- useDebugConfig(name, properties);
59
+ // `null` = config not yet collected; `[]` = collected but empty.
60
+ // This distinction is critical: children must NOT render until the
61
+ // PropertyStore debounce has flushed and delivered the initial config.
62
+ // Rendering children with partial/empty config causes errors in
63
+ // consumers like LexicalEditor that require a complete config on mount.
64
+ const [properties, setProperties] = useState(null);
65
+ const resolvedProperties = properties ?? [];
66
+ useDebugConfig(name, resolvedProperties);
56
67
  const context = {
57
- properties
68
+ properties: resolvedProperties
58
69
  };
59
70
  useEffect(() => {
60
- if (typeof onProperties === "function") {
71
+ if (properties !== null && typeof onProperties === "function") {
61
72
  onProperties(properties);
62
73
  }
63
74
  }, [properties]);
64
- const stateUpdater = properties => {
75
+ const stateUpdater = useCallback(properties => {
65
76
  setProperties(properties);
66
- };
77
+ }, []);
67
78
  return /*#__PURE__*/React.createElement(ViewContext.Provider, {
68
79
  value: context
69
80
  }, /*#__PURE__*/React.createElement(Properties, {
70
81
  onChange: stateUpdater
71
- }, /*#__PURE__*/React.createElement(ConfigApplyPrimary, null), /*#__PURE__*/React.createElement(DebounceRenderer, null, /*#__PURE__*/React.createElement(ConfigApplySecondary, null), /*#__PURE__*/React.createElement(DebounceRenderer, null, children))));
82
+ }, /*#__PURE__*/React.createElement(ConfigApplyTree, null)), properties !== null ? children : null);
72
83
  };
73
84
  function useConfig() {
74
85
  const {
@@ -76,27 +87,6 @@ export function createConfigurableComponent(name) {
76
87
  } = useContext(ViewContext);
77
88
  return useMemo(() => toObject(properties), [properties]);
78
89
  }
79
- const DebounceRenderer = ({
80
- children
81
- }) => {
82
- const [render, setRender] = useState(false);
83
- const editorConfig = useConfig();
84
- const debouncedRender = useMemo(() => {
85
- return debounce(() => {
86
- setRender(true);
87
- }, 10);
88
- }, [setRender]);
89
- useEffect(() => {
90
- if (render) {
91
- return;
92
- }
93
- debouncedRender();
94
- return () => {
95
- debouncedRender.cancel();
96
- };
97
- }, [editorConfig]);
98
- return /*#__PURE__*/React.createElement(React.Fragment, null, render ? children : null);
99
- };
100
90
  return {
101
91
  WithConfig,
102
92
  Config,
@@ -1 +1 @@
1
- {"version":3,"names":["React","useContext","useEffect","useMemo","useState","Compose","makeDecoratable","Properties","toObject","useDebugConfig","debounce","createHOC","newChildren","BaseComponent","ConfigHOC","children","createElement","createConfigurableComponent","name","ConfigApplyPrimary","Fragment","ConfigApplySecondary","Config","priority","component","with","defaultContext","properties","ViewContext","createContext","WithConfig","onProperties","setProperties","context","stateUpdater","Provider","value","onChange","DebounceRenderer","useConfig","render","setRender","editorConfig","debouncedRender","cancel"],"sources":["createConfigurableComponent.tsx"],"sourcesContent":["import React, { useContext, useEffect, useMemo, useState } from \"react\";\nimport type { Decorator } from \"@webiny/react-composition\";\nimport { Compose, makeDecoratable } from \"@webiny/react-composition\";\nimport type { GenericComponent } from \"@webiny/react-composition/types.js\";\nimport type { Property } from \"~/index.js\";\nimport { Properties, toObject } from \"~/index.js\";\nimport { useDebugConfig } from \"./useDebugConfig.js\";\nimport debounce from \"lodash/debounce.js\";\n\nconst createHOC =\n (newChildren: React.ReactNode): Decorator<GenericComponent<{ children?: React.ReactNode }>> =>\n BaseComponent => {\n return function ConfigHOC({ children }) {\n return (\n <BaseComponent>\n {children}\n {newChildren}\n </BaseComponent>\n );\n };\n };\n\nexport interface WithConfigProps {\n children: React.ReactNode;\n onProperties?(properties: Property[]): void;\n}\n\ninterface ConfigApplyProps {\n children?: React.ReactNode;\n}\n\nexport interface ConfigProps {\n children: React.ReactNode;\n priority?: \"primary\" | \"secondary\";\n}\n\nexport function createConfigurableComponent<TConfig>(name: string) {\n /**\n * This component is used when we want to mount all composed configs.\n */\n const ConfigApplyPrimary = makeDecoratable(\n `${name}ConfigApply<Primary>`,\n ({ children }: ConfigApplyProps) => {\n return <>{children}</>;\n }\n );\n\n const ConfigApplySecondary = makeDecoratable(\n `${name}ConfigApply<Secondary>`,\n ({ children }: ConfigApplyProps) => {\n return <>{children}</>;\n }\n );\n\n /**\n * This component is used to configure the component (it can be mounted many times).\n */\n const Config = ({ priority = \"primary\", children }: ConfigProps) => {\n if (priority === \"primary\") {\n return <Compose component={ConfigApplyPrimary} with={createHOC(children)} />;\n }\n return <Compose component={ConfigApplySecondary} with={createHOC(children)} />;\n };\n\n interface ViewContext {\n properties: Property[];\n }\n\n const defaultContext = { properties: [] };\n\n const ViewContext = React.createContext<ViewContext>(defaultContext);\n\n const WithConfig = ({ onProperties, children }: WithConfigProps) => {\n const [properties, setProperties] = useState<Property[]>([]);\n useDebugConfig(name, properties);\n const context = { properties };\n\n useEffect(() => {\n if (typeof onProperties === \"function\") {\n onProperties(properties);\n }\n }, [properties]);\n\n const stateUpdater = (properties: Property[]) => {\n setProperties(properties);\n };\n\n return (\n <ViewContext.Provider value={context}>\n <Properties onChange={stateUpdater}>\n <ConfigApplyPrimary />\n <DebounceRenderer>\n <ConfigApplySecondary />\n <DebounceRenderer>{children}</DebounceRenderer>\n </DebounceRenderer>\n </Properties>\n </ViewContext.Provider>\n );\n };\n\n function useConfig<TExtra extends object>(): TConfig & TExtra {\n const { properties } = useContext(ViewContext);\n return useMemo(() => toObject<TConfig & TExtra>(properties), [properties]);\n }\n\n interface Props {\n children?: React.ReactNode;\n }\n\n const DebounceRenderer = ({ children }: Props) => {\n const [render, setRender] = useState(false);\n const editorConfig = useConfig();\n\n const debouncedRender = useMemo(() => {\n return debounce(() => {\n setRender(true);\n }, 10);\n }, [setRender]);\n\n useEffect(() => {\n if (render) {\n return;\n }\n\n debouncedRender();\n\n return () => {\n debouncedRender.cancel();\n };\n }, [editorConfig]);\n\n return <>{render ? children : null}</>;\n };\n\n return {\n WithConfig,\n Config,\n useConfig\n };\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","useCallback","useContext","useEffect","useMemo","useState","Compose","makeDecoratable","Properties","toObject","useDebugConfig","PropertyPriorityProvider","createHOC","newChildren","BaseComponent","ConfigHOC","children","createElement","createConfigurableComponent","name","ConfigApplyPrimary","Fragment","ConfigApplySecondary","Config","priority","component","with","defaultContext","properties","ViewContext","createContext","ConfigApplyTree","memo","WithConfig","onProperties","setProperties","resolvedProperties","context","stateUpdater","Provider","value","onChange","useConfig"],"sources":["createConfigurableComponent.tsx"],"sourcesContent":["import React, { useCallback, useContext, useEffect, useMemo, useState } from \"react\";\nimport type { Decorator } from \"@webiny/react-composition\";\nimport { Compose, makeDecoratable } from \"@webiny/react-composition\";\nimport type { GenericComponent } from \"@webiny/react-composition/types.js\";\nimport type { Property } from \"~/index.js\";\nimport { Properties, toObject } from \"~/index.js\";\nimport { useDebugConfig } from \"./useDebugConfig.js\";\nimport { PropertyPriorityProvider } from \"./PropertyPriority.js\";\n\nconst createHOC =\n (newChildren: React.ReactNode): Decorator<GenericComponent<{ children?: React.ReactNode }>> =>\n BaseComponent => {\n return function ConfigHOC({ children }) {\n return (\n <BaseComponent>\n {children}\n {newChildren}\n </BaseComponent>\n );\n };\n };\n\nexport interface WithConfigProps {\n children: React.ReactNode;\n onProperties?(properties: Property[]): void;\n}\n\ninterface ConfigApplyProps {\n children?: React.ReactNode;\n}\n\nexport interface ConfigProps {\n children: React.ReactNode;\n priority?: \"primary\" | \"secondary\";\n}\n\nexport function createConfigurableComponent<TConfig>(name: string) {\n const ConfigApplyPrimary = makeDecoratable(\n `${name}ConfigApply<Primary>`,\n ({ children }: ConfigApplyProps) => {\n return <>{children}</>;\n }\n );\n\n const ConfigApplySecondary = makeDecoratable(\n `${name}ConfigApply<Secondary>`,\n ({ children }: ConfigApplyProps) => {\n return <>{children}</>;\n }\n );\n\n const Config = ({ priority = \"primary\", children }: ConfigProps) => {\n if (priority === \"primary\") {\n return <Compose component={ConfigApplyPrimary} with={createHOC(children)} />;\n }\n return <Compose component={ConfigApplySecondary} with={createHOC(children)} />;\n };\n\n interface ViewContext {\n properties: Property[];\n }\n\n const defaultContext = { properties: [] };\n\n const ViewContext = React.createContext<ViewContext>(defaultContext);\n\n /**\n * Memoized config subtree — ConfigApply components don't depend on WithConfig\n * props, so they must not remount when the parent re-renders. Without this,\n * every parent re-render causes Property components inside HOCs to unmount\n * and remount, corrupting the config object.\n */\n const ConfigApplyTree = React.memo(function ConfigApplyTree() {\n return (\n <>\n <ConfigApplyPrimary />\n <PropertyPriorityProvider priority={1}>\n <ConfigApplySecondary />\n </PropertyPriorityProvider>\n </>\n );\n });\n\n const WithConfig = ({ onProperties, children }: WithConfigProps) => {\n // `null` = config not yet collected; `[]` = collected but empty.\n // This distinction is critical: children must NOT render until the\n // PropertyStore debounce has flushed and delivered the initial config.\n // Rendering children with partial/empty config causes errors in\n // consumers like LexicalEditor that require a complete config on mount.\n const [properties, setProperties] = useState<Property[] | null>(null);\n const resolvedProperties = properties ?? [];\n useDebugConfig(name, resolvedProperties);\n const context = { properties: resolvedProperties };\n\n useEffect(() => {\n if (properties !== null && typeof onProperties === \"function\") {\n onProperties(properties);\n }\n }, [properties]);\n\n const stateUpdater = useCallback((properties: Property[]) => {\n setProperties(properties);\n }, []);\n\n return (\n <ViewContext.Provider value={context}>\n {/* ConfigApplyTree always renders so Property components inside\n composed HOCs can mount and register with the PropertyStore.\n It lives outside the children gate below. */}\n <Properties onChange={stateUpdater}>\n <ConfigApplyTree />\n </Properties>\n {/* Gate: only render children once the PropertyStore has flushed\n its first batch (properties !== null). This guarantees that\n useConfig() returns a complete config object on first render. */}\n {properties !== null ? children : null}\n </ViewContext.Provider>\n );\n };\n\n function useConfig<TExtra extends object>(): TConfig & TExtra {\n const { properties } = useContext(ViewContext);\n return useMemo(() => toObject<TConfig & TExtra>(properties), [properties]);\n }\n\n return {\n WithConfig,\n Config,\n useConfig\n };\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,48 @@
1
+ import type { Property } from "../Properties.js";
2
+ interface AddPropertyOptions {
3
+ after?: string;
4
+ before?: string;
5
+ priority?: number;
6
+ }
7
+ type Listener = (properties: Property[]) => void;
8
+ export declare class PropertyStore {
9
+ private map;
10
+ private order;
11
+ private queue;
12
+ private listeners;
13
+ /**
14
+ * Synchronous lookup map — written immediately on addProperty (before debounce),
15
+ * so useAncestor can find properties during render.
16
+ */
17
+ private lookup;
18
+ private scheduleFlush;
19
+ get allProperties(): Property[];
20
+ subscribe(listener: Listener): () => void;
21
+ /**
22
+ * Returns properties that are children of the given parent ID.
23
+ * Reads from the synchronous lookup map, so it works during render
24
+ * before the debounced queue has flushed.
25
+ */
26
+ getChildrenOf(parentId: string): Property[];
27
+ /**
28
+ * Find a property by ID from the synchronous lookup map.
29
+ */
30
+ getById(id: string): Property | undefined;
31
+ /**
32
+ * Register a property in the synchronous lookup map during render,
33
+ * so useAncestor can find it before the debounced queue flushes.
34
+ */
35
+ registerLookup(property: Property): void;
36
+ addProperty(property: Property, options?: AddPropertyOptions): void;
37
+ removeProperty(id: string): void;
38
+ replaceProperty(oldId: string, newProperty: Property): void;
39
+ private processQueue;
40
+ private executeAdd;
41
+ private executeRemove;
42
+ private executeReplace;
43
+ private insertBefore;
44
+ private insertAfter;
45
+ private reposition;
46
+ private removeDescendants;
47
+ }
48
+ export {};
@@ -0,0 +1,200 @@
1
+ import debounce from "lodash/debounce.js";
2
+ export class PropertyStore {
3
+ map = new Map();
4
+ order = [];
5
+ queue = [];
6
+ listeners = new Set();
7
+
8
+ /**
9
+ * Synchronous lookup map — written immediately on addProperty (before debounce),
10
+ * so useAncestor can find properties during render.
11
+ */
12
+ lookup = new Map();
13
+ scheduleFlush = debounce(() => {
14
+ this.processQueue();
15
+ }, 0);
16
+ get allProperties() {
17
+ return this.order.filter(id => this.map.has(id)).map(id => this.map.get(id));
18
+ }
19
+ subscribe(listener) {
20
+ this.listeners.add(listener);
21
+ return () => {
22
+ this.listeners.delete(listener);
23
+ };
24
+ }
25
+
26
+ /**
27
+ * Returns properties that are children of the given parent ID.
28
+ * Reads from the synchronous lookup map, so it works during render
29
+ * before the debounced queue has flushed.
30
+ */
31
+ getChildrenOf(parentId) {
32
+ return Array.from(this.lookup.values()).filter(p => p.parent === parentId);
33
+ }
34
+
35
+ /**
36
+ * Find a property by ID from the synchronous lookup map.
37
+ */
38
+ getById(id) {
39
+ return this.lookup.get(id);
40
+ }
41
+
42
+ /**
43
+ * Register a property in the synchronous lookup map during render,
44
+ * so useAncestor can find it before the debounced queue flushes.
45
+ */
46
+ registerLookup(property) {
47
+ if (this.lookup.has(property.id)) {
48
+ const existing = this.lookup.get(property.id);
49
+ this.lookup.set(property.id, {
50
+ ...existing,
51
+ ...property
52
+ });
53
+ } else {
54
+ this.lookup.set(property.id, property);
55
+ }
56
+ }
57
+ addProperty(property, options = {}) {
58
+ this.registerLookup(property);
59
+ this.queue.push({
60
+ type: "add",
61
+ property,
62
+ options
63
+ });
64
+ this.scheduleFlush();
65
+ }
66
+ removeProperty(id) {
67
+ this.lookup.delete(id);
68
+ this.queue.push({
69
+ type: "remove",
70
+ id
71
+ });
72
+ this.scheduleFlush();
73
+ }
74
+ replaceProperty(oldId, newProperty) {
75
+ this.lookup.delete(oldId);
76
+ this.lookup.set(newProperty.id, newProperty);
77
+ this.queue.push({
78
+ type: "replace",
79
+ oldId,
80
+ newProperty
81
+ });
82
+ this.scheduleFlush();
83
+ }
84
+ processQueue() {
85
+ if (this.queue.length === 0) {
86
+ return;
87
+ }
88
+ const ops = this.queue.splice(0);
89
+
90
+ // Stable-sort operations so that "add" ops with lower priority numbers
91
+ // are processed first. Non-add operations and adds with default priority (0)
92
+ // keep their original order.
93
+ ops.sort((a, b) => {
94
+ const pa = a.type === "add" ? a.options.priority ?? 0 : 0;
95
+ const pb = b.type === "add" ? b.options.priority ?? 0 : 0;
96
+ return pa - pb;
97
+ });
98
+ for (const op of ops) {
99
+ switch (op.type) {
100
+ case "add":
101
+ this.executeAdd(op.property, op.options);
102
+ break;
103
+ case "remove":
104
+ this.executeRemove(op.id);
105
+ break;
106
+ case "replace":
107
+ this.executeReplace(op.oldId, op.newProperty);
108
+ break;
109
+ }
110
+ }
111
+ const properties = this.allProperties;
112
+ for (const listener of this.listeners) {
113
+ listener(properties);
114
+ }
115
+ }
116
+ executeAdd(property, options) {
117
+ const exists = this.map.has(property.id);
118
+ if (exists) {
119
+ const existing = this.map.get(property.id);
120
+ this.map.set(property.id, {
121
+ ...existing,
122
+ ...property
123
+ });
124
+ if (options.after) {
125
+ this.reposition(property.id, options.after, "after");
126
+ } else if (options.before) {
127
+ this.reposition(property.id, options.before, "before");
128
+ }
129
+ return;
130
+ }
131
+ this.map.set(property.id, property);
132
+ if (options.after) {
133
+ this.insertAfter(property.id, options.after);
134
+ } else if (options.before) {
135
+ this.insertBefore(property.id, options.before);
136
+ } else {
137
+ this.order.push(property.id);
138
+ }
139
+ }
140
+ executeRemove(id) {
141
+ if (!this.map.has(id)) {
142
+ return;
143
+ }
144
+ this.map.delete(id);
145
+ this.order = this.order.filter(oid => oid !== id);
146
+ this.removeDescendants(id);
147
+ }
148
+ executeReplace(oldId, newProperty) {
149
+ const idx = this.order.indexOf(oldId);
150
+ if (idx === -1) {
151
+ return;
152
+ }
153
+ this.map.delete(oldId);
154
+ this.map.set(newProperty.id, newProperty);
155
+ this.order[idx] = newProperty.id;
156
+ this.removeDescendants(oldId);
157
+ }
158
+ insertBefore(id, before) {
159
+ if (before.endsWith("$first")) {
160
+ this.order.unshift(id);
161
+ return;
162
+ }
163
+ const targetIdx = this.order.indexOf(before);
164
+ if (targetIdx === -1) {
165
+ this.order.push(id);
166
+ return;
167
+ }
168
+ this.order.splice(targetIdx, 0, id);
169
+ }
170
+ insertAfter(id, after) {
171
+ if (after.endsWith("$last")) {
172
+ this.order.push(id);
173
+ return;
174
+ }
175
+ const targetIdx = this.order.indexOf(after);
176
+ if (targetIdx === -1) {
177
+ this.order.push(id);
178
+ return;
179
+ }
180
+ this.order.splice(targetIdx + 1, 0, id);
181
+ }
182
+ reposition(id, targetId, position) {
183
+ this.order = this.order.filter(oid => oid !== id);
184
+ if (position === "before") {
185
+ this.insertBefore(id, targetId);
186
+ } else {
187
+ this.insertAfter(id, targetId);
188
+ }
189
+ }
190
+ removeDescendants(parentId) {
191
+ const children = Array.from(this.map.values()).filter(p => p.parent === parentId);
192
+ for (const child of children) {
193
+ this.map.delete(child.id);
194
+ this.order = this.order.filter(oid => oid !== child.id);
195
+ this.removeDescendants(child.id);
196
+ }
197
+ }
198
+ }
199
+
200
+ //# sourceMappingURL=PropertyStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["debounce","PropertyStore","map","Map","order","queue","listeners","Set","lookup","scheduleFlush","processQueue","allProperties","filter","id","has","get","subscribe","listener","add","delete","getChildrenOf","parentId","Array","from","values","p","parent","getById","registerLookup","property","existing","set","addProperty","options","push","type","removeProperty","replaceProperty","oldId","newProperty","length","ops","splice","sort","a","b","pa","priority","pb","op","executeAdd","executeRemove","executeReplace","properties","exists","after","reposition","before","insertAfter","insertBefore","oid","removeDescendants","idx","indexOf","endsWith","unshift","targetIdx","targetId","position","children","child"],"sources":["PropertyStore.ts"],"sourcesContent":["import debounce from \"lodash/debounce.js\";\nimport type { Property } from \"../Properties.js\";\n\ninterface AddPropertyOptions {\n after?: string;\n before?: string;\n priority?: number;\n}\n\ntype Operation =\n | { type: \"add\"; property: Property; options: AddPropertyOptions }\n | { type: \"remove\"; id: string }\n | { type: \"replace\"; oldId: string; newProperty: Property };\n\ntype Listener = (properties: Property[]) => void;\n\nexport class PropertyStore {\n private map = new Map<string, Property>();\n private order: string[] = [];\n private queue: Operation[] = [];\n private listeners = new Set<Listener>();\n\n /**\n * Synchronous lookup map — written immediately on addProperty (before debounce),\n * so useAncestor can find properties during render.\n */\n private lookup = new Map<string, Property>();\n\n private scheduleFlush = debounce(() => {\n this.processQueue();\n }, 0);\n\n get allProperties(): Property[] {\n return this.order.filter(id => this.map.has(id)).map(id => this.map.get(id)!);\n }\n\n subscribe(listener: Listener): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /**\n * Returns properties that are children of the given parent ID.\n * Reads from the synchronous lookup map, so it works during render\n * before the debounced queue has flushed.\n */\n getChildrenOf(parentId: string): Property[] {\n return Array.from(this.lookup.values()).filter(p => p.parent === parentId);\n }\n\n /**\n * Find a property by ID from the synchronous lookup map.\n */\n getById(id: string): Property | undefined {\n return this.lookup.get(id);\n }\n\n /**\n * Register a property in the synchronous lookup map during render,\n * so useAncestor can find it before the debounced queue flushes.\n */\n registerLookup(property: Property): void {\n if (this.lookup.has(property.id)) {\n const existing = this.lookup.get(property.id)!;\n this.lookup.set(property.id, { ...existing, ...property });\n } else {\n this.lookup.set(property.id, property);\n }\n }\n\n addProperty(property: Property, options: AddPropertyOptions = {}): void {\n this.registerLookup(property);\n this.queue.push({ type: \"add\", property, options });\n this.scheduleFlush();\n }\n\n removeProperty(id: string): void {\n this.lookup.delete(id);\n this.queue.push({ type: \"remove\", id });\n this.scheduleFlush();\n }\n\n replaceProperty(oldId: string, newProperty: Property): void {\n this.lookup.delete(oldId);\n this.lookup.set(newProperty.id, newProperty);\n this.queue.push({ type: \"replace\", oldId, newProperty });\n this.scheduleFlush();\n }\n\n private processQueue(): void {\n if (this.queue.length === 0) {\n return;\n }\n\n const ops = this.queue.splice(0);\n\n // Stable-sort operations so that \"add\" ops with lower priority numbers\n // are processed first. Non-add operations and adds with default priority (0)\n // keep their original order.\n ops.sort((a, b) => {\n const pa = a.type === \"add\" ? (a.options.priority ?? 0) : 0;\n const pb = b.type === \"add\" ? (b.options.priority ?? 0) : 0;\n return pa - pb;\n });\n\n for (const op of ops) {\n switch (op.type) {\n case \"add\":\n this.executeAdd(op.property, op.options);\n break;\n case \"remove\":\n this.executeRemove(op.id);\n break;\n case \"replace\":\n this.executeReplace(op.oldId, op.newProperty);\n break;\n }\n }\n\n const properties = this.allProperties;\n for (const listener of this.listeners) {\n listener(properties);\n }\n }\n\n private executeAdd(property: Property, options: AddPropertyOptions): void {\n const exists = this.map.has(property.id);\n\n if (exists) {\n const existing = this.map.get(property.id)!;\n this.map.set(property.id, { ...existing, ...property });\n\n if (options.after) {\n this.reposition(property.id, options.after, \"after\");\n } else if (options.before) {\n this.reposition(property.id, options.before, \"before\");\n }\n return;\n }\n\n this.map.set(property.id, property);\n\n if (options.after) {\n this.insertAfter(property.id, options.after);\n } else if (options.before) {\n this.insertBefore(property.id, options.before);\n } else {\n this.order.push(property.id);\n }\n }\n\n private executeRemove(id: string): void {\n if (!this.map.has(id)) {\n return;\n }\n this.map.delete(id);\n this.order = this.order.filter(oid => oid !== id);\n this.removeDescendants(id);\n }\n\n private executeReplace(oldId: string, newProperty: Property): void {\n const idx = this.order.indexOf(oldId);\n if (idx === -1) {\n return;\n }\n\n this.map.delete(oldId);\n this.map.set(newProperty.id, newProperty);\n this.order[idx] = newProperty.id;\n this.removeDescendants(oldId);\n }\n\n private insertBefore(id: string, before: string): void {\n if (before.endsWith(\"$first\")) {\n this.order.unshift(id);\n return;\n }\n const targetIdx = this.order.indexOf(before);\n if (targetIdx === -1) {\n this.order.push(id);\n return;\n }\n this.order.splice(targetIdx, 0, id);\n }\n\n private insertAfter(id: string, after: string): void {\n if (after.endsWith(\"$last\")) {\n this.order.push(id);\n return;\n }\n const targetIdx = this.order.indexOf(after);\n if (targetIdx === -1) {\n this.order.push(id);\n return;\n }\n this.order.splice(targetIdx + 1, 0, id);\n }\n\n private reposition(id: string, targetId: string, position: \"before\" | \"after\"): void {\n this.order = this.order.filter(oid => oid !== id);\n\n if (position === \"before\") {\n this.insertBefore(id, targetId);\n } else {\n this.insertAfter(id, targetId);\n }\n }\n\n private removeDescendants(parentId: string): void {\n const children = Array.from(this.map.values()).filter(p => p.parent === parentId);\n for (const child of children) {\n this.map.delete(child.id);\n this.order = this.order.filter(oid => oid !== child.id);\n this.removeDescendants(child.id);\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export { PropertyStore } from "./PropertyStore.js";
@@ -0,0 +1,3 @@
1
+ export { PropertyStore } from "./PropertyStore.js";
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["PropertyStore"],"sources":["index.ts"],"sourcesContent":["export { PropertyStore } from \"./PropertyStore.js\";\n"],"mappings":"AAAA,SAASA,aAAa","ignoreList":[]}
package/index.d.ts CHANGED
@@ -3,3 +3,4 @@ export * from "./Properties.js";
3
3
  export * from "./useDebugConfig.js";
4
4
  export * from "./useIdGenerator.js";
5
5
  export * from "./createConfigurableComponent.js";
6
+ export * from "./domain/index.js";
package/index.js CHANGED
@@ -3,5 +3,6 @@ export * from "./Properties.js";
3
3
  export * from "./useDebugConfig.js";
4
4
  export * from "./useIdGenerator.js";
5
5
  export * from "./createConfigurableComponent.js";
6
+ export * from "./domain/index.js";
6
7
 
7
8
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./utils.js\";\nexport * from \"./Properties.js\";\nexport * from \"./useDebugConfig.js\";\nexport * from \"./useIdGenerator.js\";\nexport * from \"./createConfigurableComponent.js\";\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./utils.js\";\nexport * from \"./Properties.js\";\nexport * from \"./useDebugConfig.js\";\nexport * from \"./useIdGenerator.js\";\nexport * from \"./createConfigurableComponent.js\";\nexport * from \"./domain/index.js\";\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/react-properties",
3
- "version": "6.0.0-rc.0",
3
+ "version": "6.0.0-rc.2",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -12,14 +12,14 @@
12
12
  "license": "MIT",
13
13
  "dependencies": {
14
14
  "@types/react": "18.2.79",
15
- "@webiny/react-composition": "6.0.0-rc.0",
15
+ "@webiny/react-composition": "6.0.0-rc.2",
16
16
  "lodash": "4.17.23",
17
17
  "nanoid": "5.1.6",
18
18
  "react": "18.2.0"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@testing-library/react": "15.0.7",
22
- "@webiny/build-tools": "6.0.0-rc.0",
22
+ "@webiny/build-tools": "6.0.0-rc.2",
23
23
  "prettier": "3.6.2",
24
24
  "vitest": "4.0.18"
25
25
  },
@@ -27,5 +27,5 @@
27
27
  "access": "public",
28
28
  "directory": "dist"
29
29
  },
30
- "gitHead": "0f2aa699f4642e550ab62c96fcd050e8d02345c9"
30
+ "gitHead": "5facada4cbb8617cc60e3c98be0f1839f44be38e"
31
31
  }