@webiny/react-properties 0.0.0-unstable.085ff6572f → 0.0.0-unstable.0d717d18dd

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,14 @@
1
+ import React from "react";
2
+ import type { Property } from "./Properties.js";
3
+ interface AsyncPropertiesContextValue {
4
+ incrementPending(): void;
5
+ decrementPending(): void;
6
+ }
7
+ export declare function useAsyncProperties(): AsyncPropertiesContextValue | undefined;
8
+ interface AsyncPropertiesProps {
9
+ name?: string;
10
+ onChange?(properties: Property[]): void;
11
+ children: React.ReactNode;
12
+ }
13
+ export declare const AsyncProperties: ({ name, onChange, children }: AsyncPropertiesProps) => React.JSX.Element;
14
+ export {};
@@ -0,0 +1,43 @@
1
+ import react, { createContext, useCallback, useContext, useRef } from "react";
2
+ import { Properties, useProperties } from "./Properties.js";
3
+ const AsyncPropertiesContext = /*#__PURE__*/ createContext(void 0);
4
+ function useAsyncProperties() {
5
+ return useContext(AsyncPropertiesContext);
6
+ }
7
+ const StoreCapture = ({ storeRef, children })=>{
8
+ const { store } = useProperties();
9
+ storeRef.current = store;
10
+ return /*#__PURE__*/ react.createElement(react.Fragment, null, children);
11
+ };
12
+ const AsyncProperties = ({ name, onChange, children })=>{
13
+ const pendingRef = useRef(0);
14
+ const onChangeRef = useRef(onChange);
15
+ onChangeRef.current = onChange;
16
+ const storeRef = useRef(null);
17
+ const interceptedOnChange = useCallback((properties)=>{
18
+ if (pendingRef.current > 0) return;
19
+ onChangeRef.current?.(properties);
20
+ }, []);
21
+ const contextValue = useRef({
22
+ incrementPending () {
23
+ pendingRef.current++;
24
+ },
25
+ decrementPending () {
26
+ pendingRef.current = Math.max(0, pendingRef.current - 1);
27
+ if (0 === pendingRef.current) setTimeout(()=>{
28
+ if (0 === pendingRef.current && storeRef.current) storeRef.current.notify();
29
+ }, 0);
30
+ }
31
+ }).current;
32
+ return /*#__PURE__*/ react.createElement(AsyncPropertiesContext.Provider, {
33
+ value: contextValue
34
+ }, /*#__PURE__*/ react.createElement(Properties, {
35
+ name: name,
36
+ onChange: interceptedOnChange
37
+ }, /*#__PURE__*/ react.createElement(StoreCapture, {
38
+ storeRef: storeRef
39
+ }, children)));
40
+ };
41
+ export { AsyncProperties, useAsyncProperties };
42
+
43
+ //# sourceMappingURL=AsyncProperties.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AsyncProperties.js","sources":["../src/AsyncProperties.tsx"],"sourcesContent":["import React, { createContext, useCallback, useContext, useRef } from \"react\";\nimport { Properties, useProperties } from \"./Properties.js\";\nimport type { Property } from \"./Properties.js\";\nimport type { PropertyStore } from \"./domain/index.js\";\n\ninterface AsyncPropertiesContextValue {\n incrementPending(): void;\n decrementPending(): void;\n}\n\nconst AsyncPropertiesContext = createContext<AsyncPropertiesContextValue | undefined>(undefined);\n\nexport function useAsyncProperties() {\n return useContext(AsyncPropertiesContext);\n}\n\ninterface AsyncPropertiesProps {\n name?: string;\n onChange?(properties: Property[]): void;\n children: React.ReactNode;\n}\n\nconst StoreCapture = ({\n storeRef,\n children\n}: {\n storeRef: React.MutableRefObject<PropertyStore | null>;\n children: React.ReactNode;\n}) => {\n const { store } = useProperties();\n storeRef.current = store;\n return <>{children}</>;\n};\n\nexport const AsyncProperties = ({ name, onChange, children }: AsyncPropertiesProps) => {\n const pendingRef = useRef(0);\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n const storeRef = useRef<PropertyStore | null>(null);\n\n const interceptedOnChange = useCallback((properties: Property[]) => {\n if (pendingRef.current > 0) {\n return;\n }\n onChangeRef.current?.(properties);\n }, []);\n\n const contextValue = useRef<AsyncPropertiesContextValue>({\n incrementPending() {\n pendingRef.current++;\n },\n decrementPending() {\n pendingRef.current = Math.max(0, pendingRef.current - 1);\n if (pendingRef.current === 0) {\n setTimeout(() => {\n if (pendingRef.current === 0 && storeRef.current) {\n storeRef.current.notify();\n }\n }, 0);\n }\n }\n }).current;\n\n return (\n <AsyncPropertiesContext.Provider value={contextValue}>\n <Properties name={name} onChange={interceptedOnChange}>\n <StoreCapture storeRef={storeRef}>{children}</StoreCapture>\n </Properties>\n </AsyncPropertiesContext.Provider>\n );\n};\n"],"names":["AsyncPropertiesContext","createContext","undefined","useAsyncProperties","useContext","StoreCapture","storeRef","children","store","useProperties","AsyncProperties","name","onChange","pendingRef","useRef","onChangeRef","interceptedOnChange","useCallback","properties","contextValue","Math","setTimeout","Properties"],"mappings":";;AAUA,MAAMA,yBAAyB,WAAHA,GAAGC,cAAuDC;AAE/E,SAASC;IACZ,OAAOC,WAAWJ;AACtB;AAQA,MAAMK,eAAe,CAAC,EAClBC,QAAQ,EACRC,QAAQ,EAIX;IACG,MAAM,EAAEC,KAAK,EAAE,GAAGC;IAClBH,SAAS,OAAO,GAAGE;IACnB,OAAO,WAAP,GAAO,0CAAGD;AACd;AAEO,MAAMG,kBAAkB,CAAC,EAAEC,IAAI,EAAEC,QAAQ,EAAEL,QAAQ,EAAwB;IAC9E,MAAMM,aAAaC,OAAO;IAC1B,MAAMC,cAAcD,OAAOF;IAC3BG,YAAY,OAAO,GAAGH;IACtB,MAAMN,WAAWQ,OAA6B;IAE9C,MAAME,sBAAsBC,YAAY,CAACC;QACrC,IAAIL,WAAW,OAAO,GAAG,GACrB;QAEJE,YAAY,OAAO,GAAGG;IAC1B,GAAG,EAAE;IAEL,MAAMC,eAAeL,OAAoC;QACrD;YACID,WAAW,OAAO;QACtB;QACA;YACIA,WAAW,OAAO,GAAGO,KAAK,GAAG,CAAC,GAAGP,WAAW,OAAO,GAAG;YACtD,IAAIA,AAAuB,MAAvBA,WAAW,OAAO,EAClBQ,WAAW;gBACP,IAAIR,AAAuB,MAAvBA,WAAW,OAAO,IAAUP,SAAS,OAAO,EAC5CA,SAAS,OAAO,CAAC,MAAM;YAE/B,GAAG;QAEX;IACJ,GAAG,OAAO;IAEV,OAAO,WAAP,GACI,oBAACN,uBAAuB,QAAQ;QAAC,OAAOmB;qBACpC,oBAACG,YAAUA;QAAC,MAAMX;QAAM,UAAUK;qBAC9B,oBAACX,cAAYA;QAAC,UAAUC;OAAWC;AAInD"}
package/Await.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ interface AwaitProps<T> {
3
+ fn: () => Promise<T>;
4
+ children: (value: T) => React.ReactNode;
5
+ }
6
+ export declare function Await<T>({ fn, children }: AwaitProps<T>): React.JSX.Element | null;
7
+ export {};
package/Await.js ADDED
@@ -0,0 +1,44 @@
1
+ import react, { useEffect, useRef, useState } from "react";
2
+ import { useAsyncProperties } from "./AsyncProperties.js";
3
+ function Await({ fn, children }) {
4
+ const async = useAsyncProperties();
5
+ const [result, setResult] = useState(null);
6
+ const registeredRef = useRef(false);
7
+ const settledRef = useRef(false);
8
+ if (!registeredRef.current && async) {
9
+ registeredRef.current = true;
10
+ async.incrementPending();
11
+ }
12
+ useEffect(()=>{
13
+ let cancelled = false;
14
+ fn().then((data)=>{
15
+ if (!cancelled) {
16
+ settledRef.current = true;
17
+ setResult({
18
+ data
19
+ });
20
+ }
21
+ }, (error)=>{
22
+ if (!cancelled) {
23
+ settledRef.current = true;
24
+ setResult({
25
+ error
26
+ });
27
+ }
28
+ });
29
+ return ()=>{
30
+ cancelled = true;
31
+ if (!settledRef.current && async) async.decrementPending();
32
+ };
33
+ }, []);
34
+ useEffect(()=>{
35
+ if (null !== result && async) async.decrementPending();
36
+ }, [
37
+ result
38
+ ]);
39
+ if (result && "data" in result) return /*#__PURE__*/ react.createElement(react.Fragment, null, children(result.data));
40
+ return null;
41
+ }
42
+ export { Await };
43
+
44
+ //# sourceMappingURL=Await.js.map
package/Await.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Await.js","sources":["../src/Await.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { useAsyncProperties } from \"./AsyncProperties.js\";\n\ninterface AwaitProps<T> {\n fn: () => Promise<T>;\n children: (value: T) => React.ReactNode;\n}\n\nexport function Await<T>({ fn, children }: AwaitProps<T>) {\n const async = useAsyncProperties();\n const [result, setResult] = useState<{ data: T } | { error: unknown } | null>(null);\n const registeredRef = useRef(false);\n const settledRef = useRef(false);\n\n if (!registeredRef.current && async) {\n registeredRef.current = true;\n async.incrementPending();\n }\n\n useEffect(() => {\n let cancelled = false;\n\n fn().then(\n data => {\n if (!cancelled) {\n settledRef.current = true;\n setResult({ data });\n }\n },\n error => {\n if (!cancelled) {\n settledRef.current = true;\n setResult({ error });\n }\n }\n );\n\n return () => {\n cancelled = true;\n if (!settledRef.current && async) {\n async.decrementPending();\n }\n };\n }, []);\n\n useEffect(() => {\n if (result !== null && async) {\n async.decrementPending();\n }\n }, [result]);\n\n if (result && \"data\" in result) {\n return <>{children(result.data)}</>;\n }\n\n return null;\n}\n"],"names":["Await","fn","children","async","useAsyncProperties","result","setResult","useState","registeredRef","useRef","settledRef","useEffect","cancelled","data","error"],"mappings":";;AAQO,SAASA,MAAS,EAAEC,EAAE,EAAEC,QAAQ,EAAiB;IACpD,MAAMC,QAAQC;IACd,MAAM,CAACC,QAAQC,UAAU,GAAGC,SAAkD;IAC9E,MAAMC,gBAAgBC,OAAO;IAC7B,MAAMC,aAAaD,OAAO;IAE1B,IAAI,CAACD,cAAc,OAAO,IAAIL,OAAO;QACjCK,cAAc,OAAO,GAAG;QACxBL,MAAM,gBAAgB;IAC1B;IAEAQ,UAAU;QACN,IAAIC,YAAY;QAEhBX,KAAK,IAAI,CACLY,CAAAA;YACI,IAAI,CAACD,WAAW;gBACZF,WAAW,OAAO,GAAG;gBACrBJ,UAAU;oBAAEO;gBAAK;YACrB;QACJ,GACAC,CAAAA;YACI,IAAI,CAACF,WAAW;gBACZF,WAAW,OAAO,GAAG;gBACrBJ,UAAU;oBAAEQ;gBAAM;YACtB;QACJ;QAGJ,OAAO;YACHF,YAAY;YACZ,IAAI,CAACF,WAAW,OAAO,IAAIP,OACvBA,MAAM,gBAAgB;QAE9B;IACJ,GAAG,EAAE;IAELQ,UAAU;QACN,IAAIN,AAAW,SAAXA,UAAmBF,OACnBA,MAAM,gBAAgB;IAE9B,GAAG;QAACE;KAAO;IAEX,IAAIA,UAAU,UAAUA,QACpB,OAAO,WAAP,GAAO,0CAAGH,SAASG,OAAO,IAAI;IAGlC,OAAO;AACX"}
@@ -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,54 @@
1
+ import { useEffect } from "react";
2
+ import { getHook } from "./useDebugConfig.js";
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;
40
+ }
41
+ function safeStringify(value) {
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
+ }
51
+ }
52
+ export { DevToolsSection };
53
+
54
+ //# sourceMappingURL=DevToolsSection.js.map
@@ -0,0 +1 @@
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.d.ts CHANGED
@@ -1,17 +1,28 @@
1
1
  import React from "react";
