cx 26.0.3 → 26.0.5

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 (123) hide show
  1. package/build/data/ArrayElementView.spec.js +1 -1
  2. package/build/hooks/store.spec.js +1 -1
  3. package/build/hooks/useTrigger.spec.js +1 -1
  4. package/build/ui/Controller.spec.js +2 -6
  5. package/build/ui/PureContainer.spec.d.ts +1 -0
  6. package/build/ui/PureContainer.spec.js +149 -0
  7. package/build/ui/layout/ContentPlaceholder.spec.js +12 -12
  8. package/build.js +129 -129
  9. package/dist/manifest.d.ts +1443 -0
  10. package/dist/manifest.js +826 -826
  11. package/package.json +4 -3
  12. package/src/charts/Chart.ts +108 -108
  13. package/src/data/ArrayElementView.ts +90 -90
  14. package/src/data/AugmentedViewBase.ts +88 -88
  15. package/src/data/Binding.ts +104 -104
  16. package/src/data/ExposedRecordView.ts +95 -95
  17. package/src/data/ExposedValueView.ts +89 -89
  18. package/src/data/Expression.spec.ts +229 -229
  19. package/src/data/Expression.ts +233 -233
  20. package/src/data/Grouper.spec.ts +57 -57
  21. package/src/data/Grouper.ts +158 -158
  22. package/src/data/NestedDataView.ts +43 -43
  23. package/src/data/ReadOnlyDataView.ts +39 -39
  24. package/src/data/Ref.ts +104 -104
  25. package/src/data/Selector.ts +10 -10
  26. package/src/data/Store.ts +52 -52
  27. package/src/data/StoreProxy.ts +19 -19
  28. package/src/data/StoreRef.ts +66 -66
  29. package/src/data/StringTemplate.spec.ts +132 -132
  30. package/src/data/StringTemplate.ts +93 -93
  31. package/src/data/StructuredSelector.spec.ts +113 -113
  32. package/src/data/StructuredSelector.ts +146 -146
  33. package/src/data/SubscribableView.ts +63 -63
  34. package/src/data/ZoomIntoPropertyView.spec.ts +64 -64
  35. package/src/data/ZoomIntoPropertyView.ts +45 -45
  36. package/src/data/computable.spec.ts +62 -62
  37. package/src/data/createAccessorModelProxy.ts +60 -60
  38. package/src/data/createStructuredSelector.ts +62 -62
  39. package/src/data/getAccessor.spec.ts +11 -11
  40. package/src/data/getAccessor.ts +74 -74
  41. package/src/data/getSelector.spec.ts +43 -43
  42. package/src/data/getSelector.ts +66 -66
  43. package/src/data/ops/filter.spec.ts +35 -35
  44. package/src/data/ops/filter.ts +9 -9
  45. package/src/data/ops/merge.ts +13 -13
  46. package/src/data/ops/removeTreeNodes.spec.ts +37 -37
  47. package/src/data/ops/removeTreeNodes.ts +15 -15
  48. package/src/data/ops/updateArray.spec.ts +69 -69
  49. package/src/data/ops/updateArray.ts +31 -31
  50. package/src/data/ops/updateTree.ts +23 -23
  51. package/src/data/test-types.ts +7 -7
  52. package/src/hooks/useTrigger.ts +26 -26
  53. package/src/index.scss +6 -6
  54. package/src/jsx-runtime.ts +72 -72
  55. package/src/svg/BoundedObject.ts +101 -101
  56. package/src/ui/CSSHelper.ts +17 -17
  57. package/src/ui/ContentResolver.ts +124 -124
  58. package/src/ui/Controller.ts +189 -189
  59. package/src/ui/Culture.ts +159 -159
  60. package/src/ui/DataProxy.ts +55 -55
  61. package/src/ui/FocusManager.ts +171 -171
  62. package/src/ui/Instance.ts +868 -868
  63. package/src/ui/RenderingContext.ts +99 -99
  64. package/src/ui/Rescope.ts +49 -49
  65. package/src/ui/StructuredInstanceDataAccessor.ts +32 -32
  66. package/src/ui/VDOM.ts +34 -34
  67. package/src/ui/adapter/ArrayAdapter.spec.ts +55 -55
  68. package/src/ui/adapter/ArrayAdapter.ts +226 -226
  69. package/src/ui/adapter/TreeAdapter.spec.ts +76 -76
  70. package/src/ui/adapter/TreeAdapter.ts +185 -185
  71. package/src/ui/app/History.ts +133 -133
  72. package/src/ui/app/Url.spec.ts +50 -50
  73. package/src/ui/app/startHotAppLoop.ts +40 -40
  74. package/src/ui/createFunctionalComponent.ts +65 -65
  75. package/src/ui/index.ts +45 -45
  76. package/src/ui/layout/Content.ts +30 -30
  77. package/src/ui/layout/FirstVisibleChildLayout.ts +60 -60
  78. package/src/ui/selection/KeySelection.ts +165 -165
  79. package/src/ui/selection/PropertySelection.ts +87 -87
  80. package/src/ui/selection/Selection.ts +118 -118
  81. package/src/util/Format.ts +267 -267
  82. package/src/util/browserSupportsPassiveEventHandlers.ts +20 -20
  83. package/src/util/color/rgbToHsl.ts +35 -35
  84. package/src/util/getActiveElement.ts +4 -4
  85. package/src/util/hasKey.ts +18 -18
  86. package/src/util/index.ts +55 -55
  87. package/src/util/innerTextTrim.ts +10 -10
  88. package/src/util/isArray.ts +3 -3
  89. package/src/util/isDataRecord.ts +5 -5
  90. package/src/util/isDefined.ts +3 -3
  91. package/src/util/isString.ts +3 -3
  92. package/src/widgets/Sandbox.ts +103 -103
  93. package/src/widgets/autoFocus.ts +9 -9
  94. package/src/widgets/cx.ts +63 -63
  95. package/src/widgets/grid/GridCell.ts +143 -143
  96. package/src/widgets/icons/calendar.tsx +17 -17
  97. package/src/widgets/icons/check.tsx +13 -13
  98. package/src/widgets/icons/clear.tsx +15 -15
  99. package/src/widgets/icons/close.tsx +20 -20
  100. package/src/widgets/icons/cx.tsx +38 -38
  101. package/src/widgets/icons/drop-down.tsx +15 -15
  102. package/src/widgets/icons/file.tsx +13 -13
  103. package/src/widgets/icons/folder-open.tsx +15 -15
  104. package/src/widgets/icons/folder.tsx +13 -13
  105. package/src/widgets/icons/forward.tsx +22 -22
  106. package/src/widgets/icons/loading.tsx +24 -24
  107. package/src/widgets/icons/menu.tsx +17 -17
  108. package/src/widgets/icons/pixel-picker.tsx +18 -18
  109. package/src/widgets/icons/search.tsx +13 -13
  110. package/src/widgets/icons/sort-asc.tsx +14 -14
  111. package/src/widgets/icons/square.tsx +18 -18
  112. package/src/widgets/nav/Route.ts +142 -142
  113. package/src/widgets/overlay/ContextMenu.ts +42 -42
  114. package/src/widgets/overlay/Dropdown.tsx +762 -762
  115. package/src/widgets/overlay/MsgBox.tsx +141 -141
  116. package/src/widgets/overlay/Toast.ts +111 -111
  117. package/src/widgets/overlay/Window.tsx +299 -299
  118. package/src/widgets/overlay/alerts.ts +46 -46
  119. package/src/widgets/overlay/captureMouse.ts +195 -195
  120. package/src/widgets/overlay/createHotPromiseWindowFactory.ts +72 -72
  121. package/src/widgets/overlay/index.d.ts +11 -11
  122. package/src/widgets/overlay/index.ts +11 -11
  123. package/src/widgets/overlay/tooltip-ops.ts +173 -173
