tutuca 0.9.40 → 0.9.41

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 (86) hide show
  1. package/dist/tutuca-cli.js +74 -39
  2. package/package.json +6 -7
  3. package/skill/immutable-js/SKILL.md +79 -0
  4. package/skill/immutable-js/references/collection.md +346 -0
  5. package/skill/immutable-js/references/conversions.md +99 -0
  6. package/skill/immutable-js/references/deep-updates.md +172 -0
  7. package/skill/immutable-js/references/equality.md +95 -0
  8. package/skill/immutable-js/references/list.md +266 -0
  9. package/skill/immutable-js/references/map.md +300 -0
  10. package/skill/immutable-js/references/predicates.md +93 -0
  11. package/skill/immutable-js/references/range-repeat.md +55 -0
  12. package/skill/immutable-js/references/record.md +196 -0
  13. package/skill/immutable-js/references/seq.md +248 -0
  14. package/skill/immutable-js/references/set.md +270 -0
  15. package/skill/immutable-js/references/shallow-functional.md +99 -0
  16. package/skill/immutable-js/references/stack.md +210 -0
  17. package/skill/margaui/SKILL.md +101 -0
  18. package/skill/margaui/components/accordion.md +127 -0
  19. package/skill/margaui/components/alert.md +174 -0
  20. package/skill/margaui/components/avatar.md +220 -0
  21. package/skill/margaui/components/badge.md +193 -0
  22. package/skill/margaui/components/breadcrumbs.md +103 -0
  23. package/skill/margaui/components/button.md +322 -0
  24. package/skill/margaui/components/calendar.md +67 -0
  25. package/skill/margaui/components/card.md +373 -0
  26. package/skill/margaui/components/carousel.md +387 -0
  27. package/skill/margaui/components/chat.md +171 -0
  28. package/skill/margaui/components/checkbox.md +101 -0
  29. package/skill/margaui/components/collapse.md +172 -0
  30. package/skill/margaui/components/countdown.md +165 -0
  31. package/skill/margaui/components/diff.md +53 -0
  32. package/skill/margaui/components/divider.md +107 -0
  33. package/skill/margaui/components/dock.md +173 -0
  34. package/skill/margaui/components/drawer.md +184 -0
  35. package/skill/margaui/components/dropdown.md +388 -0
  36. package/skill/margaui/components/fab.md +346 -0
  37. package/skill/margaui/components/fieldset.md +88 -0
  38. package/skill/margaui/components/file-input.md +84 -0
  39. package/skill/margaui/components/filter.md +52 -0
  40. package/skill/margaui/components/footer.md +583 -0
  41. package/skill/margaui/components/hero.md +135 -0
  42. package/skill/margaui/components/hover-3d.md +129 -0
  43. package/skill/margaui/components/hover-gallery.md +49 -0
  44. package/skill/margaui/components/indicator.md +265 -0
  45. package/skill/margaui/components/input.md +389 -0
  46. package/skill/margaui/components/join.md +100 -0
  47. package/skill/margaui/components/kbd.md +127 -0
  48. package/skill/margaui/components/label.md +102 -0
  49. package/skill/margaui/components/link.md +96 -0
  50. package/skill/margaui/components/list.md +182 -0
  51. package/skill/margaui/components/loading.md +105 -0
  52. package/skill/margaui/components/mask.md +168 -0
  53. package/skill/margaui/components/menu.md +856 -0
  54. package/skill/margaui/components/mockup-browser.md +39 -0
  55. package/skill/margaui/components/mockup-code.md +81 -0
  56. package/skill/margaui/components/mockup-phone.md +39 -0
  57. package/skill/margaui/components/mockup-window.md +33 -0
  58. package/skill/margaui/components/modal.md +178 -0
  59. package/skill/margaui/components/navbar.md +282 -0
  60. package/skill/margaui/components/pagination.md +122 -0
  61. package/skill/margaui/components/progress.md +135 -0
  62. package/skill/margaui/components/radial-progress.md +67 -0
  63. package/skill/margaui/components/radio.md +133 -0
  64. package/skill/margaui/components/range.md +134 -0
  65. package/skill/margaui/components/rating.md +170 -0
  66. package/skill/margaui/components/select.md +225 -0
  67. package/skill/margaui/components/skeleton.md +64 -0
  68. package/skill/margaui/components/stack.md +142 -0
  69. package/skill/margaui/components/stat.md +254 -0
  70. package/skill/margaui/components/status.md +73 -0
  71. package/skill/margaui/components/steps.md +138 -0
  72. package/skill/margaui/components/swap.md +152 -0
  73. package/skill/margaui/components/tab.md +248 -0
  74. package/skill/margaui/components/table.md +1018 -0
  75. package/skill/margaui/components/text-rotate.md +91 -0
  76. package/skill/margaui/components/textarea.md +85 -0
  77. package/skill/margaui/components/theme-controller.md +266 -0
  78. package/skill/margaui/components/timeline.md +1356 -0
  79. package/skill/margaui/components/toast.md +165 -0
  80. package/skill/margaui/components/toggle.md +135 -0
  81. package/skill/margaui/components/tooltip.md +181 -0
  82. package/skill/margaui/components/validator.md +163 -0
  83. package/skill/{advanced.md → tutuca/advanced.md} +5 -0
  84. package/skill/{cli.md → tutuca/cli.md} +17 -0
  85. package/skill/{core.md → tutuca/core.md} +5 -0
  86. /package/skill/{SKILL.md → tutuca/SKILL.md} +0 -0
