atom.io 0.29.0 → 0.29.2

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 (37) hide show
  1. package/dist/{chunk-XPYU2HY2.js → chunk-J4B56MM5.js} +36 -9
  2. package/dist/index.d.ts +15 -15
  3. package/ephemeral/dist/index.d.ts +6 -6
  4. package/ephemeral/src/find-state.ts +6 -6
  5. package/immortal/dist/index.d.ts +6 -6
  6. package/immortal/src/seek-state.ts +6 -6
  7. package/internal/dist/index.d.ts +27 -26
  8. package/internal/dist/index.js +1 -1
  9. package/internal/src/families/dispose-from-store.ts +1 -1
  10. package/internal/src/families/find-in-store.ts +8 -8
  11. package/internal/src/families/get-family-of-token.ts +64 -0
  12. package/internal/src/families/init-family-member.ts +9 -10
  13. package/internal/src/families/seek-in-store.ts +8 -8
  14. package/internal/src/future.ts +4 -0
  15. package/internal/src/get-state/get-from-store.ts +17 -4
  16. package/internal/src/set-state/set-into-store.ts +13 -5
  17. package/json/dist/index.d.ts +3 -3
  18. package/json/dist/index.js +1 -1
  19. package/json/src/entries.ts +1 -1
  20. package/json/src/index.ts +13 -1
  21. package/package.json +15 -15
  22. package/react-devtools/dist/index.css +2 -2
  23. package/react-devtools/dist/index.js +14 -11
  24. package/react-devtools/src/StateIndex.tsx +4 -4
  25. package/react-devtools/src/TimelineIndex.tsx +2 -2
  26. package/react-devtools/src/TransactionIndex.tsx +2 -2
  27. package/react-devtools/src/devtools.scss +2 -2
  28. package/react-devtools/src/elastic-input/NumberInput.tsx +8 -7
  29. package/react-devtools/src/elastic-input/TextInput.tsx +6 -2
  30. package/realtime-server/dist/index.d.ts +8 -10
  31. package/realtime-server/src/ipc-sockets/child-socket.ts +1 -5
  32. package/realtime-server/src/ipc-sockets/custom-socket.ts +7 -7
  33. package/realtime-server/src/ipc-sockets/parent-socket.ts +4 -4
  34. package/realtime-server/src/realtime-continuity-synchronizer.ts +1 -1
  35. package/src/index.ts +25 -17
  36. package/transceivers/set-rtx/dist/index.js +5 -5
  37. package/transceivers/set-rtx/src/set-rtx.ts +6 -6
@@ -37,49 +37,49 @@ export function seekInStore<
37
37
  store: Store,
38
38
  token: MutableAtomFamilyToken<T, J, K>,
39
39
  key: Key,
40
- ): MutableAtomToken<T, J> | undefined
40
+ ): MutableAtomToken<T, J, K> | undefined
41
41
 
42
42
  export function seekInStore<T, K extends Canonical, Key extends K>(
43
43
  store: Store,
44
44
  token: RegularAtomFamilyToken<T, K>,
45
45
  key: Key,
46
- ): RegularAtomToken<T> | undefined
46
+ ): RegularAtomToken<T, K> | undefined
47
47
 
48
48
  export function seekInStore<T, K extends Canonical, Key extends K>(
49
49
  store: Store,
50
50
  token: AtomFamilyToken<T, K>,
51
51
  key: Key,
52
- ): AtomToken<T> | undefined
52
+ ): AtomToken<T, K> | undefined
53
53
 
54
54
  export function seekInStore<T, K extends Canonical, Key extends K>(
55
55
  store: Store,
56
56
  token: WritableSelectorFamilyToken<T, K>,
57
57
  key: Key,
58
- ): WritableSelectorToken<T> | undefined
58
+ ): WritableSelectorToken<T, K> | undefined
59
59
 
60
60
  export function seekInStore<T, K extends Canonical, Key extends K>(
61
61
  store: Store,
62
62
  token: ReadonlySelectorFamilyToken<T, K>,
63
63
  key: Key,
64
- ): ReadonlySelectorToken<T> | undefined
64
+ ): ReadonlySelectorToken<T, K> | undefined
65
65
 
