termcast 1.3.9 → 1.3.16
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.
- package/dist/action-utils.js +1 -1
- package/dist/action-utils.js.map +1 -1
- package/dist/apis/ai.js +1 -1
- package/dist/apis/ai.js.map +1 -1
- package/dist/apis/clipboard.js +2 -2
- package/dist/apis/clipboard.js.map +1 -1
- package/dist/apis/hud.d.ts +2 -2
- package/dist/apis/hud.d.ts.map +1 -1
- package/dist/apis/hud.js +5 -5
- package/dist/apis/hud.js.map +1 -1
- package/dist/apis/oauth.d.ts +1 -1
- package/dist/apis/oauth.d.ts.map +1 -1
- package/dist/apis/oauth.js +8 -8
- package/dist/apis/oauth.js.map +1 -1
- package/dist/apis/preferences.js +4 -4
- package/dist/apis/preferences.js.map +1 -1
- package/dist/apis/toast.d.ts +1 -5
- package/dist/apis/toast.d.ts.map +1 -1
- package/dist/apis/toast.js +26 -20
- package/dist/apis/toast.js.map +1 -1
- package/dist/build.d.ts +2 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +9 -8
- package/dist/build.js.map +1 -1
- package/dist/cli.js +44 -2
- package/dist/cli.js.map +1 -1
- package/dist/colors.d.ts +8 -1
- package/dist/colors.d.ts.map +1 -1
- package/dist/colors.js +12 -0
- package/dist/colors.js.map +1 -1
- package/dist/compile.d.ts +30 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +156 -0
- package/dist/compile.js.map +1 -0
- package/dist/components/actions.d.ts +2 -1
- package/dist/components/actions.d.ts.map +1 -1
- package/dist/components/actions.js +11 -8
- package/dist/components/actions.js.map +1 -1
- package/dist/components/alert.js +4 -4
- package/dist/components/alert.js.map +1 -1
- package/dist/components/command-arguments.d.ts +9 -0
- package/dist/components/command-arguments.d.ts.map +1 -0
- package/dist/components/command-arguments.js +21 -0
- package/dist/components/command-arguments.js.map +1 -0
- package/dist/components/detail.d.ts +3 -3
- package/dist/components/detail.d.ts.map +1 -1
- package/dist/components/detail.js +20 -42
- package/dist/components/detail.js.map +1 -1
- package/dist/components/dropdown.d.ts +2 -1
- package/dist/components/dropdown.d.ts.map +1 -1
- package/dist/components/dropdown.js +81 -25
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/extension-preferences.d.ts.map +1 -1
- package/dist/components/extension-preferences.js +23 -33
- package/dist/components/extension-preferences.js.map +1 -1
- package/dist/components/form/checkbox.d.ts.map +1 -1
- package/dist/components/form/checkbox.js +11 -4
- package/dist/components/form/checkbox.js.map +1 -1
- package/dist/components/form/date-picker.d.ts.map +1 -1
- package/dist/components/form/date-picker.js +18 -31
- package/dist/components/form/date-picker.js.map +1 -1
- package/dist/components/form/description.d.ts +2 -0
- package/dist/components/form/description.d.ts.map +1 -1
- package/dist/components/form/description.js +21 -3
- package/dist/components/form/description.js.map +1 -1
- package/dist/components/form/dropdown.d.ts.map +1 -1
- package/dist/components/form/dropdown.js +17 -32
- package/dist/components/form/dropdown.js.map +1 -1
- package/dist/components/form/file-autocomplete.d.ts +7 -4
- package/dist/components/form/file-autocomplete.d.ts.map +1 -1
- package/dist/components/form/file-autocomplete.js +56 -48
- package/dist/components/form/file-autocomplete.js.map +1 -1
- package/dist/components/form/file-picker.d.ts +5 -0
- package/dist/components/form/file-picker.d.ts.map +1 -1
- package/dist/components/form/file-picker.js +48 -51
- package/dist/components/form/file-picker.js.map +1 -1
- package/dist/components/form/form-end.js +1 -1
- package/dist/components/form/form-end.js.map +1 -1
- package/dist/components/form/form-ref.d.ts +43 -0
- package/dist/components/form/form-ref.d.ts.map +1 -0
- package/dist/components/form/form-ref.js +53 -0
- package/dist/components/form/form-ref.js.map +1 -0
- package/dist/components/form/index.d.ts +16 -0
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/index.js +90 -27
- package/dist/components/form/index.js.map +1 -1
- package/dist/components/form/password-field.d.ts.map +1 -1
- package/dist/components/form/password-field.js +33 -17
- package/dist/components/form/password-field.js.map +1 -1
- package/dist/components/form/separator.js +1 -1
- package/dist/components/form/separator.js.map +1 -1
- package/dist/components/form/tagpicker.d.ts +1 -1
- package/dist/components/form/tagpicker.d.ts.map +1 -1
- package/dist/components/form/text-area.d.ts.map +1 -1
- package/dist/components/form/text-area.js +33 -16
- package/dist/components/form/text-area.js.map +1 -1
- package/dist/components/form/text-field.d.ts.map +1 -1
- package/dist/components/form/text-field.js +38 -18
- package/dist/components/form/text-field.js.map +1 -1
- package/dist/components/form/use-form-navigation.d.ts +4 -0
- package/dist/components/form/use-form-navigation.d.ts.map +1 -1
- package/dist/components/form/use-form-navigation.js +35 -18
- package/dist/components/form/use-form-navigation.js.map +1 -1
- package/dist/components/form/with-left-border.d.ts.map +1 -1
- package/dist/components/form/with-left-border.js +3 -3
- package/dist/components/form/with-left-border.js.map +1 -1
- package/dist/components/icon.d.ts +3 -1
- package/dist/components/icon.d.ts.map +1 -1
- package/dist/components/icon.js +494 -469
- package/dist/components/icon.js.map +1 -1
- package/dist/components/image.js +1 -1
- package/dist/components/image.js.map +1 -1
- package/dist/components/list.d.ts +12 -8
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/list.js +172 -40
- package/dist/components/list.js.map +1 -1
- package/dist/components/loading-bar.js +2 -2
- package/dist/components/loading-bar.js.map +1 -1
- package/dist/components/menubar-extra.d.ts +1 -1
- package/dist/components/menubar-extra.d.ts.map +1 -1
- package/dist/components/menubar-extra.js +2 -2
- package/dist/components/menubar-extra.js.map +1 -1
- package/dist/descendants.d.ts.map +1 -1
- package/dist/descendants.js +8 -5
- package/dist/descendants.js.map +1 -1
- package/dist/e2e-node.d.ts +2 -0
- package/dist/e2e-node.d.ts.map +1 -1
- package/dist/e2e-node.js +14 -0
- package/dist/e2e-node.js.map +1 -1
- package/dist/examples/action-show-in-finder.js +3 -3
- package/dist/examples/action-show-in-finder.js.map +1 -1
- package/dist/examples/environment-test.js +4 -4
- package/dist/examples/environment-test.js.map +1 -1
- package/dist/examples/error-boundary.js +5 -5
- package/dist/examples/error-boundary.js.map +1 -1
- package/dist/examples/form-basic.d.ts.map +1 -1
- package/dist/examples/form-basic.js +6 -6
- package/dist/examples/form-basic.js.map +1 -1
- package/dist/examples/form-dropdown.js +3 -3
- package/dist/examples/form-dropdown.js.map +1 -1
- package/dist/examples/form-scroll.d.ts +2 -0
- package/dist/examples/form-scroll.d.ts.map +1 -0
- package/dist/examples/form-scroll.js +8 -0
- package/dist/examples/form-scroll.js.map +1 -0
- package/dist/examples/form-tagpicker.js +3 -3
- package/dist/examples/form-tagpicker.js.map +1 -1
- package/dist/examples/internal/descendants-filtering.js +10 -5
- package/dist/examples/internal/descendants-filtering.js.map +1 -1
- package/dist/examples/internal/descendants.js +13 -6
- package/dist/examples/internal/descendants.js.map +1 -1
- package/dist/examples/internal/rhf-custom-ref.d.ts +2 -0
- package/dist/examples/internal/rhf-custom-ref.d.ts.map +1 -0
- package/dist/examples/internal/rhf-custom-ref.js +67 -0
- package/dist/examples/internal/rhf-custom-ref.js.map +1 -0
- package/dist/examples/internal/scrollbox-demo.js +4 -8
- package/dist/examples/internal/scrollbox-demo.js.map +1 -1
- package/dist/examples/internal/scrollbox-with-descendants.d.ts +2 -0
- package/dist/examples/internal/scrollbox-with-descendants.d.ts.map +1 -0
- package/dist/examples/internal/scrollbox-with-descendants.js +63 -0
- package/dist/examples/internal/scrollbox-with-descendants.js.map +1 -0
- package/dist/examples/internal/simple-dialog.js +7 -7
- package/dist/examples/internal/simple-dialog.js.map +1 -1
- package/dist/examples/internal/simple-scrollbox.d.ts +2 -0
- package/dist/examples/internal/simple-scrollbox.d.ts.map +1 -0
- package/dist/examples/internal/simple-scrollbox.js +25 -0
- package/dist/examples/internal/simple-scrollbox.js.map +1 -0
- package/dist/examples/internal/text-stacking.js +4 -2
- package/dist/examples/internal/text-stacking.js.map +1 -1
- package/dist/examples/list-dropdown-default.js +3 -3
- package/dist/examples/list-dropdown-default.js.map +1 -1
- package/dist/examples/list-fetch-data.js +3 -3
- package/dist/examples/list-fetch-data.js.map +1 -1
- package/dist/examples/list-scrollbox.d.ts +2 -0
- package/dist/examples/list-scrollbox.d.ts.map +1 -0
- package/dist/examples/list-scrollbox.js +29 -0
- package/dist/examples/list-scrollbox.js.map +1 -0
- package/dist/examples/list-with-detail.js +2 -2
- package/dist/examples/list-with-detail.js.map +1 -1
- package/dist/examples/list-with-dropdown.js +2 -2
- package/dist/examples/list-with-dropdown.js.map +1 -1
- package/dist/examples/list-with-sections.js +6 -6
- package/dist/examples/list-with-sections.js.map +1 -1
- package/dist/examples/miscellaneous.js +14 -14
- package/dist/examples/miscellaneous.js.map +1 -1
- package/dist/examples/nested-navigation.js +9 -7
- package/dist/examples/nested-navigation.js.map +1 -1
- package/dist/examples/preferences-test.js +4 -4
- package/dist/examples/preferences-test.js.map +1 -1
- package/dist/examples/simple-dropdown.js +4 -4
- package/dist/examples/simple-dropdown.js.map +1 -1
- package/dist/examples/simple-file-picker.js +3 -3
- package/dist/examples/simple-file-picker.js.map +1 -1
- package/dist/examples/simple-grid.js +2 -2
- package/dist/examples/simple-grid.js.map +1 -1
- package/dist/examples/simple-hud.js +4 -4
- package/dist/examples/simple-hud.js.map +1 -1
- package/dist/examples/simple-list-search.js +21 -5
- package/dist/examples/simple-list-search.js.map +1 -1
- package/dist/examples/simple-list.js +4 -4
- package/dist/examples/simple-list.js.map +1 -1
- package/dist/examples/simple-navigation.js +9 -7
- package/dist/examples/simple-navigation.js.map +1 -1
- package/dist/examples/store.js +1 -1
- package/dist/examples/store.js.map +1 -1
- package/dist/examples/submodule-diff.d.ts +2 -0
- package/dist/examples/submodule-diff.d.ts.map +1 -0
- package/dist/examples/submodule-diff.js +99 -0
- package/dist/examples/submodule-diff.js.map +1 -0
- package/dist/examples/tanstack-demo.js +3 -3
- package/dist/examples/tanstack-demo.js.map +1 -1
- package/dist/examples/use-promise-demo.js +3 -3
- package/dist/examples/use-promise-demo.js.map +1 -1
- package/dist/extensions/dev.d.ts +8 -0
- package/dist/extensions/dev.d.ts.map +1 -1
- package/dist/extensions/dev.js +60 -35
- package/dist/extensions/dev.js.map +1 -1
- package/dist/extensions/home.d.ts.map +1 -1
- package/dist/extensions/home.js +22 -97
- package/dist/extensions/home.js.map +1 -1
- package/dist/extensions/store.js +2 -2
- package/dist/extensions/store.js.map +1 -1
- package/dist/globals.js +1 -1
- package/dist/globals.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/use-action-panel.js +1 -1
- package/dist/hooks/use-action-panel.js.map +1 -1
- package/dist/hooks/use-unstable-ai.js +1 -1
- package/dist/hooks/use-unstable-ai.js.map +1 -1
- package/dist/index.d.ts +57 -55
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +42 -38
- package/dist/index.js.map +1 -1
- package/dist/internal/date-picker-widget.d.ts.map +1 -1
- package/dist/internal/date-picker-widget.js +56 -48
- package/dist/internal/date-picker-widget.js.map +1 -1
- package/dist/internal/dialog.d.ts +3 -3
- package/dist/internal/dialog.d.ts.map +1 -1
- package/dist/internal/dialog.js +10 -10
- package/dist/internal/dialog.js.map +1 -1
- package/dist/internal/error-handler.js +2 -2
- package/dist/internal/error-handler.js.map +1 -1
- package/dist/internal/focus-context.d.ts +1 -1
- package/dist/internal/focus-context.d.ts.map +1 -1
- package/dist/internal/navigation.d.ts +1 -1
- package/dist/internal/navigation.d.ts.map +1 -1
- package/dist/internal/navigation.js +2 -2
- package/dist/internal/navigation.js.map +1 -1
- package/dist/internal/providers.d.ts +2 -2
- package/dist/internal/providers.d.ts.map +1 -1
- package/dist/internal/providers.js +9 -9
- package/dist/internal/providers.js.map +1 -1
- package/dist/internal/scrollbox.d.ts +12 -0
- package/dist/internal/scrollbox.d.ts.map +1 -0
- package/dist/internal/scrollbox.js +34 -0
- package/dist/internal/scrollbox.js.map +1 -0
- package/dist/preload.js +1 -1
- package/dist/preload.js.map +1 -1
- package/dist/release.d.ts +11 -0
- package/dist/release.d.ts.map +1 -0
- package/dist/release.js +113 -0
- package/dist/release.js.map +1 -0
- package/dist/state.d.ts +1 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +1 -0
- package/dist/state.js.map +1 -1
- package/dist/theme.d.ts +11 -8
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +31 -8
- package/dist/theme.js.map +1 -1
- package/dist/utils/run-command.d.ts +22 -0
- package/dist/utils/run-command.d.ts.map +1 -0
- package/dist/utils/run-command.js +127 -0
- package/dist/utils/run-command.js.map +1 -0
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +6 -4
- package/dist/utils.js.map +1 -1
- package/package.json +13 -8
- package/src/apis/toast.tsx +38 -17
- package/src/build.tsx +5 -3
- package/src/cli.tsx +46 -0
- package/src/colors.tsx +22 -1
- package/src/compile.tsx +219 -0
- package/src/components/actions.tsx +7 -1
- package/src/components/command-arguments.tsx +81 -0
- package/src/components/detail.tsx +26 -58
- package/src/components/dropdown.tsx +108 -23
- package/src/components/extension-preferences.tsx +55 -35
- package/src/components/form/checkbox.tsx +13 -5
- package/src/components/form/date-picker.tsx +24 -29
- package/src/components/form/description.tsx +35 -7
- package/src/components/form/dropdown.tsx +16 -30
- package/src/components/form/file-autocomplete.tsx +87 -77
- package/src/components/form/file-picker.tsx +69 -57
- package/src/components/form/form-ref.tsx +68 -0
- package/src/components/form/index.tsx +152 -41
- package/src/components/form/password-field.tsx +35 -22
- package/src/components/form/text-area.tsx +78 -58
- package/src/components/form/text-field.tsx +82 -61
- package/src/components/form/use-form-navigation.tsx +43 -23
- package/src/components/form/with-left-border.tsx +2 -1
- package/src/components/icon.tsx +497 -469
- package/src/components/list.tsx +279 -112
- package/src/components/loading-bar.tsx +1 -1
- package/src/descendants.tsx +15 -5
- package/src/e2e-node.tsx +16 -0
- package/src/examples/action-show-in-finder.tsx +1 -1
- package/src/examples/environment-test.tsx +1 -1
- package/src/examples/error-boundary.tsx +1 -1
- package/src/examples/file-autocomplete.vitest.tsx +245 -0
- package/src/examples/form-basic.tsx +12 -12
- package/src/examples/form-basic.vitest.tsx +297 -671
- package/src/examples/form-dropdown.tsx +1 -1
- package/src/examples/form-dropdown.vitest.tsx +353 -221
- package/src/examples/form-scroll.tsx +56 -0
- package/src/examples/form-scroll.vitest.tsx +228 -0
- package/src/examples/form-tagpicker.tsx +1 -1
- package/src/examples/form-tagpicker.vitest.tsx +438 -193
- package/src/examples/internal/descendants-filtering.tsx +13 -5
- package/src/examples/internal/descendants.tsx +17 -5
- package/src/examples/internal/rhf-custom-ref.tsx +152 -0
- package/src/examples/internal/scrollbox-demo.tsx +15 -7
- package/src/examples/internal/scrollbox-with-descendants.tsx +94 -0
- package/src/examples/internal/simple-dialog.tsx +1 -1
- package/src/examples/internal/simple-scrollbox.tsx +58 -0
- package/src/examples/internal/simple-scrollbox.vitest.tsx +104 -0
- package/src/examples/internal/text-stacking.tsx +4 -2
- package/src/examples/list-dropdown-default.tsx +1 -1
- package/src/examples/list-dropdown-default.vitest.tsx +136 -71
- package/src/examples/list-fetch-data.tsx +1 -1
- package/src/examples/list-fetch-data.vitest.tsx +42 -33
- package/src/examples/list-scrollbox.tsx +46 -0
- package/src/examples/list-scrollbox.vitest.tsx +103 -0
- package/src/examples/list-with-detail.tsx +1 -1
- package/src/examples/list-with-detail.vitest.tsx +290 -294
- package/src/examples/list-with-dropdown.tsx +1 -1
- package/src/examples/list-with-dropdown.vitest.tsx +190 -150
- package/src/examples/list-with-sections.tsx +12 -1
- package/src/examples/list-with-sections.vitest.tsx +390 -218
- package/src/examples/miscellaneous.tsx +1 -1
- package/src/examples/nested-navigation.tsx +7 -5
- package/src/examples/preferences-test.tsx +1 -1
- package/src/examples/simple-dropdown.tsx +1 -1
- package/src/examples/simple-file-picker.tsx +1 -1
- package/src/examples/simple-file-picker.vitest.tsx +533 -127
- package/src/examples/simple-grid.tsx +1 -1
- package/src/examples/simple-grid.vitest.tsx +258 -234
- package/src/examples/simple-hud.tsx +1 -1
- package/src/examples/simple-list-search.tsx +42 -1
- package/src/examples/simple-list.tsx +1 -1
- package/src/examples/simple-navigation.tsx +7 -5
- package/src/examples/simple-navigation.vitest.tsx +434 -238
- package/src/examples/store.tsx +1 -1
- package/src/examples/store.vitest.tsx +31 -14
- package/src/examples/submodule-diff.tsx +153 -0
- package/src/examples/tanstack-demo.tsx +1 -1
- package/src/examples/use-promise-demo.tsx +1 -1
- package/src/extensions/dev.tsx +76 -38
- package/src/extensions/dev.vitest.tsx +220 -0
- package/src/extensions/home.tsx +20 -121
- package/src/globals.ts +1 -1
- package/src/index.tsx +12 -25
- package/src/internal/date-picker-widget.tsx +56 -46
- package/src/internal/dialog.tsx +6 -6
- package/src/internal/providers.tsx +1 -1
- package/src/internal/scrollbox.tsx +63 -0
- package/src/release.tsx +159 -0
- package/src/state.tsx +2 -0
- package/src/store-api/search.test.tsx +4 -13
- package/src/theme.tsx +33 -8
- package/src/utils/run-command.tsx +204 -0
- package/src/utils.tsx +6 -4
- package/dist/ai.d.ts +0 -104
- package/dist/ai.d.ts.map +0 -1
- package/dist/ai.js +0 -135
- package/dist/ai.js.map +0 -1
- package/dist/apis/cache.test.d.ts +0 -2
- package/dist/apis/cache.test.d.ts.map +0 -1
- package/dist/apis/cache.test.js +0 -246
- package/dist/apis/cache.test.js.map +0 -1
- package/dist/apis/localstorage.test.d.ts +0 -2
- package/dist/apis/localstorage.test.d.ts.map +0 -1
- package/dist/apis/localstorage.test.js +0 -131
- package/dist/apis/localstorage.test.js.map +0 -1
- package/dist/apis/toast.test.d.ts +0 -2
- package/dist/apis/toast.test.d.ts.map +0 -1
- package/dist/apis/toast.test.js +0 -67
- package/dist/apis/toast.test.js.map +0 -1
- package/dist/build.test.d.ts +0 -2
- package/dist/build.test.d.ts.map +0 -1
- package/dist/build.test.js +0 -73
- package/dist/build.test.js.map +0 -1
- package/dist/cache.d.ts +0 -32
- package/dist/cache.d.ts.map +0 -1
- package/dist/cache.js +0 -205
- package/dist/cache.js.map +0 -1
- package/dist/cache.test.d.ts +0 -2
- package/dist/cache.test.d.ts.map +0 -1
- package/dist/cache.test.js +0 -246
- package/dist/cache.test.js.map +0 -1
- package/dist/clipboard.d.ts +0 -36
- package/dist/clipboard.d.ts.map +0 -1
- package/dist/clipboard.js +0 -154
- package/dist/clipboard.js.map +0 -1
- package/dist/components/form/form-type-only.d.ts +0 -174
- package/dist/components/form/form-type-only.d.ts.map +0 -1
- package/dist/components/form/form-type-only.js +0 -2
- package/dist/components/form/form-type-only.js.map +0 -1
- package/dist/components/form/use-form-handling.d.ts +0 -4
- package/dist/components/form/use-form-handling.d.ts.map +0 -1
- package/dist/components/form/use-form-handling.js +0 -37
- package/dist/components/form/use-form-handling.js.map +0 -1
- package/dist/dev-ui.d.ts +0 -7
- package/dist/dev-ui.d.ts.map +0 -1
- package/dist/dev-ui.js +0 -118
- package/dist/dev-ui.js.map +0 -1
- package/dist/environment.d.ts +0 -63
- package/dist/environment.d.ts.map +0 -1
- package/dist/environment.js +0 -189
- package/dist/environment.js.map +0 -1
- package/dist/examples/datepicker.d.ts +0 -2
- package/dist/examples/datepicker.d.ts.map +0 -1
- package/dist/examples/datepicker.js +0 -344
- package/dist/examples/datepicker.js.map +0 -1
- package/dist/examples/form-basic-arrow-keys.vitest.d.ts +0 -2
- package/dist/examples/form-basic-arrow-keys.vitest.d.ts.map +0 -1
- package/dist/examples/form-basic-arrow-keys.vitest.js +0 -46
- package/dist/examples/form-basic-arrow-keys.vitest.js.map +0 -1
- package/dist/examples/form-basic.vitest.d.ts +0 -2
- package/dist/examples/form-basic.vitest.d.ts.map +0 -1
- package/dist/examples/form-basic.vitest.js +0 -995
- package/dist/examples/form-basic.vitest.js.map +0 -1
- package/dist/examples/form-dropdown-with-sections.d.ts +0 -2
- package/dist/examples/form-dropdown-with-sections.d.ts.map +0 -1
- package/dist/examples/form-dropdown-with-sections.js +0 -13
- package/dist/examples/form-dropdown-with-sections.js.map +0 -1
- package/dist/examples/form-dropdown-with-sections.vitest.d.ts +0 -2
- package/dist/examples/form-dropdown-with-sections.vitest.d.ts.map +0 -1
- package/dist/examples/form-dropdown-with-sections.vitest.js +0 -75
- package/dist/examples/form-dropdown-with-sections.vitest.js.map +0 -1
- package/dist/examples/form-dropdown.vitest.d.ts +0 -2
- package/dist/examples/form-dropdown.vitest.d.ts.map +0 -1
- package/dist/examples/form-dropdown.vitest.js +0 -722
- package/dist/examples/form-dropdown.vitest.js.map +0 -1
- package/dist/examples/form-multiselect-dropdown.d.ts +0 -2
- package/dist/examples/form-multiselect-dropdown.d.ts.map +0 -1
- package/dist/examples/form-multiselect-dropdown.js +0 -13
- package/dist/examples/form-multiselect-dropdown.js.map +0 -1
- package/dist/examples/form-tagpicker.vitest.d.ts +0 -2
- package/dist/examples/form-tagpicker.vitest.d.ts.map +0 -1
- package/dist/examples/form-tagpicker.vitest.js +0 -491
- package/dist/examples/form-tagpicker.vitest.js.map +0 -1
- package/dist/examples/internal/nested-boxes.d.ts +0 -2
- package/dist/examples/internal/nested-boxes.d.ts.map +0 -1
- package/dist/examples/internal/nested-boxes.js +0 -7
- package/dist/examples/internal/nested-boxes.js.map +0 -1
- package/dist/examples/internal/unicode-square-repro.d.ts +0 -2
- package/dist/examples/internal/unicode-square-repro.d.ts.map +0 -1
- package/dist/examples/internal/unicode-square-repro.js +0 -7
- package/dist/examples/internal/unicode-square-repro.js.map +0 -1
- package/dist/examples/list-dropdown-default.vitest.d.ts +0 -2
- package/dist/examples/list-dropdown-default.vitest.d.ts.map +0 -1
- package/dist/examples/list-dropdown-default.vitest.js +0 -164
- package/dist/examples/list-dropdown-default.vitest.js.map +0 -1
- package/dist/examples/list-fetch-data.vitest.d.ts +0 -2
- package/dist/examples/list-fetch-data.vitest.d.ts.map +0 -1
- package/dist/examples/list-fetch-data.vitest.js +0 -103
- package/dist/examples/list-fetch-data.vitest.js.map +0 -1
- package/dist/examples/list-filter-navigation.d.ts +0 -2
- package/dist/examples/list-filter-navigation.d.ts.map +0 -1
- package/dist/examples/list-filter-navigation.js +0 -8
- package/dist/examples/list-filter-navigation.js.map +0 -1
- package/dist/examples/list-with-detail.vitest.d.ts +0 -2
- package/dist/examples/list-with-detail.vitest.d.ts.map +0 -1
- package/dist/examples/list-with-detail.vitest.js +0 -438
- package/dist/examples/list-with-detail.vitest.js.map +0 -1
- package/dist/examples/list-with-dropdown.vitest.d.ts +0 -2
- package/dist/examples/list-with-dropdown.vitest.d.ts.map +0 -1
- package/dist/examples/list-with-dropdown.vitest.js +0 -297
- package/dist/examples/list-with-dropdown.vitest.js.map +0 -1
- package/dist/examples/list-with-sections.vitest.d.ts +0 -2
- package/dist/examples/list-with-sections.vitest.d.ts.map +0 -1
- package/dist/examples/list-with-sections.vitest.js +0 -441
- package/dist/examples/list-with-sections.vitest.js.map +0 -1
- package/dist/examples/simple-file-picker.vitest.d.ts +0 -2
- package/dist/examples/simple-file-picker.vitest.d.ts.map +0 -1
- package/dist/examples/simple-file-picker.vitest.js +0 -277
- package/dist/examples/simple-file-picker.vitest.js.map +0 -1
- package/dist/examples/simple-grid.vitest.d.ts +0 -2
- package/dist/examples/simple-grid.vitest.d.ts.map +0 -1
- package/dist/examples/simple-grid.vitest.js +0 -498
- package/dist/examples/simple-grid.vitest.js.map +0 -1
- package/dist/examples/simple-navigation.vitest.d.ts +0 -2
- package/dist/examples/simple-navigation.vitest.d.ts.map +0 -1
- package/dist/examples/simple-navigation.vitest.js +0 -522
- package/dist/examples/simple-navigation.vitest.js.map +0 -1
- package/dist/examples/store.vitest.d.ts +0 -2
- package/dist/examples/store.vitest.d.ts.map +0 -1
- package/dist/examples/store.vitest.js +0 -52
- package/dist/examples/store.vitest.js.map +0 -1
- package/dist/home-command.d.ts +0 -8
- package/dist/home-command.d.ts.map +0 -1
- package/dist/home-command.js +0 -181
- package/dist/home-command.js.map +0 -1
- package/dist/hooks/hooks.test.d.ts +0 -2
- package/dist/hooks/hooks.test.d.ts.map +0 -1
- package/dist/hooks/hooks.test.js +0 -37
- package/dist/hooks/hooks.test.js.map +0 -1
- package/dist/hover-repro.d.ts +0 -2
- package/dist/hover-repro.d.ts.map +0 -1
- package/dist/hover-repro.js +0 -20
- package/dist/hover-repro.js.map +0 -1
- package/dist/localstorage.d.ts +0 -13
- package/dist/localstorage.d.ts.map +0 -1
- package/dist/localstorage.js +0 -190
- package/dist/localstorage.js.map +0 -1
- package/dist/localstorage.test.d.ts +0 -2
- package/dist/localstorage.test.d.ts.map +0 -1
- package/dist/localstorage.test.js +0 -131
- package/dist/localstorage.test.js.map +0 -1
- package/dist/oauth.d.ts +0 -142
- package/dist/oauth.d.ts.map +0 -1
- package/dist/oauth.js +0 -551
- package/dist/oauth.js.map +0 -1
- package/dist/preferences.d.ts +0 -23
- package/dist/preferences.d.ts.map +0 -1
- package/dist/preferences.js +0 -105
- package/dist/preferences.js.map +0 -1
- package/dist/store-api/download.test.d.ts +0 -2
- package/dist/store-api/download.test.d.ts.map +0 -1
- package/dist/store-api/download.test.js +0 -36
- package/dist/store-api/download.test.js.map +0 -1
- package/dist/store-api/extension.test.d.ts +0 -2
- package/dist/store-api/extension.test.d.ts.map +0 -1
- package/dist/store-api/extension.test.js +0 -22
- package/dist/store-api/extension.test.js.map +0 -1
- package/dist/store-api/search.test.d.ts +0 -2
- package/dist/store-api/search.test.d.ts.map +0 -1
- package/dist/store-api/search.test.js +0 -45
- package/dist/store-api/search.test.js.map +0 -1
- package/dist/store.d.ts +0 -21
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -84
- package/dist/store.js.map +0 -1
- package/dist/toast.d.ts +0 -44
- package/dist/toast.d.ts.map +0 -1
- package/dist/toast.js +0 -221
- package/dist/toast.js.map +0 -1
- package/dist/utils.test.d.ts +0 -2
- package/dist/utils.test.d.ts.map +0 -1
- package/dist/utils.test.js +0 -152
- package/dist/utils.test.js.map +0 -1
- package/dist/window.d.ts +0 -12
- package/dist/window.d.ts.map +0 -1
- package/dist/window.js +0 -48
- package/dist/window.js.map +0 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// This example shows how to filter descendants by passing search query via context
|
|
2
2
|
// Items conditionally render null when they don't match the search
|
|
3
3
|
import { useKeyboard } from '@opentui/react'
|
|
4
|
+
import { TextareaRenderable } from '@opentui/core'
|
|
4
5
|
import { createDescendants } from 'termcast/src/descendants'
|
|
5
|
-
import { createContext, useContext, useState } from 'react'
|
|
6
|
+
import { createContext, useContext, useState, useRef } from 'react'
|
|
6
7
|
import { renderWithProviders } from '../../utils'
|
|
7
8
|
import { logger } from 'termcast/src/logger'
|
|
8
9
|
|
|
@@ -36,6 +37,7 @@ const Menu = ({ children }: { children: React.ReactNode }) => {
|
|
|
36
37
|
const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set())
|
|
37
38
|
const [selectedTitles, setSelectedTitles] = useState<string[]>([])
|
|
38
39
|
const [searchQuery, setSearchQuery] = useState('')
|
|
40
|
+
const inputRef = useRef<TextareaRenderable>(null)
|
|
39
41
|
|
|
40
42
|
useKeyboard((evt) => {
|
|
41
43
|
const items = Object.values(descendantsContext.map.current).filter(
|
|
@@ -125,9 +127,15 @@ const Menu = ({ children }: { children: React.ReactNode }) => {
|
|
|
125
127
|
<box flexDirection='column'>
|
|
126
128
|
<box flexDirection='column' borderStyle='single' padding={1}>
|
|
127
129
|
<text marginBottom={1}>Filter Menu</text>
|
|
128
|
-
<
|
|
129
|
-
|
|
130
|
-
|
|
130
|
+
<textarea
|
|
131
|
+
ref={inputRef}
|
|
132
|
+
height={1}
|
|
133
|
+
keyBindings={[
|
|
134
|
+
{ name: 'return', action: 'submit' },
|
|
135
|
+
{ name: 'linefeed', action: 'submit' },
|
|
136
|
+
]}
|
|
137
|
+
onContentChange={() => {
|
|
138
|
+
const value = inputRef.current?.plainText || ''
|
|
131
139
|
setSearchQuery(value)
|
|
132
140
|
// Reset focus to first item when search changes
|
|
133
141
|
setFocusedIndex(0)
|
|
@@ -220,4 +228,4 @@ const Example = () => {
|
|
|
220
228
|
)
|
|
221
229
|
}
|
|
222
230
|
|
|
223
|
-
renderWithProviders(<Example />)
|
|
231
|
+
await renderWithProviders(<Example />)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// read src/descendants.tsx to understand the core hooks that make this example possible
|
|
2
2
|
//
|
|
3
3
|
import { useKeyboard } from '@opentui/react'
|
|
4
|
+
import { TextareaRenderable } from '@opentui/core'
|
|
4
5
|
import { createDescendants } from 'termcast/src/descendants'
|
|
5
6
|
import { useIsInFocus } from 'termcast/src/internal/focus-context'
|
|
6
|
-
import { createContext, useContext, useState } from 'react'
|
|
7
|
+
import { createContext, useContext, useState, useRef, useLayoutEffect } from 'react'
|
|
7
8
|
import { renderWithProviders } from '../../utils'
|
|
8
9
|
import { logger } from 'termcast/src/logger'
|
|
9
10
|
|
|
@@ -167,6 +168,7 @@ const Item = ({ title }: { title: string; key?: any }) => {
|
|
|
167
168
|
|
|
168
169
|
const Example = () => {
|
|
169
170
|
const [searchQuery, setSearchQuery] = useState('')
|
|
171
|
+
const inputRef = useRef<TextareaRenderable>(null)
|
|
170
172
|
const allItems = [
|
|
171
173
|
'First Item',
|
|
172
174
|
'Second Item',
|
|
@@ -182,6 +184,7 @@ const Example = () => {
|
|
|
182
184
|
'Twelfth Item',
|
|
183
185
|
]
|
|
184
186
|
|
|
187
|
+
|
|
185
188
|
// Filter items based on search query
|
|
186
189
|
const filteredItems = allItems.filter((title) =>
|
|
187
190
|
title.toLowerCase().includes(searchQuery.toLowerCase()),
|
|
@@ -189,9 +192,18 @@ const Example = () => {
|
|
|
189
192
|
|
|
190
193
|
return (
|
|
191
194
|
<box flexDirection='column'>
|
|
192
|
-
<
|
|
193
|
-
|
|
194
|
-
|
|
195
|
+
<textarea
|
|
196
|
+
ref={inputRef}
|
|
197
|
+
height={1}
|
|
198
|
+
keyBindings={[
|
|
199
|
+
{ name: 'return', action: 'submit' },
|
|
200
|
+
{ name: 'linefeed', action: 'submit' },
|
|
201
|
+
]}
|
|
202
|
+
initialValue={searchQuery}
|
|
203
|
+
onContentChange={() => {
|
|
204
|
+
const value = inputRef.current?.plainText || ''
|
|
205
|
+
setSearchQuery(value)
|
|
206
|
+
}}
|
|
195
207
|
focused
|
|
196
208
|
placeholder='Search items...'
|
|
197
209
|
marginBottom={1}
|
|
@@ -205,4 +217,4 @@ const Example = () => {
|
|
|
205
217
|
)
|
|
206
218
|
}
|
|
207
219
|
|
|
208
|
-
renderWithProviders(<Example />)
|
|
220
|
+
await renderWithProviders(<Example />)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import React, { useRef, useState, useCallback } from 'react'
|
|
2
|
+
import { TextareaRenderable } from '@opentui/core'
|
|
3
|
+
import { useForm } from 'react-hook-form'
|
|
4
|
+
import { useKeyboard } from '@opentui/react'
|
|
5
|
+
import { renderWithProviders } from '../../utils'
|
|
6
|
+
import { Theme } from 'termcast/src/theme'
|
|
7
|
+
import { logger } from 'termcast/src/logger'
|
|
8
|
+
import { createTextareaFormRef } from 'termcast/src/components/form/form-ref'
|
|
9
|
+
|
|
10
|
+
interface FormData {
|
|
11
|
+
username: string
|
|
12
|
+
message: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function RHFCustomRefExample() {
|
|
16
|
+
const textareaRef1 = useRef<TextareaRenderable>(null)
|
|
17
|
+
const textareaRef2 = useRef<TextareaRenderable>(null)
|
|
18
|
+
const [focusedField, setFocusedField] = useState<'username' | 'message'>('username')
|
|
19
|
+
|
|
20
|
+
const { register, handleSubmit, formState, reset, setValue, getValues, watch } =
|
|
21
|
+
useForm<FormData>({
|
|
22
|
+
defaultValues: {
|
|
23
|
+
username: '',
|
|
24
|
+
message: '',
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const formValues = watch()
|
|
29
|
+
|
|
30
|
+
const onSubmit = (data: FormData) => {
|
|
31
|
+
logger.log('Form submitted:', data)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Get register props
|
|
35
|
+
const usernameRegistration = register('username', { required: 'Username is required' })
|
|
36
|
+
const messageRegistration = register('message', { required: 'Message is required' })
|
|
37
|
+
|
|
38
|
+
// Create form ref adapters with onContentChange handlers
|
|
39
|
+
const { formRef: usernameFormRef, onContentChange: onUsernameChange } =
|
|
40
|
+
createTextareaFormRef('username', textareaRef1, usernameRegistration)
|
|
41
|
+
const { formRef: messageFormRef, onContentChange: onMessageChange } =
|
|
42
|
+
createTextareaFormRef('message', textareaRef2, messageRegistration)
|
|
43
|
+
|
|
44
|
+
// Memoize ref callbacks - register() returns new object every render,
|
|
45
|
+
// so we must not pass registration.ref directly to avoid re-renders
|
|
46
|
+
const handleUsernameRef = useCallback((el: TextareaRenderable | null) => {
|
|
47
|
+
textareaRef1.current = el
|
|
48
|
+
usernameRegistration.ref(usernameFormRef)
|
|
49
|
+
}, [])
|
|
50
|
+
|
|
51
|
+
const handleMessageRef = useCallback((el: TextareaRenderable | null) => {
|
|
52
|
+
textareaRef2.current = el
|
|
53
|
+
messageRegistration.ref(messageFormRef)
|
|
54
|
+
}, [])
|
|
55
|
+
|
|
56
|
+
useKeyboard((evt) => {
|
|
57
|
+
if (evt.name === 'escape') {
|
|
58
|
+
reset()
|
|
59
|
+
logger.log('Form reset')
|
|
60
|
+
}
|
|
61
|
+
if (evt.ctrl && evt.name === 's') {
|
|
62
|
+
handleSubmit(onSubmit)()
|
|
63
|
+
}
|
|
64
|
+
if (evt.ctrl && evt.name === 'v') {
|
|
65
|
+
setValue('username', 'test-user')
|
|
66
|
+
setValue('message', 'Hello from setValue!')
|
|
67
|
+
logger.log('Set values programmatically')
|
|
68
|
+
}
|
|
69
|
+
if (evt.ctrl && evt.name === 'g') {
|
|
70
|
+
logger.log('Current values:', getValues())
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<box flexDirection="column" gap={1}>
|
|
76
|
+
<text fg={Theme.accent}>React Hook Form with Custom Ref Adapter</text>
|
|
77
|
+
<text fg={Theme.textMuted}>
|
|
78
|
+
This example uses register() directly with opentui textarea
|
|
79
|
+
</text>
|
|
80
|
+
|
|
81
|
+
<box flexDirection="column">
|
|
82
|
+
<text
|
|
83
|
+
fg={Theme.text}
|
|
84
|
+
onMouseDown={() => {
|
|
85
|
+
setFocusedField('username')
|
|
86
|
+
}}
|
|
87
|
+
>
|
|
88
|
+
Username:
|
|
89
|
+
</text>
|
|
90
|
+
<textarea
|
|
91
|
+
ref={handleUsernameRef}
|
|
92
|
+
height={1}
|
|
93
|
+
placeholder="Enter username..."
|
|
94
|
+
onContentChange={onUsernameChange}
|
|
95
|
+
onMouseDown={() => {
|
|
96
|
+
setFocusedField('username')
|
|
97
|
+
}}
|
|
98
|
+
focused={focusedField === 'username'}
|
|
99
|
+
/>
|
|
100
|
+
{formState.errors.username && (
|
|
101
|
+
<text fg={Theme.error}>{formState.errors.username.message}</text>
|
|
102
|
+
)}
|
|
103
|
+
</box>
|
|
104
|
+
|
|
105
|
+
<box flexDirection="column">
|
|
106
|
+
<text
|
|
107
|
+
fg={Theme.text}
|
|
108
|
+
onMouseDown={() => {
|
|
109
|
+
setFocusedField('message')
|
|
110
|
+
}}
|
|
111
|
+
>
|
|
112
|
+
Message:
|
|
113
|
+
</text>
|
|
114
|
+
<textarea
|
|
115
|
+
ref={handleMessageRef}
|
|
116
|
+
height={2}
|
|
117
|
+
placeholder="Enter message..."
|
|
118
|
+
onContentChange={onMessageChange}
|
|
119
|
+
onMouseDown={() => {
|
|
120
|
+
setFocusedField('message')
|
|
121
|
+
}}
|
|
122
|
+
focused={focusedField === 'message'}
|
|
123
|
+
/>
|
|
124
|
+
{formState.errors.message && (
|
|
125
|
+
<text fg={Theme.error}>{formState.errors.message.message}</text>
|
|
126
|
+
)}
|
|
127
|
+
</box>
|
|
128
|
+
|
|
129
|
+
<box flexDirection="column" marginTop={1}>
|
|
130
|
+
<text fg={Theme.textMuted}>Controls:</text>
|
|
131
|
+
<text fg={Theme.textMuted}>• Ctrl+S: Submit form</text>
|
|
132
|
+
<text fg={Theme.textMuted}>• Ctrl+V: Set values programmatically</text>
|
|
133
|
+
<text fg={Theme.textMuted}>• Ctrl+G: Get current values</text>
|
|
134
|
+
<text fg={Theme.textMuted}>• ESC: Reset form</text>
|
|
135
|
+
</box>
|
|
136
|
+
|
|
137
|
+
<box marginTop={1}>
|
|
138
|
+
<text fg={Theme.textMuted}>
|
|
139
|
+
isDirty: {String(formState.isDirty)} | isValid:{' '}
|
|
140
|
+
{String(formState.isValid)} | submitCount: {formState.submitCount}
|
|
141
|
+
</text>
|
|
142
|
+
</box>
|
|
143
|
+
|
|
144
|
+
<box marginTop={1} flexDirection="column">
|
|
145
|
+
<text fg={Theme.accent}>Form values:</text>
|
|
146
|
+
<text fg={Theme.text}>{JSON.stringify(formValues, null, 2)}</text>
|
|
147
|
+
</box>
|
|
148
|
+
</box>
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
renderWithProviders(<RHFCustomRefExample />)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { useState, useRef, useEffect } from 'react'
|
|
2
2
|
import { renderWithProviders } from 'termcast'
|
|
3
3
|
import { useKeyboard } from '@opentui/react'
|
|
4
|
-
import { fg, bold } from '@opentui/core'
|
|
5
4
|
|
|
6
5
|
function ScrollBoxListDemo(): any {
|
|
7
6
|
const [selectedIndex, setSelectedIndex] = useState(0)
|
|
@@ -81,7 +80,11 @@ function ScrollBoxListDemo(): any {
|
|
|
81
80
|
return (
|
|
82
81
|
<box flexDirection='column' width='100%' height='100%'>
|
|
83
82
|
<box padding={1} backgroundColor='#2e3440'>
|
|
84
|
-
<text>
|
|
83
|
+
<text>
|
|
84
|
+
<strong>
|
|
85
|
+
<span fg='#88c0d0'>ScrollBox Demo</span>
|
|
86
|
+
</strong>
|
|
87
|
+
</text>
|
|
85
88
|
<text fg='#d8dee9'>
|
|
86
89
|
↑↓ Navigate | PgUp/PgDn Jump | Home/End First/Last
|
|
87
90
|
</text>
|
|
@@ -89,6 +92,7 @@ function ScrollBoxListDemo(): any {
|
|
|
89
92
|
|
|
90
93
|
<scrollbox
|
|
91
94
|
ref={scrollBoxRef}
|
|
95
|
+
focused={true}
|
|
92
96
|
flexGrow={1}
|
|
93
97
|
flexShrink={1}
|
|
94
98
|
style={{
|
|
@@ -105,7 +109,7 @@ function ScrollBoxListDemo(): any {
|
|
|
105
109
|
flexShrink: 0,
|
|
106
110
|
},
|
|
107
111
|
scrollbarOptions: {
|
|
108
|
-
|
|
112
|
+
|
|
109
113
|
showArrows: true,
|
|
110
114
|
},
|
|
111
115
|
}}
|
|
@@ -123,9 +127,13 @@ function ScrollBoxListDemo(): any {
|
|
|
123
127
|
marginBottom={0.5}
|
|
124
128
|
>
|
|
125
129
|
<text>
|
|
126
|
-
{isSelected
|
|
127
|
-
|
|
128
|
-
|
|
130
|
+
{isSelected ? (
|
|
131
|
+
<strong>
|
|
132
|
+
<span fg='#eceff4'>{`▶ ${item.title}`}</span>
|
|
133
|
+
</strong>
|
|
134
|
+
) : (
|
|
135
|
+
<span fg='#d8dee9'>{` ${item.title}`}</span>
|
|
136
|
+
)}
|
|
129
137
|
</text>
|
|
130
138
|
<text fg={isSelected ? '#e5e9f0' : '#81a1c1'}>
|
|
131
139
|
{item.description}
|
|
@@ -145,5 +153,5 @@ function ScrollBoxListDemo(): any {
|
|
|
145
153
|
}
|
|
146
154
|
|
|
147
155
|
if (import.meta.main) {
|
|
148
|
-
renderWithProviders(<ScrollBoxListDemo />)
|
|
156
|
+
await renderWithProviders(<ScrollBoxListDemo />)
|
|
149
157
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { useKeyboard } from '@opentui/react'
|
|
3
|
+
import { createDescendants } from 'termcast/src/descendants'
|
|
4
|
+
import { renderWithProviders } from 'termcast/src/utils'
|
|
5
|
+
|
|
6
|
+
interface ItemDescendant {
|
|
7
|
+
title: string
|
|
8
|
+
elementRef?: { y: number; height: number } | null
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const { DescendantsProvider, useDescendants, useDescendant } =
|
|
12
|
+
createDescendants<ItemDescendant>()
|
|
13
|
+
|
|
14
|
+
function ScrollboxWithDescendants() {
|
|
15
|
+
const context = useDescendants()
|
|
16
|
+
const [selectedIndex, setSelectedIndex] = React.useState(0)
|
|
17
|
+
const scrollBoxRef = React.useRef<any>(null)
|
|
18
|
+
|
|
19
|
+
const scrollToItem = (item: { props?: ItemDescendant }) => {
|
|
20
|
+
const scrollBox = scrollBoxRef.current
|
|
21
|
+
const elementRef = item.props?.elementRef
|
|
22
|
+
if (!scrollBox || !elementRef) return
|
|
23
|
+
|
|
24
|
+
const contentY = scrollBox.content?.y || 0
|
|
25
|
+
const viewportHeight = scrollBox.viewport?.height || 10
|
|
26
|
+
const currentScrollTop = scrollBox.scrollTop || 0
|
|
27
|
+
|
|
28
|
+
const itemTop = elementRef.y - contentY
|
|
29
|
+
const itemBottom = itemTop + elementRef.height
|
|
30
|
+
|
|
31
|
+
if (itemTop < currentScrollTop) {
|
|
32
|
+
scrollBox.scrollTo(itemTop)
|
|
33
|
+
} else if (itemBottom > currentScrollTop + viewportHeight) {
|
|
34
|
+
scrollBox.scrollTo(itemBottom - viewportHeight)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const move = (direction: -1 | 1) => {
|
|
39
|
+
const items = Object.values(context.map.current)
|
|
40
|
+
.filter((item) => item.index !== -1)
|
|
41
|
+
.sort((a, b) => a.index - b.index)
|
|
42
|
+
|
|
43
|
+
if (items.length === 0) return
|
|
44
|
+
|
|
45
|
+
let nextIndex = selectedIndex + direction
|
|
46
|
+
if (nextIndex < 0) nextIndex = items.length - 1
|
|
47
|
+
if (nextIndex >= items.length) nextIndex = 0
|
|
48
|
+
|
|
49
|
+
const nextItem = items[nextIndex]
|
|
50
|
+
if (nextItem) {
|
|
51
|
+
setSelectedIndex(nextIndex)
|
|
52
|
+
scrollToItem(nextItem)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
useKeyboard((evt) => {
|
|
57
|
+
if (evt.name === 'up') move(-1)
|
|
58
|
+
if (evt.name === 'down') move(1)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
const items = Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`)
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<DescendantsProvider value={context}>
|
|
65
|
+
<box style={{ flexDirection: 'column', height: 10 }}>
|
|
66
|
+
<scrollbox ref={scrollBoxRef} focused={true} flexGrow={1} flexShrink={1}>
|
|
67
|
+
{items.map((title, i) => (
|
|
68
|
+
<Item key={i} title={title} isSelected={selectedIndex === i} />
|
|
69
|
+
))}
|
|
70
|
+
</scrollbox>
|
|
71
|
+
<text>↑↓ to navigate</text>
|
|
72
|
+
</box>
|
|
73
|
+
</DescendantsProvider>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function Item(props: { title: string; isSelected: boolean }) {
|
|
78
|
+
const elementRef = React.useRef<any>(null)
|
|
79
|
+
const { index } = useDescendant({
|
|
80
|
+
title: props.title,
|
|
81
|
+
elementRef: elementRef.current,
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<box ref={elementRef}>
|
|
86
|
+
<text>
|
|
87
|
+
{props.isSelected ? '›' : ' '}
|
|
88
|
+
{props.title}
|
|
89
|
+
</text>
|
|
90
|
+
</box>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
await renderWithProviders(<ScrollboxWithDescendants />)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { renderWithProviders } from 'termcast'
|
|
3
|
+
import { useKeyboard } from '@opentui/react'
|
|
4
|
+
import { ScrollBox } from 'termcast/src/internal/scrollbox'
|
|
5
|
+
|
|
6
|
+
function SimpleScrollBoxDemo(): any {
|
|
7
|
+
useKeyboard((evt) => {
|
|
8
|
+
if (evt.name === 'q' || evt.name === 'escape') {
|
|
9
|
+
process.exit(0)
|
|
10
|
+
}
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
const colors = [
|
|
14
|
+
'#e06c75',
|
|
15
|
+
'#98c379',
|
|
16
|
+
'#e5c07b',
|
|
17
|
+
'#61afef',
|
|
18
|
+
'#c678dd',
|
|
19
|
+
'#56b6c2',
|
|
20
|
+
'#abb2bf',
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<box flexDirection="column" width="100%" height="100%">
|
|
25
|
+
<box padding={1} backgroundColor="#282c34">
|
|
26
|
+
<text>
|
|
27
|
+
<strong>
|
|
28
|
+
<span fg='#61afef'>Simple ScrollBox Demo</span>
|
|
29
|
+
</strong>
|
|
30
|
+
</text>
|
|
31
|
+
</box>
|
|
32
|
+
|
|
33
|
+
<ScrollBox focused flexGrow={1} flexShrink={1}>
|
|
34
|
+
{Array.from({ length: 30 }, (_, i) => (
|
|
35
|
+
<box
|
|
36
|
+
key={i}
|
|
37
|
+
padding={1}
|
|
38
|
+
backgroundColor={colors[i % colors.length]}
|
|
39
|
+
marginBottom={1}
|
|
40
|
+
>
|
|
41
|
+
<text fg="#282c34">
|
|
42
|
+
<strong>{`Item ${i + 1}`}</strong> - This is content for item number{' '}
|
|
43
|
+
{i + 1}. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
44
|
+
</text>
|
|
45
|
+
</box>
|
|
46
|
+
))}
|
|
47
|
+
</ScrollBox>
|
|
48
|
+
|
|
49
|
+
<box padding={1} backgroundColor="#282c34">
|
|
50
|
+
<text fg="#abb2bf">Use mouse scroll or arrow keys | Press [q] to quit</text>
|
|
51
|
+
</box>
|
|
52
|
+
</box>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (import.meta.main) {
|
|
57
|
+
await renderWithProviders(<SimpleScrollBoxDemo />)
|
|
58
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { expect, test } from 'vitest'
|
|
2
|
+
import { launchTerminal, Session } from 'tuistory/src'
|
|
3
|
+
|
|
4
|
+
test('simple scrollbox navigation and scrolling', async () => {
|
|
5
|
+
const session = await launchTerminal({
|
|
6
|
+
command: 'bun',
|
|
7
|
+
args: ['src/examples/internal/simple-scrollbox.tsx'],
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
await session.text({
|
|
11
|
+
waitFor: (text) => text.includes('Simple ScrollBox Demo'),
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const initialText = await session.text()
|
|
15
|
+
expect(initialText).toMatchInlineSnapshot(`
|
|
16
|
+
"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
Simple ScrollBox Demo
|
|
21
|
+
▀
|
|
22
|
+
Item 1 - This is content for item number 1. Lorem ipsum dolor sit amet,
|
|
23
|
+
consectetur adipiscing elit.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
Item 2 - This is content for item number 2. Lorem ipsum dolor sit amet,
|
|
28
|
+
consectetur adipiscing elit.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
Item 3 - This is content for item number 3. Lorem ipsum dolor sit amet,
|
|
33
|
+
consectetur adipiscing elit.
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
Use mouse scroll or arrow keys | Press [q] to quit"
|
|
39
|
+
`)
|
|
40
|
+
|
|
41
|
+
// Scroll down to see more items
|
|
42
|
+
await session.scrollDown(3)
|
|
43
|
+
|
|
44
|
+
const afterScrollDownSnapshot = await session.text()
|
|
45
|
+
expect(afterScrollDownSnapshot).toMatchInlineSnapshot(`
|
|
46
|
+
"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
Simple ScrollBox Demo
|
|
51
|
+
▄
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
Item 2 - This is content for item number 2. Lorem ipsum dolor sit amet,
|
|
55
|
+
consectetur adipiscing elit.
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
Item 3 - This is content for item number 3. Lorem ipsum dolor sit amet,
|
|
60
|
+
consectetur adipiscing elit.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
Item 4 - This is content for item number 4. Lorem ipsum dolor sit amet,
|
|
65
|
+
consectetur adipiscing elit.
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
Use mouse scroll or arrow keys | Press [q] to quit"
|
|
69
|
+
`)
|
|
70
|
+
|
|
71
|
+
// Scroll back up
|
|
72
|
+
await session.scrollUp(2)
|
|
73
|
+
|
|
74
|
+
const afterScrollUpSnapshot = await session.text()
|
|
75
|
+
expect(afterScrollUpSnapshot).toMatchInlineSnapshot(`
|
|
76
|
+
"
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
Simple ScrollBox Demo
|
|
81
|
+
Item 1 - This is content for item number 1. Lorem ipsum dolor sit amet, ▀
|
|
82
|
+
consectetur adipiscing elit.
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
Item 2 - This is content for item number 2. Lorem ipsum dolor sit amet,
|
|
87
|
+
consectetur adipiscing elit.
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
Item 3 - This is content for item number 3. Lorem ipsum dolor sit amet,
|
|
92
|
+
consectetur adipiscing elit.
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
Item 4 - This is content for item number 4. Lorem ipsum dolor sit amet,
|
|
97
|
+
|
|
98
|
+
Use mouse scroll or arrow keys | Press [q] to quit"
|
|
99
|
+
`)
|
|
100
|
+
|
|
101
|
+
await session.press('esc')
|
|
102
|
+
|
|
103
|
+
session.close()
|
|
104
|
+
}, 30000)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRoot } from '@opentui/react'
|
|
2
|
+
import { createCliRenderer } from '@opentui/core'
|
|
2
3
|
|
|
3
4
|
function TextStackingExample() {
|
|
4
5
|
const items = [
|
|
@@ -87,4 +88,5 @@ function TextStackingExample() {
|
|
|
87
88
|
)
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
|
|
91
|
+
const renderer = await createCliRenderer()
|
|
92
|
+
createRoot(renderer).render(<TextStackingExample />)
|