@webiny/react-properties 0.0.0-unstable.7f63ea0744 → 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,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
- value: unknown;
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,172 +1,156 @@
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 _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
14
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
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
- var PropertiesContext = /*#__PURE__*/(0, _react.createContext)(undefined);
27
- var Properties = function Properties(_ref) {
28
- var onChange = _ref.onChange,
29
- children = _ref.children;
30
- var _useState = (0, _react.useState)([]),
31
- _useState2 = (0, _slicedToArray2.default)(_useState, 2),
32
- properties = _useState2[0],
33
- setProperties = _useState2[1];
34
- (0, _react.useEffect)(function () {
35
- if (onChange) {
36
- onChange(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(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;
37
34
  }
38
- }, [properties]);
39
- var context = (0, _react.useMemo)(function () {
40
- return {
41
- properties: properties,
42
- getObject: function getObject() {
43
- return (0, _utils.toObject)(properties);
44
- },
45
- addProperty: function addProperty(property) {
46
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
47
- setProperties(function (properties) {
48
- // If a property with this ID already exists, merge the two properties.
49
- var index = properties.findIndex(function (prop) {
50
- return prop.id === property.id;
51
- });
52
- if (index > -1) {
53
- 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)));
54
- }
55
- if (options.after) {
56
- var _index = properties.findIndex(function (prop) {
57
- return prop.id === options.after;
58
- });
59
- if (_index > -1) {
60
- return [].concat((0, _toConsumableArray2.default)(properties.slice(0, _index + 1)), [property], (0, _toConsumableArray2.default)(properties.slice(_index + 1)));
61
- }
62
- }
63
- if (options.before) {
64
- var _index2 = properties.findIndex(function (prop) {
65
- return prop.id === options.before;
66
- });
67
- if (_index2 > -1) {
68
- return [].concat((0, _toConsumableArray2.default)(properties.slice(0, _index2)), [property], (0, _toConsumableArray2.default)(properties.slice(_index2)));
69
- }
70
- }
71
- return [].concat((0, _toConsumableArray2.default)(properties), [property]);
72
- });
73
- },
74
- removeProperty: function removeProperty(id) {
75
- setProperties(function (properties) {
76
- return removeByParent(id, properties.filter(function (prop) {
77
- return prop.id !== id;
78
- }));
79
- });
80
- },
81
- replaceProperty: function replaceProperty(id, property) {
82
- setProperties(function (properties) {
83
- var toReplace = properties.findIndex(function (prop) {
84
- return prop.id === id;
85
- });
86
- if (toReplace > -1) {
87
- // Replace the property and remove all remaining child properties.
88
- return removeByParent(id, [].concat((0, _toConsumableArray2.default)(properties.slice(0, toReplace)), [property], (0, _toConsumableArray2.default)(properties.slice(toReplace + 1))));
89
- }
90
- return properties;
91
- });
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;
92
48
  }
93
- };
94
- }, [properties]);
95
- return /*#__PURE__*/_react.default.createElement(PropertiesContext.Provider, {
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, {
96
65
  value: context
97
66
  }, children);
98
67
  };
99
- exports.Properties = Properties;
100
- function useProperties() {
101
- var properties = (0, _react.useContext)(PropertiesContext);
102
- if (!properties) {
68
+ export function useProperties() {
69
+ const context = useContext(PropertiesContext);
70
+ if (!context) {
103
71
  throw Error("Properties context provider is missing!");
104
72
  }
105
- return properties;
73
+ return context;
106
74
  }
107
- var PropertyContext = /*#__PURE__*/(0, _react.createContext)(undefined);
108
- function useParentProperty() {
109
- return (0, _react.useContext)(PropertyContext);
75
+ export function useMaybeProperties() {
76
+ return useContext(PropertiesContext);
110
77
  }
111
- function useAncestor(params) {
112
- var property = useParentProperty();
113
- var _useProperties = useProperties(),
114
- properties = _useProperties.properties;
115
- var matchOrGetAncestor = function matchOrGetAncestor(property, params) {
116
- var matchedProps = properties.filter(function (prop) {
117
- return prop.parent === property.id;
118
- }).filter(function (prop) {
119
- return prop.name in params && prop.value === params[prop.name];
120
- });
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]);
89
+ }
90
+ const PropertyContext = /*#__PURE__*/createContext(undefined);
91
+ export function useParentProperty() {
92
+ return useContext(PropertyContext);
93
+ }
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]);
121
102
  if (matchedProps.length === Object.keys(params).length) {
122
103
  return property;
123
104
  }
124
- var newParent = property.parent ? properties.find(function (prop) {
125
- return prop.id === property.parent;
126
- }) : undefined;
105
+ const newParent = property.parent ? store.getById(property.parent) : undefined;
127
106
  return newParent ? matchOrGetAncestor(newParent, params) : undefined;
128
107
  };
129
108
  return property ? matchOrGetAncestor(property, params) : undefined;
130
109
  }
