tutuca 0.9.39 → 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 (88) hide show
  1. package/dist/tutuca-cli.js +92 -39
  2. package/dist/tutuca-dev.js +18 -0
  3. package/dist/tutuca-dev.min.js +1 -1
  4. package/package.json +6 -7
  5. package/skill/immutable-js/SKILL.md +79 -0
  6. package/skill/immutable-js/references/collection.md +346 -0
  7. package/skill/immutable-js/references/conversions.md +99 -0
  8. package/skill/immutable-js/references/deep-updates.md +172 -0
  9. package/skill/immutable-js/references/equality.md +95 -0
  10. package/skill/immutable-js/references/list.md +266 -0
  11. package/skill/immutable-js/references/map.md +300 -0
  12. package/skill/immutable-js/references/predicates.md +93 -0
  13. package/skill/immutable-js/references/range-repeat.md +55 -0
  14. package/skill/immutable-js/references/record.md +196 -0
  15. package/skill/immutable-js/references/seq.md +248 -0
  16. package/skill/immutable-js/references/set.md +270 -0
  17. package/skill/immutable-js/references/shallow-functional.md +99 -0
  18. package/skill/immutable-js/references/stack.md +210 -0
  19. package/skill/margaui/SKILL.md +101 -0
  20. package/skill/margaui/components/accordion.md +127 -0
  21. package/skill/margaui/components/alert.md +174 -0
  22. package/skill/margaui/components/avatar.md +220 -0
  23. package/skill/margaui/components/badge.md +193 -0
  24. package/skill/margaui/components/breadcrumbs.md +103 -0
  25. package/skill/margaui/components/button.md +322 -0
  26. package/skill/margaui/components/calendar.md +67 -0
  27. package/skill/margaui/components/card.md +373 -0
  28. package/skill/margaui/components/carousel.md +387 -0
  29. package/skill/margaui/components/chat.md +171 -0
  30. package/skill/margaui/components/checkbox.md +101 -0
  31. package/skill/margaui/components/collapse.md +172 -0
  32. package/skill/margaui/components/countdown.md +165 -0
  33. package/skill/margaui/components/diff.md +53 -0
  34. package/skill/margaui/components/divider.md +107 -0
  35. package/skill/margaui/components/dock.md +173 -0
  36. package/skill/margaui/components/drawer.md +184 -0
  37. package/skill/margaui/components/dropdown.md +388 -0
  38. package/skill/margaui/components/fab.md +346 -0
  39. package/skill/margaui/components/fieldset.md +88 -0
  40. package/skill/margaui/components/file-input.md +84 -0
  41. package/skill/margaui/components/filter.md +52 -0
  42. package/skill/margaui/components/footer.md +583 -0
  43. package/skill/margaui/components/hero.md +135 -0
  44. package/skill/margaui/components/hover-3d.md +129 -0
  45. package/skill/margaui/components/hover-gallery.md +49 -0
  46. package/skill/margaui/components/indicator.md +265 -0
  47. package/skill/margaui/components/input.md +389 -0
  48. package/skill/margaui/components/join.md +100 -0
  49. package/skill/margaui/components/kbd.md +127 -0
  50. package/skill/margaui/components/label.md +102 -0
  51. package/skill/margaui/components/link.md +96 -0
  52. package/skill/margaui/components/list.md +182 -0
  53. package/skill/margaui/components/loading.md +105 -0
  54. package/skill/margaui/components/mask.md +168 -0
  55. package/skill/margaui/components/menu.md +856 -0
  56. package/skill/margaui/components/mockup-browser.md +39 -0
  57. package/skill/margaui/components/mockup-code.md +81 -0
  58. package/skill/margaui/components/mockup-phone.md +39 -0
  59. package/skill/margaui/components/mockup-window.md +33 -0
  60. package/skill/margaui/components/modal.md +178 -0
  61. package/skill/margaui/components/navbar.md +282 -0
  62. package/skill/margaui/components/pagination.md +122 -0
  63. package/skill/margaui/components/progress.md +135 -0
  64. package/skill/margaui/components/radial-progress.md +67 -0
  65. package/skill/margaui/components/radio.md +133 -0
  66. package/skill/margaui/components/range.md +134 -0
  67. package/skill/margaui/components/rating.md +170 -0
  68. package/skill/margaui/components/select.md +225 -0
  69. package/skill/margaui/components/skeleton.md +64 -0
  70. package/skill/margaui/components/stack.md +142 -0
  71. package/skill/margaui/components/stat.md +254 -0
  72. package/skill/margaui/components/status.md +73 -0
  73. package/skill/margaui/components/steps.md +138 -0
  74. package/skill/margaui/components/swap.md +152 -0
  75. package/skill/margaui/components/tab.md +248 -0
  76. package/skill/margaui/components/table.md +1018 -0
  77. package/skill/margaui/components/text-rotate.md +91 -0
  78. package/skill/margaui/components/textarea.md +85 -0
  79. package/skill/margaui/components/theme-controller.md +266 -0
  80. package/skill/margaui/components/timeline.md +1356 -0
  81. package/skill/margaui/components/toast.md +165 -0
  82. package/skill/margaui/components/toggle.md +135 -0
  83. package/skill/margaui/components/tooltip.md +181 -0
  84. package/skill/margaui/components/validator.md +163 -0
  85. package/skill/{advanced.md → tutuca/advanced.md} +5 -0
  86. package/skill/{cli.md → tutuca/cli.md} +17 -0
  87. package/skill/{core.md → tutuca/core.md} +5 -0
  88. /package/skill/{SKILL.md → tutuca/SKILL.md} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tutuca",
