cognikit 0.2.0 → 1.0.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.
package/README.md CHANGED
@@ -1,316 +1,388 @@
1
- # COGNIKIT
1
+ # Cognikit
2
2
 
3
- A TypesScript framework for creating cognitively-grounded assessment systems, quizzes and interactive educationally-oriented exercises.
4
- It is built on research in assessment design, psycometrics and cognitive science, while not limiting itself from implementing from casual
5
- environments like classrooms (the author, *me*, is a teacher), and being flexible enough to be used in other contexts like games, articles,
6
- and more.
3
+ Cognikit is a browser-first toolkit for building cognitive and educational interactions: classification, recall, recognition, text activities, and table-based tasks.
7
4
 
8
- ---
5
+ It gives you two main integration styles:
9
6
 
10
- ## Overview
7
+ - `shell + interaction`: use the built-in shell for prompt display, timer, progress, retry, score, and navigation.
8
+ - `shell-less interaction`: mount an interaction directly and manage the surrounding UI yourself.
11
9
 
12
- 'Cognikit' provides a structured approach to building educational assessments while aligning them with specific cognitive processes, a curated list
13
- of the later which are suitable for simple implementations anywhere and do not require "heavy machinery" to do so.
10
+ ## What It Includes
14
11
 
15
- Key end-use features:
12
+ - Built-in interaction classes such as `OpenClassification`, `SequentialClassification`, `MCQ`, `ListRecall`, `RankOrder`, text interactions, and table interactions.
13
+ - `createInteraction(id, data, config, assets)` for runtime creation from a registry id.
14
+ - `InteractionsBaseShell` for a ready-made interaction container.
15
+ - Asset parsing and validation helpers.
16
+ - Theme and audio configuration helpers.
17
+ - SSR compatibility guards for browser-oriented environments.
16
18
 
17
- - **Simple authoring for each interaction**
18
- - **Validators to enforce constraints over the data passed to the interactions**
19
- - **Utility Components**
20
- - **Engines for unique tools**
21
- - **Styling variations supporting components**
22
- - **Grading utilities**
19
+ ## Install
23
20
 
24
- Key development features:
21
+ ```bash
22
+ pnpm add cognikit
23
+ ```
25
24
 
26
- - **One dependency**
27
- - **Uses vanilla web technologies (and typescript)**
28
- - **Strongly typed system**
29
- - **Modular Arquitecture**
30
- - **Mixes up OOP and FP**
25
+ ## Basic Setup
31
26
 
32
- ---
27
+ The package is browser-oriented. In frameworks like React or Next.js, create and mount interactions inside a client-side effect.
33
28
 
