@oscarpalmer/mora 0.26.0 → 0.27.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.
Files changed (41) hide show
  1. package/dist/batch.d.mts +14 -0
  2. package/dist/{batch.js → batch.mjs} +13 -3
  3. package/dist/constants-Cy6_M9Vk.d.mts +20 -0
  4. package/dist/constants.d.mts +2 -0
  5. package/dist/{constants.js → constants.mjs} +2 -0
  6. package/dist/effect-BkupB1p9.d.mts +17 -0
  7. package/dist/effect.d.mts +2 -0
  8. package/dist/{effect.js → effect.mjs} +11 -4
  9. package/dist/helpers/is.d.mts +45 -0
  10. package/dist/helpers/is.mjs +55 -0
  11. package/dist/helpers/proxy.d.mts +14 -0
  12. package/dist/helpers/{proxy.js → proxy.mjs} +6 -4
  13. package/dist/helpers/value.d.mts +8 -0
  14. package/dist/helpers/{value.js → value.mjs} +4 -2
  15. package/dist/index.d.mts +7 -0
  16. package/dist/index.mjs +8 -0
  17. package/dist/models-QwNga87R.d.mts +148 -0
  18. package/dist/models.d.mts +2 -0
  19. package/dist/models.mjs +1 -0
  20. package/dist/{mora.full.js → mora.full.mjs} +68 -49
  21. package/dist/subscription.d.mts +2 -0
  22. package/dist/{subscription.js → subscription.mjs} +2 -0
  23. package/dist/value/array.d.mts +140 -0
  24. package/dist/value/{array.js → array.mjs} +80 -18
  25. package/dist/value/computed.d.mts +2 -0
  26. package/dist/value/{computed.js → computed.mjs} +16 -5
  27. package/dist/value/reactive.d.mts +2 -0
  28. package/dist/value/{reactive.js → reactive.mjs} +25 -2
  29. package/dist/value/signal.d.mts +2 -0
  30. package/dist/value/signal.mjs +43 -0
  31. package/dist/value/store.d.mts +97 -0
  32. package/dist/value/{store.js → store.mjs} +25 -7
  33. package/package.json +41 -35
  34. package/src/constants.ts +1 -6
  35. package/src/helpers/is.ts +1 -1
  36. package/src/value/array.ts +6 -6
  37. package/src/value/store.ts +1 -1
  38. package/dist/helpers/is.js +0 -23
  39. package/dist/index.js +0 -8
  40. package/dist/models.js +0 -0
  41. package/dist/value/signal.js +0 -24
