rask-ui 0.10.4 → 0.10.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.
@@ -1,54 +1,32 @@
1
- type Simplify<T> = {
1
+ /**
2
+ * Utility type that preserves unions while "flattening" object types.
3
+ */
4
+ type Simplify<T> = T extends any ? {
2
5
  [K in keyof T]: T[K];
3
- } & {};
4
- type MergeTwo<A extends object, B extends object> = Simplify<Omit<A, keyof B> & B>;
6
+ } : never;
7
+ /**
8
+ * Merge two object types where properties from B override properties from A.
9
+ * Distributes over unions in A.
10
+ */
11
+ type MergeTwo<A extends object, B extends object> = A extends any ? Simplify<Omit<A, keyof B> & B> : never;
12
+ /**
13
+ * Merge a readonly tuple of objects left-to-right, with later entries
14
+ * overriding earlier ones. Distributes over unions in the head element.
15
+ */
5
16
  type MergeMany<T extends readonly object[]> = T extends [
6
17
  infer H extends object,
7
18
  ...infer R extends object[]
8
19
  ] ? MergeTwo<H, MergeMany<R>> : {};
9
20
  /**
10
- * Creates a view that merges multiple objects (reactive or not) into a single object while
11
- * maintaining reactivity through getters. Properties from later arguments override earlier ones.
12
- *
13
- * @warning **Do not destructure the returned view object!** Destructuring breaks reactivity
14
- * because it extracts plain values instead of maintaining getter access. This is the same rule
15
- * as other reactive primitives.
16
- *
17
- * @example
18
- * // ❌ Bad - destructuring loses reactivity
19
- * function Component() {
20
- * const state = createState({ count: 0 });
21
- * const helpers = { increment: () => state.count++ };
22
- * const view = createView(state, helpers);
23
- * const { count, increment } = view; // Don't do this!
24
- * return () => <button onClick={increment}>{count}</button>; // Won't update!
25
- * }
26
- *
27
- * // ✅ Good - access properties directly in render
28
- * function Component() {
29
- * const state = createState({ count: 0 });
30
- * const helpers = { increment: () => state.count++ };
31
- * const view = createView(state, helpers);
32
- * return () => <button onClick={view.increment}>{view.count}</button>; // Reactive!
33
- * }
34
- *
35
- * @example
36
- * // Merge multiple reactive objects
37
- * const state = createState({ count: 0 });
38
- * const user = createState({ name: "Alice" });
39
- * const view = createView(state, user);
40
- * // view has both count and name properties, maintaining reactivity
41
- *
42
- * @example
43
- * // Later arguments override earlier ones
44
- * const a = { x: 1, y: 2 };
45
- * const b = { y: 3, z: 4 };
46
- * const view = createView(a, b);
47
- * // view.x === 1, view.y === 3, view.z === 4
21
+ * Creates a view that merges multiple objects (reactive or not) into a single
22
+ * object while maintaining reactivity through getters. Properties from later
23
+ * arguments override earlier ones.
48
24
  *
49
- * @param args - Objects to merge (reactive or plain objects)
50
- * @returns A view object with getters for all properties, maintaining reactivity
25
+ * ⚠️ Do not destructure the returned view object; always read properties
26
+ * directly from the view to preserve reactivity.
51
27
  */
28
+ export declare function createView<A extends object>(a: A): A;
29
+ export declare function createView<A extends object, B extends object>(a: A, b: B): MergeTwo<A, B>;
52
30
  export declare function createView<T extends readonly object[]>(...args: T): MergeMany<T>;
53
31
  export {};
54
32
  //# sourceMappingURL=createView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createView.d.ts","sourceRoot":"","sources":["../src/createView.ts"],"names":[],"mappings":"AAGA,KAAK,QAAQ,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAE,GAAG,EAAE,CAAC;AAEjD,KAAK,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,IAAI,QAAQ,CAC1D,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CACrB,CAAC;AAEF,KAAK,SAAS,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,IAAI,CAAC,SAAS;IACtD,MAAM,CAAC,SAAS,MAAM;IACtB,GAAG,MAAM,CAAC,SAAS,MAAM,EAAE;CAC5B,GACG,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,GACzB,EAAE,CAAC;AAEP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,EACpD,GAAG,IAAI,EAAE,CAAC,GACT,SAAS,CAAC,CAAC,CAAC,CAyEd"}
