@webiny/react-properties 6.3.0 → 6.4.0-beta.1

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.
@@ -1,70 +1,54 @@
1
1
  import { useEffect } from "react";
2
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;
3
+ function DevToolsSection({ name, data, group, views }) {
4
+ const dataKey = safeStringify(data);
5
+ useEffect(()=>{
6
+ if ("development" !== process.env.NODE_ENV) return;
7
+ const normalizedViews = views ? Array.isArray(views) ? views : [
8
+ views
9
+ ] : [
10
+ "browse",
11
+ "raw"
12
+ ];
13
+ let plainData;
14
+ try {
15
+ plainData = JSON.parse(dataKey);
16
+ } catch {
17
+ plainData = data;
18
+ }
19
+ const hook = getHook();
20
+ hook.sections[name] = {
21
+ data: plainData,
22
+ group: group || "Sections",
23
+ views: normalizedViews,
24
+ updatedAt: Date.now()
25
+ };
26
+ hook.revision++;
27
+ return ()=>{
28
+ if (window.__WEBINY_DEVTOOLS_HOOK__) {
29
+ delete window.__WEBINY_DEVTOOLS_HOOK__.sections[name];
30
+ window.__WEBINY_DEVTOOLS_HOOK__.revision++;
31
+ }
32
+ };
33
+ }, [
34
+ name,
35
+ dataKey,
36
+ group,
37
+ Array.isArray(views) ? views.join(",") : views
38
+ ]);
39
+ return null;
53
40
  }
54
41
  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
- }
42
+ try {
43
+ return JSON.stringify(value, (_key, v)=>{
44
+ if ("function" == typeof v) return `[Function: ${v.name || "anonymous"}]`;
45
+ if (void 0 === v) return "[undefined]";
46
+ return v;
47
+ });
48
+ } catch {
49
+ return String(value);
50
+ }
68
51
  }
52
+ export { DevToolsSection };
69
53
 
70
54
  //# sourceMappingURL=DevToolsSection.js.map
@@ -1 +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":[]}
1
+ {"version":3,"file":"DevToolsSection.js","sources":["../src/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"],"names":["DevToolsSection","name","data","group","views","dataKey","safeStringify","useEffect","process","normalizedViews","Array","plainData","JSON","hook","getHook","Date","window","value","_key","v","String"],"mappings":";;AA2CO,SAASA,gBAAgB,EAAEC,IAAI,EAAEC,IAAI,EAAEC,KAAK,EAAEC,KAAK,EAAwB;IAI9E,MAAMC,UAAUC,cAAcJ;IAE9BK,UAAU;QACN,IAAIC,AAAyB,kBAAzBA,QAAQ,GAAG,CAAC,QAAQ,EACpB;QAGJ,MAAMC,kBAAkCL,QAClCM,MAAM,OAAO,CAACN,SACVA,QACA;YAACA;SAAM,GACX;YAAC;YAAU;SAAM;QAEvB,IAAIO;QACJ,IAAI;YACAA,YAAYC,KAAK,KAAK,CAACP;QAC3B,EAAE,OAAM;YACJM,YAAYT;QAChB;QAEA,MAAMW,OAAOC;QACbD,KAAK,QAAQ,CAACZ,KAAK,GAAG;YAClB,MAAMU;YACN,OAAOR,SAAS;YAChB,OAAOM;YACP,WAAWM,KAAK,GAAG;QACvB;QACAF,KAAK,QAAQ;QAEb,OAAO;YACH,IAAIG,OAAO,wBAAwB,EAAE;gBACjC,OAAOA,OAAO,wBAAwB,CAAC,QAAQ,CAACf,KAAK;gBACrDe,OAAO,wBAAwB,CAAC,QAAQ;YAC5C;QACJ;IACJ,GAAG;QAACf;QAAMI;QAASF;QAAOO,MAAM,OAAO,CAACN,SAASA,MAAM,IAAI,CAAC,OAAOA;KAAM;IAEzE,OAAO;AACX;AAEA,SAASE,cAAcW,KAAc;IACjC,IAAI;QACA,OAAOL,KAAK,SAAS,CAACK,OAAO,CAACC,MAAMC;YAChC,IAAI,AAAa,cAAb,OAAOA,GACP,OAAO,CAAC,WAAW,EAAEA,EAAE,IAAI,IAAI,YAAY,CAAC,CAAC;YAEjD,IAAI,AAAa,WAANA,GACP,OAAO;YAEX,OAAOA;QACX;IACJ,EAAE,OAAM;QACJ,OAAOC,OAAOH;IAClB;AACJ"}
package/Properties.js CHANGED
@@ -1,193 +1,140 @@
1
- import React, { createContext, useContext, useEffect, useMemo, useRef } from "react";
1
+ import react, { createContext, useContext, useEffect, useMemo, useRef } from "react";
2
2
  import { getUniqueId, toObject } from "./utils.js";