@@ -1,5 +1,6 @@
1
- import { NAME_MORA } from "../constants.js";
2
- import { subscribe, unsubscribe } from "../subscription.js";
1
+ import { NAME_MORA } from "../constants.mjs";
2
+ import { subscribe, unsubscribe } from "../subscription.mjs";
3
+ //#region src/value/reactive.ts
3
4
  var Reactive = class {
4
5
  state = {
5
6
  computeds: /* @__PURE__ */ new Set(),
@@ -13,20 +14,42 @@ var Reactive = class {
13
14
  if (typeof options === "object" && typeof options.equal === "function") this.state.equal = options.equal;
14
15
  Object.defineProperty(this, NAME_MORA, { value: name });
15
16
  }
17
+ /**
18
+ * Get the value _(without reactivity)_
19
+ * @return Current value
20
+ */
16
21
  peek() {
17
22
  return this.state.value;
18
23
  }
24
+ /**
25
+ * Subscribe to changes
26
+ * @param callback Callback for changes
27
+ * @return Unsubscribe callback
28
+ */
19
29
  subscribe(callback) {
20
30
  return subscribe(this.state, callback);
21
31
  }
32
+ /**
33
+ * JSON representation of the value
34
+ * @return JSON value
35
+ */
22
36
  toJSON() {
23
37
  return this.get();
24
38
  }
39
+ /**
40
+ * String representation of the value
41
+ * @return Value as string
42
+ */
25
43
  toString() {
26
44
  return String(this.get());
27
45
  }
46
+ /**
47
+ * Unsubscribe from changes
48
+ * @param callback Callback to unsubscribe
49
+ */
28
50
  unsubscribe(callback) {
29
51
  unsubscribe(this.state, callback);
30
52
  }
31
53
  };
54
+ //#endregion
32
55
  export { Reactive };
@@ -0,0 +1,2 @@
1
+ import { d as Signal, f as signal } from "../models-QwNga87R.mjs";
2
+ export { Signal, signal };
@@ -0,0 +1,43 @@
1
+ import { NAME_SIGNAL } from "../constants.mjs";
2
+ import { Reactive } from "./reactive.mjs";
3
+ import { emitValue, getValue } from "../helpers/value.mjs";
4
+ //#region src/value/signal.ts
5
+ var Signal = class extends Reactive {
6
+ constructor(value, options) {
7
+ super(NAME_SIGNAL, value, options);
8
+ }
9
+ /**
10
+ * @inheritdoc
11
+ */
12
+ get() {
13
+ return getValue(this.state);
14
+ }
15
+ /**
16
+ * Set the value
17
+ * @param value New value
18
+ */
19
+ set(value) {
20
+ if (!this.state.equal(this.state.value, value)) {
21
+ this.state.value = value;
22
+ emitValue(this.state);
23
+ }
24
+ }
25
+ /**
26
+ * Update the value _(based on the current value)_
27
+ * @param callback Callback to update the value
28
+ */
29
+ update(callback) {
30
+ this.set(callback(this.state.value));
31
+ }
32
+ };
33
+ /**
34
+ * Create a reactive value
35
+ * @param value Initial value
36
+ * @param options Reactivity options
37
+ * @returns Reactive value
38
+ */
39
+ function signal(value, options) {
40
+ return new Signal(value, options);
41
+ }
42
+ //#endregion
43
+ export { Signal, signal };
@@ -0,0 +1,97 @@
1
+ import { h as Reactive, s as ReactiveOptions, u as Unsubscribe } from "../models-QwNga87R.mjs";
2
+ import { Key, PlainObject } from "@oscarpalmer/atoms/models";
3
+
4
+ //#region src/value/store.d.ts
5
+ declare class Store<Value extends PlainObject> extends Reactive<Value, Value> {
6
+ #private;
7
+ constructor(value: Value, options?: ReactiveOptions<Value>);
8
+ /**
9
+ * @inheritdoc
10
+ */
11
+ get(): Value;
12
+ /**
13
+ * Get a value by key
14
+ * @param key Key of the value to get
15
+ * @returns Value for the specified key, or `undefined` if it doesn't exist
16
+ */
17
+ get<Key extends keyof Value>(key: Key): Value[Key];
18
+ /**
19
+ * Get a value by key
20
+ * @param key Key of the value to get
21
+ * @returns Value for the specified key, or `undefined` if it doesn't exist
22
+ */
23
+ get(key: Key): unknown;
24
+ /**
25
+ * Notify dependents of changes
26
+ *
27
+ * _This bypasses equality checks and will immediately notify dependents.
28
+ * Use this only if you're modifying nested data that would be ignored by equality checks._
29
+ */
30
+ notify(): void;
31
+ /**
32
+ * Get the value _(without reactivity)_
33
+ * @returns The current value
34
+ */
35
+ peek(): Value;
36
+ /**
37
+ * Get a value by key _(without reactivity)_
38
+ * @param key Key of the value to get
39
+ * @returns Value for the specified key, or `undefined` if it doesn't exist
40
+ */
41
+ peek<Key extends keyof Value>(key: Key): Value[Key];
42
+ /**
43
+ * Get a value by key _(without reactivity)_
44
+ * @param key Key of the value to get
45
+ * @returns Value for the specified key, or `undefined` if it doesn't exist
46
+ */
47
+ peek(key: Key): unknown;
48
+ /**
49
+ * Set the value
50
+ * @param value New value _(defaults to an empty object)_
51
+ */
52
+ set(value?: Value): void;
53
+ /**
54
+ * Set a value by key
55
+ * @param key Key of the value to set
56
+ * @param value New value
57
+ */
58
+ set<Key extends keyof Value>(key: Key, value: Value[Key]): void;
59
+ /**
60
+ * Set a value by key
61
+ * @param key Key of the value to set
62
+ * @param value New value
63
+ */
64
+ set(key: Key, value: unknown): void;
65
+ /**
66
+ * @inheritdoc
67
+ */
68
+ subscribe(callback: (value: Value) => void): Unsubscribe;
69
+ /**
70
+ * Subscribe to changes for a specific key
71
+ * @param key Key of the value to subscribe to
72
+ * @param callback Callback for changes
73
+ * @returns Unsubscribe callback
74
+ */
75
+ subscribe<Key extends keyof Value>(key: Key, callback: (value: Value[Key] | undefined) => void): Unsubscribe;
76
+ /**
77
+ * Subscribe to changes for a specific key
78
+ * @param key Key of the value to subscribe to
79
+ * @param callback Callback for changes
80
+ * @returns Unsubscribe callback
81
+ */
82
+ subscribe(key: Key, callback: (value: unknown) => void): Unsubscribe;
83
+ /**
84
+ * Update the value _(based on the current value)_
85
+ * @param callback Callback to update the value
86
+ */
87
+ update(callback: (value: Value) => Value): void;
88
+ }
89
+ /**
90
+ * Create a reactive store
91
+ * @param value Initial object value
92
+ * @param options Reactivity options
93
+ * @returns Reactive store
94
+ */
95
+ declare function store<Value extends PlainObject>(value: Value, options?: ReactiveOptions<Value>): Store<Value>;
96
+ //#endregion
97
+ export { Store, store };
@@ -1,16 +1,17 @@
1
- import { NAME_STORE } from "../constants.js";
2
- import { noop, subscribe } from "../subscription.js";
3
- import { Reactive } from "./reactive.js";
4
- import { getValue } from "../helpers/value.js";
5
- import { emityProxyValues, getReactiveValueInProxy, setProxyValue, setValueInProxy } from "../helpers/proxy.js";
1
+ import { NAME_STORE } from "../constants.mjs";
2
+ import { noop, subscribe } from "../subscription.mjs";
3
+ import { Reactive } from "./reactive.mjs";
4
+ import { getValue } from "../helpers/value.mjs";
5
+ import { emityProxyValues, getReactiveValueInProxy, setProxyValue, setValueInProxy } from "../helpers/proxy.mjs";
6
6
  import { isKey, isPlainObject } from "@oscarpalmer/atoms/is";
7
+ //#region src/value/store.ts
7
8
  var Store = class extends Reactive {
8
9
  #keyed = /* @__PURE__ */ new Map();
9
10
  constructor(value, options) {
10
- super(NAME_STORE, new Proxy(value, { set: (target, property, value$1) => setValueInProxy({
11
+ super(NAME_STORE, new Proxy(value, { set: (target, property, value) => setValueInProxy({
11
12
  target,
12
13
  property,
13
- value: value$1,
14
+ value,
14
15
  isArray: false,
15
16
  state: this.state
16
17
  }) }), options);
@@ -18,6 +19,12 @@ var Store = class extends Reactive {
18
19
  get(key) {
19
20
  return isKey(key) ? getReactiveValueInProxy(this, this.#keyed, key, false).get() : getValue(this.state);
20
21
  }
22
+ /**
23
+ * Notify dependents of changes
24
+ *
25
+ * _This bypasses equality checks and will immediately notify dependents.
26
+ * Use this only if you're modifying nested data that would be ignored by equality checks._
27
+ */
21
28
  notify() {
22
29
  emityProxyValues(this.state, this.#keyed);
23
30
  }
@@ -32,12 +39,23 @@ var Store = class extends Reactive {
32
39
  if (isKey(first) && typeof second === "function") return getReactiveValueInProxy(this, this.#keyed, first, false).subscribe(second);
33
40
  return typeof first === "function" ? subscribe(this.state, first) : noop;
34
41
  }
42
+ /**
43
+ * Update the value _(based on the current value)_
44
+ * @param callback Callback to update the value
45
+ */
35
46
  update(callback) {
36
47
  const updated = callback({ ...this.state.value });
37
48
  if (updated == null || isPlainObject(updated)) setProxyValue(this.state.value, updated ?? {});
38
49
  }
39
50
  };
51
+ /**
52
+ * Create a reactive store
53
+ * @param value Initial object value
54
+ * @param options Reactivity options
55
+ * @returns Reactive store
56
+ */
40
57
  function store(value, options) {
41
58
  return new Store(isPlainObject(value) ? value : {}, options);
42
59
  }
60
+ //#endregion
43
61
  export { Store, store };
package/package.json CHANGED
@@ -1,49 +1,55 @@
1
1
  {
2
+ "name": "@oscarpalmer/mora",
3
+ "version": "0.27.0",
4
+ "description": "Signals and stuff…",
5
+ "keywords": [
6
+ "reactive",
7
+ "signal",
8
+ "signals"
9
+ ],
10
+ "license": "MIT",
2
11
  "author": {
3
12
  "name": "Oscar Palmér",
4
13
  "url": "https://oscarpalmer.se"
5
14
  },
6
- "dependencies": {
7
- "@oscarpalmer/atoms": "^0.124"
8
- },
9
- "description": "Signals and stuff…",
10
- "devDependencies": {
11
- "@types/node": "^25",
12
- "@vitest/coverage-istanbul": "^4",
13
- "jsdom": "^27.3",
14
- "oxfmt": "^0.21",
15
- "oxlint": "^1.36",
16
- "rolldown": "1.0.0-beta.58",
17
- "tslib": "^2.8",
18
- "typescript": "^5.9",
19
- "vite": "8.0.0-beta.5",
20
- "vitest": "^4"
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/oscarpalmer/mora.git"
21
18
  },
19
+ "files": [
20
+ "dist",
21
+ "src",
22
+ "types"
23
+ ],
24
+ "type": "module",
25
+ "module": "./dist/index.mjs",
26
+ "types": "./dist/index.d.mts",
22
27
  "exports": {
23
28
  "./package.json": "./package.json",
24
29
  ".": {
25
- "types": "./types/index.d.ts",
26
- "default": "./dist/index.js"
30
+ "types": "./dist/index.d.mts",
31
+ "default": "./dist/index.mjs"
27
32
  }
28
33
  },
29
- "files": ["dist", "src", "types"],
30
- "keywords": ["signal", "signals", "reactive"],
31
- "license": "MIT",
32
- "module": "./dist/index.js",
33
- "name": "@oscarpalmer/mora",
34
- "repository": {
35
- "type": "git",
36
- "url": "git+https://github.com/oscarpalmer/mora.git"
37
- },
38
34
  "scripts": {
39
- "build": "npm run clean && npx vite build && npm run rolldown:build && npx tsc",
40
- "clean": "rm -rf ./dist && rm -rf ./types && rm -f ./tsconfig.tsbuildinfo",
41
- "rolldown:build": "npx rolldown -c",
42
- "rolldown:watch": "npx rolldown -c --watch",
43
- "test": "npx vitest --coverage",
44
- "watch": "npx vite build --watch"
35
+ "build": "vpx vp run tsdown:build && vpx vp pack",
36
+ "tsdown:build": "vpx tsdown -c ./tsdown.config.ts",
37
+ "tsdown:watch": "vpx tsdown -c ./tsdown.config.ts --watch",
38
+ "test": "vpx vp test run --coverage",
39
+ "test:leak": "vpx vp test run --detect-async-leaks --coverage"
45
40
  },
46
- "type": "module",
47
- "types": "./types/index.d.ts",
48
- "version": "0.26.0"
41
+ "dependencies": {
42
+ "@oscarpalmer/atoms": "^0.165"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^25.5",
46
+ "@vitest/coverage-istanbul": "^4.1",
47
+ "jsdom": "^28.1",
48
+ "tsdown": "^0.21",
49
+ "typescript": "^5.9",
50
+ "vite": "npm:@voidzero-dev/vite-plus-core@latest",
51
+ "vite-plus": "latest",
52
+ "vitest": "npm:@voidzero-dev/vite-plus-test@latest"
53
+ },
54
+ "packageManager": "npm@11.11.1"
49
55
  }
package/src/constants.ts CHANGED
@@ -15,12 +15,7 @@ export const BATCH: Batch = {
15
15
  handlers: new Set<Effect | Subscription>(),
16
16
  };
17
17
 
18
- export const METHODS_AFFECTING_LENGTH = new Set<string>([
19
- 'pop',
20
- 'push',
21
- 'shift',
22
- 'unshift',
23
- ]);
18
+ export const METHODS_AFFECTING_LENGTH = new Set<string>(['pop', 'push', 'shift', 'unshift']);
24
19
 
25
20
  export const METHODS_UPDATE = new Set<string>([
26
21
  ...METHODS_AFFECTING_LENGTH,
package/src/helpers/is.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import type {PlainObject} from '@oscarpalmer/atoms/models';
2
2
  import {
3
+ NAME_ALL,
3
4
  NAME_ARRAY,
4
5
  NAME_COMPUTED,
5
6
  NAME_EFFECT,
6
7
  NAME_MORA,
7
8
  NAME_SIGNAL,
8
9
  NAME_STORE,
9
- NAME_ALL,
10
10
  } from '../constants';
11
11
  import type {Effect} from '../effect';
12
12
  import type {ReactiveArray} from '../value/array';
@@ -85,7 +85,7 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
85
85
  * Get the length of the array
86
86
  * @returns Length of the array
87
87
  */
88
- get(property: 'length'): number;
88
+ get(property: typeof PROPERTY_LENGTH): number;
89
89
 
90
90
  get(first?: unknown): unknown {
91
91
  if (typeof first === 'number') {
@@ -130,10 +130,10 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
130
130
  * Get the length of the array _(without reactivity)_
131
131
  * @returns Length of the array
132
132
  */
133
- override peek(property: 'length'): number;
133
+ override peek(property: typeof PROPERTY_LENGTH): number;
134
134
 
135
135
  override peek(value?: unknown): unknown {
136
- if (value === 'length') {
136
+ if (value === PROPERTY_LENGTH) {
137
137
  return this.#size.peek();
138
138
  }
139
139
 
@@ -174,12 +174,12 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
174
174
  * Set the length of the array
175
175
  * @param value New array length
176
176
  */
177
- set(property: 'length', value: number): void;
177
+ set(property: typeof PROPERTY_LENGTH, value: number): void;
178
178
 
179
- set(first?: number | 'length' | Item[], second?: number | Item): void {
179
+ set(first?: number | typeof PROPERTY_LENGTH | Item[], second?: number | Item): void {
180
180
  if (first == null || Array.isArray(first)) {
181
181
  this.state.value.splice(0, this.state.value.length, ...(first ?? []));
182
- } else if (first === 'length') {
182
+ } else if (first === PROPERTY_LENGTH) {
183
183
  this.length = second as number;
184
184
  } else if (typeof first === 'number' && !Number.isNaN(first)) {
185
185
  setAtIndex(this.state.value, first, second as Item);
@@ -2,8 +2,8 @@ import {isKey, isPlainObject} from '@oscarpalmer/atoms/is';
2
2
  import type {GenericCallback, Key, PlainObject} from '@oscarpalmer/atoms/models';
3
3
  import {NAME_STORE} from '../constants';
4
4
  import {
5
- getReactiveValueInProxy,
6
5
  emityProxyValues,
6
+ getReactiveValueInProxy,
7
7
  setProxyValue,
8
8
  setValueInProxy,
9
9
  } from '../helpers/proxy';
@@ -1,23 +0,0 @@
1
- import { NAME_ALL, NAME_ARRAY, NAME_COMPUTED, NAME_EFFECT, NAME_MORA, NAME_SIGNAL, NAME_STORE } from "../constants.js";
2
- function isArray(value) {
3
- return isMora(value, NAME_ARRAY);
4
- }
5
- function isComputed(value) {
6
- return isMora(value, NAME_COMPUTED);
7
- }
8
- function isEffect(value) {
9
- return isMora(value, NAME_EFFECT);
10
- }
11
- function isMora(value, name) {
12
- return typeof value === "object" && value != null && "$mora" in value && (typeof name === "string" ? value["$mora"] === name : name.has(value["$mora"]));
13
- }
14
- function isReactive(value) {
15
- return isMora(value, NAME_ALL);
16
- }
17
- function isSignal(value) {
18
- return isMora(value, NAME_SIGNAL);
19
- }
20
- function isStore(value) {
21
- return isMora(value, NAME_STORE);
22
- }
23
- export { isArray, isComputed, isEffect, isReactive, isSignal, isStore };
package/dist/index.js DELETED
@@ -1,8 +0,0 @@
1
- import { effect } from "./effect.js";
2
- import { isArray, isComputed, isEffect, isReactive, isSignal } from "./helpers/is.js";
3
- import { startBatch, stopBatch } from "./batch.js";
4
- import { computed } from "./value/computed.js";
5
- import { signal } from "./value/signal.js";
6
- import { array } from "./value/array.js";
7
- import { store } from "./value/store.js";
8
- export { array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
package/dist/models.js DELETED
File without changes
@@ -1,24 +0,0 @@
1
- import { NAME_SIGNAL } from "../constants.js";
2
- import { Reactive } from "./reactive.js";
3
- import { emitValue, getValue } from "../helpers/value.js";
4
- var Signal = class extends Reactive {
5
- constructor(value, options) {
6
- super(NAME_SIGNAL, value, options);
7
- }
8
- get() {
9
- return getValue(this.state);
10
- }
11
- set(value) {
12
- if (!this.state.equal(this.state.value, value)) {
13
- this.state.value = value;
14
- emitValue(this.state);
15
- }
16
- }
17
- update(callback) {
18
- this.set(callback(this.state.value));
19
- }
20
- };
21
- function signal(value, options) {
22
- return new Signal(value, options);
23
- }
24
- export { Signal, signal };