131
- var Property = function Property(_ref2) {
132
- var id = _ref2.id,
133
- name = _ref2.name,
134
- value = _ref2.value,
135
- children = _ref2.children,
136
- _ref2$after = _ref2.after,
137
- after = _ref2$after === void 0 ? undefined : _ref2$after,
138
- _ref2$before = _ref2.before,
139
- before = _ref2$before === void 0 ? undefined : _ref2$before,
140
- _ref2$replace = _ref2.replace,
141
- replace = _ref2$replace === void 0 ? undefined : _ref2$replace,
142
- _ref2$remove = _ref2.remove,
143
- remove = _ref2$remove === void 0 ? false : _ref2$remove,
144
- _ref2$array = _ref2.array,
145
- array = _ref2$array === void 0 ? false : _ref2$array,
146
- _ref2$root = _ref2.root,
147
- root = _ref2$root === void 0 ? false : _ref2$root,
148
- _ref2$parent = _ref2.parent,
149
- parent = _ref2$parent === void 0 ? undefined : _ref2$parent;
150
- var uniqueId = (0, _react.useMemo)(function () {
151
- return id || (0, _utils.getUniqueId)();
152
- }, []);
153
- var parentProperty = useParentProperty();
154
- var properties = useProperties();
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;
155
131
  if (!properties) {
156
132
  throw Error("<Properties> provider is missing higher in the hierarchy!");
157
133
  }
158
- var addProperty = properties.addProperty,
159
- removeProperty = properties.removeProperty,
160
- replaceProperty = properties.replaceProperty;
161
- var parentId = parent ? parent : root ? "" : (parentProperty === null || parentProperty === void 0 ? void 0 : parentProperty.id) || "";
162
- var property = {
134
+ const {
135
+ addProperty,
136
+ removeProperty,
137
+ replaceProperty,
138
+ store: propertyStore
139
+ } = properties;
140
+ const parentId = parent ? parent : root ? "" : parentProperty?.id || "";
141
+ const property = {
163
142
  id: uniqueId,
164
- name: name,
165
- value: value,
143
+ name,
144
+ value,
166
145
  parent: parentId,
167
- array: array
146
+ array
168
147
  };
169
- (0, _react.useEffect)(function () {
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(() => {
170
154
  if (remove) {
171
155
  removeProperty(uniqueId);
172
156
  return;
@@ -175,19 +159,35 @@ var Property = function Property(_ref2) {
175
159
  replaceProperty(replace, property);
176
160
  return;
177
161
  }
178
- addProperty(property, {
179
- after: after,
180
- before: before
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
181
172
  });
182
- return function () {
173
+ return () => {
183
174
  removeProperty(uniqueId);
184
175
  };
185
176
  }, []);
177
+ useEffect(() => {
178
+ if (previousValue.current !== value) {
179
+ previousValue.current = value;
180
+ if (!remove && !replace) {
181
+ replaceProperty(uniqueId, property);
182
+ }
183
+ }
184
+ }, [value]);
186
185
  if (children) {
187
- return /*#__PURE__*/_react.default.createElement(PropertyContext.Provider, {
186
+ return /*#__PURE__*/React.createElement(PropertyContext.Provider, {
188
187
  value: property
189
188
  }, children);
190
189
  }
191
190
  return null;
192
191
  };
193
- exports.Property = Property;
192
+
193
+ //# sourceMappingURL=Properties.js.map
package/Properties.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["removeByParent","id","properties","filter","prop","parent","reduce","acc","item","PropertiesContext","createContext","undefined","Properties","onChange","children","useState","setProperties","useEffect","context","useMemo","getObject","toObject","addProperty","property","options","index","findIndex","slice","after","before","removeProperty","replaceProperty","toReplace","useProperties","useContext","Error","PropertyContext","useParentProperty","useAncestor","params","matchOrGetAncestor","matchedProps","name","value","length","Object","keys","newParent","find","Property","replace","remove","array","root","uniqueId","getUniqueId","parentProperty","parentId"],"sources":["Properties.tsx"],"sourcesContent":["import React, { createContext, useContext, useEffect, useMemo, useState } from \"react\";\nimport { getUniqueId, toObject } from \"./utils\";\n\nexport interface Property {\n id: string;\n parent: string;\n name: string;\n value: unknown;\n array?: 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 properties: Property[];\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 onChange?(properties: Property[]): void;\n}\n\nexport const Properties: React.FC<PropertiesProps> = ({ onChange, children }) => {\n const [properties, setProperties] = useState<Property[]>([]);\n\n useEffect(() => {\n if (onChange) {\n onChange(properties);\n }\n }, [properties]);\n\n const context: PropertiesContext = useMemo(\n () => ({\n properties,\n getObject<T>() {\n return toObject(properties) as T;\n },\n addProperty(property, options = {}) {\n setProperties(properties => {\n // If a property with this ID already exists, merge the two properties.\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\n if (options.after) {\n const index = properties.findIndex(prop => prop.id === options.after);\n if (index > -1) {\n return [\n ...properties.slice(0, index + 1),\n property,\n ...properties.slice(index + 1)\n ];\n }\n }\n\n if (options.before) {\n const index = properties.findIndex(prop => prop.id === options.before);\n if (index > -1) {\n return [\n ...properties.slice(0, index),\n property,\n ...properties.slice(index)\n ];\n }\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\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}\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: React.FC<PropertyProps> = ({\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}) => {\n const uniqueId = useMemo(() => id || getUniqueId(), []);\n const parentProperty = useParentProperty();\n const properties = useProperties();\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 addProperty(property, { 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":"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"}
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":[]}