cx 26.1.0 → 26.1.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.
Files changed (113) hide show
  1. package/build/ui/Widget.js +0 -5
  2. package/build/util/Component.js +5 -0
  3. package/build/util/test/createTestRenderer.d.ts +3 -1
  4. package/build/util/test/createTestRenderer.js +8 -2
  5. package/build/widgets/icons/calendar.js +4 -3
  6. package/build/widgets/icons/check.js +2 -2
  7. package/build/widgets/icons/clear.js +2 -2
  8. package/build/widgets/icons/close.js +2 -2
  9. package/build/widgets/icons/cx.js +2 -2
  10. package/build/widgets/icons/drop-down.js +2 -2
  11. package/build/widgets/icons/file.js +2 -2
  12. package/build/widgets/icons/folder-open.js +2 -2
  13. package/build/widgets/icons/folder.js +2 -2
  14. package/build/widgets/icons/forward.js +2 -2
  15. package/build/widgets/icons/loading.js +2 -2
  16. package/build/widgets/icons/menu.js +2 -2
  17. package/build/widgets/icons/pixel-picker.js +2 -2
  18. package/build/widgets/icons/search.js +2 -2
  19. package/build/widgets/icons/sort-asc.js +2 -2
  20. package/build/widgets/icons/square.js +2 -2
  21. package/dist/manifest.js +896 -896
  22. package/dist/ui.js +1 -8
  23. package/dist/util.js +4 -0
  24. package/dist/widgets.js +377 -313
  25. package/package.json +3 -1
  26. package/src/core.d.ts +182 -182
  27. package/src/data/ArrayElementView.ts +90 -90
  28. package/src/data/AugmentedViewBase.ts +88 -88
  29. package/src/data/Binding.ts +104 -104
  30. package/src/data/ExposedRecordView.ts +95 -95
  31. package/src/data/ExposedValueView.ts +89 -89
  32. package/src/data/Grouper.spec.ts +57 -57
  33. package/src/data/NestedDataView.ts +43 -43
  34. package/src/data/ReadOnlyDataView.ts +39 -39
  35. package/src/data/Ref.ts +104 -104
  36. package/src/data/Store.ts +52 -52
  37. package/src/data/StoreProxy.ts +19 -19
  38. package/src/data/StoreRef.ts +66 -66
  39. package/src/data/StringTemplate.ts +93 -93
  40. package/src/data/StructuredSelector.spec.ts +113 -113
  41. package/src/data/SubscribableView.ts +63 -63
  42. package/src/data/ZoomIntoPropertyView.ts +45 -45
  43. package/src/data/comparer.ts +78 -78
  44. package/src/data/ops/updateArray.ts +31 -31
  45. package/src/hooks/invokeCallback.spec.tsx +4 -4
  46. package/src/hooks/resolveCallback.spec.tsx +4 -4
  47. package/src/hooks/store.spec.tsx +15 -15
  48. package/src/hooks/useTrigger.spec.tsx +16 -10
  49. package/src/jsx-dev-runtime.ts +4 -4
  50. package/src/jsx-runtime.ts +79 -79
  51. package/src/ui/CSS.ts +87 -87
  52. package/src/ui/ContentResolver.spec.tsx +31 -29
  53. package/src/ui/Controller.spec.tsx +47 -39
  54. package/src/ui/Cx.spec.tsx +10 -8
  55. package/src/ui/DataProxy.spec.tsx +18 -18
  56. package/src/ui/DataProxy.ts +55 -55
  57. package/src/ui/FocusManager.ts +171 -171
  58. package/src/ui/IsolatedScope.spec.tsx +16 -9
  59. package/src/ui/PureContainer.spec.tsx +20 -18
  60. package/src/ui/Repeater.spec.tsx +8 -6
  61. package/src/ui/Rescope.spec.tsx +13 -13
  62. package/src/ui/Rescope.ts +49 -49
  63. package/src/ui/Restate.spec.tsx +31 -27
  64. package/src/ui/VDOM.ts +1 -1
  65. package/src/ui/Widget.tsx +0 -7
  66. package/src/ui/adapter/ArrayAdapter.spec.ts +55 -55
  67. package/src/ui/createFunctionalComponent.spec.tsx +20 -18
  68. package/src/ui/layout/Content.ts +30 -30
  69. package/src/ui/layout/ContentPlaceholder.spec.tsx +46 -34
  70. package/src/ui/layout/FirstVisibleChildLayout.spec.tsx +31 -19
  71. package/src/ui/selection/PropertySelection.ts +87 -87
  72. package/src/util/Component.spec.ts +30 -0
  73. package/src/util/Component.ts +301 -296
  74. package/src/util/DOM.ts +88 -88
  75. package/src/util/Format.spec.ts +69 -69
  76. package/src/util/Format.ts +267 -267
  77. package/src/util/addEventListenerWithOptions.ts +41 -41
  78. package/src/util/browserSupportsPassiveEventHandlers.ts +20 -20
  79. package/src/util/color/rgbToHsl.ts +35 -35
  80. package/src/util/getActiveElement.ts +4 -4
  81. package/src/util/innerTextTrim.ts +10 -10
  82. package/src/util/isDataRecord.ts +5 -5
  83. package/src/util/test/createTestRenderer.tsx +9 -2
  84. package/src/widgets/AccessorBindings.spec.tsx +4 -4
  85. package/src/widgets/HtmlElement.spec.tsx +6 -6
  86. package/src/widgets/ReactElementWrapper.spec.tsx +37 -37
  87. package/src/widgets/Sandbox.ts +103 -103
  88. package/src/widgets/form/ValidationGroup.spec.tsx +12 -12
  89. package/src/widgets/grid/GridCell.ts +143 -143
  90. package/src/widgets/icons/calendar.tsx +22 -17
  91. package/src/widgets/icons/check.tsx +14 -13
  92. package/src/widgets/icons/clear.tsx +16 -15
  93. package/src/widgets/icons/close.tsx +20 -20
  94. package/src/widgets/icons/cx.tsx +39 -38
  95. package/src/widgets/icons/drop-down.tsx +16 -15
  96. package/src/widgets/icons/file.tsx +14 -13
  97. package/src/widgets/icons/folder-open.tsx +16 -15
  98. package/src/widgets/icons/folder.tsx +14 -13
  99. package/src/widgets/icons/forward.tsx +23 -22
  100. package/src/widgets/icons/loading.tsx +25 -24
  101. package/src/widgets/icons/menu.tsx +18 -17
  102. package/src/widgets/icons/pixel-picker.tsx +18 -18
  103. package/src/widgets/icons/search.tsx +14 -13
  104. package/src/widgets/icons/sort-asc.tsx +15 -14
  105. package/src/widgets/icons/square.tsx +19 -18
  106. package/src/widgets/nav/Route.spec.tsx +2 -2
  107. package/src/widgets/nav/Route.ts +142 -142
  108. package/src/widgets/overlay/Dropdown.tsx +762 -762
  109. package/src/widgets/overlay/MsgBox.tsx +141 -141
  110. package/src/widgets/overlay/Toast.ts +111 -111
  111. package/src/widgets/overlay/Window.tsx +299 -299
  112. package/src/widgets/overlay/alerts.ts +46 -46
  113. package/src/widgets/overlay/index.ts +11 -11
