@burdenoff/microfe-theculturepost 2026.1030.1 → 2026.1031.2
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/dist/stories/AddCitationDialog.stories.d.ts +11 -0
- package/dist/stories/AddCitationDialog.stories.d.ts.map +1 -0
- package/dist/stories/ArchiveItemCard.stories.d.ts +9 -0
- package/dist/stories/ArchiveItemCard.stories.d.ts.map +1 -0
- package/dist/stories/CitationList.stories.d.ts +13 -0
- package/dist/stories/CitationList.stories.d.ts.map +1 -0
- package/dist/stories/DiscussionCard.stories.d.ts +9 -0
- package/dist/stories/DiscussionCard.stories.d.ts.map +1 -0
- package/dist/stories/RecordOralHistoryDialog.stories.d.ts +11 -0
- package/dist/stories/RecordOralHistoryDialog.stories.d.ts.map +1 -0
- package/dist/stories/ReplyThread.stories.d.ts +12 -0
- package/dist/stories/ReplyThread.stories.d.ts.map +1 -0
- package/dist/stories/StoryCard.stories.d.ts +11 -0
- package/dist/stories/StoryCard.stories.d.ts.map +1 -0
- package/dist/stories/support/fixtures.d.ts +19 -0
- package/dist/stories/support/fixtures.d.ts.map +1 -0
- package/dist/stories/support/graphqlMock.d.ts +18 -0
- package/dist/stories/support/graphqlMock.d.ts.map +1 -0
- package/dist/stories/support/variables.d.ts +11 -0
- package/dist/stories/support/variables.d.ts.map +1 -0
- package/dist/stories/support/withTcpProviders.d.ts +13 -0
- package/dist/stories/support/withTcpProviders.d.ts.map +1 -0
- package/dist/theculturepost/analytics/index.d.ts +7 -0
- package/dist/theculturepost/analytics/index.d.ts.map +1 -0
- package/dist/theculturepost/analytics/index.js +2 -0
- package/dist/theculturepost/analytics/theculturepostAnalytics.d.ts +127 -0
- package/dist/theculturepost/analytics/theculturepostAnalytics.d.ts.map +1 -0
- package/dist/theculturepost/analytics/theculturepostAnalytics.js +135 -0
- package/dist/theculturepost/analytics/theculturepostAnalytics.js.map +1 -0
- package/dist/theculturepost/analytics/useTheculturepostAnalytics.d.ts +5 -0
- package/dist/theculturepost/analytics/useTheculturepostAnalytics.d.ts.map +1 -0
- package/dist/theculturepost/analytics/useTheculturepostAnalytics.js +15 -0
- package/dist/theculturepost/analytics/useTheculturepostAnalytics.js.map +1 -0
- package/dist/theculturepost/hooks/usePageAnalytics.d.ts +13 -4
- package/dist/theculturepost/hooks/usePageAnalytics.d.ts.map +1 -1
- package/dist/theculturepost/hooks/usePageAnalytics.js +19 -26
- package/dist/theculturepost/hooks/usePageAnalytics.js.map +1 -1
- package/dist/theculturepost/hooks/useTcpApi.d.ts +6 -6
- package/dist/theculturepost/hooks/useTcpApi.d.ts.map +1 -1
- package/dist/theculturepost/hooks/useTcpApi.js +242 -239
- package/dist/theculturepost/hooks/useTcpApi.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { AddCitationDialog } from '../theculturepost/components/AddCitationDialog';
|
|
3
|
+
|
|
4
|
+
declare const meta: Meta<typeof AddCitationDialog>;
|
|
5
|
+
export default meta;
|
|
6
|
+
type Story = StoryObj<typeof meta>;
|
|
7
|
+
export declare const Open: Story;
|
|
8
|
+
export declare const TitleIsRequired: Story;
|
|
9
|
+
export declare const SubmitsCitationForClaim: Story;
|
|
10
|
+
export declare const ServerErrorIsShown: Story;
|
|
11
|
+
//# sourceMappingURL=AddCitationDialog.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AddCitationDialog.stories.d.ts","sourceRoot":"","sources":["../../src/stories/AddCitationDialog.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gDAAgD,CAAC;AAenF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,iBAAiB,CAUxC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAKnC,eAAO,MAAM,IAAI,EAAE,KAQlB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAQ7B,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,KA2CrC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAkBhC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { ArchiveItemCard } from '../theculturepost/components/ArchiveItemCard';
|
|
3
|
+
|
|
4
|
+
declare const meta: Meta<typeof ArchiveItemCard>;
|
|
5
|
+
export default meta;
|
|
6
|
+
type Story = StoryObj<typeof meta>;
|
|
7
|
+
export declare const Manuscript: Story;
|
|
8
|
+
export declare const MinimalMetadata: Story;
|
|
9
|
+
//# sourceMappingURL=ArchiveItemCard.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArchiveItemCard.stories.d.ts","sourceRoot":"","sources":["../../src/stories/ArchiveItemCard.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAC;AAG/E,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,eAAe,CAWtC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,UAAU,EAAE,KAaxB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAkB7B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { CitationList } from '../theculturepost/components/CitationList';
|
|
3
|
+
|
|
4
|
+
declare const meta: Meta<typeof CitationList>;
|
|
5
|
+
export default meta;
|
|
6
|
+
type Story = StoryObj<typeof meta>;
|
|
7
|
+
export declare const Sources: Story;
|
|
8
|
+
export declare const VerifyCitation: Story;
|
|
9
|
+
export declare const Compact: Story;
|
|
10
|
+
export declare const Empty: Story;
|
|
11
|
+
export declare const Loading: Story;
|
|
12
|
+
export declare const LoadErrorWithRetry: Story;
|
|
13
|
+
//# sourceMappingURL=CitationList.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CitationList.stories.d.ts","sourceRoot":"","sources":["../../src/stories/CitationList.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAiB,MAAM,2CAA2C,CAAC;AA6BxF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,YAAY,CAKnC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAQnC,eAAO,MAAM,OAAO,EAAE,KAsBrB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAyB5B,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAQrB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAKnB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAKrB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAmBhC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { DiscussionCard } from '../theculturepost/components/DiscussionCard';
|
|
3
|
+
|
|
4
|
+
declare const meta: Meta<typeof DiscussionCard>;
|
|
5
|
+
export default meta;
|
|
6
|
+
type Story = StoryObj<typeof meta>;
|
|
7
|
+
export declare const Open: Story;
|
|
8
|
+
export declare const InterfaithAndLocked: Story;
|
|
9
|
+
//# sourceMappingURL=DiscussionCard.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscussionCard.stories.d.ts","sourceRoot":"","sources":["../../src/stories/DiscussionCard.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,MAAM,6CAA6C,CAAC;AAG7E,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,cAAc,CAWrC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,IAAI,EAAE,KAalB,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,KAkBjC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { RecordOralHistoryDialog } from '../theculturepost/components/RecordOralHistoryDialog';
|
|
3
|
+
|
|
4
|
+
declare const meta: Meta<typeof RecordOralHistoryDialog>;
|
|
5
|
+
export default meta;
|
|
6
|
+
type Story = StoryObj<typeof meta>;
|
|
7
|
+
export declare const ConsentGate: Story;
|
|
8
|
+
export declare const RecordsWithCollectionAndTags: Story;
|
|
9
|
+
export declare const PreselectedCollection: Story;
|
|
10
|
+
export declare const UploadSource: Story;
|
|
11
|
+
//# sourceMappingURL=RecordOralHistoryDialog.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecordOralHistoryDialog.stories.d.ts","sourceRoot":"","sources":["../../src/stories/RecordOralHistoryDialog.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sDAAsD,CAAC;AAsB/F,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,uBAAuB,CAK9C,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAQnC,eAAO,MAAM,WAAW,EAAE,KAezB,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,KA8C1C,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,KAUnC,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAO1B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { ReplyThread } from '../theculturepost/components/ReplyThread';
|
|
3
|
+
|
|
4
|
+
declare const meta: Meta<typeof ReplyThread>;
|
|
5
|
+
export default meta;
|
|
6
|
+
type Story = StoryObj<typeof meta>;
|
|
7
|
+
export declare const Thread: Story;
|
|
8
|
+
export declare const PostReplyWithPerspective: Story;
|
|
9
|
+
export declare const ModerateReply: Story;
|
|
10
|
+
export declare const RemovedReplyIsHidden: Story;
|
|
11
|
+
export declare const LockedAndEmpty: Story;
|
|
12
|
+
//# sourceMappingURL=ReplyThread.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReplyThread.stories.d.ts","sourceRoot":"","sources":["../../src/stories/ReplyThread.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAyCvE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,WAAW,CAKlC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAUnC,eAAO,MAAM,MAAM,EAAE,KAepB,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,KAkCtC,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAoB3B,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,KAWlC,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAW5B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { StoryCard } from '../theculturepost/components/StoryCard';
|
|
3
|
+
|
|
4
|
+
declare const meta: Meta<typeof StoryCard>;
|
|
5
|
+
export default meta;
|
|
6
|
+
type Story = StoryObj<typeof meta>;
|
|
7
|
+
export declare const Published: Story;
|
|
8
|
+
export declare const SaveToReadingList: Story;
|
|
9
|
+
export declare const Bookmarked: Story;
|
|
10
|
+
export declare const DraftWithoutStatus: Story;
|
|
11
|
+
//# sourceMappingURL=StoryCard.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StoryCard.stories.d.ts","sourceRoot":"","sources":["../../src/stories/StoryCard.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AASnE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,SAAS,CAYhC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,SAAS,EAAE,KAkBvB,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,KAe/B,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KASxB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAUhC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { TcpArchiveItem, TcpCitation, TcpCollection, TcpDiscussion, TcpOralHistory, TcpReply, TcpStory, TcpStoryClaim, TcpTopic } from '../../theculturepost/types';
|
|
2
|
+
|
|
3
|
+
export declare const STORYBOOK_USER: {
|
|
4
|
+
readonly id: "user-storybook-self";
|
|
5
|
+
readonly email: "storybook@theculturepost.test";
|
|
6
|
+
readonly workspaceId: "ws-storybook";
|
|
7
|
+
};
|
|
8
|
+
export declare const topicFixture: TcpTopic;
|
|
9
|
+
export declare function makeStory(overrides?: Partial<TcpStory>): TcpStory;
|
|
10
|
+
export declare function makeArchiveItem(overrides?: Partial<TcpArchiveItem>): TcpArchiveItem;
|
|
11
|
+
export declare function makeDiscussion(overrides?: Partial<TcpDiscussion>): TcpDiscussion;
|
|
12
|
+
export declare function makeCitation(overrides?: Partial<TcpCitation>): TcpCitation;
|
|
13
|
+
export declare const citationFixtures: TcpCitation[];
|
|
14
|
+
export declare const claimFixtures: TcpStoryClaim[];
|
|
15
|
+
export declare function makeReply(overrides?: Partial<TcpReply>): TcpReply;
|
|
16
|
+
export declare const replyFixtures: TcpReply[];
|
|
17
|
+
export declare function makeCollection(overrides?: Partial<TcpCollection>): TcpCollection;
|
|
18
|
+
export declare function makeOralHistory(overrides?: Partial<TcpOralHistory>): TcpOralHistory;
|
|
19
|
+
//# sourceMappingURL=fixtures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../../src/stories/support/fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,aAAa,EACb,aAAa,EACb,cAAc,EACd,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,QAAQ,EACT,MAAM,4BAA4B,CAAC;AAEpC,eAAO,MAAM,cAAc;;;;CAIjB,CAAC;AAMX,eAAO,MAAM,YAAY,EAAE,QAa1B,CAAC;AAEF,wBAAgB,SAAS,CAAC,SAAS,GAAE,OAAO,CAAC,QAAQ,CAAM,GAAG,QAAQ,CA2BrE;AAED,wBAAgB,eAAe,CAAC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GAAG,cAAc,CAoBvF;AAED,wBAAgB,cAAc,CAAC,SAAS,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,aAAa,CAkBpF;AAED,wBAAgB,YAAY,CAAC,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CAqB9E;AAED,eAAO,MAAM,gBAAgB,EAAE,WAAW,EAsBzC,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,aAAa,EAWxC,CAAC;AAEF,wBAAgB,SAAS,CAAC,SAAS,GAAE,OAAO,CAAC,QAAQ,CAAM,GAAG,QAAQ,CAarE;AAED,eAAO,MAAM,aAAa,EAAE,QAAQ,EAWnC,CAAC;AAEF,wBAAgB,cAAc,CAAC,SAAS,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,aAAa,CAgBpF;AAED,wBAAgB,eAAe,CAAC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GAAG,cAAc,CAqBvF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { GraphQLFetchOptions, GraphQLResponse } from '@burdenoff/fe-libs/shared/graphql';
|
|
2
|
+
|
|
3
|
+
export * from '@burdenoff/fe-libs/shared/graphql';
|
|
4
|
+
/** Resolves an operation's root field from its variables, or throws to emit a GraphQL error. */
|
|
5
|
+
export type TcpMockResolver = (variables: Record<string, unknown>) => unknown;
|
|
6
|
+
export type TcpMockResolvers = Record<string, TcpMockResolver>;
|
|
7
|
+
export interface TcpRecordedCall {
|
|
8
|
+
field: string;
|
|
9
|
+
variables: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
/** Replace the active resolver set and clear the call log (one call per story render). */
|
|
12
|
+
export declare function setGraphqlMocks(next: TcpMockResolvers): void;
|
|
13
|
+
/** Calls recorded since the last `setGraphqlMocks`, optionally filtered by root field. */
|
|
14
|
+
export declare function getGraphqlCalls(field?: string): TcpRecordedCall[];
|
|
15
|
+
/** The first root selection of an operation string (`mutation X { tcpAddCitation(...) }` → `tcpAddCitation`). */
|
|
16
|
+
export declare function rootFieldOf(query: string): string | null;
|
|
17
|
+
export declare function graphqlFetch<T = unknown>(options: GraphQLFetchOptions): Promise<GraphQLResponse<T>>;
|
|
18
|
+
//# sourceMappingURL=graphqlMock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphqlMock.d.ts","sourceRoot":"","sources":["../../../src/stories/support/graphqlMock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAE9F,cAAc,mCAAmC,CAAC;AAElD,gGAAgG;AAChG,MAAM,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;AAE9E,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAKD,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAI5D;AAED,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,eAAe,EAAE,CAEjE;AAID,iHAAiH;AACjH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAExD;AAED,wBAAsB,YAAY,CAAC,CAAC,GAAG,OAAO,EAC5C,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CA2B7B"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Narrow helpers for reading GraphQL variables inside story resolvers without
|
|
3
|
+
* unchecked casts.
|
|
4
|
+
*/
|
|
5
|
+
export declare function readString(variables: Record<string, unknown>, key: string): string;
|
|
6
|
+
export declare function readObject(variables: Record<string, unknown>, key: string): Record<string, unknown>;
|
|
7
|
+
/** Pick `value` out of an allowed list, rejecting anything the schema would not accept. */
|
|
8
|
+
export declare function readEnum<T extends string>(value: unknown, allowed: readonly T[]): T;
|
|
9
|
+
/** Never-settling promise, used to hold a query in its loading state. */
|
|
10
|
+
export declare function pending(): Promise<never>;
|
|
11
|
+
//# sourceMappingURL=variables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../../../src/stories/support/variables.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIlF;AAED,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,GAAG,EAAE,MAAM,GACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMzB;AAED,2FAA2F;AAC3F,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,CAInF;AAED,yEAAyE;AACzE,wBAAgB,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,CAExC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Decorator } from '@storybook/react';
|
|
2
|
+
import { TcpMockResolvers } from './graphqlMock';
|
|
3
|
+
|
|
4
|
+
/** Story parameters understood by {@link withTcpProviders}. */
|
|
5
|
+
export interface TcpStoryParameters {
|
|
6
|
+
/**
|
|
7
|
+
* Factory for the story's GraphQL resolvers. A factory (rather than a plain
|
|
8
|
+
* object) lets stateful resolvers start from a clean slate on every render.
|
|
9
|
+
*/
|
|
10
|
+
tcpGraphql?: () => TcpMockResolvers;
|
|
11
|
+
}
|
|
12
|
+
export declare const withTcpProviders: Decorator;
|
|
13
|
+
//# sourceMappingURL=withTcpProviders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withTcpProviders.d.ts","sourceRoot":"","sources":["../../../src/stories/support/withTcpProviders.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAAmB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGvE,+DAA+D;AAC/D,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,gBAAgB,CAAC;CACrC;AAgCD,eAAO,MAAM,gBAAgB,EAAE,SAQ9B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TheCulturePost product analytics (BOFF-3167).
|
|
3
|
+
* @module theculturepost/analytics
|
|
4
|
+
*/
|
|
5
|
+
export { THECULTUREPOST_ANALYTICS_EVENTS, normalizePageName, theculturepostAnalytics, type TheculturepostAnalyticsEmission, type TheculturepostAnalyticsEventName, } from './theculturepostAnalytics';
|
|
6
|
+
export { useTheculturepostAnalytics, type TheculturepostAnalyticsSend, } from './useTheculturepostAnalytics';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/analytics/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,+BAA+B,EAC/B,iBAAiB,EACjB,uBAAuB,EACvB,KAAK,+BAA+B,EACpC,KAAK,gCAAgC,GACtC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,0BAA0B,EAC1B,KAAK,2BAA2B,GACjC,MAAM,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { TcpArchiveItem, TcpCitation, TcpCollection, TcpDiscussion, TcpOralHistory, TcpReply, TcpStory } from '../types';
|
|
2
|
+
|
|
3
|
+
/** Every TheCulturePost analytics event this MFE emits. */
|
|
4
|
+
export declare const THECULTUREPOST_ANALYTICS_EVENTS: {
|
|
5
|
+
readonly pageViewed: "theculturepost.page.viewed";
|
|
6
|
+
readonly storyDraftCreated: "theculturepost.story.draft_created";
|
|
7
|
+
readonly storyPublished: "theculturepost.story.published";
|
|
8
|
+
readonly storySaved: "theculturepost.story.saved";
|
|
9
|
+
readonly citationAttached: "theculturepost.citation.attached";
|
|
10
|
+
readonly collectionCreated: "theculturepost.collection.created";
|
|
11
|
+
readonly archiveItemUploaded: "theculturepost.archive_item.uploaded";
|
|
12
|
+
readonly oralHistoryRecorded: "theculturepost.oral_history.recorded";
|
|
13
|
+
readonly discussionOpened: "theculturepost.discussion.opened";
|
|
14
|
+
readonly discussionReplied: "theculturepost.discussion.replied";
|
|
15
|
+
};
|
|
16
|
+
export type TheculturepostAnalyticsEventName = (typeof THECULTUREPOST_ANALYTICS_EVENTS)[keyof typeof THECULTUREPOST_ANALYTICS_EVENTS];
|
|
17
|
+
/** A single bus emission: the event name and its payload. */
|
|
18
|
+
export interface TheculturepostAnalyticsEmission {
|
|
19
|
+
name: TheculturepostAnalyticsEventName;
|
|
20
|
+
payload: Record<string, string | boolean | undefined>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Turns a pathname (already stripped of the MFE base path) into a stable,
|
|
24
|
+
* low-cardinality page key, mirroring the MFE routes:
|
|
25
|
+
* `/` -> `home`, `/stories` -> `stories`, `/stories/:id` -> `stories.detail`,
|
|
26
|
+
* `/stories/:id/citations` -> `stories.citations`,
|
|
27
|
+
* `/archive/collections/:id` -> `archive.collections`. Ids and slugs never
|
|
28
|
+
* reach the key, so the dimension is safe for Rybbit.
|
|
29
|
+
*/
|
|
30
|
+
export declare function normalizePageName(pathname: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Pure payload builders. Kept separate from the hook so the exact shape that
|
|
33
|
+
* reaches the bus is reviewable (and testable) without a React tree.
|
|
34
|
+
*/
|
|
35
|
+
export declare const theculturepostAnalytics: {
|
|
36
|
+
pageViewed(workspaceId: string | undefined, pathname: string): {
|
|
37
|
+
name: "theculturepost.page.viewed";
|
|
38
|
+
payload: {
|
|
39
|
+
workspaceId: string | undefined;
|
|
40
|
+
page: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
storyDraftCreated(story: Pick<TcpStory, "id" | "workspaceId" | "topicId" | "format">): {
|
|
44
|
+
name: "theculturepost.story.draft_created";
|
|
45
|
+
payload: {
|
|
46
|
+
workspaceId: string;
|
|
47
|
+
storyId: string;
|
|
48
|
+
topicId: string | undefined;
|
|
49
|
+
format: import('../types').TcpStoryFormat;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
storyPublished(story: Pick<TcpStory, "id" | "workspaceId" | "topicId" | "format"> & {
|
|
53
|
+
citations?: readonly unknown[] | null;
|
|
54
|
+
}): {
|
|
55
|
+
name: "theculturepost.story.published";
|
|
56
|
+
payload: {
|
|
57
|
+
workspaceId: string;
|
|
58
|
+
storyId: string;
|
|
59
|
+
topicId: string | undefined;
|
|
60
|
+
format: import('../types').TcpStoryFormat;
|
|
61
|
+
cited: boolean;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
storySaved(workspaceId: string | undefined, storyId: string): {
|
|
65
|
+
name: "theculturepost.story.saved";
|
|
66
|
+
payload: {
|
|
67
|
+
workspaceId: string | undefined;
|
|
68
|
+
storyId: string;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
citationAttached(citation: Pick<TcpCitation, "id" | "workspaceId" | "storyId" | "sourceType" | "claimId">): {
|
|
72
|
+
name: "theculturepost.citation.attached";
|
|
73
|
+
payload: {
|
|
74
|
+
workspaceId: string;
|
|
75
|
+
storyId: string;
|
|
76
|
+
citationId: string;
|
|
77
|
+
sourceType: import('../types').TcpSourceType;
|
|
78
|
+
linkedToClaim: boolean;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
collectionCreated(collection: Pick<TcpCollection, "id" | "workspaceId">): {
|
|
82
|
+
name: "theculturepost.collection.created";
|
|
83
|
+
payload: {
|
|
84
|
+
workspaceId: string;
|
|
85
|
+
collectionId: string;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
archiveItemUploaded(item: Pick<TcpArchiveItem, "id" | "workspaceId" | "kind" | "accessLevel" | "collectionId" | "file">): {
|
|
89
|
+
name: "theculturepost.archive_item.uploaded";
|
|
90
|
+
payload: {
|
|
91
|
+
workspaceId: string;
|
|
92
|
+
archiveItemId: string;
|
|
93
|
+
collectionId: string | undefined;
|
|
94
|
+
kind: import('../types').TcpArchiveItemKind;
|
|
95
|
+
accessLevel: import('../types').TcpAccessLevel;
|
|
96
|
+
hasFile: boolean;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
oralHistoryRecorded(oralHistory: Pick<TcpOralHistory, "id" | "workspaceId" | "accessLevel" | "collectionId" | "recording">): {
|
|
100
|
+
name: "theculturepost.oral_history.recorded";
|
|
101
|
+
payload: {
|
|
102
|
+
workspaceId: string;
|
|
103
|
+
oralHistoryId: string;
|
|
104
|
+
collectionId: string | undefined;
|
|
105
|
+
accessLevel: import('../types').TcpAccessLevel;
|
|
106
|
+
hasRecording: boolean;
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
discussionOpened(discussion: Pick<TcpDiscussion, "id" | "workspaceId" | "storyId" | "isInterfaith">): {
|
|
110
|
+
name: "theculturepost.discussion.opened";
|
|
111
|
+
payload: {
|
|
112
|
+
workspaceId: string;
|
|
113
|
+
discussionId: string;
|
|
114
|
+
storyId: string | undefined;
|
|
115
|
+
isInterfaith: boolean;
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
discussionReplied(reply: Pick<TcpReply, "id" | "workspaceId" | "discussionId">): {
|
|
119
|
+
name: "theculturepost.discussion.replied";
|
|
120
|
+
payload: {
|
|
121
|
+
workspaceId: string;
|
|
122
|
+
discussionId: string;
|
|
123
|
+
replyId: string;
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
//# sourceMappingURL=theculturepostAnalytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theculturepostAnalytics.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/analytics/theculturepostAnalytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,aAAa,EACb,aAAa,EACb,cAAc,EACd,QAAQ,EACR,QAAQ,EACT,MAAM,UAAU,CAAC;AAElB,2DAA2D;AAC3D,eAAO,MAAM,+BAA+B;;;;;;;;;;;CAWlC,CAAC;AAEX,MAAM,MAAM,gCAAgC,GAC1C,CAAC,OAAO,+BAA+B,CAAC,CAAC,MAAM,OAAO,+BAA+B,CAAC,CAAC;AAEzF,6DAA6D;AAC7D,MAAM,WAAW,+BAA+B;IAC9C,IAAI,EAAE,gCAAgC,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;CACvD;AAQD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAS1D;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB;4BACV,MAAM,GAAG,SAAS,YAAY,MAAM;;;;;;;6BAMnC,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,aAAa,GAAG,SAAS,GAAG,QAAQ,CAAC;;;;;;;;;0BAY3E,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,aAAa,GAAG,SAAS,GAAG,QAAQ,CAAC,GAAG;QACnE,SAAS,CAAC,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI,CAAC;KACvC;;;;;;;;;;4BAaqB,MAAM,GAAG,SAAS,WAAW,MAAM;;;;;;;+BAO/C,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,aAAa,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;;;;;;;;;;kCAa5D,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,aAAa,CAAC;;;;;;;8BAO/D,IAAI,CACR,cAAc,EACd,IAAI,GAAG,aAAa,GAAG,MAAM,GAAG,aAAa,GAAG,cAAc,GAAG,MAAM,CACxE;;;;;;;;;;;qCAeY,IAAI,CACf,cAAc,EACd,IAAI,GAAG,aAAa,GAAG,aAAa,GAAG,cAAc,GAAG,WAAW,CACpE;;;;;;;;;;iCAcW,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,aAAa,GAAG,SAAS,GAAG,cAAc,CAAC;;;;;;;;;6BAY3D,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,aAAa,GAAG,cAAc,CAAC;;;;;;;;CAU/E,CAAC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
//#region src/theculturepost/analytics/theculturepostAnalytics.ts
|
|
2
|
+
var e = {
|
|
3
|
+
pageViewed: "theculturepost.page.viewed",
|
|
4
|
+
storyDraftCreated: "theculturepost.story.draft_created",
|
|
5
|
+
storyPublished: "theculturepost.story.published",
|
|
6
|
+
storySaved: "theculturepost.story.saved",
|
|
7
|
+
citationAttached: "theculturepost.citation.attached",
|
|
8
|
+
collectionCreated: "theculturepost.collection.created",
|
|
9
|
+
archiveItemUploaded: "theculturepost.archive_item.uploaded",
|
|
10
|
+
oralHistoryRecorded: "theculturepost.oral_history.recorded",
|
|
11
|
+
discussionOpened: "theculturepost.discussion.opened",
|
|
12
|
+
discussionReplied: "theculturepost.discussion.replied"
|
|
13
|
+
}, t = new Set([
|
|
14
|
+
"stories",
|
|
15
|
+
"topics",
|
|
16
|
+
"discussions"
|
|
17
|
+
]), n = /^[a-z][a-z-]*$/;
|
|
18
|
+
function r(e) {
|
|
19
|
+
let [r, i, a] = e.split("/").filter(Boolean);
|
|
20
|
+
return r ? n.test(r) ? i ? t.has(r) ? a && n.test(a) ? `${r}.${a}` : `${r}.detail` : n.test(i) ? `${r}.${i}` : `${r}.detail` : r : "other" : "home";
|
|
21
|
+
}
|
|
22
|
+
var i = {
|
|
23
|
+
pageViewed(t, n) {
|
|
24
|
+
return {
|
|
25
|
+
name: e.pageViewed,
|
|
26
|
+
payload: {
|
|
27
|
+
workspaceId: t,
|
|
28
|
+
page: r(n)
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
storyDraftCreated(t) {
|
|
33
|
+
return {
|
|
34
|
+
name: e.storyDraftCreated,
|
|
35
|
+
payload: {
|
|
36
|
+
workspaceId: t.workspaceId,
|
|
37
|
+
storyId: t.id,
|
|
38
|
+
topicId: t.topicId ?? void 0,
|
|
39
|
+
format: t.format
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
storyPublished(t) {
|
|
44
|
+
return {
|
|
45
|
+
name: e.storyPublished,
|
|
46
|
+
payload: {
|
|
47
|
+
workspaceId: t.workspaceId,
|
|
48
|
+
storyId: t.id,
|
|
49
|
+
topicId: t.topicId ?? void 0,
|
|
50
|
+
format: t.format,
|
|
51
|
+
cited: (t.citations?.length ?? 0) > 0
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
storySaved(t, n) {
|
|
56
|
+
return {
|
|
57
|
+
name: e.storySaved,
|
|
58
|
+
payload: {
|
|
59
|
+
workspaceId: t,
|
|
60
|
+
storyId: n
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
citationAttached(t) {
|
|
65
|
+
return {
|
|
66
|
+
name: e.citationAttached,
|
|
67
|
+
payload: {
|
|
68
|
+
workspaceId: t.workspaceId,
|
|
69
|
+
storyId: t.storyId,
|
|
70
|
+
citationId: t.id,
|
|
71
|
+
sourceType: t.sourceType,
|
|
72
|
+
linkedToClaim: !!t.claimId
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
collectionCreated(t) {
|
|
77
|
+
return {
|
|
78
|
+
name: e.collectionCreated,
|
|
79
|
+
payload: {
|
|
80
|
+
workspaceId: t.workspaceId,
|
|
81
|
+
collectionId: t.id
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
archiveItemUploaded(t) {
|
|
86
|
+
return {
|
|
87
|
+
name: e.archiveItemUploaded,
|
|
88
|
+
payload: {
|
|
89
|
+
workspaceId: t.workspaceId,
|
|
90
|
+
archiveItemId: t.id,
|
|
91
|
+
collectionId: t.collectionId ?? void 0,
|
|
92
|
+
kind: t.kind,
|
|
93
|
+
accessLevel: t.accessLevel,
|
|
94
|
+
hasFile: !!t.file
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
oralHistoryRecorded(t) {
|
|
99
|
+
return {
|
|
100
|
+
name: e.oralHistoryRecorded,
|
|
101
|
+
payload: {
|
|
102
|
+
workspaceId: t.workspaceId,
|
|
103
|
+
oralHistoryId: t.id,
|
|
104
|
+
collectionId: t.collectionId ?? void 0,
|
|
105
|
+
accessLevel: t.accessLevel,
|
|
106
|
+
hasRecording: !!t.recording
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
},
|
|
110
|
+
discussionOpened(t) {
|
|
111
|
+
return {
|
|
112
|
+
name: e.discussionOpened,
|
|
113
|
+
payload: {
|
|
114
|
+
workspaceId: t.workspaceId,
|
|
115
|
+
discussionId: t.id,
|
|
116
|
+
storyId: t.storyId ?? void 0,
|
|
117
|
+
isInterfaith: t.isInterfaith
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
discussionReplied(t) {
|
|
122
|
+
return {
|
|
123
|
+
name: e.discussionReplied,
|
|
124
|
+
payload: {
|
|
125
|
+
workspaceId: t.workspaceId,
|
|
126
|
+
discussionId: t.discussionId,
|
|
127
|
+
replyId: t.id
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
//#endregion
|
|
133
|
+
export { e as THECULTUREPOST_ANALYTICS_EVENTS, r as normalizePageName, i as theculturepostAnalytics };
|
|
134
|
+
|
|
135
|
+
//# sourceMappingURL=theculturepostAnalytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theculturepostAnalytics.js","names":[],"sources":["../../../src/theculturepost/analytics/theculturepostAnalytics.ts"],"sourcesContent":["/**\n * TheCulturePost product analytics (BOFF-3167).\n *\n * The activation and engagement events this MFE emits on the shared fe-libs\n * event bus. The MFE never talks to Rybbit: the app shell's RybbitSink forwards\n * the names in `THECULTUREPOST_RYBBIT_EVENTS` (fe-libs\n * `shared/events/theculturepost.ts`), and the other sinks (BroadcastChannel,\n * OTel, devtools) see every event.\n *\n * The event dictionary (firing rules, dimensions, funnels, backend twins) is\n * `theculturepost-specs/business/status/ANALYTICS_PLAN.md`. Keep the names\n * here, the fe-libs taxonomy and that plan identical.\n *\n * Payload rule: ids are carried for the bus sinks, but RybbitSink strips every\n * identifier key before Rybbit. Never put titles, story bodies, citation text,\n * narrator names, transcripts, reply text or a contributor's tradition or\n * perspective in a payload: the builders below only read ids, enums and flags.\n */\nimport type {\n TcpArchiveItem,\n TcpCitation,\n TcpCollection,\n TcpDiscussion,\n TcpOralHistory,\n TcpReply,\n TcpStory,\n} from '../types';\n\n/** Every TheCulturePost analytics event this MFE emits. */\nexport const THECULTUREPOST_ANALYTICS_EVENTS = {\n pageViewed: 'theculturepost.page.viewed',\n storyDraftCreated: 'theculturepost.story.draft_created',\n storyPublished: 'theculturepost.story.published',\n storySaved: 'theculturepost.story.saved',\n citationAttached: 'theculturepost.citation.attached',\n collectionCreated: 'theculturepost.collection.created',\n archiveItemUploaded: 'theculturepost.archive_item.uploaded',\n oralHistoryRecorded: 'theculturepost.oral_history.recorded',\n discussionOpened: 'theculturepost.discussion.opened',\n discussionReplied: 'theculturepost.discussion.replied',\n} as const;\n\nexport type TheculturepostAnalyticsEventName =\n (typeof THECULTUREPOST_ANALYTICS_EVENTS)[keyof typeof THECULTUREPOST_ANALYTICS_EVENTS];\n\n/** A single bus emission: the event name and its payload. */\nexport interface TheculturepostAnalyticsEmission {\n name: TheculturepostAnalyticsEventName;\n payload: Record<string, string | boolean | undefined>;\n}\n\n/** Top-level sections whose second path part is an entity id (`/stories/:id`). */\nconst ENTITY_SECTIONS = new Set(['stories', 'topics', 'discussions']);\n\n/** Allowed shape of a route word; ids, slugs and anything else never match. */\nconst PAGE_WORD = /^[a-z][a-z-]*$/;\n\n/**\n * Turns a pathname (already stripped of the MFE base path) into a stable,\n * low-cardinality page key, mirroring the MFE routes:\n * `/` -> `home`, `/stories` -> `stories`, `/stories/:id` -> `stories.detail`,\n * `/stories/:id/citations` -> `stories.citations`,\n * `/archive/collections/:id` -> `archive.collections`. Ids and slugs never\n * reach the key, so the dimension is safe for Rybbit.\n */\nexport function normalizePageName(pathname: string): string {\n const [first, second, third] = pathname.split('/').filter(Boolean);\n if (!first) return 'home';\n if (!PAGE_WORD.test(first)) return 'other';\n if (!second) return first;\n if (ENTITY_SECTIONS.has(first)) {\n return third && PAGE_WORD.test(third) ? `${first}.${third}` : `${first}.detail`;\n }\n return PAGE_WORD.test(second) ? `${first}.${second}` : `${first}.detail`;\n}\n\n/**\n * Pure payload builders. Kept separate from the hook so the exact shape that\n * reaches the bus is reviewable (and testable) without a React tree.\n */\nexport const theculturepostAnalytics = {\n pageViewed(workspaceId: string | undefined, pathname: string) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.pageViewed,\n payload: { workspaceId, page: normalizePageName(pathname) },\n } satisfies TheculturepostAnalyticsEmission;\n },\n storyDraftCreated(story: Pick<TcpStory, 'id' | 'workspaceId' | 'topicId' | 'format'>) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.storyDraftCreated,\n payload: {\n workspaceId: story.workspaceId,\n storyId: story.id,\n topicId: story.topicId ?? undefined,\n format: story.format,\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n storyPublished(\n story: Pick<TcpStory, 'id' | 'workspaceId' | 'topicId' | 'format'> & {\n citations?: readonly unknown[] | null;\n }\n ) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.storyPublished,\n payload: {\n workspaceId: story.workspaceId,\n storyId: story.id,\n topicId: story.topicId ?? undefined,\n format: story.format,\n cited: (story.citations?.length ?? 0) > 0,\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n storySaved(workspaceId: string | undefined, storyId: string) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.storySaved,\n payload: { workspaceId, storyId },\n } satisfies TheculturepostAnalyticsEmission;\n },\n citationAttached(\n citation: Pick<TcpCitation, 'id' | 'workspaceId' | 'storyId' | 'sourceType' | 'claimId'>\n ) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.citationAttached,\n payload: {\n workspaceId: citation.workspaceId,\n storyId: citation.storyId,\n citationId: citation.id,\n sourceType: citation.sourceType,\n linkedToClaim: Boolean(citation.claimId),\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n collectionCreated(collection: Pick<TcpCollection, 'id' | 'workspaceId'>) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.collectionCreated,\n payload: { workspaceId: collection.workspaceId, collectionId: collection.id },\n } satisfies TheculturepostAnalyticsEmission;\n },\n archiveItemUploaded(\n item: Pick<\n TcpArchiveItem,\n 'id' | 'workspaceId' | 'kind' | 'accessLevel' | 'collectionId' | 'file'\n >\n ) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.archiveItemUploaded,\n payload: {\n workspaceId: item.workspaceId,\n archiveItemId: item.id,\n collectionId: item.collectionId ?? undefined,\n kind: item.kind,\n accessLevel: item.accessLevel,\n hasFile: Boolean(item.file),\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n oralHistoryRecorded(\n oralHistory: Pick<\n TcpOralHistory,\n 'id' | 'workspaceId' | 'accessLevel' | 'collectionId' | 'recording'\n >\n ) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.oralHistoryRecorded,\n payload: {\n workspaceId: oralHistory.workspaceId,\n oralHistoryId: oralHistory.id,\n collectionId: oralHistory.collectionId ?? undefined,\n accessLevel: oralHistory.accessLevel,\n hasRecording: Boolean(oralHistory.recording),\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n discussionOpened(\n discussion: Pick<TcpDiscussion, 'id' | 'workspaceId' | 'storyId' | 'isInterfaith'>\n ) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.discussionOpened,\n payload: {\n workspaceId: discussion.workspaceId,\n discussionId: discussion.id,\n storyId: discussion.storyId ?? undefined,\n isInterfaith: discussion.isInterfaith,\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n discussionReplied(reply: Pick<TcpReply, 'id' | 'workspaceId' | 'discussionId'>) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.discussionReplied,\n payload: {\n workspaceId: reply.workspaceId,\n discussionId: reply.discussionId,\n replyId: reply.id,\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n};\n"],"mappings":";AA6BA,IAAa,IAAkC;CAC7C,YAAY;CACZ,mBAAmB;CACnB,gBAAgB;CAChB,YAAY;CACZ,kBAAkB;CAClB,mBAAmB;CACnB,qBAAqB;CACrB,qBAAqB;CACrB,kBAAkB;CAClB,mBAAmB;CACpB,EAYK,IAAkB,IAAI,IAAI;CAAC;CAAW;CAAU;CAAc,CAAC,EAG/D,IAAY;AAUlB,SAAgB,EAAkB,GAA0B;CAC1D,IAAM,CAAC,GAAO,GAAQ,KAAS,EAAS,MAAM,IAAI,CAAC,OAAO,QAAQ;AAOlE,QANK,IACA,EAAU,KAAK,EAAM,GACrB,IACD,EAAgB,IAAI,EAAM,GACrB,KAAS,EAAU,KAAK,EAAM,GAAG,GAAG,EAAM,GAAG,MAAU,GAAG,EAAM,WAElE,EAAU,KAAK,EAAO,GAAG,GAAG,EAAM,GAAG,MAAW,GAAG,EAAM,WAJ5C,IADe,UADhB;;AAarB,IAAa,IAA0B;CACrC,WAAW,GAAiC,GAAkB;AAC5D,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IAAE;IAAa,MAAM,EAAkB,EAAS;IAAE;GAC5D;;CAEH,kBAAkB,GAAoE;AACpF,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAM;IACnB,SAAS,EAAM;IACf,SAAS,EAAM,WAAW,KAAA;IAC1B,QAAQ,EAAM;IACf;GACF;;CAEH,eACE,GAGA;AACA,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAM;IACnB,SAAS,EAAM;IACf,SAAS,EAAM,WAAW,KAAA;IAC1B,QAAQ,EAAM;IACd,QAAQ,EAAM,WAAW,UAAU,KAAK;IACzC;GACF;;CAEH,WAAW,GAAiC,GAAiB;AAC3D,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IAAE;IAAa;IAAS;GAClC;;CAEH,iBACE,GACA;AACA,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAS;IACtB,SAAS,EAAS;IAClB,YAAY,EAAS;IACrB,YAAY,EAAS;IACrB,eAAe,EAAQ,EAAS;IACjC;GACF;;CAEH,kBAAkB,GAAuD;AACvE,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IAAE,aAAa,EAAW;IAAa,cAAc,EAAW;IAAI;GAC9E;;CAEH,oBACE,GAIA;AACA,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAK;IAClB,eAAe,EAAK;IACpB,cAAc,EAAK,gBAAgB,KAAA;IACnC,MAAM,EAAK;IACX,aAAa,EAAK;IAClB,SAAS,EAAQ,EAAK;IACvB;GACF;;CAEH,oBACE,GAIA;AACA,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAY;IACzB,eAAe,EAAY;IAC3B,cAAc,EAAY,gBAAgB,KAAA;IAC1C,aAAa,EAAY;IACzB,cAAc,EAAQ,EAAY;IACnC;GACF;;CAEH,iBACE,GACA;AACA,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAW;IACxB,cAAc,EAAW;IACzB,SAAS,EAAW,WAAW,KAAA;IAC/B,cAAc,EAAW;IAC1B;GACF;;CAEH,kBAAkB,GAA8D;AAC9E,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAM;IACnB,cAAc,EAAM;IACpB,SAAS,EAAM;IAChB;GACF;;CAEJ"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { TheculturepostAnalyticsEmission } from './theculturepostAnalytics';
|
|
2
|
+
|
|
3
|
+
export type TheculturepostAnalyticsSend = (emission: TheculturepostAnalyticsEmission) => void;
|
|
4
|
+
export declare function useTheculturepostAnalytics(): TheculturepostAnalyticsSend;
|
|
5
|
+
//# sourceMappingURL=useTheculturepostAnalytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTheculturepostAnalytics.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/analytics/useTheculturepostAnalytics.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAC;AAEjF,MAAM,MAAM,2BAA2B,GAAG,CAAC,QAAQ,EAAE,+BAA+B,KAAK,IAAI,CAAC;AAE9F,wBAAgB,0BAA0B,IAAI,2BAA2B,CAexE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useCallback as e } from "react";
|
|
2
|
+
import { useEventBus as t } from "@burdenoff/fe-libs/shared/events";
|
|
3
|
+
//#region src/theculturepost/analytics/useTheculturepostAnalytics.ts
|
|
4
|
+
function n() {
|
|
5
|
+
let n = t();
|
|
6
|
+
return e((e) => {
|
|
7
|
+
try {
|
|
8
|
+
n.emitCustom(e.name, e.payload);
|
|
9
|
+
} catch {}
|
|
10
|
+
}, [n]);
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { n as useTheculturepostAnalytics };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=useTheculturepostAnalytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTheculturepostAnalytics.js","names":[],"sources":["../../../src/theculturepost/analytics/useTheculturepostAnalytics.ts"],"sourcesContent":["/**\n * React hook that emits TheCulturePost analytics events on the shared event bus.\n *\n * `send` is fire-and-forget and never throws: analytics must not be able to\n * break a contributor's draft, citation, upload or reply. Outside an app shell\n * (Storybook, standalone) the bus context is a no-op, so calls are inert.\n */\nimport { useCallback } from 'react';\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\n\nimport type { TheculturepostAnalyticsEmission } from './theculturepostAnalytics';\n\nexport type TheculturepostAnalyticsSend = (emission: TheculturepostAnalyticsEmission) => void;\n\nexport function useTheculturepostAnalytics(): TheculturepostAnalyticsSend {\n const bus = useEventBus();\n return useCallback(\n (emission: TheculturepostAnalyticsEmission) => {\n try {\n // emitCustom: the names are registered in fe-libs' BurdenoffEventName\n // union from the fe-libs release that ships the TheCulturePost taxonomy;\n // the runtime path (bus.onAny -> sinks) is identical to emit().\n bus.emitCustom(emission.name, emission.payload);\n } catch {\n /* analytics is best-effort and must never break the contributor flow */\n }\n },\n [bus]\n );\n}\n"],"mappings":";;;AAcA,SAAgB,IAA0D;CACxE,IAAM,IAAM,GAAa;AACzB,QAAO,GACJ,MAA8C;AAC7C,MAAI;AAIF,KAAI,WAAW,EAAS,MAAM,EAAS,QAAQ;UACzC;IAIV,CAAC,EAAI,CACN"}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Page-view analytics hook for TheCulturePost.
|
|
2
|
+
* Page-view analytics hook for TheCulturePost (BOFF-3167).
|
|
3
3
|
*
|
|
4
|
-
* Emits
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Emits `theculturepost.page.viewed` on the shared event bus every time the
|
|
5
|
+
* MFE route changes. The shell's RybbitSink forwards it (it is in fe-libs'
|
|
6
|
+
* `THECULTUREPOST_RYBBIT_EVENTS`) once the visitor has granted analytics
|
|
7
|
+
* consent. The payload is the normalised page key only (`stories.detail`,
|
|
8
|
+
* never the raw path with an id in it), plus the workspace id, which the sink
|
|
9
|
+
* strips before Rybbit.
|
|
10
|
+
*
|
|
11
|
+
* Driven by the router location rather than `popstate`: in-app navigation is
|
|
12
|
+
* `history.pushState`, which never fires `popstate`, so the earlier listener
|
|
13
|
+
* only ever reported the first screen and back/forward moves.
|
|
7
14
|
*/
|
|
15
|
+
/** Strips the MFE mount path so `/culture/stories` and `/stories` map to the same key. */
|
|
16
|
+
export declare function stripBasePath(pathname: string, basePath: string | undefined): string;
|
|
8
17
|
export declare function usePageAnalytics(): void;
|
|
9
18
|
//# sourceMappingURL=usePageAnalytics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePageAnalytics.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/hooks/usePageAnalytics.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"usePageAnalytics.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/hooks/usePageAnalytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAQH,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAKpF;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAQvC"}
|
|
@@ -1,34 +1,27 @@
|
|
|
1
1
|
import { useTheCulturePost as e } from "../context/TheCulturePostContext.js";
|
|
2
|
+
import { theculturepostAnalytics as t } from "../analytics/theculturepostAnalytics.js";
|
|
3
|
+
import { useTheculturepostAnalytics as n } from "../analytics/useTheculturepostAnalytics.js";
|
|
4
|
+
import "../analytics/index.js";
|
|
2
5
|
import "../context/index.js";
|
|
3
|
-
import { useEffect as
|
|
4
|
-
import {
|
|
6
|
+
import { useEffect as r } from "react";
|
|
7
|
+
import { useLocation as i } from "react-router";
|
|
5
8
|
//#region src/theculturepost/hooks/usePageAnalytics.ts
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
return t.length <= 1 ? n : [
|
|
10
|
-
"stories",
|
|
11
|
-
"topics",
|
|
12
|
-
"discussions",
|
|
13
|
-
"archive"
|
|
14
|
-
].includes(t[1] ?? "") ? t.length >= 3 ? `${t[1]}.detail` : t[1] ?? n : t.slice(1).join(".");
|
|
9
|
+
function a(e, t) {
|
|
10
|
+
let n = t && t !== "/" ? t.replace(/\/$/, "") : "";
|
|
11
|
+
return n ? e === n ? "/" : e.startsWith(`${n}/`) ? e.slice(n.length) : e : e;
|
|
15
12
|
}
|
|
16
|
-
function
|
|
17
|
-
let
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
return e(), window.addEventListener("popstate", e), () => window.removeEventListener("popstate", e);
|
|
29
|
-
}, [o, a]);
|
|
13
|
+
function o() {
|
|
14
|
+
let o = n(), { basePath: s, workspaceId: c } = e(), { pathname: l } = i();
|
|
15
|
+
r(() => {
|
|
16
|
+
o(t.pageViewed(c, a(l, s)));
|
|
17
|
+
}, [
|
|
18
|
+
s,
|
|
19
|
+
l,
|
|
20
|
+
o,
|
|
21
|
+
c
|
|
22
|
+
]);
|
|
30
23
|
}
|
|
31
24
|
//#endregion
|
|
32
|
-
export { a as usePageAnalytics };
|
|
25
|
+
export { a as stripBasePath, o as usePageAnalytics };
|
|
33
26
|
|
|
34
27
|
//# sourceMappingURL=usePageAnalytics.js.map
|