@emuanalytics/flow-rdf-core 4.0.3 → 4.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +1 -64
  2. package/dist/index.d.mts +36 -31
  3. package/dist/index.d.ts +36 -31
  4. package/dist/index.mjs +20 -3249
  5. package/dist/lib/context/context-registry.mjs +63 -0
  6. package/dist/lib/context/debugger.mjs +240 -0
  7. package/dist/lib/context/flow-context.mjs +61 -0
  8. package/dist/lib/context/global-state.mjs +70 -0
  9. package/dist/lib/context/map-registry.mjs +59 -0
  10. package/dist/lib/context/query-registry.mjs +53 -0
  11. package/dist/lib/errors/flow-error.mjs +10 -0
  12. package/dist/lib/errors/flow-expression-error.mjs +14 -0
  13. package/dist/lib/errors/flow-map-error.mjs +9 -0
  14. package/dist/lib/expressions/expression-parser.mjs +198 -0
  15. package/dist/lib/expressions/functions/from-palette.mjs +75 -0
  16. package/dist/lib/expressions/functions/regex.mjs +25 -0
  17. package/dist/lib/expressions/functions/state.mjs +25 -0
  18. package/dist/lib/expressions/parser-helpers.mjs +37 -0
  19. package/dist/lib/expressions/reactive-expression.mjs +253 -0
  20. package/dist/lib/map/flow-core-map.mjs +749 -0
  21. package/dist/lib/map/plugins/annotations/annotation-layers.mjs +163 -0
  22. package/dist/lib/map/plugins/annotations/annotation.events.mjs +27 -0
  23. package/dist/lib/map/plugins/annotations/annotation.plugin.mjs +498 -0
  24. package/dist/lib/map/plugins/annotations/maplibre-gl-draw-circle/lib/modes/DirectModeOverride.mjs +67 -0
  25. package/dist/lib/map/plugins/annotations/maplibre-gl-draw-circle/lib/modes/DragCircleMode.mjs +65 -0
  26. package/dist/lib/map/plugins/annotations/maplibre-gl-draw-circle/lib/utils/create_supplementary_points_circle.mjs +15 -0
  27. package/dist/lib/map/plugins/annotations/maplibre-gl-draw-circle/lib/utils/drag_pan.mjs +20 -0
  28. package/dist/lib/map/plugins/data-join.plugin.mjs +173 -0
  29. package/dist/lib/map/plugins/export/export.plugin.mjs +21 -0
  30. package/dist/lib/map/plugins/export/map-exporter.mjs +177 -0
  31. package/dist/lib/map/plugins/hover-effect.plugin.mjs +58 -0
  32. package/dist/lib/map/plugins/index.d.mts +37 -72
  33. package/dist/lib/map/plugins/index.d.ts +37 -72
  34. package/dist/lib/map/plugins/index.mjs +11 -1811
  35. package/dist/lib/map/plugins/keyboard-shortcut-manager.mjs +120 -0
  36. package/dist/lib/map/plugins/map-plugin-base.mjs +25 -0
  37. package/dist/lib/map/plugins/plugin-manager.mjs +135 -0
  38. package/dist/lib/map/plugins/popup.plugin.mjs +55 -0
  39. package/dist/lib/map/plugins/selection/selection.events.mjs +21 -0
  40. package/dist/lib/map/plugins/selection/selection.plugin.mjs +136 -0
  41. package/dist/lib/map/plugins/selection/source-selection.mjs +156 -0
  42. package/dist/lib/map/plugins/url-sync.plugin.mjs +55 -0
  43. package/dist/lib/map/support/image-registry.mjs +82 -0
  44. package/dist/lib/map/support/map-events.mjs +71 -0
  45. package/dist/lib/map/support/map-feature-stream.mjs +158 -0
  46. package/dist/lib/map/support/map-popup.mjs +159 -0
  47. package/dist/lib/map/types.mjs +7 -0
  48. package/dist/lib/map-style/map-data-source.mjs +192 -0
  49. package/dist/lib/map-style/map-layer-style-builder-generated.mjs +1307 -0
  50. package/dist/lib/map-style/map-layer-style-builder.mjs +86 -0
  51. package/dist/lib/map-style/map-layer.mjs +223 -0
  52. package/dist/lib/map-style/map-style.mjs +178 -0
  53. package/dist/lib/queries/async-committer.mjs +30 -0
  54. package/dist/lib/queries/query.mjs +172 -0
  55. package/dist/lib/state-store/decorators.mjs +83 -0
  56. package/dist/lib/state-store/state-store.mjs +534 -0
  57. package/dist/lib/state-store/utils.mjs +7 -0
  58. package/dist/lib/utils/announce.mjs +12 -0
  59. package/dist/lib/utils/assert.mjs +12 -0
  60. package/dist/{shared/flow-rdf-core.187cb345.mjs → lib/utils/debounce.mjs} +3 -39
  61. package/dist/lib/utils/decorators.mjs +59 -0
  62. package/dist/lib/utils/deferred.mjs +11 -0
  63. package/dist/lib/utils/ensure-array.mjs +16 -0
  64. package/dist/{shared/flow-rdf-core.1f0901c5.mjs → lib/utils/feature-type-checks.mjs} +2 -2
  65. package/dist/lib/utils/functional.mjs +22 -0
  66. package/dist/lib/utils/global.mjs +18 -0
  67. package/dist/lib/utils/index.mjs +8 -5
  68. package/dist/lib/utils/random-id.mjs +9 -0
  69. package/dist/lib/utils/string-utils.mjs +3 -0
  70. package/dist/lib/utils/throttle.mjs +20 -0
  71. package/dist/{shared/flow-rdf-core.25e5f6d7.mjs → lib/utils/type-checks.mjs} +1 -26
  72. package/dist/lib/utils/watchable-promise.mjs +55 -0
  73. package/dist/package.json.mjs +3 -0
  74. package/dist/shared/{flow-rdf-core.4dde996e.d.cts → flow-rdf-core.8b5acf14.d.mts} +1315 -172
  75. package/dist/shared/{flow-rdf-core.4dde996e.d.ts → flow-rdf-core.8b5acf14.d.ts} +1315 -172
  76. package/package.json +4 -8
  77. package/dist/index.cjs +0 -3316
  78. package/dist/index.d.cts +0 -90
  79. package/dist/lib/map/plugins/index.cjs +0 -1851
  80. package/dist/lib/map/plugins/index.d.cts +0 -345
  81. package/dist/lib/utils/index.cjs +0 -48
  82. package/dist/lib/utils/index.d.cts +0 -160
  83. package/dist/shared/flow-rdf-core.06e85a6c.cjs +0 -1394
  84. package/dist/shared/flow-rdf-core.4dde996e.d.mts +0 -1916
  85. package/dist/shared/flow-rdf-core.55c169ca.cjs +0 -150
  86. package/dist/shared/flow-rdf-core.63162669.d.cts +0 -10
  87. package/dist/shared/flow-rdf-core.65045caf.mjs +0 -1360
  88. package/dist/shared/flow-rdf-core.a82b9be4.cjs +0 -34
  89. package/dist/shared/flow-rdf-core.f50908f0.cjs +0 -102