2
+ import { PropertyStore } from "./domain/index.js";
3
+ export interface ConnectToPropertiesProps {
4
+ name: string;
5
+ children: React.ReactNode;
6
+ }
7
+ export declare const ConnectToProperties: ({ name, children }: ConnectToPropertiesProps) => React.JSX.Element;
2
8
  export interface Property {
3
9
  id: string;
4
10
  parent: string;
5
11
  name: string;
6
12
  value?: unknown;
7
13
  array?: boolean;
14
+ $isFirst?: boolean;
15
+ $isLast?: boolean;
8
16
  }
9
17
  interface AddPropertyOptions {
10
18
  after?: string;
11
19
  before?: string;
20
+ priority?: number;
12
21
  }
13
22
  interface PropertiesContext {
14
- properties: Property[];
23
+ name?: string;
24
+ store: PropertyStore;
25
+ getAncestor(name: string): PropertiesContext | undefined;
15
26
  getObject<T = unknown>(): T;
16
27
  addProperty(property: Property, options?: AddPropertyOptions): void;
17
28
  removeProperty(id: string): void;
@@ -19,10 +30,14 @@ interface PropertiesContext {
19
30
  }
20
31
  declare const PropertiesContext: React.Context<PropertiesContext | undefined>;
21
32
  interface PropertiesProps {
33
+ name?: string;
22
34
  onChange?(properties: Property[]): void;
35
+ children: React.ReactNode;
23
36
  }
24
- export declare const Properties: React.FC<PropertiesProps>;
37
+ export declare const Properties: ({ name, onChange, children }: PropertiesProps) => React.JSX.Element;
25
38
  export declare function useProperties(): PropertiesContext;
39
+ export declare function useMaybeProperties(): PropertiesContext | undefined;
40
+ export declare function useAncestorByName(name: string | undefined): PropertiesContext | undefined;
26
41
  interface PropertyProps {
27
42
  id?: string;
28
43
  name: string;
@@ -34,11 +49,12 @@ interface PropertyProps {
34
49
  remove?: boolean;
35
50
  parent?: string;
36
51
  root?: boolean;
52
+ children?: React.ReactNode;
37
53
  }
38
54
  export declare function useParentProperty(): Property | undefined;
39
55
  interface AncestorMatch {
40
56
  [key: string]: string | boolean | number | null | undefined;
41
57
  }
42
58
  export declare function useAncestor(params: AncestorMatch): Property | undefined;
43
- export declare const Property: React.FC<PropertyProps>;
59
+ export declare const Property: ({ id, name, value, children, after, before, replace, remove, array, root, parent }: PropertyProps) => React.JSX.Element | null;
44
60
  export {};
package/Properties.js CHANGED
@@ -1,235 +1,140 @@
1
- "use strict";
2
-
3
- var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
4
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
5
- Object.defineProperty(exports, "__esModule", {
6
- value: true
7
- });
8
- exports.Property = exports.Properties = void 0;
9
- exports.useAncestor = useAncestor;
10
- exports.useParentProperty = useParentProperty;
11
- exports.useProperties = useProperties;
12
- var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
13
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
14
- var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
15
- var _react = _interopRequireWildcard(require("react"));
16
- var _utils = require("./utils");
17
- function removeByParent(id, properties) {
18
- return properties.filter(function (prop) {
19
- return prop.parent === id;
20
- }).reduce(function (acc, item) {
21
- return removeByParent(item.id, acc.filter(function (prop) {
22
- return prop.id !== item.id;
23
- }));
24
- }, properties);
25
- }
26
- function putPropertyBefore(properties, property, before) {
27
- var existingIndex = properties.findIndex(function (prop) {
28
- return prop.id === property.id;
29
- });
30
- if (existingIndex > -1) {
31
- var existingProperty = properties[existingIndex];
32
- var newProperties = properties.filter(function (p) {
33
- return p.id !== property.id;
34
- });
35
- var _targetIndex = newProperties.findIndex(function (prop) {
36
- return prop.id === before;
37
- });
38
- return [].concat((0, _toConsumableArray2.default)(newProperties.slice(0, _targetIndex)), [existingProperty], (0, _toConsumableArray2.default)(newProperties.slice(_targetIndex)));
39
- }
40
- var targetIndex = properties.findIndex(function (prop) {
41
- return prop.id === before;
42
- });
43
- return [].concat((0, _toConsumableArray2.default)(properties.slice(0, targetIndex)), [property], (0, _toConsumableArray2.default)(properties.slice(targetIndex)));
44
- }
45
- function putPropertyAfter(properties, property, after) {
46
- var existingIndex = properties.findIndex(function (prop) {
47
- return prop.id === property.id;
48
- });
49
- if (existingIndex > -1) {
50
- var _properties$splice = properties.splice(existingIndex, 1),
51
- _properties$splice2 = (0, _slicedToArray2.default)(_properties$splice, 1),
52
- removedProperty = _properties$splice2[0];
53
- var _targetIndex2 = properties.findIndex(function (prop) {
54
- return prop.id === after;
55
- });
56
- return [].concat((0, _toConsumableArray2.default)(properties.slice(0, _targetIndex2 + 1)), [removedProperty], (0, _toConsumableArray2.default)(properties.slice(_targetIndex2 + 1)));
57
- }
58
- var targetIndex = properties.findIndex(function (prop) {
59
- return prop.id === after;
60
- });
61
- return [].concat((0, _toConsumableArray2.default)(properties.slice(0, targetIndex + 1)), [property], (0, _toConsumableArray2.default)(properties.slice(targetIndex + 1)));
62
- }
63
- function mergeProperty(properties, property) {
64
- var index = properties.findIndex(function (prop) {
65
- return prop.id === property.id;
66
- });
67
- if (index > -1) {
68
- return [].concat((0, _toConsumableArray2.default)(properties.slice(0, index)), [(0, _objectSpread2.default)((0, _objectSpread2.default)({}, properties[index]), property)], (0, _toConsumableArray2.default)(properties.slice(index + 1)));
69
- }
70
- return properties;
71
- }
72
- var PropertiesContext = /*#__PURE__*/(0, _react.createContext)(undefined);
73
- var Properties = function Properties(_ref) {
74
- var onChange = _ref.onChange,
75
- children = _ref.children;
76
- var _useState = (0, _react.useState)([]),
77
- _useState2 = (0, _slicedToArray2.default)(_useState, 2),
78
- properties = _useState2[0],
79
- setProperties = _useState2[1];
80
- (0, _react.useEffect)(function () {
81
- if (onChange) {
82
- onChange(properties);
83
- }
84
- }, [properties]);
85
- var context = (0, _react.useMemo)(function () {
86
- return {
87
- properties: properties,
88
- getObject: function getObject() {
89
- return (0, _utils.toObject)(properties);
90
- },
91
- addProperty: function addProperty(property) {
92
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
93
- setProperties(function (properties) {
94
- var index = properties.findIndex(function (prop) {
95
- return prop.id === property.id;
96
- });
97
- if (index > -1) {
98
- var newProperties = mergeProperty(properties, property);
99
- if (options.after) {
100
- return putPropertyAfter(newProperties, property, options.after);
101
- }
102
- if (options.before) {
103
- return putPropertyBefore(newProperties, property, options.before);
104
- }
105
- return newProperties;
106
- }
107
- if (options.after) {
108
- return putPropertyAfter(properties, property, options.after);
109
- }
110
- if (options.before) {
111
- return putPropertyBefore(properties, property, options.before);
112
- }
113
- return [].concat((0, _toConsumableArray2.default)(properties), [property]);
114
- });
115
- },
116
- removeProperty: function removeProperty(id) {
117
- setProperties(function (properties) {
118
- return removeByParent(id, properties.filter(function (prop) {
119
- return prop.id !== id;
120
- }));
121
- });
122
- },
123
- replaceProperty: function replaceProperty(id, property) {
124
- setProperties(function (properties) {
125
- var toReplace = properties.findIndex(function (prop) {
126
- return prop.id === id;
127
- });
128
- if (toReplace > -1) {
129
- // Replace the property and remove all remaining child properties.
130
- return removeByParent(id, [].concat((0, _toConsumableArray2.default)(properties.slice(0, toReplace)), [property], (0, _toConsumableArray2.default)(properties.slice(toReplace + 1))));
131
- }
132
- return properties;
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";
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);
133
22
  });
134
- }
135
- };
136
- }, [properties]);
137
- return /*#__PURE__*/_react.default.createElement(PropertiesContext.Provider, {
138
- value: context
139
- }, children);
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);
140
52
  };
