convex-feedback-ui 0.1.4 → 0.1.6

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 (141) hide show
  1. package/README.md +176 -3
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/native/expo/ExpoFeedbackBody.d.ts +1 -1
  4. package/dist/native/expo/ExpoFeedbackBody.d.ts.map +1 -1
  5. package/dist/native/expo/ExpoFeedbackBody.js +2 -2
  6. package/dist/native/expo/ExpoFeedbackBody.js.map +1 -1
  7. package/dist/native/expo/FeedbackCreateStackLayout.d.ts +3 -0
  8. package/dist/native/expo/FeedbackCreateStackLayout.d.ts.map +1 -0
  9. package/dist/native/expo/FeedbackCreateStackLayout.js +35 -0
  10. package/dist/native/expo/FeedbackCreateStackLayout.js.map +1 -0
  11. package/dist/native/expo/FeedbackRoutes.d.ts +4 -0
  12. package/dist/native/expo/FeedbackRoutes.d.ts.map +1 -0
  13. package/dist/native/expo/FeedbackRoutes.js +76 -0
  14. package/dist/native/expo/FeedbackRoutes.js.map +1 -0
  15. package/dist/native/expo/FeedbackScreen.d.ts +1 -1
  16. package/dist/native/expo/FeedbackScreen.d.ts.map +1 -1
  17. package/dist/native/expo/FeedbackScreen.js +3 -2
  18. package/dist/native/expo/FeedbackScreen.js.map +1 -1
  19. package/dist/native/expo/FeedbackStack.d.ts +1 -1
  20. package/dist/native/expo/FeedbackStack.d.ts.map +1 -1
  21. package/dist/native/expo/FeedbackStack.js +4 -2
  22. package/dist/native/expo/FeedbackStack.js.map +1 -1
  23. package/dist/native/expo/FeedbackStackLayout.d.ts +3 -0
  24. package/dist/native/expo/FeedbackStackLayout.d.ts.map +1 -0
  25. package/dist/native/expo/FeedbackStackLayout.js +54 -0
  26. package/dist/native/expo/FeedbackStackLayout.js.map +1 -0
  27. package/dist/native/expo/RoutedFeedbackContext.d.ts +4 -0
  28. package/dist/native/expo/RoutedFeedbackContext.d.ts.map +1 -0
  29. package/dist/native/expo/RoutedFeedbackContext.js +11 -0
  30. package/dist/native/expo/RoutedFeedbackContext.js.map +1 -0
  31. package/dist/native/expo/RoutedFeedbackModalContext.d.ts +7 -0
  32. package/dist/native/expo/RoutedFeedbackModalContext.d.ts.map +1 -0
  33. package/dist/native/expo/RoutedFeedbackModalContext.js +7 -0
  34. package/dist/native/expo/RoutedFeedbackModalContext.js.map +1 -0
  35. package/dist/native/expo/index.d.ts +6 -0
  36. package/dist/native/expo/index.d.ts.map +1 -1
  37. package/dist/native/expo/index.js +6 -0
  38. package/dist/native/expo/index.js.map +1 -1
  39. package/dist/native/expo/metadata.d.ts +4 -0
  40. package/dist/native/expo/metadata.d.ts.map +1 -0
  41. package/dist/native/expo/metadata.js +44 -0
  42. package/dist/native/expo/metadata.js.map +1 -0
  43. package/dist/native/expo/routes.d.ts +16 -0
  44. package/dist/native/expo/routes.d.ts.map +1 -0
  45. package/dist/native/expo/routes.js +23 -0
  46. package/dist/native/expo/routes.js.map +1 -0
  47. package/dist/native/expo/types.d.ts +51 -1
  48. package/dist/native/expo/types.d.ts.map +1 -1
  49. package/dist/native/native/FeedbackScreen.d.ts +1 -1
  50. package/dist/native/native/FeedbackScreen.d.ts.map +1 -1
  51. package/dist/native/native/FeedbackScreen.js +3 -2
  52. package/dist/native/native/FeedbackScreen.js.map +1 -1
  53. package/dist/native/native/index.d.ts +2 -0
  54. package/dist/native/native/index.d.ts.map +1 -1
  55. package/dist/native/native/index.js +2 -0
  56. package/dist/native/native/index.js.map +1 -1
  57. package/dist/native/shared/metadata.d.ts +5 -0
  58. package/dist/native/shared/metadata.d.ts.map +1 -0
  59. package/dist/native/shared/metadata.js +31 -0
  60. package/dist/native/shared/metadata.js.map +1 -0
  61. package/dist/native/shared/ui/EntryDetail.d.ts.map +1 -1
  62. package/dist/native/shared/ui/EntryDetail.js +3 -1
  63. package/dist/native/shared/ui/EntryDetail.js.map +1 -1
  64. package/dist/native/shared/ui/FeedbackScreenList.d.ts +1 -1
  65. package/dist/native/shared/ui/FeedbackScreenList.d.ts.map +1 -1
  66. package/dist/native/shared/ui/FeedbackScreenList.js +2 -2
  67. package/dist/native/shared/ui/FeedbackScreenList.js.map +1 -1
  68. package/dist/native/shared/ui/MetadataModal.d.ts +6 -0
  69. package/dist/native/shared/ui/MetadataModal.d.ts.map +1 -0
  70. package/dist/native/shared/ui/MetadataModal.js +39 -0
  71. package/dist/native/shared/ui/MetadataModal.js.map +1 -0
  72. package/dist/native/shared/ui/NewEntry.d.ts +10 -0
  73. package/dist/native/shared/ui/NewEntry.d.ts.map +1 -1
  74. package/dist/native/shared/ui/NewEntry.js +11 -4
  75. package/dist/native/shared/ui/NewEntry.js.map +1 -1
  76. package/dist/react/index.d.ts +2 -0
  77. package/dist/react/index.d.ts.map +1 -1
  78. package/dist/react/index.js +2 -0
  79. package/dist/react/index.js.map +1 -1
  80. package/dist/react/metadata.d.ts +4 -0
  81. package/dist/react/metadata.d.ts.map +1 -0
  82. package/dist/react/metadata.js +40 -0
  83. package/dist/react/metadata.js.map +1 -0
  84. package/dist/react/screen.d.ts +1 -1
  85. package/dist/react/screen.d.ts.map +1 -1
  86. package/dist/react/screen.js +18 -4
  87. package/dist/react/screen.js.map +1 -1
  88. package/dist/react/styles.css +35 -0
  89. package/dist/shared/context/FeedbackBodyProvider.d.ts +1 -1
  90. package/dist/shared/context/FeedbackBodyProvider.d.ts.map +1 -1
  91. package/dist/shared/context/FeedbackBodyProvider.js +5 -1
  92. package/dist/shared/context/FeedbackBodyProvider.js.map +1 -1
  93. package/dist/shared/messages.d.ts.map +1 -1
  94. package/dist/shared/messages.js +9 -0
  95. package/dist/shared/messages.js.map +1 -1
  96. package/dist/shared/metadata.d.ts +6 -0
  97. package/dist/shared/metadata.d.ts.map +1 -0
  98. package/dist/shared/metadata.js +54 -0
  99. package/dist/shared/metadata.js.map +1 -0
  100. package/dist/shared/types/index.d.ts +1 -0
  101. package/dist/shared/types/index.d.ts.map +1 -1
  102. package/dist/shared/types/messages.d.ts +17 -0
  103. package/dist/shared/types/messages.d.ts.map +1 -1
  104. package/dist/shared/types/metadata.d.ts +22 -0
  105. package/dist/shared/types/metadata.d.ts.map +1 -0
  106. package/dist/shared/types/metadata.js +2 -0
  107. package/dist/shared/types/metadata.js.map +1 -0
  108. package/dist/shared/types/screen.d.ts +14 -1
  109. package/dist/shared/types/screen.d.ts.map +1 -1
  110. package/package.json +12 -8
  111. package/src/native/expo/ExpoFeedbackBody.tsx +6 -1
  112. package/src/native/expo/FeedbackCreateStackLayout.tsx +62 -0
  113. package/src/native/expo/FeedbackRoutes.tsx +204 -0
  114. package/src/native/expo/FeedbackScreen.tsx +4 -0
  115. package/src/native/expo/FeedbackStack.tsx +16 -4
  116. package/src/native/expo/FeedbackStackLayout.tsx +116 -0
  117. package/src/native/expo/README.md +24 -0
  118. package/src/native/expo/RoutedFeedbackContext.tsx +20 -0
  119. package/src/native/expo/RoutedFeedbackModalContext.tsx +14 -0
  120. package/src/native/expo/index.ts +6 -0
  121. package/src/native/expo/metadata.ts +62 -0
  122. package/src/native/expo/routes.ts +41 -0
  123. package/src/native/expo/types.ts +63 -1
  124. package/src/native/native/FeedbackScreen.tsx +4 -0
  125. package/src/native/native/index.ts +2 -0
  126. package/src/native/shared/metadata.ts +39 -0
  127. package/src/native/shared/ui/EntryDetail.tsx +14 -0
  128. package/src/native/shared/ui/FeedbackScreenList.tsx +2 -1
  129. package/src/native/shared/ui/MetadataModal.tsx +112 -0
  130. package/src/native/shared/ui/NewEntry.tsx +18 -4
  131. package/src/react/index.ts +2 -0
  132. package/src/react/metadata.ts +51 -0
  133. package/src/react/screen.tsx +89 -2
  134. package/src/react/styles.css +35 -0
  135. package/src/shared/context/FeedbackBodyProvider.tsx +8 -0
  136. package/src/shared/messages.ts +9 -0
  137. package/src/shared/metadata.ts +84 -0
  138. package/src/shared/types/index.ts +1 -0
  139. package/src/shared/types/messages.ts +24 -0
  140. package/src/shared/types/metadata.ts +55 -0
  141. package/src/shared/types/screen.ts +17 -2
