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,113 +1,113 @@
1
- import { StructuredSelector } from "./StructuredSelector";
2
- import assert from "assert";
3
- import { createAccessorModelProxy } from "./createAccessorModelProxy";
4
-
5
- describe("StructuredSelector", function () {
6
- describe("#create()", function () {
7
- it("constants", function () {
8
- var x = {};
9
- var s = new StructuredSelector({
10
- props: {
11
- a: undefined,
12
- b: undefined,
13
- },
14
- values: {
15
- a: 1,
16
- b: 2,
17
- },
18
- }).create();
19
-
20
- assert.deepEqual(s(x), { a: 1, b: 2 });
21
- });
22
-
23
- it("bindings", function () {
24
- var x = { a: 1, b: 2 };
25
- var s = new StructuredSelector({
26
- props: {
27
- a: undefined,
28
- b: undefined,
29
- },
30
- values: {
31
- a: { bind: "b" },
32
- b: { bind: "a" },
33
- },
34
- }).create();
35
-
36
- assert.deepEqual(s(x), { a: 2, b: 1 });
37
- });
38
-
39
- it("templates", function () {
40
- var x = { a: 1, b: 2 };
41
- var s = new StructuredSelector({
42
- props: {
43
- a: undefined,
44
- b: undefined,
45
- },
46
- values: {
47
- a: { tpl: "b{a}" },
48
- b: { tpl: "a{b}" },
49
- },
50
- }).create();
51
-
52
- assert.deepEqual(s(x), { a: "b1", b: "a2" });
53
- });
54
-
55
- it("structured", function () {
56
- var x = { a: 1, b: 2 };
57
- var s = new StructuredSelector({
58
- props: {
59
- a: {
60
- structured: true,
61
- },
62
- b: undefined,
63
- },
64
- values: {
65
- a: {
66
- x: { expr: "{a} == 1" },
67
- y: { expr: "{b} == 1" },
68
- },
69
- b: { tpl: "a{b}" },
70
- },
71
- }).create();
72
-
73
- assert.deepEqual(s(x), { a: { x: true, y: false }, b: "a2" });
74
- });
75
- });
76
-
77
- it("structures do not change if data doesn't change", function () {
78
- var x = { a: 1, b: 2 };
79
- var s = new StructuredSelector({
80
- props: {
81
- a: {
82
- structured: true,
83
- },
84
- },
85
- values: {
86
- a: {
87
- x: { expr: "{a} == 1" },
88
- y: { expr: "{b} == 1" },
89
- },
90
- b: { tpl: "a{b}" },
91
- },
92
- }).create();
93
-
94
- let r1 = s(x);
95
- let r2 = s(x);
96
-
97
- assert.equal(r1, r2);
98
- });
99
-
100
- it("accessor model proxy works", function () {
101
- var x = { a: { b: 2 } };
102
- var m = createAccessorModelProxy<typeof x>();
103
- var s = new StructuredSelector({
104
- props: {
105
- b: undefined,
106
- },
107
- values: {
108
- b: m.a.b,
109
- },
110
- }).create();
111
- assert.deepEqual(s(x), { b: 2 });
112
- });
113
- });
1
+ import { StructuredSelector } from "./StructuredSelector";
2
+ import assert from "assert";
3
+ import { createAccessorModelProxy } from "./createAccessorModelProxy";
4
+
5
+ describe("StructuredSelector", function () {
6
+ describe("#create()", function () {
7
+ it("constants", function () {
8
+ var x = {};
9
+ var s = new StructuredSelector({
10
+ props: {
11
+ a: undefined,
12
+ b: undefined,
13
+ },
14
+ values: {
15
+ a: 1,
16
+ b: 2,
17
+ },
18
+ }).create();
19
+
20
+ assert.deepEqual(s(x), { a: 1, b: 2 });
21
+ });
22
+
23
+ it("bindings", function () {
24
+ var x = { a: 1, b: 2 };
25
+ var s = new StructuredSelector({
26
+ props: {
27
+ a: undefined,
28
+ b: undefined,
29
+ },
30
+ values: {
31
+ a: { bind: "b" },
32
+ b: { bind: "a" },
33
+ },
34
+ }).create();
35
+
36
+ assert.deepEqual(s(x), { a: 2, b: 1 });
37
+ });
38
+
39
+ it("templates", function () {
40
+ var x = { a: 1, b: 2 };
41
+ var s = new StructuredSelector({
42
+ props: {
43
+ a: undefined,
44
+ b: undefined,
45
+ },
46
+ values: {
47
+ a: { tpl: "b{a}" },
48
+ b: { tpl: "a{b}" },
49
+ },
50
+ }).create();
51
+
52
+ assert.deepEqual(s(x), { a: "b1", b: "a2" });
53
+ });
54
+
55
+ it("structured", function () {
56
+ var x = { a: 1, b: 2 };
57
+ var s = new StructuredSelector({
58
+ props: {
59
+ a: {
60
+ structured: true,
61
+ },
62
+ b: undefined,
63
+ },
64
+ values: {
65
+ a: {
66
+ x: { expr: "{a} == 1" },
67
+ y: { expr: "{b} == 1" },
68
+ },
69
+ b: { tpl: "a{b}" },
70
+ },
71
+ }).create();
72
+
73
+ assert.deepEqual(s(x), { a: { x: true, y: false }, b: "a2" });
74
+ });
75
+ });
76
+
77
+ it("structures do not change if data doesn't change", function () {
78
+ var x = { a: 1, b: 2 };
79
+ var s = new StructuredSelector({
80
+ props: {
81
+ a: {
82
+ structured: true,
83
+ },
84
+ },
85
+ values: {
86
+ a: {
87
+ x: { expr: "{a} == 1" },
88
+ y: { expr: "{b} == 1" },
89
+ },
90
+ b: { tpl: "a{b}" },
91
+ },
92
+ }).create();
93
+
94
+ let r1 = s(x);
95
+ let r2 = s(x);
96
+
97
+ assert.equal(r1, r2);
98
+ });
99
+
100
+ it("accessor model proxy works", function () {
101
+ var x = { a: { b: 2 } };
102
+ var m = createAccessorModelProxy<typeof x>();
103
+ var s = new StructuredSelector({
104
+ props: {
105
+ b: undefined,
106
+ },
107
+ values: {
108
+ b: m.a.b,
109
+ },
110
+ }).create();
111
+ assert.deepEqual(s(x), { b: 2 });
112
+ });
113
+ });
@@ -1,63 +1,63 @@
1
- import { View, ViewConfig } from "./View";
2
- import { SubscriberList } from "../util/SubscriberList";
3
-
4
- export interface SubscribableViewConfig extends ViewConfig {
5
- async?: boolean;
6
- }
7
-
8
- export class SubscribableView<D> extends View<D> {
9
- subscribers?: any;
10
- changes: string[];
11
- declare async: boolean;
12
- scheduled: boolean;
13
-
14
- constructor(config?: SubscribableViewConfig) {
15
- super(config);
16
- this.subscribers = new SubscriberList();
17
- this.changes = [];
18
- }
19
-
20
- subscribe(callback: () => void) {
21
- return this.subscribers.subscribe(callback);
22
- }
23
-
24
- unsubscribeAll() {
25
- this.subscribers.clear();
26
- }
27
-
28
- doNotify(path: string) {
29
- if (this.notificationsSuspended) return;
30
-
31
- if (!this.async) {
32
- this.subscribers.notify([path]);
33
- } else {
34
- this.changes.push(path || "");
35
- if (!this.scheduled) {
36
- this.scheduled = true;
37
- setTimeout(() => {
38
- this.scheduled = false;
39
- let changes = this.changes;
40
- this.changes = [];
41
- this.subscribers.notify(changes);
42
- }, 0);
43
- }
44
- }
45
- }
46
-
47
- silently(callback: (store?: View) => void) {
48
- this.notificationsSuspended = (this.notificationsSuspended || 0) + 1;
49
- let wasDirty = this.dirty,
50
- dirty;
51
- this.dirty = false;
52
- try {
53
- callback(this);
54
- } finally {
55
- this.notificationsSuspended--;
56
- dirty = this.dirty;
57
- this.dirty = wasDirty;
58
- }
59
- return dirty;
60
- }
61
- }
62
-
63
- SubscribableView.prototype.async = false;
1
+ import { View, ViewConfig } from "./View";
2
+ import { SubscriberList } from "../util/SubscriberList";
3
+
4
+ export interface SubscribableViewConfig extends ViewConfig {
5
+ async?: boolean;
6
+ }
7
+
8
+ export class SubscribableView<D> extends View<D> {
9
+ subscribers?: any;
10
+ changes: string[];
11
+ declare async: boolean;
12
+ scheduled: boolean;
13
+
14
+ constructor(config?: SubscribableViewConfig) {
15
+ super(config);
16
+ this.subscribers = new SubscriberList();
17
+ this.changes = [];
18
+ }
19
+
20
+ subscribe(callback: () => void) {
21
+ return this.subscribers.subscribe(callback);
22
+ }
23
+
24
+ unsubscribeAll() {
25
+ this.subscribers.clear();
26
+ }
27
+
28
+ doNotify(path: string) {
29
+ if (this.notificationsSuspended) return;
30
+
31
+ if (!this.async) {
32
+ this.subscribers.notify([path]);
33
+ } else {
34
+ this.changes.push(path || "");
35
+ if (!this.scheduled) {
36
+ this.scheduled = true;
37
+ setTimeout(() => {
38
+ this.scheduled = false;
39
+ let changes = this.changes;
40
+ this.changes = [];
41
+ this.subscribers.notify(changes);
42
+ }, 0);
43
+ }
44
+ }
45
+ }
46
+
47
+ silently(callback: (store?: View) => void) {
48
+ this.notificationsSuspended = (this.notificationsSuspended || 0) + 1;
49
+ let wasDirty = this.dirty,
50
+ dirty;
51
+ this.dirty = false;
52
+ try {
53
+ callback(this);
54
+ } finally {
55
+ this.notificationsSuspended--;
56
+ dirty = this.dirty;
57
+ this.dirty = wasDirty;
58
+ }
59
+ return dirty;
60
+ }
61
+ }
62
+
63
+ SubscribableView.prototype.async = false;
@@ -1,45 +1,45 @@
1
- import { Binding } from "./Binding";
2
- import { NestedDataView, NestedDataViewConfig } from "./NestedDataView";
3
-
4
- export interface ZoomIntoPropertyViewConfig extends NestedDataViewConfig {
5
- binding: Binding;
6
- rootName?: string;
7
- }
8
-
9
- export class ZoomIntoPropertyView extends NestedDataView {
10
- declare binding: Binding;
11
- declare rootName: string;
12
-
13
- constructor(config: ZoomIntoPropertyViewConfig) {
14
- super(config);
15
- }
16
-
17
- protected getBaseData(parentStoreData: any): any {
18
- let x = this.binding.value(parentStoreData);
19
- if (x != null && typeof x != "object") throw new Error("Zoomed value must be an object.");
20
- return {
21
- ...x,
22
- };
23
- }
24
-
25
- protected embedAugmentData(result: any, parentStoreData: any): void {
26
- result[this.rootName] = parentStoreData;
27
- super.embedAugmentData(result, parentStoreData);
28
- }
29
-
30
- setItem(path: string, value: any): boolean {
31
- if (path.indexOf(this.rootName + ".") == 0)
32
- return this.store.setItem(path.substring(this.rootName.length + 1), value);
33
- if (this.isExtraKey(Binding.get(path).parts[0])) return super.setItem(path, value);
34
- return super.setItem(this.binding.path + "." + path, value);
35
- }
36
-
37
- deleteItem(path: string): boolean {
38
- if (path.indexOf(this.rootName + ".") == 0)
39
- return this.store.deleteItem(path.substring(this.rootName.length + 1));
40
- if (this.isExtraKey(Binding.get(path).parts[0])) return super.deleteItem(path);
41
- return super.deleteItem(this.binding.path + "." + path);
42
- }
43
- }
44
-
45
- ZoomIntoPropertyView.prototype.rootName = "$root";
1
+ import { Binding } from "./Binding";
2
+ import { NestedDataView, NestedDataViewConfig } from "./NestedDataView";
3
+
4
+ export interface ZoomIntoPropertyViewConfig extends NestedDataViewConfig {
5
+ binding: Binding;
6
+ rootName?: string;
7
+ }
8
+
9
+ export class ZoomIntoPropertyView extends NestedDataView {
10
+ declare binding: Binding;
11
+ declare rootName: string;
12
+
13
+ constructor(config: ZoomIntoPropertyViewConfig) {
14
+ super(config);
15
+ }
16
+
17
+ protected getBaseData(parentStoreData: any): any {
18
+ let x = this.binding.value(parentStoreData);
19
+ if (x != null && typeof x != "object") throw new Error("Zoomed value must be an object.");
20
+ return {
21
+ ...x,
22
+ };
23
+ }
24
+
25
+ protected embedAugmentData(result: any, parentStoreData: any): void {
26
+ result[this.rootName] = parentStoreData;
27
+ super.embedAugmentData(result, parentStoreData);
28
+ }
29
+
30
+ setItem(path: string, value: any): boolean {
31
+ if (path.indexOf(this.rootName + ".") == 0)
32
+ return this.store.setItem(path.substring(this.rootName.length + 1), value);
33
+ if (this.isExtraKey(Binding.get(path).parts[0])) return super.setItem(path, value);
34
+ return super.setItem(this.binding.path + "." + path, value);
35
+ }
36
+
37
+ deleteItem(path: string): boolean {
38
+ if (path.indexOf(this.rootName + ".") == 0)
39
+ return this.store.deleteItem(path.substring(this.rootName.length + 1));
40
+ if (this.isExtraKey(Binding.get(path).parts[0])) return super.deleteItem(path);
41
+ return super.deleteItem(this.binding.path + "." + path);
42
+ }
43
+ }
44
+
45
+ ZoomIntoPropertyView.prototype.rootName = "$root";
@@ -1,78 +1,78 @@
1
- import { getSelector } from "./getSelector";
2
- import { isDefined } from "../util/isDefined";
3
- import { defaultCompare } from "./defaultCompare";
4
-
5
- interface Sorter {
6
- value?: any;
7
- field?: string;
8
- direction?: string;
9
- comparer?: (a: any, b: any) => number;
10
- compare?: (a: any, b: any) => number;
11
- }
12
-
13
- export function getComparer(
14
- sorters: Sorter[],
15
- dataAccessor?: (x: any) => any,
16
- comparer?: (a: any, b: any) => number,
17
- ): (a: any, b: any) => number {
18
- let resolvedSorters = (sorters || []).map((s) => {
19
- let selector = isDefined(s.value)
20
- ? getSelector(s.value)
21
- : s.field
22
- ? (x: Record<string, any>) => x[s.field!]
23
- : () => null;
24
- return {
25
- getter: dataAccessor ? (x: any) => selector(dataAccessor(x)) : selector,
26
- factor: s.direction && s.direction[0].toLowerCase() == "d" ? -1 : 1,
27
- compare: s.comparer || s.compare || comparer || defaultCompare,
28
- };
29
- });
30
-
31
- return function (a, b) {
32
- let d, av, bv;
33
- for (let i = 0; i < resolvedSorters.length; i++) {
34
- d = resolvedSorters[i];
35
- av = d.getter(a);
36
- bv = d.getter(b);
37
-
38
- // show nulls always on the bottom
39
- if (av == null) {
40
- if (bv == null) continue;
41
- else return 1;
42
- }
43
- if (bv == null) return -1;
44
-
45
- let r = d.compare(av, bv);
46
- if (r == 0) continue;
47
- return d.factor * r;
48
- }
49
- return 0;
50
- };
51
- }
52
-
53
- export function indexSorter(
54
- sorters: Sorter[],
55
- dataAccessor?: (x: any) => any,
56
- compare?: (a: any, b: any) => number,
57
- ): (data: any[]) => number[] {
58
- let cmp = getComparer(sorters, dataAccessor, compare);
59
- return function (data) {
60
- let result = Array.from({ length: data.length }, (v, k) => k);
61
- result.sort((ia, ib) => cmp(data[ia], data[ib]));
62
- return result;
63
- };
64
- }
65
-
66
- export function sorter(
67
- sorters: Sorter[],
68
- dataAccessor?: (x: any) => any,
69
- compare?: (a: any, b: any) => number,
70
- ): (data: any[]) => any[] {
71
- let cmp = getComparer(sorters, dataAccessor, compare);
72
-
73
- return function (data) {
74
- let result = [...data];
75
- result.sort(cmp);
76
- return result;
77
- };
78
- }
1
+ import { getSelector } from "./getSelector";
2
+ import { isDefined } from "../util/isDefined";
3
+ import { defaultCompare } from "./defaultCompare";
4
+
5
+ interface Sorter {
6
+ value?: any;
7
+ field?: string;
8
+ direction?: string;
9
+ comparer?: (a: any, b: any) => number;
10
+ compare?: (a: any, b: any) => number;
11
+ }
12
+
13
+ export function getComparer(
14
+ sorters: Sorter[],
15
+ dataAccessor?: (x: any) => any,
16
+ comparer?: (a: any, b: any) => number,
17
+ ): (a: any, b: any) => number {
18
+ let resolvedSorters = (sorters || []).map((s) => {
19
+ let selector = isDefined(s.value)
20
+ ? getSelector(s.value)
21
+ : s.field
22
+ ? (x: Record<string, any>) => x[s.field!]
23
+ : () => null;
24
+ return {
25
+ getter: dataAccessor ? (x: any) => selector(dataAccessor(x)) : selector,
26
+ factor: s.direction && s.direction[0].toLowerCase() == "d" ? -1 : 1,
27
+ compare: s.comparer || s.compare || comparer || defaultCompare,
28
+ };
29
+ });
30
+
31
+ return function (a, b) {
32
+ let d, av, bv;
33
+ for (let i = 0; i < resolvedSorters.length; i++) {
34
+ d = resolvedSorters[i];
35
+ av = d.getter(a);
36
+ bv = d.getter(b);
37
+
38
+ // show nulls always on the bottom
39
+ if (av == null) {
40
+ if (bv == null) continue;
41
+ else return 1;
42
+ }
43
+ if (bv == null) return -1;
44
+
45
+ let r = d.compare(av, bv);
46
+ if (r == 0) continue;
47
+ return d.factor * r;
48
+ }
49
+ return 0;
50
+ };
51
+ }
52
+
53
+ export function indexSorter(
54
+ sorters: Sorter[],
55
+ dataAccessor?: (x: any) => any,
56
+ compare?: (a: any, b: any) => number,
57
+ ): (data: any[]) => number[] {
58
+ let cmp = getComparer(sorters, dataAccessor, compare);
59
+ return function (data) {
60
+ let result = Array.from({ length: data.length }, (v, k) => k);
61
+ result.sort((ia, ib) => cmp(data[ia], data[ib]));
62
+ return result;
63
+ };
64
+ }
65
+
66
+ export function sorter(
67
+ sorters: Sorter[],
68
+ dataAccessor?: (x: any) => any,
69
+ compare?: (a: any, b: any) => number,
70
+ ): (data: any[]) => any[] {
71
+ let cmp = getComparer(sorters, dataAccessor, compare);
72
+
73
+ return function (data) {
74
+ let result = [...data];
75
+ result.sort(cmp);
76
+ return result;
77
+ };
78
+ }
@@ -1,31 +1,31 @@
1
- export function updateArray<T = any>(
2
- array: T[] | undefined,
3
- updateCallback: (item: T, index: number) => T,
4
- itemFilter?: null | ((item: T, index: number) => boolean),
5
- removeFilter?: (item: T, index: number) => boolean,
6
- ): T[] | undefined {
7
- if (!array) return array;
8
-
9
- const newArray: T[] = [];
10
- let dirty: boolean = false;
11
-
12
- for (let index = 0; index < array.length; index++) {
13
- const item = array[index];
14
-
15
- if (removeFilter && removeFilter(item, index)) {
16
- dirty = true;
17
- continue;
18
- }
19
-
20
- if (!itemFilter || itemFilter(item, index)) {
21
- const newItem = updateCallback(item, index);
22
- newArray.push(newItem);
23
-
24
- if (newItem !== item) dirty = true;
25
- } else {
26
- newArray.push(item);
27
- }
28
- }
29
-
30
- return dirty ? newArray : array;
31
- }
1
+ export function updateArray<T = any>(
2
+ array: T[] | undefined,
3
+ updateCallback: (item: T, index: number) => T,
4
+ itemFilter?: null | ((item: T, index: number) => boolean),
5
+ removeFilter?: (item: T, index: number) => boolean,
6
+ ): T[] | undefined {
7
+ if (!array) return array;
8
+
9
+ const newArray: T[] = [];
10
+ let dirty: boolean = false;
11
+
12
+ for (let index = 0; index < array.length; index++) {
13
+ const item = array[index];
14
+
15
+ if (removeFilter && removeFilter(item, index)) {
16
+ dirty = true;
17
+ continue;
18
+ }
19
+
20
+ if (!itemFilter || itemFilter(item, index)) {
21
+ const newItem = updateCallback(item, index);
22
+ newArray.push(newItem);
23
+
24
+ if (newItem !== item) dirty = true;
25
+ } else {
26
+ newArray.push(item);
27
+ }
28
+ }
29
+
30
+ return dirty ? newArray : array;
31
+ }