34
- Take a look at the file structure to also visualize some of the features mentioned:
29
+ ```ts
30
+ import * as cognikit from "cognikit";
35
31
 
36
- ```txt
37
- src/
38
- // base *abstract* class which is used for all other interactions.
39
- // It itself depends on the *shell* custom component at @shell
40
- core/
41
- BaseInteraction.ts
42
-
43
- // modules which on themselves provide the *interactions*, more detailed later
44
- modules/
45
- classification/
46
- discrimination/
47
- recognition/
48
- seriation/
49
- comparison/
50
- ...
51
-
52
- engines/
53
- tables/
54
- html/
55
- ...
56
-
57
- // Custom base component that listens to the events of an interactions and triggers features like
58
- // progress, radio navigation, check button, prompt visualization and timer.
59
- shell/
60
- base/
61
- script.ts
62
-
63
- ui/
64
- input/
65
- misc/
66
-
67
- shared/
68
- ...
69
-
70
- types/
71
- Tables.ts
72
- Grading.ts
32
+ cognikit.configureCognikit({
33
+ audioBaseUrl: "/assets/audio/",
34
+ theme: "default-light",
35
+ });
73
36
  ```
74
37
 
75
- Each 'module' follow a designed pattern:
38
+ ## Quick Start: Shell + Interaction
39
+
40
+ This is the recommended path if you want the packaged UX.
76
41
 
42
+ ```ts
43
+ import * as cognikit from "cognikit";
44
+
45
+ const shell = new cognikit.InteractionsBaseShell();
46
+
47
+ const data = {
48
+ type: "sequential-classification",
49
+ categories: [
50
+ { label: "Ocean", items: ["Dolphin", "Shark", "Octopus"] },
51
+ { label: "Land", items: ["Lion", "Elephant", "Tiger"] },
52
+ { label: "Air", items: ["Eagle", "Parrot", "Hawk"] },
53
+ ],
54
+ };
55
+
56
+ const config = {
57
+ prompt: "Sort the animals by habitat",
58
+ variant: "elegant",
59
+ shuffle: true,
60
+ attemptLimit: 2,
61
+ timer: 120,
62
+ animationsEnabled: true,
63
+ soundEnabled: true,
64
+ };
65
+
66
+ const interaction = cognikit.createInteraction(
67
+ "sequential-classification",
68
+ data,
69
+ config,
70
+ null,
71
+ );
72
+
73
+ shell.setInteraction(interaction);
74
+ document.body.appendChild(shell);
77
75
  ```
78
- modules/<process>/
79
- module.ts // Central object that exports all features of the module
80
- interactions/
81
- <interaction>.ts // Classes that extend the *BaseInteraction* abstract class to create a unique way to complete an item
82
- utilitits/
83
- parser.ts
84
- grader.ts
85
- validator.ts
86
- doc/
87
- interactions.ts // Use the "IInteraction" interface and works as a programmatic documentation object
88
- <process>.md // Research and justification of the 'conginitive process'
76
+
77
+ ![Interaction Example](public/assets/DEMONSTRATION-1.jpeg)
78
+
79
+ ### What the shell gives you
80
+
81
+ - Prompt header
82
+ - Timer
83
+ - Progress bar
84
+ - Check / retry controls
85
+ - Score screen
86
+ - Sequential navigation for interactions that expose steps
87
+ - Basic error screen for invalid interactions
88
+
89
+ ## Shell-less Interactions
90
+
91
+ If you want full control over layout and surrounding controls, mount the interaction directly.
92
+
93
+ ```ts
94
+ import { ListRecall } from "cognikit";
95
+
96
+ const interaction = new ListRecall(
97
+ {
98
+ type: "seriation",
99
+ items: ["Passport", "Wallet", "Keys", "Phone"],
100
+ },
101
+ {
102
+ prompt: "Recall the travel checklist",
103
+ variant: "minimal",
104
+ shuffle: false,
105
+ attemptLimit: 1,
106
+ timer: null,
107
+ animationsEnabled: true,
108
+ soundEnabled: true,
109
+ },
110
+ );
111
+
112
+ document.querySelector("#app")?.appendChild(interaction);
89
113
  ```
90
114
 
91
- ---
115
+ Use shell-less mode when:
116
+
117
+ - you already have your own timer / scoring UI
118
+ - you want to embed interactions into an existing app layout
119
+ - you want tighter control over fullscreen, dialogs, or analytics
92
120
 
93
- ### Architecture Overview
121
+ ## Assets
94
122
 
95
- [https://sage-babka-680d4e.netlify.app]
123
+ Some interactions and prompts can reference assets such as images, video, audio, HTML, or TTS.
96
124
 
97
- ### Common Patterns
125
+ ### YAML assets
98
126
 
99
- There are built-in parsers that read a specific pattern in a string and generate the data for the interaction, but the data
100
- can be generated in any other way and ultimatilely GUI forms are best for managing assets.
127
+ ```yaml
128
+ butterfly:
129
+ type: image
130
+ url: https://example.com/butterfly.jpg
101
131
 
