@david-xpn/llm-ui-feedback 0.1.4 → 0.1.7

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.mjs CHANGED
@@ -789,14 +789,24 @@ function DraftModal({ pendingContext, addingDraft, onAdd, onCancel }) {
789
789
 
790
790
  // src/components/SubmitModal.tsx
791
791
  import { useState as useState5 } from "react";
792
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
793
- function SubmitModal({ count, onSubmit, onCancel, submitting }) {
792
+ import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
793
+ function SubmitModal({ count, onSubmit, onCancel, onDone, submitting, submittedUrl }) {
794
794
  const [title, setTitle] = useState5("");
795
+ const [copied, setCopied] = useState5(false);
795
796
  const handleSubmit = () => {
796
797
  if (title.trim() && !submitting) {
797
798
  onSubmit(title.trim());
798
799
  }
799
800
  };
801
+ const handleCopy = async () => {
802
+ if (!submittedUrl) return;
803
+ try {
804
+ await navigator.clipboard.writeText(submittedUrl);
805
+ setCopied(true);
806
+ setTimeout(() => setCopied(false), 2e3);
807
+ } catch {
808
+ }
809
+ };
800
810
  return /* @__PURE__ */ jsx6(
801
811
  "div",
802
812
  {
@@ -811,9 +821,12 @@ function SubmitModal({ count, onSubmit, onCancel, submitting }) {
811
821
  fontFamily: "system-ui, sans-serif"
812
822
  },
813
823
  onClick: (e) => {
814
- if (e.target === e.currentTarget && !submitting) onCancel();
824
+ if (e.target === e.currentTarget) {
825
+ if (submittedUrl) onDone();
826
+ else if (!submitting) onCancel();
827
+ }
815
828
  },
816
- children: /* @__PURE__ */ jsxs6(
829
+ children: /* @__PURE__ */ jsx6(
817
830
  "div",
818
831
  {
819
832
  style: {
@@ -824,7 +837,64 @@ function SubmitModal({ count, onSubmit, onCancel, submitting }) {
824
837
  maxWidth: "90vw",
825
838
  boxShadow: "0 8px 32px rgba(0,0,0,0.2)"
826
839
  },
827
- children: [
840
+ children: submittedUrl ? /* @__PURE__ */ jsxs6(Fragment2, { children: [
841
+ /* @__PURE__ */ jsx6("h3", { style: { margin: "0 0 16px", fontSize: 16 }, children: "Feedback Submitted" }),
842
+ /* @__PURE__ */ jsx6("p", { style: { margin: "0 0 12px", fontSize: 14, color: "#6b7280" }, children: "Share this link to view the feedback:" }),
843
+ /* @__PURE__ */ jsxs6("div", { style: { display: "flex", gap: 8 }, children: [
844
+ /* @__PURE__ */ jsx6(
845
+ "input",
846
+ {
847
+ type: "text",
848
+ value: submittedUrl,
849
+ readOnly: true,
850
+ onFocus: (e) => e.target.select(),
851
+ style: {
852
+ flex: 1,
853
+ padding: 10,
854
+ borderRadius: 8,
855
+ border: "1px solid #d1d5db",
856
+ fontSize: 13,
857
+ boxSizing: "border-box",
858
+ color: "#374151",
859
+ background: "#f9fafb"
860
+ }
861
+ }
862
+ ),
863
+ /* @__PURE__ */ jsx6(
864
+ "button",
865
+ {
866
+ onClick: handleCopy,
867
+ style: {
868
+ padding: "8px 14px",
869
+ borderRadius: 8,
870
+ border: "1px solid #d1d5db",
871
+ background: copied ? "#dcfce7" : "#f3f4f6",
872
+ color: copied ? "#166534" : "#374151",
873
+ fontSize: 13,
874
+ cursor: "pointer",
875
+ whiteSpace: "nowrap"
876
+ },
877
+ children: copied ? "Copied!" : "Copy"
878
+ }
879
+ )
880
+ ] }),
881
+ /* @__PURE__ */ jsx6("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 16 }, children: /* @__PURE__ */ jsx6(
882
+ "button",
883
+ {
884
+ onClick: onDone,
885
+ style: {
886
+ padding: "8px 16px",
887
+ borderRadius: 6,
888
+ border: "none",
889
+ background: "#3b82f6",
890
+ color: "#fff",
891
+ fontSize: 13,
892
+ cursor: "pointer"
893
+ },
894
+ children: "Done"
895
+ }
896
+ ) })
897
+ ] }) : /* @__PURE__ */ jsxs6(Fragment2, { children: [
828
898
  /* @__PURE__ */ jsx6("h3", { style: { margin: "0 0 16px", fontSize: 16 }, children: "Submit Feedback" }),
829
899
  /* @__PURE__ */ jsxs6("p", { style: { margin: "0 0 12px", fontSize: 14, color: "#6b7280" }, children: [
830
900
  count,
@@ -889,7 +959,7 @@ function SubmitModal({ count, onSubmit, onCancel, submitting }) {
889
959
  }
890
960
  )
891
961
  ] })
892
- ]
962
+ ] })
893
963
  }
894
964
  )
895
965
  }
@@ -1179,7 +1249,7 @@ function createApiClient(apiUrl, clientId) {
1179
1249
  }
1180
1250
 
1181
1251
  // src/components/FeedbackWidget.tsx
1182
- import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1252
+ import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1183
1253
  var CONTAINER_ID = "llm-ui-feedback-root";
1184
1254
  function getOrCreateContainer() {
1185
1255
  let el = document.getElementById(CONTAINER_ID);
@@ -1198,7 +1268,8 @@ var initialState = {
1198
1268
  selectedDraftIds: /* @__PURE__ */ new Set(),
1199
1269
  submitModalOpen: false,
1200
1270
  addingDraft: false,
1201
- submitting: false
1271
+ submitting: false,
1272
+ submittedShareUrl: null
1202
1273
  };
1203
1274
  function widgetReducer(state, action) {
1204
1275
  switch (action.type) {
@@ -1243,12 +1314,15 @@ function widgetReducer(state, action) {
1243
1314
  return { ...state, submitModalOpen: false };
1244
1315
  case "SET_SUBMITTING":
1245
1316
  return { ...state, submitting: action.submitting };
1317
+ case "SUBMIT_SUCCESS":
1318
+ return { ...state, submitting: false, submittedShareUrl: action.shareUrl };
1246
1319
  case "SUBMIT_COMPLETE": {
1247
1320
  const submitted = new Set(action.submittedIds);
1248
1321
  return {
1249
1322
  ...state,
1250
1323
  submitting: false,
1251
1324
  submitModalOpen: false,
1325
+ submittedShareUrl: null,
1252
1326
  drafts: state.drafts.filter((d) => !submitted.has(d.id)),
1253
1327
  selectedDraftIds: /* @__PURE__ */ new Set()
1254
1328
  };
@@ -1426,19 +1500,27 @@ function FeedbackWidget({
1426
1500
  });
1427
1501
  }
1428
1502
  }, [api]);
1503
+ const submittedDraftIdsRef = useRef3([]);
1429
1504
  const handleSubmit = useCallback3(async (title) => {
1430
1505
  dispatch({ type: "SET_SUBMITTING", submitting: true });
1431
1506
  const draftIds = Array.from(state.selectedDraftIds);
1507
+ submittedDraftIdsRef.current = draftIds;
1432
1508
  try {
1433
- await api.submitSession({ title, draftIds });
1434
- dispatch({ type: "SUBMIT_COMPLETE", submittedIds: draftIds });
1509
+ const result = await api.submitSession({ title, draftIds });
1510
+ const group = result.feedbackGroup;
1511
+ const shareUrl = group.shareToken ? `${apiUrl}/feedback-groups/${group.id}/markdown?token=${group.shareToken}` : "";
1512
+ dispatch({ type: "SUBMIT_SUCCESS", shareUrl });
1435
1513
  } catch {
1436
1514
  dispatch({ type: "SET_SUBMITTING", submitting: false });
1437
1515
  }
1438
- }, [state.selectedDraftIds, api]);
1516
+ }, [state.selectedDraftIds, api, apiUrl]);
1517
+ const handleSubmitDone = useCallback3(() => {
1518
+ dispatch({ type: "SUBMIT_COMPLETE", submittedIds: submittedDraftIdsRef.current });
1519
+ submittedDraftIdsRef.current = [];
1520
+ }, []);
1439
1521
  if (session.status === "loading") return null;
1440
1522
  return createPortal(
1441
- /* @__PURE__ */ jsxs7(Fragment2, { children: [
1523
+ /* @__PURE__ */ jsxs7(Fragment3, { children: [
1442
1524
  /* @__PURE__ */ jsx7(
1443
1525
  FloatingButton,
1444
1526
  {
@@ -1482,7 +1564,9 @@ function FeedbackWidget({
1482
1564
  count: state.selectedDraftIds.size,
1483
1565
  onSubmit: handleSubmit,
1484
1566
  onCancel: () => dispatch({ type: "CLOSE_SUBMIT_MODAL" }),
1485
- submitting: state.submitting
1567
+ onDone: handleSubmitDone,
1568
+ submitting: state.submitting,
1569
+ submittedUrl: state.submittedShareUrl
1486
1570
  }
1487
1571
  )
1488
1572
  ] }),