@openrails/contentkit-ui 0.79.0 → 0.81.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.
- package/README.md +82 -54
- package/dist/client/beacons.d.ts +53 -0
- package/dist/client/beacons.js +72 -0
- package/dist/client/beacons.js.map +1 -0
- package/dist/client/catalog.d.ts +2 -2
- package/dist/client/catalog.js +1 -1
- package/dist/client/catalog.js.map +1 -1
- package/dist/client/client.d.ts +24 -11
- package/dist/client/client.js +37 -29
- package/dist/client/client.js.map +1 -1
- package/dist/client/content/comments.d.ts +12 -8
- package/dist/client/content/comments.js +33 -20
- package/dist/client/content/comments.js.map +1 -1
- package/dist/client/content/favorites.d.ts +24 -9
- package/dist/client/content/favorites.js +21 -22
- package/dist/client/content/favorites.js.map +1 -1
- package/dist/client/content/moderation.d.ts +1 -1
- package/dist/client/content/moderation.js.map +1 -1
- package/dist/client/content/reactions.d.ts +11 -6
- package/dist/client/content/reactions.js +23 -18
- package/dist/client/content/reactions.js.map +1 -1
- package/dist/client/content/types.d.ts +40 -21
- package/dist/client/content/types.js +5 -2
- package/dist/client/content/types.js.map +1 -1
- package/dist/client/contents.d.ts +55 -0
- package/dist/client/contents.js +144 -0
- package/dist/client/contents.js.map +1 -0
- package/dist/client/discovery.d.ts +126 -0
- package/dist/client/discovery.js +125 -0
- package/dist/client/discovery.js.map +1 -0
- package/dist/client/generated/error-codes.d.ts +1 -1
- package/dist/client/generated/error-codes.js +12 -0
- package/dist/client/generated/error-codes.js.map +1 -1
- package/dist/client/generated/routes.d.ts +1244 -370
- package/dist/client/generated/routes.js +1870 -554
- package/dist/client/generated/routes.js.map +1 -1
- package/dist/client/generated/wire.d.ts +960 -134
- package/dist/client/generated/wire.js.map +1 -1
- package/dist/client/group-fields.d.ts +25 -0
- package/dist/client/group-fields.js +63 -0
- package/dist/client/group-fields.js.map +1 -0
- package/dist/client/groups.d.ts +58 -0
- package/dist/client/groups.js +119 -0
- package/dist/client/groups.js.map +1 -0
- package/dist/client/http.d.ts +24 -12
- package/dist/client/http.js +20 -24
- package/dist/client/http.js.map +1 -1
- package/dist/client/index.d.ts +11 -6
- package/dist/client/media/api.d.ts +1 -1
- package/dist/client/media/api.js +4 -2
- package/dist/client/media/api.js.map +1 -1
- package/dist/client/media/client.d.ts +8 -9
- package/dist/client/media/client.js +58 -71
- package/dist/client/media/client.js.map +1 -1
- package/dist/client/media/ref.d.ts +30 -0
- package/dist/client/media/ref.js +10 -3
- package/dist/client/media/ref.js.map +1 -1
- package/dist/client/offers.d.ts +41 -0
- package/dist/client/offers.js +66 -0
- package/dist/client/offers.js.map +1 -0
- package/dist/client/route.d.ts +2 -0
- package/dist/client/route.js +2 -1
- package/dist/client/route.js.map +1 -1
- package/dist/client/versions.d.ts +20 -0
- package/dist/client/versions.js +53 -0
- package/dist/client/versions.js.map +1 -0
- package/dist/client.js +35 -30
- package/dist/components/admin/content-manager.d.ts +80 -0
- package/dist/components/admin/content-manager.js +591 -0
- package/dist/components/admin/content-manager.js.map +1 -0
- package/dist/components/admin/group-manager.d.ts +24 -0
- package/dist/components/admin/group-manager.js +244 -0
- package/dist/components/admin/group-manager.js.map +1 -0
- package/dist/components/admin/media-item-panel.js +1 -1
- package/dist/components/admin/media-item-panel.js.map +1 -1
- package/dist/components/content/card.d.ts +44 -0
- package/dist/components/content/card.js +285 -0
- package/dist/components/content/card.js.map +1 -0
- package/dist/components/content/editors.d.ts +40 -0
- package/dist/components/content/editors.js +764 -0
- package/dist/components/content/editors.js.map +1 -0
- package/dist/components/content/filters.d.ts +28 -0
- package/dist/components/content/filters.js +134 -0
- package/dist/components/content/filters.js.map +1 -0
- package/dist/components/content/grid.d.ts +62 -0
- package/dist/components/content/grid.js +233 -0
- package/dist/components/content/grid.js.map +1 -0
- package/dist/components/content/index.d.ts +8 -0
- package/dist/components/content/listing.d.ts +20 -0
- package/dist/components/content/listing.js +150 -0
- package/dist/components/content/listing.js.map +1 -0
- package/dist/components/content/offer-fields.d.ts +8 -0
- package/dist/components/content/offer-fields.js +127 -0
- package/dist/components/content/offer-fields.js.map +1 -0
- package/dist/components/content/paywall.d.ts +53 -0
- package/dist/components/content/paywall.js +221 -0
- package/dist/components/content/paywall.js.map +1 -0
- package/dist/components/content/search.d.ts +27 -0
- package/dist/components/content/search.js +164 -0
- package/dist/components/content/search.js.map +1 -0
- package/dist/components/groups/banner.d.ts +51 -0
- package/dist/components/groups/banner.js +194 -0
- package/dist/components/groups/banner.js.map +1 -0
- package/dist/components/groups/directory.d.ts +37 -0
- package/dist/components/groups/directory.js +117 -0
- package/dist/components/groups/directory.js.map +1 -0
- package/dist/components/groups/editor.d.ts +44 -0
- package/dist/components/groups/editor.js +860 -0
- package/dist/components/groups/editor.js.map +1 -0
- package/dist/components/groups/fields.d.ts +13 -0
- package/dist/components/groups/fields.js +68 -0
- package/dist/components/groups/fields.js.map +1 -0
- package/dist/components/groups/header.d.ts +25 -0
- package/dist/components/groups/header.js +131 -0
- package/dist/components/groups/header.js.map +1 -0
- package/dist/components/groups/index.d.ts +6 -0
- package/dist/components/groups/memberships.d.ts +55 -0
- package/dist/components/groups/memberships.js +527 -0
- package/dist/components/groups/memberships.js.map +1 -0
- package/dist/components/groups/parts.d.ts +49 -0
- package/dist/components/groups/parts.js +172 -0
- package/dist/components/groups/parts.js.map +1 -0
- package/dist/components/media-folder-editor.js +153 -152
- package/dist/components/media-folder-editor.js.map +1 -1
- package/dist/components/social/comments.d.ts +7 -5
- package/dist/components/social/comments.js +6 -2
- package/dist/components/social/comments.js.map +1 -1
- package/dist/components/social/engagement.d.ts +4 -3
- package/dist/components/social/engagement.js.map +1 -1
- package/dist/components/social/moderation.d.ts +1 -1
- package/dist/components/social/moderation.js +3 -3
- package/dist/components/social/moderation.js.map +1 -1
- package/dist/editor/rich-text-editor.d.ts +4 -4
- package/dist/editor/rich-text-editor.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +23 -9
- package/dist/locales/admin/de.js +5 -66
- package/dist/locales/admin/de.js.map +1 -1
- package/dist/locales/admin/en.d.ts +5 -66
- package/dist/locales/admin/en.js +19 -80
- package/dist/locales/admin/en.js.map +1 -1
- package/dist/locales/admin/es.js +5 -66
- package/dist/locales/admin/es.js.map +1 -1
- package/dist/locales/admin/ja.js +5 -66
- package/dist/locales/admin/ja.js.map +1 -1
- package/dist/locales/admin/ko.js +5 -66
- package/dist/locales/admin/ko.js.map +1 -1
- package/dist/locales/admin/zh.js +5 -66
- package/dist/locales/admin/zh.js.map +1 -1
- package/dist/locales/content/de.d.ts +2 -0
- package/dist/locales/content/de.js +98 -0
- package/dist/locales/content/de.js.map +1 -0
- package/dist/locales/content/en.d.ts +93 -0
- package/dist/locales/content/en.js +98 -0
- package/dist/locales/content/en.js.map +1 -0
- package/dist/locales/content/es.d.ts +2 -0
- package/dist/locales/content/es.js +98 -0
- package/dist/locales/content/es.js.map +1 -0
- package/dist/locales/content/ja.d.ts +2 -0
- package/dist/locales/content/ja.js +98 -0
- package/dist/locales/content/ja.js.map +1 -0
- package/dist/locales/content/ko.d.ts +2 -0
- package/dist/locales/content/ko.js +98 -0
- package/dist/locales/content/ko.js.map +1 -0
- package/dist/locales/content/zh.d.ts +2 -0
- package/dist/locales/content/zh.js +98 -0
- package/dist/locales/content/zh.js.map +1 -0
- package/dist/locales/de.js +11 -2
- package/dist/locales/de.js.map +1 -1
- package/dist/locales/discovery/de.d.ts +2 -0
- package/dist/locales/discovery/de.js +68 -0
- package/dist/locales/discovery/de.js.map +1 -0
- package/dist/locales/discovery/en.d.ts +63 -0
- package/dist/locales/discovery/en.js +68 -0
- package/dist/locales/discovery/en.js.map +1 -0
- package/dist/locales/discovery/es.d.ts +2 -0
- package/dist/locales/discovery/es.js +68 -0
- package/dist/locales/discovery/es.js.map +1 -0
- package/dist/locales/discovery/ja.d.ts +2 -0
- package/dist/locales/discovery/ja.js +68 -0
- package/dist/locales/discovery/ja.js.map +1 -0
- package/dist/locales/discovery/ko.d.ts +2 -0
- package/dist/locales/discovery/ko.js +68 -0
- package/dist/locales/discovery/ko.js.map +1 -0
- package/dist/locales/discovery/zh.d.ts +2 -0
- package/dist/locales/discovery/zh.js +68 -0
- package/dist/locales/discovery/zh.js.map +1 -0
- package/dist/locales/en.d.ts +288 -67
- package/dist/locales/en.js +11 -2
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +11 -2
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/groups/de.d.ts +2 -0
- package/dist/locales/groups/de.js +133 -0
- package/dist/locales/groups/de.js.map +1 -0
- package/dist/locales/groups/en.d.ts +128 -0
- package/dist/locales/groups/en.js +133 -0
- package/dist/locales/groups/en.js.map +1 -0
- package/dist/locales/groups/es.d.ts +2 -0
- package/dist/locales/groups/es.js +133 -0
- package/dist/locales/groups/es.js.map +1 -0
- package/dist/locales/groups/ja.d.ts +2 -0
- package/dist/locales/groups/ja.js +133 -0
- package/dist/locales/groups/ja.js.map +1 -0
- package/dist/locales/groups/ko.d.ts +2 -0
- package/dist/locales/groups/ko.js +133 -0
- package/dist/locales/groups/ko.js.map +1 -0
- package/dist/locales/groups/zh.d.ts +2 -0
- package/dist/locales/groups/zh.js +133 -0
- package/dist/locales/groups/zh.js.map +1 -0
- package/dist/locales/ja.js +11 -2
- package/dist/locales/ja.js.map +1 -1
- package/dist/locales/ko.js +11 -2
- package/dist/locales/ko.js.map +1 -1
- package/dist/locales/social/de.js +2 -1
- package/dist/locales/social/de.js.map +1 -1
- package/dist/locales/social/en.d.ts +2 -1
- package/dist/locales/social/en.js +2 -1
- package/dist/locales/social/en.js.map +1 -1
- package/dist/locales/social/es.js +2 -1
- package/dist/locales/social/es.js.map +1 -1
- package/dist/locales/social/ja.js +2 -1
- package/dist/locales/social/ja.js.map +1 -1
- package/dist/locales/social/ko.js +2 -1
- package/dist/locales/social/ko.js.map +1 -1
- package/dist/locales/social/zh.js +2 -1
- package/dist/locales/social/zh.js.map +1 -1
- package/dist/locales/zh.js +11 -2
- package/dist/locales/zh.js.map +1 -1
- package/dist/react/admin.d.ts +1 -1
- package/dist/react/admin.js +8 -6
- package/dist/react/admin.js.map +1 -1
- package/dist/react/comments.d.ts +9 -7
- package/dist/react/comments.js +42 -27
- package/dist/react/comments.js.map +1 -1
- package/dist/react/contents.d.ts +57 -0
- package/dist/react/contents.js +214 -0
- package/dist/react/contents.js.map +1 -0
- package/dist/react/context.d.ts +1 -1
- package/dist/react/context.js.map +1 -1
- package/dist/react/crop.js +45 -44
- package/dist/react/crop.js.map +1 -1
- package/dist/react/detail.d.ts +30 -0
- package/dist/react/detail.js +42 -0
- package/dist/react/detail.js.map +1 -0
- package/dist/react/discovery.d.ts +138 -0
- package/dist/react/discovery.js +299 -0
- package/dist/react/discovery.js.map +1 -0
- package/dist/react/engagement.d.ts +5 -5
- package/dist/react/engagement.js +55 -41
- package/dist/react/engagement.js.map +1 -1
- package/dist/react/folder.js +54 -53
- package/dist/react/folder.js.map +1 -1
- package/dist/react/groups.d.ts +115 -0
- package/dist/react/groups.js +229 -0
- package/dist/react/groups.js.map +1 -0
- package/dist/react/index.d.ts +5 -1
- package/dist/react/public.d.ts +6 -5
- package/dist/react/public.js +19 -22
- package/dist/react/public.js.map +1 -1
- package/dist/react/read.js +105 -106
- package/dist/react/read.js.map +1 -1
- package/dist/react/resources.d.ts +2 -2
- package/dist/react/resources.js +69 -40
- package/dist/react/resources.js.map +1 -1
- package/dist/react/store.js +41 -39
- package/dist/react/store.js.map +1 -1
- package/dist/react/upload.js +54 -53
- package/dist/react/upload.js.map +1 -1
- package/dist/react/use-resource.d.ts +2 -1
- package/dist/react/use-resource.js +1 -0
- package/dist/react/use-resource.js.map +1 -1
- package/dist/react/versions.d.ts +57 -0
- package/dist/react/versions.js +94 -0
- package/dist/react/versions.js.map +1 -0
- package/dist/react/video.js +87 -86
- package/dist/react/video.js.map +1 -1
- package/dist/react.js +9 -5
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/dist/client/content/posts.d.ts +0 -52
- package/dist/client/content/posts.js +0 -84
- package/dist/client/content/posts.js.map +0 -1
- package/dist/client/taxonomy.d.ts +0 -34
- package/dist/client/taxonomy.js +0 -84
- package/dist/client/taxonomy.js.map +0 -1
- package/dist/components/admin/post-manager.d.ts +0 -45
- package/dist/components/admin/post-manager.js +0 -602
- package/dist/components/admin/post-manager.js.map +0 -1
- package/dist/components/admin/taxonomy-manager.d.ts +0 -54
- package/dist/components/admin/taxonomy-manager.js +0 -976
- package/dist/components/admin/taxonomy-manager.js.map +0 -1
- package/dist/react/posts.d.ts +0 -61
- package/dist/react/posts.js +0 -183
- package/dist/react/posts.js.map +0 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Beacons, Attribution, BeaconOptions, ViewSession } from '../client/beacons.js';
|
|
2
|
+
import { ContentKitClient } from '../client/client.js';
|
|
3
|
+
import { MineQuery } from '../client/content/favorites.js';
|
|
4
|
+
import { ContentQuery, HistoryQuery, RailQuery, ReleaseDatesQuery, SearchQuery, TypeaheadQuery } from '../client/discovery.js';
|
|
5
|
+
import { ContentKitError } from '../client/errors.js';
|
|
6
|
+
import { Card, ContentFilters, ContentFiltersUpdate, DateCount, GroupCard, Interaction, RecentSearch } from '../client/generated/wire.js';
|
|
7
|
+
import { UseList } from './use-resource.js';
|
|
8
|
+
/** Contents as cards, a cursor page at a time; null reads nothing. */
|
|
9
|
+
export declare function useContents(q: ContentQuery | null, o?: {
|
|
10
|
+
client?: ContentKitClient;
|
|
11
|
+
}): UseList<Card>;
|
|
12
|
+
/** Keyword search results as cards; nothing while q.q is empty. */
|
|
13
|
+
export declare function useSearch(q: SearchQuery | null, o?: {
|
|
14
|
+
client?: ContentKitClient;
|
|
15
|
+
}): UseList<Card>;
|
|
16
|
+
export interface UseRail {
|
|
17
|
+
items: Card[];
|
|
18
|
+
loading: boolean;
|
|
19
|
+
error?: ContentKitError;
|
|
20
|
+
/** The site runs without the signal plane (not_configured): leave the rail out. */
|
|
21
|
+
unavailable: boolean;
|
|
22
|
+
reload: () => void;
|
|
23
|
+
}
|
|
24
|
+
/** Contents like one: co-engagement, or the site's configured source. */
|
|
25
|
+
export declare function useSimilar(id: string | null | undefined, q?: RailQuery, o?: {
|
|
26
|
+
client?: ContentKitClient;
|
|
27
|
+
}): UseRail;
|
|
28
|
+
/** Contents for the signed-in reader; nothing signed out, or when q is null. */
|
|
29
|
+
export declare function useRecommendations(q?: RailQuery | null, o?: {
|
|
30
|
+
client?: ContentKitClient;
|
|
31
|
+
}): UseRail;
|
|
32
|
+
/** A release date bucket, keyed by its date. */
|
|
33
|
+
export type ReleaseDate = DateCount & {
|
|
34
|
+
id: string;
|
|
35
|
+
};
|
|
36
|
+
/** The release date index: per month or day, newest first. */
|
|
37
|
+
export declare function useReleaseDates(q?: ReleaseDatesQuery, o?: {
|
|
38
|
+
client?: ContentKitClient;
|
|
39
|
+
}): UseList<ReleaseDate>;
|
|
40
|
+
export interface UseHistory extends UseList<Card> {
|
|
41
|
+
/** Erases the reader's history: of one content item, one kind, or (no argument) everything. */
|
|
42
|
+
forget: (o?: {
|
|
43
|
+
kind?: string;
|
|
44
|
+
content_id?: string;
|
|
45
|
+
}) => Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
/** What the signed-in reader engaged with, most recent first; nothing signed out, or when q is null. */
|
|
48
|
+
export declare function useHistory(q?: HistoryQuery | null, o?: {
|
|
49
|
+
client?: ContentKitClient;
|
|
50
|
+
}): UseHistory;
|
|
51
|
+
export interface UseRecentSearches {
|
|
52
|
+
searches: RecentSearch[];
|
|
53
|
+
loading: boolean;
|
|
54
|
+
error?: ContentKitError;
|
|
55
|
+
/** Clears one query, or every recent search. */
|
|
56
|
+
clear: (query?: string) => Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
/** The reader's recent searches, newest first (signed out, of this tab's session); enabled false reads nothing yet. */
|
|
59
|
+
export declare function useRecentSearches(o?: {
|
|
60
|
+
limit?: number;
|
|
61
|
+
enabled?: boolean;
|
|
62
|
+
client?: ContentKitClient;
|
|
63
|
+
}): UseRecentSearches;
|
|
64
|
+
/** A favorite or reaction with its content's or group's id. */
|
|
65
|
+
export type MyInteraction = Interaction & {
|
|
66
|
+
id: string;
|
|
67
|
+
};
|
|
68
|
+
/** The signed-in reader's favorites, most recent first: content cards or groups. */
|
|
69
|
+
export declare function useMyFavorites(q?: MineQuery, o?: {
|
|
70
|
+
client?: ContentKitClient;
|
|
71
|
+
}): UseList<MyInteraction>;
|
|
72
|
+
/** What the signed-in reader liked (or, with value, disliked), most recent first. */
|
|
73
|
+
export declare function useMyReactions(q?: MineQuery & {
|
|
74
|
+
value?: "like" | "dislike";
|
|
75
|
+
}, o?: {
|
|
76
|
+
client?: ContentKitClient;
|
|
77
|
+
}): UseList<MyInteraction>;
|
|
78
|
+
export interface UseContentFilters {
|
|
79
|
+
/** null until read (and signed out). */
|
|
80
|
+
filters: ContentFilters | null;
|
|
81
|
+
loading: boolean;
|
|
82
|
+
error?: ContentKitError;
|
|
83
|
+
saving: boolean;
|
|
84
|
+
/** Replaces every setting; the lists showing re-read. */
|
|
85
|
+
save: (update: ContentFiltersUpdate) => Promise<ContentFilters>;
|
|
86
|
+
/** Shows or hides one filter's group, keeping the other settings. */
|
|
87
|
+
setVisible: (groupId: string, visible: boolean) => Promise<ContentFilters>;
|
|
88
|
+
setIncludeDeleted: (include: boolean) => Promise<ContentFilters>;
|
|
89
|
+
}
|
|
90
|
+
/** The signed-in reader's content filters: each configured group, its default and their setting. */
|
|
91
|
+
export declare function useContentFilters(o?: {
|
|
92
|
+
language?: string;
|
|
93
|
+
client?: ContentKitClient;
|
|
94
|
+
}): UseContentFilters;
|
|
95
|
+
export interface UseTypeahead {
|
|
96
|
+
contents: Card[];
|
|
97
|
+
groups: GroupCard[];
|
|
98
|
+
/** The query the suggestions answer (trimmed). */
|
|
99
|
+
query: string;
|
|
100
|
+
loading: boolean;
|
|
101
|
+
error?: ContentKitError;
|
|
102
|
+
}
|
|
103
|
+
/** Suggestions while the reader types: debounced, the stale ones abandoned. */
|
|
104
|
+
export declare function useTypeahead(text: string, o?: Omit<TypeaheadQuery, "q"> & {
|
|
105
|
+
debounce?: number;
|
|
106
|
+
minLength?: number;
|
|
107
|
+
client?: ContentKitClient;
|
|
108
|
+
}): UseTypeahead;
|
|
109
|
+
/** The client's signal and exposure batcher: one per client. */
|
|
110
|
+
export declare function beaconsFor(client: ContentKitClient, o?: BeaconOptions): Beacons;
|
|
111
|
+
export declare function useBeacons(o?: {
|
|
112
|
+
client?: ContentKitClient;
|
|
113
|
+
}): Beacons;
|
|
114
|
+
/** A view of a content (or one version) while it is shown: report its progress as it changes. */
|
|
115
|
+
export declare function useViewSignal(content: string | null | undefined, version?: string, o?: Attribution & {
|
|
116
|
+
client?: ContentKitClient;
|
|
117
|
+
}): ViewSession["update"];
|
|
118
|
+
export interface ExposureOptions {
|
|
119
|
+
/** Where the list is: "home", "search", "similar". */
|
|
120
|
+
surface: string;
|
|
121
|
+
/** Changes with what the list shows: a new render id. */
|
|
122
|
+
render: string;
|
|
123
|
+
ranker?: string;
|
|
124
|
+
query_id?: string;
|
|
125
|
+
language?: string;
|
|
126
|
+
client?: ContentKitClient;
|
|
127
|
+
}
|
|
128
|
+
export interface UseExposure {
|
|
129
|
+
render_id: string;
|
|
130
|
+
/** A card's ref: reports it shown once at least half of it is in view. */
|
|
131
|
+
track: (content: string, position: number) => (el: Element | null) => void;
|
|
132
|
+
/** Reports a click on the card at position. */
|
|
133
|
+
click: (content: string, position: number) => void;
|
|
134
|
+
}
|
|
135
|
+
/** A rendered result list: each page rendered, each card shown, clicks attributed to the render. */
|
|
136
|
+
export declare function useExposure(items: readonly {
|
|
137
|
+
id: string;
|
|
138
|
+
}[], o: ExposureOptions): UseExposure;
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { toContentKitError as e } from "../client/errors.js";
|
|
2
|
+
import { ContentKitContext as t, useGuarded as n } from "./context.js";
|
|
3
|
+
import { keyOf as r, useContentScope as i, useList as a, useResource as o } from "./use-resource.js";
|
|
4
|
+
import { Beacons as s, eventId as c } from "../client/beacons.js";
|
|
5
|
+
import { useCallback as l, useContext as u, useEffect as d, useMemo as f, useRef as p, useState as m } from "react";
|
|
6
|
+
//#region src/react/discovery.ts
|
|
7
|
+
var h = (e) => ({
|
|
8
|
+
items: e.contents,
|
|
9
|
+
next: e.next_cursor ?? null
|
|
10
|
+
});
|
|
11
|
+
function g(e) {
|
|
12
|
+
let n = u(t)?.language;
|
|
13
|
+
return f(() => e && !e.display_language && n ? {
|
|
14
|
+
...e,
|
|
15
|
+
display_language: n
|
|
16
|
+
} : e, [e, n]);
|
|
17
|
+
}
|
|
18
|
+
function _(e, t = {}) {
|
|
19
|
+
let { client: n, store: o, scope: s } = i(t.client), c = g(e);
|
|
20
|
+
return a(o, c ? r("cards", s, "list", c) : null, { type: "cards" }, async (e, t) => h(await n.discovery.list({
|
|
21
|
+
...c,
|
|
22
|
+
cursor: e
|
|
23
|
+
}, t)));
|
|
24
|
+
}
|
|
25
|
+
function v(e, t = {}) {
|
|
26
|
+
let { client: n, store: o, scope: s } = i(t.client), c = g(e?.q.trim() ? e : null);
|
|
27
|
+
return a(o, c ? r("cards", s, "search", c) : null, { type: "cards" }, async (e, t) => h(await n.discovery.search({
|
|
28
|
+
...c,
|
|
29
|
+
cursor: e
|
|
30
|
+
}, t)));
|
|
31
|
+
}
|
|
32
|
+
function y(e, t, n) {
|
|
33
|
+
let { store: r } = i(n.client), a = o(r, e, { type: "cards" }, async (e) => (await t(e)).contents), s = a.error?.code === "not_configured";
|
|
34
|
+
return {
|
|
35
|
+
items: a.data ?? [],
|
|
36
|
+
loading: !!e && (a.loading || !a.loaded),
|
|
37
|
+
error: s ? void 0 : a.error,
|
|
38
|
+
unavailable: s,
|
|
39
|
+
reload: a.reload
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function b(e, t = {}, n = {}) {
|
|
43
|
+
let { client: a, scope: o } = i(n.client), s = g(t);
|
|
44
|
+
return y(e ? r("cards", o, "similar", e, s) : null, (t) => a.discovery.similar(e, s, t), n);
|
|
45
|
+
}
|
|
46
|
+
function x(e = {}, t = {}) {
|
|
47
|
+
let { client: n, scope: a, viewer: o } = i(t.client), s = g(e);
|
|
48
|
+
return y(o === null || !s ? null : r("cards", a, "recommended", s), (e) => n.discovery.recommendations(s, e), t);
|
|
49
|
+
}
|
|
50
|
+
function S(e = {}, t = {}) {
|
|
51
|
+
let { client: n, store: o, scope: s } = i(t.client), c = g(e);
|
|
52
|
+
return a(o, r("release-dates", s, c), { type: "release-dates" }, async (e, t) => {
|
|
53
|
+
let r = await n.discovery.releaseDates({
|
|
54
|
+
...c,
|
|
55
|
+
cursor: e
|
|
56
|
+
}, t);
|
|
57
|
+
return {
|
|
58
|
+
items: r.dates.map((e) => ({
|
|
59
|
+
...e,
|
|
60
|
+
id: e.date
|
|
61
|
+
})),
|
|
62
|
+
next: r.next_cursor ?? null
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function C(e = {}, t = {}) {
|
|
67
|
+
let { client: o, store: s, scope: c, viewer: u } = i(t.client), d = g(e), f = n(), p = a(s, u === null || !d ? null : r("history", c, d), { type: "history" }, async (e, t) => h(await o.discovery.history({
|
|
68
|
+
...d,
|
|
69
|
+
cursor: e
|
|
70
|
+
}, t))), m = l((e = {}) => f(() => o.discovery.forgetHistory(e)), [o, f]);
|
|
71
|
+
return {
|
|
72
|
+
...p,
|
|
73
|
+
forget: m
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function w(e = {}) {
|
|
77
|
+
let { client: t, store: a, scope: s } = i(e.client), c = n(), u = e.enabled === !1 ? null : r("searches", s, e.limit ?? 10), d = o(a, u, { type: "searches" }, async (n) => (await t.discovery.recentSearches({ limit: e.limit }, n)).searches), f = l((e) => c(() => t.discovery.clearSearches(e ? { query: e } : {})), [t, c]);
|
|
78
|
+
return {
|
|
79
|
+
searches: d.data ?? [],
|
|
80
|
+
loading: !!u && (d.loading || !d.loaded),
|
|
81
|
+
error: d.error,
|
|
82
|
+
clear: f
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
var T = (e) => ({
|
|
86
|
+
items: e.items.map((e) => ({
|
|
87
|
+
...e,
|
|
88
|
+
id: e.content?.id ?? e.group?.id ?? ""
|
|
89
|
+
})),
|
|
90
|
+
next: e.next_cursor ?? null
|
|
91
|
+
});
|
|
92
|
+
function E(e = {}, t = {}) {
|
|
93
|
+
let { client: n, store: o, scope: s, viewer: c } = i(t.client), l = g(e);
|
|
94
|
+
return a(o, c === null ? null : r("favorites", s, l), { type: "favorites" }, async (e, t) => T(await n.favorites.mine({
|
|
95
|
+
...l,
|
|
96
|
+
cursor: e
|
|
97
|
+
}, t)));
|
|
98
|
+
}
|
|
99
|
+
function D(e = {}, t = {}) {
|
|
100
|
+
let { client: n, store: o, scope: s, viewer: c } = i(t.client), l = g(e);
|
|
101
|
+
return a(o, c === null ? null : r("reactions", s, l), { type: "reactions" }, async (e, t) => T(await n.reactions.mine({
|
|
102
|
+
...l,
|
|
103
|
+
cursor: e
|
|
104
|
+
}, t)));
|
|
105
|
+
}
|
|
106
|
+
function O(e = {}) {
|
|
107
|
+
let { client: t, store: a, scope: s, viewer: c, language: u } = i(e.client), d = e.language ?? u, f = c === null ? null : r("content-filters", s, d), h = o(a, f, { type: "content-filters" }, (e) => t.discovery.contentFilters(d, e)), g = n(), [_, v] = m(0), y = p(h.data);
|
|
108
|
+
y.current = h.data;
|
|
109
|
+
let b = l(async (e) => {
|
|
110
|
+
v((e) => e + 1);
|
|
111
|
+
try {
|
|
112
|
+
let n = await g(() => t.discovery.setContentFilters(e, d));
|
|
113
|
+
return f && a.set(f, n), n;
|
|
114
|
+
} finally {
|
|
115
|
+
v((e) => e - 1);
|
|
116
|
+
}
|
|
117
|
+
}, [
|
|
118
|
+
t,
|
|
119
|
+
g,
|
|
120
|
+
d,
|
|
121
|
+
f,
|
|
122
|
+
a
|
|
123
|
+
]), x = (e) => e.filters.filter((e) => e.overridden).map((e) => ({
|
|
124
|
+
group_id: e.group.id,
|
|
125
|
+
visible: e.visible
|
|
126
|
+
})), S = l((e, t) => {
|
|
127
|
+
let n = y.current;
|
|
128
|
+
return n ? b({
|
|
129
|
+
filters: [...x(n).filter((t) => t.group_id !== e), {
|
|
130
|
+
group_id: e,
|
|
131
|
+
visible: t
|
|
132
|
+
}],
|
|
133
|
+
include_deleted: n.include_deleted
|
|
134
|
+
}) : Promise.reject(/* @__PURE__ */ Error("contentkit-ui: the content filters have not loaded"));
|
|
135
|
+
}, [b]), C = l((e) => {
|
|
136
|
+
let t = y.current;
|
|
137
|
+
return t ? b({
|
|
138
|
+
filters: x(t),
|
|
139
|
+
include_deleted: e
|
|
140
|
+
}) : Promise.reject(/* @__PURE__ */ Error("contentkit-ui: the content filters have not loaded"));
|
|
141
|
+
}, [b]);
|
|
142
|
+
return {
|
|
143
|
+
filters: h.data ?? null,
|
|
144
|
+
loading: !!f && (h.loading || !h.loaded),
|
|
145
|
+
error: h.error,
|
|
146
|
+
saving: _ > 0,
|
|
147
|
+
save: b,
|
|
148
|
+
setVisible: S,
|
|
149
|
+
setIncludeDeleted: C
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
var k = {
|
|
153
|
+
contents: [],
|
|
154
|
+
groups: []
|
|
155
|
+
};
|
|
156
|
+
function A(t, n = {}) {
|
|
157
|
+
let { client: r, language: a } = i(n.client), { debounce: o = 150, minLength: s = 1, client: c, ...l } = n, u = t.trim(), p = f(() => ({
|
|
158
|
+
display_language: a,
|
|
159
|
+
...l,
|
|
160
|
+
q: u
|
|
161
|
+
}), [
|
|
162
|
+
a,
|
|
163
|
+
u,
|
|
164
|
+
JSON.stringify(l)
|
|
165
|
+
]), [h, g] = m({
|
|
166
|
+
...k,
|
|
167
|
+
query: "",
|
|
168
|
+
loading: !1
|
|
169
|
+
});
|
|
170
|
+
return d(() => {
|
|
171
|
+
if (u.length < s) {
|
|
172
|
+
g({
|
|
173
|
+
...k,
|
|
174
|
+
query: "",
|
|
175
|
+
loading: !1
|
|
176
|
+
});
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
g((e) => ({
|
|
180
|
+
...e,
|
|
181
|
+
loading: !0
|
|
182
|
+
}));
|
|
183
|
+
let t = new AbortController(), n = setTimeout(() => {
|
|
184
|
+
r.discovery.typeahead(p, t.signal).then((e) => g({
|
|
185
|
+
contents: e.contents,
|
|
186
|
+
groups: e.groups,
|
|
187
|
+
query: u,
|
|
188
|
+
loading: !1
|
|
189
|
+
}), (t) => {
|
|
190
|
+
let n = e(t);
|
|
191
|
+
n.code !== "aborted" && g({
|
|
192
|
+
...k,
|
|
193
|
+
query: u,
|
|
194
|
+
loading: !1,
|
|
195
|
+
error: n
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
}, o);
|
|
199
|
+
return () => {
|
|
200
|
+
clearTimeout(n), t.abort();
|
|
201
|
+
};
|
|
202
|
+
}, [
|
|
203
|
+
r,
|
|
204
|
+
p,
|
|
205
|
+
u,
|
|
206
|
+
o,
|
|
207
|
+
s
|
|
208
|
+
]), h;
|
|
209
|
+
}
|
|
210
|
+
var j = /* @__PURE__ */ new WeakMap();
|
|
211
|
+
function M(e, t) {
|
|
212
|
+
let n = j.get(e);
|
|
213
|
+
return n || j.set(e, n = new s(e.discovery, t)), n;
|
|
214
|
+
}
|
|
215
|
+
function N(e = {}) {
|
|
216
|
+
let { client: t } = i(e.client);
|
|
217
|
+
return M(t);
|
|
218
|
+
}
|
|
219
|
+
function P(e, t, n = {}) {
|
|
220
|
+
let r = N(n), { client: i, ...a } = n, o = f(() => e ? r.view(e, t, a) : null, [
|
|
221
|
+
r,
|
|
222
|
+
e,
|
|
223
|
+
t
|
|
224
|
+
]);
|
|
225
|
+
return l((e) => o?.update(e), [o]);
|
|
226
|
+
}
|
|
227
|
+
function F(e, t) {
|
|
228
|
+
let n = N(t), r = f(() => c(), [t.render]), i = f(() => ({
|
|
229
|
+
render_id: r,
|
|
230
|
+
surface: t.surface,
|
|
231
|
+
ranker: t.ranker,
|
|
232
|
+
query_id: t.query_id,
|
|
233
|
+
language: t.language
|
|
234
|
+
}), [
|
|
235
|
+
r,
|
|
236
|
+
t.surface,
|
|
237
|
+
t.ranker,
|
|
238
|
+
t.query_id,
|
|
239
|
+
t.language
|
|
240
|
+
]), a = p(/* @__PURE__ */ new Set()), o = p(/* @__PURE__ */ new Set());
|
|
241
|
+
d(() => {
|
|
242
|
+
a.current = /* @__PURE__ */ new Set(), o.current = /* @__PURE__ */ new Set();
|
|
243
|
+
}, [r]), d(() => {
|
|
244
|
+
let t = e.flatMap((e, t) => a.current.has(e.id) ? [] : [{
|
|
245
|
+
content_id: e.id,
|
|
246
|
+
position: t + 1
|
|
247
|
+
}]);
|
|
248
|
+
for (let e of t) a.current.add(e.content_id);
|
|
249
|
+
t.length && n.exposure({
|
|
250
|
+
...i,
|
|
251
|
+
stage: "rendered",
|
|
252
|
+
occurred_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
253
|
+
shown: t
|
|
254
|
+
});
|
|
255
|
+
}, [
|
|
256
|
+
n,
|
|
257
|
+
i,
|
|
258
|
+
e
|
|
259
|
+
]);
|
|
260
|
+
let s = p([]), u = p(void 0), m = f(() => typeof IntersectionObserver == "function" ? new IntersectionObserver((e) => {
|
|
261
|
+
for (let t of e) {
|
|
262
|
+
if (!t.isIntersecting) continue;
|
|
263
|
+
let e = t.target, n = e.dataset.exposureContent;
|
|
264
|
+
o.current.has(n) || (o.current.add(n), s.current.push({
|
|
265
|
+
content_id: n,
|
|
266
|
+
position: Number(e.dataset.exposurePosition)
|
|
267
|
+
}));
|
|
268
|
+
}
|
|
269
|
+
u.current ??= setTimeout(() => {
|
|
270
|
+
u.current = void 0;
|
|
271
|
+
let e = s.current.splice(0);
|
|
272
|
+
e.length && n.exposure({
|
|
273
|
+
...i,
|
|
274
|
+
stage: "visible",
|
|
275
|
+
occurred_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
276
|
+
shown: e
|
|
277
|
+
});
|
|
278
|
+
}, 300);
|
|
279
|
+
}, { threshold: .5 }) : null, [n, i]);
|
|
280
|
+
return d(() => () => m?.disconnect(), [m]), {
|
|
281
|
+
render_id: r,
|
|
282
|
+
track: l((e, t) => (n) => {
|
|
283
|
+
n && m && (n.dataset.exposureContent = e, n.dataset.exposurePosition = String(t), m.observe(n));
|
|
284
|
+
}, [m]),
|
|
285
|
+
click: l((e, i) => n.click(e, {
|
|
286
|
+
render_id: r,
|
|
287
|
+
surface: t.surface,
|
|
288
|
+
position: i
|
|
289
|
+
}), [
|
|
290
|
+
n,
|
|
291
|
+
r,
|
|
292
|
+
t.surface
|
|
293
|
+
])
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
//#endregion
|
|
297
|
+
export { M as beaconsFor, N as useBeacons, O as useContentFilters, _ as useContents, F as useExposure, C as useHistory, E as useMyFavorites, D as useMyReactions, w as useRecentSearches, x as useRecommendations, S as useReleaseDates, v as useSearch, b as useSimilar, A as useTypeahead, P as useViewSignal };
|
|
298
|
+
|
|
299
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","names":[],"sources":["../../src/react/discovery.ts"],"sourcesContent":["import { useCallback, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport { Beacons, eventId, type Attribution, type BeaconOptions, type ViewSession } from \"../client/beacons.js\";\nimport type { ContentKitClient } from \"../client/client.js\";\nimport type { MineQuery } from \"../client/content/favorites.js\";\nimport type { ContentQuery, HistoryQuery, RailQuery, ReleaseDatesQuery, SearchQuery, TypeaheadQuery } from \"../client/discovery.js\";\nimport { toContentKitError, type ContentKitError } from \"../client/errors.js\";\nimport type { Card, ContentFilters, ContentFiltersUpdate, ContentPage, DateCount, GroupCard, Interaction, InteractionPage, RecentSearch } from \"../client/generated/wire.js\";\nimport { ContentKitContext, useGuarded } from \"./context.js\";\nimport { keyOf, useContentScope, useList, useResource, type UseList } from \"./use-resource.js\";\n\nconst page = (p: ContentPage) => ({ items: p.contents, next: p.next_cursor ?? null });\n\n/** Titles, names and paths in the provider's language unless the query says otherwise. */\nfunction useDisplay<T extends { display_language?: string }>(q: T | null): T | null {\n const language = useContext(ContentKitContext)?.language;\n return useMemo(() => (q && !q.display_language && language ? { ...q, display_language: language } : q), [q, language]);\n}\n\n/** Contents as cards, a cursor page at a time; null reads nothing. */\nexport function useContents(q: ContentQuery | null, o: { client?: ContentKitClient } = {}): UseList<Card> {\n const { client, store, scope } = useContentScope(o.client);\n const query = useDisplay(q);\n return useList(store, query ? keyOf(\"cards\", scope, \"list\", query) : null, { type: \"cards\" }, async (cursor, signal) =>\n page(await client.discovery.list({ ...query, cursor: cursor as string | undefined }, signal)),\n );\n}\n\n/** Keyword search results as cards; nothing while q.q is empty. */\nexport function useSearch(q: SearchQuery | null, o: { client?: ContentKitClient } = {}): UseList<Card> {\n const { client, store, scope } = useContentScope(o.client);\n const query = useDisplay(q?.q.trim() ? q : null);\n return useList(store, query ? keyOf(\"cards\", scope, \"search\", query) : null, { type: \"cards\" }, async (cursor, signal) =>\n page(await client.discovery.search({ ...query!, cursor: cursor as string | undefined }, signal)),\n );\n}\n\nexport interface UseRail {\n items: Card[];\n loading: boolean;\n error?: ContentKitError;\n /** The site runs without the signal plane (not_configured): leave the rail out. */\n unavailable: boolean;\n reload: () => void;\n}\n\nfunction useRail(key: string | null, fetch: (signal: AbortSignal) => Promise<ContentPage>, o: { client?: ContentKitClient }): UseRail {\n const { store } = useContentScope(o.client);\n const r = useResource<Card[]>(store, key, { type: \"cards\" }, async (signal) => (await fetch(signal)).contents);\n const unavailable = r.error?.code === \"not_configured\";\n return { items: r.data ?? [], loading: !!key && (r.loading || !r.loaded), error: unavailable ? undefined : r.error, unavailable, reload: r.reload };\n}\n\n/** Contents like one: co-engagement, or the site's configured source. */\nexport function useSimilar(id: string | null | undefined, q: RailQuery = {}, o: { client?: ContentKitClient } = {}): UseRail {\n const { client, scope } = useContentScope(o.client);\n const query = useDisplay(q)!;\n return useRail(id ? keyOf(\"cards\", scope, \"similar\", id, query) : null, (s) => client.discovery.similar(id!, query, s), o);\n}\n\n/** Contents for the signed-in reader; nothing signed out, or when q is null. */\nexport function useRecommendations(q: RailQuery | null = {}, o: { client?: ContentKitClient } = {}): UseRail {\n const { client, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q);\n return useRail(viewer === null || !query ? null : keyOf(\"cards\", scope, \"recommended\", query), (s) => client.discovery.recommendations(query!, s), o);\n}\n\n/** A release date bucket, keyed by its date. */\nexport type ReleaseDate = DateCount & { id: string };\n\n/** The release date index: per month or day, newest first. */\nexport function useReleaseDates(q: ReleaseDatesQuery = {}, o: { client?: ContentKitClient } = {}): UseList<ReleaseDate> {\n const { client, store, scope } = useContentScope(o.client);\n const query = useDisplay(q)!;\n return useList(store, keyOf(\"release-dates\", scope, query), { type: \"release-dates\" }, async (cursor, signal) => {\n const r = await client.discovery.releaseDates({ ...query, cursor: cursor as string | undefined }, signal);\n return { items: r.dates.map((d) => ({ ...d, id: d.date })), next: r.next_cursor ?? null };\n });\n}\n\nexport interface UseHistory extends UseList<Card> {\n /** Erases the reader's history: of one content item, one kind, or (no argument) everything. */\n forget: (o?: { kind?: string; content_id?: string }) => Promise<void>;\n}\n\n/** What the signed-in reader engaged with, most recent first; nothing signed out, or when q is null. */\nexport function useHistory(q: HistoryQuery | null = {}, o: { client?: ContentKitClient } = {}): UseHistory {\n const { client, store, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q);\n const guarded = useGuarded();\n const list = useList(store, viewer === null || !query ? null : keyOf(\"history\", scope, query), { type: \"history\" }, async (cursor, signal) =>\n page(await client.discovery.history({ ...query, cursor: cursor as string | undefined }, signal)),\n );\n const forget = useCallback((f: { kind?: string; content_id?: string } = {}) => guarded(() => client.discovery.forgetHistory(f)), [client, guarded]);\n return { ...list, forget };\n}\n\nexport interface UseRecentSearches {\n searches: RecentSearch[];\n loading: boolean;\n error?: ContentKitError;\n /** Clears one query, or every recent search. */\n clear: (query?: string) => Promise<void>;\n}\n\n/** The reader's recent searches, newest first (signed out, of this tab's session); enabled false reads nothing yet. */\nexport function useRecentSearches(o: { limit?: number; enabled?: boolean; client?: ContentKitClient } = {}): UseRecentSearches {\n const { client, store, scope } = useContentScope(o.client);\n const guarded = useGuarded();\n const key = o.enabled === false ? null : keyOf(\"searches\", scope, o.limit ?? 10);\n const r = useResource<RecentSearch[]>(store, key, { type: \"searches\" }, async (s) => (await client.discovery.recentSearches({ limit: o.limit }, s)).searches);\n const clear = useCallback((query?: string) => guarded(() => client.discovery.clearSearches(query ? { query } : {})), [client, guarded]);\n return { searches: r.data ?? [], loading: !!key && (r.loading || !r.loaded), error: r.error, clear };\n}\n\n/** A favorite or reaction with its content's or group's id. */\nexport type MyInteraction = Interaction & { id: string };\n\nconst interactions = (p: InteractionPage) => ({ items: p.items.map((x) => ({ ...x, id: x.content?.id ?? x.group?.id ?? \"\" })), next: p.next_cursor ?? null });\n\n/** The signed-in reader's favorites, most recent first: content cards or groups. */\nexport function useMyFavorites(q: MineQuery = {}, o: { client?: ContentKitClient } = {}): UseList<MyInteraction> {\n const { client, store, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q)!;\n return useList(store, viewer === null ? null : keyOf(\"favorites\", scope, query), { type: \"favorites\" }, async (cursor, signal) =>\n interactions(await client.favorites.mine({ ...query, cursor: cursor as string | undefined }, signal)),\n );\n}\n\n/** What the signed-in reader liked (or, with value, disliked), most recent first. */\nexport function useMyReactions(q: MineQuery & { value?: \"like\" | \"dislike\" } = {}, o: { client?: ContentKitClient } = {}): UseList<MyInteraction> {\n const { client, store, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q)!;\n return useList(store, viewer === null ? null : keyOf(\"reactions\", scope, query), { type: \"reactions\" }, async (cursor, signal) =>\n interactions(await client.reactions.mine({ ...query, cursor: cursor as string | undefined }, signal)),\n );\n}\n\nexport interface UseContentFilters {\n /** null until read (and signed out). */\n filters: ContentFilters | null;\n loading: boolean;\n error?: ContentKitError;\n saving: boolean;\n /** Replaces every setting; the lists showing re-read. */\n save: (update: ContentFiltersUpdate) => Promise<ContentFilters>;\n /** Shows or hides one filter's group, keeping the other settings. */\n setVisible: (groupId: string, visible: boolean) => Promise<ContentFilters>;\n setIncludeDeleted: (include: boolean) => Promise<ContentFilters>;\n}\n\n/** The signed-in reader's content filters: each configured group, its default and their setting. */\nexport function useContentFilters(o: { language?: string; client?: ContentKitClient } = {}): UseContentFilters {\n const { client, store, scope, viewer, language: provided } = useContentScope(o.client);\n const language = o.language ?? provided;\n const key = viewer === null ? null : keyOf(\"content-filters\", scope, language);\n const r = useResource<ContentFilters>(store, key, { type: \"content-filters\" }, (s) => client.discovery.contentFilters(language, s));\n const guarded = useGuarded();\n const [inflight, setInflight] = useState(0);\n const current = useRef(r.data);\n current.current = r.data;\n const save = useCallback(\n async (update: ContentFiltersUpdate) => {\n setInflight((n) => n + 1);\n try {\n const out = await guarded(() => client.discovery.setContentFilters(update, language));\n if (key) store.set(key, out);\n return out;\n } finally {\n setInflight((n) => n - 1);\n }\n },\n [client, guarded, language, key, store],\n );\n const settings = (f: ContentFilters) => f.filters.filter((x) => x.overridden).map((x) => ({ group_id: x.group.id, visible: x.visible }));\n const setVisible = useCallback(\n (groupId: string, visible: boolean) => {\n const f = current.current;\n if (!f) return Promise.reject(new Error(\"contentkit-ui: the content filters have not loaded\"));\n return save({ filters: [...settings(f).filter((x) => x.group_id !== groupId), { group_id: groupId, visible }], include_deleted: f.include_deleted });\n },\n [save],\n );\n const setIncludeDeleted = useCallback(\n (include: boolean) => {\n const f = current.current;\n if (!f) return Promise.reject(new Error(\"contentkit-ui: the content filters have not loaded\"));\n return save({ filters: settings(f), include_deleted: include });\n },\n [save],\n );\n return { filters: r.data ?? null, loading: !!key && (r.loading || !r.loaded), error: r.error, saving: inflight > 0, save, setVisible, setIncludeDeleted };\n}\n\nexport interface UseTypeahead {\n contents: Card[];\n groups: GroupCard[];\n /** The query the suggestions answer (trimmed). */\n query: string;\n loading: boolean;\n error?: ContentKitError;\n}\n\nconst NONE: Pick<UseTypeahead, \"contents\" | \"groups\"> = { contents: [], groups: [] };\n\n/** Suggestions while the reader types: debounced, the stale ones abandoned. */\nexport function useTypeahead(\n text: string,\n o: Omit<TypeaheadQuery, \"q\"> & { debounce?: number; minLength?: number; client?: ContentKitClient } = {},\n): UseTypeahead {\n const { client, language } = useContentScope(o.client);\n const { debounce = 150, minLength = 1, client: _own, ...rest } = o;\n const q = text.trim();\n const query = useMemo(() => ({ display_language: language, ...rest, q }), [language, q, JSON.stringify(rest)]); // eslint-disable-line react-hooks/exhaustive-deps\n const [state, setState] = useState<UseTypeahead>({ ...NONE, query: \"\", loading: false });\n useEffect(() => {\n if (q.length < minLength) {\n setState({ ...NONE, query: \"\", loading: false });\n return;\n }\n setState((s) => ({ ...s, loading: true }));\n const ctl = new AbortController();\n const timer = setTimeout(() => {\n client.discovery.typeahead(query, ctl.signal).then(\n (r) => setState({ contents: r.contents, groups: r.groups, query: q, loading: false }),\n (e) => {\n const error = toContentKitError(e);\n if (error.code !== \"aborted\") setState({ ...NONE, query: q, loading: false, error });\n },\n );\n }, debounce);\n return () => {\n clearTimeout(timer);\n ctl.abort();\n };\n }, [client, query, q, debounce, minLength]);\n return state;\n}\n\nconst beacons = new WeakMap<ContentKitClient, Beacons>();\n\n/** The client's signal and exposure batcher: one per client. */\nexport function beaconsFor(client: ContentKitClient, o?: BeaconOptions): Beacons {\n let b = beacons.get(client);\n if (!b) beacons.set(client, (b = new Beacons(client.discovery, o)));\n return b;\n}\n\nexport function useBeacons(o: { client?: ContentKitClient } = {}): Beacons {\n const { client } = useContentScope(o.client);\n return beaconsFor(client);\n}\n\n/** A view of a content (or one version) while it is shown: report its progress as it changes. */\nexport function useViewSignal(content: string | null | undefined, version?: string, o: Attribution & { client?: ContentKitClient } = {}): ViewSession[\"update\"] {\n const b = useBeacons(o);\n const { client: _c, ...attribution } = o;\n const session = useMemo(() => (content ? b.view(content, version, attribution) : null), [b, content, version]); // eslint-disable-line react-hooks/exhaustive-deps\n return useCallback((u) => session?.update(u), [session]);\n}\n\nexport interface ExposureOptions {\n /** Where the list is: \"home\", \"search\", \"similar\". */\n surface: string;\n /** Changes with what the list shows: a new render id. */\n render: string;\n ranker?: string;\n query_id?: string;\n language?: string;\n client?: ContentKitClient;\n}\n\nexport interface UseExposure {\n render_id: string;\n /** A card's ref: reports it shown once at least half of it is in view. */\n track: (content: string, position: number) => (el: Element | null) => void;\n /** Reports a click on the card at position. */\n click: (content: string, position: number) => void;\n}\n\n/** A rendered result list: each page rendered, each card shown, clicks attributed to the render. */\nexport function useExposure(items: readonly { id: string }[], o: ExposureOptions): UseExposure {\n const b = useBeacons(o);\n const renderId = useMemo(() => eventId(), [o.render]); // eslint-disable-line react-hooks/exhaustive-deps\n const base = useMemo(() => ({ render_id: renderId, surface: o.surface, ranker: o.ranker, query_id: o.query_id, language: o.language }), [renderId, o.surface, o.ranker, o.query_id, o.language]);\n const rendered = useRef(new Set<string>());\n const visible = useRef(new Set<string>());\n useEffect(() => {\n rendered.current = new Set();\n visible.current = new Set();\n }, [renderId]);\n useEffect(() => {\n const shown = items.flatMap((it, i) => (rendered.current.has(it.id) ? [] : [{ content_id: it.id, position: i + 1 }]));\n for (const s of shown) rendered.current.add(s.content_id);\n if (shown.length) b.exposure({ ...base, stage: \"rendered\", occurred_at: new Date().toISOString(), shown });\n }, [b, base, items]);\n const pending = useRef<{ content_id: string; position: number }[]>([]);\n const timer = useRef<ReturnType<typeof setTimeout>>(undefined);\n const observer = useMemo(() => {\n if (typeof IntersectionObserver !== \"function\") return null;\n return new IntersectionObserver(\n (entries) => {\n for (const e of entries) {\n if (!e.isIntersecting) continue;\n const el = e.target as HTMLElement;\n const content = el.dataset.exposureContent!;\n if (visible.current.has(content)) continue;\n visible.current.add(content);\n pending.current.push({ content_id: content, position: Number(el.dataset.exposurePosition) });\n }\n timer.current ??= setTimeout(() => {\n timer.current = undefined;\n const shown = pending.current.splice(0);\n if (shown.length) b.exposure({ ...base, stage: \"visible\", occurred_at: new Date().toISOString(), shown });\n }, 300);\n },\n { threshold: 0.5 },\n );\n }, [b, base]);\n useEffect(() => () => observer?.disconnect(), [observer]);\n const track = useCallback(\n (content: string, position: number) => (el: Element | null) => {\n if (!el || !observer) return;\n (el as HTMLElement).dataset.exposureContent = content;\n (el as HTMLElement).dataset.exposurePosition = String(position);\n observer.observe(el);\n },\n [observer],\n );\n const click = useCallback((content: string, position: number) => b.click(content, { render_id: renderId, surface: o.surface, position }), [b, renderId, o.surface]);\n return { render_id: renderId, track, click };\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ContentKitClient } from '../client/client.js';
|
|
2
2
|
import { ContentKitError } from '../client/errors.js';
|
|
3
|
-
import { Reaction } from '../client/content/types.js';
|
|
4
|
-
import { FavoriteState, ReactionCounts
|
|
3
|
+
import { Reaction, Target } from '../client/content/types.js';
|
|
4
|
+
import { FavoriteState, ReactionCounts } from '../client/generated/wire.js';
|
|
5
5
|
export interface UseReaction {
|
|
6
6
|
counts: ReactionCounts;
|
|
7
7
|
loading: boolean;
|
|
@@ -11,8 +11,8 @@ export interface UseReaction {
|
|
|
11
11
|
/** Sets value, or clears it when it is the current one. */
|
|
12
12
|
toggle: (value: 1 | -1) => Promise<void>;
|
|
13
13
|
}
|
|
14
|
-
/**
|
|
15
|
-
export declare function useReaction(
|
|
14
|
+
/** A target's likes and dislikes and the caller's own reaction (initial: counts the host already has). */
|
|
15
|
+
export declare function useReaction(target: Target, o?: {
|
|
16
16
|
initial?: ReactionCounts;
|
|
17
17
|
client?: ContentKitClient;
|
|
18
18
|
}): UseReaction;
|
|
@@ -32,7 +32,7 @@ export interface UseFavorite {
|
|
|
32
32
|
* An item's favorite count and whether the signed-in caller favorited it
|
|
33
33
|
* (initial: what the host already has). Signed out, favorited stays false.
|
|
34
34
|
*/
|
|
35
|
-
export declare function useFavorite(
|
|
35
|
+
export declare function useFavorite(target: Target, o?: {
|
|
36
36
|
initial?: FavoriteState;
|
|
37
37
|
client?: ContentKitClient;
|
|
38
38
|
}): UseFavorite;
|
package/dist/react/engagement.js
CHANGED
|
@@ -9,77 +9,91 @@ var s = {
|
|
|
9
9
|
mine: 0
|
|
10
10
|
};
|
|
11
11
|
function c(o, c = {}) {
|
|
12
|
-
let { client: l, store: u, scope: d } = n(c.client), f = t("reaction", d,
|
|
12
|
+
let { client: l, store: u, scope: d } = n(c.client), { type: f, id: p, version: m } = o, h = t("reaction", d, f, p, m), g = r(u, h, {
|
|
13
13
|
type: "reaction",
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
id:
|
|
14
|
+
target: {
|
|
15
|
+
type: f,
|
|
16
|
+
id: p,
|
|
17
|
+
version: m
|
|
17
18
|
}
|
|
18
|
-
}, (e) => l.reactions.get(
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
}, (e) => l.reactions.get({
|
|
20
|
+
type: f,
|
|
21
|
+
id: p,
|
|
22
|
+
version: m
|
|
23
|
+
}, e), { initial: c.initial }), _ = g.data ?? s, v = a(async (t) => {
|
|
24
|
+
let n = u.snapshot(h).data ?? _, r = u.mark(h);
|
|
25
|
+
u.set(h, i(n, t));
|
|
21
26
|
try {
|
|
22
27
|
await l.reactions.set({
|
|
23
|
-
|
|
24
|
-
id:
|
|
28
|
+
type: f,
|
|
29
|
+
id: p,
|
|
30
|
+
version: m
|
|
25
31
|
}, t);
|
|
26
32
|
} catch (t) {
|
|
27
|
-
throw u.rollback(
|
|
33
|
+
throw u.rollback(h, r, n), e(t);
|
|
28
34
|
}
|
|
29
35
|
}, [
|
|
30
36
|
l,
|
|
31
37
|
u,
|
|
32
|
-
f,
|
|
33
38
|
h,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
f,
|
|
40
|
+
p,
|
|
41
|
+
m,
|
|
42
|
+
_
|
|
43
|
+
]), y = a((e) => v(_.mine === e ? 0 : e), [v, _.mine]);
|
|
37
44
|
return {
|
|
38
|
-
counts:
|
|
39
|
-
loading:
|
|
40
|
-
error:
|
|
41
|
-
set:
|
|
42
|
-
toggle:
|
|
45
|
+
counts: _,
|
|
46
|
+
loading: g.loading || !g.loaded && c.initial === void 0,
|
|
47
|
+
error: g.error,
|
|
48
|
+
set: v,
|
|
49
|
+
toggle: y
|
|
43
50
|
};
|
|
44
51
|
}
|
|
45
52
|
function l(i, s = {}) {
|
|
46
|
-
let { client: c, store: l, scope: u } = n(s.client), d = t("favorite", u,
|
|
53
|
+
let { client: c, store: l, scope: u } = n(s.client), { type: d, id: f, version: p } = i, m = t("favorite", u, d, f, p), h = r(l, m, {
|
|
47
54
|
type: "favorite",
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
id:
|
|
55
|
+
target: {
|
|
56
|
+
type: d,
|
|
57
|
+
id: f,
|
|
58
|
+
version: p
|
|
51
59
|
}
|
|
52
|
-
}, (e) => c.favorites.get(
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
}, (e) => c.favorites.get({
|
|
61
|
+
type: d,
|
|
62
|
+
id: f,
|
|
63
|
+
version: p
|
|
64
|
+
}, e), { initial: s.initial }), g = !!h.data?.favorited, [_, v] = o(!1), y = a(async (t) => {
|
|
65
|
+
let n = l.snapshot(m).data, r = l.mark(m);
|
|
66
|
+
n && n.favorited !== t && l.set(m, {
|
|
55
67
|
favorited: t,
|
|
56
68
|
count: Math.max(0, n.count + (t ? 1 : -1))
|
|
57
|
-
}),
|
|
69
|
+
}), v(!0);
|
|
58
70
|
try {
|
|
59
71
|
await c.favorites.set({
|
|
60
|
-
|
|
61
|
-
id:
|
|
72
|
+
type: d,
|
|
73
|
+
id: f,
|
|
74
|
+
version: p
|
|
62
75
|
}, t);
|
|
63
76
|
} catch (t) {
|
|
64
|
-
throw n && l.rollback(
|
|
77
|
+
throw n && l.rollback(m, r, n), e(t);
|
|
65
78
|
} finally {
|
|
66
|
-
|
|
79
|
+
v(!1);
|
|
67
80
|
}
|
|
68
81
|
}, [
|
|
69
82
|
c,
|
|
70
83
|
l,
|
|
84
|
+
m,
|
|
71
85
|
d,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
]),
|
|
86
|
+
f,
|
|
87
|
+
p
|
|
88
|
+
]), b = a(() => y(!g), [y, g]);
|
|
75
89
|
return {
|
|
76
|
-
favorited:
|
|
77
|
-
count:
|
|
78
|
-
loading:
|
|
79
|
-
pending:
|
|
80
|
-
error:
|
|
81
|
-
set:
|
|
82
|
-
toggle:
|
|
90
|
+
favorited: g,
|
|
91
|
+
count: h.data?.count,
|
|
92
|
+
loading: h.loading || !h.loaded && s.initial === void 0,
|
|
93
|
+
pending: _,
|
|
94
|
+
error: h.error,
|
|
95
|
+
set: y,
|
|
96
|
+
toggle: b
|
|
83
97
|
};
|
|
84
98
|
}
|
|
85
99
|
//#endregion
|