@@ -1,22 +1,22 @@
1
- /** @jsxImportSource react */
2
- import {VDOM} from '../../ui/Widget';
3
- import {registerIcon} from './registry';
4
-
5
- export default registerIcon('forward', (props: any) => {
6
- return <svg
7
- {...props}
8
- viewBox="0 0 20 20">
9
-
10
- <path fill="currentColor"
11
- strokeWidth="0"
12
- stroke="currentColor"
13
- d="M10.15 15.5L14.5 10l-4.33-5.47-.65.47 3.98 5-4 5z" />
14
-
15
- <path fill="currentColor"
16
- strokeWidth="0"
17
- stroke="currentColor"
18
- d="M6.15 15.5L10.5 10 6.17 4.53 5.52 5l3.98 5-4 5z" />
19
-
20
- </svg>
21
- }, true);
22
-
1
+ /** @jsxImportSource react */
2
+ import {VDOM} from '../../ui/Widget';
3
+ import {registerIcon} from './registry';
4
+
5
+ export default registerIcon('forward', (props: any) => {
6
+ return <svg
7
+ {...props}
8
+ viewBox="0 0 20 20">
9
+
10
+ <path fill="currentColor"
11
+ strokeWidth="0"
12
+ stroke="currentColor"
13
+ d="M10.15 15.5L14.5 10l-4.33-5.47-.65.47 3.98 5-4 5z" />
14
+
15
+ <path fill="currentColor"
16
+ strokeWidth="0"
17
+ stroke="currentColor"
18
+ d="M6.15 15.5L10.5 10 6.17 4.53 5.52 5l3.98 5-4 5z" />
19
+
20
+ </svg>
21
+ }, true);
22
+
@@ -1,24 +1,24 @@
1
- /** @jsxImportSource react */
2
- import {VDOM} from '../../ui/Widget';
3
- import {registerIcon} from './registry';
4
-
5
- export default registerIcon('loading', (props: any) => {
6
- let style = {
7
- animation: 'linear infinite 0.5s cx-rotate'
8
- };
9
-
10
- if (props && props.style)
11
- Object.assign(style, props.style);
12
-
13
- props = {
14
- ...props,
15
- style
16
- };
17
-
18
- return <svg
19
- {...props}
20
- viewBox="0 0 50 50">
21
- <path fill="currentColor" d="M43.94 25.14c0-10.3-8.37-18.68-18.7-18.68-10.3 0-18.67 8.37-18.67 18.68h4.07c0-8.07 6.54-14.6 14.6-14.6 8.08 0 14.63 6.53 14.63 14.6h4.07z" />
22
- </svg>
23
- }, true);
24
-
1
+ /** @jsxImportSource react */
2
+ import {VDOM} from '../../ui/Widget';
3
+ import {registerIcon} from './registry';
4
+
5
+ export default registerIcon('loading', (props: any) => {
6
+ let style = {
7
+ animation: 'linear infinite 0.5s cx-rotate'
8
+ };
9
+
10
+ if (props && props.style)
11
+ Object.assign(style, props.style);
12
+
13
+ props = {
14
+ ...props,
15
+ style
16
+ };
17
+
18
+ return <svg
19
+ {...props}
20
+ viewBox="0 0 50 50">
21
+ <path fill="currentColor" d="M43.94 25.14c0-10.3-8.37-18.68-18.7-18.68-10.3 0-18.67 8.37-18.67 18.68h4.07c0-8.07 6.54-14.6 14.6-14.6 8.08 0 14.63 6.53 14.63 14.6h4.07z" />
22
+ </svg>
23
+ }, true);
24
+
@@ -1,17 +1,17 @@
1
- /** @jsxImportSource react */
2
- import {VDOM} from '../../ui/Widget';
3
- import {registerIcon} from './registry';
4
-
5
- export default registerIcon('menu', (props: any) => {
6
- return <svg
7
- {...props}
8
- viewBox="0 0 24 24">
9
-
10
- <path d="M0 0h24v24H0z"
11
- fill="none" />
12
- <path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"
13
- fill="currentColor" />
14
-
15
- </svg>
16
- }, true);
17
-
1
+ /** @jsxImportSource react */
2
+ import {VDOM} from '../../ui/Widget';
3
+ import {registerIcon} from './registry';
4
+
5
+ export default registerIcon('menu', (props: any) => {
6
+ return <svg
7
+ {...props}
8
+ viewBox="0 0 24 24">
9
+
10
+ <path d="M0 0h24v24H0z"
11
+ fill="none" />
12
+ <path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"
13
+ fill="currentColor" />
14
+
15
+ </svg>
16
+ }, true);
17
+
@@ -1,18 +1,18 @@
1
- /** @jsxImportSource react */
2
- import { VDOM } from "../../ui/Widget";
3
- import { registerIcon } from "./registry";
4
-
5
- export default registerIcon(
6
- "pixel-picker",
7
- (props: any) => {
8
- return (
9
- <svg {...props} viewBox="0 0 30 30">
10
- <path
11
- d="M27.7,3.3c-1.5-1.5-3.9-1.5-5.4,0L17,8.6l-1.3-1.3c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l1.3,1.3L5,20.6 c-0.6,0.6-1,1.4-1.1,2.3C3.3,23.4,3,24.2,3,25c0,1.7,1.3,3,3,3c0.8,0,1.6-0.3,2.2-0.9C9,27,9.8,26.6,10.4,26L21,15.4l1.3,1.3 c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4L22.4,14l5.3-5.3C29.2,7.2,29.2,4.8,27.7,3.3z M9,24.6 c-0.4,0.4-0.8,0.6-1.3,0.5c-0.4,0-0.7,0.2-0.9,0.5C6.7,25.8,6.3,26,6,26c-0.6,0-1-0.4-1-1c0-0.3,0.2-0.7,0.5-0.8 c0.3-0.2,0.5-0.5,0.5-0.9c0-0.5,0.2-1,0.5-1.3L17,11.4l2.6,2.6L9,24.6z"
12
- fill="currentColor"
13
- />
14
- </svg>
15
- );
16
- },
17
- true
18
- );
1
+ /** @jsxImportSource react */
2
+ import { VDOM } from "../../ui/Widget";
3
+ import { registerIcon } from "./registry";
4
+
5
+ export default registerIcon(
6
+ "pixel-picker",
7
+ (props: any) => {
8
+ return (
9
+ <svg {...props} viewBox="0 0 30 30">
10
+ <path
11
+ d="M27.7,3.3c-1.5-1.5-3.9-1.5-5.4,0L17,8.6l-1.3-1.3c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l1.3,1.3L5,20.6 c-0.6,0.6-1,1.4-1.1,2.3C3.3,23.4,3,24.2,3,25c0,1.7,1.3,3,3,3c0.8,0,1.6-0.3,2.2-0.9C9,27,9.8,26.6,10.4,26L21,15.4l1.3,1.3 c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4L22.4,14l5.3-5.3C29.2,7.2,29.2,4.8,27.7,3.3z M9,24.6 c-0.4,0.4-0.8,0.6-1.3,0.5c-0.4,0-0.7,0.2-0.9,0.5C6.7,25.8,6.3,26,6,26c-0.6,0-1-0.4-1-1c0-0.3,0.2-0.7,0.5-0.8 c0.3-0.2,0.5-0.5,0.5-0.9c0-0.5,0.2-1,0.5-1.3L17,11.4l2.6,2.6L9,24.6z"
12
+ fill="currentColor"
13
+ />
14
+ </svg>
15
+ );
16
+ },
17
+ true
18
+ );
@@ -1,13 +1,13 @@
1
- /** @jsxImportSource react */
2
- import {VDOM} from '../../ui/Widget';
3
- import {registerIcon} from './registry';
4
-
5
- export default registerIcon('search', (props: any) => {
6
- return <svg
7
- {...props}
8
- viewBox="0 0 32 32">
9
- <path fill="currentColor"
10
- d="M25.595 22.036l-5.26-5.075c.75-1.18 1.206-2.56 1.206-4.05 0-4.32-3.63-7.82-8.103-7.82-4.477 0-8.107 3.503-8.107 7.82 0 4.32 3.63 7.825 8.106 7.825 1.544 0 2.972-.44 4.198-1.162l5.26 5.074c.37.356.98.354 1.35 0l1.352-1.304c.37-.357.37-.947 0-1.304zm-12.16-3.91c-2.985 0-5.405-2.336-5.405-5.216 0-2.88 2.42-5.214 5.405-5.214 2.984 0 5.404 2.335 5.404 5.214 0 2.88-2.42 5.215-5.407 5.215z" />
11
- </svg>
12
- }, true);
13
-
1
+ /** @jsxImportSource react */
2
+ import {VDOM} from '../../ui/Widget';
3
+ import {registerIcon} from './registry';
4
+
5
+ export default registerIcon('search', (props: any) => {
6
+ return <svg
7
+ {...props}
8
+ viewBox="0 0 32 32">
9
+ <path fill="currentColor"
10
+ d="M25.595 22.036l-5.26-5.075c.75-1.18 1.206-2.56 1.206-4.05 0-4.32-3.63-7.82-8.103-7.82-4.477 0-8.107 3.503-8.107 7.82 0 4.32 3.63 7.825 8.106 7.825 1.544 0 2.972-.44 4.198-1.162l5.26 5.074c.37.356.98.354 1.35 0l1.352-1.304c.37-.357.37-.947 0-1.304zm-12.16-3.91c-2.985 0-5.405-2.336-5.405-5.216 0-2.88 2.42-5.214 5.405-5.214 2.984 0 5.404 2.335 5.404 5.214 0 2.88-2.42 5.215-5.407 5.215z" />
11
+ </svg>
12
+ }, true);
13
+
@@ -1,14 +1,14 @@
1
- /** @jsxImportSource react */
2
- import {VDOM} from '../../ui/Widget';
3
- import {registerIcon} from './registry';
4
-
5
- export default registerIcon('sort-asc', (props: any) => {
6
- return <svg
7
- {...props}
8
- viewBox="0 0 16 16">
9
- <path fill="currentColor"
10
- d="M10.5 5.8l-3-3-3 3 .707.708L7 4.688v8.312h1V4.69l1.793 1.817z"
11
- />
12
- </svg>
13
- }, true);
14
-
1
+ /** @jsxImportSource react */
2
+ import {VDOM} from '../../ui/Widget';
3
+ import {registerIcon} from './registry';
4
+
5
+ export default registerIcon('sort-asc', (props: any) => {
6
+ return <svg
7
+ {...props}
8
+ viewBox="0 0 16 16">
9
+ <path fill="currentColor"
10
+ d="M10.5 5.8l-3-3-3 3 .707.708L7 4.688v8.312h1V4.69l1.793 1.817z"
11
+ />
12
+ </svg>
13
+ }, true);
14
+
@@ -1,18 +1,18 @@
1
- /** @jsxImportSource react */
2
- import {VDOM} from '../../ui/Widget';
3
- import {registerIcon} from './registry';
4
-
5
- export default registerIcon('square', (props: any) => {
6
- return <svg
7
- {...props}
8
- viewBox="0 0 64 64">
9
- <rect
10
- x="12"
11
- y="12"
12
- width="40"
13
- height="40"
14
- fill="currentColor"
15
- />
16
- </svg>
17
- }, true);
18
-
1
+ /** @jsxImportSource react */
2
+ import {VDOM} from '../../ui/Widget';
3
+ import {registerIcon} from './registry';
4
+
5
+ export default registerIcon('square', (props: any) => {
6
+ return <svg
7
+ {...props}
8
+ viewBox="0 0 64 64">
9
+ <rect
10
+ x="12"
11
+ y="12"
12
+ width="40"
13
+ height="40"
14
+ fill="currentColor"
15
+ />
16
+ </svg>
17
+ }, true);
18
+
@@ -1,142 +1,142 @@
1
- import { Widget } from "../../ui/Widget";
2
- import { PureContainerBase, PureContainerConfig } from "../../ui/PureContainer";
3
- import RouteMatcher from "route-parser";
4
- import { ReadOnlyDataView } from "../../data/ReadOnlyDataView";
5
- import { routeAppend } from "../../util/routeAppend";
6
- import { StringProp, BooleanProp, Prop } from "../../ui/Prop";
7
- import { RenderingContext } from "../../ui/RenderingContext";
8
- import { Instance } from "../../ui/Instance";
9
-
10
- export interface RouteConfig extends PureContainerConfig {
11
- /** Url binding. Bind this to the global `url` variable. */
12
- url?: StringProp;
13
-
14
- /** Target route, e.g. `~/user/:userId`. All routes should start with `~/`. */
15
- route?: string;
16
-
17
- /** Target route, e.g. `~/user/:userId`. All routes should start with `~/`. */
18
- path?: string;
19
-
20
- /** Name used to expose local data. Defaults to `$route`. */
21
- recordName?: string;
22
-
23
- /** Match route even if given `route` is only a prefix of the current `url`. */
24
- prefix?: BooleanProp;
25
-
26
- /** Parameters mapping */
27
- params?: Prop<any>;
28
-
29
- /** Parameter name mapping */
30
- map?: Record<string, string>;
31
- }
32
-
33
- // Base class for extending with custom Config types
34
- export class RouteBase<Config extends RouteConfig = RouteConfig> extends PureContainerBase<Config> {
35
- declare url?: string;
36
- declare route: string;
37
- declare path?: string;
38
- declare prefix?: boolean;
39
- declare recordName: string;
40
- declare params?: Prop<any>;
41
- declare map?: Record<string, string>;
42
- declare matcher?: any;
43
- init() {
44
- if (this.path) this.route = this.path;
45
-
46
- super.init();
47
-
48
- if (this.route && this.route[0] !== "+")
49
- this.matcher = new RouteMatcher(this.route + (this.prefix ? "(*remainder)" : ""));
50
- }
51
-
52
- initInstance(context: RenderingContext, instance: Instance) {
53
- instance.store = new ReadOnlyDataView({
54
- store: instance.parentStore,
55
- });
56
- super.initInstance(context, instance);
57
- }
58
-
59
- applyParentStore(instance: Instance) {
60
- instance.store.setStore(instance.parentStore);
61
- }
62
-
63
- declareData(...args: any[]): void {
64
- super.declareData(...args, {
65
- url: undefined,
66
- });
67
- }
68
-
69
- checkVisible(context: RenderingContext, instance: Instance, data: any) {
70
- if (!data.visible) return false;
71
-
72
- if (data.url !== instance.cached.url) {
73
- instance.cached.url = data.url;
74
- let matcher = this.matcher;
75
- let route = this.route;
76
- if (this.route[0] === "+") {
77
- route = routeAppend(context.lastRoute.route, this.route.substring(1));
78
- if (!instance.cached.matcher || instance.cached.route !== route)
79
- instance.cached.matcher = new RouteMatcher(route + (this.prefix ? "(*remainder)" : ""));
80
- matcher = instance.cached.matcher;
81
- }
82
- instance.cached.result = matcher.match(data.url);
83
- instance.cached.matcher = matcher;
84
- instance.cached.route = data.route = route;
85
- }
86
- if (!instance.cached.result) return false;
87
-
88
- return super.checkVisible(context, instance, data);
89
- }
90
-
91
- prepareData(context: RenderingContext, instance: Instance) {
92
- super.prepareData(context, instance);
93
-
94
- const { store, cached } = instance;
95
-
96
- (store as ReadOnlyDataView).setData({
97
- [this.recordName]: cached.result,
98
- });
99
-
100
- //TODO: Replace comparison with deepEquals
101
- if (this.params && this.params.bind) {
102
- var params = store.get(this.params.bind);
103
- if (JSON.stringify(params) != JSON.stringify(cached.result)) {
104
- store.set(this.params.bind, cached.result);
105
- }
106
- }
107
-
108
- if (this.map) {
109
- for (var key in cached.result) {
110
- var binding = this.map[key];
111
- if (binding) store.set(binding, cached.result[key]);
112
- }
113
- }
114
- }
115
-
116
- explore(context: RenderingContext, instance: Instance) {
117
- context.push("lastRoute", {
118
- route: instance.cached.route,
119
- result: instance.cached.result,
120
- reverse: function (data: any) {
121
- return instance.cached.matcher.reverse({
122
- ...instance.cached.result,
123
- remainder: "",
124
- ...data,
125
- });
126
- },
127
- });
128
- super.explore(context, instance);
129
- }
130
-
131
- exploreCleanup(context: RenderingContext, instance: Instance) {
132
- context.pop("lastRoute");
133
- }
134
- }
135
-
136
- RouteBase.prototype.recordName = "$route";
137
- RouteBase.prototype.prefix = false;
138
-
139
- // Closed type for direct usage
140
- export class Route extends RouteBase<RouteConfig> {}
141
-
142
- Widget.alias("route", Route);
1
+ import { Widget } from "../../ui/Widget";
2
+ import { PureContainerBase, PureContainerConfig } from "../../ui/PureContainer";
3
+ import RouteMatcher from "route-parser";
4
+ import { ReadOnlyDataView } from "../../data/ReadOnlyDataView";
5
+ import { routeAppend } from "../../util/routeAppend";
6
+ import { StringProp, BooleanProp, Prop } from "../../ui/Prop";
7
+ import { RenderingContext } from "../../ui/RenderingContext";
8
+ import { Instance } from "../../ui/Instance";
9
+
10
+ export interface RouteConfig extends PureContainerConfig {
11
+ /** Url binding. Bind this to the global `url` variable. */
12
+ url?: StringProp;
13
+
14
+ /** Target route, e.g. `~/user/:userId`. All routes should start with `~/`. */
15
+ route?: string;
16
+
17
+ /** Target route, e.g. `~/user/:userId`. All routes should start with `~/`. */
18
+ path?: string;
19
+
20
+ /** Name used to expose local data. Defaults to `$route`. */
21
+ recordName?: string;
22
+
23
+ /** Match route even if given `route` is only a prefix of the current `url`. */
24
+ prefix?: BooleanProp;
25
+
26
+ /** Parameters mapping */
27
+ params?: Prop<any>;
28
+
29
+ /** Parameter name mapping */
30
+ map?: Record<string, string>;
31
+ }
32
+
33
+ // Base class for extending with custom Config types
34
+ export class RouteBase<Config extends RouteConfig = RouteConfig> extends PureContainerBase<Config> {
35
+ declare url?: string;
36
+ declare route: string;
37
+ declare path?: string;
38
+ declare prefix?: boolean;
39
+ declare recordName: string;
40
+ declare params?: Prop<any>;
41
+ declare map?: Record<string, string>;
42
+ declare matcher?: any;
43
+ init() {
44
+ if (this.path) this.route = this.path;
45
+
46
+ super.init();
47
+
48
+ if (this.route && this.route[0] !== "+")
49
+ this.matcher = new RouteMatcher(this.route + (this.prefix ? "(*remainder)" : ""));
50
+ }
51
+
52
+ initInstance(context: RenderingContext, instance: Instance) {
53
+ instance.store = new ReadOnlyDataView({
54
+ store: instance.parentStore,
55
+ });
56
+ super.initInstance(context, instance);
57
+ }
58
+
59
+ applyParentStore(instance: Instance) {
60
+ instance.store.setStore(instance.parentStore);
61
+ }
62
+
63
+ declareData(...args: any[]): void {
64
+ super.declareData(...args, {
65
+ url: undefined,
66
+ });
67
+ }
68
+
69
+ checkVisible(context: RenderingContext, instance: Instance, data: any) {
70
+ if (!data.visible) return false;
71
+
72
+ if (data.url !== instance.cached.url) {
73
+ instance.cached.url = data.url;
74
+ let matcher = this.matcher;
75
+ let route = this.route;
76
+ if (this.route[0] === "+") {
77
+ route = routeAppend(context.lastRoute.route, this.route.substring(1));
78
+ if (!instance.cached.matcher || instance.cached.route !== route)
79
+ instance.cached.matcher = new RouteMatcher(route + (this.prefix ? "(*remainder)" : ""));
80
+ matcher = instance.cached.matcher;
81
+ }
82
+ instance.cached.result = matcher.match(data.url);
83
+ instance.cached.matcher = matcher;
84
+ instance.cached.route = data.route = route;
85
+ }
86
+ if (!instance.cached.result) return false;
87
+
88
+ return super.checkVisible(context, instance, data);
89
+ }
90
+
91
+ prepareData(context: RenderingContext, instance: Instance) {
92
+ super.prepareData(context, instance);
93
+
94
+ const { store, cached } = instance;
95
+
96
+ (store as ReadOnlyDataView).setData({
97
+ [this.recordName]: cached.result,
98
+ });
99
+
100
+ //TODO: Replace comparison with deepEquals
101
+ if (this.params && this.params.bind) {
102
+ var params = store.get(this.params.bind);
103
+ if (JSON.stringify(params) != JSON.stringify(cached.result)) {
104
+ store.set(this.params.bind, cached.result);
105
+ }
106
+ }
107
+
108
+ if (this.map) {
109
+ for (var key in cached.result) {
110
+ var binding = this.map[key];
111
+ if (binding) store.set(binding, cached.result[key]);
112
+ }
113
+ }
114
+ }
115
+
116
+ explore(context: RenderingContext, instance: Instance) {
117
+ context.push("lastRoute", {
118
+ route: instance.cached.route,
119
+ result: instance.cached.result,
120
+ reverse: function (data: any) {
121
+ return instance.cached.matcher.reverse({
122
+ ...instance.cached.result,
123
+ remainder: "",
124
+ ...data,
125
+ });
126
+ },
127
+ });
128
+ super.explore(context, instance);
129
+ }
130
+
131
+ exploreCleanup(context: RenderingContext, instance: Instance) {
132
+ context.pop("lastRoute");
133
+ }
134
+ }
135
+
136
+ RouteBase.prototype.recordName = "$route";
137
+ RouteBase.prototype.prefix = false;
138
+
139
+ // Closed type for direct usage
140
+ export class Route extends RouteBase<RouteConfig> {}
141
+
142
+ Widget.alias("route", Route);
@@ -1,42 +1,42 @@
1
- import { Dropdown, DropdownConfig } from "./Dropdown";
2
- import { getCursorPos } from "./captureMouse";
3
- import { View } from "../../data/View";
4
- import { Instance } from "../../ui/Instance";
5
-
6
- export interface ContextMenuConfig extends DropdownConfig {}
7
-
8
- export class ContextMenu extends Dropdown {
9
- constructor(config?: ContextMenuConfig) {
10
- super(config);
11
- }
12
- }
13
- ContextMenu.prototype.trackMouse = true;
14
- ContextMenu.prototype.dismissOnFocusOut = true;
15
- ContextMenu.prototype.firstChildDefinesWidth = true;
16
- ContextMenu.prototype.matchWidth = false;
17
- ContextMenu.prototype.placementOrder = "down-right right up-right down-left left up-left";
18
- ContextMenu.prototype.offset = 0;
19
- ContextMenu.prototype.autoFocus = true;
20
- ContextMenu.prototype.autoFocusFirstChild = false;
21
- ContextMenu.prototype.focusable = true;
22
-
23
- export const openContextMenu = (
24
- e: React.MouseEvent,
25
- content: any,
26
- storeOrInstance?: View | Instance,
27
- options?: any,
28
- ) => {
29
- e.preventDefault();
30
- e.stopPropagation();
31
- let position = getCursorPos(e);
32
- let menu = ContextMenu.create({
33
- relatedElement: e.currentTarget,
34
- mousePosition: {
35
- x: position.clientX,
36
- y: position.clientY,
37
- },
38
- trackMouse: true,
39
- items: content,
40
- });
41
- return menu.open(storeOrInstance, options);
42
- };
1
+ import { Dropdown, DropdownConfig } from "./Dropdown";
2
+ import { getCursorPos } from "./captureMouse";
3
+ import { View } from "../../data/View";
4
+ import { Instance } from "../../ui/Instance";
5
+
6
+ export interface ContextMenuConfig extends DropdownConfig {}
7
+
8
+ export class ContextMenu extends Dropdown {
9
+ constructor(config?: ContextMenuConfig) {
10
+ super(config);
11
+ }
12
+ }
13
+ ContextMenu.prototype.trackMouse = true;
14
+ ContextMenu.prototype.dismissOnFocusOut = true;
15
+ ContextMenu.prototype.firstChildDefinesWidth = true;
16
+ ContextMenu.prototype.matchWidth = false;
17
+ ContextMenu.prototype.placementOrder = "down-right right up-right down-left left up-left";
18
+ ContextMenu.prototype.offset = 0;
19
+ ContextMenu.prototype.autoFocus = true;
20
+ ContextMenu.prototype.autoFocusFirstChild = false;
21
+ ContextMenu.prototype.focusable = true;
22
+
23
+ export const openContextMenu = (
24
+ e: React.MouseEvent,
25
+ content: any,
26
+ storeOrInstance?: View | Instance,
27
+ options?: any,
28
+ ) => {
29
+ e.preventDefault();
30
+ e.stopPropagation();
31
+ let position = getCursorPos(e);
32
+ let menu = ContextMenu.create({
33
+ relatedElement: e.currentTarget,
34
+ mousePosition: {
35
+ x: position.clientX,
36
+ y: position.clientY,
37
+ },
38
+ trackMouse: true,
39
+ items: content,
40
+ });
41
+ return menu.open(storeOrInstance, options);
42
+ };