@citolab/tspci 1.5.8 → 2.0.6

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,328 +1,338 @@
1
- <h1>
2
- A modern QTI-PCI development environment creating and testing portable custom interactions
3
- </h1>
4
-
5
- <p align="center">
6
- <img src="tspci-development.png" alt="Typescript Pci Builder">
7
- </p>
8
-
9
- ## ✨ Features <a name="features"></a>
10
-
11
- - Use modern tooling like typescript, preact, postcss and tailwind
12
- - Build and bundle your library PCI using only a `package.json`
13
- - Test and develop all your PCI states, configs, responses and lifecycle without uploading
14
- - Develop in live server which directly updates on code changes
15
- - Produces a single bundle .js file to use in any delivery engine that supports the latest IMS PCI standard
16
- - 0 configuration TypeScript support
17
- - Bundles all your css, images and json files.
18
- - Postcss support, use CSS nesting out of the box.
19
- - First class (p)react and tailwind support
20
- - Extension for TAO, configuring icon, label, support for setting correct response and pci-properties
21
-
22
- ## 🔧 Installation & Setup
23
-
24
- 1️. **Install** by running: `npm i -D @citolab/tspci`
25
-
26
- 2️. **Set up** your `package.json`:
27
-
28
- `// package.json`
29
- ```json
30
- {
31
- "name": "@citolab/hello-world",
32
- "description": "Hello world pci",
33
- "version": "1.0.0",
34
- "main": "dist/index.js",
35
- "types": "dist/types.d.ts",
36
- "dependencies": {},
37
- "devDependencies": {
38
- "@citolab/tspci": "^1.5.6",
39
- "@citolab/tspci-tao": "^1.0.0"
40
- },
41
- "scripts": {
42
- "dev": "tspci --dev",
43
- "prod": "tspci"
44
- },
45
- "source": "src/index.ts"
46
- }
47
- ```
48
-
49
- Add the following PCI in the src folder `index.ts`
50
-
51
- ```ts
52
- // src/index.ts
53
- import { Configuration, IMSpci } from "@citolab/tspci";
54
- import * as ctx from "qtiCustomInteractionContext";
55
-
56
- class Pci implements IMSpci<{}> {
57
- typeIdentifier = "HelloWorld"; // same as in package.json
58
- shadowdom: ShadowRoot;
59
-
60
- constructor() {
61
- ctx && ctx.register(this);
62
- }
63
-
64
- getInstance = (dom: HTMLElement, config: Configuration<any>, state: string) => {
65
- this.shadowdom = dom.attachShadow({ mode: "closed" });
66
- this.render();
67
- config.onready(this);
68
- };
69
-
70
- private render = () => {
71
- this.shadowdom.innerHTML = `<div>Hello-World</div>`;
72
- };
73
-
74
- getResponse = () => {
75
- return null;
76
- };
77
-
78
- getState = () => null;
79
- }
80
- export default new Pci();
81
- ```
82
-
83
- Add this in your root project: `global.d.ts` file
84
-
85
- ```ts
86
- // global.d.ts
87
- declare module "qtiCustomInteractionContext" {
88
- const register: { register: (PortableInteraction) => void };
89
- export = register;
90
- }
91
- ```
92
-
93
- Add a `tsconfig.json` to your project for type checking
94
-
95
- ```json
96
- {
97
- "compilerOptions": {
98
- "declaration": true,
99
- "lib": ["es6", "dom", "dom.iterable"],
100
- "module": "es6",
101
- "moduleResolution": "node",
102
- "removeComments": true,
103
- "sourceMap": true,
104
- "strict": false,
105
- "target": "es6",
106
- "outDir": "./dist",
107
- "jsx": "react-jsx",
108
- "jsxImportSource": "preact",
109
- "allowSyntheticDefaultImports": true,
110
- "resolveJsonModule": true,
111
- "esModuleInterop": true,
112
- },
113
- "include": ["**/*"],
114
- }
115
- ```
116
-
117
- 3️⃣ **Try it out** by running `tspci --dev`.
118
-
119
- ### All CLI Options
120
-
121
- ```
122
- Usage
123
- $ tspci <command> [options]
124
-
125
- Available Commands
126
- --dev -d Start development server
127
- --watch -w Only watch changes
128
- --help -h Help about commandos
129
- --target Build production for platform
130
-
131
- Examples package.json scripts
132
- $ "dev": "tspci --dev",
133
- $ "prod": "tspci",
134
- $ "watch": "tspci --watch",
135
- $ "package-tao": "tspci --target tao"
136
- ```
137
-
138
- ## 🛣 What's next
139
-
140
- Use one of the [examples](https://github.com/Citolab/tspci-helloworld) to get a headstart
141
-
142
- Or read further how we build our PCIs
143
-
144
- Our prefered layout of our PCIs
145
- ```
146
- your-pci-project
147
- │ package.json // Definition of your PCI in a standard package.json, TAO adds some props
148
- │ global.d.ts // Tell typescript qtiCustomInteractionContext is supplied later, adds a shim
149
- │ tsconfig.json // Typescript configuration, also for type checking your code
150
- │
151
- └───src
152
- │ │ config.json // Used to configure PCI, and in TAO for authors
153
- │ │ index.ts // The api for the player and bootstraps your interaction
154
- │ │ interaction.ts // the actual interaction, preferably a main preact component
155
- │ │ store.ts // definition of the state and all possible state mutations of your pci
156
- │ └───style.css // css styles, imported by your pci and possible to use tailwind classes
157
- │
158
- │ postcss.config.js // optionally adds postcss processing of css
159
- │ tailwind.config.js // include tailwind classes
160
- ```
161
-
162
-
163
- ### Use JSX
164
- Use (p)react in your PCI's to create interactions and bind your data to HTML
165
-
166
- ```ts
167
- + import { h, render } from "preact";
168
-
169
- render(null, this.shadowdom);
170
-
171
- render = () => {
172
- + render(null, this.shadowdom);
173
- + render(<Interaction config={this.config.properties} />, this.shadowdom);
174
- };
175
- ```
176
-
177
- ### Bundle your css
178
- Import and bundle css
179
- Appending css to shadowdom will prevent styles leaking into your player
180
-
181
- ```ts
182
- + import style from "./style.css";
183
-
184
- render = () => {
185
- render(...
186
- + const css = document.createElement("style");
187
- + css.innerHTML = style;
188
- + this.shadowdom.appendChild(css);
189
- render(...
190
- };
191
- ```
192
-
193
- ### Use modern css
194
- add `postcss.config.js` with autoprefixer
195
-
196
- // postcss.config.js
197
- ```js
198
- module.exports = {
199
- plugins: [
200
- require('postcss-import'),
201
- require('autoprefixer'),
202
- ]
203
- }
204
- ```
205
-
206
- ### Modern UI with existing classes
207
-
208
- add tailwind to `postcss.config.js`
209
- and add a `tailwind.config.js`
210
-
211
- ```js
212
- // postcss.config.js
213
- plugins: [
214
- + require('tailwindcss/nesting'),
215
- + require('tailwindcss'),
216
- ];
217
- ```
218
-
219
- ```js
220
- // tailwind.config.js
221
- module.exports = {
222
- content: ["./src/**/*.{html,js,ts,jsx,tsx}", "./*.xml"], // html/javascript and typescript, and everything in pci markup
223
- theme: {
224
- extend: {},
225
- },
226
- plugins: [],
227
- };
228
- ```
229
-
230
- ### Bundle all your images
231
- Images are bundled in the js by importing them in code:
232
- imports JPG, PNG, GIF, SVG, and WebP files
233
-
234
- ```ts
235
- import procenten from "./assets/procenten.png";
236
- <img src={procenten} />;
237
- ```
238
-
239
- ### Create advanced PCIs with 3D libraries
240
- For example, import threejs to create 3D pci's
241
-
242
- ```ts
243
- // src/interaction.ts
244
- import * as THREE from "three";
245
-
246
- class VoxelPainterClass {
247
- private scene: THREE.Scene;
248
- ```
249
-
250
- ### Record user interaction
251
- A store will centralize your PCI state but also all mutations.
252
- This means, this way you could replay everything a user did
253
- And you can use Redux devtools to debug
254
-
255
- ```ts
256
- // src/index.ts
257
- const [state, dispatch] = useStore<StateModel, ActionType>((type, payload) => {});
258
-
259
- dispatch<{ x: number }>("ADD_ACTION", { x: +inputValue });
260
- ```
261
-
262
- ### Let authors configure your PCI in QTI
263
- Use properties in config.json to let authors configure your PCI
264
- Also used in the TAO export for configuring PCIs in TAO
265
- ```json
266
- `// src/config.json`
267
- {
268
- "buttonText": "Calculate",
269
- "sum1" : "$1 * 14 + 1",
270
- "sum2" : "$1 * 2 + 21",
271
- "tableSize" : "4"
272
- }
273
- ```
274
- ```ts
275
- // src/index.ts
276
- + import configProps from "./config.json";
277
- + type PropTypes = typeof configProps;
278
-
279
- // add to types
280
- + private config: Configuration<PropTypes>;
281
-
282
- getInstance = (dom: HTMLElement, config: Configuration<PropTypes>, stateString: string) => {
283
- + config.properties = { ...configProps, ...config.properties }; // merge our props with players
284
- + this.config = config;
285
-
286
- // destructure props for use in PCI
287
- + const { sum1, sum2, buttonText, tableSize } = config;
288
-
289
- ```
290
-
291
- ### Make use of existing react hooks
292
- ```ts
293
- // src/useMousePosition
294
- import { useEffect, useState } from "react";
295
-
296
- export const useMousePosition = () => {
297
- const [position, setPosition] = useState({ x: 0, y: 0 });
298
-
299
- useEffect(() => {
300
- const setPosFromEvent = (e) => setPosition({ x: e.clientX, y: e.clientY });
301
- window.addEventListener("mousemove", setPosFromEvent);
302
- return () => window.removeEventListener("mousemove", setPosFromEvent);
303
- }, []);
304
-
305
- return { clientX: position.x, clientY: position.y }
306
- };
307
- ```
308
-
309
- ### Use in TAO
310
- Tao adds some lifecycle methods which you can implement and we supply an extended interfaee on top of the IMS one.
311
-
312
- More info, see our extension
313
- [@citolab/tspci-tao](https://www.npmjs.com/package/@citolab/tspci-tao)
314
-
315
-
316
- ## Roadmap
317
-
318
- - Packager for Facet
319
- - Packager for Trifork
320
- - Create PCI with Vue
321
- - Create PCI with Haunted
322
-
323
- If you want your platform to be support, [contact us](mailto://getinspiredbycitolab@gmail.com)
324
-
325
-
326
- ## License
327
-
1
+ <h1>
2
+ A modern QTI-PCI development environment creating and testing portable custom interactions
3
+ </h1>
4
+
5
+ <p align="center">
6
+ <img src="https://github.com/Citolab/tspci/blob/main/lib/tspci/tspci-development.png" alt="Typescript Pci Builder">
7
+ </p>
8
+
9
+ [Release notes](https://github.com/Citolab/tspci/lib/tspci/release-notes.md)
10
+
11
+ ## ✨ Features <a name="features"></a>
12
+
13
+ - Use modern tooling like typescript, preact, postcss and tailwind
14
+ - Build and bundle your library PCI using only a `package.json`
15
+ - Test and develop all your PCI states, configs, responses and lifecycle without uploading
16
+ - Develop in live server which directly updates on code changes
17
+ - Produces a single bundle .js file to use in any delivery engine that supports the latest IMS PCI standard
18
+ - 0 configuration TypeScript support
19
+ - Bundles all your css, images and json files.
20
+ - Postcss support, use CSS nesting out of the box.
21
+ - First class (p)react and tailwind support
22
+ - Extension for TAO, configuring icon, label, support for setting correct response and pci-properties
23
+
24
+ ## 🔧 Installation & Setup
25
+
26
+ 1️. **Install** by running: `npm i -D @citolab/tspci`
27
+
28
+ 2️. **Set up** your `package.json`:
29
+
30
+ `// package.json`
31
+ ```json
32
+ {
33
+ "name": "@citolab/hello-world",
34
+ "description": "Hello world pci",
35
+ "version": "1.0.0",
36
+ "main": "dist/index.js",
37
+ "types": "dist/types.d.ts",
38
+ "dependencies": {},
39
+ "devDependencies": {
40
+ "@citolab/tspci": "^1.5.6",
41
+ "@citolab/tspci-tao": "^1.0.0"
42
+ },
43
+ "scripts": {
44
+ "dev": "tspci --dev",
45
+ "prod": "tspci"
46
+ },
47
+ "source": "src/index.ts"
48
+ }
49
+ ```
50
+
51
+ Add the following PCI in the src folder `index.ts`
52
+
53
+ ```ts
54
+ // src/index.ts
55
+ import { Configuration, IMSpci } from "@citolab/tspci";
56
+ import * as ctx from "qtiCustomInteractionContext";
57
+
58
+ class Pci implements IMSpci<{}> {
59
+ typeIdentifier = "HelloWorld"; // same as in package.json
60
+ shadowdom: ShadowRoot;
61
+
62
+ constructor() {
63
+ ctx && ctx.register(this);
64
+ }
65
+
66
+ getInstance = (dom: HTMLElement, config: Configuration<any>, state: string) => {
67
+ this.shadowdom = dom.attachShadow({ mode: "closed" });
68
+ this.render();
69
+ config.onready(this);
70
+ };
71
+
72
+ private render = () => {
73
+ this.shadowdom.innerHTML = `<div>Hello-World</div>`;
74
+ };
75
+
76
+ getResponse = () => {
77
+ return null;
78
+ };
79
+
80
+ getState = () => null;
81
+ }
82
+ export default new Pci();
83
+ ```
84
+
85
+ Add this in your root project: `global.d.ts` file
86
+
87
+ ```ts
88
+ // global.d.ts
89
+ declare module "qtiCustomInteractionContext" {
90
+ const register: { register: (PortableInteraction) => void };
91
+ export = register;
92
+ }
93
+ ```
94
+
95
+ Add a `tsconfig.json` to your project for type checking
96
+
97
+ ```json
98
+ {
99
+ "compilerOptions": {
100
+ "declaration": true,
101
+ "lib": ["es6", "dom", "dom.iterable"],
102
+ "module": "es6",
103
+ "moduleResolution": "node",
104
+ "removeComments": true,
105
+ "sourceMap": true,
106
+ "strict": false,
107
+ "target": "es6",
108
+ "outDir": "./dist",
109
+ "jsx": "react-jsx",
110
+ "jsxImportSource": "preact",
111
+ "allowSyntheticDefaultImports": true,
112
+ "resolveJsonModule": true,
113
+ "esModuleInterop": true,
114
+ },
115
+ "include": ["**/*"],
116
+ }
117
+ ```
118
+
119
+ **Try it out** by running `tspci --dev`.
120
+
121
+ ### All CLI Options
122
+
123
+ ```
124
+ Usage
125
+ $ tspci <command> [options]
126
+
127
+ Available Commands
128
+ --dev -d Start development server
129
+ --watch -w Only watch changes
130
+ --help -h Help about commandos
131
+ --target -t Build production for platform
132
+
133
+ Examples package.json scripts
134
+ $ "dev": "tspci --dev",
135
+ $ "prod": "tspci",
136
+ $ "watch": "tspci --watch",
137
+ $ "package-tao": "tspci --target tao"
138
+ ```
139
+
140
+ ## 🛣 What's next
141
+
142
+ Use one of the [examples](https://github.com/Citolab/tspci-helloworld) to get a headstart
143
+
144
+ Or read further how we build our PCIs
145
+
146
+ Our prefered layout of our PCIs
147
+ ```
148
+ your-pci-project
149
+ │ package.json // Definition of your PCI in a standard package.json, TAO adds some props
150
+ │ global.d.ts // Tell typescript qtiCustomInteractionContext is supplied later, adds a shim
151
+ │ tsconfig.json // Typescript configuration, also for type checking your code
152
+ │
153
+ └───src
154
+ │ │ config.json // Used to configure PCI, and in TAO for authors
155
+ │ │ index.ts // The api for the player and bootstraps your interaction
156
+ │ │ interaction.ts // the actual interaction, preferably a main preact component
157
+ │ │ store.ts // definition of the state and all possible state mutations of your pci
158
+ │ └───style.css // css styles, imported by your pci and possible to use tailwind classes
159
+ │
160
+ │ postcss.config.js // optionally adds postcss processing of css
161
+ │ tailwind.config.js // include tailwind classes
162
+ ```
163
+
164
+
165
+ ### Use JSX
166
+ Use (p)react in your PCI's to create interactions and bind your data to HTML
167
+
168
+ ```ts
169
+ + import { h, render } from "preact";
170
+
171
+ render(null, this.shadowdom);
172
+
173
+ render = () => {
174
+ + render(null, this.shadowdom);
175
+ + render(<Interaction config={this.config.properties} />, this.shadowdom);
176
+ };
177
+ ```
178
+
179
+ ### Bundle your css
180
+ Import and bundle css
181
+ Appending css to shadowdom will prevent styles leaking into your player
182
+
183
+ ```ts
184
+ + import style from "./style.css";
185
+
186
+ render = () => {
187
+ render(...
188
+ + const css = document.createElement("style");
189
+ + css.innerHTML = style;
190
+ + this.shadowdom.appendChild(css);
191
+ render(...
192
+ };
193
+ ```
194
+
195
+ ### Use modern css
196
+
197
+ install autoprefixer
198
+
199
+ ``` sh
200
+ npm i -D autoprefixer
201
+ ```
202
+
203
+ add `postcss.config.js` with autoprefixer
204
+
205
+ // postcss.config.js
206
+ ```js
207
+ module.exports = {
208
+ plugins: [
209
+ require('postcss-import'),
210
+ require('autoprefixer'),
211
+ ]
212
+ }
213
+ ```
214
+
215
+ ### Modern UI with existing classes
216
+
217
+ add tailwind to `postcss.config.js`
218
+ and add a `tailwind.config.js`
219
+
220
+ ```js
221
+ // postcss.config.js
222
+ plugins: [
223
+ + require('tailwindcss/nesting'),
224
+ + require('tailwindcss'),
225
+ ];
226
+ ```
227
+
228
+ ```js
229
+ // tailwind.config.js
230
+ module.exports = {
231
+ content: ["./src/**/*.{html,js,ts,jsx,tsx}", "./*.xml"], // html/javascript and typescript, and everything in pci markup
232
+ theme: {
233
+ extend: {},
234
+ },
235
+ plugins: [],
236
+ };
237
+ ```
238
+
239
+ ### Bundle all your images
240
+ Images are bundled in the js by importing them in code:
241
+ imports JPG, PNG, GIF, SVG, and WebP files
242
+
243
+ ```ts
244
+ import procenten from "./assets/procenten.png";
245
+ <img src={procenten} />;
246
+ ```
247
+
248
+ ### Create advanced PCIs with 3D libraries
249
+ For example, import threejs to create 3D pci's
250
+
251
+ ```ts
252
+ // src/interaction.ts
253
+ import * as THREE from "three";
254
+
255
+ class VoxelPainterClass {
256
+ private scene: THREE.Scene;
257
+ ```
258
+
259
+ ### Record user interaction
260
+ A store will centralize your PCI state but also all mutations.
261
+ This means, this way you could replay everything a user did
262
+ And you can use Redux devtools to debug
263
+
264
+ ```ts
265
+ // src/index.ts
266
+ const [state, dispatch] = useStore<StateModel, ActionType>((type, payload) => {});
267
+
268
+ dispatch<{ x: number }>("ADD_ACTION", { x: +inputValue });
269
+ ```
270
+
271
+ ### Let authors configure your PCI in QTI
272
+ Use properties in config.json to let authors configure your PCI
273
+ Also used in the TAO export for configuring PCIs in TAO
274
+ `// src/config.json`
275
+ ```json
276
+ {
277
+ "buttonText": "Calculate",
278
+ "sum1" : "$1 * 14 + 1",
279
+ "sum2" : "$1 * 2 + 21",
280
+ "tableSize" : "4"
281
+ }
282
+ ```
283
+ ```ts
284
+ // src/index.ts
285
+ + import configProps from "./config.json";
286
+ + type PropTypes = typeof configProps;
287
+
288
+ // add to types
289
+ + private config: Configuration<PropTypes>;
290
+
291
+ getInstance = (dom: HTMLElement, config: Configuration<PropTypes>, stateString: string) => {
292
+ + config.properties = { ...configProps, ...config.properties }; // merge our props with players
293
+ + this.config = config;
294
+
295
+ // destructure props for use in PCI
296
+ + const { sum1, sum2, buttonText, tableSize } = config;
297
+
298
+ ```
299
+
300
+ ### Make use of existing react hooks
301
+ ```ts
302
+ // src/useMousePosition
303
+ import { useEffect, useState } from "react";
304
+
305
+ export const useMousePosition = () => {
306
+ const [position, setPosition] = useState({ x: 0, y: 0 });
307
+
308
+ useEffect(() => {
309
+ const setPosFromEvent = (e) => setPosition({ x: e.clientX, y: e.clientY });
310
+ window.addEventListener("mousemove", setPosFromEvent);
311
+ return () => window.removeEventListener("mousemove", setPosFromEvent);
312
+ }, []);
313
+
314
+ return { clientX: position.x, clientY: position.y }
315
+ };
316
+ ```
317
+
318
+ ### Use in TAO
319
+ Tao adds some lifecycle methods which you can implement and we supply an extended interfaee on top of the IMS one.
320
+
321
+ More info, see our extension
322
+ - [github](../tspci-tao)
323
+ - [@citolab/tspci-tao](https://www.npmjs.com/package/@citolab/tspci-tao)
324
+
325
+
326
+ ## Roadmap
327
+
328
+ - Packager for Facet
329
+ - Packager for Trifork
330
+ - Create PCI with Vue
331
+ - Create PCI with Haunted
332
+
333
+ If you want your platform to be support, [contact us](mailto://getinspiredbycitolab@gmail.com)
334
+
335
+
336
+ ## License
337
+
328
338
  [GPLv3](./LICENSE)