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
|
@@ -17,8 +17,12 @@ import {
|
|
|
17
17
|
moveToTrash,
|
|
18
18
|
} from 'termcast/src/action-utils'
|
|
19
19
|
import { useDialog } from 'termcast/src/internal/dialog'
|
|
20
|
+
import { useNavigation } from 'termcast/src/internal/navigation'
|
|
20
21
|
import { Dropdown } from 'termcast/src/components/dropdown'
|
|
22
|
+
import { ExtensionPreferences } from 'termcast/src/components/extension-preferences'
|
|
23
|
+
import { useStore } from 'termcast/src/state'
|
|
21
24
|
import { useIsInFocus } from 'termcast/src/internal/focus-context'
|
|
25
|
+
import { useIsOffscreen } from 'termcast/src/internal/offscreen'
|
|
22
26
|
import { CommonProps } from 'termcast/src/utils'
|
|
23
27
|
import type {
|
|
24
28
|
KeyboardShortcut,
|
|
@@ -180,7 +184,7 @@ const Action: ActionType = (props) => {
|
|
|
180
184
|
|
|
181
185
|
const isDestructive = props.style === ActionStyle.Destructive
|
|
182
186
|
|
|
183
|
-
// Render as Dropdown.Item
|
|
187
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
184
188
|
return (
|
|
185
189
|
<Dropdown.Item
|
|
186
190
|
title={props.title}
|
|
@@ -210,7 +214,7 @@ Action.Push = (props) => {
|
|
|
210
214
|
},
|
|
211
215
|
})
|
|
212
216
|
|
|
213
|
-
// Render as Dropdown.Item
|
|
217
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
214
218
|
return (
|
|
215
219
|
<Dropdown.Item
|
|
216
220
|
title={props.title}
|
|
@@ -243,7 +247,7 @@ Action.CopyToClipboard = (props) => {
|
|
|
243
247
|
},
|
|
244
248
|
})
|
|
245
249
|
|
|
246
|
-
// Render as Dropdown.Item
|
|
250
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
247
251
|
return (
|
|
248
252
|
<Dropdown.Item
|
|
249
253
|
title={props.title}
|
|
@@ -270,7 +274,7 @@ Action.OpenInBrowser = (props) => {
|
|
|
270
274
|
},
|
|
271
275
|
})
|
|
272
276
|
|
|
273
|
-
// Render as Dropdown.Item
|
|
277
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
274
278
|
return (
|
|
275
279
|
<Dropdown.Item
|
|
276
280
|
title={props.title}
|
|
@@ -298,7 +302,7 @@ Action.Open = (props) => {
|
|
|
298
302
|
},
|
|
299
303
|
})
|
|
300
304
|
|
|
301
|
-
// Render as Dropdown.Item
|
|
305
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
302
306
|
return (
|
|
303
307
|
<Dropdown.Item
|
|
304
308
|
title={props.title}
|
|
@@ -328,7 +332,7 @@ Action.Paste = (props) => {
|
|
|
328
332
|
},
|
|
329
333
|
})
|
|
330
334
|
|
|
331
|
-
// Render as Dropdown.Item
|
|
335
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
332
336
|
return (
|
|
333
337
|
<Dropdown.Item
|
|
334
338
|
title={props.title}
|
|
@@ -355,7 +359,7 @@ Action.ShowInFinder = (props) => {
|
|
|
355
359
|
},
|
|
356
360
|
})
|
|
357
361
|
|
|
358
|
-
// Render as Dropdown.Item
|
|
362
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
359
363
|
return (
|
|
360
364
|
<Dropdown.Item
|
|
361
365
|
title={props.title || 'Show in Finder'}
|
|
@@ -382,7 +386,7 @@ Action.OpenWith = (props) => {
|
|
|
382
386
|
},
|
|
383
387
|
})
|
|
384
388
|
|
|
385
|
-
// Render as Dropdown.Item
|
|
389
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
386
390
|
return (
|
|
387
391
|
<Dropdown.Item
|
|
388
392
|
title={props.title || `Open with ${props.application}`}
|
|
@@ -413,7 +417,7 @@ Action.Trash = (props) => {
|
|
|
413
417
|
},
|
|
414
418
|
})
|
|
415
419
|
|
|
416
|
-
// Render as Dropdown.Item
|
|
420
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
417
421
|
return (
|
|
418
422
|
<Dropdown.Item
|
|
419
423
|
title={props.title || 'Move to Trash'}
|
|
@@ -448,7 +452,7 @@ Action.SubmitForm = (props) => {
|
|
|
448
452
|
},
|
|
449
453
|
})
|
|
450
454
|
|
|
451
|
-
// Render as Dropdown.Item
|
|
455
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
452
456
|
return (
|
|
453
457
|
<Dropdown.Item
|
|
454
458
|
title={props.title || 'Submit'}
|
|
@@ -480,7 +484,7 @@ Action.CreateSnippet = (props) => {
|
|
|
480
484
|
},
|
|
481
485
|
})
|
|
482
486
|
|
|
483
|
-
// Render as Dropdown.Item
|
|
487
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
484
488
|
return (
|
|
485
489
|
<Dropdown.Item
|
|
486
490
|
title={props.title || 'Create Snippet'}
|
|
@@ -510,7 +514,7 @@ Action.CreateQuicklink = (props) => {
|
|
|
510
514
|
},
|
|
511
515
|
})
|
|
512
516
|
|
|
513
|
-
// Render as Dropdown.Item
|
|
517
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
514
518
|
return (
|
|
515
519
|
<Dropdown.Item
|
|
516
520
|
title={props.title || 'Create Quicklink'}
|
|
@@ -540,7 +544,7 @@ Action.ToggleQuickLook = (props) => {
|
|
|
540
544
|
},
|
|
541
545
|
})
|
|
542
546
|
|
|
543
|
-
// Render as Dropdown.Item
|
|
547
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
544
548
|
return (
|
|
545
549
|
<Dropdown.Item
|
|
546
550
|
title={props.title || 'Quick Look'}
|
|
@@ -552,8 +556,6 @@ Action.ToggleQuickLook = (props) => {
|
|
|
552
556
|
}
|
|
553
557
|
|
|
554
558
|
Action.PickDate = (props) => {
|
|
555
|
-
const dialog = useDialog()
|
|
556
|
-
|
|
557
559
|
// Register as descendant with execute function
|
|
558
560
|
useActionDescendant({
|
|
559
561
|
title: props.title || 'Pick Date',
|
|
@@ -570,7 +572,7 @@ Action.PickDate = (props) => {
|
|
|
570
572
|
},
|
|
571
573
|
})
|
|
572
574
|
|
|
573
|
-
// Render as Dropdown.Item
|
|
575
|
+
// Render as Dropdown.Item (handles offscreen check internally)
|
|
574
576
|
return (
|
|
575
577
|
<Dropdown.Item
|
|
576
578
|
title={props.title || 'Pick Date'}
|
|
@@ -631,31 +633,55 @@ function formatShortcut(
|
|
|
631
633
|
const ActionPanel: ActionPanelType = (props) => {
|
|
632
634
|
const { children, title } = props
|
|
633
635
|
const dialog = useDialog()
|
|
636
|
+
const { push } = useNavigation()
|
|
634
637
|
const inFocus = useIsInFocus()
|
|
638
|
+
const isOffscreen = useIsOffscreen()
|
|
635
639
|
const descendantsContext = useActionDescendants()
|
|
636
640
|
|
|
641
|
+
// Get extension and command info for configure actions
|
|
642
|
+
const extensionPackageJson = useStore((state) => state.extensionPackageJson)
|
|
643
|
+
const currentCommandName = useStore((state) => state.currentCommandName)
|
|
644
|
+
|
|
645
|
+
const hasExtensionPrefs =
|
|
646
|
+
(extensionPackageJson?.preferences?.length ?? 0) > 0
|
|
647
|
+
const currentCommand = extensionPackageJson?.commands?.find(
|
|
648
|
+
(c) => c.name === currentCommandName,
|
|
649
|
+
)
|
|
650
|
+
const hasCommandPrefs = (currentCommand?.preferences?.length ?? 0) > 0
|
|
651
|
+
|
|
637
652
|
// Create context value
|
|
638
653
|
const contextValue = useMemo<ActionPanelContextValue>(
|
|
639
654
|
() => ({ currentSection: undefined }),
|
|
640
655
|
[],
|
|
641
656
|
)
|
|
642
657
|
|
|
643
|
-
//
|
|
644
|
-
|
|
645
|
-
// if (!inFocus) return
|
|
646
|
-
|
|
647
|
-
// Check if there's only one action and execute it immediately
|
|
658
|
+
// Auto-execute first action if flag is set (triggered by enter/ctrl+enter)
|
|
659
|
+
// Also report first action title when rendered offscreen
|
|
648
660
|
useLayoutEffect(() => {
|
|
649
661
|
const allActions = Object.values(descendantsContext.map.current)
|
|
650
662
|
.filter((item: any) => item.index !== -1)
|
|
651
663
|
.map((item: any) => item.props as ActionDescendant)
|
|
652
664
|
|
|
653
|
-
|
|
654
|
-
|
|
665
|
+
// When offscreen, just report first action title for footer display
|
|
666
|
+
if (isOffscreen) {
|
|
667
|
+
useStore.setState({ firstActionTitle: allActions[0]?.title ?? '' })
|
|
668
|
+
return
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
const shouldExecute = useStore.getState().shouldAutoExecuteFirstAction
|
|
672
|
+
useStore.setState({ shouldAutoExecuteFirstAction: false })
|
|
673
|
+
|
|
674
|
+
if (!shouldExecute) return
|
|
675
|
+
|
|
676
|
+
if (allActions[0]) {
|
|
677
|
+
logger.log(`Auto-executing first action: ${allActions[0].title}`)
|
|
655
678
|
dialog.clear()
|
|
656
679
|
allActions[0].execute()
|
|
657
680
|
}
|
|
658
|
-
}, [descendantsContext.map, dialog])
|
|
681
|
+
}, [descendantsContext.map, dialog, isOffscreen])
|
|
682
|
+
|
|
683
|
+
// prevent showing actions if no dialog is shown (must be after hooks)
|
|
684
|
+
if (!dialog.stack.length && !isOffscreen) return null
|
|
659
685
|
|
|
660
686
|
// ActionPanel renders as Dropdown with children
|
|
661
687
|
return (
|
|
@@ -680,6 +706,38 @@ const ActionPanel: ActionPanelType = (props) => {
|
|
|
680
706
|
}}
|
|
681
707
|
>
|
|
682
708
|
{children}
|
|
709
|
+
{(hasExtensionPrefs || hasCommandPrefs) && (
|
|
710
|
+
<ActionPanel.Section title="Settings">
|
|
711
|
+
{hasExtensionPrefs && (
|
|
712
|
+
<Action
|
|
713
|
+
title="Configure Extension..."
|
|
714
|
+
shortcut={{ modifiers: ['cmd', 'shift'], key: ',' }}
|
|
715
|
+
onAction={() => {
|
|
716
|
+
dialog.clear()
|
|
717
|
+
push(
|
|
718
|
+
<ExtensionPreferences
|
|
719
|
+
extensionName={extensionPackageJson!.name}
|
|
720
|
+
/>,
|
|
721
|
+
)
|
|
722
|
+
}}
|
|
723
|
+
/>
|
|
724
|
+
)}
|
|
725
|
+
{hasCommandPrefs && (
|
|
726
|
+
<Action
|
|
727
|
+
title="Configure Command..."
|
|
728
|
+
onAction={() => {
|
|
729
|
+
dialog.clear()
|
|
730
|
+
push(
|
|
731
|
+
<ExtensionPreferences
|
|
732
|
+
extensionName={extensionPackageJson!.name}
|
|
733
|
+
commandName={currentCommandName!}
|
|
734
|
+
/>,
|
|
735
|
+
)
|
|
736
|
+
}}
|
|
737
|
+
/>
|
|
738
|
+
)}
|
|
739
|
+
</ActionPanel.Section>
|
|
740
|
+
)}
|
|
683
741
|
</Dropdown>
|
|
684
742
|
</ActionPanelContext.Provider>
|
|
685
743
|
</ActionDescendantsProvider>
|
|
@@ -698,11 +756,13 @@ ActionPanel.Section = (props) => {
|
|
|
698
756
|
[parentContext, props.title],
|
|
699
757
|
)
|
|
700
758
|
|
|
701
|
-
// Section provides context to its children
|
|
759
|
+
// Section renders Dropdown.Section and provides context to its children
|
|
702
760
|
return (
|
|
703
|
-
<
|
|
704
|
-
{
|
|
705
|
-
|
|
761
|
+
<Dropdown.Section title={props.title}>
|
|
762
|
+
<ActionPanelContext.Provider value={sectionContextValue}>
|
|
763
|
+
{props.children}
|
|
764
|
+
</ActionPanelContext.Provider>
|
|
765
|
+
</Dropdown.Section>
|
|
706
766
|
)
|
|
707
767
|
}
|
|
708
768
|
|
|
@@ -718,11 +778,13 @@ ActionPanel.Submenu = (props) => {
|
|
|
718
778
|
[parentContext, props.title],
|
|
719
779
|
)
|
|
720
780
|
|
|
721
|
-
// Submenu provides context to its children
|
|
781
|
+
// Submenu renders Dropdown.Section and provides context to its children
|
|
722
782
|
return (
|
|
723
|
-
<
|
|
724
|
-
{
|
|
725
|
-
|
|
783
|
+
<Dropdown.Section title={props.title}>
|
|
784
|
+
<ActionPanelContext.Provider value={submenuContextValue}>
|
|
785
|
+
{props.children}
|
|
786
|
+
</ActionPanelContext.Provider>
|
|
787
|
+
</Dropdown.Section>
|
|
726
788
|
)
|
|
727
789
|
}
|
|
728
790
|
|
|
@@ -9,6 +9,7 @@ import { Color, resolveColor } from 'termcast/src/colors'
|
|
|
9
9
|
|
|
10
10
|
import { useDialog } from 'termcast/src/internal/dialog'
|
|
11
11
|
import { ScrollBox } from 'termcast/src/internal/scrollbox'
|
|
12
|
+
import { useStore } from 'termcast/src/state'
|
|
12
13
|
|
|
13
14
|
interface ActionsInterface {
|
|
14
15
|
actions?: ReactNode
|
|
@@ -277,8 +278,11 @@ const Detail: DetailType = (props) => {
|
|
|
277
278
|
if (!inFocus) return
|
|
278
279
|
|
|
279
280
|
if (evt.name === 'k' && evt.ctrl && actions) {
|
|
281
|
+
// Ctrl+K shows actions (always show sheet)
|
|
280
282
|
dialog.push(actions, 'bottom-right')
|
|
281
283
|
} else if (evt.name === 'return' && actions) {
|
|
284
|
+
// Enter executes first action directly
|
|
285
|
+
useStore.setState({ shouldAutoExecuteFirstAction: true })
|
|
282
286
|
dialog.push(actions, 'bottom-right')
|
|
283
287
|
}
|
|
284
288
|
})
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import { Theme } from 'termcast/src/theme'
|
|
17
17
|
import { logger } from 'termcast/src/logger'
|
|
18
18
|
import { useIsInFocus } from 'termcast/src/internal/focus-context'
|
|
19
|
+
import { useIsOffscreen } from 'termcast/src/internal/offscreen'
|
|
19
20
|
import { CommonProps } from 'termcast/src/utils'
|
|
20
21
|
import { createDescendants } from 'termcast/src/descendants'
|
|
21
22
|
import { ScrollBox } from 'termcast/src/internal/scrollbox'
|
|
@@ -107,6 +108,7 @@ const Dropdown: DropdownType = (props) => {
|
|
|
107
108
|
throttle,
|
|
108
109
|
} = props
|
|
109
110
|
|
|
111
|
+
const isOffscreen = useIsOffscreen()
|
|
110
112
|
const [selected, setSelected] = useState(0)
|
|
111
113
|
const [searchText, setSearchTextState] = useState('')
|
|
112
114
|
const [currentValue, setCurrentValue] = useState<string | undefined>(
|
|
@@ -122,7 +124,14 @@ const Dropdown: DropdownType = (props) => {
|
|
|
122
124
|
const setSearchText = (text: string) => {
|
|
123
125
|
inputRef.current?.setText(text)
|
|
124
126
|
setSearchTextState(text)
|
|
125
|
-
|
|
127
|
+
// TODO: use flushSync when available to force descendants to update visibility
|
|
128
|
+
const items = Object.values(descendantsContext.map.current)
|
|
129
|
+
.filter((item: any) => item.index !== -1 && !item.props?.hidden)
|
|
130
|
+
.sort((a: any, b: any) => a.index - b.index)
|
|
131
|
+
|
|
132
|
+
if (items.length > 0 && items[0]) {
|
|
133
|
+
setSelected(items[0].index)
|
|
134
|
+
}
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
const scrollToItem = (item: { props?: DropdownItemDescendant }) => {
|
|
@@ -132,19 +141,13 @@ const Dropdown: DropdownType = (props) => {
|
|
|
132
141
|
|
|
133
142
|
const contentY = scrollBox.content?.y || 0
|
|
134
143
|
const viewportHeight = scrollBox.viewport?.height || 10
|
|
135
|
-
const currentScrollTop = scrollBox.scrollTop || 0
|
|
136
144
|
|
|
145
|
+
// Calculate item position relative to content
|
|
137
146
|
const itemTop = elementRef.y - contentY
|
|
138
|
-
const itemBottom = itemTop + elementRef.height
|
|
139
147
|
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
if (itemTop < visibleTop) {
|
|
144
|
-
scrollBox.scrollTo(itemTop)
|
|
145
|
-
} else if (itemBottom > visibleBottom) {
|
|
146
|
-
scrollBox.scrollTo(itemBottom - viewportHeight)
|
|
147
|
-
}
|
|
148
|
+
// Scroll so the top of the item is centered in the viewport
|
|
149
|
+
const targetScrollTop = itemTop - viewportHeight / 2
|
|
150
|
+
scrollBox.scrollTo(Math.max(0, targetScrollTop))
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
// Create context value for children
|
|
@@ -173,9 +176,16 @@ const Dropdown: DropdownType = (props) => {
|
|
|
173
176
|
const handleSearchTextChange = (text: string) => {
|
|
174
177
|
if (!inFocus) return
|
|
175
178
|
|
|
176
|
-
// Update state for context
|
|
179
|
+
// Update state for context
|
|
177
180
|
setSearchTextState(text)
|
|
178
|
-
|
|
181
|
+
// TODO: use flushSync when available to force descendants to update visibility
|
|
182
|
+
const items = Object.values(descendantsContext.map.current)
|
|
183
|
+
.filter((item: any) => item.index !== -1 && !item.props?.hidden)
|
|
184
|
+
.sort((a: any, b: any) => a.index - b.index)
|
|
185
|
+
|
|
186
|
+
if (items.length > 0 && items[0]) {
|
|
187
|
+
setSelected(items[0].index)
|
|
188
|
+
}
|
|
179
189
|
|
|
180
190
|
if (onSearchTextChange) {
|
|
181
191
|
if (throttle) {
|
|
@@ -244,18 +254,36 @@ const Dropdown: DropdownType = (props) => {
|
|
|
244
254
|
if (evt.name === 'down') {
|
|
245
255
|
move(1)
|
|
246
256
|
}
|
|
257
|
+
// Tab and shift+tab for navigation
|
|
258
|
+
if (evt.name === 'tab' && !evt.shift) {
|
|
259
|
+
move(1)
|
|
260
|
+
}
|
|
261
|
+
if (evt.name === 'tab' && evt.shift) {
|
|
262
|
+
move(-1)
|
|
263
|
+
}
|
|
247
264
|
if (evt.name === 'return') {
|
|
248
265
|
const items = Object.values(descendantsContext.map.current)
|
|
249
266
|
.filter((item: any) => item.index !== -1)
|
|
250
267
|
.sort((a: any, b: any) => a.index - b.index)
|
|
251
268
|
|
|
252
|
-
const currentItem = items
|
|
269
|
+
const currentItem = items.find((item) => item.index === selected)
|
|
253
270
|
if (currentItem?.props) {
|
|
254
271
|
selectItem((currentItem.props as DropdownItemDescendant).value)
|
|
255
272
|
}
|
|
256
273
|
}
|
|
257
274
|
})
|
|
258
275
|
|
|
276
|
+
// When offscreen, just render children to collect descendants without UI
|
|
277
|
+
if (isOffscreen) {
|
|
278
|
+
return (
|
|
279
|
+
<DropdownDescendantsProvider value={descendantsContext}>
|
|
280
|
+
<DropdownContext.Provider value={contextValue}>
|
|
281
|
+
{children}
|
|
282
|
+
</DropdownContext.Provider>
|
|
283
|
+
</DropdownDescendantsProvider>
|
|
284
|
+
)
|
|
285
|
+
}
|
|
286
|
+
|
|
259
287
|
return (
|
|
260
288
|
<DropdownDescendantsProvider value={descendantsContext}>
|
|
261
289
|
<DropdownContext.Provider value={contextValue}>
|
|
@@ -275,6 +303,7 @@ const Dropdown: DropdownType = (props) => {
|
|
|
275
303
|
<textarea
|
|
276
304
|
ref={inputRef}
|
|
277
305
|
height={1}
|
|
306
|
+
wrapMode='none'
|
|
278
307
|
keyBindings={[
|
|
279
308
|
{ name: 'return', action: 'submit' },
|
|
280
309
|
{ name: 'linefeed', action: 'submit' },
|
|
@@ -419,7 +448,11 @@ function ItemOption(props: {
|
|
|
419
448
|
const DropdownItem: (props: DropdownItemProps) => any = (props) => {
|
|
420
449
|
const context = useContext(DropdownContext)
|
|
421
450
|
const elementRef = useRef<{ y: number; height: number } | null>(null)
|
|
451
|
+
const isOffscreen = useIsOffscreen()
|
|
422
452
|
if (!context) return null
|
|
453
|
+
|
|
454
|
+
// Don't render UI when offscreen (used for collecting action descendants)
|
|
455
|
+
if (isOffscreen) return null
|
|
423
456
|
|
|
424
457
|
const { searchText, filtering, currentSection, selectedIndex, currentValue } =
|
|
425
458
|
context
|
|
@@ -9,6 +9,7 @@ import { LocalStorage } from 'termcast/src/apis/localstorage'
|
|
|
9
9
|
import { useNavigation } from 'termcast/src/internal/navigation'
|
|
10
10
|
import { logger } from 'termcast/src/logger'
|
|
11
11
|
import { getStoreDirectory } from 'termcast/src/utils'
|
|
12
|
+
import { useStore } from 'termcast/src/state'
|
|
12
13
|
import type { RaycastPackageJson } from 'termcast/src/package-json'
|
|
13
14
|
|
|
14
15
|
interface ExtensionPreferencesProps {
|
|
@@ -46,17 +47,26 @@ export function ExtensionPreferences({
|
|
|
46
47
|
queryKey: ['extension-preferences', extensionName, commandName],
|
|
47
48
|
queryFn: async () => {
|
|
48
49
|
try {
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
const packageJsonPath = path.join(extensionDir, 'package.json')
|
|
50
|
+
// First check extensionPath from state (dev mode), then fall back to store directory
|
|
51
|
+
const { extensionPath, extensionPackageJson } = useStore.getState()
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
let packageJson: RaycastPackageJson
|
|
54
|
+
|
|
55
|
+
if (extensionPath && extensionPackageJson?.name === extensionName) {
|
|
56
|
+
// Dev mode - use package.json from state or read from extensionPath
|
|
57
|
+
packageJson = extensionPackageJson
|
|
58
|
+
} else {
|
|
59
|
+
// Store extension - read from store directory
|
|
60
|
+
const storeDir = getStoreDirectory()
|
|
61
|
+
const extensionDir = path.join(storeDir, extensionName)
|
|
62
|
+
const packageJsonPath = path.join(extensionDir, 'package.json')
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
65
|
+
throw new Error(`Extension ${extensionName} not found`)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))
|
|
69
|
+
}
|
|
60
70
|
|
|
61
71
|
let prefsToUse: PreferenceManifest[] = []
|
|
62
72
|
|
|
@@ -103,11 +113,29 @@ export function ExtensionPreferences({
|
|
|
103
113
|
|
|
104
114
|
const handleSubmit = async (values: Record<string, any>) => {
|
|
105
115
|
try {
|
|
116
|
+
// Transform file/directory values from arrays to strings
|
|
117
|
+
// Form.FilePicker returns string[] but Raycast preferences expect string for file/directory types
|
|
118
|
+
const transformedValues: Record<string, any> = {}
|
|
119
|
+
for (const pref of preferences) {
|
|
120
|
+
const value = values[pref.name]
|
|
121
|
+
if (
|
|
122
|
+
(pref.type === 'file' ||
|
|
123
|
+
pref.type === 'directory' ||
|
|
124
|
+
pref.type === 'appPicker') &&
|
|
125
|
+
Array.isArray(value)
|
|
126
|
+
) {
|
|
127
|
+
// Extract first element from array, or empty string if empty
|
|
128
|
+
transformedValues[pref.name] = value[0] || ''
|
|
129
|
+
} else {
|
|
130
|
+
transformedValues[pref.name] = value
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
106
134
|
// Save preferences to LocalStorage
|
|
107
135
|
const preferencesKey = commandName
|
|
108
136
|
? `preferences.${extensionName}.${commandName}`
|
|
109
137
|
: `preferences.${extensionName}`
|
|
110
|
-
await LocalStorage.setItem(preferencesKey, JSON.stringify(
|
|
138
|
+
await LocalStorage.setItem(preferencesKey, JSON.stringify(transformedValues))
|
|
111
139
|
|
|
112
140
|
await showToast({
|
|
113
141
|
style: Toast.Style.Success,
|
|
@@ -118,7 +146,7 @@ export function ExtensionPreferences({
|
|
|
118
146
|
})
|
|
119
147
|
|
|
120
148
|
if (onSubmit) {
|
|
121
|
-
onSubmit(
|
|
149
|
+
onSubmit(transformedValues)
|
|
122
150
|
} else {
|
|
123
151
|
pop()
|
|
124
152
|
}
|
|
@@ -136,11 +164,11 @@ export function ExtensionPreferences({
|
|
|
136
164
|
}
|
|
137
165
|
|
|
138
166
|
if (preferences.length === 0) {
|
|
139
|
-
//
|
|
140
|
-
if (onSubmit) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
167
|
+
// TODO this causes an infinite loop, because initially prefs are zero
|
|
168
|
+
// if (onSubmit) {
|
|
169
|
+
// onSubmit({})
|
|
170
|
+
// return null
|
|
171
|
+
// }
|
|
144
172
|
|
|
145
173
|
return (
|
|
146
174
|
<Form
|
|
@@ -9,6 +9,7 @@ import { Theme } from 'termcast/src/theme'
|
|
|
9
9
|
import { WithLeftBorder } from './with-left-border'
|
|
10
10
|
import { useFormNavigation } from './use-form-navigation'
|
|
11
11
|
import { useIsInFocus } from 'termcast/src/internal/focus-context'
|
|
12
|
+
import { LoadingText } from 'termcast/src/components/loading-text'
|
|
12
13
|
|
|
13
14
|
export interface CheckboxProps extends FormItemProps<boolean> {
|
|
14
15
|
label: string
|
|
@@ -18,7 +19,8 @@ export type CheckboxRef = FormItemRef
|
|
|
18
19
|
|
|
19
20
|
export const Checkbox = (props: CheckboxProps): any => {
|
|
20
21
|
const { control, setValue, getValues } = useFormContext()
|
|
21
|
-
const
|
|
22
|
+
const focusContext = useFocusContext()
|
|
23
|
+
const { focusedField, setFocusedField } = focusContext
|
|
22
24
|
const isFocused = focusedField === props.id
|
|
23
25
|
const isInFocus = useIsInFocus()
|
|
24
26
|
|
|
@@ -57,9 +59,8 @@ export const Checkbox = (props: CheckboxProps): any => {
|
|
|
57
59
|
render={({ field, fieldState, formState }) => {
|
|
58
60
|
return (
|
|
59
61
|
<box ref={elementRef} flexDirection='column'>
|
|
60
|
-
<WithLeftBorder withDiamond isFocused={isFocused}>
|
|
61
|
-
<
|
|
62
|
-
fg={isFocused ? Theme.primary : Theme.text}
|
|
62
|
+
<WithLeftBorder withDiamond isFocused={isFocused} isLoading={focusContext.isLoading}>
|
|
63
|
+
<box
|
|
63
64
|
onMouseDown={() => {
|
|
64
65
|
// Always focus the field when clicked
|
|
65
66
|
if (!isFocused) {
|
|
@@ -69,8 +70,13 @@ export const Checkbox = (props: CheckboxProps): any => {
|
|
|
69
70
|
handleToggle()
|
|
70
71
|
}}
|
|
71
72
|
>
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
<LoadingText
|
|
74
|
+
isLoading={isFocused && focusContext.isLoading}
|
|
75
|
+
color={isFocused ? Theme.primary : Theme.text}
|
|
76
|
+
>
|
|
77
|
+
{props.title || ''}
|
|
78
|
+
</LoadingText>
|
|
79
|
+
</box>
|
|
74
80
|
</WithLeftBorder>
|
|
75
81
|
<WithLeftBorder isFocused={isFocused}>
|
|
76
82
|
<text
|
|
@@ -9,6 +9,7 @@ import { WithLeftBorder } from './with-left-border'
|
|
|
9
9
|
import { DatePickerWidget } from 'termcast/src/internal/date-picker-widget'
|
|
10
10
|
import { useIsInFocus } from 'termcast/src/internal/focus-context'
|
|
11
11
|
import { useFormNavigationHelpers } from './use-form-navigation'
|
|
12
|
+
import { LoadingText } from 'termcast/src/components/loading-text'
|
|
12
13
|
|
|
13
14
|
export enum DatePickerType {
|
|
14
15
|
Date = 'date',
|
|
@@ -30,7 +31,8 @@ interface DatePickerComponentType {
|
|
|
30
31
|
|
|
31
32
|
const DatePickerComponent = (props: DatePickerProps): any => {
|
|
32
33
|
const { control } = useFormContext()
|
|
33
|
-
const
|
|
34
|
+
const focusContext = useFocusContext()
|
|
35
|
+
const { focusedField, setFocusedField } = focusContext
|
|
34
36
|
const isFocused = focusedField === props.id
|
|
35
37
|
const isInFocus = useIsInFocus()
|
|
36
38
|
|
|
@@ -65,15 +67,19 @@ const DatePickerComponent = (props: DatePickerProps): any => {
|
|
|
65
67
|
render={({ field, fieldState, formState }) => {
|
|
66
68
|
return (
|
|
67
69
|
<box ref={elementRef} flexDirection='column'>
|
|
68
|
-
<WithLeftBorder withDiamond isFocused={isFocused}>
|
|
69
|
-
<
|
|
70
|
-
fg={isFocused ? Theme.primary : Theme.text}
|
|
70
|
+
<WithLeftBorder withDiamond isFocused={isFocused} isLoading={focusContext.isLoading}>
|
|
71
|
+
<box
|
|
71
72
|
onMouseDown={() => {
|
|
72
73
|
setFocusedField(props.id)
|
|
73
74
|
}}
|
|
74
75
|
>
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
<LoadingText
|
|
77
|
+
isLoading={isFocused && focusContext.isLoading}
|
|
78
|
+
color={isFocused ? Theme.primary : Theme.text}
|
|
79
|
+
>
|
|
80
|
+
{props.title || ''}
|
|
81
|
+
</LoadingText>
|
|
82
|
+
</box>
|
|
77
83
|
</WithLeftBorder>
|
|
78
84
|
<WithLeftBorder isFocused={isFocused}>
|
|
79
85
|
<DatePickerWidget
|
|
@@ -4,6 +4,7 @@ import { Theme } from 'termcast/src/theme'
|
|
|
4
4
|
import { WithLeftBorder } from './with-left-border'
|
|
5
5
|
import { useFocusContext, useFormFieldDescendant } from './index'
|
|
6
6
|
import { useFormNavigation } from './use-form-navigation'
|
|
7
|
+
import { LoadingText } from 'termcast/src/components/loading-text'
|
|
7
8
|
|
|
8
9
|
export interface DescriptionProps {
|
|
9
10
|
id?: string
|
|
@@ -44,10 +45,14 @@ export const Description = (props: DescriptionProps): any => {
|
|
|
44
45
|
<WithLeftBorder
|
|
45
46
|
customCharacter={{ focused: '■', unfocused: '▪︎' }}
|
|
46
47
|
isFocused={isFocused}
|
|
48
|
+
isLoading={focusContext.isLoading}
|
|
47
49
|
>
|
|
48
|
-
<
|
|
50
|
+
<LoadingText
|
|
51
|
+
isLoading={isFocused && focusContext.isLoading}
|
|
52
|
+
color={isFocused ? Theme.primary : Theme.text}
|
|
53
|
+
>
|
|
49
54
|
{props.title}
|
|
50
|
-
</
|
|
55
|
+
</LoadingText>
|
|
51
56
|
</WithLeftBorder>
|
|
52
57
|
)}
|
|
53
58
|
<WithLeftBorder isFocused={isFocused}>
|