141
- exports.Properties = Properties;
142
53
  function useProperties() {
143
- var properties = (0, _react.useContext)(PropertiesContext);
144
- if (!properties) {
145
- throw Error("Properties context provider is missing!");
146
- }
147
- return properties;
54
+ const context = useContext(PropertiesContext);
55
+ if (!context) throw Error("Properties context provider is missing!");
56
+ return context;
57
+ }
58
+ function useMaybeProperties() {
59
+ return useContext(PropertiesContext);
148
60
  }
149
- var PropertyContext = /*#__PURE__*/(0, _react.createContext)(undefined);
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
+ ]);
70
+ }
71
+ const PropertyContext = /*#__PURE__*/ createContext(void 0);
150
72
  function useParentProperty() {
151
- return (0, _react.useContext)(PropertyContext);
73
+ return useContext(PropertyContext);
152
74
  }
153
75
  function useAncestor(params) {
154
- var property = useParentProperty();
155
- var _useProperties = useProperties(),
156
- properties = _useProperties.properties;
157
- var matchOrGetAncestor = function matchOrGetAncestor(property, params) {
158
- var matchedProps = properties.filter(function (prop) {
159
- return prop.parent === property.id;
160
- }).filter(function (prop) {
161
- return prop.name in params && prop.value === params[prop.name];
162
- });
163
- if (matchedProps.length === Object.keys(params).length) {
164
- return property;
165
- }
166
- var newParent = property.parent ? properties.find(function (prop) {
167
- return prop.id === property.parent;
168
- }) : undefined;
169
- return newParent ? matchOrGetAncestor(newParent, params) : undefined;
170
- };
171
- return property ? matchOrGetAncestor(property, params) : undefined;
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;
172
86
  }