@@ -0,0 +1,84 @@
1
+ import type {
2
+ EntryKind,
3
+ FeedbackMetadata,
4
+ FeedbackMetadataValue,
5
+ } from "convex-feedback";
6
+
7
+ import type {
8
+ CollectMetadata,
9
+ EnabledStandardMetadataSelection,
10
+ MetadataCollectionContext,
11
+ MetadataSource,
12
+ StandardMetadataKey,
13
+ } from "./types/metadata.js";
14
+
15
+ export type StandardMetadataCollector = (
16
+ selection: EnabledStandardMetadataSelection,
17
+ ) => Partial<Record<StandardMetadataKey, FeedbackMetadataValue>>;
18
+
19
+ async function resolveAdditionalMetadata(
20
+ source: MetadataSource | undefined,
21
+ context: MetadataCollectionContext,
22
+ ): Promise<Record<string, FeedbackMetadataValue>> {
23
+ if (source === undefined) return {};
24
+
25
+ try {
26
+ return typeof source === "function" ? await source(context) : source;
27
+ } catch {
28
+ return {};
29
+ }
30
+ }
31
+
32
+ export async function collectEntryMetadata(
33
+ config: CollectMetadata | undefined,
34
+ kind: EntryKind,
35
+ collectStandard: StandardMetadataCollector,
36
+ ): Promise<FeedbackMetadata | undefined> {
37
+ if (config === undefined || config === false) return undefined;
38
+
39
+ const root = config === true ? { standard: true as const } : config;
40
+ const kindConfig = root.kinds?.[kind];
41
+ if (kindConfig === false) return undefined;
42
+
43
+ const kindOptions =
44
+ kindConfig === true ? { standard: true as const } : kindConfig;
45
+ const standardSelection = kindOptions?.standard ?? root.standard ?? false;
46
+ const context = { kind } satisfies MetadataCollectionContext;
47
+ const [globalAdditional, kindAdditional] = await Promise.all([
48
+ resolveAdditionalMetadata(root.additional, context),
49
+ resolveAdditionalMetadata(kindOptions?.additional, context),
50
+ ]);
51
+
52
+ let standard: FeedbackMetadata["standard"];
53
+ try {
54
+ standard =
55
+ standardSelection === false
56
+ ? undefined
57
+ : collectStandard(standardSelection);
58
+ } catch {
59
+ standard = undefined;
60
+ }
61
+
62
+ const additional = { ...globalAdditional, ...kindAdditional };
63
+ const hasStandard =
64
+ standard !== undefined && Object.keys(standard).length > 0;
65
+ const hasAdditional = Object.keys(additional).length > 0;
66
+
67
+ if (!hasStandard && !hasAdditional) return undefined;
68
+
69
+ return {
70
+ ...(hasStandard ? { standard } : {}),
71
+ ...(hasAdditional ? { additional } : {}),
72
+ };
73
+ }
74
+
75
+ export function formatMetadataKey(key: string): string {
76
+ const words = key
77
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
78
+ .replace(/[_-]+/g, " ")
79
+ .trim();
80
+
81
+ return words.length === 0
82
+ ? key
83
+ : words.charAt(0).toLocaleUpperCase("en-US") + words.slice(1);
84
+ }
@@ -4,6 +4,7 @@ export type * from "./context.js";
4
4
  export type * from "./entry.js";
