@tensor_1/react 2.12.0 → 2.13.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/README.md +16 -0
- package/dist/calendar-model.d.ts +31 -0
- package/dist/calendar-model.js +89 -0
- package/dist/color-model.d.ts +20 -0
- package/dist/color-model.js +74 -0
- package/dist/components/BrandProfiles.d.ts +45 -0
- package/dist/components/BrandProfiles.js +150 -0
- package/dist/components/BuilderCanvas.d.ts +34 -0
- package/dist/components/BuilderCanvas.js +117 -0
- package/dist/components/ColorPicker.d.ts +17 -0
- package/dist/components/ColorPicker.js +158 -0
- package/dist/components/DateRangePicker.d.ts +23 -0
- package/dist/components/DateRangePicker.js +123 -0
- package/dist/components/DiffViewer.d.ts +18 -0
- package/dist/components/DiffViewer.js +93 -0
- package/dist/components/LicensePositionBar.d.ts +17 -0
- package/dist/components/LicensePositionBar.js +50 -0
- package/dist/components/MatchReview.d.ts +39 -0
- package/dist/components/MatchReview.js +120 -0
- package/dist/components/MetricInput.d.ts +23 -0
- package/dist/components/MetricInput.js +92 -0
- package/dist/components/RelationshipGraph.d.ts +30 -0
- package/dist/components/RelationshipGraph.js +138 -0
- package/dist/components/RuleBuilder.d.ts +45 -0
- package/dist/components/RuleBuilder.js +163 -0
- package/dist/components/SchedulingCalendar.d.ts +42 -0
- package/dist/components/SchedulingCalendar.js +124 -0
- package/dist/diff-model.d.ts +23 -0
- package/dist/diff-model.js +50 -0
- package/dist/index.cjs +1753 -2
- package/dist/index.d.cts +439 -1
- package/dist/index.d.ts +18 -0
- package/dist/index.js +91 -1
- package/dist/json-value.d.ts +10 -0
- package/dist/json-value.js +19 -0
- package/dist/metric-model.d.ts +9 -0
- package/dist/metric-model.js +25 -0
- package/dist/relationship-graph-model.d.ts +31 -0
- package/dist/relationship-graph-model.js +68 -0
- package/dist/rule-builder-model.d.ts +41 -0
- package/dist/rule-builder-model.js +101 -0
- package/package.json +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function decimals(value) {
|
|
2
|
+
const text = String(value).toLowerCase();
|
|
3
|
+
if (text.includes("e-")) return Number(text.split("e-")[1]);
|
|
4
|
+
return text.includes(".") ? text.split(".")[1].length : 0;
|
|
5
|
+
}
|
|
6
|
+
function clampMetricValue(value, min, max) {
|
|
7
|
+
return Math.min(max ?? Number.POSITIVE_INFINITY, Math.max(min ?? Number.NEGATIVE_INFINITY, value));
|
|
8
|
+
}
|
|
9
|
+
function stepMetricValue(value, direction, options = {}) {
|
|
10
|
+
const step = options.step && options.step > 0 ? options.step : 1;
|
|
11
|
+
const base = value ?? options.min ?? 0;
|
|
12
|
+
const precision = Math.max(decimals(base), decimals(step), decimals(options.min ?? 0), decimals(options.max ?? 0));
|
|
13
|
+
const next = Number((base + direction * step).toFixed(precision));
|
|
14
|
+
return clampMetricValue(next, options.min, options.max);
|
|
15
|
+
}
|
|
16
|
+
function parseMetricValue(value) {
|
|
17
|
+
if (value.trim() === "") return null;
|
|
18
|
+
const parsed = Number(value);
|
|
19
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
clampMetricValue,
|
|
23
|
+
parseMetricValue,
|
|
24
|
+
stepMetricValue
|
|
25
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
interface RelationshipGraphNode {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
type?: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
x?: number;
|
|
7
|
+
y?: number;
|
|
8
|
+
}
|
|
9
|
+
interface RelationshipGraphEdge {
|
|
10
|
+
id: string;
|
|
11
|
+
source: string;
|
|
12
|
+
target: string;
|
|
13
|
+
type?: string;
|
|
14
|
+
label?: string;
|
|
15
|
+
}
|
|
16
|
+
interface PositionedRelationshipNode extends RelationshipGraphNode {
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
depth: number;
|
|
20
|
+
}
|
|
21
|
+
interface BoundedRelationshipGraph {
|
|
22
|
+
nodes: RelationshipGraphNode[];
|
|
23
|
+
edges: RelationshipGraphEdge[];
|
|
24
|
+
omittedNodeCount: number;
|
|
25
|
+
}
|
|
26
|
+
declare function boundRelationshipGraph(nodes: RelationshipGraphNode[], edges: RelationshipGraphEdge[], maxNodes?: number): BoundedRelationshipGraph;
|
|
27
|
+
declare function relationshipNeighbors(nodeId: string, edges: RelationshipGraphEdge[]): string[];
|
|
28
|
+
declare function layoutRelationshipGraph(nodes: RelationshipGraphNode[], edges: RelationshipGraphEdge[], rootId?: string): PositionedRelationshipNode[];
|
|
29
|
+
declare function traverseRelationshipNode(nodes: RelationshipGraphNode[], currentId: string | undefined, direction: -1 | 1): string | undefined;
|
|
30
|
+
|
|
31
|
+
export { type BoundedRelationshipGraph, type PositionedRelationshipNode, type RelationshipGraphEdge, type RelationshipGraphNode, boundRelationshipGraph, layoutRelationshipGraph, relationshipNeighbors, traverseRelationshipNode };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
function boundRelationshipGraph(nodes, edges, maxNodes = 40) {
|
|
2
|
+
const boundedNodes = nodes.slice(0, Math.max(1, maxNodes));
|
|
3
|
+
const ids = new Set(boundedNodes.map((node) => node.id));
|
|
4
|
+
return {
|
|
5
|
+
nodes: boundedNodes,
|
|
6
|
+
edges: edges.filter((edge) => ids.has(edge.source) && ids.has(edge.target)),
|
|
7
|
+
omittedNodeCount: Math.max(0, nodes.length - boundedNodes.length)
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function relationshipNeighbors(nodeId, edges) {
|
|
11
|
+
const result = [];
|
|
12
|
+
for (const edge of edges) {
|
|
13
|
+
if (edge.source === nodeId) result.push(edge.target);
|
|
14
|
+
else if (edge.target === nodeId) result.push(edge.source);
|
|
15
|
+
}
|
|
16
|
+
return [...new Set(result)];
|
|
17
|
+
}
|
|
18
|
+
function layoutRelationshipGraph(nodes, edges, rootId = nodes[0]?.id) {
|
|
19
|
+
if (nodes.length === 0) return [];
|
|
20
|
+
const root = nodes.some((node) => node.id === rootId) ? rootId : nodes[0].id;
|
|
21
|
+
const depth = /* @__PURE__ */ new Map([[root, 0]]);
|
|
22
|
+
const queue = [root];
|
|
23
|
+
while (queue.length) {
|
|
24
|
+
const current = queue.shift();
|
|
25
|
+
for (const neighbor of relationshipNeighbors(current, edges)) {
|
|
26
|
+
if (!depth.has(neighbor) && nodes.some((node) => node.id === neighbor)) {
|
|
27
|
+
depth.set(neighbor, (depth.get(current) ?? 0) + 1);
|
|
28
|
+
queue.push(neighbor);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
let disconnectedDepth = Math.max(0, ...depth.values()) + 1;
|
|
33
|
+
nodes.forEach((node) => {
|
|
34
|
+
if (!depth.has(node.id)) depth.set(node.id, disconnectedDepth);
|
|
35
|
+
});
|
|
36
|
+
const groups = /* @__PURE__ */ new Map();
|
|
37
|
+
nodes.forEach((node) => {
|
|
38
|
+
const level = depth.get(node.id);
|
|
39
|
+
groups.set(level, [...groups.get(level) ?? [], node]);
|
|
40
|
+
});
|
|
41
|
+
const maxDepth = Math.max(1, ...groups.keys());
|
|
42
|
+
return nodes.map((node) => {
|
|
43
|
+
const level = depth.get(node.id);
|
|
44
|
+
if (node.x !== void 0 && node.y !== void 0) return { ...node, x: node.x, y: node.y, depth: level };
|
|
45
|
+
if (level === 0) return { ...node, x: 50, y: 50, depth: 0 };
|
|
46
|
+
const peers = groups.get(level);
|
|
47
|
+
const index = peers.findIndex((peer) => peer.id === node.id);
|
|
48
|
+
const angle = Math.PI * 2 * index / peers.length - Math.PI / 2;
|
|
49
|
+
const radius = 16 + level / maxDepth * 26;
|
|
50
|
+
return {
|
|
51
|
+
...node,
|
|
52
|
+
x: Number((50 + Math.cos(angle) * radius).toFixed(3)),
|
|
53
|
+
y: Number((50 + Math.sin(angle) * radius).toFixed(3)),
|
|
54
|
+
depth: level
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function traverseRelationshipNode(nodes, currentId, direction) {
|
|
59
|
+
if (nodes.length === 0) return void 0;
|
|
60
|
+
const current = Math.max(0, nodes.findIndex((node) => node.id === currentId));
|
|
61
|
+
return nodes[(current + direction + nodes.length) % nodes.length]?.id;
|
|
62
|
+
}
|
|
63
|
+
export {
|
|
64
|
+
boundRelationshipGraph,
|
|
65
|
+
layoutRelationshipGraph,
|
|
66
|
+
relationshipNeighbors,
|
|
67
|
+
traverseRelationshipNode
|
|
68
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { JsonValue } from './json-value.js';
|
|
2
|
+
|
|
3
|
+
interface RuleCondition {
|
|
4
|
+
id: string;
|
|
5
|
+
field: string;
|
|
6
|
+
operator: string;
|
|
7
|
+
value?: JsonValue;
|
|
8
|
+
}
|
|
9
|
+
interface RuleGroup {
|
|
10
|
+
id: string;
|
|
11
|
+
combinator: 'and' | 'or';
|
|
12
|
+
conditions: Array<RuleCondition | RuleGroup>;
|
|
13
|
+
}
|
|
14
|
+
interface RuleAction {
|
|
15
|
+
id: string;
|
|
16
|
+
type: string;
|
|
17
|
+
parameters: Record<string, JsonValue>;
|
|
18
|
+
}
|
|
19
|
+
interface RuleDefinition {
|
|
20
|
+
when: RuleGroup;
|
|
21
|
+
then: RuleAction[];
|
|
22
|
+
}
|
|
23
|
+
interface RuleValidationIssue {
|
|
24
|
+
path: string;
|
|
25
|
+
message: string;
|
|
26
|
+
}
|
|
27
|
+
declare function isRuleGroup(node: RuleCondition | RuleGroup): node is RuleGroup;
|
|
28
|
+
declare function ruleDepth(group: RuleGroup): number;
|
|
29
|
+
declare function findRuleNodeDepth(group: RuleGroup, id: string, depth?: number): number | undefined;
|
|
30
|
+
declare function mapRuleGroup(group: RuleGroup, id: string, update: (node: RuleCondition | RuleGroup) => RuleCondition | RuleGroup): RuleGroup;
|
|
31
|
+
declare function appendRuleNode(group: RuleGroup, parentId: string, node: RuleCondition | RuleGroup, maxDepth?: number): RuleGroup;
|
|
32
|
+
declare function removeRuleNode(group: RuleGroup, id: string): RuleGroup;
|
|
33
|
+
declare function moveRuleNode(group: RuleGroup, id: string, direction: -1 | 1): RuleGroup;
|
|
34
|
+
declare function validateRuleDefinition(value: RuleDefinition, maxDepth?: number): RuleValidationIssue[];
|
|
35
|
+
declare function summarizeRule(value: RuleDefinition, labels?: {
|
|
36
|
+
fields?: Record<string, string>;
|
|
37
|
+
operators?: Record<string, string>;
|
|
38
|
+
actions?: Record<string, string>;
|
|
39
|
+
}): string;
|
|
40
|
+
|
|
41
|
+
export { type RuleAction, type RuleCondition, type RuleDefinition, type RuleGroup, type RuleValidationIssue, appendRuleNode, findRuleNodeDepth, isRuleGroup, mapRuleGroup, moveRuleNode, removeRuleNode, ruleDepth, summarizeRule, validateRuleDefinition };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
function isRuleGroup(node) {
|
|
2
|
+
return "conditions" in node;
|
|
3
|
+
}
|
|
4
|
+
function ruleDepth(group) {
|
|
5
|
+
return 1 + Math.max(0, ...group.conditions.filter(isRuleGroup).map(ruleDepth));
|
|
6
|
+
}
|
|
7
|
+
function findRuleNodeDepth(group, id, depth = 1) {
|
|
8
|
+
if (group.id === id) return depth;
|
|
9
|
+
for (const node of group.conditions) {
|
|
10
|
+
if (node.id === id) return depth + 1;
|
|
11
|
+
if (isRuleGroup(node)) {
|
|
12
|
+
const found = findRuleNodeDepth(node, id, depth + 1);
|
|
13
|
+
if (found !== void 0) return found;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return void 0;
|
|
17
|
+
}
|
|
18
|
+
function mapRuleGroup(group, id, update) {
|
|
19
|
+
if (group.id === id) return update(group);
|
|
20
|
+
return {
|
|
21
|
+
...group,
|
|
22
|
+
conditions: group.conditions.map((node) => {
|
|
23
|
+
if (node.id === id) return update(node);
|
|
24
|
+
return isRuleGroup(node) ? mapRuleGroup(node, id, update) : node;
|
|
25
|
+
})
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function appendRuleNode(group, parentId, node, maxDepth = 3) {
|
|
29
|
+
const parentDepth = findRuleNodeDepth(group, parentId);
|
|
30
|
+
if (parentDepth === void 0) return group;
|
|
31
|
+
const addedDepth = isRuleGroup(node) ? ruleDepth(node) : 0;
|
|
32
|
+
if (parentDepth + addedDepth > maxDepth) return group;
|
|
33
|
+
return mapRuleGroup(group, parentId, (parent) => isRuleGroup(parent) ? { ...parent, conditions: [...parent.conditions, node] } : parent);
|
|
34
|
+
}
|
|
35
|
+
function removeRuleNode(group, id) {
|
|
36
|
+
return {
|
|
37
|
+
...group,
|
|
38
|
+
conditions: group.conditions.filter((node) => node.id !== id).map((node) => isRuleGroup(node) ? removeRuleNode(node, id) : node)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function moveRuleNode(group, id, direction) {
|
|
42
|
+
const index = group.conditions.findIndex((node) => node.id === id);
|
|
43
|
+
if (index >= 0) {
|
|
44
|
+
const target = index + direction;
|
|
45
|
+
if (target < 0 || target >= group.conditions.length) return group;
|
|
46
|
+
const conditions = [...group.conditions];
|
|
47
|
+
[conditions[index], conditions[target]] = [conditions[target], conditions[index]];
|
|
48
|
+
return { ...group, conditions };
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
...group,
|
|
52
|
+
conditions: group.conditions.map((node) => isRuleGroup(node) ? moveRuleNode(node, id, direction) : node)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function validateRuleDefinition(value, maxDepth = 3) {
|
|
56
|
+
const issues = [];
|
|
57
|
+
const ids = /* @__PURE__ */ new Set();
|
|
58
|
+
const visit = (group, path, depth) => {
|
|
59
|
+
if (ids.has(group.id)) issues.push({ path, message: `Duplicate id \u201C${group.id}\u201D.` });
|
|
60
|
+
ids.add(group.id);
|
|
61
|
+
if (depth > maxDepth) issues.push({ path, message: `Nesting exceeds ${maxDepth} levels.` });
|
|
62
|
+
if (group.conditions.length === 0) issues.push({ path, message: "Add at least one condition." });
|
|
63
|
+
group.conditions.forEach((node, index) => {
|
|
64
|
+
const nodePath = `${path}.conditions[${index}]`;
|
|
65
|
+
if (ids.has(node.id)) issues.push({ path: nodePath, message: `Duplicate id \u201C${node.id}\u201D.` });
|
|
66
|
+
if (isRuleGroup(node)) visit(node, nodePath, depth + 1);
|
|
67
|
+
else {
|
|
68
|
+
ids.add(node.id);
|
|
69
|
+
if (!node.field) issues.push({ path: nodePath, message: "Choose a field." });
|
|
70
|
+
if (!node.operator) issues.push({ path: nodePath, message: "Choose an operator." });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
visit(value.when, "when", 1);
|
|
75
|
+
if (value.then.length === 0) issues.push({ path: "then", message: "Add at least one action." });
|
|
76
|
+
value.then.forEach((action, index) => {
|
|
77
|
+
if (ids.has(action.id)) issues.push({ path: `then[${index}]`, message: `Duplicate id \u201C${action.id}\u201D.` });
|
|
78
|
+
ids.add(action.id);
|
|
79
|
+
if (!action.type) issues.push({ path: `then[${index}]`, message: "Choose an action." });
|
|
80
|
+
});
|
|
81
|
+
return issues;
|
|
82
|
+
}
|
|
83
|
+
function summarizeRule(value, labels = {}) {
|
|
84
|
+
const formatValue = (input) => input === void 0 ? "" : ` ${JSON.stringify(input)}`;
|
|
85
|
+
const formatGroup = (group) => group.conditions.map(
|
|
86
|
+
(node) => isRuleGroup(node) ? `(${formatGroup(node)})` : `${labels.fields?.[node.field] ?? node.field} ${labels.operators?.[node.operator] ?? node.operator}${formatValue(node.value)}`
|
|
87
|
+
).join(` ${group.combinator.toUpperCase()} `);
|
|
88
|
+
const actions = value.then.map((action) => labels.actions?.[action.type] ?? action.type).join(", ");
|
|
89
|
+
return `When ${formatGroup(value.when) || "no conditions"}, then ${actions || "no actions"}.`;
|
|
90
|
+
}
|
|
91
|
+
export {
|
|
92
|
+
appendRuleNode,
|
|
93
|
+
findRuleNodeDepth,
|
|
94
|
+
isRuleGroup,
|
|
95
|
+
mapRuleGroup,
|
|
96
|
+
moveRuleNode,
|
|
97
|
+
removeRuleNode,
|
|
98
|
+
ruleDepth,
|
|
99
|
+
summarizeRule,
|
|
100
|
+
validateRuleDefinition
|
|
101
|
+
};
|