@@ -1,89 +1,89 @@
1
- import { View, ViewConfig } from "./View";
2
- import { Binding } from "./Binding";
3
-
4
- export interface ExposedValueViewConfig extends ViewConfig {
5
- containerBinding: Binding;
6
- key?: string | null;
7
- recordName?: string;
8
- }
9
-
10
- export class ExposedValueView extends View {
11
- declare key: string;
12
- declare containerBinding: Binding;
13
- declare recordName: string;
14
- declare immutable?: boolean;
15
- declare store: View;
16
-
17
- constructor(config: ExposedValueViewConfig) {
18
- super(config);
19
- }
20
-
21
- getData(): any {
22
- if (
23
- this.sealed &&
24
- this.meta.version === this.cache.version &&
25
- this.cache.key === this.key &&
26
- this.meta == this.store.meta
27
- )
28
- return this.cache.result;
29
-
30
- let data = this.store.getData();
31
- let container = this.containerBinding.value(data) || {};
32
- let record = container[this.key];
33
-
34
- this.cache.version = this.meta.version;
35
- this.cache.key = this.key;
36
- this.cache.result = this.sealed || this.immutable || this.store.sealed ? { ...data } : data;
37
- this.cache.result[this.recordName] = record;
38
- this.meta = this.store.meta;
39
- return this.cache.result;
40
- }
41
-
42
- setKey(key: string) {
43
- this.key = key;
44
- }
45
-
46
- getKey() {
47
- return this.key;
48
- }
49
-
50
- setItem(path: string, value: any) {
51
- if (path == this.recordName || path.indexOf(this.recordName + ".") == 0) {
52
- var data = this.getData();
53
- var d = Binding.get(path).set(data, value);
54
- if (d === data) return false;
55
- var container = this.containerBinding.value(d);
56
- var record = d[this.recordName];
57
- var newContainer = Object.assign({}, container);
58
- newContainer[this.key] = record;
59
- return this.store.setItem(this.containerBinding.path, newContainer);
60
- }
61
- return this.store.setItem(path, value);
62
- }
63
-
64
- deleteItem(path: string) {
65
- var data, container, newContainer;
66
-
67
- if (path == this.recordName) {
68
- data = this.getData();
69
- container = this.containerBinding.value(data);
70
- if (!container || !container.hasOwnProperty(path)) return false;
71
- newContainer = Object.assign({}, container);
72
- delete newContainer[this.key];
73
- this.store.set(this.containerBinding.path, newContainer);
74
- } else if (path.indexOf(this.recordName + ".") == 0) {
75
- data = this.getData();
76
- var d = Binding.get(path).delete(data);
77
- if (d === data) return false;
78
- container = this.containerBinding.value(d);
79
- var record = d[this.recordName];
80
- newContainer = Object.assign({}, container);
81
- newContainer[this.key] = record;
82
- return this.store.setItem(this.containerBinding.path, newContainer);
83
- }
84
-
85
- return this.store.deleteItem(path);
86
- }
87
- }
88
-
89
- ExposedValueView.prototype.immutable = false;
1
+ import { View, ViewConfig } from "./View";
2
+ import { Binding } from "./Binding";
3
+
4
+ export interface ExposedValueViewConfig extends ViewConfig {
5
+ containerBinding: Binding;
6
+ key?: string | null;
7
+ recordName?: string;
8
+ }
9
+
10
+ export class ExposedValueView extends View {
11
+ declare key: string;
12
+ declare containerBinding: Binding;
13
+ declare recordName: string;
14
+ declare immutable?: boolean;
15
+ declare store: View;
16
+
17
+ constructor(config: ExposedValueViewConfig) {
18
+ super(config);
19
+ }
20
+
21
+ getData(): any {
22
+ if (
23
+ this.sealed &&
24
+ this.meta.version === this.cache.version &&
25
+ this.cache.key === this.key &&
26
+ this.meta == this.store.meta
27
+ )
28
+ return this.cache.result;
29
+
30
+ let data = this.store.getData();
31
+ let container = this.containerBinding.value(data) || {};
32
+ let record = container[this.key];
33
+
34
+ this.cache.version = this.meta.version;
35
+ this.cache.key = this.key;
36
+ this.cache.result = this.sealed || this.immutable || this.store.sealed ? { ...data } : data;
37
+ this.cache.result[this.recordName] = record;
38
+ this.meta = this.store.meta;
39
+ return this.cache.result;
40
+ }
41
+
42
+ setKey(key: string) {
43
+ this.key = key;
44
+ }
45
+
46
+ getKey() {
47
+ return this.key;
48
+ }
49
+
50
+ setItem(path: string, value: any) {
51
+ if (path == this.recordName || path.indexOf(this.recordName + ".") == 0) {
52
+ var data = this.getData();
53
+ var d = Binding.get(path).set(data, value);
54
+ if (d === data) return false;
55
+ var container = this.containerBinding.value(d);
56
+ var record = d[this.recordName];
57
+ var newContainer = Object.assign({}, container);
58
+ newContainer[this.key] = record;
59
+ return this.store.setItem(this.containerBinding.path, newContainer);
60
+ }
61
+ return this.store.setItem(path, value);
62
+ }
63
+
64
+ deleteItem(path: string) {
65
+ var data, container, newContainer;
66
+
67
+ if (path == this.recordName) {
68
+ data = this.getData();
69
+ container = this.containerBinding.value(data);
70
+ if (!container || !container.hasOwnProperty(path)) return false;
71
+ newContainer = Object.assign({}, container);
72
+ delete newContainer[this.key];
73
+ this.store.set(this.containerBinding.path, newContainer);
74
+ } else if (path.indexOf(this.recordName + ".") == 0) {
75
+ data = this.getData();
76
+ var d = Binding.get(path).delete(data);
77
+ if (d === data) return false;
78
+ container = this.containerBinding.value(d);
79
+ var record = d[this.recordName];
80
+ newContainer = Object.assign({}, container);
81
+ newContainer[this.key] = record;
82
+ return this.store.setItem(this.containerBinding.path, newContainer);
83
+ }
84
+
85
+ return this.store.deleteItem(path);
86
+ }
87
+ }
88
+
89
+ ExposedValueView.prototype.immutable = false;
@@ -1,57 +1,57 @@
1
- import { Grouper } from "./Grouper";
2
- import assert from "assert";
3
-
4
- describe("Grouper", function () {
5
- describe("single grouping", function () {
6
- it("should work", function () {
7
- let data = [
8
- { name: "John", age: 12 },
9
- { name: "Jane", age: 12 },
10
- ];
11
-
12
- let grouper = new Grouper({ name: { bind: "name" } });
13
- grouper.processAll(data);
14
-
15
- let results = grouper.getResults();
16
- // console.log(results);
17
- assert.equal(results.length, 2);
18
- });
19
-
20
- it("keys can have nested properties", function () {
21
- let data = [
22
- { name: "John", age: 12 },
23
- { name: "Jane", age: 12 },
24
- ];
25
-
26
- let grouper = new Grouper({ "person.name": { bind: "name" } });
27
- grouper.processAll(data);
28
-
29
- let results = grouper.getResults();
30
- assert.equal(results.length, 2);
31
- assert.equal(results[0].key.person?.name, "John");
32
- assert.equal(results[1].key.person?.name, "Jane");
33
- });
34
- });
35
-
36
- describe("multi grouping", function () {
37
- it("should work", function () {
38
- let data = [
39
- { name: "John", age: 12 },
40
- { name: "John", age: 12 },
41
- { name: "John", age: 13 },
42
- { name: "John", age: 14 },
43
- { name: "Jane", age: 12 },
44
- { name: "Jane", age: 13 },
45
- { name: "Jane", age: 14 },
46
- ];
47
-
48
- let grouper = new Grouper({ name: { bind: "name" }, age: { bind: "age" } });
49
- grouper.processAll(data);
50
-
51
- let results = grouper.getResults();
52
- // console.log(results);
53
- assert.equal(results.length, 6);
54
- assert.equal(results[0].records.length, 2);
55
- });
56
- });
57
- });
1
+ import { Grouper } from "./Grouper";
2
+ import assert from "assert";
3
+
4
+ describe("Grouper", function () {
5
+ describe("single grouping", function () {
6
+ it("should work", function () {
7
+ let data = [
8
+ { name: "John", age: 12 },
9
+ { name: "Jane", age: 12 },
10
+ ];
11
+
12
+ let grouper = new Grouper({ name: { bind: "name" } });
13
+ grouper.processAll(data);
14
+
15
+ let results = grouper.getResults();
16
+ // console.log(results);
17
+ assert.equal(results.length, 2);
18
+ });
19
+
20
+ it("keys can have nested properties", function () {
21
+ let data = [
22
+ { name: "John", age: 12 },
23
+ { name: "Jane", age: 12 },
24
+ ];
25
+
26
+ let grouper = new Grouper({ "person.name": { bind: "name" } });
27
+ grouper.processAll(data);
28
+
29
+ let results = grouper.getResults();
30
+ assert.equal(results.length, 2);
31
+ assert.equal(results[0].key.person?.name, "John");
32
+ assert.equal(results[1].key.person?.name, "Jane");
33
+ });
34
+ });
35
+
36
+ describe("multi grouping", function () {
37
+ it("should work", function () {
38
+ let data = [
39
+ { name: "John", age: 12 },
40
+ { name: "John", age: 12 },
41
+ { name: "John", age: 13 },
42
+ { name: "John", age: 14 },
43
+ { name: "Jane", age: 12 },
44
+ { name: "Jane", age: 13 },
45
+ { name: "Jane", age: 14 },
46
+ ];
47
+
48
+ let grouper = new Grouper({ name: { bind: "name" }, age: { bind: "age" } });
49
+ grouper.processAll(data);
50
+
51
+ let results = grouper.getResults();
52
+ // console.log(results);
53
+ assert.equal(results.length, 6);
54
+ assert.equal(results[0].records.length, 2);
55
+ });
56
+ });
57
+ });
@@ -1,43 +1,43 @@
1
- import { View, ViewConfig } from "./View";
2
- import { AugmentedViewBase } from "../data/AugmentedViewBase";
3
-
4
- export interface StructuredDataAccessor {
5
- getSelector(): (data: object) => Record<string, any>;
6
- get(): object;
7
- setItem(key: string, value: any): boolean;
8
- containsKey(key: string): boolean;
9
- getKeys(): string[];
10
- }
11
-
12
- export interface NestedDataViewConfig extends ViewConfig {
13
- nestedData?: StructuredDataAccessor;
14
- store: View;
15
- }
16
-
17
- export class NestedDataView extends AugmentedViewBase {
18
- declare nestedData?: StructuredDataAccessor;
19
-
20
- constructor(config: NestedDataViewConfig) {
21
- super(config);
22
- }
23
-
24
- protected embedAugmentData(result: Record<string, any>, parentStoreData: Record<string, any>): void {
25
- if (this.nestedData) {
26
- let nested = this.nestedData.getSelector()(parentStoreData);
27
- for (let key in nested) result[key] = nested[key];
28
- }
29
- }
30
-
31
- protected isExtraKey(key: string): boolean {
32
- return !!this.nestedData && this.nestedData.containsKey(key);
33
- }
34
-
35
- protected setExtraKeyValue(key: string, value: any): boolean {
36
- if (!this.nestedData) throw new Error("Internal error. This should not happen.");
37
- return this.nestedData.setItem(key, value);
38
- }
39
-
40
- protected deleteExtraKeyValue(key: string): boolean {
41
- return this.setExtraKeyValue(key, undefined);
42
- }
43
- }
1
+ import { View, ViewConfig } from "./View";
2
+ import { AugmentedViewBase } from "../data/AugmentedViewBase";
3
+
4
+ export interface StructuredDataAccessor {
5
+ getSelector(): (data: object) => Record<string, any>;
6
+ get(): object;
7
+ setItem(key: string, value: any): boolean;
8
+ containsKey(key: string): boolean;
9
+ getKeys(): string[];
10
+ }
11
+
12
+ export interface NestedDataViewConfig extends ViewConfig {
13
+ nestedData?: StructuredDataAccessor;
14
+ store: View;
15
+ }
16
+
17
+ export class NestedDataView extends AugmentedViewBase {
18
+ declare nestedData?: StructuredDataAccessor;
19
+
20
+ constructor(config: NestedDataViewConfig) {
21
+ super(config);
22
+ }
23
+
24
+ protected embedAugmentData(result: Record<string, any>, parentStoreData: Record<string, any>): void {
25
+ if (this.nestedData) {
26
+ let nested = this.nestedData.getSelector()(parentStoreData);
27
+ for (let key in nested) result[key] = nested[key];
28
+ }
29
+ }
30
+
31
+ protected isExtraKey(key: string): boolean {
32
+ return !!this.nestedData && this.nestedData.containsKey(key);
33
+ }
34
+
35
+ protected setExtraKeyValue(key: string, value: any): boolean {
36
+ if (!this.nestedData) throw new Error("Internal error. This should not happen.");
37
+ return this.nestedData.setItem(key, value);
38
+ }
39
+
40
+ protected deleteExtraKeyValue(key: string): boolean {
41
+ return this.setExtraKeyValue(key, undefined);
42
+ }
43
+ }
@@ -1,39 +1,39 @@
1
- import { View, ViewConfig } from "./View";
2
-
3
- export interface ReadOnlyDataViewConfig extends ViewConfig {
4
- data?: any;
5
- }
6
-
7
- export class ReadOnlyDataView extends View {
8
- declare store: View;
9
- declare data?: any;
10
- declare immutable?: boolean;
11
-
12
- constructor(config?: ReadOnlyDataViewConfig) {
13
- super(config);
14
- }
15
-
16
- getData(): any {
17
- if (this.sealed && this.meta.version === this.cache.version && this.cache.data === this.data)
18
- return this.cache.result;
19
-
20
- let data = this.store.getData();
21
- this.cache.result =
22
- this.sealed || this.immutable || this.store.sealed
23
- ? Object.assign({}, data, this.getAdditionalData(data))
24
- : Object.assign(data, this.getAdditionalData(data));
25
- this.cache.version = this.meta.version;
26
- this.cache.data = this.data;
27
- return this.cache.result;
28
- }
29
-
30
- getAdditionalData(data?: any): any {
31
- return this.data;
32
- }
33
-
34
- setData(data: any): void {
35
- this.data = data;
36
- }
37
- }
38
-
39
- ReadOnlyDataView.prototype.immutable = false;
1
+ import { View, ViewConfig } from "./View";
2
+
3
+ export interface ReadOnlyDataViewConfig extends ViewConfig {
4
+ data?: any;
5
+ }
6
+
7
+ export class ReadOnlyDataView extends View {
8
+ declare store: View;
9
+ declare data?: any;
10
+ declare immutable?: boolean;
11
+
12
+ constructor(config?: ReadOnlyDataViewConfig) {
13
+ super(config);
14
+ }
15
+
16
+ getData(): any {
17
+ if (this.sealed && this.meta.version === this.cache.version && this.cache.data === this.data)
18
+ return this.cache.result;
19
+
20
+ let data = this.store.getData();
21
+ this.cache.result =
22
+ this.sealed || this.immutable || this.store.sealed
23
+ ? Object.assign({}, data, this.getAdditionalData(data))
24
+ : Object.assign(data, this.getAdditionalData(data));
25
+ this.cache.version = this.meta.version;
26
+ this.cache.data = this.data;
27
+ return this.cache.result;
28
+ }
29
+
30
+ getAdditionalData(data?: any): any {
31
+ return this.data;
32
+ }
33
+
34
+ setData(data: any): void {
35
+ this.data = data;
36
+ }
37
+ }
38
+
39
+ ReadOnlyDataView.prototype.immutable = false;
package/src/data/Ref.ts CHANGED
@@ -1,104 +1,104 @@
1
- import { isFunction } from "../util/isFunction";
2
- import { Component } from "../util/Component";
3
- import { Binding } from "./Binding";
4
- import { View } from "./View";
5
- import { CanMemoize } from "./Selector";
6
-
7
- export interface RefConfig<T> {
8
- store?: View;
9
- path?: string;
10
- get?: () => T;
11
- set?: (value: T) => boolean;
12
- }
13
-
14
- export class Ref<T = any> extends Component implements CanMemoize<T> {
15
- declare isRef?: boolean;
16
-
17
- constructor(config: RefConfig<T>) {
18
- super(config);
19
- this.get = this.get.bind(this);
20
- if (this.set) this.set = this.set.bind(this);
21
- }
22
-
23
- get(): T {
24
- throw new Error("Ref's get method is not implemented.");
25
- }
26
-
27
- set(value: T): boolean {
28
- throw new Error("Ref's set method is not implemented.");
29
- }
30
-
31
- delete(): boolean {
32
- throw new Error("Ref's delete method is not implemented.");
33
- }
34
-
35
- // Component.init() override - no-op for compatibility
36
- init(): void;
37
- // Initialize ref value if it's currently undefined
38
- init(value: T): boolean;
39
- init(value?: T): boolean | void {
40
- if (value === undefined) return; // Component.init() compatibility
41
- if (this.get() === undefined) return this.set(value);
42
- return false;
43
- }
44
-
45
- toggle(): boolean {
46
- return this.set(!this.get() as T);
47
- }
48
-
49
- update(cb: (currentValue: T, ...args: any[]) => T, ...args: any[]): boolean {
50
- return this.set(cb(this.get(), ...args));
51
- }
52
-
53
- as(config: any): Ref {
54
- return Ref.create(config, {
55
- get: this.get,
56
- set: this.set,
57
- });
58
- }
59
-
60
- ref<ST = any>(path: string): Ref<ST> {
61
- let binding = Binding.get(path);
62
- return Ref.create({
63
- get: () => binding.value(this.get()),
64
- set: (value: any) => {
65
- let data = this.get();
66
- let newData = binding.set(data as Record<string, any>, value);
67
- if (data === newData) return false;
68
- return this.set(newData as T);
69
- },
70
- }) as Ref<ST>;
71
- }
72
-
73
- //allows the function to be passed as a selector, e.g. to computable or addTrigger
74
- memoize(): () => T {
75
- return this.get;
76
- }
77
- }
78
-
79
- Ref.prototype.isRef = true;
80
-
81
- Ref.factory = function (alias: any, config?: any, more?: any): Ref {
82
- if (isFunction(alias)) {
83
- let cfg = {
84
- ...config,
85
- ...more,
86
- };
87
-
88
- if (cfg.store) Object.assign(cfg, cfg.store.getMethods());
89
-
90
- let result = alias(cfg);
91
- if (result instanceof Ref) return result;
92
-
93
- return this.create({
94
- ...config,
95
- ...more,
96
- ...result,
97
- });
98
- }
99
-
100
- return this.create({
101
- ...config,
102
- ...more,
103
- });
104
- };
1
+ import { isFunction } from "../util/isFunction";
2
+ import { Component } from "../util/Component";
3
+ import { Binding } from "./Binding";
4
+ import { View } from "./View";
5
+ import { CanMemoize } from "./Selector";
6
+
7
+ export interface RefConfig<T> {
8
+ store?: View;
9
+ path?: string;
10
+ get?: () => T;
11
+ set?: (value: T) => boolean;
12
+ }
13
+
14
+ export class Ref<T = any> extends Component implements CanMemoize<T> {
15
+ declare isRef?: boolean;
16
+
17
+ constructor(config: RefConfig<T>) {
18
+ super(config);
19
+ this.get = this.get.bind(this);
20
+ if (this.set) this.set = this.set.bind(this);
21
+ }
22
+
23
+ get(): T {
24
+ throw new Error("Ref's get method is not implemented.");
25
+ }
26
+
27
+ set(value: T): boolean {
28
+ throw new Error("Ref's set method is not implemented.");
29
+ }
30
+
31
+ delete(): boolean {
32
+ throw new Error("Ref's delete method is not implemented.");
33
+ }
34
+
35
+ // Component.init() override - no-op for compatibility
36
+ init(): void;
37
+ // Initialize ref value if it's currently undefined
38
+ init(value: T): boolean;
39
+ init(value?: T): boolean | void {
40
+ if (value === undefined) return; // Component.init() compatibility
41
+ if (this.get() === undefined) return this.set(value);
42
+ return false;
43
+ }
44
+
45
+ toggle(): boolean {
46
+ return this.set(!this.get() as T);
47
+ }
48
+
49
+ update(cb: (currentValue: T, ...args: any[]) => T, ...args: any[]): boolean {
50
+ return this.set(cb(this.get(), ...args));
51
+ }
52
+
53
+ as(config: any): Ref {
54
+ return Ref.create(config, {
55
+ get: this.get,
56
+ set: this.set,
57
+ });
58
+ }
59
+
60
+ ref<ST = any>(path: string): Ref<ST> {
61
+ let binding = Binding.get(path);
62
+ return Ref.create({
63
+ get: () => binding.value(this.get()),
64
+ set: (value: any) => {
65
+ let data = this.get();
66
+ let newData = binding.set(data as Record<string, any>, value);
67
+ if (data === newData) return false;
68
+ return this.set(newData as T);
69
+ },
70
+ }) as Ref<ST>;
71
+ }
72
+
73
+ //allows the function to be passed as a selector, e.g. to computable or addTrigger
74
+ memoize(): () => T {
75
+ return this.get;
76
+ }
77
+ }
78
+
79
+ Ref.prototype.isRef = true;
80
+
81
+ Ref.factory = function (alias: any, config?: any, more?: any): Ref {
82
+ if (isFunction(alias)) {
83
+ let cfg = {
84
+ ...config,
85
+ ...more,
86
+ };
87
+
88
+ if (cfg.store) Object.assign(cfg, cfg.store.getMethods());
89
+
90
+ let result = alias(cfg);
91
+ if (result instanceof Ref) return result;
92
+
93
+ return this.create({
94
+ ...config,
95
+ ...more,
96
+ ...result,
97
+ });
98
+ }
99
+
100
+ return this.create({
101
+ ...config,
102
+ ...more,
103
+ });
104
+ };