@citolab/tspci 2.5.30-beta.11 → 2.5.30-beta.3

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/CHANGELOG.md CHANGED
@@ -3,76 +3,6 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [2.5.30-beta.11](/compare/v2.5.30-beta.10...v2.5.30-beta.11) (2025-02-04)
7
-
8
-
9
- ### Features
10
-
11
- * add tailwindcss to devDependencies and set version based on @tailwindcss/postcss 907b541
12
-
13
-
14
-
15
-
16
-
17
- ## [2.5.30-beta.10](/compare/v2.5.30-beta.9...v2.5.30-beta.10) (2025-02-04)
18
-
19
- **Note:** Version bump only for package @citolab/tspci
20
-
21
-
22
-
23
-
24
-
25
- ## [2.5.30-beta.9](/compare/v2.5.30-beta.8...v2.5.30-beta.9) (2025-02-04)
26
-
27
- **Note:** Version bump only for package @citolab/tspci
28
-
29
-
30
-
31
-
32
-
33
- ## [2.5.30-beta.8](/compare/v2.5.30-beta.7...v2.5.30-beta.8) (2025-02-04)
34
-
35
- **Note:** Version bump only for package @citolab/tspci
36
-
37
-
38
-
39
-
40
-
41
- ## [2.5.30-beta.7](/compare/v2.5.30-beta.6...v2.5.30-beta.7) (2025-02-04)
42
-
43
-
44
- ### Features
45
-
46
- * dispatch qti-interaction-changed event 5c81bab
47
-
48
-
49
-
50
-
51
-
52
- ## [2.5.30-beta.6](/compare/v2.5.30-beta.5...v2.5.30-beta.6) (2025-02-03)
53
-
54
- **Note:** Version bump only for package @citolab/tspci
55
-
56
-
57
-
58
-
59
-
60
- ## [2.5.30-beta.5](/compare/v2.5.30-beta.4...v2.5.30-beta.5) (2025-02-03)
61
-
62
- **Note:** Version bump only for package @citolab/tspci
63
-
64
-
65
-
66
-
67
-
68
- ## [2.5.30-beta.4](/compare/v2.5.30-beta.3...v2.5.30-beta.4) (2025-02-03)
69
-
70
- **Note:** Version bump only for package @citolab/tspci
71
-
72
-
73
-
74
-
75
-
76
6
  ## [2.5.30-beta.3](/compare/v2.5.30-beta.2...v2.5.30-beta.3) (2025-02-03)
77
7
 
78
8
  **Note:** Version bump only for package @citolab/tspci
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@citolab/tspci",
3
- "version": "2.5.30-beta.11",
3
+ "version": "2.5.30-beta.3",
4
4
  "description": "an opiniated typescript ims-pci builder with tao integration",
5
5
  "author": "patrick <patrick.deklein@cito.nl>",
6
6
  "repository": "@citolab/tspci",
@@ -24,7 +24,6 @@
24
24
  "@rollup/plugin-terser": "^0.4.4",
25
25
  "@rollup/plugin-typescript": "^12.1.0",
26
26
  "@tailwindcss/nesting": "0.0.0-insiders.565cd3e",
27
- "@tailwindcss/postcss": "^4.0.3",
28
27
  "@testing-library/dom": "^10.4.0",
29
28
  "@types/node": "^22.5.5",
30
29
  "@typescript-eslint/eslint-plugin": "^8.9.0",
@@ -51,5 +50,5 @@
51
50
  "resolutions": {
52
51
  "chokidar": "^4.0.0"
53
52
  },
54
- "gitHead": "b49f38a0dcf06c589224b7730c5dc9cbd31ccccd"
53
+ "gitHead": "5b9acc4c3375c831ed4885bfd8a389e4c5e5a990"
55
54
  }
@@ -41,38 +41,14 @@ class Pci {
41
41
 
42
42
  this.shadowdom = dom.attachShadow({ mode: "closed" });
43
43
  this.render();
44
- const event = {
45
- interaction: this,
46
- responseIdentifier: this.config.responseIdentifier,
47
- valid: true,
48
- value: this.getResponse(),
49
- };
50
- // dispatch a custom event to notify the Delivery System that the interaction has changed
51
- const interactionChangedEvent = new CustomEvent("qtiInteractionChanged", {
52
- detail: event,
53
- });
54
- this.shadowdom.dispatchEvent(interactionChangedEvent);
55
- };
56
44
 
