termcast 1.3.21 → 1.3.25
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/apis/toast.d.ts +5 -0
- package/dist/apis/toast.d.ts.map +1 -1
- package/dist/apis/toast.js +7 -43
- package/dist/apis/toast.js.map +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +3 -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 +87 -41
- 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 +2 -1
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +31 -12
- 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 +104 -30
- 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 +155 -70
- 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/examples/toast-variations.d.ts +2 -0
- package/dist/examples/toast-variations.d.ts.map +1 -0
- package/dist/examples/toast-variations.js +122 -0
- package/dist/examples/toast-variations.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/release.d.ts +1 -1
- package/dist/release.d.ts.map +1 -1
- package/dist/release.js +29 -33
- package/dist/release.js.map +1 -1
- 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 +26 -1
- package/dist/utils/run-command.d.ts.map +1 -1
- package/dist/utils/run-command.js +53 -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 -12
- 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/apis/toast.tsx +37 -62
- package/src/build.test.tsx +52 -0
- package/src/build.tsx +3 -1
- package/src/cli.tsx +99 -48
- package/src/compile.tsx +32 -11
- 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 +168 -41
- 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 +243 -101
- 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 +191 -85
- 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 +221 -97
- package/src/examples/list-with-toast.vitest.tsx +16 -16
- package/src/examples/simple-file-picker.vitest.tsx +63 -469
- package/src/examples/simple-grid.vitest.tsx +238 -233
- package/src/examples/simple-navigation.tsx +15 -7
- package/src/examples/simple-navigation.vitest.tsx +130 -219
- 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/examples/toast-variations.tsx +150 -0
- package/src/examples/toast-variations.vitest.tsx +370 -0
- package/src/extensions/dev.tsx +74 -7
- package/src/extensions/dev.vitest.tsx +102 -34
- 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/release.tsx +32 -38
- 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 +82 -6
|
@@ -38,11 +38,10 @@ test('dev command shows extension commands list', async () => {
|
|
|
38
38
|
›List Items Displays a simple list with some ite view ▀
|
|
39
39
|
Search Items Search and filter through a list o view
|
|
40
40
|
Google Oauth view
|
|
41
|
-
usePromise Demo Shows how to use the usePromise view
|
|
42
|
-
▼
|
|
41
|
+
usePromise Demo Shows how to use the usePromise view ▼
|
|
43
42
|
|
|
44
43
|
|
|
45
|
-
↵
|
|
44
|
+
↵ run command ↑↓ navigate ^k actions"
|
|
46
45
|
`)
|
|
47
46
|
}, 30000)
|
|
48
47
|
|
|
@@ -68,15 +67,14 @@ test('selecting command with arguments shows arguments form', async () => {
|
|
|
68
67
|
|
|
69
68
|
Search commands...
|
|
70
69
|
|
|
71
|
-
|
|
72
|
-
Google Oauth view
|
|
73
|
-
usePromise Demo Shows how to use the usePromise view ▄
|
|
70
|
+
usePromise Demo Shows how to use the usePromise view ▲
|
|
74
71
|
Show State Shows the current application state view
|
|
75
72
|
›With Arguments Demonstrates command arguments ( view
|
|
73
|
+
Quick Action Copies current timestamp to cli no-view ▄
|
|
76
74
|
▼
|
|
77
75
|
|
|
78
76
|
|
|
79
|
-
↵
|
|
77
|
+
↵ run command ↑↓ navigate ^k actions"
|
|
80
78
|
`)
|
|
81
79
|
|
|
82
80
|
// Select the command to show arguments form (enter opens action panel, enter again runs)
|
|
@@ -93,19 +91,19 @@ test('selecting command with arguments shows arguments form', async () => {
|
|
|
93
91
|
"
|
|
94
92
|
|
|
95
93
|
|
|
96
|
-
|
|
97
|
-
│ Enter the arguments to run this command.
|
|
94
|
+
■ With Arguments █
|
|
95
|
+
│ Enter the arguments to run this command.
|
|
96
|
+
│
|
|
97
|
+
◇ Search query
|
|
98
|
+
│ Search query
|
|
98
99
|
│
|
|
99
|
-
◆ Search query
|
|
100
|
-
┃ Search query
|
|
101
|
-
┃
|
|
102
100
|
◇ Secret key
|
|
103
101
|
│ Secret key
|
|
104
102
|
◇ Category
|
|
105
103
|
│ Category
|
|
106
104
|
|
|
107
105
|
|
|
108
|
-
|
|
106
|
+
ctrl ↵ submit tab navigate ^k actions"
|
|
109
107
|
`)
|
|
110
108
|
}, 30000)
|
|
111
109
|
|
|
@@ -137,19 +135,19 @@ test('can fill arguments and run command', async () => {
|
|
|
137
135
|
"
|
|
138
136
|
|
|
139
137
|
|
|
140
|
-
|
|
141
|
-
│ Enter the arguments to run this command.
|
|
138
|
+
■ With Arguments █
|
|
139
|
+
│ Enter the arguments to run this command.
|
|
140
|
+
│
|
|
141
|
+
◇ Search query
|
|
142
|
+
│ Search query
|
|
142
143
|
│
|
|
143
|
-
◆ Search query
|
|
144
|
-
┃ my search term
|
|
145
|
-
┃
|
|
146
144
|
◇ Secret key
|
|
147
145
|
│ Secret key
|
|
148
146
|
◇ Category
|
|
149
147
|
│ Category
|
|
150
148
|
|
|
151
149
|
|
|
152
|
-
|
|
150
|
+
ctrl ↵ submit tab navigate ^k actions"
|
|
153
151
|
`)
|
|
154
152
|
|
|
155
153
|
// Submit the form with Alt+Enter (opens action panel), then Enter (selects submit)
|
|
@@ -171,15 +169,15 @@ test('can fill arguments and run command', async () => {
|
|
|
171
169
|
Search...
|
|
172
170
|
|
|
173
171
|
Received Arguments
|
|
174
|
-
|
|
175
|
-
Secret Key (empty)
|
|
176
|
-
Category (empty)
|
|
172
|
+
›▼ Search Query (empty)
|
|
173
|
+
▼ Secret Key (empty)
|
|
174
|
+
▼ Category (empty)
|
|
177
175
|
|
|
178
176
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
177
|
+
┌───────────────────────┐
|
|
178
|
+
│ ✓ Copied to Clipboard │
|
|
179
|
+
│ (empty) │
|
|
180
|
+
└───────────────────────┘"
|
|
183
181
|
`)
|
|
184
182
|
}, 30000)
|
|
185
183
|
|
|
@@ -208,13 +206,83 @@ test('can run simple view command without arguments', async () => {
|
|
|
208
206
|
Search...
|
|
209
207
|
|
|
210
208
|
Items ▲
|
|
211
|
-
|
|
212
|
-
Second Item This is the second item
|
|
213
|
-
Third Item This is the third item
|
|
214
|
-
Fourth Item This is the fourth item
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
209
|
+
›▲ First Item This is the first item █
|
|
210
|
+
▲ Second Item This is the second item █
|
|
211
|
+
▲ Third Item This is the third item ▀
|
|
212
|
+
▲ Fourth Item This is the fourth item
|
|
213
|
+
▲ Fifth Item This is the fifth item ▼
|
|
214
|
+
┌───────────────────────┐
|
|
215
|
+
│ ✓ Copied to Clipboard │
|
|
216
|
+
│ First Item │
|
|
217
|
+
└───────────────────────┘"
|
|
219
218
|
`)
|
|
220
219
|
}, 30000)
|
|
220
|
+
|
|
221
|
+
test('hot reload updates TUI when source file changes', async () => {
|
|
222
|
+
const hotReloadFixtureDir = path.resolve(__dirname, '../../fixtures/hot-reload-extension')
|
|
223
|
+
const sourceFilePath = path.join(hotReloadFixtureDir, 'src/detail-view.tsx')
|
|
224
|
+
const fs = await import('node:fs')
|
|
225
|
+
|
|
226
|
+
// Read original content to restore later
|
|
227
|
+
const originalContent = fs.readFileSync(sourceFilePath, 'utf-8')
|
|
228
|
+
|
|
229
|
+
// Start a new session for this test
|
|
230
|
+
const hotReloadSession = await launchTerminal({
|
|
231
|
+
command: 'bun',
|
|
232
|
+
args: ['src/cli.tsx', 'dev', hotReloadFixtureDir],
|
|
233
|
+
cols: 60,
|
|
234
|
+
rows: 16,
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
// Wait for the extension to load
|
|
239
|
+
await hotReloadSession.text({
|
|
240
|
+
waitFor: (text) => /Hot Reload Test/i.test(text) && /Detail View/i.test(text),
|
|
241
|
+
timeout: 5000,
|
|
242
|
+
})
|
|
243
|
+
await hotReloadSession.waitIdle()
|
|
244
|
+
|
|
245
|
+
// Run the Detail View command
|
|
246
|
+
await hotReloadSession.press('enter')
|
|
247
|
+
await hotReloadSession.press('enter')
|
|
248
|
+
await hotReloadSession.waitIdle()
|
|
249
|
+
|
|
250
|
+
// Wait for the detail view to show
|
|
251
|
+
await hotReloadSession.text({
|
|
252
|
+
waitFor: (text) => /MARKER_VALUE/i.test(text),
|
|
253
|
+
timeout: 10000,
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
// Generate a random number
|
|
257
|
+
const randomNumber = Math.floor(Math.random() * 1000000)
|
|
258
|
+
|
|
259
|
+
// Update the source file with the random number
|
|
260
|
+
const newContent = originalContent.replace('MARKER_VALUE', `UPDATED_${randomNumber}`)
|
|
261
|
+
fs.writeFileSync(sourceFilePath, newContent)
|
|
262
|
+
|
|
263
|
+
// Wait for rebuild - navigation resets to commands list
|
|
264
|
+
await hotReloadSession.text({
|
|
265
|
+
waitFor: (text) => /Hot Reload Test/i.test(text) && /Detail View/i.test(text),
|
|
266
|
+
timeout: 5000,
|
|
267
|
+
})
|
|
268
|
+
await hotReloadSession.waitIdle()
|
|
269
|
+
|
|
270
|
+
// Run the command again to see updated content
|
|
271
|
+
await hotReloadSession.press('enter')
|
|
272
|
+
await hotReloadSession.press('enter')
|
|
273
|
+
await hotReloadSession.waitIdle()
|
|
274
|
+
|
|
275
|
+
// Wait for the updated content
|
|
276
|
+
await hotReloadSession.text({
|
|
277
|
+
waitFor: (text) => text.includes(`UPDATED_${randomNumber}`),
|
|
278
|
+
timeout: 10000,
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
const updatedSnapshot = await hotReloadSession.text()
|
|
282
|
+
expect(updatedSnapshot).toContain(`UPDATED_${randomNumber}`)
|
|
283
|
+
} finally {
|
|
284
|
+
// Restore original content
|
|
285
|
+
fs.writeFileSync(sourceFilePath, originalContent)
|
|
286
|
+
hotReloadSession?.close()
|
|
287
|
+
}
|
|
288
|
+
}, 60000)
|
package/src/extensions/home.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
2
3
|
import React from 'react'
|
|
3
4
|
import { createRoot } from '@opentui/react'
|
|
4
5
|
import { createCliRenderer } from '@opentui/core'
|
|
@@ -17,6 +18,7 @@ import '../globals'
|
|
|
17
18
|
interface ExtensionCommand {
|
|
18
19
|
extensionName: string
|
|
19
20
|
extensionTitle: string
|
|
21
|
+
extensionDir?: string
|
|
20
22
|
command: any
|
|
21
23
|
bundledPath?: string
|
|
22
24
|
Component?: () => any
|
|
@@ -52,6 +54,8 @@ function ExtensionsList({
|
|
|
52
54
|
const handleCommandSelect = async (item: ExtensionCommand) => {
|
|
53
55
|
clearCommandArguments()
|
|
54
56
|
|
|
57
|
+
|
|
58
|
+
|
|
55
59
|
try {
|
|
56
60
|
await runCommand({
|
|
57
61
|
command: item.command,
|
|
@@ -208,12 +212,14 @@ export default function Home({
|
|
|
208
212
|
const packageJson = JSON.parse(
|
|
209
213
|
fs.readFileSync(extension.packageJsonPath, 'utf-8'),
|
|
210
214
|
)
|
|
215
|
+
const extensionPath = path.dirname(extension.packageJsonPath)
|
|
211
216
|
|
|
212
217
|
for (const command of extension.commands) {
|
|
213
218
|
if (command.bundledPath) {
|
|
214
219
|
allCommands.push({
|
|
215
220
|
extensionName: extension.name,
|
|
216
221
|
extensionTitle: packageJson.title || extension.name,
|
|
222
|
+
extensionDir: extensionPath,
|
|
217
223
|
command,
|
|
218
224
|
bundledPath: command.bundledPath,
|
|
219
225
|
packageJson,
|
package/src/index.tsx
CHANGED
package/src/internal/dialog.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useKeyboard, useTerminalDimensions } from '@opentui/react'
|
|
2
|
-
import React, { type ReactNode, useRef } from 'react'
|
|
2
|
+
import React, { type ReactNode, useRef, useContext } from 'react'
|
|
3
3
|
import { Theme } from 'termcast/src/theme'
|
|
4
4
|
import { InFocus, useIsInFocus } from 'termcast/src/internal/focus-context'
|
|
5
5
|
import { CommonProps } from 'termcast/src/utils'
|
|
@@ -10,13 +10,14 @@ import {
|
|
|
10
10
|
} from 'termcast/src/state'
|
|
11
11
|
import { logger } from '../logger'
|
|
12
12
|
import { ToastOverlay } from 'termcast/src/apis/toast'
|
|
13
|
+
import { NavigationContext } from 'termcast/src/internal/navigation'
|
|
13
14
|
|
|
14
15
|
const Border = {
|
|
15
|
-
topLeft: '',
|
|
16
|
-
topRight: '',
|
|
16
|
+
topLeft: '┏',
|
|
17
|
+
topRight: '┓',
|
|
17
18
|
bottomLeft: '',
|
|
18
19
|
bottomRight: '',
|
|
19
|
-
horizontal: '',
|
|
20
|
+
horizontal: '━',
|
|
20
21
|
vertical: '┃',
|
|
21
22
|
topT: '+',
|
|
22
23
|
bottomT: '+',
|
|
@@ -107,7 +108,7 @@ export function Dialog({
|
|
|
107
108
|
onMouseDown={handleBackdropClick}
|
|
108
109
|
>
|
|
109
110
|
<box
|
|
110
|
-
border
|
|
111
|
+
border
|
|
111
112
|
customBorderChars={Border}
|
|
112
113
|
width={76}
|
|
113
114
|
maxWidth={dimensions.width - 2}
|
|
@@ -145,31 +146,6 @@ export function DialogProvider(props: DialogProviderProps): any {
|
|
|
145
146
|
return (
|
|
146
147
|
<>
|
|
147
148
|
<InFocus inFocus={!dialogStack?.length}>{props.children}</InFocus>
|
|
148
|
-
{dialogStack.length > 0 && (
|
|
149
|
-
<box position='absolute'>
|
|
150
|
-
{dialogStack.map((item, index) => {
|
|
151
|
-
const isLastItem = index === dialogStack.length - 1
|
|
152
|
-
return (
|
|
153
|
-
<InFocus key={'dialog' + String(index)} inFocus={isLastItem}>
|
|
154
|
-
<Dialog
|
|
155
|
-
position={item.position}
|
|
156
|
-
onClickOutside={() => {
|
|
157
|
-
if (!isLastItem) return
|
|
158
|
-
const state = useStore.getState()
|
|
159
|
-
if (state.dialogStack.length > 0) {
|
|
160
|
-
useStore.setState({
|
|
161
|
-
dialogStack: state.dialogStack.slice(0, -1),
|
|
162
|
-
})
|
|
163
|
-
}
|
|
164
|
-
}}
|
|
165
|
-
>
|
|
166
|
-
{item.element}
|
|
167
|
-
</Dialog>
|
|
168
|
-
</InFocus>
|
|
169
|
-
)
|
|
170
|
-
})}
|
|
171
|
-
</box>
|
|
172
|
-
)}
|
|
173
149
|
<InFocus inFocus={false}>
|
|
174
150
|
<ToastOverlay />
|
|
175
151
|
</InFocus>
|
|
@@ -177,6 +153,43 @@ export function DialogProvider(props: DialogProviderProps): any {
|
|
|
177
153
|
)
|
|
178
154
|
}
|
|
179
155
|
|
|
156
|
+
export function DialogOverlay(): any {
|
|
157
|
+
const dialogStack = useStore((state) => state.dialogStack)
|
|
158
|
+
const navContext = useContext(NavigationContext)
|
|
159
|
+
|
|
160
|
+
if (dialogStack.length === 0) {
|
|
161
|
+
return null
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return (
|
|
165
|
+
<box position='absolute'>
|
|
166
|
+
{dialogStack.map((item, index) => {
|
|
167
|
+
const isLastItem = index === dialogStack.length - 1
|
|
168
|
+
return (
|
|
169
|
+
<InFocus key={'dialog' + String(index)} inFocus={isLastItem}>
|
|
170
|
+
<Dialog
|
|
171
|
+
position={item.position}
|
|
172
|
+
onClickOutside={() => {
|
|
173
|
+
if (!isLastItem) return
|
|
174
|
+
const state = useStore.getState()
|
|
175
|
+
if (state.dialogStack.length > 0) {
|
|
176
|
+
useStore.setState({
|
|
177
|
+
dialogStack: state.dialogStack.slice(0, -1),
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
}}
|
|
181
|
+
>
|
|
182
|
+
<NavigationContext.Provider value={navContext}>
|
|
183
|
+
{item.element}
|
|
184
|
+
</NavigationContext.Provider>
|
|
185
|
+
</Dialog>
|
|
186
|
+
</InFocus>
|
|
187
|
+
)
|
|
188
|
+
})}
|
|
189
|
+
</box>
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
|
|
180
193
|
export function useDialog() {
|
|
181
194
|
const dialogStack = useStore((state) => state.dialogStack)
|
|
182
195
|
|
|
@@ -26,12 +26,13 @@ interface NavigationContextType {
|
|
|
26
26
|
isPending: boolean
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const NavigationContext = createContext<NavigationContextType | undefined>(
|
|
29
|
+
export const NavigationContext = createContext<NavigationContextType | undefined>(
|
|
30
30
|
undefined,
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
interface NavigationProviderProps extends CommonProps {
|
|
34
34
|
children: ReactNode
|
|
35
|
+
overlay?: ReactNode
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
export function NavigationProvider(props: NavigationProviderProps): any {
|
|
@@ -139,6 +140,7 @@ export function NavigationProvider(props: NavigationProviderProps): any {
|
|
|
139
140
|
{React.cloneElement(currentItem?.element as React.ReactElement, {
|
|
140
141
|
key: stack.length,
|
|
141
142
|
})}
|
|
143
|
+
{props.overlay}
|
|
142
144
|
</NavigationContext.Provider>
|
|
143
145
|
)
|
|
144
146
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createContext, useContext, ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
const OffscreenContext = createContext(false)
|
|
4
|
+
|
|
5
|
+
export function useIsOffscreen(): boolean {
|
|
6
|
+
return useContext(OffscreenContext)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function Offscreen({ children }: { children: ReactNode }): any {
|
|
10
|
+
return (
|
|
11
|
+
<OffscreenContext.Provider value={true}>
|
|
12
|
+
{children}
|
|
13
|
+
</OffscreenContext.Provider>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
@@ -6,7 +6,7 @@ import React, {
|
|
|
6
6
|
} from 'react'
|
|
7
7
|
import { QueryClient } from '@tanstack/react-query'
|
|
8
8
|
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
|
|
9
|
-
import { DialogProvider } from 'termcast/src/internal/dialog'
|
|
9
|
+
import { DialogProvider, DialogOverlay } from 'termcast/src/internal/dialog'
|
|
10
10
|
import { NavigationProvider } from 'termcast/src/internal/navigation'
|
|
11
11
|
import { CommonProps } from 'termcast/src/utils'
|
|
12
12
|
import { Cache } from 'termcast/src/apis/cache'
|
|
@@ -420,7 +420,9 @@ export function TermcastProvider(props: ProvidersProps): any {
|
|
|
420
420
|
<DialogProvider>
|
|
421
421
|
<box padding={2}>
|
|
422
422
|
{/* NavigationProvider must be last to ensure parent providers remain in the tree when navigation changes */}
|
|
423
|
-
<NavigationProvider
|
|
423
|
+
<NavigationProvider overlay={<DialogOverlay />}>
|
|
424
|
+
{props.children}
|
|
425
|
+
</NavigationProvider>
|
|
424
426
|
</box>
|
|
425
427
|
</DialogProvider>
|
|
426
428
|
</PersistQueryClientProvider>
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import Theme from '../theme'
|
|
3
|
+
import { MacOSScrollAccel } from '@opentui/core'
|
|
4
|
+
import { ScrollBoxProps } from '@opentui/react'
|
|
3
5
|
|
|
4
|
-
interface ScrollBoxProps {
|
|
5
|
-
children?: React.ReactNode
|
|
6
|
-
focused?: boolean
|
|
7
|
-
flexGrow?: number
|
|
8
|
-
flexShrink?: number
|
|
9
|
-
style?: any
|
|
10
|
-
ref?: React.Ref<any>
|
|
11
|
-
}
|
|
12
6
|
|
|
13
7
|
export function ScrollBox({
|
|
14
8
|
children,
|
|
@@ -23,6 +17,7 @@ export function ScrollBox({
|
|
|
23
17
|
<scrollbox
|
|
24
18
|
ref={ref}
|
|
25
19
|
focused={focused}
|
|
20
|
+
scrollAcceleration={new MacOSScrollAccel()}
|
|
26
21
|
flexGrow={flexGrow}
|
|
27
22
|
flexShrink={flexShrink}
|
|
28
23
|
style={{
|
|
@@ -34,6 +29,7 @@ export function ScrollBox({
|
|
|
34
29
|
flexGrow: 1,
|
|
35
30
|
flexShrink: 1,
|
|
36
31
|
paddingRight: 1,
|
|
32
|
+
|
|
37
33
|
...(style?.viewportOptions || {}),
|
|
38
34
|
},
|
|
39
35
|
contentOptions: {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, test, expect } from 'bun:test'
|
|
2
|
+
import { Keyboard } from 'termcast/src/keyboard'
|
|
3
|
+
import type {
|
|
4
|
+
KeyboardKeyEquivalent,
|
|
5
|
+
KeyboardKeyModifier,
|
|
6
|
+
KeyboardShortcut,
|
|
7
|
+
} from 'termcast/src/keyboard'
|
|
8
|
+
|
|
9
|
+
describe('Keyboard', () => {
|
|
10
|
+
test('Keyboard.Shortcut.Common has all expected shortcuts', () => {
|
|
11
|
+
const commonShortcuts = Object.keys(Keyboard.Shortcut.Common)
|
|
12
|
+
expect(commonShortcuts).toMatchInlineSnapshot(`
|
|
13
|
+
[
|
|
14
|
+
"Copy",
|
|
15
|
+
"CopyDeeplink",
|
|
16
|
+
"CopyName",
|
|
17
|
+
"CopyPath",
|
|
18
|
+
"Save",
|
|
19
|
+
"Duplicate",
|
|
20
|
+
"Edit",
|
|
21
|
+
"MoveDown",
|
|
22
|
+
"MoveUp",
|
|
23
|
+
"New",
|
|
24
|
+
"Open",
|
|
25
|
+
"OpenWith",
|
|
26
|
+
"Pin",
|
|
27
|
+
"Refresh",
|
|
28
|
+
"Remove",
|
|
29
|
+
"RemoveAll",
|
|
30
|
+
"ToggleQuickLook",
|
|
31
|
+
]
|
|
32
|
+
`)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('Keyboard.Shortcut.Common.Open has correct structure', () => {
|
|
36
|
+
expect(Keyboard.Shortcut.Common.Open).toMatchInlineSnapshot(`
|
|
37
|
+
{
|
|
38
|
+
"key": "o",
|
|
39
|
+
"modifiers": [
|
|
40
|
+
"cmd",
|
|
41
|
+
],
|
|
42
|
+
}
|
|
43
|
+
`)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('Keyboard.Shortcut.Common.Copy has correct structure', () => {
|
|
47
|
+
expect(Keyboard.Shortcut.Common.Copy).toMatchInlineSnapshot(`
|
|
48
|
+
{
|
|
49
|
+
"key": "c",
|
|
50
|
+
"modifiers": [
|
|
51
|
+
"cmd",
|
|
52
|
+
"shift",
|
|
53
|
+
],
|
|
54
|
+
}
|
|
55
|
+
`)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('Keyboard.Shortcut.Common.Remove uses ctrl modifier', () => {
|
|
59
|
+
expect(Keyboard.Shortcut.Common.Remove).toMatchInlineSnapshot(`
|
|
60
|
+
{
|
|
61
|
+
"key": "x",
|
|
62
|
+
"modifiers": [
|
|
63
|
+
"ctrl",
|
|
64
|
+
],
|
|
65
|
+
}
|
|
66
|
+
`)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
})
|
package/src/release.tsx
CHANGED
|
@@ -19,7 +19,7 @@ export interface ReleaseOptions {
|
|
|
19
19
|
|
|
20
20
|
export interface ReleaseResult {
|
|
21
21
|
success: boolean
|
|
22
|
-
|
|
22
|
+
tag: string
|
|
23
23
|
uploadedFiles: string[]
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -33,46 +33,38 @@ export async function releaseExtension({
|
|
|
33
33
|
throw new Error(`Extension path does not exist: ${resolvedPath}`)
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
throw new Error(`No package.json found at: ${packageJsonPath}`)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))
|
|
42
|
-
const name = packageJson.name
|
|
43
|
-
const version = packageJson.version
|
|
44
|
-
|
|
45
|
-
if (!name) {
|
|
46
|
-
throw new Error('package.json must have a name field')
|
|
47
|
-
}
|
|
48
|
-
if (!version) {
|
|
49
|
-
throw new Error('package.json must have a version field')
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const tag = `${name}@${version}`
|
|
53
|
-
console.log(`Preparing release ${tag}...`)
|
|
54
|
-
|
|
55
|
-
// Check if release already exists
|
|
36
|
+
// Get repo name from git remote
|
|
37
|
+
let repoName: string
|
|
56
38
|
try {
|
|
57
|
-
const
|
|
39
|
+
const remoteUrl = execSync('git config --get remote.origin.url', {
|
|
58
40
|
cwd: resolvedPath,
|
|
59
41
|
encoding: 'utf-8',
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
42
|
+
}).trim()
|
|
43
|
+
// Handle both HTTPS and SSH URLs:
|
|
44
|
+
// https://github.com/user/repo.git -> repo
|
|
45
|
+
// git@github.com:user/repo.git -> repo
|
|
46
|
+
const match = remoteUrl.match(/\/([^/]+?)(?:\.git)?$/) || remoteUrl.match(/:([^/]+?)(?:\.git)?$/)
|
|
47
|
+
if (!match) {
|
|
48
|
+
throw new Error(`Could not parse repo name from remote URL: ${remoteUrl}`)
|
|
64
49
|
}
|
|
50
|
+
repoName = match[1].replace(/\.git$/, '')
|
|
65
51
|
} catch (error: any) {
|
|
66
|
-
|
|
67
|
-
throw error
|
|
68
|
-
}
|
|
69
|
-
const stderr = error.stderr?.toString() || ''
|
|
70
|
-
const isNotFound = stderr.includes('release not found') || stderr.includes('Not Found')
|
|
71
|
-
if (!isNotFound) {
|
|
72
|
-
throw new Error(`Failed to check release status: ${stderr || error.message}`)
|
|
73
|
-
}
|
|
52
|
+
throw new Error(`Failed to get git remote: ${error.message}`)
|
|
74
53
|
}
|
|
75
54
|
|
|
55
|
+
// Generate date-based tag with hour and minute
|
|
56
|
+
const now = new Date()
|
|
57
|
+
const dateTag = [
|
|
58
|
+
now.getFullYear(),
|
|
59
|
+
String(now.getMonth() + 1).padStart(2, '0'),
|
|
60
|
+
String(now.getDate()).padStart(2, '0'),
|
|
61
|
+
String(now.getHours()).padStart(2, '0'),
|
|
62
|
+
String(now.getMinutes()).padStart(2, '0'),
|
|
63
|
+
].join('')
|
|
64
|
+
|
|
65
|
+
const tag = `${repoName}@${dateTag}`
|
|
66
|
+
console.log(`Preparing release ${tag}...`)
|
|
67
|
+
|
|
76
68
|
// Install dependencies for all platforms
|
|
77
69
|
console.log('Installing dependencies for all platforms...')
|
|
78
70
|
execSync('bun install --os="*" --cpu="*"', {
|
|
@@ -92,13 +84,14 @@ export async function releaseExtension({
|
|
|
92
84
|
if (!fs.existsSync(outputDir)) {
|
|
93
85
|
fs.mkdirSync(outputDir, { recursive: true })
|
|
94
86
|
}
|
|
87
|
+
fs.writeFileSync(path.join(outputDir, '.gitignore'), '*\n')
|
|
95
88
|
|
|
96
89
|
// Compile for all targets in parallel
|
|
97
90
|
console.log(`Compiling for ${targets.length} targets in parallel...`)
|
|
98
91
|
const compileResults = await Promise.all(
|
|
99
92
|
targets.map(async (target) => {
|
|
100
93
|
const suffix = targetToFileSuffix(target)
|
|
101
|
-
const binaryName = `${
|
|
94
|
+
const binaryName = `${repoName}-${suffix}`
|
|
102
95
|
const outfile = path.join(outputDir, binaryName)
|
|
103
96
|
|
|
104
97
|
const result = await compileExtension({
|
|
@@ -106,12 +99,13 @@ export async function releaseExtension({
|
|
|
106
99
|
outfile,
|
|
107
100
|
minify: true,
|
|
108
101
|
target,
|
|
102
|
+
version: tag,
|
|
109
103
|
})
|
|
110
104
|
|
|
111
105
|
console.log(` ✓ ${path.basename(result.outfile)}`)
|
|
112
106
|
|
|
113
107
|
const archiveExt = getArchiveExtension(target)
|
|
114
|
-
const archiveName = `${
|
|
108
|
+
const archiveName = `${repoName}-${suffix}${archiveExt}`
|
|
115
109
|
const archivePath = path.join(outputDir, archiveName)
|
|
116
110
|
|
|
117
111
|
if (archiveExt === '.tar.gz') {
|
|
@@ -130,7 +124,7 @@ export async function releaseExtension({
|
|
|
130
124
|
// Create GitHub release
|
|
131
125
|
console.log(`\nCreating GitHub release ${tag}...`)
|
|
132
126
|
try {
|
|
133
|
-
execSync(`gh release create "${tag}" --title "${tag}" --notes "Release ${
|
|
127
|
+
execSync(`gh release create "${tag}" --title "${tag}" --notes "Release ${tag}"`, {
|
|
134
128
|
cwd: resolvedPath,
|
|
135
129
|
stdio: 'inherit',
|
|
136
130
|
})
|
|
@@ -158,7 +152,7 @@ export async function releaseExtension({
|
|
|
158
152
|
|
|
159
153
|
return {
|
|
160
154
|
success: true,
|
|
161
|
-
|
|
155
|
+
tag,
|
|
162
156
|
uploadedFiles: compileResults,
|
|
163
157
|
}
|
|
164
158
|
}
|
package/src/state.tsx
CHANGED
|
@@ -30,6 +30,10 @@ interface AppState {
|
|
|
30
30
|
// OAuth state
|
|
31
31
|
googleAccessToken?: string
|
|
32
32
|
googleIdToken?: string
|
|
33
|
+
// Actions state - when true, auto-execute first action instead of showing sheet
|
|
34
|
+
shouldAutoExecuteFirstAction: boolean
|
|
35
|
+
// First action title for footer display (set by offscreen ActionPanel)
|
|
36
|
+
firstActionTitle: string
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
export const useStore = create<AppState>(() => ({
|
|
@@ -48,4 +52,7 @@ export const useStore = create<AppState>(() => ({
|
|
|
48
52
|
// OAuth state
|
|
49
53
|
googleAccessToken: undefined,
|
|
50
54
|
googleIdToken: undefined,
|
|
55
|
+
// Actions state
|
|
56
|
+
shouldAutoExecuteFirstAction: false,
|
|
57
|
+
firstActionTitle: '',
|
|
51
58
|
}))
|