convex-feedback-ui 0.1.6 → 0.1.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.
Files changed (102) hide show
  1. package/README.md +21 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/native/expo/FeedbackCreateStackLayout.d.ts.map +1 -1
  4. package/dist/native/expo/FeedbackCreateStackLayout.js +1 -0
  5. package/dist/native/expo/FeedbackCreateStackLayout.js.map +1 -1
  6. package/dist/native/expo/FeedbackRoutes.d.ts.map +1 -1
  7. package/dist/native/expo/FeedbackRoutes.js +12 -7
  8. package/dist/native/expo/FeedbackRoutes.js.map +1 -1
  9. package/dist/native/expo/FeedbackScreen.d.ts +1 -1
  10. package/dist/native/expo/FeedbackScreen.d.ts.map +1 -1
  11. package/dist/native/expo/FeedbackScreen.js +2 -2
  12. package/dist/native/expo/FeedbackScreen.js.map +1 -1
  13. package/dist/native/expo/FeedbackStack.d.ts.map +1 -1
  14. package/dist/native/expo/FeedbackStack.js +10 -6
  15. package/dist/native/expo/FeedbackStack.js.map +1 -1
  16. package/dist/native/expo/FeedbackStackLayout.d.ts +1 -1
  17. package/dist/native/expo/FeedbackStackLayout.d.ts.map +1 -1
  18. package/dist/native/expo/FeedbackStackLayout.js +3 -2
  19. package/dist/native/expo/FeedbackStackLayout.js.map +1 -1
  20. package/dist/native/expo/types.d.ts +2 -0
  21. package/dist/native/expo/types.d.ts.map +1 -1
  22. package/dist/native/native/FeedbackScreen.d.ts +1 -1
  23. package/dist/native/native/FeedbackScreen.d.ts.map +1 -1
  24. package/dist/native/native/FeedbackScreen.js +2 -2
  25. package/dist/native/native/FeedbackScreen.js.map +1 -1
  26. package/dist/native/shared/ui/BodyContent.d.ts +1 -1
  27. package/dist/native/shared/ui/BodyContent.d.ts.map +1 -1
  28. package/dist/native/shared/ui/BodyContent.js +2 -2
  29. package/dist/native/shared/ui/BodyContent.js.map +1 -1
  30. package/dist/native/shared/ui/Button.d.ts +2 -1
  31. package/dist/native/shared/ui/Button.d.ts.map +1 -1
  32. package/dist/native/shared/ui/Button.js +9 -4
  33. package/dist/native/shared/ui/Button.js.map +1 -1
  34. package/dist/native/shared/ui/FeedbackScreenHeader.d.ts.map +1 -1
  35. package/dist/native/shared/ui/FeedbackScreenHeader.js +8 -4
  36. package/dist/native/shared/ui/FeedbackScreenHeader.js.map +1 -1
  37. package/dist/native/shared/ui/FeedbackScreenList.d.ts +1 -1
  38. package/dist/native/shared/ui/FeedbackScreenList.d.ts.map +1 -1
  39. package/dist/native/shared/ui/FeedbackScreenList.js +18 -5
  40. package/dist/native/shared/ui/FeedbackScreenList.js.map +1 -1
  41. package/dist/native/shared/ui/NewEntry.d.ts.map +1 -1
  42. package/dist/native/shared/ui/NewEntry.js +5 -12
  43. package/dist/native/shared/ui/NewEntry.js.map +1 -1
  44. package/dist/native/shared/ui/primitives.d.ts +7 -1
  45. package/dist/native/shared/ui/primitives.d.ts.map +1 -1
  46. package/dist/native/shared/ui/primitives.js +38 -0
  47. package/dist/native/shared/ui/primitives.js.map +1 -1
  48. package/dist/react/primitives.d.ts +9 -1
  49. package/dist/react/primitives.d.ts.map +1 -1
  50. package/dist/react/primitives.js +12 -0
  51. package/dist/react/primitives.js.map +1 -1
  52. package/dist/react/screen.d.ts +1 -1
  53. package/dist/react/screen.d.ts.map +1 -1
  54. package/dist/react/screen.js +22 -11
  55. package/dist/react/screen.js.map +1 -1
  56. package/dist/react/styles.css +38 -1
  57. package/dist/shared/context/FeedbackBodyProvider.d.ts +1 -1
  58. package/dist/shared/context/FeedbackBodyProvider.d.ts.map +1 -1
  59. package/dist/shared/context/FeedbackBodyProvider.js +6 -1
  60. package/dist/shared/context/FeedbackBodyProvider.js.map +1 -1
  61. package/dist/shared/helpers.d.ts +5 -1
  62. package/dist/shared/helpers.d.ts.map +1 -1
  63. package/dist/shared/helpers.js +11 -0
  64. package/dist/shared/helpers.js.map +1 -1
  65. package/dist/shared/messages.d.ts.map +1 -1
  66. package/dist/shared/messages.js +1 -0
  67. package/dist/shared/messages.js.map +1 -1
  68. package/dist/shared/types/choice.d.ts +10 -0
  69. package/dist/shared/types/choice.d.ts.map +1 -0
  70. package/dist/shared/types/choice.js +2 -0
  71. package/dist/shared/types/choice.js.map +1 -0
  72. package/dist/shared/types/index.d.ts +1 -0
  73. package/dist/shared/types/index.d.ts.map +1 -1
  74. package/dist/shared/types/messages.d.ts +2 -0
  75. package/dist/shared/types/messages.d.ts.map +1 -1
  76. package/dist/shared/types/screen.d.ts +12 -2
  77. package/dist/shared/types/screen.d.ts.map +1 -1
  78. package/package.json +6 -2
  79. package/src/native/expo/FeedbackCreateStackLayout.tsx +1 -0
  80. package/src/native/expo/FeedbackRoutes.tsx +41 -3
  81. package/src/native/expo/FeedbackScreen.tsx +4 -0
  82. package/src/native/expo/FeedbackStack.tsx +28 -6
  83. package/src/native/expo/FeedbackStackLayout.tsx +5 -0
  84. package/src/native/expo/README.md +2 -2
  85. package/src/native/expo/types.ts +2 -0
  86. package/src/native/native/FeedbackScreen.tsx +4 -0
  87. package/src/native/shared/ui/BodyContent.tsx +2 -0
  88. package/src/native/shared/ui/Button.tsx +12 -3
  89. package/src/native/shared/ui/FeedbackScreenHeader.tsx +25 -4
  90. package/src/native/shared/ui/FeedbackScreenList.tsx +48 -8
  91. package/src/native/shared/ui/NewEntry.tsx +10 -28
  92. package/src/native/shared/ui/primitives.tsx +90 -0
  93. package/src/react/primitives.tsx +55 -0
  94. package/src/react/screen.tsx +73 -34
  95. package/src/react/styles.css +38 -1
  96. package/src/shared/context/FeedbackBodyProvider.tsx +8 -0
  97. package/src/shared/helpers.ts +21 -1
  98. package/src/shared/messages.ts +1 -0
  99. package/src/shared/types/choice.ts +10 -0
  100. package/src/shared/types/index.ts +1 -0
  101. package/src/shared/types/messages.ts +3 -0
  102. package/src/shared/types/screen.ts +20 -1
