promptslide 0.3.6 → 0.3.8

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
@@ -666,8 +666,505 @@ function SlideEmbed({ slides, transition, directionalTransition }) {
666
666
 
667
667
  // src/core/slide-deck.tsx
668
668
  import { LayoutGroup } from "framer-motion";
669
- import { ChevronLeft, ChevronRight, Download, Grid3X3, List, Maximize, Monitor } from "lucide-react";
670
- import { useCallback as useCallback3, useEffect as useEffect3, useRef, useState as useState3 } from "react";
669
+ import { ChevronLeft, ChevronRight, Download, Grid3X3, List, Maximize, MessageCircle as MessageCircle2, Monitor } from "lucide-react";
670
+ import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo4, useRef as useRef4, useState as useState6 } from "react";
671
+
672
+ // src/core/annotations/annotation-overlay.tsx
673
+ import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef2, useState as useState4 } from "react";
674
+
675
+ // src/core/annotations/annotation-form.tsx
676
+ import { useEffect as useEffect3, useRef, useState as useState3 } from "react";
677
+ import { ArrowUp, X } from "lucide-react";
678
+ import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
679
+ function AnnotationForm({ xPercent, yPercent, onSubmit, onCancel }) {
680
+ const [text, setText] = useState3("");
681
+ const textareaRef = useRef(null);
682
+ useEffect3(() => {
683
+ textareaRef.current?.focus();
684
+ }, []);
685
+ const handleSubmit = () => {
686
+ const trimmed = text.trim();
687
+ if (!trimmed) return;
688
+ onSubmit(trimmed);
689
+ };
690
+ const handleKeyDown = (e) => {
691
+ if (e.key === "Enter" && !e.shiftKey) {
692
+ e.preventDefault();
693
+ handleSubmit();
694
+ }
695
+ if (e.key === "Escape") {
696
+ onCancel();
697
+ }
698
+ e.stopPropagation();
699
+ };
700
+ const left = xPercent > 70 ? void 0 : `${xPercent}%`;
701
+ const right = xPercent > 70 ? `${100 - xPercent}%` : void 0;
702
+ const top = yPercent > 70 ? void 0 : `${yPercent}%`;
703
+ const bottom = yPercent > 70 ? `${100 - yPercent}%` : void 0;
704
+ return /* @__PURE__ */ jsxs2(
705
+ "div",
706
+ {
707
+ role: "dialog",
708
+ className: "absolute z-40 w-72 overflow-hidden rounded-xl border border-white/[0.08] bg-neutral-900/95 shadow-2xl backdrop-blur-2xl",
709
+ style: { left, right, top, bottom },
710
+ onClick: (e) => e.stopPropagation(),
711
+ onKeyDown: (e) => e.stopPropagation(),
712
+ children: [
713
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between border-b border-white/[0.06] px-3.5 py-2.5", children: [
714
+ /* @__PURE__ */ jsx8("span", { className: "text-xs font-medium tracking-wide text-neutral-400", children: "Add annotation" }),
715
+ /* @__PURE__ */ jsx8(
716
+ "button",
717
+ {
718
+ onClick: onCancel,
719
+ className: "rounded-lg p-1 text-neutral-500 transition-colors hover:bg-white/[0.06] hover:text-neutral-300",
720
+ children: /* @__PURE__ */ jsx8(X, { className: "h-3.5 w-3.5" })
721
+ }
722
+ )
723
+ ] }),
724
+ /* @__PURE__ */ jsxs2("div", { className: "p-3", children: [
725
+ /* @__PURE__ */ jsx8(
726
+ "textarea",
727
+ {
728
+ ref: textareaRef,
729
+ value: text,
730
+ onChange: (e) => setText(e.target.value),
731
+ onKeyDown: handleKeyDown,
732
+ placeholder: "Describe the change you want...",
733
+ className: "w-full resize-none rounded-lg border border-white/[0.08] bg-white/[0.04] px-3 py-2 text-sm text-white placeholder-neutral-500 outline-none transition-colors focus:border-[#FF6B35]/50 focus:bg-white/[0.06]",
734
+ rows: 3
735
+ }
736
+ ),
737
+ /* @__PURE__ */ jsxs2("div", { className: "mt-2.5 flex items-center justify-between", children: [
738
+ /* @__PURE__ */ jsx8("span", { className: "text-[11px] text-neutral-600", children: "Enter to send" }),
739
+ /* @__PURE__ */ jsx8(
740
+ "button",
741
+ {
742
+ onClick: handleSubmit,
743
+ disabled: !text.trim(),
744
+ className: "flex h-7 w-7 items-center justify-center rounded-lg bg-[#FF6B35] text-white shadow-lg shadow-[#FF6B35]/20 transition-all hover:bg-[#FF7A4A] hover:shadow-[#FF6B35]/30 disabled:opacity-30 disabled:shadow-none disabled:hover:bg-[#FF6B35]",
745
+ children: /* @__PURE__ */ jsx8(ArrowUp, { className: "h-3.5 w-3.5", strokeWidth: 2.5 })
746
+ }
747
+ )
748
+ ] })
749
+ ] })
750
+ ]
751
+ }
752
+ );
753
+ }
754
+
755
+ // src/core/annotations/annotation-pin.tsx
756
+ import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
757
+ function AnnotationPin({ number, status, xPercent, yPercent, isSelected, onClick }) {
758
+ const isResolved = status === "resolved";
759
+ return /* @__PURE__ */ jsxs3(
760
+ "button",
761
+ {
762
+ onClick: (e) => {
763
+ e.stopPropagation();
764
+ onClick();
765
+ },
766
+ className: "absolute z-30 -translate-x-1/2 -translate-y-1/2 transition-all duration-200 hover:scale-110",
767
+ style: { left: `${xPercent}%`, top: `${yPercent}%` },
768
+ title: `Annotation #${number}`,
769
+ children: [
770
+ isSelected && !isResolved && /* @__PURE__ */ jsx9("div", { className: "absolute inset-[-4px] animate-pulse rounded-full bg-[#FF6B35]/25 blur-sm" }),
771
+ /* @__PURE__ */ jsx9(
772
+ "div",
773
+ {
774
+ className: `relative flex h-7 w-7 items-center justify-center rounded-full text-[11px] font-semibold shadow-lg backdrop-blur-sm transition-all duration-200 ${isSelected ? isResolved ? "bg-neutral-500/90 text-white ring-2 ring-neutral-400/50" : "bg-[#FF6B35] text-white ring-2 ring-[#FF6B35]/40 ring-offset-1 ring-offset-black/50" : isResolved ? "bg-neutral-700/80 text-neutral-400" : "bg-[#FF6B35]/90 text-white hover:bg-[#FF6B35]"}`,
775
+ children: number
776
+ }
777
+ )
778
+ ]
779
+ }
780
+ );
781
+ }
782
+
783
+ // src/core/annotations/selectors.ts
784
+ function buildElementTarget(element, slideRoot) {
785
+ const rect = element.getBoundingClientRect();
786
+ const rootRect = slideRoot.getBoundingClientRect();
787
+ const xPercent = (rect.left + rect.width / 2 - rootRect.left) / rootRect.width * 100;
788
+ const yPercent = (rect.top + rect.height / 2 - rootRect.top) / rootRect.height * 100;
789
+ return {
790
+ dataAnnotate: element.getAttribute("data-annotate") || void 0,
791
+ contentNearPin: getTextFingerprint(element),
792
+ position: { xPercent, yPercent }
793
+ };
794
+ }
795
+ function resolveTarget(target, slideRoot) {
796
+ if (target.dataAnnotate) {
797
+ const el = slideRoot.querySelector(`[data-annotate="${target.dataAnnotate}"]`);
798
+ if (el) return { element: el, method: "dataAnnotate" };
799
+ }
800
+ if (target.contentNearPin) {
801
+ const match = findByTextContent(slideRoot, target.contentNearPin);
802
+ if (match) return { element: match, method: "contentNearPin" };
803
+ }
804
+ return { element: null, method: "position" };
805
+ }
806
+ function getTextFingerprint(element) {
807
+ const text = element.textContent?.trim();
808
+ if (!text) return void 0;
809
+ return text.slice(0, 100);
810
+ }
811
+ function findByTextContent(root, text) {
812
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
813
+ let best = null;
814
+ let bestLength = Infinity;
815
+ while (walker.nextNode()) {
816
+ const el = walker.currentNode;
817
+ const elText = el.textContent?.trim();
818
+ if (!elText) continue;
819
+ const elFingerprint = elText.slice(0, 100);
820
+ if (elFingerprint === text && elText.length < bestLength) {
821
+ best = el;
822
+ bestLength = elText.length;
823
+ }
824
+ }
825
+ return best;
826
+ }
827
+
828
+ // src/core/annotations/annotation-overlay.tsx
829
+ import { Fragment, jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
830
+ function AnnotationOverlay({ slides, currentSlide, slideContainerRef, selectedId, onSelectId, onShowPanel, slideAnnotations, addAnnotation }) {
831
+ const [pending, setPending] = useState4(null);
832
+ const [hoveredElement, setHoveredElement] = useState4(null);
833
+ const overlayRef = useRef2(null);
834
+ const slideTitle = slides[currentSlide]?.title || `Slide ${currentSlide + 1}`;
835
+ const resolvedAnnotations = slideAnnotations.map((a, i) => {
836
+ const container = slideContainerRef.current;
837
+ if (!container) {
838
+ return { annotation: a, xPercent: a.target.position.xPercent, yPercent: a.target.position.yPercent, number: i + 1 };
839
+ }
840
+ const { element } = resolveTarget(a.target, container);
841
+ if (element) {
842
+ const rect = element.getBoundingClientRect();
843
+ const containerRect = container.getBoundingClientRect();
844
+ const xPercent = (rect.left + rect.width / 2 - containerRect.left) / containerRect.width * 100;
845
+ const yPercent = (rect.top + rect.height / 2 - containerRect.top) / containerRect.height * 100;
846
+ return { annotation: a, xPercent, yPercent, number: i + 1 };
847
+ }
848
+ return { annotation: a, xPercent: a.target.position.xPercent, yPercent: a.target.position.yPercent, number: i + 1 };
849
+ });
850
+ const handleOverlayClick = useCallback3(
851
+ (e) => {
852
+ const container = slideContainerRef.current;
853
+ if (!container) return;
854
+ const overlay = overlayRef.current;
855
+ if (overlay) overlay.style.pointerEvents = "none";
856
+ const elementUnder = document.elementFromPoint(e.clientX, e.clientY);
857
+ if (overlay) overlay.style.pointerEvents = "";
858
+ if (!elementUnder || !container.contains(elementUnder)) {
859
+ setPending(null);
860
+ onSelectId(null);
861
+ return;
862
+ }
863
+ let target = elementUnder;
864
+ if (target.tagName === "SPAN" && target.parentElement && container.contains(target.parentElement)) {
865
+ const parent = target.parentElement;
866
+ if (parent.tagName !== "DIV" || parent.children.length <= 3) {
867
+ target = parent;
868
+ }
869
+ }
870
+ const annotationTarget = buildElementTarget(target, container);
871
+ const containerRect = container.getBoundingClientRect();
872
+ const xPercent = (e.clientX - containerRect.left) / containerRect.width * 100;
873
+ const yPercent = (e.clientY - containerRect.top) / containerRect.height * 100;
874
+ setPending({ target: annotationTarget, xPercent, yPercent });
875
+ onSelectId(null);
876
+ },
877
+ [slideContainerRef, onSelectId]
878
+ );
879
+ const handleSubmit = useCallback3(
880
+ (text) => {
881
+ if (!pending) return;
882
+ addAnnotation(currentSlide, slideTitle, pending.target, text);
883
+ setPending(null);
884
+ onShowPanel();
885
+ },
886
+ [pending, currentSlide, slideTitle, addAnnotation, onShowPanel]
887
+ );
888
+ const handleMouseMove = useCallback3(
889
+ (e) => {
890
+ if (pending) {
891
+ setHoveredElement(null);
892
+ return;
893
+ }
894
+ const container = slideContainerRef.current;
895
+ if (!container) return;
896
+ const overlay = overlayRef.current;
897
+ if (overlay) overlay.style.pointerEvents = "none";
898
+ const elementUnder = document.elementFromPoint(e.clientX, e.clientY);
899
+ if (overlay) overlay.style.pointerEvents = "";
900
+ if (elementUnder && container.contains(elementUnder) && elementUnder !== container) {
901
+ const containerRect = container.getBoundingClientRect();
902
+ const elRect = elementUnder.getBoundingClientRect();
903
+ setHoveredElement(
904
+ new DOMRect(
905
+ elRect.left - containerRect.left,
906
+ elRect.top - containerRect.top,
907
+ elRect.width,
908
+ elRect.height
909
+ )
910
+ );
911
+ } else {
912
+ setHoveredElement(null);
913
+ }
914
+ },
915
+ [slideContainerRef, pending]
916
+ );
917
+ useEffect4(() => {
918
+ setPending(null);
919
+ onSelectId(null);
920
+ setHoveredElement(null);
921
+ }, [currentSlide, onSelectId]);
922
+ return /* @__PURE__ */ jsxs4(Fragment, { children: [
923
+ hoveredElement && /* @__PURE__ */ jsx10(
924
+ "div",
925
+ {
926
+ className: "pointer-events-none absolute z-20 rounded-lg border-2 border-dashed border-[#FF6B35]/50 bg-[#FF6B35]/5",
927
+ style: {
928
+ left: hoveredElement.x,
929
+ top: hoveredElement.y,
930
+ width: hoveredElement.width,
931
+ height: hoveredElement.height
932
+ }
933
+ }
934
+ ),
935
+ /* @__PURE__ */ jsx10(
936
+ "div",
937
+ {
938
+ ref: overlayRef,
939
+ role: "button",
940
+ tabIndex: 0,
941
+ className: "absolute inset-0 z-20",
942
+ style: { cursor: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none'%3E%3Ccircle cx='12' cy='12' r='8' stroke='%23FF6B35' stroke-width='2' opacity='0.8'/%3E%3Ccircle cx='12' cy='12' r='2' fill='%23FF6B35'/%3E%3C/svg%3E") 12 12, crosshair` },
943
+ onClick: handleOverlayClick,
944
+ onKeyDown: (e) => {
945
+ if (e.key === "Escape") {
946
+ setPending(null);
947
+ onSelectId(null);
948
+ }
949
+ },
950
+ onMouseMove: handleMouseMove,
951
+ onMouseLeave: () => setHoveredElement(null)
952
+ }
953
+ ),
954
+ resolvedAnnotations.map(({ annotation, xPercent, yPercent, number }) => /* @__PURE__ */ jsx10(
955
+ AnnotationPin,
956
+ {
957
+ number,
958
+ status: annotation.status,
959
+ xPercent,
960
+ yPercent,
961
+ isSelected: annotation.id === selectedId,
962
+ onClick: () => {
963
+ onSelectId(annotation.id === selectedId ? null : annotation.id);
964
+ onShowPanel();
965
+ setPending(null);
966
+ }
967
+ },
968
+ annotation.id
969
+ )),
970
+ pending && /* @__PURE__ */ jsx10(
971
+ AnnotationForm,
972
+ {
973
+ xPercent: pending.xPercent,
974
+ yPercent: pending.yPercent,
975
+ onSubmit: handleSubmit,
976
+ onCancel: () => setPending(null)
977
+ }
978
+ )
979
+ ] });
980
+ }
981
+
982
+ // src/core/annotations/annotation-panel.tsx
983
+ import { MessageCircle, Trash2, X as X2 } from "lucide-react";
984
+ import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
985
+ function AnnotationPanel({ annotations, selectedId, onSelect, onDelete, onClose }) {
986
+ const open = annotations.filter((a) => a.status === "open");
987
+ const resolved = annotations.filter((a) => a.status === "resolved");
988
+ return /* @__PURE__ */ jsxs5("div", { className: "flex h-full w-80 flex-shrink-0 flex-col border-l border-white/[0.06] bg-neutral-950/95 backdrop-blur-2xl", children: [
989
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between px-4 py-3.5", children: [
990
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2.5", children: [
991
+ /* @__PURE__ */ jsx11("div", { className: "flex h-6 w-6 items-center justify-center rounded-lg bg-[#FF6B35]/15", children: /* @__PURE__ */ jsx11(MessageCircle, { className: "h-3.5 w-3.5 text-[#FF6B35]" }) }),
992
+ /* @__PURE__ */ jsx11("span", { className: "text-sm font-medium text-white", children: "Annotations" }),
993
+ open.length > 0 && /* @__PURE__ */ jsx11("span", { className: "flex h-5 min-w-5 items-center justify-center rounded-full bg-[#FF6B35]/15 px-1.5 text-[11px] font-semibold text-[#FF6B35]", children: open.length })
994
+ ] }),
995
+ /* @__PURE__ */ jsx11(
996
+ "button",
997
+ {
998
+ onClick: onClose,
999
+ className: "rounded-lg p-1.5 text-neutral-500 transition-colors hover:bg-white/[0.06] hover:text-neutral-300",
1000
+ children: /* @__PURE__ */ jsx11(X2, { className: "h-4 w-4" })
1001
+ }
1002
+ )
1003
+ ] }),
1004
+ /* @__PURE__ */ jsx11("div", { className: "h-px bg-gradient-to-r from-transparent via-white/[0.06] to-transparent" }),
1005
+ /* @__PURE__ */ jsxs5("div", { className: "flex-1 overflow-y-auto p-2", children: [
1006
+ annotations.length === 0 && /* @__PURE__ */ jsxs5("div", { className: "flex flex-col items-center gap-2 px-4 py-8 text-center", children: [
1007
+ /* @__PURE__ */ jsx11("div", { className: "flex h-10 w-10 items-center justify-center rounded-xl bg-white/[0.04]", children: /* @__PURE__ */ jsx11(MessageCircle, { className: "h-5 w-5 text-neutral-600" }) }),
1008
+ /* @__PURE__ */ jsx11("p", { className: "text-sm text-neutral-500", children: "Click on slide elements to add annotations" })
1009
+ ] }),
1010
+ open.length > 0 && /* @__PURE__ */ jsxs5("div", { children: [
1011
+ /* @__PURE__ */ jsx11("div", { className: "mb-1.5 px-2 pt-1 text-[11px] font-medium tracking-wider text-neutral-500 uppercase", children: "Open" }),
1012
+ open.map((a, i) => /* @__PURE__ */ jsx11(
1013
+ AnnotationItem,
1014
+ {
1015
+ annotation: a,
1016
+ number: i + 1,
1017
+ isSelected: a.id === selectedId,
1018
+ onSelect: () => onSelect(a.id),
1019
+ onDelete: () => onDelete(a.id)
1020
+ },
1021
+ a.id
1022
+ ))
1023
+ ] }),
1024
+ resolved.length > 0 && /* @__PURE__ */ jsxs5("div", { className: open.length > 0 ? "mt-3" : "", children: [
1025
+ /* @__PURE__ */ jsx11("div", { className: "mb-1.5 px-2 pt-1 text-[11px] font-medium tracking-wider text-neutral-500 uppercase", children: "Resolved" }),
1026
+ resolved.map((a, i) => /* @__PURE__ */ jsx11(
1027
+ AnnotationItem,
1028
+ {
1029
+ annotation: a,
1030
+ number: open.length + i + 1,
1031
+ isSelected: a.id === selectedId,
1032
+ onSelect: () => onSelect(a.id),
1033
+ onDelete: () => onDelete(a.id)
1034
+ },
1035
+ a.id
1036
+ ))
1037
+ ] })
1038
+ ] })
1039
+ ] });
1040
+ }
1041
+ function AnnotationItem({
1042
+ annotation,
1043
+ number,
1044
+ isSelected,
1045
+ onSelect,
1046
+ onDelete
1047
+ }) {
1048
+ return /* @__PURE__ */ jsxs5(
1049
+ "div",
1050
+ {
1051
+ role: "button",
1052
+ tabIndex: 0,
1053
+ onClick: onSelect,
1054
+ onKeyDown: (e) => {
1055
+ if (e.key === "Enter" || e.key === " ") onSelect();
1056
+ },
1057
+ className: `group relative mb-0.5 cursor-pointer rounded-xl p-2.5 transition-all duration-150 ${isSelected ? "bg-[#FF6B35]/10 ring-1 ring-[#FF6B35]/20" : "hover:bg-white/[0.04]"}`,
1058
+ children: [
1059
+ /* @__PURE__ */ jsx11(
1060
+ "button",
1061
+ {
1062
+ onClick: (e) => {
1063
+ e.stopPropagation();
1064
+ onDelete();
1065
+ },
1066
+ className: "absolute top-2 right-2 rounded-lg p-1 text-neutral-600 opacity-0 transition-all hover:bg-white/[0.08] hover:text-neutral-300 group-hover:opacity-100",
1067
+ children: /* @__PURE__ */ jsx11(Trash2, { className: "h-3 w-3" })
1068
+ }
1069
+ ),
1070
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-start gap-2.5", children: [
1071
+ /* @__PURE__ */ jsx11(
1072
+ "div",
1073
+ {
1074
+ className: `mt-0.5 flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full text-[11px] font-semibold ${annotation.status === "open" ? "bg-[#FF6B35] text-white" : "bg-neutral-700 text-neutral-400"}`,
1075
+ children: number
1076
+ }
1077
+ ),
1078
+ /* @__PURE__ */ jsxs5("div", { className: "min-w-0 pr-4", children: [
1079
+ /* @__PURE__ */ jsx11("p", { className: "text-[13px] leading-relaxed text-neutral-200", children: annotation.body }),
1080
+ annotation.target.contentNearPin && /* @__PURE__ */ jsx11("p", { className: "mt-1 truncate text-[11px] text-neutral-600", children: annotation.target.contentNearPin }),
1081
+ annotation.resolution && /* @__PURE__ */ jsx11("p", { className: "mt-1.5 text-[11px] text-emerald-400/80 italic", children: annotation.resolution })
1082
+ ] })
1083
+ ] })
1084
+ ]
1085
+ }
1086
+ );
1087
+ }
1088
+
1089
+ // src/core/annotations/use-annotations.ts
1090
+ import { useCallback as useCallback4, useEffect as useEffect5, useMemo as useMemo3, useRef as useRef3, useState as useState5 } from "react";
1091
+
1092
+ // src/core/annotations/adapters/http.ts
1093
+ var ENDPOINT = "/__promptslide_annotations";
1094
+ async function loadAll() {
1095
+ try {
1096
+ const res = await fetch(ENDPOINT);
1097
+ if (!res.ok) return [];
1098
+ const data = await res.json();
1099
+ return data.annotations || [];
1100
+ } catch {
1101
+ return [];
1102
+ }
1103
+ }
1104
+ async function saveAll(annotations) {
1105
+ const data = { version: 1, annotations };
1106
+ await fetch(ENDPOINT, {
1107
+ method: "POST",
1108
+ headers: { "Content-Type": "application/json" },
1109
+ body: JSON.stringify(data)
1110
+ });
1111
+ }
1112
+ function createHttpAdapter() {
1113
+ let cache = [];
1114
+ return {
1115
+ async load() {
1116
+ cache = await loadAll();
1117
+ return cache;
1118
+ },
1119
+ async add(annotation) {
1120
+ cache = [...cache, annotation];
1121
+ await saveAll(cache);
1122
+ },
1123
+ async remove(id) {
1124
+ cache = cache.filter((a) => a.id !== id);
1125
+ await saveAll(cache);
1126
+ }
1127
+ };
1128
+ }
1129
+
1130
+ // src/core/annotations/use-annotations.ts
1131
+ function useAnnotations(adapter) {
1132
+ const adapterRef = useRef3(adapter ?? createHttpAdapter());
1133
+ const [annotations, setAnnotations] = useState5([]);
1134
+ useEffect5(() => {
1135
+ adapterRef.current.load().then(setAnnotations);
1136
+ return adapterRef.current.subscribe?.(setAnnotations);
1137
+ }, []);
1138
+ const addAnnotation = useCallback4(
1139
+ (slideIndex, slideTitle, target, body) => {
1140
+ const annotation = {
1141
+ id: crypto.randomUUID(),
1142
+ slideIndex,
1143
+ slideTitle,
1144
+ target,
1145
+ body,
1146
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1147
+ status: "open"
1148
+ };
1149
+ setAnnotations((prev) => [...prev, annotation]);
1150
+ adapterRef.current.add(annotation);
1151
+ },
1152
+ []
1153
+ );
1154
+ const deleteAnnotation = useCallback4((id) => {
1155
+ setAnnotations((prev) => prev.filter((a) => a.id !== id));
1156
+ adapterRef.current.remove(id);
1157
+ }, []);
1158
+ const getSlideAnnotations = useCallback4(
1159
+ (slideIndex) => annotations.filter((a) => a.slideIndex === slideIndex),
1160
+ [annotations]
1161
+ );
1162
+ const openCount = useMemo3(() => annotations.filter((a) => a.status === "open").length, [annotations]);
1163
+ const updateAnnotations = useCallback4((updated) => {
1164
+ setAnnotations(updated);
1165
+ }, []);
1166
+ return { annotations, addAnnotation, deleteAnnotation, getSlideAnnotations, openCount, updateAnnotations };
1167
+ }
671
1168
 
