termcast 1.3.32 → 1.3.34

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 (327) hide show
  1. package/dist/action-utils.d.ts.map +1 -1
  2. package/dist/action-utils.js +8 -0
  3. package/dist/action-utils.js.map +1 -1
  4. package/dist/apis/cache.d.ts +1 -2
  5. package/dist/apis/cache.d.ts.map +1 -1
  6. package/dist/apis/cache.js +138 -54
  7. package/dist/apis/cache.js.map +1 -1
  8. package/dist/apis/clipboard.d.ts.map +1 -1
  9. package/dist/apis/clipboard.js +4 -0
  10. package/dist/apis/clipboard.js.map +1 -1
  11. package/dist/apis/oauth.d.ts.map +1 -1
  12. package/dist/apis/oauth.js +31 -4
  13. package/dist/apis/oauth.js.map +1 -1
  14. package/dist/build.d.ts +0 -1
  15. package/dist/build.d.ts.map +1 -1
  16. package/dist/build.js +30 -51
  17. package/dist/build.js.map +1 -1
  18. package/dist/cli.js +31 -14
  19. package/dist/cli.js.map +1 -1
  20. package/dist/compile.d.ts.map +1 -1
  21. package/dist/compile.js +5 -1
  22. package/dist/compile.js.map +1 -1
  23. package/dist/components/actions.d.ts +14 -0
  24. package/dist/components/actions.d.ts.map +1 -1
  25. package/dist/components/actions.js +151 -59
  26. package/dist/components/actions.js.map +1 -1
  27. package/dist/components/alert.d.ts.map +1 -1
  28. package/dist/components/alert.js +6 -5
  29. package/dist/components/alert.js.map +1 -1
  30. package/dist/components/animation-tick.d.ts +1 -1
  31. package/dist/components/animation-tick.js +1 -1
  32. package/dist/components/animation-tick.js.map +1 -1
  33. package/dist/components/detail.d.ts +5 -31
  34. package/dist/components/detail.d.ts.map +1 -1
  35. package/dist/components/detail.js +36 -52
  36. package/dist/components/detail.js.map +1 -1
  37. package/dist/components/dropdown.d.ts +1 -1
  38. package/dist/components/dropdown.d.ts.map +1 -1
  39. package/dist/components/dropdown.js +50 -22
  40. package/dist/components/dropdown.js.map +1 -1
  41. package/dist/components/footer.d.ts.map +1 -1
  42. package/dist/components/footer.js +19 -18
  43. package/dist/components/footer.js.map +1 -1
  44. package/dist/components/form/checkbox.d.ts.map +1 -1
  45. package/dist/components/form/checkbox.js +12 -11
  46. package/dist/components/form/checkbox.js.map +1 -1
  47. package/dist/components/form/date-picker.d.ts.map +1 -1
  48. package/dist/components/form/date-picker.js +7 -22
  49. package/dist/components/form/date-picker.js.map +1 -1
  50. package/dist/components/form/description.d.ts +1 -1
  51. package/dist/components/form/description.d.ts.map +1 -1
  52. package/dist/components/form/description.js +6 -5
  53. package/dist/components/form/description.js.map +1 -1
  54. package/dist/components/form/dropdown.d.ts.map +1 -1
  55. package/dist/components/form/dropdown.js +53 -50
  56. package/dist/components/form/dropdown.js.map +1 -1
  57. package/dist/components/form/file-autocomplete.d.ts.map +1 -1
  58. package/dist/components/form/file-autocomplete.js +5 -4
  59. package/dist/components/form/file-autocomplete.js.map +1 -1
  60. package/dist/components/form/file-picker.d.ts.map +1 -1
  61. package/dist/components/form/file-picker.js +23 -22
  62. package/dist/components/form/file-picker.js.map +1 -1
  63. package/dist/components/form/form-end.d.ts.map +1 -1
  64. package/dist/components/form/form-end.js +6 -4
  65. package/dist/components/form/form-end.js.map +1 -1
  66. package/dist/components/form/form-field-wrapper.d.ts +15 -0
  67. package/dist/components/form/form-field-wrapper.d.ts.map +1 -0
  68. package/dist/components/form/form-field-wrapper.js +29 -0
  69. package/dist/components/form/form-field-wrapper.js.map +1 -0
  70. package/dist/components/form/index.d.ts.map +1 -1
  71. package/dist/components/form/index.js +31 -30
  72. package/dist/components/form/index.js.map +1 -1
  73. package/dist/components/form/password-field.d.ts.map +1 -1
  74. package/dist/components/form/password-field.js +7 -6
  75. package/dist/components/form/password-field.js.map +1 -1
  76. package/dist/components/form/separator.d.ts.map +1 -1
  77. package/dist/components/form/separator.js +3 -2
  78. package/dist/components/form/separator.js.map +1 -1
  79. package/dist/components/form/tagpicker.d.ts.map +1 -1
  80. package/dist/components/form/tagpicker.js +2 -1
  81. package/dist/components/form/tagpicker.js.map +1 -1
  82. package/dist/components/form/text-area.d.ts.map +1 -1
  83. package/dist/components/form/text-area.js +7 -6
  84. package/dist/components/form/text-area.js.map +1 -1
  85. package/dist/components/form/text-field.d.ts.map +1 -1
  86. package/dist/components/form/text-field.js +7 -6
  87. package/dist/components/form/text-field.js.map +1 -1
  88. package/dist/components/form/use-form-navigation.d.ts.map +1 -1
  89. package/dist/components/form/use-form-navigation.js +4 -4
  90. package/dist/components/form/use-form-navigation.js.map +1 -1
  91. package/dist/components/form/with-left-border.d.ts +15 -0
  92. package/dist/components/form/with-left-border.d.ts.map +1 -1
  93. package/dist/components/form/with-left-border.js +21 -9
  94. package/dist/components/form/with-left-border.js.map +1 -1
  95. package/dist/components/icon.d.ts +14 -0
  96. package/dist/components/icon.d.ts.map +1 -1
  97. package/dist/components/icon.js +60 -0
  98. package/dist/components/icon.js.map +1 -1
  99. package/dist/components/image.d.ts +47 -2
  100. package/dist/components/image.d.ts.map +1 -1
  101. package/dist/components/image.js +46 -7
  102. package/dist/components/image.js.map +1 -1
  103. package/dist/components/list.d.ts +5 -0
  104. package/dist/components/list.d.ts.map +1 -1
  105. package/dist/components/list.js +188 -132
  106. package/dist/components/list.js.map +1 -1
  107. package/dist/components/loading-bar.d.ts.map +1 -1
  108. package/dist/components/loading-bar.js +4 -3
  109. package/dist/components/loading-bar.js.map +1 -1
  110. package/dist/components/metadata.d.ts +70 -0
  111. package/dist/components/metadata.d.ts.map +1 -0
  112. package/dist/components/metadata.js +82 -0
  113. package/dist/components/metadata.js.map +1 -0
  114. package/dist/components/theme-picker.d.ts.map +1 -1
  115. package/dist/components/theme-picker.js +3 -2
  116. package/dist/components/theme-picker.js.map +1 -1
  117. package/dist/descendants-v2.d.ts +60 -0
  118. package/dist/descendants-v2.d.ts.map +1 -0
  119. package/dist/descendants-v2.js +144 -0
  120. package/dist/descendants-v2.js.map +1 -0
  121. package/dist/examples/actions-context.d.ts +2 -0
  122. package/dist/examples/actions-context.d.ts.map +1 -0
  123. package/dist/examples/actions-context.js +33 -0
  124. package/dist/examples/actions-context.js.map +1 -0
  125. package/dist/examples/form-basic.d.ts.map +1 -1
  126. package/dist/examples/form-basic.js +1 -1
  127. package/dist/examples/form-basic.js.map +1 -1
  128. package/dist/examples/form-dropdown.js +1 -1
  129. package/dist/examples/form-dropdown.js.map +1 -1
  130. package/dist/examples/internal/custom-action-renderables.d.ts +70 -0
  131. package/dist/examples/internal/custom-action-renderables.d.ts.map +1 -0
  132. package/dist/examples/internal/custom-action-renderables.js +163 -0
  133. package/dist/examples/internal/custom-action-renderables.js.map +1 -0
  134. package/dist/examples/internal/custom-dropdown.d.ts +99 -0
  135. package/dist/examples/internal/custom-dropdown.d.ts.map +1 -0
  136. package/dist/examples/internal/custom-dropdown.js +270 -0
  137. package/dist/examples/internal/custom-dropdown.js.map +1 -0
  138. package/dist/examples/internal/custom-renderable-form.d.ts +43 -0
  139. package/dist/examples/internal/custom-renderable-form.d.ts.map +1 -0
  140. package/dist/examples/internal/custom-renderable-form.js +284 -0
  141. package/dist/examples/internal/custom-renderable-form.js.map +1 -0
  142. package/dist/examples/internal/custom-renderable-list-default-search.d.ts +2 -0
  143. package/dist/examples/internal/custom-renderable-list-default-search.d.ts.map +1 -0
  144. package/dist/examples/internal/custom-renderable-list-default-search.js +16 -0
  145. package/dist/examples/internal/custom-renderable-list-default-search.js.map +1 -0
  146. package/dist/examples/internal/custom-renderable-list-v2-default-search.d.ts +2 -0
  147. package/dist/examples/internal/custom-renderable-list-v2-default-search.d.ts.map +1 -0
  148. package/dist/examples/internal/custom-renderable-list-v2-default-search.js +24 -0
  149. package/dist/examples/internal/custom-renderable-list-v2-default-search.js.map +1 -0
  150. package/dist/examples/internal/custom-renderable-list-v2.d.ts +189 -0
  151. package/dist/examples/internal/custom-renderable-list-v2.d.ts.map +1 -0
  152. package/dist/examples/internal/custom-renderable-list-v2.js +708 -0
  153. package/dist/examples/internal/custom-renderable-list-v2.js.map +1 -0
  154. package/dist/examples/internal/custom-renderable-list.d.ts +72 -0
  155. package/dist/examples/internal/custom-renderable-list.d.ts.map +1 -0
  156. package/dist/examples/internal/custom-renderable-list.js +544 -0
  157. package/dist/examples/internal/custom-renderable-list.js.map +1 -0
  158. package/dist/examples/internal/rhf-custom-ref.js +5 -4
  159. package/dist/examples/internal/rhf-custom-ref.js.map +1 -1
  160. package/dist/examples/internal/scrollbox-with-descendants.js +4 -2
  161. package/dist/examples/internal/scrollbox-with-descendants.js.map +1 -1
  162. package/dist/examples/list-controlled-search.d.ts +2 -0
  163. package/dist/examples/list-controlled-search.d.ts.map +1 -0
  164. package/dist/examples/list-controlled-search.js +12 -0
  165. package/dist/examples/list-controlled-search.js.map +1 -0
  166. package/dist/examples/list-detail-metadata.js +1 -1
  167. package/dist/examples/list-detail-metadata.js.map +1 -1
  168. package/dist/examples/simple-image-mask.d.ts +8 -0
  169. package/dist/examples/simple-image-mask.d.ts.map +1 -0
  170. package/dist/examples/simple-image-mask.js +12 -0
  171. package/dist/examples/simple-image-mask.js.map +1 -0
  172. package/dist/examples/toast-variations.js +1 -1
  173. package/dist/examples/toast-variations.js.map +1 -1
  174. package/dist/extensions/dev.d.ts.map +1 -1
  175. package/dist/extensions/dev.js +3 -2
  176. package/dist/extensions/dev.js.map +1 -1
  177. package/dist/extensions/react-refresh-init.d.ts.map +1 -1
  178. package/dist/extensions/react-refresh-init.js +4 -3
  179. package/dist/extensions/react-refresh-init.js.map +1 -1
  180. package/dist/index.d.ts +3 -2
  181. package/dist/index.d.ts.map +1 -1
  182. package/dist/index.js +1 -1
  183. package/dist/index.js.map +1 -1
  184. package/dist/internal/date-picker-widget.d.ts.map +1 -1
  185. package/dist/internal/date-picker-widget.js +2 -1
  186. package/dist/internal/date-picker-widget.js.map +1 -1
  187. package/dist/internal/dialog.d.ts +6 -0
  188. package/dist/internal/dialog.d.ts.map +1 -1
  189. package/dist/internal/dialog.js +59 -18
  190. package/dist/internal/dialog.js.map +1 -1
  191. package/dist/internal/navigation.d.ts.map +1 -1
  192. package/dist/internal/navigation.js +8 -1
  193. package/dist/internal/navigation.js.map +1 -1
  194. package/dist/internal/offscreen.d.ts +3 -0
  195. package/dist/internal/offscreen.d.ts.map +1 -1
  196. package/dist/internal/offscreen.js +5 -0
  197. package/dist/internal/offscreen.js.map +1 -1
  198. package/dist/internal/providers.d.ts.map +1 -1
  199. package/dist/internal/providers.js +20 -3
  200. package/dist/internal/providers.js.map +1 -1
  201. package/dist/internal/scrollbox.d.ts.map +1 -1
  202. package/dist/internal/scrollbox.js +3 -2
  203. package/dist/internal/scrollbox.js.map +1 -1
  204. package/dist/logger.d.ts.map +1 -1
  205. package/dist/logger.js +4 -0
  206. package/dist/logger.js.map +1 -1
  207. package/dist/preload.js +5 -17
  208. package/dist/preload.js.map +1 -1
  209. package/dist/state.d.ts +4 -0
  210. package/dist/state.d.ts.map +1 -1
  211. package/dist/state.js +4 -0
  212. package/dist/state.js.map +1 -1
  213. package/dist/test-border-overlay.d.ts +2 -0
  214. package/dist/test-border-overlay.d.ts.map +1 -0
  215. package/dist/test-border-overlay.js +7 -0
  216. package/dist/test-border-overlay.js.map +1 -0
  217. package/dist/test-layout-2.d.ts +2 -0
  218. package/dist/test-layout-2.d.ts.map +1 -0
  219. package/dist/test-layout-2.js +5 -0
  220. package/dist/test-layout-2.js.map +1 -0
  221. package/dist/test-layout.d.ts +2 -0
  222. package/dist/test-layout.d.ts.map +1 -0
  223. package/dist/test-layout.js +7 -0
  224. package/dist/test-layout.js.map +1 -0
  225. package/dist/theme.d.ts +1 -2
  226. package/dist/theme.d.ts.map +1 -1
  227. package/dist/theme.js +5 -9
  228. package/dist/theme.js.map +1 -1
  229. package/dist/utils/run-command.d.ts +1 -1
  230. package/dist/utils/run-command.d.ts.map +1 -1
  231. package/dist/utils/run-command.js +27 -7
  232. package/dist/utils/run-command.js.map +1 -1
  233. package/dist/utils.d.ts +1 -0
  234. package/dist/utils.d.ts.map +1 -1
  235. package/dist/utils.js +44 -23
  236. package/dist/utils.js.map +1 -1
  237. package/dist/watcher.d.ts.map +1 -1
  238. package/dist/watcher.js +24 -4
  239. package/dist/watcher.js.map +1 -1
  240. package/package.json +14 -12
  241. package/src/action-utils.tsx +10 -0
  242. package/src/apis/cache.test.ts +35 -3
  243. package/src/apis/cache.tsx +184 -59
  244. package/src/apis/clipboard.tsx +5 -0
  245. package/src/apis/oauth.tsx +33 -4
  246. package/src/build.tsx +35 -58
  247. package/src/cli.tsx +156 -134
  248. package/src/compile.tsx +6 -3
  249. package/src/compile.vitest.tsx +33 -15
  250. package/src/components/actions.tsx +230 -99
  251. package/src/components/alert.tsx +11 -10
  252. package/src/components/animation-tick.tsx +1 -1
  253. package/src/components/detail.tsx +56 -151
  254. package/src/components/dropdown.tsx +70 -36
  255. package/src/components/footer.tsx +58 -33
  256. package/src/components/form/checkbox.tsx +30 -32
  257. package/src/components/form/date-picker.tsx +27 -47
  258. package/src/components/form/description.tsx +19 -18
  259. package/src/components/form/dropdown.tsx +95 -103
  260. package/src/components/form/file-autocomplete.tsx +9 -8
  261. package/src/components/form/file-picker.tsx +46 -46
  262. package/src/components/form/form-end.tsx +6 -4
  263. package/src/components/form/index.tsx +38 -48
  264. package/src/components/form/password-field.tsx +25 -27
  265. package/src/components/form/separator.tsx +3 -2
  266. package/src/components/form/tagpicker.tsx +2 -1
  267. package/src/components/form/text-area.tsx +25 -30
  268. package/src/components/form/text-field.tsx +25 -27
  269. package/src/components/form/use-form-navigation.tsx +4 -5
  270. package/src/components/form/with-left-border.tsx +48 -10
  271. package/src/components/icon.tsx +69 -0
  272. package/src/components/image.tsx +60 -7
  273. package/src/components/list.tsx +270 -202
  274. package/src/components/loading-bar.tsx +4 -3
  275. package/src/components/metadata.tsx +217 -0
  276. package/src/components/theme-picker.tsx +3 -2
  277. package/src/examples/actions-context.tsx +63 -0
  278. package/src/examples/actions-context.vitest.tsx +110 -0
  279. package/src/examples/actions-dialog-layout.vitest.tsx +2 -1
  280. package/src/examples/file-autocomplete.vitest.tsx +15 -15
  281. package/src/examples/form-basic.tsx +12 -0
  282. package/src/examples/form-basic.vitest.tsx +74 -74
  283. package/src/examples/form-dropdown.tsx +8 -0
  284. package/src/examples/form-dropdown.vitest.tsx +364 -421
  285. package/src/examples/form-tagpicker.vitest.tsx +56 -54
  286. package/src/examples/github.vitest.tsx +252 -0
  287. package/src/examples/internal/rhf-custom-ref.tsx +16 -15
  288. package/src/examples/internal/scrollbox-with-descendants.tsx +4 -2
  289. package/src/examples/internal/simple-dialog.tsx +1 -1
  290. package/src/examples/internal/simple-scrollbox.vitest.tsx +14 -9
  291. package/src/examples/list-controlled-search.tsx +28 -0
  292. package/src/examples/list-controlled-search.vitest.tsx +49 -0
  293. package/src/examples/list-detail-metadata.tsx +8 -5
  294. package/src/examples/list-detail-metadata.vitest.tsx +22 -22
  295. package/src/examples/list-dropdown-default.vitest.tsx +12 -12
  296. package/src/examples/list-scrollbox.vitest.tsx +52 -38
  297. package/src/examples/list-with-detail.vitest.tsx +45 -41
  298. package/src/examples/list-with-dropdown.vitest.tsx +5 -5
  299. package/src/examples/list-with-sections.vitest.tsx +65 -12
  300. package/src/examples/list-with-toast.vitest.tsx +4 -4
  301. package/src/examples/simple-file-picker.vitest.tsx +12 -12
  302. package/src/examples/simple-grid.vitest.tsx +53 -53
  303. package/src/examples/simple-image-mask.tsx +58 -0
  304. package/src/examples/simple-navigation.vitest.tsx +19 -19
  305. package/src/examples/store.vitest.tsx +1 -1
  306. package/src/examples/swift-extension.vitest.tsx +4 -2
  307. package/src/examples/synonyms.vitest.tsx +31 -9
  308. package/src/examples/toast-action.vitest.tsx +8 -8
  309. package/src/examples/toast-variations.tsx +1 -1
  310. package/src/examples/toast-variations.vitest.tsx +69 -134
  311. package/src/extensions/dev.tsx +3 -2
  312. package/src/extensions/dev.vitest.tsx +65 -28
  313. package/src/extensions/react-refresh-init.tsx +4 -3
  314. package/src/index.tsx +3 -1
  315. package/src/internal/date-picker-widget.tsx +2 -1
  316. package/src/internal/dialog.tsx +100 -28
  317. package/src/internal/navigation.tsx +8 -1
  318. package/src/internal/offscreen.tsx +10 -0
  319. package/src/internal/providers.tsx +34 -8
  320. package/src/internal/scrollbox.tsx +4 -2
  321. package/src/logger.tsx +4 -0
  322. package/src/preload.tsx +5 -17
  323. package/src/state.tsx +12 -0
  324. package/src/theme.tsx +6 -9
  325. package/src/utils/run-command.tsx +32 -8
  326. package/src/utils.tsx +58 -23
  327. package/src/watcher.tsx +26 -6