57
- interactionChanged = () => {
58
- const event = {
59
- interaction: this,
60
- responseIdentifier: this.config.responseIdentifier,
61
- valid: true,
62
- value: this.getResponse(),
63
- };
64
- // dispatch a custom event to notify the Delivery System that the interaction has changed
65
- const interactionChangedEvent = new CustomEvent("qti-interaction-changed", {
66
- detail: event,
67
- });
68
- this.dom.dispatchEvent(interactionChangedEvent);
45
+ config.onready(this);
69
46
  };
70
47
 
71
48
  render = () => {
72
49
  this.shadowdom.addEventListener("change", (e) => {
73
50
  const value = e.target.value;
74
51
  this.state = value;
75
- this.interactionChanged();
76
52
  });
77
53
  this.shadowdom.innerHTML = `<div class="pci-container">
78
54
  <h1>${this.config.properties.title}</h1>
@@ -4,7 +4,7 @@ import { IStore } from "@citolab/preact-store";
4
4
  import * as ctx from "qtiCustomInteractionContext";
5
5
  import Interaction from "./interaction";
6
6
  import style from "./styles.css";
7
- import { ConfigProperties, IMSpci, QtiInteractionChangedDetail, QtiVariableJSON } from "@citolab/tspci";
7
+ import { Configuration, IMSpci, QtiVariableJSON } from "@citolab/tspci";
8
8
  import configProps from "./config.json";
9
9
  import { StateModel, initStore } from "./store";
10
10
 
@@ -12,7 +12,7 @@ type PropTypes = typeof configProps;
12
12
 
13
13
  class App implements IMSpci<PropTypes> {
14
14
  typeIdentifier = "###___PCI_NAME___###"; // typeIdentifier is mandatory for all PCI's
15
- config: ConfigProperties<PropTypes>; // reference to the interface of the config object which you get when getInstance is called by the player
15
+ config: Configuration<PropTypes>; // reference to the interface of the config object which you get when getInstance is called by the player
16
16
  state: string; // keep a reference to the state
17
17
  shadowdom: ShadowRoot; // Not mandatory, but its wise to create a shadowroot
18
18
  store: IStore<StateModel>;
@@ -20,17 +20,13 @@ class App implements IMSpci<PropTypes> {
20
20
  private logActions: { type: string; payload: unknown }[] = []; // optional logActions
21
21
  private initialState: StateModel = { input: undefined }; // optional initial state
22
22
  constructor() {
23
- if (ctx) {
24
- ctx.register(this);
25
- }
23
+ ctx && ctx.register(this);
26
24
  }
27
25
 
28
- getInstance = (dom: HTMLElement, config: ConfigProperties<PropTypes>, stateString: string) => {
26
+ getInstance = (dom: HTMLElement, config: Configuration<PropTypes>, stateString: string) => {
29
27
  config.properties = { ...configProps, ...config.properties }; // merge current props with incoming
30
28
  this.config = config;
31
- if (!dom) {
32
- throw new Error("No DOM Element provided");
33
- }
29
+
34
30
  this.logActions = stateString ? JSON.parse(stateString).log : [];
35
31
  this.store = initStore(this.initialState);
36
32
  try {
@@ -43,26 +39,9 @@ class App implements IMSpci<PropTypes> {
43
39
  }
44
40
 
45
41
  this.shadowdom = dom.attachShadow({ mode: "closed" });
46
-
47
- this.store.subscribe(() => {
48
- const event: QtiInteractionChangedDetail = {
49
- interaction: this,
50
- responseIdentifier: this.config.responseIdentifier,
51
- valid: true,
52
- value: this.getResponse(),
53
- };
54
- // dispatch a custom event to notify the Delivery System that the interaction has changed
55
- const interactionChangedEvent = new CustomEvent("qti-interaction-changed", {
56
- detail: event,
57
- });
58
- dom.dispatchEvent(interactionChangedEvent);
59
- });
60
-
61
42
  this.render();
62
43
 
63
- if (this.config.onready) {
64
- this.config.onready(this);
65
- }
44
+ this.config.onready && this.config.onready(this);
66
45
  };
67
46
 
68
47
  render = () => {
@@ -1,19 +1,15 @@
1
1
  import { Store } from "@citolab/preact-store";
2
2
 
3
3
  export type ActionType = "SET_INPUT" | "RESTORE_STATE";
4
- export type StateModel = { input: number | undefined };
4
+ export type StateModel = { input: number };
5
5
 
6
- export const initStore = (
7
- initialState: StateModel,
8
- restoreData?: {
9
- state: StateModel;
10
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
- actions: { type: string; payload: any; timestamp?: number }[];
12
- }
13
- ) => {
6
+ export const initStore = (initialState: StateModel, restoreData?: {
7
+ state?: StateModel;
8
+ actions: { type: string; payload: any; timestamp?: number }[];
9
+ }) => {
14
10
  const store = new Store<StateModel>(initialState, restoreData);
15
- store.addReducer<{ input: number | undefined }>("SET_INPUT", (state, { input }) => {
16
- return { ...state, input };
11
+ store.addReducer<{ input: number }>("SET_INPUT", (state, { input }) => {
12
+ return {...state, input };
17
13
  });
18
14
  return store;
19
- };
15
+ }
@@ -1,8 +1,8 @@
1
1
  module.exports = {
2
2
  plugins: [
3
- require("postcss-import"),
4
- require("@tailwindcss/nesting"),
5
- require("@tailwindcss/postcss"),
6
- require("autoprefixer"),
7
- ],
8
- };
3
+ require('postcss-import'),
4
+ require('@tailwindcss/nesting'),
5
+ require('tailwindcss'),
6
+ require('autoprefixer'),
7
+ ]
8
+ }
@@ -1,10 +1,7 @@
1
- @import "tailwindcss";
2
- .pci-container {
3
- @apply container flex flex-col justify-center items-center;
4
- }
5
- h1 {
6
- @apply text-2xl text-red-500 m-4;
7
- }
8
- input {
9
- @apply border border-gray-400 rounded p-2 m-1;
10
- }
1
+ @tailwind components;
2
+ @tailwind utilities;
3
+ @tailwind base;
4
+
5
+ .pci-container { @apply container flex flex-col justify-center items-center; }
6
+ h1 { @apply text-2xl text-red-500 m-4; }
7
+ input { @apply border border-gray-400 rounded p-2 m-1; }
@@ -1,4 +1,4 @@
1
- import { ConfigProperties, IMSpci, QtiInteractionChangedDetail, QtiVariableJSON } from "@citolab/tspci";
1
+ import { Configuration, IMSpci, QtiVariableJSON } from "@citolab/tspci";
2
2
  import * as ctx from "qtiCustomInteractionContext";
3
3
  import configProps from "./config.json";
4
4
  import Interaction from "./interaction"; // import and bundle this interaction file
@@ -10,53 +10,31 @@ type PropTypes = typeof configProps;
10
10
 
11
11
  class Pci implements IMSpci<PropTypes> {
12
12
  typeIdentifier = "###___PCI_NAME___###"; // typeIdentifier is mandatory for all PCI's
13
- config: ConfigProperties<PropTypes>; // reference to the interface of the config object which you get when getInstance is called by the player
13
+ config: Configuration<PropTypes>; // reference to the interface of the config object which you get when getInstance is called by the player
14
14
  state: string; // keep a reference to the state
15
15
  shadowdom: ShadowRoot | Element; // Not mandatory, but its wise to create a shadowroot
16
- dom: HTMLElement;
17
16
 
18
17
  constructor() {
19
- if (ctx) {
20
- ctx.register(this); // we assume the qtiCustomInteractionContext is avaible due to the import above
21
- }
18
+ ctx && ctx.register(this); // we assume the qtiCustomInteractionContext is avaible due to the import above
22
19
  }
23
20
 
24
21
  // First in the lifecycle of a PCI, this method is called with the domElement ( usually qti-interaction-markup ) where we can add our dom tree.
25
22
  // config is the configuration object which has an onready
26
- getInstance = (dom: HTMLElement, config: ConfigProperties<PropTypes>, state: string) => {
23
+ getInstance = (dom: HTMLElement, config: Configuration<any>, state: string) => {
27
24
  config.properties = { ...configProps, ...config.properties }; // merge current props with incoming
28
25
  this.config = config;
29
26
  this.state = state ? state : "";
30
- if (!dom) {
31
- throw new Error("No DOM Element provided");
32
- }
33
- this.shadowdom = dom.attachShadow({ mode: "closed" });
34
- this.dom = dom;
35
27
 
28
+ this.shadowdom = dom.attachShadow({ mode: "closed" });
36
29
  this.render();
37
30
 
38
31
  config.onready(this);
39
32
  };
40
33
 
41
- private interactionChanged = () => {
42
- const event: QtiInteractionChangedDetail = {
43
- interaction: this,
44
- responseIdentifier: this.config.responseIdentifier,
45
- valid: true,
46
- value: this.getResponse(),
47
- };
48
- // dispatch a custom event to notify the Delivery System that the interaction has changed
49
- const interactionChangedEvent = new CustomEvent("qti-interaction-changed", {
50
- detail: event,
51
- });
52
- this.dom.dispatchEvent(interactionChangedEvent);
53
- };
54
-
55
34
  private render = () => {
56
35
  this.shadowdom.addEventListener("change", (e: Event) => {
57
36
  const value = (e.target as HTMLInputElement)?.value || "";
58
37
  this.state = value;
59
- this.interactionChanged();
60
38
  });
61
39
  this.shadowdom.innerHTML = `<div class="pci-container">
62
40
  <h1>${this.config.properties.title}</h1>
package/readme.md CHANGED
@@ -97,7 +97,7 @@ Add the following PCI in the src folder `index.ts`
97
97
 
98
98
  ```ts
99
99
  // src/index.ts
100
- import { ConfigProperties, IMSpci } from "@citolab/tspci";
100
+ import { Configuration, IMSpci } from "@citolab/tspci";
101
101
  import * as ctx from "qtiCustomInteractionContext";
102
102
 
103
103
  class Pci implements IMSpci<{}> {
@@ -108,7 +108,7 @@ class Pci implements IMSpci<{}> {
108
108
  ctx && ctx.register(this);
109
109
  }
110
110
 
111
- getInstance = (dom: HTMLElement, config: ConfigProperties<any>, state: string) => {
111
+ getInstance = (dom: HTMLElement, config: Configuration<any>, state: string) => {
112
112
  this.shadowdom = dom.attachShadow({ mode: "closed" });
113
113
  this.render();
114
114
  config.onready(this);
@@ -337,9 +337,9 @@ Also used in the TAO export for configuring PCIs in TAO
337
337
  + type PropTypes = typeof configProps;
338
338
 
339
339
  // add to types
340
- + private config: ConfigProperties<PropTypes>;
340
+ + private config: Configuration<PropTypes>;
341
341
 
342
- getInstance = (dom: HTMLElement, config: ConfigProperties<PropTypes>, stateString: string) => {
342
+ getInstance = (dom: HTMLElement, config: Configuration<PropTypes>, stateString: string) => {
343
343
  + config.properties = { ...configProps, ...config.properties }; // merge our props with players
344
344
  + this.config = config;
345
345
 
package/src/cli.js CHANGED
@@ -289,38 +289,22 @@ const run = async () => {
289
289
 
290
290
  // read postcss.config.js
291
291
  const postcssConfig = path.resolve(cliPath, "./../preset/tailwind/postcss.config.js");
292
- // get all plugin names
293
292
  const postcssConfigContent = fs.readFileSync(postcssConfig, "utf8");
294
293
  // get all plugin names
295
- // Match require statements that use either single or double quotes
296
- const pluginMatches = postcssConfigContent.match(/require\(["']([^"']+)["']\)/g);
297
- let pluginNames = [];
298
- if (pluginMatches) {
299
- pluginNames = pluginMatches.map((plugin) => plugin.replace(/require\(["']([^"']+)["']\)/, "$1"));
300
- } else {
301
- console.log("No PostCSS plugins found.");
302
- }
294
+ const pluginNames = postcssConfigContent
295
+ .match(/require\('(.*)'\)/g)
296
+ .map((plugin) => plugin.replace(/require\('(.*)'\)/, "$1"));
303
297
  const packageJsonCli = path.resolve(cliPath, "./../package.json");
304
298
  const packageJsonCliContent = fs.readFileSync(packageJsonCli, "utf8");
305
299
  const packageJsonCliContentJson = JSON.parse(packageJsonCliContent);
306
300
  // add all plugins to package.json and map the version to the version in tspci package.json
307
- let version = "latest";
308
301
  for (const pluginName of pluginNames) {
309
302
  const pluginVersion = packageJsonCliContentJson.dependencies[pluginName];
310
- if (pluginName === "@tailwindcss/postcss") {
311
- version = pluginVersion.toString();
312
- }
313
303
  packageJsonContentJson.devDependencies = {
314
304
  ...packageJsonContentJson.devDependencies,
315
305
  [pluginName]: pluginVersion,
316
306
  };
317
307
  }
318
-
319
- // add tailwindcss itself to the devDependencies
320
- packageJsonContentJson.devDependencies = {
321
- ...packageJsonContentJson.devDependencies,
322
- tailwindcss: version,
323
- };
324
308
  const newPackageJsonContent = JSON.stringify(packageJsonContentJson, null, 2);
325
309
  fs.writeFileSync(packageJson, newPackageJsonContent);
326
310
  // copy tailwind config file
@@ -446,14 +430,15 @@ const run = async () => {
446
430
  }
447
431
 
448
432
  prodBuild().then(() => {
449
- if (!targetName) {
450
- console.error("Missing target name. Use tspci --target target or tspci --targetExt target");
451
- return;
433
+ if (t) {
434
+ if (!targetName) {
435
+ console.error("Missing target name. Use tspci --target target or tspci --targetExt target");
436
+ }
437
+ const scriptFile = path.join(path.join(path.join(NODE_MODULES, `${targetName}`), "src"), `createPackage.mjs`);
438
+ import(`file:///${scriptFile}`).then((script) => {
439
+ script.bundle();
440
+ });
452
441
  }