@@ -6,6 +6,7 @@ import {
6
6
  useMemo,
7
7
  useState,
8
8
  } from "react";
9
+ import type { EntryStatusFilter } from "convex-feedback";
9
10
  import { debounce } from "../helpers";
10
11
  import type {
11
12
  FeedbackScreenBodyContextValue,
@@ -23,6 +24,8 @@ export function FeedbackBodyProvider({
23
24
  maxCommentDepth,
24
25
  debounceDuration,
25
26
  collectMetadata,
27
+ emptyState,
28
+ loading,
26
29
  collectStandardMetadata,
27
30
  transformComments,
28
31
  renderActor,
@@ -33,6 +36,7 @@ export function FeedbackBodyProvider({
33
36
  const [isSearching, setIsSearching] = useState(false);
34
37
  const [query, setQuery] = useState("");
35
38
  const [debouncedQuery, setDebouncedQuery] = useState("");
39
+ const [statusFilter, setStatusFilter] = useState<EntryStatusFilter>("open");
36
40
 
37
41
  const updateDebouncedQuery = useMemo(
38
42
  () => debounce(setDebouncedQuery, debounceDuration),
@@ -51,12 +55,14 @@ export function FeedbackBodyProvider({
51
55
  showForm,
52
56
  isSearching,
53
57
  selectedEntryId,
58
+ statusFilter,
54
59
 
55
60
  setQuery,
56
61
  setDebouncedQuery,
57
62
  setShowForm,
58
63
  setIsSearching,
59
64
  setSelectedEntryId,
65
+ setStatusFilter,
60
66
 
61
67
  hooks,
62
68
  entrySort,
@@ -65,6 +71,8 @@ export function FeedbackBodyProvider({
65
71
  maxCommentDepth,
66
72
  debounceDuration,
67
73
  collectMetadata,
74
+ emptyState,
75
+ loading,
68
76
  collectStandardMetadata,
69
77
  transformComments,
70
78
  renderActor,
@@ -1,4 +1,6 @@
1
- import type { EntryKind } from "convex-feedback";
1
+ import type { EntryKind, EntryStatusFilter } from "convex-feedback";
2
+ import type { FeedbackMessages } from "./types/messages.js";
3
+ import type { ChoiceChipOption } from "./types/choice.js";
2
4
 
3
5
  export const kinds: readonly EntryKind[] = [
4
6
  "feedback",
@@ -6,6 +8,24 @@ export const kinds: readonly EntryKind[] = [
6
8
  "bug_report",
7
9
  ];
8
10
 
11
+ export function createEntryLabel(
12
+ enabledKinds: readonly EntryKind[],
13
+ messages: FeedbackMessages,
14
+ ): string {
15
+ return enabledKinds.length === 1
16
+ ? messages.newFeedback[enabledKinds[0]!]
17
+ : messages.board.createEntry;
18
+ }
19
+
20
+ export function entryStatusChoices(
21
+ messages: FeedbackMessages,
22
+ ): readonly ChoiceChipOption<EntryStatusFilter>[] {
23
+ return [
24
+ { value: "open", label: messages.statuses.open },
25
+ { value: "closed", label: messages.statuses.closed },
26
+ ];
27
+ }
28
+
9
29
  export function debounce<TArgs extends unknown[]>(
10
30
  callback: (...args: TArgs) => void,
11
31
  delay: number,
@@ -5,6 +5,7 @@ export const englishFeedbackMessages: FeedbackMessages = {
5
5
  title: "Feedback",
6
6
  subtitle: "Share ideas, report problems, and help shape what comes next.",
7
7
  searchPlaceholder: "Search feedback…",
8
+ statusFilter: "Filter by status",
8
9
  createEntry: "Create feedback",
9
10
  noEntries: "No feedback yet.",
10
11
  noSearchResults: "No matching feedback found.",
@@ -0,0 +1,10 @@
1
+ export interface ChoiceChipOption<Value extends string = string> {
2
+ value: Value;
3
+ label: string;
4
+ }
5
+
6
+ export interface ChoiceChipsBaseProps<Value extends string = string> {
7
+ options: readonly ChoiceChipOption<Value>[];
8
+ value: Value;
9
+ onValueChange: (value: Value) => void;
10
+ }
@@ -1,5 +1,6 @@
1
1
  export type * from "./board.js";
2
2
  export type * from "./comment.js";
3
+ export type * from "./choice.js";
3
4
  export type * from "./context.js";
4
5
  export type * from "./entry.js";
5
6
  export type * from "./form.js";
@@ -18,6 +18,9 @@ export interface FeedbackMessages {
18
18
  /** Search input placeholder. */
19
19
  searchPlaceholder: string;
20
20
 
21
+ /** Accessible label for the open/closed entry status filter. */
22
+ statusFilter: string;
23
+
21
24
  /** CTA for opening the create-entry flow.
22
25
  * This is shown when enabled kinds are two or more.
23
26
  * Use messages.newFeedback for a single-kind entry.
@@ -2,6 +2,7 @@ import type {
2
2
  CommentSort,
3
3
  EntryKind,
4
4
  EntrySort,
5
+ EntryStatusFilter,
5
6
  FeedbackComment,
6
7
  FeedbackEntry,
7
8
  } from "convex-feedback";
@@ -95,6 +96,12 @@ export interface FeedbackScreenBaseProps {
95
96
  * entry kind. Disabled by default.
96
97
  */
97
98
  collectMetadata?: CollectMetadata;
99
+
100
+ /** Optional host-owned content rendered above the empty-state message. */
101
+ emptyState?: ReactNode;
102
+
103
+ /** Optional host-owned loading indicator rendered during board loading. */
104
+ loading?: ReactNode;
98
105
  }
99
106
 
100
107
  export interface FeedbackScreenRootProps
@@ -106,9 +113,16 @@ export interface FeedbackScreenRootProps
106
113
 
107
114
  export interface FeedbackScreenProviderProps
108
115
  extends
109
- Required<Omit<FeedbackScreenBaseProps, "collectMetadata">>,
116
+ Required<
117
+ Omit<
118
+ FeedbackScreenBaseProps,
119
+ "collectMetadata" | "emptyState" | "loading"
120
+ >
121
+ >,
110
122
  FeedbackScreenTransformationProps {
111
123
  collectMetadata?: CollectMetadata;
124
+ emptyState?: ReactNode;
125
+ loading?: ReactNode;
112
126
  collectStandardMetadata: StandardMetadataCollector;
113
127
  }
114
128
 
@@ -119,11 +133,13 @@ export interface FeedbackScreenBodyContextValue
119
133
  showForm: boolean;
120
134
  isSearching: boolean;
121
135
  selectedEntryId: string | null;
136
+ statusFilter: EntryStatusFilter;
122
137
  setQuery: React.Dispatch<React.SetStateAction<string>>;
123
138
  setDebouncedQuery: React.Dispatch<React.SetStateAction<string>>;
124
139
  setShowForm: React.Dispatch<React.SetStateAction<boolean>>;
125
140
  setIsSearching: React.Dispatch<React.SetStateAction<boolean>>;
126
141
  setSelectedEntryId: React.Dispatch<React.SetStateAction<string | null>>;
142
+ setStatusFilter: React.Dispatch<React.SetStateAction<EntryStatusFilter>>;
127
143
  }
128
144
 
129
145
  export type FeedbackScreenBodyProps = FeedbackColorProps;
@@ -143,6 +159,9 @@ export interface FeedbackScreenListProps {
143
159
  * @default true
144
160
  */
145
161
  showSelectedEntry?: boolean;
162
+
163
+ /** Callback for the empty-state create-entry action. */
164
+ onCreateEntry?: () => void;
146
165
  }
147
166
 
148
167
  export interface FeedbackScreenContentProps