102
- Check this example workflow (doesn't utilize assets):
132
+ intro_audio:
133
+ type: audio
134
+ url: https://example.com/intro.mp3
135
+ volume: 80
136
+ ```
137
+
138
+ ### Parse and validate
103
139
 
104
140
  ```ts
105
- // *CLASSIFICATION* module 'DSL'
106
- const data = `
107
- AMERICA = DR | USA | Mexico;
108
- ASIA = Thailand | PNG | India | Mongolia;
109
- Africa = Madagascar | Kenya;
110
- = Antartica | Greenland;
141
+ import { parseYamlAssets, validateAndNormalizeAssets } from "cognikit";
142
+
143
+ const yaml = `
144
+ butterfly:
145
+ type: image
146
+ url: https://example.com/butterfly.jpg
111
147
  `;
112
148
 
113
- const parsedData = classificationParser(data);
114
- const isValid = classificationValidator(parsedData);
115
-
116
- if (isValid) {
117
- console.log(parsedData);
118
- }
119
-
120
- /** Which would be equal to something like this:
121
- * [
122
- * { label: 'AMERICA', items: [ 'DR', 'USA', 'Mexico ] },
123
- * { label: 'ASIA', items: [ 'Thailand', 'PNG', 'India', 'Mongolia' ] },
124
- * { label: 'Africa', items: [ 'Madagascar' | 'Kenya' ] }
125
- * ],
126
- * [ 'Antartica', 'Greenland' ] -> These are distractors
127
- */
149
+ const assets = validateAndNormalizeAssets(parseYamlAssets(yaml));
128
150
  ```
129
151
 
130
- Example expected data objects
152
+ If validation fails, Cognikit throws `AssetValidationError`.
153
+
154
+ To be able to use these assets in an interaction, you need to set <@:assetName> in the data value.
155
+
131
156
  ```ts
132
- interface ClassificationData {
133
- type: 'classification';
134
- categories: { label: string; items: string[] }[];
135
- distractors?: string[];
136
- }
137
-
138
- interface AssociationData {
139
- type: 'association';
140
- pairs: { left: string; right: string }[];
141
- distractors?: string[];
142
- }
143
-
144
- interface FreeRecallData {
145
- type: 'freerecall';
146
- instructions: { prompt: string; words: string[] }[];
147
- }
157
+ const assets = ...;
158
+
159
+ // supposing you have a asset name called "phone"
160
+ const data = {
161
+ type: "seriation",
162
+ items: ["Passport", "Wallet", "Keys", "@:phone"],
163
+ };
148
164
  ```
149
165
 
150
- ## NOTES
166
+ ## Configuring Theme
151
167
 
152
- 1) Each module has a unique text-based way of representing their required data
153
- 2) Each data model is defined in the central types (@src/shared/types.ts)
154
- 3) While it's heavily focused on this method, the way to construct the data can be done in any other way, interactions are unrelated to those processes
155
- 4) ** The 'engines' use this pattern too, but the way to use them is different since they are stand-alone.**
168
+ Cognikit exposes preset themes and theme variable overrides.
156
169
 
157
170
  ```ts
158
- // example "interaction" that uses the *TABLES* engine
159
- export class ClassificationMatrix extends BaseInteraction<BaseTableData> {
171
+ import { configureCognikit } from "cognikit";
160
172
 
161
- private _tableConfig: TableConfiguration;
162
- private _$table!: EduTable;
173
+ configureCognikit({
174
+ theme: "default-dark",
175
+ });
176
+ ```
163
177
 
164
- constructor(options: InteractionOptions<BaseTableData>) {
165
- super(options);
178
+ Available built-in themes:
166
179
 
167
- this._tableConfig = {
168
- rows: this.data.rows,
169
- cols: this.data.cols,
170
- answerKey: this.data.answerKey,
171
- cellKind: 'checkbox',
172
- preset: 'classification',
173
- variant: this.data.variant ?? 'outline'
174
- };
180
+ - `default-light`
181
+ - `default-dark`
182
+ - `ocean-light`
183
+ - `ocean-dark`
184
+ - `forest-light`
185
+ - `forest-dark`
175
186
 
176
- this.initializeProgress(this.data.rows.length);
177
- }
187
+ ### Custom theme variables
178
188
 
179
- render(): void {
180
- const content = this.getContentArea();
189
+ ```ts
190
+ configureCognikit({
191
+ theme: "default-light",
192
+ themeVariables: {
193
+ "--edu-first-accent": "124 58 237",
194
+ "--edu-radius": "0.75rem",
195
+ "--edu-card": "255 255 255",
196
+ },
197
+ });
198
+ ```
181
199
 
182
- this._$table = document.createElement('edu-table') as EduTable;
183
- this._$table.config = this._tableConfig;
200
+ ### Theme helpers
184
201
 
185
- content.innerHTML = '';
186
- content.append(this._$table);
187
- }
202
+ You can also use:
188
203
 
189
- getCurrentState(): any {
190
- return this._$table.getState();
191
- }
204
+ - `ensureCognikitTheme()`
205
+ - `getCognikitConfig()`
206
+ - `getCognikitThemePresets()`
207
+ - `resolveCognikitTheme()`
208
+ - `setCognikitTheme()`
209
+ - `resetCognikitTheme()`
210
+ - `defaultCognikitThemeVariables`
211
+ - `cognikitThemePresets`
192
212
 