@@ -0,0 +1,284 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
2
+ /**
3
+ * Custom Renderable Form Example
4
+ *
5
+ * Demonstrates hybrid pattern for building forms:
6
+ * - Form container = custom renderable (owns focus, navigation, scroll, RHF methods)
7
+ * - Form fields = React components wrapped in self-registering renderables
8
+ * - Tests dynamic field registration via timeout
9
+ *
10
+ * ## Architecture
11
+ *
12
+ * CustomFormRenderable (custom renderable)
13
+ * ├── owns: react-hook-form methods, focusedFieldId, field registry, scrollbox
14
+ * ├── methods: registerField(), focusField(), focusNext(), focusPrev()
15
+ * │
16
+ * └── CustomFormFieldWrapperRenderable (thin wrapper)
17
+ * ├── self-registers via onLifecyclePass (SYNC - no timing issues)
18
+ * └── React children (label, textarea) rendered inside
19
+ *
20
+ * ## Key Patterns
21
+ *
22
+ * 1. Wrapper renderable self-registers synchronously when added to tree
23
+ * 2. No useEffect needed for registration - onLifecyclePass handles it
24
+ * 3. Focus state in parent, checked in children each render
25
+ * 4. react-hook-form: useForm() in React, passed as prop to renderable, exposed via context
26
+ * 5. Tab navigation via parent methods (focusNext/focusPrev)
27
+ */
28
+ import { BoxRenderable, TextRenderable, ScrollBoxRenderable, } from '@opentui/core';
29
+ import { extend, useKeyboard } from '@opentui/react';
30
+ import { useIsInFocus } from 'termcast/src/internal/focus-context';
31
+ import { useRef, createContext, useContext, useState, useEffect } from 'react';
32
+ // Generic helper to find parent of specific type by traversing up
33
+ function findParent(node, type) {
34
+ let current = node.parent;
35
+ while (current) {
36
+ if (current instanceof type) {
37
+ return current;
38
+ }
39
+ current = current.parent;
40
+ }
41
+ return undefined;
42
+ }
43
+ import { renderWithProviders } from '../../utils';
44
+ import { useForm } from 'react-hook-form';
45
+ import { Theme } from 'termcast/src/theme';
46
+ // ─────────────────────────────────────────────────────────────────────────────
47
+ // CustomFormRenderable
48
+ // ─────────────────────────────────────────────────────────────────────────────
49
+ class CustomFormRenderable extends BoxRenderable {
50
+ // RHF integration - set by React as prop
51
+ formControl;
52
+ // Field registry - replaces useDescendants
53
+ fields = new Map();
54
+ fieldOrder = []; // ordered list for tab navigation
55
+ nextOrder = 0;
56
+ // Focus state
57
+ _focusedFieldId = null;
58
+ // UI components
59
+ scrollBox;
60
+ statusText;
61
+ constructor(ctx, options) {
62
+ super(ctx, { ...options, flexDirection: 'column' });
63
+ this.scrollBox = new ScrollBoxRenderable(ctx, { flexGrow: 1 });
64
+ this.statusText = new TextRenderable(ctx, { content: '0 fields', fg: Theme.textMuted });
65
+ super.add(this.scrollBox);
66
+ super.add(this.statusText);
67
+ }
68
+ // React children go to scrollbox
69
+ add(child, index) {
70
+ return this.scrollBox.add(child, index);
71
+ }
72
+ // React reconciler calls insertBefore when a new child must be inserted
73
+ // before an existing sibling. Example: delayed field inserted before "Field 1"
74
+ // Without this, dynamic children cause "Anchor does not exist" error
75
+ insertBefore(child, anchor) {
76
+ return this.scrollBox.insertBefore(child, anchor);
77
+ }
78
+ // Delegate remove to scrollbox
79
+ remove(id) {
80
+ this.scrollBox.remove(id);
81
+ }
82
+ // --- RHF Integration ---
83
+ // formControl is set by React as prop, use it directly
84
+ getValues() {
85
+ return this.formControl?.getValues() ?? {};
86
+ }
87
+ setValue(name, value) {
88
+ this.formControl?.setValue(name, value);
89
+ }
90
+ // --- Field Registration ---
91
+ // Called by wrapper renderables via onLifecyclePass (SYNC)
92
+ registerField(id, wrapper) {
93
+ this.fields.set(id, { id, elementRef: wrapper, order: this.nextOrder++ });
94
+ this.updateFieldOrder();
95
+ // Update status text immediately
96
+ this.statusText.content = `${this.fieldOrder.length} fields registered`;
97
+ this.requestRender();
98
+ // Auto-focus first field
99
+ if (this.fieldOrder.length === 1 && !this._focusedFieldId) {
100
+ this._focusedFieldId = id;
101
+ if (wrapper instanceof CustomFormFieldWrapperRenderable) {
102
+ wrapper.setFocused(true);
103
+ }
104
+ }
105
+ }
106
+ unregisterField(id) {
107
+ this.fields.delete(id);
108
+ this.updateFieldOrder();
109
+ this.statusText.content = `${this.fieldOrder.length} fields registered`;
110
+ this.requestRender();
111
+ }
112
+ updateFieldOrder() {
113
+ this.fieldOrder = Array.from(this.fields.values())
114
+ .sort((a, b) => a.order - b.order)
115
+ .map((f) => f.id);
116
+ }
117
+ // --- Focus Management ---
118
+ get focusedFieldId() {
119
+ return this._focusedFieldId;
120
+ }
121
+ focusField(id) {
122
+ if (!this.fields.has(id))
123
+ return;
124
+ // Update focus state on wrappers
125
+ const oldField = this._focusedFieldId ? this.fields.get(this._focusedFieldId) : null;
126
+ const newField = this.fields.get(id);
127
+ if (oldField?.elementRef instanceof CustomFormFieldWrapperRenderable) {
128
+ oldField.elementRef.setFocused(false);
129
+ }
130
+ if (newField?.elementRef instanceof CustomFormFieldWrapperRenderable) {
131
+ newField.elementRef.setFocused(true);
132
+ }
133
+ this._focusedFieldId = id;
134
+ this.scrollToField(id);
135
+ this.requestRender();
136
+ }
137
+ focusNext() {
138
+ if (this.fieldOrder.length === 0)
139
+ return;
140
+ const idx = this._focusedFieldId ? this.fieldOrder.indexOf(this._focusedFieldId) : -1;
141
+ const nextIdx = (idx + 1) % this.fieldOrder.length;
142
+ this.focusField(this.fieldOrder[nextIdx]);
143
+ }
144
+ focusPrev() {
145
+ if (this.fieldOrder.length === 0)
146
+ return;
147
+ const idx = this._focusedFieldId ? this.fieldOrder.indexOf(this._focusedFieldId) : 0;
148
+ const prevIdx = (idx - 1 + this.fieldOrder.length) % this.fieldOrder.length;
149
+ this.focusField(this.fieldOrder[prevIdx]);
150
+ }
151
+ scrollToField(id) {
152
+ const field = this.fields.get(id);
153
+ if (!field?.elementRef)
154
+ return;
155
+ const itemY = field.elementRef.y;
156
+ const scrollBoxY = this.scrollBox.content.y;
157
+ const viewportHeight = this.scrollBox.viewport?.height || 10;
158
+ const relativeY = itemY - scrollBoxY;
159
+ const targetScrollTop = relativeY - Math.floor(viewportHeight / 2);
160
+ this.scrollBox.scrollTop = Math.max(0, targetScrollTop);
161
+ }
162
+ }
163
+ class CustomFormFieldWrapperRenderable extends BoxRenderable {
164
+ parentForm;
165
+ focusIndicator;
166
+ contentBox;
167
+ isFocusedField = false;
168
+ // Set by React after constructor
169
+ fieldId = '';
170
+ constructor(ctx, options) {
171
+ // Outer wrapper is a row: [indicator] [content column]
172
+ super(ctx, { ...options, flexDirection: 'row', paddingBottom: 1 });
173
+ // Focus indicator - updated by parent form
174
+ this.focusIndicator = new TextRenderable(ctx, { content: ' ', flexShrink: 0 });
175
+ super.add(this.focusIndicator);
176
+ // Content box holds React children in a column
177
+ this.contentBox = new BoxRenderable(ctx, { flexDirection: 'column', flexGrow: 1 });
178
+ super.add(this.contentBox);
179
+ // SYNC registration when added to tree - no timing issues
180
+ this.onLifecyclePass = () => {
181
+ if (!this.parentForm && this.fieldId) {
182
+ this.parentForm = findParent(this, CustomFormRenderable);
183
+ this.parentForm?.registerField(this.fieldId, this);
184
+ }
185
+ };
186
+ }
187
+ // React children go into the content box
188
+ add(child, index) {
189
+ return this.contentBox.add(child, index);
190
+ }
191
+ // React reconciler calls insertBefore when a new child must be inserted
192
+ // before an existing sibling. Not strictly needed here since wrapper children
193
+ // (title, textarea) are always added in fixed order, but included for safety
194
+ // in case future usage adds dynamic children inside the wrapper
195
+ insertBefore(child, anchor) {
196
+ return this.contentBox.insertBefore(child, anchor);
197
+ }
198
+ // Called by parent form when focus changes
199
+ setFocused(focused) {
200
+ if (this.isFocusedField === focused)
201
+ return;
202
+ this.isFocusedField = focused;
203
+ this.focusIndicator.content = focused ? '› ' : ' ';
204
+ this.focusIndicator.fg = focused ? Theme.primary : undefined;
205
+ this.requestRender();
206
+ }
207
+ }
208
+ // ─────────────────────────────────────────────────────────────────────────────
209
+ // Register with opentui
210
+ // ─────────────────────────────────────────────────────────────────────────────
211
+ extend({
212
+ 'custom-form': CustomFormRenderable,
213
+ 'custom-form-field-wrapper': CustomFormFieldWrapperRenderable,
214
+ });
215
+ const CustomFormContext = createContext(null);
216
+ function useCustomForm() {
217
+ const ctx = useContext(CustomFormContext);
218
+ if (!ctx)
219
+ throw new Error('Must be inside CustomForm');
220
+ return ctx;
221
+ }
222
+ function CustomForm({ children }) {
223
+ const formRef = useRef(null);
224
+ const methods = useForm();
225
+ const inFocus = useIsInFocus();
226
+ // Tab navigation
227
+ useKeyboard((evt) => {
228
+ if (!inFocus || !formRef.current)
229
+ return;
230
+ if (evt.name === 'tab') {
231
+ if (evt.shift) {
232
+ formRef.current.focusPrev();
233
+ }
234
+ else {
235
+ formRef.current.focusNext();
236
+ }
237
+ }
238
+ });
239
+ // Pass formControl as prop to renderable, expose methods via context
240
+ return (_jsx(CustomFormContext.Provider, { value: { formRef, methods }, children: _jsx("custom-form", { ref: formRef, formControl: methods, flexGrow: 1, children: children }) }));
241
+ }
242
+ function CustomFormTextField({ id, title, placeholder }) {
243
+ const { formRef, methods } = useCustomForm();
244
+ const inputRef = useRef(null);
245
+ // No useEffect needed - wrapper self-registers via onLifecyclePass
246
+ // Check if focused - read from parent each render
247
+ const isFocused = formRef.current?.focusedFieldId === id;
248
+ // RHF integration - use methods from context (no useFormContext needed)
249
+ const registration = methods.register(id);
250
+ const handleContentChange = () => {
251
+ registration.onChange({
252
+ target: { name: id, value: inputRef.current?.plainText || '' },
253
+ type: 'change',
254
+ });
255
+ };
256
+ // Focus indicator is rendered by the wrapper renderable (updates synchronously)
257
+ return (_jsxs("custom-form-field-wrapper", { fieldId: id, children: [_jsx("text", { fg: isFocused ? Theme.primary : Theme.text, children: title }), _jsx("textarea", { ref: inputRef, height: 1, placeholder: placeholder, focused: isFocused, keyBindings: [
258
+ { name: 'return', action: 'submit' },
259
+ { name: 'linefeed', action: 'submit' },
260
+ ], onContentChange: handleContentChange })] }));
261
+ }
262
+ // Add compound component
263
+ CustomForm.TextField = CustomFormTextField;
264
+ // ─────────────────────────────────────────────────────────────────────────────
265
+ // Example with dynamic field via useEffect
266
+ // ─────────────────────────────────────────────────────────────────────────────
267
+ function Example() {
268
+ const [showDelayedField, setShowDelayedField] = useState(false);
269
+ // Test: add field after timeout
270
+ useEffect(() => {
271
+ const timer = setTimeout(() => {
272
+ setShowDelayedField(true);
273
+ }, 2000);
274
+ return () => {
275
+ clearTimeout(timer);
276
+ };
277
+ }, []);
278
+ return (_jsxs("box", { flexDirection: "column", padding: 1, flexGrow: 1, children: [_jsx("text", { marginBottom: 1, children: "Custom Form Renderable Example" }), _jsx("text", { fg: Theme.textMuted, marginBottom: 1, children: "Tab to navigate \u2022 Dynamic field appears after 2s" }), _jsxs(CustomForm, { children: [_jsx(CustomForm.TextField, { id: "name", title: "Name", placeholder: "Enter name..." }), _jsx(CustomForm.TextField, { id: "email", title: "Email", placeholder: "Enter email..." }), _jsx(CustomForm.TextField, { id: "phone", title: "Phone", placeholder: "Enter phone..." }), showDelayedField && (_jsx(CustomForm.TextField, { id: "delayed", title: "Delayed Field (added after 2s)", placeholder: "Dynamic field..." })), Array.from({ length: 8 }, (_, i) => (_jsx(CustomForm.TextField, { id: `field-${i}`, title: `Field ${i + 1}`, placeholder: `Enter field ${i + 1}...` }, `field-${i}`)))] })] }));
279
+ }
280
+ if (import.meta.main) {
281
+ renderWithProviders(_jsx(Example, {}));
282
+ }
283
+ export { CustomForm, CustomFormTextField, Example };
284
+ //# sourceMappingURL=custom-renderable-form.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-renderable-form.js","sourceRoot":"","sources":["../../../src/examples/internal/custom-renderable-form.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=custom-renderable-list-default-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-renderable-list-default-search.d.ts","sourceRoot":"","sources":["../../../src/examples/internal/custom-renderable-list-default-search.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
2
+ /**
3
+ * Test file for defaultSearchQuery prop
4
+ */
5
+ import { renderWithProviders } from '../../utils';
6
+ import { CustomList } from './custom-renderable-list';
7
+ const ITEMS = [
8
+ { title: 'Apple', subtitle: 'Red fruit' },
9
+ { title: 'Banana', subtitle: 'Yellow fruit' },
10
+ { title: 'Cherry', subtitle: 'Small red fruit' },
11
+ ];
12
+ function Test() {
13
+ return (_jsxs("box", { flexDirection: "column", padding: 1, flexGrow: 1, children: [_jsx("text", { marginBottom: 1, children: "Default Search Test" }), _jsx(CustomList, { defaultSearchQuery: "banana", children: ITEMS.map((item) => (_jsx(CustomList.Item, { title: item.title, subtitle: item.subtitle }, item.title))) })] }));
14
+ }
15
+ renderWithProviders(_jsx(Test, {}));
16
+ //# sourceMappingURL=custom-renderable-list-default-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-renderable-list-default-search.js","sourceRoot":"","sources":["../../../src/examples/internal/custom-renderable-list-default-search.tsx"],"names":[],"mappings":";AAAA;;GAEG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAErD,MAAM,KAAK,GAAG;IACZ,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE;IACzC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE;IAC7C,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,EAAE;CACjD,CAAA;AAED,SAAS,IAAI;IACX,OAAO,CACL,eAAK,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,aACjD,eAAM,YAAY,EAAE,CAAC,oCAA4B,EACjD,KAAC,UAAU,IAAC,kBAAkB,EAAC,QAAQ,YACpC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,KAAC,UAAU,CAAC,IAAI,IAAkB,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAtD,IAAI,CAAC,KAAK,CAAgD,CACjF,CAAC,GACS,IACT,CACP,CAAA;AACH,CAAC;AAED,mBAAmB,CAAC,KAAC,IAAI,KAAG,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=custom-renderable-list-v2-default-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-renderable-list-v2-default-search.d.ts","sourceRoot":"","sources":["../../../src/examples/internal/custom-renderable-list-v2-default-search.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
2
+ /**
3
+ * Test file for defaultSearchQuery prop (v2)
4
+ */
5
+ import { renderWithProviders } from '../../utils';
6
+ import { CustomList, useCustomListStore } from './custom-renderable-list-v2';
7
+ const ITEMS = [
8
+ { title: 'Apple', subtitle: 'Red fruit' },
9
+ { title: 'Banana', subtitle: 'Yellow fruit' },
10
+ { title: 'Cherry', subtitle: 'Small red fruit' },
11
+ ];
12
+ function Test() {
13
+ return (_jsxs("box", { flexDirection: "column", padding: 1, flexGrow: 1, children: [_jsx("text", { marginBottom: 1, children: "Default Search Test" }), _jsx(CustomList, { defaultSearchQuery: "banana", children: ITEMS.map((item) => (_jsx(CustomList.Item, { title: item.title, subtitle: item.subtitle }, item.title))) })] }));
14
+ }
15
+ // Reset store before running
16
+ useCustomListStore.setState({
17
+ selectedIndex: 0,
18
+ visibleCount: 0,
19
+ totalCount: 0,
20
+ searchQuery: '',
21
+ itemStates: {},
22
+ });
23
+ renderWithProviders(_jsx(Test, {}));
24
+ //# sourceMappingURL=custom-renderable-list-v2-default-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-renderable-list-v2-default-search.js","sourceRoot":"","sources":["../../../src/examples/internal/custom-renderable-list-v2-default-search.tsx"],"names":[],"mappings":";AAAA;;GAEG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAE5E,MAAM,KAAK,GAAG;IACZ,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE;IACzC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE;IAC7C,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,EAAE;CACjD,CAAA;AAED,SAAS,IAAI;IACX,OAAO,CACL,eAAK,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,aACjD,eAAM,YAAY,EAAE,CAAC,oCAA4B,EACjD,KAAC,UAAU,IAAC,kBAAkB,EAAC,QAAQ,YACpC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,KAAC,UAAU,CAAC,IAAI,IAAkB,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAtD,IAAI,CAAC,KAAK,CAAgD,CACjF,CAAC,GACS,IACT,CACP,CAAA;AACH,CAAC;AAED,6BAA6B;AAC7B,kBAAkB,CAAC,QAAQ,CAAC;IAC1B,aAAa,EAAE,CAAC;IAChB,YAAY,EAAE,CAAC;IACf,UAAU,EAAE,CAAC;IACb,WAAW,EAAE,EAAE;IACf,UAAU,EAAE,EAAE;CACf,CAAC,CAAA;AAEF,mBAAmB,CAAC,KAAC,IAAI,KAAG,CAAC,CAAA"}
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Custom Renderable List V2 - Wrapper Pattern
3
+ *
4
+ * This example uses opentui's extend() to register thin wrapper renderables
5
+ * that handle tracking and visibility, while React handles all UI rendering.
6
+ *
7
+ * ## Architecture
8
+ *
9
+ * CustomListRenderable (custom renderable)
10
+ * ├── owns: filtering logic, navigation, scrolling
11
+ * ├── children redirected to scrollBox
12
+ * │
13
+ * └── CustomListItemWrapperRenderable (thin wrapper)
14
+ * ├── tracks: keywords, onAction, section, visibleIndex, itemId
15
+ * ├── handles: visibility (height: 0 when hidden)
16
+ * └── React children render all UI (indicator, title, subtitle)
17
+ *
18
+ * ## Key Patterns
19
+ *
20
+ * 1. Wrapper renderables self-register via onLifecyclePass (SYNC)
21
+ * 2. All UI in JSX - wrappers only track/hide
22
+ * 3. Zustand store for React state (selectedIndex, visibleCount, searchQuery)
23
+ * 4. Renderable calls zustand.setState to trigger React re-renders
24
+ * 5. Items compare visibleIndex to selectedIndex from zustand
25
+ *
26
+ * ## Phase 1: Bidirectional Selection Sync
27
+ *
28
+ * - `selectedItemId` prop on List controls selection by item id
29
+ * - `onSelectionChange` callback fires when selection changes
30
+ * - Supports both controlled (via prop) and uncontrolled (internal) selection
31
+ *
32
+ * ## Phase 2: Detail Panel Support
33
+ *
34
+ * - `isShowingDetail` prop on List enables detail panel on the right
35
+ * - `detail` prop on Item provides React node to render in detail panel
36
+ * - Detail updates automatically when selection changes
37
+ * - List splits into two columns when detail is shown
38
+ *
39
+ * ## How React Props Work with opentui Renderables
40
+ *
41
+ * React props are applied via direct property assignment, NOT just constructor:
42
+ *
43
+ * 1. `createInstance()` - constructor called (props passed in options)
44
+ * 2. `setInitialProperties()` - iterates props, does `instance[propKey] = propValue`
45
+ * 3. `commitUpdate()` - on re-render, applies changed props via `instance[propKey] = propValue`
46
+ *
47
+ * This means:
48
+ * - Props don't need to be read from constructor options - React sets them after
49
+ * - Simple props (just stored/read later) can be public fields
50
+ * - Props that need side effects on change require setters
51
+ * - Constructor should just create the renderable structure
52
+ *
53
+ * ─────────────────────────────────────────────────────────────────────────────
54
+ * ## Migration Notes (Lessons from Form conversion)
55
+ * ─────────────────────────────────────────────────────────────────────────────
56
+ *
57
+ * ### 1. Registration Order ≠ Visual Order
58
+ *
59
+ * IMPORTANT: `onLifecyclePass` is called in tree traversal order, which may NOT
60
+ * match the visual/React render order. For Form, we solved this by sorting
61
+ * fields by y-position instead of registration order:
62
+ *
63
+ * ```typescript
64
+ * private getFieldOrder(): string[] {
65
+ * return Array.from(this.fields.values())
66
+ * .sort((a, b) => (a.elementRef?.y ?? 0) - (b.elementRef?.y ?? 0))
67
+ * .map((f) => f.id)
68
+ * }
69
+ * ```
70
+ *
71
+ * For List, this is less critical since items use visibleIndex from filtering,
72
+ * but be aware if you need stable ordering based on visual position.
73
+ *
74
+ * ### 2. Auto-Focus Pattern
75
+ *
76
+ * Don't auto-focus in registerField() - registration order is unpredictable.
77
+ * Instead, use React useEffect that runs until focus is set:
78
+ *
79
+ * ```typescript
80
+ * useEffect(() => {
81
+ * if (focusedField) return
82
+ * const firstId = formRef.current?.getFirstFieldId()
83
+ * if (firstId) formRef.current?.focusField(firstId)
84
+ * })
85
+ * ```
86
+ *
87
+ * ### 3. Hybrid Approach - Keep React for Styling
88
+ *
89
+ * The renderable should only handle STATE (registry, focus, scroll).
90
+ * Keep existing React components for UI (e.g., WithLeftBorder for Form).
91
+ * This ensures visual output stays identical - only the wiring changes.
92
+ *
93
+ * ### 4. Focus State Sync to React
94
+ *
95
+ * Form uses `onFocusChange` callback to sync focus to React state:
96
+ *
97
+ * ```typescript
98
+ * // In FormRenderable
99
+ * public onFocusChange?: (fieldId: string | null) => void
100
+ *
101
+ * focusField(id: string) {
102
+ * this._focusedFieldId = id
103
+ * this.onFocusChange?.(id) // Notify React
104
+ * }
105
+ *
106
+ * // In Form component
107
+ * const handleFormRef = (ref: FormRenderable | null) => {
108
+ * formRef.current = ref
109
+ * if (ref) ref.onFocusChange = setFocusedField
110
+ * }
111
+ * ```
112
+ *
113
+ * This example uses zustand instead (setState triggers re-render).
114
+ * Both patterns work - zustand is simpler for shared state.
115
+ *
116
+ * ### 5. Legacy Compatibility
117
+ *
118
+ * When migrating, keep old descendants/context during transition:
119
+ *
120
+ * ```typescript
121
+ * // Keep old system for components not yet migrated
122
+ * const { DescendantsProvider, useDescendant } = createDescendants<...>()
123
+ * export { useDescendant } // Still exported for old components
124
+ * ```
125
+ *
126
+ * ### 6. Field Component Changes
127
+ *
128
+ * Each field component needs minimal changes:
129
+ * - Remove: useFormFieldDescendant() call, elementRef
130
+ * - Add: wrap return in <termcast-form-field-wrapper fieldId={id}>
131
+ * - Keep: all UI code (WithLeftBorder, etc.) unchanged
132
+ *
133
+ * ### 7. Testing Strategy
134
+ *
135
+ * Run existing tests with -u to update snapshots. Visual output should be
136
+ * identical - if tests fail, the wiring is wrong, not the rendering.
137
+ * ─────────────────────────────────────────────────────────────────────────────
138
+ */
139
+ import React from 'react';
140
+ interface ItemState {
141
+ visibleIndex: number;
142
+ }
143
+ interface CustomListStoreState {
144
+ selectedIndex: number;
145
+ visibleCount: number;
146
+ totalCount: number;
147
+ searchQuery: string;
148
+ itemStates: Record<string, ItemState>;
149
+ selectedItemId: string | null;
150
+ isShowingDetail: boolean;
151
+ currentDetailNode: React.ReactNode | null;
152
+ }
153
+ declare const useCustomListStore: import("zustand").UseBoundStore<import("zustand").StoreApi<CustomListStoreState>>;
154
+ interface ListProps {
155
+ children?: React.ReactNode;
156
+ placeholder?: string;
157
+ defaultSearchQuery?: string;
158
+ selectedItemId?: string | null;
159
+ onSelectionChange?: (id: string | null) => void;
160
+ isShowingDetail?: boolean;
161
+ }
162
+ declare function CustomList({ children, placeholder, defaultSearchQuery, selectedItemId, onSelectionChange, isShowingDetail }: ListProps): any;
163
+ declare namespace CustomList {
164
+ var Item: typeof CustomListItem;
165
+ var Section: typeof CustomListSection;
166
+ var EmptyView: typeof CustomListEmptyView;
167
+ }
168
+ interface ListItemProps {
169
+ id?: string;
170
+ title: string;
171
+ subtitle?: string;
172
+ keywords?: string[];
173
+ onAction?: () => void;
174
+ detail?: React.ReactNode;
175
+ }
176
+ declare function CustomListItem({ id, title, subtitle, keywords, onAction, detail }: ListItemProps): any;
177
+ interface ListSectionProps {
178
+ title?: string;
179
+ children?: React.ReactNode;
180
+ }
181
+ declare function CustomListSection({ title, children }: ListSectionProps): any;
182
+ interface ListEmptyViewProps {
183
+ title?: string;
184
+ description?: string;
185
+ }
186
+ declare function CustomListEmptyView({ title, description }: ListEmptyViewProps): any;
187
+ declare function Example(): any;
188
+ export { CustomList, CustomListItem, CustomListSection, CustomListEmptyView, Example, useCustomListStore };
189
+ //# sourceMappingURL=custom-renderable-list-v2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-renderable-list-v2.d.ts","sourceRoot":"","sources":["../../../src/examples/internal/custom-renderable-list-v2.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyIG;AAcH,OAAO,KAA2B,MAAM,OAAO,CAAA;AAS/C,UAAU,SAAS;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,UAAU,oBAAoB;IAC5B,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IAEnB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAIrC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAE7B,eAAe,EAAE,OAAO,CAAA;IACxB,iBAAiB,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI,CAAA;CAC1C;AAED,QAAA,MAAM,kBAAkB,mFASrB,CAAA;AAihBH,UAAU,SAAS;IACjB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAE3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,iBAAiB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IAE/C,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED,iBAAS,UAAU,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAAE,EAAE,SAAS,GAAG,GAAG,CA4ErI;kBA5EQ,UAAU;;;;;AAkFnB,UAAU,aAAa;IACrB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IAErB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACzB;AAED,iBAAS,cAAc,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,aAAa,GAAG,GAAG,CA4B/F;AAMD,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC3B;AAED,iBAAS,iBAAiB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,gBAAgB,GAAG,GAAG,CAYrE;AAMD,UAAU,kBAAkB;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,iBAAS,mBAAmB,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,kBAAkB,GAAG,GAAG,CAE5E;AAmCD,iBAAS,OAAO,IAAI,GAAG,CAoFtB;AAgBD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAA"}