@webiny/react-properties 0.0.0-unstable.7c9e8fbfd6 → 0.0.0-unstable.81ae05e56b

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.
@@ -0,0 +1,40 @@
1
+ type DevToolsView = "browse" | "raw";
2
+ interface DevToolsSectionProps {
3
+ name: string;
4
+ data: unknown;
5
+ /**
6
+ * Group name for the sidebar. Items with the same group appear
7
+ * under the same header. Defaults to "Sections".
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * <DevToolsSection name="Article" group="CMS" data={model} />
12
+ * <DevToolsSection name="Author" group="CMS" data={author} />
13
+ * ```
14
+ */
15
+ group?: string;
16
+ /**
17
+ * Which views to show in the detail panel.
18
+ * - `"browse"` — split view with root keys on the left, value tree on the right
19
+ * - `"raw"` — full JSON tree view
20
+ *
21
+ * Accepts a single view or an array. First item is the default tab.
22
+ * @default ["browse", "raw"]
23
+ */
24
+ views?: DevToolsView | DevToolsView[];
25
+ }
26
+ /**
27
+ * Registers a named section in the Webiny DevTools extension.
28
+ * Renders nothing — purely a data registration side-effect.
29
+ *
30
+ * When the component unmounts (e.g., route change), the section
31
+ * is automatically removed from DevTools.
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * <DevToolsSection name="CMS Model" data={model} />
36
+ * <DevToolsSection name="Article" group="CMS" data={model} views="raw" />
37
+ * ```
38
+ */
39
+ export declare function DevToolsSection({ name, data, group, views }: DevToolsSectionProps): null;
40
+ export {};
@@ -0,0 +1,70 @@
1
+ import { useEffect } from "react";
2
+ import { getHook } from "./useDebugConfig.js";
3
+ /**
4
+ * Registers a named section in the Webiny DevTools extension.
5
+ * Renders nothing — purely a data registration side-effect.
6
+ *
7
+ * When the component unmounts (e.g., route change), the section
8
+ * is automatically removed from DevTools.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * <DevToolsSection name="CMS Model" data={model} />
13
+ * <DevToolsSection name="Article" group="CMS" data={model} views="raw" />
14
+ * ```
15
+ */
16
+ export function DevToolsSection({
17
+ name,
18
+ data,
19
+ group,
20
+ views
21
+ }) {
22
+ // Snapshot the data on every render to get a stable, plain value.
23
+ // This also ensures that if data is a MobX observable, we capture
24
+ // the current state as a plain object (no proxies on the hook).
25
+ const dataKey = safeStringify(data);
26
+ useEffect(() => {
27
+ if (process.env.NODE_ENV !== "development") {
28
+ return;
29
+ }
30
+ const normalizedViews = views ? Array.isArray(views) ? views : [views] : ["browse", "raw"];
31
+ let plainData;
32
+ try {
33
+ plainData = JSON.parse(dataKey);
34
+ } catch {
35
+ plainData = data;
36
+ }
37
+ const hook = getHook();
38
+ hook.sections[name] = {
39
+ data: plainData,
40
+ group: group || "Sections",
41
+ views: normalizedViews,
42
+ updatedAt: Date.now()
43
+ };
44
+ hook.revision++;
45
+ return () => {
46
+ if (window.__WEBINY_DEVTOOLS_HOOK__) {
47
+ delete window.__WEBINY_DEVTOOLS_HOOK__.sections[name];
48
+ window.__WEBINY_DEVTOOLS_HOOK__.revision++;
49
+ }
50
+ };
51
+ }, [name, dataKey, group, Array.isArray(views) ? views.join(",") : views]);
52
+ return null;
53
+ }
54
+ function safeStringify(value) {
55
+ try {
56
+ return JSON.stringify(value, (_key, v) => {
57
+ if (typeof v === "function") {
58
+ return `[Function: ${v.name || "anonymous"}]`;
59
+ }
60
+ if (typeof v === "undefined") {
61
+ return "[undefined]";
62
+ }
63
+ return v;
64
+ });
65
+ } catch {
66
+ return String(value);
67
+ }
68
+ }
69
+
70
+ //# sourceMappingURL=DevToolsSection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useEffect","getHook","DevToolsSection","name","data","group","views","dataKey","safeStringify","process","env","NODE_ENV","normalizedViews","Array","isArray","plainData","JSON","parse","hook","sections","updatedAt","Date","now","revision","window","__WEBINY_DEVTOOLS_HOOK__","join","value","stringify","_key","v","String"],"sources":["DevToolsSection.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport { getHook } from \"./useDebugConfig.js\";\n\ntype DevToolsView = \"browse\" | \"raw\";\n\ninterface DevToolsSectionProps {\n name: string;\n data: unknown;\n /**\n * Group name for the sidebar. Items with the same group appear\n * under the same header. Defaults to \"Sections\".\n *\n * @example\n * ```tsx\n * <DevToolsSection name=\"Article\" group=\"CMS\" data={model} />\n * <DevToolsSection name=\"Author\" group=\"CMS\" data={author} />\n * ```\n */\n group?: string;\n /**\n * Which views to show in the detail panel.\n * - `\"browse\"` — split view with root keys on the left, value tree on the right\n * - `\"raw\"` — full JSON tree view\n *\n * Accepts a single view or an array. First item is the default tab.\n * @default [\"browse\", \"raw\"]\n */\n views?: DevToolsView | DevToolsView[];\n}\n\n/**\n * Registers a named section in the Webiny DevTools extension.\n * Renders nothing — purely a data registration side-effect.\n *\n * When the component unmounts (e.g., route change), the section\n * is automatically removed from DevTools.\n *\n * @example\n * ```tsx\n * <DevToolsSection name=\"CMS Model\" data={model} />\n * <DevToolsSection name=\"Article\" group=\"CMS\" data={model} views=\"raw\" />\n * ```\n */\nexport function DevToolsSection({ name, data, group, views }: DevToolsSectionProps) {\n // Snapshot the data on every render to get a stable, plain value.\n // This also ensures that if data is a MobX observable, we capture\n // the current state as a plain object (no proxies on the hook).\n const dataKey = safeStringify(data);\n\n useEffect(() => {\n if (process.env.NODE_ENV !== \"development\") {\n return;\n }\n\n const normalizedViews: DevToolsView[] = views\n ? Array.isArray(views)\n ? views\n : [views]\n : [\"browse\", \"raw\"];\n\n let plainData: unknown;\n try {\n plainData = JSON.parse(dataKey);\n } catch {\n plainData = data;\n }\n\n const hook = getHook();\n hook.sections[name] = {\n data: plainData,\n group: group || \"Sections\",\n views: normalizedViews,\n updatedAt: Date.now()\n };\n hook.revision++;\n\n return () => {\n if (window.__WEBINY_DEVTOOLS_HOOK__) {\n delete window.__WEBINY_DEVTOOLS_HOOK__.sections[name];\n window.__WEBINY_DEVTOOLS_HOOK__.revision++;\n }\n };\n }, [name, dataKey, group, Array.isArray(views) ? views.join(\",\") : views]);\n\n return null;\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value, (_key, v) => {\n if (typeof v === \"function\") {\n return `[Function: ${v.name || \"anonymous\"}]`;\n }\n if (typeof v === \"undefined\") {\n return \"[undefined]\";\n }\n return v;\n });\n } catch {\n return String(value);\n }\n}\n"],"mappings":"AAAA,SAASA,SAAS,QAAQ,OAAO;AACjC,SAASC,OAAO;AA6BhB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,eAAeA,CAAC;EAAEC,IAAI;EAAEC,IAAI;EAAEC,KAAK;EAAEC;AAA4B,CAAC,EAAE;EAChF;EACA;EACA;EACA,MAAMC,OAAO,GAAGC,aAAa,CAACJ,IAAI,CAAC;EAEnCJ,SAAS,CAAC,MAAM;IACZ,IAAIS,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,aAAa,EAAE;MACxC;IACJ;IAEA,MAAMC,eAA+B,GAAGN,KAAK,GACvCO,KAAK,CAACC,OAAO,CAACR,KAAK,CAAC,GAChBA,KAAK,GACL,CAACA,KAAK,CAAC,GACX,CAAC,QAAQ,EAAE,KAAK,CAAC;IAEvB,IAAIS,SAAkB;IACtB,IAAI;MACAA,SAAS,GAAGC,IAAI,CAACC,KAAK,CAACV,OAAO,CAAC;IACnC,CAAC,CAAC,MAAM;MACJQ,SAAS,GAAGX,IAAI;IACpB;IAEA,MAAMc,IAAI,GAAGjB,OAAO,CAAC,CAAC;IACtBiB,IAAI,CAACC,QAAQ,CAAChB,IAAI,CAAC,GAAG;MAClBC,IAAI,EAAEW,SAAS;MACfV,KAAK,EAAEA,KAAK,IAAI,UAAU;MAC1BC,KAAK,EAAEM,eAAe;MACtBQ,SAAS,EAAEC,IAAI,CAACC,GAAG,CAAC;IACxB,CAAC;IACDJ,IAAI,CAACK,QAAQ,EAAE;IAEf,OAAO,MAAM;MACT,IAAIC,MAAM,CAACC,wBAAwB,EAAE;QACjC,OAAOD,MAAM,CAACC,wBAAwB,CAACN,QAAQ,CAAChB,IAAI,CAAC;QACrDqB,MAAM,CAACC,wBAAwB,CAACF,QAAQ,EAAE;MAC9C;IACJ,CAAC;EACL,CAAC,EAAE,CAACpB,IAAI,EAAEI,OAAO,EAAEF,KAAK,EAAEQ,KAAK,CAACC,OAAO,CAACR,KAAK,CAAC,GAAGA,KAAK,CAACoB,IAAI,CAAC,GAAG,CAAC,GAAGpB,KAAK,CAAC,CAAC;EAE1E,OAAO,IAAI;AACf;AAEA,SAASE,aAAaA,CAACmB,KAAc,EAAU;EAC3C,IAAI;IACA,OAAOX,IAAI,CAACY,SAAS,CAACD,KAAK,EAAE,CAACE,IAAI,EAAEC,CAAC,KAAK;MACtC,IAAI,OAAOA,CAAC,KAAK,UAAU,EAAE;QACzB,OAAO,cAAcA,CAAC,CAAC3B,IAAI,IAAI,WAAW,GAAG;MACjD;MACA,IAAI,OAAO2B,CAAC,KAAK,WAAW,EAAE;QAC1B,OAAO,aAAa;MACxB;MACA,OAAOA,CAAC;IACZ,CAAC,CAAC;EACN,CAAC,CAAC,MAAM;IACJ,OAAOC,MAAM,CAACJ,KAAK,CAAC;EACxB;AACJ","ignoreList":[]}
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;
@@ -34,6 +36,7 @@ interface PropertiesProps {
34
36
  }
