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.
- package/README.md +176 -3
- package/dist/.tsbuildinfo +1 -1
- package/dist/native/expo/ExpoFeedbackBody.d.ts +1 -1
- package/dist/native/expo/ExpoFeedbackBody.d.ts.map +1 -1
- package/dist/native/expo/ExpoFeedbackBody.js +2 -2
- package/dist/native/expo/ExpoFeedbackBody.js.map +1 -1
- package/dist/native/expo/FeedbackCreateStackLayout.d.ts +3 -0
- package/dist/native/expo/FeedbackCreateStackLayout.d.ts.map +1 -0
- package/dist/native/expo/FeedbackCreateStackLayout.js +35 -0
- package/dist/native/expo/FeedbackCreateStackLayout.js.map +1 -0
- package/dist/native/expo/FeedbackRoutes.d.ts +4 -0
- package/dist/native/expo/FeedbackRoutes.d.ts.map +1 -0
- package/dist/native/expo/FeedbackRoutes.js +76 -0
- package/dist/native/expo/FeedbackRoutes.js.map +1 -0
- package/dist/native/expo/FeedbackScreen.d.ts +1 -1
- package/dist/native/expo/FeedbackScreen.d.ts.map +1 -1
- package/dist/native/expo/FeedbackScreen.js +3 -2
- package/dist/native/expo/FeedbackScreen.js.map +1 -1
- package/dist/native/expo/FeedbackStack.d.ts +1 -1
- package/dist/native/expo/FeedbackStack.d.ts.map +1 -1
- package/dist/native/expo/FeedbackStack.js +4 -2
- package/dist/native/expo/FeedbackStack.js.map +1 -1
- package/dist/native/expo/FeedbackStackLayout.d.ts +3 -0
- package/dist/native/expo/FeedbackStackLayout.d.ts.map +1 -0
- package/dist/native/expo/FeedbackStackLayout.js +54 -0
- package/dist/native/expo/FeedbackStackLayout.js.map +1 -0
- package/dist/native/expo/RoutedFeedbackContext.d.ts +4 -0
- package/dist/native/expo/RoutedFeedbackContext.d.ts.map +1 -0
- package/dist/native/expo/RoutedFeedbackContext.js +11 -0
- package/dist/native/expo/RoutedFeedbackContext.js.map +1 -0
- package/dist/native/expo/RoutedFeedbackModalContext.d.ts +7 -0
- package/dist/native/expo/RoutedFeedbackModalContext.d.ts.map +1 -0
- package/dist/native/expo/RoutedFeedbackModalContext.js +7 -0
- package/dist/native/expo/RoutedFeedbackModalContext.js.map +1 -0
- package/dist/native/expo/index.d.ts +6 -0
- package/dist/native/expo/index.d.ts.map +1 -1
- package/dist/native/expo/index.js +6 -0
- package/dist/native/expo/index.js.map +1 -1
- package/dist/native/expo/metadata.d.ts +4 -0
- package/dist/native/expo/metadata.d.ts.map +1 -0
- package/dist/native/expo/metadata.js +44 -0
- package/dist/native/expo/metadata.js.map +1 -0
- package/dist/native/expo/routes.d.ts +16 -0
- package/dist/native/expo/routes.d.ts.map +1 -0
- package/dist/native/expo/routes.js +23 -0
- package/dist/native/expo/routes.js.map +1 -0
- package/dist/native/expo/types.d.ts +51 -1
- package/dist/native/expo/types.d.ts.map +1 -1
- package/dist/native/native/FeedbackScreen.d.ts +1 -1
- package/dist/native/native/FeedbackScreen.d.ts.map +1 -1
- package/dist/native/native/FeedbackScreen.js +3 -2
- package/dist/native/native/FeedbackScreen.js.map +1 -1
- package/dist/native/native/index.d.ts +2 -0
- package/dist/native/native/index.d.ts.map +1 -1
- package/dist/native/native/index.js +2 -0
- package/dist/native/native/index.js.map +1 -1
- package/dist/native/shared/metadata.d.ts +5 -0
- package/dist/native/shared/metadata.d.ts.map +1 -0
- package/dist/native/shared/metadata.js +31 -0
- package/dist/native/shared/metadata.js.map +1 -0
- package/dist/native/shared/ui/EntryDetail.d.ts.map +1 -1
- package/dist/native/shared/ui/EntryDetail.js +3 -1
- package/dist/native/shared/ui/EntryDetail.js.map +1 -1
- package/dist/native/shared/ui/FeedbackScreenList.d.ts +1 -1
- package/dist/native/shared/ui/FeedbackScreenList.d.ts.map +1 -1
- package/dist/native/shared/ui/FeedbackScreenList.js +2 -2
- package/dist/native/shared/ui/FeedbackScreenList.js.map +1 -1
- package/dist/native/shared/ui/MetadataModal.d.ts +6 -0
- package/dist/native/shared/ui/MetadataModal.d.ts.map +1 -0
- package/dist/native/shared/ui/MetadataModal.js +39 -0
- package/dist/native/shared/ui/MetadataModal.js.map +1 -0
- package/dist/native/shared/ui/NewEntry.d.ts +10 -0
- package/dist/native/shared/ui/NewEntry.d.ts.map +1 -1
- package/dist/native/shared/ui/NewEntry.js +11 -4
- package/dist/native/shared/ui/NewEntry.js.map +1 -1
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +2 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/metadata.d.ts +4 -0
- package/dist/react/metadata.d.ts.map +1 -0
- package/dist/react/metadata.js +40 -0
- package/dist/react/metadata.js.map +1 -0
- package/dist/react/screen.d.ts +1 -1
- package/dist/react/screen.d.ts.map +1 -1
- package/dist/react/screen.js +18 -4
- package/dist/react/screen.js.map +1 -1
- package/dist/react/styles.css +35 -0
- package/dist/shared/context/FeedbackBodyProvider.d.ts +1 -1
- package/dist/shared/context/FeedbackBodyProvider.d.ts.map +1 -1
- package/dist/shared/context/FeedbackBodyProvider.js +5 -1
- package/dist/shared/context/FeedbackBodyProvider.js.map +1 -1
- package/dist/shared/messages.d.ts.map +1 -1
- package/dist/shared/messages.js +9 -0
- package/dist/shared/messages.js.map +1 -1
- package/dist/shared/metadata.d.ts +6 -0
- package/dist/shared/metadata.d.ts.map +1 -0
- package/dist/shared/metadata.js +54 -0
- package/dist/shared/metadata.js.map +1 -0
- package/dist/shared/types/index.d.ts +1 -0
- package/dist/shared/types/index.d.ts.map +1 -1
- package/dist/shared/types/messages.d.ts +17 -0
- package/dist/shared/types/messages.d.ts.map +1 -1
- package/dist/shared/types/metadata.d.ts +22 -0
- package/dist/shared/types/metadata.d.ts.map +1 -0
- package/dist/shared/types/metadata.js +2 -0
- package/dist/shared/types/metadata.js.map +1 -0
- package/dist/shared/types/screen.d.ts +14 -1
- package/dist/shared/types/screen.d.ts.map +1 -1
- package/package.json +12 -8
- package/src/native/expo/ExpoFeedbackBody.tsx +6 -1
- package/src/native/expo/FeedbackCreateStackLayout.tsx +62 -0
- package/src/native/expo/FeedbackRoutes.tsx +204 -0
- package/src/native/expo/FeedbackScreen.tsx +4 -0
- package/src/native/expo/FeedbackStack.tsx +16 -4
- package/src/native/expo/FeedbackStackLayout.tsx +116 -0
- package/src/native/expo/README.md +24 -0
- package/src/native/expo/RoutedFeedbackContext.tsx +20 -0
- package/src/native/expo/RoutedFeedbackModalContext.tsx +14 -0
- package/src/native/expo/index.ts +6 -0
- package/src/native/expo/metadata.ts +62 -0
- package/src/native/expo/routes.ts +41 -0
- package/src/native/expo/types.ts +63 -1
- package/src/native/native/FeedbackScreen.tsx +4 -0
- package/src/native/native/index.ts +2 -0
- package/src/native/shared/metadata.ts +39 -0
- package/src/native/shared/ui/EntryDetail.tsx +14 -0
- package/src/native/shared/ui/FeedbackScreenList.tsx +2 -1
- package/src/native/shared/ui/MetadataModal.tsx +112 -0
- package/src/native/shared/ui/NewEntry.tsx +18 -4
- package/src/react/index.ts +2 -0
- package/src/react/metadata.ts +51 -0
- package/src/react/screen.tsx +89 -2
- package/src/react/styles.css +35 -0
- package/src/shared/context/FeedbackBodyProvider.tsx +8 -0
- package/src/shared/messages.ts +9 -0
- package/src/shared/metadata.ts +84 -0
- package/src/shared/types/index.ts +1 -0
- package/src/shared/types/messages.ts +24 -0
- package/src/shared/types/metadata.ts +55 -0
- 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
|