page.tsx 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. "use client";
  2. import { useState, useEffect, useCallback, type ReactNode } from "react";
  3. import ConfettiExplosion from "react-confetti-explosion";
  4. import {
  5. Renderer,
  6. StateProvider,
  7. VisibilityProvider,
  8. ActionProvider,
  9. ValidationProvider,
  10. } from "@json-render/react";
  11. import type { Spec } from "@json-render/core";
  12. import { registry, actionHandlers, onConfetti } from "@/lib/render/registry";
  13. import { examples } from "@/lib/examples";
  14. function SpecRenderer({ spec }: { spec: Spec }): ReactNode {
  15. return (
  16. <StateProvider initialState={spec.state ?? {}}>
  17. <VisibilityProvider>
  18. <ActionProvider handlers={actionHandlers}>
  19. <ValidationProvider>
  20. <Renderer spec={spec} registry={registry} />
  21. </ValidationProvider>
  22. </ActionProvider>
  23. </VisibilityProvider>
  24. </StateProvider>
  25. );
  26. }
  27. export default function Page() {
  28. const [selectedIndex] = useState(0);
  29. const selected = examples[selectedIndex]!;
  30. const [confettiKey, setConfettiKey] = useState(0);
  31. const [confettiActive, setConfettiActive] = useState(false);
  32. const fireConfetti = useCallback(() => {
  33. setConfettiKey((k) => k + 1);
  34. setConfettiActive(true);
  35. }, []);
  36. useEffect(() => onConfetti(fireConfetti), [fireConfetti]);
  37. return (
  38. <div className="h-screen flex items-center justify-center bg-muted/30">
  39. <div
  40. className="relative bg-background border rounded-lg shadow-sm"
  41. style={{ width: 960, height: 1080 }}
  42. >
  43. {confettiActive && (
  44. <div className="absolute inset-0 flex items-center justify-center pointer-events-none">
  45. <ConfettiExplosion
  46. key={confettiKey}
  47. portal={false}
  48. force={0.8}
  49. duration={3500}
  50. particleCount={400}
  51. particleSize={8}
  52. colors={["#00F0FF", "#7B61FF", "#FF3DFF", "#00FF94", "#FFE14D"]}
  53. width={1600}
  54. height="200vh"
  55. zIndex={1}
  56. onComplete={() => setConfettiActive(false)}
  57. />
  58. </div>
  59. )}
  60. <div className="h-full overflow-auto p-6 flex items-center justify-center relative z-10">
  61. <SpecRenderer key={selectedIndex} spec={selected.spec} />
  62. </div>
  63. </div>
  64. </div>
  65. );
  66. }