cx 26.1.13 → 26.2.0
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.
- package/build/charts/Marker.d.ts +1 -1
- package/build/charts/Marker.d.ts.map +1 -1
- package/build/charts/Marker.js +16 -6
- package/build/charts/MouseTracker.d.ts +2 -0
- package/build/charts/MouseTracker.d.ts.map +1 -1
- package/build/charts/helpers/PointReducer.d.ts +2 -2
- package/build/charts/helpers/PointReducer.d.ts.map +1 -1
- package/build/data/View.d.ts +5 -3
- package/build/data/View.d.ts.map +1 -1
- package/build/data/View.js +3 -1
- package/build/data/ops/findTreeNode.d.ts +20 -1
- package/build/data/ops/findTreeNode.d.ts.map +1 -1
- package/build/data/ops/findTreeNode.js +19 -0
- package/build/data/ops/findTreePath.d.ts +1 -1
- package/build/data/ops/findTreePath.d.ts.map +1 -1
- package/build/data/ops/findTreePath.js +1 -1
- package/build/data/ops/removeTreeNodes.d.ts +14 -1
- package/build/data/ops/removeTreeNodes.d.ts.map +1 -1
- package/build/data/ops/removeTreeNodes.js +13 -0
- package/build/data/ops/updateArray.d.ts +1 -1
- package/build/data/ops/updateArray.d.ts.map +1 -1
- package/build/data/ops/updateArray.js +1 -1
- package/build/data/ops/updateTree.d.ts +20 -1
- package/build/data/ops/updateTree.d.ts.map +1 -1
- package/build/data/ops/updateTree.js +19 -0
- package/build/jsx-runtime.d.ts +1 -0
- package/build/jsx-runtime.d.ts.map +1 -1
- package/build/jsx-runtime.js +3 -1
- package/build/svg/Rectangle.d.ts +6 -4
- package/build/svg/Rectangle.d.ts.map +1 -1
- package/build/svg/Rectangle.js +9 -7
- package/build/ui/Instance.d.ts +1 -1
- package/build/ui/Instance.d.ts.map +1 -1
- package/build/ui/Instance.js +18 -8
- package/build/ui/IsolatedScope.d.ts +2 -1
- package/build/ui/IsolatedScope.d.ts.map +1 -1
- package/build/ui/Prop.d.ts +1 -1
- package/build/ui/Prop.d.ts.map +1 -1
- package/build/ui/Widget.d.ts +2 -0
- package/build/ui/Widget.d.ts.map +1 -1
- package/build/ui/Widget.js +4 -0
- package/build/ui/adapter/GroupAdapter.d.ts +4 -4
- package/build/ui/adapter/GroupAdapter.d.ts.map +1 -1
- package/build/ui/adapter/GroupAdapter.js +4 -4
- package/build/ui/adapter/TreeAdapter.d.ts +5 -3
- package/build/ui/adapter/TreeAdapter.d.ts.map +1 -1
- package/build/ui/adapter/TreeAdapter.js +12 -5
- package/build/ui/app/startAppLoop.d.ts +2 -2
- package/build/ui/app/startAppLoop.d.ts.map +1 -1
- package/build/ui/app/startHotAppLoop.d.ts +4 -4
- package/build/ui/app/startHotAppLoop.d.ts.map +1 -1
- package/build/ui/app/startHotAppLoop.js +1 -1
- package/build/ui/batchUpdates.d.ts.map +1 -1
- package/build/ui/batchUpdates.js +3 -4
- package/build/widgets/Button.d.ts +0 -7
- package/build/widgets/Button.d.ts.map +1 -1
- package/build/widgets/HtmlElement.d.ts +2 -2
- package/build/widgets/HtmlElement.d.ts.map +1 -1
- package/build/widgets/form/Checkbox.d.ts +3 -3
- package/build/widgets/form/Checkbox.d.ts.map +1 -1
- package/build/widgets/form/Checkbox.js +11 -6
- package/build/widgets/form/DateTimeField.d.ts +4 -0
- package/build/widgets/form/DateTimeField.d.ts.map +1 -1
- package/build/widgets/form/TextField.d.ts +2 -2
- package/build/widgets/form/TextField.d.ts.map +1 -1
- package/build/widgets/grid/Grid.d.ts +20 -16
- package/build/widgets/grid/Grid.d.ts.map +1 -1
- package/build/widgets/grid/Grid.js +200 -86
- package/build/widgets/nav/Menu.d.ts +2 -0
- package/build/widgets/nav/Menu.d.ts.map +1 -1
- package/build/widgets/nav/Route.js +1 -1
- package/build/widgets/overlay/FlyweightTooltipTracker.d.ts +6 -4
- package/build/widgets/overlay/FlyweightTooltipTracker.d.ts.map +1 -1
- package/build/widgets/overlay/FlyweightTooltipTracker.js +3 -0
- package/build/widgets/overlay/Overlay.d.ts +2 -2
- package/build/widgets/overlay/Overlay.d.ts.map +1 -1
- package/dist/data.js +52 -1
- package/dist/jsx-runtime.js +4 -2
- package/dist/manifest.js +910 -904
- package/dist/svg.js +3 -0
- package/dist/ui.js +1548 -1544
- package/dist/widgets.css +1 -1
- package/dist/widgets.js +395 -4
- package/package.json +2 -2
- package/src/charts/Marker.tsx +448 -394
- package/src/charts/MouseTracker.tsx +3 -0
- package/src/charts/helpers/PointReducer.ts +2 -2
- package/src/data/View.ts +76 -19
- package/src/data/ops/findTreeNode.ts +20 -1
- package/src/data/ops/findTreePath.ts +7 -2
- package/src/data/ops/removeTreeNodes.ts +14 -1
- package/src/data/ops/updateArray.ts +4 -4
- package/src/data/ops/updateTree.ts +32 -6
- package/src/index.scss +6 -6
- package/src/jsx-runtime.spec.tsx +40 -0
- package/src/jsx-runtime.ts +87 -84
- package/src/svg/Rectangle.tsx +80 -73
- package/src/ui/DataProxy.ts +55 -55
- package/src/ui/Instance.ts +142 -45
- package/src/ui/IsolatedScope.ts +4 -2
- package/src/ui/Prop.ts +141 -141
- package/src/ui/Rescope.ts +50 -50
- package/src/ui/Widget.tsx +292 -234
- package/src/ui/adapter/ArrayAdapter.ts +229 -229
- package/src/ui/adapter/GroupAdapter.ts +8 -10
- package/src/ui/adapter/TreeAdapter.ts +75 -15
- package/src/ui/app/Url.spec.ts +1 -1
- package/src/ui/app/startAppLoop.tsx +56 -45
- package/src/ui/app/startHotAppLoop.ts +4 -4
- package/src/ui/batchUpdates.ts +16 -21
- package/src/ui/exprHelpers.ts +96 -96
- package/src/widgets/Button.tsx +0 -8
- package/src/widgets/HtmlElement.spec.tsx +100 -72
- package/src/widgets/HtmlElement.tsx +11 -10
- package/src/widgets/Sandbox.ts +104 -104
- package/src/widgets/Section.scss +55 -55
- package/src/widgets/drag-drop/DropZone.scss +74 -74
- package/src/widgets/form/Checkbox.tsx +296 -243
- package/src/widgets/form/DateTimeField.tsx +6 -0
- package/src/widgets/form/TextField.tsx +2 -2
- package/src/widgets/grid/Grid.scss +43 -10
- package/src/widgets/grid/Grid.tsx +4401 -3848
- package/src/widgets/nav/Menu.tsx +3 -0
- package/src/widgets/nav/Route.ts +1 -1
- package/src/widgets/overlay/FlyweightTooltipTracker.ts +15 -4
- package/src/widgets/overlay/Overlay.tsx +2 -1
- package/src/widgets/overlay/index.d.ts +11 -11
package/dist/widgets.css
CHANGED
package/dist/widgets.js
CHANGED
|
@@ -144,7 +144,6 @@ import {
|
|
|
144
144
|
enableFatArrowExpansion,
|
|
145
145
|
} from "cx/data";
|
|
146
146
|
import { jsx as jsx$1, jsxs as jsxs$1 } from "cx/jsx-runtime";
|
|
147
|
-
import RouteMatcher from "route-parser";
|
|
148
147
|
|
|
149
148
|
function autoFocus(el, component) {
|
|
150
149
|
let data = component.props.data || component.props.instance.data;
|
|
@@ -4537,6 +4536,9 @@ const openContextMenu = (e, content, storeOrInstance, options) => {
|
|
|
4537
4536
|
|
|
4538
4537
|
class FlyweightTooltipTrackerInstance extends Instance {}
|
|
4539
4538
|
class FlyweightTooltipTracker extends Widget {
|
|
4539
|
+
constructor(config) {
|
|
4540
|
+
super(config);
|
|
4541
|
+
}
|
|
4540
4542
|
initInstance(context, instance) {
|
|
4541
4543
|
let handler = (e) => this.handleMouseMove(e, instance);
|
|
4542
4544
|
if (typeof document !== "undefined") {
|
|
@@ -4619,13 +4621,391 @@ function createHotPromiseWindowFactory(module, factory) {
|
|
|
4619
4621
|
return (options) => result(null, options);
|
|
4620
4622
|
}
|
|
4621
4623
|
|
|
4624
|
+
/**
|
|
4625
|
+
* Route Parser - A TypeScript URL routing library
|
|
4626
|
+
* Supports named parameters (:param), splats (*param), and optional segments (())
|
|
4627
|
+
*/
|
|
4628
|
+
/**
|
|
4629
|
+
* Parse a route specification into tokens
|
|
4630
|
+
*/
|
|
4631
|
+
function tokenize(spec) {
|
|
4632
|
+
const tokens = [];
|
|
4633
|
+
let i = 0;
|
|
4634
|
+
while (i < spec.length) {
|
|
4635
|
+
const char = spec[i];
|
|
4636
|
+
if (char === ":") {
|
|
4637
|
+
// Named parameter
|
|
4638
|
+
i++;
|
|
4639
|
+
let name = "";
|
|
4640
|
+
while (i < spec.length && /[\w]/.test(spec[i])) {
|
|
4641
|
+
name += spec[i];
|
|
4642
|
+
i++;
|
|
4643
|
+
}
|
|
4644
|
+
if (name) {
|
|
4645
|
+
tokens.push({
|
|
4646
|
+
type: "param",
|
|
4647
|
+
value: name,
|
|
4648
|
+
});
|
|
4649
|
+
}
|
|
4650
|
+
} else if (char === "*") {
|
|
4651
|
+
// Splat parameter
|
|
4652
|
+
i++;
|
|
4653
|
+
let name = "";
|
|
4654
|
+
while (i < spec.length && /[\w]/.test(spec[i])) {
|
|
4655
|
+
name += spec[i];
|
|
4656
|
+
i++;
|
|
4657
|
+
}
|
|
4658
|
+
if (name) {
|
|
4659
|
+
tokens.push({
|
|
4660
|
+
type: "splat",
|
|
4661
|
+
value: name,
|
|
4662
|
+
});
|
|
4663
|
+
}
|
|
4664
|
+
} else if (char === "(") {
|
|
4665
|
+
// Optional segment - find matching closing paren
|
|
4666
|
+
i++;
|
|
4667
|
+
let depth = 1;
|
|
4668
|
+
let optionalContent = "";
|
|
4669
|
+
while (i < spec.length && depth > 0) {
|
|
4670
|
+
if (spec[i] === "(") depth++;
|
|
4671
|
+
else if (spec[i] === ")") depth--;
|
|
4672
|
+
if (depth > 0) {
|
|
4673
|
+
optionalContent += spec[i];
|
|
4674
|
+
}
|
|
4675
|
+
i++;
|
|
4676
|
+
}
|
|
4677
|
+
// Recursively parse the optional content
|
|
4678
|
+
const children = tokenize(optionalContent);
|
|
4679
|
+
tokens.push({
|
|
4680
|
+
type: "optional",
|
|
4681
|
+
value: optionalContent,
|
|
4682
|
+
children,
|
|
4683
|
+
});
|
|
4684
|
+
} else if (char === "?" || char === "&") {
|
|
4685
|
+
// Query separator - mark it specially
|
|
4686
|
+
tokens.push({
|
|
4687
|
+
type: "querySeparator",
|
|
4688
|
+
value: char,
|
|
4689
|
+
});
|
|
4690
|
+
i++;
|
|
4691
|
+
} else {
|
|
4692
|
+
// Static text - consume until we hit a special character
|
|
4693
|
+
let text = "";
|
|
4694
|
+
while (i < spec.length && !":*()&?".includes(spec[i])) {
|
|
4695
|
+
text += spec[i];
|
|
4696
|
+
i++;
|
|
4697
|
+
}
|
|
4698
|
+
if (text) {
|
|
4699
|
+
tokens.push({
|
|
4700
|
+
type: "static",
|
|
4701
|
+
value: text,
|
|
4702
|
+
});
|
|
4703
|
+
}
|
|
4704
|
+
}
|
|
4705
|
+
}
|
|
4706
|
+
return tokens;
|
|
4707
|
+
}
|
|
4708
|
+
/**
|
|
4709
|
+
* Check if tokens contain any query-related content (? or &)
|
|
4710
|
+
*/
|
|
4711
|
+
function hasQueryTokens(tokens) {
|
|
4712
|
+
for (const token of tokens) {
|
|
4713
|
+
if (token.type === "querySeparator") return true;
|
|
4714
|
+
if (token.type === "optional" && token.children && hasQueryTokens(token.children)) return true;
|
|
4715
|
+
}
|
|
4716
|
+
return false;
|
|
4717
|
+
}
|
|
4718
|
+
/**
|
|
4719
|
+
* Extract query parameter definitions from tokens
|
|
4720
|
+
*/
|
|
4721
|
+
function extractQueryParams(tokens, optional = false) {
|
|
4722
|
+
const params = [];
|
|
4723
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
4724
|
+
const token = tokens[i];
|
|
4725
|
+
if (token.type === "param") {
|
|
4726
|
+
// Look back for the key name (e.g., 'page=' before ':page')
|
|
4727
|
+
let key = token.value; // Default to param name
|
|
4728
|
+
if (i > 0) {
|
|
4729
|
+
const prevToken = tokens[i - 1];
|
|
4730
|
+
if (prevToken.type === "static" && prevToken.value.endsWith("=")) {
|
|
4731
|
+
// Extract key from "key="
|
|
4732
|
+
const match = prevToken.value.match(/([^=&?]+)=$/);
|
|
4733
|
+
if (match) {
|
|
4734
|
+
key = match[1];
|
|
4735
|
+
}
|
|
4736
|
+
}
|
|
4737
|
+
}
|
|
4738
|
+
params.push({
|
|
4739
|
+
name: token.value,
|
|
4740
|
+
key,
|
|
4741
|
+
optional,
|
|
4742
|
+
});
|
|
4743
|
+
} else if (token.type === "optional" && token.children) {
|
|
4744
|
+
// Recursively extract from optional segments
|
|
4745
|
+
params.push(...extractQueryParams(token.children, true));
|
|
4746
|
+
}
|
|
4747
|
+
}
|
|
4748
|
+
return params;
|
|
4749
|
+
}
|
|
4750
|
+
/**
|
|
4751
|
+
* Split tokens into path tokens and query tokens
|
|
4752
|
+
*/
|
|
4753
|
+
function splitPathAndQuery(tokens) {
|
|
4754
|
+
const pathTokens = [];
|
|
4755
|
+
const queryTokens = [];
|
|
4756
|
+
let inQuery = false;
|
|
4757
|
+
for (const token of tokens) {
|
|
4758
|
+
if (token.type === "querySeparator" && token.value === "?") {
|
|
4759
|
+
inQuery = true;
|
|
4760
|
+
queryTokens.push(token);
|
|
4761
|
+
} else if (inQuery) {
|
|
4762
|
+
queryTokens.push(token);
|
|
4763
|
+
} else if (token.type === "optional" && token.children) {
|
|
4764
|
+
// Check if this optional contains query content
|
|
4765
|
+
if (hasQueryTokens(token.children)) {
|
|
4766
|
+
// This optional is part of query
|
|
4767
|
+
queryTokens.push(token);
|
|
4768
|
+
inQuery = true; // After query optional, we're in query mode
|
|
4769
|
+
} else {
|
|
4770
|
+
pathTokens.push(token);
|
|
4771
|
+
}
|
|
4772
|
+
} else {
|
|
4773
|
+
pathTokens.push(token);
|
|
4774
|
+
}
|
|
4775
|
+
}
|
|
4776
|
+
return {
|
|
4777
|
+
pathTokens,
|
|
4778
|
+
queryTokens,
|
|
4779
|
+
};
|
|
4780
|
+
}
|
|
4781
|
+
/**
|
|
4782
|
+
* Escape special regex characters in a string
|
|
4783
|
+
*/
|
|
4784
|
+
function escapeRegex(str) {
|
|
4785
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4786
|
+
}
|
|
4787
|
+
/**
|
|
4788
|
+
* Build a regex pattern from path tokens only (no query handling)
|
|
4789
|
+
*/
|
|
4790
|
+
function buildPathRegex(tokens) {
|
|
4791
|
+
let pattern = "";
|
|
4792
|
+
const paramNames = [];
|
|
4793
|
+
for (const token of tokens) {
|
|
4794
|
+
switch (token.type) {
|
|
4795
|
+
case "static":
|
|
4796
|
+
pattern += escapeRegex(token.value);
|
|
4797
|
+
break;
|
|
4798
|
+
case "param":
|
|
4799
|
+
// Named parameter matches one path segment (no slashes)
|
|
4800
|
+
pattern += "([^/]+)";
|
|
4801
|
+
paramNames.push(token.value);
|
|
4802
|
+
break;
|
|
4803
|
+
case "splat":
|
|
4804
|
+
// Splat matches any characters including slashes (non-greedy within constraints)
|
|
4805
|
+
pattern += "(.+?)";
|
|
4806
|
+
paramNames.push(token.value);
|
|
4807
|
+
break;
|
|
4808
|
+
case "optional":
|
|
4809
|
+
// Optional segment - recursively build and wrap in optional group
|
|
4810
|
+
if (token.children) {
|
|
4811
|
+
const { pattern: childPattern, paramNames: childNames } = buildPathRegex(token.children);
|
|
4812
|
+
pattern += `(?:${childPattern})?`;
|
|
4813
|
+
paramNames.push(...childNames);
|
|
4814
|
+
}
|
|
4815
|
+
break;
|
|
4816
|
+
}
|
|
4817
|
+
}
|
|
4818
|
+
return {
|
|
4819
|
+
pattern,
|
|
4820
|
+
paramNames,
|
|
4821
|
+
};
|
|
4822
|
+
}
|
|
4823
|
+
/**
|
|
4824
|
+
* Parse a query string into key-value pairs
|
|
4825
|
+
*/
|
|
4826
|
+
function parseQueryString(queryString) {
|
|
4827
|
+
const params = new Map();
|
|
4828
|
+
if (!queryString) return params;
|
|
4829
|
+
// Remove leading ? if present
|
|
4830
|
+
const qs = queryString.startsWith("?") ? queryString.slice(1) : queryString;
|
|
4831
|
+
if (!qs) return params;
|
|
4832
|
+
for (const pair of qs.split("&")) {
|
|
4833
|
+
const [key, value] = pair.split("=");
|
|
4834
|
+
if (key) {
|
|
4835
|
+
params.set(key, value || "");
|
|
4836
|
+
}
|
|
4837
|
+
}
|
|
4838
|
+
return params;
|
|
4839
|
+
}
|
|
4840
|
+
/**
|
|
4841
|
+
* Attempt to reverse a route with given parameters
|
|
4842
|
+
*/
|
|
4843
|
+
function reverseTokens(tokens, params, isFirstQueryParam) {
|
|
4844
|
+
let result = "";
|
|
4845
|
+
for (const token of tokens) {
|
|
4846
|
+
switch (token.type) {
|
|
4847
|
+
case "static":
|
|
4848
|
+
result += token.value;
|
|
4849
|
+
break;
|
|
4850
|
+
case "param":
|
|
4851
|
+
case "splat": {
|
|
4852
|
+
const value = params[token.value];
|
|
4853
|
+
if (value === undefined || value === null || value === "") {
|
|
4854
|
+
return false;
|
|
4855
|
+
}
|
|
4856
|
+
result += String(value);
|
|
4857
|
+
break;
|
|
4858
|
+
}
|
|
4859
|
+
case "querySeparator":
|
|
4860
|
+
// For reverse, we handle ? and & smartly
|
|
4861
|
+
if (token.value === "?") {
|
|
4862
|
+
if (isFirstQueryParam.value) {
|
|
4863
|
+
result += "?";
|
|
4864
|
+
isFirstQueryParam.value = false;
|
|
4865
|
+
} else {
|
|
4866
|
+
result += "&";
|
|
4867
|
+
}
|
|
4868
|
+
} else if (token.value === "&") {
|
|
4869
|
+
if (isFirstQueryParam.value) {
|
|
4870
|
+
result += "?";
|
|
4871
|
+
isFirstQueryParam.value = false;
|
|
4872
|
+
} else {
|
|
4873
|
+
result += "&";
|
|
4874
|
+
}
|
|
4875
|
+
}
|
|
4876
|
+
break;
|
|
4877
|
+
case "optional":
|
|
4878
|
+
if (token.children) {
|
|
4879
|
+
// Try to fill the optional segment
|
|
4880
|
+
const optionalResult = reverseTokens(token.children, params, isFirstQueryParam);
|
|
4881
|
+
if (optionalResult !== false) {
|
|
4882
|
+
result += optionalResult;
|
|
4883
|
+
}
|
|
4884
|
+
// If it fails, just skip the optional part (don't return false)
|
|
4885
|
+
}
|
|
4886
|
+
break;
|
|
4887
|
+
}
|
|
4888
|
+
}
|
|
4889
|
+
return result;
|
|
4890
|
+
}
|
|
4891
|
+
/**
|
|
4892
|
+
* RouteParser class
|
|
4893
|
+
*/
|
|
4894
|
+
class RouteParser {
|
|
4895
|
+
spec;
|
|
4896
|
+
tokens;
|
|
4897
|
+
pathRegex;
|
|
4898
|
+
pathParamNames;
|
|
4899
|
+
queryParamDefs;
|
|
4900
|
+
hasQueryInSpec;
|
|
4901
|
+
constructor(spec) {
|
|
4902
|
+
if (!spec) {
|
|
4903
|
+
throw new Error("spec is required");
|
|
4904
|
+
}
|
|
4905
|
+
this.spec = spec;
|
|
4906
|
+
this.tokens = tokenize(spec);
|
|
4907
|
+
// Split into path and query parts
|
|
4908
|
+
const { pathTokens, queryTokens } = splitPathAndQuery(this.tokens);
|
|
4909
|
+
// Build regex for path part only
|
|
4910
|
+
const { pattern, paramNames } = buildPathRegex(pathTokens);
|
|
4911
|
+
this.pathRegex = new RegExp(`^${pattern}(?:\\?.*)?$`);
|
|
4912
|
+
this.pathParamNames = paramNames;
|
|
4913
|
+
// Extract query parameter definitions
|
|
4914
|
+
this.queryParamDefs = extractQueryParams(queryTokens);
|
|
4915
|
+
this.hasQueryInSpec = queryTokens.length > 0;
|
|
4916
|
+
}
|
|
4917
|
+
/**
|
|
4918
|
+
* Match a path against this route
|
|
4919
|
+
* Returns params object on match, false otherwise
|
|
4920
|
+
*/
|
|
4921
|
+
match(path) {
|
|
4922
|
+
// Split path into pathname and query string
|
|
4923
|
+
const queryIndex = path.indexOf("?");
|
|
4924
|
+
const pathname = queryIndex >= 0 ? path.slice(0, queryIndex) : path;
|
|
4925
|
+
const queryString = queryIndex >= 0 ? path.slice(queryIndex + 1) : "";
|
|
4926
|
+
// Match only the pathname part (not query string) to avoid capturing ? in params
|
|
4927
|
+
const match = this.pathRegex.exec(pathname);
|
|
4928
|
+
if (!match) {
|
|
4929
|
+
return false;
|
|
4930
|
+
}
|
|
4931
|
+
const params = {};
|
|
4932
|
+
// Extract path parameters
|
|
4933
|
+
for (let i = 0; i < this.pathParamNames.length; i++) {
|
|
4934
|
+
params[this.pathParamNames[i]] = match[i + 1];
|
|
4935
|
+
}
|
|
4936
|
+
// If route has query params in spec, match them from URL's query string
|
|
4937
|
+
if (this.hasQueryInSpec) {
|
|
4938
|
+
const urlQueryParams = parseQueryString(queryString);
|
|
4939
|
+
for (const paramDef of this.queryParamDefs) {
|
|
4940
|
+
const value = urlQueryParams.get(paramDef.key);
|
|
4941
|
+
if (value !== undefined) {
|
|
4942
|
+
params[paramDef.name] = value;
|
|
4943
|
+
} else if (paramDef.optional) {
|
|
4944
|
+
params[paramDef.name] = undefined;
|
|
4945
|
+
} else {
|
|
4946
|
+
// Required query param not found
|
|
4947
|
+
return false;
|
|
4948
|
+
}
|
|
4949
|
+
}
|
|
4950
|
+
}
|
|
4951
|
+
return params;
|
|
4952
|
+
}
|
|
4953
|
+
/**
|
|
4954
|
+
* Reverse the route with given parameters
|
|
4955
|
+
* Returns the path string on success, false otherwise
|
|
4956
|
+
*/
|
|
4957
|
+
reverse(params = {}) {
|
|
4958
|
+
// Check if required (non-optional) params can be fulfilled
|
|
4959
|
+
if (!this.canFulfillRequired(this.tokens, params)) {
|
|
4960
|
+
return false;
|
|
4961
|
+
}
|
|
4962
|
+
const isFirstQueryParam = {
|
|
4963
|
+
value: true,
|
|
4964
|
+
};
|
|
4965
|
+
return reverseTokens(this.tokens, params, isFirstQueryParam);
|
|
4966
|
+
}
|
|
4967
|
+
/**
|
|
4968
|
+
* Check if required params (non-optional) can be fulfilled
|
|
4969
|
+
*/
|
|
4970
|
+
canFulfillRequired(tokens, params) {
|
|
4971
|
+
for (const token of tokens) {
|
|
4972
|
+
if (token.type === "param" || token.type === "splat") {
|
|
4973
|
+
const value = params[token.value];
|
|
4974
|
+
if (value === undefined || value === null || value === "") {
|
|
4975
|
+
return false;
|
|
4976
|
+
}
|
|
4977
|
+
}
|
|
4978
|
+
// Optional segments don't need to be checked at top level
|
|
4979
|
+
}
|
|
4980
|
+
return true;
|
|
4981
|
+
}
|
|
4982
|
+
}
|
|
4983
|
+
// Export a wrapper that supports both calling conventions
|
|
4984
|
+
const Route$1 = function (spec) {
|
|
4985
|
+
if (!(this instanceof Route$1)) {
|
|
4986
|
+
return new Route$1(spec);
|
|
4987
|
+
}
|
|
4988
|
+
if (!spec) {
|
|
4989
|
+
throw new Error("spec is required");
|
|
4990
|
+
}
|
|
4991
|
+
const parser = new RouteParser(spec);
|
|
4992
|
+
// Copy properties to this instance
|
|
4993
|
+
this.spec = parser.spec;
|
|
4994
|
+
this.match = parser.match.bind(parser);
|
|
4995
|
+
this.reverse = parser.reverse.bind(parser);
|
|
4996
|
+
return this;
|
|
4997
|
+
};
|
|
4998
|
+
// Ensure prototype chain works for instanceof
|
|
4999
|
+
Route$1.prototype = Object.create(Object.prototype);
|
|
5000
|
+
Route$1.prototype.constructor = Route$1;
|
|
5001
|
+
|
|
4622
5002
|
// Base class for extending with custom Config types
|
|
4623
5003
|
class RouteBase extends PureContainerBase {
|
|
4624
5004
|
init() {
|
|
4625
5005
|
if (this.path) this.route = this.path;
|
|
4626
5006
|
super.init();
|
|
4627
5007
|
if (this.route && this.route[0] !== "+")
|
|
4628
|
-
this.matcher = new
|
|
5008
|
+
this.matcher = new Route$1(this.route + (this.prefix ? "(*remainder)" : ""));
|
|
4629
5009
|
}
|
|
4630
5010
|
initInstance(context, instance) {
|
|
4631
5011
|
instance.store = new ReadOnlyDataView({
|
|
@@ -4650,7 +5030,7 @@ class RouteBase extends PureContainerBase {
|
|
|
4650
5030
|
if (this.route[0] === "+") {
|
|
4651
5031
|
route = routeAppend(context.lastRoute.route, this.route.substring(1));
|
|
4652
5032
|
if (!instance.cached.matcher || instance.cached.route !== route)
|
|
4653
|
-
instance.cached.matcher = new
|
|
5033
|
+
instance.cached.matcher = new Route$1(route + (this.prefix ? "(*remainder)" : ""));
|
|
4654
5034
|
matcher = instance.cached.matcher;
|
|
4655
5035
|
}
|
|
4656
5036
|
instance.cached.result = matcher.match(data.url);
|
|
@@ -14071,6 +14451,13 @@ class GridRowComponent extends VDOM.Component {
|
|
|
14071
14451
|
}
|
|
14072
14452
|
}
|
|
14073
14453
|
|
|
14454
|
+
class GridInstance extends Instance {
|
|
14455
|
+
resetColumnWidths() {
|
|
14456
|
+
this.setState({
|
|
14457
|
+
colWidth: {},
|
|
14458
|
+
});
|
|
14459
|
+
}
|
|
14460
|
+
}
|
|
14074
14461
|
class Grid extends ContainerBase {
|
|
14075
14462
|
constructor(config) {
|
|
14076
14463
|
super(config);
|
|
@@ -14128,6 +14515,9 @@ class Grid extends ContainerBase {
|
|
|
14128
14515
|
if (this.focusable == null) this.focusable = !this.selection.isDummy || this.cellEditable;
|
|
14129
14516
|
super.init();
|
|
14130
14517
|
}
|
|
14518
|
+
createInstance(key, parent, parentStore) {
|
|
14519
|
+
return new GridInstance(this, key, parent, parentStore);
|
|
14520
|
+
}
|
|
14131
14521
|
initState(context, instance) {
|
|
14132
14522
|
instance.state = {
|
|
14133
14523
|
colWidth: {},
|
|
@@ -16353,7 +16743,7 @@ class GridComponent extends VDOM.Component {
|
|
|
16353
16743
|
if (dstTableBody) {
|
|
16354
16744
|
let srcTableBody = this.dom.table.lastElementChild;
|
|
16355
16745
|
copyCellSize(srcTableBody, dstTableBody, fixedFooterOverlap);
|
|
16356
|
-
let scrollColumnEl = dstTableBody.firstElementChild?.
|
|
16746
|
+
let scrollColumnEl = dstTableBody.firstElementChild?.lastElementChild;
|
|
16357
16747
|
if (scrollColumnEl) scrollColumnEl.style.minWidth = scrollColumnEl.style.maxWidth = this.scrollWidth + "px";
|
|
16358
16748
|
this.dom.fixedFooter.style.display = "block";
|
|
16359
16749
|
footerHeight = this.dom.fixedFooter.offsetHeight;
|
|
@@ -17793,6 +18183,7 @@ export {
|
|
|
17793
18183
|
FlyweightTooltipTracker,
|
|
17794
18184
|
FlyweightTooltipTrackerInstance,
|
|
17795
18185
|
Grid,
|
|
18186
|
+
GridInstance,
|
|
17796
18187
|
GridRow,
|
|
17797
18188
|
GridRowComponent,
|
|
17798
18189
|
GridRowLine,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cx",
|
|
3
|
-
"version": "26.
|
|
3
|
+
"version": "26.2.0",
|
|
4
4
|
"description": "Advanced JavaScript UI framework for admin and dashboard applications with ready to use grid, form and chart components.",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./data": {
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"dependencies": {
|
|
71
71
|
"@types/route-parser": "^0.1.7",
|
|
72
72
|
"intl-io": "^0.4.4",
|
|
73
|
-
"route-parser": "^
|
|
73
|
+
"route-parser-ts": "^1.1.0"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"@types/react": ">=18",
|