feedtack 0.2.1 → 0.3.0

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.
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React from 'react';
3
- import { F as FeedtackAdapter, o as FeedtackUser, n as FeedtackTheme } from '../theme-C-uctIoI.js';
3
+ import { F as FeedtackAdapter, o as FeedtackUser, n as FeedtackTheme, e as FeedbackItem } from '../theme-C-uctIoI.js';
4
4
 
5
5
  interface FeedtackClasses {
6
6
  button?: string;
@@ -24,8 +24,10 @@ interface FeedtackProviderProps {
24
24
  sentimentLabels?: FeedtackSentimentLabels;
25
25
  onError?: (err: Error) => void;
26
26
  disabled?: boolean;
27
+ /** Render custom content inside a submitted pin marker. Receives the feedback item. */
28
+ renderPinIcon?: (item: FeedbackItem) => React.ReactNode;
27
29
  }
28
- declare function FeedtackProvider({ children, adapter, currentUser, hotkey, adminOnly, theme, classes, sentimentLabels, onError, disabled, }: FeedtackProviderProps): react_jsx_runtime.JSX.Element;
30
+ declare function FeedtackProvider({ children, adapter, currentUser, hotkey, adminOnly, theme, classes, sentimentLabels, onError, disabled, renderPinIcon, }: FeedtackProviderProps): react_jsx_runtime.JSX.Element;
29
31
 
30
32
  interface FeedtackContextValue {
31
33
  activatePinMode: () => void;
@@ -66,17 +66,27 @@ function CommentForm({
66
66
  className: cx("feedtack-form", classes.form),
67
67
  style: { position: "fixed", ...formPos },
68
68
  children: [
69
+ /* @__PURE__ */ jsx("label", { htmlFor: "feedtack-comment", className: "feedtack-sr-only", children: "Feedback comment" }),
69
70
  /* @__PURE__ */ jsx(
70
71
  "textarea",
71
72
  {
73
+ id: "feedtack-comment",
72
74
  className: commentError ? "error" : "",
73
75
  placeholder: "What's the issue? (required)",
74
76
  value: comment,
75
77
  onChange: (e) => onCommentChange(e.target.value),
76
- ref: (el) => el?.focus()
78
+ onKeyDown: (e) => {
79
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
80
+ e.preventDefault();
81
+ onSubmit();
82
+ }
83
+ },
84
+ ref: (el) => el?.focus(),
85
+ "aria-describedby": commentError ? "feedtack-comment-error" : void 0,
86
+ "aria-invalid": commentError || void 0
77
87
  }
78
88
  ),
79
- commentError && /* @__PURE__ */ jsx("span", { className: "feedtack-error-msg", children: "Comment is required" }),
89
+ commentError && /* @__PURE__ */ jsx("span", { id: "feedtack-comment-error", className: "feedtack-error-msg", children: "Comment is required" }),
80
90
  /* @__PURE__ */ jsxs("div", { className: "feedtack-sentiment", children: [
81
91
  /* @__PURE__ */ jsx(
82
92
  "button",
@@ -308,6 +318,22 @@ var FEEDTACK_STYLES = `
308
318
  pointer-events: all;
309
319
  }
310
320
 
321
+ .feedtack-pin-resolved { opacity: 0.6; }
322
+
323
+ .feedtack-pin-icon {
324
+ position: absolute;
325
+ inset: 0;
326
+ display: flex;
327
+ align-items: center;
328
+ justify-content: center;
329
+ transform: rotate(45deg);
330
+ font-size: 12px;
331
+ font-weight: 700;
332
+ color: #fff;
333
+ line-height: 1;
334
+ pointer-events: none;
335
+ }
336
+
311
337
  .feedtack-pin-badge {
312
338
  position: absolute;
313
339
  top: -4px;
@@ -455,6 +481,11 @@ var FEEDTACK_STYLES = `
455
481
  gap: 10px;
456
482
  }
457
483
 
484
+ .feedtack-sr-only {
485
+ position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
486
+ overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
487
+ }
488
+
458
489
  .feedtack-loading {
459
490
  position: fixed;
460
491
  bottom: 70px;
@@ -772,7 +803,8 @@ function FeedtackProvider({
772
803
  classes = {},
773
804
  sentimentLabels = {},
774
805
  onError,
775
- disabled = false
806
+ disabled = false,
807
+ renderPinIcon
776
808
  }) {
777
809
  const state = useFeedtackState({
778
810
  adapter,
@@ -809,6 +841,8 @@ function FeedtackProvider({
809
841
  ),
810
842
  onClick: () => state.isPinModeActive ? state.deactivatePinMode() : state.activatePinMode(),
811
843
  title: "Toggle feedback pin mode",
844
+ "aria-label": "Toggle feedback pin mode",
845
+ "aria-pressed": state.isPinModeActive,
812
846
  children: [
813
847
  "Drop Pin [Shift+",
814
848
  hotkey.toUpperCase(),
@@ -864,11 +898,15 @@ function FeedtackProvider({
864
898
  ),
865
899
  !state.loading && state.feedbackItems.filter((item) => item.payload.page.pathname === state.pathname).filter((item) => !state.isArchivedForUser(item)).filter((item) => state.hasValidPins(item)).map((item) => {
866
900
  const pin = item.payload.pins[0];
867
- return /* @__PURE__ */ jsx3(
901
+ return /* @__PURE__ */ jsxs3(
868
902
  "button",
869
903
  {
870
904
  type: "button",
871
- className: cx("feedtack-pin-marker", classes.pinMarker),
905
+ className: cx(
906
+ "feedtack-pin-marker",
907
+ item.resolutions.length > 0 && "feedtack-pin-resolved",
908
+ classes.pinMarker
909
+ ),
872
910
  style: {
873
911
  background: pin.color,
874
912
  left: pin.x,
@@ -879,7 +917,18 @@ function FeedtackProvider({
879
917
  onClick: () => state.setOpenThreadId(
880
918
  state.openThreadId === item.payload.id ? null : item.payload.id
881
919
  ),
882
- children: state.hasUnread(item) && /* @__PURE__ */ jsx3("div", { className: "feedtack-pin-badge" })
920
+ children: [
921
+ renderPinIcon ? /* @__PURE__ */ jsx3("span", { className: "feedtack-pin-icon", children: renderPinIcon(item) }) : item.resolutions.length > 0 && /* @__PURE__ */ jsx3(
922
+ "span",
923
+ {
924
+ className: "feedtack-pin-icon",
925
+ role: "img",
926
+ "aria-label": "Resolved",
927
+ children: "\u2713"
928
+ }
929
+ ),
930
+ state.hasUnread(item) && /* @__PURE__ */ jsx3("div", { className: "feedtack-pin-badge" })
931
+ ]
883
932
  },
884
933
  item.payload.id
885
934
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "feedtack",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Click anywhere. Drop a pin. Get a payload a developer can act on.",
5
5
  "type": "module",
6
6
  "license": "MIT",