453
- const scriptFile = path.join(path.join(path.join(NODE_MODULES, `${targetName}`), "src"), `createPackage.mjs`);
454
- import(`file:///${scriptFile}`).then((script) => {
455
- script.bundle();
456
- });
457
442
  });
458
443
  };
459
444
 
package/types/index.d.ts CHANGED
@@ -1,22 +1,22 @@
1
1
  // Define the payload structure for the custom event
2
2
  export interface QtiInteractionChangedDetail {
3
- interaction: IMSpci<unknown>; // The PCI instance itself
3
+ interaction: IMSpci<ConfigProperties>; // The PCI instance itself
4
4
  responseIdentifier: string; // The response identifier provided in the getInstance call
5
5
  valid?: boolean; // Optional boolean indicating if checkValidity() returns true
6
6
  value?: QtiVariableJSON; // Optional value returned by getResponse()
7
7
  }
8
8
 
9
9
  // Define the ConfigProperties interface
10
- export interface ConfigProperties<T> {
11
- properties: T; // Follows dataset conversion rules (camelCased keys)
10
+ export interface ConfigProperties {
11
+ properties: Record<string, string>; // Follows dataset conversion rules (camelCased keys)
12
12
  templateVariables: Record<string, QtiVariableJSON>; // Follows structure in Appendix C
13
13
  contextVariables: Record<string, QtiVariableJSON>; // Follows structure in Appendix C
14
14
  boundTo: Record<string, QtiVariableJSON>; // Follows structure in Appendix C
15
15
  responseIdentifier: string; // Unique within interaction scope
16
16
 
17
- onready: (interaction: IMSpci<T>, state?: string) => void; // Callback when PCI is fully constructed and ready
17
+ onready: (interaction: IMSpci<ConfigProperties>, state?: string) => void; // Callback when PCI is fully constructed and ready
18
18
  ondone?: (
19
- interaction: IMSpci<T>,
19
+ interaction: IMSpci<ConfigProperties>,
20
20
  response: Record<string, QtiVariableJSON>,
21
21
  state: string,
22
22
  status?: "interacting" | "closed" | "solution" | "review"
@@ -25,7 +25,7 @@ export interface ConfigProperties<T> {
25
25
  status?: "interacting" | "suspended" | "closed" | "solution" | "review"; // Optional, defaults to "interacting"
26
26
  }
27
27
 
28
- export interface IMSpci<T> {
28
+ export interface IMSpci<CustomConfigProperties extends ConfigProperties> {
29
29
  typeIdentifier: string;
30
30
 
31
31
  /** @access public
@@ -37,7 +37,7 @@ export interface IMSpci<T> {
37
37
  * This must have been obtained from a prior call to getState on an
38
38
  * instance of this type (same typeIdentifier)
39
39
  */
40
- getInstance: (dom: HTMLElement, configuration: ConfigProperties<T>, state: string) => void;
40
+ getInstance: (dom: HTMLElement, configuration: Configuration<CustomConfigProperties>, state: string) => void;
41
41
 
42
42
  /** @access public
43
43
  * @method getResponse
@@ -55,6 +55,11 @@ export interface IMSpci<T> {
55
55
  destroy?: () => void; // Not used in IMS and not in TAO implementation, so not used here (optional)
56
56
  }
57
57
 
58
+ export declare type Configuration<T extends ConfigProperties> = {
59
+ onready: () => void;
60
+ properties: T;
61
+ };
62
+
58
63
  export interface directedPair {
59
64
  destination: string;
60
65
  source: string;