@tensor_1/react 2.11.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.
Files changed (65) hide show
  1. package/README.md +26 -1
  2. package/dist/ChartCore-Bt1C84ty.d.cts +22 -0
  3. package/dist/calendar-model.d.ts +31 -0
  4. package/dist/calendar-model.js +89 -0
  5. package/dist/chart-preset.cjs +168 -0
  6. package/dist/chart-preset.d.cts +9 -0
  7. package/dist/chart-preset.d.ts +9 -0
  8. package/dist/chart-preset.js +35 -0
  9. package/dist/chart.cjs +58 -32
  10. package/dist/chart.d.cts +6 -21
  11. package/dist/chart.d.ts +2 -1
  12. package/dist/color-model.d.ts +20 -0
  13. package/dist/color-model.js +74 -0
  14. package/dist/components/BrandProfiles.d.ts +45 -0
  15. package/dist/components/BrandProfiles.js +150 -0
  16. package/dist/components/BuilderCanvas.d.ts +34 -0
  17. package/dist/components/BuilderCanvas.js +117 -0
  18. package/dist/components/Chart.d.ts +6 -21
  19. package/dist/components/Chart.js +5 -76
  20. package/dist/components/ChartCore.d.ts +33 -0
  21. package/dist/components/ChartCore.js +100 -0
  22. package/dist/components/ColorPicker.d.ts +17 -0
  23. package/dist/components/ColorPicker.js +158 -0
  24. package/dist/components/DateRangePicker.d.ts +23 -0
  25. package/dist/components/DateRangePicker.js +123 -0
  26. package/dist/components/DiffViewer.d.ts +18 -0
  27. package/dist/components/DiffViewer.js +93 -0
  28. package/dist/components/Inbox.js +0 -1
  29. package/dist/components/LicensePositionBar.d.ts +17 -0
  30. package/dist/components/LicensePositionBar.js +50 -0
  31. package/dist/components/MatchReview.d.ts +39 -0
  32. package/dist/components/MatchReview.js +120 -0
  33. package/dist/components/Meter.js +0 -1
  34. package/dist/components/MetricInput.d.ts +23 -0
  35. package/dist/components/MetricInput.js +92 -0
  36. package/dist/components/NavFavourites.js +35 -108
  37. package/dist/components/RelationshipGraph.d.ts +30 -0
  38. package/dist/components/RelationshipGraph.js +138 -0
  39. package/dist/components/RuleBuilder.d.ts +45 -0
  40. package/dist/components/RuleBuilder.js +163 -0
  41. package/dist/components/SchedulingCalendar.d.ts +42 -0
  42. package/dist/components/SchedulingCalendar.js +124 -0
  43. package/dist/components/Segmented.js +3 -2
  44. package/dist/components/Table.d.ts +1 -1
  45. package/dist/components/Table.js +4 -3
  46. package/dist/components/Tabs.js +3 -2
  47. package/dist/diff-model.d.ts +23 -0
  48. package/dist/diff-model.js +50 -0
  49. package/dist/hooks/useTable.js +11 -7
  50. package/dist/hooks/useVirtualRows.d.ts +27 -0
  51. package/dist/hooks/useVirtualRows.js +50 -0
  52. package/dist/index.cjs +1930 -194
  53. package/dist/index.d.cts +464 -2
  54. package/dist/index.d.ts +19 -0
  55. package/dist/index.js +93 -1
  56. package/dist/json-value.d.ts +10 -0
  57. package/dist/json-value.js +19 -0
  58. package/dist/metric-model.d.ts +9 -0
  59. package/dist/metric-model.js +25 -0
  60. package/dist/relationship-graph-model.d.ts +31 -0
  61. package/dist/relationship-graph-model.js +68 -0
  62. package/dist/rule-builder-model.d.ts +41 -0
  63. package/dist/rule-builder-model.js +101 -0
  64. package/dist/table-engine.js +8 -6
  65. package/package.json +16 -2
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { cx } from "./cx.js";
2
2
  import { useDialog } from "./hooks/useDialog.js";
