@amritanshu3011/mdx-renderer 1.0.0 → 1.0.3

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 (91) hide show
  1. package/dist/MDXRenderer.d.ts +7 -0
  2. package/dist/MDXRenderer.js +56 -0
  3. package/dist/components/DynamicVisualizations.d.ts +2 -0
  4. package/dist/components/DynamicVisualizations.js +17 -0
  5. package/dist/components/WeatherWidget.d.ts +6 -0
  6. package/dist/components/WeatherWidget.js +29 -0
  7. package/dist/components/composite/Dashboard.d.ts +8 -0
  8. package/dist/components/composite/Dashboard.js +14 -0
  9. package/dist/components/composite/DataExplorer.d.ts +8 -0
  10. package/dist/components/composite/DataExplorer.js +37 -0
  11. package/dist/components/composite/index.d.ts +0 -0
  12. package/dist/components/composite/index.js +1 -0
  13. package/dist/components/data/BarChart.d.ts +10 -0
  14. package/dist/components/data/BarChart.js +17 -0
  15. package/dist/components/data/LineChart.d.ts +10 -0
  16. package/dist/components/data/LineChart.js +17 -0
  17. package/dist/components/data/SimpleChart.d.ts +6 -0
  18. package/dist/components/data/SimpleChart.js +18 -0
  19. package/dist/components/data/Table.d.ts +0 -0
  20. package/dist/components/data/Table.js +1 -0
  21. package/dist/components/data/index.d.ts +0 -0
  22. package/dist/components/data/index.js +1 -0
  23. package/dist/components/index.d.ts +0 -0
  24. package/dist/components/index.js +1 -0
  25. package/dist/components/interactive/Accordion.d.ts +8 -0
  26. package/dist/components/interactive/Accordion.js +29 -0
  27. package/dist/components/interactive/Modal.d.ts +0 -0
  28. package/dist/components/interactive/Modal.js +1 -0
  29. package/dist/components/interactive/Tabs.d.ts +11 -0
  30. package/dist/components/interactive/Tabs.js +22 -0
  31. package/dist/components/interactive/index.d.ts +0 -0
  32. package/dist/components/interactive/index.js +1 -0
  33. package/dist/components/layout/Card.d.ts +6 -0
  34. package/dist/components/layout/Card.js +13 -0
  35. package/dist/components/layout/Container.d.ts +0 -0
  36. package/dist/components/layout/Container.js +1 -0
  37. package/dist/components/layout/Grid.d.ts +0 -0
  38. package/dist/components/layout/Grid.js +1 -0
  39. package/dist/components/layout/index.d.ts +0 -0
  40. package/dist/components/layout/index.js +1 -0
  41. package/dist/components/smart/ComparisonBlock.d.ts +14 -0
  42. package/dist/components/smart/ComparisonBlock.js +81 -0
  43. package/dist/components/smart/ConceptTreeBlock.d.ts +11 -0
  44. package/dist/components/smart/ConceptTreeBlock.js +140 -0
  45. package/dist/components/smart/FlowBlock.d.ts +11 -0
  46. package/dist/components/smart/FlowBlock.js +122 -0
  47. package/dist/components/smart/InteractiveCompositeBlock.d.ts +22 -0
  48. package/dist/components/smart/InteractiveCompositeBlock.js +102 -0
  49. package/dist/components/smart/LineChartBlock.d.ts +8 -0
  50. package/dist/components/smart/LineChartBlock.js +22 -0
  51. package/dist/components/smart/ProsConsBlock.d.ts +7 -0
  52. package/dist/components/smart/ProsConsBlock.js +77 -0
  53. package/dist/components/smart/Sunburst.d.ts +12 -0
  54. package/dist/components/smart/Sunburst.js +152 -0
  55. package/dist/components/text/Blockquote.d.ts +7 -0
  56. package/dist/components/text/Blockquote.js +16 -0
  57. package/dist/components/text/ComparisonGrid.d.ts +14 -0
  58. package/dist/components/text/ComparisonGrid.js +46 -0
  59. package/dist/components/text/Heading.d.ts +7 -0
  60. package/dist/components/text/Heading.js +13 -0
  61. package/dist/components/text/List.d.ts +7 -0
  62. package/dist/components/text/List.js +12 -0
  63. package/dist/components/text/Paragraph.d.ts +6 -0
  64. package/dist/components/text/Paragraph.js +13 -0
  65. package/dist/components/text/ProcessFlow.d.ts +12 -0
  66. package/dist/components/text/ProcessFlow.js +48 -0
  67. package/dist/components/text/index.d.ts +0 -0
  68. package/dist/components/text/index.js +1 -0
  69. package/dist/context/VisualizationContext.d.ts +13 -0
  70. package/dist/context/VisualizationContext.js +21 -0
  71. package/dist/index.d.ts +27 -0
  72. package/dist/index.js +34 -0
  73. package/dist/registry/visualizationRegistry.d.ts +10 -0
  74. package/dist/registry/visualizationRegistry.js +16 -0
  75. package/dist/theme/ThemeContext.d.ts +14 -0
  76. package/dist/theme/ThemeContext.js +19 -0
  77. package/dist/theme/defaultTheme.d.ts +2 -0
  78. package/dist/theme/defaultTheme.js +30 -0
  79. package/dist/theme/index.d.ts +0 -0
  80. package/dist/theme/index.js +1 -0
  81. package/dist/theme/themes.d.ts +3 -0
  82. package/dist/theme/themes.js +60 -0
  83. package/dist/theme/types.d.ts +30 -0
  84. package/dist/theme/types.js +1 -0
  85. package/dist/types/mockLLM.d.ts +5 -0
  86. package/dist/types/mockLLM.js +109 -0
  87. package/dist/utils/useThemeWithFallback.d.ts +2 -0
  88. package/dist/utils/useThemeWithFallback.js +7 -0
  89. package/dist/utils/withDefaults.d.ts +2 -0
  90. package/dist/utils/withDefaults.js +4 -0
  91. package/package.json +29 -24
