termcast 1.3.21 → 1.3.24
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/ai.d.ts +104 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +135 -0
- package/dist/ai.js.map +1 -0
- package/dist/apis/browser-extension.d.ts +18 -0
- package/dist/apis/browser-extension.d.ts.map +1 -0
- package/dist/apis/browser-extension.js +14 -0
- package/dist/apis/browser-extension.js.map +1 -0
- package/dist/apis/localstorage.d.ts.map +1 -1
- package/dist/apis/localstorage.js +4 -7
- package/dist/apis/localstorage.js.map +1 -1
- package/dist/apis/oauth.d.ts.map +1 -1
- package/dist/apis/oauth.js +5 -1
- package/dist/apis/oauth.js.map +1 -1
- package/dist/apis/preferences.d.ts.map +1 -1
- package/dist/apis/preferences.js +38 -19
- package/dist/apis/preferences.js.map +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +2 -1
- package/dist/build.js.map +1 -1
- package/dist/cache.d.ts +32 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +205 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +67 -31
- package/dist/cli.js.map +1 -1
- package/dist/clipboard.d.ts +36 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +154 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +22 -5
- package/dist/compile.js.map +1 -1
- package/dist/components/actions.d.ts.map +1 -1
- package/dist/components/actions.js +56 -30
- package/dist/components/actions.js.map +1 -1
- package/dist/components/detail.d.ts.map +1 -1
- package/dist/components/detail.js +4 -0
- package/dist/components/detail.js.map +1 -1
- package/dist/components/dropdown.d.ts.map +1 -1
- package/dist/components/dropdown.js +38 -15
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/extension-preferences.d.ts.map +1 -1
- package/dist/components/extension-preferences.js +40 -13
- 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 +5 -3
- 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 +5 -3
- package/dist/components/form/date-picker.js.map +1 -1
- package/dist/components/form/description.d.ts.map +1 -1
- package/dist/components/form/description.js +2 -2
- 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 +84 -80
- package/dist/components/form/dropdown.js.map +1 -1
- package/dist/components/form/file-autocomplete.d.ts +3 -6
- package/dist/components/form/file-autocomplete.d.ts.map +1 -1
- package/dist/components/form/file-autocomplete.js +61 -66
- package/dist/components/form/file-autocomplete.js.map +1 -1
- package/dist/components/form/file-picker.d.ts.map +1 -1
- package/dist/components/form/file-picker.js +33 -30
- package/dist/components/form/file-picker.js.map +1 -1
- package/dist/components/form/form-end.d.ts.map +1 -1
- package/dist/components/form/form-end.js +21 -1
- package/dist/components/form/form-end.js.map +1 -1
- package/dist/components/form/form-type-only.d.ts +174 -0
- package/dist/components/form/form-type-only.d.ts.map +1 -0
- package/dist/components/form/form-type-only.js +2 -0
- package/dist/components/form/form-type-only.js.map +1 -0
- package/dist/components/form/index.d.ts +3 -1
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/index.js +100 -28
- 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 +5 -3
- package/dist/components/form/password-field.js.map +1 -1
- package/dist/components/form/text-area.d.ts.map +1 -1
- package/dist/components/form/text-area.js +5 -3
- 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 +6 -4
- package/dist/components/form/text-field.js.map +1 -1
- package/dist/components/form/types.d.ts +5 -0
- package/dist/components/form/types.d.ts.map +1 -1
- package/dist/components/form/use-form-handling.d.ts +4 -0
- package/dist/components/form/use-form-handling.d.ts.map +1 -0
- package/dist/components/form/use-form-handling.js +37 -0
- package/dist/components/form/use-form-handling.js.map +1 -0
- package/dist/components/form/with-left-border.d.ts +2 -1
- package/dist/components/form/with-left-border.d.ts.map +1 -1
- package/dist/components/form/with-left-border.js +27 -3
- package/dist/components/form/with-left-border.js.map +1 -1
- package/dist/components/icon.d.ts +1 -0
- package/dist/components/icon.d.ts.map +1 -1
- package/dist/components/icon.js +24 -8
- package/dist/components/icon.js.map +1 -1
- package/dist/components/list.d.ts +2 -2
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/list.js +140 -62
- package/dist/components/list.js.map +1 -1
- package/dist/components/loading-bar.d.ts.map +1 -1
- package/dist/components/loading-bar.js +2 -2
- package/dist/components/loading-bar.js.map +1 -1
- package/dist/components/loading-text.d.ts +8 -0
- package/dist/components/loading-text.d.ts.map +1 -0
- package/dist/components/loading-text.js +58 -0
- package/dist/components/loading-text.js.map +1 -0
- package/dist/descendants.js +1 -1
- package/dist/descendants.js.map +1 -1
- package/dist/dev-ui.d.ts +7 -0
- package/dist/dev-ui.d.ts.map +1 -0
- package/dist/dev-ui.js +118 -0
- package/dist/dev-ui.js.map +1 -0
- package/dist/environment.d.ts +63 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/environment.js +189 -0
- package/dist/environment.js.map +1 -0
- package/dist/examples/datepicker.d.ts +2 -0
- package/dist/examples/datepicker.d.ts.map +1 -0
- package/dist/examples/datepicker.js +344 -0
- package/dist/examples/datepicker.js.map +1 -0
- package/dist/examples/file-autocomplete.vitest.d.ts +2 -0
- package/dist/examples/file-autocomplete.vitest.d.ts.map +1 -0
- package/dist/examples/file-autocomplete.vitest.js +223 -0
- package/dist/examples/file-autocomplete.vitest.js.map +1 -0
- package/dist/examples/form-basic-arrow-keys.vitest.d.ts +2 -0
- package/dist/examples/form-basic-arrow-keys.vitest.d.ts.map +1 -0
- package/dist/examples/form-basic-arrow-keys.vitest.js +46 -0
- package/dist/examples/form-basic-arrow-keys.vitest.js.map +1 -0
- package/dist/examples/form-basic.vitest.d.ts +2 -0
- package/dist/examples/form-basic.vitest.d.ts.map +1 -0
- package/dist/examples/form-basic.vitest.js +630 -0
- package/dist/examples/form-basic.vitest.js.map +1 -0
- package/dist/examples/form-dropdown-with-sections.d.ts +2 -0
- package/dist/examples/form-dropdown-with-sections.d.ts.map +1 -0
- package/dist/examples/form-dropdown-with-sections.js +13 -0
- package/dist/examples/form-dropdown-with-sections.js.map +1 -0
- package/dist/examples/form-dropdown-with-sections.vitest.d.ts +2 -0
- package/dist/examples/form-dropdown-with-sections.vitest.d.ts.map +1 -0
- package/dist/examples/form-dropdown-with-sections.vitest.js +75 -0
- package/dist/examples/form-dropdown-with-sections.vitest.js.map +1 -0
- package/dist/examples/form-dropdown.vitest.d.ts +2 -0
- package/dist/examples/form-dropdown.vitest.d.ts.map +1 -0
- package/dist/examples/form-dropdown.vitest.js +854 -0
- package/dist/examples/form-dropdown.vitest.js.map +1 -0
- package/dist/examples/form-multiselect-dropdown.d.ts +2 -0
- package/dist/examples/form-multiselect-dropdown.d.ts.map +1 -0
- package/dist/examples/form-multiselect-dropdown.js +13 -0
- package/dist/examples/form-multiselect-dropdown.js.map +1 -0
- package/dist/examples/form-scroll.d.ts.map +1 -1
- package/dist/examples/form-scroll.js +7 -1
- package/dist/examples/form-scroll.js.map +1 -1
- package/dist/examples/form-scroll.vitest.d.ts +2 -0
- package/dist/examples/form-scroll.vitest.d.ts.map +1 -0
- package/dist/examples/form-scroll.vitest.js +211 -0
- package/dist/examples/form-scroll.vitest.js.map +1 -0
- package/dist/examples/form-tagpicker.vitest.d.ts +2 -0
- package/dist/examples/form-tagpicker.vitest.d.ts.map +1 -0
- package/dist/examples/form-tagpicker.vitest.js +736 -0
- package/dist/examples/form-tagpicker.vitest.js.map +1 -0
- package/dist/examples/internal/descendants-filtering.js +1 -1
- package/dist/examples/internal/descendants-filtering.js.map +1 -1
- package/dist/examples/internal/descendants.js +1 -1
- package/dist/examples/internal/descendants.js.map +1 -1
- package/dist/examples/internal/nested-boxes.d.ts +2 -0
- package/dist/examples/internal/nested-boxes.d.ts.map +1 -0
- package/dist/examples/internal/nested-boxes.js +7 -0
- package/dist/examples/internal/nested-boxes.js.map +1 -0
- package/dist/examples/internal/rhf-custom-ref.js +2 -2
- package/dist/examples/internal/rhf-custom-ref.js.map +1 -1
- package/dist/examples/internal/scrollbox-demo.js +3 -22
- package/dist/examples/internal/scrollbox-demo.js.map +1 -1
- package/dist/examples/internal/scrollbox-descendants.d.ts +2 -0
- package/dist/examples/internal/scrollbox-descendants.d.ts.map +1 -0
- package/dist/examples/internal/scrollbox-descendants.js +83 -0
- package/dist/examples/internal/scrollbox-descendants.js.map +1 -0
- package/dist/examples/internal/scrollbox-with-descendants.js +4 -8
- package/dist/examples/internal/scrollbox-with-descendants.js.map +1 -1
- package/dist/examples/internal/simple-scrollbox.vitest.d.ts +2 -0
- package/dist/examples/internal/simple-scrollbox.vitest.d.ts.map +1 -0
- package/dist/examples/internal/simple-scrollbox.vitest.js +96 -0
- package/dist/examples/internal/simple-scrollbox.vitest.js.map +1 -0
- package/dist/examples/internal/unicode-square-repro.d.ts +2 -0
- package/dist/examples/internal/unicode-square-repro.d.ts.map +1 -0
- package/dist/examples/internal/unicode-square-repro.js +7 -0
- package/dist/examples/internal/unicode-square-repro.js.map +1 -0
- package/dist/examples/list-detail-metadata.d.ts +2 -0
- package/dist/examples/list-detail-metadata.d.ts.map +1 -0
- package/dist/examples/list-detail-metadata.js +8 -0
- package/dist/examples/list-detail-metadata.js.map +1 -0
- package/dist/examples/list-dropdown-default.vitest.d.ts +2 -0
- package/dist/examples/list-dropdown-default.vitest.d.ts.map +1 -0
- package/dist/examples/list-dropdown-default.vitest.js +234 -0
- package/dist/examples/list-dropdown-default.vitest.js.map +1 -0
- package/dist/examples/list-fetch-data.vitest.d.ts +2 -0
- package/dist/examples/list-fetch-data.vitest.d.ts.map +1 -0
- package/dist/examples/list-fetch-data.vitest.js +111 -0
- package/dist/examples/list-fetch-data.vitest.js.map +1 -0
- package/dist/examples/list-filter-navigation.d.ts +2 -0
- package/dist/examples/list-filter-navigation.d.ts.map +1 -0
- package/dist/examples/list-filter-navigation.js +8 -0
- package/dist/examples/list-filter-navigation.js.map +1 -0
- package/dist/examples/list-scrollbox.vitest.d.ts +2 -0
- package/dist/examples/list-scrollbox.vitest.d.ts.map +1 -0
- package/dist/examples/list-scrollbox.vitest.js +93 -0
- package/dist/examples/list-scrollbox.vitest.js.map +1 -0
- package/dist/examples/list-with-detail-long.d.ts +2 -0
- package/dist/examples/list-with-detail-long.d.ts.map +1 -0
- package/dist/examples/list-with-detail-long.js +53 -0
- package/dist/examples/list-with-detail-long.js.map +1 -0
- package/dist/examples/list-with-detail.vitest.d.ts +2 -0
- package/dist/examples/list-with-detail.vitest.d.ts.map +1 -0
- package/dist/examples/list-with-detail.vitest.js +434 -0
- package/dist/examples/list-with-detail.vitest.js.map +1 -0
- package/dist/examples/list-with-dropdown.vitest.d.ts +2 -0
- package/dist/examples/list-with-dropdown.vitest.d.ts.map +1 -0
- package/dist/examples/list-with-dropdown.vitest.js +337 -0
- package/dist/examples/list-with-dropdown.vitest.js.map +1 -0
- package/dist/examples/list-with-sections.js +5 -1
- package/dist/examples/list-with-sections.js.map +1 -1
- package/dist/examples/list-with-sections.vitest.d.ts +2 -0
- package/dist/examples/list-with-sections.vitest.d.ts.map +1 -0
- package/dist/examples/list-with-sections.vitest.js +601 -0
- package/dist/examples/list-with-sections.vitest.js.map +1 -0
- package/dist/examples/scrollbox-vertical-centering.d.ts +6 -0
- package/dist/examples/scrollbox-vertical-centering.d.ts.map +1 -0
- package/dist/examples/scrollbox-vertical-centering.js +17 -0
- package/dist/examples/scrollbox-vertical-centering.js.map +1 -0
- package/dist/examples/simple-file-picker.vitest.d.ts +2 -0
- package/dist/examples/simple-file-picker.vitest.d.ts.map +1 -0
- package/dist/examples/simple-file-picker.vitest.js +678 -0
- package/dist/examples/simple-file-picker.vitest.js.map +1 -0
- package/dist/examples/simple-grid.vitest.d.ts +2 -0
- package/dist/examples/simple-grid.vitest.d.ts.map +1 -0
- package/dist/examples/simple-grid.vitest.js +521 -0
- package/dist/examples/simple-grid.vitest.js.map +1 -0
- package/dist/examples/simple-navigation.js +10 -4
- package/dist/examples/simple-navigation.js.map +1 -1
- package/dist/examples/simple-navigation.vitest.d.ts +2 -0
- package/dist/examples/simple-navigation.vitest.d.ts.map +1 -0
- package/dist/examples/simple-navigation.vitest.js +718 -0
- package/dist/examples/simple-navigation.vitest.js.map +1 -0
- package/dist/examples/store.vitest.d.ts +2 -0
- package/dist/examples/store.vitest.d.ts.map +1 -0
- package/dist/examples/store.vitest.js +69 -0
- package/dist/examples/store.vitest.js.map +1 -0
- package/dist/extensions/dev.d.ts +4 -2
- package/dist/extensions/dev.d.ts.map +1 -1
- package/dist/extensions/dev.js +61 -10
- package/dist/extensions/dev.js.map +1 -1
- package/dist/extensions/dev.vitest.d.ts +2 -0
- package/dist/extensions/dev.vitest.d.ts.map +1 -0
- package/dist/extensions/dev.vitest.js +197 -0
- package/dist/extensions/dev.vitest.js.map +1 -0
- package/dist/extensions/home.d.ts.map +1 -1
- package/dist/extensions/home.js +3 -0
- package/dist/extensions/home.js.map +1 -1
- package/dist/home-command.d.ts +8 -0
- package/dist/home-command.d.ts.map +1 -0
- package/dist/home-command.js +181 -0
- package/dist/home-command.js.map +1 -0
- package/dist/hover-repro.d.ts +2 -0
- package/dist/hover-repro.d.ts.map +1 -0
- package/dist/hover-repro.js +20 -0
- package/dist/hover-repro.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/dialog.d.ts +1 -0
- package/dist/internal/dialog.d.ts.map +1 -1
- package/dist/internal/dialog.js +27 -18
- package/dist/internal/dialog.js.map +1 -1
- package/dist/internal/navigation.d.ts +9 -1
- package/dist/internal/navigation.d.ts.map +1 -1
- package/dist/internal/navigation.js +5 -5
- package/dist/internal/navigation.js.map +1 -1
- package/dist/internal/offscreen.d.ts +6 -0
- package/dist/internal/offscreen.d.ts.map +1 -0
- package/dist/internal/offscreen.js +10 -0
- package/dist/internal/offscreen.js.map +1 -0
- package/dist/internal/providers.d.ts.map +1 -1
- package/dist/internal/providers.js +2 -2
- package/dist/internal/providers.js.map +1 -1
- package/dist/internal/scrollbox.d.ts +1 -10
- package/dist/internal/scrollbox.d.ts.map +1 -1
- package/dist/internal/scrollbox.js +2 -1
- package/dist/internal/scrollbox.js.map +1 -1
- package/dist/localstorage.d.ts +13 -0
- package/dist/localstorage.d.ts.map +1 -0
- package/dist/localstorage.js +190 -0
- package/dist/localstorage.js.map +1 -0
- package/dist/oauth.d.ts +142 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +551 -0
- package/dist/oauth.js.map +1 -0
- package/dist/preferences.d.ts +23 -0
- package/dist/preferences.d.ts.map +1 -0
- package/dist/preferences.js +105 -0
- package/dist/preferences.js.map +1 -0
- package/dist/state.d.ts +2 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +3 -0
- package/dist/state.js.map +1 -1
- package/dist/store.d.ts +21 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +84 -0
- package/dist/store.js.map +1 -0
- package/dist/swift-loader.d.ts +3 -0
- package/dist/swift-loader.d.ts.map +1 -0
- package/dist/swift-loader.js +193 -0
- package/dist/swift-loader.js.map +1 -0
- package/dist/swift-runtime.d.ts +2 -0
- package/dist/swift-runtime.d.ts.map +1 -0
- package/dist/swift-runtime.js +27 -0
- package/dist/swift-runtime.js.map +1 -0
- package/dist/toast.d.ts +44 -0
- package/dist/toast.d.ts.map +1 -0
- package/dist/toast.js +221 -0
- package/dist/toast.js.map +1 -0
- package/dist/utils/file-system.d.ts +9 -0
- package/dist/utils/file-system.d.ts.map +1 -1
- package/dist/utils/file-system.js +49 -0
- package/dist/utils/file-system.js.map +1 -1
- package/dist/utils/run-command.d.ts +25 -1
- package/dist/utils/run-command.d.ts.map +1 -1
- package/dist/utils/run-command.js +47 -4
- package/dist/utils/run-command.js.map +1 -1
- package/dist/window.d.ts +12 -0
- package/dist/window.d.ts.map +1 -0
- package/dist/window.js +48 -0
- package/dist/window.js.map +1 -0
- package/package.json +12 -10
- package/src/apis/browser-extension.tsx +29 -0
- package/src/apis/localstorage.test.ts +14 -6
- package/src/apis/localstorage.tsx +8 -5
- package/src/apis/oauth.tsx +5 -1
- package/src/apis/preferences.tsx +48 -22
- package/src/build.test.tsx +52 -0
- package/src/build.tsx +2 -1
- package/src/cli.tsx +78 -37
- package/src/compile.tsx +22 -5
- package/src/components/actions.tsx +94 -32
- package/src/components/detail.tsx +4 -0
- package/src/components/dropdown.tsx +47 -14
- package/src/components/extension-preferences.tsx +44 -16
- package/src/components/form/checkbox.tsx +12 -6
- package/src/components/form/date-picker.tsx +12 -6
- package/src/components/form/description.tsx +7 -2
- package/src/components/form/dropdown.tsx +131 -119
- package/src/components/form/file-autocomplete.tsx +90 -108
- package/src/components/form/file-picker.tsx +54 -43
- package/src/components/form/form-end.tsx +23 -2
- package/src/components/form/index.tsx +152 -34
- package/src/components/form/password-field.tsx +12 -6
- package/src/components/form/text-area.tsx +13 -6
- package/src/components/form/text-field.tsx +13 -6
- package/src/components/form/types.tsx +6 -0
- package/src/components/form/with-left-border.tsx +41 -8
- package/src/components/icon.tsx +27 -8
- package/src/components/list.tsx +193 -74
- package/src/components/loading-bar.tsx +3 -2
- package/src/components/loading-text.tsx +79 -0
- package/src/descendants.tsx +1 -0
- package/src/examples/file-autocomplete.vitest.tsx +130 -125
- package/src/examples/form-basic.vitest.tsx +376 -176
- package/src/examples/form-dropdown.vitest.tsx +126 -126
- package/src/examples/form-scroll.tsx +2 -0
- package/src/examples/form-scroll.vitest.tsx +58 -58
- package/src/examples/form-tagpicker.vitest.tsx +99 -99
- package/src/examples/internal/descendants-filtering.tsx +1 -0
- package/src/examples/internal/descendants.tsx +1 -0
- package/src/examples/internal/rhf-custom-ref.tsx +2 -0
- package/src/examples/internal/scrollbox-demo.tsx +3 -27
- package/src/examples/internal/scrollbox-with-descendants.tsx +4 -7
- package/src/examples/internal/simple-scrollbox.vitest.tsx +7 -5
- package/src/examples/list-detail-metadata.tsx +49 -0
- package/src/examples/list-detail-metadata.vitest.tsx +88 -0
- package/src/examples/list-dropdown-default.vitest.tsx +51 -51
- package/src/examples/list-fetch-data.vitest.tsx +4 -4
- package/src/examples/list-scrollbox.vitest.tsx +73 -14
- package/src/examples/list-with-detail-long.tsx +70 -0
- package/src/examples/list-with-detail.vitest.tsx +198 -92
- package/src/examples/list-with-dropdown.vitest.tsx +53 -53
- package/src/examples/list-with-sections.tsx +1 -0
- package/src/examples/list-with-sections.vitest.tsx +213 -89
- package/src/examples/list-with-toast.vitest.tsx +4 -4
- package/src/examples/simple-file-picker.vitest.tsx +61 -471
- package/src/examples/simple-grid.vitest.tsx +238 -233
- package/src/examples/simple-navigation.tsx +15 -7
- package/src/examples/simple-navigation.vitest.tsx +121 -210
- package/src/examples/store.vitest.tsx +1 -1
- package/src/examples/swift-extension.vitest.tsx +148 -0
- package/src/examples/synonyms.vitest.tsx +159 -0
- package/src/extensions/dev.tsx +74 -7
- package/src/extensions/dev.vitest.tsx +97 -31
- package/src/extensions/home.tsx +6 -0
- package/src/index.tsx +3 -0
- package/src/internal/dialog.tsx +43 -30
- package/src/internal/navigation.tsx +3 -1
- package/src/internal/offscreen.tsx +15 -0
- package/src/internal/providers.tsx +4 -2
- package/src/internal/scrollbox.tsx +4 -8
- package/src/keyboard.test.tsx +69 -0
- package/src/state.tsx +7 -0
- package/src/swift-loader.tsx +239 -0
- package/src/swift-runtime.tsx +36 -0
- package/src/utils/file-system.ts +61 -0
- package/src/utils/run-command.tsx +75 -6
|
@@ -1,12 +1,41 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { TextAttributes } from '@opentui/core'
|
|
3
3
|
import { Theme } from 'termcast/src/theme'
|
|
4
|
+
import { colord } from 'colord'
|
|
5
|
+
|
|
6
|
+
const spinnerFrames = [
|
|
7
|
+
{ char: ' ', color: Theme.accent },
|
|
8
|
+
{ char: '·', color: Theme.accent },
|
|
9
|
+
{ char: '•', color: colord(Theme.accent).lighten(0.1).toHex() },
|
|
10
|
+
// { char: '●', color: colord(Theme.accent).lighten(0.2).toHex() },
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
function Spinner(): any {
|
|
14
|
+
const [index, setIndex] = React.useState(0)
|
|
15
|
+
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
const interval = setInterval(() => {
|
|
18
|
+
setIndex((i) => (i + 1) % spinnerFrames.length)
|
|
19
|
+
}, 200)
|
|
20
|
+
return () => {
|
|
21
|
+
clearInterval(interval)
|
|
22
|
+
}
|
|
23
|
+
}, [])
|
|
24
|
+
|
|
25
|
+
const frame = spinnerFrames[index]
|
|
26
|
+
return (
|
|
27
|
+
<text flexShrink={0} fg={frame.color}>
|
|
28
|
+
<b>{frame.char}</b>
|
|
29
|
+
</text>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
4
32
|
|
|
5
33
|
interface WithLeftBorderProps {
|
|
6
34
|
children: React.ReactNode
|
|
7
35
|
withDiamond?: boolean
|
|
8
36
|
customCharacter?: { focused: string; unfocused: string }
|
|
9
37
|
isFocused: boolean
|
|
38
|
+
isLoading?: boolean
|
|
10
39
|
paddingBottom?: number
|
|
11
40
|
paddingLeft?: number
|
|
12
41
|
paddingTop?: number
|
|
@@ -18,21 +47,24 @@ export const WithLeftBorder = ({
|
|
|
18
47
|
withDiamond,
|
|
19
48
|
customCharacter,
|
|
20
49
|
isFocused,
|
|
50
|
+
isLoading,
|
|
21
51
|
paddingBottom = 1,
|
|
22
52
|
paddingLeft = 2,
|
|
23
53
|
paddingTop = 0,
|
|
24
54
|
}: WithLeftBorderProps): any => {
|
|
25
55
|
if (withDiamond || customCharacter) {
|
|
26
56
|
const chars = customCharacter || { focused: '◆', unfocused: '◇' }
|
|
57
|
+
const color = isFocused ? Theme.accent : Theme.text
|
|
27
58
|
return (
|
|
28
59
|
<box flexDirection='row'>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
60
|
+
{isFocused && isLoading ? (
|
|
61
|
+
<Spinner />
|
|
62
|
+
) : (
|
|
63
|
+
<text key={String(isFocused)} flexShrink={0} fg={color}>
|
|
64
|
+
<b>{isFocused ? chars.focused : chars.unfocused}</b>
|
|
65
|
+
</text>
|
|
66
|
+
)}
|
|
67
|
+
<box flexShrink={0} flexGrow={1} paddingLeft={paddingLeft}>
|
|
36
68
|
{children}
|
|
37
69
|
</box>
|
|
38
70
|
</box>
|
|
@@ -42,8 +74,9 @@ export const WithLeftBorder = ({
|
|
|
42
74
|
<box
|
|
43
75
|
paddingLeft={paddingLeft}
|
|
44
76
|
border={['left']}
|
|
45
|
-
borderStyle={isFocused ? 'heavy' : 'single'}
|
|
77
|
+
// borderStyle={isFocused ? 'heavy' : 'single'}
|
|
46
78
|
borderColor={isFocused ? Theme.accent : undefined}
|
|
79
|
+
flexShrink={0}
|
|
47
80
|
flexDirection='row'
|
|
48
81
|
>
|
|
49
82
|
<box paddingTop={paddingTop} paddingBottom={paddingBottom} flexGrow={1}>
|
package/src/components/icon.tsx
CHANGED
|
@@ -6,11 +6,11 @@ const ICON_SHAPES = [
|
|
|
6
6
|
'◆', // filled diamond
|
|
7
7
|
'▲', // filled triangle up
|
|
8
8
|
'▼', // filled triangle down
|
|
9
|
-
'★', // filled star
|
|
10
|
-
'♦', // diamond suit
|
|
11
|
-
'♥', // heart suit
|
|
12
|
-
'♠', // spade suit
|
|
13
|
-
'♣', // club suit
|
|
9
|
+
// '★', // filled star
|
|
10
|
+
// '♦', // diamond suit
|
|
11
|
+
// '♥', // heart suit
|
|
12
|
+
// '♠', // spade suit
|
|
13
|
+
// '♣', // club suit
|
|
14
14
|
]
|
|
15
15
|
|
|
16
16
|
function hashString(str: string): number {
|
|
@@ -505,13 +505,28 @@ function createIconEnum(): Record<string, string> {
|
|
|
505
505
|
return icons
|
|
506
506
|
}
|
|
507
507
|
|
|
508
|
-
|
|
508
|
+
function createIconWithUnicode(): Record<string, string> {
|
|
509
|
+
const icons: Record<string, string> = {}
|
|
510
|
+
|
|
511
|
+
for (const iconId of iconIds) {
|
|
512
|
+
const name = iconId.replace(/-16$/, '')
|
|
513
|
+
const pascalName = pascalCase(name)
|
|
514
|
+
icons[pascalName] = getIconShape(iconId)
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return icons
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
export const IconSource = createIconEnum()
|
|
521
|
+
export const Icon = createIconWithUnicode()
|
|
509
522
|
|
|
510
523
|
export function getIconEmoji(icon: string): string {
|
|
524
|
+
// If it's an icon ID (like 'pencil-16'), convert to unicode
|
|
511
525
|
if (iconIds.includes(icon)) {
|
|
512
526
|
return getIconShape(icon)
|
|
513
527
|
}
|
|
514
|
-
return
|
|
528
|
+
// Otherwise assume it's already unicode and return as-is
|
|
529
|
+
return icon
|
|
515
530
|
}
|
|
516
531
|
|
|
517
532
|
interface IconProps {
|
|
@@ -520,5 +535,9 @@ interface IconProps {
|
|
|
520
535
|
}
|
|
521
536
|
|
|
522
537
|
export function IconComponent({ source }: IconProps): any {
|
|
523
|
-
return
|
|
538
|
+
// If it's an icon ID, convert to unicode; otherwise return as-is
|
|
539
|
+
if (iconIds.includes(source)) {
|
|
540
|
+
return getIconShape(source)
|
|
541
|
+
}
|
|
542
|
+
return source
|
|
524
543
|
}
|
package/src/components/list.tsx
CHANGED
|
@@ -18,9 +18,11 @@ import React, {
|
|
|
18
18
|
} from 'react'
|
|
19
19
|
import { LoadingBar } from 'termcast/src/components/loading-bar'
|
|
20
20
|
import { createDescendants } from 'termcast/src/descendants'
|
|
21
|
+
import { useStore } from 'termcast/src/state'
|
|
21
22
|
import { useDialog } from 'termcast/src/internal/dialog'
|
|
22
23
|
import { useIsInFocus } from 'termcast/src/internal/focus-context'
|
|
23
24
|
import { useNavigationPending } from 'termcast/src/internal/navigation'
|
|
25
|
+
import { Offscreen } from 'termcast/src/internal/offscreen'
|
|
24
26
|
import { ScrollBox } from 'termcast/src/internal/scrollbox'
|
|
25
27
|
|
|
26
28
|
import { Color, resolveColor } from 'termcast/src/colors'
|
|
@@ -67,6 +69,8 @@ interface ActionsInterface {
|
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
function ListFooter(): any {
|
|
72
|
+
const firstActionTitle = useStore((s) => s.firstActionTitle)
|
|
73
|
+
|
|
70
74
|
return (
|
|
71
75
|
<box
|
|
72
76
|
border={false}
|
|
@@ -79,10 +83,14 @@ function ListFooter(): any {
|
|
|
79
83
|
flexDirection: 'row',
|
|
80
84
|
}}
|
|
81
85
|
>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
{firstActionTitle && (
|
|
87
|
+
<>
|
|
88
|
+
<text fg={Theme.text} attributes={TextAttributes.BOLD}>
|
|
89
|
+
↵
|
|
90
|
+
</text>
|
|
91
|
+
<text fg={Theme.textMuted}> {firstActionTitle.toLowerCase()}</text>
|
|
92
|
+
</>
|
|
93
|
+
)}
|
|
86
94
|
<text fg={Theme.text} attributes={TextAttributes.BOLD}>
|
|
87
95
|
{' '}↑↓
|
|
88
96
|
</text>
|
|
@@ -175,13 +183,13 @@ export interface ItemProps extends ActionsInterface, CommonProps {
|
|
|
175
183
|
tooltip: string
|
|
176
184
|
}
|
|
177
185
|
accessories?: ItemAccessory[]
|
|
178
|
-
detail?:
|
|
186
|
+
detail?: ReactNode
|
|
179
187
|
}
|
|
180
188
|
|
|
181
189
|
export interface DetailProps extends CommonProps {
|
|
182
190
|
isLoading?: boolean
|
|
183
191
|
markdown?: string
|
|
184
|
-
metadata?:
|
|
192
|
+
metadata?: ReactNode
|
|
185
193
|
}
|
|
186
194
|
|
|
187
195
|
export interface MetadataProps extends CommonProps {
|
|
@@ -380,7 +388,14 @@ function ListDropdownDialog(props: ListDropdownDialogProps): any {
|
|
|
380
388
|
// Wrapper function that updates search text
|
|
381
389
|
const setSearchText = (value: string) => {
|
|
382
390
|
setSearchTextRaw(value)
|
|
383
|
-
|
|
391
|
+
// TODO: use flushSync when available to force descendants to update visibility
|
|
392
|
+
const items = Object.values(descendantsContext.map.current)
|
|
393
|
+
.filter((item) => item.index !== -1 && item.props?.visible !== false)
|
|
394
|
+
.sort((a, b) => a.index - b.index)
|
|
395
|
+
|
|
396
|
+
if (items.length > 0 && items[0]) {
|
|
397
|
+
setSelectedIndex(items[0].index)
|
|
398
|
+
}
|
|
384
399
|
}
|
|
385
400
|
|
|
386
401
|
|
|
@@ -456,6 +471,7 @@ function ListDropdownDialog(props: ListDropdownDialogProps): any {
|
|
|
456
471
|
<textarea
|
|
457
472
|
ref={inputRef}
|
|
458
473
|
height={1}
|
|
474
|
+
wrapMode='none'
|
|
459
475
|
keyBindings={[
|
|
460
476
|
{ name: 'return', action: 'submit' },
|
|
461
477
|
{ name: 'linefeed', action: 'submit' },
|
|
@@ -670,7 +686,7 @@ export const List: ListType = (props) => {
|
|
|
670
686
|
const {
|
|
671
687
|
children,
|
|
672
688
|
onSelectionChange,
|
|
673
|
-
filtering
|
|
689
|
+
filtering,
|
|
674
690
|
searchText: controlledSearchText,
|
|
675
691
|
onSearchTextChange,
|
|
676
692
|
searchBarPlaceholder = 'Search...',
|
|
@@ -686,6 +702,7 @@ export const List: ListType = (props) => {
|
|
|
686
702
|
const [selectedIndex, setSelectedIndex] = useState(0)
|
|
687
703
|
const [isDropdownOpen, setIsDropdownOpen] = useState(false)
|
|
688
704
|
const [currentDetail, setCurrentDetail] = useState<ReactNode>(null)
|
|
705
|
+
const [currentItemActions, setCurrentItemActions] = useState<ReactNode>(null)
|
|
689
706
|
const inputRef = useRef<TextareaRenderable>(null)
|
|
690
707
|
const scrollBoxRef = useRef<ScrollBoxRenderable>(null)
|
|
691
708
|
const descendantsContext = useListDescendants()
|
|
@@ -700,23 +717,35 @@ export const List: ListType = (props) => {
|
|
|
700
717
|
useLayoutEffect(() => {
|
|
701
718
|
if (controlledSearchText === undefined) return
|
|
702
719
|
const textarea = inputRef.current
|
|
703
|
-
if (textarea
|
|
704
|
-
|
|
705
|
-
|
|
720
|
+
if (!textarea) return
|
|
721
|
+
|
|
722
|
+
// Skip if textarea already has the correct value
|
|
723
|
+
if (textarea.plainText === controlledSearchText) return
|
|
724
|
+
|
|
725
|
+
// Save cursor position, set text, then restore cursor (clamped to valid range)
|
|
726
|
+
const cursorOffset = textarea.cursorOffset
|
|
727
|
+
textarea.setText(controlledSearchText)
|
|
728
|
+
textarea.cursorOffset = Math.min(cursorOffset, controlledSearchText.length)
|
|
706
729
|
}, [controlledSearchText])
|
|
707
730
|
|
|
708
|
-
//
|
|
709
|
-
//
|
|
710
|
-
//
|
|
711
|
-
//
|
|
712
|
-
//
|
|
713
|
-
//
|
|
714
|
-
//
|
|
731
|
+
// Filtering logic (matches Raycast behavior):
|
|
732
|
+
//
|
|
733
|
+
// | filtering prop | onSearchTextChange | Result |
|
|
734
|
+
// |----------------|-------------------|-----------------|
|
|
735
|
+
// | undefined | undefined | true (default) |
|
|
736
|
+
// | undefined | provided | false |
|
|
737
|
+
// | true | undefined | true |
|
|
738
|
+
// | true | provided | true |
|
|
739
|
+
// | false | undefined | false |
|
|
740
|
+
// | false | provided | false |
|
|
741
|
+
//
|
|
742
|
+
// Summary: filtering defaults to true, but is implicitly disabled when
|
|
743
|
+
// onSearchTextChange is provided (user manages filtering). Set filtering={true}
|
|
744
|
+
// explicitly to use built-in filtering alongside onSearchTextChange.
|
|
715
745
|
const isFilteringEnabled = (() => {
|
|
716
746
|
if (filtering === false) return false
|
|
717
747
|
if (filtering === true) return true
|
|
718
|
-
|
|
719
|
-
return !onSearchTextChange // defaults to true unless onSearchTextChange is provided
|
|
748
|
+
return !onSearchTextChange
|
|
720
749
|
})()
|
|
721
750
|
|
|
722
751
|
const openDropdown = () => {
|
|
@@ -726,8 +755,15 @@ export const List: ListType = (props) => {
|
|
|
726
755
|
// Wrapper function that updates search text
|
|
727
756
|
const setInternalSearchText = (value: string) => {
|
|
728
757
|
setInternalSearchTextRaw(value)
|
|
729
|
-
//
|
|
730
|
-
|
|
758
|
+
// TODO: use flushSync when available to force descendants to update visibility
|
|
759
|
+
// before querying. For now, we compute visibility inline with the new search value.
|
|
760
|
+
const items = Object.values(descendantsContext.map.current)
|
|
761
|
+
.filter((item) => item.index !== -1 && item.props?.visible !== false)
|
|
762
|
+
.sort((a, b) => a.index - b.index)
|
|
763
|
+
|
|
764
|
+
if (items.length > 0 && items[0]) {
|
|
765
|
+
setSelectedIndex(items[0].index)
|
|
766
|
+
}
|
|
731
767
|
}
|
|
732
768
|
|
|
733
769
|
const listContextValue = useMemo<ListContextValue>(
|
|
@@ -758,27 +794,37 @@ export const List: ListType = (props) => {
|
|
|
758
794
|
if (selectedItemId !== undefined) {
|
|
759
795
|
const items = Object.values(descendantsContext.map.current)
|
|
760
796
|
.filter((item) => item.index !== -1)
|
|
761
|
-
.sort((a, b) => a.index - b.index)
|
|
762
797
|
|
|
763
|
-
const
|
|
764
|
-
if (
|
|
765
|
-
setSelectedIndex(index)
|
|
798
|
+
const foundItem = items.find((item) => item.props?.id === selectedItemId)
|
|
799
|
+
if (foundItem) {
|
|
800
|
+
setSelectedIndex(foundItem.index)
|
|
766
801
|
}
|
|
767
802
|
}
|
|
768
803
|
}, [selectedItemId])
|
|
769
804
|
|
|
770
|
-
// Call onSelectionChange when selection changes
|
|
805
|
+
// Call onSelectionChange when selection changes and track current item's actions
|
|
771
806
|
useEffect(() => {
|
|
772
|
-
if (!onSelectionChange) return
|
|
773
|
-
|
|
774
807
|
const items = Object.values(descendantsContext.map.current)
|
|
775
808
|
.filter((item) => item.index !== -1)
|
|
776
809
|
.sort((a, b) => a.index - b.index)
|
|
777
810
|
|
|
778
811
|
const currentItem = items.find((item) => item.index === selectedIndex)
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
812
|
+
|
|
813
|
+
// Track current item's actions for footer display
|
|
814
|
+
const actions = currentItem?.props?.actions ?? props.actions ?? null
|
|
815
|
+
setCurrentItemActions(actions)
|
|
816
|
+
|
|
817
|
+
// Clear first action title when there are no actions
|
|
818
|
+
if (!actions) {
|
|
819
|
+
useStore.setState({ firstActionTitle: '' })
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Call onSelectionChange callback if provided
|
|
823
|
+
if (onSelectionChange) {
|
|
824
|
+
const selectedId = currentItem?.props?.id ?? null
|
|
825
|
+
onSelectionChange(selectedId)
|
|
826
|
+
}
|
|
827
|
+
}, [selectedIndex, props.actions])
|
|
782
828
|
|
|
783
829
|
const scrollToItem = (item: { props?: ListItemDescendant }) => {
|
|
784
830
|
const scrollBox = scrollBoxRef.current
|
|
@@ -787,29 +833,24 @@ export const List: ListType = (props) => {
|
|
|
787
833
|
|
|
788
834
|
const contentY = scrollBox.content?.y || 0
|
|
789
835
|
const viewportHeight = scrollBox.viewport?.height || 10
|
|
790
|
-
const currentScrollTop = scrollBox.scrollTop || 0
|
|
791
836
|
|
|
837
|
+
// Calculate item position relative to content
|
|
792
838
|
const itemTop = elementRef.y - contentY
|
|
793
|
-
const itemBottom = itemTop + elementRef.height
|
|
794
|
-
|
|
795
|
-
const visibleTop = currentScrollTop
|
|
796
|
-
const visibleBottom = currentScrollTop + viewportHeight
|
|
797
839
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
scrollBox.scrollTo(itemBottom - viewportHeight)
|
|
802
|
-
}
|
|
840
|
+
// Scroll so the top of the item is centered in the viewport
|
|
841
|
+
const targetScrollTop = itemTop - viewportHeight / 2
|
|
842
|
+
scrollBox.scrollTo(Math.max(0, targetScrollTop))
|
|
803
843
|
}
|
|
804
844
|
|
|
805
845
|
const move = (direction: -1 | 1) => {
|
|
846
|
+
// Get all visible items
|
|
806
847
|
const items = Object.values(descendantsContext.map.current)
|
|
807
848
|
.filter((item) => item.index !== -1 && item.props?.visible !== false)
|
|
808
849
|
.sort((a, b) => a.index - b.index)
|
|
809
850
|
|
|
810
851
|
if (items.length === 0) return
|
|
811
852
|
|
|
812
|
-
|
|
853
|
+
// Find currently selected item's position in visible items
|
|
813
854
|
let currentVisibleIndex = items.findIndex(
|
|
814
855
|
(item) => item.index === selectedIndex,
|
|
815
856
|
)
|
|
@@ -817,19 +858,19 @@ export const List: ListType = (props) => {
|
|
|
817
858
|
// If current selection is not visible, select first visible item
|
|
818
859
|
if (items[0]) {
|
|
819
860
|
setSelectedIndex(items[0].index)
|
|
820
|
-
scrollToItem(items[0])
|
|
821
861
|
}
|
|
822
862
|
return
|
|
823
863
|
}
|
|
824
864
|
|
|
865
|
+
// Calculate next visible index
|
|
825
866
|
let nextVisibleIndex = currentVisibleIndex + direction
|
|
826
867
|
if (nextVisibleIndex < 0) nextVisibleIndex = items.length - 1
|
|
827
868
|
if (nextVisibleIndex >= items.length) nextVisibleIndex = 0
|
|
828
869
|
|
|
829
870
|
const nextItem = items[nextVisibleIndex]
|
|
830
871
|
if (nextItem) {
|
|
831
|
-
setSelectedIndex(nextItem.index)
|
|
832
872
|
scrollToItem(nextItem)
|
|
873
|
+
setSelectedIndex(nextItem.index)
|
|
833
874
|
}
|
|
834
875
|
}
|
|
835
876
|
|
|
@@ -845,14 +886,14 @@ export const List: ListType = (props) => {
|
|
|
845
886
|
return
|
|
846
887
|
}
|
|
847
888
|
|
|
848
|
-
//
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
const currentItem = items.find((item) => item.index === selectedIndex)
|
|
889
|
+
// Get current item by selectedIndex (which is a descendant index)
|
|
890
|
+
const items = Object.values(descendantsContext.map.current)
|
|
891
|
+
.filter((item) => item.index !== -1)
|
|
892
|
+
.sort((a, b) => a.index - b.index)
|
|
893
|
+
const currentItem = items.find((item) => item.index === selectedIndex)
|
|
855
894
|
|
|
895
|
+
// Handle Ctrl+K to show actions (always show sheet)
|
|
896
|
+
if (evt.name === 'k' && evt.ctrl) {
|
|
856
897
|
// Show current item's actions if available
|
|
857
898
|
if (currentItem?.props?.actions) {
|
|
858
899
|
dialog.push(currentItem.props.actions, 'bottom-right')
|
|
@@ -866,15 +907,12 @@ export const List: ListType = (props) => {
|
|
|
866
907
|
|
|
867
908
|
if (evt.name === 'up') move(-1)
|
|
868
909
|
if (evt.name === 'down') move(1)
|
|
910
|
+
// Handle Enter to execute first action directly
|
|
869
911
|
if (evt.name === 'return') {
|
|
870
|
-
const items = Object.values(descendantsContext.map.current)
|
|
871
|
-
.filter((item) => item.index !== -1)
|
|
872
|
-
.sort((a, b) => a.index - b.index)
|
|
873
|
-
|
|
874
|
-
const currentItem = items.find((item) => item.index === selectedIndex)
|
|
875
912
|
if (!currentItem?.props) return
|
|
876
913
|
|
|
877
914
|
if (currentItem.props.actions) {
|
|
915
|
+
useStore.setState({ shouldAutoExecuteFirstAction: true })
|
|
878
916
|
dialog.push(currentItem.props.actions, 'bottom-right')
|
|
879
917
|
}
|
|
880
918
|
}
|
|
@@ -904,7 +942,10 @@ export const List: ListType = (props) => {
|
|
|
904
942
|
border={false}
|
|
905
943
|
style={{
|
|
906
944
|
paddingBottom: 0,
|
|
907
|
-
|
|
945
|
+
flexShrink: 0,
|
|
946
|
+
paddingLeft: 1,
|
|
947
|
+
paddingRight: 1,
|
|
948
|
+
overflow: 'hidden',
|
|
908
949
|
}}
|
|
909
950
|
>
|
|
910
951
|
<LoadingBar
|
|
@@ -938,6 +979,7 @@ export const List: ListType = (props) => {
|
|
|
938
979
|
<textarea
|
|
939
980
|
ref={inputRef}
|
|
940
981
|
height={1}
|
|
982
|
+
wrapMode='none'
|
|
941
983
|
keyBindings={[
|
|
942
984
|
{ name: 'return', action: 'submit' },
|
|
943
985
|
{ name: 'linefeed', action: 'submit' },
|
|
@@ -985,6 +1027,11 @@ export const List: ListType = (props) => {
|
|
|
985
1027
|
|
|
986
1028
|
{/* Footer with keyboard shortcuts or toast */}
|
|
987
1029
|
<ListFooter />
|
|
1030
|
+
|
|
1031
|
+
{/* Render current item's actions offscreen to collect first action title */}
|
|
1032
|
+
{currentItemActions && (
|
|
1033
|
+
<Offscreen>{currentItemActions}</Offscreen>
|
|
1034
|
+
)}
|
|
988
1035
|
</box>
|
|
989
1036
|
|
|
990
1037
|
{/* Detail panel on the right */}
|
|
@@ -1076,7 +1123,7 @@ const ListItem: ListItemType = (props) => {
|
|
|
1076
1123
|
elementRef: elementRef.current,
|
|
1077
1124
|
})
|
|
1078
1125
|
|
|
1079
|
-
//
|
|
1126
|
+
// Check if this item is selected
|
|
1080
1127
|
const selectedIndex = listContext?.selectedIndex ?? 0
|
|
1081
1128
|
const isActive = index === selectedIndex
|
|
1082
1129
|
|
|
@@ -1156,7 +1203,7 @@ const ListItemDetail: ListItemDetailType = (props) => {
|
|
|
1156
1203
|
)}
|
|
1157
1204
|
|
|
1158
1205
|
<ScrollBox
|
|
1159
|
-
focused={
|
|
1206
|
+
focused={false}
|
|
1160
1207
|
flexGrow={1}
|
|
1161
1208
|
flexShrink={1}
|
|
1162
1209
|
style={{
|
|
@@ -1200,8 +1247,8 @@ const ListItemDetailMetadata = (props: MetadataProps) => {
|
|
|
1200
1247
|
|
|
1201
1248
|
const ListItemDetailMetadataLabel = (props: { title: string; text?: string; icon?: Image.ImageLike }) => {
|
|
1202
1249
|
return (
|
|
1203
|
-
<box style={{ flexDirection: '
|
|
1204
|
-
<text fg={Theme.textMuted}
|
|
1250
|
+
<box style={{ flexDirection: 'column', paddingBottom: 0.5 }}>
|
|
1251
|
+
<text fg={Theme.textMuted}>{props.title}:</text>
|
|
1205
1252
|
{props.text && <text fg={Theme.text}>{props.text}</text>}
|
|
1206
1253
|
</box>
|
|
1207
1254
|
)
|
|
@@ -1217,8 +1264,8 @@ const ListItemDetailMetadataSeparator = () => {
|
|
|
1217
1264
|
|
|
1218
1265
|
const ListItemDetailMetadataLink = (props: { title: string; target: string; text: string }) => {
|
|
1219
1266
|
return (
|
|
1220
|
-
<box style={{ flexDirection: '
|
|
1221
|
-
<text fg={Theme.textMuted}
|
|
1267
|
+
<box style={{ flexDirection: 'column', paddingBottom: 0.5 }}>
|
|
1268
|
+
<text fg={Theme.textMuted}>{props.title}:</text>
|
|
1222
1269
|
<text fg={Theme.link}>{props.text}</text>
|
|
1223
1270
|
</box>
|
|
1224
1271
|
)
|
|
@@ -1568,13 +1615,21 @@ const ListSection = (props: SectionProps) => {
|
|
|
1568
1615
|
[parentContext, props.title, searchText],
|
|
1569
1616
|
)
|
|
1570
1617
|
|
|
1571
|
-
|
|
1572
|
-
|
|
1618
|
+
const isSearching = searchText.trim().length > 0
|
|
1619
|
+
|
|
1620
|
+
const children = (
|
|
1621
|
+
<ListSectionContext.Provider value={sectionContextValue}>
|
|
1622
|
+
{props.children}
|
|
1623
|
+
</ListSectionContext.Provider>
|
|
1624
|
+
)
|
|
1625
|
+
|
|
1626
|
+
if (isSearching) {
|
|
1627
|
+
return children
|
|
1628
|
+
}
|
|
1573
1629
|
|
|
1574
1630
|
return (
|
|
1575
1631
|
<box style={{ marginBottom: 1 }}>
|
|
1576
|
-
{
|
|
1577
|
-
{showTitle && (
|
|
1632
|
+
{props.title && (
|
|
1578
1633
|
<box
|
|
1579
1634
|
border={false}
|
|
1580
1635
|
style={{
|
|
@@ -1586,18 +1641,82 @@ const ListSection = (props: SectionProps) => {
|
|
|
1586
1641
|
</text>
|
|
1587
1642
|
</box>
|
|
1588
1643
|
)}
|
|
1589
|
-
{
|
|
1590
|
-
<ListSectionContext.Provider value={sectionContextValue}>
|
|
1591
|
-
{props.children}
|
|
1592
|
-
</ListSectionContext.Provider>
|
|
1644
|
+
{children}
|
|
1593
1645
|
</box>
|
|
1594
1646
|
)
|
|
1595
1647
|
}
|
|
1596
1648
|
|
|
1597
1649
|
List.Section = ListSection
|
|
1598
1650
|
List.Dropdown = ListDropdown
|
|
1599
|
-
List.EmptyView = (props) => {
|
|
1600
|
-
|
|
1651
|
+
List.EmptyView = (props: EmptyViewProps) => {
|
|
1652
|
+
const dialog = useDialog()
|
|
1653
|
+
const inFocus = useIsInFocus()
|
|
1654
|
+
|
|
1655
|
+
// Handle keyboard for actions
|
|
1656
|
+
useKeyboard((evt) => {
|
|
1657
|
+
if (!inFocus) return
|
|
1658
|
+
|
|
1659
|
+
// Handle Ctrl+K to show actions
|
|
1660
|
+
if (evt.name === 'k' && evt.ctrl && props.actions) {
|
|
1661
|
+
dialog.push(props.actions, 'bottom-right')
|
|
1662
|
+
return
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
// Handle Enter to execute first action
|
|
1666
|
+
if (evt.name === 'return' && props.actions) {
|
|
1667
|
+
useStore.setState({ shouldAutoExecuteFirstAction: true })
|
|
1668
|
+
dialog.push(props.actions, 'bottom-right')
|
|
1669
|
+
}
|
|
1670
|
+
})
|
|
1671
|
+
|
|
1672
|
+
// Get icon string from ImageLike
|
|
1673
|
+
const getIconString = (icon: Image.ImageLike): string | null => {
|
|
1674
|
+
if (typeof icon === 'string') {
|
|
1675
|
+
return getIconEmoji(icon)
|
|
1676
|
+
}
|
|
1677
|
+
if (icon && typeof icon === 'object' && 'source' in icon) {
|
|
1678
|
+
// For { source: string } or { source: { light, dark } } objects
|
|
1679
|
+
const source = icon.source
|
|
1680
|
+
if (typeof source === 'string') {
|
|
1681
|
+
return getIconEmoji(source)
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
return null
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
const iconEmoji = props.icon ? getIconString(props.icon) : null
|
|
1688
|
+
|
|
1689
|
+
return (
|
|
1690
|
+
<box
|
|
1691
|
+
style={{
|
|
1692
|
+
flexDirection: 'column',
|
|
1693
|
+
alignItems: 'center',
|
|
1694
|
+
justifyContent: 'center',
|
|
1695
|
+
flexGrow: 1,
|
|
1696
|
+
paddingTop: 2,
|
|
1697
|
+
paddingBottom: 2,
|
|
1698
|
+
paddingLeft: 2,
|
|
1699
|
+
paddingRight: 2,
|
|
1700
|
+
gap: 1,
|
|
1701
|
+
}}
|
|
1702
|
+
>
|
|
1703
|
+
{iconEmoji && (
|
|
1704
|
+
<text fg={Theme.textMuted} style={{ marginBottom: 1 }}>
|
|
1705
|
+
{iconEmoji}
|
|
1706
|
+
</text>
|
|
1707
|
+
)}
|
|
1708
|
+
{props.title && (
|
|
1709
|
+
<text fg={Theme.text} attributes={TextAttributes.BOLD}>
|
|
1710
|
+
{props.title?.replace(/\bRaycast\b/g, 'Termcast').replace(/\braycast\b/g, 'termcast') || ''}
|
|
1711
|
+
</text>
|
|
1712
|
+
)}
|
|
1713
|
+
{props.description && (
|
|
1714
|
+
<text fg={Theme.textMuted} wrapMode='word'>
|
|
1715
|
+
{props.description?.replace(/\bRaycast\b/g, 'Termcast').replace(/\braycast\b/g, 'termcast') || ''}
|
|
1716
|
+
</text>
|
|
1717
|
+
)}
|
|
1718
|
+
</box>
|
|
1719
|
+
)
|
|
1601
1720
|
}
|
|
1602
1721
|
|
|
1603
1722
|
export default List
|
|
@@ -127,10 +127,11 @@ export function LoadingBar(props: LoadingBarProps): any {
|
|
|
127
127
|
style={{
|
|
128
128
|
flexDirection: 'row',
|
|
129
129
|
flexGrow: 1,
|
|
130
|
-
paddingLeft: 1,
|
|
131
|
-
paddingRight: 1,
|
|
130
|
+
// paddingLeft: 1,
|
|
131
|
+
// paddingRight: 1,
|
|
132
132
|
}}
|
|
133
133
|
>
|
|
134
|
+
|
|
134
135
|
{characters.map((char, index) => (
|
|
135
136
|
<text key={index} fg={getCharacterColor(index)} flexShrink={0}>
|
|
136
137
|
{char}
|