cmx-sdk 0.2.12 → 0.2.14

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/dist/index.js CHANGED
@@ -365,32 +365,64 @@ var icons = {
365
365
  tip: Lightbulb
366
366
  };
367
367
  var styles = {
368
- info: "cmx-mdx__callout--info bg-blue-50 border-blue-200 text-blue-800",
369
- warning: "cmx-mdx__callout--warning bg-yellow-50 border-yellow-200 text-yellow-800",
370
- error: "cmx-mdx__callout--error bg-red-50 border-red-200 text-red-800",
371
- success: "cmx-mdx__callout--success bg-green-50 border-green-200 text-green-800",
372
- tip: "cmx-mdx__callout--tip bg-purple-50 border-purple-200 text-purple-800"
373
- };
374
- var iconColors = {
375
- info: "text-blue-500",
376
- warning: "text-yellow-500",
377
- error: "text-red-500",
378
- success: "text-green-500",
379
- tip: "text-purple-500"
368
+ info: "cmx-mdx__callout--info",
369
+ warning: "cmx-mdx__callout--warning",
370
+ error: "cmx-mdx__callout--error",
371
+ success: "cmx-mdx__callout--success",
372
+ tip: "cmx-mdx__callout--tip"
380
373
  };
381
374
  function Callout({ type = "info", title, children }) {
382
375
  const Icon = icons[type];
383
- return /* @__PURE__ */ jsx("div", { className: `cmx-mdx__callout my-4 p-4 border rounded-lg ${styles[type]}`, children: /* @__PURE__ */ jsxs("div", { className: "cmx-mdx__callout-content flex gap-3", children: [
384
- /* @__PURE__ */ jsx(Icon, { className: `cmx-mdx__callout-icon w-5 h-5 flex-shrink-0 mt-0.5 ${iconColors[type]}` }),
376
+ return /* @__PURE__ */ jsx("div", { className: `cmx-mdx__callout ${styles[type]}`, children: /* @__PURE__ */ jsxs("div", { className: "cmx-mdx__callout-content flex gap-3", children: [
377
+ /* @__PURE__ */ jsx(Icon, { className: "cmx-mdx__callout-icon flex-shrink-0" }),
385
378
  /* @__PURE__ */ jsxs("div", { className: "cmx-mdx__callout-body flex-1", children: [
386
- title && /* @__PURE__ */ jsx("p", { className: "cmx-mdx__callout-title font-semibold mb-1", children: title }),
387
- /* @__PURE__ */ jsx("div", { className: "cmx-mdx__callout-text text-sm", children })
379
+ title && /* @__PURE__ */ jsx("p", { className: "cmx-mdx__callout-title", children: title }),
380
+ /* @__PURE__ */ jsx("div", { className: "cmx-mdx__callout-text", children })
388
381
  ] })
389
382
  ] }) });
390
383
  }
391
384
 
385
+ // src/mdx/components/basic/Button.tsx
386
+ import Link from "next/link";
387
+ import { jsx as jsx2 } from "react/jsx-runtime";
388
+ var variants = {
389
+ primary: "cmx-mdx__button--primary",
390
+ secondary: "cmx-mdx__button--secondary",
391
+ outline: "cmx-mdx__button--outline"
392
+ };
393
+ function Button({ href, children, variant = "primary" }) {
394
+ const isExternal = href.startsWith("http");
395
+ const className = `cmx-mdx__button ${variants[variant]}`;
396
+ if (isExternal) {
397
+ return /* @__PURE__ */ jsx2(
398
+ "a",
399
+ {
400
+ href,
401
+ target: "_blank",
402
+ rel: "noopener noreferrer",
403
+ className,
404
+ children
405
+ }
406
+ );
407
+ }
408
+ return /* @__PURE__ */ jsx2(Link, { href, className, children });
409
+ }
410
+
392
411
  // src/mdx/components/basic/Embed.tsx
393
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
412
+ import { jsx as jsx3 } from "react/jsx-runtime";
413
+ function Embed({ url }) {
414
+ return /* @__PURE__ */ jsx3("div", { className: "cmx-mdx__embed cmx-mdx__embed--generic aspect-video", children: /* @__PURE__ */ jsx3(
415
+ "iframe",
416
+ {
417
+ src: url,
418
+ className: "cmx-mdx__embed-iframe w-full h-full",
419
+ allowFullScreen: true
420
+ }
421
+ ) });
422
+ }
423
+
424
+ // src/mdx/components/basic/YouTube.tsx
425
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
394
426
  function extractYouTubeId(url) {
395
427
  const patterns = [
396
428
  /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/
@@ -401,97 +433,446 @@ function extractYouTubeId(url) {
401
433
  }
402
434
  return null;
403
435
  }
404
- function Embed({ url, type = "generic" }) {
405
- if (type === "youtube") {
406
- const videoId = extractYouTubeId(url);
407
- if (videoId) {
408
- return /* @__PURE__ */ jsx2("div", { className: "cmx-mdx__embed cmx-mdx__embed--youtube my-4 aspect-video", children: /* @__PURE__ */ jsx2(
409
- "iframe",
410
- {
411
- src: `https://www.youtube.com/embed/${videoId}`,
412
- className: "cmx-mdx__embed-iframe w-full h-full rounded-lg",
413
- allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
414
- allowFullScreen: true
415
- }
416
- ) });
417
- }
436
+ function YouTube({ url, start }) {
437
+ const videoId = extractYouTubeId(url);
438
+ if (!videoId) {
439
+ return /* @__PURE__ */ jsx4("div", { className: "cmx-mdx__youtube cmx-mdx__youtube--error", children: /* @__PURE__ */ jsxs2("p", { className: "cmx-mdx__error-text", children: [
440
+ "\u7121\u52B9\u306AYouTube URL: ",
441
+ url
442
+ ] }) });
418
443
  }
419
- if (type === "twitter") {
420
- return /* @__PURE__ */ jsxs2("div", { className: "cmx-mdx__embed cmx-mdx__embed--twitter my-4 border border-gray-200 rounded-lg p-4 bg-gray-50", children: [
421
- /* @__PURE__ */ jsx2("p", { className: "cmx-mdx__embed-label text-sm text-gray-500", children: "Twitter\u57CB\u3081\u8FBC\u307F" }),
422
- /* @__PURE__ */ jsx2(
444
+ const embedUrl = `https://www.youtube.com/embed/${videoId}${start ? `?start=${start}` : ""}`;
445
+ return /* @__PURE__ */ jsx4("div", { className: "cmx-mdx__youtube aspect-video", children: /* @__PURE__ */ jsx4(
446
+ "iframe",
447
+ {
448
+ src: embedUrl,
449
+ className: "cmx-mdx__youtube-iframe w-full h-full",
450
+ allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
451
+ allowFullScreen: true
452
+ }
453
+ ) });
454
+ }
455
+
456
+ // src/mdx/components/basic/Twitter.tsx
457
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
458
+ function Twitter({ url }) {
459
+ return /* @__PURE__ */ jsxs3("div", { className: "cmx-mdx__twitter", children: [
460
+ /* @__PURE__ */ jsx5("p", { className: "cmx-mdx__twitter-label", children: "Twitter / X" }),
461
+ /* @__PURE__ */ jsx5(
462
+ "a",
463
+ {
464
+ href: url,
465
+ target: "_blank",
466
+ rel: "noopener noreferrer",
467
+ className: "cmx-mdx__twitter-link break-all",
468
+ children: url
469
+ }
470
+ )
471
+ ] });
472
+ }
473
+
474
+ // src/mdx/components/basic/Instagram.tsx
475
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
476
+ function Instagram({ url }) {
477
+ return /* @__PURE__ */ jsxs4("div", { className: "cmx-mdx__instagram", children: [
478
+ /* @__PURE__ */ jsx6("p", { className: "cmx-mdx__instagram-label", children: "Instagram" }),
479
+ /* @__PURE__ */ jsx6(
480
+ "a",
481
+ {
482
+ href: url,
483
+ target: "_blank",
484
+ rel: "noopener noreferrer",
485
+ className: "cmx-mdx__instagram-link break-all",
486
+ children: url
487
+ }
488
+ )
489
+ ] });
490
+ }
491
+
492
+ // src/mdx/components/basic/TikTok.tsx
493
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
494
+ function extractTikTokVideoId(url) {
495
+ const match = url.match(/\/video\/(\d+)/);
496
+ return match ? match[1] : null;
497
+ }
498
+ function TikTok({ url }) {
499
+ const videoId = extractTikTokVideoId(url);
500
+ if (!videoId) {
501
+ return /* @__PURE__ */ jsxs5("div", { className: "cmx-mdx__tiktok cmx-mdx__tiktok--error", children: [
502
+ /* @__PURE__ */ jsx7("p", { className: "cmx-mdx__tiktok-label", children: "TikTok" }),
503
+ /* @__PURE__ */ jsx7(
423
504
  "a",
424
505
  {
425
506
  href: url,
426
507
  target: "_blank",
427
508
  rel: "noopener noreferrer",
428
- className: "cmx-mdx__embed-link text-blue-500 hover:underline text-sm",
509
+ className: "cmx-mdx__tiktok-link break-all",
429
510
  children: url
430
511
  }
431
512
  )
432
513
  ] });
433
514
  }
434
- return /* @__PURE__ */ jsx2("div", { className: "cmx-mdx__embed cmx-mdx__embed--generic my-4 aspect-video", children: /* @__PURE__ */ jsx2(
515
+ return /* @__PURE__ */ jsx7("div", { className: "cmx-mdx__tiktok", children: /* @__PURE__ */ jsx7(
435
516
  "iframe",
436
517
  {
437
- src: url,
438
- className: "cmx-mdx__embed-iframe w-full h-full rounded-lg border border-gray-200",
439
- allowFullScreen: true
518
+ src: `https://www.tiktok.com/embed/v2/${videoId}`,
519
+ className: "cmx-mdx__tiktok-iframe w-full border-0",
520
+ style: { height: 740, maxWidth: 325 },
521
+ allowFullScreen: true,
522
+ allow: "encrypted-media"
440
523
  }
441
524
  ) });
442
525
  }
443
526
 
444
- // src/mdx/components/basic/Button.tsx
445
- import Link from "next/link";
446
- import { jsx as jsx3 } from "react/jsx-runtime";
447
- var variants = {
448
- primary: "cmx-mdx__button--primary bg-blue-600 text-white hover:bg-blue-700",
449
- secondary: "cmx-mdx__button--secondary bg-gray-600 text-white hover:bg-gray-700",
450
- outline: "cmx-mdx__button--outline border border-gray-300 text-gray-700 hover:bg-gray-50"
451
- };
452
- function Button({ href, children, variant = "primary" }) {
453
- const isExternal = href.startsWith("http");
454
- const className = `cmx-mdx__button inline-block px-4 py-2 rounded-lg font-medium transition-colors ${variants[variant]}`;
455
- if (isExternal) {
456
- return /* @__PURE__ */ jsx3(
527
+ // src/mdx/components/basic/Bluesky.tsx
528
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
529
+ function Bluesky({ url }) {
530
+ return /* @__PURE__ */ jsxs6("div", { className: "cmx-mdx__bluesky", children: [
531
+ /* @__PURE__ */ jsx8("p", { className: "cmx-mdx__bluesky-label", children: "Bluesky" }),
532
+ /* @__PURE__ */ jsx8(
457
533
  "a",
458
534
  {
459
- href,
535
+ href: url,
460
536
  target: "_blank",
461
537
  rel: "noopener noreferrer",
462
- className,
463
- children
538
+ className: "cmx-mdx__bluesky-link break-all",
539
+ children: url
464
540
  }
465
- );
541
+ )
542
+ ] });
543
+ }
544
+
545
+ // src/mdx/components/basic/Vimeo.tsx
546
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
547
+ function extractVimeoId(url) {
548
+ const match = url.match(/vimeo\.com\/(\d+)/);
549
+ return match ? match[1] : null;
550
+ }
551
+ function Vimeo({ url }) {
552
+ const videoId = extractVimeoId(url);
553
+ if (!videoId) {
554
+ return /* @__PURE__ */ jsx9("div", { className: "cmx-mdx__vimeo cmx-mdx__vimeo--error", children: /* @__PURE__ */ jsxs7("p", { className: "cmx-mdx__error-text", children: [
555
+ "\u7121\u52B9\u306AVimeo URL: ",
556
+ url
557
+ ] }) });
466
558
  }
467
- return /* @__PURE__ */ jsx3(Link, { href, className, children });
559
+ return /* @__PURE__ */ jsx9("div", { className: "cmx-mdx__vimeo aspect-video", children: /* @__PURE__ */ jsx9(
560
+ "iframe",
561
+ {
562
+ src: `https://player.vimeo.com/video/${videoId}`,
563
+ className: "cmx-mdx__vimeo-iframe w-full h-full",
564
+ allow: "autoplay; fullscreen; picture-in-picture",
565
+ allowFullScreen: true
566
+ }
567
+ ) });
568
+ }
569
+
570
+ // src/mdx/components/basic/Spotify.tsx
571
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
572
+ function toSpotifyEmbedUrl(url) {
573
+ const match = url.match(/open\.spotify\.com\/(track|album|playlist|episode|show)\/([^?#]+)/);
574
+ if (!match) return null;
575
+ return `https://open.spotify.com/embed/${match[1]}/${match[2]}`;
576
+ }
577
+ function Spotify({ url, theme = "light" }) {
578
+ const embedUrl = toSpotifyEmbedUrl(url);
579
+ if (!embedUrl) {
580
+ return /* @__PURE__ */ jsx10("div", { className: "cmx-mdx__spotify cmx-mdx__spotify--error", children: /* @__PURE__ */ jsxs8("p", { className: "cmx-mdx__error-text", children: [
581
+ "\u7121\u52B9\u306ASpotify URL: ",
582
+ url
583
+ ] }) });
584
+ }
585
+ const src = `${embedUrl}?theme=${theme === "dark" ? "0" : "1"}`;
586
+ return /* @__PURE__ */ jsx10("div", { className: "cmx-mdx__spotify", children: /* @__PURE__ */ jsx10(
587
+ "iframe",
588
+ {
589
+ src,
590
+ className: "cmx-mdx__spotify-iframe w-full border-0",
591
+ height: 152,
592
+ allow: "autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture",
593
+ loading: "lazy"
594
+ }
595
+ ) });
596
+ }
597
+
598
+ // src/mdx/components/basic/Gist.tsx
599
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
600
+ function extractGistId(url) {
601
+ const match = url.match(/gist\.github\.com\/([^/]+)\/([a-f0-9]+)/);
602
+ if (!match) return null;
603
+ return { user: match[1], id: match[2] };
604
+ }
605
+ function Gist({ url }) {
606
+ const gist = extractGistId(url);
607
+ if (!gist) {
608
+ return /* @__PURE__ */ jsx11("div", { className: "cmx-mdx__gist cmx-mdx__gist--error", children: /* @__PURE__ */ jsxs9("p", { className: "cmx-mdx__error-text", children: [
609
+ "\u7121\u52B9\u306AGist URL: ",
610
+ url
611
+ ] }) });
612
+ }
613
+ return /* @__PURE__ */ jsx11("div", { className: "cmx-mdx__gist", children: /* @__PURE__ */ jsx11(
614
+ "iframe",
615
+ {
616
+ src: `https://gist.github.com/${gist.user}/${gist.id}.pibb`,
617
+ className: "cmx-mdx__gist-iframe w-full",
618
+ style: { minHeight: 200 }
619
+ }
620
+ ) });
621
+ }
622
+
623
+ // src/mdx/components/basic/CodePen.tsx
624
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
625
+ function toCodePenEmbedUrl(url) {
626
+ const match = url.match(/codepen\.io\/([^/]+)\/(?:pen|full|details)\/([^?#]+)/);
627
+ if (!match) return null;
628
+ return `https://codepen.io/${match[1]}/embed/${match[2]}`;
629
+ }
630
+ function CodePen({ url, height = 400, defaultTab = "result" }) {
631
+ const embedUrl = toCodePenEmbedUrl(url);
632
+ if (!embedUrl) {
633
+ return /* @__PURE__ */ jsx12("div", { className: "cmx-mdx__codepen cmx-mdx__codepen--error", children: /* @__PURE__ */ jsxs10("p", { className: "cmx-mdx__error-text", children: [
634
+ "\u7121\u52B9\u306ACodePen URL: ",
635
+ url
636
+ ] }) });
637
+ }
638
+ const src = `${embedUrl}?default-tab=${defaultTab}&editable=true`;
639
+ return /* @__PURE__ */ jsx12("div", { className: "cmx-mdx__codepen", children: /* @__PURE__ */ jsx12(
640
+ "iframe",
641
+ {
642
+ src,
643
+ className: "cmx-mdx__codepen-iframe w-full",
644
+ style: { height },
645
+ loading: "lazy",
646
+ allowFullScreen: true
647
+ }
648
+ ) });
649
+ }
650
+
651
+ // src/mdx/components/basic/CodeSandbox.tsx
652
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
653
+ function toCodeSandboxEmbedUrl(url) {
654
+ const match = url.match(/codesandbox\.io\/(?:s|p)\/([^?#]+)/);
655
+ if (!match) return null;
656
+ return `https://codesandbox.io/embed/${match[1]}`;
657
+ }
658
+ function CodeSandbox({ url, height = 500 }) {
659
+ const embedUrl = toCodeSandboxEmbedUrl(url);
660
+ if (!embedUrl) {
661
+ return /* @__PURE__ */ jsx13("div", { className: "cmx-mdx__codesandbox cmx-mdx__codesandbox--error", children: /* @__PURE__ */ jsxs11("p", { className: "cmx-mdx__error-text", children: [
662
+ "\u7121\u52B9\u306ACodeSandbox URL: ",
663
+ url
664
+ ] }) });
665
+ }
666
+ return /* @__PURE__ */ jsx13("div", { className: "cmx-mdx__codesandbox", children: /* @__PURE__ */ jsx13(
667
+ "iframe",
668
+ {
669
+ src: embedUrl,
670
+ className: "cmx-mdx__codesandbox-iframe w-full",
671
+ style: { height },
672
+ allow: "accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking",
673
+ sandbox: "allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
674
+ }
675
+ ) });
676
+ }
677
+
678
+ // src/mdx/components/basic/GoogleMap.tsx
679
+ import { jsx as jsx14 } from "react/jsx-runtime";
680
+ function GoogleMap({ url, height = 450 }) {
681
+ let embedUrl = url;
682
+ if (!url.includes("/maps/embed")) {
683
+ embedUrl = url;
684
+ }
685
+ return /* @__PURE__ */ jsx14("div", { className: "cmx-mdx__googlemap", children: /* @__PURE__ */ jsx14(
686
+ "iframe",
687
+ {
688
+ src: embedUrl,
689
+ className: "cmx-mdx__googlemap-iframe w-full",
690
+ style: { height },
691
+ allowFullScreen: true,
692
+ loading: "lazy",
693
+ referrerPolicy: "no-referrer-when-downgrade"
694
+ }
695
+ ) });
696
+ }
697
+
698
+ // src/mdx/components/basic/Details.tsx
699
+ import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
700
+ function Details({ summary, children }) {
701
+ return /* @__PURE__ */ jsxs12("details", { className: "cmx-mdx__details", children: [
702
+ /* @__PURE__ */ jsx15("summary", { className: "cmx-mdx__details-summary cursor-pointer select-none", children: summary }),
703
+ /* @__PURE__ */ jsx15("div", { className: "cmx-mdx__details-content", children })
704
+ ] });
705
+ }
706
+
707
+ // src/mdx/components/basic/Tabs.tsx
708
+ import { useState, Children, isValidElement } from "react";
709
+ import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
710
+ function Tabs({ children }) {
711
+ const [activeIndex, setActiveIndex] = useState(0);
712
+ const tabs = [];
713
+ Children.forEach(children, (child) => {
714
+ if (isValidElement(child) && child.props.label) {
715
+ const tabChild = child;
716
+ tabs.push({
717
+ label: tabChild.props.label,
718
+ content: tabChild.props.children
719
+ });
720
+ }
721
+ });
722
+ if (tabs.length === 0) return null;
723
+ return /* @__PURE__ */ jsxs13("div", { className: "cmx-mdx__tabs overflow-hidden", children: [
724
+ /* @__PURE__ */ jsx16("div", { className: "cmx-mdx__tabs-header flex", role: "tablist", children: tabs.map((tab, i) => /* @__PURE__ */ jsx16(
725
+ "button",
726
+ {
727
+ role: "tab",
728
+ "aria-selected": i === activeIndex,
729
+ className: `cmx-mdx__tabs-button ${i === activeIndex ? "cmx-mdx__tabs-button--active" : ""}`,
730
+ onClick: () => setActiveIndex(i),
731
+ children: tab.label
732
+ },
733
+ i
734
+ )) }),
735
+ /* @__PURE__ */ jsx16("div", { className: "cmx-mdx__tabs-content", role: "tabpanel", children: tabs[activeIndex]?.content })
736
+ ] });
737
+ }
738
+ function Tab({ children }) {
739
+ return /* @__PURE__ */ jsx16("div", { className: "cmx-mdx__tab", children });
740
+ }
741
+
742
+ // src/mdx/components/basic/Columns.tsx
743
+ import { jsx as jsx17 } from "react/jsx-runtime";
744
+ var gridClasses = {
745
+ 2: "grid-cols-1 md:grid-cols-2",
746
+ 3: "grid-cols-1 md:grid-cols-3",
747
+ 4: "grid-cols-1 md:grid-cols-2 lg:grid-cols-4"
748
+ };
749
+ function Columns({ cols = 2, children }) {
750
+ const gridClass = gridClasses[cols] || gridClasses[2];
751
+ return /* @__PURE__ */ jsx17("div", { className: `cmx-mdx__columns grid gap-4 ${gridClass}`, children });
752
+ }
753
+ function Column({ children }) {
754
+ return /* @__PURE__ */ jsx17("div", { className: "cmx-mdx__column", children });
755
+ }
756
+
757
+ // src/mdx/components/basic/Audio.tsx
758
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
759
+ function Audio({ src, title }) {
760
+ return /* @__PURE__ */ jsxs14("div", { className: "cmx-mdx__audio", children: [
761
+ title && /* @__PURE__ */ jsx18("p", { className: "cmx-mdx__audio-title", children: title }),
762
+ /* @__PURE__ */ jsx18(
763
+ "audio",
764
+ {
765
+ src,
766
+ controls: true,
767
+ className: "cmx-mdx__audio-player w-full",
768
+ preload: "metadata"
769
+ }
770
+ )
771
+ ] });
772
+ }
773
+
774
+ // src/mdx/components/basic/Video.tsx
775
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
776
+ function Video({ src, title, poster }) {
777
+ return /* @__PURE__ */ jsxs15("div", { className: "cmx-mdx__video", children: [
778
+ title && /* @__PURE__ */ jsx19("p", { className: "cmx-mdx__video-title", children: title }),
779
+ /* @__PURE__ */ jsx19(
780
+ "video",
781
+ {
782
+ src,
783
+ poster,
784
+ controls: true,
785
+ className: "cmx-mdx__video-player w-full",
786
+ preload: "metadata"
787
+ }
788
+ )
789
+ ] });
790
+ }
791
+
792
+ // src/mdx/components/basic/FileDownload.tsx
793
+ import { Download } from "lucide-react";
794
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
795
+ function FileDownload({ url, filename, size }) {
796
+ const displayName = filename || url.split("/").pop() || "\u30D5\u30A1\u30A4\u30EB";
797
+ return /* @__PURE__ */ jsxs16("div", { className: "cmx-mdx__filedownload flex items-center gap-3", children: [
798
+ /* @__PURE__ */ jsx20(Download, { className: "cmx-mdx__filedownload-icon flex-shrink-0" }),
799
+ /* @__PURE__ */ jsxs16("div", { className: "cmx-mdx__filedownload-info flex-1 min-w-0", children: [
800
+ /* @__PURE__ */ jsx20(
801
+ "a",
802
+ {
803
+ href: url,
804
+ download: true,
805
+ className: "cmx-mdx__filedownload-link truncate block",
806
+ children: displayName
807
+ }
808
+ ),
809
+ size && /* @__PURE__ */ jsx20("p", { className: "cmx-mdx__filedownload-size", children: size })
810
+ ] })
811
+ ] });
812
+ }
813
+
814
+ // src/mdx/components/basic/TableOfContents.tsx
815
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
816
+ function TableOfContents({ maxDepth = 3 }) {
817
+ return /* @__PURE__ */ jsxs17(
818
+ "nav",
819
+ {
820
+ className: "cmx-mdx__toc",
821
+ "aria-label": "\u76EE\u6B21",
822
+ "data-max-depth": maxDepth,
823
+ children: [
824
+ /* @__PURE__ */ jsx21("p", { className: "cmx-mdx__toc-title", children: "\u76EE\u6B21" }),
825
+ /* @__PURE__ */ jsx21("p", { className: "cmx-mdx__toc-placeholder", children: "\u76EE\u6B21\u306F\u30EC\u30F3\u30C0\u30EA\u30F3\u30B0\u6642\u306B\u81EA\u52D5\u751F\u6210\u3055\u308C\u307E\u3059" })
826
+ ]
827
+ }
828
+ );
468
829
  }
469
830
 
470
831
  // src/mdx/components/basic/index.ts
471
832
  var basicComponents = {
472
833
  Callout,
834
+ Button,
473
835
  Embed,
474
- Button
836
+ YouTube,
837
+ Twitter,
838
+ Instagram,
839
+ TikTok,
840
+ Bluesky,
841
+ Vimeo,
842
+ Spotify,
843
+ Gist,
844
+ CodePen,
845
+ CodeSandbox,
846
+ GoogleMap,
847
+ Details,
848
+ Tabs,
849
+ Tab,
850
+ Columns,
851
+ Column,
852
+ Audio,
853
+ Video,
854
+ FileDownload,
855
+ TableOfContents
475
856
  };
476
857
 
477
858
  // src/mdx/components/custom/BlogCard.tsx
478
859
  import Link2 from "next/link";
479
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
860
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
480
861
  function BlogCard({ contentId, title, slug, excerpt }) {
481
862
  if (!title || !slug) {
482
- return /* @__PURE__ */ jsx4("div", { className: "border border-dashed border-gray-300 rounded-lg p-4 bg-gray-50", children: /* @__PURE__ */ jsxs3("p", { className: "text-sm text-gray-500", children: [
863
+ return /* @__PURE__ */ jsx22("div", { className: "cmx-mdx__blogcard cmx-mdx__blogcard--unresolved", children: /* @__PURE__ */ jsxs18("p", { className: "cmx-mdx__blogcard-text", children: [
483
864
  "\u8A18\u4E8B\u30AB\u30FC\u30C9: ",
484
865
  contentId
485
866
  ] }) });
486
867
  }
487
- return /* @__PURE__ */ jsxs3(
868
+ return /* @__PURE__ */ jsxs18(
488
869
  Link2,
489
870
  {
490
871
  href: `/${slug}`,
491
- className: "block border border-gray-200 rounded-lg p-4 hover:border-blue-400 hover:shadow-md transition-all",
872
+ className: "cmx-mdx__blogcard-link",
492
873
  children: [
493
- /* @__PURE__ */ jsx4("h3", { className: "text-lg font-semibold text-gray-900 mb-2", children: title }),
494
- excerpt && /* @__PURE__ */ jsx4("p", { className: "text-sm text-gray-600 line-clamp-2", children: excerpt })
874
+ /* @__PURE__ */ jsx22("h3", { className: "cmx-mdx__blogcard-title", children: title }),
875
+ excerpt && /* @__PURE__ */ jsx22("p", { className: "cmx-mdx__blogcard-excerpt line-clamp-2", children: excerpt })
495
876
  ]
496
877
  }
497
878
  );
@@ -499,7 +880,7 @@ function BlogCard({ contentId, title, slug, excerpt }) {
499
880
 
500
881
  // src/mdx/components/custom/Image.tsx
501
882
  import NextImage from "next/image";
502
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
883
+ import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
503
884
  function Image({
504
885
  assetId,
505
886
  alt = "",
@@ -510,62 +891,97 @@ function Image({
510
891
  height
511
892
  }) {
512
893
  if (!url) {
513
- return /* @__PURE__ */ jsxs4("figure", { className: "my-4", children: [
514
- /* @__PURE__ */ jsxs4("div", { className: "border border-dashed border-gray-300 rounded-lg p-8 bg-gray-50 text-center", children: [
515
- /* @__PURE__ */ jsxs4("p", { className: "text-sm text-gray-500", children: [
894
+ return /* @__PURE__ */ jsxs19("figure", { className: "cmx-mdx__image", children: [
895
+ /* @__PURE__ */ jsxs19("div", { className: "cmx-mdx__image--unresolved", children: [
896
+ /* @__PURE__ */ jsxs19("p", { className: "cmx-mdx__image-id", children: [
516
897
  "\u753B\u50CF: ",
517
898
  assetId
518
899
  ] }),
519
- /* @__PURE__ */ jsxs4("p", { className: "text-xs text-gray-400", children: [
900
+ /* @__PURE__ */ jsxs19("p", { className: "cmx-mdx__image-size", children: [
520
901
  "\u30B5\u30A4\u30BA: ",
521
902
  size
522
903
  ] })
523
904
  ] }),
524
- caption && /* @__PURE__ */ jsx5("figcaption", { className: "mt-2 text-sm text-gray-500 text-center", children: caption })
905
+ caption && /* @__PURE__ */ jsx23("figcaption", { className: "cmx-mdx__image-caption", children: caption })
525
906
  ] });
526
907
  }
527
- return /* @__PURE__ */ jsxs4("figure", { className: "my-4", children: [
528
- /* @__PURE__ */ jsx5(
908
+ return /* @__PURE__ */ jsxs19("figure", { className: "cmx-mdx__image", children: [
909
+ /* @__PURE__ */ jsx23(
529
910
  NextImage,
530
911
  {
531
912
  src: url,
532
913
  alt,
533
914
  width: width || 800,
534
915
  height: height || 600,
535
- className: "rounded-lg"
916
+ className: "cmx-mdx__image-img"
536
917
  }
537
918
  ),
538
- caption && /* @__PURE__ */ jsx5("figcaption", { className: "mt-2 text-sm text-gray-500 text-center", children: caption })
919
+ caption && /* @__PURE__ */ jsx23("figcaption", { className: "cmx-mdx__image-caption", children: caption })
920
+ ] });
921
+ }
922
+
923
+ // src/mdx/components/custom/Gallery.tsx
924
+ import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
925
+ var gridClasses2 = {
926
+ 1: "grid-cols-1",
927
+ 2: "grid-cols-1 sm:grid-cols-2",
928
+ 3: "grid-cols-1 sm:grid-cols-2 md:grid-cols-3",
929
+ 4: "grid-cols-2 md:grid-cols-4",
930
+ 5: "grid-cols-2 md:grid-cols-3 lg:grid-cols-5",
931
+ 6: "grid-cols-2 md:grid-cols-3 lg:grid-cols-6"
932
+ };
933
+ function Gallery({ assetIds, columns = 3, caption, images }) {
934
+ const gridClass = gridClasses2[columns] || gridClasses2[3];
935
+ const items = images || assetIds.map((id) => ({ assetId: id }));
936
+ return /* @__PURE__ */ jsxs20("figure", { className: "cmx-mdx__gallery", children: [
937
+ /* @__PURE__ */ jsx24("div", { className: `cmx-mdx__gallery-grid grid gap-2 ${gridClass}`, children: items.map((item, i) => /* @__PURE__ */ jsx24(
938
+ "div",
939
+ {
940
+ className: "cmx-mdx__gallery-item aspect-square overflow-hidden",
941
+ children: item.url ? /* @__PURE__ */ jsx24(
942
+ "img",
943
+ {
944
+ src: item.url,
945
+ alt: item.alt || "",
946
+ className: "cmx-mdx__gallery-image w-full h-full object-cover",
947
+ loading: "lazy"
948
+ }
949
+ ) : /* @__PURE__ */ jsx24("div", { className: "cmx-mdx__gallery-placeholder w-full h-full flex items-center justify-center", children: "\u753B\u50CF" })
950
+ },
951
+ item.assetId || i
952
+ )) }),
953
+ caption && /* @__PURE__ */ jsx24("figcaption", { className: "cmx-mdx__gallery-caption", children: caption })
539
954
  ] });
540
955
  }
541
956
 
542
957
  // src/mdx/components/custom/index.ts
543
958
  var customComponents = {
544
959
  BlogCard,
545
- Image
960
+ Image,
961
+ Gallery
546
962
  };
547
963
 
548
964
  // src/mdx/components/markdown/index.tsx
549
- import { jsx as jsx6 } from "react/jsx-runtime";
550
- var mdxH1 = ({ children, ...props }) => /* @__PURE__ */ jsx6("h1", { className: "text-4xl font-bold mt-8 mb-4", ...props, children });
551
- var mdxH2 = ({ children, ...props }) => /* @__PURE__ */ jsx6("h2", { className: "text-3xl font-bold mt-6 mb-3", ...props, children });
552
- var mdxH3 = ({ children, ...props }) => /* @__PURE__ */ jsx6("h3", { className: "text-2xl font-semibold mt-4 mb-2", ...props, children });
553
- var mdxH4 = ({ children, ...props }) => /* @__PURE__ */ jsx6("h4", { className: "text-xl font-semibold mt-3 mb-2", ...props, children });
554
- var mdxH5 = ({ children, ...props }) => /* @__PURE__ */ jsx6("h5", { className: "text-lg font-medium mt-2 mb-1", ...props, children });
555
- var mdxH6 = ({ children, ...props }) => /* @__PURE__ */ jsx6("h6", { className: "text-base font-medium mt-2 mb-1", ...props, children });
556
- var mdxP = ({ children, ...props }) => /* @__PURE__ */ jsx6("p", { className: "my-4 leading-7", ...props, children });
557
- var mdxUl = ({ children, ...props }) => /* @__PURE__ */ jsx6("ul", { className: "my-4 pl-6 list-disc", ...props, children });
558
- var mdxOl = ({ children, ...props }) => /* @__PURE__ */ jsx6("ol", { className: "my-4 pl-6 list-decimal", ...props, children });
559
- var mdxLi = ({ children, ...props }) => /* @__PURE__ */ jsx6("li", { className: "my-1", ...props, children });
560
- var mdxBlockquote = ({ children, ...props }) => /* @__PURE__ */ jsx6("blockquote", { className: "border-l-4 border-primary pl-4 italic my-4", ...props, children });
561
- var mdxPre = ({ children, ...props }) => /* @__PURE__ */ jsx6("pre", { className: "overflow-x-auto rounded-lg bg-slate-900 p-4 text-sm my-4", ...props, children });
562
- var mdxCode = ({ children, ...props }) => /* @__PURE__ */ jsx6("code", { className: "bg-muted px-1.5 py-0.5 rounded text-sm font-mono", ...props, children });
563
- var mdxHr = () => /* @__PURE__ */ jsx6("hr", { className: "my-8 border-t border-border" });
564
- var mdxA = ({ children, href, ...props }) => /* @__PURE__ */ jsx6(
965
+ import { jsx as jsx25 } from "react/jsx-runtime";
966
+ var mdxH1 = ({ children, ...props }) => /* @__PURE__ */ jsx25("h1", { className: "cmx-mdx__h1", ...props, children });
967
+ var mdxH2 = ({ children, ...props }) => /* @__PURE__ */ jsx25("h2", { className: "cmx-mdx__h2", ...props, children });
968
+ var mdxH3 = ({ children, ...props }) => /* @__PURE__ */ jsx25("h3", { className: "cmx-mdx__h3", ...props, children });
969
+ var mdxH4 = ({ children, ...props }) => /* @__PURE__ */ jsx25("h4", { className: "cmx-mdx__h4", ...props, children });
970
+ var mdxH5 = ({ children, ...props }) => /* @__PURE__ */ jsx25("h5", { className: "cmx-mdx__h5", ...props, children });
971
+ var mdxH6 = ({ children, ...props }) => /* @__PURE__ */ jsx25("h6", { className: "cmx-mdx__h6", ...props, children });
972
+ var mdxP = ({ children, ...props }) => /* @__PURE__ */ jsx25("p", { className: "cmx-mdx__p", ...props, children });
973
+ var mdxUl = ({ children, ...props }) => /* @__PURE__ */ jsx25("ul", { className: "cmx-mdx__ul", ...props, children });
974
+ var mdxOl = ({ children, ...props }) => /* @__PURE__ */ jsx25("ol", { className: "cmx-mdx__ol", ...props, children });
975
+ var mdxLi = ({ children, ...props }) => /* @__PURE__ */ jsx25("li", { className: "cmx-mdx__li", ...props, children });
976
+ var mdxBlockquote = ({ children, ...props }) => /* @__PURE__ */ jsx25("blockquote", { className: "cmx-mdx__blockquote", ...props, children });
977
+ var mdxPre = ({ children, ...props }) => /* @__PURE__ */ jsx25("pre", { className: "cmx-mdx__pre", ...props, children });
978
+ var mdxCode = ({ children, ...props }) => /* @__PURE__ */ jsx25("code", { className: "cmx-mdx__code", ...props, children });
979
+ var mdxHr = () => /* @__PURE__ */ jsx25("hr", { className: "cmx-mdx__hr" });
980
+ var mdxA = ({ children, href, ...props }) => /* @__PURE__ */ jsx25(
565
981
  "a",
566
982
  {
567
983
  href,
568
- className: "text-primary underline underline-offset-4 hover:text-primary/80",
984
+ className: "cmx-mdx__a",
569
985
  target: href?.startsWith("http") ? "_blank" : void 0,
570
986
  rel: href?.startsWith("http") ? "noopener noreferrer" : void 0,
571
987
  ...props,
@@ -574,24 +990,24 @@ var mdxA = ({ children, href, ...props }) => /* @__PURE__ */ jsx6(
574
990
  );
575
991
  var mdxImg = ({ src, alt, ...props }) => (
576
992
  // eslint-disable-next-line @next/next/no-img-element
577
- /* @__PURE__ */ jsx6(
993
+ /* @__PURE__ */ jsx25(
578
994
  "img",
579
995
  {
580
996
  src,
581
997
  alt: alt || "",
582
- className: "max-w-full h-auto rounded-lg my-4",
998
+ className: "cmx-mdx__img",
583
999
  ...props
584
1000
  }
585
1001
  )
586
1002
  );
587
- var mdxStrong = ({ children, ...props }) => /* @__PURE__ */ jsx6("strong", { className: "font-bold", ...props, children });
588
- var mdxEm = ({ children, ...props }) => /* @__PURE__ */ jsx6("em", { className: "italic", ...props, children });
589
- var mdxTable = ({ children, ...props }) => /* @__PURE__ */ jsx6("div", { className: "my-4 overflow-x-auto", children: /* @__PURE__ */ jsx6("table", { className: "min-w-full border-collapse border border-border", ...props, children }) });
590
- var mdxThead = ({ children, ...props }) => /* @__PURE__ */ jsx6("thead", { className: "bg-muted", ...props, children });
591
- var mdxTbody = ({ children, ...props }) => /* @__PURE__ */ jsx6("tbody", { ...props, children });
592
- var mdxTr = ({ children, ...props }) => /* @__PURE__ */ jsx6("tr", { className: "border-b border-border", ...props, children });
593
- var mdxTh = ({ children, ...props }) => /* @__PURE__ */ jsx6("th", { className: "px-4 py-2 text-left font-semibold border border-border", ...props, children });
594
- var mdxTd = ({ children, ...props }) => /* @__PURE__ */ jsx6("td", { className: "px-4 py-2 border border-border", ...props, children });
1003
+ var mdxStrong = ({ children, ...props }) => /* @__PURE__ */ jsx25("strong", { className: "cmx-mdx__strong", ...props, children });
1004
+ var mdxEm = ({ children, ...props }) => /* @__PURE__ */ jsx25("em", { className: "cmx-mdx__em", ...props, children });
1005
+ var mdxTable = ({ children, ...props }) => /* @__PURE__ */ jsx25("div", { className: "cmx-mdx__table-wrapper", children: /* @__PURE__ */ jsx25("table", { className: "cmx-mdx__table", ...props, children }) });
1006
+ var mdxThead = ({ children, ...props }) => /* @__PURE__ */ jsx25("thead", { className: "cmx-mdx__thead", ...props, children });
1007
+ var mdxTbody = ({ children, ...props }) => /* @__PURE__ */ jsx25("tbody", { ...props, children });
1008
+ var mdxTr = ({ children, ...props }) => /* @__PURE__ */ jsx25("tr", { className: "cmx-mdx__tr", ...props, children });
1009
+ var mdxTh = ({ children, ...props }) => /* @__PURE__ */ jsx25("th", { className: "cmx-mdx__th", ...props, children });
1010
+ var mdxTd = ({ children, ...props }) => /* @__PURE__ */ jsx25("td", { className: "cmx-mdx__td", ...props, children });
595
1011
  var markdownComponents = {
596
1012
  h1: mdxH1,
597
1013
  h2: mdxH2,
@@ -629,45 +1045,149 @@ var mdxComponents = {
629
1045
  // src/mdx/component-catalog.ts
630
1046
  import { z } from "zod";
631
1047
  var componentSchemas = {
632
- BlogCard: z.object({
633
- contentId: z.string().uuid().describe("\u53C2\u7167\u5148\u30B3\u30F3\u30C6\u30F3\u30C4\u306EUUID")
1048
+ // --- content ---
1049
+ Callout: z.object({
1050
+ type: z.enum(["info", "warning", "error", "success", "tip"]).default("info").describe("\u30BF\u30A4\u30D7"),
1051
+ title: z.string().optional().describe("\u30BF\u30A4\u30C8\u30EB"),
1052
+ children: z.string().describe("\u672C\u6587\uFF08Markdown\u53EF\uFF09")
634
1053
  }),
1054
+ Button: z.object({
1055
+ href: z.string().describe("\u30EA\u30F3\u30AF\u5148URL"),
1056
+ children: z.string().describe("\u30DC\u30BF\u30F3\u30C6\u30AD\u30B9\u30C8"),
1057
+ variant: z.enum(["primary", "secondary", "outline"]).default("primary").describe("\u30B9\u30BF\u30A4\u30EB")
1058
+ }),
1059
+ // --- media ---
635
1060
  Image: z.object({
636
1061
  assetId: z.string().uuid().describe("\u30A2\u30BB\u30C3\u30C8\u306EUUID"),
637
1062
  alt: z.string().optional().describe("\u4EE3\u66FF\u30C6\u30AD\u30B9\u30C8"),
638
1063
  size: z.enum(["thumbnail", "medium", "large", "original"]).default("large").describe("\u8868\u793A\u30B5\u30A4\u30BA"),
639
1064
  caption: z.string().optional().describe("\u30AD\u30E3\u30D7\u30B7\u30E7\u30F3")
640
1065
  }),
641
- Callout: z.object({
642
- type: z.enum(["info", "warning", "error", "success", "tip"]).default("info").describe("\u30BF\u30A4\u30D7"),
1066
+ Audio: z.object({
1067
+ src: z.string().url().describe("\u97F3\u58F0\u30D5\u30A1\u30A4\u30EBURL"),
1068
+ title: z.string().optional().describe("\u30BF\u30A4\u30C8\u30EB")
1069
+ }),
1070
+ Video: z.object({
1071
+ src: z.string().url().describe("\u52D5\u753B\u30D5\u30A1\u30A4\u30EBURL"),
643
1072
  title: z.string().optional().describe("\u30BF\u30A4\u30C8\u30EB"),
644
- children: z.string().describe("\u672C\u6587\uFF08Markdown\u53EF\uFF09")
1073
+ poster: z.string().url().optional().describe("\u30DD\u30B9\u30BF\u30FC\u753B\u50CFURL")
1074
+ }),
1075
+ Gallery: z.object({
1076
+ assetIds: z.array(z.string().uuid()).describe("\u30A2\u30BB\u30C3\u30C8UUID\u306E\u914D\u5217"),
1077
+ columns: z.number().min(1).max(6).default(3).describe("\u5217\u6570"),
1078
+ caption: z.string().optional().describe("\u30AD\u30E3\u30D7\u30B7\u30E7\u30F3")
1079
+ }),
1080
+ // --- reference ---
1081
+ BlogCard: z.object({
1082
+ contentId: z.string().uuid().describe("\u53C2\u7167\u5148\u30B3\u30F3\u30C6\u30F3\u30C4\u306EUUID")
1083
+ }),
1084
+ // --- embed ---
1085
+ YouTube: z.object({
1086
+ url: z.string().url().describe("YouTube\u52D5\u753BURL"),
1087
+ start: z.number().optional().describe("\u958B\u59CB\u79D2\u6570")
1088
+ }),
1089
+ Twitter: z.object({
1090
+ url: z.string().url().describe("\u30C4\u30A4\u30FC\u30C8URL")
1091
+ }),
1092
+ Instagram: z.object({
1093
+ url: z.string().url().describe("Instagram\u6295\u7A3FURL")
1094
+ }),
1095
+ TikTok: z.object({
1096
+ url: z.string().url().describe("TikTok\u52D5\u753BURL")
1097
+ }),
1098
+ Bluesky: z.object({
1099
+ url: z.string().url().describe("Bluesky\u30DD\u30B9\u30C8URL")
1100
+ }),
1101
+ Vimeo: z.object({
1102
+ url: z.string().url().describe("Vimeo\u52D5\u753BURL")
645
1103
  }),
1104
+ Spotify: z.object({
1105
+ url: z.string().url().describe("Spotify\u30B3\u30F3\u30C6\u30F3\u30C4URL"),
1106
+ theme: z.enum(["light", "dark"]).default("light").describe("\u30C6\u30FC\u30DE")
1107
+ }),
1108
+ Gist: z.object({
1109
+ url: z.string().url().describe("GitHub Gist URL")
1110
+ }),
1111
+ CodePen: z.object({
1112
+ url: z.string().url().describe("CodePen URL"),
1113
+ height: z.number().default(400).describe("\u9AD8\u3055\uFF08px\uFF09"),
1114
+ defaultTab: z.enum(["html", "css", "js", "result"]).default("result").describe("\u30C7\u30D5\u30A9\u30EB\u30C8\u30BF\u30D6")
1115
+ }),
1116
+ CodeSandbox: z.object({
1117
+ url: z.string().url().describe("CodeSandbox URL"),
1118
+ height: z.number().default(500).describe("\u9AD8\u3055\uFF08px\uFF09")
1119
+ }),
1120
+ GoogleMap: z.object({
1121
+ url: z.string().url().describe("Google Maps URL"),
1122
+ height: z.number().default(450).describe("\u9AD8\u3055\uFF08px\uFF09")
1123
+ }),
1124
+ // --- layout ---
1125
+ Details: z.object({
1126
+ summary: z.string().describe("\u6298\u308A\u305F\u305F\u307F\u306E\u898B\u51FA\u3057"),
1127
+ children: z.string().describe("\u6298\u308A\u305F\u305F\u307E\u308C\u308B\u5185\u5BB9")
1128
+ }),
1129
+ Tabs: z.object({
1130
+ children: z.string().describe("Tab\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u306E\u4E26\u3073")
1131
+ }),
1132
+ Tab: z.object({
1133
+ label: z.string().describe("\u30BF\u30D6\u306E\u30E9\u30D9\u30EB"),
1134
+ children: z.string().describe("\u30BF\u30D6\u306E\u5185\u5BB9")
1135
+ }),
1136
+ Columns: z.object({
1137
+ cols: z.number().min(2).max(4).default(2).describe("\u5217\u6570"),
1138
+ children: z.string().describe("Column\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u306E\u4E26\u3073")
1139
+ }),
1140
+ Column: z.object({
1141
+ children: z.string().describe("\u30AB\u30E9\u30E0\u306E\u5185\u5BB9")
1142
+ }),
1143
+ // --- utility ---
646
1144
  Embed: z.object({
647
- url: z.string().url().describe("\u57CB\u3081\u8FBC\u307FURL"),
648
- type: z.enum(["youtube", "twitter", "generic"]).default("generic").describe("\u30BF\u30A4\u30D7")
1145
+ url: z.string().url().describe("\u57CB\u3081\u8FBC\u307FURL")
649
1146
  }),
650
- Button: z.object({
651
- href: z.string().describe("\u30EA\u30F3\u30AF\u5148URL"),
652
- children: z.string().describe("\u30DC\u30BF\u30F3\u30C6\u30AD\u30B9\u30C8"),
653
- variant: z.enum(["primary", "secondary", "outline"]).default("primary").describe("\u30B9\u30BF\u30A4\u30EB")
1147
+ FileDownload: z.object({
1148
+ url: z.string().url().describe("\u30D5\u30A1\u30A4\u30EBURL"),
1149
+ filename: z.string().optional().describe("\u8868\u793A\u30D5\u30A1\u30A4\u30EB\u540D"),
1150
+ size: z.string().optional().describe("\u30D5\u30A1\u30A4\u30EB\u30B5\u30A4\u30BA\u8868\u793A")
1151
+ }),
1152
+ TableOfContents: z.object({
1153
+ maxDepth: z.number().min(1).max(6).default(3).describe("\u898B\u51FA\u3057\u306E\u6700\u5927\u6DF1\u3055")
654
1154
  })
655
1155
  };
656
1156
  var componentCatalog = {
657
- BlogCard: {
658
- name: "BlogCard",
659
- displayName: "\u8A18\u4E8B\u30AB\u30FC\u30C9",
660
- description: "\u4ED6\u306E\u8A18\u4E8B\u3078\u306E\u30EA\u30F3\u30AF\u30AB\u30FC\u30C9\u3092\u8868\u793A\u3057\u307E\u3059",
661
- category: "reference",
662
- schema: componentSchemas.BlogCard,
663
- examples: ['<BlogCard contentId="123e4567-e89b-12d3-a456-426614174000" />'],
664
- hasReferences: true,
1157
+ // --- content ---
1158
+ Callout: {
1159
+ name: "Callout",
1160
+ displayName: "\u30B3\u30FC\u30EB\u30A2\u30A6\u30C8",
1161
+ description: "\u6CE8\u610F\u66F8\u304D\u3084\u88DC\u8DB3\u60C5\u5831\u3092\u76EE\u7ACB\u305F\u305B\u308B\u30DC\u30C3\u30AF\u30B9",
1162
+ category: "content",
1163
+ schema: componentSchemas.Callout,
1164
+ examples: [
1165
+ '<Callout type="info">\u3053\u308C\u306F\u60C5\u5831\u3067\u3059</Callout>',
1166
+ '<Callout type="warning" title="\u6CE8\u610F">\u91CD\u8981\u306A\u6CE8\u610F\u4E8B\u9805\u3067\u3059</Callout>'
1167
+ ],
1168
+ hasReferences: false,
665
1169
  source: "standard",
666
- kind: "data-bound",
1170
+ kind: "presentational",
667
1171
  locked: true,
668
- editable: false,
669
- bindings: [{ prop: "contentId", target: "content", strategy: "by-id" }]
1172
+ editable: false
670
1173
  },
1174
+ Button: {
1175
+ name: "Button",
1176
+ displayName: "\u30DC\u30BF\u30F3",
1177
+ description: "\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u4FC3\u3059\u30DC\u30BF\u30F3\u30EA\u30F3\u30AF",
1178
+ category: "content",
1179
+ schema: componentSchemas.Button,
1180
+ examples: [
1181
+ '<Button href="/contact">\u304A\u554F\u3044\u5408\u308F\u305B</Button>',
1182
+ '<Button href="https://example.com" variant="secondary">\u8A73\u7D30\u3092\u898B\u308B</Button>'
1183
+ ],
1184
+ hasReferences: false,
1185
+ source: "standard",
1186
+ kind: "presentational",
1187
+ locked: true,
1188
+ editable: false
1189
+ },
1190
+ // --- media ---
671
1191
  Image: {
672
1192
  name: "Image",
673
1193
  displayName: "\u753B\u50CF",
@@ -685,31 +1205,74 @@ var componentCatalog = {
685
1205
  editable: false,
686
1206
  bindings: [{ prop: "assetId", target: "asset", strategy: "by-id" }]
687
1207
  },
688
- Callout: {
689
- name: "Callout",
690
- displayName: "\u30B3\u30FC\u30EB\u30A2\u30A6\u30C8",
691
- description: "\u6CE8\u610F\u66F8\u304D\u3084\u88DC\u8DB3\u60C5\u5831\u3092\u76EE\u7ACB\u305F\u305B\u308B\u30DC\u30C3\u30AF\u30B9",
692
- category: "content",
693
- schema: componentSchemas.Callout,
694
- examples: [
695
- '<Callout type="info">\u3053\u308C\u306F\u60C5\u5831\u3067\u3059</Callout>',
696
- '<Callout type="warning" title="\u6CE8\u610F">\u91CD\u8981\u306A\u6CE8\u610F\u4E8B\u9805\u3067\u3059</Callout>'
697
- ],
1208
+ Audio: {
1209
+ name: "Audio",
1210
+ displayName: "\u97F3\u58F0\u30D7\u30EC\u30A4\u30E4\u30FC",
1211
+ description: "\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u3092\u518D\u751F\u3059\u308B\u30D7\u30EC\u30A4\u30E4\u30FC",
1212
+ category: "media",
1213
+ schema: componentSchemas.Audio,
1214
+ examples: ['<Audio src="https://example.com/podcast.mp3" title="\u30A8\u30D4\u30BD\u30FC\u30C91" />'],
698
1215
  hasReferences: false,
699
1216
  source: "standard",
700
1217
  kind: "presentational",
701
1218
  locked: true,
702
1219
  editable: false
703
1220
  },
704
- Embed: {
705
- name: "Embed",
706
- displayName: "\u57CB\u3081\u8FBC\u307F",
707
- description: "YouTube\u52D5\u753B\u3084\u30C4\u30A4\u30FC\u30C8\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1221
+ Video: {
1222
+ name: "Video",
1223
+ displayName: "\u52D5\u753B\u30D7\u30EC\u30A4\u30E4\u30FC",
1224
+ description: "\u30BB\u30EB\u30D5\u30DB\u30B9\u30C8\u52D5\u753B\u3092\u518D\u751F\u3059\u308B\u30D7\u30EC\u30A4\u30E4\u30FC",
708
1225
  category: "media",
709
- schema: componentSchemas.Embed,
1226
+ schema: componentSchemas.Video,
1227
+ examples: ['<Video src="https://example.com/video.mp4" poster="https://example.com/thumb.jpg" />'],
1228
+ hasReferences: false,
1229
+ source: "standard",
1230
+ kind: "presentational",
1231
+ locked: true,
1232
+ editable: false
1233
+ },
1234
+ Gallery: {
1235
+ name: "Gallery",
1236
+ displayName: "\u753B\u50CF\u30AE\u30E3\u30E9\u30EA\u30FC",
1237
+ description: "\u8907\u6570\u306E\u753B\u50CF\u3092\u30B0\u30EA\u30C3\u30C9\u30EC\u30A4\u30A2\u30A6\u30C8\u3067\u8868\u793A\u3057\u307E\u3059",
1238
+ category: "media",
1239
+ schema: componentSchemas.Gallery,
1240
+ examples: [
1241
+ '<Gallery assetIds={["uuid1", "uuid2", "uuid3"]} />',
1242
+ '<Gallery assetIds={["uuid1", "uuid2"]} columns={2} caption="\u5199\u771F\u96C6" />'
1243
+ ],
1244
+ hasReferences: true,
1245
+ source: "standard",
1246
+ kind: "data-bound",
1247
+ locked: true,
1248
+ editable: false,
1249
+ bindings: [{ prop: "assetIds", target: "asset", strategy: "by-id" }]
1250
+ },
1251
+ // --- reference ---
1252
+ BlogCard: {
1253
+ name: "BlogCard",
1254
+ displayName: "\u8A18\u4E8B\u30AB\u30FC\u30C9",
1255
+ description: "\u4ED6\u306E\u8A18\u4E8B\u3078\u306E\u30EA\u30F3\u30AF\u30AB\u30FC\u30C9\u3092\u8868\u793A\u3057\u307E\u3059",
1256
+ category: "reference",
1257
+ schema: componentSchemas.BlogCard,
1258
+ examples: ['<BlogCard contentId="123e4567-e89b-12d3-a456-426614174000" />'],
1259
+ hasReferences: true,
1260
+ source: "standard",
1261
+ kind: "data-bound",
1262
+ locked: true,
1263
+ editable: false,
1264
+ bindings: [{ prop: "contentId", target: "content", strategy: "by-id" }]
1265
+ },
1266
+ // --- embed ---
1267
+ YouTube: {
1268
+ name: "YouTube",
1269
+ displayName: "YouTube",
1270
+ description: "YouTube\u52D5\u753B\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1271
+ category: "embed",
1272
+ schema: componentSchemas.YouTube,
710
1273
  examples: [
711
- '<Embed url="https://www.youtube.com/watch?v=dQw4w9WgXcQ" type="youtube" />',
712
- '<Embed url="https://twitter.com/example/status/123456789" type="twitter" />'
1274
+ '<YouTube url="https://www.youtube.com/watch?v=dQw4w9WgXcQ" />',
1275
+ '<YouTube url="https://youtu.be/dQw4w9WgXcQ" start={30} />'
713
1276
  ],
714
1277
  hasReferences: false,
715
1278
  source: "standard",
@@ -717,23 +1280,252 @@ var componentCatalog = {
717
1280
  locked: true,
718
1281
  editable: false
719
1282
  },
720
- Button: {
721
- name: "Button",
722
- displayName: "\u30DC\u30BF\u30F3",
723
- description: "\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u4FC3\u3059\u30DC\u30BF\u30F3\u30EA\u30F3\u30AF",
724
- category: "content",
725
- schema: componentSchemas.Button,
1283
+ Twitter: {
1284
+ name: "Twitter",
1285
+ displayName: "Twitter / X",
1286
+ description: "\u30C4\u30A4\u30FC\u30C8\u30FB\u30DD\u30B9\u30C8\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1287
+ category: "embed",
1288
+ schema: componentSchemas.Twitter,
1289
+ examples: ['<Twitter url="https://twitter.com/example/status/123456789" />'],
1290
+ hasReferences: false,
1291
+ source: "standard",
1292
+ kind: "presentational",
1293
+ locked: true,
1294
+ editable: false
1295
+ },
1296
+ Instagram: {
1297
+ name: "Instagram",
1298
+ displayName: "Instagram",
1299
+ description: "Instagram\u6295\u7A3F\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1300
+ category: "embed",
1301
+ schema: componentSchemas.Instagram,
1302
+ examples: ['<Instagram url="https://www.instagram.com/p/ABC123/" />'],
1303
+ hasReferences: false,
1304
+ source: "standard",
1305
+ kind: "presentational",
1306
+ locked: true,
1307
+ editable: false
1308
+ },
1309
+ TikTok: {
1310
+ name: "TikTok",
1311
+ displayName: "TikTok",
1312
+ description: "TikTok\u52D5\u753B\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1313
+ category: "embed",
1314
+ schema: componentSchemas.TikTok,
1315
+ examples: ['<TikTok url="https://www.tiktok.com/@user/video/123456789" />'],
1316
+ hasReferences: false,
1317
+ source: "standard",
1318
+ kind: "presentational",
1319
+ locked: true,
1320
+ editable: false
1321
+ },
1322
+ Bluesky: {
1323
+ name: "Bluesky",
1324
+ displayName: "Bluesky",
1325
+ description: "Bluesky\u30DD\u30B9\u30C8\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1326
+ category: "embed",
1327
+ schema: componentSchemas.Bluesky,
1328
+ examples: ['<Bluesky url="https://bsky.app/profile/user.bsky.social/post/abc123" />'],
1329
+ hasReferences: false,
1330
+ source: "standard",
1331
+ kind: "presentational",
1332
+ locked: true,
1333
+ editable: false
1334
+ },
1335
+ Vimeo: {
1336
+ name: "Vimeo",
1337
+ displayName: "Vimeo",
1338
+ description: "Vimeo\u52D5\u753B\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1339
+ category: "embed",
1340
+ schema: componentSchemas.Vimeo,
1341
+ examples: ['<Vimeo url="https://vimeo.com/123456789" />'],
1342
+ hasReferences: false,
1343
+ source: "standard",
1344
+ kind: "presentational",
1345
+ locked: true,
1346
+ editable: false
1347
+ },
1348
+ Spotify: {
1349
+ name: "Spotify",
1350
+ displayName: "Spotify",
1351
+ description: "Spotify\u697D\u66F2\u30FB\u30D7\u30EC\u30A4\u30EA\u30B9\u30C8\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1352
+ category: "embed",
1353
+ schema: componentSchemas.Spotify,
726
1354
  examples: [
727
- '<Button href="/contact">\u304A\u554F\u3044\u5408\u308F\u305B</Button>',
728
- '<Button href="https://example.com" variant="secondary">\u8A73\u7D30\u3092\u898B\u308B</Button>'
1355
+ '<Spotify url="https://open.spotify.com/track/xxx" />',
1356
+ '<Spotify url="https://open.spotify.com/playlist/xxx" theme="dark" />'
729
1357
  ],
730
1358
  hasReferences: false,
731
1359
  source: "standard",
732
1360
  kind: "presentational",
733
1361
  locked: true,
734
1362
  editable: false
1363
+ },
1364
+ Gist: {
1365
+ name: "Gist",
1366
+ displayName: "GitHub Gist",
1367
+ description: "GitHub Gist\u306E\u30B3\u30FC\u30C9\u30B9\u30CB\u30DA\u30C3\u30C8\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1368
+ category: "embed",
1369
+ schema: componentSchemas.Gist,
1370
+ examples: ['<Gist url="https://gist.github.com/user/abc123" />'],
1371
+ hasReferences: false,
1372
+ source: "standard",
1373
+ kind: "presentational",
1374
+ locked: true,
1375
+ editable: false
1376
+ },
1377
+ CodePen: {
1378
+ name: "CodePen",
1379
+ displayName: "CodePen",
1380
+ description: "CodePen\u306E\u30E9\u30A4\u30D6\u30C7\u30E2\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1381
+ category: "embed",
1382
+ schema: componentSchemas.CodePen,
1383
+ examples: ['<CodePen url="https://codepen.io/user/pen/abc123" height={500} defaultTab="result" />'],
1384
+ hasReferences: false,
1385
+ source: "standard",
1386
+ kind: "presentational",
1387
+ locked: true,
1388
+ editable: false
1389
+ },
1390
+ CodeSandbox: {
1391
+ name: "CodeSandbox",
1392
+ displayName: "CodeSandbox",
1393
+ description: "CodeSandbox\u306E\u30E9\u30A4\u30D6\u30C7\u30E2\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1394
+ category: "embed",
1395
+ schema: componentSchemas.CodeSandbox,
1396
+ examples: ['<CodeSandbox url="https://codesandbox.io/s/abc123" height={500} />'],
1397
+ hasReferences: false,
1398
+ source: "standard",
1399
+ kind: "presentational",
1400
+ locked: true,
1401
+ editable: false
1402
+ },
1403
+ GoogleMap: {
1404
+ name: "GoogleMap",
1405
+ displayName: "Google Maps",
1406
+ description: "Google Maps\u306E\u5730\u56F3\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1407
+ category: "embed",
1408
+ schema: componentSchemas.GoogleMap,
1409
+ examples: ['<GoogleMap url="https://www.google.com/maps/embed?pb=..." height={400} />'],
1410
+ hasReferences: false,
1411
+ source: "standard",
1412
+ kind: "presentational",
1413
+ locked: true,
1414
+ editable: false
1415
+ },
1416
+ // --- layout ---
1417
+ Details: {
1418
+ name: "Details",
1419
+ displayName: "\u6298\u308A\u305F\u305F\u307F",
1420
+ description: "\u30AF\u30EA\u30C3\u30AF\u3067\u5C55\u958B\u30FB\u6298\u308A\u305F\u305F\u307F\u53EF\u80FD\u306A\u30BB\u30AF\u30B7\u30E7\u30F3",
1421
+ category: "layout",
1422
+ schema: componentSchemas.Details,
1423
+ examples: ['<Details summary="\u8A73\u7D30\u3092\u898B\u308B">\u6298\u308A\u305F\u305F\u307E\u308C\u305F\u5185\u5BB9</Details>'],
1424
+ hasReferences: false,
1425
+ source: "standard",
1426
+ kind: "presentational",
1427
+ locked: true,
1428
+ editable: false
1429
+ },
1430
+ Tabs: {
1431
+ name: "Tabs",
1432
+ displayName: "\u30BF\u30D6",
1433
+ description: "\u30BF\u30D6\u3067\u5207\u308A\u66FF\u3048\u53EF\u80FD\u306A\u30B3\u30F3\u30C6\u30F3\u30C4",
1434
+ category: "layout",
1435
+ schema: componentSchemas.Tabs,
1436
+ examples: ['<Tabs><Tab label="\u30BF\u30D61">\u5185\u5BB91</Tab><Tab label="\u30BF\u30D62">\u5185\u5BB92</Tab></Tabs>'],
1437
+ hasReferences: false,
1438
+ source: "standard",
1439
+ kind: "presentational",
1440
+ locked: true,
1441
+ editable: false
1442
+ },
1443
+ Tab: {
1444
+ name: "Tab",
1445
+ displayName: "\u30BF\u30D6\uFF08\u5B50\uFF09",
1446
+ description: "Tabs\u306E\u5B50\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8",
1447
+ category: "layout",
1448
+ schema: componentSchemas.Tab,
1449
+ examples: ['<Tab label="\u30BF\u30D6\u540D">\u5185\u5BB9</Tab>'],
1450
+ hasReferences: false,
1451
+ source: "standard",
1452
+ kind: "presentational",
1453
+ locked: true,
1454
+ editable: false,
1455
+ parentComponent: "Tabs"
1456
+ },
1457
+ Columns: {
1458
+ name: "Columns",
1459
+ displayName: "\u30AB\u30E9\u30E0",
1460
+ description: "\u30DE\u30EB\u30C1\u30AB\u30E9\u30E0\u30EC\u30A4\u30A2\u30A6\u30C8",
1461
+ category: "layout",
1462
+ schema: componentSchemas.Columns,
1463
+ examples: ["<Columns cols={2}><Column>\u5DE6</Column><Column>\u53F3</Column></Columns>"],
1464
+ hasReferences: false,
1465
+ source: "standard",
1466
+ kind: "presentational",
1467
+ locked: true,
1468
+ editable: false
1469
+ },
1470
+ Column: {
1471
+ name: "Column",
1472
+ displayName: "\u30AB\u30E9\u30E0\uFF08\u5B50\uFF09",
1473
+ description: "Columns\u306E\u5B50\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8",
1474
+ category: "layout",
1475
+ schema: componentSchemas.Column,
1476
+ examples: ["<Column>\u30AB\u30E9\u30E0\u306E\u5185\u5BB9</Column>"],
1477
+ hasReferences: false,
1478
+ source: "standard",
1479
+ kind: "presentational",
1480
+ locked: true,
1481
+ editable: false,
1482
+ parentComponent: "Columns"
1483
+ },
1484
+ // --- utility ---
1485
+ Embed: {
1486
+ name: "Embed",
1487
+ displayName: "\u6C4E\u7528\u57CB\u3081\u8FBC\u307F",
1488
+ description: "\u6C4E\u7528iframe\u3067\u5916\u90E8\u30B3\u30F3\u30C6\u30F3\u30C4\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1489
+ category: "utility",
1490
+ schema: componentSchemas.Embed,
1491
+ examples: ['<Embed url="https://example.com/widget" />'],
1492
+ hasReferences: false,
1493
+ source: "standard",
1494
+ kind: "presentational",
1495
+ locked: true,
1496
+ editable: false
1497
+ },
1498
+ FileDownload: {
1499
+ name: "FileDownload",
1500
+ displayName: "\u30D5\u30A1\u30A4\u30EB\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9",
1501
+ description: "\u30D5\u30A1\u30A4\u30EB\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u30EA\u30F3\u30AF\u3092\u8868\u793A\u3057\u307E\u3059",
1502
+ category: "utility",
1503
+ schema: componentSchemas.FileDownload,
1504
+ examples: ['<FileDownload url="https://example.com/doc.pdf" filename="\u8CC7\u6599.pdf" size="2.4MB" />'],
1505
+ hasReferences: false,
1506
+ source: "standard",
1507
+ kind: "presentational",
1508
+ locked: true,
1509
+ editable: false
1510
+ },
1511
+ TableOfContents: {
1512
+ name: "TableOfContents",
1513
+ displayName: "\u76EE\u6B21",
1514
+ description: "\u8A18\u4E8B\u5185\u306E\u898B\u51FA\u3057\u304B\u3089\u76EE\u6B21\u3092\u81EA\u52D5\u751F\u6210\u3057\u307E\u3059",
1515
+ category: "utility",
1516
+ schema: componentSchemas.TableOfContents,
1517
+ examples: ["<TableOfContents />", "<TableOfContents maxDepth={2} />"],
1518
+ hasReferences: false,
1519
+ source: "standard",
1520
+ kind: "presentational",
1521
+ locked: true,
1522
+ editable: false
735
1523
  }
736
1524
  };
1525
+ var CHILD_COMPONENT_MAP = {
1526
+ Tab: "Tabs",
1527
+ Column: "Columns"
1528
+ };
737
1529
  function isValidComponent(name) {
738
1530
  return name in componentCatalog;
739
1531
  }
@@ -760,8 +1552,12 @@ function getComponentsByCategory() {
760
1552
  }
761
1553
  return grouped;
762
1554
  }
763
- function getCatalogForAI() {
764
- return Object.values(componentCatalog).map((def) => {
1555
+ function getCatalogForAI(enabledComponents) {
1556
+ let entries = Object.values(componentCatalog);
1557
+ if (enabledComponents) {
1558
+ entries = entries.filter((def) => enabledComponents.includes(def.name));
1559
+ }
1560
+ return entries.map((def) => {
765
1561
  const shape = def.schema.shape;
766
1562
  const props = {};
767
1563
  for (const [key, zodType] of Object.entries(shape)) {
@@ -781,7 +1577,8 @@ function getCatalogForAI() {
781
1577
  kind: def.kind,
782
1578
  locked: def.locked,
783
1579
  editable: def.editable,
784
- bindings: def.bindings
1580
+ bindings: def.bindings,
1581
+ parentComponent: def.parentComponent
785
1582
  };
786
1583
  });
787
1584
  }
@@ -818,6 +1615,7 @@ function getZodTypeName(zodType) {
818
1615
 
819
1616
  // src/mdx/validator.ts
820
1617
  import { compile } from "@mdx-js/mdx";
1618
+ import remarkGfm from "remark-gfm";
821
1619
  var FORBIDDEN_PATTERNS = [
822
1620
  // import/export statements (at MDX level, not inside code blocks)
823
1621
  { pattern: /^\s*import\s+/m, message: "import\u6587\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093" },
@@ -996,13 +1794,18 @@ function extractReferences(components) {
996
1794
  if (component.name === "Image" && typeof component.props.assetId === "string") {
997
1795
  assetIds.push(component.props.assetId);
998
1796
  }
1797
+ if (component.name === "Gallery" && Array.isArray(component.props.assetIds)) {
1798
+ for (const id of component.props.assetIds) {
1799
+ if (typeof id === "string") assetIds.push(id);
1800
+ }
1801
+ }
999
1802
  }
1000
1803
  return {
1001
1804
  contentIds: [...new Set(contentIds)],
1002
1805
  assetIds: [...new Set(assetIds)]
1003
1806
  };
1004
1807
  }
1005
- async function validateMdx(mdx) {
1808
+ async function validateMdx(mdx, options) {
1006
1809
  const errors = [];
1007
1810
  const warnings = [];
1008
1811
  const mdxWithoutCodeBlocks = stripCodeBlocksForPatternCheck(mdx);
@@ -1024,7 +1827,8 @@ async function validateMdx(mdx) {
1024
1827
  const escapedMdx = escapeCodeBlocksForCompile(mdx);
1025
1828
  try {
1026
1829
  await compile(escapedMdx, {
1027
- development: false
1830
+ development: false,
1831
+ remarkPlugins: [remarkGfm]
1028
1832
  });
1029
1833
  } catch (error) {
1030
1834
  const err = error;
@@ -1037,6 +1841,7 @@ async function validateMdx(mdx) {
1037
1841
  }
1038
1842
  const mdxForComponentExtraction = stripCodeBlocksForPatternCheck(mdx);
1039
1843
  const components = extractComponents(mdxForComponentExtraction);
1844
+ const enabledSet = options?.enabledComponents ? new Set(options.enabledComponents) : void 0;
1040
1845
  for (const component of components) {
1041
1846
  if (!isValidComponent(component.name)) {
1042
1847
  errors.push({
@@ -1047,6 +1852,27 @@ async function validateMdx(mdx) {
1047
1852
  });
1048
1853
  continue;
1049
1854
  }
1855
+ if (enabledSet && !enabledSet.has(component.name)) {
1856
+ errors.push({
1857
+ type: "component",
1858
+ message: `\u7121\u52B9\u306A\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8: ${component.name}\uFF08\u3053\u306E\u74B0\u5883\u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\uFF09`,
1859
+ line: component.line,
1860
+ component: component.name
1861
+ });
1862
+ continue;
1863
+ }
1864
+ const parentName = CHILD_COMPONENT_MAP[component.name];
1865
+ if (parentName) {
1866
+ const hasParent = components.some((c) => c.name === parentName);
1867
+ if (!hasParent) {
1868
+ errors.push({
1869
+ type: "component",
1870
+ message: `${component.name} \u306F ${parentName} \u306E\u4E2D\u3067\u4F7F\u7528\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059`,
1871
+ line: component.line,
1872
+ component: component.name
1873
+ });
1874
+ }
1875
+ }
1050
1876
  const result = validateComponentProps(component.name, component.props);
1051
1877
  if (!result.success) {
1052
1878
  for (const issue of result.error.issues) {
@@ -1086,8 +1912,9 @@ function quickValidateMdx(mdx) {
1086
1912
 
1087
1913
  // src/render.tsx
1088
1914
  import { compile as compile2, run } from "@mdx-js/mdx";
1915
+ import remarkGfm2 from "remark-gfm";
1089
1916
  import * as runtime from "react/jsx-runtime";
1090
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1917
+ import { jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
1091
1918
  function convertReferencesToMaps(refs) {
1092
1919
  const contentsMap = /* @__PURE__ */ new Map();
1093
1920
  const assetsMap = /* @__PURE__ */ new Map();
@@ -1110,7 +1937,7 @@ function createResolvedComponents(references, additionalComponents) {
1110
1937
  // Custom components with reference resolution
1111
1938
  BlogCard: (props) => {
1112
1939
  const ref = references.contents.get(props.contentId);
1113
- return /* @__PURE__ */ jsx7(
1940
+ return /* @__PURE__ */ jsx26(
1114
1941
  BlogCard,
1115
1942
  {
1116
1943
  contentId: props.contentId,
@@ -1127,7 +1954,7 @@ function createResolvedComponents(references, additionalComponents) {
1127
1954
  if (asset?.variants && size !== "original") {
1128
1955
  url = asset.variants[size] || asset.url;
1129
1956
  }
1130
- return /* @__PURE__ */ jsx7(
1957
+ return /* @__PURE__ */ jsx26(
1131
1958
  Image,
1132
1959
  {
1133
1960
  assetId: props.assetId,
@@ -1140,10 +1967,42 @@ function createResolvedComponents(references, additionalComponents) {
1140
1967
  }
1141
1968
  );
1142
1969
  },
1970
+ // Gallery with reference resolution
1971
+ Gallery: (props) => {
1972
+ const images = props.assetIds.map((id) => {
1973
+ const asset = references.assets.get(id);
1974
+ return {
1975
+ assetId: id,
1976
+ url: asset?.url,
1977
+ alt: asset?.alt ?? void 0
1978
+ };
1979
+ });
1980
+ return /* @__PURE__ */ jsx26(Gallery, { assetIds: props.assetIds, columns: props.columns, caption: props.caption, images });
1981
+ },
1143
1982
  // Components without resolution
1144
1983
  Callout,
1145
1984
  Embed,
1146
1985
  Button,
1986
+ YouTube,
1987
+ Twitter,
1988
+ Instagram,
1989
+ TikTok,
1990
+ Bluesky,
1991
+ Vimeo,
1992
+ Spotify,
1993
+ Gist,
1994
+ CodePen,
1995
+ CodeSandbox,
1996
+ GoogleMap,
1997
+ Details,
1998
+ Tabs,
1999
+ Tab,
2000
+ Columns,
2001
+ Column,
2002
+ Audio,
2003
+ Video,
2004
+ FileDownload,
2005
+ TableOfContents,
1147
2006
  // User-provided custom components
1148
2007
  ...additionalComponents
1149
2008
  };
@@ -1181,13 +2040,14 @@ async function renderMdx(mdx, references, options) {
1181
2040
  const components = createResolvedComponents(resolvedReferences, options?.additionalComponents);
1182
2041
  const code = await compile2(mdx, {
1183
2042
  outputFormat: "function-body",
1184
- development: false
2043
+ development: false,
2044
+ remarkPlugins: [remarkGfm2]
1185
2045
  });
1186
2046
  const { default: MDXContent } = await run(String(code), {
1187
2047
  ...runtime,
1188
2048
  baseUrl: import.meta.url
1189
2049
  });
1190
- const content = /* @__PURE__ */ jsx7(MDXContent, { components });
2050
+ const content = /* @__PURE__ */ jsx26(MDXContent, { components });
1191
2051
  return {
1192
2052
  content,
1193
2053
  references: resolvedReferences
@@ -1198,27 +2058,49 @@ async function renderMdxPreview(mdx, additionalComponents) {
1198
2058
  ...markdownComponents,
1199
2059
  BlogCard,
1200
2060
  Image,
2061
+ Gallery,
1201
2062
  Callout,
1202
2063
  Embed,
1203
2064
  Button,
2065
+ YouTube,
2066
+ Twitter,
2067
+ Instagram,
2068
+ TikTok,
2069
+ Bluesky,
2070
+ Vimeo,
2071
+ Spotify,
2072
+ Gist,
2073
+ CodePen,
2074
+ CodeSandbox,
2075
+ GoogleMap,
2076
+ Details,
2077
+ Tabs,
2078
+ Tab,
2079
+ Columns,
2080
+ Column,
2081
+ Audio,
2082
+ Video,
2083
+ FileDownload,
2084
+ TableOfContents,
1204
2085
  ...additionalComponents
1205
2086
  };
1206
2087
  try {
1207
2088
  validateMdx2(mdx);
1208
2089
  const code = await compile2(mdx, {
1209
2090
  outputFormat: "function-body",
1210
- development: false
2091
+ development: false,
2092
+ remarkPlugins: [remarkGfm2]
1211
2093
  });
1212
2094
  const { default: MDXContent } = await run(String(code), {
1213
2095
  ...runtime,
1214
2096
  baseUrl: import.meta.url
1215
2097
  });
1216
- return /* @__PURE__ */ jsx7(MDXContent, { components });
2098
+ return /* @__PURE__ */ jsx26(MDXContent, { components });
1217
2099
  } catch (error) {
1218
2100
  console.error("MDX render error:", error);
1219
- return /* @__PURE__ */ jsxs5("div", { className: "p-4 bg-red-50 border border-red-200 rounded-lg", children: [
1220
- /* @__PURE__ */ jsx7("p", { className: "text-red-600 font-medium", children: "MDX Render Error" }),
1221
- /* @__PURE__ */ jsx7("pre", { className: "mt-2 text-sm text-red-500 whitespace-pre-wrap", children: error instanceof Error ? error.message : "Unknown error" })
2101
+ return /* @__PURE__ */ jsxs21("div", { className: "p-4 bg-red-50 border border-red-200 rounded-lg", children: [
2102
+ /* @__PURE__ */ jsx26("p", { className: "text-red-600 font-medium", children: "MDX Render Error" }),
2103
+ /* @__PURE__ */ jsx26("pre", { className: "mt-2 text-sm text-red-500 whitespace-pre-wrap", children: error instanceof Error ? error.message : "Unknown error" })
1222
2104
  ] });
1223
2105
  }
1224
2106
  }