@vue-skuilder/common-ui 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/assets/index.css +10 -0
  2. package/dist/common-ui.es.js +16404 -0
  3. package/dist/common-ui.es.js.map +1 -0
  4. package/dist/common-ui.umd.js +9 -0
  5. package/dist/common-ui.umd.js.map +1 -0
  6. package/dist/components/HeatMap.types.d.ts +13 -0
  7. package/dist/components/PaginatingToolbar.types.d.ts +40 -0
  8. package/dist/components/SkMouseTrap.types.d.ts +3 -0
  9. package/dist/components/SkMouseTrapToolTip.types.d.ts +35 -0
  10. package/dist/components/SnackbarService.d.ts +11 -0
  11. package/dist/components/StudySession.types.d.ts +6 -0
  12. package/dist/components/auth/index.d.ts +4 -0
  13. package/dist/components/cardRendering/MarkdownRendererHelpers.d.ts +22 -0
  14. package/dist/components/studentInputs/BaseUserInput.d.ts +16 -0
  15. package/dist/components/studentInputs/RadioMultipleChoice.types.d.ts +5 -0
  16. package/dist/composables/CompositionViewable.d.ts +33 -0
  17. package/dist/composables/Displayable.d.ts +47 -0
  18. package/dist/composables/index.d.ts +2 -0
  19. package/dist/index.d.ts +36 -0
  20. package/dist/plugins/pinia.d.ts +5 -0
  21. package/dist/stores/useAuthStore.d.ts +225 -0
  22. package/dist/stores/useCardPreviewModeStore.d.ts +8 -0
  23. package/dist/stores/useConfigStore.d.ts +11 -0
  24. package/dist/utils/SkldrMouseTrap.d.ts +32 -0
  25. package/package.json +67 -0
  26. package/src/components/HeatMap.types.ts +15 -0
  27. package/src/components/HeatMap.vue +354 -0
  28. package/src/components/PaginatingToolbar.types.ts +48 -0
  29. package/src/components/PaginatingToolbar.vue +75 -0
  30. package/src/components/SkMouseTrap.types.ts +3 -0
  31. package/src/components/SkMouseTrap.vue +70 -0
  32. package/src/components/SkMouseTrapToolTip.types.ts +41 -0
  33. package/src/components/SkMouseTrapToolTip.vue +316 -0
  34. package/src/components/SnackbarService.ts +39 -0
  35. package/src/components/SnackbarService.vue +71 -0
  36. package/src/components/StudySession.types.ts +6 -0
  37. package/src/components/StudySession.vue +670 -0
  38. package/src/components/StudySessionTimer.vue +121 -0
  39. package/src/components/auth/UserChip.vue +106 -0
  40. package/src/components/auth/UserLogin.vue +141 -0
  41. package/src/components/auth/UserLoginAndRegistrationContainer.vue +85 -0
  42. package/src/components/auth/UserRegistration.vue +181 -0
  43. package/src/components/auth/index.ts +4 -0
  44. package/src/components/cardRendering/AudioAutoPlayer.vue +131 -0
  45. package/src/components/cardRendering/CardLoader.vue +123 -0
  46. package/src/components/cardRendering/CardViewer.vue +101 -0
  47. package/src/components/cardRendering/CodeBlockRenderer.vue +81 -0
  48. package/src/components/cardRendering/MarkdownRenderer.vue +46 -0
  49. package/src/components/cardRendering/MarkdownRendererHelpers.ts +114 -0
  50. package/src/components/cardRendering/MdTokenRenderer.vue +244 -0
  51. package/src/components/studentInputs/BaseUserInput.ts +71 -0
  52. package/src/components/studentInputs/MultipleChoiceOption.vue +127 -0
  53. package/src/components/studentInputs/RadioMultipleChoice.types.ts +6 -0
  54. package/src/components/studentInputs/RadioMultipleChoice.vue +168 -0
  55. package/src/components/studentInputs/TrueFalse.vue +27 -0
  56. package/src/components/studentInputs/UserInputNumber.vue +63 -0
  57. package/src/components/studentInputs/UserInputString.vue +89 -0
  58. package/src/components/studentInputs/fillInInput.vue +71 -0
  59. package/src/composables/CompositionViewable.ts +180 -0
  60. package/src/composables/Displayable.ts +133 -0
  61. package/src/composables/index.ts +2 -0
  62. package/src/index.ts +79 -0
  63. package/src/plugins/pinia.ts +24 -0
  64. package/src/stores/useAuthStore.ts +92 -0
  65. package/src/stores/useCardPreviewModeStore.ts +32 -0
  66. package/src/stores/useConfigStore.ts +60 -0
  67. package/src/utils/SkldrMouseTrap.ts +141 -0
  68. package/src/vue-shims.d.ts +5 -0