@@ -0,0 +1,83 @@
1
+ import * as mobx from 'mobx';
2
+ import { toJS } from 'mobx';
3
+ import { createDecoratorAnnotation, createDecoratorAnnotationWithArg } from '../utils/decorators.mjs';
4
+
5
+ const SYNC_ANNOTATION_TYPE = "state-sync-annotation";
6
+ const REACTIVE_ANNOTATION_TYPE = "state-reactive-annotation";
7
+ const serializeRaw = {
8
+ annotationType: SYNC_ANNOTATION_TYPE,
9
+ type: "raw",
10
+ serialize(val) {
11
+ return toJS(val);
12
+ },
13
+ deserialize(val) {
14
+ return val;
15
+ }
16
+ };
17
+ const serializeString = {
18
+ annotationType: SYNC_ANNOTATION_TYPE,
19
+ type: "string",
20
+ serialize(val) {
21
+ return val.toString();
22
+ },
23
+ deserialize(val) {
24
+ return val;
25
+ }
26
+ };
27
+ const serializeNumber = {
28
+ annotationType: SYNC_ANNOTATION_TYPE,
29
+ type: "number",
30
+ serialize(val) {
31
+ return val.toString();
32
+ },
33
+ deserialize(val) {
34
+ return +val;
35
+ }
36
+ };
37
+ const serializeJson = {
38
+ annotationType: SYNC_ANNOTATION_TYPE,
39
+ type: "json",
40
+ serialize(val) {
41
+ return JSON.stringify(val);
42
+ },
43
+ deserialize(val) {
44
+ return JSON.parse(val);
45
+ }
46
+ };
47
+ const serializeState = {
48
+ annotationType: SYNC_ANNOTATION_TYPE,
49
+ type: "state",
50
+ serialize(val, group) {
51
+ return val.serialize("raw", group);
52
+ },
53
+ deserialize(val, target) {
54
+ target.deserialize("raw", val);
55
+ return target;
56
+ }
57
+ };
58
+ const serialize = Object.assign(createDecoratorAnnotation(serializeRaw), {
59
+ raw: createDecoratorAnnotation(serializeRaw),
60
+ string: createDecoratorAnnotation(serializeString),
61
+ number: createDecoratorAnnotation(serializeNumber),
62
+ json: createDecoratorAnnotation(serializeJson),
63
+ state: createDecoratorAnnotation(serializeState),
64
+ for: createDecoratorAnnotationWithArg(serializeRaw)
65
+ });
66
+ function createReactiveAnnotation(mobxAnnotation) {
67
+ return createDecoratorAnnotation({
68
+ annotationType: REACTIVE_ANNOTATION_TYPE,
69
+ mobxAnnotation
70
+ });
71
+ }
72
+ const observable = Object.assign(createReactiveAnnotation(mobx.observable), {
73
+ deep: createReactiveAnnotation(mobx.observable.deep),
74
+ ref: createReactiveAnnotation(mobx.observable.ref),
75
+ struct: createReactiveAnnotation(mobx.observable.struct),
76
+ shallow: createReactiveAnnotation(mobx.observable.shallow)
77
+ });
78
+ const computed = Object.assign(createReactiveAnnotation(mobx.computed), {
79
+ struct: createReactiveAnnotation(mobx.computed.struct)
80
+ });
81
+ const action = createReactiveAnnotation(mobx.action);
82
+
83
+ export { REACTIVE_ANNOTATION_TYPE, SYNC_ANNOTATION_TYPE, action, computed, observable, serialize };
@@ -0,0 +1,534 @@
1
+ import Debug from 'debug';
2
+ import lzString from 'lz-string';
3
+ import * as mobx from 'mobx';
4
+ import { toStream } from 'mobx-utils';
5
+ import { collectStoredAnnotations } from '../utils/decorators.mjs';
6
+ import { randomId } from '../utils/random-id.mjs';
7
+ import { REACTIVE_ANNOTATION_TYPE, SYNC_ANNOTATION_TYPE } from './decorators.mjs';
8
+ import { ensureArray } from '../utils/ensure-array.mjs';
9
+ import { isDefined } from '../utils/type-checks.mjs';
10
+ import { FlowCoreError } from '../errors/flow-error.mjs';
11
+
12
+ var __defProp = Object.defineProperty;
13
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
+ var __publicField = (obj, key, value) => {
15
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
16
+ return value;
17
+ };
18
+ const debug = Debug("flow:state-store");
19
+ const StateStoreMarker = Symbol("FlowCoreStateStoreMarker");
20
+ const StateStorCache = Symbol("FlowCoreStateStorCache");
21
+ class StateStore {
22
+ /**
23
+ * Constructs a new `StateStore`.
24
+ *
25
+ * In derived classes, call `super()` in the constructor followed by `this.initialize(...)`.
26
+ *
27
+ * @example
28
+ * ```js
29
+ * constructor() {
30
+ * super();
31
+ *
32
+ * // Required!
33
+ * this.initialize();
34
+ * }
35
+ * ```
36
+ * @param id - Optional unique identifier for debugging purposes. If not supplied, a random identifier will be generated.
37
+ */
38
+ constructor(id) {
39
+ __publicField(this, "serializationAnnotations", {});
40
+ __publicField(this, "id");
41
+ this.id = id || randomId("state");
42
+ }
43
+ get formattedName() {
44
+ return `StateStore<${this.id}>`;
45
+ }
46
+ /**
47
+ * Returns `true` if the store has been initialized.
48
+ *
49
+ * Derived state stores **must** be initialized before use by calling {@link StateStore.initialize}
50
+ * in the constructor.
51
+ *
52
+ * @returns `true` if the store has been initialized.
53
+ */
54
+ get initialized() {
55
+ return mobx.isObservable(this);
56
+ }
57
+ /**
58
+ * Returns the value at the specified path in the state store.
59
+ *
60
+ * @param path - State store path to retrieve.
61
+ * @typeParam TPath - Type defining possible state store paths.
62
+ * @returns The value of the state store property at the specified path.
63
+ */
64
+ get(path) {
65
+ this.checkInitialized();
66
+ const pathStr = path;
67
+ let value = this;
68
+ const p = pathStr.split(".");
69
+ let k;
70
+ while (k = p.shift()) {
71
+ value = value[k];
72
+ }
73
+ return value;
74
+ }
75
+ /**
76
+ * Sets the value at the specified path in the state store.
77
+ *
78
+ * @param path - State store path to set
79
+ * @param val - Value to set at the specified path
80
+ */
81
+ set(path, val) {
82
+ this.checkInitialized();
83
+ const pathArray = path.split(".");
84
+ let k;
85
+ let value = this;
86
+ while (pathArray.length > 1) {
87
+ k = pathArray.shift();
88
+ value = value[k];
89
+ }
90
+ k = pathArray.shift();
91
+ value[k] = val;
92
+ }
93
+ /**
94
+ * Use this method to batch multiple state updates into a single transaction.
95
+ * This can improve performance by reducing the number of reactive updates triggered by
96
+ * state updates.
97
+ *
98
+ * @example
99
+ * Set multiple state properties within a transaction:
100
+ * ```js
101
+ * store.transaction(() => {
102
+ * store.set('a', 1);
103
+ * store.set('b', 2);
104
+ * store.set('c', 3);
105
+ * });
106
+ * ```
107
+ *
108
+ * @param fn - The function to run within the transaction.
109
+ */
110
+ transaction(fn) {
111
+ this.checkInitialized();
112
+ mobx.runInAction(() => fn(this));
113
+ }
114
+ /**
115
+ * Toggles the value at the specified path in the state store.
116
+ * This method assumes that the value at the specified path is a boolean.
117
+ *
118
+ * @param path - The path to the boolean value to toggle.
119
+ * @returns The new value at the specified path.
120
+ */
121
+ toggle(path) {
122
+ this.checkInitialized();
123
+ const val = !this.get(path);
124
+ this.set(path, val);
125
+ return val;
126
+ }
127
+ /**
128
+ * Increments the value at the specified path in the state store.
129
+ * This method assumes that the value at the specified path is a number.
130
+ *
131
+ * @param path - The path to the number value to increment.
132
+ * @returns The new value at the specified path.
133
+ */
134
+ increment(path) {
135
+ this.checkInitialized();
136
+ const val = +this.get(path) + 1;
137
+ this.set(path, val);
138
+ return val;
139
+ }
140
+ /**
141
+ * Decrements the value at the specified path in the state store.
142
+ * This method assumes that the value at the specified path is a number.
143
+ *
144
+ * @param path The path to the number value to decrement.
145
+ * @returns The new value at the specified path.
146
+ */
147
+ decrement(path) {
148
+ this.checkInitialized();
149
+ const val = +this.get(path) - 1;
150
+ this.set(path, val);
151
+ return val;
152
+ }
153
+ /**
154
+ * Bind an HTML control element to a state store property. Two-way binding
155
+ * is established between the control and the state store property. When the
156
+ * control value changes, the state store property is updated. When the state
157
+ * store property changes, the control value is updated.
158
+ *
159
+ * Supports:
160
+ * - Native elements that emit an `input` event and have a `value` property.
161
+ * - Flo.w RDF UI custom elements that emit `flow-ui-input` or `flow-ui-change` events and have
162
+ * a value property.
163
+ *
164
+ * :::warning
165
+ * Bindings should be disposed of when no longer needed by calling `unsubscribe()` on the returned subscription.
166
+ * :::
167
+ *
168
+ * :::warning
169
+ * This method is provided to support reactive binding for vanilla JS and TS applications. When using
170
+ * other supported frameworks (e.g. Angular) use the preferred binding method for that framework.
171
+ * :::
172
+ *
173
+ * @example
174
+ * ```js
175
+ * const subscription = store.bindControl(document.getElementById('my-input'), 'myStateProperty');
176
+ * ...
177
+ * subscription.unsubscribe();
178
+ * ```
179
+ *
180
+ * @param el - The HTML element to bind
181
+ * @param statePath - The path to the state store property to bind
182
+ * @param options - Binding options
183
+ * @param options.toState - A function to convert the control value to the state store value
184
+ * @param options.fromState - A function to convert the state store value to the control value
185
+ * @param options.updateOn - The event type that will trigger an update of the state store property. Default is `input`.
186
+ * @returns A subscription that can be used to `unsubscribe()` the binding.
187
+ */
188
+ bindControl(el, statePath, options) {
189
+ const toState = options?.toState ?? ((v) => v);
190
+ const fromState = options?.fromState ?? ((v) => v);
191
+ const updateOn = options?.updateOn ?? "input";
192
+ el.addEventListener("input", () => {
193
+ if (updateOn === "input") {
194
+ this.set(statePath, toState(el.value));
195
+ }
196
+ });
197
+ el.addEventListener("flow-ui-input", () => {
198
+ if (updateOn === "input") {
199
+ this.set(statePath, toState(el.value));
200
+ }
201
+ });
202
+ el.addEventListener("flow-ui-change", () => {
203
+ if (updateOn === "change") {
204
+ this.set(statePath, toState(el.value));
205
+ }
206
+ });
207
+ return this.toStream(statePath, true).subscribe((value) => {
208
+ if (value !== el.value) {
209
+ el.value = fromState(value);
210
+ }
211
+ });
212
+ }
213
+ /**
214
+ * Bind an HTML element property to a state store property. One-way binding
215
+ * is established between the element property and the state store property.
216
+ * When the state store property changes, the element property is updated.
217
+ *
218
+ * :::warning
219
+ * Bindings should be disposed of when no longer needed by calling `unsubscribe()` on the returned subscription.
220
+ * :::
221
+ *
222
+ * :::warning
223
+ * This method is provided to support reactive binding for vanilla JS and TS applications. When using
224
+ * other supported frameworks (e.g. Angular) use the preferred binding method for that framework.
225
+ * :::
226
+ *
227
+ * @example
228
+ * ```js
229
+ * const el = document.getElementById('my-span');
230
+ * const subscription = store.bindElementProp(el, 'textContent', 'myStateProperty');
231
+ * ...
232
+ * subscription.unsubscribe();
233
+ * ```
234
+ *
235
+ * @param el - The HTML element to bind
236
+ * @param prop - The property of the element to bind
237
+ * @param path - The path to the state store property to bind
238
+ * @param options - Binding options
239
+ * @param options.fromState - A function to convert the state store value to the element property value
240
+ * @returns A subscription that can be used to `unsubscribe()` the binding.
241
+ */
242
+ bindElementProp(el, prop, path, options) {
243
+ const fromState = options?.fromState ?? ((v) => v);
244
+ return this.toStream(path, true).subscribe((value) => {
245
+ if (value !== el[prop]) {
246
+ el[prop] = fromState(value);
247
+ }
248
+ });
249
+ }
250
+ /**
251
+ * Bind an HTML element attribute to a state store property. One-way binding
252
+ * is established between the element attribute and the state store property.
253
+ * When the state store property changes, the element attribute is updated
254
+ * (using `el.setAttribute(...)`).
255
+ *
256
+ * :::warning
257
+ * Bindings should be disposed of when no longer needed by calling `unsubscribe()` on the returned subscription.
258
+ * :::
259
+ *
260
+ * :::warning
261
+ * This method is provided to support reactive binding for vanilla JS and TS applications. When using
262
+ * other supported frameworks (e.g. Angular) use the preferred binding method for that framework.
263
+ * :::
264
+ *
265
+ * @param el - The HTML element to bind
266
+ * @param attr - The attribute of the element to bind
267
+ * @param path - The path to the state store property to bind
268
+ * @returns
269
+ */
270
+ bindElementAttr(el, attr, path, options) {
271
+ const fromState = options?.fromState ?? ((v) => v.toString ? v.toString() : v);
272
+ return this.toStream(path, true).subscribe((value) => {
273
+ el.setAttribute(attr, fromState(value));
274
+ });
275
+ }
276
+ /**
277
+ * Create an observable stream that emits the value of the specified state store property
278
+ * when it changes. The stream can be subscribed to using its `subscribe()` method.
279
+ *
280
+ * :::warning
281
+ * Subscriptions should be disposed of when no longer required by calling their `unsubscribe()` method.
282
+ * :::
283
+ *
284
+ * :::danger
285
+ * It is an anti-pattern to modify state store properties directly from within a stream subscription.
286
+ * Use a `computed` property instead. Limit use of `toStream` to running imperative side-effects
287
+ * in response to a reactive update of a state property.
288
+ * :::
289
+ *
290
+ * @example
291
+ * ```js
292
+ * const subscription = store.toStream('myStateProperty').subscribe((value) => {
293
+ * console.log('myStateProperty changed:', value);
294
+ * });
295
+ * ...
296
+ * subscription.unsubscribe();
297
+ * ```
298
+ *
299
+ * @param path - The path to the state store property to bind
300
+ * @param fireImmediately - If `true`, the stream will emit the current value immediately
301
+ * If `false`, the stream will only emit values when the state store property changes.
302
+ *
303
+ * @returns An observable stream that emits the value of the specified state property.
304
+ */
305
+ toStream(path, fireImmediately = true) {
306
+ this.checkInitialized();
307
+ return toStream(() => this.get(path), fireImmediately);
308
+ }
309
+ /**
310
+ * Creates a reactive context that will automatically re-run the specified function
311
+ * whenever referenced reactive state changes. The supplied function is run immediately
312
+ * and referenced state properties are tracked. The function will be re-run when tracked
313
+ * state properties change.
314
+ *
315
+ * Note that referenced state properties are determined dynamically
316
+ * by access. If a code branch is not taken, the referenced state properties in that branch
317
+ * will not be tracked. If, on a subsequent run, the code branch is taken, the tracking
318
+ * will be updated to include the newly accessed state properties.
319
+ *
320
+ * This method is similar to `toStream` but allows access to the complete state object rather
321
+ * than a single property.
322
+ *
323
+ * :::warning
324
+ * Autoruns should be disposed of when no longer needed by invoking the `disposer` function
325
+ * returned when creating an autorun.
326
+ * :::
327
+ *
328
+ * :::danger
329
+ * It is an anti-pattern to modify state store properties directly from within an autorun.
330
+ * Use a `computed` property instead. Limit use of autoruns to running imperative side-effects
331
+ * in response to a reactive update.
332
+ * :::
333
+ *
334
+ * @example
335
+ * ```js
336
+ * const disposer = store.autorun((state) => {
337
+ * // Set map properties as a side effect whenever any of `state.zoom`, `state.bearing`, or `state.pitch` change
338
+ * map.setCenter({zoom: state.zoom, bearing: state.bearing, pitch: state.pitch});
339
+ * });
340
+ * ...
341
+ * disposer();
342
+ * ```
343
+ *
344
+ * @param autorunFn - The function to run within a reactive context
345
+ * @param name - Optional name for debugging purposes
346
+ * @returns - A disposer function. Invoke this function to dispose of the autorun.
347
+ */
348
+ autorun(autorunFn, name) {
349
+ this.checkInitialized();
350
+ return mobx.autorun(() => autorunFn(this), { name });
351
+ }
352
+ /**
353
+ * This method **must**
354
+ * be called in the constructor of derived classes to initialize the state store.
355
+ * An exception will be thrown if this method is not called before using the state store.
356
+ *
357
+ * If using decorators to configure reactive properties, this method should be called without arguments.
358
+ * If not using decorators, supply reactive annotations to configure reactive properties.
359
+ *
360
+ * See {@link StoreAnnotations} for a list of available annotations.
361
+ *
362
+ * :::info
363
+ * If this method is called without using decorators and without supplying reactive annotations,
364
+ * the state store will be configured automatically:
365
+ *
366
+ * - All properties will be made observable.
367
+ * - All getters will converted to computed properties.
368
+ *
369
+ * This is only recommended for simple state stores in demos.
370
+ * :::
371
+ *
372
+ * @param annotations Optional annotations for configuring reactive properties.
373
+ */
374
+ initialize(annotations = {}) {
375
+ if (this.initialized) {
376
+ throw new FlowCoreError(`${this.formattedName}: store has already been initialized`);
377
+ }
378
+ const annotationsByType = {
379
+ [REACTIVE_ANNOTATION_TYPE]: collectStoredAnnotations(this, REACTIVE_ANNOTATION_TYPE),
380
+ [SYNC_ANNOTATION_TYPE]: collectStoredAnnotations(this, SYNC_ANNOTATION_TYPE)
381
+ };
382
+ Object.keys(annotations).forEach((prop) => {
383
+ const propAnnotations = ensureArray(annotations[prop]);
384
+ propAnnotations.forEach((annotation) => {
385
+ const type = annotation.annotationType;
386
+ annotationsByType[type] ?? (annotationsByType[type] = {});
387
+ annotationsByType[type][prop] = annotation;
388
+ });
389
+ });
390
+ this.serializationAnnotations = annotationsByType[SYNC_ANNOTATION_TYPE];
391
+ if (Object.keys(annotationsByType[REACTIVE_ANNOTATION_TYPE]).length) {
392
+ const mobxAnnotations = Object.keys(annotationsByType[REACTIVE_ANNOTATION_TYPE]).reduce((accum, prop) => {
393
+ accum[prop] = annotationsByType[REACTIVE_ANNOTATION_TYPE][prop].mobxAnnotation;
394
+ return accum;
395
+ }, {});
396
+ const reactivity = Object.keys(mobxAnnotations).reduce((accum, prop) => {
397
+ accum[prop] = mobxAnnotations[prop].annotationType_;
398
+ return accum;
399
+ }, {});
400
+ const serialization = Object.keys(annotationsByType[SYNC_ANNOTATION_TYPE]).reduce((accum, prop) => {
401
+ accum[prop] = annotationsByType[SYNC_ANNOTATION_TYPE][prop].syncType;
402
+ return accum;
403
+ }, {});
404
+ this.makeObservable(mobxAnnotations);
405
+ debug(`${this.formattedName}: initialized with annotations`, {
406
+ reactivity,
407
+ serialization
408
+ });
409
+ } else {
410
+ this.makeAutoObservable();
411
+ debug(`${this.formattedName}: initialized with auto-annotations`);
412
+ }
413
+ }
414
+ /**
415
+ * Serialize the state store properties that have been annotated as serializable to an object or string.
416
+ *
417
+ * The following formats are supported:
418
+ * - `raw` (default): Plain object with property values serialized as JSON strings.
419
+ * - `json`: The `raw` object format serialized as a single JSON string.
420
+ * - `lz`: The `raw` object format serialized as a single JSON string and then compressed using [lzString.compressToEncodedURIComponent](https://github.com/pieroxy/lz-string).
421
+ *
422
+ * The `lz` format is designed for serializing state store properties to a URL query string.
423
+ */
424
+ serialize(format = "raw", group) {
425
+ const annotations = this.serializationAnnotations;
426
+ const serializedProps = Object.keys(annotations).reduce((accum, prop) => {
427
+ const annotationGroup = ensureArray(annotations[prop].arg);
428
+ const annotationType = annotations[prop].type;
429
+ if (group && annotationType !== "state" && !annotationGroup.includes(group)) {
430
+ return accum;
431
+ }
432
+ const val = this[prop];
433
+ if (isDefined(val)) {
434
+ const serializedValue = annotations[prop].serialize(val, group);
435
+ accum[prop] = serializedValue;
436
+ }
437
+ return accum;
438
+ }, {});
439
+ switch (format) {
440
+ case "json":
441
+ return JSON.stringify(serializedProps);
442
+ case "lz":
443
+ return lzString.compressToEncodedURIComponent(JSON.stringify(serializedProps));
444
+ default:
445
+ return serializedProps;
446
+ }
447
+ }
448
+ /**
449
+ * Set state store properties by deserializing from serialized output of the {@link serialize} method.
450
+ * Only properties that have been annotated as serializable and are present in the serialized value will be deserialized.
451
+ * Other properties will be left unchanged.
452
+ */
453
+ deserialize(value, format = "raw") {
454
+ let deserializedValue;
455
+ switch (format) {
456
+ case "json":
457
+ deserializedValue = JSON.parse(value);
458
+ break;
459
+ case "lz":
460
+ deserializedValue = JSON.parse(lzString.decompressFromEncodedURIComponent(value));
461
+ break;
462
+ default:
463
+ deserializedValue = value;
464
+ break;
465
+ }
466
+ this.transaction(() => {
467
+ const annotations = this.serializationAnnotations;
468
+ Object.keys(deserializedValue).forEach((prop) => {
469
+ const annotation = annotations[prop];
470
+ if (annotation) {
471
+ this[prop] = annotation.deserialize(deserializedValue[prop], this[prop]);
472
+ }
473
+ });
474
+ });
475
+ }
476
+ makeObservable(overrides) {
477
+ if (this.initialized) {
478
+ throw new FlowCoreError(`${this.formattedName}: store is already observable`);
479
+ }
480
+ overrides = {
481
+ ...overrides,
482
+ set: mobx.action,
483
+ toggle: mobx.action,
484
+ increment: mobx.action,
485
+ decrement: mobx.action
486
+ };
487
+ mobx.makeObservable(this, overrides, { name: this.formattedName });
488
+ }
489
+ makeAutoObservable(overrides = {}) {
490
+ if (this.initialized) {
491
+ throw new FlowCoreError(`${this.formattedName}: store is already observable`);
492
+ }
493
+ const target = this;
494
+ overrides = {
495
+ ...overrides,
496
+ _initialized: false,
497
+ $mobx: false,
498
+ constructor: false
499
+ };
500
+ let annotations = target[StateStorCache];
501
+ if (!annotations) {
502
+ annotations = {};
503
+ let current = target;
504
+ while (current && !Object.prototype.hasOwnProperty.call(current, StateStoreMarker)) {
505
+ Reflect.ownKeys(current).forEach((k) => {
506
+ annotations[k] = !overrides ? true : k in overrides ? overrides[k] : true;
507
+ });
508
+ current = Object.getPrototypeOf(current);
509
+ }
510
+ const proto = Object.getPrototypeOf(target);
511
+ if (proto) {
512
+ Object.defineProperty(proto, StateStorCache, { value: annotations });
513
+ }
514
+ }
515
+ annotations = {
516
+ ...annotations,
517
+ set: mobx.action,
518
+ toggle: mobx.action,
519
+ increment: mobx.action,
520
+ decrement: mobx.action
521
+ };
522
+ return mobx.makeObservable(target, annotations, { name: this.formattedName });
523
+ }
524
+ checkInitialized() {
525
+ if (!this.initialized) {
526
+ throw new FlowCoreError(
527
+ `${this.formattedName} not initialized. Please use one of the recommended methods to make this state store observable.`
528
+ );
529
+ }
530
+ }
531
+ }
532
+ StateStore.prototype[StateStoreMarker] = true;
533
+
534
+ export { StateStore };
@@ -0,0 +1,7 @@
1
+ import { trace } from 'mobx';
2
+
3
+ function traceReaction() {
4
+ trace();
5
+ }
6
+
7
+ export { traceReaction };
@@ -0,0 +1,12 @@
1
+ import { version } from '../../package.json.mjs';
2
+
3
+ const CONSOLE_HIGHLIGHT_STYLE = `
4
+ padding: 2px 4px;
5
+ border-radius: 2px;
6
+ background: #389DFF;
7
+ color: white;`;
8
+ function announce() {
9
+ console.log("%cFlo.w RDF Core v%s", CONSOLE_HIGHLIGHT_STYLE, version);
10
+ }
11
+
12
+ export { announce as default };
@@ -0,0 +1,12 @@
1
+ import { FlowCoreError } from '../errors/flow-error.mjs';
2
+
3
+ function assert(condition, message) {
4
+ if (!condition) {
5
+ throw new FlowCoreError(message ?? "Assertion failed");
6
+ }
7
+ }
8
+ function die(message) {
9
+ throw new FlowCoreError(message);
10
+ }
11
+
12
+ export { assert, die };
@@ -1,25 +1,5 @@
1
- import { o as isNumber } from './flow-rdf-core.25e5f6d7.mjs';
2
-
3
- const doNotMemoize = Symbol("Do not memoize");
4
- function memoize(originalFunction, options) {
5
- const cache = /* @__PURE__ */ new Map();
6
- const hash = options.hash ? options.hash : (...args) => args[0];
7
- const context = options.context;
8
- return function memoizedFunction(...args) {
9
- const key = hash.apply(context, args);
10
- if (key === doNotMemoize) {
11
- return originalFunction.apply(context, args);
12
- }
13
- let value;
14
- if (!cache.has(key)) {
15
- value = originalFunction.apply(context, args);
16
- cache.set(key, value);
17
- } else {
18
- value = cache.get(key);
19
- }
20
- return value;
21
- };
22
- }
1
+ import { memoize } from './functional.mjs';
2
+ import { isNumber } from './type-checks.mjs';
23
3
 
24
4
  function debounce(func, wait, options) {
25
5
  options = {
@@ -125,20 +105,4 @@ function debounceWithArgs(fn, wait, options) {
125
105
  };
126
106
  }
127
107
 
128
- function throttle(func, wait, options) {
129
- if (typeof func != "function") {
130
- throw new TypeError("Expected a function");
131
- }
132
- return debounce(func, wait, { ...options, maxWait: wait });
133
- }
134
- function throttleWithArgs(fn, wait, options) {
135
- const memoizedThrottleFn = memoize(
136
- () => debounce(fn, wait, options),
137
- options
138
- );
139
- return (...args) => {
140
- memoizedThrottleFn(...args)(...args);
141
- };
142
- }
143
-
144
- export { debounceWithArgs as a, throttleWithArgs as b, debounce as d, memoize as m, throttle as t };
108
+ export { debounce, debounceWithArgs, debounce as default };