3
3
  import { PropertyStore } from "./domain/index.js";
4
4
  import { usePropertyPriority } from "./PropertyPriority.js";
5
- const PropertiesTargetContext = /*#__PURE__*/createContext(undefined);
6
- export const ConnectToProperties = ({
7
- name,
8
- children
9
- }) => {
10
- return /*#__PURE__*/React.createElement(PropertiesTargetContext.Provider, {
11
- value: name
12
- }, children);
13
- };
14
- const PropertiesContext = /*#__PURE__*/createContext(undefined);
15
- export const Properties = ({
16
- name,
17
- onChange,
18
- children
19
- }) => {
20
- const storeRef = useRef(null);
21
- if (!storeRef.current) {
22
- storeRef.current = new PropertyStore();
23
- }
24
- const store = storeRef.current;
25
- let parent;
26
- try {
27
- parent = useProperties();
28
- } catch {
29
- // Do nothing, if there's no parent.
30
- }
31
- useEffect(() => {
32
- if (!onChange) {
33
- return;
34
- }
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.
42
- const context = useMemo(() => ({
43
- name,
44
- store,
45
- getAncestor(ancestorName) {
46
- if (!parent) {
47
- return undefined;
48
- }
49
- return parent && parent.name === ancestorName ? parent : parent.getAncestor(ancestorName);
50
- },
51
- getObject() {
52
- return toObject(store.allProperties);
53
- },
54
- addProperty(property, options = {}) {
55
- store.addProperty(property, options);
56
- },
57
- removeProperty(id) {
58
- store.removeProperty(id);
59
- },
60
- replaceProperty(id, property) {
61
- store.replaceProperty(id, property);
62
- }
63
- }), [store]);
64
- return /*#__PURE__*/React.createElement(PropertiesContext.Provider, {
65
- value: context
66
- }, children);
5
+ const PropertiesTargetContext = /*#__PURE__*/ createContext(void 0);
6
+ const ConnectToProperties = ({ name, children })=>/*#__PURE__*/ react.createElement(PropertiesTargetContext.Provider, {
7
+ value: name
8
+ }, children);
9
+ const PropertiesContext = /*#__PURE__*/ createContext(void 0);
10
+ const Properties = ({ name, onChange, children })=>{
11
+ const storeRef = useRef(null);
12
+ if (!storeRef.current) storeRef.current = new PropertyStore();
13
+ const store = storeRef.current;
14
+ let parent;
15
+ try {
16
+ parent = useProperties();
17
+ } catch {}
18
+ useEffect(()=>{
19
+ if (!onChange) return;
20
+ return store.subscribe((properties)=>{
21
+ onChange(properties);
22
+ });
23
+ }, [
24
+ store,
25
+ onChange
26
+ ]);
27
+ const context = useMemo(()=>({
28
+ name,
29
+ store,
30
+ getAncestor (ancestorName) {
31
+ if (!parent) return;
32
+ return parent && parent.name === ancestorName ? parent : parent.getAncestor(ancestorName);
33
+ },
34
+ getObject () {
35
+ return toObject(store.allProperties);
36
+ },
37
+ addProperty (property, options = {}) {
38
+ store.addProperty(property, options);
39
+ },
40
+ removeProperty (id) {
41
+ store.removeProperty(id);
42
+ },
43
+ replaceProperty (id, property) {
44
+ store.replaceProperty(id, property);
45
+ }
46
+ }), [
47
+ store
48
+ ]);
49
+ return /*#__PURE__*/ react.createElement(PropertiesContext.Provider, {
50
+ value: context
51
+ }, children);
67
52
  };
68
- export function useProperties() {
69
- const context = useContext(PropertiesContext);
70
- if (!context) {
71
- throw Error("Properties context provider is missing!");
72
- }
73
- return context;
53
+ function useProperties() {
54
+ const context = useContext(PropertiesContext);
55
+ if (!context) throw Error("Properties context provider is missing!");
56
+ return context;
74
57
  }
75
- export function useMaybeProperties() {
76
- return useContext(PropertiesContext);
58
+ function useMaybeProperties() {
59
+ return useContext(PropertiesContext);
77
60
  }
78
- export function useAncestorByName(name) {
79
- const parent = useMaybeProperties();
80
- return useMemo(() => {
81
- if (!name || !parent) {
82
- return undefined;
83
- }
84
- if (parent.name === name) {
85
- return parent;
86
- }
87
- return parent.getAncestor(name);
88
- }, [name]);
61
+ function useAncestorByName(name) {
62
+ const parent = useMaybeProperties();
63
+ return useMemo(()=>{
64
+ if (!name || !parent) return;
65
+ if (parent.name === name) return parent;
66
+ return parent.getAncestor(name);
67
+ }, [
68
+ name
69
+ ]);
89
70
  }
90
- const PropertyContext = /*#__PURE__*/createContext(undefined);
91
- export function useParentProperty() {
92
- return useContext(PropertyContext);
71
+ const PropertyContext = /*#__PURE__*/ createContext(void 0);
72
+ function useParentProperty() {
73
+ return useContext(PropertyContext);
93
74
  }
94
- export function useAncestor(params) {
95
- const property = useParentProperty();
96
- const {
97
- store
98
- } = useProperties();
99
- const matchOrGetAncestor = (property, params) => {
100
- const children = store.getChildrenOf(property.id);
101
- const matchedProps = children.filter(prop => prop.name in params && prop.value === params[prop.name]);
102
- if (matchedProps.length === Object.keys(params).length) {
103
- return property;
104
- }
105
- const newParent = property.parent ? store.getById(property.parent) : undefined;
106
- return newParent ? matchOrGetAncestor(newParent, params) : undefined;
107
- };
108
- return property ? matchOrGetAncestor(property, params) : undefined;
75
+ function useAncestor(params) {
76
+ const property = useParentProperty();
77
+ const { store } = useProperties();
78
+ const matchOrGetAncestor = (property, params)=>{
79
+ const children = store.getChildrenOf(property.id);
80
+ const matchedProps = children.filter((prop)=>prop.name in params && prop.value === params[prop.name]);
81
+ if (matchedProps.length === Object.keys(params).length) return property;
82
+ const newParent = property.parent ? store.getById(property.parent) : void 0;
83
+ return newParent ? matchOrGetAncestor(newParent, params) : void 0;
84
+ };
85
+ return property ? matchOrGetAncestor(property, params) : void 0;
109
86
  }
110
- export const Property = ({
111
- id,
112
- name,
113
- value,
114
- children,
115
- after = undefined,
116
- before = undefined,
117
- replace = undefined,
118
- remove = false,
119
- array = false,
120
- root = false,
121
- parent = undefined
122
- }) => {
123
- const targetName = useContext(PropertiesTargetContext);
124
- const uniqueId = useMemo(() => id || getUniqueId(), []);
125
- const parentProperty = useParentProperty();
126
- const immediateProperties = useProperties();
127
- const ancestorByName = useAncestorByName(targetName);
128
- const previousValue = useRef(value);
129
- const priority = usePropertyPriority();
130
- const properties = targetName && ancestorByName ? ancestorByName : immediateProperties;
131
- if (!properties) {
132
- throw Error("<Properties> provider is missing higher in the hierarchy!");
133
- }
134
- const {
135
- addProperty,
136
- removeProperty,
137
- replaceProperty,
138
- store: propertyStore
139
- } = properties;
140
- const parentId = parent ? parent : root ? "" : parentProperty?.id || "";
141
- const property = {
142
- id: uniqueId,
143
- name,
144
- value,
145
- parent: parentId,
146
- array
147
- };
148
-
149
- // Register in the synchronous lookup during render so useAncestor can find this property.
150
- if (!remove) {
151
- propertyStore.registerLookup(property);
152
- }
153
- useEffect(() => {
154
- if (remove) {
155
- removeProperty(uniqueId);
156
- return;
157
- }
158
- if (replace) {
159
- replaceProperty(replace, property);
160
- return;
161
- }
162
- const $isFirst = before === "$first";
163
- const $isLast = after === "$last";
164
- addProperty({
165
- ...property,
166
- $isFirst,
167
- $isLast
168
- }, {
169
- after,
170
- before,
171
- priority
172
- });
173
- return () => {
174
- removeProperty(uniqueId);
87
+ const Property = ({ id, name, value, children, after, before, replace, remove = false, array = false, root = false, parent })=>{
88
+ const targetName = useContext(PropertiesTargetContext);
89
+ const uniqueId = useMemo(()=>id || getUniqueId(), []);
90
+ const parentProperty = useParentProperty();
91
+ const immediateProperties = useProperties();
92
+ const ancestorByName = useAncestorByName(targetName);
93
+ const previousValue = useRef(value);
94
+ const priority = usePropertyPriority();
95
+ const properties = targetName && ancestorByName ? ancestorByName : immediateProperties;
96
+ if (!properties) throw Error("<Properties> provider is missing higher in the hierarchy!");
97
+ const { addProperty, removeProperty, replaceProperty, store: propertyStore } = properties;
98
+ const parentId = parent ? parent : root ? "" : parentProperty?.id || "";
99
+ const property = {
100
+ id: uniqueId,
101
+ name,
102
+ value,
103
+ parent: parentId,
104
+ array
175
105
  };
176
- }, []);
177
- useEffect(() => {
178
- if (previousValue.current !== value) {
179
- previousValue.current = value;
180
- if (!remove && !replace) {
181
- replaceProperty(uniqueId, property);
182
- }
183
- }
184
- }, [value]);
185
- if (children) {
186
- return /*#__PURE__*/React.createElement(PropertyContext.Provider, {
187
- value: property
106
+ if (!remove) propertyStore.registerLookup(property);
107
+ useEffect(()=>{
108
+ if (remove) return void removeProperty(uniqueId);
109
+ if (replace) return void replaceProperty(replace, property);
110
+ const $isFirst = "$first" === before;
111
+ const $isLast = "$last" === after;
112
+ addProperty({
113
+ ...property,
114
+ $isFirst,
115
+ $isLast
116
+ }, {
117
+ after,
118
+ before,
119
+ priority
120
+ });
121
+ return ()=>{
122
+ removeProperty(uniqueId);
123
+ };
124
+ }, []);
125
+ useEffect(()=>{
126
+ if (previousValue.current !== value) {
127
+ previousValue.current = value;
128
+ if (!remove && !replace) replaceProperty(uniqueId, property);
129
+ }
130
+ }, [
131
+ value
132
+ ]);
133
+ if (children) return /*#__PURE__*/ react.createElement(PropertyContext.Provider, {
134
+ value: property
188
135
  }, children);
189
- }
190
- return null;
136
+ return null;
191
137
  };
138
+ export { ConnectToProperties, Properties, Property, useAncestor, useAncestorByName, useMaybeProperties, useParentProperty, useProperties };
192
139
 
193
140
  //# sourceMappingURL=Properties.js.map
package/Properties.js.map CHANGED
@@ -1 +1 @@
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":[]}
1
+ {"version":3,"file":"Properties.js","sources":["../src/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"],"names":["PropertiesTargetContext","createContext","undefined","ConnectToProperties","name","children","PropertiesContext","Properties","onChange","storeRef","useRef","PropertyStore","store","parent","useProperties","useEffect","properties","context","useMemo","ancestorName","toObject","property","options","id","useContext","Error","useMaybeProperties","useAncestorByName","PropertyContext","useParentProperty","useAncestor","params","matchOrGetAncestor","matchedProps","prop","Object","newParent","Property","value","after","before","replace","remove","array","root","targetName","uniqueId","getUniqueId","parentProperty","immediateProperties","ancestorByName","previousValue","priority","usePropertyPriority","addProperty","removeProperty","replaceProperty","propertyStore","parentId","$isFirst","$isLast"],"mappings":";;;;AAKA,MAAMA,0BAA0B,WAAHA,GAAGC,cAAkCC;AAO3D,MAAMC,sBAAsB,CAAC,EAAEC,IAAI,EAAEC,QAAQ,EAA4B,GACrE,WAAP,GACI,oBAACL,wBAAwB,QAAQ;QAAC,OAAOI;OAAOC;AA8BxD,MAAMC,oBAAoB,WAAHA,GAAGL,cAA6CC;AAQhE,MAAMK,aAAa,CAAC,EAAEH,IAAI,EAAEI,QAAQ,EAAEH,QAAQ,EAAmB;IACpE,MAAMI,WAAWC,OAA6B;IAC9C,IAAI,CAACD,SAAS,OAAO,EACjBA,SAAS,OAAO,GAAG,IAAIE;IAE3B,MAAMC,QAAQH,SAAS,OAAO;IAE9B,IAAII;IAEJ,IAAI;QACAA,SAASC;IACb,EAAE,OAAM,CAER;IAEAC,UAAU;QACN,IAAI,CAACP,UACD;QAGJ,OAAOI,MAAM,SAAS,CAACI,CAAAA;YACnBR,SAASQ;QACb;IACJ,GAAG;QAACJ;QAAOJ;KAAS;IAIpB,MAAMS,UAA6BC,QAC/B,IAAO;YACHd;YACAQ;YACA,aAAYO,YAAoB;gBAC5B,IAAI,CAACN,QACD;gBAGJ,OAAOA,UAAUA,OAAO,IAAI,KAAKM,eAC3BN,SACAA,OAAO,WAAW,CAACM;YAC7B;YACA;gBACI,OAAOC,SAASR,MAAM,aAAa;YACvC;YACA,aAAYS,QAAQ,EAAEC,UAAU,CAAC,CAAC;gBAC9BV,MAAM,WAAW,CAACS,UAAUC;YAChC;YACA,gBAAeC,EAAE;gBACbX,MAAM,cAAc,CAACW;YACzB;YACA,iBAAgBA,EAAE,EAAEF,QAAQ;gBACxBT,MAAM,eAAe,CAACW,IAAIF;YAC9B;QACJ,IACA;QAACT;KAAM;IAGX,OAAO,WAAP,GAAO,oBAACN,kBAAkB,QAAQ;QAAC,OAAOW;OAAUZ;AACxD;AAEO,SAASS;IACZ,MAAMG,UAAUO,WAAWlB;IAC3B,IAAI,CAACW,SACD,MAAMQ,MAAM;IAGhB,OAAOR;AACX;AAEO,SAASS;IACZ,OAAOF,WAAWlB;AACtB;AAEO,SAASqB,kBAAkBvB,IAAwB;IACtD,MAAMS,SAASa;IAEf,OAAOR,QAAQ;QACX,IAAI,CAACd,QAAQ,CAACS,QACV;QAGJ,IAAIA,OAAO,IAAI,KAAKT,MAChB,OAAOS;QAGX,OAAOA,OAAO,WAAW,CAACT;IAC9B,GAAG;QAACA;KAAK;AACb;AAgBA,MAAMwB,kBAAkB,WAAHA,GAAG3B,cAAoCC;AAErD,SAAS2B;IACZ,OAAOL,WAAWI;AACtB;AAMO,SAASE,YAAYC,MAAqB;IAC7C,MAAMV,WAAWQ;IACjB,MAAM,EAAEjB,KAAK,EAAE,GAAGE;IAElB,MAAMkB,qBAAqB,CACvBX,UACAU;QAEA,MAAM1B,WAAWO,MAAM,aAAa,CAACS,SAAS,EAAE;QAChD,MAAMY,eAAe5B,SAAS,MAAM,CAChC6B,CAAAA,OAAQA,KAAK,IAAI,IAAIH,UAAUG,KAAK,KAAK,KAAKH,MAAM,CAACG,KAAK,IAAI,CAAC;QAGnE,IAAID,aAAa,MAAM,KAAKE,OAAO,IAAI,CAACJ,QAAQ,MAAM,EAClD,OAAOV;QAGX,MAAMe,YAAYf,SAAS,MAAM,GAAGT,MAAM,OAAO,CAACS,SAAS,MAAM,IAAInB;QAErE,OAAOkC,YAAYJ,mBAAmBI,WAAWL,UAAU7B;IAC/D;IAEA,OAAOmB,WAAWW,mBAAmBX,UAAUU,UAAU7B;AAC7D;AAEO,MAAMmC,WAAW,CAAC,EACrBd,EAAE,EACFnB,IAAI,EACJkC,KAAK,EACLjC,QAAQ,EACRkC,KAAiB,EACjBC,MAAkB,EAClBC,OAAmB,EACnBC,SAAS,KAAK,EACdC,QAAQ,KAAK,EACbC,OAAO,KAAK,EACZ/B,MAAkB,EACN;IACZ,MAAMgC,aAAarB,WAAWxB;IAC9B,MAAM8C,WAAW5B,QAAQ,IAAMK,MAAMwB,eAAe,EAAE;IACtD,MAAMC,iBAAiBnB;IACvB,MAAMoB,sBAAsBnC;IAC5B,MAAMoC,iBAAiBvB,kBAAkBkB;IACzC,MAAMM,gBAAgBzC,OAAO4B;IAC7B,MAAMc,WAAWC;IAEjB,MAAMrC,aAAa6B,cAAcK,iBAAiBA,iBAAiBD;IAEnE,IAAI,CAACjC,YACD,MAAMS,MAAM;IAGhB,MAAM,EAAE6B,WAAW,EAAEC,cAAc,EAAEC,eAAe,EAAE,OAAOC,aAAa,EAAE,GAAGzC;IAC/E,MAAM0C,WAAW7C,SAASA,SAAS+B,OAAO,KAAKI,gBAAgB,MAAM;IACrE,MAAM3B,WAAW;QAAE,IAAIyB;QAAU1C;QAAMkC;QAAO,QAAQoB;QAAUf;IAAM;IAGtE,IAAI,CAACD,QACDe,cAAc,cAAc,CAACpC;IAGjCN,UAAU;QACN,IAAI2B,QAAQ,YACRa,eAAeT;QAInB,IAAIL,SAAS,YACTe,gBAAgBf,SAASpB;QAI7B,MAAMsC,WAAWnB,AAAW,aAAXA;QACjB,MAAMoB,UAAUrB,AAAU,YAAVA;QAEhBe,YAAY;YAAE,GAAGjC,QAAQ;YAAEsC;YAAUC;QAAQ,GAAG;YAAErB;YAAOC;YAAQY;QAAS;QAE1E,OAAO;YACHG,eAAeT;QACnB;IACJ,GAAG,EAAE;IAEL/B,UAAU;QACN,IAAIoC,cAAc,OAAO,KAAKb,OAAO;YACjCa,cAAc,OAAO,GAAGb;YACxB,IAAI,CAACI,UAAU,CAACD,SACZe,gBAAgBV,UAAUzB;QAElC;IACJ,GAAG;QAACiB;KAAM;IAEV,IAAIjC,UACA,OAAO,WAAP,GAAO,oBAACuB,gBAAgB,QAAQ;QAAC,OAAOP;OAAWhB;IAGvD,OAAO;AACX"}
@@ -1,15 +1,11 @@
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);
1
+ import react, { createContext, useContext } from "react";
2
+ const PropertyPriorityContext = /*#__PURE__*/ createContext(0);
3
+ const PropertyPriorityProvider = ({ priority, children })=>/*#__PURE__*/ react.createElement(PropertyPriorityContext.Provider, {
4
+ value: priority
5
+ }, children);
6
+ function usePropertyPriority() {
7
+ return useContext(PropertyPriorityContext);
13
8
  }
9
+ export { PropertyPriorityProvider, usePropertyPriority };
14
10
 
15
11
  //# sourceMappingURL=PropertyPriority.js.map
@@ -1 +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
+ {"version":3,"file":"PropertyPriority.js","sources":["../src/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"],"names":["PropertyPriorityContext","createContext","PropertyPriorityProvider","priority","children","usePropertyPriority","useContext"],"mappings":";AAEA,MAAMA,0BAA0B,WAAHA,GAAGC,cAAc;AAOvC,MAAMC,2BAA2B,CAAC,EAAEC,QAAQ,EAAEC,QAAQ,EAAiC,GACnF,WAAP,GACI,oBAACJ,wBAAwB,QAAQ;QAAC,OAAOG;OACpCC;AAKN,SAASC;IACZ,OAAOC,WAAWN;AACtB"}