3
- "version": "0.9.39",
3
+ "version": "0.9.41",
4
4
  "type": "module",
5
5
  "description": "Zero-dependency SPA framework with immutable state and virtual DOM",
6
6
  "main": "./dist/tutuca.js",
@@ -20,9 +20,11 @@
20
20
  "dist": "bun scripts/dist.js",
21
21
  "dist-immutable": "bun scripts/dist-immutable.js",
22
22
  "dist-all": "bun run dist-immutable && bun run dist",
23
- "release": "bun run dist-all && bun run build-skill && npm publish --access public",
24
- "release-dry": "bun run dist-all && bun run build-skill && npm publish --dry-run",
23
+ "release": "bun run dist-all && bun run build-skill && bun run build-margaui-skill && bun run build-immutable-skill && npm publish --access public",
24
+ "release-dry": "bun run dist-all && bun run build-skill && bun run build-margaui-skill && bun run build-immutable-skill && npm publish --dry-run",
25
25
  "build-skill": "bun scripts/build-skill.js",
26
+ "build-margaui-skill": "bun scripts/build-margaui-skill.js",
27
+ "build-immutable-skill": "bun scripts/build-immutable-skill.js",
26
28
  "test": "bun test test/*.test.js",
27
29
  "test-watch": "bun test --watch test/*.test.js",
28
30
  "format": "bunx @biomejs/biome format --write src test/*.js docs/src/*.js docs/examples/*.js tools/*.js tools/*/*.js",
@@ -42,10 +44,7 @@
42
44
  "dist/tutuca-extra.js",
43
45
  "dist/tutuca-extra.min.js",
44
46
  "dist/tutuca-cli.js",
45
- "skill/SKILL.md",
46
- "skill/core.md",
47
- "skill/cli.md",
48
- "skill/advanced.md"
47
+ "skill"
49
48
  ],