@@ -0,0 +1,13 @@
1
+ export interface DayData {
2
+ date: string;
3
+ count: number;
4
+ }
5
+ export interface Color {
6
+ h: number;
7
+ s: number;
8
+ l: number;
9
+ }
10
+ export interface ActivityRecord {
11
+ timeStamp: number | string;
12
+ [key: string]: any;
13
+ }
@@ -0,0 +1,40 @@
1
+ export interface PaginatingToolbarProps {
2
+ /**
3
+ * Array of page numbers
4
+ */
5
+ pages: number[];
6
+ /**
7
+ * Current active page
8
+ */
9
+ page: number;
10
+ /**
11
+ * Main title displayed in the toolbar
12
+ */
13
+ title?: string;
14
+ /**
15
+ * Secondary text displayed next to the title
16
+ */
17
+ subtitle?: string;
18
+ }
19
+ export interface PaginatingToolbarEvents {
20
+ /**
21
+ * Navigate to the first page
22
+ */
23
+ (e: 'first'): void;
24
+ /**
25
+ * Navigate to the previous page
26
+ */
27
+ (e: 'prev'): void;
28
+ /**
29
+ * Navigate to the next page
30
+ */
31
+ (e: 'next'): void;
32
+ /**
33
+ * Navigate to the last page
34
+ */
35
+ (e: 'last'): void;
36
+ /**
37
+ * Set the page to a specific number
38
+ */
39
+ (e: 'set-page', page: number): void;
40
+ }
@@ -0,0 +1,3 @@
1
+ export interface SkMouseTrapProps {
2
+ refreshInterval?: number;
3
+ }
@@ -0,0 +1,35 @@
1
+ export interface SkMouseTrapToolTipProps {
2
+ /**
3
+ * The keyboard shortcut(s) to bind to this tooltip.
4
+ * Can be a single string like "ctrl+s" or an array of strings.
5
+ */
6
+ hotkey: string | string[];
7
+ /**
8
+ * Descriptive name for the keyboard shortcut.
9
+ * Will be displayed in the shortcut dialog.
10
+ */
11
+ command: string;
12
+ /**
13
+ * Whether the shortcut is currently disabled.
14
+ * @default false
15
+ */
16
+ disabled?: boolean;
17
+ /**
18
+ * The position of the tooltip relative to the wrapped element.
19
+ * @default 'top'
20
+ */
21
+ position?: 'top' | 'bottom' | 'left' | 'right';
22
+ /**
23
+ * Whether to show the tooltip when the Ctrl key is pressed.
24
+ * @default true
25
+ */
26
+ showTooltip?: boolean;
27
+ /**
28
+ * The visual effect to apply to the wrapped element when Ctrl is pressed.
29
+ * @default 'glow'
30
+ */
31
+ highlightEffect?: 'glow' | 'scale' | 'border' | 'none';
32
+ }
33
+ export interface SkMouseTrapToolTipEmits {
34
+ (event: 'hotkey-triggered', hotkey: string | string[]): void;
35
+ }
@@ -0,0 +1,11 @@
1
+ import { Status } from '@vue-skuilder/common';
2
+ export interface SnackbarOptions {
3
+ text: string;
4
+ status: Status;
5
+ timeout?: number;
6
+ }
7
+ export declare const setInstance: (instance: {
8
+ addSnack: (snack: SnackbarOptions) => void;
9
+ }) => void, getInstance: () => {
10
+ addSnack: (snack: SnackbarOptions) => void;
11
+ } | null, alertUser: (msg: SnackbarOptions) => void;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Misc. config for a study StudySessionConfig
3
+ */
4
+ export type StudySessionConfig = {
5
+ likesConfetti: boolean;
6
+ };
@@ -0,0 +1,4 @@
1
+ export { default as UserChip } from './UserChip.vue';
2
+ export { default as UserLogin } from './UserLogin.vue';
3
+ export { default as UserRegistration } from './UserRegistration.vue';
4
+ export { default as UserLoginAndRegistrationContainer } from './UserLoginAndRegistrationContainer.vue';
@@ -0,0 +1,22 @@
1
+ import { MarkedToken, Tokens } from 'marked';
2
+ /**
3
+ * recursively splits text according to the passed delimiters.
4
+ *
5
+ * eg: ("abcde", "b", "d") => ["a", "bcd", "e"]
6
+ * ("a[b][c]", "[", "]") => ["a", "[b]", "[c]"]
7
+ *
8
+ * it does not check that the delimiters are well formed in the text
9
+ * @param text the text to be split
10
+ * @param l the left delimiter
11
+ * @param r the right delimiter
12
+ * @returns the split result
13
+ */
14
+ export declare function splitByDelimiters(text: string, l: string, r: string): string[];
15
+ export declare function splitTextToken(token: Tokens.Text): Tokens.Text[];
16
+ export type TokenOrComponent = MarkedToken | {
17
+ type: 'component';
18
+ raw: string;
19
+ };
20
+ export declare function splitParagraphToken(token: Tokens.Paragraph): TokenOrComponent[];
21
+ export declare function containsComponent(token: MarkedToken): boolean;
22
+ export declare function isComponent(token: MarkedToken): boolean;
@@ -0,0 +1,16 @@
1
+ import { Answer } from '@vue-skuilder/common';
2
+ import { useCardPreviewModeStore } from '../../stores/useCardPreviewModeStore';
3
+ import { ViewComponent } from '../../composables/Displayable';
4
+ import { QuestionRecord } from '@vue-skuilder/db';
5
+ declare const _default: import("vue").DefineComponent<{}, {}, {
6
+ answer: Answer;
7
+ previewModeStore: ReturnType<typeof useCardPreviewModeStore> | null;
8
+ }, {
9
+ autofocus(): boolean;
10
+ autoFocus(): boolean;
11
+ }, {
12
+ submitAnswer(answer: Answer): QuestionRecord;
13
+ submit(answer: Answer): any;
14
+ getQuestionViewAncestor(): ViewComponent;
15
+ }, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
16
+ export default _default;
@@ -0,0 +1,5 @@
1
+ import { Answer } from '@vue-skuilder/common';
2
+ export interface RadioMultipleChoiceAnswer extends Answer {
3
+ choiceList: string[];
4
+ selection: number;
5
+ }
@@ -0,0 +1,33 @@
1
+ import moment from 'moment';
2
+ import { ComputedRef, Ref } from 'vue';
3
+ import { CardRecord, QuestionRecord } from '@vue-skuilder/db';
4
+ import { HotKey } from '../utils/SkldrMouseTrap';
5
+ import { Question } from './Displayable';
6
+ import { ViewData, Answer } from '@vue-skuilder/common';
7
+ export interface ViewableUtils {
8
+ startTime: Ref<moment.Moment>;
9
+ hotKeys: Ref<HotKey[]>;
10
+ timeSpent: ComputedRef<number>;
11
+ logger: ViewableLogger;
12
+ getURL: (item: string, dataShapeIndex?: number) => string;
13
+ emitResponse: (record: CardRecord) => void;
14
+ }
15
+ export interface ViewableLogger {
16
+ log: (message?: unknown, ...params: unknown[]) => void;
17
+ error: (message?: unknown, ...params: unknown[]) => void;
18
+ warn: (message?: unknown, ...params: unknown[]) => void;
19
+ }
20
+ export interface QuestionViewUtils<Q extends Question> {
21
+ priorSessionViews: Ref<number>;
22
+ priorAttempts: Ref<number>;
23
+ priorAnswers: Ref<[Answer, string][]>;
24
+ maxAttemptsPerView: Ref<number>;
25
+ maxSessionViews: Ref<number>;
26
+ question: Ref<Q | undefined>;
27
+ submitAnswer: (answer: Answer, submittingClass?: string) => QuestionRecord;
28
+ }
29
+ export declare function useViewable(props: {
30
+ data: ViewData[];
31
+ }, emit: (event: string, ...args: unknown[]) => void, componentName: string): ViewableUtils;
32
+ export declare function useQuestionView<Q extends Question>(viewableUtils: ViewableUtils): QuestionViewUtils<Q>;
33
+ export declare function isQuestionView(component: any): component is QuestionViewUtils<Question>;
@@ -0,0 +1,47 @@
1
+ import { type DefineComponent, defineComponent } from 'vue';
2
+ import { DataShape, ViewData, Answer, Evaluation } from '@vue-skuilder/common';
3
+ export type ViewComponent = DefineComponent<unknown, unknown, unknown> | ReturnType<typeof defineComponent>;
4
+ export declare function isDefineComponent(v: ViewComponent): v is DefineComponent<unknown, unknown, unknown>;
5
+ export declare abstract class Displayable {
6
+ static dataShapes: DataShape[];
7
+ static views: Array<ViewComponent>;
8
+ static seedData?: Array<any>;
9
+ /**
10
+ * True if this displayable content type is meant to have
11
+ * user-submitted questions. False if supplied seedData array
12
+ * is comprehensive for the content type. EG, a SingleDigitAddition
13
+ * type may comprehensively supply 0+0,0+1,...,9+9 as its seed
14
+ * data, and not want any user input.
15
+ */
16
+ static acceptsUserData: boolean;
17
+ /**
18
+ *
19
+ */
20
+ constructor(viewData: ViewData[]);
21
+ abstract dataShapes(): DataShape[];
22
+ abstract views(): Array<ViewComponent>;
23
+ }
24
+ export declare abstract class Question extends Displayable {
25
+ /**
26
+ * returns a yes/no evaluation of a user's answer. Informs the SRS
27
+ * algorithm's decision to expand or reset a card's spacing
28
+ * @param answer
29
+ */
30
+ protected abstract isCorrect(answer: Answer): boolean;
31
+ /**
32
+ * returns a number from [0,1] representing the user's performance on the question,
33
+ * which informs elo adjustments and SRS multipliers
34
+ *
35
+ * @param answer the user's answer
36
+ * @param timeSpent the time the user spent on the card in milliseconds
37
+ * @returns a rating of the user's displayed skill, from 0-1
38
+ */
39
+ protected displayedSkill(answer: Answer, timeSpent: number): number;
40
+ /**
41
+ *
42
+ * @param answer the student's answer
43
+ * @param timeSpent the amount of time spent in ms
44
+ * @returns
45
+ */
46
+ evaluate(answer: Answer, timeSpent: number): Evaluation;
47
+ }
@@ -0,0 +1,2 @@
1
+ export * from './CompositionViewable';
2
+ export * from './Displayable';
@@ -0,0 +1,36 @@
1
+ export { default as HeatMap } from './components/HeatMap.vue';
2
+ export type { DayData, Color, ActivityRecord } from './components/HeatMap.types';
3
+ export { default as SkMouseTrap } from './components/SkMouseTrap.vue';
4
+ export { default as SkMouseTrapToolTip } from './components/SkMouseTrapToolTip.vue';
5
+ export * from './components/SkMouseTrap.types';
6
+ export * from './components/SkMouseTrapToolTip.types';
7
+ export { SkldrMouseTrap } from './utils/SkldrMouseTrap';
8
+ export type { HotKey, HotKeyMetaData } from './utils/SkldrMouseTrap';
9
+ export { default as SnackbarService } from './components/SnackbarService.vue';
10
+ export { alertUser, type SnackbarOptions } from './components/SnackbarService';
11
+ export { default as PaginatingToolbar } from './components/PaginatingToolbar.vue';
12
+ export * from './components/PaginatingToolbar.types';
13
+ export * from './composables/CompositionViewable';
14
+ export * from './composables/Displayable';
15
+ export { default as StudySession } from './components/StudySession.vue';
16
+ export { default as StudySessionTimer } from './components/StudySessionTimer.vue';
17
+ export type { StudySessionConfig } from './components/StudySession.types';
18
+ export * from './components/studentInputs/BaseUserInput';
19
+ export { default as RadioMultipleChoice } from './components/studentInputs/RadioMultipleChoice.vue';
20
+ export { default as MultipleChoiceOption } from './components/studentInputs/MultipleChoiceOption.vue';
21
+ export { default as TFSelect } from './components/studentInputs/TrueFalse.vue';
22
+ export { default as UserInputNumber } from './components/studentInputs/UserInputNumber.vue';
23
+ export { default as UserInputString } from './components/studentInputs/UserInputString.vue';
24
+ export { default as FillInInput } from './components/studentInputs/fillInInput.vue';
25
+ export { default as CardViewer } from './components/cardRendering/CardViewer.vue';
26
+ export { default as CardLoader } from './components/cardRendering/CardLoader.vue';
27
+ export * from './components/cardRendering/MarkdownRendererHelpers';
28
+ export { default as AudioAutoPlayer } from './components/cardRendering/AudioAutoPlayer.vue';
29
+ export { default as CodeBlockRenderer } from './components/cardRendering/CodeBlockRenderer.vue';
30
+ export { default as MdTokenRenderer } from './components/cardRendering/MdTokenRenderer.vue';
31
+ export { default as MarkdownRenderer } from './components/cardRendering/MarkdownRenderer.vue';
32
+ export * from './components/auth';
33
+ export * from './stores/useCardPreviewModeStore';
34
+ export * from './stores/useAuthStore';
35
+ export * from './stores/useConfigStore';
36
+ export { piniaPlugin } from './plugins/pinia';
@@ -0,0 +1,5 @@
1
+ import { Plugin } from 'vue';
2
+ import { Pinia } from 'pinia';
3
+ export declare const setPinia: (pinia: Pinia) => void;
4
+ export declare const getPinia: () => Pinia | null;
5
+ export declare const piniaPlugin: Plugin;
@@ -0,0 +1,225 @@
1
+ import { UserDBInterface } from '@vue-skuilder/db';
2
+ export interface AuthState {
3
+ _user: UserDBInterface | undefined;
4
+ loginAndRegistration: {
5
+ init: boolean;
6
+ loggedIn: boolean;
7
+ regDialogOpen: boolean;
8
+ loginDialogOpen: boolean;
9
+ };
10
+ onLoadComplete: boolean;
11
+ }
12
+ export declare function getCurrentUser(): Promise<UserDBInterface>;
13
+ export declare const useAuthStore: () => import("pinia").Store<"auth", AuthState, {
14
+ currentUser: () => Promise<UserDBInterface>;
15
+ isLoggedIn: (state: {
16
+ _user: {
17
+ createAccount: (username: string, password: string) => Promise<{
18
+ status: import("@vue-skuilder/common").Status;
19
+ error: string;
20
+ }>;
21
+ login: (username: string, password: string) => Promise<{
22
+ ok: boolean;
23
+ name?: string;
24
+ roles?: string[];
25
+ }>;
26
+ logout: () => Promise<{
27
+ ok: boolean;
28
+ }>;
29
+ getUsername: () => string;
30
+ isLoggedIn: () => boolean;
31
+ getConfig: () => Promise<import("@vue-skuilder/db").UserConfig>;
32
+ setConfig: (config: Partial<import("@vue-skuilder/db").UserConfig>) => Promise<void>;
33
+ putCardRecord: <T extends import("@vue-skuilder/db").CardRecord>(record: T) => Promise<import("@vue-skuilder/db").CardHistory<import("@vue-skuilder/db").CardRecord>>;
34
+ getSeenCards: (courseId?: string) => Promise<string[]>;
35
+ getActiveCards: () => Promise<string[]>;
36
+ registerForCourse: (courseId: string, previewMode?: boolean) => Promise<PouchDB.Core.Response>;
37
+ dropCourse: (courseId: string, dropStatus?: string) => Promise<PouchDB.Core.Response>;
38
+ getCourseRegistrationsDoc: () => Promise<import("@vue-skuilder/db").CourseRegistrationDoc>;
39
+ getCourseRegDoc: (courseId: string) => Promise<import("@vue-skuilder/db").CourseRegistration>;
40
+ getActiveCourses: () => Promise<import("@vue-skuilder/db").CourseRegistration[]>;
41
+ getPendingReviews: (courseId?: string) => Promise<import("@vue-skuilder/db").ScheduledCard[]>;
42
+ getActivityRecords: () => Promise<import("@vue-skuilder/db").ActivityRecord[]>;
43
+ scheduleCardReview: (review: {
44
+ user: string;
45
+ course_id: string;
46
+ card_id: string;
47
+ time: import("moment").Moment;
48
+ scheduledFor: "course" | "classroom";
49
+ schedulingAgentId: string;
50
+ }) => Promise<void>;
51
+ removeScheduledCardReview: (reviewId: string) => Promise<void>;
52
+ registerForClassroom: (classId: string, registerAs: "student" | "teacher" | "aide" | "admin") => Promise<PouchDB.Core.Response>;
53
+ dropFromClassroom: (classId: string) => Promise<PouchDB.Core.Response>;
54
+ getUserClassrooms: () => Promise<import("@vue-skuilder/db").ClassroomRegistrationDoc>;
55
+ getActiveClasses: () => Promise<string[]>;
56
+ updateUserElo: (courseId: string, elo: import("@vue-skuilder/common").CourseElo) => Promise<PouchDB.Core.Response>;
57
+ getCourseInterface: (courseId: string) => Promise<import("@vue-skuilder/db").UsrCrsDataInterface>;
58
+ update: <T extends PouchDB.Core.Document<object>>(id: string, update: Partial<T> | ((x: T) => T)) => Promise<T>;
59
+ } | undefined;
60
+ loginAndRegistration: {
61
+ init: boolean;
62
+ loggedIn: boolean;
63
+ regDialogOpen: boolean;
64
+ loginDialogOpen: boolean;
65
+ };
66
+ onLoadComplete: boolean;
67
+ } & import("pinia").PiniaCustomStateProperties<AuthState>) => boolean;
68
+ isInitialized: (state: {
69
+ _user: {
70
+ createAccount: (username: string, password: string) => Promise<{
71
+ status: import("@vue-skuilder/common").Status;
72
+ error: string;
73
+ }>;
74
+ login: (username: string, password: string) => Promise<{
75
+ ok: boolean;
76
+ name?: string;
77
+ roles?: string[];
78
+ }>;
79
+ logout: () => Promise<{
80
+ ok: boolean;
81
+ }>;
82
+ getUsername: () => string;
83
+ isLoggedIn: () => boolean;
84
+ getConfig: () => Promise<import("@vue-skuilder/db").UserConfig>;
85
+ setConfig: (config: Partial<import("@vue-skuilder/db").UserConfig>) => Promise<void>;
86
+ putCardRecord: <T extends import("@vue-skuilder/db").CardRecord>(record: T) => Promise<import("@vue-skuilder/db").CardHistory<import("@vue-skuilder/db").CardRecord>>;
87
+ getSeenCards: (courseId?: string) => Promise<string[]>;
88
+ getActiveCards: () => Promise<string[]>;
89
+ registerForCourse: (courseId: string, previewMode?: boolean) => Promise<PouchDB.Core.Response>;
90
+ dropCourse: (courseId: string, dropStatus?: string) => Promise<PouchDB.Core.Response>;
91
+ getCourseRegistrationsDoc: () => Promise<import("@vue-skuilder/db").CourseRegistrationDoc>;
92
+ getCourseRegDoc: (courseId: string) => Promise<import("@vue-skuilder/db").CourseRegistration>;
93
+ getActiveCourses: () => Promise<import("@vue-skuilder/db").CourseRegistration[]>;
94
+ getPendingReviews: (courseId?: string) => Promise<import("@vue-skuilder/db").ScheduledCard[]>;
95
+ getActivityRecords: () => Promise<import("@vue-skuilder/db").ActivityRecord[]>;
96
+ scheduleCardReview: (review: {
97
+ user: string;
98
+ course_id: string;
99
+ card_id: string;
100
+ time: import("moment").Moment;
101
+ scheduledFor: "course" | "classroom";
102
+ schedulingAgentId: string;
103
+ }) => Promise<void>;
104
+ removeScheduledCardReview: (reviewId: string) => Promise<void>;
105
+ registerForClassroom: (classId: string, registerAs: "student" | "teacher" | "aide" | "admin") => Promise<PouchDB.Core.Response>;
106
+ dropFromClassroom: (classId: string) => Promise<PouchDB.Core.Response>;
107
+ getUserClassrooms: () => Promise<import("@vue-skuilder/db").ClassroomRegistrationDoc>;
108
+ getActiveClasses: () => Promise<string[]>;
109
+ updateUserElo: (courseId: string, elo: import("@vue-skuilder/common").CourseElo) => Promise<PouchDB.Core.Response>;
110
+ getCourseInterface: (courseId: string) => Promise<import("@vue-skuilder/db").UsrCrsDataInterface>;
111
+ update: <T extends PouchDB.Core.Document<object>>(id: string, update: Partial<T> | ((x: T) => T)) => Promise<T>;
112
+ } | undefined;
113
+ loginAndRegistration: {
114
+ init: boolean;
115
+ loggedIn: boolean;
116
+ regDialogOpen: boolean;
117
+ loginDialogOpen: boolean;
118
+ };
119
+ onLoadComplete: boolean;
120
+ } & import("pinia").PiniaCustomStateProperties<AuthState>) => boolean;
121
+ status: (state: {
122
+ _user: {
123
+ createAccount: (username: string, password: string) => Promise<{
124
+ status: import("@vue-skuilder/common").Status;
125
+ error: string;
126
+ }>;
127
+ login: (username: string, password: string) => Promise<{
128
+ ok: boolean;
129
+ name?: string;
130
+ roles?: string[];
131
+ }>;
132
+ logout: () => Promise<{
133
+ ok: boolean;
134
+ }>;
135
+ getUsername: () => string;
136
+ isLoggedIn: () => boolean;
137
+ getConfig: () => Promise<import("@vue-skuilder/db").UserConfig>;
138
+ setConfig: (config: Partial<import("@vue-skuilder/db").UserConfig>) => Promise<void>;
139
+ putCardRecord: <T extends import("@vue-skuilder/db").CardRecord>(record: T) => Promise<import("@vue-skuilder/db").CardHistory<import("@vue-skuilder/db").CardRecord>>;
140
+ getSeenCards: (courseId?: string) => Promise<string[]>;
141
+ getActiveCards: () => Promise<string[]>;
142
+ registerForCourse: (courseId: string, previewMode?: boolean) => Promise<PouchDB.Core.Response>;
143
+ dropCourse: (courseId: string, dropStatus?: string) => Promise<PouchDB.Core.Response>;
144
+ getCourseRegistrationsDoc: () => Promise<import("@vue-skuilder/db").CourseRegistrationDoc>;
145
+ getCourseRegDoc: (courseId: string) => Promise<import("@vue-skuilder/db").CourseRegistration>;
146
+ getActiveCourses: () => Promise<import("@vue-skuilder/db").CourseRegistration[]>;
147
+ getPendingReviews: (courseId?: string) => Promise<import("@vue-skuilder/db").ScheduledCard[]>;
148
+ getActivityRecords: () => Promise<import("@vue-skuilder/db").ActivityRecord[]>;
149
+ scheduleCardReview: (review: {
150
+ user: string;
151
+ course_id: string;
152
+ card_id: string;
153
+ time: import("moment").Moment;
154
+ scheduledFor: "course" | "classroom";
155
+ schedulingAgentId: string;
156
+ }) => Promise<void>;
157
+ removeScheduledCardReview: (reviewId: string) => Promise<void>;
158
+ registerForClassroom: (classId: string, registerAs: "student" | "teacher" | "aide" | "admin") => Promise<PouchDB.Core.Response>;
159
+ dropFromClassroom: (classId: string) => Promise<PouchDB.Core.Response>;
160
+ getUserClassrooms: () => Promise<import("@vue-skuilder/db").ClassroomRegistrationDoc>;
161
+ getActiveClasses: () => Promise<string[]>;
162
+ updateUserElo: (courseId: string, elo: import("@vue-skuilder/common").CourseElo) => Promise<PouchDB.Core.Response>;
163
+ getCourseInterface: (courseId: string) => Promise<import("@vue-skuilder/db").UsrCrsDataInterface>;
164
+ update: <T extends PouchDB.Core.Document<object>>(id: string, update: Partial<T> | ((x: T) => T)) => Promise<T>;
165
+ } | undefined;
166
+ loginAndRegistration: {
167
+ init: boolean;
168
+ loggedIn: boolean;
169
+ regDialogOpen: boolean;
170
+ loginDialogOpen: boolean;
171
+ };
172
+ onLoadComplete: boolean;
173
+ } & import("pinia").PiniaCustomStateProperties<AuthState>) => {
174
+ loggedIn: boolean;
175
+ init: boolean;
176
+ user: {
177
+ createAccount: (username: string, password: string) => Promise<{
178
+ status: import("@vue-skuilder/common").Status;
179
+ error: string;
180
+ }>;
181
+ login: (username: string, password: string) => Promise<{
182
+ ok: boolean;
183
+ name?: string;
184
+ roles?: string[];
185
+ }>;
186
+ logout: () => Promise<{
187
+ ok: boolean;
188
+ }>;
189
+ getUsername: () => string;
190
+ isLoggedIn: () => boolean;
191
+ getConfig: () => Promise<import("@vue-skuilder/db").UserConfig>;
192
+ setConfig: (config: Partial<import("@vue-skuilder/db").UserConfig>) => Promise<void>;
193
+ putCardRecord: <T extends import("@vue-skuilder/db").CardRecord>(record: T) => Promise<import("@vue-skuilder/db").CardHistory<import("@vue-skuilder/db").CardRecord>>;
194
+ getSeenCards: (courseId?: string) => Promise<string[]>;
195
+ getActiveCards: () => Promise<string[]>;
196
+ registerForCourse: (courseId: string, previewMode?: boolean) => Promise<PouchDB.Core.Response>;
197
+ dropCourse: (courseId: string, dropStatus?: string) => Promise<PouchDB.Core.Response>;
198
+ getCourseRegistrationsDoc: () => Promise<import("@vue-skuilder/db").CourseRegistrationDoc>;
199
+ getCourseRegDoc: (courseId: string) => Promise<import("@vue-skuilder/db").CourseRegistration>;
200
+ getActiveCourses: () => Promise<import("@vue-skuilder/db").CourseRegistration[]>;
201
+ getPendingReviews: (courseId?: string) => Promise<import("@vue-skuilder/db").ScheduledCard[]>;
202
+ getActivityRecords: () => Promise<import("@vue-skuilder/db").ActivityRecord[]>;
203
+ scheduleCardReview: (review: {
204
+ user: string;
205
+ course_id: string;
206
+ card_id: string;
207
+ time: import("moment").Moment;
208
+ scheduledFor: "course" | "classroom";
209
+ schedulingAgentId: string;
210
+ }) => Promise<void>;
211
+ removeScheduledCardReview: (reviewId: string) => Promise<void>;
212
+ registerForClassroom: (classId: string, registerAs: "student" | "teacher" | "aide" | "admin") => Promise<PouchDB.Core.Response>;
213
+ dropFromClassroom: (classId: string) => Promise<PouchDB.Core.Response>;
214
+ getUserClassrooms: () => Promise<import("@vue-skuilder/db").ClassroomRegistrationDoc>;
215
+ getActiveClasses: () => Promise<string[]>;
216
+ updateUserElo: (courseId: string, elo: import("@vue-skuilder/common").CourseElo) => Promise<PouchDB.Core.Response>;
217
+ getCourseInterface: (courseId: string) => Promise<import("@vue-skuilder/db").UsrCrsDataInterface>;
218
+ update: <T extends PouchDB.Core.Document<object>>(id: string, update: Partial<T> | ((x: T) => T)) => Promise<T>;
219
+ } | undefined;
220
+ };
221
+ }, {
222
+ init(): Promise<void>;
223
+ setLoginDialog(open: boolean): void;
224
+ setRegDialog(open: boolean): void;
225
+ }>;
@@ -0,0 +1,8 @@
1
+ export interface PreviewModeState {
2
+ previewMode: boolean;
3
+ }
4
+ export declare const useCardPreviewModeStore: () => import("pinia").Store<"previewMode", PreviewModeState, {
5
+ isPreviewMode(): boolean;
6
+ }, {
7
+ setPreviewMode(mode: boolean): void;
8
+ }>;
@@ -0,0 +1,11 @@
1
+ import { UserConfig } from '@vue-skuilder/db';
2
+ export declare const useConfigStore: () => import("pinia").Store<"config", {
3
+ config: UserConfig;
4
+ }, {}, {
5
+ updateConfig(newConfig: UserConfig): void;
6
+ updateDarkMode(darkMode: boolean): Promise<void>;
7
+ updateLikesConfetti(likesConfetti: boolean): Promise<void>;
8
+ hydrate(): Promise<void>;
9
+ init(): Promise<void>;
10
+ resetDefaults(): void;
11
+ }>;
@@ -0,0 +1,32 @@
1
+ import 'mousetrap/plugins/global-bind/mousetrap-global-bind.js';
2
+ import { ExtendedKeyboardEvent } from 'mousetrap';
3
+ export interface HotKey extends HotKeyMetaData {
4
+ callback: (e: ExtendedKeyboardEvent, combo: string) => any;
5
+ }
6
+ export interface HotKeyMetaData {
7
+ command: string;
8
+ hotkey: string | string[];
9
+ }
10
+ export declare class SkldrMouseTrap {
11
+ private static _instance;
12
+ private mouseTrap;
13
+ private hotkeys;
14
+ private constructor();
15
+ static get commands(): HotKeyMetaData[];
16
+ /**
17
+ * Add keyboard bindings without resetting existing ones
18
+ * @param hk Single hotkey or array of hotkeys to bind
19
+ */
20
+ static addBinding(hk: HotKey | HotKey[]): void;
21
+ /**
22
+ * Remove specific keyboard binding(s) without affecting others
23
+ * @param hotkey Single hotkey or array of hotkeys to remove
24
+ */
25
+ static removeBinding(hotkey: string | string[]): void;
26
+ /**
27
+ * Reset all keyboard bindings
28
+ * @warning Consider using removeBinding() for targeted cleanup instead to avoid affecting other components
29
+ */
30
+ static reset(): void;
31
+ private static instance;
32
+ }
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@vue-skuilder/common-ui",
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
6
+ "version": "0.1.1",
7
+ "main": "./dist/common-ui.umd.js",
8
+ "module": "./dist/common-ui.es.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/common-ui.es.js",
14
+ "require": "./dist/common-ui.umd.js"
15
+ },
16
+ "./style": "./dist/assets/index.css",
17
+ "./styles": "./dist/assets/index.css"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "src"
22
+ ],
23
+ "scripts": {
24
+ "dev": "vite build --watch",
25
+ "build": "vite build && yarn build-types",
26
+ "build-types": "tsc --project tsconfig.types.json",
27
+ "lint": "eslint . --fix",
28
+ "lint:check": "eslint .",
29
+ "test:unit": "vitest run",
30
+ "cypress:open": "cypress open --component",
31
+ "cypress:run": "cypress run --component"
32
+ },
33
+ "dependencies": {
34
+ "@highlightjs/vue-plugin": "^2.1.2",
35
+ "@mdi/font": "^7.3.67",
36
+ "@vue-skuilder/common": "workspace:*",
37
+ "@vue-skuilder/db": "workspace:*",
38
+ "highlight.js": "^11.0.1",
39
+ "marked": "^15.0.6",
40
+ "moment": "^2.29.4",
41
+ "mousetrap": "^1.6.5",
42
+ "pinia": "^2.3.0",
43
+ "vue": "^3.5.13",
44
+ "vuetify": "^3.7.0"
45
+ },
46
+ "peerDependencies": {
47
+ "vue": "^3.2.0",
48
+ "vuetify": "^3.0.0"
49
+ },
50
+ "devDependencies": {
51
+ "@cypress/vite-dev-server": "^6.0.3",
52
+ "@types/pouchdb": "^6.4.2",
53
+ "@typescript-eslint/eslint-plugin": "^8.25.0",
54
+ "@typescript-eslint/parser": "^8.25.0",
55
+ "@vitejs/plugin-vue": "^5.2.1",
56
+ "@vue/eslint-config-typescript": "^14.4.0",
57
+ "cypress": "^14.2.1",
58
+ "cypress-vite": "^1.6.0",
59
+ "eslint": "^9.21.0",
60
+ "eslint-config-prettier": "^10.0.2",
61
+ "eslint-plugin-vue": "^9.32.0",
62
+ "sass": "^1.83.0",
63
+ "typescript": "~5.7.2",
64
+ "vite": "^6.0.9",
65
+ "vitest": "^3.0.5"
66
+ }
67
+ }