chore(core): replace with new track impl (#7735)

This commit is contained in:
liuyi
2024-08-06 17:15:15 +08:00
committed by GitHub
parent 7373e174db
commit d0f1bb24fd
59 changed files with 647 additions and 821 deletions
+8 -2
View File
@@ -15,7 +15,7 @@ export function makeTracker(trackFn: TrackFn): CallableEventsChain {
get(target, prop) {
if (
typeof prop !== 'string' ||
prop === '$$typeof' /* webpack hot load reading this prop */
prop === '$$typeof' /* webpack hot-reload reads this prop */
) {
return undefined;
}
@@ -55,7 +55,12 @@ export function makeTracker(trackFn: TrackFn): CallableEventsChain {
* @example
*
* ```html
* <button data-event-chain='$.cmdk.settings.quicksearch.changeLanguage' data-event-arg='cn' />
* <button
* data-event-chain='$.cmdk.settings.changeLanguage'
* data-event-arg='cn'
* <!-- or -->
* data-event-args-foo='bar'
* />
* ```
*/
export function enableAutoTrack(root: HTMLElement, trackFn: TrackFn) {
@@ -114,5 +119,6 @@ declare module 'react' {
interface HTMLAttributes<T> {
'data-event-props'?: EventsUnion;
'data-event-arg'?: string;
'data-event-args-control'?: string;
}
}
+284 -36
View File
@@ -1,43 +1,291 @@
// let '$' stands for unspecific matrix
/* eslint-disable rxjs/finnish */
export interface Events {
$: {
cmdk: {
settings: ['openSettings', 'changeLanguage'];
};
navigationPanel: {
generalFunction: [
'quickSearch',
'createDoc',
'goToAllPage',
'goToJournals',
'openSettings',
];
collection: ['createDoc'];
bottomButtong: ['downloadApp', 'restartAndInstallUpdate'];
others: ['openTrash', 'export'];
// SECTION: app events
type GeneralEvents = 'openMigrationDataHelp' | 'export';
type CmdkEvents = 'quickSearch';
type AppEvents =
| 'checkUpdates'
| 'downloadUpdate'
| 'downloadApp'
| 'quitAndInstall'
| 'openChangelog'
| 'dismissChangelog';
type NavigationEvents =
| 'openInNewTab'
| 'openInSplitView'
| 'switchTab'
| 'switchSplitView'
| 'navigate'
| 'open'
| 'close'; // openclose modal/diaglog
// END SECTION
// SECTION: doc events
type WorkspaceEvents =
| 'createWorkspace'
| 'upgradeWorkspace'
| 'enableCloudWorkspace'
| 'import'
| 'export'
| 'openWorkspaceList';
type DocEvents =
| 'createDoc'
| 'renameDoc'
| 'linkDoc'
| 'deleteDoc'
| 'switchPageMode';
type EditorEvents = 'bold' | 'italic' | 'underline' | 'strikeThrough';
// END SECTION
// SECTION: setting events
type SettingEvents =
| 'openSettings'
| 'changeAppSetting'
| 'changeEditorSetting';
// END SECTION
// SECTION: organize events
type CollectionEvents =
| 'createCollection'
| 'deleteCollection'
| 'renameCollection'
| 'addDocToCollection';
type FolderEvents =
| 'createFolder'
| 'renameFolder'
| 'moveFolder'
| 'deleteFolder';
type TagEvents = 'createTag' | 'deleteTag' | 'renameTag' | 'tagDoc';
type FavoriteEvents = 'toggleFavorite';
type OrganizeItemEvents = // doc, link, folder, collection, tag
| 'createOrganizeItem'
| 'renameOrganizeItem'
| 'moveOrganizeItem'
| 'deleteOrganizeItem'
| 'orderOrganizeItem';
type OrganizeEvents =
| OrganizeItemEvents
| CollectionEvents
| FolderEvents
| TagEvents
| FavoriteEvents;
// END SECTION
// SECTION: cloud events
type ShareEvents = 'createShareLink' | 'copyShareLink';
type AuthEvents = 'signIn' | 'signUp' | 'oauth' | 'signOut';
type AccountEvents = 'uploadAvatar' | 'removeAvatar' | 'updateUserName';
type PaymentEvents =
| 'viewPlans'
| 'bookDemo'
| 'checkout'
| 'changeSubscriptionRecurring'
| 'confirmChangingSubscriptionRecurring'
| 'cancelSubscription'
| 'confirmCancelingSubscription'
| 'resumeSubscription'
| 'confirmResumingSubscription';
// END SECTION
type UserEvents =
| GeneralEvents
| AppEvents
| NavigationEvents
| WorkspaceEvents
| DocEvents
| EditorEvents
| SettingEvents
| CmdkEvents
| OrganizeEvents
| ShareEvents
| AuthEvents
| AccountEvents
| PaymentEvents;
interface PageDivision {
[page: string]: {
[segment: string]: {
[module: string]: UserEvents[];
};
};
}
const PageEvents = {
// page: {
// $: {}
// ^ if empty
// segment: {
// module: ['event1', 'event2']
// },
// },
// to: page.$.segment.module.event1()
$: {
$: {
$: ['createWorkspace', 'checkout'],
auth: ['oauth', 'signIn', 'signUp'],
},
settingsPanel: {
menu: ['openSettings'],
workspace: ['viewPlans'],
profileAndBadge: ['viewPlans'],
accountUsage: ['viewPlans'],
accountSettings: ['uploadAvatar', 'removeAvatar', 'updateUserName'],
plans: [
'checkout',
'changeSubscriptionRecurring',
'confirmChangingSubscriptionRecurring',
'cancelSubscription',
'confirmCancelingSubscription',
'resumeSubscription',
'confirmResumingSubscription',
],
billing: ['viewPlans', 'bookDemo'],
about: ['checkUpdates', 'downloadUpdate', 'changeAppSetting'],
},
cmdk: {
$: ['createDoc'],
settings: ['openSettings', 'changeAppSetting'],
},
navigationPanel: {
$: ['quickSearch', 'createDoc', 'navigate', 'openSettings'],
organize: [
'createOrganizeItem',
'renameOrganizeItem',
'moveOrganizeItem',
'deleteOrganizeItem',
'orderOrganizeItem',
'openInNewTab',
'openInSplitView',
'toggleFavorite',
],
docs: ['createDoc', 'deleteDoc', 'linkDoc'],
collections: ['createDoc', 'addDocToCollection'],
folders: ['createDoc'],
tags: ['createDoc', 'tagDoc'],
favorites: ['createDoc'],
migrationData: ['openMigrationDataHelp'],
bottomButtons: [
'downloadApp',
'quitAndInstall',
'openChangelog',
'dismissChangelog',
],
others: ['navigate', 'import'],
workspaceList: [
'open',
'signIn',
'createWorkspace',
'createDoc',
'openSettings',
],
profileAndBadge: ['openSettings'],
},
aiOnboarding: {
dialog: ['viewPlans'],
},
docHistory: {
$: ['open', 'close', 'switchPageMode', 'viewPlans'],
},
paywall: {
storage: ['viewPlans'],
aiAction: ['viewPlans'],
},
header: {
actions: ['createDoc', 'createWorkspace', 'switchPageMode'],
share: ['createShareLink', 'copyShareLink', 'export'],
},
},
doc: {
editor: {
formatToolbar: ['bold'];
slashMenu: ['linkDoc', 'createDoc'],
atMenu: ['linkDoc'],
formatToolbar: ['bold'],
},
},
// remove when type added
// eslint-disable-next-line @typescript-eslint/ban-types
edgeless: {},
workspace: {
$: {
$: ['upgradeWorkspace'],
},
},
allDocs: {
header: {
actions: ['createDoc', 'createWorkspace'],
},
list: {
docMenu: ['createDoc'],
},
},
// remove when type added
// eslint-disable-next-line @typescript-eslint/ban-types
collection: {},
// remove when type added
// eslint-disable-next-line @typescript-eslint/ban-types
tag: {},
// remove when type added
// eslint-disable-next-line @typescript-eslint/ban-types
trash: {},
subscriptionLanding: {
$: {
$: ['checkout'],
},
},
} as const satisfies PageDivision;
type OrganizeItemType = 'doc' | 'folder' | 'collection' | 'tag' | 'favorite';
type OrganizeItemArgs =
| {
type: 'link';
target: OrganizeItemType;
}
| {
type: OrganizeItemType;
};
};
edgeless: {
editor: {
formatToolbar: ['drawConnector'];
};
};
// remove when type added
// eslint-disable-next-line @typescript-eslint/ban-types
allDocs: {};
// remove when type added
// eslint-disable-next-line @typescript-eslint/ban-types
collection: {};
// remove when type added
// eslint-disable-next-line @typescript-eslint/ban-types
tag: {};
// remove when type added
// eslint-disable-next-line @typescript-eslint/ban-types
trash: {};
}
type PaymentEventArgs = {
plan: string;
recurring: string;
};
export type EventArgs = {
createWorkspace: { flavour: string };
oauth: { provider: string };
viewPlans: PaymentEventArgs;
checkout: PaymentEventArgs;
cancelSubscription: PaymentEventArgs;
confirmCancelingSubscription: PaymentEventArgs;
resumeSubscription: PaymentEventArgs;
confirmResumingSubscription: PaymentEventArgs;
changeSubscriptionRecurring: PaymentEventArgs;
confirmChangingSubscriptionRecurring: PaymentEventArgs;
navigate: { to: string };
openSettings: { to: string };
changeAppSetting: { key: string; value: string | boolean | number };
changeEditorSetting: { key: string; value: string | boolean | number };
createOrganizeItem: OrganizeItemArgs;
renameOrganizeItem: OrganizeItemArgs;
moveOrganizeItem: OrganizeItemArgs;
deleteOrganizeItem: OrganizeItemArgs;
orderOrganizeItem: OrganizeItemArgs;
openInNewTab: { type: OrganizeItemType };
openInSplitView: { type: OrganizeItemType };
toggleFavorite: OrganizeItemArgs & { on: boolean };
createDoc: { mode?: 'edgeless' | 'page' };
switchPageMode: { mode: 'edgeless' | 'page' };
createShareLink: { mode: 'edgeless' | 'page' };
copyShareLink: { type: 'public' | 'private' };
export: { type: string };
};
// for type checking
// if it complains, check the definition of [EventArgs] to make sure it's key is a subset of [UserEvents]
export const YOU_MUST_DEFINE_ARGS_WITH_WRONG_EVENT_NAME: keyof EventArgs extends UserEvents
? true
: false = true;
export type Events = typeof PageEvents;
+16 -6
View File
@@ -1,13 +1,23 @@
import type { Events } from './events';
import type { EventArgs, Events } from './events';
type EventPropsOverride = {
page?: keyof Events;
segment?: string;
module?: string;
control?: string;
};
export type CallableEventsChain = {
[Page in keyof Events]: {
[Segment in keyof Events[Page]]: {
[Module in keyof Events[Page][Segment]]: {
// @ts-expect-error ignore `symbol | number` as key
[Control in Events[Page][Segment][Module][number]]: (
arg?: string
) => void;
[Event in Events[Page][Segment][Module][number]]: Event extends keyof EventArgs
? (
// we make all args partial to simply satisfies nullish type checking
args?: Partial<EventArgs[Event]> & EventPropsOverride
) => void
: (args?: EventPropsOverride) => void;
};
};
};
@@ -18,14 +28,14 @@ export type EventsUnion = {
[Segment in keyof Events[Page]]: {
[Module in keyof Events[Page][Segment]]: {
// @ts-expect-error ignore `symbol | number` as key
[Control in Events[Page][Segment][Module][number]]: `${Page}.${Segment}.${Module}.${Control}`;
[Event in Events[Page][Segment][Module][number]]: `${Page}.${Segment}.${Module}.${Event}`;
// @ts-expect-error ignore `symbol | number` as key
}[Events[Page][Segment][Module][number]];
}[keyof Events[Page][Segment]];
}[keyof Events[Page]];
}[keyof Events];
// page > segment > module > [controls]
// page > segment > module > [events]
type IsFourLevelsDeep<
T,
Depth extends number[] = [],