@moldable-ai/ui 0.2.19 → 0.2.20
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/catalog/catalog-manifest.d.ts +6 -0
- package/dist/catalog/catalog-manifest.d.ts.map +1 -0
- package/dist/catalog/catalog-manifest.js +105 -0
- package/dist/catalog/catalog-types.d.ts +54 -0
- package/dist/catalog/catalog-types.d.ts.map +1 -0
- package/dist/catalog/catalog-types.js +14 -0
- package/dist/catalog/component-catalog.d.ts +14 -0
- package/dist/catalog/component-catalog.d.ts.map +1 -0
- package/dist/catalog/component-catalog.js +39 -0
- package/dist/catalog/core-catalog.d.ts +6 -0
- package/dist/catalog/core-catalog.d.ts.map +1 -0
- package/dist/catalog/core-catalog.js +105 -0
- package/dist/catalog/index.d.ts +5 -0
- package/dist/catalog/index.d.ts.map +1 -0
- package/dist/catalog/index.js +4 -0
- package/dist/components/app-error-boundary.d.ts +1 -0
- package/dist/components/app-error-boundary.d.ts.map +1 -1
- package/dist/components/app-error-boundary.js +13 -0
- package/dist/components/chat/chat-image-lightbox.d.ts +9 -0
- package/dist/components/chat/chat-image-lightbox.d.ts.map +1 -0
- package/dist/components/chat/chat-image-lightbox.js +9 -0
- package/dist/components/chat/chat-message.d.ts +19 -1
- package/dist/components/chat/chat-message.d.ts.map +1 -1
- package/dist/components/chat/chat-message.js +66 -16
- package/dist/components/chat/chat-messages.d.ts +5 -2
- package/dist/components/chat/chat-messages.d.ts.map +1 -1
- package/dist/components/chat/chat-messages.js +61 -6
- package/dist/components/chat/chat-panel.d.ts +50 -6
- package/dist/components/chat/chat-panel.d.ts.map +1 -1
- package/dist/components/chat/chat-panel.js +200 -163
- package/dist/components/chat/conversation-history.d.ts +39 -5
- package/dist/components/chat/conversation-history.d.ts.map +1 -1
- package/dist/components/chat/conversation-history.js +192 -26
- package/dist/components/chat/index.d.ts +2 -2
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +1 -1
- package/dist/components/chat/tool-handlers.d.ts.map +1 -1
- package/dist/components/chat/tool-handlers.js +40 -2
- package/dist/components/chat/vertical-scroll-fade.d.ts +6 -0
- package/dist/components/chat/vertical-scroll-fade.d.ts.map +1 -0
- package/dist/components/chat/vertical-scroll-fade.js +12 -0
- package/dist/components/native-capabilities/bluetooth-panel-helpers.d.ts +9 -0
- package/dist/components/native-capabilities/bluetooth-panel-helpers.d.ts.map +1 -0
- package/dist/components/native-capabilities/bluetooth-panel-helpers.js +37 -0
- package/dist/components/native-capabilities/bluetooth-panel.d.ts +56 -0
- package/dist/components/native-capabilities/bluetooth-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/bluetooth-panel.js +470 -0
- package/dist/components/native-capabilities/camera-preview.d.ts +39 -0
- package/dist/components/native-capabilities/camera-preview.d.ts.map +1 -0
- package/dist/components/native-capabilities/camera-preview.js +228 -0
- package/dist/components/native-capabilities/capability-badge.d.ts +23 -0
- package/dist/components/native-capabilities/capability-badge.d.ts.map +1 -0
- package/dist/components/native-capabilities/capability-badge.js +39 -0
- package/dist/components/native-capabilities/capability-matrix.d.ts +14 -0
- package/dist/components/native-capabilities/capability-matrix.d.ts.map +1 -0
- package/dist/components/native-capabilities/capability-matrix.js +97 -0
- package/dist/components/native-capabilities/clipboard-button.d.ts +26 -0
- package/dist/components/native-capabilities/clipboard-button.d.ts.map +1 -0
- package/dist/components/native-capabilities/clipboard-button.js +99 -0
- package/dist/components/native-capabilities/device-io-controls.d.ts +4 -0
- package/dist/components/native-capabilities/device-io-controls.d.ts.map +1 -0
- package/dist/components/native-capabilities/device-io-controls.js +28 -0
- package/dist/components/native-capabilities/device-list.d.ts +20 -0
- package/dist/components/native-capabilities/device-list.d.ts.map +1 -0
- package/dist/components/native-capabilities/device-list.js +14 -0
- package/dist/components/native-capabilities/display-map.d.ts +23 -0
- package/dist/components/native-capabilities/display-map.d.ts.map +1 -0
- package/dist/components/native-capabilities/display-map.js +114 -0
- package/dist/components/native-capabilities/haptic-button.d.ts +26 -0
- package/dist/components/native-capabilities/haptic-button.d.ts.map +1 -0
- package/dist/components/native-capabilities/haptic-button.js +94 -0
- package/dist/components/native-capabilities/hid-panel.d.ts +40 -0
- package/dist/components/native-capabilities/hid-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/hid-panel.js +373 -0
- package/dist/components/native-capabilities/index.d.ts +27 -0
- package/dist/components/native-capabilities/index.d.ts.map +1 -0
- package/dist/components/native-capabilities/index.js +26 -0
- package/dist/components/native-capabilities/live-indicator.d.ts +15 -0
- package/dist/components/native-capabilities/live-indicator.d.ts.map +1 -0
- package/dist/components/native-capabilities/live-indicator.js +26 -0
- package/dist/components/native-capabilities/local-auth-button.d.ts +33 -0
- package/dist/components/native-capabilities/local-auth-button.d.ts.map +1 -0
- package/dist/components/native-capabilities/local-auth-button.js +115 -0
- package/dist/components/native-capabilities/location-panel.d.ts +29 -0
- package/dist/components/native-capabilities/location-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/location-panel.js +146 -0
- package/dist/components/native-capabilities/microphone-meter.d.ts +35 -0
- package/dist/components/native-capabilities/microphone-meter.d.ts.map +1 -0
- package/dist/components/native-capabilities/microphone-meter.js +244 -0
- package/dist/components/native-capabilities/midi-monitor.d.ts +54 -0
- package/dist/components/native-capabilities/midi-monitor.d.ts.map +1 -0
- package/dist/components/native-capabilities/midi-monitor.js +534 -0
- package/dist/components/native-capabilities/native-capability-panel.d.ts +11 -0
- package/dist/components/native-capabilities/native-capability-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/native-capability-panel.js +28 -0
- package/dist/components/native-capabilities/notification-panel.d.ts +24 -0
- package/dist/components/native-capabilities/notification-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/notification-panel.js +124 -0
- package/dist/components/native-capabilities/power-blocker-controller.d.ts +19 -0
- package/dist/components/native-capabilities/power-blocker-controller.d.ts.map +1 -0
- package/dist/components/native-capabilities/power-blocker-controller.js +83 -0
- package/dist/components/native-capabilities/power-panel.d.ts +67 -0
- package/dist/components/native-capabilities/power-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/power-panel.js +309 -0
- package/dist/components/native-capabilities/readout.d.ts +10 -0
- package/dist/components/native-capabilities/readout.d.ts.map +1 -0
- package/dist/components/native-capabilities/readout.js +11 -0
- package/dist/components/native-capabilities/screen-share-preview.d.ts +36 -0
- package/dist/components/native-capabilities/screen-share-preview.d.ts.map +1 -0
- package/dist/components/native-capabilities/screen-share-preview.js +191 -0
- package/dist/components/native-capabilities/secure-storage-panel.d.ts +36 -0
- package/dist/components/native-capabilities/secure-storage-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/secure-storage-panel.js +193 -0
- package/dist/components/native-capabilities/serial-console.d.ts +64 -0
- package/dist/components/native-capabilities/serial-console.d.ts.map +1 -0
- package/dist/components/native-capabilities/serial-console.js +399 -0
- package/dist/components/native-capabilities/shortcut-recorder.d.ts +35 -0
- package/dist/components/native-capabilities/shortcut-recorder.d.ts.map +1 -0
- package/dist/components/native-capabilities/shortcut-recorder.js +217 -0
- package/dist/components/native-capabilities/stream-log.d.ts +35 -0
- package/dist/components/native-capabilities/stream-log.d.ts.map +1 -0
- package/dist/components/native-capabilities/stream-log.js +65 -0
- package/dist/components/native-capabilities/system-audio-monitor.d.ts +34 -0
- package/dist/components/native-capabilities/system-audio-monitor.d.ts.map +1 -0
- package/dist/components/native-capabilities/system-audio-monitor.js +275 -0
- package/dist/components/native-capabilities/usb-panel.d.ts +54 -0
- package/dist/components/native-capabilities/usb-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/usb-panel.js +363 -0
- package/dist/components/native-capabilities/use-capability.d.ts +20 -0
- package/dist/components/native-capabilities/use-capability.d.ts.map +1 -0
- package/dist/components/native-capabilities/use-capability.js +61 -0
- package/dist/components/ui/app-frame.d.ts +22 -0
- package/dist/components/ui/app-frame.d.ts.map +1 -0
- package/dist/components/ui/app-frame.js +56 -0
- package/dist/components/ui/button-group.d.ts +1 -1
- package/dist/components/ui/button.js +1 -1
- package/dist/components/ui/color-well.d.ts +13 -0
- package/dist/components/ui/color-well.d.ts.map +1 -0
- package/dist/components/ui/color-well.js +30 -0
- package/dist/components/ui/date-field.d.ts +19 -0
- package/dist/components/ui/date-field.d.ts.map +1 -0
- package/dist/components/ui/date-field.js +54 -0
- package/dist/components/ui/edge-fade.d.ts +11 -0
- package/dist/components/ui/edge-fade.d.ts.map +1 -0
- package/dist/components/ui/edge-fade.js +41 -0
- package/dist/components/ui/empty.js +1 -1
- package/dist/components/ui/field.d.ts +1 -1
- package/dist/components/ui/grid.d.ts +24 -0
- package/dist/components/ui/grid.d.ts.map +1 -0
- package/dist/components/ui/grid.js +234 -0
- package/dist/components/ui/icon-button.d.ts +15 -0
- package/dist/components/ui/icon-button.d.ts.map +1 -0
- package/dist/components/ui/icon-button.js +15 -0
- package/dist/components/ui/index.d.ts +19 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +19 -0
- package/dist/components/ui/input-group.d.ts +1 -1
- package/dist/components/ui/inspector.d.ts +15 -0
- package/dist/components/ui/inspector.d.ts.map +1 -0
- package/dist/components/ui/inspector.js +26 -0
- package/dist/components/ui/kbd.d.ts +1 -1
- package/dist/components/ui/list.d.ts +24 -0
- package/dist/components/ui/list.d.ts.map +1 -0
- package/dist/components/ui/list.js +224 -0
- package/dist/components/ui/message-scroller-layout-stability.d.ts +33 -0
- package/dist/components/ui/message-scroller-layout-stability.d.ts.map +1 -0
- package/dist/components/ui/message-scroller-layout-stability.js +153 -0
- package/dist/components/ui/message-scroller.d.ts +11 -0
- package/dist/components/ui/message-scroller.d.ts.map +1 -0
- package/dist/components/ui/message-scroller.js +37 -0
- package/dist/components/ui/notification-dot.d.ts +4 -0
- package/dist/components/ui/notification-dot.d.ts.map +1 -0
- package/dist/components/ui/notification-dot.js +7 -0
- package/dist/components/ui/number-input.d.ts +16 -0
- package/dist/components/ui/number-input.d.ts.map +1 -0
- package/dist/components/ui/number-input.js +56 -0
- package/dist/components/ui/panel.d.ts +18 -0
- package/dist/components/ui/panel.d.ts.map +1 -0
- package/dist/components/ui/panel.js +40 -0
- package/dist/components/ui/popover.js +1 -1
- package/dist/components/ui/search-field.d.ts +19 -0
- package/dist/components/ui/search-field.d.ts.map +1 -0
- package/dist/components/ui/search-field.js +64 -0
- package/dist/components/ui/segmented-control.d.ts +21 -0
- package/dist/components/ui/segmented-control.d.ts.map +1 -0
- package/dist/components/ui/segmented-control.js +61 -0
- package/dist/components/ui/sidebar.js +1 -1
- package/dist/components/ui/sonner.d.ts +4 -3
- package/dist/components/ui/sonner.d.ts.map +1 -1
- package/dist/components/ui/sonner.js +7 -6
- package/dist/components/ui/split-view.d.ts +11 -0
- package/dist/components/ui/split-view.d.ts.map +1 -0
- package/dist/components/ui/split-view.js +13 -0
- package/dist/components/ui/status.d.ts +13 -0
- package/dist/components/ui/status.d.ts.map +1 -0
- package/dist/components/ui/status.js +36 -0
- package/dist/components/ui/table.d.ts +11 -2
- package/dist/components/ui/table.d.ts.map +1 -1
- package/dist/components/ui/table.js +28 -6
- package/dist/components/ui/text.d.ts +17 -0
- package/dist/components/ui/text.d.ts.map +1 -0
- package/dist/components/ui/text.js +55 -0
- package/dist/components/ui/toggle.js +1 -1
- package/dist/components/ui/toolbar.d.ts +20 -0
- package/dist/components/ui/toolbar.d.ts.map +1 -0
- package/dist/components/ui/toolbar.js +52 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/lib/frame-lifecycle.d.ts +28 -0
- package/dist/lib/frame-lifecycle.d.ts.map +1 -1
- package/dist/lib/frame-lifecycle.js +84 -0
- package/dist/lib/native-capabilities/access.d.ts +13 -0
- package/dist/lib/native-capabilities/access.d.ts.map +1 -0
- package/dist/lib/native-capabilities/access.js +53 -0
- package/dist/lib/native-capabilities/bluetooth-access.d.ts +14 -0
- package/dist/lib/native-capabilities/bluetooth-access.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth-access.js +43 -0
- package/dist/lib/native-capabilities/bluetooth-connection.d.ts +19 -0
- package/dist/lib/native-capabilities/bluetooth-connection.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth-connection.js +88 -0
- package/dist/lib/native-capabilities/bluetooth-gatt.d.ts +7 -0
- package/dist/lib/native-capabilities/bluetooth-gatt.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth-gatt.js +77 -0
- package/dist/lib/native-capabilities/bluetooth-internal.d.ts +10 -0
- package/dist/lib/native-capabilities/bluetooth-internal.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth-internal.js +105 -0
- package/dist/lib/native-capabilities/bluetooth-native-fallback.d.ts +33 -0
- package/dist/lib/native-capabilities/bluetooth-native-fallback.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth-native-fallback.js +214 -0
- package/dist/lib/native-capabilities/bluetooth-types.d.ts +85 -0
- package/dist/lib/native-capabilities/bluetooth-types.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth-types.js +2 -0
- package/dist/lib/native-capabilities/bluetooth.d.ts +7 -0
- package/dist/lib/native-capabilities/bluetooth.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth.js +4 -0
- package/dist/lib/native-capabilities/bridge.d.ts +23 -0
- package/dist/lib/native-capabilities/bridge.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bridge.js +266 -0
- package/dist/lib/native-capabilities/capabilities.d.ts +7 -0
- package/dist/lib/native-capabilities/capabilities.d.ts.map +1 -0
- package/dist/lib/native-capabilities/capabilities.js +95 -0
- package/dist/lib/native-capabilities/clipboard.d.ts +11 -0
- package/dist/lib/native-capabilities/clipboard.d.ts.map +1 -0
- package/dist/lib/native-capabilities/clipboard.js +58 -0
- package/dist/lib/native-capabilities/device-io-errors.d.ts +11 -0
- package/dist/lib/native-capabilities/device-io-errors.d.ts.map +1 -0
- package/dist/lib/native-capabilities/device-io-errors.js +82 -0
- package/dist/lib/native-capabilities/displays.d.ts +38 -0
- package/dist/lib/native-capabilities/displays.d.ts.map +1 -0
- package/dist/lib/native-capabilities/displays.js +12 -0
- package/dist/lib/native-capabilities/global-shortcuts.d.ts +86 -0
- package/dist/lib/native-capabilities/global-shortcuts.d.ts.map +1 -0
- package/dist/lib/native-capabilities/global-shortcuts.js +351 -0
- package/dist/lib/native-capabilities/haptics.d.ts +25 -0
- package/dist/lib/native-capabilities/haptics.d.ts.map +1 -0
- package/dist/lib/native-capabilities/haptics.js +18 -0
- package/dist/lib/native-capabilities/hid-native.d.ts +26 -0
- package/dist/lib/native-capabilities/hid-native.d.ts.map +1 -0
- package/dist/lib/native-capabilities/hid-native.js +229 -0
- package/dist/lib/native-capabilities/hid.d.ts +52 -0
- package/dist/lib/native-capabilities/hid.d.ts.map +1 -0
- package/dist/lib/native-capabilities/hid.js +163 -0
- package/dist/lib/native-capabilities/index.d.ts +40 -0
- package/dist/lib/native-capabilities/index.d.ts.map +1 -0
- package/dist/lib/native-capabilities/index.js +21 -0
- package/dist/lib/native-capabilities/local-authentication.d.ts +32 -0
- package/dist/lib/native-capabilities/local-authentication.d.ts.map +1 -0
- package/dist/lib/native-capabilities/local-authentication.js +46 -0
- package/dist/lib/native-capabilities/location.d.ts +49 -0
- package/dist/lib/native-capabilities/location.d.ts.map +1 -0
- package/dist/lib/native-capabilities/location.js +114 -0
- package/dist/lib/native-capabilities/media-permissions.d.ts +28 -0
- package/dist/lib/native-capabilities/media-permissions.d.ts.map +1 -0
- package/dist/lib/native-capabilities/media-permissions.js +37 -0
- package/dist/lib/native-capabilities/media.d.ts +17 -0
- package/dist/lib/native-capabilities/media.d.ts.map +1 -0
- package/dist/lib/native-capabilities/media.js +104 -0
- package/dist/lib/native-capabilities/midi-access.d.ts +13 -0
- package/dist/lib/native-capabilities/midi-access.d.ts.map +1 -0
- package/dist/lib/native-capabilities/midi-access.js +68 -0
- package/dist/lib/native-capabilities/midi-internal.d.ts +12 -0
- package/dist/lib/native-capabilities/midi-internal.d.ts.map +1 -0
- package/dist/lib/native-capabilities/midi-internal.js +88 -0
- package/dist/lib/native-capabilities/midi-native-fallback.d.ts +27 -0
- package/dist/lib/native-capabilities/midi-native-fallback.d.ts.map +1 -0
- package/dist/lib/native-capabilities/midi-native-fallback.js +127 -0
- package/dist/lib/native-capabilities/midi-ports.d.ts +6 -0
- package/dist/lib/native-capabilities/midi-ports.d.ts.map +1 -0
- package/dist/lib/native-capabilities/midi-ports.js +115 -0
- package/dist/lib/native-capabilities/midi-types.d.ts +25 -0
- package/dist/lib/native-capabilities/midi-types.d.ts.map +1 -0
- package/dist/lib/native-capabilities/midi-types.js +1 -0
- package/dist/lib/native-capabilities/midi.d.ts +6 -0
- package/dist/lib/native-capabilities/midi.d.ts.map +1 -0
- package/dist/lib/native-capabilities/midi.js +3 -0
- package/dist/lib/native-capabilities/native-device-io.d.ts +28 -0
- package/dist/lib/native-capabilities/native-device-io.d.ts.map +1 -0
- package/dist/lib/native-capabilities/native-device-io.js +91 -0
- package/dist/lib/native-capabilities/native-device-lifecycle.d.ts +13 -0
- package/dist/lib/native-capabilities/native-device-lifecycle.d.ts.map +1 -0
- package/dist/lib/native-capabilities/native-device-lifecycle.js +40 -0
- package/dist/lib/native-capabilities/notifications.d.ts +38 -0
- package/dist/lib/native-capabilities/notifications.d.ts.map +1 -0
- package/dist/lib/native-capabilities/notifications.js +50 -0
- package/dist/lib/native-capabilities/power-session.d.ts +113 -0
- package/dist/lib/native-capabilities/power-session.d.ts.map +1 -0
- package/dist/lib/native-capabilities/power-session.js +264 -0
- package/dist/lib/native-capabilities/secure-storage.d.ts +36 -0
- package/dist/lib/native-capabilities/secure-storage.d.ts.map +1 -0
- package/dist/lib/native-capabilities/secure-storage.js +64 -0
- package/dist/lib/native-capabilities/serial-native.d.ts +23 -0
- package/dist/lib/native-capabilities/serial-native.d.ts.map +1 -0
- package/dist/lib/native-capabilities/serial-native.js +181 -0
- package/dist/lib/native-capabilities/serial.d.ts +76 -0
- package/dist/lib/native-capabilities/serial.d.ts.map +1 -0
- package/dist/lib/native-capabilities/serial.js +215 -0
- package/dist/lib/native-capabilities/system-audio.d.ts +127 -0
- package/dist/lib/native-capabilities/system-audio.d.ts.map +1 -0
- package/dist/lib/native-capabilities/system-audio.js +330 -0
- package/dist/lib/native-capabilities/types.d.ts +62 -0
- package/dist/lib/native-capabilities/types.d.ts.map +1 -0
- package/dist/lib/native-capabilities/types.js +27 -0
- package/dist/lib/native-capabilities/usb-native.d.ts +39 -0
- package/dist/lib/native-capabilities/usb-native.d.ts.map +1 -0
- package/dist/lib/native-capabilities/usb-native.js +217 -0
- package/dist/lib/native-capabilities/usb.d.ts +85 -0
- package/dist/lib/native-capabilities/usb.d.ts.map +1 -0
- package/dist/lib/native-capabilities/usb.js +225 -0
- package/docs/README.md +37 -0
- package/docs/accessibility.md +32 -0
- package/docs/app-anatomy.md +72 -0
- package/docs/component-catalog.md +59 -0
- package/docs/component-guide-template.md +37 -0
- package/docs/design-tokens.md +172 -0
- package/docs/foundations.md +56 -0
- package/docs/native-integration.md +33 -0
- package/docs/standalone-app-windows.md +128 -0
- package/package.json +9 -3
- package/src/components/ui/alert.md +55 -0
- package/src/components/ui/app-frame.md +33 -0
- package/src/components/ui/badge.md +57 -0
- package/src/components/ui/button.md +76 -0
- package/src/components/ui/color-well.md +11 -0
- package/src/components/ui/combobox.md +43 -0
- package/src/components/ui/date-field.md +32 -0
- package/src/components/ui/edge-fade.md +7 -0
- package/src/components/ui/empty.md +82 -0
- package/src/components/ui/field.md +77 -0
- package/src/components/ui/grid.md +105 -0
- package/src/components/ui/icon-button.md +36 -0
- package/src/components/ui/inspector.md +11 -0
- package/src/components/ui/item.md +87 -0
- package/src/components/ui/list.md +107 -0
- package/src/components/ui/notification-dot.md +7 -0
- package/src/components/ui/number-input.md +19 -0
- package/src/components/ui/panel.md +11 -0
- package/src/components/ui/resizable.md +66 -0
- package/src/components/ui/scroll-area.md +68 -0
- package/src/components/ui/search-field.md +33 -0
- package/src/components/ui/segmented-control.md +39 -0
- package/src/components/ui/sidebar.md +113 -0
- package/src/components/ui/sonner.md +37 -0
- package/src/components/ui/split-view.md +15 -0
- package/src/components/ui/status.md +12 -0
- package/src/components/ui/table.md +35 -0
- package/src/components/ui/tabs.md +66 -0
- package/src/components/ui/text.md +17 -0
- package/src/components/ui/toggle-group.md +80 -0
- package/src/components/ui/toggle.md +73 -0
- package/src/components/ui/toolbar.md +21 -0
- package/src/styles/index.css +491 -3
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx,
|
|
3
|
-
import { AlertCircle,
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { AlertCircle, ChevronDown, ClipboardList, Code2, CornerDownRight, GripVertical, Image as ImageIcon, ListPlus, Loader2, Maximize2, Minimize2, Pencil, RotateCcw, Trash2, } from 'lucide-react';
|
|
4
4
|
import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
5
5
|
import { cn } from '../../lib/utils';
|
|
6
6
|
import { Button } from '../ui/button';
|
|
7
|
-
import {
|
|
7
|
+
import { Dialog, DialogContent, DialogTitle } from '../ui/dialog';
|
|
8
|
+
import { MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, useMessageScroller, useMessageScrollerVisibility, } from '../ui/message-scroller';
|
|
9
|
+
import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
|
|
8
10
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from '../ui/tooltip';
|
|
9
11
|
import { ChatInput, } from './chat-input';
|
|
10
|
-
import { CompactingMessage, ThinkingMessage, } from './chat-message';
|
|
12
|
+
import { CompactingMessage, ThinkingMessage, getChatMessageRenderKey, } from './chat-message';
|
|
11
13
|
import { MessageRow, computeIsThinking, } from './chat-messages';
|
|
12
|
-
import { ConversationHistory, } from './conversation-history';
|
|
14
|
+
import { ConversationHistory, ConversationSidebar, } from './conversation-history';
|
|
13
15
|
import { ModelEffortSelector, } from './model-effort-selector';
|
|
14
16
|
import { ToolApprovalProvider, } from './tool-approval-context';
|
|
15
17
|
import { ToolProgressProvider } from './tool-progress-context';
|
|
@@ -17,7 +19,6 @@ import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, us
|
|
|
17
19
|
import { SortableContext, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable';
|
|
18
20
|
import { CSS } from '@dnd-kit/utilities';
|
|
19
21
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
20
|
-
import { Virtualizer } from 'virtua';
|
|
21
22
|
const CODEX_OAUTH_ERROR_PATTERNS = [
|
|
22
23
|
'codex oauth',
|
|
23
24
|
'codex-oauth',
|
|
@@ -34,18 +35,26 @@ const MISSING_API_KEY_ERROR_PATTERNS = [
|
|
|
34
35
|
'credential required in vault',
|
|
35
36
|
'credential not configured in vault',
|
|
36
37
|
];
|
|
38
|
+
function isToastInteractionTarget(target) {
|
|
39
|
+
return (target instanceof Element &&
|
|
40
|
+
target.closest('[data-sonner-toaster], [data-sonner-toast]') !== null);
|
|
41
|
+
}
|
|
37
42
|
const AUTH_PROMPT_COPY = {
|
|
38
43
|
'missing-api-key': {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
action: 'Add API key',
|
|
44
|
+
label: 'Sign in with your ChatGPT account to chat with AI',
|
|
45
|
+
action: 'Connect ChatGPT',
|
|
42
46
|
},
|
|
43
47
|
'codex-oauth-expired': {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
action: 'Reconnect OpenAI Codex',
|
|
48
|
+
label: 'Sign in again to refresh your ChatGPT connection',
|
|
49
|
+
action: 'Reconnect ChatGPT',
|
|
47
50
|
},
|
|
48
51
|
};
|
|
52
|
+
export function getChatAuthPromptCopy(issue) {
|
|
53
|
+
return AUTH_PROMPT_COPY[issue];
|
|
54
|
+
}
|
|
55
|
+
function ChatAuthPrompt({ copy, isConnecting, onConnect, onAdvancedSetup, }) {
|
|
56
|
+
return (_jsxs("div", { className: "flex flex-col items-center gap-2 py-3 text-center", "data-chat-auth-prompt": true, children: [_jsx("p", { className: "text-muted-foreground max-w-sm text-sm", children: copy.label }), onConnect && (_jsx(Button, { onClick: onConnect, size: "sm", className: "cursor-pointer", disabled: isConnecting, children: isConnecting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 size-4 animate-spin" }), "Waiting for ChatGPT..."] })) : (copy.action) })), onAdvancedSetup && (_jsx(Button, { variant: "ghost", size: "sm", className: "text-muted-foreground hover:text-foreground h-auto cursor-pointer px-2 py-1 text-xs font-normal", onClick: onAdvancedSetup, disabled: isConnecting, children: "Advanced setup" }))] }));
|
|
57
|
+
}
|
|
49
58
|
function messageIncludesAny(message, patterns) {
|
|
50
59
|
const normalized = message.toLowerCase();
|
|
51
60
|
return patterns.some((pattern) => normalized.includes(pattern));
|
|
@@ -64,6 +73,85 @@ export function resolveChatAuthIssue({ missingApiKey, authIssue, error, }) {
|
|
|
64
73
|
}
|
|
65
74
|
return null;
|
|
66
75
|
}
|
|
76
|
+
export function hasPersistedChatError(messages) {
|
|
77
|
+
const lastMessage = messages.at(-1);
|
|
78
|
+
return Boolean(lastMessage?.parts?.some((part) => part.type === 'error'));
|
|
79
|
+
}
|
|
80
|
+
export function getPrependPreservedScrollTop(previousScrollTop, previousScrollHeight, nextScrollHeight) {
|
|
81
|
+
return (previousScrollTop + Math.max(0, nextScrollHeight - previousScrollHeight));
|
|
82
|
+
}
|
|
83
|
+
function MessageScrollerCommandSync({ signal }) {
|
|
84
|
+
const { scrollToEnd } = useMessageScroller();
|
|
85
|
+
const previousSignalRef = useRef(signal);
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (previousSignalRef.current === signal)
|
|
88
|
+
return;
|
|
89
|
+
previousSignalRef.current = signal;
|
|
90
|
+
scrollToEnd({ behavior: 'auto' });
|
|
91
|
+
}, [scrollToEnd, signal]);
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
function getNavigationLabel(message) {
|
|
95
|
+
const text = message.content ??
|
|
96
|
+
message.parts
|
|
97
|
+
?.flatMap((part) => (part.type === 'text' ? [part.text] : []))
|
|
98
|
+
.join(' ');
|
|
99
|
+
const normalized = text?.replace(/\s+/g, ' ').trim() || 'User message';
|
|
100
|
+
return normalized.length > 56 ? `${normalized.slice(0, 53)}...` : normalized;
|
|
101
|
+
}
|
|
102
|
+
function MessageNavigationTrail({ items }) {
|
|
103
|
+
const { scrollToMessage } = useMessageScroller();
|
|
104
|
+
const { currentAnchorId } = useMessageScrollerVisibility();
|
|
105
|
+
const anchors = useMemo(() => items.flatMap((item) => item.kind === 'message' && item.message.role === 'user'
|
|
106
|
+
? [{ id: item.key, label: getNavigationLabel(item.message) }]
|
|
107
|
+
: []), [items]);
|
|
108
|
+
if (anchors.length < 2)
|
|
109
|
+
return null;
|
|
110
|
+
return (_jsx("div", { "data-fullscreen-message-navigation": true, className: "absolute bottom-8 left-3 top-8 z-20 flex w-9 items-center", children: _jsx(TooltipProvider, { delayDuration: 250, children: _jsx("nav", { "aria-label": "Conversation turns", className: "flex max-h-full w-full flex-col items-start overflow-y-auto py-2 [scrollbar-width:none]", children: _jsx("div", { "data-message-navigation-list": true, className: "my-auto flex w-full shrink-0 flex-col items-start", children: anchors.map((anchor) => {
|
|
111
|
+
const isCurrent = anchor.id === currentAnchorId;
|
|
112
|
+
return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-current": isCurrent ? 'location' : undefined, "aria-label": `Jump to: ${anchor.label}`, onClick: () => scrollToMessage(anchor.id, {
|
|
113
|
+
align: 'start',
|
|
114
|
+
behavior: 'smooth',
|
|
115
|
+
scrollMargin: 64,
|
|
116
|
+
}), "data-message-navigation-row": true, className: "flex h-2.5 w-9 shrink-0 cursor-pointer items-center outline-none", children: _jsx("span", { className: "flex h-0.5 w-[30px] items-center", children: _jsx("span", { "data-message-navigation-marker": true, className: cn('bg-muted-foreground h-0.5 w-[26px] origin-left rounded-full opacity-40', isCurrent && 'bg-foreground opacity-60') }) }) }) }), _jsx(TooltipContent, { side: "right", className: "max-w-72", children: anchor.label })] }, anchor.id));
|
|
117
|
+
}) }) }) }) }));
|
|
118
|
+
}
|
|
119
|
+
function ChatMessageViewport({ items, renderItem, toolProgress, onApprovalResponse, currentConversationId, scrollToBottomSignal, isBusy, hasOlderMessages = false, isLoadingOlderMessages = false, onLoadOlderMessages, showNavigationTrail = false, scrollAreaClassName, contentClassName, scrollButtonClassName, }) {
|
|
120
|
+
const viewportRef = useRef(null);
|
|
121
|
+
const loadingOlderRef = useRef(false);
|
|
122
|
+
const handleViewportScroll = useCallback((event) => {
|
|
123
|
+
const viewport = event.currentTarget;
|
|
124
|
+
if (viewport.scrollTop > 64 ||
|
|
125
|
+
!hasOlderMessages ||
|
|
126
|
+
isLoadingOlderMessages ||
|
|
127
|
+
loadingOlderRef.current ||
|
|
128
|
+
!onLoadOlderMessages) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
loadingOlderRef.current = true;
|
|
132
|
+
const previousScrollHeight = viewport.scrollHeight;
|
|
133
|
+
const previousScrollTop = viewport.scrollTop;
|
|
134
|
+
void onLoadOlderMessages()
|
|
135
|
+
.then((outcome) => {
|
|
136
|
+
window.requestAnimationFrame(() => {
|
|
137
|
+
if (viewportRef.current !== viewport)
|
|
138
|
+
return;
|
|
139
|
+
if (outcome === 'reset') {
|
|
140
|
+
viewport.scrollTop = viewport.scrollHeight;
|
|
141
|
+
}
|
|
142
|
+
else if (outcome === 'prepended') {
|
|
143
|
+
viewport.scrollTop = getPrependPreservedScrollTop(previousScrollTop, previousScrollHeight, viewport.scrollHeight);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
})
|
|
147
|
+
.finally(() => {
|
|
148
|
+
window.requestAnimationFrame(() => {
|
|
149
|
+
loadingOlderRef.current = false;
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
}, [hasOlderMessages, isLoadingOlderMessages, onLoadOlderMessages]);
|
|
153
|
+
return (_jsx(MessageScrollerProvider, { autoScroll: true, defaultScrollPosition: "end", scrollPreviousItemPeek: 64, children: _jsxs(MessageScroller, { className: "relative min-h-0 min-w-0 flex-1", children: [_jsx(MessageScrollerCommandSync, { signal: scrollToBottomSignal }), _jsx(MessageScrollerViewport, { ref: viewportRef, className: scrollAreaClassName, "data-message-scroll-fade": true, "data-has-older-messages": hasOlderMessages ? 'true' : 'false', onScroll: handleViewportScroll, children: _jsx(MessageScrollerContent, { "aria-busy": isBusy || isLoadingOlderMessages, className: contentClassName, children: _jsx(ToolProgressProvider, { value: toolProgress, children: _jsx(ToolApprovalProvider, { onApprovalResponse: onApprovalResponse ?? null, children: items.map((item) => (_jsx(MessageScrollerItem, { messageId: item.key, scrollAnchor: item.kind === 'message' && item.message.role === 'user', children: renderItem(item) }, item.key))) }) }) }) }), items.length > 0 && (_jsx(MessageScrollerButton, { className: scrollButtonClassName })), showNavigationTrail && _jsx(MessageNavigationTrail, { items: items })] }) }, currentConversationId ?? 'new-conversation'));
|
|
154
|
+
}
|
|
67
155
|
function clampPercent(value) {
|
|
68
156
|
if (!Number.isFinite(value))
|
|
69
157
|
return 0;
|
|
@@ -77,7 +165,16 @@ function formatTokenCount(tokens) {
|
|
|
77
165
|
const millions = tokens / 1_000_000;
|
|
78
166
|
return `${Number.isInteger(millions) ? millions.toFixed(0) : millions.toFixed(2)}M`;
|
|
79
167
|
}
|
|
80
|
-
function
|
|
168
|
+
function formatUsageReset(resetAt) {
|
|
169
|
+
if (!resetAt)
|
|
170
|
+
return null;
|
|
171
|
+
return new Intl.DateTimeFormat(undefined, {
|
|
172
|
+
weekday: 'short',
|
|
173
|
+
hour: 'numeric',
|
|
174
|
+
minute: '2-digit',
|
|
175
|
+
}).format(new Date(resetAt * 1_000));
|
|
176
|
+
}
|
|
177
|
+
function ContextWindowIndicator({ usage, planUsage, }) {
|
|
81
178
|
if (!usage || usage.maxTokens <= 0)
|
|
82
179
|
return null;
|
|
83
180
|
const usedPercent = clampPercent(Math.round((usage.usedTokens / usage.maxTokens) * 100));
|
|
@@ -86,9 +183,15 @@ function ContextWindowIndicator({ usage }) {
|
|
|
86
183
|
: usedPercent >= 75
|
|
87
184
|
? 'var(--warning)'
|
|
88
185
|
: 'var(--muted-foreground)';
|
|
89
|
-
return (_jsxs(
|
|
186
|
+
return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "text-muted-foreground hover:text-foreground focus-visible:ring-ring flex size-8 cursor-pointer items-center justify-center rounded-full bg-transparent p-0 focus-visible:outline-none focus-visible:ring-2", "aria-label": `Context window ${usedPercent}% full`, children: _jsx("span", { className: "relative size-4 rounded-full", style: {
|
|
90
187
|
background: `conic-gradient(${ringColor} ${usedPercent}%, color-mix(in oklch, var(--muted-foreground) 22%, transparent) 0)`,
|
|
91
|
-
}, children: _jsx("span", { className: "bg-background absolute inset-[3px] rounded-full" }) }) }) }), _jsxs(
|
|
188
|
+
}, children: _jsx("span", { className: "bg-background absolute inset-[3px] rounded-full" }) }) }) }), _jsxs(PopoverContent, { align: "end", side: "top", sideOffset: 8, className: "w-80 p-3 shadow-lg", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Context window" }), _jsxs("span", { children: [formatTokenCount(usage.usedTokens), " /", ' ', formatTokenCount(usage.maxTokens), " (", usedPercent, "%)"] })] }), _jsx("div", { className: "bg-muted mt-2 h-1.5 overflow-hidden rounded-full", children: _jsx("div", { className: "bg-primary h-full rounded-full", style: { width: `${usedPercent}%` } }) }), usage.compactsAutomatically && (_jsx("div", { className: "text-muted-foreground mt-2 text-[11px] leading-4", children: "Moldable automatically compacts its context" })), planUsage && planUsage.windows.length > 0 && (_jsxs("div", { className: "border-border mt-3 flex flex-col gap-3 border-t pt-3", children: [_jsxs("div", { children: [_jsxs("div", { className: "text-muted-foreground text-xs", children: ["Plan usage limits", planUsage.planLabel ? ` · ${planUsage.planLabel}` : ''] }), planUsage.accountLabel && (_jsx("div", { className: "mt-0.5 truncate text-xs font-medium", children: planUsage.accountLabel }))] }), planUsage.windows.map((window) => {
|
|
189
|
+
const reset = formatUsageReset(window.resetAt);
|
|
190
|
+
const percent = clampPercent(window.usedPercent);
|
|
191
|
+
return (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-xs", children: [_jsx("span", { children: window.label }), _jsxs("span", { className: "text-muted-foreground", children: [reset ? `Resets ${reset} · ` : '', percent, "%"] })] }), _jsx("div", { className: "bg-muted h-1.5 overflow-hidden rounded-full", children: _jsx("div", { className: percent >= 90
|
|
192
|
+
? 'bg-destructive h-full rounded-full'
|
|
193
|
+
: 'bg-primary h-full rounded-full', style: { width: `${percent}%` } }) })] }, window.label));
|
|
194
|
+
})] }))] })] }));
|
|
92
195
|
}
|
|
93
196
|
function ContextCompactedDivider() {
|
|
94
197
|
return (_jsx("div", { "data-testid": "context-compacted-divider", className: "text-muted-foreground/80 w-full px-4 py-2", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "bg-border h-px min-w-8 flex-1" }), _jsxs("div", { className: "flex select-none items-center gap-2 whitespace-nowrap text-[13px] font-medium leading-5", children: [_jsx(ClipboardList, { className: "size-4" }), _jsx("span", { children: "Context automatically compacted" })] }), _jsx("div", { className: "bg-border h-px min-w-8 flex-1" })] }) }));
|
|
@@ -118,19 +221,10 @@ function QueuedMessageRow({ message, isResponding, onRetryQueuedMessage, onSteer
|
|
|
118
221
|
/**
|
|
119
222
|
* Floating chat panel with model selector
|
|
120
223
|
*/
|
|
121
|
-
export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChange, onSubmit, onStop, onNewChat, modelProviders, modelEffortPresets, selectedModel, selectedReasoningEffort, onModelEffortChange, conversations, currentConversationId, scrollToBottomSignal = 0, onSelectConversation,
|
|
224
|
+
export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChange, onSubmit, onStop, onNewChat, modelProviders, modelEffortPresets, selectedModel, selectedReasoningEffort, onModelEffortChange, conversations, currentConversationId, currentAppId, hasMoreConversations = false, isLoadingMoreConversations = false, onLoadMoreConversations, onResolveMessageContent, scrollToBottomSignal = 0, hasOlderMessages = false, isLoadingOlderMessages = false, onLoadOlderMessages, onSelectConversation, onArchiveConversation, onArchiveConversationGroup, placeholder = 'Ask anything...', welcomeMessage, isExpanded, onExpandedChange, isFullScreen = false, onFullScreenChange, isMinimized = false, onMinimizedChange, className, error, onRetryError, missingApiKey, authIssue, onConnectChatGPT, onAdvancedSetup, toolProgress = {}, onApprovalResponse, isEditingApp = true, onEditingAppChange, showEditingAppToggle = false, checkpoints, restoringMessageId, onRestoreCheckpoint, imageAttachments = [], onRemoveImageAttachment, isImageDropActive = false, queuedMessages = [], onRemoveQueuedMessage, onRetryQueuedMessage, onSteerQueuedMessage, onReorderQueuedMessages, onEditQueuedMessage, slashCommands, onSlashCommandSelect, isCompacting = false, compactedHistoryStartIndex, contextUsage, planUsage, }) {
|
|
122
225
|
const inputRef = useRef(null);
|
|
123
|
-
const
|
|
124
|
-
const
|
|
125
|
-
const virtualizerRef = useRef(null);
|
|
126
|
-
const prevMessageCountRef = useRef(messages.length);
|
|
127
|
-
const prevConversationIdRef = useRef(currentConversationId ?? null);
|
|
128
|
-
const prevScrollToBottomSignalRef = useRef(scrollToBottomSignal);
|
|
129
|
-
const pendingConversationScrollIdRef = useRef(null);
|
|
130
|
-
const hasPendingScrollToBottomSignalRef = useRef(false);
|
|
131
|
-
const scrollRafRef = useRef(null);
|
|
132
|
-
const [viewportVersion, setViewportVersion] = useState(0);
|
|
133
|
-
const [isAtBottom, setIsAtBottom] = useState(true);
|
|
226
|
+
const fullScreenTriggerRef = useRef(null);
|
|
227
|
+
const [isConnectingChatGPT, setIsConnectingChatGPT] = useState(false);
|
|
134
228
|
const queuedMessageIds = useMemo(() => queuedMessages.map((message) => message.id), [queuedMessages]);
|
|
135
229
|
const queueSensors = useSensors(useSensor(PointerSensor, {
|
|
136
230
|
activationConstraint: {
|
|
@@ -141,59 +235,31 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
|
|
|
141
235
|
}));
|
|
142
236
|
const isResponding = status === 'streaming' || status === 'submitted';
|
|
143
237
|
const controlsDisabled = isTurnInFlight ?? isResponding;
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
useEffect(() => {
|
|
147
|
-
const scrollArea = scrollAreaRef.current;
|
|
148
|
-
if (!scrollArea)
|
|
149
|
-
return;
|
|
150
|
-
const viewport = scrollArea.querySelector('[data-radix-scroll-area-viewport]');
|
|
151
|
-
if (!viewport)
|
|
152
|
-
return;
|
|
153
|
-
viewport.style.overflowAnchor = 'none';
|
|
154
|
-
if (viewportRef.current !== viewport) {
|
|
155
|
-
viewportRef.current = viewport;
|
|
156
|
-
setViewportVersion((version) => version + 1);
|
|
157
|
-
}
|
|
158
|
-
}, [isExpanded]);
|
|
159
|
-
// Track scroll position to detect if user is at bottom
|
|
160
|
-
useEffect(() => {
|
|
161
|
-
const viewport = viewportRef.current;
|
|
162
|
-
if (!viewport)
|
|
163
|
-
return;
|
|
164
|
-
const handleScroll = () => {
|
|
165
|
-
const { scrollTop, scrollHeight, clientHeight } = viewport;
|
|
166
|
-
// Consider "at bottom" if within 50px of the bottom
|
|
167
|
-
const atBottom = scrollHeight - scrollTop - clientHeight < 50;
|
|
168
|
-
setIsAtBottom(atBottom);
|
|
169
|
-
};
|
|
170
|
-
handleScroll();
|
|
171
|
-
viewport.addEventListener('scroll', handleScroll);
|
|
172
|
-
return () => viewport.removeEventListener('scroll', handleScroll);
|
|
173
|
-
}, [viewportVersion]);
|
|
238
|
+
const isChatOpen = isExpanded || isFullScreen;
|
|
239
|
+
const composerControls = (_jsxs(_Fragment, { children: [_jsx(ContextWindowIndicator, { usage: contextUsage, planUsage: planUsage }), modelProviders.length > 0 && modelEffortPresets.length > 0 ? (_jsx(ModelEffortSelector, { providers: modelProviders, presets: modelEffortPresets, selectedModel: selectedModel, selectedReasoningEffort: selectedReasoningEffort, onSelectionChange: onModelEffortChange, disabled: controlsDisabled })) : null] }));
|
|
174
240
|
// Focus input when expanded
|
|
175
241
|
useEffect(() => {
|
|
176
|
-
if (
|
|
242
|
+
if (isChatOpen) {
|
|
177
243
|
const timer = setTimeout(() => {
|
|
178
244
|
inputRef.current?.focus();
|
|
179
245
|
}, 200);
|
|
180
246
|
return () => clearTimeout(timer);
|
|
181
247
|
}
|
|
182
|
-
}, [
|
|
248
|
+
}, [isChatOpen]);
|
|
183
249
|
const resolvedAuthIssue = resolveChatAuthIssue({
|
|
184
250
|
missingApiKey,
|
|
185
251
|
authIssue,
|
|
186
252
|
error,
|
|
187
253
|
});
|
|
188
254
|
const authPromptCopy = resolvedAuthIssue
|
|
189
|
-
?
|
|
255
|
+
? getChatAuthPromptCopy(resolvedAuthIssue)
|
|
190
256
|
: null;
|
|
191
257
|
const showAuthPrompt = Boolean(resolvedAuthIssue);
|
|
192
258
|
const submitDisabled = showAuthPrompt;
|
|
193
259
|
const handleSubmit = useCallback((e, mode) => {
|
|
194
260
|
e?.preventDefault();
|
|
195
261
|
if (submitDisabled) {
|
|
196
|
-
if (!
|
|
262
|
+
if (!isChatOpen) {
|
|
197
263
|
onExpandedChange(true);
|
|
198
264
|
}
|
|
199
265
|
return;
|
|
@@ -201,17 +267,15 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
|
|
|
201
267
|
if (!input.trim() && imageAttachments.length === 0)
|
|
202
268
|
return;
|
|
203
269
|
const submitMode = mode ?? (isResponding ? 'queue' : 'send');
|
|
204
|
-
if (!
|
|
270
|
+
if (!isChatOpen) {
|
|
205
271
|
onExpandedChange(true);
|
|
206
272
|
}
|
|
207
|
-
// Reset to bottom when user sends a message
|
|
208
|
-
setIsAtBottom(true);
|
|
209
273
|
onSubmit(e, submitMode);
|
|
210
274
|
}, [
|
|
211
275
|
imageAttachments.length,
|
|
212
276
|
input,
|
|
213
277
|
isResponding,
|
|
214
|
-
|
|
278
|
+
isChatOpen,
|
|
215
279
|
onExpandedChange,
|
|
216
280
|
onSubmit,
|
|
217
281
|
submitDisabled,
|
|
@@ -224,50 +288,79 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
|
|
|
224
288
|
}, [onReorderQueuedMessages]);
|
|
225
289
|
const handleEditQueuedMessage = useCallback((id) => {
|
|
226
290
|
onEditQueuedMessage?.(id);
|
|
227
|
-
if (!
|
|
291
|
+
if (!isChatOpen) {
|
|
228
292
|
onExpandedChange(true);
|
|
229
293
|
}
|
|
230
294
|
window.setTimeout(() => inputRef.current?.focus(), 0);
|
|
231
|
-
}, [
|
|
295
|
+
}, [isChatOpen, onEditQueuedMessage, onExpandedChange]);
|
|
232
296
|
const handleNewChat = useCallback(() => {
|
|
233
297
|
onNewChat?.();
|
|
234
298
|
inputRef.current?.focus();
|
|
235
299
|
}, [onNewChat]);
|
|
300
|
+
const handleConnectChatGPT = useCallback(async () => {
|
|
301
|
+
if (!onConnectChatGPT || isConnectingChatGPT)
|
|
302
|
+
return;
|
|
303
|
+
setIsConnectingChatGPT(true);
|
|
304
|
+
try {
|
|
305
|
+
await onConnectChatGPT();
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
console.error('Failed to connect ChatGPT:', error);
|
|
309
|
+
}
|
|
310
|
+
finally {
|
|
311
|
+
setIsConnectingChatGPT(false);
|
|
312
|
+
}
|
|
313
|
+
}, [isConnectingChatGPT, onConnectChatGPT]);
|
|
314
|
+
const editingAppControl = showEditingAppToggle && onEditingAppChange ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: (event) => {
|
|
315
|
+
event.preventDefault();
|
|
316
|
+
onEditingAppChange(!isEditingApp);
|
|
317
|
+
}, className: cn('cursor-pointer', isEditingApp
|
|
318
|
+
? 'text-primary bg-primary/10 hover:bg-primary/20'
|
|
319
|
+
: 'text-muted-foreground hover:text-foreground'), children: _jsx(Code2, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "top", children: _jsx("p", { children: isEditingApp
|
|
320
|
+
? 'Editing this app (click to disable)'
|
|
321
|
+
: 'Not editing app (click to enable)' }) })] }) })) : null;
|
|
236
322
|
const composerStartControls = (_jsxs(_Fragment, { children: [conversations &&
|
|
237
323
|
(conversations.length > 0 || onNewChat) &&
|
|
238
|
-
onSelectConversation && (_jsx(ConversationHistory, { conversations: conversations, currentConversationId: currentConversationId, onSelect: onSelectConversation,
|
|
239
|
-
event.preventDefault();
|
|
240
|
-
onEditingAppChange(!isEditingApp);
|
|
241
|
-
}, className: cn('cursor-pointer', isEditingApp
|
|
242
|
-
? 'text-primary bg-primary/10 hover:bg-primary/20'
|
|
243
|
-
: 'text-muted-foreground hover:text-foreground'), children: _jsx(Code2, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "top", children: _jsx("p", { children: isEditingApp
|
|
244
|
-
? 'Editing this app (click to disable)'
|
|
245
|
-
: 'Not editing app (click to enable)' }) })] }) }))] }));
|
|
324
|
+
onSelectConversation && (_jsx(ConversationHistory, { conversations: conversations, currentConversationId: currentConversationId, currentAppId: currentAppId, onSelect: onSelectConversation, onArchive: onArchiveConversation, onArchiveGroup: onArchiveConversationGroup, onNewChat: handleNewChat, newChatDisabled: false, disabled: false, dropdownAlign: "start", dropdownSide: "top", tooltipSide: "top", hasMoreConversations: hasMoreConversations, isLoadingMoreConversations: isLoadingMoreConversations, onLoadMoreConversations: onLoadMoreConversations })), editingAppControl] }));
|
|
246
325
|
// Keyboard shortcut: Cmd+Shift+O for new chat
|
|
247
326
|
useEffect(() => {
|
|
248
327
|
const handleKeyDown = (e) => {
|
|
249
328
|
if (e.key === 'o' && e.metaKey && e.shiftKey) {
|
|
250
329
|
e.preventDefault();
|
|
251
330
|
// Only create new chat if conversation controls are currently available.
|
|
252
|
-
if (
|
|
331
|
+
if (isChatOpen) {
|
|
253
332
|
handleNewChat();
|
|
254
333
|
}
|
|
255
334
|
}
|
|
256
335
|
};
|
|
257
336
|
document.addEventListener('keydown', handleKeyDown);
|
|
258
337
|
return () => document.removeEventListener('keydown', handleKeyDown);
|
|
259
|
-
}, [
|
|
338
|
+
}, [isChatOpen, handleNewChat]);
|
|
260
339
|
// Handle minimize button - now goes to minimized state
|
|
261
340
|
const handleMinimize = useCallback(() => {
|
|
341
|
+
if (isFullScreen) {
|
|
342
|
+
onFullScreenChange?.(false);
|
|
343
|
+
}
|
|
262
344
|
if (isExpanded) {
|
|
263
345
|
onExpandedChange(false);
|
|
264
346
|
}
|
|
265
347
|
onMinimizedChange?.(true);
|
|
266
|
-
}, [
|
|
348
|
+
}, [
|
|
349
|
+
isExpanded,
|
|
350
|
+
isFullScreen,
|
|
351
|
+
onExpandedChange,
|
|
352
|
+
onFullScreenChange,
|
|
353
|
+
onMinimizedChange,
|
|
354
|
+
]);
|
|
267
355
|
const isStreaming = status === 'streaming' || status === 'submitted';
|
|
268
356
|
const isThinking = useMemo(() => computeIsThinking(messages, status), [messages, status]);
|
|
269
|
-
const showErrorMessage = Boolean(error) &&
|
|
270
|
-
|
|
357
|
+
const showErrorMessage = Boolean(error) &&
|
|
358
|
+
status === 'error' &&
|
|
359
|
+
!showAuthPrompt &&
|
|
360
|
+
!hasPersistedChatError(messages);
|
|
361
|
+
const lastMessageKey = messages.length > 0
|
|
362
|
+
? getChatMessageRenderKey(messages[messages.length - 1], messages.length - 1)
|
|
363
|
+
: null;
|
|
271
364
|
const listItems = useMemo(() => {
|
|
272
365
|
const items = [];
|
|
273
366
|
if (messages.length === 0 && welcomeMessage) {
|
|
@@ -283,7 +376,11 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
|
|
|
283
376
|
kind: 'context-compacted-divider',
|
|
284
377
|
});
|
|
285
378
|
}
|
|
286
|
-
items.push({
|
|
379
|
+
items.push({
|
|
380
|
+
key: getChatMessageRenderKey(message, index),
|
|
381
|
+
kind: 'message',
|
|
382
|
+
message,
|
|
383
|
+
});
|
|
287
384
|
}
|
|
288
385
|
if (isThinking && !isCompacting) {
|
|
289
386
|
items.push({ key: 'thinking', kind: 'thinking' });
|
|
@@ -291,9 +388,6 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
|
|
|
291
388
|
if (isCompacting) {
|
|
292
389
|
items.push({ key: 'compacting', kind: 'compacting' });
|
|
293
390
|
}
|
|
294
|
-
if (showAuthPrompt) {
|
|
295
|
-
items.push({ key: 'auth-prompt', kind: 'auth-prompt' });
|
|
296
|
-
}
|
|
297
391
|
if (showErrorMessage) {
|
|
298
392
|
items.push({ key: 'error', kind: 'error' });
|
|
299
393
|
}
|
|
@@ -304,7 +398,6 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
|
|
|
304
398
|
compactedHistoryStartIndex,
|
|
305
399
|
messages,
|
|
306
400
|
showErrorMessage,
|
|
307
|
-
showAuthPrompt,
|
|
308
401
|
welcomeMessage,
|
|
309
402
|
]);
|
|
310
403
|
const renderVirtualItem = useCallback((item) => {
|
|
@@ -315,99 +408,43 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
|
|
|
315
408
|
return (_jsx("div", { className: "px-2 pb-3", children: _jsx(ContextCompactedDivider, {}) }));
|
|
316
409
|
case 'message': {
|
|
317
410
|
const checkpoint = checkpoints?.get(item.message.id);
|
|
318
|
-
return (_jsx("div", { className: "px-2 pb-3", children: _jsx(MessageRow, { message: item.message, isLast: item.
|
|
411
|
+
return (_jsx("div", { className: "px-2 pb-3", children: _jsx(MessageRow, { message: item.message, isLast: item.key === lastMessageKey, isStreaming: isStreaming, checkpoint: checkpoint, restoringMessageId: restoringMessageId, onRestoreCheckpoint: onRestoreCheckpoint, onResolveMessageContent: onResolveMessageContent, onRetryError: item.key === lastMessageKey ? onRetryError : undefined }) }));
|
|
319
412
|
}
|
|
320
413
|
case 'thinking':
|
|
321
414
|
return (_jsx("div", { className: "px-2 pb-3", children: _jsx(ThinkingMessage, {}) }));
|
|
322
415
|
case 'compacting':
|
|
323
416
|
return (_jsx("div", { className: "px-2 pb-3", children: _jsx(CompactingMessage, {}) }));
|
|
324
|
-
case 'auth-prompt':
|
|
325
|
-
if (resolvedAuthIssue === 'codex-oauth-expired') {
|
|
326
|
-
return (_jsx("div", { className: "px-2 pb-4", children: _jsxs("div", { className: "bg-muted/30 mx-2 flex flex-col gap-3 rounded-lg p-4", children: [_jsx("div", { className: "flex items-start justify-between gap-3", children: _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium", children: authPromptCopy?.title ?? 'Refresh OpenAI Codex auth' }), _jsx("p", { className: "text-muted-foreground text-xs", children: authPromptCopy?.description ??
|
|
327
|
-
'Open Settings > API Keys and reconnect OpenAI Codex.' })] }) }), onAddApiKey && (_jsxs(Button, { variant: "outline", className: "w-full cursor-pointer", onClick: onAddApiKey, children: [_jsx(ExternalLink, { className: "mr-2 size-4" }), authPromptCopy?.action ?? 'Reconnect OpenAI Codex'] }))] }) }));
|
|
328
|
-
}
|
|
329
|
-
return (_jsx("div", { className: "px-2 pb-4", children: _jsxs("div", { className: "border-primary/30 bg-primary/5 mx-2 flex flex-col items-center gap-3 rounded-lg border p-4 text-center", children: [_jsx("div", { className: "bg-primary/10 flex size-10 items-center justify-center rounded-full", children: _jsx(AlertCircle, { className: "text-primary size-5" }) }), _jsxs("div", { className: "max-w-sm", children: [_jsx("p", { className: "text-foreground font-medium", children: authPromptCopy?.title ?? 'Authentication required' }), _jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: authPromptCopy?.description ??
|
|
330
|
-
'Open settings to configure chat authentication.' })] }), onAddApiKey && (_jsx(Button, { onClick: onAddApiKey, size: "sm", className: "cursor-pointer", children: authPromptCopy?.action ?? 'Open settings' }))] }) }));
|
|
331
417
|
case 'error':
|
|
332
|
-
return (_jsx("div", { className: "px-2 pb-4", children: error && (_jsxs("div", { className: "border-destructive/30 bg-destructive/10 text-destructive mx-2 flex items-start gap-2 rounded-lg border p-3 text-sm", children: [_jsx(AlertCircle, { className: "mt-0.5 size-4 shrink-0" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "font-medium", children: "Request failed" }), _jsx("p", { className: "text-destructive/80 mt-0.5 break-words", children: error.message || 'An unknown error occurred' })] })] })) }));
|
|
418
|
+
return (_jsx("div", { className: "px-2 pb-4", children: error && (_jsxs("div", { className: "border-destructive/30 bg-destructive/10 text-destructive mx-2 flex items-start gap-2 rounded-lg border p-3 text-sm", children: [_jsx(AlertCircle, { className: "mt-0.5 size-4 shrink-0" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "font-medium", children: "Request failed" }), _jsx("p", { className: "text-destructive/80 mt-0.5 break-words", children: error.message || 'An unknown error occurred' }), onRetryError && (_jsxs("button", { type: "button", onClick: onRetryError, className: "border-destructive/30 hover:bg-destructive/10 mt-2 inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md border px-2.5 text-xs font-medium transition-colors", children: [_jsx(RotateCcw, { className: "size-3.5" }), "Retry"] }))] })] })) }));
|
|
333
419
|
}
|
|
334
420
|
}, [
|
|
335
421
|
checkpoints,
|
|
336
422
|
error,
|
|
337
|
-
authPromptCopy,
|
|
338
|
-
resolvedAuthIssue,
|
|
339
423
|
isStreaming,
|
|
340
|
-
|
|
424
|
+
lastMessageKey,
|
|
341
425
|
messages.length,
|
|
342
|
-
onAddApiKey,
|
|
343
426
|
onRestoreCheckpoint,
|
|
427
|
+
onResolveMessageContent,
|
|
428
|
+
onRetryError,
|
|
344
429
|
restoringMessageId,
|
|
345
430
|
welcomeMessage,
|
|
346
431
|
]);
|
|
347
|
-
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
}
|
|
363
|
-
// New conversations loaded from history should start at the latest message.
|
|
364
|
-
useEffect(() => {
|
|
365
|
-
const previousConversationId = prevConversationIdRef.current;
|
|
366
|
-
const nextConversationId = currentConversationId ?? null;
|
|
367
|
-
prevConversationIdRef.current = nextConversationId;
|
|
368
|
-
if (previousConversationId !== nextConversationId) {
|
|
369
|
-
pendingConversationScrollIdRef.current = nextConversationId;
|
|
370
|
-
setIsAtBottom(true);
|
|
371
|
-
}
|
|
372
|
-
if (!nextConversationId ||
|
|
373
|
-
pendingConversationScrollIdRef.current !== nextConversationId ||
|
|
374
|
-
!isExpanded ||
|
|
375
|
-
listItems.length === 0) {
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
scrollToBottom(false);
|
|
379
|
-
pendingConversationScrollIdRef.current = null;
|
|
380
|
-
}, [currentConversationId, isExpanded, listItems.length, scrollToBottom]);
|
|
381
|
-
useEffect(() => {
|
|
382
|
-
if (prevScrollToBottomSignalRef.current !== scrollToBottomSignal) {
|
|
383
|
-
prevScrollToBottomSignalRef.current = scrollToBottomSignal;
|
|
384
|
-
hasPendingScrollToBottomSignalRef.current = true;
|
|
385
|
-
setIsAtBottom(true);
|
|
386
|
-
}
|
|
387
|
-
if (!hasPendingScrollToBottomSignalRef.current ||
|
|
388
|
-
!isExpanded ||
|
|
389
|
-
listItems.length === 0) {
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
scrollToBottom(false);
|
|
393
|
-
hasPendingScrollToBottomSignalRef.current = false;
|
|
394
|
-
}, [isExpanded, listItems.length, scrollToBottom, scrollToBottomSignal]);
|
|
395
|
-
// Scroll to bottom on new messages if the user is already at bottom
|
|
396
|
-
useEffect(() => {
|
|
397
|
-
const previousMessageCount = prevMessageCountRef.current;
|
|
398
|
-
const hasNewMessage = messages.length > previousMessageCount;
|
|
399
|
-
prevMessageCountRef.current = messages.length;
|
|
400
|
-
if (!isExpanded || !isAtBottom) {
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
scrollToBottom(hasNewMessage);
|
|
404
|
-
return () => {
|
|
405
|
-
if (scrollRafRef.current !== null) {
|
|
406
|
-
cancelAnimationFrame(scrollRafRef.current);
|
|
407
|
-
scrollRafRef.current = null;
|
|
408
|
-
}
|
|
409
|
-
};
|
|
410
|
-
}, [isAtBottom, isExpanded, messages.length, scrollToBottom]);
|
|
432
|
+
if (isFullScreen && !isMinimized) {
|
|
433
|
+
const selectedConversation = conversations?.find((conversation) => conversation.id === currentConversationId);
|
|
434
|
+
return (_jsx(Dialog, { open: true, onOpenChange: () => undefined, children: _jsxs(DialogContent, { "data-moldable-chat-fullscreen": true, "data-chat-drop-target": true, showCloseButton: false, "aria-describedby": undefined, onInteractOutside: (event) => {
|
|
435
|
+
if (isToastInteractionTarget(event.target)) {
|
|
436
|
+
event.preventDefault();
|
|
437
|
+
}
|
|
438
|
+
}, onEscapeKeyDown: (event) => {
|
|
439
|
+
event.preventDefault();
|
|
440
|
+
onFullScreenChange?.(false);
|
|
441
|
+
}, onCloseAutoFocus: (event) => {
|
|
442
|
+
event.preventDefault();
|
|
443
|
+
window.requestAnimationFrame(() => {
|
|
444
|
+
fullScreenTriggerRef.current?.focus();
|
|
445
|
+
});
|
|
446
|
+
}, className: "bottom-1 left-1 right-1 top-1 z-50 flex h-auto w-auto max-w-none translate-x-0 translate-y-0 gap-0 overflow-hidden rounded-lg border-0 p-0 sm:max-w-none", children: [_jsx("div", { "data-tauri-drag-region": true, className: "absolute inset-x-0 top-0 z-20 h-9", "aria-hidden": "true" }), isImageDropActive && (_jsxs("div", { className: "bg-background/90 border-primary/50 text-foreground absolute inset-0 z-50 flex flex-col items-center justify-center gap-2 rounded-[inherit] border-2 border-dashed backdrop-blur-sm", children: [_jsx(ImageIcon, { className: "text-primary size-7" }), _jsxs("div", { className: "text-center", children: [_jsx("p", { className: "text-sm font-medium", children: "Drop images to attach" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "They stay on disk and are read when sent" })] })] })), _jsxs("aside", { className: "border-border bg-muted/50 relative z-10 flex w-[280px] shrink-0 flex-col overflow-hidden rounded-r-lg border-r px-3 pb-4 pt-11", children: [_jsxs("button", { type: "button", onClick: () => onFullScreenChange?.(false), className: "text-muted-foreground hover:text-foreground mb-4 flex h-8 cursor-pointer items-center gap-2 rounded-lg px-2 text-sm transition-colors", children: [_jsx(Minimize2, { className: "size-4" }), "Back to app"] }), _jsx(ConversationSidebar, { conversations: conversations ?? [], currentConversationId: currentConversationId, currentAppId: currentAppId, onSelect: onSelectConversation ?? (() => undefined), onArchive: onArchiveConversation, onArchiveGroup: onArchiveConversationGroup, onNewChat: handleNewChat, newChatDisabled: false, hideScrollbar: true, disabled: false, hasMoreConversations: hasMoreConversations, isLoadingMoreConversations: isLoadingMoreConversations, onLoadMoreConversations: onLoadMoreConversations, className: "min-h-0 flex-1" })] }), _jsxs("section", { className: "relative flex min-w-0 flex-1 flex-col", children: [_jsxs("header", { className: "border-border flex h-14 shrink-0 items-center justify-between border-b px-5", children: [_jsx(DialogTitle, { className: "truncate text-sm font-medium", children: selectedConversation?.title ?? 'New conversation' }), _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () => onFullScreenChange?.(false), "aria-label": "Exit full screen", className: "text-muted-foreground hover:text-foreground relative z-30 cursor-pointer", children: _jsx(Minimize2, { className: "size-4" }) }) }), _jsx(TooltipContent, { children: "Exit full screen" })] }) })] }), _jsx(ChatMessageViewport, { items: listItems, renderItem: renderVirtualItem, toolProgress: toolProgress, onApprovalResponse: onApprovalResponse, currentConversationId: currentConversationId, scrollToBottomSignal: scrollToBottomSignal, isBusy: isResponding, hasOlderMessages: hasOlderMessages, isLoadingOlderMessages: isLoadingOlderMessages, onLoadOlderMessages: onLoadOlderMessages, showNavigationTrail: true, contentClassName: "mx-auto w-full min-w-0 max-w-3xl overflow-hidden px-6 py-6", scrollButtonClassName: "absolute bottom-3 left-1/2 z-20 size-8 -translate-x-1/2 cursor-pointer rounded-full shadow-lg" }), authPromptCopy && (_jsx("div", { className: "mx-auto w-full max-w-3xl shrink-0 px-6 pb-2", children: _jsx(ChatAuthPrompt, { copy: authPromptCopy, isConnecting: isConnectingChatGPT, onConnect: onConnectChatGPT ? handleConnectChatGPT : undefined, onAdvancedSetup: onAdvancedSetup }) })), _jsxs("div", { className: "mx-auto w-full max-w-3xl shrink-0 px-6 pb-2", children: [queuedMessages.length > 0 && (_jsxs("div", { className: "border-border bg-muted/30 mb-2 rounded-xl border p-3", children: [_jsxs("div", { className: "text-muted-foreground mb-2 flex items-center gap-2 text-xs font-medium", children: [_jsx(ListPlus, { className: "size-3.5" }), _jsx("span", { children: "Queued follow-ups" })] }), _jsx(DndContext, { sensors: queueSensors, collisionDetection: closestCenter, onDragEnd: handleQueuedDragEnd, children: _jsx(SortableContext, { items: queuedMessageIds, strategy: verticalListSortingStrategy, children: _jsx("div", { className: "space-y-1.5", children: queuedMessages.map((message) => (_jsx(QueuedMessageRow, { message: message, isResponding: isResponding, onRetryQueuedMessage: onRetryQueuedMessage, onSteerQueuedMessage: onSteerQueuedMessage, onRemoveQueuedMessage: onRemoveQueuedMessage, onEditQueuedMessage: handleEditQueuedMessage }, message.id))) }) }) })] })), _jsx("div", { className: "bg-background overflow-hidden rounded-[24px] shadow-[0_8px_40px_-12px_rgba(0,0,0,0.2)]", children: _jsx(ChatInput, { input: input, onInputChange: onInputChange, onSubmit: handleSubmit, isResponding: isResponding, placeholder: placeholder, inputRef: inputRef, onStop: onStop, imageAttachments: imageAttachments, onRemoveImageAttachment: onRemoveImageAttachment, footerStartControls: editingAppControl, footerControls: composerControls, submitDisabled: submitDisabled, slashCommands: slashCommands, onSlashCommandSelect: onSlashCommandSelect }) })] })] })] }) }));
|
|
447
|
+
}
|
|
411
448
|
return (_jsxs(_Fragment, { children: [_jsx(AnimatePresence, { children: isExpanded && !isMinimized && (_jsx(motion.div, { "data-moldable-chat-backdrop": true, initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 }, className: "fixed inset-0 z-40 bg-black/20", onClick: () => onExpandedChange(false) })) }), _jsx(motion.div, { "data-moldable-chat-panel": true, initial: false, animate: {
|
|
412
449
|
width: isExpanded ? 'min(90vw, 640px)' : '400px',
|
|
413
450
|
y: isMinimized ? 'calc(100% + 24px)' : 0,
|
|
@@ -437,7 +474,7 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
|
|
|
437
474
|
} })), _jsxs("div", { className: "relative z-10 overflow-hidden rounded-[inherit]", children: [_jsxs(motion.div, { initial: false, animate: {
|
|
438
475
|
height: isExpanded ? 'min(60vh, 480px)' : '0px',
|
|
439
476
|
opacity: isExpanded ? 1 : 0,
|
|
440
|
-
}, transition: { type: 'tween', duration: 0.2, ease: 'easeOut' }, className: "flex flex-col overflow-hidden", style: { pointerEvents: isExpanded ? 'auto' : 'none' }, children: [
|
|
477
|
+
}, transition: { type: 'tween', duration: 0.2, ease: 'easeOut' }, className: "flex flex-col overflow-hidden", style: { pointerEvents: isExpanded ? 'auto' : 'none' }, children: [isExpanded && !isMinimized && (_jsxs("div", { className: "absolute right-2 top-2 z-20 grid grid-cols-1 gap-0.5", "data-moldable-chat-panel-controls": true, role: "toolbar", "aria-label": "Chat view controls", "aria-orientation": "vertical", children: [onFullScreenChange && (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { ref: fullScreenTriggerRef, "data-moldable-chat-enter-fullscreen": true, variant: "ghost", size: "icon-sm", onClick: () => onFullScreenChange(true), "aria-label": "Enter full screen", className: "text-muted-foreground hover:text-foreground cursor-pointer", children: _jsx(Maximize2, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "bottom", children: "Full screen" })] }) })), _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", onClick: handleMinimize, className: "text-muted-foreground hover:text-foreground cursor-pointer", children: _jsx(ChevronDown, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "bottom", children: _jsx("p", { children: "Minimize" }) })] }) })] })), _jsx(ChatMessageViewport, { items: listItems, renderItem: renderVirtualItem, toolProgress: toolProgress, onApprovalResponse: onApprovalResponse, currentConversationId: currentConversationId, scrollToBottomSignal: scrollToBottomSignal, isBusy: isResponding, hasOlderMessages: hasOlderMessages, isLoadingOlderMessages: isLoadingOlderMessages, onLoadOlderMessages: onLoadOlderMessages, scrollAreaClassName: "px-2", contentClassName: "w-full min-w-0 max-w-full overflow-hidden py-4 pr-12", scrollButtonClassName: "absolute bottom-3 left-auto right-4 z-20 size-8 translate-x-0 cursor-pointer rounded-full shadow-lg" }), authPromptCopy && (_jsx("div", { className: "shrink-0 px-4 pb-2", children: _jsx(ChatAuthPrompt, { copy: authPromptCopy, isConnecting: isConnectingChatGPT, onConnect: onConnectChatGPT ? handleConnectChatGPT : undefined, onAdvancedSetup: onAdvancedSetup }) }))] }), _jsxs("div", { className: "relative z-10", onClick: () => {
|
|
441
478
|
if (!isExpanded) {
|
|
442
479
|
onExpandedChange(true);
|
|
443
480
|
}
|