@@ -0,0 +1,99 @@
1
+ Immutable.js conversions go in two directions: PARSE plain JS into Immutable with `fromJS`, and PROJECT Immutable back to plain JS with `toJS` / `toJSON` / `toArray` / `toObject` / specific-type converters (`toList`, `toMap`, `toSet`, ...). Reach for `fromJS` when you receive JSON or other plain data at a boundary. Reach for `toJS` only at boundaries (serialization, debugging, libraries that don't speak Immutable) — passing Immutable values around inside your code is preferred since `toJS` is recursive and allocates a fresh deep copy.
2
+
3
+ ## fromJS
4
+
5
+ ```ts
6
+ fromJS(jsValue, reviver?: (key, sequence, path) => unknown): unknown
7
+ ```
8
+
9
+ Default behavior:
10
+ - Plain `Array` → `List`
11
+ - Plain `Object` (no custom prototype, own enumerable string keys) → `Map`
12
+ - Recurses into both
13
+ - Numbers, strings, booleans, `null`, `Date`, `RegExp`, JS `Map`/`Set`, custom class instances pass through unchanged
14
+
15
+ ```js
16
+ import { fromJS } from 'immutable';
17
+ fromJS({ a: { b: [10, 20, 30] }, c: 40 });
18
+ // Map { a: Map { b: List [ 10, 20, 30 ] }, c: 40 }
19
+ ```
20
+
21
+ The optional `reviver` is called bottom-up (deepest collection first) with each level wrapped as a `Seq.Keyed` (for objects) or `Seq.Indexed` (for arrays). It must return an Immutable Collection. The default reviver is effectively:
22
+
23
+ ```js
24
+ (key, value) => (isKeyed(value) ? value.toMap() : value.toList());
25
+ ```
26
+
27
+ Override it to choose different bucket types — e.g. `OrderedMap` + `List`:
28
+
29
+ ```js
30
+ import { fromJS, isKeyed } from 'immutable';
31
+ fromJS(payload, (_, value) =>
32
+ isKeyed(value) ? value.toOrderedMap() : value.toList()
33
+ );
34
+ ```
35
+
36
+ The reviver also receives a `path` array (sequence of keys from the root) — useful for selectively converting only certain branches (e.g. leave `events` as a `List` but turn `index` into an `OrderedMap`).
37
+
38
+ ## toJS / toJSON
39
+
40
+ - `toJS()` — recursively converts an Immutable value into plain JS. `Map`/`Record`/Keyed → object (string keys), `List`/`Stack`/Indexed → array, `Set`/`OrderedSet` → array.
41
+ - `toJSON()` — SHALLOW one-level conversion. The same shape (object vs array) but the values are still Immutable.
42
+ - `JSON.stringify(immutableValue)` works out of the box: each node's `toJSON` is invoked recursively by the serializer, so the resulting JSON string IS deeply plain.
43
+ - `Record#toJSON()` returns a plain object with the record's defined keys (no prototype).
44
+
45
+ ```js
46
+ import { Map, List } from 'immutable';
47
+ const m = Map({ items: List([1, 2, 3]) });
48
+ m.toJS(); // { items: [1, 2, 3] } (deep)
49
+ m.toJSON(); // { items: List [ 1, 2, 3 ] } (shallow)
50
+ JSON.stringify(m); // '{"items":[1,2,3]}' (deep, via toJSON recursion)
51
+ ```
52
+
53
+ ## Per-type converters
54
+
55
+ Shallow conversions to plain JS containers:
56
+
57
+ ```ts
58
+ toArray(): Array<V> | Array<[K, V]> // Keyed → entries; Indexed/Set → values
59
+ toObject(): { [key: string]: V } // Keyed only; coerces keys to strings
60
+ ```
61
+
62
+ Re-bucket into another Immutable collection (the source's keys may or may not survive — see notes):
63
+
64
+ ```ts
65
+ toList(): List<V> // discards keys (Map → values only)
66
+ toMap(): Map<K, V> // requires hashable keys; throws otherwise
67
+ toOrderedMap(): OrderedMap<K, V> // preserves iteration order
68
+ toSet(): Set<V> // discards keys; requires hashable values
69
+ toOrderedSet(): OrderedSet<V> // preserves iteration order
70
+ toStack(): Stack<V> // discards keys
71
+ ```
72
+
73
+ Lazy `Seq` variants (no work until iterated):
74
+
75
+ ```ts
76
+ toSeq(): Seq<K, V> // same kind as the source
77
+ toKeyedSeq(): Seq.Keyed<K, V> // for Indexed: indices become keys
78
+ toIndexedSeq(): Seq.Indexed<V> // discards keys
79
+ toSetSeq(): Seq.Set<V> // discards keys
80
+ ```
81
+
82
+ These are equivalent to passing the collection to the corresponding constructor (`List(coll)`, `Map(coll)`, ...) but read better in chains and have one important difference: `List(map)` produces a list of `[key, value]` entry tuples, while `map.toList()` produces a list of values only.
83
+
84
+ ## Gotchas
85
+
86
+ - `fromJS` does NOT convert `Date`, JS `Map`/`Set`, `RegExp`, typed arrays, or custom class instances — they pass through. Use a `reviver` if you need to convert them.
87
+ - `fromJS` only treats objects with the default `Object.prototype` as plain — anything with a custom prototype is left alone. This is usually what you want, but means subclasses of `Object` won't be deepened.
88
+ - `toJS` is recursive and allocates a fresh deep copy on every call. On large structures it is expensive — iterate Immutable values directly rather than calling `.toJS()` in render paths or hot loops.
89
+ - `Map#toList()` discards keys (values-only). If you want pairs, use `map.entrySeq().toList()` or `map.toIndexedSeq()` over `entrySeq`.
90
+ - `Map#toArray()` (and other Keyed `toArray()`) returns `[key, value]` tuples, not values — use `valueSeq().toArray()` for a flat values array.
91
+ - Round-tripping `fromJS(value).toJS()` produces a structurally similar object but not necessarily identical: property iteration order may change, and any non-plain instances on the input round-trip as the same reference (since `fromJS` left them alone).
92
+ - `JSON.stringify(immutable)` works without explicit conversion — `toJSON` is wired up on every collection. No need to call `.toJS()` first.
93
+ - `toMap()` and `toSet()` throw at runtime if the values/keys are not hashable (e.g. mutable JS objects). `toOrderedMap`/`toOrderedSet` have the same constraint but preserve insertion order.
94
+
95
+ ## See also
96
+
97
+ - `references/deep-updates.md` — `getIn`/`setIn`/`updateIn`/`mergeDeep` for working without converting back to JS.
98
+ - `references/list.md`, `references/map.md`, `references/set.md` — per-type construction and method details.
99
+ - `references/predicates.md` — `isImmutable`, `isKeyed`, `isIndexed` (used in `fromJS` revivers).
@@ -0,0 +1,172 @@
1
+ When you have nested data, these helpers update by path without writing the boilerplate yourself. Each returns a new structure with structural sharing for the unchanged parts. Available both as top-level functions imported from `immutable` (which also accept plain JS objects/arrays) and as instance methods on every Immutable collection. The instance forms (`map.setIn(...)`, `list.updateIn(...)`, etc.) have identical semantics on Immutable inputs.
2
+
3
+ ## Paths
4
+
5
+ - A path is any iterable of keys/indices — most code uses an `Array`, but any `Iterable` works.
6
+ - Use numeric indices for `List`/`Array` segments and string keys for `Map`/`Record`/object segments. Keys are matched exactly (no negative-index resolution like `List.get(-1)` does).
7
+ - For `setIn`/`updateIn`/`mergeIn`, missing intermediate keys are auto-created as empty `Map`s to fill out the path. If you want a `List` at some level, initialize it explicitly first.
8
+ - `getIn`/`hasIn` never mutate or extend — a missing intermediate just yields `notSetValue` / `false`.
9
+ - All functions return the same identity (`===`) when no change occurs (e.g. `setIn` to the existing value).
10
+
11
+ ## getIn
12
+
13
+ ```ts
14
+ getIn(collection, keyPath, notSetValue?): any
15
+ ```
16
+
17
+ Walks `keyPath` from `collection` and returns the value found, or `notSetValue` (default `undefined`) if any segment is missing.
18
+
19
+ ```js
20
+ getIn({ x: { y: { z: 123 } } }, ['x', 'y', 'z']); // => 123
21
+ getIn({ x: { y: { z: 123 } } }, ['x', 'q', 'p'], 'fallback'); // => 'fallback'
22
+ ```
23
+
24
+ ## hasIn
25
+
26
+ ```ts
27
+ hasIn(collection, keyPath): boolean
28
+ ```
29
+
30
+ Returns `true` iff every segment of `keyPath` resolves. Distinguishes "key absent" from "key present but `undefined`", unlike `getIn(...) !== undefined`.
31
+
32
+ ```js
33
+ hasIn({ x: { y: { z: 123 } } }, ['x', 'y', 'z']); // => true
34
+ hasIn({ x: { y: { z: 123 } } }, ['x', 'q', 'p']); // => false
35
+ ```
36
+
37
+ ## setIn
38
+
39
+ ```ts
40
+ setIn(collection: C, keyPath: Iterable, value: any): C
41
+ ```
42
+
43
+ Returns a copy of `collection` with the value at `keyPath` replaced by `value`. Missing intermediate keys are filled in as empty `Map`s.
44
+
45
+ ```js
46
+ setIn({ x: { y: { z: 123 } } }, ['x', 'y', 'z'], 456);
47
+ // => { x: { y: { z: 456 } } }
48
+
49
+ setIn(Map(), ['a', 'b', 'c'], 1);
50
+ // => Map { "a": Map { "b": Map { "c": 1 } } }
51
+ ```
52
+
53
+ ## updateIn
54
+
55
+ ```ts
56
+ updateIn(collection, keyPath, updater)
57
+ updateIn(collection, keyPath, notSetValue, updater)
58
+ ```
59
+
60
+ Returns a copy where the value at `keyPath` is replaced by `updater(currentValue)`. With four arguments, `notSetValue` is passed to `updater` when the path is missing (otherwise `updater` receives `undefined`). Like `setIn`, missing intermediates become empty `Map`s.
61
+
62
+ ```js
63
+ // 3-arg: updater receives undefined when path is missing
64
+ updateIn(Map(), ['hits'], n => (n || 0) + 1);
65
+ // => Map { "hits": 1 }
66
+
67
+ // 4-arg: notSetValue is passed in when path is missing
68
+ updateIn(Map({ x: { y: 10 } }), ['x', 'y'], 0, n => n + 1);
69
+ // => Map { "x": { "y": 11 } }
70
+ updateIn(Map(), ['x', 'y'], 0, n => n + 1);
71
+ // => Map { "x": Map { "y": 1 } }
72
+ ```
73
+
74
+ ## removeIn (alias deleteIn)
75
+
76
+ ```ts
77
+ removeIn(collection: C, keyPath: Iterable): C
78
+ ```
79
+
80
+ Returns a copy with the entry at `keyPath` removed. Intermediate containers are left in place even if they become empty.
81
+
82
+ ```js
83
+ removeIn({ x: { y: { z: 123 } } }, ['x', 'y', 'z']);
84
+ // => { x: { y: {} } }
85
+ ```
86
+
87
+ ## merge
88
+
89
+ ```ts
90
+ merge<C>(collection: C, ...sources): C
91
+ ```
92
+
93
+ Shallow non-mutating merge: each source's keys overwrite `collection`'s at the top level only. For plain objects this behaves like `Object.assign({}, target, ...sources)` but never mutates; for `Map`-like targets it merges entries.
94
+
95
+ ```js
96
+ merge({ x: 123, y: 456 }, { y: 789 });
97
+ // => { x: 123, y: 789 }
98
+ ```
99
+
100
+ ## mergeWith
101
+
102
+ ```ts
103
+ mergeWith<C>(
104
+ merger: (oldVal, newVal, key) => any,
105
+ collection: C,
106
+ ...sources
107
+ ): C
108
+ ```
109
+
110
+ Like `merge`, but `merger(oldVal, newVal, key)` resolves every collision (called only when both sides have the key).
111
+
112
+ ```js
113
+ mergeWith(
114
+ (oldVal, newVal) => oldVal + newVal,
115
+ { x: 123, y: 456 },
116
+ { y: 789, z: 'abc' }
117
+ );
118
+ // => { x: 123, y: 1245, z: 'abc' }
119
+ ```
120
+
121
+ ## mergeDeep
122
+
123
+ ```ts
124
+ mergeDeep<C>(collection: C, ...sources): C
125
+ ```
126
+
127
+ Recursive merge. At each key: if both old and new values are "compatible" collections in the same category (keyed: `Map`/`Record`/object, indexed: `List`/`Array`, set-like: `Set`), they are merged together; otherwise the new value replaces the old. Indexed and set-like values are merged via `concat()`/`union()` — they do NOT recurse element-wise. Mixing categories at a key (e.g. `List` vs `Map`) replaces.
128
+
129
+ ```js
130
+ mergeDeep({ x: { y: 123 } }, { x: { z: 456 } });
131
+ // => { x: { y: 123, z: 456 } }
132
+
133
+ mergeDeep({ xs: [1, 2] }, { xs: [3, 4] });
134
+ // => { xs: [1, 2, 3, 4] } // concat, NOT element-wise merge
135
+ ```
136
+
137
+ ## mergeDeepWith
138
+
139
+ ```ts
140
+ mergeDeepWith<C>(
141
+ merger: (oldVal, newVal, key) => any,
142
+ collection: C,
143
+ ...sources
144
+ ): C
145
+ ```
146
+
147
+ Like `mergeDeep`, but at any leaf collision (or when the two sides are in incompatible categories), `merger(oldVal, newVal, key)` decides the resulting value.
148
+
149
+ ```js
150
+ mergeDeepWith(
151
+ (oldVal, newVal) => oldVal + newVal,
152
+ { x: { y: 123 } },
153
+ { x: { y: 456 } }
154
+ );
155
+ // => { x: { y: 579 } }
156
+ ```
157
+
158
+ ## Gotchas
159
+
160
+ - `setIn`/`updateIn`/`mergeIn` create missing intermediates as empty `Map`s. If a layer should be a `List`, build it yourself (e.g. `setIn(state, ['items'], List())` first) — paths cannot signal which container type to materialize.
161
+ - `mergeDeep` does NOT element-merge `List`s/`Array`s — same-key indexed values are concatenated, and `Set`s are unioned. To deep-merge by index, write a custom `mergeDeepWith` merger.
162
+ - A category mismatch at a key (e.g. existing `List`, incoming `Map`) replaces under `mergeDeep`; only `mergeDeepWith` lets you intervene.
163
+ - Top-level functional forms accept plain JS as the target and return the same kind back (object in / object out, `Map` in / `Map` out). The instance methods are only on Immutable collections.
164
+ - All operations are identity-preserving on no-op: `setIn(c, path, c.getIn(path)) === c`, `merge(c) === c` when nothing changes.
165
+ - `getIn`/`hasIn` perform exact key lookups. `getIn(list, [-1])` does not return the last element — use `list.last()`.
166
+
167
+ ## See also
168
+
169
+ - `list.md`, `map.md` — instance variants and additional `*In` methods (`mergeIn`, `mergeDeepIn`).
170
+ - `record.md` — path access on `Record` respects declared fields.
171
+ - `conversions.md` — when mixing JS and Immutable inputs across these helpers.
172
+ - `shallow-functional.md` — single-level versions (`get`, `set`, `update`, `remove`, `has`).
@@ -0,0 +1,95 @@
1
+ Immutable.js treats collections as VALUES, not references: two distinct `Map({a: 1})` instances are equal even though `===` says otherwise. This is implemented via two protocols, `equals(other): boolean` and `hashCode(): number`, together forming the `ValueObject` interface. The top-level `is(a, b)` function dispatches to the appropriate comparison. Anything that implements both methods becomes a `ValueObject` and can be used as a `Map`/`OrderedMap` key or a `Set`/`OrderedSet` member with value-equality semantics — so two structurally equal custom objects collapse to a single entry, and lookup works with any equivalent instance.
2
+
3
+ ## is
4
+
5
+ ### is
6
+
7
+ ```ts
8
+ is(first: unknown, second: unknown): boolean
9
+ ```
10
+
11
+ Value-equality check. Returns `true` for SameValue semantics (handles `NaN === NaN` as true), but unlike `Object.is` treats `0` and `-0` as equal (matching ES6 `Map` key equality). For `ValueObject` arguments dispatches to `first.equals(second)`. For primitives and non-`ValueObject` objects falls back to `Object.is`-style comparison.
12
+
13
+ ```js
14
+ import { Map, is } from 'immutable';
15
+ const a = Map({ x: 1, y: 2 });
16
+ const b = Map({ x: 1, y: 2 });
17
+ a !== b; // true — distinct instances
18
+ Object.is(a, b); // false
19
+ is(a, b); // true — value-equal
20
+ a.equals(b); // true — same as is(a, b)
21
+ ```
22
+
23
+ Used internally throughout Immutable.js for `Map` key equality, `Set` membership, `.includes()`, `.indexOf()`, etc.
24
+
25
+ ## hash
26
+
27
+ ### hash
28
+
29
+ ```ts
30
+ hash(value: unknown): number
31
+ ```
32
+
33
+ Returns a 31-bit integer hash for any value. For `ValueObject`s, calls `value.hashCode()`. For primitives (strings, numbers, booleans, `null`, `undefined`), produces a deterministic per-value hash. For plain objects, plain arrays, `Date`, etc. that don't implement `hashCode`, generates a unique per-instance hash and memoizes it on the object — so the hash represents referential identity (stable across mutations), not value equality.
34
+
35
+ Used internally by `Map`/`Set` for hash bucketing. Balances speed and collision avoidance; not cryptographically secure. _New in v4.0._
36
+
37
+ ## ValueObject
38
+
39
+ ### ValueObject
40
+
41
+ ```ts
42
+ interface ValueObject {
43
+ equals(other: unknown): boolean;
44
+ hashCode(): number;
45
+ }
46
+ ```
47
+
48
+ The interface to implement so a custom class behaves as a value: usable as a `Map`/`OrderedMap` key, in a `Set`/`OrderedSet`, and comparable via `is()`. All Immutable collections (`List`, `Map`, `Set`, `Record`, etc.) already implement it.
49
+
50
+ Contract:
51
+
52
+ - `a.equals(b) === true` MUST imply `a.hashCode() === b.hashCode()` (the converse is not required — hash collisions are allowed).
53
+ - `hashCode()` MUST return a Uint32. Idiomatic guard: `return myHash | 0`.
54
+ - `hashCode()` is not guaranteed to be called before `equals()`; lookups always verify via `equals()`.
55
+
56
+ ```js
57
+ import { Set, hash } from 'immutable';
58
+
59
+ class Point {
60
+ constructor(x, y) { this.x = x; this.y = y; }
61
+ equals(other) {
62
+ return other instanceof Point && other.x === this.x && other.y === this.y;
63
+ }
64
+ hashCode() {
65
+ return (hash(this.x) * 31 + hash(this.y)) | 0;
66
+ }
67
+ }
68
+
69
+ const s = Set([new Point(1, 2)]);
70
+ s.has(new Point(1, 2)); // true — different instance, value-equal
71
+ ```
72
+
73
+ ## isValueObject
74
+
75
+ ### isValueObject
76
+
77
+ ```ts
78
+ isValueObject(maybeValue: unknown): maybeValue is ValueObject
79
+ ```
80
+
81
+ Returns `true` iff `maybeValue` is a JavaScript object that has BOTH `equals` and `hashCode` methods. Any two value objects can be compared with `is()` and used as `Map` keys or `Set` members.
82
+
83
+ ## Reference identity vs value equality
84
+
85
+ - All Immutable collections implement `ValueObject`, so `is(a, b)` and `a.equals(b)` give value-equality.
86
+ - Persistent operations that don't change content return the SAME identity: `map.set('k', v)` where `map.get('k') === v` returns `map` itself (`===`). This makes `===` a valid fast-path for "definitely unchanged" — useful for `React.memo`, `shouldComponentUpdate`, and memoization.
87
+ - JavaScript's `===` between two distinct Immutable collections with equal content is `false`. This is intentional: cheap reference checks remain cheap, and value-equality is opt-in via `is()` / `.equals()`.
88
+ - Rule of thumb: use `===` to detect "this reference changed"; use `is()` / `.equals()` to ask "is the content the same?".
89
+
90
+ ## See also
91
+
92
+ - `map.md`, `set.md` — collections whose key/member identity is governed by `is`/`hashCode`.
93
+ - `record.md` — `Record` instances are `ValueObject`s, equal when their fields are value-equal.
94
+ - `predicates.md` — `isImmutable`, `isCollection`, etc. for runtime type checks.
95
+ - `conversions.md` — `fromJS`/`toJS` boundary where value identity is created/lost.
@@ -0,0 +1,266 @@
1
+ `List` is an ordered, indexed, dense, immutable collection — the Immutable.js analogue of a JavaScript Array. It is fully persistent with `O(log32 N)` `get`/`set` and `O(1)` `push`/`pop`, and it implements Deque (efficient `unshift`/`shift` as well). Reach for `List` when you need an ordered sequence keyed by integer index; prefer `Map` for keyed data, `Set`/`OrderedSet` for uniqueness, and `Stack` when you only push/pop one end and want amortised `O(1)` random access via head. Unlike a JS Array, `List` does not distinguish "unset" from `undefined`: `forEach` visits every index from `0` to `size`.
2
+
3
+ ## Construction
4
+
5
+ ```ts
6
+ import { List } from 'immutable';
7
+ ```
8
+
9
+ ### List / List.of / List.isList
10
+
11
+ ```ts
12
+ function List<T>(collection?: Iterable<T> | ArrayLike<T>): List<T>;
13
+ function List.of<T>(...values: Array<T>): List<T>;
14
+ function List.isList(maybeList: unknown): maybeList is List<unknown>;
15
+ ```
16
+
17
+ Factory function (no `new`). `List.of` is variadic; values are not converted. See also `predicates.md`.
18
+
19
+ ```js
20
+ List(); // => List []
21
+ List([1, 2, 3, 4]); // => List [ 1, 2, 3, 4 ]
22
+ List.of('a', 'b'); // => List [ "a", "b" ]
23
+ ```
24
+
25
+ ## Reading
26
+
27
+ ### size / get / has / includes (alias `contains`) / first / last / indexOf / lastIndexOf
28
+
29
+ ```ts
30
+ readonly size: number;
31
+ get(index: number): T | undefined;
32
+ get<NSV>(index: number, notSetValue: NSV): T | NSV;
33
+ has(index: number): boolean;
34
+ includes(value: T): boolean;
35
+ first<NSV = undefined>(notSetValue?: NSV): T | NSV;
36
+ last<NSV = undefined>(notSetValue?: NSV): T | NSV;
37
+ indexOf(value: T): number;
38
+ lastIndexOf(value: T): number;
39
+ ```
40
+
41
+ Negative indices on `get` count from the end (`get(-1)` is the last item). `includes` uses `Immutable.is` for equality. `indexOf`/`lastIndexOf` return `-1` if not found.
42
+
43
+ ### find / findLast / findIndex / findLastIndex / findEntry / findLastEntry / findKey / findLastKey
44
+
45
+ ```ts
46
+ find(predicate, context?, notSetValue?): T | undefined;
47
+ findLast(predicate, context?, notSetValue?): T | undefined;
48
+ findIndex(predicate, context?): number;
49
+ findLastIndex(predicate, context?): number;
50
+ findEntry(predicate, context?): [number, T] | undefined;
51
+ findLastEntry(predicate, context?): [number, T] | undefined;
52
+ findKey(predicate, context?): number | undefined;
53
+ findLastKey(predicate, context?): number | undefined;
54
+ ```
55
+
56
+ `predicate: (value: T, index: number, iter: this) => boolean`. `*Last` variants iterate in reverse.
57
+
58
+ ### keyOf / lastKeyOf / max / min / maxBy / minBy
59
+
60
+ ```ts
61
+ keyOf(searchValue: T): number | undefined;
62
+ lastKeyOf(searchValue: T): number | undefined;
63
+ max(comparator?: (a: T, b: T) => number): T | undefined;
64
+ min(comparator?: (a: T, b: T) => number): T | undefined;
65
+ maxBy<C>(mapper: (value: T, key: number, iter: this) => C, comparator?: (a: C, b: C) => number): T | undefined;
66
+ minBy<C>(mapper: (value: T, key: number, iter: this) => C, comparator?: (a: C, b: C) => number): T | undefined;
67
+ ```
68
+
69
+ ## Persistent changes
70
+
71
+ ### set
72
+
73
+ ```ts
74
+ set(index: number, value: T): List<T>;
75
+ ```
76
+
77
+ Negative `index` is allowed. Setting beyond `size` grows the List (gaps become `undefined`). `List().set(50000, 'v').size === 50001`.
78
+
79
+ ### delete (alias `remove`)
80
+
81
+ ```ts
82
+ delete(index: number): List<T>;
83
+ remove(index: number): List<T>;
84
+ ```
85
+
86
+ Re-indexes successors; `O(N)`. Cannot be used in `withMutations`.
87
+
88
+ ### insert
89
+
90
+ ```ts
91
+ insert(index: number, value: T): List<T>;
92
+ ```
93
+
94
+ Equivalent to `splice(index, 0, value)`. `O(N)`. Cannot be used in `withMutations`.
95
+
96
+ ### clear
97
+
98
+ ```ts
99
+ clear(): List<T>;
100
+ ```
101
+
102
+ ### push / pop / unshift / shift
103
+
104
+ ```ts
105
+ push(...values: Array<T>): List<T>;
106
+ pop(): List<T>;
107
+ unshift(...values: Array<T>): List<T>;
108
+ shift(): List<T>;
109
+ ```
110
+
111
+ `pop`/`shift` return the trimmed List, not the removed value (use `last()`/`first()`).
112
+
113
+ ### update
114
+
115
+ ```ts
116
+ update(index: number, notSetValue: T, updater: (value: T) => T): this;
117
+ update(index: number, updater: (value: T | undefined) => T | undefined): this;
118
+ update<R>(updater: (value: this) => R): R;
119
+ ```
120
+
121
+ The single-argument form is a "thru" / pipe: `list.update(sum)` calls `sum(list)`. See `shallow-functional.md`.
122
+
123
+ ### setSize
124
+
125
+ ```ts
126
+ setSize(size: number): List<T>;
127
+ ```
128
+
129
+ Truncates or pads with `undefined`. Pair with `withMutations` when the final size is known up front for faster construction.
130
+
131
+ ## Deep persistent changes
132
+
133
+ See `deep-updates.md` for full semantics, key-path conventions, and interaction with nested plain JS objects/arrays.
134
+
135
+ ### setIn / deleteIn (alias `removeIn`) / updateIn / mergeIn / mergeDeepIn
136
+
137
+ ```ts
138
+ setIn(keyPath: Iterable<unknown>, value: unknown): this;
139
+ deleteIn(keyPath: Iterable<unknown>): this;
140
+ removeIn(keyPath: Iterable<unknown>): this;
141
+ updateIn(keyPath: Iterable<unknown>, notSetValue: unknown, updater: (value: unknown) => unknown): this;
142
+ updateIn(keyPath: Iterable<unknown>, updater: (value: unknown) => unknown): this;
143
+ mergeIn(keyPath: Iterable<unknown>, ...collections: Array<unknown>): this;
144
+ mergeDeepIn(keyPath: Iterable<unknown>, ...collections: Array<unknown>): this;
145
+ ```
146
+
147
+ Numeric keys index into the List; string keys traverse nested Maps/objects. `deleteIn` cannot be used in `withMutations`; the others can.
148
+
149
+ ## Sequence algorithms
150
+
151
+ ### concat (alias `merge`) / map / flatMap
152
+
153
+ ```ts
154
+ concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): List<T | C>;
155
+ map<M>(mapper: (value: T, key: number, iter: this) => M, context?: unknown): List<M>;
156
+ flatMap<M>(mapper: (value: T, key: number, iter: this) => Iterable<M>, context?: unknown): List<M>;
157
+ ```
158
+
159
+ `flatMap` is equivalent to `list.map(...).flatten(true)`.
160
+
161
+ ### filter / filterNot / partition
162
+
163
+ ```ts
164
+ filter<F extends T>(predicate: (value: T, index: number, iter: this) => value is F, context?: unknown): List<F>;
165
+ filter(predicate: (value: T, index: number, iter: this) => unknown, context?: unknown): this;
166
+ filterNot(predicate: (value: T, index: number, iter: this) => boolean, context?: unknown): this;
167
+ partition<F extends T, C>(predicate: (this: C, value: T, index: number, iter: this) => value is F, context?: C): [List<T>, List<F>];
168
+ partition<C>(predicate: (this: C, value: T, index: number, iter: this) => unknown, context?: C): [this, this];
169
+ ```
170
+
171
+ `filter`/`filterNot` always return a new instance. `partition` returns `[falses, trues]`.
172
+
173
+ ### zip / zipAll / zipWith
174
+
175
+ ```ts
176
+ zip<U>(other: Collection<unknown, U>): List<[T, U]>;
177
+ zipAll<U>(other: Collection<unknown, U>): List<[T, U]>;
178
+ zipWith<U, Z>(zipper: (value: T, otherValue: U) => Z, otherCollection: Collection<unknown, U>): List<Z>;
179
+ ```
180
+
181
+ `zip` stops at the shortest input; `zipAll` pads shorter inputs with `undefined`.
182
+
183
+ ### slice / reverse / sort / sortBy / groupBy
184
+
185
+ ```ts
186
+ slice(begin?: number, end?: number): this;
187
+ reverse(): this;
188
+ sort(comparator?: (a: T, b: T) => PairSorting | number): this;
189
+ sortBy<C>(mapper: (value: T, key: number, iter: this) => C, comparator?: (a: C, b: C) => number): this;
190
+ groupBy<G>(grouper: (value: T, index: number, iter: this) => G, context?: unknown): Map<G, this>;
191
+ ```
192
+
193
+ `slice` accepts negative indices (inherited from `Collection.Indexed`). `sort`/`sortBy` are stable, eager, and always return a new instance. `groupBy` is also eager.
194
+
195
+ ### Other (inherited from `Collection.Indexed`)
196
+
197
+ `interpose(separator)`, `interleave(...collections)`, `splice(index, removeNum, ...values)`, `flatten(depth?)`, `shuffle(random?)`, `mapKeys`, `mapEntries`.
198
+
199
+ ## Conversion
200
+
201
+ See `conversions.md` for `toJS` deep-conversion rules and the relationship with `toJSON` / `JSON.stringify`.
202
+
203
+ ### toArray / toJS / toJSON
204
+
205
+ ```ts
206
+ toArray(): Array<T>; // shallow
207
+ toJS(): Array<DeepCopy<T>>; // deep — recursively unwraps nested Immutable collections
208
+ toJSON(): Array<T>; // shallow; called by JSON.stringify
209
+ ```
210
+
211
+ ### toSeq / toIndexedSeq / toKeyedSeq / toSetSeq
212
+
213
+ ```ts
214
+ toSeq(): Seq.Indexed<T>;
215
+ toIndexedSeq(): Seq.Indexed<T>;
216
+ toKeyedSeq(): Seq.Keyed<number, T>;
217
+ toSetSeq(): Seq.Set<T>;
218
+ ```
219
+
220
+ `toKeyedSeq` preserves `[index, value]` pairs through later filter/map.
221
+
222
+ ### asImmutable / asMutable
223
+
224
+ ```ts
225
+ asImmutable(): this;
226
+ asMutable(): this;
227
+ ```
228
+
229
+ See "Mutation batching".
230
+
231
+ ## Mutation batching
232
+
233
+ `withMutations` returns a transient mutable copy; once the callback returns, the result is frozen back into a regular persistent `List`. Useful when chaining many updates to avoid intermediate allocations.
234
+
235
+ ### withMutations
236
+
237
+ ```ts
238
+ withMutations(mutator: (mutable: this) => unknown): this;
239
+ ```
240
+
241
+ Not every method is safe inside the mutator — methods that re-index (`delete`, `insert`, `splice`, `interleave`, `deleteIn`) are unsafe. Each method's signature in this file notes whether it is safe.
242
+
243
+ ### asMutable / asImmutable
244
+
245
+ ```ts
246
+ asMutable(): this;
247
+ asImmutable(): this;
248
+ ```
249
+
250
+ Alternative to `withMutations` when you want explicit begin/end calls.
251
+
252
+ ### wasAltered
253
+
254
+ ```ts
255
+ wasAltered(): boolean;
256
+ ```
257
+
258
+ True if a transient mutation actually changed the collection.
259
+
260
+ ## See also
261
+
262
+ - `Collection.Indexed` for inherited iteration, search, and reduction methods (`forEach`, `reduce`, `every`, `some`, `count`, `keys`, `values`, `entries`, etc.)
263
+ - `deep-updates.md` for `setIn` / `updateIn` / `mergeIn` / `mergeDeepIn` semantics
264
+ - `shallow-functional.md` for `update`-as-pipe and other functional patterns
265
+ - `conversions.md` for `toJS` vs `toJSON` vs `toArray`
266
+ - `predicates.md` for `List.isList` and other type guards