termcast 1.3.32 → 1.3.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action-utils.d.ts.map +1 -1
- package/dist/action-utils.js +8 -0
- package/dist/action-utils.js.map +1 -1
- package/dist/apis/cache.d.ts +1 -2
- package/dist/apis/cache.d.ts.map +1 -1
- package/dist/apis/cache.js +138 -54
- package/dist/apis/cache.js.map +1 -1
- package/dist/apis/clipboard.d.ts.map +1 -1
- package/dist/apis/clipboard.js +4 -0
- package/dist/apis/clipboard.js.map +1 -1
- package/dist/apis/oauth.d.ts.map +1 -1
- package/dist/apis/oauth.js +31 -4
- package/dist/apis/oauth.js.map +1 -1
- package/dist/build.d.ts +0 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +30 -51
- package/dist/build.js.map +1 -1
- package/dist/cli.js +31 -14
- package/dist/cli.js.map +1 -1
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +5 -1
- package/dist/compile.js.map +1 -1
- package/dist/components/actions.d.ts +14 -0
- package/dist/components/actions.d.ts.map +1 -1
- package/dist/components/actions.js +151 -59
- package/dist/components/actions.js.map +1 -1
- package/dist/components/alert.d.ts.map +1 -1
- package/dist/components/alert.js +6 -5
- package/dist/components/alert.js.map +1 -1
- package/dist/components/animation-tick.d.ts +1 -1
- package/dist/components/animation-tick.js +1 -1
- package/dist/components/animation-tick.js.map +1 -1
- package/dist/components/detail.d.ts +5 -31
- package/dist/components/detail.d.ts.map +1 -1
- package/dist/components/detail.js +36 -52
- package/dist/components/detail.js.map +1 -1
- package/dist/components/dropdown.d.ts +1 -1
- package/dist/components/dropdown.d.ts.map +1 -1
- package/dist/components/dropdown.js +50 -22
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/footer.d.ts.map +1 -1
- package/dist/components/footer.js +19 -18
- package/dist/components/footer.js.map +1 -1
- package/dist/components/form/checkbox.d.ts.map +1 -1
- package/dist/components/form/checkbox.js +12 -11
- 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 +7 -22
- package/dist/components/form/date-picker.js.map +1 -1
- package/dist/components/form/description.d.ts +1 -1
- package/dist/components/form/description.d.ts.map +1 -1
- package/dist/components/form/description.js +6 -5
- 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 +53 -50
- package/dist/components/form/dropdown.js.map +1 -1
- package/dist/components/form/file-autocomplete.d.ts.map +1 -1
- package/dist/components/form/file-autocomplete.js +5 -4
- 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 +23 -22
- 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 +6 -4
- package/dist/components/form/form-end.js.map +1 -1
- package/dist/components/form/form-field-wrapper.d.ts +15 -0
- package/dist/components/form/form-field-wrapper.d.ts.map +1 -0
- package/dist/components/form/form-field-wrapper.js +29 -0
- package/dist/components/form/form-field-wrapper.js.map +1 -0
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/index.js +31 -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 +7 -6
- package/dist/components/form/password-field.js.map +1 -1
- package/dist/components/form/separator.d.ts.map +1 -1
- package/dist/components/form/separator.js +3 -2
- package/dist/components/form/separator.js.map +1 -1
- package/dist/components/form/tagpicker.d.ts.map +1 -1
- package/dist/components/form/tagpicker.js +2 -1
- package/dist/components/form/tagpicker.js.map +1 -1
- package/dist/components/form/text-area.d.ts.map +1 -1
- package/dist/components/form/text-area.js +7 -6
- 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 +7 -6
- package/dist/components/form/text-field.js.map +1 -1
- package/dist/components/form/use-form-navigation.d.ts.map +1 -1
- package/dist/components/form/use-form-navigation.js +4 -4
- package/dist/components/form/use-form-navigation.js.map +1 -1
- package/dist/components/form/with-left-border.d.ts +15 -0
- package/dist/components/form/with-left-border.d.ts.map +1 -1
- package/dist/components/form/with-left-border.js +21 -9
- package/dist/components/form/with-left-border.js.map +1 -1
- package/dist/components/icon.d.ts +14 -0
- package/dist/components/icon.d.ts.map +1 -1
- package/dist/components/icon.js +60 -0
- package/dist/components/icon.js.map +1 -1
- package/dist/components/image.d.ts +47 -2
- package/dist/components/image.d.ts.map +1 -1
- package/dist/components/image.js +46 -7
- package/dist/components/image.js.map +1 -1
- package/dist/components/list.d.ts +5 -0
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/list.js +188 -132
- package/dist/components/list.js.map +1 -1
- package/dist/components/loading-bar.d.ts.map +1 -1
- package/dist/components/loading-bar.js +4 -3
- package/dist/components/loading-bar.js.map +1 -1
- package/dist/components/metadata.d.ts +70 -0
- package/dist/components/metadata.d.ts.map +1 -0
- package/dist/components/metadata.js +82 -0
- package/dist/components/metadata.js.map +1 -0
- package/dist/components/theme-picker.d.ts.map +1 -1
- package/dist/components/theme-picker.js +3 -2
- package/dist/components/theme-picker.js.map +1 -1
- package/dist/descendants-v2.d.ts +60 -0
- package/dist/descendants-v2.d.ts.map +1 -0
- package/dist/descendants-v2.js +144 -0
- package/dist/descendants-v2.js.map +1 -0
- package/dist/examples/actions-context.d.ts +2 -0
- package/dist/examples/actions-context.d.ts.map +1 -0
- package/dist/examples/actions-context.js +33 -0
- package/dist/examples/actions-context.js.map +1 -0
- package/dist/examples/form-basic.d.ts.map +1 -1
- package/dist/examples/form-basic.js +1 -1
- package/dist/examples/form-basic.js.map +1 -1
- package/dist/examples/form-dropdown.js +1 -1
- package/dist/examples/form-dropdown.js.map +1 -1
- package/dist/examples/internal/custom-action-renderables.d.ts +70 -0
- package/dist/examples/internal/custom-action-renderables.d.ts.map +1 -0
- package/dist/examples/internal/custom-action-renderables.js +163 -0
- package/dist/examples/internal/custom-action-renderables.js.map +1 -0
- package/dist/examples/internal/custom-dropdown.d.ts +99 -0
- package/dist/examples/internal/custom-dropdown.d.ts.map +1 -0
- package/dist/examples/internal/custom-dropdown.js +270 -0
- package/dist/examples/internal/custom-dropdown.js.map +1 -0
- package/dist/examples/internal/custom-renderable-form.d.ts +43 -0
- package/dist/examples/internal/custom-renderable-form.d.ts.map +1 -0
- package/dist/examples/internal/custom-renderable-form.js +284 -0
- package/dist/examples/internal/custom-renderable-form.js.map +1 -0
- package/dist/examples/internal/custom-renderable-list-default-search.d.ts +2 -0
- package/dist/examples/internal/custom-renderable-list-default-search.d.ts.map +1 -0
- package/dist/examples/internal/custom-renderable-list-default-search.js +16 -0
- package/dist/examples/internal/custom-renderable-list-default-search.js.map +1 -0
- package/dist/examples/internal/custom-renderable-list-v2-default-search.d.ts +2 -0
- package/dist/examples/internal/custom-renderable-list-v2-default-search.d.ts.map +1 -0
- package/dist/examples/internal/custom-renderable-list-v2-default-search.js +24 -0
- package/dist/examples/internal/custom-renderable-list-v2-default-search.js.map +1 -0
- package/dist/examples/internal/custom-renderable-list-v2.d.ts +189 -0
- package/dist/examples/internal/custom-renderable-list-v2.d.ts.map +1 -0
- package/dist/examples/internal/custom-renderable-list-v2.js +708 -0
- package/dist/examples/internal/custom-renderable-list-v2.js.map +1 -0
- package/dist/examples/internal/custom-renderable-list.d.ts +72 -0
- package/dist/examples/internal/custom-renderable-list.d.ts.map +1 -0
- package/dist/examples/internal/custom-renderable-list.js +544 -0
- package/dist/examples/internal/custom-renderable-list.js.map +1 -0
- package/dist/examples/internal/rhf-custom-ref.js +5 -4
- package/dist/examples/internal/rhf-custom-ref.js.map +1 -1
- package/dist/examples/internal/scrollbox-with-descendants.js +4 -2
- package/dist/examples/internal/scrollbox-with-descendants.js.map +1 -1
- package/dist/examples/list-controlled-search.d.ts +2 -0
- package/dist/examples/list-controlled-search.d.ts.map +1 -0
- package/dist/examples/list-controlled-search.js +12 -0
- package/dist/examples/list-controlled-search.js.map +1 -0
- package/dist/examples/list-detail-metadata.js +1 -1
- package/dist/examples/list-detail-metadata.js.map +1 -1
- package/dist/examples/simple-image-mask.d.ts +8 -0
- package/dist/examples/simple-image-mask.d.ts.map +1 -0
- package/dist/examples/simple-image-mask.js +12 -0
- package/dist/examples/simple-image-mask.js.map +1 -0
- package/dist/examples/toast-variations.js +1 -1
- package/dist/examples/toast-variations.js.map +1 -1
- package/dist/extensions/dev.d.ts.map +1 -1
- package/dist/extensions/dev.js +3 -2
- package/dist/extensions/dev.js.map +1 -1
- package/dist/extensions/react-refresh-init.d.ts.map +1 -1
- package/dist/extensions/react-refresh-init.js +4 -3
- package/dist/extensions/react-refresh-init.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/date-picker-widget.d.ts.map +1 -1
- package/dist/internal/date-picker-widget.js +2 -1
- package/dist/internal/date-picker-widget.js.map +1 -1
- package/dist/internal/dialog.d.ts +6 -0
- package/dist/internal/dialog.d.ts.map +1 -1
- package/dist/internal/dialog.js +59 -18
- package/dist/internal/dialog.js.map +1 -1
- package/dist/internal/navigation.d.ts.map +1 -1
- package/dist/internal/navigation.js +8 -1
- package/dist/internal/navigation.js.map +1 -1
- package/dist/internal/offscreen.d.ts +3 -0
- package/dist/internal/offscreen.d.ts.map +1 -1
- package/dist/internal/offscreen.js +5 -0
- package/dist/internal/offscreen.js.map +1 -1
- package/dist/internal/providers.d.ts.map +1 -1
- package/dist/internal/providers.js +20 -3
- package/dist/internal/providers.js.map +1 -1
- package/dist/internal/scrollbox.d.ts.map +1 -1
- package/dist/internal/scrollbox.js +3 -2
- package/dist/internal/scrollbox.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +4 -0
- package/dist/logger.js.map +1 -1
- package/dist/preload.js +5 -17
- package/dist/preload.js.map +1 -1
- package/dist/state.d.ts +4 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +4 -0
- package/dist/state.js.map +1 -1
- package/dist/test-border-overlay.d.ts +2 -0
- package/dist/test-border-overlay.d.ts.map +1 -0
- package/dist/test-border-overlay.js +7 -0
- package/dist/test-border-overlay.js.map +1 -0
- package/dist/test-layout-2.d.ts +2 -0
- package/dist/test-layout-2.d.ts.map +1 -0
- package/dist/test-layout-2.js +5 -0
- package/dist/test-layout-2.js.map +1 -0
- package/dist/test-layout.d.ts +2 -0
- package/dist/test-layout.d.ts.map +1 -0
- package/dist/test-layout.js +7 -0
- package/dist/test-layout.js.map +1 -0
- package/dist/theme.d.ts +1 -2
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +5 -9
- package/dist/theme.js.map +1 -1
- package/dist/utils/run-command.d.ts +1 -1
- package/dist/utils/run-command.d.ts.map +1 -1
- package/dist/utils/run-command.js +27 -7
- package/dist/utils/run-command.js.map +1 -1
- package/dist/utils.d.ts +1 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +44 -23
- package/dist/utils.js.map +1 -1
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +24 -4
- package/dist/watcher.js.map +1 -1
- package/package.json +14 -12
- package/src/action-utils.tsx +10 -0
- package/src/apis/cache.test.ts +35 -3
- package/src/apis/cache.tsx +184 -59
- package/src/apis/clipboard.tsx +5 -0
- package/src/apis/oauth.tsx +33 -4
- package/src/build.tsx +35 -58
- package/src/cli.tsx +156 -134
- package/src/compile.tsx +6 -3
- package/src/compile.vitest.tsx +33 -15
- package/src/components/actions.tsx +230 -99
- package/src/components/alert.tsx +11 -10
- package/src/components/animation-tick.tsx +1 -1
- package/src/components/detail.tsx +56 -151
- package/src/components/dropdown.tsx +70 -36
- package/src/components/footer.tsx +58 -33
- package/src/components/form/checkbox.tsx +30 -32
- package/src/components/form/date-picker.tsx +27 -47
- package/src/components/form/description.tsx +19 -18
- package/src/components/form/dropdown.tsx +95 -103
- package/src/components/form/file-autocomplete.tsx +9 -8
- package/src/components/form/file-picker.tsx +46 -46
- package/src/components/form/form-end.tsx +6 -4
- package/src/components/form/index.tsx +38 -48
- package/src/components/form/password-field.tsx +25 -27
- package/src/components/form/separator.tsx +3 -2
- package/src/components/form/tagpicker.tsx +2 -1
- package/src/components/form/text-area.tsx +25 -30
- package/src/components/form/text-field.tsx +25 -27
- package/src/components/form/use-form-navigation.tsx +4 -5
- package/src/components/form/with-left-border.tsx +48 -10
- package/src/components/icon.tsx +69 -0
- package/src/components/image.tsx +60 -7
- package/src/components/list.tsx +270 -202
- package/src/components/loading-bar.tsx +4 -3
- package/src/components/metadata.tsx +217 -0
- package/src/components/theme-picker.tsx +3 -2
- package/src/examples/actions-context.tsx +63 -0
- package/src/examples/actions-context.vitest.tsx +110 -0
- package/src/examples/actions-dialog-layout.vitest.tsx +2 -1
- package/src/examples/file-autocomplete.vitest.tsx +15 -15
- package/src/examples/form-basic.tsx +12 -0
- package/src/examples/form-basic.vitest.tsx +74 -74
- package/src/examples/form-dropdown.tsx +8 -0
- package/src/examples/form-dropdown.vitest.tsx +364 -421
- package/src/examples/form-tagpicker.vitest.tsx +56 -54
- package/src/examples/github.vitest.tsx +252 -0
- package/src/examples/internal/rhf-custom-ref.tsx +16 -15
- package/src/examples/internal/scrollbox-with-descendants.tsx +4 -2
- package/src/examples/internal/simple-dialog.tsx +1 -1
- package/src/examples/internal/simple-scrollbox.vitest.tsx +14 -9
- package/src/examples/list-controlled-search.tsx +28 -0
- package/src/examples/list-controlled-search.vitest.tsx +49 -0
- package/src/examples/list-detail-metadata.tsx +8 -5
- package/src/examples/list-detail-metadata.vitest.tsx +22 -22
- package/src/examples/list-dropdown-default.vitest.tsx +12 -12
- package/src/examples/list-scrollbox.vitest.tsx +52 -38
- package/src/examples/list-with-detail.vitest.tsx +45 -41
- package/src/examples/list-with-dropdown.vitest.tsx +5 -5
- package/src/examples/list-with-sections.vitest.tsx +65 -12
- package/src/examples/list-with-toast.vitest.tsx +4 -4
- package/src/examples/simple-file-picker.vitest.tsx +12 -12
- package/src/examples/simple-grid.vitest.tsx +53 -53
- package/src/examples/simple-image-mask.tsx +58 -0
- package/src/examples/simple-navigation.vitest.tsx +19 -19
- package/src/examples/store.vitest.tsx +1 -1
- package/src/examples/swift-extension.vitest.tsx +4 -2
- package/src/examples/synonyms.vitest.tsx +31 -9
- package/src/examples/toast-action.vitest.tsx +8 -8
- package/src/examples/toast-variations.tsx +1 -1
- package/src/examples/toast-variations.vitest.tsx +69 -134
- package/src/extensions/dev.tsx +3 -2
- package/src/extensions/dev.vitest.tsx +65 -28
- package/src/extensions/react-refresh-init.tsx +4 -3
- package/src/index.tsx +3 -1
- package/src/internal/date-picker-widget.tsx +2 -1
- package/src/internal/dialog.tsx +100 -28
- package/src/internal/navigation.tsx +8 -1
- package/src/internal/offscreen.tsx +10 -0
- package/src/internal/providers.tsx +34 -8
- package/src/internal/scrollbox.tsx +4 -2
- package/src/logger.tsx +4 -0
- package/src/preload.tsx +5 -17
- package/src/state.tsx +12 -0
- package/src/theme.tsx +6 -9
- package/src/utils/run-command.tsx +32 -8
- package/src/utils.tsx +58 -23
- package/src/watcher.tsx +26 -6
|
@@ -2,8 +2,9 @@ import React, { ReactNode, useState, useEffect } from 'react'
|
|
|
2
2
|
import { TextAttributes } from '@opentui/core'
|
|
3
3
|
import { useTerminalDimensions, useKeyboard } from '@opentui/react'
|
|
4
4
|
import { colord } from 'colord'
|
|
5
|
-
import {
|
|
5
|
+
import { useTheme } from 'termcast/src/theme'
|
|
6
6
|
import { openInBrowser } from 'termcast/src/action-utils'
|
|
7
|
+
import { termcastMaxContentWidth } from 'termcast/src/utils'
|
|
7
8
|
import {
|
|
8
9
|
useStore,
|
|
9
10
|
toastPrimaryActionKey,
|
|
@@ -12,11 +13,6 @@ import {
|
|
|
12
13
|
} from 'termcast/src/state'
|
|
13
14
|
import { useIsInFocus } from 'termcast/src/internal/focus-context'
|
|
14
15
|
|
|
15
|
-
/** Returns white or black foreground color based on background lightness */
|
|
16
|
-
function getFgForBg(bgColor: string): string {
|
|
17
|
-
return colord(bgColor).isLight() ? '#000000' : '#ffffff'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
16
|
interface FooterProps {
|
|
21
17
|
children?: ReactNode
|
|
22
18
|
paddingLeft?: number
|
|
@@ -29,8 +25,12 @@ interface FooterProps {
|
|
|
29
25
|
|
|
30
26
|
const MIN_WIDTH_FOR_POWERED_BY = 75
|
|
31
27
|
|
|
28
|
+
const TOAST_MARGIN = 2
|
|
29
|
+
|
|
32
30
|
function ToastInline({ toast }: { toast: ToastData }): any {
|
|
31
|
+
const theme = useTheme()
|
|
33
32
|
const inFocus = useIsInFocus()
|
|
33
|
+
const { width: terminalWidth } = useTerminalDimensions()
|
|
34
34
|
const [animationFrame, setAnimationFrame] = useState(0)
|
|
35
35
|
|
|
36
36
|
// Keyboard handling for toast actions
|
|
@@ -91,66 +91,76 @@ function ToastInline({ toast }: { toast: ToastData }): any {
|
|
|
91
91
|
const getIconColor = () => {
|
|
92
92
|
switch (toast.style) {
|
|
93
93
|
case 'SUCCESS':
|
|
94
|
-
return
|
|
94
|
+
return theme.success
|
|
95
95
|
case 'FAILURE':
|
|
96
|
-
return
|
|
96
|
+
return theme.error
|
|
97
97
|
case 'ANIMATED':
|
|
98
|
-
return
|
|
98
|
+
return theme.primary
|
|
99
99
|
default:
|
|
100
|
-
return
|
|
100
|
+
return theme.success
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
const
|
|
105
|
-
const
|
|
106
|
-
|
|
104
|
+
const primaryColor = theme.primary
|
|
105
|
+
const mutedColor = colord(primaryColor).darken(0.06).toHex()
|
|
106
|
+
|
|
107
|
+
const maxToastWidth = Math.min(terminalWidth, termcastMaxContentWidth)
|
|
108
|
+
const toastWidth = maxToastWidth - TOAST_MARGIN * 2
|
|
107
109
|
|
|
108
|
-
const hasKeys = !!toast.primaryAction?.title || !!toast.secondaryAction?.title
|
|
109
110
|
return (
|
|
110
111
|
<box
|
|
111
112
|
flexDirection='row'
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
width={toastWidth}
|
|
114
|
+
marginLeft={-TOAST_MARGIN}
|
|
115
|
+
marginRight={-TOAST_MARGIN}
|
|
116
|
+
flexGrow={0}
|
|
117
|
+
flexShrink={0}
|
|
115
118
|
overflow='hidden'
|
|
119
|
+
height={1}
|
|
116
120
|
>
|
|
117
121
|
{/* Title box */}
|
|
118
122
|
<box
|
|
119
123
|
flexDirection='row'
|
|
120
124
|
flexShrink={0}
|
|
121
|
-
backgroundColor={colord(primaryBg).lighten(0.1).toHex()}
|
|
122
|
-
paddingLeft={3}
|
|
123
125
|
paddingRight={1}
|
|
126
|
+
overflow='hidden'
|
|
127
|
+
height={1}
|
|
124
128
|
>
|
|
125
|
-
<text flexShrink={0} fg={getIconColor()}>
|
|
129
|
+
<text flexShrink={0} fg={getIconColor()} wrapMode='none'>
|
|
126
130
|
{getIcon()}{' '}
|
|
127
131
|
</text>
|
|
128
|
-
<text
|
|
132
|
+
<text
|
|
133
|
+
flexShrink={1}
|
|
134
|
+
fg={primaryColor}
|
|
135
|
+
attributes={TextAttributes.BOLD}
|
|
136
|
+
wrapMode='none'
|
|
137
|
+
>
|
|
129
138
|
{toast.title}
|
|
130
139
|
</text>
|
|
131
140
|
</box>
|
|
132
|
-
{/* Message/description box
|
|
141
|
+
{/* Message/description box */}
|
|
133
142
|
<box
|
|
134
143
|
flexGrow={1}
|
|
135
|
-
|
|
144
|
+
flexShrink={1}
|
|
136
145
|
paddingLeft={1}
|
|
137
146
|
paddingRight={1}
|
|
138
147
|
flexDirection='row'
|
|
139
148
|
overflow='hidden'
|
|
149
|
+
height={1}
|
|
140
150
|
>
|
|
141
|
-
<text fg={
|
|
151
|
+
<text fg={mutedColor} flexShrink={1} wrapMode='none'>
|
|
142
152
|
{toast.message || ''}
|
|
143
153
|
</text>
|
|
144
154
|
</box>
|
|
145
155
|
{/* Keys box (right aligned, no grow) */}
|
|
146
|
-
|
|
147
156
|
<box
|
|
148
|
-
backgroundColor={keysBg}
|
|
149
157
|
paddingLeft={1}
|
|
150
|
-
|
|
158
|
+
|
|
151
159
|
gap={1}
|
|
152
160
|
flexDirection='row'
|
|
153
161
|
flexShrink={0}
|
|
162
|
+
overflow='hidden'
|
|
163
|
+
height={1}
|
|
154
164
|
>
|
|
155
165
|
{toast.primaryAction?.title && (
|
|
156
166
|
<box
|
|
@@ -160,10 +170,17 @@ function ToastInline({ toast }: { toast: ToastData }): any {
|
|
|
160
170
|
toast.primaryAction?.onAction()
|
|
161
171
|
}}
|
|
162
172
|
>
|
|
163
|
-
<text
|
|
173
|
+
<text
|
|
174
|
+
fg={mutedColor}
|
|
175
|
+
attributes={TextAttributes.BOLD}
|
|
176
|
+
wrapMode='none'
|
|
177
|
+
>
|
|
164
178
|
{toast.primaryAction.title}
|
|
165
179
|
</text>
|
|
166
|
-
<text fg={
|
|
180
|
+
<text fg={mutedColor} wrapMode='none'>
|
|
181
|
+
{' '}
|
|
182
|
+
ctrl t
|
|
183
|
+
</text>
|
|
167
184
|
</box>
|
|
168
185
|
)}
|
|
169
186
|
{toast.secondaryAction?.title && (
|
|
@@ -174,10 +191,17 @@ function ToastInline({ toast }: { toast: ToastData }): any {
|
|
|
174
191
|
toast.secondaryAction?.onAction()
|
|
175
192
|
}}
|
|
176
193
|
>
|
|
177
|
-
<text
|
|
194
|
+
<text
|
|
195
|
+
fg={mutedColor}
|
|
196
|
+
attributes={TextAttributes.BOLD}
|
|
197
|
+
wrapMode='none'
|
|
198
|
+
>
|
|
178
199
|
{toast.secondaryAction.title}
|
|
179
200
|
</text>
|
|
180
|
-
<text fg={
|
|
201
|
+
<text fg={mutedColor} wrapMode='none'>
|
|
202
|
+
{' '}
|
|
203
|
+
ctrl g
|
|
204
|
+
</text>
|
|
181
205
|
</box>
|
|
182
206
|
)}
|
|
183
207
|
</box>
|
|
@@ -194,6 +218,7 @@ export function Footer({
|
|
|
194
218
|
marginTop = 1,
|
|
195
219
|
hidePoweredBy = false,
|
|
196
220
|
}: FooterProps): any {
|
|
221
|
+
const theme = useTheme()
|
|
197
222
|
const { width } = useTerminalDimensions()
|
|
198
223
|
const showPoweredBy = !hidePoweredBy && width >= MIN_WIDTH_FOR_POWERED_BY
|
|
199
224
|
const toast = useStore((state) => state.toast)
|
|
@@ -219,7 +244,7 @@ export function Footer({
|
|
|
219
244
|
{children}
|
|
220
245
|
{showPoweredBy && (
|
|
221
246
|
<box flexDirection='row' gap={1}>
|
|
222
|
-
<text flexShrink={0} fg={
|
|
247
|
+
<text flexShrink={0} fg={theme.textMuted}>
|
|
223
248
|
powered by
|
|
224
249
|
</text>
|
|
225
250
|
<text
|
|
@@ -227,7 +252,7 @@ export function Footer({
|
|
|
227
252
|
onMouseDown={() => {
|
|
228
253
|
openInBrowser('https://termcast.app')
|
|
229
254
|
}}
|
|
230
|
-
fg={
|
|
255
|
+
fg={theme.textMuted}
|
|
231
256
|
attributes={TextAttributes.BOLD}
|
|
232
257
|
>
|
|
233
258
|
termcast
|
|
@@ -5,8 +5,8 @@ import { useFormContext, Controller } from 'react-hook-form'
|
|
|
5
5
|
import { useFocusContext, useFormFieldDescendant } from './index'
|
|
6
6
|
import { FormItemProps, FormItemRef } from './types'
|
|
7
7
|
import { logger } from 'termcast/src/logger'
|
|
8
|
-
import {
|
|
9
|
-
import { WithLeftBorder } from './with-left-border'
|
|
8
|
+
import { useTheme } from 'termcast/src/theme'
|
|
9
|
+
import { WithLeftBorder, TitleIndicator } from './with-left-border'
|
|
10
10
|
import { useFormNavigation } from './use-form-navigation'
|
|
11
11
|
import { useIsInFocus } from 'termcast/src/internal/focus-context'
|
|
12
12
|
import { LoadingText } from 'termcast/src/components/loading-text'
|
|
@@ -18,6 +18,7 @@ export interface CheckboxProps extends FormItemProps<boolean> {
|
|
|
18
18
|
export type CheckboxRef = FormItemRef
|
|
19
19
|
|
|
20
20
|
export const Checkbox = (props: CheckboxProps): any => {
|
|
21
|
+
const theme = useTheme()
|
|
21
22
|
const { control, setValue, getValues } = useFormContext()
|
|
22
23
|
const focusContext = useFocusContext()
|
|
23
24
|
const { focusedField, setFocusedField } = focusContext
|
|
@@ -59,28 +60,28 @@ export const Checkbox = (props: CheckboxProps): any => {
|
|
|
59
60
|
render={({ field, fieldState, formState }) => {
|
|
60
61
|
return (
|
|
61
62
|
<box ref={elementRef} flexDirection='column'>
|
|
62
|
-
<WithLeftBorder
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
<LoadingText
|
|
74
|
-
isLoading={isFocused && focusContext.isLoading}
|
|
75
|
-
color={isFocused ? Theme.primary : Theme.text}
|
|
63
|
+
<WithLeftBorder isFocused={isFocused} paddingBottom={1}>
|
|
64
|
+
<TitleIndicator isFocused={isFocused} isLoading={focusContext.isLoading}>
|
|
65
|
+
<box
|
|
66
|
+
onMouseDown={() => {
|
|
67
|
+
// Always focus the field when clicked
|
|
68
|
+
if (!isFocused) {
|
|
69
|
+
setFocusedField(props.id)
|
|
70
|
+
}
|
|
71
|
+
// Always toggle the value when clicked
|
|
72
|
+
handleToggle()
|
|
73
|
+
}}
|
|
76
74
|
>
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
<LoadingText
|
|
76
|
+
isLoading={isFocused && focusContext.isLoading}
|
|
77
|
+
color={isFocused ? theme.primary : theme.text}
|
|
78
|
+
>
|
|
79
|
+
{props.title || ''}
|
|
80
|
+
</LoadingText>
|
|
81
|
+
</box>
|
|
82
|
+
</TitleIndicator>
|
|
82
83
|
<text
|
|
83
|
-
fg={isFocused ?
|
|
84
|
+
fg={isFocused ? theme.accent : theme.text}
|
|
84
85
|
selectable={false}
|
|
85
86
|
onMouseDown={() => {
|
|
86
87
|
if (!isFocused) {
|
|
@@ -91,17 +92,14 @@ export const Checkbox = (props: CheckboxProps): any => {
|
|
|
91
92
|
>
|
|
92
93
|
{field.value ? '●' : '○'} {props.label}
|
|
93
94
|
</text>
|
|
95
|
+
{(props.error || props.info) && <box height={1} />}
|
|
96
|
+
{props.error && (
|
|
97
|
+
<text fg={theme.error}>{props.error}</text>
|
|
98
|
+
)}
|
|
99
|
+
{props.info && (
|
|
100
|
+
<text fg={theme.textMuted}>{props.info}</text>
|
|
101
|
+
)}
|
|
94
102
|
</WithLeftBorder>
|
|
95
|
-
{props.error && (
|
|
96
|
-
<WithLeftBorder isFocused={isFocused}>
|
|
97
|
-
<text fg={Theme.error}>{props.error}</text>
|
|
98
|
-
</WithLeftBorder>
|
|
99
|
-
)}
|
|
100
|
-
{props.info && (
|
|
101
|
-
<WithLeftBorder isFocused={isFocused}>
|
|
102
|
-
<text fg={Theme.textMuted}>{props.info}</text>
|
|
103
|
-
</WithLeftBorder>
|
|
104
|
-
)}
|
|
105
103
|
</box>
|
|
106
104
|
) as React.ReactElement
|
|
107
105
|
}}
|
|
@@ -4,8 +4,8 @@ import { useKeyboard } from '@opentui/react'
|
|
|
4
4
|
import { useFormContext, Controller } from 'react-hook-form'
|
|
5
5
|
import { useFocusContext, useFormFieldDescendant } from './index'
|
|
6
6
|
import { FormItemProps, FormItemRef } from './types'
|
|
7
|
-
import {
|
|
8
|
-
import { WithLeftBorder } from './with-left-border'
|
|
7
|
+
import { useTheme } from 'termcast/src/theme'
|
|
8
|
+
import { WithLeftBorder, TitleIndicator } 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'
|
|
@@ -30,6 +30,7 @@ interface DatePickerComponentType {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const DatePickerComponent = (props: DatePickerProps): any => {
|
|
33
|
+
const theme = useTheme()
|
|
33
34
|
const { control } = useFormContext()
|
|
34
35
|
const focusContext = useFocusContext()
|
|
35
36
|
const { focusedField, setFocusedField } = focusContext
|
|
@@ -44,21 +45,6 @@ const DatePickerComponent = (props: DatePickerProps): any => {
|
|
|
44
45
|
elementRef: elementRef.current,
|
|
45
46
|
})
|
|
46
47
|
|
|
47
|
-
const { navigateToPrevious, navigateToNext } = useFormNavigationHelpers(props.id)
|
|
48
|
-
|
|
49
|
-
// Handle tab navigation only
|
|
50
|
-
useKeyboard((evt) => {
|
|
51
|
-
if (!isFocused || !isInFocus) return
|
|
52
|
-
|
|
53
|
-
if (evt.name === 'tab') {
|
|
54
|
-
if (evt.shift) {
|
|
55
|
-
navigateToPrevious()
|
|
56
|
-
} else {
|
|
57
|
-
navigateToNext()
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
})
|
|
61
|
-
|
|
62
48
|
return (
|
|
63
49
|
<Controller
|
|
64
50
|
name={props.id}
|
|
@@ -67,21 +53,21 @@ const DatePickerComponent = (props: DatePickerProps): any => {
|
|
|
67
53
|
render={({ field, fieldState, formState }) => {
|
|
68
54
|
return (
|
|
69
55
|
<box ref={elementRef} flexDirection='column'>
|
|
70
|
-
<WithLeftBorder
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
<LoadingText
|
|
77
|
-
isLoading={isFocused && focusContext.isLoading}
|
|
78
|
-
color={isFocused ? Theme.primary : Theme.text}
|
|
56
|
+
<WithLeftBorder isFocused={isFocused} paddingBottom={1}>
|
|
57
|
+
<TitleIndicator isFocused={isFocused} isLoading={focusContext.isLoading}>
|
|
58
|
+
<box
|
|
59
|
+
onMouseDown={() => {
|
|
60
|
+
setFocusedField(props.id)
|
|
61
|
+
}}
|
|
79
62
|
>
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
63
|
+
<LoadingText
|
|
64
|
+
isLoading={isFocused && focusContext.isLoading}
|
|
65
|
+
color={isFocused ? theme.primary : theme.text}
|
|
66
|
+
>
|
|
67
|
+
{props.title || ''}
|
|
68
|
+
</LoadingText>
|
|
69
|
+
</box>
|
|
70
|
+
</TitleIndicator>
|
|
85
71
|
<DatePickerWidget
|
|
86
72
|
enableColors={isFocused}
|
|
87
73
|
initialValue={field.value || undefined}
|
|
@@ -93,26 +79,20 @@ const DatePickerComponent = (props: DatePickerProps): any => {
|
|
|
93
79
|
}}
|
|
94
80
|
focused={isFocused}
|
|
95
81
|
/>
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<WithLeftBorder isFocused={isFocused}>
|
|
99
|
-
<text fg={Theme.accent}>
|
|
82
|
+
{field.value && (
|
|
83
|
+
<text fg={theme.accent}>
|
|
100
84
|
Selected: {field.value.toISOString().split('T')[0]}
|
|
101
85
|
</text>
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
<WithLeftBorder isFocused={isFocused}>
|
|
106
|
-
<text fg={Theme.error}>
|
|
86
|
+
)}
|
|
87
|
+
{(fieldState.error || props.error) && (
|
|
88
|
+
<text fg={theme.error}>
|
|
107
89
|
{fieldState.error?.message || props.error}
|
|
108
90
|
</text>
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
</WithLeftBorder>
|
|
115
|
-
)}
|
|
91
|
+
)}
|
|
92
|
+
{props.info && (
|
|
93
|
+
<text fg={theme.textMuted}>{props.info}</text>
|
|
94
|
+
)}
|
|
95
|
+
</WithLeftBorder>
|
|
116
96
|
</box>
|
|
117
97
|
) as React.ReactElement
|
|
118
98
|
}}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useRef, useId } from 'react'
|
|
2
2
|
import { BoxRenderable, TextAttributes } from '@opentui/core'
|
|
3
|
-
import {
|
|
4
|
-
import { WithLeftBorder } from './with-left-border'
|
|
3
|
+
import { useTheme } from 'termcast/src/theme'
|
|
4
|
+
import { WithLeftBorder, TitleIndicator } from './with-left-border'
|
|
5
5
|
import { useFocusContext, useFormFieldDescendant } from './index'
|
|
6
6
|
import { useFormNavigation } from './use-form-navigation'
|
|
7
7
|
import { LoadingText } from 'termcast/src/components/loading-text'
|
|
@@ -13,9 +13,10 @@ export interface DescriptionProps {
|
|
|
13
13
|
isFormTitle?: boolean
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export const FORM_MAX_WIDTH =
|
|
16
|
+
export const FORM_MAX_WIDTH = 120
|
|
17
17
|
|
|
18
18
|
export const Description = (props: DescriptionProps): any => {
|
|
19
|
+
const theme = useTheme()
|
|
19
20
|
const elementRef = useRef<BoxRenderable>(null)
|
|
20
21
|
const autoId = useId()
|
|
21
22
|
const id = props.id || autoId
|
|
@@ -41,22 +42,22 @@ export const Description = (props: DescriptionProps): any => {
|
|
|
41
42
|
focusContext.setFocusedField(id)
|
|
42
43
|
}}
|
|
43
44
|
>
|
|
44
|
-
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<LoadingText
|
|
51
|
-
isLoading={isFocused && focusContext.isLoading}
|
|
52
|
-
color={isFocused ? Theme.primary : Theme.text}
|
|
45
|
+
<WithLeftBorder isFocused={isFocused} paddingBottom={1}>
|
|
46
|
+
{props.title && (
|
|
47
|
+
<TitleIndicator
|
|
48
|
+
isFocused={isFocused}
|
|
49
|
+
isLoading={focusContext.isLoading}
|
|
50
|
+
customCharacter={{ focused: '■', unfocused: '▪︎' }}
|
|
53
51
|
>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
<LoadingText
|
|
53
|
+
isLoading={isFocused && focusContext.isLoading}
|
|
54
|
+
color={isFocused ? theme.primary : theme.text}
|
|
55
|
+
>
|
|
56
|
+
{props.title}
|
|
57
|
+
</LoadingText>
|
|
58
|
+
</TitleIndicator>
|
|
59
|
+
)}
|
|
60
|
+
<text fg={theme.textMuted}>{props.text}</text>
|
|
60
61
|
</WithLeftBorder>
|
|
61
62
|
</box>
|
|
62
63
|
)
|