3
3
  import { useTable } from "./hooks/useTable.js";
4
+ import { useVirtualRows } from "./hooks/useVirtualRows.js";
4
5
  import { useAnchoredPosition } from "./hooks/useAnchoredPosition.js";
5
6
  import { computePosition } from "./overlay-position.js";
6
7
  import { Button, ButtonGroup } from "./components/Button.js";
@@ -78,11 +79,53 @@ import {
78
79
  EventRow,
79
80
  StatusRow
80
81
  } from "./components/EditorialHome.js";
82
+ import { RuleBuilder } from "./components/RuleBuilder.js";
83
+ import {
84
+ appendRuleNode,
85
+ findRuleNodeDepth,
86
+ isRuleGroup,
87
+ mapRuleGroup,
88
+ moveRuleNode,
89
+ removeRuleNode,
90
+ ruleDepth,
91
+ summarizeRule,
92
+ validateRuleDefinition
93
+ } from "./rule-builder-model.js";
94
+ import { BuilderCanvas } from "./components/BuilderCanvas.js";
95
+ import { SchedulingCalendar } from "./components/SchedulingCalendar.js";
96
+ import { DateRangePicker } from "./components/DateRangePicker.js";
97
+ import {
98
+ addCalendarDays,
99
+ addCalendarMonths,
100
+ buildMonthGrid,
101
+ enumerateDateSpan,
102
+ isDateInRange,
103
+ isDateUnavailable,
104
+ selectRangeDate,
105
+ startOfMonth,
106
+ toDateKey,
107
+ zonedDateKey,
108
+ zonedDateSpan
109
+ } from "./calendar-model.js";
110
+ import { RelationshipGraph } from "./components/RelationshipGraph.js";
111
+ import { boundRelationshipGraph, layoutRelationshipGraph, relationshipNeighbors, traverseRelationshipNode } from "./relationship-graph-model.js";
112
+ import { MatchReview } from "./components/MatchReview.js";
113
+ import { MetricInput } from "./components/MetricInput.js";
114
+ import { clampMetricValue, parseMetricValue, stepMetricValue } from "./metric-model.js";
115
+ import { LicensePositionBar } from "./components/LicensePositionBar.js";
116
+ import { BrandProfiles, BrandProfileEditor, applyBrandProfile, restoreBrandProfile } from "./components/BrandProfiles.js";
117
+ import { DiffViewer } from "./components/DiffViewer.js";
118
+ import { buildThreeWayDiff, summarizeDiff } from "./diff-model.js";
119
+ import { ColorPicker } from "./components/ColorPicker.js";
120
+ import { contrastRatio, hexToRgb, hsvToHex, hsvToRgb, meetsContrast, normalizeHex, rgbToHex, rgbToHsv } from "./color-model.js";
81
121
  export {
82
122
  Alert,
83
123
  AppShell,
84
124
  Avatar,
85
125
  AvatarGroup,
126
+ BrandProfileEditor,
127
+ BrandProfiles,
128
+ BuilderCanvas,
86
129
  BulkBar,
87
130
  Button,
88
131
  ButtonGroup,
@@ -90,6 +133,7 @@ export {
90
133
  CellStrong,
91
134
  CellSub,
92
135
  Checkbox,
136
+ ColorPicker,
93
137
  CommandGroup,
94
138
  CommandItem,
95
139
  CommandPalette,
@@ -99,9 +143,11 @@ export {
99
143
  ComposerBar,
100
144
  ContentList,
101
145
  ContentListItem,
146
+ DateRangePicker,
102
147
  DescriptionItem,
103
148
  DescriptionList,
104
149
  DetailLayout,
150
+ DiffViewer,
105
151
  Drawer,
106
152
  EmptyState,
107
153
  ErrorState,
@@ -122,11 +168,14 @@ export {
122
168
  KanbanCard,
123
169
  KanbanColumn,
124
170
  Label,
171
+ LicensePositionBar,
125
172
  List,
126
173
  ListItem,
127
174
  LoadingState,
128
175
  Mark,
176
+ MatchReview,
129
177
  Meter,
178
+ MetricInput,
130
179
  Modal,
131
180
  NavFavourites,
132
181
  NavGroup,
@@ -143,9 +192,12 @@ export {
143
192
  Prose,
144
193
  Radio,
145
194
  RadioGroup,
195
+ RelationshipGraph,
146
196
  ResourceGrid,
147
197
  RowAction,
148
198
  RowActions,
199
+ RuleBuilder,
200
+ SchedulingCalendar,
149
201
  SectionHead,
150
202
  Segmented,
151
203
  SegmentedOption,
@@ -176,11 +228,51 @@ export {
176
228
  Tr,
177
229
  Tree,
178
230
  UserChip,
231
+ addCalendarDays,
232
+ addCalendarMonths,
233
+ appendRuleNode,
234
+ applyBrandProfile,
235
+ boundRelationshipGraph,
236
+ buildMonthGrid,
237
+ buildThreeWayDiff,
238
+ clampMetricValue,
179
239
  computePosition,
240
+ contrastRatio,
180
241
  cx,
242
+ enumerateDateSpan,
243
+ findRuleNodeDepth,
181
244
  flattenTree,
245
+ hexToRgb,
246
+ hsvToHex,
247
+ hsvToRgb,
248
+ isDateInRange,
249
+ isDateUnavailable,
250
+ isRuleGroup,
251
+ layoutRelationshipGraph,
252
+ mapRuleGroup,
253
+ meetsContrast,
254
+ moveRuleNode,
255
+ normalizeHex,
256
+ parseMetricValue,
257
+ relationshipNeighbors,
258
+ removeRuleNode,
259
+ restoreBrandProfile,
260
+ rgbToHex,
261
+ rgbToHsv,
262
+ ruleDepth,
263
+ selectRangeDate,
264
+ startOfMonth,
265
+ stepMetricValue,
266
+ summarizeDiff,
267
+ summarizeRule,
268
+ toDateKey,
269
+ traverseRelationshipNode,
182
270
  treeNav,
183
271
  useAnchoredPosition,
184
272
  useDialog,
185
- useTable
273
+ useTable,
274
+ useVirtualRows,
275
+ validateRuleDefinition,
276
+ zonedDateKey,
277
+ zonedDateSpan
186
278
  };
@@ -0,0 +1,10 @@
1
+ type JsonPrimitive = string | number | boolean | null;
2
+ type JsonValue = JsonPrimitive | JsonValue[] | {
3
+ [key: string]: JsonValue;
4
+ };
5
+ declare function isJsonObject(value: JsonValue | undefined): value is {
6
+ [key: string]: JsonValue;
7
+ };
8
+ declare function jsonEqual(a: JsonValue | undefined, b: JsonValue | undefined): boolean;
9
+
10
+ export { type JsonPrimitive, type JsonValue, isJsonObject, jsonEqual };
@@ -0,0 +1,19 @@
1
+ function isJsonObject(value) {
2
+ return value !== null && typeof value === "object" && !Array.isArray(value);
3
+ }
4
+ function jsonEqual(a, b) {
5
+ if (a === b) return true;
6
+ if (Array.isArray(a) && Array.isArray(b)) {
7
+ return a.length === b.length && a.every((value, index) => jsonEqual(value, b[index]));
8
+ }
9
+ if (isJsonObject(a) && isJsonObject(b)) {
10
+ const aKeys = Object.keys(a).sort();
11
+ const bKeys = Object.keys(b).sort();
12
+ return aKeys.length === bKeys.length && aKeys.every((key, index) => key === bKeys[index] && jsonEqual(a[key], b[key]));
13
+ }
14
+ return false;
15
+ }
16
+ export {
17
+ isJsonObject,
18
+ jsonEqual
19
+ };
@@ -0,0 +1,9 @@
1
+ declare function clampMetricValue(value: number, min?: number, max?: number): number;
2
+ declare function stepMetricValue(value: number | null, direction: -1 | 1, options?: {
3
+ min?: number;
4
+ max?: number;
5
+ step?: number;
6
+ }): number;
7
+ declare function parseMetricValue(value: string): number | null;
8
+
9
+ export { clampMetricValue, parseMetricValue, stepMetricValue };
@@ -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
+ };
@@ -1,19 +1,20 @@
1
+ const stringCollator = new Intl.Collator(void 0, { numeric: true, sensitivity: "base" });
1
2
  function compare(a, b) {
2
3
  if (a == null && b == null) return 0;
3
4
  if (a == null) return -1;
4
5
  if (b == null) return 1;
5
6
  if (typeof a === "number" && typeof b === "number") return a - b;
6
- return String(a).localeCompare(String(b), void 0, { numeric: true, sensitivity: "base" });
7
+ return stringCollator.compare(String(a), String(b));
7
8
  }
8
9
  function multiSort(rows, keys) {
9
10
  if (!keys.length) return rows.slice();
10
- return rows.map((row, i) => ({ row, i })).sort((x, y) => {
11
+ return rows.slice().sort((a, b) => {
11
12
  for (const k of keys) {
12
- const c = compare(x.row[k.field], y.row[k.field]);
13
+ const c = compare(a[k.field], b[k.field]);
13
14
  if (c !== 0) return k.dir === "ascending" ? c : -c;
14
15
  }
15
- return x.i - y.i;
16
- }).map((w) => w.row);
16
+ return 0;
17
+ });
17
18
  }
18
19
  function nextSortDir(current) {
19
20
  if (current === "ascending") return "descending";
@@ -213,7 +214,8 @@ function toggleId(set, id) {
213
214
  return next;
214
215
  }
215
216
  function selectAllState(selected, pageIds) {
216
- const on = pageIds.filter((id) => selected.has(id)).length;
217
+ let on = 0;
218
+ for (const id of pageIds) if (selected.has(id)) on += 1;
217
219
  if (on === 0) return "none";
218
220
  return on === pageIds.length ? "all" : "some";
219
221
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tensor_1/react",
3
- "version": "2.11.0",
3
+ "version": "2.13.0",
4
4
  "description": "Thin React wrappers over the UIx v2 CSS component library.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -26,22 +26,36 @@
26
26
  "types": "./dist/chart.d.ts",
27
27
  "import": "./dist/chart.js",
28
28
  "require": "./dist/chart.cjs"
29
+ },
30
+ "./chart/preset": {
31
+ "types": "./dist/chart-preset.d.ts",
32
+ "import": "./dist/chart-preset.js",
33
+ "require": "./dist/chart-preset.cjs"
29
34
  }
30
35
  },
31
36
  "scripts": {
32
37
  "build": "tsup",
33
38
  "dev": "tsup --watch",
34
39
  "typecheck": "tsc --noEmit",
35
- "test": "node --test"
40
+ "test": "node --test",
41
+ "test:performance": "node scripts/table-performance.mjs",
42
+ "size": "node scripts/check-chart-preset-size.mjs"
36
43
  },
37
44
  "peerDependencies": {
45
+ "echarts": "^5.6.0",
38
46
  "react": "^18.0.0 || ^19.0.0",
39
47
  "react-dom": "^18.0.0 || ^19.0.0"
40
48
  },
49
+ "peerDependenciesMeta": {
50
+ "echarts": {
51
+ "optional": true
52
+ }
53
+ },
41
54
  "devDependencies": {
42
55
  "@types/react": "^18.0.0",
43
56
  "@types/react-dom": "^18.0.0",
44
57
  "echarts": "^5.6.0",
58
+ "esbuild": "^0.27.0",
45
59
  "tsup": "^8.0.0",
46
60
  "typescript": "^5.0.0"
47
61
  }