@@ -0,0 +1,140 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState, useMemo, useEffect } from 'react';
3
+ import { useThemeWithFallback } from '../../utils/useThemeWithFallback';
4
+ export const ConceptTreeBlock = ({ title, root }) => {
5
+ const theme = useThemeWithFallback();
6
+ // --- State ---
7
+ const [viewMode, setViewMode] = useState('tree');
8
+ const [filterText, setFilterText] = useState('');
9
+ const [sortMode, setSortMode] = useState('original');
10
+ const [expanded, setExpanded] = useState(new Set([root.name])); // Root open by default
11
+ const [isPivoted, setIsPivoted] = useState(false); // Used to toggle Level view
12
+ // --- Helpers ---
13
+ // 1. Flatten Tree (for List/Grid/Level views)
14
+ const flattenTree = (node, depth = 0) => {
15
+ let result = [{ node, depth, path: node.name }];
16
+ if (node.children) {
17
+ node.children.forEach(child => {
18
+ result = [...result, ...flattenTree(child, depth + 1)];
19
+ });
20
+ }
21
+ return result;
22
+ };
23
+ // 2. Recursive Filter & Sort (For Tree View)
24
+ const processTree = (node) => {
25
+ // A. Check if current node matches
26
+ const matchesSelf = node.name.toLowerCase().includes(filterText.toLowerCase());
27
+ // B. Process Children
28
+ let processedChildren = [];
29
+ if (node.children) {
30
+ processedChildren = node.children
31
+ .map(child => processTree(child))
32
+ .filter((child) => child !== null);
33
+ // Sort Children if needed
34
+ if (sortMode !== 'original') {
35
+ processedChildren.sort((a, b) => sortMode === 'asc' ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name));
36
+ }
37
+ }
38
+ // C. Return Node if it matches OR if it has matching children (keep context)
39
+ if (matchesSelf || processedChildren.length > 0) {
40
+ return { ...node, children: processedChildren.length > 0 ? processedChildren : undefined };
41
+ }
42
+ return null;
43
+ };
44
+ // --- Memoized Data ---
45
+ const processedRoot = useMemo(() => processTree(root), [root, filterText, sortMode]);
46
+ const flatData = useMemo(() => {
47
+ if (!processedRoot)
48
+ return [];
49
+ return flattenTree(processedRoot);
50
+ }, [processedRoot]);
51
+ // Group by Levels (The "Pivot")
52
+ const dataByLevel = useMemo(() => {
53
+ const levels = {};
54
+ flatData.forEach(item => {
55
+ if (!levels[item.depth])
56
+ levels[item.depth] = [];
57
+ levels[item.depth].push(item);
58
+ });
59
+ return levels;
60
+ }, [flatData]);
61
+ // --- Handlers ---
62
+ const toggleExpand = (name) => {
63
+ const next = new Set(expanded);
64
+ if (next.has(name))
65
+ next.delete(name);
66
+ else
67
+ next.add(name);
68
+ setExpanded(next);
69
+ };
70
+ const expandAll = () => {
71
+ const allNames = new Set(flatData.map(d => d.node.name));
72
+ setExpanded(allNames);
73
+ };
74
+ const collapseAll = () => setExpanded(new Set());
75
+ // Auto-expand when searching
76
+ useEffect(() => {
77
+ if (filterText)
78
+ expandAll();
79
+ }, [filterText]);
80
+ // --- Render Helpers ---
81
+ const btnStyle = (active) => ({
82
+ padding: `${theme.spacing.small} ${theme.spacing.medium}`,
83
+ backgroundColor: active ? theme.colors.primary : 'transparent',
84
+ color: active ? '#fff' : theme.colors.text,
85
+ border: `1px solid ${theme.colors.primary}`,
86
+ borderRadius: theme.borderRadius.small,
87
+ cursor: 'pointer',
88
+ fontSize: theme.typography.smallSize
89
+ });
90
+ // Recursive Renderer (The Original Logic, enhanced)
91
+ const renderNode = (node, level = 0) => {
92
+ const hasChildren = node.children && node.children.length > 0;
93
+ const isExpanded = expanded.has(node.name);
94
+ return (_jsxs("div", { style: { marginLeft: level > 0 ? theme.spacing.large : '0' }, children: [_jsxs("div", { style: {
95
+ display: 'flex',
96
+ alignItems: 'center',
97
+ gap: theme.spacing.small,
98
+ padding: theme.spacing.small,
99
+ backgroundColor: theme.colors.cardBackground,
100
+ border: `1px solid ${theme.colors.border}`,
101
+ borderRadius: theme.borderRadius.small,
102
+ marginBottom: theme.spacing.small,
103
+ color: theme.colors.text,
104
+ fontWeight: level === 0 ? 'bold' : 'normal'
105
+ }, children: [hasChildren ? (_jsx("button", { onClick: () => toggleExpand(node.name), style: {
106
+ background: 'none', border: 'none', cursor: 'pointer',
107
+ color: theme.colors.primary, fontWeight: 'bold', width: '20px'
108
+ }, children: isExpanded ? '▼' : '▶' })) : _jsx("span", { style: { width: '20px' } }), node.name, level === 0 && _jsx("span", { style: { fontSize: '10px', color: theme.colors.textSecondary, border: `1px solid ${theme.colors.border}`, padding: '0 4px', borderRadius: '4px' }, children: "ROOT" })] }), hasChildren && isExpanded && (_jsx("div", { style: { borderLeft: `1px solid ${theme.colors.border}`, marginLeft: '12px', paddingLeft: '12px' }, children: node.children.map(child => renderNode(child, level + 1)) }))] }, node.name));
109
+ };
110
+ return (_jsxs("div", { style: {
111
+ margin: `${theme.spacing.large} 0`,
112
+ border: `1px solid ${theme.colors.border}`,
113
+ borderRadius: theme.borderRadius.medium,
114
+ boxShadow: '0 4px 12px rgba(0,0,0,0.05)',
115
+ overflow: 'hidden'
116
+ }, children: [_jsxs("div", { style: {
117
+ padding: theme.spacing.medium,
118
+ borderBottom: `1px solid ${theme.colors.border}`,
119
+ backgroundColor: theme.colors.background
120
+ }, children: [_jsx("h2", { style: { margin: `0 0 ${theme.spacing.medium} 0`, color: theme.colors.text }, children: title }), _jsxs("div", { style: { display: 'flex', flexWrap: 'wrap', gap: theme.spacing.medium, justifyContent: 'space-between' }, children: [_jsxs("div", { style: { display: 'flex', gap: theme.spacing.small, flexWrap: 'wrap' }, children: [_jsx("input", { type: "text", placeholder: "Filter nodes...", value: filterText, onChange: (e) => setFilterText(e.target.value), style: { padding: theme.spacing.small, borderRadius: theme.borderRadius.small, border: `1px solid ${theme.colors.border}` } }), _jsxs("button", { onClick: () => setSortMode(prev => prev === 'original' ? 'asc' : prev === 'asc' ? 'desc' : 'original'), style: btnStyle(sortMode !== 'original'), children: ["Sort ", sortMode === 'original' ? 'Original' : sortMode === 'asc' ? '(A-Z)' : '(Z-A)'] }), viewMode === 'tree' && (_jsxs(_Fragment, { children: [_jsx("button", { onClick: expandAll, style: btnStyle(false), children: "Expand All" }), _jsx("button", { onClick: collapseAll, style: btnStyle(false), children: "Collapse All" })] }))] }), _jsxs("div", { style: { display: 'flex', gap: theme.spacing.small }, children: [_jsx("button", { onClick: () => { setIsPivoted(!isPivoted); setViewMode(isPivoted ? 'tree' : 'levels'); }, style: btnStyle(isPivoted), children: "Pivot (By Depth)" }), _jsxs("div", { style: { display: 'flex', border: `1px solid ${theme.colors.primary}`, borderRadius: theme.borderRadius.small, overflow: 'hidden' }, children: [_jsx("button", { onClick: () => { setViewMode('tree'); setIsPivoted(false); }, style: { ...btnStyle(viewMode === 'tree'), border: 'none', borderRadius: 0 }, children: "Tree" }), _jsx("button", { onClick: () => { setViewMode('grid'); setIsPivoted(false); }, style: { ...btnStyle(viewMode === 'grid'), border: 'none', borderRadius: 0 }, children: "Grid" }), _jsx("button", { onClick: () => { setViewMode('list'); setIsPivoted(false); }, style: { ...btnStyle(viewMode === 'list'), border: 'none', borderRadius: 0 }, children: "List" })] })] })] })] }), _jsxs("div", { style: { padding: theme.spacing.medium, backgroundColor: theme.colors.background, minHeight: '200px' }, children: [!processedRoot && _jsx("div", { style: { color: theme.colors.textSecondary, textAlign: 'center' }, children: "No matches found." }), viewMode === 'tree' && processedRoot && (renderNode(processedRoot)), viewMode === 'grid' && (_jsx("div", { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))', gap: theme.spacing.medium }, children: flatData.map((item, i) => (_jsxs("div", { style: {
121
+ padding: theme.spacing.medium,
122
+ border: `1px solid ${theme.colors.border}`,
123
+ backgroundColor: theme.colors.cardBackground,
124
+ borderRadius: theme.borderRadius.medium
125
+ }, children: [_jsx("div", { style: { fontWeight: 'bold', color: theme.colors.primary }, children: item.node.name }), _jsxs("div", { style: { fontSize: '10px', color: theme.colors.textSecondary, marginTop: '5px' }, children: ["Depth: ", item.depth] })] }, i))) })), viewMode === 'list' && (_jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '4px' }, children: flatData.map((item, i) => (_jsxs("div", { style: {
126
+ padding: theme.spacing.small,
127
+ borderBottom: `1px solid ${theme.colors.border}`,
128
+ display: 'flex', justifyContent: 'space-between'
129
+ }, children: [_jsx("span", { children: item.node.name }), _jsxs("span", { style: { color: theme.colors.textSecondary, fontSize: '12px' }, children: ["Level ", item.depth] })] }, i))) })), viewMode === 'levels' && (_jsx("div", { children: Object.entries(dataByLevel).map(([level, items]) => (_jsxs("div", { style: { marginBottom: theme.spacing.large }, children: [_jsxs("h4", { style: {
130
+ color: theme.colors.textSecondary,
131
+ borderBottom: `2px solid ${theme.colors.primary}`,
132
+ marginBottom: theme.spacing.small
133
+ }, children: ["Depth Level ", level] }), _jsx("div", { style: { display: 'flex', flexWrap: 'wrap', gap: theme.spacing.small }, children: items.map((item, i) => (_jsx("span", { style: {
134
+ padding: '4px 8px',
135
+ backgroundColor: theme.colors.cardBackground,
136
+ border: `1px solid ${theme.colors.border}`,
137
+ borderRadius: '12px',
138
+ fontSize: theme.typography.smallSize
139
+ }, children: item.node.name }, i))) })] }, level))) }))] })] }));
140
+ };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ interface FlowStep {
3
+ title: string;
4
+ description: string;
5
+ }
6
+ export interface FlowBlockProps {
7
+ title: string;
8
+ steps: FlowStep[];
9
+ }
10
+ export declare const FlowBlock: React.FC<FlowBlockProps>;
11
+ export {};
@@ -0,0 +1,122 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import React, { useState, useMemo } from 'react';
3
+ import { useThemeWithFallback } from '../../utils/useThemeWithFallback';
4
+ export const FlowBlock = ({ title, steps }) => {
5
+ const theme = useThemeWithFallback();
6
+ // --- State for Data Manipulation ---
7
+ const [viewMode, setViewMode] = useState('flow');
8
+ const [filterText, setFilterText] = useState('');
9
+ const [sortMode, setSortMode] = useState('original');
10
+ const [isGrouped, setIsGrouped] = useState(false); // Group by First Letter
11
+ const [isPivoted, setIsPivoted] = useState(false); // Only useful in Table view
12
+ // --- Logic: Filter & Sort ---
13
+ const processedData = useMemo(() => {
14
+ let data = [...steps];
15
+ // 1. Filter
16
+ if (filterText) {
17
+ const lower = filterText.toLowerCase();
18
+ data = data.filter(s => s.title.toLowerCase().includes(lower) ||
19
+ s.description.toLowerCase().includes(lower));
20
+ }
21
+ // 2. Sort
22
+ if (sortMode !== 'original') {
23
+ data.sort((a, b) => {
24
+ return sortMode === 'asc'
25
+ ? a.title.localeCompare(b.title)
26
+ : b.title.localeCompare(a.title);
27
+ });
28
+ }
29
+ return data;
30
+ }, [steps, filterText, sortMode]);
31
+ // --- Logic: Grouping ---
32
+ const groupedData = useMemo(() => {
33
+ if (!isGrouped)
34
+ return { 'All Steps': processedData };
35
+ return processedData.reduce((acc, step) => {
36
+ const key = step.title.charAt(0).toUpperCase();
37
+ if (!acc[key])
38
+ acc[key] = [];
39
+ acc[key].push(step);
40
+ return acc;
41
+ }, {});
42
+ }, [processedData, isGrouped]);
43
+ // --- Styles Helper ---
44
+ const btnStyle = (active) => ({
45
+ padding: `${theme.spacing.small} ${theme.spacing.medium}`,
46
+ backgroundColor: active ? theme.colors.primary : 'transparent',
47
+ color: active ? '#fff' : theme.colors.text,
48
+ border: `1px solid ${theme.colors.primary}`,
49
+ borderRadius: theme.borderRadius.small,
50
+ cursor: 'pointer',
51
+ fontSize: theme.typography.smallSize,
52
+ fontWeight: 'bold'
53
+ });
54
+ return (_jsxs("div", { style: {
55
+ margin: `${theme.spacing.large} 0`,
56
+ border: `1px solid ${theme.colors.border || '#ddd'}`,
57
+ borderRadius: theme.borderRadius.medium,
58
+ boxShadow: '0 4px 12px rgba(0,0,0,0.05)',
59
+ overflow: 'hidden'
60
+ }, children: [_jsxs("div", { style: {
61
+ padding: theme.spacing.medium,
62
+ borderBottom: `1px solid ${theme.colors.border || '#eee'}`,
63
+ backgroundColor: theme.colors.background || '#f9f9f9'
64
+ }, children: [_jsx("h2", { style: {
65
+ color: theme.colors.text,
66
+ margin: `0 0 ${theme.spacing.medium} 0`,
67
+ textAlign: 'left'
68
+ }, children: title }), _jsxs("div", { style: { display: 'flex', flexWrap: 'wrap', gap: theme.spacing.medium, alignItems: 'center', justifyContent: 'space-between' }, children: [_jsxs("div", { style: { display: 'flex', gap: theme.spacing.small, flexWrap: 'wrap' }, children: [_jsx("input", { type: "text", placeholder: "Filter steps...", value: filterText, onChange: (e) => setFilterText(e.target.value), style: {
69
+ padding: theme.spacing.small,
70
+ borderRadius: theme.borderRadius.small,
71
+ border: `1px solid ${theme.colors.border || '#ccc'}`
72
+ } }), _jsxs("button", { onClick: () => setSortMode(prev => prev === 'original' ? 'asc' : prev === 'asc' ? 'desc' : 'original'), style: btnStyle(sortMode !== 'original'), children: ["Sort ", sortMode === 'original' ? 'Original' : sortMode === 'asc' ? '(A-Z)' : '(Z-A)'] }), _jsx("button", { onClick: () => setIsGrouped(!isGrouped), style: btnStyle(isGrouped), children: isGrouped ? 'Ungroup' : 'Group (A-Z)' })] }), _jsxs("div", { style: { display: 'flex', gap: theme.spacing.small }, children: [viewMode === 'table' && (_jsx("button", { onClick: () => setIsPivoted(!isPivoted), style: btnStyle(isPivoted), children: "Pivot Data" })), _jsx("div", { style: { display: 'flex', border: `1px solid ${theme.colors.primary}`, borderRadius: theme.borderRadius.small, overflow: 'hidden' }, children: ['flow', 'grid', 'list', 'table'].map((v) => (_jsx("button", { onClick: () => setViewMode(v), style: {
73
+ ...btnStyle(viewMode === v),
74
+ border: 'none',
75
+ borderRadius: 0,
76
+ textTransform: 'capitalize'
77
+ }, children: v }, v))) })] })] })] }), _jsxs("div", { style: { padding: theme.spacing.medium, backgroundColor: theme.colors.background }, children: [Object.entries(groupedData).map(([groupTitle, groupSteps]) => (_jsxs("div", { style: { marginBottom: theme.spacing.large }, children: [isGrouped && (_jsxs("h4", { style: {
78
+ color: theme.colors.textSecondary,
79
+ borderBottom: `1px solid ${theme.colors.border || '#eee'}`,
80
+ marginBottom: theme.spacing.medium
81
+ }, children: ["Group: ", groupTitle] })), viewMode === 'flow' && (_jsxs("div", { style: {
82
+ display: 'flex',
83
+ alignItems: 'center',
84
+ gap: theme.spacing.medium,
85
+ overflowX: 'auto',
86
+ padding: theme.spacing.small
87
+ }, children: [groupSteps.map((step, i) => (_jsxs(React.Fragment, { children: [_jsxs("div", { style: {
88
+ flex: '0 0 220px',
89
+ padding: theme.spacing.medium,
90
+ backgroundColor: theme.colors.cardBackground,
91
+ border: `2px solid ${theme.colors.primary}`,
92
+ borderRadius: theme.borderRadius.medium,
93
+ boxShadow: '0 2px 5px rgba(0,0,0,0.1)'
94
+ }, children: [_jsxs("div", { style: {
95
+ fontWeight: 'bold',
96
+ color: theme.colors.primary,
97
+ marginBottom: theme.spacing.small,
98
+ fontSize: theme.typography.bodySize
99
+ }, children: [i + 1, ". ", step.title] }), _jsx("div", { style: {
100
+ color: theme.colors.textSecondary,
101
+ fontSize: theme.typography.smallSize,
102
+ lineHeight: '1.5'
103
+ }, children: step.description })] }), i < groupSteps.length - 1 && (_jsx("div", { style: {
104
+ color: theme.colors.primary,
105
+ fontSize: '28px',
106
+ fontWeight: 'bold',
107
+ minWidth: '20px'
108
+ }, children: "\u2192" }))] }, i))), groupSteps.length === 0 && _jsx("div", { style: { color: theme.colors.textSecondary }, children: "No steps match filter." })] })), viewMode === 'grid' && (_jsx("div", { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: theme.spacing.medium }, children: groupSteps.map((step, i) => (_jsxs("div", { style: {
109
+ padding: theme.spacing.medium,
110
+ backgroundColor: theme.colors.cardBackground,
111
+ border: `1px solid ${theme.colors.border || '#ddd'}`,
112
+ borderRadius: theme.borderRadius.medium
113
+ }, children: [_jsx("div", { style: { fontWeight: 'bold', color: theme.colors.text }, children: step.title }), _jsx("hr", { style: { margin: '8px 0', border: '0', borderTop: `1px solid ${theme.colors.border || '#eee'}` } }), _jsx("div", { style: { color: theme.colors.textSecondary, fontSize: theme.typography.smallSize }, children: step.description })] }, i))) })), viewMode === 'list' && (_jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.small }, children: groupSteps.map((step, i) => (_jsxs("div", { style: {
114
+ padding: theme.spacing.medium,
115
+ backgroundColor: theme.colors.cardBackground,
116
+ borderLeft: `4px solid ${theme.colors.primary}`,
117
+ borderRadius: theme.borderRadius.small,
118
+ display: 'flex',
119
+ alignItems: 'center',
120
+ justifyContent: 'space-between'
121
+ }, children: [_jsxs("span", { style: { fontWeight: 'bold', color: theme.colors.text }, children: [i + 1, ". ", step.title] }), _jsx("span", { style: { color: theme.colors.textSecondary }, children: step.description })] }, i))) })), viewMode === 'table' && (_jsx("div", { style: { overflowX: 'auto' }, children: _jsxs("table", { style: { width: '100%', borderCollapse: 'collapse', fontSize: theme.typography.smallSize }, children: [!isPivoted && (_jsxs(_Fragment, { children: [_jsx("thead", { children: _jsxs("tr", { style: { backgroundColor: theme.colors.background, borderBottom: `2px solid ${theme.colors.primary}` }, children: [_jsx("th", { style: { padding: theme.spacing.small, textAlign: 'left' }, children: "Step #" }), _jsx("th", { style: { padding: theme.spacing.small, textAlign: 'left' }, children: "Title" }), _jsx("th", { style: { padding: theme.spacing.small, textAlign: 'left' }, children: "Description" })] }) }), _jsx("tbody", { children: groupSteps.map((step, i) => (_jsxs("tr", { style: { borderBottom: `1px solid ${theme.colors.border || '#eee'}` }, children: [_jsx("td", { style: { padding: theme.spacing.small }, children: i + 1 }), _jsx("td", { style: { padding: theme.spacing.small, fontWeight: 'bold' }, children: step.title }), _jsx("td", { style: { padding: theme.spacing.small, color: theme.colors.textSecondary }, children: step.description })] }, i))) })] })), isPivoted && (_jsxs("tbody", { children: [_jsxs("tr", { style: { borderBottom: `1px solid ${theme.colors.border || '#eee'}` }, children: [_jsx("th", { style: { padding: theme.spacing.small, textAlign: 'right', backgroundColor: theme.colors.background }, children: "Title" }), groupSteps.map((step, i) => (_jsx("td", { style: { padding: theme.spacing.small, fontWeight: 'bold', borderLeft: `1px solid ${theme.colors.border}` }, children: step.title }, i)))] }), _jsxs("tr", { children: [_jsx("th", { style: { padding: theme.spacing.small, textAlign: 'right', backgroundColor: theme.colors.background }, children: "Description" }), groupSteps.map((step, i) => (_jsx("td", { style: { padding: theme.spacing.small, color: theme.colors.textSecondary, borderLeft: `1px solid ${theme.colors.border}` }, children: step.description }, i)))] })] }))] }) }))] }, groupTitle))), processedData.length === 0 && (_jsxs("div", { style: { textAlign: 'center', padding: theme.spacing.large, color: theme.colors.textSecondary }, children: ["No results found for \"", filterText, "\""] }))] })] }));
122
+ };
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ export interface InteractiveCompositeProps {
3
+ title: string;
4
+ selector: {
5
+ label: string;
6
+ options: string[];
7
+ default: string;
8
+ };
9
+ views: {
10
+ chart: {
11
+ chartType: 'line' | 'radial_bar' | 'treemap';
12
+ xKey?: string;
13
+ yKey: string;
14
+ series: Record<string, any[]>;
15
+ };
16
+ table: {
17
+ columns: string[];
18
+ rows: Record<string, Record<string, string | number>[]>;
19
+ };
20
+ };
21
+ }
22
+ export declare const InteractiveCompositeBlock: React.FC<InteractiveCompositeProps>;
@@ -0,0 +1,102 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useMemo } from 'react';
3
+ import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer, RadialBarChart, RadialBar, Treemap } from 'recharts';
4
+ import { useThemeWithFallback } from '../../utils/useThemeWithFallback';
5
+ export const InteractiveCompositeBlock = ({ title, selector, views }) => {
6
+ const theme = useThemeWithFallback();
7
+ // --- State ---
8
+ const [selected, setSelected] = useState(selector.default);
9
+ const [viewMode, setViewMode] = useState('split');
10
+ const [filterText, setFilterText] = useState('');
11
+ const [sortConfig, setSortConfig] = useState({ col: '', dir: null });
12
+ // --- Data Access ---
13
+ const chartData = views.chart.series[selected] || [];
14
+ const rawTableRows = views.table.rows[selected] || [];
15
+ // --- Logic: Process Table Data ---
16
+ const tableRows = useMemo(() => {
17
+ let data = [...rawTableRows];
18
+ // 1. Filter
19
+ if (filterText) {
20
+ const lower = filterText.toLowerCase();
21
+ data = data.filter(row => Object.values(row).some(val => String(val).toLowerCase().includes(lower)));
22
+ }
23
+ // 2. Sort
24
+ if (sortConfig.col && sortConfig.dir) {
25
+ data.sort((a, b) => {
26
+ const valA = a[sortConfig.col];
27
+ const valB = b[sortConfig.col];
28
+ if (typeof valA === 'number' && typeof valB === 'number') {
29
+ return sortConfig.dir === 'asc' ? valA - valB : valB - valA;
30
+ }
31
+ return sortConfig.dir === 'asc'
32
+ ? String(valA).localeCompare(String(valB))
33
+ : String(valB).localeCompare(String(valA));
34
+ });
35
+ }
36
+ return data;
37
+ }, [rawTableRows, filterText, sortConfig]);
38
+ // --- Handlers ---
39
+ const handleSort = (col) => {
40
+ setSortConfig(prev => ({
41
+ col,
42
+ dir: prev.col === col && prev.dir === 'asc' ? 'desc' : 'asc'
43
+ }));
44
+ };
45
+ const renderChart = () => {
46
+ switch (views.chart.chartType) {
47
+ case 'radial_bar':
48
+ return (_jsxs(RadialBarChart, { innerRadius: "30%", outerRadius: "90%", data: chartData, children: [_jsx(RadialBar, { dataKey: views.chart.yKey, fill: theme.colors.primary }), _jsx(Tooltip, {})] }));
49
+ case 'treemap':
50
+ return (_jsx(Treemap, { data: chartData, dataKey: views.chart.yKey, stroke: theme.colors.border, fill: theme.colors.primary, children: _jsx(Tooltip, {}) }));
51
+ case 'line':
52
+ default:
53
+ return (_jsxs(LineChart, { data: chartData, children: [views.chart.xKey && _jsx(XAxis, { dataKey: views.chart.xKey, tick: { fill: theme.colors.textSecondary } }), _jsx(YAxis, { tick: { fill: theme.colors.textSecondary } }), _jsx(Tooltip, {}), _jsx(Line, { type: "monotone", dataKey: views.chart.yKey, stroke: theme.colors.primary, strokeWidth: 2, dot: false })] }));
54
+ }
55
+ };
56
+ const btnStyle = (active) => ({
57
+ padding: '4px 12px',
58
+ backgroundColor: active ? theme.colors.primary : 'transparent',
59
+ color: active ? '#fff' : theme.colors.text,
60
+ border: `1px solid ${theme.colors.border}`,
61
+ borderRadius: 0,
62
+ cursor: 'pointer',
63
+ fontSize: theme.typography.smallSize
64
+ });
65
+ return (_jsxs("div", { style: {
66
+ margin: `${theme.spacing.large} 0`,
67
+ border: `1px solid ${theme.colors.border}`,
68
+ borderRadius: theme.borderRadius.medium,
69
+ overflow: 'hidden',
70
+ boxShadow: '0 4px 12px rgba(0,0,0,0.05)'
71
+ }, children: [_jsxs("div", { style: {
72
+ padding: theme.spacing.medium,
73
+ backgroundColor: theme.colors.background,
74
+ borderBottom: `1px solid ${theme.colors.border}`,
75
+ display: 'flex', flexWrap: 'wrap', gap: theme.spacing.medium, alignItems: 'center', justifyContent: 'space-between'
76
+ }, children: [_jsx("div", { children: _jsx("h2", { style: { margin: 0, fontSize: theme.typography.h2Size, color: theme.colors.text }, children: title }) }), _jsxs("div", { style: { display: 'flex', gap: theme.spacing.medium, alignItems: 'center', flexWrap: 'wrap' }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: theme.spacing.small }, children: [_jsxs("span", { style: { fontSize: '12px', color: theme.colors.textSecondary }, children: [selector.label, ":"] }), _jsx("select", { value: selected, onChange: (e) => setSelected(e.target.value), style: {
77
+ padding: '4px 8px', borderRadius: theme.borderRadius.small,
78
+ border: `1px solid ${theme.colors.border}`, backgroundColor: theme.colors.cardBackground
79
+ }, children: selector.options.map(o => _jsx("option", { value: o, children: o }, o)) })] }), _jsxs("div", { style: { display: 'flex', border: `1px solid ${theme.colors.primary}`, borderRadius: theme.borderRadius.small, overflow: 'hidden' }, children: [_jsx("button", { onClick: () => setViewMode('split'), style: btnStyle(viewMode === 'split'), children: "Split" }), _jsx("button", { onClick: () => setViewMode('chart'), style: btnStyle(viewMode === 'chart'), children: "Chart" }), _jsx("button", { onClick: () => setViewMode('table'), style: btnStyle(viewMode === 'table'), children: "Table" })] })] })] }), _jsxs("div", { style: { padding: theme.spacing.medium, backgroundColor: theme.colors.background }, children: [(viewMode === 'split' || viewMode === 'chart') && (_jsx("div", { style: {
80
+ height: viewMode === 'chart' ? 450 : 320,
81
+ padding: theme.spacing.medium,
82
+ backgroundColor: theme.colors.cardBackground,
83
+ borderRadius: theme.borderRadius.medium,
84
+ border: `1px solid ${theme.colors.border}`,
85
+ marginBottom: viewMode === 'split' ? theme.spacing.medium : 0
86
+ }, children: _jsx(ResponsiveContainer, { width: "100%", height: "100%", children: renderChart() }) })), (viewMode === 'split' || viewMode === 'table') && (_jsxs("div", { children: [_jsxs("div", { style: { marginBottom: theme.spacing.small, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }, children: [_jsx("input", { type: "text", placeholder: "Filter table data...", value: filterText, onChange: (e) => setFilterText(e.target.value), style: { padding: '4px 8px', borderRadius: theme.borderRadius.small, border: `1px solid ${theme.colors.border}`, width: '200px' } }), _jsxs("span", { style: { fontSize: '11px', color: theme.colors.textSecondary }, children: [tableRows.length, " rows found"] })] }), _jsx("div", { style: {
87
+ overflowX: 'auto',
88
+ backgroundColor: theme.colors.cardBackground,
89
+ borderRadius: theme.borderRadius.medium,
90
+ border: `1px solid ${theme.colors.border}`,
91
+ maxHeight: viewMode === 'table' ? '500px' : '300px',
92
+ overflowY: 'auto'
93
+ }, children: _jsxs("table", { style: { width: '100%', borderCollapse: 'collapse' }, children: [_jsx("thead", { style: { position: 'sticky', top: 0, backgroundColor: theme.colors.cardBackground, zIndex: 1 }, children: _jsx("tr", { children: views.table.columns.map(col => (_jsxs("th", { onClick: () => handleSort(col), style: {
94
+ textAlign: 'left',
95
+ padding: theme.spacing.small,
96
+ borderBottom: `2px solid ${theme.colors.border}`,
97
+ color: theme.colors.text,
98
+ cursor: 'pointer',
99
+ userSelect: 'none',
100
+ minWidth: '100px'
101
+ }, children: [col, " ", sortConfig.col === col ? (sortConfig.dir === 'asc' ? '↑' : '↓') : ''] }, col))) }) }), _jsxs("tbody", { children: [tableRows.map((row, i) => (_jsx("tr", { style: { backgroundColor: i % 2 === 0 ? 'transparent' : 'rgba(0,0,0,0.02)' }, children: views.table.columns.map(col => (_jsx("td", { style: { padding: theme.spacing.small, borderBottom: `1px solid ${theme.colors.border}`, color: theme.colors.textSecondary }, children: row[col] }, col))) }, i))), tableRows.length === 0 && (_jsx("tr", { children: _jsx("td", { colSpan: views.table.columns.length, style: { padding: '20px', textAlign: 'center', color: theme.colors.textSecondary }, children: "No matches found." }) }))] })] }) })] }))] })] }));
102
+ };
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ export interface LineChartBlockProps {
3
+ title: string;
4
+ xKey: string;
5
+ yKey: string;
6
+ points: any[];
7
+ }
8
+ export declare const LineChartBlock: React.FC<LineChartBlockProps>;
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';
3
+ import { useThemeWithFallback } from '../../utils/useThemeWithFallback';
4
+ export const LineChartBlock = ({ title, xKey, yKey, points }) => {
5
+ const theme = useThemeWithFallback();
6
+ return (_jsxs("div", { style: { margin: `${theme.spacing.large} 0` }, children: [_jsx("h2", { style: {
7
+ color: theme.colors.text,
8
+ marginBottom: theme.spacing.medium,
9
+ textAlign: 'center'
10
+ }, children: title }), _jsx("div", { style: {
11
+ height: 320,
12
+ padding: theme.spacing.medium,
13
+ backgroundColor: theme.colors.cardBackground,
14
+ borderRadius: theme.borderRadius.medium,
15
+ border: `1px solid ${theme.colors.border}`
16
+ }, children: _jsx(ResponsiveContainer, { width: "100%", height: "100%", children: _jsxs(LineChart, { data: points, children: [_jsx(XAxis, { dataKey: xKey, tick: { fill: theme.colors.textSecondary } }), _jsx(YAxis, { tick: { fill: theme.colors.textSecondary } }), _jsx(Tooltip, { contentStyle: {
17
+ backgroundColor: theme.colors.cardBackground,
18
+ border: `1px solid ${theme.colors.border}`,
19
+ borderRadius: theme.borderRadius.small,
20
+ color: theme.colors.text
21
+ } }), _jsx(Line, { type: "monotone", dataKey: yKey, stroke: theme.colors.primary, strokeWidth: 2, dot: false })] }) }) })] }));
22
+ };
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ export interface ProsConsBlockProps {
3
+ title: string;
4
+ pros: string[];
5
+ cons: string[];
6
+ }
7
+ export declare const ProsConsBlock: React.FC<ProsConsBlockProps>;
@@ -0,0 +1,77 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useMemo } from 'react';
3
+ import { useThemeWithFallback } from '../../utils/useThemeWithFallback';
4
+ export const ProsConsBlock = ({ title, pros, cons }) => {
5
+ const theme = useThemeWithFallback();
6
+ // --- State ---
7
+ const [filterText, setFilterText] = useState('');
8
+ const [sortMode, setSortMode] = useState('original');
9
+ const [isPivoted, setIsPivoted] = useState(false); // Merges lists into one
10
+ const [viewMode, setViewMode] = useState('split');
11
+ // --- Data Processing ---
12
+ const processedData = useMemo(() => {
13
+ // 1. Unify data structure
14
+ const allItems = [
15
+ ...pros.map(t => ({ text: t, type: 'pro' })),
16
+ ...cons.map(t => ({ text: t, type: 'con' }))
17
+ ];
18
+ // 2. Filter
19
+ let filtered = allItems;
20
+ if (filterText) {
21
+ filtered = allItems.filter(i => i.text.toLowerCase().includes(filterText.toLowerCase()));
22
+ }
23
+ // 3. Sort
24
+ if (sortMode !== 'original') {
25
+ filtered.sort((a, b) => sortMode === 'asc'
26
+ ? a.text.localeCompare(b.text)
27
+ : b.text.localeCompare(a.text));
28
+ }
29
+ return filtered;
30
+ }, [pros, cons, filterText, sortMode]);
31
+ // Derived arrays for "Split" view
32
+ const currentPros = processedData.filter(i => i.type === 'pro');
33
+ const currentCons = processedData.filter(i => i.type === 'con');
34
+ // --- Styles ---
35
+ const btnStyle = (active) => ({
36
+ padding: '4px 12px',
37
+ backgroundColor: active ? theme.colors.primary : 'transparent',
38
+ color: active ? '#fff' : theme.colors.text,
39
+ border: `1px solid ${theme.colors.border}`,
40
+ borderRadius: theme.borderRadius.small,
41
+ cursor: 'pointer',
42
+ fontSize: theme.typography.smallSize
43
+ });
44
+ const badgeStyle = (type) => ({
45
+ display: 'inline-block',
46
+ padding: '2px 8px',
47
+ borderRadius: '12px',
48
+ fontSize: '11px',
49
+ fontWeight: 'bold',
50
+ backgroundColor: type === 'pro' ? 'rgba(40, 167, 69, 0.1)' : 'rgba(220, 53, 69, 0.1)',
51
+ color: type === 'pro' ? '#28a745' : '#dc3545',
52
+ border: `1px solid ${type === 'pro' ? '#28a745' : '#dc3545'}`
53
+ });
54
+ return (_jsxs("div", { style: {
55
+ margin: `${theme.spacing.large} 0`,
56
+ border: `1px solid ${theme.colors.border}`,
57
+ borderRadius: theme.borderRadius.medium,
58
+ overflow: 'hidden'
59
+ }, children: [_jsxs("div", { style: {
60
+ padding: theme.spacing.medium,
61
+ backgroundColor: theme.colors.background,
62
+ borderBottom: `1px solid ${theme.colors.border}`,
63
+ display: 'flex', flexWrap: 'wrap', gap: theme.spacing.medium, alignItems: 'center', justifyContent: 'space-between'
64
+ }, children: [_jsx("h2", { style: { margin: 0, fontSize: theme.typography.h2Size, color: theme.colors.text }, children: title }), _jsxs("div", { style: { display: 'flex', gap: theme.spacing.small }, children: [_jsx("input", { type: "text", placeholder: "Filter...", value: filterText, onChange: (e) => setFilterText(e.target.value), style: { padding: '4px 8px', borderRadius: theme.borderRadius.small, border: `1px solid ${theme.colors.border}` } }), _jsx("button", { onClick: () => setSortMode(p => p === 'original' ? 'asc' : 'original'), style: btnStyle(sortMode === 'asc'), children: "Sort A-Z" }), _jsx("button", { onClick: () => setIsPivoted(!isPivoted), style: btnStyle(isPivoted), children: isPivoted ? 'Split View' : 'Pivot (Merge)' })] })] }), _jsx("div", { style: { padding: theme.spacing.medium, backgroundColor: theme.colors.background }, children: isPivoted ? (_jsxs("table", { style: { width: '100%', borderCollapse: 'collapse' }, children: [_jsx("thead", { children: _jsxs("tr", { style: { textAlign: 'left', borderBottom: `2px solid ${theme.colors.border}` }, children: [_jsx("th", { style: { padding: theme.spacing.small }, children: "Type" }), _jsx("th", { style: { padding: theme.spacing.small }, children: "Point" })] }) }), _jsxs("tbody", { children: [processedData.map((item, i) => (_jsxs("tr", { style: { borderBottom: `1px solid ${theme.colors.border}` }, children: [_jsx("td", { style: { padding: theme.spacing.small, width: '80px' }, children: _jsx("span", { style: badgeStyle(item.type), children: item.type.toUpperCase() }) }), _jsx("td", { style: { padding: theme.spacing.small, color: theme.colors.text }, children: item.text })] }, i))), processedData.length === 0 && _jsx("tr", { children: _jsx("td", { colSpan: 2, style: { textAlign: 'center', padding: '20px' }, children: "No matches." }) })] })] })) : (
65
+ /* VIEW 2: ORIGINAL SPLIT (Grid) */
66
+ _jsxs("div", { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: theme.spacing.medium }, children: [_jsxs("div", { style: {
67
+ padding: theme.spacing.medium,
68
+ backgroundColor: theme.colors.cardBackground,
69
+ border: `2px solid #28a745`,
70
+ borderRadius: theme.borderRadius.medium
71
+ }, children: [_jsxs("h3", { style: { color: '#28a745', margin: `0 0 ${theme.spacing.medium} 0`, display: 'flex', alignItems: 'center', gap: '8px' }, children: ["\u2713 Pros (", currentPros.length, ")"] }), _jsx("ul", { style: { margin: 0, paddingLeft: theme.spacing.medium, color: theme.colors.text }, children: currentPros.map((item, i) => (_jsx("li", { style: { marginBottom: theme.spacing.small }, children: item.text }, i))) })] }), _jsxs("div", { style: {
72
+ padding: theme.spacing.medium,
73
+ backgroundColor: theme.colors.cardBackground,
74
+ border: `2px solid #dc3545`,
75
+ borderRadius: theme.borderRadius.medium
76
+ }, children: [_jsxs("h3", { style: { color: '#dc3545', margin: `0 0 ${theme.spacing.medium} 0`, display: 'flex', alignItems: 'center', gap: '8px' }, children: ["\u2717 Cons (", currentCons.length, ")"] }), _jsx("ul", { style: { margin: 0, paddingLeft: theme.spacing.medium, color: theme.colors.text }, children: currentCons.map((item, i) => (_jsx("li", { style: { marginBottom: theme.spacing.small }, children: item.text }, i))) })] })] })) })] }));
77
+ };
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ interface Node {
3
+ name: string;
4
+ value?: number;
5
+ children?: Node[];
6
+ }
7
+ export interface SunburstProps {
8
+ title: string;
9
+ root: Node;
10
+ }
11
+ export declare const Sunburst: React.FC<SunburstProps>;
12
+ export {};