diff --git a/examples/test-statements-viewer.html b/examples/test-statements-viewer.html new file mode 100644 index 0000000..c99a3dc --- /dev/null +++ b/examples/test-statements-viewer.html @@ -0,0 +1,306 @@ + + + + + + Enhanced Statement Viewer Test + + + +

Enhanced Statement Viewer Test

+
+ + + + + + + + + \ No newline at end of file diff --git a/statements.jsx b/statements.jsx index 0ce4c56..f626d2d 100644 --- a/statements.jsx +++ b/statements.jsx @@ -6,13 +6,139 @@ if (typeof React === 'undefined') { console.error('React is not available. Make sure React is loaded before this script.'); } +/** + * Reference Component + * Renders a single reference that confirms or refutes a statement + */ +function Reference({ reference, getLabel, onEntityClick, onPropertyClick, selectedLanguage }) { + const [isExpanded, setIsExpanded] = React.useState(false); + + const renderSnakValue = (snak) => { + if (!snak.datavalue) return 'No value'; + + const value = snak.datavalue.value; + + if (snak.datatype === 'wikibase-item' && value.id) { + return ( + { + e.preventDefault(); + if (onEntityClick) { + onEntityClick(value.id); + } else { + window.location.href = `entities.html#${value.id}`; + } + }} + > + {getLabel(value.id)} + + ); + } else if (snak.datatype === 'time') { + return value.time; + } else if (snak.datatype === 'string' || snak.datatype === 'external-id') { + return value; + } else if (snak.datatype === 'url') { + return ( + + {value} + + ); + } + + return String(value); + }; + + const mainSnaks = Object.entries(reference.snaks).slice(0, 2); // Show first 2 snaks by default + const hasMore = Object.keys(reference.snaks).length > 2; + + return ( +
+
+ 📍 +
+ {mainSnaks.map(([propId, snakArray]) => ( +
+ { + if (onPropertyClick) { + e.preventDefault(); + onPropertyClick(propId); + } + }} + style={{ fontWeight: 'bold', fontSize: '0.8em' }} + > + {getLabel(propId)} + + {': '} + {renderSnakValue(snakArray[0])} +
+ ))} + {hasMore && ( + + )} +
+
+ + {isExpanded && ( +
+ {Object.entries(reference.snaks).slice(2).map(([propId, snakArray]) => ( +
+ { + if (onPropertyClick) { + e.preventDefault(); + onPropertyClick(propId); + } + }} + style={{ fontWeight: 'bold', fontSize: '0.8em' }} + > + {getLabel(propId)} + + {': '} + {renderSnakValue(snakArray[0])} +
+ ))} +
+ )} +
+ ); +} + /** * Statement Component * Renders individual Wikidata statements with proper formatting and links - * Receives an array of items: entities (Q), properties (P), and values (V) + * Now includes confirmations and refutations */ function Statement({ items, + claim, getLabel, onEntityClick, onPropertyClick, @@ -62,22 +188,104 @@ function Statement({ ); } }; + const [showReferences, setShowReferences] = React.useState(false); + const hasReferences = claim && claim.references && claim.references.length > 0; + const isDeprecated = claim && claim.rank === 'deprecated'; + + const getRankColor = (rank) => { + switch (rank) { + case 'preferred': return 'rgba(0, 255, 255, 0.1)'; // Cyan for preferred + case 'deprecated': return 'rgba(255, 0, 0, 0.1)'; // Red for deprecated + default: return 'rgba(0, 255, 0, 0.05)'; // Green for normal + } + }; + + const getRankBorder = (rank) => { + switch (rank) { + case 'preferred': return '1px solid var(--neon-selected)'; + case 'deprecated': return '1px solid #FF6B6B'; + default: return '1px solid var(--neon)'; + } + }; + + const getRankIcon = (rank) => { + switch (rank) { + case 'preferred': return '⭐'; + case 'deprecated': return '❌'; + default: return ''; + } + }; + return (
- {items.map((item, index) => ( - - {renderItem(item, index)} - {index < items.length - 1 && ' '} - - ))} +
+ {claim?.rank && claim.rank !== 'normal' && ( + + {getRankIcon(claim.rank)} + + )} +
+ {items.map((item, index) => ( + + {renderItem(item, index)} + {index < items.length - 1 && ' '} + + ))} +
+ {hasReferences && ( + + )} +
+ + {showReferences && hasReferences && ( +
+
+ {isDeprecated ? 'Refutations:' : 'Confirmations:'} +
+ {claim.references.map((reference, index) => ( + + ))} +
+ )}
); } @@ -148,6 +356,7 @@ function StatementsList({