@popp0102/questify 0.10.0 → 0.11.0

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/dist/questify.js CHANGED
@@ -1,282 +1,277 @@
1
- import { jsx as T } from "react/jsx-runtime";
2
- import { createContext as Q, useState as O, useEffect as q, useContext as B } from "react";
3
- const I = {}, F = {
4
- store: async (i, t) => {
5
- I[i] = t;
1
+ import { jsx as p } from "react/jsx-runtime";
2
+ import { createContext as q, useState as O, useEffect as B, useContext as F } from "react";
3
+ const I = {}, J = {
4
+ store: async (r, e) => {
5
+ I[r] = e;
6
6
  },
7
- load: async (i) => I[i]
7
+ load: async (r) => I[r]
8
8
  };
9
- class y {
10
- constructor(t, e, s, l, a) {
11
- this.id = t, this.type = e, this.title = s, this.solution = l, this.blueprint = a, this.isSolved = !1;
9
+ class w {
10
+ constructor(e, t, s, l, c) {
11
+ this.id = e, this.type = t, this.title = s, this.solution = l, this.blueprint = c, this.isSolved = !1;
12
12
  }
13
- clone({ isSolved: t }) {
14
- const e = Object.create(y.prototype);
15
- return e.id = this.id, e.type = this.type, e.title = this.title, e.solution = this.solution, e.blueprint = this.blueprint, e.isSolved = t, e;
13
+ clone({ isSolved: e }) {
14
+ const t = Object.create(w.prototype);
15
+ return t.id = this.id, t.type = this.type, t.title = this.title, t.solution = this.solution, t.blueprint = this.blueprint, t.isSolved = e, t;
16
16
  }
17
17
  markAsSolved() {
18
18
  return this.clone({ isSolved: !0 });
19
19
  }
20
20
  }
21
- class v {
22
- constructor(t) {
23
- this.id = t.id, this.name = t.name, this.icon = t.icon, this.subtitle = t.subtitle, this.description = t.description, this.trials = t.trials.map(
24
- (e, s) => new y(s, e.type, e.title, e.solution, e.blueprint)
21
+ class h {
22
+ constructor(e) {
23
+ this.id = e.id, this.name = e.name, this.icon = e.icon, this.subtitle = e.subtitle, this.description = e.description, this.levels = e.levels.map(
24
+ (t, s) => new w(s, t.type, t.title, t.solution, t.blueprint)
25
25
  ), this.updateStatus();
26
26
  }
27
- static constructFromTrials(t, e, s, l, a, n) {
28
- const r = Object.create(v.prototype);
29
- return r.id = t, r.name = e, r.icon = l, r.subtitle = a, r.description = n, r.trials = s, r.updateStatus(), r;
27
+ static constructFromLevels(e, t, s, l, c, n) {
28
+ const i = Object.create(h.prototype);
29
+ return i.id = e, i.name = t, i.icon = l, i.subtitle = c, i.description = n, i.levels = s, i.updateStatus(), i;
30
30
  }
31
- submitAnswer(t, e) {
32
- const s = this.trials.find((l) => l.id === t);
31
+ submitAnswer(e, t) {
32
+ const s = this.levels.find((l) => l.id === e);
33
33
  if (!s)
34
34
  return null;
35
- if (s.solution === e.trim().toLowerCase()) {
36
- const l = this.trials.map(
37
- (a) => a.id === t ? a.markAsSolved() : a
35
+ if (s.solution === t.trim().toLowerCase()) {
36
+ const l = this.levels.map(
37
+ (c) => c.id === e ? c.markAsSolved() : c
38
38
  );
39
- return this.clone({ trials: l });
39
+ return this.clone({ levels: l });
40
40
  }
41
41
  return null;
42
42
  }
43
43
  updateStatus() {
44
- const t = this.trials.filter((l) => l.isSolved).length, e = this.trials.length;
44
+ const e = this.levels.filter((l) => l.isSolved).length, t = this.levels.length;
45
45
  let s;
46
- t === 0 ? s = "not-started" : t === e ? s = "completed" : s = "in-progress", this.progressSummary = {
46
+ e === 0 ? s = "not-started" : e === t ? s = "completed" : s = "in-progress", this.progressSummary = {
47
47
  status: s,
48
- solvedCount: t,
49
- totalTrials: e,
50
- percentageComplete: e > 0 ? t / e * 100 : 0
48
+ solvedCount: e,
49
+ totalLevels: t,
50
+ percentageComplete: t > 0 ? e / t * 100 : 0
51
51
  };
52
52
  }
53
- clone(t) {
54
- const e = Object.create(v.prototype);
55
- return e.id = this.id, e.name = this.name, e.icon = this.icon, e.subtitle = this.subtitle, e.description = this.description, e.trials = t.trials ?? this.trials, e.updateStatus(), e;
53
+ clone(e) {
54
+ const t = Object.create(h.prototype);
55
+ return t.id = this.id, t.name = this.name, t.icon = this.icon, t.subtitle = this.subtitle, t.description = this.description, t.levels = e.levels ?? this.levels, t.updateStatus(), t;
56
56
  }
57
57
  }
58
- class H {
59
- constructor(t = null, e = null) {
60
- this.activeHuntId = t, this.activeTrialIndex = e;
58
+ class y {
59
+ constructor(e = null, t = null) {
60
+ this.activeAdventureId = e, this.activeLevelIndex = t;
61
61
  }
62
62
  clone() {
63
- const t = Object.create(H.prototype);
64
- return t.activeHuntId = this.activeHuntId, t.activeTrialIndex = this.activeTrialIndex, t;
65
- }
66
- isOnHuntSelection() {
67
- return this.activeHuntId === null;
63
+ const e = Object.create(y.prototype);
64
+ return e.activeAdventureId = this.activeAdventureId, e.activeLevelIndex = this.activeLevelIndex, e;
68
65
  }
69
- isOnTrialSelection() {
70
- return this.activeHuntId !== null && this.activeTrialIndex === null;
66
+ isOnAdventureSelection() {
67
+ return this.activeAdventureId === null;
71
68
  }
72
- isOnActiveTrial() {
73
- return this.activeHuntId !== null && this.activeTrialIndex !== null;
69
+ isOnLevelSelection() {
70
+ return this.activeAdventureId !== null && this.activeLevelIndex === null;
74
71
  }
75
- moveToHuntSelection() {
76
- const t = this.clone();
77
- return t.activeHuntId = null, t.activeTrialIndex = null, t;
72
+ isOnActiveLevel() {
73
+ return this.activeAdventureId !== null && this.activeLevelIndex !== null;
78
74
  }
79
- moveToHunt(t) {
75
+ moveToAdventureSelection() {
80
76
  const e = this.clone();
81
- return e.activeHuntId = t, e.activeTrialIndex = null, e;
77
+ return e.activeAdventureId = null, e.activeLevelIndex = null, e;
82
78
  }
83
- moveToTrialSelectScreen() {
84
- if (this.activeHuntId === null)
85
- throw new Error("Cannot move to trial select when no hunt is active");
79
+ moveToAdventure(e) {
86
80
  const t = this.clone();
87
- return t.activeTrialIndex = null, t;
81
+ return t.activeAdventureId = e, t.activeLevelIndex = null, t;
88
82
  }
89
- moveToTrialScreen(t) {
90
- if (this.activeHuntId === null)
91
- throw new Error("Cannot move to trial when no hunt is active");
83
+ moveToLevelSelectScreen() {
84
+ if (this.activeAdventureId === null)
85
+ throw new Error("Cannot move to level select when no adventure is active");
92
86
  const e = this.clone();
93
- return e.activeTrialIndex = t, e;
87
+ return e.activeLevelIndex = null, e;
88
+ }
89
+ moveToLevelScreen(e) {
90
+ if (this.activeAdventureId === null)
91
+ throw new Error("Cannot move to level when no adventure is active");
92
+ const t = this.clone();
93
+ return t.activeLevelIndex = e, t;
94
94
  }
95
95
  }
96
- const g = Q({
97
- hunts: [],
96
+ const T = q({
97
+ adventures: [],
98
98
  playerLocation: null,
99
- activeHunt: () => null,
100
- activeTrial: () => null,
101
- isOnHuntSelection: () => !1,
102
- isOnTrialSelection: () => !1,
103
- isOnActiveTrial: () => !1,
104
- activateHunt: () => {
99
+ activeAdventure: () => null,
100
+ activeLevel: () => null,
101
+ isOnAdventureSelection: () => !1,
102
+ isOnLevelSelection: () => !1,
103
+ isOnActiveLevel: () => !1,
104
+ activateAdventure: () => {
105
105
  },
106
- moveToHuntSelection: () => {
106
+ moveToAdventureSelection: () => {
107
107
  },
108
- moveToTrialSelectScreen: () => {
108
+ moveToLevelSelectScreen: () => {
109
109
  },
110
- moveToTrialScreen: () => {
110
+ moveToLevelScreen: () => {
111
111
  },
112
112
  submitAnswer: () => {
113
113
  }
114
114
  });
115
- function R({ huntConfigs: i, persister: t, children: e }) {
116
- const s = t || F, [l, a] = O(i.map((o) => new v(o))), [n, r] = O(new H());
117
- q(() => {
115
+ function V({ adventureConfigs: r, persister: e, children: t }) {
116
+ const s = e || J, [l, c] = O(r.map((o) => new h(o))), [n, i] = O(new y());
117
+ B(() => {
118
118
  async function o() {
119
119
  const d = await Promise.all(
120
- i.map(async (u) => {
121
- const m = `questify-${u.id}-solved-trials`, p = await s.load(m), S = new v(u);
122
- if (p) {
123
- const f = JSON.parse(p), h = S.trials.map((w) => f.includes(w.id) ? w.markAsSolved() : w);
124
- return v.constructFromTrials(u.id, u.name, h);
120
+ r.map(async (u) => {
121
+ const m = `questify-${u.id}-solved-levels`, L = await s.load(m), S = new h(u);
122
+ if (L) {
123
+ const A = JSON.parse(L), a = S.levels.map((f) => A.includes(f.id) ? f.markAsSolved() : f);
124
+ return h.constructFromLevels(u.id, u.name, a);
125
125
  }
126
126
  return S;
127
127
  })
128
128
  );
129
- a(d);
129
+ c(d);
130
130
  }
131
131
  o();
132
- }, [s, i]);
133
- function c() {
134
- return n.activeHuntId === null ? null : l.find((o) => o.id === n.activeHuntId) || null;
132
+ }, [s, r]);
133
+ function v() {
134
+ return n.activeAdventureId === null ? null : l.find((o) => o.id === n.activeAdventureId) || null;
135
135
  }
136
136
  function b() {
137
- const o = c();
138
- return !o || n.activeTrialIndex === null ? null : o.trials[n.activeTrialIndex] || null;
137
+ const o = v();
138
+ return !o || n.activeLevelIndex === null ? null : o.levels[n.activeLevelIndex] || null;
139
139
  }
140
- function A() {
141
- return n.isOnHuntSelection();
140
+ function g() {
141
+ return n.isOnAdventureSelection();
142
142
  }
143
143
  function C() {
144
- return n.isOnTrialSelection();
144
+ return n.isOnLevelSelection();
145
145
  }
146
146
  function E() {
147
- return n.isOnActiveTrial();
147
+ return n.isOnActiveLevel();
148
148
  }
149
- function L(o) {
149
+ function P(o) {
150
150
  if (!l.find((u) => u.id === o))
151
- throw new Error(`Hunt with id "${o}" not found`);
152
- r(n.moveToHunt(o));
153
- }
154
- function P() {
155
- r(n.moveToHuntSelection());
151
+ throw new Error(`Adventure with id "${o}" not found`);
152
+ i(n.moveToAdventure(o));
156
153
  }
157
154
  function k() {
158
- r(n.moveToTrialSelectScreen());
155
+ i(n.moveToAdventureSelection());
159
156
  }
160
- function $(o) {
161
- const d = c();
157
+ function $() {
158
+ i(n.moveToLevelSelectScreen());
159
+ }
160
+ function j(o) {
161
+ const d = v();
162
162
  if (!d)
163
- throw new Error("Cannot move to trial when no hunt is selected");
164
- if (o < 0 || o >= d.trials.length)
165
- throw new Error(`Trial index ${o} is out of bounds for hunt "${d.id}"`);
166
- r(n.moveToTrialScreen(o));
163
+ throw new Error("Cannot move to level when no adventure is selected");
164
+ if (o < 0 || o >= d.levels.length)
165
+ throw new Error(`Level index ${o} is out of bounds for adventure "${d.id}"`);
166
+ i(n.moveToLevelScreen(o));
167
167
  }
168
- async function j(o) {
169
- const d = b(), u = c();
168
+ async function N(o) {
169
+ const d = b(), u = v();
170
170
  if (!d || !u)
171
171
  return !1;
172
172
  const m = u.submitAnswer(d.id, o);
173
173
  if (m) {
174
- const p = l.map((h) => h.id === u.id ? m : h);
175
- a(p);
176
- const S = `questify-${u.id}-solved-trials`, f = m.trials.filter((h) => h.isSolved).map((h) => h.id);
177
- return await s.store(S, JSON.stringify(f)), !0;
174
+ const L = l.map((a) => a.id === u.id ? m : a);
175
+ c(L);
176
+ const S = `questify-${u.id}-solved-levels`, A = m.levels.filter((a) => a.isSolved).map((a) => a.id);
177
+ return await s.store(S, JSON.stringify(A)), !0;
178
178
  }
179
179
  return !1;
180
180
  }
181
- const N = {
182
- hunts: l,
181
+ const Q = {
182
+ adventures: l,
183
183
  playerLocation: n,
184
- activeHunt: c,
185
- activeTrial: b,
186
- isOnHuntSelection: A,
187
- isOnTrialSelection: C,
188
- isOnActiveTrial: E,
189
- activateHunt: L,
190
- moveToHuntSelection: P,
191
- moveToTrialSelectScreen: k,
192
- moveToTrialScreen: $,
193
- submitAnswer: j
184
+ activeAdventure: v,
185
+ activeLevel: b,
186
+ isOnAdventureSelection: g,
187
+ isOnLevelSelection: C,
188
+ isOnActiveLevel: E,
189
+ activateAdventure: P,
190
+ moveToAdventureSelection: k,
191
+ moveToLevelSelectScreen: $,
192
+ moveToLevelScreen: j,
193
+ submitAnswer: N
194
194
  };
195
- return /* @__PURE__ */ T(g.Provider, { value: N, children: e });
195
+ return /* @__PURE__ */ p(T.Provider, { value: Q, children: t });
196
196
  }
197
- class J {
197
+ class K {
198
198
  constructor() {
199
199
  this.registry = /* @__PURE__ */ new Map();
200
200
  }
201
- register(t, e) {
202
- this.registry.set(t, e);
201
+ register(e, t) {
202
+ this.registry.set(e, t);
203
203
  }
204
- get(t) {
205
- return this.registry.get(t);
204
+ get(e) {
205
+ return this.registry.get(e);
206
206
  }
207
- has(t) {
208
- return this.registry.has(t);
207
+ has(e) {
208
+ return this.registry.has(e);
209
209
  }
210
210
  }
211
- const x = new J();
212
- function V() {
213
- const i = B(g);
214
- if (!i.hunts || i.hunts.length === 0)
215
- throw new Error("No hunts found. Make sure you pass huntConfigs to the QuestifyProvider");
216
- function t(s, l, a) {
217
- if (i.isOnHuntSelection()) {
218
- const n = i.hunts.map((r) => ({
219
- id: r.id,
220
- name: r.name,
221
- progressSummary: r.progressSummary,
222
- onSelectHunt: () => i.activateHunt(r.id)
223
- }));
224
- return /* @__PURE__ */ T(s, { hunts: n });
211
+ const x = new K();
212
+ function z() {
213
+ const r = F(T);
214
+ if (!r.adventures || r.adventures.length === 0)
215
+ throw new Error("No adventures found. Make sure you pass adventureConfigs to the QuestifyProvider");
216
+ function e(s, l, c) {
217
+ if (r.isOnAdventureSelection()) {
218
+ const n = r.adventures.map((i) => ({ ...i, onSelectAdventure: () => r.activateAdventure(i.id) }));
219
+ return /* @__PURE__ */ p(s, { adventures: n });
225
220
  }
226
- if (i.isOnTrialSelection()) {
227
- const n = i.activeHunt();
221
+ if (r.isOnLevelSelection()) {
222
+ const n = r.activeAdventure();
228
223
  if (!n)
229
- throw new Error("Cannot render trial selection without an active hunt");
230
- const r = n.trials.map((c) => ({
231
- id: c.id,
232
- title: c.title,
233
- type: c.type,
234
- isSolved: c.isSolved,
235
- solution: c.solution,
236
- onSelectTrial: () => i.moveToTrialScreen(c.id)
224
+ throw new Error("Cannot render level selection without an active adventure");
225
+ const i = n.levels.map((v) => ({
226
+ id: v.id,
227
+ title: v.title,
228
+ type: v.type,
229
+ isSolved: v.isSolved,
230
+ solution: v.solution,
231
+ onSelectLevel: () => r.moveToLevelScreen(v.id)
237
232
  }));
238
- return /* @__PURE__ */ T(
233
+ return /* @__PURE__ */ p(
239
234
  l,
240
235
  {
241
- hunt: n,
242
- trials: r,
243
- onBack: i.moveToHuntSelection
236
+ adventure: n,
237
+ levels: i,
238
+ onBack: r.moveToAdventureSelection
244
239
  }
245
240
  );
246
241
  }
247
- if (i.isOnActiveTrial()) {
248
- const n = i.activeTrial();
242
+ if (r.isOnActiveLevel()) {
243
+ const n = r.activeLevel();
249
244
  if (!n)
250
- throw new Error("Cannot render trial screen without an active trial");
251
- const r = x.get(n.type);
252
- if (!r)
253
- throw new Error(`No trial component registered for type: ${n.type}`);
254
- return /* @__PURE__ */ T(
255
- a,
245
+ throw new Error("Cannot render level screen without an active level");
246
+ const i = x.get(n.type);
247
+ if (!i)
248
+ throw new Error(`No level component registered for type: ${n.type}`);
249
+ return /* @__PURE__ */ p(
250
+ c,
256
251
  {
257
252
  title: n.title,
258
- onBack: i.moveToTrialSelectScreen,
253
+ onBack: r.moveToLevelSelectScreen,
259
254
  isSolved: n.isSolved,
260
- TrialComponent: () => /* @__PURE__ */ T(r, { ...n.blueprint, title: n.title })
255
+ LevelComponent: () => /* @__PURE__ */ p(i, { ...n.blueprint, title: n.title })
261
256
  }
262
257
  );
263
258
  }
264
259
  throw new Error("Invalid player location state");
265
260
  }
266
- function e(s) {
267
- return i.submitAnswer(s);
261
+ function t(s) {
262
+ return r.submitAnswer(s);
268
263
  }
269
264
  return {
270
- renderScreen: t,
271
- submitAnswer: e
265
+ renderScreen: e,
266
+ submitAnswer: t
272
267
  };
273
268
  }
274
- const z = (i, t) => {
275
- x.register(i, t);
269
+ const D = (r, e) => {
270
+ x.register(r, e);
276
271
  };
277
272
  export {
278
- R as QuestifyProvider,
279
- z as registerTrialComponent,
280
- V as useQuestify
273
+ V as QuestifyProvider,
274
+ D as registerLevelComponent,
275
+ z as useQuestify
281
276
  };
282
277
  //# sourceMappingURL=questify.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"questify.js","sources":["../lib/store/MemoryPersister.ts","../lib/models/Trial.ts","../lib/models/Hunt.ts","../lib/models/PlayerLocation.ts","../lib/store/QuestifyContext.tsx","../lib/registry/TrialRegistry.ts","../lib/hooks/useQuestify.tsx","../lib/index.ts"],"sourcesContent":["const storage = {};\nexport const memoryPersister = {\n store: async (key, value) => {\n storage[key] = value;\n },\n load: async (key) => {\n return storage[key];\n },\n};\n","class Trial {\n id: number;\n type: string;\n title: string;\n solution: string;\n blueprint: Record<string, any>;\n isSolved: boolean;\n\n constructor(id: number, type: string, title: string, solution: string, blueprint: Record<string, any>) {\n this.id = id;\n this.type = type;\n this.title = title;\n this.solution = solution;\n this.blueprint = blueprint;\n this.isSolved = false;\n }\n\n private clone({ isSolved }: { isSolved: boolean }): Trial {\n const cloned = Object.create(Trial.prototype);\n cloned.id = this.id;\n cloned.type = this.type;\n cloned.title = this.title;\n cloned.solution = this.solution;\n cloned.blueprint = this.blueprint;\n cloned.isSolved = isSolved;\n return cloned;\n }\n\n markAsSolved(): Trial {\n return this.clone({ isSolved: true });\n }\n}\n\nexport default Trial;\n","import Trial from '@models/Trial';\n\nenum HuntStatus {\n NOT_STARTED = 'not-started',\n IN_PROGRESS = 'in-progress',\n COMPLETED = 'completed'\n}\n\ninterface TrialConfig {\n type: string;\n title: string;\n solution: string;\n blueprint: Record<string, any>;\n}\n\ninterface HuntConfig {\n id: string;\n name: string;\n icon?: string;\n subtitle?: string;\n description?: string;\n trials: TrialConfig[];\n}\n\ninterface ProgressSummary {\n status: HuntStatus;\n solvedCount: number;\n totalTrials: number;\n percentageComplete: number;\n}\n\nclass Hunt {\n id: string;\n name: string;\n icon?: string;\n subtitle?: string;\n description?: string;\n trials: Trial[];\n progressSummary: ProgressSummary;\n\n constructor(config: HuntConfig) {\n this.id = config.id;\n this.name = config.name;\n this.icon = config.icon;\n this.subtitle = config.subtitle;\n this.description = config.description;\n this.trials = config.trials.map((trialConfig, index) =>\n new Trial(index, trialConfig.type, trialConfig.title, trialConfig.solution, trialConfig.blueprint)\n );\n this.updateStatus();\n }\n\n static constructFromTrials(id: string, name: string, trials: Trial[], icon?: string, subtitle?: string, description?: string): Hunt {\n const hunt = Object.create(Hunt.prototype);\n hunt.id = id;\n hunt.name = name;\n hunt.icon = icon;\n hunt.subtitle = subtitle;\n hunt.description = description;\n hunt.trials = trials;\n hunt.updateStatus();\n return hunt;\n }\n\n submitAnswer(trialId: number, answer: string): Hunt | null {\n const trial = this.trials.find(trial => trial.id === trialId);\n\n if (!trial) {\n return null;\n }\n\n if (trial.solution === answer.trim().toLowerCase()) {\n const updatedTrials = this.trials.map(trial =>\n trial.id === trialId ? trial.markAsSolved() : trial\n );\n return this.clone({ trials: updatedTrials });\n }\n\n return null;\n }\n\n private updateStatus(): void {\n const solvedCount = this.trials.filter(trial => trial.isSolved).length;\n const totalTrials = this.trials.length;\n\n let status: HuntStatus;\n if (solvedCount === 0) {\n status = HuntStatus.NOT_STARTED;\n } else if (solvedCount === totalTrials) {\n status = HuntStatus.COMPLETED;\n } else {\n status = HuntStatus.IN_PROGRESS;\n }\n\n this.progressSummary = {\n status,\n solvedCount,\n totalTrials,\n percentageComplete: totalTrials > 0 ? (solvedCount / totalTrials) * 100 : 0\n };\n }\n\n private clone(updates: Partial<{ trials: Trial[] }>): Hunt {\n const cloned = Object.create(Hunt.prototype);\n cloned.id = this.id;\n cloned.name = this.name;\n cloned.icon = this.icon;\n cloned.subtitle = this.subtitle;\n cloned.description = this.description;\n cloned.trials = updates.trials ?? this.trials;\n cloned.updateStatus();\n return cloned;\n }\n}\n\nexport default Hunt;\n","class PlayerLocation {\n activeHuntId: string | null;\n activeTrialIndex: number | null;\n\n constructor(huntId: string | null = null, trialIndex: number | null = null) {\n this.activeHuntId = huntId;\n this.activeTrialIndex = trialIndex;\n }\n\n private clone(): PlayerLocation {\n const cloned = Object.create(PlayerLocation.prototype);\n cloned.activeHuntId = this.activeHuntId;\n cloned.activeTrialIndex = this.activeTrialIndex;\n return cloned;\n }\n\n isOnHuntSelection(): boolean {\n return this.activeHuntId === null;\n }\n\n isOnTrialSelection(): boolean {\n return this.activeHuntId !== null && this.activeTrialIndex === null;\n }\n\n isOnActiveTrial(): boolean {\n return this.activeHuntId !== null && this.activeTrialIndex !== null;\n }\n\n moveToHuntSelection(): PlayerLocation {\n const newLocation = this.clone();\n newLocation.activeHuntId = null;\n newLocation.activeTrialIndex = null;\n return newLocation;\n }\n\n moveToHunt(huntId: string): PlayerLocation {\n const newLocation = this.clone();\n newLocation.activeHuntId = huntId;\n newLocation.activeTrialIndex = null;\n return newLocation;\n }\n\n moveToTrialSelectScreen(): PlayerLocation {\n if (this.activeHuntId === null) {\n throw new Error('Cannot move to trial select when no hunt is active');\n }\n\n const newLocation = this.clone();\n newLocation.activeTrialIndex = null;\n return newLocation;\n }\n\n moveToTrialScreen(trialIdx: number): PlayerLocation {\n if (this.activeHuntId === null) {\n throw new Error('Cannot move to trial when no hunt is active');\n }\n\n const newLocation = this.clone();\n newLocation.activeTrialIndex = trialIdx;\n return newLocation;\n }\n}\n\nexport default PlayerLocation;\n","import { useState, useEffect, createContext } from \"react\";\nimport { memoryPersister } from '@store/MemoryPersister';\nimport Hunt from '@models/Hunt';\nimport PlayerLocation from '@models/PlayerLocation';\n\nexport const QuestifyContext = createContext({\n hunts: [],\n playerLocation: null,\n activeHunt: () => null,\n activeTrial: () => null,\n isOnHuntSelection: () => false,\n isOnTrialSelection: () => false,\n isOnActiveTrial: () => false,\n activateHunt: () => {},\n moveToHuntSelection: () => {},\n moveToTrialSelectScreen: () => {},\n moveToTrialScreen: () => {},\n submitAnswer: () => {},\n});\n\nexport default function QuestifyProvider({ huntConfigs, persister, children }) {\n const progressPersister = persister || memoryPersister;\n const [hunts, setHunts] = useState(huntConfigs.map(config => new Hunt(config)));\n const [playerLocation, setPlayerLocation] = useState(new PlayerLocation());\n\n useEffect(() => {\n async function loadProgress() {\n const restoredHunts = await Promise.all(\n huntConfigs.map(async (config) => {\n const storageKey = `questify-${config.id}-solved-trials`;\n const savedTrialsStr = await progressPersister.load(storageKey);\n const restoredHunt = new Hunt(config);\n\n if (savedTrialsStr) {\n const solvedTrialIds = JSON.parse(savedTrialsStr);\n const updatedTrials = restoredHunt.trials.map(trial => solvedTrialIds.includes(trial.id) ? trial.markAsSolved() : trial);\n return Hunt.constructFromTrials(config.id, config.name, updatedTrials);\n }\n\n return restoredHunt;\n })\n );\n\n setHunts(restoredHunts);\n }\n\n loadProgress();\n }, [progressPersister, huntConfigs]);\n\n function activeHunt() {\n if (playerLocation.activeHuntId === null) {\n return null;\n }\n return hunts.find(hunt => hunt.id === playerLocation.activeHuntId) || null;\n }\n\n function activeTrial() {\n const hunt = activeHunt();\n if (!hunt || playerLocation.activeTrialIndex === null) {\n return null;\n }\n return hunt.trials[playerLocation.activeTrialIndex] || null;\n }\n\n function isOnHuntSelection() {\n return playerLocation.isOnHuntSelection();\n }\n\n function isOnTrialSelection() {\n return playerLocation.isOnTrialSelection();\n }\n\n function isOnActiveTrial() {\n return playerLocation.isOnActiveTrial();\n }\n\n function activateHunt(huntId) {\n const hunt = hunts.find(hunt => hunt.id === huntId);\n if (!hunt) {\n throw new Error(`Hunt with id \"${huntId}\" not found`);\n }\n setPlayerLocation(playerLocation.moveToHunt(huntId));\n }\n\n function moveToHuntSelection() {\n setPlayerLocation(playerLocation.moveToHuntSelection());\n }\n\n function moveToTrialSelectScreen() {\n setPlayerLocation(playerLocation.moveToTrialSelectScreen());\n }\n\n function moveToTrialScreen(trialIdx) {\n const hunt = activeHunt();\n if (!hunt) {\n throw new Error('Cannot move to trial when no hunt is selected');\n }\n if (trialIdx < 0 || trialIdx >= hunt.trials.length) {\n throw new Error(`Trial index ${trialIdx} is out of bounds for hunt \"${hunt.id}\"`);\n }\n setPlayerLocation(playerLocation.moveToTrialScreen(trialIdx));\n }\n\n async function handleSubmitAnswer(answer) {\n const trial = activeTrial();\n const currentHunt = activeHunt();\n\n if (!trial || !currentHunt) {\n return false;\n }\n\n const newHunt = currentHunt.submitAnswer(trial.id, answer);\n\n if (newHunt) {\n const updatedHunts = hunts.map(hunt => hunt.id === currentHunt.id ? newHunt : hunt);\n setHunts(updatedHunts);\n\n const storageKey = `questify-${currentHunt.id}-solved-trials`;\n const solvedTrialIds = newHunt.trials.filter(trial => trial.isSolved).map(trial => trial.id);\n await progressPersister.store(storageKey, JSON.stringify(solvedTrialIds));\n return true;\n }\n\n return false;\n }\n\n const questifyCtxValue = {\n hunts: hunts,\n playerLocation: playerLocation,\n activeHunt: activeHunt,\n activeTrial: activeTrial,\n isOnHuntSelection: isOnHuntSelection,\n isOnTrialSelection: isOnTrialSelection,\n isOnActiveTrial: isOnActiveTrial,\n activateHunt: activateHunt,\n moveToHuntSelection: moveToHuntSelection,\n moveToTrialSelectScreen: moveToTrialSelectScreen,\n moveToTrialScreen: moveToTrialScreen,\n submitAnswer: handleSubmitAnswer,\n };\n\n return (\n <QuestifyContext.Provider value={questifyCtxValue}>\n {children}\n </QuestifyContext.Provider>\n );\n}\n","type TrialComponent = React.ComponentType<any>;\n\nclass TrialRegistry {\n private registry: Map<string, TrialComponent> = new Map();\n\n register(type: string, component: TrialComponent): void {\n this.registry.set(type, component);\n }\n\n get(type: string): TrialComponent | undefined {\n return this.registry.get(type);\n }\n\n has(type: string): boolean {\n return this.registry.has(type);\n }\n}\n\nexport const trialRegistry = new TrialRegistry();\n","import { useContext } from \"react\";\nimport { QuestifyContext } from \"@store/QuestifyContext\";\nimport { trialRegistry } from \"@registry/TrialRegistry\";\n\nexport function useQuestify() {\n const context = useContext(QuestifyContext);\n\n if (!context.hunts || context.hunts.length === 0) {\n throw new Error(\"No hunts found. Make sure you pass huntConfigs to the QuestifyProvider\");\n }\n\n function renderScreen(HuntSelectComponent, TrialSelectComponent, TrialScreenComponent) {\n if (context.isOnHuntSelection()) {\n const hunts = context.hunts.map((hunt) => ({\n id: hunt.id,\n name: hunt.name,\n progressSummary: hunt.progressSummary,\n onSelectHunt: () => context.activateHunt(hunt.id)\n }));\n return <HuntSelectComponent hunts={hunts} />;\n }\n\n if (context.isOnTrialSelection()) {\n const activeHunt = context.activeHunt();\n if (!activeHunt) {\n throw new Error(\"Cannot render trial selection without an active hunt\");\n }\n\n const trials = activeHunt.trials.map((trial) => ({\n id: trial.id,\n title: trial.title,\n type: trial.type,\n isSolved: trial.isSolved,\n solution: trial.solution,\n onSelectTrial: () => context.moveToTrialScreen(trial.id)\n }));\n\n return <TrialSelectComponent\n hunt={activeHunt}\n trials={trials}\n onBack={context.moveToHuntSelection}\n />;\n }\n\n if (context.isOnActiveTrial()) {\n const trial = context.activeTrial();\n if (!trial) {\n throw new Error(\"Cannot render trial screen without an active trial\");\n }\n\n const TrialComponent = trialRegistry.get(trial.type);\n\n if (!TrialComponent) {\n throw new Error(`No trial component registered for type: ${trial.type}`);\n }\n\n return <TrialScreenComponent\n title={trial.title}\n onBack={context.moveToTrialSelectScreen}\n isSolved={trial.isSolved} \n TrialComponent={() => <TrialComponent {...trial.blueprint} title={trial.title}/>}\n />;\n }\n\n throw new Error(\"Invalid player location state\");\n }\n\n function submitAnswer(answer) {\n return context.submitAnswer(answer);\n }\n\n return {\n renderScreen: renderScreen,\n submitAnswer: submitAnswer,\n };\n}\n","import { useQuestify } from '@hooks/useQuestify';\nimport QuestifyProvider from '@store/QuestifyContext';\nimport { trialRegistry } from '@registry/TrialRegistry';\n\nexport const registerTrialComponent = (type: string, component: React.ComponentType<any>) => {\n trialRegistry.register(type, component);\n};\n\nexport { QuestifyProvider, useQuestify };\n"],"names":["storage","memoryPersister","key","value","Trial","id","type","title","solution","blueprint","isSolved","cloned","Hunt","config","trialConfig","index","name","trials","icon","subtitle","description","hunt","trialId","answer","trial","updatedTrials","solvedCount","totalTrials","status","updates","PlayerLocation","huntId","trialIndex","newLocation","trialIdx","QuestifyContext","createContext","QuestifyProvider","huntConfigs","persister","children","progressPersister","hunts","setHunts","useState","playerLocation","setPlayerLocation","useEffect","loadProgress","restoredHunts","storageKey","savedTrialsStr","restoredHunt","solvedTrialIds","activeHunt","activeTrial","isOnHuntSelection","isOnTrialSelection","isOnActiveTrial","activateHunt","moveToHuntSelection","moveToTrialSelectScreen","moveToTrialScreen","handleSubmitAnswer","currentHunt","newHunt","updatedHunts","questifyCtxValue","TrialRegistry","component","trialRegistry","useQuestify","context","useContext","renderScreen","HuntSelectComponent","TrialSelectComponent","TrialScreenComponent","jsx","TrialComponent","submitAnswer","registerTrialComponent"],"mappings":"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"}
1
+ {"version":3,"file":"questify.js","sources":["../lib/store/MemoryPersister.ts","../lib/models/Level.ts","../lib/models/Adventure.ts","../lib/models/PlayerLocation.ts","../lib/store/QuestifyContext.tsx","../lib/registry/LevelRegistry.ts","../lib/hooks/useQuestify.tsx","../lib/index.ts"],"sourcesContent":["const storage = {};\nexport const memoryPersister = {\n store: async (key, value) => {\n storage[key] = value;\n },\n load: async (key) => {\n return storage[key];\n },\n};\n","class Level {\n id: number;\n type: string;\n title: string;\n solution: string;\n blueprint: Record<string, any>;\n isSolved: boolean;\n\n constructor(id: number, type: string, title: string, solution: string, blueprint: Record<string, any>) {\n this.id = id;\n this.type = type;\n this.title = title;\n this.solution = solution;\n this.blueprint = blueprint;\n this.isSolved = false;\n }\n\n private clone({ isSolved }: { isSolved: boolean }): Level {\n const cloned = Object.create(Level.prototype);\n cloned.id = this.id;\n cloned.type = this.type;\n cloned.title = this.title;\n cloned.solution = this.solution;\n cloned.blueprint = this.blueprint;\n cloned.isSolved = isSolved;\n return cloned;\n }\n\n markAsSolved(): Level {\n return this.clone({ isSolved: true });\n }\n}\n\nexport default Level;\n","import Level from '@models/Level';\n\nenum AdventureStatus {\n NOT_STARTED = 'not-started',\n IN_PROGRESS = 'in-progress',\n COMPLETED = 'completed'\n}\n\ninterface LevelConfig {\n type: string;\n title: string;\n solution: string;\n blueprint: Record<string, any>;\n}\n\ninterface AdventureConfig {\n id: string;\n name: string;\n icon?: string;\n subtitle?: string;\n description?: string;\n levels: LevelConfig[];\n}\n\ninterface ProgressSummary {\n status: AdventureStatus;\n solvedCount: number;\n totalLevels: number;\n percentageComplete: number;\n}\n\nclass Adventure {\n id: string;\n name: string;\n icon?: string;\n subtitle?: string;\n description?: string;\n levels: Level[];\n progressSummary: ProgressSummary;\n\n constructor(config: AdventureConfig) {\n this.id = config.id;\n this.name = config.name;\n this.icon = config.icon;\n this.subtitle = config.subtitle;\n this.description = config.description;\n this.levels = config.levels.map((levelConfig, index) =>\n new Level(index, levelConfig.type, levelConfig.title, levelConfig.solution, levelConfig.blueprint)\n );\n this.updateStatus();\n }\n\n static constructFromLevels(id: string, name: string, levels: Level[], icon?: string, subtitle?: string, description?: string): Adventure {\n const adventure = Object.create(Adventure.prototype);\n adventure.id = id;\n adventure.name = name;\n adventure.icon = icon;\n adventure.subtitle = subtitle;\n adventure.description = description;\n adventure.levels = levels;\n adventure.updateStatus();\n return adventure;\n }\n\n submitAnswer(levelId: number, answer: string): Adventure | null {\n const level = this.levels.find(level => level.id === levelId);\n\n if (!level) {\n return null;\n }\n\n if (level.solution === answer.trim().toLowerCase()) {\n const updatedLevels = this.levels.map(level =>\n level.id === levelId ? level.markAsSolved() : level\n );\n return this.clone({ levels: updatedLevels });\n }\n\n return null;\n }\n\n private updateStatus(): void {\n const solvedCount = this.levels.filter(level => level.isSolved).length;\n const totalLevels = this.levels.length;\n\n let status: AdventureStatus;\n if (solvedCount === 0) {\n status = AdventureStatus.NOT_STARTED;\n } else if (solvedCount === totalLevels) {\n status = AdventureStatus.COMPLETED;\n } else {\n status = AdventureStatus.IN_PROGRESS;\n }\n\n this.progressSummary = {\n status,\n solvedCount,\n totalLevels,\n percentageComplete: totalLevels > 0 ? (solvedCount / totalLevels) * 100 : 0\n };\n }\n\n private clone(updates: Partial<{ levels: Level[] }>): Adventure {\n const cloned = Object.create(Adventure.prototype);\n cloned.id = this.id;\n cloned.name = this.name;\n cloned.icon = this.icon;\n cloned.subtitle = this.subtitle;\n cloned.description = this.description;\n cloned.levels = updates.levels ?? this.levels;\n cloned.updateStatus();\n return cloned;\n }\n}\n\nexport default Adventure;\nexport { Adventure, AdventureStatus, AdventureConfig, LevelConfig, ProgressSummary };\n","class PlayerLocation {\n activeAdventureId: string | null;\n activeLevelIndex: number | null;\n\n constructor(adventureId: string | null = null, levelIndex: number | null = null) {\n this.activeAdventureId = adventureId;\n this.activeLevelIndex = levelIndex;\n }\n\n private clone(): PlayerLocation {\n const cloned = Object.create(PlayerLocation.prototype);\n cloned.activeAdventureId = this.activeAdventureId;\n cloned.activeLevelIndex = this.activeLevelIndex;\n return cloned;\n }\n\n isOnAdventureSelection(): boolean {\n return this.activeAdventureId === null;\n }\n\n isOnLevelSelection(): boolean {\n return this.activeAdventureId !== null && this.activeLevelIndex === null;\n }\n\n isOnActiveLevel(): boolean {\n return this.activeAdventureId !== null && this.activeLevelIndex !== null;\n }\n\n moveToAdventureSelection(): PlayerLocation {\n const newLocation = this.clone();\n newLocation.activeAdventureId = null;\n newLocation.activeLevelIndex = null;\n return newLocation;\n }\n\n moveToAdventure(adventureId: string): PlayerLocation {\n const newLocation = this.clone();\n newLocation.activeAdventureId = adventureId;\n newLocation.activeLevelIndex = null;\n return newLocation;\n }\n\n moveToLevelSelectScreen(): PlayerLocation {\n if (this.activeAdventureId === null) {\n throw new Error('Cannot move to level select when no adventure is active');\n }\n\n const newLocation = this.clone();\n newLocation.activeLevelIndex = null;\n return newLocation;\n }\n\n moveToLevelScreen(levelIdx: number): PlayerLocation {\n if (this.activeAdventureId === null) {\n throw new Error('Cannot move to level when no adventure is active');\n }\n\n const newLocation = this.clone();\n newLocation.activeLevelIndex = levelIdx;\n return newLocation;\n }\n}\n\nexport default PlayerLocation;\n","import { useState, useEffect, createContext } from \"react\";\nimport { memoryPersister } from '@store/MemoryPersister';\nimport Adventure from '@models/Adventure';\nimport PlayerLocation from '@models/PlayerLocation';\n\nexport const QuestifyContext = createContext({\n adventures: [],\n playerLocation: null,\n activeAdventure: () => null,\n activeLevel: () => null,\n isOnAdventureSelection: () => false,\n isOnLevelSelection: () => false,\n isOnActiveLevel: () => false,\n activateAdventure: () => {},\n moveToAdventureSelection: () => {},\n moveToLevelSelectScreen: () => {},\n moveToLevelScreen: () => {},\n submitAnswer: () => {},\n});\n\nexport default function QuestifyProvider({ adventureConfigs, persister, children }) {\n const progressPersister = persister || memoryPersister;\n const [adventures, setAdventures] = useState(adventureConfigs.map(config => new Adventure(config)));\n const [playerLocation, setPlayerLocation] = useState(new PlayerLocation());\n\n useEffect(() => {\n async function loadProgress() {\n const restoredAdventures = await Promise.all(\n adventureConfigs.map(async (config) => {\n const storageKey = `questify-${config.id}-solved-levels`;\n const savedLevelsStr = await progressPersister.load(storageKey);\n const restoredAdventure = new Adventure(config);\n\n if (savedLevelsStr) {\n const solvedLevelIds = JSON.parse(savedLevelsStr);\n const updatedLevels = restoredAdventure.levels.map(level => solvedLevelIds.includes(level.id) ? level.markAsSolved() : level);\n return Adventure.constructFromLevels(config.id, config.name, updatedLevels);\n }\n\n return restoredAdventure;\n })\n );\n\n setAdventures(restoredAdventures);\n }\n\n loadProgress();\n }, [progressPersister, adventureConfigs]);\n\n function activeAdventure() {\n if (playerLocation.activeAdventureId === null) {\n return null;\n }\n return adventures.find(adventure => adventure.id === playerLocation.activeAdventureId) || null;\n }\n\n function activeLevel() {\n const adventure = activeAdventure();\n if (!adventure || playerLocation.activeLevelIndex === null) {\n return null;\n }\n return adventure.levels[playerLocation.activeLevelIndex] || null;\n }\n\n function isOnAdventureSelection() {\n return playerLocation.isOnAdventureSelection();\n }\n\n function isOnLevelSelection() {\n return playerLocation.isOnLevelSelection();\n }\n\n function isOnActiveLevel() {\n return playerLocation.isOnActiveLevel();\n }\n\n function activateAdventure(adventureId) {\n const adventure = adventures.find(adventure => adventure.id === adventureId);\n if (!adventure) {\n throw new Error(`Adventure with id \"${adventureId}\" not found`);\n }\n setPlayerLocation(playerLocation.moveToAdventure(adventureId));\n }\n\n function moveToAdventureSelection() {\n setPlayerLocation(playerLocation.moveToAdventureSelection());\n }\n\n function moveToLevelSelectScreen() {\n setPlayerLocation(playerLocation.moveToLevelSelectScreen());\n }\n\n function moveToLevelScreen(levelIdx) {\n const adventure = activeAdventure();\n if (!adventure) {\n throw new Error('Cannot move to level when no adventure is selected');\n }\n if (levelIdx < 0 || levelIdx >= adventure.levels.length) {\n throw new Error(`Level index ${levelIdx} is out of bounds for adventure \"${adventure.id}\"`);\n }\n setPlayerLocation(playerLocation.moveToLevelScreen(levelIdx));\n }\n\n async function handleSubmitAnswer(answer) {\n const level = activeLevel();\n const currentAdventure = activeAdventure();\n\n if (!level || !currentAdventure) {\n return false;\n }\n\n const newAdventure = currentAdventure.submitAnswer(level.id, answer);\n\n if (newAdventure) {\n const updatedAdventures = adventures.map(adventure => adventure.id === currentAdventure.id ? newAdventure : adventure);\n setAdventures(updatedAdventures);\n\n const storageKey = `questify-${currentAdventure.id}-solved-levels`;\n const solvedLevelIds = newAdventure.levels.filter(level => level.isSolved).map(level => level.id);\n await progressPersister.store(storageKey, JSON.stringify(solvedLevelIds));\n return true;\n }\n\n return false;\n }\n\n const questifyCtxValue = {\n adventures: adventures,\n playerLocation: playerLocation,\n activeAdventure: activeAdventure,\n activeLevel: activeLevel,\n isOnAdventureSelection: isOnAdventureSelection,\n isOnLevelSelection: isOnLevelSelection,\n isOnActiveLevel: isOnActiveLevel,\n activateAdventure: activateAdventure,\n moveToAdventureSelection: moveToAdventureSelection,\n moveToLevelSelectScreen: moveToLevelSelectScreen,\n moveToLevelScreen: moveToLevelScreen,\n submitAnswer: handleSubmitAnswer,\n };\n\n return (\n <QuestifyContext.Provider value={questifyCtxValue}>\n {children}\n </QuestifyContext.Provider>\n );\n}\n","type LevelComponent = React.ComponentType<any>;\n\nclass LevelRegistry {\n private registry: Map<string, LevelComponent> = new Map();\n\n register(type: string, component: LevelComponent): void {\n this.registry.set(type, component);\n }\n\n get(type: string): LevelComponent | undefined {\n return this.registry.get(type);\n }\n\n has(type: string): boolean {\n return this.registry.has(type);\n }\n}\n\nexport const levelRegistry = new LevelRegistry();\nexport { LevelRegistry, LevelComponent };\n","import { useContext } from \"react\";\nimport { QuestifyContext } from \"@store/QuestifyContext\";\nimport { levelRegistry } from \"@registry/LevelRegistry\";\n\nexport function useQuestify() {\n const context = useContext(QuestifyContext);\n\n if (!context.adventures || context.adventures.length === 0) {\n throw new Error(\"No adventures found. Make sure you pass adventureConfigs to the QuestifyProvider\");\n }\n\n function renderScreen(AdventureSelectComponent, LevelSelectComponent, LevelScreenComponent) {\n if (context.isOnAdventureSelection()) {\n const adventures = context.adventures.map((adventure) => ({ ...adventure, onSelectAdventure: () => context.activateAdventure(adventure.id) }));\n return <AdventureSelectComponent adventures={adventures} />;\n }\n\n if (context.isOnLevelSelection()) {\n const activeAdventure = context.activeAdventure();\n if (!activeAdventure) {\n throw new Error(\"Cannot render level selection without an active adventure\");\n }\n\n const levels = activeAdventure.levels.map((level) => ({\n id: level.id,\n title: level.title,\n type: level.type,\n isSolved: level.isSolved,\n solution: level.solution,\n onSelectLevel: () => context.moveToLevelScreen(level.id)\n }));\n\n return <LevelSelectComponent\n adventure={activeAdventure}\n levels={levels}\n onBack={context.moveToAdventureSelection}\n />;\n }\n\n if (context.isOnActiveLevel()) {\n const level = context.activeLevel();\n if (!level) {\n throw new Error(\"Cannot render level screen without an active level\");\n }\n\n const LevelComponent = levelRegistry.get(level.type);\n\n if (!LevelComponent) {\n throw new Error(`No level component registered for type: ${level.type}`);\n }\n\n return <LevelScreenComponent\n title={level.title}\n onBack={context.moveToLevelSelectScreen}\n isSolved={level.isSolved}\n LevelComponent={() => <LevelComponent {...level.blueprint} title={level.title}/>}\n />;\n }\n\n throw new Error(\"Invalid player location state\");\n }\n\n function submitAnswer(answer) {\n return context.submitAnswer(answer);\n }\n\n return {\n renderScreen: renderScreen,\n submitAnswer: submitAnswer,\n };\n}\n","import { useQuestify } from '@hooks/useQuestify';\nimport QuestifyProvider from '@store/QuestifyContext';\nimport { levelRegistry } from '@registry/LevelRegistry';\n\nexport const registerLevelComponent = (type: string, component: React.ComponentType<any>) => {\n levelRegistry.register(type, component);\n};\n\nexport { QuestifyProvider, useQuestify };\n"],"names":["storage","memoryPersister","key","value","Level","id","type","title","solution","blueprint","isSolved","cloned","Adventure","config","levelConfig","index","name","levels","icon","subtitle","description","adventure","levelId","answer","level","updatedLevels","solvedCount","totalLevels","status","updates","PlayerLocation","adventureId","levelIndex","newLocation","levelIdx","QuestifyContext","createContext","QuestifyProvider","adventureConfigs","persister","children","progressPersister","adventures","setAdventures","useState","playerLocation","setPlayerLocation","useEffect","loadProgress","restoredAdventures","storageKey","savedLevelsStr","restoredAdventure","solvedLevelIds","activeAdventure","activeLevel","isOnAdventureSelection","isOnLevelSelection","isOnActiveLevel","activateAdventure","moveToAdventureSelection","moveToLevelSelectScreen","moveToLevelScreen","handleSubmitAnswer","currentAdventure","newAdventure","updatedAdventures","questifyCtxValue","LevelRegistry","component","levelRegistry","useQuestify","context","useContext","renderScreen","AdventureSelectComponent","LevelSelectComponent","LevelScreenComponent","jsx","LevelComponent","submitAnswer","registerLevelComponent"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@popp0102/questify",
3
3
  "private": false,
4
- "version": "0.10.0",
4
+ "version": "0.11.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite --config config/vite.config.ts public",