aidos-ui 4.0.3 → 4.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +23 -3
  3. package/dist/index.d.ts +797 -68
  4. package/dist/index.js +3868 -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 +12 -6
  13. package/dist/vite-plugin-jss-debug.js +57 -72
  14. package/dist/vite-plugin-jss-debug.js.map +1 -1
  15. package/package.json +58 -27
  16. package/.claude/settings.local.json +0 -22
  17. package/.prettierrc +0 -4
  18. package/CLAUDE.md +0 -72
  19. package/dist/Badge.d.ts +0 -6
  20. package/dist/Badge.js +0 -22
  21. package/dist/Badge.js.map +0 -1
  22. package/dist/BaseButton.d.ts +0 -14
  23. package/dist/BaseButton.js +0 -23
  24. package/dist/BaseButton.js.map +0 -1
  25. package/dist/BaseInput.d.ts +0 -14
  26. package/dist/BaseInput.js +0 -15
  27. package/dist/BaseInput.js.map +0 -1
  28. package/dist/BaseLink.d.ts +0 -18
  29. package/dist/BaseLink.js +0 -29
  30. package/dist/BaseLink.js.map +0 -1
  31. package/dist/BaseList.d.ts +0 -6
  32. package/dist/BaseList.js +0 -14
  33. package/dist/BaseList.js.map +0 -1
  34. package/dist/BaseListAddOn.d.ts +0 -5
  35. package/dist/BaseListAddOn.js +0 -7
  36. package/dist/BaseListAddOn.js.map +0 -1
  37. package/dist/BaseListItem.d.ts +0 -26
  38. package/dist/BaseListItem.js +0 -29
  39. package/dist/BaseListItem.js.map +0 -1
  40. package/dist/BaseView.d.ts +0 -12
  41. package/dist/BaseView.js +0 -26
  42. package/dist/BaseView.js.map +0 -1
  43. package/dist/Box.d.ts +0 -4
  44. package/dist/Box.js +0 -6
  45. package/dist/Box.js.map +0 -1
  46. package/dist/Button.d.ts +0 -20
  47. package/dist/Button.js +0 -19
  48. package/dist/Button.js.map +0 -1
  49. package/dist/Calendar.d.ts +0 -18
  50. package/dist/Calendar.js +0 -57
  51. package/dist/Calendar.js.map +0 -1
  52. package/dist/Card.d.ts +0 -4
  53. package/dist/Card.js +0 -14
  54. package/dist/Card.js.map +0 -1
  55. package/dist/Checkbox.d.ts +0 -11
  56. package/dist/Checkbox.js +0 -32
  57. package/dist/Checkbox.js.map +0 -1
  58. package/dist/Circle.d.ts +0 -5
  59. package/dist/Circle.js +0 -12
  60. package/dist/Circle.js.map +0 -1
  61. package/dist/Column.d.ts +0 -6
  62. package/dist/Column.js +0 -7
  63. package/dist/Column.js.map +0 -1
  64. package/dist/DarkMode.d.ts +0 -13
  65. package/dist/DarkMode.js +0 -62
  66. package/dist/DarkMode.js.map +0 -1
  67. package/dist/DateInput.d.ts +0 -13
  68. package/dist/DateInput.js +0 -29
  69. package/dist/DateInput.js.map +0 -1
  70. package/dist/DatePicker.d.ts +0 -11
  71. package/dist/DatePicker.js +0 -34
  72. package/dist/DatePicker.js.map +0 -1
  73. package/dist/DatetimeInput.d.ts +0 -13
  74. package/dist/DatetimeInput.js +0 -31
  75. package/dist/DatetimeInput.js.map +0 -1
  76. package/dist/DesignBook.d.ts +0 -1
  77. package/dist/DesignBook.js +0 -55
  78. package/dist/DesignBook.js.map +0 -1
  79. package/dist/Dialog.d.ts +0 -17
  80. package/dist/Dialog.js +0 -92
  81. package/dist/Dialog.js.map +0 -1
  82. package/dist/Dropdown.d.ts +0 -14
  83. package/dist/Dropdown.js +0 -65
  84. package/dist/Dropdown.js.map +0 -1
  85. package/dist/Emitter.d.ts +0 -6
  86. package/dist/Emitter.js +0 -19
  87. package/dist/Emitter.js.map +0 -1
  88. package/dist/FlexLayout.d.ts +0 -11
  89. package/dist/FlexLayout.js +0 -18
  90. package/dist/FlexLayout.js.map +0 -1
  91. package/dist/Icon.d.ts +0 -12
  92. package/dist/Icon.js +0 -60
  93. package/dist/Icon.js.map +0 -1
  94. package/dist/IconButton.d.ts +0 -9
  95. package/dist/IconButton.js +0 -31
  96. package/dist/IconButton.js.map +0 -1
  97. package/dist/IconLink.d.ts +0 -9
  98. package/dist/IconLink.js +0 -32
  99. package/dist/IconLink.js.map +0 -1
  100. package/dist/IconType.d.ts +0 -1
  101. package/dist/IconType.js +0 -2
  102. package/dist/IconType.js.map +0 -1
  103. package/dist/Interactable.d.ts +0 -50
  104. package/dist/Interactable.js +0 -169
  105. package/dist/Interactable.js.map +0 -1
  106. package/dist/JSSComment.d.ts +0 -10
  107. package/dist/JSSComment.js +0 -52
  108. package/dist/JSSComment.js.map +0 -1
  109. package/dist/Link.d.ts +0 -22
  110. package/dist/Link.js +0 -29
  111. package/dist/Link.js.map +0 -1
  112. package/dist/List.d.ts +0 -15
  113. package/dist/List.js +0 -29
  114. package/dist/List.js.map +0 -1
  115. package/dist/ListButtonItem.d.ts +0 -14
  116. package/dist/ListButtonItem.js +0 -11
  117. package/dist/ListButtonItem.js.map +0 -1
  118. package/dist/ListDivider.d.ts +0 -1
  119. package/dist/ListDivider.js +0 -12
  120. package/dist/ListDivider.js.map +0 -1
  121. package/dist/ListHeaderItem.d.ts +0 -10
  122. package/dist/ListHeaderItem.js +0 -15
  123. package/dist/ListHeaderItem.js.map +0 -1
  124. package/dist/ListItem.d.ts +0 -9
  125. package/dist/ListItem.js +0 -9
  126. package/dist/ListItem.js.map +0 -1
  127. package/dist/ListLinkItem.d.ts +0 -16
  128. package/dist/ListLinkItem.js +0 -11
  129. package/dist/ListLinkItem.js.map +0 -1
  130. package/dist/ListSpacer.d.ts +0 -1
  131. package/dist/ListSpacer.js +0 -13
  132. package/dist/ListSpacer.js.map +0 -1
  133. package/dist/MenuIcon.d.ts +0 -5
  134. package/dist/MenuIcon.js +0 -31
  135. package/dist/MenuIcon.js.map +0 -1
  136. package/dist/NextJSRouter.d.ts +0 -1
  137. package/dist/NextJSRouter.js +0 -37
  138. package/dist/NextJSRouter.js.map +0 -1
  139. package/dist/NextJSRouterState.d.ts +0 -38
  140. package/dist/NextJSRouterState.js +0 -111
  141. package/dist/NextJSRouterState.js.map +0 -1
  142. package/dist/OnVisible.d.ts +0 -5
  143. package/dist/OnVisible.js +0 -28
  144. package/dist/OnVisible.js.map +0 -1
  145. package/dist/Popover.d.ts +0 -22
  146. package/dist/Popover.js +0 -90
  147. package/dist/Popover.js.map +0 -1
  148. package/dist/ProgressBar.d.ts +0 -7
  149. package/dist/ProgressBar.js +0 -42
  150. package/dist/ProgressBar.js.map +0 -1
  151. package/dist/ProgressCircle.d.ts +0 -5
  152. package/dist/ProgressCircle.js +0 -12
  153. package/dist/ProgressCircle.js.map +0 -1
  154. package/dist/Providers.d.ts +0 -9
  155. package/dist/Providers.js +0 -16
  156. package/dist/Providers.js.map +0 -1
  157. package/dist/RangeInput.d.ts +0 -14
  158. package/dist/RangeInput.js +0 -32
  159. package/dist/RangeInput.js.map +0 -1
  160. package/dist/ResultOrError.d.ts +0 -13
  161. package/dist/ResultOrError.js +0 -7
  162. package/dist/ResultOrError.js.map +0 -1
  163. package/dist/RootView.d.ts +0 -5
  164. package/dist/RootView.js +0 -35
  165. package/dist/RootView.js.map +0 -1
  166. package/dist/Row.d.ts +0 -6
  167. package/dist/Row.js +0 -7
  168. package/dist/Row.js.map +0 -1
  169. package/dist/Select.d.ts +0 -9
  170. package/dist/Select.js +0 -17
  171. package/dist/Select.js.map +0 -1
  172. package/dist/StackContext.d.ts +0 -8
  173. package/dist/StackContext.js +0 -25
  174. package/dist/StackContext.js.map +0 -1
  175. package/dist/StaticCheckbox.d.ts +0 -16
  176. package/dist/StaticCheckbox.js +0 -48
  177. package/dist/StaticCheckbox.js.map +0 -1
  178. package/dist/Storage.d.ts +0 -13
  179. package/dist/Storage.js +0 -146
  180. package/dist/Storage.js.map +0 -1
  181. package/dist/Stream.d.ts +0 -9
  182. package/dist/Stream.js +0 -36
  183. package/dist/Stream.js.map +0 -1
  184. package/dist/Sublist.d.ts +0 -12
  185. package/dist/Sublist.js +0 -18
  186. package/dist/Sublist.js.map +0 -1
  187. package/dist/SubmitIconInput.d.ts +0 -8
  188. package/dist/SubmitIconInput.js +0 -25
  189. package/dist/SubmitIconInput.js.map +0 -1
  190. package/dist/Tabs.d.ts +0 -23
  191. package/dist/Tabs.js +0 -39
  192. package/dist/Tabs.js.map +0 -1
  193. package/dist/Text.d.ts +0 -25
  194. package/dist/Text.js +0 -52
  195. package/dist/Text.js.map +0 -1
  196. package/dist/TextArea.d.ts +0 -11
  197. package/dist/TextArea.js +0 -27
  198. package/dist/TextArea.js.map +0 -1
  199. package/dist/TextInput.d.ts +0 -15
  200. package/dist/TextInput.js +0 -61
  201. package/dist/TextInput.js.map +0 -1
  202. package/dist/TextInputWithState.d.ts +0 -8
  203. package/dist/TextInputWithState.js +0 -14
  204. package/dist/TextInputWithState.js.map +0 -1
  205. package/dist/TextPairing.d.ts +0 -21
  206. package/dist/TextPairing.js +0 -26
  207. package/dist/TextPairing.js.map +0 -1
  208. package/dist/TimeInput.d.ts +0 -15
  209. package/dist/TimeInput.js +0 -58
  210. package/dist/TimeInput.js.map +0 -1
  211. package/dist/Tooltip.d.ts +0 -11
  212. package/dist/Tooltip.js +0 -73
  213. package/dist/Tooltip.js.map +0 -1
  214. package/dist/aria.d.ts +0 -8
  215. package/dist/aria.js +0 -42
  216. package/dist/aria.js.map +0 -1
  217. package/dist/guid.d.ts +0 -1
  218. package/dist/guid.js +0 -7
  219. package/dist/guid.js.map +0 -1
  220. package/dist/hash.d.ts +0 -1
  221. package/dist/hash.js +0 -20
  222. package/dist/hash.js.map +0 -1
  223. package/dist/isServer.d.ts +0 -1
  224. package/dist/isServer.js +0 -4
  225. package/dist/isServer.js.map +0 -1
  226. package/dist/jss.d.ts +0 -122
  227. package/dist/jss.js +0 -515
  228. package/dist/jss.js.map +0 -1
  229. package/dist/numberToBase.d.ts +0 -1
  230. package/dist/numberToBase.js +0 -44
  231. package/dist/numberToBase.js.map +0 -1
  232. package/dist/stateMachineContextFactory.d.ts +0 -36
  233. package/dist/stateMachineContextFactory.js +0 -48
  234. package/dist/stateMachineContextFactory.js.map +0 -1
  235. package/dist/useCookie.d.ts +0 -9
  236. package/dist/useCookie.js +0 -67
  237. package/dist/useCookie.js.map +0 -1
  238. package/dist/useKeyboard.d.ts +0 -8
  239. package/dist/useKeyboard.js +0 -26
  240. package/dist/useKeyboard.js.map +0 -1
  241. package/dist/useNavigation.d.ts +0 -5
  242. package/dist/useNavigation.js +0 -79
  243. package/dist/useNavigation.js.map +0 -1
  244. package/dist/usePromise.d.ts +0 -1
  245. package/dist/usePromise.js +0 -12
  246. package/dist/usePromise.js.map +0 -1
  247. package/dist/useRefEffect.d.ts +0 -1
  248. package/dist/useRefEffect.js +0 -15
  249. package/dist/useRefEffect.js.map +0 -1
  250. package/jss-debug-loader.mjs +0 -44
  251. package/next-env.d.ts +0 -6
  252. package/next.config.js +0 -33
  253. package/scripts/embeddings.js +0 -93
  254. package/scripts/openai_embeddings.js +0 -100
  255. package/scripts/publish.js +0 -28
  256. package/scripts/test_embeddings.js +0 -47
  257. package/src/Badge.tsx +0 -36
  258. package/src/BaseButton.tsx +0 -62
  259. package/src/BaseInput.tsx +0 -63
  260. package/src/BaseLink.tsx +0 -80
  261. package/src/BaseList.tsx +0 -26
  262. package/src/BaseListAddOn.tsx +0 -10
  263. package/src/BaseListItem.tsx +0 -119
  264. package/src/BaseView.tsx +0 -57
  265. package/src/Box.tsx +0 -20
  266. package/src/Button.tsx +0 -90
  267. package/src/Calendar.tsx +0 -125
  268. package/src/Card.tsx +0 -30
  269. package/src/Checkbox.tsx +0 -63
  270. package/src/Circle.tsx +0 -24
  271. package/src/Column.tsx +0 -12
  272. package/src/DarkMode.tsx +0 -100
  273. package/src/DateInput.tsx +0 -63
  274. package/src/DatePicker.tsx +0 -67
  275. package/src/DatetimeInput.tsx +0 -64
  276. package/src/DesignBook.tsx +0 -677
  277. package/src/Dialog.tsx +0 -150
  278. package/src/Dropdown.tsx +0 -146
  279. package/src/Emitter.ts +0 -26
  280. package/src/FlexLayout.tsx +0 -53
  281. package/src/Icon.tsx +0 -80
  282. package/src/IconButton.tsx +0 -58
  283. package/src/IconLink.tsx +0 -59
  284. package/src/IconType.ts +0 -787
  285. package/src/Interactable.tsx +0 -210
  286. package/src/JSSComment.tsx +0 -56
  287. package/src/Link.tsx +0 -110
  288. package/src/List.tsx +0 -58
  289. package/src/ListButtonItem.tsx +0 -69
  290. package/src/ListDivider.tsx +0 -13
  291. package/src/ListHeaderItem.tsx +0 -45
  292. package/src/ListItem.tsx +0 -24
  293. package/src/ListLinkItem.tsx +0 -76
  294. package/src/ListSpacer.tsx +0 -14
  295. package/src/MenuIcon.tsx +0 -50
  296. package/src/NextJSRouter.tsx +0 -62
  297. package/src/NextJSRouterState.tsx +0 -154
  298. package/src/OnVisible.tsx +0 -42
  299. package/src/Popover.tsx +0 -145
  300. package/src/ProgressBar.tsx +0 -63
  301. package/src/ProgressCircle.tsx +0 -38
  302. package/src/Providers.tsx +0 -33
  303. package/src/RangeInput.tsx +0 -82
  304. package/src/ResultOrError.ts +0 -15
  305. package/src/RootView.tsx +0 -55
  306. package/src/Row.tsx +0 -12
  307. package/src/Select.tsx +0 -39
  308. package/src/StackContext.tsx +0 -52
  309. package/src/StaticCheckbox.tsx +0 -72
  310. package/src/Storage.tsx +0 -198
  311. package/src/Stream.tsx +0 -50
  312. package/src/Sublist.tsx +0 -61
  313. package/src/SubmitIconInput.tsx +0 -45
  314. package/src/Tabs.tsx +0 -110
  315. package/src/Text.tsx +0 -111
  316. package/src/TextArea.tsx +0 -58
  317. package/src/TextInput.tsx +0 -123
  318. package/src/TextInputWithState.tsx +0 -32
  319. package/src/TextPairing.tsx +0 -115
  320. package/src/TimeInput.tsx +0 -109
  321. package/src/Tooltip.tsx +0 -109
  322. package/src/aria.ts +0 -72
  323. package/src/docs/mdx.tsx +0 -137
  324. package/src/docs/pages.ts +0 -115
  325. package/src/docs/searchIndex.ts +0 -1
  326. package/src/examples/ExampleDialog.tsx +0 -28
  327. package/src/guid.ts +0 -7
  328. package/src/hash.ts +0 -21
  329. package/src/index.ts +0 -68
  330. package/src/isServer.ts +0 -3
  331. package/src/jss.tsx +0 -712
  332. package/src/jsx-dev-runtime.ts +0 -74
  333. package/src/jsx-runtime.ts +0 -2
  334. package/src/numberToBase.ts +0 -52
  335. package/src/pages/Badge.mdx +0 -152
  336. package/src/pages/Button.mdx +0 -163
  337. package/src/pages/Calendar.mdx +0 -254
  338. package/src/pages/Card.mdx +0 -147
  339. package/src/pages/Checkbox.mdx +0 -131
  340. package/src/pages/Dialog.mdx +0 -197
  341. package/src/pages/FlexLayout.mdx +0 -211
  342. package/src/pages/Hashing.mdx +0 -211
  343. package/src/pages/Icon.mdx +0 -171
  344. package/src/pages/IconButton.mdx +0 -155
  345. package/src/pages/Link.mdx +0 -160
  346. package/src/pages/List.mdx +0 -262
  347. package/src/pages/ListHeader.mdx +0 -220
  348. package/src/pages/Popover.mdx +0 -223
  349. package/src/pages/ProgressBar.mdx +0 -200
  350. package/src/pages/ProgressCircle.mdx +0 -218
  351. package/src/pages/RangeInput.mdx +0 -237
  352. package/src/pages/Tabs.mdx +0 -281
  353. package/src/pages/Text.mdx +0 -154
  354. package/src/pages/TextInput.mdx +0 -235
  355. package/src/pages/TextPairing.mdx +0 -204
  356. package/src/pages/TimeInput.mdx +0 -178
  357. package/src/pages/Tooltip.mdx +0 -115
  358. package/src/pages/_app.tsx +0 -466
  359. package/src/pages/_document.tsx +0 -30
  360. package/src/pages/css-in-js.mdx +0 -240
  361. package/src/pages/index.mdx +0 -58
  362. package/src/pages/navigation.mdx +0 -158
  363. package/src/pages/prism.css +0 -3
  364. package/src/pages/useCookie.mdx +0 -176
  365. package/src/pages/useKeyboard.mdx +0 -257
  366. package/src/pages/useNavigation.mdx +0 -258
  367. package/src/pages/usePromise.mdx +0 -280
  368. package/src/pages/useRefEffect.mdx +0 -251
  369. package/src/stateMachineContextFactory.tsx +0 -111
  370. package/src/useCookie.tsx +0 -95
  371. package/src/useKeyboard.tsx +0 -43
  372. package/src/useNavigation.tsx +0 -89
  373. package/src/usePromise.tsx +0 -18
  374. package/src/useRefEffect.tsx +0 -18
  375. package/src/vite-plugin-jss-debug.ts +0 -75
  376. package/tsconfig.build.json +0 -23
  377. 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
- }