50
49
  "dependencies": {
51
50
  "jsdom": "^28.0.0 || ^29.0.0"
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: immutable-js
3
+ description: Reference for the Immutable.js API organized by datatype (List, Map, Set, OrderedMap, OrderedSet, Stack, Record, Seq, Collection, Range, Repeat) and by topic (deep updates, equality, type predicates, JS conversion). Use when the user asks how to use a specific Immutable.js datatype or method, when writing or reviewing code in this repository, or when explaining Immutable.js semantics like persistent updates, value equality, or lazy evaluation.
4
+ ---
5
+
6
+ # Immutable.js
7
+
8
+ Persistent immutable data structures for JavaScript. All operations return a
9
+ new collection rather than mutating the original; structural sharing keeps
10
+ this efficient. Treat collections as **values**, not objects — compare with
11
+ `is(a, b)` or `a.equals(b)`, never `===`.
12
+
13
+ ```js
14
+ import { Map } from 'immutable';
15
+ const m1 = Map({ a: 1, b: 2 });
16
+ const m2 = m1.set('b', 50);
17
+ m1.get('b'); // 2 — m1 is unchanged
18
+ m2.get('b'); // 50
19
+ ```
20
+
21
+ ## Inheritance cheatsheet
22
+
23
+ ```
24
+ Collection ─┬─ Collection.Keyed ─┬─ Map ── OrderedMap
25
+ │ └─ Record (object-like, fixed keys)
26
+
27
+ ├─ Collection.Indexed ─┬─ List
28
+ │ └─ Stack
29
+
30
+ └─ Collection.Set ─┬─ Set ── OrderedSet
31
+ └─ (OrderedCollection marker)
32
+
33
+ Seq mirrors the hierarchy lazily:
34
+ Seq ─┬─ Seq.Keyed ─ keyed lazy sequence
35
+ ├─ Seq.Indexed ─ indexed lazy sequence
36
+ └─ Seq.Set ─ set-like lazy sequence
37
+ ```
38
+
39
+ ## Datatypes
40
+
41
+ Read the reference for a specific datatype when answering questions about
42
+ its constructors, methods, or semantics.
43
+
44
+ - [List](references/list.md) — ordered indexed collection (push/pop/get/set/etc.)
45
+ - [Map](references/map.md) — keyed collection with value-equality keys; covers OrderedMap
46
+ - [Set](references/set.md) — unique values with value equality; covers OrderedSet
47
+ - [Stack](references/stack.md) — LIFO; fast push/pop/peek at the front
48
+ - [Record](references/record.md) — fixed-shape, named, typed record; class-like
49
+ - [Seq](references/seq.md) — lazy sequence (Keyed / Indexed / Set variants)
50
+ - [Collection](references/collection.md) — abstract base; methods shared by all collections
51
+ - [Range, Repeat](references/range-repeat.md) — lazy generator factories
52
+
53
+ ## Operations and topics
54
+
55
+ Cross-cutting topics. Load these alongside (or instead of) a datatype reference
56
+ when the question is about an operation rather than a single type.
57
+
58
+ - [Deep updates](references/deep-updates.md) — `getIn`, `setIn`, `updateIn`, `removeIn`, `hasIn`, `merge`, `mergeWith`, `mergeDeep`, `mergeDeepWith`
59
+ - [Shallow functional helpers](references/shallow-functional.md) — top-level `get`, `set`, `has`, `update`, `remove` that work on any collection or plain JS object
60
+ - [JS conversions](references/conversions.md) — `fromJS`, `toJS`, plain-JS interop, reviver patterns
61
+ - [Equality and hashing](references/equality.md) — `is`, `hash`, `ValueObject`, `isValueObject`, value vs reference semantics
62
+ - [Type predicates](references/predicates.md) — `isList`, `isMap`, `isSet`, `isOrderedMap`, `isOrderedSet`, `isStack`, `isRecord`, `isSeq`, `isCollection`, `isKeyed`, `isIndexed`, `isAssociative`, `isOrdered`, `isImmutable`
63
+
64
+ ## Cross-cutting semantics worth knowing up front
65
+
66
+ - **Value equality**: keys in `Map`/`Set` and elements in `Set` compare by `is()`, not `===`. Two distinct `Map({a:1})` instances are equal as keys.
67
+ - **Identity preservation**: an operation that produces an equal collection returns the original (`===`-identical), so memoization with `===` is sound.
68
+ - **Mutation batching**: `withMutations(c => { c.set(...).push(...) })` builds a transient copy; cheaper than chained calls when doing many updates.
69
+ - **Lazy `Seq`**: chained `map`/`filter`/etc. on a `Seq` doesn't run until something pulls values (e.g. `toList()`, `forEach`, iteration). See [seq.md](references/seq.md).
70
+ - **Path-based updates**: `setIn`/`updateIn`/`mergeDeep` create missing intermediate `Map`s by default. See [deep-updates.md](references/deep-updates.md).
71
+ - **`fromJS` is shallow-recursive**: arrays become `List`, plain objects become `Map`. Customize with the `reviver`. See [conversions.md](references/conversions.md).
72
+
73
+ ## Authoritative sources in this repo
74
+
75
+ When a reference here is ambiguous or you need an exact signature, fall back to:
76
+
77
+ - `type-definitions/immutable.d.ts` — canonical TypeScript signatures for the entire public API
78
+ - `website/docs/<Name>.mdx` — the original long-form docs each reference here distills
79
+ - `README.md` — top-level rationale and worked examples
@@ -0,0 +1,346 @@
1
+ `Collection<K, V>` is the abstract base interface for every immutable iterable in immutable-js. You never construct a `Collection` directly — you construct one of the concrete types (`List`, `Map`, `Set`, `Stack`, `Seq`, `Record`) and use the methods documented here, all of which they inherit. Three sub-interfaces tailor the iteration shape: `Collection.Keyed<K, V>` yields `[K, V]` tuples, `Collection.Indexed<T>` yields values in numeric-index order, and `Collection.Set<T>` yields values (value-unique on concrete `Set`/`OrderedSet`). The `Collection(...)` factory is also a conversion function: returns an existing `Collection` unchanged, wraps an array-like as `Collection.Indexed`, wraps a plain object as `Collection.Keyed<string, V>`.
2
+
3
+ ## Class hierarchy summary
4
+
5
+ ```
6
+ Collection
7
+ ├─ Collection.Keyed → Map, OrderedMap, Record (and Seq.Keyed)
8
+ ├─ Collection.Indexed → List, Stack (and Seq.Indexed)
9
+ └─ Collection.Set → Set, OrderedSet (and Seq.Set)
10
+ ```
11
+
12
+ `OrderedCollection<T>` is a marker interface (no own behaviour) mixed into every type with stable iteration order: `List`, `Stack`, `OrderedMap`, `OrderedSet`, every `Collection.Indexed`/`Seq.Indexed`, and any `Seq.Keyed` built from an ordered source. Detect at runtime with `isOrdered()`. There is no `OrderedCollection` value to construct.
13
+
14
+ ## Reading
15
+
16
+ ### size
17
+
18
+ ```ts
19
+ readonly size: number | undefined;
20
+ ```
21
+
22
+ Element count. Always defined on concrete types; may be `undefined` on a lazy `Seq` whose source has not been evaluated. Use `count()` for a guaranteed number.
23
+
24
+ ### get
25
+
26
+ ```ts
27
+ get(key: K): V | undefined;
28
+ get<NSV>(key: K, notSetValue: NSV): V | NSV;
29
+ ```
30
+
31
+ Returns the value for `key`, or `notSetValue` (or `undefined`) if absent. On `Collection.Indexed`, `key` is a numeric index and negative values count from the end (`get(-1)` is last). Because a stored value may itself be `undefined`, prefer the two-arg form to disambiguate "missing" from "set to undefined".
32
+
33
+ ### has / includes / contains
34
+
35
+ ```ts
36
+ has(key: K): boolean;
37
+ includes(value: V): boolean;
38
+ contains(value: V): boolean; // alias of includes
39
+ ```
40
+
41
+ `has` checks key membership; `includes`/`contains` check value membership. Both use `Immutable.is` (deep value equality).
42
+
43
+ ### first / last
44
+
45
+ ```ts
46
+ first(): V | undefined;
47
+ first<NSV>(notSetValue: NSV): V | NSV;
48
+ last(): V | undefined;
49
+ last<NSV>(notSetValue: NSV): V | NSV;
50
+ ```
51
+
52
+ First/last value in iteration order, or the optional default if empty.
53
+
54
+ ### getIn / hasIn
55
+
56
+ ```ts
57
+ getIn(searchKeyPath: Iterable<unknown>, notSetValue?: unknown): unknown;
58
+ hasIn(searchKeyPath: Iterable<unknown>): boolean;
59
+ ```
60
+
61
+ Walk a path of keys/indices through nested Immutable collections (and plain JS objects/arrays). See `nested-updates.md`.
62
+
63
+ ## Sequence algorithms (return same kind of collection)
64
+
65
+ Most return a Collection of the same variant (`this`-typed where possible). For `Map`/`Set`, sorting/reversing returns the ordered counterpart (`OrderedMap`/`OrderedSet`).
66
+
67
+ ### map / flatMap
68
+
69
+ ```ts
70
+ map<M>(mapper: (value: V, key: K, iter: this) => M, context?: unknown): Collection<K, M>;
71
+ flatMap<M>(mapper: (value: V, key: K, iter: this) => Iterable<M>, context?: unknown): Collection<K, M>;
72
+ flatMap<KM, VM>(mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>, context?: unknown): Collection<KM, VM>;
73
+ ```
74
+
75
+ Always returns a new instance. `flatMap` is `map(...).flatten(true)`. On `Collection.Set` callbacks, `key === value`.
76
+
77
+ ### filter / filterNot
78
+
79
+ ```ts
80
+ filter(predicate: (value: V, key: K, iter: this) => unknown, context?: unknown): this;
81
+ filter<F extends V>(predicate: (value: V, key: K, iter: this) => value is F, context?: unknown): Collection<K, F>;
82
+ filterNot(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): this;
83
+ ```
84
+
85
+ `filter` keeps truthy entries; `filterNot` keeps falsy ones. Type guards narrow the result.
86
+
87
+ ### reverse / sort / sortBy
88
+
89
+ ```ts
90
+ reverse(): this;
91
+ sort(comparator?: Comparator<V>): this;
92
+ sortBy<C>(mapper: (value: V, key: K, iter: this) => C, comparator?: Comparator<C>): this;
93
+ ```
94
+
95
+ `comparator(a, b)` returns negative/zero/positive (or a `PairSorting` enum value) and must be pure. Sort is stable. On unordered collections (`Map`, `Set`), the result is the ordered counterpart. Always eager.
96
+
97
+ ### slice / rest / butLast
98
+
99
+ ```ts
100
+ slice(begin?: number, end?: number): this;
101
+ rest(): this; // all but first
102
+ butLast(): this; // all but last
103
+ ```
104
+
105
+ Negative slice indices count from the end. Returns the same instance if the slice is the whole collection.
106
+
107
+ ### skip / skipLast / skipWhile / skipUntil / take / takeLast / takeWhile / takeUntil
108
+
109
+ ```ts
110
+ skip(amount: number): this;
111
+ skipLast(amount: number): this;
112
+ skipWhile(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): this;
113
+ skipUntil(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): this;
114
+ take(amount: number): this;
115
+ takeLast(amount: number): this;
116
+ takeWhile(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): this;
117
+ takeUntil(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): this;
118
+ ```
119
+
120
+ `*While` keeps taking/skipping while predicate is true; `*Until` until it becomes true.
121
+
122
+ ### concat / flatten
123
+
124
+ ```ts
125
+ concat(...valuesOrCollections: Array<unknown>): Collection<unknown, unknown>;
126
+ flatten(depth?: number): Collection<unknown, unknown>;
127
+ flatten(shallow?: boolean): Collection<unknown, unknown>;
128
+ ```
129
+
130
+ Concrete variants narrow `concat`'s return type — see the per-variant sections below. `flatten()` (no args) flattens deeply; `flatten(true)` flattens one level; `flatten(0)` flattens deeply. Only flattens nested Immutable Collections, not arrays/objects.
131
+
132
+ ### groupBy / partition
133
+
134
+ ```ts
135
+ groupBy<G>(grouper: (value: V, key: K, iter: this) => G, context?: unknown): Map<G, this>;
136
+ partition(predicate, context?): [this, this]; // [falsy, truthy]
137
+ partition<F extends V, C>(predicate: (...) => value is F, context?: C): [Collection<K, V>, Collection<K, F>];
138
+ ```
139
+
140
+ `groupBy` is eager and returns a `Map` of group key → Collection of the same variant. `partition` returns `[notMatching, matching]` in one pass.
141
+
142
+ ## Side effects and reductions
143
+
144
+ ### forEach
145
+
146
+ ```ts
147
+ forEach(sideEffect: (value: V, key: K, iter: this) => unknown, context?: unknown): number;
148
+ ```
149
+
150
+ Returns the number of iterations executed. Unlike `Array#forEach`, returning `false` from `sideEffect` aborts iteration.
151
+
152
+ ### reduce / reduceRight
153
+
154
+ ```ts
155
+ reduce<R>(reducer: (acc: R, value: V, key: K, iter: this) => R, initialReduction: R, context?: unknown): R;
156
+ reduce<R>(reducer): R; // first item is the initial reduction
157
+ reduceRight<R>(reducer, initialReduction: R, context?: unknown): R;
158
+ reduceRight<R>(reducer): R;
159
+ ```
160
+
161
+ `reduceRight` is `reverse().reduce(...)`.
162
+
163
+ ### every / some / find* / keyOf*
164
+
165
+ ```ts
166
+ every(predicate, context?: unknown): boolean;
167
+ some(predicate, context?: unknown): boolean;
168
+
169
+ find(predicate, context?, notSetValue?: V): V | undefined;
170
+ findLast(predicate, context?, notSetValue?: V): V | undefined;
171
+ findEntry(predicate, context?, notSetValue?: V): [K, V] | undefined;
172
+ findLastEntry(predicate, context?, notSetValue?: V): [K, V] | undefined;
173
+ findKey(predicate, context?): K | undefined;
174
+ findLastKey(predicate, context?): K | undefined;
175
+
176
+ keyOf(searchValue: V): K | undefined;
177
+ lastKeyOf(searchValue: V): K | undefined;
178
+ ```
179
+
180
+ `*Last` variants iterate in reverse. `keyOf`/`lastKeyOf` look up by `Immutable.is` value equality; on `Collection.Indexed` prefer `indexOf`/`lastIndexOf` for clarity.
181
+
182
+ ### max / maxBy / min / minBy
183
+
184
+ ```ts
185
+ max(comparator?: Comparator<V>): V | undefined;
186
+ maxBy<C>(mapper: (value, key, iter) => C, comparator?: Comparator<C>): V | undefined;
187
+ min(comparator?: Comparator<V>): V | undefined;
188
+ minBy<C>(mapper: (value, key, iter) => C, comparator?: Comparator<C>): V | undefined;
189
+ ```
190
+
191
+ Default comparator is `>` / `<`. On ties, the first encountered wins.
192
+
193
+ ### count / countBy / isEmpty / join
194
+
195
+ ```ts
196
+ count(): number;
197
+ count(predicate, context?): number;
198
+ countBy<G>(grouper, context?): Map<G, number>;
199
+ isEmpty(): boolean;
200
+ join(separator?: string): string; // default ","
201
+ ```
202
+
203
+ `count()` always returns the actual size, even for a lazy `Seq` (forcing evaluation). `isEmpty` may iterate at most once on a lazy `Seq`.
204
+
205
+ ### isSubset / isSuperset
206
+
207
+ ```ts
208
+ isSubset(iter: Iterable<V>): boolean; // every value in this is in iter
209
+ isSuperset(iter: Iterable<V>): boolean; // every value in iter is in this
210
+ ```
211
+
212
+ ## Conversion
213
+
214
+ ```ts
215
+ toArray(): Array<V> | Array<[K, V]>;
216
+ toObject(): { [key: string]: V };
217
+ toJS(): Array<DeepCopy<V>> | { [key: PropertyKey]: DeepCopy<V> };
218
+ toJSON(): Array<V> | { [key: PropertyKey]: V };
219
+
220
+ toList(): List<V>;
221
+ toMap(): Map<K, V>;
222
+ toOrderedMap(): OrderedMap<K, V>;
223
+ toSet(): Set<V>;
224
+ toOrderedSet(): OrderedSet<V>;
225
+ toStack(): Stack<V>;
226
+
227
+ toSeq(): Seq<K, V>;
228
+ toKeyedSeq(): Seq.Keyed<K, V>;
229
+ toIndexedSeq(): Seq.Indexed<V>;
230
+ toSetSeq(): Seq.Set<V>;
231
+ ```
232
+
233
+ `toJS` is deep (recursively converts nested Immutable structures); `toJSON`/`toArray`/`toObject` are shallow. `Collection.Keyed#toArray` returns `Array<[K, V]>`; `Collection.Indexed`/`Collection.Set#toArray` return `Array<V>`. `to{List,Set,OrderedSet,Stack}` discard keys; `toMap`/`toOrderedMap` throw if keys are not hashable. See `conversions.md`.
234
+
235
+ ## Comparison
236
+
237
+ ```ts
238
+ equals(other: unknown): boolean;
239
+ hashCode(): number;
240
+ ```
241
+
242
+ `equals` is `Immutable.is(this, other)` — deep value equality. `hashCode` is a stable Uint32; equal collections must produce equal hashes. See `equality.md`.
243
+
244
+ ## Iteration
245
+
246
+ ```ts
247
+ keys(): IterableIterator<K>;
248
+ values(): IterableIterator<V>;
249
+ entries(): IterableIterator<[K, V]>;
250
+ [Symbol.iterator](): IterableIterator<unknown>;
251
+
252
+ keySeq(): Seq.Indexed<K>;
253
+ valueSeq(): Seq.Indexed<V>;
254
+ entrySeq(): Seq.Indexed<[K, V]>;
255
+ ```
256
+
257
+ Default iteration shape per variant: `Keyed` yields `[K, V]` tuples; `Indexed` yields `V` in index order; `Set` yields `V` (value-unique on concrete `Set`). The `keys()`/`values()`/`entries()` methods return ES iterators (no chainable Immutable methods); `keySeq()`/`valueSeq()`/`entrySeq()` return `Seq.Indexed`s that you can chain.
258
+
259
+ ### update
260
+
261
+ ```ts
262
+ update<R>(updater: (value: this) => R): R;
263
+ ```
264
+
265
+ Pipe the collection through a function — useful for chaining (`coll.update(fn).map(...)`). RxJS calls this `let`, lodash calls it `thru`.
266
+
267
+ ## Variant-specific methods
268
+
269
+ ### Collection.Keyed
270
+
271
+ ```ts
272
+ flip(): Collection.Keyed<V, K>;
273
+ mapKeys<M>(mapper: (key: K, value: V, iter: this) => M, context?: unknown): Collection.Keyed<M, V>;
274
+ mapEntries<KM, VM>(
275
+ mapper: (entry: [K, V], index: number, iter: this) => [KM, VM] | undefined,
276
+ context?: unknown,
277
+ ): Collection.Keyed<KM, VM>;
278
+
279
+ concat<KC, VC>(...collections: Array<Iterable<[KC, VC]>>): Collection.Keyed<K | KC, V | VC>;
280
+ concat<C>(...collections: Array<{ [key: string]: C }>): Collection.Keyed<K | string, V | C>;
281
+ ```
282
+
283
+ `flip` swaps keys and values. `mapEntries` may return `undefined` to drop that entry. Inherited `keyOf` returns the key associated with a value (not an index). When iterated, yields `[K, V]`.
284
+
285
+ ### Collection.Indexed
286
+
287
+ Indices are 0-based and dense ("unset" and `undefined` are indistinguishable; iteration visits every index `0..size`). Negative indices count from the end.
288
+
289
+ ```ts
290
+ indexOf(searchValue: T): number; // -1 if absent
291
+ lastIndexOf(searchValue: T): number;
292
+ findIndex(predicate, context?): number;
293
+ findLastIndex(predicate, context?): number;
294
+
295
+ interpose(separator: T): this; // T, sep, T, sep, T
296
+ interleave(...collections: Array<Collection<unknown, T>>): this; // round-robin; stops at shortest
297
+ splice(index: number, removeNum: number, ...values: Array<T>): this;
298
+
299
+ zip<U>(other: Collection<unknown, U>): Collection.Indexed<[T, U]>;
300
+ zip(...collections): Collection.Indexed<unknown>;
301
+ zipAll<U>(other: Collection<unknown, U>): Collection.Indexed<[T, U]>; // pads shorter with undefined
302
+ zipWith<U, Z>(zipper: (value: T, otherValue: U) => Z, other: Collection<unknown, U>): Collection.Indexed<Z>;
303
+
304
+ concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): Collection.Indexed<T | C>;
305
+ fromEntrySeq(): Seq.Keyed<unknown, unknown>; // when T is [K, V], reinterpret as keyed
306
+ ```
307
+
308
+ `splice`, `interleave`, and other reindexing operations are `O(N)` and cannot be used inside `withMutations`. All `Collection.Indexed` methods return re-indexed Collections — to preserve original indices as keys, call `toKeyedSeq()`.
309
+
310
+ ### Collection.Set
311
+
312
+ Iterates values; on the concrete `Set`/`OrderedSet`, values are unique (`Immutable.is`). On lazy `Seq.Set`, duplicates may be present. In callbacks, `key === value`.
313
+
314
+ ```ts
315
+ concat<U>(...collections: Array<Iterable<U>>): Collection.Set<T | U>;
316
+ map<M>(mapper: (value: T, key: T, iter: this) => M, context?: unknown): Collection.Set<M>;
317
+ flatMap<M>(mapper: (value: T, key: T, iter: this) => Iterable<M>, context?: unknown): Collection.Set<M>;
318
+ filter<F extends T>(predicate: (value: T, key: T, iter: this) => value is F, context?: unknown): Collection.Set<F>;
319
+ filter(predicate, context?): this;
320
+ partition(predicate, context?): [this, this];
321
+ ```
322
+
323
+ `union`, `intersect`, and `subtract` are NOT on `Collection.Set` — they live on the concrete `Set`/`OrderedSet`. See `set.md`.
324
+
325
+ ## OrderedCollection
326
+
327
+ `OrderedCollection<T>` is a marker interface — it adds nothing beyond `toArray()` and `[Symbol.iterator]()` that every collection already has. Its purpose is purely type-level: it identifies collections whose iteration order is deterministic and stable across operations.
328
+
329
+ Implementers: `List`, `Stack`, `OrderedMap`, `OrderedSet`, every `Collection.Indexed` (so every `Seq.Indexed`), and any `Seq.Keyed` constructed from an ordered source. `Map` and `Set` are NOT ordered. Detect at runtime:
330
+
331
+ ```ts
332
+ function isOrdered<T>(maybeOrdered: Collection<unknown, T>): maybeOrdered is OrderedCollection<T>;
333
+ function isOrdered(maybeOrdered: unknown): maybeOrdered is OrderedCollection<unknown>;
334
+ ```
335
+
336
+ `KeyPath<K>` (used by `getIn`/`setIn`/etc.) is typed as `OrderedCollection<K> | ArrayLike<K>` — so any ordered Collection is a valid key path.
337
+
338
+ ## See also
339
+
340
+ - `list.md`, `stack.md` — concrete `Collection.Indexed` types
341
+ - `map.md`, `record.md` — concrete `Collection.Keyed` types
342
+ - `set.md` — concrete `Collection.Set` types (`union`/`intersect`/`subtract` live here)
343
+ - `seq.md` — lazy `Seq.Keyed`/`Seq.Indexed`/`Seq.Set`
344
+ - `equality.md` — `equals`, `hashCode`, `Immutable.is`
345
+ - `conversions.md` — `toJS`/`fromJS`, `toArray`, cross-type `to*`
346
+ - `predicates.md` — `isCollection`, `isOrdered`, `isKeyed`, etc.
@@ -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).