35
37
  export declare const Properties: ({ name, onChange, children }: PropertiesProps) => React.JSX.Element;
36
38
  export declare function useProperties(): PropertiesContext;
39
+ export declare function useMaybeProperties(): PropertiesContext | undefined;
37
40
  export declare function useAncestorByName(name: string | undefined): PropertiesContext | undefined;
38
41
  interface PropertyProps {
39
42
  id?: string;
package/Properties.js CHANGED
@@ -1,5 +1,7 @@
1
- import React, { createContext, useContext, useEffect, useMemo, useState } from "react";
2
- import { getUniqueId, toObject } from "./utils";
1
+ import React, { createContext, useContext, useEffect, useMemo, useRef } from "react";
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,61 +49,36 @@ 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;
74
+ }
75
+ export function useMaybeProperties() {
76
+ return useContext(PropertiesContext);
126
77
  }
127
78
  export function useAncestorByName(name) {
128
- const parent = useProperties();
79
+ const parent = useMaybeProperties();
129
80
  return useMemo(() => {
130
- if (!name) {
81
+ if (!name || !parent) {
131
82
  return undefined;
132
83
  }
133
84
  if (parent.name === name) {
@@ -143,14 +94,15 @@ export function useParentProperty() {
143
94
  export function useAncestor(params) {
144
95
  const property = useParentProperty();
145
96
  const {
146
- properties
97
+ store
147
98
  } = useProperties();
148
99
  const matchOrGetAncestor = (property, params) => {
149
- 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]);
150
102
  if (matchedProps.length === Object.keys(params).length) {
151
103
  return property;
152
104
  }
153
- const newParent = property.parent ? properties.find(prop => prop.id === property.parent) : undefined;
105
+ const newParent = property.parent ? store.getById(property.parent) : undefined;
154
106
  return newParent ? matchOrGetAncestor(newParent, params) : undefined;
155
107
  };
156
108
  return property ? matchOrGetAncestor(property, params) : undefined;
@@ -173,14 +125,17 @@ export const Property = ({
173
125
  const parentProperty = useParentProperty();
174
126
  const immediateProperties = useProperties();
175
127
  const ancestorByName = useAncestorByName(targetName);
176
- const properties = targetName ? ancestorByName : immediateProperties;
128
+ const previousValue = useRef(value);
129
+ const priority = usePropertyPriority();
130
+ const properties = targetName && ancestorByName ? ancestorByName : immediateProperties;
177
131
  if (!properties) {
178
132
  throw Error("<Properties> provider is missing higher in the hierarchy!");
179
133
  }
180
134
  const {
181
135
  addProperty,
182
136
  removeProperty,
183
- replaceProperty
137
+ replaceProperty,
138
+ store: propertyStore
184
139
  } = properties;
185
140
  const parentId = parent ? parent : root ? "" : parentProperty?.id || "";
186
141
  const property = {
@@ -190,6 +145,11 @@ export const Property = ({
190
145
  parent: parentId,
191
146
  array
192
147
  };
148
+
149
+ // Register in the synchronous lookup during render so useAncestor can find this property.
150
+ if (!remove) {
151
+ propertyStore.registerLookup(property);
152
+ }
193
153
  useEffect(() => {
194
154
  if (remove) {
195
155
  removeProperty(uniqueId);
@@ -207,12 +167,21 @@ export const Property = ({
207
167
  $isLast
208
168
  }, {
209
169
  after,
210
- before
170
+ before,
171
+ priority
211
172
  });
212
173
  return () => {
213
174
  removeProperty(uniqueId);
214
175
  };
215
176
  }, []);
177
+ useEffect(() => {
178
+ if (previousValue.current !== value) {
179
+ previousValue.current = value;
180
+ if (!remove && !replace) {
181
+ replaceProperty(uniqueId, property);
182
+ }
183
+ }
184
+ }, [value]);
216
185
  if (children) {
217
186
  return /*#__PURE__*/React.createElement(PropertyContext.Provider, {
218
187
  value: property
package/Properties.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["React","createContext","useContext","useEffect","useMemo","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","useAncestorByName","PropertyContext","useParentProperty","useAncestor","params","matchOrGetAncestor","matchedProps","Object","keys","newParent","find","Property","replace","remove","array","root","targetName","uniqueId","parentProperty","immediateProperties","ancestorByName","parentId","$isFirst","$isLast"],"sources":["Properties.tsx"],"sourcesContent":["import React, { createContext, useContext, useEffect, useMemo, useState } from \"react\";\nimport { getUniqueId, toObject } from \"./utils\";\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 useAncestorByName(name: string | undefined) {\n const parent = useProperties();\n\n return useMemo(() => {\n if (!name) {\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\n const properties = targetName ? 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 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,QAAQ,QAAQ,OAAO;AACtF,SAASC,WAAW,EAAEC,QAAQ;AAE9B,MAAMC,uBAAuB,gBAAGP,aAAa,CAAqBQ,SAAS,CAAC;AAO5E,OAAO,MAAMC,mBAAmB,GAAGA,CAAC;EAAEC,IAAI;EAAEC;AAAmC,CAAC,KAAK;EACjF,oBACIZ,KAAA,CAAAa,aAAA,CAACL,uBAAuB,CAACM,QAAQ;IAACC,KAAK,EAAEJ;EAAK,GAAEC,QAA2C,CAAC;AAEpG,CAAC;AAYD,SAASI,cAAcA,CAACC,EAAU,EAAEC,UAAsB,EAAc;EACpE,OAAOA,UAAU,CACZC,MAAM,CAACC,IAAI,IAAIA,IAAI,CAACC,MAAM,KAAKJ,EAAE,CAAC,CAClCK,MAAM,CAAC,CAACC,GAAG,EAAEC,IAAI,KAAK;IACnB,OAAOR,cAAc,CACjBQ,IAAI,CAACP,EAAE,EACPM,GAAG,CAACJ,MAAM,CAACC,IAAI,IAAIA,IAAI,CAACH,EAAE,KAAKO,IAAI,CAACP,EAAE,CAC1C,CAAC;EACL,CAAC,EAAEC,UAAU,CAAC;AACtB;AAiBA,SAASO,iBAAiBA,CAACP,UAAsB,EAAEQ,QAAkB,EAAEC,MAAc,EAAE;EACnF,MAAMC,aAAa,GAAGV,UAAU,CAACW,SAAS,CAACT,IAAI,IAAIA,IAAI,CAACH,EAAE,KAAKS,QAAQ,CAACT,EAAE,CAAC;EAC3E,IAAIW,aAAa,GAAG,CAAC,CAAC,EAAE;IACpB,MAAME,gBAAgB,GAAGZ,UAAU,CAACU,aAAa,CAAC;IAClD,MAAMG,aAAa,GAAGb,UAAU,CAACC,MAAM,CAACa,CAAC,IAAIA,CAAC,CAACf,EAAE,KAAKS,QAAQ,CAACT,EAAE,CAAC;IAClE,MAAMgB,WAAW,GAAGN,MAAM,CAACO,QAAQ,CAAC,QAAQ,CAAC,GACvC,CAAC,GACDH,aAAa,CAACF,SAAS,CAACT,IAAI,IAAIA,IAAI,CAACH,EAAE,KAAKU,MAAM,CAAC;IACzD,OAAO,CACH,GAAGI,aAAa,CAACI,KAAK,CAAC,CAAC,EAAEF,WAAW,CAAC,EACtCH,gBAAgB,EAChB,GAAGC,aAAa,CAACI,KAAK,CAACF,WAAW,CAAC,CACtC;EACL;EAEA,MAAMA,WAAW,GAAGf,UAAU,CAACW,SAAS,CAACT,IAAI,IAAIA,IAAI,CAACH,EAAE,KAAKU,MAAM,CAAC;EAEpE,OAAO,CAAC,GAAGT,UAAU,CAACiB,KAAK,CAAC,CAAC,EAAEF,WAAW,CAAC,EAAEP,QAAQ,EAAE,GAAGR,UAAU,CAACiB,KAAK,CAACF,WAAW,CAAC,CAAC;AAC5F;AAEA,SAASG,gBAAgBA,CAAClB,UAAsB,EAAEQ,QAAkB,EAAEW,KAAa,EAAE;EACjF,MAAMT,aAAa,GAAGV,UAAU,CAACW,SAAS,CAACT,IAAI,IAAIA,IAAI,CAACH,EAAE,KAAKS,QAAQ,CAACT,EAAE,CAAC;EAE3E,IAAIW,aAAa,GAAG,CAAC,CAAC,EAAE;IACpB,MAAM,CAACU,eAAe,CAAC,GAAGpB,UAAU,CAACqB,MAAM,CAACX,aAAa,EAAE,CAAC,CAAC;IAC7D,MAAMK,WAAW,GAAGI,KAAK,CAACH,QAAQ,CAAC,OAAO,CAAC,GACrChB,UAAU,CAACsB,MAAM,GAAG,CAAC,GACrBtB,UAAU,CAACW,SAAS,CAACT,IAAI,IAAIA,IAAI,CAACH,EAAE,KAAKoB,KAAK,CAAC;IACrD,OAAO,CACH,GAAGnB,UAAU,CAACiB,KAAK,CAAC,CAAC,EAAEF,WAAW,GAAG,CAAC,CAAC,EACvCK,eAAe,EACf,GAAGpB,UAAU,CAACiB,KAAK,CAACF,WAAW,GAAG,CAAC,CAAC,CACvC;EACL;EAEA,MAAMA,WAAW,GAAGf,UAAU,CAACW,SAAS,CAACT,IAAI,IAAIA,IAAI,CAACH,EAAE,KAAKoB,KAAK,CAAC;EAEnE,OAAO,CACH,GAAGnB,UAAU,CAACiB,KAAK,CAAC,CAAC,EAAEF,WAAW,GAAG,CAAC,CAAC,EACvCP,QAAQ,EACR,GAAGR,UAAU,CAACiB,KAAK,CAACF,WAAW,GAAG,CAAC,CAAC,CACvC;AACL;AAEA,SAASQ,aAAaA,CAACvB,UAAsB,EAAEQ,QAAkB,EAAE;EAC/D,MAAMgB,KAAK,GAAGxB,UAAU,CAACW,SAAS,CAACT,IAAI,IAAIA,IAAI,CAACH,EAAE,KAAKS,QAAQ,CAACT,EAAE,CAAC;EACnE,IAAIyB,KAAK,GAAG,CAAC,CAAC,EAAE;IACZ,OAAO,CACH,GAAGxB,UAAU,CAACiB,KAAK,CAAC,CAAC,EAAEO,KAAK,CAAC,EAC7B;MAAE,GAAGxB,UAAU,CAACwB,KAAK,CAAC;MAAE,GAAGhB;IAAS,CAAC,EACrC,GAAGR,UAAU,CAACiB,KAAK,CAACO,KAAK,GAAG,CAAC,CAAC,CACjC;EACL;EACA,OAAOxB,UAAU;AACrB;AAEA,MAAMyB,iBAAiB,gBAAG1C,aAAa,CAAgCQ,SAAS,CAAC;AAQjF,OAAO,MAAMmC,UAAU,GAAGA,CAAC;EAAEjC,IAAI;EAAEkC,QAAQ;EAAEjC;AAA0B,CAAC,KAAK;EACzE,MAAM,CAACM,UAAU,EAAE4B,aAAa,CAAC,GAAGzC,QAAQ,CAAa,EAAE,CAAC;EAC5D,IAAIgB,MAAyB;EAE7B,IAAI;IACAA,MAAM,GAAG0B,aAAa,CAAC,CAAC;EAC5B,CAAC,CAAC,MAAM;IACJ;EAAA;EAGJ5C,SAAS,CAAC,MAAM;IACZ,IAAI0C,QAAQ,EAAE;MACVA,QAAQ,CAAC3B,UAAU,CAAC;IACxB;EACJ,CAAC,EAAE,CAACA,UAAU,CAAC,CAAC;EAEhB,MAAM8B,OAA0B,GAAG5C,OAAO,CACtC,OAAO;IACHO,IAAI;IACJO,UAAU;IACV+B,WAAWA,CAACC,YAAoB,EAAE;MAC9B,IAAI,CAAC7B,MAAM,EAAE;QACT,OAAOZ,SAAS;MACpB;MAEA,OAAOY,MAAM,IAAIA,MAAM,CAACV,IAAI,KAAKuC,YAAY,GACvC7B,MAAM,GACNA,MAAM,CAAC4B,WAAW,CAACC,YAAY,CAAC;IAC1C,CAAC;IACDC,SAASA,CAAA,EAAM;MACX,OAAO5C,QAAQ,CAACW,UAAU,CAAC;IAC/B,CAAC;IACDkC,WAAWA,CAAC1B,QAAQ,EAAE2B,OAAO,GAAG,CAAC,CAAC,EAAE;MAChCP,aAAa,CAAC5B,UAAU,IAAI;QACxB,MAAMwB,KAAK,GAAGxB,UAAU,CAACW,SAAS,CAACT,IAAI,IAAIA,IAAI,CAACH,EAAE,KAAKS,QAAQ,CAACT,EAAE,CAAC;QAEnE,IAAIyB,KAAK,GAAG,CAAC,CAAC,EAAE;UACZ,MAAMX,aAAa,GAAGU,aAAa,CAACvB,UAAU,EAAEQ,QAAQ,CAAC;UACzD,IAAI2B,OAAO,CAAChB,KAAK,EAAE;YACf,OAAOD,gBAAgB,CAACL,aAAa,EAAEL,QAAQ,EAAE2B,OAAO,CAAChB,KAAK,CAAC;UACnE;UACA,IAAIgB,OAAO,CAAC1B,MAAM,EAAE;YAChB,OAAOF,iBAAiB,CAACM,aAAa,EAAEL,QAAQ,EAAE2B,OAAO,CAAC1B,MAAM,CAAC;UACrE;UAEA,OAAOI,aAAa;QACxB;QAEA,IAAIsB,OAAO,CAAChB,KAAK,EAAE;UACf,OAAOD,gBAAgB,CAAClB,UAAU,EAAEQ,QAAQ,EAAE2B,OAAO,CAAChB,KAAK,CAAC;QAChE;QAEA,IAAIgB,OAAO,CAAC1B,MAAM,EAAE;UAChB,OAAOF,iBAAiB,CAACP,UAAU,EAAEQ,QAAQ,EAAE2B,OAAO,CAAC1B,MAAM,CAAC;QAClE;QAEA,OAAO,CAAC,GAAGT,UAAU,EAAEQ,QAAQ,CAAC;MACpC,CAAC,CAAC;IACN,CAAC;IACD4B,cAAcA,CAACrC,EAAE,EAAE;MACf6B,aAAa,CAAC5B,UAAU,IAAI;QACxB,OAAOF,cAAc,CACjBC,EAAE,EACFC,UAAU,CAACC,MAAM,CAACC,IAAI,IAAIA,IAAI,CAACH,EAAE,KAAKA,EAAE,CAC5C,CAAC;MACL,CAAC,CAAC;IACN,CAAC;IACDsC,eAAeA,CAACtC,EAAE,EAAES,QAAQ,EAAE;MAC1BoB,aAAa,CAAC5B,UAAU,IAAI;QACxB,MAAMsC,SAAS,GAAGtC,UAAU,CAACW,SAAS,CAACT,IAAI,IAAIA,IAAI,CAACH,EAAE,KAAKA,EAAE,CAAC;QAE9D,IAAIuC,SAAS,GAAG,CAAC,CAAC,EAAE;UAChB;UACA,OAAOxC,cAAc,CAACC,EAAE,EAAE,CACtB,GAAGC,UAAU,CAACiB,KAAK,CAAC,CAAC,EAAEqB,SAAS,CAAC,EACjC9B,QAAQ,EACR,GAAGR,UAAU,CAACiB,KAAK,CAACqB,SAAS,GAAG,CAAC,CAAC,CACrC,CAAC;QACN;QACA,OAAOtC,UAAU;MACrB,CAAC,CAAC;IACN;EACJ,CAAC,CAAC,EACF,CAACA,UAAU,CACf,CAAC;EAED,oBAAOlB,KAAA,CAAAa,aAAA,CAAC8B,iBAAiB,CAAC7B,QAAQ;IAACC,KAAK,EAAEiC;EAAQ,GAAEpC,QAAqC,CAAC;AAC9F,CAAC;AAED,OAAO,SAASmC,aAAaA,CAAA,EAAG;EAC5B,MAAM7B,UAAU,GAAGhB,UAAU,CAACyC,iBAAiB,CAAC;EAChD,IAAI,CAACzB,UAAU,EAAE;IACb,MAAMuC,KAAK,CAAC,yCAAyC,CAAC;EAC1D;EAEA,OAAOvC,UAAU;AACrB;AAEA,OAAO,SAASwC,iBAAiBA,CAAC/C,IAAwB,EAAE;EACxD,MAAMU,MAAM,GAAG0B,aAAa,CAAC,CAAC;EAE9B,OAAO3C,OAAO,CAAC,MAAM;IACjB,IAAI,CAACO,IAAI,EAAE;MACP,OAAOF,SAAS;IACpB;IAEA,IAAIY,MAAM,CAACV,IAAI,KAAKA,IAAI,EAAE;MACtB,OAAOU,MAAM;IACjB;IAEA,OAAOA,MAAM,CAAC4B,WAAW,CAACtC,IAAI,CAAC;EACnC,CAAC,EAAE,CAACA,IAAI,CAAC,CAAC;AACd;AAgBA,MAAMgD,eAAe,gBAAG1D,aAAa,CAAuBQ,SAAS,CAAC;AAEtE,OAAO,SAASmD,iBAAiBA,CAAA,EAAG;EAChC,OAAO1D,UAAU,CAACyD,eAAe,CAAC;AACtC;AAMA,OAAO,SAASE,WAAWA,CAACC,MAAqB,EAAE;EAC/C,MAAMpC,QAAQ,GAAGkC,iBAAiB,CAAC,CAAC;EACpC,MAAM;IAAE1C;EAAW,CAAC,GAAG6B,aAAa,CAAC,CAAC;EAEtC,MAAMgB,kBAAkB,GAAGA,CACvBrC,QAAkB,EAClBoC,MAAqB,KACE;IACvB,MAAME,YAAY,GAAG9C,UAAU,CAC1BC,MAAM,CAACC,IAAI,IAAIA,IAAI,CAACC,MAAM,KAAKK,QAAQ,CAACT,EAAE,CAAC,CAC3CE,MAAM,CAACC,IAAI,IAAIA,IAAI,CAACT,IAAI,IAAImD,MAAM,IAAI1C,IAAI,CAACL,KAAK,KAAK+C,MAAM,CAAC1C,IAAI,CAACT,IAAI,CAAC,CAAC;IAE5E,IAAIqD,YAAY,CAACxB,MAAM,KAAKyB,MAAM,CAACC,IAAI,CAACJ,MAAM,CAAC,CAACtB,MAAM,EAAE;MACpD,OAAOd,QAAQ;IACnB;IAEA,MAAMyC,SAAS,GAAGzC,QAAQ,CAACL,MAAM,GAC3BH,UAAU,CAACkD,IAAI,CAAChD,IAAI,IAAIA,IAAI,CAACH,EAAE,KAAKS,QAAQ,CAACL,MAAM,CAAC,GACpDZ,SAAS;IAEf,OAAO0D,SAAS,GAAGJ,kBAAkB,CAACI,SAAS,EAAEL,MAAM,CAAC,GAAGrD,SAAS;EACxE,CAAC;EAED,OAAOiB,QAAQ,GAAGqC,kBAAkB,CAACrC,QAAQ,EAAEoC,MAAM,CAAC,GAAGrD,SAAS;AACtE;AAEA,OAAO,MAAM4D,QAAQ,GAAGA,CAAC;EACrBpD,EAAE;EACFN,IAAI;EACJI,KAAK;EACLH,QAAQ;EACRyB,KAAK,GAAG5B,SAAS;EACjBkB,MAAM,GAAGlB,SAAS;EAClB6D,OAAO,GAAG7D,SAAS;EACnB8D,MAAM,GAAG,KAAK;EACdC,KAAK,GAAG,KAAK;EACbC,IAAI,GAAG,KAAK;EACZpD,MAAM,GAAGZ;AACE,CAAC,KAAK;EACjB,MAAMiE,UAAU,GAAGxE,UAAU,CAACM,uBAAuB,CAAC;EACtD,MAAMmE,QAAQ,GAAGvE,OAAO,CAAC,MAAMa,EAAE,IAAIX,WAAW,CAAC,CAAC,EAAE,EAAE,CAAC;EACvD,MAAMsE,cAAc,GAAGhB,iBAAiB,CAAC,CAAC;EAC1C,MAAMiB,mBAAmB,GAAG9B,aAAa,CAAC,CAAC;EAC3C,MAAM+B,cAAc,GAAGpB,iBAAiB,CAACgB,UAAU,CAAC;EAEpD,MAAMxD,UAAU,GAAGwD,UAAU,GAAGI,cAAc,GAAGD,mBAAmB;EAEpE,IAAI,CAAC3D,UAAU,EAAE;IACb,MAAMuC,KAAK,CAAC,2DAA2D,CAAC;EAC5E;EAEA,MAAM;IAAEL,WAAW;IAAEE,cAAc;IAAEC;EAAgB,CAAC,GAAGrC,UAAU;EACnE,MAAM6D,QAAQ,GAAG1D,MAAM,GAAGA,MAAM,GAAGoD,IAAI,GAAG,EAAE,GAAGG,cAAc,EAAE3D,EAAE,IAAI,EAAE;EACvE,MAAMS,QAAQ,GAAG;IAAET,EAAE,EAAE0D,QAAQ;IAAEhE,IAAI;IAAEI,KAAK;IAAEM,MAAM,EAAE0D,QAAQ;IAAEP;EAAM,CAAC;EAEvErE,SAAS,CAAC,MAAM;IACZ,IAAIoE,MAAM,EAAE;MACRjB,cAAc,CAACqB,QAAQ,CAAC;MACxB;IACJ;IAEA,IAAIL,OAAO,EAAE;MACTf,eAAe,CAACe,OAAO,EAAE5C,QAAQ,CAAC;MAClC;IACJ;IAEA,MAAMsD,QAAQ,GAAGrD,MAAM,KAAK,QAAQ;IACpC,MAAMsD,OAAO,GAAG5C,KAAK,KAAK,OAAO;IAEjCe,WAAW,CAAC;MAAE,GAAG1B,QAAQ;MAAEsD,QAAQ;MAAEC;IAAQ,CAAC,EAAE;MAAE5C,KAAK;MAAEV;IAAO,CAAC,CAAC;IAElE,OAAO,MAAM;MACT2B,cAAc,CAACqB,QAAQ,CAAC;IAC5B,CAAC;EACL,CAAC,EAAE,EAAE,CAAC;EAEN,IAAI/D,QAAQ,EAAE;IACV,oBAAOZ,KAAA,CAAAa,aAAA,CAAC8C,eAAe,CAAC7C,QAAQ;MAACC,KAAK,EAAEW;IAAS,GAAEd,QAAmC,CAAC;EAC3F;EAEA,OAAO,IAAI;AACf,CAAC","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":"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","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":[]}
package/README.md CHANGED
@@ -1,65 +1,11 @@
1
- # React Properties
1
+ # @webiny/react-properties
2
2
 
3
- [![](https://img.shields.io/npm/dw/@webiny/react-properties.svg)](https://www.npmjs.com/package/@webiny/react-properties)
4
- [![](https://img.shields.io/npm/v/@webiny/react-properties.svg)](https://www.npmjs.com/package/@webiny/react-properties)
5
- [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
6
- [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
3
+ > [!NOTE]
4
+ > This package is part of the [Webiny](https://www.webiny.com) monorepo.
5
+ > It’s **included in every Webiny project by default** and is not meant to be used as a standalone package.
7
6
 
8
- A tiny React properties framework, to build dynamic data objects using React components, which can be customized after initial creation. The usage is very similar to how you write XML data structures, but in this case you're using actual React.
7
+ 📘 **Documentation:** [https://www.webiny.com/docs](https://www.webiny.com/docs)
9
8
 
10
- ## Basic Example
9
+ ---
11
10
 
12
- ```jsx
13
- import React, { useCallback } from "react";
14
- import { Properties, Property, toObject } from "@webiny/react-properties";
15
-
16
- const View = () => {
17
- const onChange = useCallback(properties => {
18
- console.log(toObject(properties));
19
- }, []);
20
-
21
- return (
22
- <Properties onChange={onChange}>
23
- <Property name={"group"}>
24
- <Property name={"name"} value={"layout"} />
25
- <Property name={"label"} value={"Layout"} />
26
- <Property name={"toolbar"}>
27
- <Property name={"name"} value={"basic"} />
28
- </Property>
29
- </Property>
30
- <Property name={"group"}>
31
- <Property name={"name"} value={"heroes"} />
32
- <Property name={"label"} value={"Heroes"} />
33
- <Property name={"toolbar"}>
34
- <Property name={"name"} value={"heroes"} />
35
- </Property>
36
- </Property>
37
- </Properties>
38
- );
39
- };
40
- ```
41
-
42
- Output:
43
-
44
- ```json
45
- {
46
- "group": [
47
- {
48
- "name": "layout",
49
- "label": "Layout",
50
- "toolbar": {
51
- "name": "basic"
52
- }
53
- },
54
- {
55
- "name": "heroes",
56
- "label": "Heroes",
57
- "toolbar": {
58
- "name": "heroes"
59
- }
60
- }
61
- ]
62
- }
63
- ```
64
-
65
- For more examples, check out the test files.
11
+ _This README file is automatically generated during the publish process._
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { Property } from "./index";
2
+ import type { Property } from "./index.js";
3
3
  export interface WithConfigProps {
4
4
  children: React.ReactNode;
5
5
  onProperties?(properties: Property[]): void;