193
- isInteractionComplete(): boolean {
194
- return false;
195
- }
196
- }
197
- ```
213
+ ## Configuring Audio
198
214
 
199
- ---
215
+ Built-in shell and interaction sounds resolve through Cognikit config.
200
216
 
201
- ## Variant System
217
+ ```ts
218
+ configureCognikit({
219
+ audioBaseUrl: "/assets/audio/",
220
+ });
221
+ ```
202
222
 
203
- All custom components support a `variant` attribute for consistent theming:
223
+ You can also override named sound files:
204
224
 
205
225
  ```ts
206
- type Variant =
207
- | 'elegant'
208
- | 'playful'
209
- | 'outline'
210
- | 'letter'
211
- | 'sign'
212
- | 'minimal'
213
- | 'glass'
214
- | 'empty';
226
+ configureCognikit({
227
+ audioBaseUrl: "/assets/audio/",
228
+ soundFiles: {
229
+ start: "custom-start.mp3",
230
+ success: "custom-success.mp3",
231
+ failure: "custom-failure.mp3",
232
+ },
233
+ });
215
234
  ```
216
235
 
217
- Variants are applied via CSS host selectors:
236
+ ## Interaction Setup
218
237
 
219
- ```css
220
- :host([variant="elegant"]) {
221
- /* Elegant styling */
222
- }
238
+ Most interactions use the same setup pattern:
223
239
 
224
- :host([variant="playful"]) {
225
- /* Playful styling */
226
- }
227
- ```
240
+ 1. Prepare `data`
241
+ 2. Prepare `config`
242
+ 3. Optionally parse and validate `assets`
243
+ 4. Create the interaction
244
+ 5. Mount it directly or pass it into `InteractionsBaseShell`
228
245
 
229
- ---
246
+ ### Data types
230
247
 
231
- ### SPECIFICS
248
+ Cognikit currently exposes these base data shapes:
232
249
 
233
- Most subdirectories that introduce some sort of system or important file provide a README.md that is to be read to get more insight on what it does and
234
- how it works. This overview here provides a great general idea of how everything pretty much works, but reading specifics is also necessary.
250
+ - `ClassificationData`
251
+ - `AssociationData`
252
+ - `RecognitionData`
253
+ - `SeriationData`
254
+ - `FreeRecallData`
255
+ - table data types
256
+ - text engine data types
235
257
 
236
- ---
258
+ ### Example configs
237
259
 
238
- ## Development
260
+ ```ts
261
+ const config = {
262
+ prompt: "Arrange the butterfly life cycle",
263
+ variant: "outline",
264
+ shuffle: true,
265
+ attemptLimit: 2,
266
+ timer: 180,
267
+ animationsEnabled: true,
268
+ soundEnabled: true,
269
+ };
270
+ ```
239
271
 
240
- ### Setup
272
+ Important config fields:
273
+
274
+ - `prompt`
275
+ - `variant`
276
+ - `shuffle`
277
+ - `attemptLimit`
278
+ - `timer`
279
+ - `animationsEnabled`
280
+ - `soundEnabled`
281
+ - `promptModality`
282
+ - `promptData`
283
+ - `promptDataSpec`
284
+
285
+ ## Built-in Interaction Registry IDs
286
+
287
+ These ids are registered out of the box and work with `createInteraction(...)`:
288
+
289
+ - `open-classification`
290
+ - `sequential-classification`
291
+ - `mcq`
292
+ - `simultaneous-association`
293
+ - `list-recall`
294
+ - `lookup-table`
295
+ - `classification-matrix`
296
+ - `nary-choice-table`
297
+ - `adjacency-table`
298
+ - `mark-the-words`
299
+ - `sequential-mark-the-words`
300
+ - `categorize-the-words`
301
+ - `sequential-categorize-the-words`
302
+ - `text-transformation`
303
+ - `sequential-text-transformation`
304
+ - `fill-blanks`
305
+ - `sequential-fill-blanks`
306
+ - `rank-order`
307
+
308
+ ## Recommended Imports
309
+
310
+ ### General use
241
311
 
242
- ```bash
243
- pnpm install
312
+ ```ts
313
+ import * as cognikit from "cognikit";
244
314
  ```
