aidos-ui 4.0.4 → 4.0.6

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 (376) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +23 -3
  3. package/dist/index.d.ts +801 -68
  4. package/dist/index.js +3934 -68
  5. package/dist/index.js.map +1 -1
  6. package/dist/jsx-dev-runtime.d.ts +6 -2
  7. package/dist/jsx-dev-runtime.js +87 -42
  8. package/dist/jsx-dev-runtime.js.map +1 -1
  9. package/dist/jsx-runtime.d.ts +1 -1
  10. package/dist/jsx-runtime.js +2 -2
  11. package/dist/jsx-runtime.js.map +1 -1
  12. package/dist/vite-plugin-jss-debug.d.ts +3 -1
  13. package/dist/vite-plugin-jss-debug.js +57 -74
  14. package/dist/vite-plugin-jss-debug.js.map +1 -1
  15. package/package.json +61 -27
  16. package/.prettierrc +0 -4
  17. package/CLAUDE.md +0 -72
  18. package/dist/Badge.d.ts +0 -6
  19. package/dist/Badge.js +0 -22
  20. package/dist/Badge.js.map +0 -1
  21. package/dist/BaseButton.d.ts +0 -14
  22. package/dist/BaseButton.js +0 -23
  23. package/dist/BaseButton.js.map +0 -1
  24. package/dist/BaseInput.d.ts +0 -14
  25. package/dist/BaseInput.js +0 -15
  26. package/dist/BaseInput.js.map +0 -1
  27. package/dist/BaseLink.d.ts +0 -18
  28. package/dist/BaseLink.js +0 -29
  29. package/dist/BaseLink.js.map +0 -1
  30. package/dist/BaseList.d.ts +0 -6
  31. package/dist/BaseList.js +0 -14
  32. package/dist/BaseList.js.map +0 -1
  33. package/dist/BaseListAddOn.d.ts +0 -5
  34. package/dist/BaseListAddOn.js +0 -7
  35. package/dist/BaseListAddOn.js.map +0 -1
  36. package/dist/BaseListItem.d.ts +0 -26
  37. package/dist/BaseListItem.js +0 -29
  38. package/dist/BaseListItem.js.map +0 -1
  39. package/dist/BaseView.d.ts +0 -12
  40. package/dist/BaseView.js +0 -26
  41. package/dist/BaseView.js.map +0 -1
  42. package/dist/Box.d.ts +0 -4
  43. package/dist/Box.js +0 -6
  44. package/dist/Box.js.map +0 -1
  45. package/dist/Button.d.ts +0 -20
  46. package/dist/Button.js +0 -19
  47. package/dist/Button.js.map +0 -1
  48. package/dist/Calendar.d.ts +0 -18
  49. package/dist/Calendar.js +0 -57
  50. package/dist/Calendar.js.map +0 -1
  51. package/dist/Card.d.ts +0 -4
  52. package/dist/Card.js +0 -14
  53. package/dist/Card.js.map +0 -1
  54. package/dist/Checkbox.d.ts +0 -11
  55. package/dist/Checkbox.js +0 -32
  56. package/dist/Checkbox.js.map +0 -1
  57. package/dist/Circle.d.ts +0 -5
  58. package/dist/Circle.js +0 -12
  59. package/dist/Circle.js.map +0 -1
  60. package/dist/Column.d.ts +0 -6
  61. package/dist/Column.js +0 -7
  62. package/dist/Column.js.map +0 -1
  63. package/dist/DarkMode.d.ts +0 -13
  64. package/dist/DarkMode.js +0 -62
  65. package/dist/DarkMode.js.map +0 -1
  66. package/dist/DateInput.d.ts +0 -13
  67. package/dist/DateInput.js +0 -29
  68. package/dist/DateInput.js.map +0 -1
  69. package/dist/DatePicker.d.ts +0 -11
  70. package/dist/DatePicker.js +0 -34
  71. package/dist/DatePicker.js.map +0 -1
  72. package/dist/DatetimeInput.d.ts +0 -13
  73. package/dist/DatetimeInput.js +0 -31
  74. package/dist/DatetimeInput.js.map +0 -1
  75. package/dist/DesignBook.d.ts +0 -1
  76. package/dist/DesignBook.js +0 -55
  77. package/dist/DesignBook.js.map +0 -1
  78. package/dist/Dialog.d.ts +0 -17
  79. package/dist/Dialog.js +0 -92
  80. package/dist/Dialog.js.map +0 -1
  81. package/dist/Dropdown.d.ts +0 -14
  82. package/dist/Dropdown.js +0 -65
  83. package/dist/Dropdown.js.map +0 -1
  84. package/dist/Emitter.d.ts +0 -6
  85. package/dist/Emitter.js +0 -19
  86. package/dist/Emitter.js.map +0 -1
  87. package/dist/FlexLayout.d.ts +0 -11
  88. package/dist/FlexLayout.js +0 -18
  89. package/dist/FlexLayout.js.map +0 -1
  90. package/dist/Icon.d.ts +0 -12
  91. package/dist/Icon.js +0 -60
  92. package/dist/Icon.js.map +0 -1
  93. package/dist/IconButton.d.ts +0 -11
  94. package/dist/IconButton.js +0 -34
  95. package/dist/IconButton.js.map +0 -1
  96. package/dist/IconLink.d.ts +0 -9
  97. package/dist/IconLink.js +0 -32
  98. package/dist/IconLink.js.map +0 -1
  99. package/dist/IconType.d.ts +0 -1
  100. package/dist/IconType.js +0 -2
  101. package/dist/IconType.js.map +0 -1
  102. package/dist/Interactable.d.ts +0 -50
  103. package/dist/Interactable.js +0 -169
  104. package/dist/Interactable.js.map +0 -1
  105. package/dist/JSSComment.d.ts +0 -10
  106. package/dist/JSSComment.js +0 -52
  107. package/dist/JSSComment.js.map +0 -1
  108. package/dist/Link.d.ts +0 -22
  109. package/dist/Link.js +0 -29
  110. package/dist/Link.js.map +0 -1
  111. package/dist/List.d.ts +0 -15
  112. package/dist/List.js +0 -29
  113. package/dist/List.js.map +0 -1
  114. package/dist/ListButtonItem.d.ts +0 -14
  115. package/dist/ListButtonItem.js +0 -11
  116. package/dist/ListButtonItem.js.map +0 -1
  117. package/dist/ListDivider.d.ts +0 -1
  118. package/dist/ListDivider.js +0 -12
  119. package/dist/ListDivider.js.map +0 -1
  120. package/dist/ListHeaderItem.d.ts +0 -10
  121. package/dist/ListHeaderItem.js +0 -15
  122. package/dist/ListHeaderItem.js.map +0 -1
  123. package/dist/ListItem.d.ts +0 -9
  124. package/dist/ListItem.js +0 -9
  125. package/dist/ListItem.js.map +0 -1
  126. package/dist/ListLinkItem.d.ts +0 -16
  127. package/dist/ListLinkItem.js +0 -11
  128. package/dist/ListLinkItem.js.map +0 -1
  129. package/dist/ListSpacer.d.ts +0 -1
  130. package/dist/ListSpacer.js +0 -13
  131. package/dist/ListSpacer.js.map +0 -1
  132. package/dist/MenuIcon.d.ts +0 -5
  133. package/dist/MenuIcon.js +0 -31
  134. package/dist/MenuIcon.js.map +0 -1
  135. package/dist/NextJSRouter.d.ts +0 -1
  136. package/dist/NextJSRouter.js +0 -37
  137. package/dist/NextJSRouter.js.map +0 -1
  138. package/dist/NextJSRouterState.d.ts +0 -38
  139. package/dist/NextJSRouterState.js +0 -111
  140. package/dist/NextJSRouterState.js.map +0 -1
  141. package/dist/OnVisible.d.ts +0 -5
  142. package/dist/OnVisible.js +0 -28
  143. package/dist/OnVisible.js.map +0 -1
  144. package/dist/Popover.d.ts +0 -22
  145. package/dist/Popover.js +0 -90
  146. package/dist/Popover.js.map +0 -1
  147. package/dist/ProgressBar.d.ts +0 -7
  148. package/dist/ProgressBar.js +0 -42
  149. package/dist/ProgressBar.js.map +0 -1
  150. package/dist/ProgressCircle.d.ts +0 -5
  151. package/dist/ProgressCircle.js +0 -12
  152. package/dist/ProgressCircle.js.map +0 -1
  153. package/dist/Providers.d.ts +0 -9
  154. package/dist/Providers.js +0 -16
  155. package/dist/Providers.js.map +0 -1
  156. package/dist/RangeInput.d.ts +0 -14
  157. package/dist/RangeInput.js +0 -32
  158. package/dist/RangeInput.js.map +0 -1
  159. package/dist/ResultOrError.d.ts +0 -13
  160. package/dist/ResultOrError.js +0 -7
  161. package/dist/ResultOrError.js.map +0 -1
  162. package/dist/RootView.d.ts +0 -5
  163. package/dist/RootView.js +0 -35
  164. package/dist/RootView.js.map +0 -1
  165. package/dist/Row.d.ts +0 -6
  166. package/dist/Row.js +0 -7
  167. package/dist/Row.js.map +0 -1
  168. package/dist/Select.d.ts +0 -9
  169. package/dist/Select.js +0 -17
  170. package/dist/Select.js.map +0 -1
  171. package/dist/StackContext.d.ts +0 -8
  172. package/dist/StackContext.js +0 -25
  173. package/dist/StackContext.js.map +0 -1
  174. package/dist/StaticCheckbox.d.ts +0 -16
  175. package/dist/StaticCheckbox.js +0 -48
  176. package/dist/StaticCheckbox.js.map +0 -1
  177. package/dist/Storage.d.ts +0 -13
  178. package/dist/Storage.js +0 -146
  179. package/dist/Storage.js.map +0 -1
  180. package/dist/Stream.d.ts +0 -9
  181. package/dist/Stream.js +0 -36
  182. package/dist/Stream.js.map +0 -1
  183. package/dist/Sublist.d.ts +0 -12
  184. package/dist/Sublist.js +0 -18
  185. package/dist/Sublist.js.map +0 -1
  186. package/dist/SubmitIconInput.d.ts +0 -8
  187. package/dist/SubmitIconInput.js +0 -25
  188. package/dist/SubmitIconInput.js.map +0 -1
  189. package/dist/Tabs.d.ts +0 -23
  190. package/dist/Tabs.js +0 -39
  191. package/dist/Tabs.js.map +0 -1
  192. package/dist/Text.d.ts +0 -25
  193. package/dist/Text.js +0 -52
  194. package/dist/Text.js.map +0 -1
  195. package/dist/TextArea.d.ts +0 -11
  196. package/dist/TextArea.js +0 -27
  197. package/dist/TextArea.js.map +0 -1
  198. package/dist/TextInput.d.ts +0 -15
  199. package/dist/TextInput.js +0 -61
  200. package/dist/TextInput.js.map +0 -1
  201. package/dist/TextInputWithState.d.ts +0 -8
  202. package/dist/TextInputWithState.js +0 -14
  203. package/dist/TextInputWithState.js.map +0 -1
  204. package/dist/TextPairing.d.ts +0 -21
  205. package/dist/TextPairing.js +0 -26
  206. package/dist/TextPairing.js.map +0 -1
  207. package/dist/TimeInput.d.ts +0 -15
  208. package/dist/TimeInput.js +0 -58
  209. package/dist/TimeInput.js.map +0 -1
  210. package/dist/Tooltip.d.ts +0 -11
  211. package/dist/Tooltip.js +0 -73
  212. package/dist/Tooltip.js.map +0 -1
  213. package/dist/aria.d.ts +0 -8
  214. package/dist/aria.js +0 -42
  215. package/dist/aria.js.map +0 -1
  216. package/dist/guid.d.ts +0 -1
  217. package/dist/guid.js +0 -7
  218. package/dist/guid.js.map +0 -1
  219. package/dist/hash.d.ts +0 -1
  220. package/dist/hash.js +0 -20
  221. package/dist/hash.js.map +0 -1
  222. package/dist/isServer.d.ts +0 -1
  223. package/dist/isServer.js +0 -4
  224. package/dist/isServer.js.map +0 -1
  225. package/dist/jss.d.ts +0 -122
  226. package/dist/jss.js +0 -515
  227. package/dist/jss.js.map +0 -1
  228. package/dist/numberToBase.d.ts +0 -1
  229. package/dist/numberToBase.js +0 -44
  230. package/dist/numberToBase.js.map +0 -1
  231. package/dist/stateMachineContextFactory.d.ts +0 -36
  232. package/dist/stateMachineContextFactory.js +0 -48
  233. package/dist/stateMachineContextFactory.js.map +0 -1
  234. package/dist/useCookie.d.ts +0 -9
  235. package/dist/useCookie.js +0 -67
  236. package/dist/useCookie.js.map +0 -1
  237. package/dist/useKeyboard.d.ts +0 -8
  238. package/dist/useKeyboard.js +0 -26
  239. package/dist/useKeyboard.js.map +0 -1
  240. package/dist/useNavigation.d.ts +0 -5
  241. package/dist/useNavigation.js +0 -79
  242. package/dist/useNavigation.js.map +0 -1
  243. package/dist/usePromise.d.ts +0 -1
  244. package/dist/usePromise.js +0 -12
  245. package/dist/usePromise.js.map +0 -1
  246. package/dist/useRefEffect.d.ts +0 -1
  247. package/dist/useRefEffect.js +0 -15
  248. package/dist/useRefEffect.js.map +0 -1
  249. package/jss-debug-loader.mjs +0 -44
  250. package/next-env.d.ts +0 -6
  251. package/next.config.js +0 -33
  252. package/scripts/embeddings.js +0 -93
  253. package/scripts/openai_embeddings.js +0 -100
  254. package/scripts/publish.js +0 -28
  255. package/scripts/test_embeddings.js +0 -47
  256. package/src/Badge.tsx +0 -36
  257. package/src/BaseButton.tsx +0 -62
  258. package/src/BaseInput.tsx +0 -63
  259. package/src/BaseLink.tsx +0 -80
  260. package/src/BaseList.tsx +0 -26
  261. package/src/BaseListAddOn.tsx +0 -10
  262. package/src/BaseListItem.tsx +0 -119
  263. package/src/BaseView.tsx +0 -57
  264. package/src/Box.tsx +0 -20
  265. package/src/Button.tsx +0 -90
  266. package/src/Calendar.tsx +0 -123
  267. package/src/Card.tsx +0 -30
  268. package/src/Checkbox.tsx +0 -63
  269. package/src/Circle.tsx +0 -24
  270. package/src/Column.tsx +0 -12
  271. package/src/DarkMode.tsx +0 -100
  272. package/src/DateInput.tsx +0 -63
  273. package/src/DatePicker.tsx +0 -67
  274. package/src/DatetimeInput.tsx +0 -64
  275. package/src/DesignBook.tsx +0 -677
  276. package/src/Dialog.tsx +0 -150
  277. package/src/Dropdown.tsx +0 -146
  278. package/src/Emitter.ts +0 -26
  279. package/src/FlexLayout.tsx +0 -53
  280. package/src/Icon.tsx +0 -80
  281. package/src/IconButton.tsx +0 -81
  282. package/src/IconLink.tsx +0 -59
  283. package/src/IconType.ts +0 -787
  284. package/src/Interactable.tsx +0 -210
  285. package/src/JSSComment.tsx +0 -56
  286. package/src/Link.tsx +0 -110
  287. package/src/List.tsx +0 -58
  288. package/src/ListButtonItem.tsx +0 -69
  289. package/src/ListDivider.tsx +0 -13
  290. package/src/ListHeaderItem.tsx +0 -45
  291. package/src/ListItem.tsx +0 -24
  292. package/src/ListLinkItem.tsx +0 -76
  293. package/src/ListSpacer.tsx +0 -14
  294. package/src/MenuIcon.tsx +0 -50
  295. package/src/NextJSRouter.tsx +0 -60
  296. package/src/NextJSRouterState.tsx +0 -154
  297. package/src/OnVisible.tsx +0 -42
  298. package/src/Popover.tsx +0 -145
  299. package/src/ProgressBar.tsx +0 -63
  300. package/src/ProgressCircle.tsx +0 -38
  301. package/src/Providers.tsx +0 -33
  302. package/src/RangeInput.tsx +0 -82
  303. package/src/ResultOrError.ts +0 -15
  304. package/src/RootView.tsx +0 -55
  305. package/src/Row.tsx +0 -12
  306. package/src/Select.tsx +0 -39
  307. package/src/StackContext.tsx +0 -52
  308. package/src/StaticCheckbox.tsx +0 -72
  309. package/src/Storage.tsx +0 -198
  310. package/src/Stream.tsx +0 -50
  311. package/src/Sublist.tsx +0 -61
  312. package/src/SubmitIconInput.tsx +0 -45
  313. package/src/Tabs.tsx +0 -110
  314. package/src/Text.tsx +0 -111
  315. package/src/TextArea.tsx +0 -58
  316. package/src/TextInput.tsx +0 -123
  317. package/src/TextInputWithState.tsx +0 -32
  318. package/src/TextPairing.tsx +0 -115
  319. package/src/TimeInput.tsx +0 -109
  320. package/src/Tooltip.tsx +0 -109
  321. package/src/aria.ts +0 -72
  322. package/src/docs/mdx.tsx +0 -137
  323. package/src/docs/pages.ts +0 -115
  324. package/src/docs/searchIndex.ts +0 -1
  325. package/src/examples/ExampleDialog.tsx +0 -28
  326. package/src/guid.ts +0 -7
  327. package/src/hash.ts +0 -21
  328. package/src/index.ts +0 -68
  329. package/src/isServer.ts +0 -3
  330. package/src/jss.tsx +0 -712
  331. package/src/jsx-dev-runtime.ts +0 -74
  332. package/src/jsx-runtime.ts +0 -2
  333. package/src/numberToBase.ts +0 -52
  334. package/src/pages/Badge.mdx +0 -152
  335. package/src/pages/Button.mdx +0 -163
  336. package/src/pages/Calendar.mdx +0 -254
  337. package/src/pages/Card.mdx +0 -147
  338. package/src/pages/Checkbox.mdx +0 -131
  339. package/src/pages/Dialog.mdx +0 -197
  340. package/src/pages/FlexLayout.mdx +0 -211
  341. package/src/pages/Hashing.mdx +0 -211
  342. package/src/pages/Icon.mdx +0 -171
  343. package/src/pages/IconButton.mdx +0 -155
  344. package/src/pages/Link.mdx +0 -160
  345. package/src/pages/List.mdx +0 -262
  346. package/src/pages/ListHeader.mdx +0 -220
  347. package/src/pages/Popover.mdx +0 -223
  348. package/src/pages/ProgressBar.mdx +0 -200
  349. package/src/pages/ProgressCircle.mdx +0 -218
  350. package/src/pages/RangeInput.mdx +0 -237
  351. package/src/pages/Tabs.mdx +0 -281
  352. package/src/pages/Text.mdx +0 -154
  353. package/src/pages/TextInput.mdx +0 -235
  354. package/src/pages/TextPairing.mdx +0 -204
  355. package/src/pages/TimeInput.mdx +0 -178
  356. package/src/pages/Tooltip.mdx +0 -115
  357. package/src/pages/_app.tsx +0 -466
  358. package/src/pages/_document.tsx +0 -30
  359. package/src/pages/css-in-js.mdx +0 -240
  360. package/src/pages/index.mdx +0 -58
  361. package/src/pages/navigation.mdx +0 -158
  362. package/src/pages/prism.css +0 -3
  363. package/src/pages/useCookie.mdx +0 -176
  364. package/src/pages/useKeyboard.mdx +0 -257
  365. package/src/pages/useNavigation.mdx +0 -258
  366. package/src/pages/usePromise.mdx +0 -280
  367. package/src/pages/useRefEffect.mdx +0 -251
  368. package/src/stateMachineContextFactory.tsx +0 -111
  369. package/src/useCookie.tsx +0 -95
  370. package/src/useKeyboard.tsx +0 -43
  371. package/src/useNavigation.tsx +0 -89
  372. package/src/usePromise.tsx +0 -18
  373. package/src/useRefEffect.tsx +0 -18
  374. package/src/vite-plugin-jss-debug.ts +0 -77
  375. package/tsconfig.build.json +0 -23
  376. package/tsconfig.json +0 -38