672
1169
  // src/core/utils.ts
673
1170
  import { clsx } from "clsx";
@@ -677,16 +1174,16 @@ function cn(...inputs) {
677
1174
  }
678
1175
 
679
1176
  // src/core/slide-deck.tsx
680
- import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
1177
+ import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
681
1178
  function SlideExportView({ slides, slideIndex }) {
682
- const [ready, setReady] = useState3(false);
1179
+ const [ready, setReady] = useState6(false);
683
1180
  const clampedIndex = Math.max(0, Math.min(slideIndex, slides.length - 1));
684
1181
  const slideConfig = slides[clampedIndex];
685
1182
  const SlideComponent = slideConfig.component;
686
- useEffect3(() => {
1183
+ useEffect6(() => {
687
1184
  setReady(true);
688
1185
  }, []);
689
- return /* @__PURE__ */ jsx8(
1186
+ return /* @__PURE__ */ jsx12(
690
1187
  "div",
691
1188
  {
692
1189
  "data-export-ready": ready ? "true" : void 0,
@@ -697,32 +1194,46 @@ function SlideExportView({ slides, slideIndex }) {
697
1194
  position: "relative",
698
1195
  background: "black"
699
1196
  },
700
- children: /* @__PURE__ */ jsx8(
1197
+ children: /* @__PURE__ */ jsx12(
701
1198
  AnimationProvider,
702
1199
  {
703
1200
  currentStep: slideConfig.steps,
704
1201
  totalSteps: slideConfig.steps,
705
1202
  showAllAnimations: true,
706
- children: /* @__PURE__ */ jsx8(SlideErrorBoundary, { slideIndex: clampedIndex, slideTitle: slideConfig.title, children: /* @__PURE__ */ jsx8(SlideComponent, { slideNumber: clampedIndex + 1, totalSlides: slides.length }) })
1203
+ children: /* @__PURE__ */ jsx12(SlideErrorBoundary, { slideIndex: clampedIndex, slideTitle: slideConfig.title, children: /* @__PURE__ */ jsx12(SlideComponent, { slideNumber: clampedIndex + 1, totalSlides: slides.length }) })
707
1204
  }
708
1205
  )
709
1206
  }
710
1207
  );
711
1208
  }
712
- function SlideDeck({ slides, transition, directionalTransition }) {
713
- const [exportParams] = useState3(() => {
1209
+ function SlideDeck({ slides, transition, directionalTransition, annotations, onAnnotationAdd, onAnnotationDelete }) {
1210
+ const [exportParams] = useState6(() => {
714
1211
  if (typeof window === "undefined") return null;
715
1212
  const params = new URLSearchParams(window.location.search);
716
1213
  if (params.get("export") !== "true") return null;
717
1214
  return { slideIndex: parseInt(params.get("slide") || "0", 10) };
718
1215
  });
719
1216
  if (exportParams) {
720
- return /* @__PURE__ */ jsx8(SlideExportView, { slides, slideIndex: exportParams.slideIndex });
1217
+ return /* @__PURE__ */ jsx12(SlideExportView, { slides, slideIndex: exportParams.slideIndex });
721
1218
  }
722
- const [viewMode, setViewMode] = useState3("slide");
723
- const [isPresentationMode, setIsPresentationMode] = useState3(false);
724
- const [scale, setScale] = useState3(1);
725
- const containerRef = useRef(null);
1219
+ const internal = useAnnotations();
1220
+ const isExternallyManaged = annotations !== void 0;
1221
+ const effectiveAnnotations = isExternallyManaged ? annotations : internal.annotations;
1222
+ const effectiveAdd = isExternallyManaged ? onAnnotationAdd : internal.addAnnotation;
1223
+ const effectiveDelete = isExternallyManaged ? onAnnotationDelete : internal.deleteAnnotation;
1224
+ const openCount = useMemo4(() => effectiveAnnotations.filter((a) => a.status === "open").length, [effectiveAnnotations]);
1225
+ const getSlideAnnotations = useCallback5(
1226
+ (slideIndex) => effectiveAnnotations.filter((a) => a.slideIndex === slideIndex),
1227
+ [effectiveAnnotations]
1228
+ );
1229
+ const [viewMode, setViewMode] = useState6("slide");
1230
+ const [isPresentationMode, setIsPresentationMode] = useState6(false);
1231
+ const [isAnnotationMode, setIsAnnotationMode] = useState6(false);
1232
+ const [showAnnotationPanel, setShowAnnotationPanel] = useState6(false);
1233
+ const [selectedAnnotationId, setSelectedAnnotationId] = useState6(null);
1234
+ const [scale, setScale] = useState6(1);
1235
+ const containerRef = useRef4(null);
1236
+ const slideContainerRef = useRef4(null);
726
1237
  const {
727
1238
  currentSlide,
728
1239
  animationStep,
@@ -736,21 +1247,21 @@ function SlideDeck({ slides, transition, directionalTransition }) {
736
1247
  } = useSlideNavigation({
737
1248
  slides
738
1249
  });
739
- const togglePresentationMode = useCallback3(async () => {
1250
+ const togglePresentationMode = useCallback5(async () => {
740
1251
  if (!document.fullscreenElement) {
741
1252
  await document.documentElement.requestFullscreen();
742
1253
  } else {
743
1254
  await document.exitFullscreen();
744
1255
  }
745
1256
  }, []);
746
- useEffect3(() => {
1257
+ useEffect6(() => {
747
1258
  const handleFullscreenChange = () => {
748
1259
  setIsPresentationMode(!!document.fullscreenElement);
749
1260
  };
750
1261
  document.addEventListener("fullscreenchange", handleFullscreenChange);
751
1262
  return () => document.removeEventListener("fullscreenchange", handleFullscreenChange);
752
1263
  }, []);
753
- useEffect3(() => {
1264
+ useEffect6(() => {
754
1265
  const calculateScale = () => {
755
1266
  if (!isPresentationMode) {
756
1267
  setScale(1);
@@ -778,7 +1289,7 @@ function SlideDeck({ slides, transition, directionalTransition }) {
778
1289
  window.print();
779
1290
  }, 100);
780
1291
  };
781
- useEffect3(() => {
1292
+ useEffect6(() => {
782
1293
  const handleKeyDown = (e) => {
783
1294
  if (e.key === "f" || e.key === "F") {
784
1295
  togglePresentationMode();
@@ -788,7 +1299,7 @@ function SlideDeck({ slides, transition, directionalTransition }) {
788
1299
  setViewMode((prev) => prev === "grid" ? "slide" : "grid");
789
1300
  return;
790
1301
  }
791
- if (viewMode !== "slide") return;
1302
+ if (viewMode !== "slide" || isAnnotationMode) return;
792
1303
  if (e.key === "ArrowRight" || e.key === " ") {
793
1304
  e.preventDefault();
794
1305
  advance();
@@ -799,9 +1310,9 @@ function SlideDeck({ slides, transition, directionalTransition }) {
799
1310
  };
800
1311
  window.addEventListener("keydown", handleKeyDown);
801
1312
  return () => window.removeEventListener("keydown", handleKeyDown);
802
- }, [advance, goBack, viewMode, togglePresentationMode]);
803
- return /* @__PURE__ */ jsxs2("div", { className: "min-h-screen w-full bg-neutral-950 text-foreground", children: [
804
- /* @__PURE__ */ jsx8("style", { children: `
1313
+ }, [advance, goBack, viewMode, togglePresentationMode, isAnnotationMode]);
1314
+ return /* @__PURE__ */ jsxs6("div", { className: "min-h-screen w-full bg-neutral-950 text-foreground", children: [
1315
+ /* @__PURE__ */ jsx12("style", { children: `
805
1316
  @media print {
806
1317
  @page {
807
1318
  size: 1920px 1080px;
@@ -822,15 +1333,16 @@ function SlideDeck({ slides, transition, directionalTransition }) {
822
1333
  }
823
1334
  }
824
1335
  ` }),
825
- /* @__PURE__ */ jsxs2(
1336
+ /* @__PURE__ */ jsxs6(
826
1337
  "div",
827
1338
  {
828
1339
  className: cn(
829
- "fixed top-4 right-4 z-50 flex gap-1 rounded-lg border border-neutral-800 bg-neutral-950/90 p-1 backdrop-blur-sm print:hidden",
830
- isPresentationMode && "hidden"
1340
+ "fixed top-4 z-50 flex gap-1 rounded-lg border border-neutral-800 bg-neutral-950/90 p-1 backdrop-blur-sm transition-[right] print:hidden",
1341
+ isPresentationMode && "hidden",
1342
+ isAnnotationMode && showAnnotationPanel ? "right-[19.5rem]" : "right-4"
831
1343
  ),
832
1344
  children: [
833
- /* @__PURE__ */ jsx8(
1345
+ /* @__PURE__ */ jsx12(
834
1346
  "button",
835
1347
  {
836
1348
  onClick: () => setViewMode("slide"),
@@ -839,10 +1351,10 @@ function SlideDeck({ slides, transition, directionalTransition }) {
839
1351
  viewMode === "slide" && "bg-neutral-800 text-white"
840
1352
  ),
841
1353
  title: "Presentation View",
842
- children: /* @__PURE__ */ jsx8(Monitor, { className: "h-4 w-4" })
1354
+ children: /* @__PURE__ */ jsx12(Monitor, { className: "h-4 w-4" })
843
1355
  }
844
1356
  ),
845
- /* @__PURE__ */ jsx8(
1357
+ /* @__PURE__ */ jsx12(
846
1358
  "button",
847
1359
  {
848
1360
  onClick: () => setViewMode("list"),
@@ -851,10 +1363,10 @@ function SlideDeck({ slides, transition, directionalTransition }) {
851
1363
  viewMode === "list" && "bg-neutral-800 text-white"
852
1364
  ),
853
1365
  title: "List View",
854
- children: /* @__PURE__ */ jsx8(List, { className: "h-4 w-4" })
1366
+ children: /* @__PURE__ */ jsx12(List, { className: "h-4 w-4" })
855
1367
  }
856
1368
  ),
857
- /* @__PURE__ */ jsx8(
1369
+ /* @__PURE__ */ jsx12(
858
1370
  "button",
859
1371
  {
860
1372
  onClick: () => setViewMode("grid"),
@@ -863,121 +1375,185 @@ function SlideDeck({ slides, transition, directionalTransition }) {
863
1375
  viewMode === "grid" && "bg-neutral-800 text-white"
864
1376
  ),
865
1377
  title: "Grid View",
866
- children: /* @__PURE__ */ jsx8(Grid3X3, { className: "h-4 w-4" })
1378
+ children: /* @__PURE__ */ jsx12(Grid3X3, { className: "h-4 w-4" })
867
1379
  }
868
1380
  ),
869
- /* @__PURE__ */ jsx8("div", { className: "mx-1 w-px bg-neutral-800" }),
870
- /* @__PURE__ */ jsx8(
1381
+ /* @__PURE__ */ jsx12("div", { className: "mx-1 w-px bg-neutral-800" }),
1382
+ /* @__PURE__ */ jsxs6(
1383
+ "button",
1384
+ {
1385
+ onClick: () => {
1386
+ setIsAnnotationMode((prev) => {
1387
+ const next = !prev;
1388
+ setShowAnnotationPanel(next);
1389
+ if (!next) setSelectedAnnotationId(null);
1390
+ return next;
1391
+ });
1392
+ },
1393
+ className: cn(
1394
+ "relative rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white",
1395
+ isAnnotationMode && "bg-[#FF6B35] text-white hover:bg-[#FF7A4A]"
1396
+ ),
1397
+ title: "Annotate slides",
1398
+ children: [
1399
+ /* @__PURE__ */ jsx12(MessageCircle2, { className: "h-4 w-4" }),
1400
+ openCount > 0 && /* @__PURE__ */ jsx12("span", { className: "absolute -top-1 -right-1 flex h-4 w-4 items-center justify-center rounded-full bg-[#FF6B35] text-[10px] font-bold text-white", children: openCount })
1401
+ ]
1402
+ }
1403
+ ),
1404
+ /* @__PURE__ */ jsx12("div", { className: "mx-1 w-px bg-neutral-800" }),
1405
+ /* @__PURE__ */ jsx12(
871
1406
  "button",
872
1407
  {
873
1408
  onClick: handleExportPdf,
874
1409
  className: "rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white",
875
1410
  title: "Download PDF",
876
- children: /* @__PURE__ */ jsx8(Download, { className: "h-4 w-4" })
1411
+ children: /* @__PURE__ */ jsx12(Download, { className: "h-4 w-4" })
877
1412
  }
878
1413
  ),
879
- /* @__PURE__ */ jsx8(
1414
+ /* @__PURE__ */ jsx12(
880
1415
  "button",
881
1416
  {
882
1417
  onClick: togglePresentationMode,
883
1418
  className: "rounded-md p-2 text-neutral-400 transition-colors hover:bg-neutral-800 hover:text-white",
884
1419
  title: "Present (F)",
885
- children: /* @__PURE__ */ jsx8(Maximize, { className: "h-4 w-4" })
1420
+ children: /* @__PURE__ */ jsx12(Maximize, { className: "h-4 w-4" })
886
1421
  }
887
1422
  )
888
1423
  ]
889
1424
  }
890
1425
  ),
891
- viewMode === "slide" && /* @__PURE__ */ jsxs2(
1426
+ viewMode === "slide" && /* @__PURE__ */ jsxs6(
892
1427
  "div",
893
1428
  {
894
- ref: containerRef,
895
- role: "presentation",
896
- tabIndex: isPresentationMode ? 0 : void 0,
897
1429
  className: cn(
898
- "flex h-screen w-full flex-col items-center justify-center overflow-hidden print:hidden",
899
- isPresentationMode ? "bg-black p-0" : "p-4 md:p-8"
1430
+ "flex h-screen w-full print:hidden",
1431
+ isPresentationMode ? "bg-black" : ""
900
1432
  ),
901
- onClick: isPresentationMode ? advance : void 0,
902
- onKeyDown: isPresentationMode ? (e) => {
903
- if (e.key === "Enter" || e.key === " ") advance();
904
- } : void 0,
905
1433
  children: [
906
- /* @__PURE__ */ jsx8(LayoutGroup, { id: "slide-deck", children: isPresentationMode ? /* @__PURE__ */ jsx8(
1434
+ /* @__PURE__ */ jsxs6(
907
1435
  "div",
908
1436
  {
909
- className: "pointer-events-none relative overflow-hidden bg-black",
910
- style: {
911
- width: SLIDE_DIMENSIONS.width,
912
- height: SLIDE_DIMENSIONS.height,
913
- transform: `scale(${scale})`,
914
- transformOrigin: "center center"
915
- },
916
- children: /* @__PURE__ */ jsx8(
917
- SlideRenderer,
918
- {
919
- slides,
920
- currentSlide,
921
- animationStep,
922
- totalSteps,
923
- direction,
924
- showAllAnimations,
925
- transition,
926
- directionalTransition,
927
- onTransitionComplete
928
- }
929
- )
1437
+ ref: containerRef,
1438
+ role: "presentation",
1439
+ tabIndex: isPresentationMode ? 0 : void 0,
1440
+ className: cn(
1441
+ "flex flex-1 flex-col items-center justify-center overflow-hidden",
1442
+ isPresentationMode ? "bg-black p-0" : "p-4 md:p-8"
1443
+ ),
1444
+ onClick: isPresentationMode ? advance : void 0,
1445
+ onKeyDown: isPresentationMode ? (e) => {
1446
+ if (e.key === "Enter" || e.key === " ") advance();
1447
+ } : void 0,
1448
+ children: [
1449
+ /* @__PURE__ */ jsx12(LayoutGroup, { id: "slide-deck", children: isPresentationMode ? /* @__PURE__ */ jsx12(
1450
+ "div",
1451
+ {
1452
+ className: "pointer-events-none relative overflow-hidden bg-black",
1453
+ style: {
1454
+ width: SLIDE_DIMENSIONS.width,
1455
+ height: SLIDE_DIMENSIONS.height,
1456
+ transform: `scale(${scale})`,
1457
+ transformOrigin: "center center"
1458
+ },
1459
+ children: /* @__PURE__ */ jsx12(
1460
+ SlideRenderer,
1461
+ {
1462
+ slides,
1463
+ currentSlide,
1464
+ animationStep,
1465
+ totalSteps,
1466
+ direction,
1467
+ showAllAnimations,
1468
+ transition,
1469
+ directionalTransition,
1470
+ onTransitionComplete
1471
+ }
1472
+ )
1473
+ }
1474
+ ) : /* @__PURE__ */ jsxs6("div", { ref: slideContainerRef, className: "relative aspect-video w-full max-w-7xl overflow-hidden rounded-xl border border-neutral-800 bg-black shadow-2xl", children: [
1475
+ /* @__PURE__ */ jsx12(
1476
+ SlideRenderer,
1477
+ {
1478
+ slides,
1479
+ currentSlide,
1480
+ animationStep,
1481
+ totalSteps,
1482
+ direction,
1483
+ showAllAnimations,
1484
+ transition,
1485
+ directionalTransition,
1486
+ onTransitionComplete
1487
+ }
1488
+ ),
1489
+ isAnnotationMode && /* @__PURE__ */ jsx12(
1490
+ AnnotationOverlay,
1491
+ {
1492
+ slides,
1493
+ currentSlide,
1494
+ slideContainerRef,
1495
+ selectedId: selectedAnnotationId,
1496
+ onSelectId: setSelectedAnnotationId,
1497
+ onShowPanel: () => setShowAnnotationPanel(true),
1498
+ slideAnnotations: getSlideAnnotations(currentSlide),
1499
+ addAnnotation: effectiveAdd ?? (() => {
1500
+ })
1501
+ }
1502
+ )
1503
+ ] }) }),
1504
+ !isPresentationMode && /* @__PURE__ */ jsxs6("div", { className: "mt-6 flex items-center gap-4", children: [
1505
+ /* @__PURE__ */ jsx12(
1506
+ "button",
1507
+ {
1508
+ onClick: goBack,
1509
+ className: "rounded-full border border-neutral-800 bg-black/50 p-2 text-neutral-400 backdrop-blur-sm transition-colors hover:bg-neutral-900 hover:text-white",
1510
+ children: /* @__PURE__ */ jsx12(ChevronLeft, { className: "h-5 w-5" })
1511
+ }
1512
+ ),
1513
+ /* @__PURE__ */ jsxs6("div", { className: "flex min-w-[4rem] flex-col items-center", children: [
1514
+ /* @__PURE__ */ jsxs6("span", { className: "font-mono text-sm text-neutral-500", children: [
1515
+ currentSlide + 1,
1516
+ " / ",
1517
+ slides.length
1518
+ ] }),
1519
+ slides[currentSlide]?.title && /* @__PURE__ */ jsx12("span", { className: "mt-0.5 text-xs text-neutral-600", children: slides[currentSlide].title })
1520
+ ] }),
1521
+ /* @__PURE__ */ jsx12(
1522
+ "button",
1523
+ {
1524
+ onClick: advance,
1525
+ className: "rounded-full border border-neutral-800 bg-black/50 p-2 text-neutral-400 backdrop-blur-sm transition-colors hover:bg-neutral-900 hover:text-white",
1526
+ children: /* @__PURE__ */ jsx12(ChevronRight, { className: "h-5 w-5" })
1527
+ }
1528
+ )
1529
+ ] })
1530
+ ]
930
1531
  }
931
- ) : /* @__PURE__ */ jsx8("div", { className: "relative aspect-video w-full max-w-7xl overflow-hidden rounded-xl border border-neutral-800 bg-black shadow-2xl", children: /* @__PURE__ */ jsx8(
932
- SlideRenderer,
1532
+ ),
1533
+ isAnnotationMode && showAnnotationPanel && !isPresentationMode && /* @__PURE__ */ jsx12(
1534
+ AnnotationPanel,
933
1535
  {
934
- slides,
935
- currentSlide,
936
- animationStep,
937
- totalSteps,
938
- direction,
939
- showAllAnimations,
940
- transition,
941
- directionalTransition,
942
- onTransitionComplete
943
- }
944
- ) }) }),
945
- !isPresentationMode && /* @__PURE__ */ jsxs2("div", { className: "mt-6 flex items-center gap-4", children: [
946
- /* @__PURE__ */ jsx8(
947
- "button",
948
- {
949
- onClick: goBack,
950
- className: "rounded-full border border-neutral-800 bg-black/50 p-2 text-neutral-400 backdrop-blur-sm transition-colors hover:bg-neutral-900 hover:text-white",
951
- children: /* @__PURE__ */ jsx8(ChevronLeft, { className: "h-5 w-5" })
1536
+ annotations: getSlideAnnotations(currentSlide),
1537
+ selectedId: selectedAnnotationId,
1538
+ onSelect: setSelectedAnnotationId,
1539
+ onDelete: effectiveDelete ?? (() => {
1540
+ }),
1541
+ onClose: () => {
1542
+ setShowAnnotationPanel(false);
1543
+ setSelectedAnnotationId(null);
952
1544
  }
953
- ),
954
- /* @__PURE__ */ jsxs2("div", { className: "flex min-w-[4rem] flex-col items-center", children: [
955
- /* @__PURE__ */ jsxs2("span", { className: "font-mono text-sm text-neutral-500", children: [
956
- currentSlide + 1,
957
- " / ",
958
- slides.length
959
- ] }),
960
- slides[currentSlide]?.title && /* @__PURE__ */ jsx8("span", { className: "mt-0.5 text-xs text-neutral-600", children: slides[currentSlide].title })
961
- ] }),
962
- /* @__PURE__ */ jsx8(
963
- "button",
964
- {
965
- onClick: advance,
966
- className: "rounded-full border border-neutral-800 bg-black/50 p-2 text-neutral-400 backdrop-blur-sm transition-colors hover:bg-neutral-900 hover:text-white",
967
- children: /* @__PURE__ */ jsx8(ChevronRight, { className: "h-5 w-5" })
968
- }
969
- )
970
- ] })
1545
+ }
1546
+ )
971
1547
  ]
972
1548
  }
973
1549
  ),
974
- viewMode === "grid" && /* @__PURE__ */ jsx8("div", { className: "mx-auto max-w-7xl p-8 pt-16 print:hidden", children: /* @__PURE__ */ jsx8("div", { className: "grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4", children: slides.map((slideConfig, index) => {
1550
+ viewMode === "grid" && /* @__PURE__ */ jsx12("div", { className: "mx-auto max-w-7xl p-8 pt-16 print:hidden", children: /* @__PURE__ */ jsx12("div", { className: "grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4", children: slides.map((slideConfig, index) => {
975
1551
  const SlideComponent = slideConfig.component;
976
1552
  const prevSection = index > 0 ? slides[index - 1]?.section : void 0;
977
1553
  const showSectionHeader = slideConfig.section && slideConfig.section !== prevSection;
978
- return /* @__PURE__ */ jsxs2("div", { className: showSectionHeader ? "col-span-full" : void 0, children: [
979
- showSectionHeader && /* @__PURE__ */ jsx8("h3", { className: "mt-4 mb-3 text-xs font-bold tracking-[0.2em] text-neutral-500 uppercase first:mt-0", children: slideConfig.section }),
980
- /* @__PURE__ */ jsxs2(
1554
+ return /* @__PURE__ */ jsxs6("div", { className: showSectionHeader ? "col-span-full" : void 0, children: [
1555
+ showSectionHeader && /* @__PURE__ */ jsx12("h3", { className: "mt-4 mb-3 text-xs font-bold tracking-[0.2em] text-neutral-500 uppercase first:mt-0", children: slideConfig.section }),
1556
+ /* @__PURE__ */ jsxs6(
981
1557
  "button",
982
1558
  {
983
1559
  onClick: () => {
@@ -986,30 +1562,30 @@ function SlideDeck({ slides, transition, directionalTransition }) {
986
1562
  },
987
1563
  className: "group relative aspect-video w-full overflow-hidden rounded-lg border border-neutral-800 bg-black shadow-sm transition-all hover:border-primary hover:shadow-lg hover:shadow-primary/10",
988
1564
  children: [
989
- /* @__PURE__ */ jsx8(
1565
+ /* @__PURE__ */ jsx12(
990
1566
  "div",
991
1567
  {
992
1568
  className: "h-full w-full origin-top-left scale-[0.25]",
993
1569
  style: { width: "400%", height: "400%" },
994
- children: /* @__PURE__ */ jsx8(
1570
+ children: /* @__PURE__ */ jsx12(
995
1571
  AnimationProvider,
996
1572
  {
997
1573
  currentStep: slideConfig.steps,
998
1574
  totalSteps: slideConfig.steps,
999
1575
  showAllAnimations: true,
1000
- children: /* @__PURE__ */ jsx8(SlideErrorBoundary, { slideIndex: index, slideTitle: slideConfig.title, children: /* @__PURE__ */ jsx8(SlideComponent, { slideNumber: index + 1, totalSlides: slides.length }) })
1576
+ children: /* @__PURE__ */ jsx12(SlideErrorBoundary, { slideIndex: index, slideTitle: slideConfig.title, children: /* @__PURE__ */ jsx12(SlideComponent, { slideNumber: index + 1, totalSlides: slides.length }) })
1001
1577
  }
1002
1578
  )
1003
1579
  }
1004
1580
  ),
1005
- /* @__PURE__ */ jsx8("div", { className: "absolute inset-0 bg-black/0 transition-colors group-hover:bg-black/20" }),
1006
- /* @__PURE__ */ jsx8("div", { className: "absolute bottom-2 left-2 rounded bg-black/70 px-2 py-1 text-xs font-medium text-white", children: slideConfig.title ? `${index + 1}. ${slideConfig.title}` : index + 1 })
1581
+ /* @__PURE__ */ jsx12("div", { className: "absolute inset-0 bg-black/0 transition-colors group-hover:bg-black/20" }),
1582
+ /* @__PURE__ */ jsx12("div", { className: "absolute bottom-2 left-2 rounded bg-black/70 px-2 py-1 text-xs font-medium text-white", children: slideConfig.title ? `${index + 1}. ${slideConfig.title}` : index + 1 })
1007
1583
  ]
1008
1584
  }
1009
1585
  )
1010
1586
  ] }, index);
1011
1587
  }) }) }),
1012
- /* @__PURE__ */ jsx8(
1588
+ /* @__PURE__ */ jsx12(
1013
1589
  "div",
1014
1590
  {
1015
1591
  className: cn(
@@ -1017,19 +1593,19 @@ function SlideDeck({ slides, transition, directionalTransition }) {
1017
1593
  "print:m-0 print:block print:max-w-none print:p-0",
1018
1594
  viewMode === "list" ? "block" : "hidden print:block"
1019
1595
  ),
1020
- children: /* @__PURE__ */ jsx8("div", { className: "grid grid-cols-1 gap-8 print:block", children: slides.map((slideConfig, index) => {
1596
+ children: /* @__PURE__ */ jsx12("div", { className: "grid grid-cols-1 gap-8 print:block", children: slides.map((slideConfig, index) => {
1021
1597
  const SlideComponent = slideConfig.component;
1022
- return /* @__PURE__ */ jsx8(
1598
+ return /* @__PURE__ */ jsx12(
1023
1599
  "div",
1024
1600
  {
1025
1601
  className: "aspect-video w-full overflow-hidden rounded-xl border border-neutral-800 bg-black shadow-sm print:relative print:m-0 print:h-[1080px] print:w-[1920px] print:break-after-page print:overflow-hidden print:rounded-none print:border-0 print:shadow-none",
1026
- children: /* @__PURE__ */ jsx8("div", { className: "h-full w-full print:h-[720px] print:w-[1280px] print:origin-top-left print:scale-[1.5]", children: /* @__PURE__ */ jsx8(
1602
+ children: /* @__PURE__ */ jsx12("div", { className: "h-full w-full print:h-[720px] print:w-[1280px] print:origin-top-left print:scale-[1.5]", children: /* @__PURE__ */ jsx12(
1027
1603
  AnimationProvider,
1028
1604
  {
1029
1605
  currentStep: slideConfig.steps,
1030
1606
  totalSteps: slideConfig.steps,
1031
1607
  showAllAnimations: true,
1032
- children: /* @__PURE__ */ jsx8(SlideErrorBoundary, { slideIndex: index, slideTitle: slideConfig.title, children: /* @__PURE__ */ jsx8(SlideComponent, { slideNumber: index + 1, totalSlides: slides.length }) })
1608
+ children: /* @__PURE__ */ jsx12(SlideErrorBoundary, { slideIndex: index, slideTitle: slideConfig.title, children: /* @__PURE__ */ jsx12(SlideComponent, { slideNumber: index + 1, totalSlides: slides.length }) })
1033
1609
  }
1034
1610
  ) })
1035
1611
  },
@@ -1044,6 +1620,7 @@ export {
1044
1620
  Animated,
1045
1621
  AnimatedGroup,
1046
1622
  AnimationProvider,
1623
+ AnnotationOverlay,
1047
1624
  DEFAULT_SLIDE_TRANSITION,
1048
1625
  EASE_DEFAULT,
1049
1626
  EASE_IN,
@@ -1074,11 +1651,13 @@ export {
1074
1651
  SlideThemeProvider,
1075
1652
  cn,
1076
1653
  createDirectionalVariants,
1654
+ createHttpAdapter,
1077
1655
  directionalSlideX,
1078
1656
  directionalSlideY,
1079
1657
  getSlideTransition,
1080
1658
  getSlideVariants,
1081
1659
  useAnimationContext,
1660
+ useAnnotations,
1082
1661
  useSlideNavigation,
1083
1662
  useTheme
1084
1663
  };