1
+ {"version":3,"file":"createView.d.ts","sourceRoot":"","sources":["../src/createView.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAE,GAAG,KAAK,CAAC;AAEpE;;;GAGG;AACH,KAAK,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,GAC7D,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,GAC9B,KAAK,CAAC;AAEV;;;GAGG;AACH,KAAK,SAAS,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,IAAI,CAAC,SAAS;IACtD,MAAM,CAAC,SAAS,MAAM;IACtB,GAAG,MAAM,CAAC,SAAS,MAAM,EAAE;CAC5B,GACG,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,GACzB,EAAE,CAAC;AAEP;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;AACtD,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,EAC3D,CAAC,EAAE,CAAC,EACJ,CAAC,EAAE,CAAC,GACH,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAClB,wBAAgB,UAAU,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,EACpD,GAAG,IAAI,EAAE,CAAC,GACT,SAAS,CAAC,CAAC,CAAC,CAAC"}
@@ -1,64 +1,22 @@
1
1
  import { INSPECT_MARKER, INSPECTOR_ENABLED } from "./inspect";
2
- /**
3
- * Creates a view that merges multiple objects (reactive or not) into a single object while
4
- * maintaining reactivity through getters. Properties from later arguments override earlier ones.
5
- *
6
- * @warning **Do not destructure the returned view object!** Destructuring breaks reactivity
7
- * because it extracts plain values instead of maintaining getter access. This is the same rule
8
- * as other reactive primitives.
9
- *
10
- * @example
11
- * // ❌ Bad - destructuring loses reactivity
12
- * function Component() {
13
- * const state = createState({ count: 0 });
14
- * const helpers = { increment: () => state.count++ };
15
- * const view = createView(state, helpers);
16
- * const { count, increment } = view; // Don't do this!
17
- * return () => <button onClick={increment}>{count}</button>; // Won't update!
18
- * }
19
- *
20
- * // ✅ Good - access properties directly in render
21
- * function Component() {
22
- * const state = createState({ count: 0 });
23
- * const helpers = { increment: () => state.count++ };
24
- * const view = createView(state, helpers);
25
- * return () => <button onClick={view.increment}>{view.count}</button>; // Reactive!
26
- * }
27
- *
28
- * @example
29
- * // Merge multiple reactive objects
30
- * const state = createState({ count: 0 });
31
- * const user = createState({ name: "Alice" });
32
- * const view = createView(state, user);
33
- * // view has both count and name properties, maintaining reactivity
34
- *
35
- * @example
36
- * // Later arguments override earlier ones
37
- * const a = { x: 1, y: 2 };
38
- * const b = { y: 3, z: 4 };
39
- * const view = createView(a, b);
40
- * // view.x === 1, view.y === 3, view.z === 4
41
- *
42
- * @param args - Objects to merge (reactive or plain objects)
43
- * @returns A view object with getters for all properties, maintaining reactivity
44
- */
45
2
  export function createView(...args) {
46
3
  const result = {};
47
4
  const seen = new Set();
48
5
  let notifyInspectorRef = {};
49
6
  for (let i = args.length - 1; i >= 0; i--) {
50
7
  const src = args[i];
8
+ if (!src)
9
+ continue;
51
10
  if (INSPECTOR_ENABLED && src[INSPECT_MARKER]) {
52
11
  src[INSPECT_MARKER] = notifyInspectorRef;
53
12
  }
54
- // mimic Object.assign: only enumerable own property keys
13
+ // Mimic Object.assign: only enumerable own property keys
55
14
  for (const key of Reflect.ownKeys(src)) {
56
15
  if (seen.has(key))
57
16
  continue;
58
17
  const desc = Object.getOwnPropertyDescriptor(src, key);
59
18
  if (!desc || !desc.enumerable)
60
19
  continue;
61
- // Capture the current source for this key (last write wins).
62
20
  Object.defineProperty(result, key, {
63
21
  enumerable: true,
64
22
  configurable: true,
@@ -67,6 +25,7 @@ export function createView(...args) {
67
25
  if (!INSPECTOR_ENABLED || !notifyInspectorRef.current) {
68
26
  return value;
69
27
  }
28
+ // Propagate inspector marker into nested observables
70
29
  if (value?.[INSPECT_MARKER]) {
71
30
  value[INSPECT_MARKER] = {
72
31
  current: {
@@ -76,6 +35,7 @@ export function createView(...args) {
76
35
  };
77
36
  }
78
37
  else if (typeof value === "function") {
38
+ // Wrap actions to notify inspector
79
39
  return (...params) => {
80
40
  notifyInspectorRef.current.notify({
81
41
  type: "action",
@@ -100,6 +60,7 @@ export function createView(...args) {
100
60
  },
101
61
  set: (value) => {
102
62
  Object.defineProperty(notifyInspectorRef, "current", {
63
+ configurable: true,
103
64
  get() {
104
65
  return value.current;
105
66
  },
@@ -107,5 +68,6 @@ export function createView(...args) {
107
68
  },
108
69
  });
109
70
  }
71
+ // The overload signatures expose a precise type; this is the shared impl.
110
72
  return result;
111
73
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rask-ui",
3
- "version": "0.10.4",
3
+ "version": "0.10.5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",