@@ -1,280 +0,0 @@
1
- # usePromise
2
-
3
- A React hook for unwrapping Promise values into React state. Handles loading, success, and error states automatically.
4
-
5
- ---
6
-
7
- ## Signature
8
-
9
- ```ts
10
- function usePromise<T>(
11
- promiseFactory: () => Promise<T>,
12
- inputs: Array<any>,
13
- initialValue: T
14
- ): [T | null, any]
15
- ```
16
-
17
- ---
18
-
19
- ## Parameters
20
-
21
- | Parameter | Type | Description |
22
- |-----------|------|-------------|
23
- | `promiseFactory` | `() => Promise<T>` | Factory function that returns a Promise |
24
- | `inputs` | `Array<any>` | Dependency array (like useEffect deps) |
25
- | `initialValue` | `T` | Value to use before the Promise resolves |
26
-
27
- ---
28
-
29
- ## Returns
30
-
31
- A tuple with two elements:
32
-
33
- | Index | Type | Description |
34
- |-------|------|-------------|
35
- | `0` | `T \| null` | The resolved value, or `initialValue` while loading |
36
- | `1` | `any` | Error if the Promise rejected, otherwise `null` |
37
-
38
- ---
39
-
40
- ## Basic usage
41
-
42
- ```js
43
- import { usePromise } from "aidos-ui";
44
-
45
- function UserProfile({ userId }) {
46
- const [user, error] = usePromise(
47
- () => fetchUser(userId),
48
- [userId],
49
- null
50
- );
51
-
52
- if (error) {
53
- return <ErrorMessage error={error} />;
54
- }
55
-
56
- if (!user) {
57
- return <LoadingSpinner />;
58
- }
59
-
60
- return <div>{user.name}</div>;
61
- }
62
- ```
63
-
64
- ---
65
-
66
- ## With initial value
67
-
68
- Provide an initial value to show immediately while loading:
69
-
70
- ```js
71
- function Counter() {
72
- const [count, error] = usePromise(
73
- () => fetchCurrentCount(),
74
- [],
75
- 0 // Show 0 while loading
76
- );
77
-
78
- return <span>{count}</span>;
79
- }
80
- ```
81
-
82
- ---
83
-
84
- ## Dependency-based refetching
85
-
86
- The Promise re-executes when dependencies change:
87
-
88
- ```js
89
- function SearchResults({ query }) {
90
- const [results, error] = usePromise(
91
- () => searchAPI(query),
92
- [query], // Refetch when query changes
93
- []
94
- );
95
-
96
- return (
97
- <ul>
98
- {results.map((result) => (
99
- <li key={result.id}>{result.title}</li>
100
- ))}
101
- </ul>
102
- );
103
- }
104
- ```
105
-
106
- ---
107
-
108
- ## Error handling
109
-
110
- ```js
111
- function DataDisplay() {
112
- const [data, error] = usePromise(
113
- () => fetchData(),
114
- [],
115
- null
116
- );
117
-
118
- if (error) {
119
- return (
120
- <Card>
121
- <Span color="negative">Error: {error.message}</Span>
122
- <Button onClick={() => window.location.reload()}>
123
- Retry
124
- </Button>
125
- </Card>
126
- );
127
- }
128
-
129
- if (!data) {
130
- return <Spinner />;
131
- }
132
-
133
- return <DataTable data={data} />;
134
- }
135
- ```
136
-
137
- ---
138
-
139
- ## Multiple async calls
140
-
141
- Use multiple `usePromise` hooks for parallel data fetching:
142
-
143
- ```js
144
- function Dashboard() {
145
- const [stats, statsError] = usePromise(
146
- () => fetchStats(),
147
- [],
148
- null
149
- );
150
-
151
- const [notifications, notifError] = usePromise(
152
- () => fetchNotifications(),
153
- [],
154
- []
155
- );
156
-
157
- const [user, userError] = usePromise(
158
- () => fetchCurrentUser(),
159
- [],
160
- null
161
- );
162
-
163
- const isLoading = !stats || !user;
164
- const hasError = statsError || notifError || userError;
165
-
166
- if (hasError) {
167
- return <ErrorPage />;
168
- }
169
-
170
- if (isLoading) {
171
- return <LoadingSkeleton />;
172
- }
173
-
174
- return (
175
- <Column gap="large">
176
- <StatsWidget stats={stats} />
177
- <NotificationList notifications={notifications} />
178
- <UserGreeting user={user} />
179
- </Column>
180
- );
181
- }
182
- ```
183
-
184
- ---
185
-
186
- ## With typed responses
187
-
188
- ```ts
189
- interface User {
190
- id: string;
191
- name: string;
192
- email: string;
193
- }
194
-
195
- function UserCard({ userId }: { userId: string }) {
196
- const [user, error] = usePromise<User | null>(
197
- () => fetchUser(userId),
198
- [userId],
199
- null
200
- );
201
-
202
- // user is typed as User | null
203
- if (user) {
204
- return <span>{user.name}</span>;
205
- }
206
-
207
- return <span>Loading...</span>;
208
- }
209
- ```
210
-
211
- ---
212
-
213
- ## Conditional fetching
214
-
215
- Use dependencies to control when fetching occurs:
216
-
217
- ```js
218
- function OptionalData({ shouldFetch, id }) {
219
- const [data, error] = usePromise(
220
- () => shouldFetch ? fetchData(id) : Promise.resolve(null),
221
- [shouldFetch, id],
222
- null
223
- );
224
-
225
- // ...
226
- }
227
- ```
228
-
229
- ---
230
-
231
- ## Comparison with other approaches
232
-
233
- ### vs. plain useEffect
234
-
235
- ```js
236
- // ❌ Manual state management
237
- const [data, setData] = useState(null);
238
- const [error, setError] = useState(null);
239
-
240
- useEffect(() => {
241
- fetchData()
242
- .then(setData)
243
- .catch(setError);
244
- }, []);
245
-
246
- // ✅ usePromise - cleaner
247
- const [data, error] = usePromise(() => fetchData(), [], null);
248
- ```
249
-
250
- ### vs. React Query / SWR
251
-
252
- `usePromise` is simpler but lacks:
253
- - Caching
254
- - Background refetching
255
- - Stale-while-revalidate
256
- - Automatic retries
257
-
258
- Use `usePromise` for simple cases; consider React Query or SWR for complex data fetching needs.
259
-
260
- ---
261
-
262
- ## Best practices
263
-
264
- 1. **Use meaningful initial values** - Choose values that make sense for your UI (empty array for lists, null for objects)
265
-
266
- 2. **Handle all states** - Always check for error and loading states
267
-
268
- 3. **Keep factories stable** - Avoid creating new functions on each render:
269
-
270
- ```js
271
- // ❌ Creates new function each render
272
- const [data] = usePromise(() => fetch(`/api/${id}`), [id], null);
273
-
274
- // ✅ Factory only changes when id changes
275
- const [data] = usePromise(
276
- () => fetchById(id),
277
- [id],
278
- null
279
- );
280
- ```
@@ -1,251 +0,0 @@
1
- # useRefEffect
2
-
3
- A React hook that reliably runs an effect once when an element is mounted. Unlike `useEffect`, this hook guarantees single execution and proper cleanup, making it ideal for setting up event listeners and DOM manipulations.
4
-
5
- ---
6
-
7
- ## Signature
8
-
9
- ```ts
10
- function useRefEffect<T>(
11
- callback: (root: T) => (() => void) | void
12
- ): (root: T) => void
13
- ```
14
-
15
- ---
16
-
17
- ## Parameters
18
-
19
- | Parameter | Type | Description |
20
- |-----------|------|-------------|
21
- | `callback` | `(root: T) => (() => void) \| void` | Function called when the element mounts. Can return a cleanup function. |
22
-
23
- ---
24
-
25
- ## Returns
26
-
27
- A ref callback function that should be passed to the element's `ref` prop.
28
-
29
- ---
30
-
31
- ## Why use this?
32
-
33
- React's `useEffect` with an empty dependency array doesn't reliably run only once due to:
34
- - Strict Mode double-invocation in development
35
- - Concurrent rendering behaviors
36
- - Fast refresh during development
37
-
38
- `useRefEffect` solves this by using a ref callback pattern that guarantees:
39
- - The effect runs exactly once when the element mounts
40
- - Cleanup runs exactly once when the element unmounts
41
- - No dependency array needed
42
-
43
- ---
44
-
45
- ## Basic usage
46
-
47
- ```js
48
- import { useRefEffect } from "aidos-ui";
49
-
50
- function ResizeObserverComponent() {
51
- const ref = useRefEffect((element) => {
52
- const observer = new ResizeObserver((entries) => {
53
- console.log("Size changed:", entries[0].contentRect);
54
- });
55
-
56
- observer.observe(element);
57
-
58
- // Return cleanup function
59
- return () => observer.disconnect();
60
- });
61
-
62
- return <div ref={ref}>Resize me!</div>;
63
- }
64
- ```
65
-
66
- ---
67
-
68
- ## Event listeners
69
-
70
- Perfect for attaching event listeners to elements:
71
-
72
- ```js
73
- function DraggableElement() {
74
- const ref = useRefEffect((element) => {
75
- let isDragging = false;
76
- let startX = 0;
77
- let startY = 0;
78
-
79
- const onMouseDown = (e) => {
80
- isDragging = true;
81
- startX = e.clientX;
82
- startY = e.clientY;
83
- };
84
-
85
- const onMouseMove = (e) => {
86
- if (!isDragging) return;
87
- const dx = e.clientX - startX;
88
- const dy = e.clientY - startY;
89
- element.style.transform = `translate(${dx}px, ${dy}px)`;
90
- };
91
-
92
- const onMouseUp = () => {
93
- isDragging = false;
94
- };
95
-
96
- element.addEventListener("mousedown", onMouseDown);
97
- window.addEventListener("mousemove", onMouseMove);
98
- window.addEventListener("mouseup", onMouseUp);
99
-
100
- return () => {
101
- element.removeEventListener("mousedown", onMouseDown);
102
- window.removeEventListener("mousemove", onMouseMove);
103
- window.removeEventListener("mouseup", onMouseUp);
104
- };
105
- });
106
-
107
- return <div ref={ref}>Drag me</div>;
108
- }
109
- ```
110
-
111
- ---
112
-
113
- ## DOM measurements
114
-
115
- Use for operations that need the actual DOM element:
116
-
117
- ```js
118
- function MeasuredElement() {
119
- const [dimensions, setDimensions] = useState(null);
120
-
121
- const ref = useRefEffect((element) => {
122
- const rect = element.getBoundingClientRect();
123
- setDimensions({
124
- width: rect.width,
125
- height: rect.height,
126
- });
127
- });
128
-
129
- return (
130
- <div ref={ref}>
131
- {dimensions && (
132
- <span>
133
- {dimensions.width}x{dimensions.height}
134
- </span>
135
- )}
136
- </div>
137
- );
138
- }
139
- ```
140
-
141
- ---
142
-
143
- ## Third-party library integration
144
-
145
- Initialize libraries that need a DOM element:
146
-
147
- ```js
148
- function ChartComponent({ data }) {
149
- const ref = useRefEffect((element) => {
150
- const chart = new SomeChartLibrary(element, {
151
- data,
152
- width: 400,
153
- height: 300,
154
- });
155
-
156
- return () => chart.destroy();
157
- });
158
-
159
- return <div ref={ref} />;
160
- }
161
- ```
162
-
163
- ---
164
-
165
- ## Without cleanup
166
-
167
- If no cleanup is needed, simply don't return anything:
168
-
169
- ```js
170
- const ref = useRefEffect((element) => {
171
- element.scrollIntoView({ behavior: "smooth" });
172
- // No cleanup needed
173
- });
174
- ```
175
-
176
- ---
177
-
178
- ## Building other hooks
179
-
180
- `useRefEffect` is the foundation for other hooks in this library:
181
-
182
- ```js
183
- // useKeyboard is built on useRefEffect
184
- export function useKeyboard<T extends HTMLElement>(
185
- shortcuts: Array<KeyboardShortcut<T>>
186
- ) {
187
- return useRefEffect<T>((root: T) => {
188
- const onKeyDown = (e: KeyboardEvent) => {
189
- // Handle shortcuts...
190
- };
191
-
192
- window.addEventListener("keydown", onKeyDown);
193
-
194
- return () => {
195
- window.removeEventListener("keydown", onKeyDown);
196
- };
197
- });
198
- }
199
- ```
200
-
201
- ---
202
-
203
- ## TypeScript usage
204
-
205
- The hook is generic and preserves element types:
206
-
207
- ```ts
208
- // Typed as HTMLInputElement
209
- const inputRef = useRefEffect<HTMLInputElement>((input) => {
210
- input.focus();
211
- input.select();
212
- });
213
-
214
- // Typed as HTMLCanvasElement
215
- const canvasRef = useRefEffect<HTMLCanvasElement>((canvas) => {
216
- const ctx = canvas.getContext("2d");
217
- // ctx is properly typed
218
- });
219
- ```
220
-
221
- ---
222
-
223
- ## Comparison with useEffect
224
-
225
- ```js
226
- // ❌ useEffect - may run multiple times in dev/strict mode
227
- useEffect(() => {
228
- const element = ref.current;
229
- if (!element) return;
230
-
231
- element.addEventListener("click", handler);
232
- return () => element.removeEventListener("click", handler);
233
- }, []);
234
-
235
- // ✅ useRefEffect - runs exactly once
236
- const ref = useRefEffect((element) => {
237
- element.addEventListener("click", handler);
238
- return () => element.removeEventListener("click", handler);
239
- });
240
- ```
241
-
242
- ---
243
-
244
- ## How it works
245
-
246
- The hook uses a ref callback combined with a cleanup ref:
247
-
248
- 1. When the element mounts, the callback receives the element
249
- 2. The callback's return value (cleanup function) is stored
250
- 3. When the element unmounts (ref receives `null`), cleanup runs
251
- 4. The callback is memoized with `useCallback` to prevent re-runs
@@ -1,111 +0,0 @@
1
- import React, {
2
- useContext,
3
- useCallback,
4
- ReactNode,
5
- useMemo,
6
- useRef,
7
- } from "react";
8
- import { Subscribe, createEmitter, Callback } from "./Emitter";
9
-
10
- export type Reducer<State, Context> = <Data extends any>({
11
- state,
12
- context,
13
- data,
14
- }: {
15
- state: State;
16
- context: Context;
17
- data: Data;
18
- }) => { state: State; context: Context };
19
-
20
- type StateMachineConfig<State, Transition, Context> = {
21
- states: {
22
- [state: string]: {
23
- // @ts-ignore
24
- on: { [transition: Transition]: Reducer<State, Context> };
25
- };
26
- };
27
- context: Context;
28
- state: State;
29
- };
30
-
31
- type Send = <Transition, Data>(transition: Transition, data: Data) => void;
32
-
33
- type StateMachineContextType<State, Context> = {
34
- subscribe: Subscribe<{ state: State; context: Context }>;
35
- send: Send;
36
- };
37
-
38
- export function stateMachineContextFactory<State, Transition, Context>(
39
- stateMachineConfig: StateMachineConfig<State, Transition, Context>
40
- ) {
41
- const StateMachineContext = React.createContext<
42
- StateMachineContextType<State, Context>
43
- >({
44
- subscribe: () => {
45
- throw new Error("Not implemented");
46
- },
47
- send: (_) => {
48
- throw new Error("Not implemented");
49
- },
50
- });
51
-
52
- type StateMachineState = {
53
- state: State;
54
- context: Context;
55
- };
56
-
57
- function Provider({ children }: { children: ReactNode }) {
58
- const stateMachineRef = useRef<StateMachineState>({
59
- state: stateMachineConfig.state,
60
- context: stateMachineConfig.context,
61
- });
62
-
63
- const emitterRef = useRef(
64
- createEmitter<{ state: State; context: Context }>()
65
- );
66
-
67
- const subscribe = useCallback((callback: Callback<StateMachineState>) => {
68
- const unsbuscribe = emitterRef.current.subscribe(callback);
69
- callback(stateMachineRef.current);
70
-
71
- return unsbuscribe;
72
- }, []);
73
-
74
- const send = useCallback(
75
- <Transition, Data extends any>(transition: Transition, data: Data) => {
76
- const state = stateMachineRef.current.state;
77
- // @ts-ignore I don't know how to fix this
78
- const transitions = stateMachineConfig.states[state].on;
79
- const reducer: Reducer<State, Context> = transitions[transition];
80
-
81
- if (!reducer) {
82
- // No transition available in the current state, so no update needed
83
- return;
84
- }
85
-
86
- const newState = reducer({
87
- ...stateMachineRef.current,
88
- data,
89
- });
90
-
91
- stateMachineRef.current = newState;
92
- emitterRef.current.emit(newState);
93
- },
94
- []
95
- );
96
-
97
- const value = useMemo(() => ({ subscribe, send }), [subscribe, send]);
98
-
99
- return (
100
- <StateMachineContext.Provider value={value}>
101
- {children}
102
- </StateMachineContext.Provider>
103
- );
104
- }
105
-
106
- function useStateMachine() {
107
- return useContext(StateMachineContext);
108
- }
109
-
110
- return { Provider, useStateMachine };
111
- }