66
66
  export function seekInStore<T, K extends Canonical, Key extends K>(
67
67
  store: Store,
68
68
  token: SelectorFamilyToken<T, K>,
69
69
  key: Key,
70
- ): SelectorToken<T> | undefined
70
+ ): SelectorToken<T, K> | undefined
71
71
 
72
72
  export function seekInStore<T, K extends Canonical, Key extends K>(
73
73
  store: Store,
74
74
  token: WritableFamilyToken<T, K>,
75
75
  key: Key,
76
- ): WritableToken<T> | undefined
76
+ ): WritableToken<T, K> | undefined
77
77
 
78
78
  export function seekInStore<T, K extends Canonical, Key extends K>(
79
79
  store: Store,
80
80
  token: ReadableFamilyToken<T, K>,
81
81
  key: Key,
82
- ): ReadableToken<T> | undefined
82
+ ): ReadableToken<T, K> | undefined
83
83
 
84
84
  export function seekInStore<M extends MoleculeConstructor>(
85
85
  store: Store,
@@ -12,6 +12,8 @@ export class Future<T> extends Promise<T> {
12
12
  private resolve: (value: T) => void
13
13
  private reject: (reason?: any) => void
14
14
 
15
+ public done = false
16
+
15
17
  public constructor(
16
18
  executor:
17
19
  | Promise<T>
@@ -31,11 +33,13 @@ export class Future<T> extends Promise<T> {
31
33
  private pass(promise: Promise<T>, value: T) {
32
34
  if (promise === this.fate) {
33
35
  this.resolve(value)
36
+ this.done = true
34
37
  }
35
38
  }
36
39
  private fail(promise: Promise<T>, reason: any) {
37
40
  if (promise === this.fate) {
38
41
  this.reject(reason)
42
+ this.done = true
39
43
  }
40
44
  }
41
45
 
@@ -6,9 +6,10 @@ import type {
6
6
  ReadableFamilyToken,
7
7
  ReadableToken,
8
8
  } from "atom.io"
9
- import { type Canonical, stringifyJson } from "atom.io/json"
9
+ import { type Canonical, parseJson } from "atom.io/json"
10
10
 
11
11
  import { findInStore, seekInStore } from "../families"
12
+ import { getFamilyOfToken } from "../families/get-family-of-token"
12
13
  import { NotFoundError } from "../not-found-error"
13
14
  import type { Store } from "../store"
14
15
  import { counterfeit, withdraw } from "../store"
@@ -58,11 +59,23 @@ export function getFromStore(
58
59
  | [token: ReadableToken<any>]
59
60
  ): any {
60
61
  let token: MoleculeToken<any> | ReadableToken<any>
62
+ let family:
63
+ | MoleculeFamilyToken<any>
64
+ | ReadableFamilyToken<any, Canonical>
65
+ | null
66
+ let key: Canonical | null
61
67
  if (params.length === 1) {
62
68
  token = params[0]
69
+ if (token.type !== `molecule`) {
70
+ family = getFamilyOfToken(store, token) ?? null
71
+ if (family) {
72
+ key = token.family ? parseJson(token.family.subKey) : null
73
+ token = findInStore(store, family, key)
74
+ }
75
+ }
63
76
  } else {
64
- const family = params[0]
65
- const key = params[1]
77
+ family = params[0]
78
+ key = params[1]
66
79
  let maybeToken: MoleculeToken<any> | ReadableToken<any>
67
80
  if (family.type === `molecule_family`) {
68
81
  maybeToken = seekInStore(store, family, key) ?? counterfeit(family, key)
@@ -72,7 +85,7 @@ export function getFromStore(
72
85
  token = maybeToken
73
86
  }
74
87
  if (`counterfeit` in token && `family` in token) {
75
- const family =
88
+ family =
76
89
  token.type === `molecule`
77
90
  ? withdraw(token.family, store)
78
91
  : // biome-ignore lint/style/noNonNullAssertion: family must be present
@@ -1,7 +1,8 @@
1
1
  import type { WritableFamilyToken, WritableToken } from "atom.io"
2
- import { type Canonical, stringifyJson } from "atom.io/json"
2
+ import { type Canonical, parseJson, stringifyJson } from "atom.io/json"
3
3
 
4
4
  import { findInStore } from "../families"
5
+ import { getFamilyOfToken } from "../families/get-family-of-token"
5
6
  import { closeOperation, openOperation } from "../operation"
6
7
  import type { Store } from "../store"
7
8
  import { withdraw } from "../store"
@@ -31,17 +32,24 @@ export function setIntoStore<T, New extends T>(
31
32
  | [token: WritableToken<T>, value: New | ((oldValue: T) => New)]
32
33
  ): void {
33
34
  let token: WritableToken<T>
35
+ let family: WritableFamilyToken<T, Canonical> | null
36
+ let key: Canonical | null
34
37
  let value: New | ((oldValue: T) => New)
35
38
  if (params.length === 2) {
36
39
  token = params[0]
37
40
  value = params[1]
41
+ family = getFamilyOfToken(store, token) ?? null
42
+ if (family) {
43
+ key = token.family ? parseJson(token.family.subKey) : null
44
+ token = findInStore(store, family, key)
45
+ }
38
46
  } else {
39
- const family = params[0]
40
- const key = params[1]
47
+ family = params[0]
48
+ key = params[1]
41
49
  value = params[2]
42
- const maybeToken = findInStore(store, family, key)
43
- token = maybeToken
50
+ token = findInStore(store, family, key)
44
51
  }
52
+
45
53
  if (`counterfeit` in token) {
46
54
  const disposal = store.disposalTraces.buffer.find(
47
55
  (item) => item?.key === token.key,
@@ -1,7 +1,7 @@
1
1
  import { Range, Flat, Store, Transceiver } from 'atom.io/internal';
2
2
  import * as AtomIO from 'atom.io';
3
3
 
4
- type Entries<K extends keyof any = keyof any, V = any> = [K, V][];
4
+ type Entries<K extends PropertyKey = keyof any, V = any> = [K, V][];
5
5
  type KeyOfEntries<E extends Entries> = E extends [infer K, any][] ? K : never;
6
6
  type ValueOfEntry<E extends Entries, K extends KeyOfEntries<E>> = {
7
7
  [P in Range<E[`length`]>]: E[P] extends [K, infer V] ? V : never;
@@ -32,8 +32,8 @@ declare namespace Json {
32
32
  type Object<Key extends string = string, Value extends Serializable = Serializable> = Record<Key, Value>;
33
33
  type Array<Element extends Serializable = Serializable> = ReadonlyArray<Element>;
34
34
  }
35
- type stringified<J extends Json.Serializable> = string & {
36
- __json: J;
35
+ type stringified<J extends Json.Serializable> = J extends string ? `"${J}"` : J extends number ? `${J}` : J extends true ? `true` : J extends false ? `false` : J extends boolean ? `false` | `true` : J extends null ? `null` : string & {
36
+ __json?: J;
37
37
  };
38
38
  declare const parseJson: <S extends stringified<Json.Serializable>>(str: S | string) => S extends stringified<infer J> ? J : Json.Serializable;
39
39
  declare const stringifyJson: <J extends Json.Serializable>(json: J) => stringified<J>;
@@ -1,4 +1,4 @@
1
- import { createWritableSelectorFamily } from '../../dist/chunk-XPYU2HY2.js';
1
+ import { createWritableSelectorFamily } from '../../dist/chunk-J4B56MM5.js';
2
2
  import '../../dist/chunk-IBTHB2PI.js';
3
3
  import '../../dist/chunk-XWL6SNVU.js';
4
4
  import { createStandaloneSelector, IMPLICIT, growMoleculeInStore, initFamilyMemberInStore, withdraw, seekInStore } from 'atom.io/internal';
@@ -1,6 +1,6 @@
1
1
  import type { Flat, Range } from "atom.io/internal"
2
2
 
3
- export type Entries<K extends keyof any = keyof any, V = any> = [K, V][]
3
+ export type Entries<K extends PropertyKey = keyof any, V = any> = [K, V][]
4
4
 
5
5
  export type KeyOfEntries<E extends Entries> = E extends [infer K, any][]
6
6
  ? K
package/json/src/index.ts CHANGED
@@ -27,7 +27,19 @@ export namespace Json {
27
27
  ReadonlyArray<Element>
28
28
  }
29
29
 
30
- export type stringified<J extends Json.Serializable> = string & { __json: J }
30
+ export type stringified<J extends Json.Serializable> = J extends string
31
+ ? `"${J}"`
32
+ : J extends number
33
+ ? `${J}`
34
+ : J extends true
35
+ ? `true`
36
+ : J extends false
37
+ ? `false`
38
+ : J extends boolean
39
+ ? `false` | `true`
40
+ : J extends null
41
+ ? `null`
42
+ : string & { __json?: J }
31
43
 
32
44
  export const parseJson = <S extends stringified<Json.Serializable>>(
33
45
  str: S | string,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atom.io",
3
- "version": "0.29.0",
3
+ "version": "0.29.2",
4
4
  "description": "Composable and testable reactive data library.",
5
5
  "homepage": "https://atom.io.fyi",
6
6
  "sideEffects": false,
@@ -59,32 +59,32 @@
59
59
  "@types/npmlog": "7.0.0",
60
60
  "@types/react": "18.3.5",
61
61
  "@types/tmp": "0.2.6",
62
- "@typescript-eslint/parser": "8.4.0",
63
- "@typescript-eslint/rule-tester": "8.4.0",
64
- "@vitest/coverage-v8": "2.0.5",
65
- "@vitest/ui": "2.0.5",
66
- "concurrently": "8.2.2",
62
+ "@typescript-eslint/parser": "8.5.0",
63
+ "@typescript-eslint/rule-tester": "8.5.0",
64
+ "@vitest/coverage-v8": "2.1.1",
65
+ "@vitest/ui": "2.1.1",
66
+ "concurrently": "9.0.1",
67
67
  "drizzle-kit": "0.24.2",
68
68
  "drizzle-orm": "0.33.0",
69
- "eslint": "9.9.1",
70
- "framer-motion": "11.5.2",
71
- "happy-dom": "15.7.3",
69
+ "eslint": "9.10.0",
70
+ "framer-motion": "11.5.4",
71
+ "happy-dom": "15.7.4",
72
72
  "http-proxy": "1.18.1",
73
73
  "npmlog": "7.0.1",
74
74
  "postgres": "3.4.4",
75
- "preact": "10.23.2",
75
+ "preact": "10.24.0",
76
76
  "react": "18.3.1",
77
77
  "react-dom": "18.3.1",
78
- "react-router-dom": "6.26.1",
78
+ "react-router-dom": "6.26.2",
79
79
  "socket.io": "4.7.5",
80
80
  "socket.io-client": "4.7.5",
81
81
  "tmp": "0.2.3",
82
82
  "tsup": "8.2.4",
83
- "tsx": "4.19.0",
84
- "typescript": "5.5.4",
85
- "vite": "5.4.3",
83
+ "tsx": "4.19.1",
84
+ "typescript": "5.6.2",
85
+ "vite": "5.4.5",
86
86
  "vite-tsconfig-paths": "5.0.1",
87
- "vitest": "2.0.5"
87
+ "vitest": "2.1.1"
88
88
  },
89
89
  "main": "dist/index.js",
90
90
  "types": "dist/index.d.ts",
@@ -108,7 +108,7 @@ main.atom_io_devtools {
108
108
  cursor: default;
109
109
  }
110
110
  }
111
- label {
111
+ > main {
112
112
  display: flex;
113
113
  flex-flow: row;
114
114
  gap: 5px;
@@ -186,7 +186,7 @@ main.atom_io_devtools {
186
186
  section.timeline_log {
187
187
  header {
188
188
  display: flex;
189
- label {
189
+ > main {
190
190
  display: flex;
191
191
  width: 100%;
192
192
  flex-grow: 1;
@@ -150,7 +150,7 @@ var NumberInput = ({
150
150
  testid,
151
151
  value = null
152
152
  }) => {
153
- const id = useId();
153
+ const htmlId = useId();
154
154
  const [temporaryEntry, setTemporaryEntry] = useState(null);
155
155
  const userHasMadeDeliberateChange = useRef(false);
156
156
  const refine = initRefinery({ max, min, decimalPlaces, nullable: true });
@@ -183,7 +183,7 @@ var NumberInput = ({
183
183
  };
184
184
  const displayValue = temporaryEntry ?? valueToText(value ? refine(value) : value);
185
185
  return /* @__PURE__ */ jsxs("span", { children: [
186
- label && /* @__PURE__ */ jsx("label", { htmlFor: id, children: label }),
186
+ label ? /* @__PURE__ */ jsx("label", { htmlFor: htmlId, children: label }) : null,
187
187
  autoSize ? /* @__PURE__ */ jsx(
188
188
  ElasticInput,
189
189
  {
@@ -193,8 +193,8 @@ var NumberInput = ({
193
193
  onChange: handleChange,
194
194
  onBlur: handleBlur,
195
195
  disabled,
196
- name: name ?? id,
197
- id,
196
+ name: name ?? htmlId,
197
+ id: htmlId,
198
198
  onClick,
199
199
  "data-testid": testid
200
200
  }
@@ -207,8 +207,8 @@ var NumberInput = ({
207
207
  onChange: handleChange,
208
208
  onBlur: handleBlur,
209
209
  disabled,
210
- name: name ?? id,
211
- id,
210
+ name: name ?? htmlId,
211
+ id: htmlId,
212
212
  onClick,
213
213
  "data-testid": testid
214
214
  }
@@ -223,11 +223,13 @@ var TextInput = ({
223
223
  autoSize = false,
224
224
  testid
225
225
  }) => {
226
+ const htmlId = useId();
226
227
  return /* @__PURE__ */ jsxs("span", { children: [
227
- /* @__PURE__ */ jsx("label", { children: label }),
228
+ label ? /* @__PURE__ */ jsx("label", { htmlFor: htmlId, children: label }) : null,
228
229
  autoSize ? /* @__PURE__ */ jsx(
229
230
  ElasticInput,
230
231
  {
232
+ id: htmlId,
231
233
  type: "text",
232
234
  value,
233
235
  onChange: (e) => set?.(e.target.value),
@@ -238,6 +240,7 @@ var TextInput = ({
238
240
  ) : /* @__PURE__ */ jsx(
239
241
  "input",
240
242
  {
243
+ id: htmlId,
241
244
  type: "text",
242
245
  value,
243
246
  onChange: (e) => set?.(e.target.value),
@@ -980,7 +983,7 @@ var StateIndexLeafNode = ({ node, isOpenState, typeState }) => {
980
983
  }
981
984
  ),
982
985
  /* @__PURE__ */ jsxs(
983
- "label",
986
+ "main",
984
987
  {
985
988
  onClick: () => {
986
989
  console.log(node, getState(node));
@@ -1021,7 +1024,7 @@ var StateIndexTreeNode = ({ node, isOpenState }) => {
1021
1024
  setIsOpen
1022
1025
  }
1023
1026
  ),
1024
- /* @__PURE__ */ jsxs("label", { children: [
1027
+ /* @__PURE__ */ jsxs("main", { children: [
1025
1028
  /* @__PURE__ */ jsx("h2", { children: node.key }),
1026
1029
  /* @__PURE__ */ jsx("span", { className: "type detail", children: " (family)" })
1027
1030
  ] })
@@ -1236,7 +1239,7 @@ var TimelineLog = ({ token, isOpenState, timelineState }) => {
1236
1239
  setIsOpen
1237
1240
  }
1238
1241
  ),
1239
- /* @__PURE__ */ jsxs("label", { children: [
1242
+ /* @__PURE__ */ jsxs("main", { children: [
1240
1243
  /* @__PURE__ */ jsx("h2", { children: token.key }),
1241
1244
  /* @__PURE__ */ jsxs("span", { className: "detail length", children: [
1242
1245
  "(",
@@ -1321,7 +1324,7 @@ var TransactionLog = ({ token, isOpenState, logState }) => {
1321
1324
  setIsOpen
1322
1325
  }
1323
1326
  ),
1324
- /* @__PURE__ */ jsxs("label", { children: [
1327
+ /* @__PURE__ */ jsxs("main", { children: [
1325
1328
  /* @__PURE__ */ jsx("h2", { children: token.key }),
1326
1329
  /* @__PURE__ */ jsxs("span", { className: "detail length", children: [
1327
1330
  "(",
@@ -38,7 +38,7 @@ export const StateIndexLeafNode: FC<{
38
38
  setIsOpen={setIsOpen}
39
39
  disabled={isPrimitive}
40
40
  />
41
- <label
41
+ <main
42
42
  onClick={() => {
43
43
  console.log(node, getState(node))
44
44
  }}
@@ -48,7 +48,7 @@ export const StateIndexLeafNode: FC<{
48
48
  >
49
49
  <h2>{node.family?.subKey ?? node.key}</h2>
50
50
  <span className="type detail">({stateType})</span>
51
- </label>
51
+ </main>
52
52
  <StoreEditor token={node} />
53
53
  </header>
54
54
  {isOpen && !isPrimitive ? (
@@ -80,10 +80,10 @@ export const StateIndexTreeNode: FC<{
80
80
  testid={`open-close-state-family-${node.key}`}
81
81
  setIsOpen={setIsOpen}
82
82
  />
83
- <label>
83
+ <main>
84
84
  <h2>{node.key}</h2>
85
85
  <span className="type detail"> (family)</span>
86
- </label>
86
+ </main>
87
87
  </header>
88
88
  {isOpen
89
89
  ? [...node.familyMembers.entries()].map(([key, childNode]) => (
@@ -33,7 +33,7 @@ export const TimelineLog: FC<{
33
33
  testid={`open-close-timeline-${token.key}`}
34
34
  setIsOpen={setIsOpen}
35
35
  />
36
- <label>
36
+ <main>
37
37
  <h2>{token.key}</h2>
38
38
  <span className="detail length">
39
39
  ({timeline.at}/{timeline.history.length})
@@ -59,7 +59,7 @@ export const TimelineLog: FC<{
59
59
  redo
60
60
  </button>
61
61
  </nav>
62
- </label>
62
+ </main>
63
63
  </header>
64
64
  {isOpen ? (
65
65
  <main>
@@ -32,10 +32,10 @@ export const TransactionLog: FC<{
32
32
  testid={`open-close-transaction-${token.key}`}
33
33
  setIsOpen={setIsOpen}
34
34
  />
35
- <label>
35
+ <main>
36
36
  <h2>{token.key}</h2>
37
37
  <span className="detail length">({log.length})</span>
38
- </label>
38
+ </main>
39
39
  </header>
40
40
  {isOpen ? (
41
41
  <main>
@@ -107,7 +107,7 @@ main.atom_io_devtools {
107
107
  cursor: default;
108
108
  }
109
109
  }
110
- label {
110
+ > main {
111
111
  display: flex;
112
112
  flex-flow: row;
113
113
  gap: 5px;
@@ -185,7 +185,7 @@ main.atom_io_devtools {
185
185
  section.timeline_log {
186
186
  header {
187
187
  display: flex;
188
- label {
188
+ > main {
189
189
  display: flex;
190
190
  width: 100%;
191
191
  flex-grow: 1;
@@ -115,7 +115,7 @@ export const NumberInput: FC<NumberInputProps> = ({
115
115
  testid,
116
116
  value = null,
117
117
  }) => {
118
- const id = useId()
118
+ const htmlId = useId()
119
119
  const [temporaryEntry, setTemporaryEntry] = useState<
120
120
  DecimalInProgress | ValidNonNumber | null
121
121
  >(null)
@@ -142,7 +142,7 @@ export const NumberInput: FC<NumberInputProps> = ({
142
142
  setTemporaryEntry(input)
143
143
  const textInterpretation = isDecimalInProgress(input)
144
144
  ? input
145
- : min?.toString() ?? `0`
145
+ : (min?.toString() ?? `0`)
146
146
  const newValue = textToValue(textInterpretation, allowDecimal)
147
147
  set(refine(newValue))
148
148
  return
@@ -166,7 +166,8 @@ export const NumberInput: FC<NumberInputProps> = ({
166
166
 
167
167
  return (
168
168
  <span>
169
- {label && <label htmlFor={id}>{label}</label>}
169
+ {/* biome-ignore lint/a11y/noLabelWithoutControl: it's associated via htmlFor */}
170
+ {label ? <label htmlFor={htmlId}>{label}</label> : null}
170
171
  {autoSize ? (
171
172
  <ElasticInput
172
173
  type="text"
@@ -175,8 +176,8 @@ export const NumberInput: FC<NumberInputProps> = ({
175
176
  onChange={handleChange}
176
177
  onBlur={handleBlur}
177
178
  disabled={disabled}
178
- name={name ?? id}
179
- id={id}
179
+ name={name ?? htmlId}
180
+ id={htmlId}
180
181
  onClick={onClick}
181
182
  data-testid={testid}
182
183
  />
@@ -188,8 +189,8 @@ export const NumberInput: FC<NumberInputProps> = ({
188
189
  onChange={handleChange}
189
190
  onBlur={handleBlur}
190
191
  disabled={disabled}
191
- name={name ?? id}
192
- id={id}
192
+ name={name ?? htmlId}
193
+ id={htmlId}
193
194
  onClick={onClick}
194
195
  data-testid={testid}
195
196
  />
@@ -1,4 +1,4 @@
1
- import type { FC } from "react"
1
+ import { type FC, useId } from "react"
2
2
 
3
3
  import { ElasticInput } from "."
4
4
 
@@ -20,11 +20,14 @@ export const TextInput: FC<TextInputProps> = ({
20
20
  autoSize = false,
21
21
  testid,
22
22
  }) => {
23
+ const htmlId = useId()
23
24
  return (
24
25
  <span>
25
- <label>{label}</label>
26
+ {/* biome-ignore lint/a11y/noLabelWithoutControl: it's associated via htmlFor */}
27
+ {label ? <label htmlFor={htmlId}>{label}</label> : null}
26
28
  {autoSize ? (
27
29
  <ElasticInput
30
+ id={htmlId}
28
31
  type="text"
29
32
  value={value}
30
33
  onChange={(e) => set?.(e.target.value)}
@@ -34,6 +37,7 @@ export const TextInput: FC<TextInputProps> = ({
34
37
  />
35
38
  ) : (
36
39
  <input
40
+ id={htmlId}
37
41
  type="text"
38
42
  value={value}
39
43
  onChange={(e) => set?.(e.target.value)}
@@ -14,21 +14,19 @@ interface EventBuffer<Key extends string, Params extends Json.Serializable[]> ex
14
14
  toString(): StringifiedEvent<Key, Params>;
15
15
  }
16
16
  declare class CustomSocket<I extends Events, O extends Events> implements Socket {
17
- emit: <Event extends keyof O>(event: Event, ...args: O[Event]) => CustomSocket<I, O>;
18
- protected listeners: Map<keyof I, Set<(...args: Json.Array) => void>>;
17
+ emit: <Event extends keyof I>(event: Event, ...args: I[Event]) => CustomSocket<I, O>;
18
+ protected listeners: Map<keyof O, Set<(...args: Json.Array) => void>>;
19
19
  protected globalListeners: Set<(event: string, ...args: Json.Array) => void>;
20
20
  protected handleEvent<Event extends keyof I>(event: string, ...args: I[Event]): void;
21
21
  id: string;
22
- constructor(emit: <Event extends keyof O>(event: Event, ...args: O[Event]) => CustomSocket<I, O>);
23
- on<Event extends keyof I>(event: Event, listener: (...args: I[Event]) => void): this;
22
+ constructor(emit: <Event extends keyof I>(event: Event, ...args: I[Event]) => CustomSocket<I, O>);
23
+ on<Event extends keyof O>(event: Event, listener: (...args: O[Event]) => void): this;
24
24
  onAny(listener: (event: string, ...args: Json.Array) => void): this;
25
- off<Event extends keyof I>(event: Event, listener?: (...args: I[Event]) => void): this;
25
+ off<Event extends keyof O>(event: Event, listener?: (...args: O[Event]) => void): this;
26
26
  offAny(listener: (event: string, ...args: Json.Array) => void): this;
27
27
  }
28
28
 
29
- declare class ChildSocket<I extends Events, O extends Events & {
30
- "setup-relay": [string];
31
- }> extends CustomSocket<I, O> {
29
+ declare class ChildSocket<I extends Events, O extends Events> extends CustomSocket<I, O> {
32
30
  process: ChildProcessWithoutNullStreams;
33
31
  key: string;
34
32
  logger: {
@@ -58,12 +56,12 @@ declare class SubjectSocket<I extends Events, O extends Events> extends CustomSo
58
56
  dispose(): void;
59
57
  }
60
58
  declare class ParentSocket<I extends Events & {
59
+ [id in string as `relay:${id}`]: [string, ...Json.Serializable[]];
60
+ }, O extends Events & {
61
61
  [id in string as `user:${id}`]: [string, ...Json.Serializable[]];
62
62
  } & {
63
63
  "user-joins": [string];
64
64
  "user-leaves": [string];
65
- }, O extends Events & {
66
- [id in string as `relay:${id}`]: [string, ...Json.Serializable[]];
67
65
  }> extends CustomSocket<I, O> {
68
66
  protected incompleteData: string;
69
67
  protected unprocessedEvents: string[];
@@ -10,11 +10,7 @@ import { CustomSocket } from "./custom-socket"
10
10
 
11
11
  export class ChildSocket<
12
12
  I extends Events,
13
- O extends Events & {
14
- /* eslint-disable quotes */
15
- "setup-relay": [string]
16
- /* eslint-enable quotes */
17
- },
13
+ O extends Events,
18
14
  > extends CustomSocket<I, O> {
19
15
  protected incompleteData = ``
20
16
  protected unprocessedEvents: string[] = []
@@ -17,7 +17,7 @@ export interface EventBuffer<
17
17
  }
18
18
 
19
19
  export class CustomSocket<I extends Events, O extends Events> implements Socket {
20
- protected listeners: Map<keyof I, Set<(...args: Json.Array) => void>>
20
+ protected listeners: Map<keyof O, Set<(...args: Json.Array) => void>>
21
21
  protected globalListeners: Set<(event: string, ...args: Json.Array) => void>
22
22
  protected handleEvent<Event extends keyof I>(
23
23
  event: string,
@@ -37,18 +37,18 @@ export class CustomSocket<I extends Events, O extends Events> implements Socket
37
37
  public id = `no_id_retrieved`
38
38
 
39
39
  public constructor(
40
- public emit: <Event extends keyof O>(
40
+ public emit: <Event extends keyof I>(
41
41
  event: Event,
42
- ...args: O[Event]
42
+ ...args: I[Event]
43
43
  ) => CustomSocket<I, O>,
44
44
  ) {
45
45
  this.listeners = new Map()
46
46
  this.globalListeners = new Set()
47
47
  }
48
48
 
49
- public on<Event extends keyof I>(
49
+ public on<Event extends keyof O>(
50
50
  event: Event,
51
- listener: (...args: I[Event]) => void,
51
+ listener: (...args: O[Event]) => void,
52
52
  ): this {
53
53
  const listeners = this.listeners.get(event)
54
54
  if (listeners) {
@@ -64,9 +64,9 @@ export class CustomSocket<I extends Events, O extends Events> implements Socket
64
64
  return this
65
65
  }
66
66
 
67
- public off<Event extends keyof I>(
67
+ public off<Event extends keyof O>(
68
68
  event: Event,
69
- listener?: (...args: I[Event]) => void,
69
+ listener?: (...args: O[Event]) => void,
70
70
  ): this {
71
71
  const listeners = this.listeners.get(event)
72
72
  if (listeners) {