173
- var Property = function Property(_ref2) {
174
- var id = _ref2.id,
175
- name = _ref2.name,
176
- value = _ref2.value,
177
- children = _ref2.children,
178
- _ref2$after = _ref2.after,
179
- after = _ref2$after === void 0 ? undefined : _ref2$after,
180
- _ref2$before = _ref2.before,
181
- before = _ref2$before === void 0 ? undefined : _ref2$before,
182
- _ref2$replace = _ref2.replace,
183
- replace = _ref2$replace === void 0 ? undefined : _ref2$replace,
184
- _ref2$remove = _ref2.remove,
185
- remove = _ref2$remove === void 0 ? false : _ref2$remove,
186
- _ref2$array = _ref2.array,
187
- array = _ref2$array === void 0 ? false : _ref2$array,
188
- _ref2$root = _ref2.root,
189
- root = _ref2$root === void 0 ? false : _ref2$root,
190
- _ref2$parent = _ref2.parent,
191
- parent = _ref2$parent === void 0 ? undefined : _ref2$parent;
192
- var uniqueId = (0, _react.useMemo)(function () {
193
- return id || (0, _utils.getUniqueId)();
194
- }, []);
195
- var parentProperty = useParentProperty();
196
- var properties = useProperties();
197
- if (!properties) {
198
- throw Error("<Properties> provider is missing higher in the hierarchy!");
199
- }
200
- var addProperty = properties.addProperty,
201
- removeProperty = properties.removeProperty,
202
- replaceProperty = properties.replaceProperty;
203
- var parentId = parent ? parent : root ? "" : (parentProperty === null || parentProperty === void 0 ? void 0 : parentProperty.id) || "";
204
- var property = {
205
- id: uniqueId,
206
- name: name,
207
- value: value,
208
- parent: parentId,
209
- array: array
210
- };
211
- (0, _react.useEffect)(function () {
212
- if (remove) {
213
- removeProperty(uniqueId);
214
- return;
215
- }
216
- if (replace) {
217
- replaceProperty(replace, property);
218
- return;
219
- }
220
- addProperty(property, {
221
- after: after,
222
- before: before
223
- });
224
- return function () {
225
- 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
226
105
  };
227
- }, []);
228
- if (children) {
229
- return /*#__PURE__*/_react.default.createElement(PropertyContext.Provider, {
230
- 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
231
135
  }, children);
232
- }
233
- return null;
136
+ return null;
234
137
  };
235
- exports.Property = Property;
138
+ export { ConnectToProperties, Properties, Property, useAncestor, useAncestorByName, useMaybeProperties, useParentProperty, useProperties };
139
+
140
+ //# sourceMappingURL=Properties.js.map