5
5
  export type * from "./form.js";
6
6
  export type * from "./messages.js";
7
+ export type * from "./metadata.js";
7
8
  export type * from "./render.js";
8
9
  export type * from "./screen.js";
9
10
  export type * from "./theme.js";
@@ -67,6 +67,27 @@ export interface FeedbackMessages {
67
67
  back: string;
68
68
  };
69
69
 
70
+ /** Moderator-only diagnostic metadata copy. */
71
+ metadata: {
72
+ /** Action that opens the metadata viewer. */
73
+ view: string;
74
+
75
+ /** Metadata viewer heading. */
76
+ title: string;
77
+
78
+ /** Heading for automatically collected values. */
79
+ standard: string;
80
+
81
+ /** Heading for host-provided values. */
82
+ additional: string;
83
+
84
+ /** Empty state for a metadata object without values. */
85
+ empty: string;
86
+
87
+ /** Closes the metadata viewer. */
88
+ close: string;
89
+ };
90
+
70
91
  /** Create-entry form copy. */
71
92
  form: {
72
93
  /** Entry-kind field label. */
@@ -167,6 +188,9 @@ export interface FeedbackMessageOverrides {
167
188
  /** Entry action/counter copy overrides. */
168
189
  entry?: Partial<FeedbackMessages["entry"]> | undefined;
169
190
 
191
+ /** Diagnostic metadata copy overrides. */
192
+ metadata?: Partial<FeedbackMessages["metadata"]> | undefined;
193
+
170
194
  /** Create-entry form copy overrides. */
171
195
  form?: Partial<FeedbackMessages["form"]> | undefined;
172
196
 
@@ -0,0 +1,55 @@
1
+ import type { EntryKind, FeedbackMetadataValue } from "convex-feedback";
2
+
3
+ export type StandardMetadataKey =
4
+ | "platform"
5
+ | "userAgent"
6
+ | "language"
7
+ | "timezone"
8
+ | "screenWidth"
9
+ | "screenHeight"
10
+ | "viewportWidth"
11
+ | "viewportHeight"
12
+ | "devicePixelRatio"
13
+ | "osVersion"
14
+ | "deviceModel"
15
+ | "pixelRatio"
16
+ | "fontScale"
17
+ | "appVersion"
18
+ | "buildNumber"
19
+ | "applicationId"
20
+ | "expoRuntimeVersion"
21
+ | "executionEnvironment";
22
+
23
+ export type EnabledStandardMetadataSelection =
24
+ true | readonly StandardMetadataKey[];
25
+
26
+ export type StandardMetadataSelection =
27
+ false | EnabledStandardMetadataSelection;
28
+
29
+ export interface MetadataCollectionContext {
30
+ kind: EntryKind;
31
+ }
32
+
33
+ export type AdditionalMetadata = Record<string, FeedbackMetadataValue>;
34
+
35
+ export type MetadataSource =
36
+ | AdditionalMetadata
37
+ | ((
38
+ context: MetadataCollectionContext,
39
+ ) => AdditionalMetadata | Promise<AdditionalMetadata>);
40
+
41
+ export interface MetadataCollectionOptions {
42
+ /** Standard platform fields to collect. `true` selects platform defaults. */
43
+ standard?: StandardMetadataSelection;
44
+
45
+ /** Static or submission-time host metadata. */
46
+ additional?: MetadataSource;
47
+ }
48
+
49
+ export interface MetadataCollectionConfig extends MetadataCollectionOptions {
50
+ /** Per-entry-kind overrides. `false` disables all collection for that kind. */
51
+ kinds?: Partial<Record<EntryKind, boolean | MetadataCollectionOptions>>;
52
+ }
53
+
54
+ /** Metadata collection configuration accepted by prebuilt feedback screens. */
55
+ export type CollectMetadata = boolean | MetadataCollectionConfig;
@@ -9,6 +9,8 @@ import type { FeedbackHooks } from "convex-feedback/react";
9
9
  import type { ReactNode } from "react";
10
10
 
11
11
  import type { FeedbackColorProps, FeedbackProviderProps } from "./context.js";
12
+ import type { CollectMetadata } from "./metadata.js";
13
+ import type { StandardMetadataCollector } from "../metadata.js";
12
14
 
13
15
  /**
14
16
  * Presentation-only transform applied to one currently loaded comment page.
@@ -87,6 +89,12 @@ export interface FeedbackScreenBaseProps {
87
89
  * @default 300
88
90
  */
89
91
  debounceDuration?: number;
92
+
93
+ /**
94
+ * Enables creation-time diagnostic metadata collection globally and/or by
95
+ * entry kind. Disabled by default.
96
+ */
97
+ collectMetadata?: CollectMetadata;
90
98
  }
91
99
 
92
100
  export interface FeedbackScreenRootProps
@@ -98,8 +106,11 @@ export interface FeedbackScreenRootProps
98
106
 
99
107
  export interface FeedbackScreenProviderProps
100
108
  extends
101
- Required<FeedbackScreenBaseProps>,
102
- FeedbackScreenTransformationProps {}
109
+ Required<Omit<FeedbackScreenBaseProps, "collectMetadata">>,
110
+ FeedbackScreenTransformationProps {
111
+ collectMetadata?: CollectMetadata;
112
+ collectStandardMetadata: StandardMetadataCollector;
113
+ }
103
114
 
104
115
  export interface FeedbackScreenBodyContextValue
105
116
  extends FeedbackScreenTransformationProps, FeedbackScreenProviderProps {
@@ -128,6 +139,10 @@ export interface FeedbackScreenListProps {
128
139
  hideBackButton?: boolean;
129
140
  /** Callback when the EntryCard is opened. */
130
141
  onEntryOpen: (entryId: string) => void;
142
+ /** Whether provider-selected entries are rendered in place of the list.
143
+ * @default true
144
+ */
145
+ showSelectedEntry?: boolean;
131
146
  }
132
147
 
133
148
  export interface FeedbackScreenContentProps