semantic-renderer 1.0.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/LICENSE +21 -0
- package/README.md +192 -0
- package/dist/core/classifier.d.ts +13 -0
- package/dist/core/classifier.d.ts.map +1 -0
- package/dist/core/classifier.js +478 -0
- package/dist/core/classifier.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +3 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/types.d.ts +40 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/react/FallbackMarkdown.d.ts +8 -0
- package/dist/react/FallbackMarkdown.d.ts.map +1 -0
- package/dist/react/FallbackMarkdown.js +10 -0
- package/dist/react/FallbackMarkdown.js.map +1 -0
- package/dist/react/SemanticRenderer.d.ts +14 -0
- package/dist/react/SemanticRenderer.d.ts.map +1 -0
- package/dist/react/SemanticRenderer.js +37 -0
- package/dist/react/SemanticRenderer.js.map +1 -0
- package/dist/react/index.d.ts +10 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +11 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/renderers/CodeExplanationRenderer.d.ts +10 -0
- package/dist/react/renderers/CodeExplanationRenderer.d.ts.map +1 -0
- package/dist/react/renderers/CodeExplanationRenderer.js +14 -0
- package/dist/react/renderers/CodeExplanationRenderer.js.map +1 -0
- package/dist/react/renderers/ComparisonRenderer.d.ts +10 -0
- package/dist/react/renderers/ComparisonRenderer.d.ts.map +1 -0
- package/dist/react/renderers/ComparisonRenderer.js +13 -0
- package/dist/react/renderers/ComparisonRenderer.js.map +1 -0
- package/dist/react/renderers/DataTableRenderer.d.ts +10 -0
- package/dist/react/renderers/DataTableRenderer.d.ts.map +1 -0
- package/dist/react/renderers/DataTableRenderer.js +51 -0
- package/dist/react/renderers/DataTableRenderer.js.map +1 -0
- package/dist/react/renderers/ProsConsRenderer.d.ts +10 -0
- package/dist/react/renderers/ProsConsRenderer.d.ts.map +1 -0
- package/dist/react/renderers/ProsConsRenderer.js +13 -0
- package/dist/react/renderers/ProsConsRenderer.js.map +1 -0
- package/dist/react/renderers/StepsRenderer.d.ts +10 -0
- package/dist/react/renderers/StepsRenderer.d.ts.map +1 -0
- package/dist/react/renderers/StepsRenderer.js +28 -0
- package/dist/react/renderers/StepsRenderer.js.map +1 -0
- package/dist/react/renderers/VerdictRenderer.d.ts +10 -0
- package/dist/react/renderers/VerdictRenderer.d.ts.map +1 -0
- package/dist/react/renderers/VerdictRenderer.js +13 -0
- package/dist/react/renderers/VerdictRenderer.js.map +1 -0
- package/package.json +85 -0
- package/src/react/styles.css +79 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useMemo } from 'react';
|
|
3
|
+
import { classify } from '../core/classifier.js';
|
|
4
|
+
import { FallbackMarkdown } from './FallbackMarkdown.js';
|
|
5
|
+
import { VerdictRenderer } from './renderers/VerdictRenderer.js';
|
|
6
|
+
import { ProsConsRenderer } from './renderers/ProsConsRenderer.js';
|
|
7
|
+
import { StepsRenderer } from './renderers/StepsRenderer.js';
|
|
8
|
+
import { ComparisonRenderer } from './renderers/ComparisonRenderer.js';
|
|
9
|
+
import { DataTableRenderer } from './renderers/DataTableRenderer.js';
|
|
10
|
+
import { CodeExplanationRenderer } from './renderers/CodeExplanationRenderer.js';
|
|
11
|
+
const RENDERER_MAP = {
|
|
12
|
+
'comparison': ComparisonRenderer,
|
|
13
|
+
'steps': StepsRenderer,
|
|
14
|
+
'pros-cons': ProsConsRenderer,
|
|
15
|
+
'code-explanation': CodeExplanationRenderer,
|
|
16
|
+
'data-table': DataTableRenderer,
|
|
17
|
+
'verdict': VerdictRenderer,
|
|
18
|
+
'default': ({ block, Fallback }) => _jsx(Fallback, { content: block.rawMarkdown }),
|
|
19
|
+
};
|
|
20
|
+
export const SemanticRenderer = memo(({ content, isStreaming = false, className = '', fallback: Fallback = FallbackMarkdown, }) => {
|
|
21
|
+
// During streaming, bypass classification
|
|
22
|
+
if (isStreaming) {
|
|
23
|
+
return _jsx(Fallback, { content: content });
|
|
24
|
+
}
|
|
25
|
+
const blocks = useMemo(() => classify(content), [content]);
|
|
26
|
+
// If all blocks are default, skip the wrapper overhead
|
|
27
|
+
const allDefault = blocks.every(b => b.type === 'default');
|
|
28
|
+
if (allDefault) {
|
|
29
|
+
return _jsx(Fallback, { content: content });
|
|
30
|
+
}
|
|
31
|
+
return (_jsx("div", { className: `sem-body ${className}`.trim(), children: blocks.map(block => {
|
|
32
|
+
const Renderer = RENDERER_MAP[block.type] || RENDERER_MAP['default'];
|
|
33
|
+
return _jsx(Renderer, { block: block, Fallback: Fallback }, block.id);
|
|
34
|
+
}) }));
|
|
35
|
+
});
|
|
36
|
+
SemanticRenderer.displayName = 'SemanticRenderer';
|
|
37
|
+
//# sourceMappingURL=SemanticRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SemanticRenderer.js","sourceRoot":"","sources":["../../src/react/SemanticRenderer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AAajF,MAAM,YAAY,GAAiI;IACjJ,YAAY,EAAE,kBAAkB;IAChC,OAAO,EAAE,aAAa;IACtB,WAAW,EAAE,gBAAgB;IAC7B,kBAAkB,EAAE,uBAAuB;IAC3C,YAAY,EAAE,iBAAiB;IAC/B,SAAS,EAAE,eAAe;IAC1B,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,KAAC,QAAQ,IAAC,OAAO,EAAE,KAAK,CAAC,WAAW,GAAI;CAC7E,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,CAAC,EACpC,OAAO,EACP,WAAW,GAAG,KAAK,EACnB,SAAS,GAAG,EAAE,EACd,QAAQ,EAAE,QAAQ,GAAG,gBAAgB,GACf,EAAE,EAAE;IAC1B,0CAA0C;IAC1C,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,KAAC,QAAQ,IAAC,OAAO,EAAE,OAAO,GAAI,CAAC;IACxC,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAE3D,uDAAuD;IACvD,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IAC3D,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,KAAC,QAAQ,IAAC,OAAO,EAAE,OAAO,GAAI,CAAC;IACxC,CAAC;IAED,OAAO,CACL,cAAK,SAAS,EAAE,YAAY,SAAS,EAAE,CAAC,IAAI,EAAE,YAC3C,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;YAClB,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC;YACrE,OAAO,KAAC,QAAQ,IAAgB,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,IAA1C,KAAK,CAAC,EAAE,CAAsC,CAAC;QACvE,CAAC,CAAC,GACE,CACP,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,gBAAgB,CAAC,WAAW,GAAG,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { SemanticRenderer } from './SemanticRenderer.js';
|
|
2
|
+
export { VerdictRenderer } from './renderers/VerdictRenderer.js';
|
|
3
|
+
export { ProsConsRenderer } from './renderers/ProsConsRenderer.js';
|
|
4
|
+
export { StepsRenderer } from './renderers/StepsRenderer.js';
|
|
5
|
+
export { ComparisonRenderer } from './renderers/ComparisonRenderer.js';
|
|
6
|
+
export { DataTableRenderer } from './renderers/DataTableRenderer.js';
|
|
7
|
+
export { CodeExplanationRenderer } from './renderers/CodeExplanationRenderer.js';
|
|
8
|
+
export { classify } from '../core/index.js';
|
|
9
|
+
export type { SemanticBlock, SemanticBlockType, ComparisonMeta, StepsMeta, ProsConsMeta, CodeExplanationMeta, DataTableMeta, VerdictMeta, } from '../core/index.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AAGjF,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,WAAW,GACZ,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// React entry — SemanticRenderer component + all renderers
|
|
2
|
+
export { SemanticRenderer } from './SemanticRenderer.js';
|
|
3
|
+
export { VerdictRenderer } from './renderers/VerdictRenderer.js';
|
|
4
|
+
export { ProsConsRenderer } from './renderers/ProsConsRenderer.js';
|
|
5
|
+
export { StepsRenderer } from './renderers/StepsRenderer.js';
|
|
6
|
+
export { ComparisonRenderer } from './renderers/ComparisonRenderer.js';
|
|
7
|
+
export { DataTableRenderer } from './renderers/DataTableRenderer.js';
|
|
8
|
+
export { CodeExplanationRenderer } from './renderers/CodeExplanationRenderer.js';
|
|
9
|
+
// Re-export core for convenience
|
|
10
|
+
export { classify } from '../core/index.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AAEjF,iCAAiC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SemanticBlock } from '../../core/types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
block: SemanticBlock;
|
|
4
|
+
Fallback: React.ComponentType<{
|
|
5
|
+
content: string;
|
|
6
|
+
}>;
|
|
7
|
+
}
|
|
8
|
+
export declare const CodeExplanationRenderer: import("react").MemoExoticComponent<({ block, Fallback }: Props) => import("react/jsx-runtime").JSX.Element>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=CodeExplanationRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeExplanationRenderer.d.ts","sourceRoot":"","sources":["../../../src/react/renderers/CodeExplanationRenderer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAuB,MAAM,qBAAqB,CAAC;AAE9E,UAAU,KAAK;IACb,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAED,eAAO,MAAM,uBAAuB,4DAA8B,KAAK,6CA6BrE,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { motion } from 'framer-motion';
|
|
4
|
+
import { Code2 } from 'lucide-react';
|
|
5
|
+
export const CodeExplanationRenderer = memo(({ block, Fallback }) => {
|
|
6
|
+
const meta = block.meta;
|
|
7
|
+
if (!meta?.code || !meta?.explanation) {
|
|
8
|
+
return _jsx(Fallback, { content: block.rawMarkdown });
|
|
9
|
+
}
|
|
10
|
+
const codeMd = '```' + (meta.language || '') + '\n' + meta.code + '\n```';
|
|
11
|
+
return (_jsxs(motion.div, { className: "sem-code-explain", initial: { opacity: 0, y: 8 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.3 }, children: [_jsxs("div", { className: "sem-code-panel", children: [_jsxs("div", { className: "sem-code-panel-header", children: [_jsx(Code2, { size: 14 }), _jsx("span", { children: meta.language || 'Code' })] }), _jsx(Fallback, { content: codeMd })] }), _jsxs("div", { className: "sem-explain-panel", children: [_jsx("div", { className: "sem-explain-panel-header", children: "Explanation" }), _jsx(Fallback, { content: meta.explanation })] })] }));
|
|
12
|
+
});
|
|
13
|
+
CodeExplanationRenderer.displayName = 'CodeExplanationRenderer';
|
|
14
|
+
//# sourceMappingURL=CodeExplanationRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeExplanationRenderer.js","sourceRoot":"","sources":["../../../src/react/renderers/CodeExplanationRenderer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAQrC,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAS,EAAE,EAAE;IACzE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAsC,CAAC;IAE1D,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC;QACtC,OAAO,KAAC,QAAQ,IAAC,OAAO,EAAE,KAAK,CAAC,WAAW,GAAI,CAAC;IAClD,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC;IAE1E,OAAO,CACL,MAAC,MAAM,CAAC,GAAG,IACT,SAAS,EAAC,kBAAkB,EAC5B,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAC7B,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAC7B,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,aAE7B,eAAK,SAAS,EAAC,gBAAgB,aAC7B,eAAK,SAAS,EAAC,uBAAuB,aACpC,KAAC,KAAK,IAAC,IAAI,EAAE,EAAE,GAAI,EACnB,yBAAO,IAAI,CAAC,QAAQ,IAAI,MAAM,GAAQ,IAClC,EACN,KAAC,QAAQ,IAAC,OAAO,EAAE,MAAM,GAAI,IACzB,EACN,eAAK,SAAS,EAAC,mBAAmB,aAChC,cAAK,SAAS,EAAC,0BAA0B,4BAAkB,EAC3D,KAAC,QAAQ,IAAC,OAAO,EAAE,IAAI,CAAC,WAAW,GAAI,IACnC,IACK,CACd,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,uBAAuB,CAAC,WAAW,GAAG,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SemanticBlock } from '../../core/types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
block: SemanticBlock;
|
|
4
|
+
Fallback: React.ComponentType<{
|
|
5
|
+
content: string;
|
|
6
|
+
}>;
|
|
7
|
+
}
|
|
8
|
+
export declare const ComparisonRenderer: import("react").MemoExoticComponent<({ block, Fallback }: Props) => import("react/jsx-runtime").JSX.Element>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=ComparisonRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComparisonRenderer.d.ts","sourceRoot":"","sources":["../../../src/react/renderers/ComparisonRenderer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,qBAAqB,CAAC;AAIzE,UAAU,KAAK;IACb,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAED,eAAO,MAAM,kBAAkB,4DAA8B,KAAK,6CAqChE,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { motion } from 'framer-motion';
|
|
4
|
+
const ACCENT_COLORS = ['#6366f1', '#ec4899', '#14b8a6', '#f59e0b', '#8b5cf6'];
|
|
5
|
+
export const ComparisonRenderer = memo(({ block, Fallback }) => {
|
|
6
|
+
const meta = block.meta;
|
|
7
|
+
if (!meta?.items?.length || meta.items.length < 2) {
|
|
8
|
+
return _jsx(Fallback, { content: block.rawMarkdown });
|
|
9
|
+
}
|
|
10
|
+
return (_jsx(motion.div, { className: "sem-comparison", initial: { opacity: 0, y: 8 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.3 }, children: meta.items.map((item, i) => (_jsxs("div", { className: "sem-comparison-card", children: [_jsxs("div", { className: "sem-comparison-card-header", style: { borderColor: ACCENT_COLORS[i % ACCENT_COLORS.length] }, children: [_jsx("span", { className: "sem-comparison-card-dot", style: { background: ACCENT_COLORS[i % ACCENT_COLORS.length] } }), item.title] }), _jsx("ul", { className: "sem-comparison-card-points", children: item.points.map((point, j) => (_jsx("li", { className: "sem-comparison-card-point", children: _jsx(Fallback, { content: point }) }, j))) })] }, i))) }));
|
|
11
|
+
});
|
|
12
|
+
ComparisonRenderer.displayName = 'ComparisonRenderer';
|
|
13
|
+
//# sourceMappingURL=ComparisonRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComparisonRenderer.js","sourceRoot":"","sources":["../../../src/react/renderers/ComparisonRenderer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAGvC,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAO9E,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAS,EAAE,EAAE;IACpE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAiC,CAAC;IAErD,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClD,OAAO,KAAC,QAAQ,IAAC,OAAO,EAAE,KAAK,CAAC,WAAW,GAAI,CAAC;IAClD,CAAC;IAED,OAAO,CACL,KAAC,MAAM,CAAC,GAAG,IACT,SAAS,EAAC,gBAAgB,EAC1B,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAC7B,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAC7B,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,YAE5B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAC3B,eAAa,SAAS,EAAC,qBAAqB,aAC1C,eACE,SAAS,EAAC,4BAA4B,EACtC,KAAK,EAAE,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC,EAAE,aAE/D,eACE,SAAS,EAAC,yBAAyB,EACnC,KAAK,EAAE,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC,EAAE,GAC9D,EACD,IAAI,CAAC,KAAK,IACP,EACN,aAAI,SAAS,EAAC,4BAA4B,YACvC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAC7B,aAAY,SAAS,EAAC,2BAA2B,YAC/C,KAAC,QAAQ,IAAC,OAAO,EAAE,KAAK,GAAI,IADrB,CAAC,CAEL,CACN,CAAC,GACC,KAjBG,CAAC,CAkBL,CACP,CAAC,GACS,CACd,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,kBAAkB,CAAC,WAAW,GAAG,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SemanticBlock } from '../../core/types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
block: SemanticBlock;
|
|
4
|
+
Fallback: React.ComponentType<{
|
|
5
|
+
content: string;
|
|
6
|
+
}>;
|
|
7
|
+
}
|
|
8
|
+
export declare const DataTableRenderer: import("react").MemoExoticComponent<({ block, Fallback }: Props) => import("react/jsx-runtime").JSX.Element>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=DataTableRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataTableRenderer.d.ts","sourceRoot":"","sources":["../../../src/react/renderers/DataTableRenderer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,qBAAqB,CAAC;AAExE,UAAU,KAAK;IACb,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAWD,eAAO,MAAM,iBAAiB,4DAA8B,KAAK,6CAoF/D,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useState, useMemo } from 'react';
|
|
3
|
+
import { motion } from 'framer-motion';
|
|
4
|
+
import { ArrowUpDown, ArrowUp, ArrowDown, Search } from 'lucide-react';
|
|
5
|
+
function naturalCompare(a, b) {
|
|
6
|
+
const numA = parseFloat(a);
|
|
7
|
+
const numB = parseFloat(b);
|
|
8
|
+
if (!isNaN(numA) && !isNaN(numB))
|
|
9
|
+
return numA - numB;
|
|
10
|
+
return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });
|
|
11
|
+
}
|
|
12
|
+
export const DataTableRenderer = memo(({ block, Fallback }) => {
|
|
13
|
+
const meta = block.meta;
|
|
14
|
+
const [sortCol, setSortCol] = useState(null);
|
|
15
|
+
const [sortDir, setSortDir] = useState(null);
|
|
16
|
+
const [filter, setFilter] = useState('');
|
|
17
|
+
if (!meta?.headers?.length || !meta?.rows?.length) {
|
|
18
|
+
return _jsx(Fallback, { content: block.rawMarkdown });
|
|
19
|
+
}
|
|
20
|
+
const filteredRows = useMemo(() => {
|
|
21
|
+
let rows = meta.rows;
|
|
22
|
+
if (filter.trim()) {
|
|
23
|
+
const q = filter.toLowerCase();
|
|
24
|
+
rows = rows.filter(row => row.some(cell => cell.toLowerCase().includes(q)));
|
|
25
|
+
}
|
|
26
|
+
if (sortCol !== null && sortDir) {
|
|
27
|
+
rows = [...rows].sort((a, b) => {
|
|
28
|
+
const cmp = naturalCompare(a[sortCol] || '', b[sortCol] || '');
|
|
29
|
+
return sortDir === 'asc' ? cmp : -cmp;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return rows;
|
|
33
|
+
}, [meta.rows, filter, sortCol, sortDir]);
|
|
34
|
+
const handleSort = (colIdx) => {
|
|
35
|
+
if (sortCol === colIdx) {
|
|
36
|
+
if (sortDir === 'asc')
|
|
37
|
+
setSortDir('desc');
|
|
38
|
+
else {
|
|
39
|
+
setSortCol(null);
|
|
40
|
+
setSortDir(null);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
setSortCol(colIdx);
|
|
45
|
+
setSortDir('asc');
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
return (_jsxs(motion.div, { className: "sem-data-table", initial: { opacity: 0, y: 8 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.3 }, children: [_jsxs("div", { className: "sem-table-toolbar", children: [_jsxs("div", { className: "sem-table-filter", children: [_jsx(Search, { size: 14 }), _jsx("input", { type: "text", placeholder: "Filter rows...", value: filter, onChange: e => setFilter(e.target.value) })] }), _jsxs("span", { className: "sem-table-count", children: [filteredRows.length, " of ", meta.rows.length, " rows"] })] }), _jsx("div", { className: "sem-table-scroll", children: _jsxs("table", { children: [_jsx("thead", { children: _jsx("tr", { children: meta.headers.map((header, i) => (_jsxs("th", { className: "sem-sort-header", onClick: () => handleSort(i), children: [_jsx("span", { children: header }), sortCol === i && sortDir === 'asc' && _jsx(ArrowUp, { size: 12 }), sortCol === i && sortDir === 'desc' && _jsx(ArrowDown, { size: 12 }), sortCol !== i && _jsx(ArrowUpDown, { size: 12, className: "sem-sort-idle" })] }, i))) }) }), _jsx("tbody", { children: filteredRows.map((row, i) => (_jsx("tr", { children: row.map((cell, j) => (_jsx("td", { children: cell }, j))) }, i))) })] }) })] }));
|
|
49
|
+
});
|
|
50
|
+
DataTableRenderer.displayName = 'DataTableRenderer';
|
|
51
|
+
//# sourceMappingURL=DataTableRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataTableRenderer.js","sourceRoot":"","sources":["../../../src/react/renderers/DataTableRenderer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SemanticBlock } from '../../core/types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
block: SemanticBlock;
|
|
4
|
+
Fallback: React.ComponentType<{
|
|
5
|
+
content: string;
|
|
6
|
+
}>;
|
|
7
|
+
}
|
|
8
|
+
export declare const ProsConsRenderer: import("react").MemoExoticComponent<({ block, Fallback }: Props) => import("react/jsx-runtime").JSX.Element>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=ProsConsRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProsConsRenderer.d.ts","sourceRoot":"","sources":["../../../src/react/renderers/ProsConsRenderer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,qBAAqB,CAAC;AAEvE,UAAU,KAAK;IACb,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAED,eAAO,MAAM,gBAAgB,4DAA8B,KAAK,6CA6C9D,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { motion } from 'framer-motion';
|
|
4
|
+
import { Check, X } from 'lucide-react';
|
|
5
|
+
export const ProsConsRenderer = memo(({ block, Fallback }) => {
|
|
6
|
+
const meta = block.meta;
|
|
7
|
+
if (!meta?.pros?.length || !meta?.cons?.length) {
|
|
8
|
+
return _jsx(Fallback, { content: block.rawMarkdown });
|
|
9
|
+
}
|
|
10
|
+
return (_jsxs(motion.div, { className: "sem-pros-cons", initial: { opacity: 0, y: 8 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.3 }, children: [_jsxs("div", { className: "sem-pros-col", children: [_jsxs("div", { className: "sem-pros-header", children: [_jsx(Check, { size: 18 }), _jsx("span", { children: "Pros" })] }), _jsx("ul", { className: "sem-pros-list", children: meta.pros.map((item, i) => (_jsxs("li", { className: "sem-pros-item", children: [_jsx(Check, { size: 14, className: "sem-pros-icon" }), _jsx("span", { children: _jsx(Fallback, { content: item }) })] }, i))) })] }), _jsxs("div", { className: "sem-cons-col", children: [_jsxs("div", { className: "sem-cons-header", children: [_jsx(X, { size: 18 }), _jsx("span", { children: "Cons" })] }), _jsx("ul", { className: "sem-cons-list", children: meta.cons.map((item, i) => (_jsxs("li", { className: "sem-cons-item", children: [_jsx(X, { size: 14, className: "sem-cons-icon" }), _jsx("span", { children: _jsx(Fallback, { content: item }) })] }, i))) })] })] }));
|
|
11
|
+
});
|
|
12
|
+
ProsConsRenderer.displayName = 'ProsConsRenderer';
|
|
13
|
+
//# sourceMappingURL=ProsConsRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProsConsRenderer.js","sourceRoot":"","sources":["../../../src/react/renderers/ProsConsRenderer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAQxC,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAS,EAAE,EAAE;IAClE,MAAM,IAAI,GAAG,KAAK,CAAC,IAA+B,CAAC;IAEnD,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC/C,OAAO,KAAC,QAAQ,IAAC,OAAO,EAAE,KAAK,CAAC,WAAW,GAAI,CAAC;IAClD,CAAC;IAED,OAAO,CACL,MAAC,MAAM,CAAC,GAAG,IACT,SAAS,EAAC,eAAe,EACzB,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAC7B,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAC7B,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,aAE7B,eAAK,SAAS,EAAC,cAAc,aAC3B,eAAK,SAAS,EAAC,iBAAiB,aAC9B,KAAC,KAAK,IAAC,IAAI,EAAE,EAAE,GAAI,EACnB,kCAAiB,IACb,EACN,aAAI,SAAS,EAAC,eAAe,YAC1B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAC1B,cAAY,SAAS,EAAC,eAAe,aACnC,KAAC,KAAK,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,eAAe,GAAG,EAC7C,yBAAM,KAAC,QAAQ,IAAC,OAAO,EAAE,IAAI,GAAI,GAAO,KAFjC,CAAC,CAGL,CACN,CAAC,GACC,IACD,EAEN,eAAK,SAAS,EAAC,cAAc,aAC3B,eAAK,SAAS,EAAC,iBAAiB,aAC9B,KAAC,CAAC,IAAC,IAAI,EAAE,EAAE,GAAI,EACf,kCAAiB,IACb,EACN,aAAI,SAAS,EAAC,eAAe,YAC1B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAC1B,cAAY,SAAS,EAAC,eAAe,aACnC,KAAC,CAAC,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,eAAe,GAAG,EACzC,yBAAM,KAAC,QAAQ,IAAC,OAAO,EAAE,IAAI,GAAI,GAAO,KAFjC,CAAC,CAGL,CACN,CAAC,GACC,IACD,IACK,CACd,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,gBAAgB,CAAC,WAAW,GAAG,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SemanticBlock } from '../../core/types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
block: SemanticBlock;
|
|
4
|
+
Fallback: React.ComponentType<{
|
|
5
|
+
content: string;
|
|
6
|
+
}>;
|
|
7
|
+
}
|
|
8
|
+
export declare const StepsRenderer: import("react").MemoExoticComponent<({ block, Fallback }: Props) => import("react/jsx-runtime").JSX.Element>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=StepsRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StepsRenderer.d.ts","sourceRoot":"","sources":["../../../src/react/renderers/StepsRenderer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,qBAAqB,CAAC;AAEpE,UAAU,KAAK;IACb,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAED,eAAO,MAAM,aAAa,4DAA8B,KAAK,6CA4D3D,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useState } from 'react';
|
|
3
|
+
import { motion, AnimatePresence } from 'framer-motion';
|
|
4
|
+
import { ChevronDown, ChevronRight } from 'lucide-react';
|
|
5
|
+
export const StepsRenderer = memo(({ block, Fallback }) => {
|
|
6
|
+
const meta = block.meta;
|
|
7
|
+
const [expandedSteps, setExpandedSteps] = useState(() => new Set(meta?.steps?.map((_, i) => i) ?? []));
|
|
8
|
+
if (!meta?.steps?.length) {
|
|
9
|
+
return _jsx(Fallback, { content: block.rawMarkdown });
|
|
10
|
+
}
|
|
11
|
+
const toggleStep = (index) => {
|
|
12
|
+
setExpandedSteps(prev => {
|
|
13
|
+
const next = new Set(prev);
|
|
14
|
+
if (next.has(index))
|
|
15
|
+
next.delete(index);
|
|
16
|
+
else
|
|
17
|
+
next.add(index);
|
|
18
|
+
return next;
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
return (_jsx(motion.div, { className: "sem-steps", initial: { opacity: 0, y: 8 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.3 }, children: meta.steps.map((step, i) => {
|
|
22
|
+
const isExpanded = expandedSteps.has(i);
|
|
23
|
+
const isLast = i === meta.steps.length - 1;
|
|
24
|
+
return (_jsxs("div", { className: `sem-step ${isLast ? 'sem-step-last' : ''}`, children: [_jsxs("div", { className: "sem-step-rail", children: [_jsx("div", { className: "sem-step-circle", children: step.number }), !isLast && _jsx("div", { className: "sem-step-line" })] }), _jsxs("div", { className: "sem-step-content", children: [_jsxs("button", { className: "sem-step-title", onClick: () => toggleStep(i), children: [_jsx("span", { children: step.title }), isExpanded ? _jsx(ChevronDown, { size: 16 }) : _jsx(ChevronRight, { size: 16 })] }), _jsx(AnimatePresence, { initial: false, children: isExpanded && step.body && (_jsx(motion.div, { className: "sem-step-body", initial: { height: 0, opacity: 0 }, animate: { height: 'auto', opacity: 1 }, exit: { height: 0, opacity: 0 }, transition: { duration: 0.2 }, children: _jsx(Fallback, { content: step.body }) })) })] })] }, i));
|
|
25
|
+
}) }));
|
|
26
|
+
});
|
|
27
|
+
StepsRenderer.displayName = 'StepsRenderer';
|
|
28
|
+
//# sourceMappingURL=StepsRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StepsRenderer.js","sourceRoot":"","sources":["../../../src/react/renderers/StepsRenderer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SemanticBlock } from '../../core/types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
block: SemanticBlock;
|
|
4
|
+
Fallback: React.ComponentType<{
|
|
5
|
+
content: string;
|
|
6
|
+
}>;
|
|
7
|
+
}
|
|
8
|
+
export declare const VerdictRenderer: import("react").MemoExoticComponent<({ block, Fallback }: Props) => import("react/jsx-runtime").JSX.Element>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=VerdictRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VerdictRenderer.d.ts","sourceRoot":"","sources":["../../../src/react/renderers/VerdictRenderer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,qBAAqB,CAAC;AAEtE,UAAU,KAAK;IACb,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAED,eAAO,MAAM,eAAe,4DAA8B,KAAK,6CA2B7D,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { motion } from 'framer-motion';
|
|
4
|
+
import { Lightbulb } from 'lucide-react';
|
|
5
|
+
export const VerdictRenderer = memo(({ block, Fallback }) => {
|
|
6
|
+
const meta = block.meta;
|
|
7
|
+
if (!meta?.verdict) {
|
|
8
|
+
return _jsx(Fallback, { content: block.rawMarkdown });
|
|
9
|
+
}
|
|
10
|
+
return (_jsxs(motion.div, { className: "sem-verdict", initial: { opacity: 0, y: 8 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.3 }, children: [_jsx("div", { className: "sem-verdict-icon", children: _jsx(Lightbulb, { size: 20 }) }), _jsxs("div", { className: "sem-verdict-content", children: [_jsx(Fallback, { content: meta.verdict }), meta.reasoning && (_jsx("div", { className: "sem-verdict-reasoning", children: _jsx(Fallback, { content: meta.reasoning }) }))] })] }));
|
|
11
|
+
});
|
|
12
|
+
VerdictRenderer.displayName = 'VerdictRenderer';
|
|
13
|
+
//# sourceMappingURL=VerdictRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VerdictRenderer.js","sourceRoot":"","sources":["../../../src/react/renderers/VerdictRenderer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAQzC,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAS,EAAE,EAAE;IACjE,MAAM,IAAI,GAAG,KAAK,CAAC,IAA8B,CAAC;IAElD,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;QACnB,OAAO,KAAC,QAAQ,IAAC,OAAO,EAAE,KAAK,CAAC,WAAW,GAAI,CAAC;IAClD,CAAC;IAED,OAAO,CACL,MAAC,MAAM,CAAC,GAAG,IACT,SAAS,EAAC,aAAa,EACvB,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAC7B,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAC7B,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,aAE7B,cAAK,SAAS,EAAC,kBAAkB,YAC/B,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,GACnB,EACN,eAAK,SAAS,EAAC,qBAAqB,aAClC,KAAC,QAAQ,IAAC,OAAO,EAAE,IAAI,CAAC,OAAO,GAAI,EAClC,IAAI,CAAC,SAAS,IAAI,CACjB,cAAK,SAAS,EAAC,uBAAuB,YACpC,KAAC,QAAQ,IAAC,OAAO,EAAE,IAAI,CAAC,SAAS,GAAI,GACjC,CACP,IACG,IACK,CACd,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,eAAe,CAAC,WAAW,GAAG,iBAAiB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "semantic-renderer",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Intelligent LLM response renderer that detects semantic intent (comparisons, steps, pros/cons, code explanations, tables, verdicts) and renders with purpose-built visual components instead of generic markdown.",
|
|
5
|
+
"author": "Sagar Kalra <autopriseai@gmail.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/AutoPriseAI/semantic-renderer"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"llm",
|
|
13
|
+
"ai",
|
|
14
|
+
"markdown",
|
|
15
|
+
"renderer",
|
|
16
|
+
"semantic",
|
|
17
|
+
"react",
|
|
18
|
+
"react-native",
|
|
19
|
+
"chatbot",
|
|
20
|
+
"comparison",
|
|
21
|
+
"steps",
|
|
22
|
+
"pros-cons",
|
|
23
|
+
"streaming",
|
|
24
|
+
"openai",
|
|
25
|
+
"claude",
|
|
26
|
+
"gemini"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
29
|
+
"main": "./dist/core/index.js",
|
|
30
|
+
"module": "./dist/core/index.js",
|
|
31
|
+
"types": "./dist/core/index.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/core/index.d.ts",
|
|
35
|
+
"import": "./dist/core/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./react": {
|
|
38
|
+
"types": "./dist/react/index.d.ts",
|
|
39
|
+
"import": "./dist/react/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./react/styles.css": "./src/react/styles.css"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"src/react/styles.css",
|
|
46
|
+
"README.md",
|
|
47
|
+
"LICENSE"
|
|
48
|
+
],
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsc",
|
|
51
|
+
"prepublishOnly": "npm run build"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"framer-motion": ">=10.0.0",
|
|
55
|
+
"lucide-react": ">=0.300.0",
|
|
56
|
+
"react": ">=18.0.0",
|
|
57
|
+
"react-dom": ">=18.0.0",
|
|
58
|
+
"react-markdown": ">=9.0.0"
|
|
59
|
+
},
|
|
60
|
+
"peerDependenciesMeta": {
|
|
61
|
+
"react": {
|
|
62
|
+
"optional": true
|
|
63
|
+
},
|
|
64
|
+
"react-dom": {
|
|
65
|
+
"optional": true
|
|
66
|
+
},
|
|
67
|
+
"react-markdown": {
|
|
68
|
+
"optional": true
|
|
69
|
+
},
|
|
70
|
+
"framer-motion": {
|
|
71
|
+
"optional": true
|
|
72
|
+
},
|
|
73
|
+
"lucide-react": {
|
|
74
|
+
"optional": true
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"devDependencies": {
|
|
78
|
+
"@types/react": "^19.0.0",
|
|
79
|
+
"framer-motion": "^12.38.0",
|
|
80
|
+
"lucide-react": "^1.7.0",
|
|
81
|
+
"react-dom": "^19.2.5",
|
|
82
|
+
"react-markdown": "^10.1.0",
|
|
83
|
+
"typescript": "^5.9.0"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/* semantic-renderer — default styles
|
|
2
|
+
Import: import 'semantic-renderer/react/styles.css'
|
|
3
|
+
All classes use .sem- prefix to avoid collisions. */
|
|
4
|
+
|
|
5
|
+
.sem-body { display: flex; flex-direction: column; gap: 16px; }
|
|
6
|
+
|
|
7
|
+
/* Verdict */
|
|
8
|
+
.sem-verdict { display: flex; gap: 14px; padding: 16px 18px; border-left: 4px solid var(--sem-accent, #6366f1); background: linear-gradient(135deg, rgba(99,102,241,0.04) 0%, rgba(109,40,217,0.03) 100%); border-radius: 0 10px 10px 0; }
|
|
9
|
+
.sem-verdict-icon { flex-shrink: 0; color: var(--sem-accent, #6366f1); margin-top: 2px; }
|
|
10
|
+
.sem-verdict-content { flex: 1; min-width: 0; }
|
|
11
|
+
.sem-verdict-content p { font-size: 1.02em; }
|
|
12
|
+
.sem-verdict-reasoning { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--sem-border, #e5e7eb); opacity: 0.75; font-size: 0.92em; }
|
|
13
|
+
|
|
14
|
+
/* Pros & Cons */
|
|
15
|
+
.sem-pros-cons { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
|
|
16
|
+
.sem-pros-col, .sem-cons-col { border-radius: 10px; border: 1px solid var(--sem-border, #e5e7eb); overflow: hidden; }
|
|
17
|
+
.sem-pros-header, .sem-cons-header { display: flex; align-items: center; gap: 8px; padding: 10px 14px; font-weight: 600; font-size: 0.88em; text-transform: uppercase; letter-spacing: 0.04em; }
|
|
18
|
+
.sem-pros-header { background: rgba(22,163,74,0.08); color: #16a34a; border-bottom: 1px solid rgba(22,163,74,0.15); }
|
|
19
|
+
.sem-cons-header { background: rgba(220,38,38,0.08); color: #dc2626; border-bottom: 1px solid rgba(220,38,38,0.15); }
|
|
20
|
+
.sem-pros-list, .sem-cons-list { list-style: none; padding: 8px 14px; margin: 0; }
|
|
21
|
+
.sem-pros-item, .sem-cons-item { display: flex; align-items: flex-start; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--sem-border, #e5e7eb); font-size: 0.93em; line-height: 1.5; }
|
|
22
|
+
.sem-pros-item:last-child, .sem-cons-item:last-child { border-bottom: none; }
|
|
23
|
+
.sem-pros-icon { flex-shrink: 0; color: #16a34a; margin-top: 3px; }
|
|
24
|
+
.sem-cons-icon { flex-shrink: 0; color: #dc2626; margin-top: 3px; }
|
|
25
|
+
|
|
26
|
+
/* Steps */
|
|
27
|
+
.sem-steps { display: flex; flex-direction: column; }
|
|
28
|
+
.sem-step { display: flex; gap: 14px; min-height: 48px; }
|
|
29
|
+
.sem-step-rail { display: flex; flex-direction: column; align-items: center; flex-shrink: 0; width: 32px; }
|
|
30
|
+
.sem-step-circle { width: 28px; height: 28px; border-radius: 50%; background: var(--sem-accent, #6366f1); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 0.78em; font-weight: 700; flex-shrink: 0; }
|
|
31
|
+
.sem-step-line { width: 2px; flex: 1; background: var(--sem-border, #d1d5db); margin: 4px 0; min-height: 16px; }
|
|
32
|
+
.sem-step-last .sem-step-line { display: none; }
|
|
33
|
+
.sem-step-content { flex: 1; min-width: 0; padding-bottom: 16px; }
|
|
34
|
+
.sem-step-last .sem-step-content { padding-bottom: 0; }
|
|
35
|
+
.sem-step-title { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; background: none; border: none; cursor: pointer; font: inherit; font-weight: 600; font-size: 0.95em; color: inherit; padding: 4px 8px 4px 0; text-align: left; border-radius: 6px; transition: background 0.15s; }
|
|
36
|
+
.sem-step-title:hover { background: rgba(0,0,0,0.03); }
|
|
37
|
+
.sem-step-title svg { flex-shrink: 0; opacity: 0.5; }
|
|
38
|
+
.sem-step-body { overflow: hidden; padding-top: 6px; }
|
|
39
|
+
.sem-step-body p { font-size: 0.93em; }
|
|
40
|
+
|
|
41
|
+
/* Comparison */
|
|
42
|
+
.sem-comparison { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; }
|
|
43
|
+
.sem-comparison-card { border-radius: 10px; border: 1px solid var(--sem-border, #e5e7eb); overflow: hidden; }
|
|
44
|
+
.sem-comparison-card-header { display: flex; align-items: center; gap: 8px; padding: 10px 14px; font-weight: 600; font-size: 0.95em; border-bottom: 2px solid var(--sem-accent, #6366f1); background: rgba(0,0,0,0.015); }
|
|
45
|
+
.sem-comparison-card-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
|
|
46
|
+
.sem-comparison-card-points { list-style: none; padding: 8px 14px; margin: 0; }
|
|
47
|
+
.sem-comparison-card-point { padding: 6px 0; border-bottom: 1px solid var(--sem-border, #e5e7eb); font-size: 0.92em; line-height: 1.5; }
|
|
48
|
+
.sem-comparison-card-point:last-child { border-bottom: none; }
|
|
49
|
+
|
|
50
|
+
/* Data Table */
|
|
51
|
+
.sem-data-table { border-radius: 10px; border: 1px solid var(--sem-border, #e5e7eb); overflow: hidden; }
|
|
52
|
+
.sem-table-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 12px; background: rgba(0,0,0,0.015); border-bottom: 1px solid var(--sem-border, #e5e7eb); }
|
|
53
|
+
.sem-table-filter { display: flex; align-items: center; gap: 6px; color: #6b7280; }
|
|
54
|
+
.sem-table-filter input { border: 1px solid var(--sem-border, #d1d5db); border-radius: 6px; padding: 4px 8px; font-size: 0.82em; outline: none; width: 160px; }
|
|
55
|
+
.sem-table-filter input:focus { border-color: var(--sem-accent, #6366f1); }
|
|
56
|
+
.sem-table-count { font-size: 0.78em; color: #6b7280; white-space: nowrap; }
|
|
57
|
+
.sem-table-scroll { overflow-x: auto; }
|
|
58
|
+
.sem-sort-header { cursor: pointer; user-select: none; white-space: nowrap; }
|
|
59
|
+
.sem-sort-header > span { margin-right: 4px; }
|
|
60
|
+
.sem-sort-idle { opacity: 0.3; }
|
|
61
|
+
.sem-sort-header:hover .sem-sort-idle { opacity: 0.6; }
|
|
62
|
+
|
|
63
|
+
/* Code + Explanation */
|
|
64
|
+
.sem-code-explain { display: grid; grid-template-columns: 55% 45%; border-radius: 10px; border: 1px solid var(--sem-border, #e5e7eb); overflow: hidden; }
|
|
65
|
+
.sem-code-panel { border-right: 1px solid var(--sem-border, #e5e7eb); overflow: auto; max-height: 500px; }
|
|
66
|
+
.sem-code-panel-header { display: flex; align-items: center; gap: 6px; padding: 6px 12px; background: #1e1e1e; color: #9ca3af; font-size: 0.78em; font-weight: 500; text-transform: uppercase; letter-spacing: 0.04em; }
|
|
67
|
+
.sem-explain-panel { padding: 14px 16px; overflow: auto; max-height: 500px; }
|
|
68
|
+
.sem-explain-panel-header { font-weight: 600; font-size: 0.82em; text-transform: uppercase; letter-spacing: 0.04em; color: #6b7280; margin-bottom: 10px; padding-bottom: 6px; border-bottom: 1px solid var(--sem-border, #e5e7eb); }
|
|
69
|
+
.sem-explain-panel p { font-size: 0.92em; }
|
|
70
|
+
|
|
71
|
+
/* Responsive */
|
|
72
|
+
@media (max-width: 700px) {
|
|
73
|
+
.sem-pros-cons { grid-template-columns: 1fr; }
|
|
74
|
+
.sem-comparison { grid-template-columns: 1fr; }
|
|
75
|
+
.sem-code-explain { grid-template-columns: 1fr; }
|
|
76
|
+
.sem-code-panel { border-right: none; border-bottom: 1px solid var(--sem-border, #e5e7eb); max-height: 300px; }
|
|
77
|
+
.sem-explain-panel { max-height: none; }
|
|
78
|
+
.sem-table-toolbar { flex-direction: column; align-items: flex-start; }
|
|
79
|
+
}
|