245
315
 
246
- ### Scripts
316
+ ### Named imports
247
317
 
248
- ```bash
249
- pnpm dev # Watch mode with hot reload
250
- pnpm build # Build library + types + demo
251
- pnpm build:lib # Build library only
252
- pnpm build:demo # Build demo app
253
- pnpm types
254
- pnpm serve
255
- pnpm clean
318
+ ```ts
319
+ import {
320
+ createInteraction,
321
+ InteractionsBaseShell,
322
+ configureCognikit,
323
+ parseYamlAssets,
324
+ validateAndNormalizeAssets,
325
+ } from "cognikit";
256
326
  ```
257
327
 
258
- ### Build Configuration
328
+ ### Client-focused entry
259
329
 
260
- - **Bundler**: esbuild
261
- - **Module Format**: ESM
262
- - **Platform**: Browser
263
- - **Loaders**:
264
- - `.html` files as text
265
- - `.css` files as text
330
+ ```ts
331
+ import * as cognikit from "cognikit/client";
332
+ ```
266
333
 
267
- ---
334
+ The `client` entrypoint ensures built-ins are registered and theme variables are applied immediately in client-only usage.
268
335
 
269
- ## Usage
336
+ ## React / Next.js Notes
270
337
 
271
- ### Creating a Module
338
+ - Use Cognikit inside a client component.
339
+ - Mount shells and interactions inside `useEffect`.
340
+ - If you switch between dark and light site themes, call `configureCognikit({ theme: ... })` when the app theme changes.
341
+ - If you want fullscreen previews, it is usually cleaner to create a second shell instance for the overlay rather than moving the same DOM node around.
272
342
 
273
- 1. Create directory: `src/modules/<process>/`
274
- 2. Implement parser, validator, grader in `utilities/`
275
- 3. Create interaction classes in `interactions/`
276
- 4. Define module metadata in `module.ts`
277
- 5. Document in `doc/`
343
+ ## Project Structure
278
344
 
279
- ### Creating an Interaction
345
+ High-level layout:
346
+
347
+ ```text
348
+ src/
349
+ core/ Base interaction primitives
350
+ interactions/ Built-in interaction classes and registry
351
+ engines/ Text and table engines
352
+ shell/ Shell UI
353
+ shared/ Config, assets, utils, managers
354
+ types/ Public types
355
+ ui/ Reusable custom elements
356
+ public/
357
+ index.html
358
+ app.js
359
+ demo assets
360
+ ```
280
361
 
281
- ```typescript
282
- import { BaseInteraction } from 'core';
283
- import { InteractionOptions } from "types/interactions";
284
- import { NormalizedAssets } from "shared/assets";
285
- import { MyInteractionData } from "...";
362
+ Key files:
286
363
 
287
- export class MyInteraction extends BaseInteraction<MyDataType> {
364
+ - `src/index.ts`: primary package entrypoint
365
+ - `src/client.ts`: client-focused entrypoint
366
+ - `src/interactions/register-builtins.ts`: built-in registry ids
367
+ - `src/shared/config.ts`: theme and audio configuration
368
+ - `src/shared/assets.ts`: asset validation
288
369
 
289
- constructor(data: MyInteractionData, config: InteractionConfig, assets?: NormalizedAssets) {
290
- super(data, config, assets);
291
- this.initializeProgress(/* total steps */);
292
- }
370
+ ## Local Development
293
371
 
294
- render(): void {
295
- const content = this.getContentArea();
296
- // Render interaction UI
297
- }
372
+ ```bash
373
+ pnpm install
374
+ pnpm dev
375
+ ```
298
376
 
299
- getCurrentState(): any {
300
- // Return current user state
301
- }
377
+ Useful scripts:
302
378
 
303
- isInteractionComplete(): boolean {
304
- // Check completion status
305
- }
379
+ - `pnpm build`
380
+ - `pnpm build:lib`
381
+ - `pnpm build:demo`
382
+ - `pnpm types`
383
+ - `pnpm serve`
306
384
 
307
- protected submitForScoring(): void {
308
- const state = this.getCurrentState();
309
- // Grade and handle result
310
- }
311
- }
312
- ```
385
+ ## License
313
386
 
314
- ## Contributing
387
+ MIT
315
388
 
316
- This is a research project in active development. Feedback and contributions welcome at the GitHub repository.