@3driseai/3drise-core 1.0.17 → 1.0.19

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,15 @@
1
+ export type SettingsPatch = Record<string, any>;
2
+ export declare function isPlainObject(value: unknown): value is Record<string, any>;
3
+ /** `base` with `patch` laid over it. Returns `base` itself when the patch is empty. */
4
+ export declare function applySettingsPatch<T>(base: T, patch: SettingsPatch | undefined | null): T;
5
+ /** Several patches composed into one, later ones winning. */
6
+ export declare function composeSettingsPatches(patches: SettingsPatch[]): SettingsPatch | undefined;
7
+ /**
8
+ * The patch that turns `base` into `next`: every leaf of `next` that differs from
9
+ * `base`. Keys `next` dropped are ignored — a patch sets values, it does not delete.
10
+ * `exclude` applies to top-level keys only (identity and behaviour fields).
11
+ */
12
+ export declare function diffSettings(base: unknown, next: unknown, exclude?: ReadonlySet<string>): SettingsPatch;
13
+ /** Number of leaf values a patch sets (for UI summaries). */
14
+ export declare function countPatchLeaves(patch: SettingsPatch | undefined | null): number;
15
+ //# sourceMappingURL=settingsPatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settingsPatch.d.ts","sourceRoot":"","sources":["../../src/utils/settingsPatch.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAEhD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAI1E;AAED,uFAAuF;AACvF,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,IAAI,GAAG,CAAC,CAUzF;AAED,6DAA6D;AAC7D,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,aAAa,GAAG,SAAS,CAG1F;AAYD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,WAAW,CAAC,MAAM,CAAa,GAAG,aAAa,CAiBlH;AAED,6DAA6D;AAC7D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAKhF"}
@@ -0,0 +1,91 @@
1
+ // =============================================================================
2
+ // settingsPatch — deep partials over a settings object
3
+ // =============================================================================
4
+ //
5
+ // A *patch* is a deep partial of a scene element's settings: the same shape as the
6
+ // settings themselves, holding only what differs. Actions store one per target and
7
+ // SceneActions layers them over the authored settings at runtime (never persisted
8
+ // into the settings, never written to Redux).
9
+ //
10
+ // Rules, kept deliberately small:
11
+ // - plain objects merge key by key, recursively;
12
+ // - everything else (numbers, strings, booleans, arrays, null) replaces;
13
+ // - untouched branches keep their identity, so renderers that memoise per block
14
+ // (CloudsGenerator's deck / cirrus / quality, material application keyed on
15
+ // materialSettings) only redo the block a patch actually changed.
16
+ //
17
+ export function isPlainObject(value) {
18
+ if (value === null || typeof value !== 'object')
19
+ return false;
20
+ const proto = Object.getPrototypeOf(value);
21
+ return proto === Object.prototype || proto === null;
22
+ }
23
+ /** `base` with `patch` laid over it. Returns `base` itself when the patch is empty. */
24
+ export function applySettingsPatch(base, patch) {
25
+ if (!patch || Object.keys(patch).length === 0)
26
+ return base;
27
+ if (!isPlainObject(base))
28
+ return (isPlainObject(patch) ? { ...patch } : patch);
29
+ const out = { ...base };
30
+ for (const key of Object.keys(patch)) {
31
+ const next = patch[key];
32
+ const prev = out[key];
33
+ out[key] = isPlainObject(next) && isPlainObject(prev) ? applySettingsPatch(prev, next) : next;
34
+ }
35
+ return out;
36
+ }
37
+ /** Several patches composed into one, later ones winning. */
38
+ export function composeSettingsPatches(patches) {
39
+ if (patches.length === 0)
40
+ return undefined;
41
+ return patches.reduce((acc, p) => applySettingsPatch(acc, p), {});
42
+ }
43
+ function valuesEqual(a, b) {
44
+ if (a === b)
45
+ return true;
46
+ if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null)
47
+ return false;
48
+ try {
49
+ return JSON.stringify(a) === JSON.stringify(b);
50
+ }
51
+ catch {
52
+ return false;
53
+ }
54
+ }
55
+ /**
56
+ * The patch that turns `base` into `next`: every leaf of `next` that differs from
57
+ * `base`. Keys `next` dropped are ignored — a patch sets values, it does not delete.
58
+ * `exclude` applies to top-level keys only (identity and behaviour fields).
59
+ */
60
+ export function diffSettings(base, next, exclude = new Set()) {
61
+ const out = {};
62
+ if (!isPlainObject(next))
63
+ return out;
64
+ const b = isPlainObject(base) ? base : {};
65
+ for (const key of Object.keys(next)) {
66
+ if (exclude.has(key))
67
+ continue;
68
+ const nv = next[key];
69
+ const bv = b[key];
70
+ if (nv === undefined || valuesEqual(nv, bv))
71
+ continue;
72
+ if (isPlainObject(nv) && isPlainObject(bv)) {
73
+ const sub = diffSettings(bv, nv);
74
+ if (Object.keys(sub).length > 0)
75
+ out[key] = sub;
76
+ }
77
+ else {
78
+ out[key] = nv;
79
+ }
80
+ }
81
+ return out;
82
+ }
83
+ /** Number of leaf values a patch sets (for UI summaries). */
84
+ export function countPatchLeaves(patch) {
85
+ if (!patch)
86
+ return 0;
87
+ let n = 0;
88
+ for (const v of Object.values(patch))
89
+ n += isPlainObject(v) ? countPatchLeaves(v) : 1;
90
+ return n;
91
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@3driseai/3drise-core",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",