@agent-native/core 0.98.4 → 0.98.6
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +28 -0
- package/corpus/core/docs/content/durable-background-runs.mdx +37 -0
- package/corpus/core/docs/content/external-agents.mdx +62 -7
- package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +38 -7
- package/corpus/core/docs/content/locales/ar-SA/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +39 -7
- package/corpus/core/docs/content/locales/de-DE/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +39 -7
- package/corpus/core/docs/content/locales/es-ES/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +39 -7
- package/corpus/core/docs/content/locales/fr-FR/tracking.mdx +4 -2
- package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +38 -7
- package/corpus/core/docs/content/locales/hi-IN/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +38 -7
- package/corpus/core/docs/content/locales/ja-JP/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +38 -7
- package/corpus/core/docs/content/locales/ko-KR/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +39 -7
- package/corpus/core/docs/content/locales/pt-BR/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +37 -7
- package/corpus/core/docs/content/locales/zh-CN/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-TW/durable-background-runs.mdx +14 -0
- package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +37 -7
- package/corpus/core/docs/content/locales/zh-TW/tracking.mdx +2 -0
- package/corpus/core/docs/content/tracking.mdx +2 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/handlers.ts +95 -21
- package/corpus/core/src/a2a/task-store.ts +65 -3
- package/corpus/core/src/agent/durable-background.ts +16 -16
- package/corpus/core/src/agent/engine/ai-sdk-engine.ts +25 -8
- package/corpus/core/src/agent/engine/anthropic-engine.ts +17 -3
- package/corpus/core/src/agent/engine/output-tokens.ts +6 -6
- package/corpus/core/src/agent/production-agent.ts +200 -27
- package/corpus/core/src/agent/run-manager.ts +81 -1
- package/corpus/core/src/agent/run-store.ts +301 -41
- package/corpus/core/src/client/AgentPanel.tsx +6 -2
- package/corpus/core/src/client/AssistantChat.tsx +364 -69
- package/corpus/core/src/client/agent-chat-adapter.ts +169 -1
- package/corpus/core/src/client/chat/message-components.tsx +3 -0
- package/corpus/core/src/client/chat/tool-call-display.tsx +20 -36
- package/corpus/core/src/client/conversation/use-near-bottom-autoscroll.ts +7 -0
- package/corpus/core/src/client/extensions/AgentNativeExtensionFrame.tsx +2 -0
- package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +2 -0
- package/corpus/core/src/client/extensions/ExtensionEditor.tsx +9 -2
- package/corpus/core/src/client/extensions/ExtensionViewer.tsx +2 -0
- package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +2 -0
- package/corpus/core/src/client/extensions/portable-extension.ts +2 -0
- package/corpus/core/src/client/session-replay.ts +361 -29
- package/corpus/core/src/client/sse-event-processor.ts +43 -1
- package/corpus/core/src/demo/actions/toggle-demo-mode.ts +1 -1
- package/corpus/core/src/demo/config.ts +6 -6
- package/corpus/core/src/demo/fetch-interceptor.ts +13 -4
- package/corpus/core/src/demo/redact.ts +13 -149
- package/corpus/core/src/extensions/html-shell.ts +3 -0
- package/corpus/core/src/extensions/session-replay-iframe.ts +131 -0
- package/corpus/core/src/integrations/adapters/slack.ts +123 -13
- package/corpus/core/src/integrations/identity-links-store.ts +210 -0
- package/corpus/core/src/integrations/identity.ts +132 -0
- package/corpus/core/src/integrations/index.ts +6 -0
- package/corpus/core/src/integrations/plugin.ts +58 -1
- package/corpus/core/src/integrations/types.ts +7 -0
- package/corpus/core/src/mcp/build-server.ts +127 -22
- package/corpus/core/src/mcp/external-agent-policy.ts +18 -0
- package/corpus/core/src/mcp/index.ts +1 -0
- package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +1 -20
- package/corpus/core/src/server/agent-chat/plugin-options.ts +12 -1
- package/corpus/core/src/server/agent-chat/script-entries.ts +20 -3
- package/corpus/core/src/server/agent-chat-plugin.ts +3 -0
- package/corpus/core/src/session-replay-iframe-protocol.ts +58 -0
- package/corpus/core/src/shared/reasoning-effort.ts +35 -0
- package/corpus/core/src/styles/agent-conversation.css +26 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +34 -5
- package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +0 -15
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +30 -21
- package/corpus/templates/analytics/AGENTS.md +27 -0
- package/corpus/templates/analytics/actions/create-session-replay-agent-link.ts +0 -1
- package/corpus/templates/analytics/actions/get-error-issue.ts +1 -0
- package/corpus/templates/analytics/actions/get-session-replay-summary.ts +1 -0
- package/corpus/templates/analytics/actions/get-session-replay-timeline.ts +40 -0
- package/corpus/templates/analytics/actions/list-error-issues.ts +13 -0
- package/corpus/templates/analytics/actions/list-session-recordings.ts +1 -0
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +4 -0
- package/corpus/templates/analytics/app/global.css +2 -2
- package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +41 -4
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +52 -203
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +69 -16
- package/corpus/templates/analytics/changelog/2026-07-12-analytics-chat-retries-before-showing-a-generic-no-data-mess.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-analytics-sessions-search-no-longer-loses-fast-keystrokes-an.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-chart-selection-respects-chat-state.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-connected-external-agents-can-now-look-up-sessions-error-iss.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-demo-mode-anonymizes-error-reporting-emails.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-session-identities-stay-visible-when-demo-mode-is-off.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-session-replays-show-iframe-content.md +6 -0
- package/corpus/templates/analytics/netlify.toml +0 -3
- package/corpus/templates/analytics/server/lib/analytics-connector-catalog.ts +14 -0
- package/corpus/templates/analytics/server/lib/error-capture.ts +101 -2
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +24 -0
- package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +49 -17
- package/corpus/templates/analytics/server/lib/session-replay.ts +18 -16
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +43 -6
- package/corpus/templates/analytics/server/plugins/db.ts +15 -0
- package/corpus/templates/assets/app/global.css +1 -1
- package/corpus/templates/brain/app/global.css +2 -2
- package/corpus/templates/brain/changelog/2026-07-12-fix-long-response-progress.md +6 -0
- package/corpus/templates/forms/app/components/CloudUpgrade.tsx +1 -1
- package/corpus/templates/forms/app/components/ThemeToggle.tsx +22 -6
- package/corpus/templates/forms/app/components/builder/FieldPropertiesPanel.tsx +5 -5
- package/corpus/templates/forms/app/components/builder/FieldRenderer.tsx +3 -3
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +16 -16
- package/corpus/templates/forms/app/global.css +164 -13
- package/corpus/templates/forms/app/pages/AskPage.tsx +35 -13
- package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +143 -67
- package/corpus/templates/forms/app/pages/FormFillPage.tsx +44 -11
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +42 -24
- package/corpus/templates/forms/app/pages/ResponseInsightsPage.tsx +28 -15
- package/corpus/templates/forms/app/pages/ResponsesPage.tsx +46 -20
- package/corpus/templates/forms/app/routes/_app.settings.tsx +1 -1
- package/corpus/templates/forms/changelog/2026-07-12-ask-forms-suggestions-now-sit-beneath-the-composer-for-a-tig.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-12-builder-response-tables-now-fill-the-view-without-a-redundan.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-12-form-builder-surfaces-are-calmer-fields-stay-stable-on-hover.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-12-response-tables-now-fill-the-available-pane-with-a-flexible-.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-12-smoother-more-tactile-controls-throughout-animated-icon-and-.md +6 -0
- package/corpus/templates/mail/AGENTS.md +3 -1
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +21 -13
- package/corpus/templates/mail/app/components/email/email-iframe-document.ts +18 -0
- package/corpus/templates/mail/server/lib/mail-integrations.ts +3 -0
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +84 -15
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/task-store.d.ts +20 -1
- package/dist/a2a/task-store.d.ts.map +1 -1
- package/dist/a2a/task-store.js +57 -4
- package/dist/a2a/task-store.js.map +1 -1
- package/dist/agent/durable-background.d.ts +10 -10
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +16 -16
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +19 -8
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
- package/dist/agent/engine/anthropic-engine.js +11 -3
- package/dist/agent/engine/anthropic-engine.js.map +1 -1
- package/dist/agent/engine/output-tokens.js +6 -6
- package/dist/agent/engine/output-tokens.js.map +1 -1
- package/dist/agent/production-agent.d.ts +52 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +154 -26
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +9 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +71 -1
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +9 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +243 -48
- package/dist/agent/run-store.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +6 -2
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +21 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +298 -67
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +146 -1
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +2 -1
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +3 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +13 -37
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.d.ts +1 -0
- package/dist/client/conversation/use-near-bottom-autoscroll.d.ts.map +1 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.js +6 -0
- package/dist/client/conversation/use-near-bottom-autoscroll.js.map +1 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.d.ts.map +1 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.js +2 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.js.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +2 -1
- package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
- package/dist/client/extensions/ExtensionEditor.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionEditor.js +5 -2
- package/dist/client/extensions/ExtensionEditor.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +2 -1
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -1
- package/dist/client/extensions/InlineExtensionFrame.js +2 -1
- package/dist/client/extensions/InlineExtensionFrame.js.map +1 -1
- package/dist/client/extensions/portable-extension.d.ts.map +1 -1
- package/dist/client/extensions/portable-extension.js +2 -0
- package/dist/client/extensions/portable-extension.js.map +1 -1
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +308 -29
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +5 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +37 -1
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/demo/actions/toggle-demo-mode.js +1 -1
- package/dist/demo/actions/toggle-demo-mode.js.map +1 -1
- package/dist/demo/config.js +6 -6
- package/dist/demo/config.js.map +1 -1
- package/dist/demo/fetch-interceptor.d.ts.map +1 -1
- package/dist/demo/fetch-interceptor.js +13 -4
- package/dist/demo/fetch-interceptor.js.map +1 -1
- package/dist/demo/redact.d.ts +7 -7
- package/dist/demo/redact.d.ts.map +1 -1
- package/dist/demo/redact.js +8 -145
- package/dist/demo/redact.js.map +1 -1
- package/dist/extensions/html-shell.d.ts.map +1 -1
- package/dist/extensions/html-shell.js +2 -0
- package/dist/extensions/html-shell.js.map +1 -1
- package/dist/extensions/session-replay-iframe.d.ts +10 -0
- package/dist/extensions/session-replay-iframe.d.ts.map +1 -0
- package/dist/extensions/session-replay-iframe.js +121 -0
- package/dist/extensions/session-replay-iframe.js.map +1 -0
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +98 -13
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/identity-links-store.d.ts +23 -0
- package/dist/integrations/identity-links-store.d.ts.map +1 -0
- package/dist/integrations/identity-links-store.js +158 -0
- package/dist/integrations/identity-links-store.js.map +1 -0
- package/dist/integrations/identity.d.ts +11 -0
- package/dist/integrations/identity.d.ts.map +1 -0
- package/dist/integrations/identity.js +100 -0
- package/dist/integrations/identity.js.map +1 -0
- package/dist/integrations/index.d.ts +2 -0
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js +2 -0
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +43 -1
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/types.d.ts +6 -0
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/types.js.map +1 -1
- package/dist/mcp/build-server.d.ts +9 -2
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +97 -20
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/external-agent-policy.d.ts +19 -0
- package/dist/mcp/external-agent-policy.d.ts.map +1 -0
- package/dist/mcp/external-agent-policy.js +2 -0
- package/dist/mcp/external-agent-policy.js.map +1 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +1 -19
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/server/agent-chat/plugin-options.d.ts +11 -1
- package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
- package/dist/server/agent-chat/plugin-options.js.map +1 -1
- package/dist/server/agent-chat/script-entries.d.ts.map +1 -1
- package/dist/server/agent-chat/script-entries.js +16 -2
- package/dist/server/agent-chat/script-entries.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +3 -0
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/session-replay-iframe-protocol.d.ts +36 -0
- package/dist/session-replay-iframe-protocol.d.ts.map +1 -0
- package/dist/session-replay-iframe-protocol.js +24 -0
- package/dist/session-replay-iframe-protocol.js.map +1 -0
- package/dist/shared/reasoning-effort.d.ts +11 -0
- package/dist/shared/reasoning-effort.d.ts.map +1 -1
- package/dist/shared/reasoning-effort.js +36 -0
- package/dist/shared/reasoning-effort.js.map +1 -1
- package/dist/styles/agent-conversation.css +26 -0
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +34 -5
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +0 -15
- package/docs/content/durable-background-runs.mdx +37 -0
- package/docs/content/external-agents.mdx +62 -7
- package/docs/content/locales/ar-SA/external-agents.mdx +38 -7
- package/docs/content/locales/ar-SA/tracking.mdx +2 -0
- package/docs/content/locales/de-DE/external-agents.mdx +39 -7
- package/docs/content/locales/de-DE/tracking.mdx +2 -0
- package/docs/content/locales/es-ES/external-agents.mdx +39 -7
- package/docs/content/locales/es-ES/tracking.mdx +2 -0
- package/docs/content/locales/fr-FR/external-agents.mdx +39 -7
- package/docs/content/locales/fr-FR/tracking.mdx +4 -2
- package/docs/content/locales/hi-IN/external-agents.mdx +38 -7
- package/docs/content/locales/hi-IN/tracking.mdx +2 -0
- package/docs/content/locales/ja-JP/external-agents.mdx +38 -7
- package/docs/content/locales/ja-JP/tracking.mdx +2 -0
- package/docs/content/locales/ko-KR/external-agents.mdx +38 -7
- package/docs/content/locales/ko-KR/tracking.mdx +2 -0
- package/docs/content/locales/pt-BR/external-agents.mdx +39 -7
- package/docs/content/locales/pt-BR/tracking.mdx +2 -0
- package/docs/content/locales/zh-CN/external-agents.mdx +37 -7
- package/docs/content/locales/zh-CN/tracking.mdx +2 -0
- package/docs/content/locales/zh-TW/durable-background-runs.mdx +14 -0
- package/docs/content/locales/zh-TW/external-agents.mdx +37 -7
- package/docs/content/locales/zh-TW/tracking.mdx +2 -0
- package/docs/content/tracking.mdx +2 -0
- package/package.json +2 -2
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +34 -5
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +0 -15
- package/corpus/core/src/observability/hosted-model-experiment.ts +0 -118
- package/dist/observability/hosted-model-experiment.d.ts +0 -39
- package/dist/observability/hosted-model-experiment.d.ts.map +0 -1
- package/dist/observability/hosted-model-experiment.js +0 -90
- package/dist/observability/hosted-model-experiment.js.map +0 -1
|
@@ -118,7 +118,7 @@ export function FormsListPage() {
|
|
|
118
118
|
<Button
|
|
119
119
|
onClick={handleCreate}
|
|
120
120
|
size="sm"
|
|
121
|
-
className="shrink-0 cursor-pointer"
|
|
121
|
+
className="min-h-10 shrink-0 cursor-pointer active:scale-[0.96] transition-[background-color,box-shadow,transform]"
|
|
122
122
|
>
|
|
123
123
|
<IconPlus className="h-3.5 w-3.5" />
|
|
124
124
|
<span className="hidden sm:inline">{t("forms.newForm")}</span>
|
|
@@ -269,7 +269,7 @@ export function FormsListPage() {
|
|
|
269
269
|
if (isLoading) {
|
|
270
270
|
return (
|
|
271
271
|
<div className="p-3 sm:p-6 max-w-5xl mx-auto">
|
|
272
|
-
<div className="
|
|
272
|
+
<div className="forms-list-shell overflow-hidden bg-card">
|
|
273
273
|
{Array.from({ length: 6 }).map((_, i) => (
|
|
274
274
|
<div
|
|
275
275
|
key={i}
|
|
@@ -280,8 +280,10 @@ export function FormsListPage() {
|
|
|
280
280
|
<Skeleton className="h-3 w-1/2" />
|
|
281
281
|
</div>
|
|
282
282
|
<Skeleton className="h-5 w-20 rounded-full" />
|
|
283
|
+
<Skeleton className="h-5 w-20 rounded-full" />
|
|
284
|
+
<Skeleton className="h-4 w-24" />
|
|
283
285
|
<Skeleton className="h-4 w-24" />
|
|
284
|
-
<Skeleton className="h-
|
|
286
|
+
<Skeleton className="h-10 w-10 rounded-lg md:ms-auto" />
|
|
285
287
|
</div>
|
|
286
288
|
))}
|
|
287
289
|
</div>
|
|
@@ -300,6 +302,7 @@ export function FormsListPage() {
|
|
|
300
302
|
<Button
|
|
301
303
|
variant="outline"
|
|
302
304
|
size="sm"
|
|
305
|
+
className="min-h-10 active:scale-[0.96] transition-[background-color,box-shadow,transform]"
|
|
303
306
|
onClick={() => {
|
|
304
307
|
const next = encodeURIComponent(
|
|
305
308
|
window.location.pathname + window.location.search,
|
|
@@ -322,8 +325,8 @@ export function FormsListPage() {
|
|
|
322
325
|
<Button
|
|
323
326
|
variant="outline"
|
|
324
327
|
size="sm"
|
|
328
|
+
className="min-h-10 gap-2 active:scale-[0.96] transition-[background-color,box-shadow,transform]"
|
|
325
329
|
onClick={() => refetch()}
|
|
326
|
-
className="gap-2"
|
|
327
330
|
>
|
|
328
331
|
<IconRefresh className="h-3.5 w-3.5" />
|
|
329
332
|
{t("common.retry")}
|
|
@@ -344,11 +347,17 @@ export function FormsListPage() {
|
|
|
344
347
|
value={view}
|
|
345
348
|
onValueChange={(v) => setView(v as "active" | "archive")}
|
|
346
349
|
>
|
|
347
|
-
<TabsList>
|
|
348
|
-
<TabsTrigger
|
|
350
|
+
<TabsList className="h-12">
|
|
351
|
+
<TabsTrigger
|
|
352
|
+
value="active"
|
|
353
|
+
className="min-h-10 gap-1.5 text-xs active:scale-[0.96] transition-[background-color,box-shadow,color,transform]"
|
|
354
|
+
>
|
|
349
355
|
{t("header.forms")}
|
|
350
356
|
</TabsTrigger>
|
|
351
|
-
<TabsTrigger
|
|
357
|
+
<TabsTrigger
|
|
358
|
+
value="archive"
|
|
359
|
+
className="min-h-10 gap-1.5 text-xs active:scale-[0.96] transition-[background-color,box-shadow,color,transform]"
|
|
360
|
+
>
|
|
352
361
|
<IconArchive className="h-3.5 w-3.5" />
|
|
353
362
|
{t("forms.archive")}
|
|
354
363
|
</TabsTrigger>
|
|
@@ -359,7 +368,7 @@ export function FormsListPage() {
|
|
|
359
368
|
<Button
|
|
360
369
|
variant={selectionMode ? "secondary" : "ghost"}
|
|
361
370
|
size="sm"
|
|
362
|
-
className="h-
|
|
371
|
+
className="min-h-10 gap-1.5 text-xs active:scale-[0.96] transition-[background-color,box-shadow,transform]"
|
|
363
372
|
onClick={() => {
|
|
364
373
|
setSelectionMode((current) => {
|
|
365
374
|
if (current) setSelectedIds(new Set());
|
|
@@ -374,7 +383,7 @@ export function FormsListPage() {
|
|
|
374
383
|
</div>
|
|
375
384
|
|
|
376
385
|
{selectionMode && forms.length > 0 && (
|
|
377
|
-
<div className="mb-4 flex flex-wrap items-center gap-2 rounded-
|
|
386
|
+
<div className="forms-selection-toolbar mb-4 flex flex-wrap items-center gap-2 rounded-xl bg-muted/30 px-3 py-2">
|
|
378
387
|
<span className="text-xs font-medium text-foreground">
|
|
379
388
|
{t("forms.selectedCount", {
|
|
380
389
|
count: selectedCount,
|
|
@@ -385,7 +394,7 @@ export function FormsListPage() {
|
|
|
385
394
|
<Button
|
|
386
395
|
variant="ghost"
|
|
387
396
|
size="sm"
|
|
388
|
-
className="h-
|
|
397
|
+
className="min-h-10 text-xs active:scale-[0.96] transition-[background-color,box-shadow,transform]"
|
|
389
398
|
onClick={toggleSelectAll}
|
|
390
399
|
>
|
|
391
400
|
{allFormsSelected ? t("common.clearAll") : t("common.selectAll")}
|
|
@@ -393,7 +402,7 @@ export function FormsListPage() {
|
|
|
393
402
|
<Button
|
|
394
403
|
variant="ghost"
|
|
395
404
|
size="sm"
|
|
396
|
-
className="h-
|
|
405
|
+
className="min-h-10 gap-1.5 text-xs text-destructive hover:text-destructive active:scale-[0.96] transition-[background-color,box-shadow,transform]"
|
|
397
406
|
onClick={() =>
|
|
398
407
|
isArchive ? setBulkPurgeOpen(true) : handleBulkDelete(false)
|
|
399
408
|
}
|
|
@@ -405,7 +414,7 @@ export function FormsListPage() {
|
|
|
405
414
|
<Button
|
|
406
415
|
variant="ghost"
|
|
407
416
|
size="icon"
|
|
408
|
-
className="ms-auto
|
|
417
|
+
className="relative ms-auto size-10 transition-[background-color,box-shadow,transform] active:scale-[0.96] sm:size-8 sm:before:absolute sm:before:-inset-1 sm:before:content-['']"
|
|
409
418
|
onClick={clearSelection}
|
|
410
419
|
aria-label={t("forms.exitSelectionMode")}
|
|
411
420
|
>
|
|
@@ -415,7 +424,7 @@ export function FormsListPage() {
|
|
|
415
424
|
)}
|
|
416
425
|
|
|
417
426
|
{forms.length === 0 ? (
|
|
418
|
-
<div className="flex flex-col items-center justify-center
|
|
427
|
+
<div className="forms-empty-state flex flex-col items-center justify-center rounded-xl border border-dashed border-border bg-card py-20">
|
|
419
428
|
{isArchive ? (
|
|
420
429
|
<>
|
|
421
430
|
<h3 className="font-medium mb-1">
|
|
@@ -431,7 +440,11 @@ export function FormsListPage() {
|
|
|
431
440
|
<p className="text-sm text-muted-foreground mb-4">
|
|
432
441
|
{t("forms.emptyDescription")}
|
|
433
442
|
</p>
|
|
434
|
-
<Button
|
|
443
|
+
<Button
|
|
444
|
+
onClick={handleCreate}
|
|
445
|
+
size="sm"
|
|
446
|
+
className="min-h-10 gap-2 active:scale-[0.96] transition-[background-color,box-shadow,transform]"
|
|
447
|
+
>
|
|
435
448
|
<IconPlus className="h-4 w-4" />
|
|
436
449
|
{t("forms.createForm")}
|
|
437
450
|
</Button>
|
|
@@ -439,7 +452,7 @@ export function FormsListPage() {
|
|
|
439
452
|
)}
|
|
440
453
|
</div>
|
|
441
454
|
) : (
|
|
442
|
-
<div className="
|
|
455
|
+
<div className="forms-list-shell overflow-hidden bg-card">
|
|
443
456
|
{forms.map((form: any) => {
|
|
444
457
|
const selected = selectedIds.has(form.id);
|
|
445
458
|
const dateLabel =
|
|
@@ -515,10 +528,6 @@ export function FormsListPage() {
|
|
|
515
528
|
<h3 className="min-w-0 flex-1 truncate text-sm font-medium">
|
|
516
529
|
{form.title}
|
|
517
530
|
</h3>
|
|
518
|
-
<VisibilityBadge
|
|
519
|
-
visibility={(form as any).visibility}
|
|
520
|
-
className="shrink-0"
|
|
521
|
-
/>
|
|
522
531
|
</div>
|
|
523
532
|
{form.description && (
|
|
524
533
|
<p className="mt-0.5 truncate text-xs text-muted-foreground">
|
|
@@ -528,6 +537,10 @@ export function FormsListPage() {
|
|
|
528
537
|
</div>
|
|
529
538
|
</div>
|
|
530
539
|
|
|
540
|
+
<div className="flex min-w-0 items-center">
|
|
541
|
+
<VisibilityBadge visibility={(form as any).visibility} />
|
|
542
|
+
</div>
|
|
543
|
+
|
|
531
544
|
<div className="flex items-center md:justify-start">
|
|
532
545
|
<Badge
|
|
533
546
|
variant="outline"
|
|
@@ -558,7 +571,7 @@ export function FormsListPage() {
|
|
|
558
571
|
<Button
|
|
559
572
|
variant="ghost"
|
|
560
573
|
size="sm"
|
|
561
|
-
className="
|
|
574
|
+
className="relative size-10 rounded-lg p-0 transition-[background-color,opacity,transform] duration-150 ease-out active:scale-[0.96] focus:opacity-100 sm:size-8 sm:opacity-0 sm:before:absolute sm:before:-inset-1 sm:before:content-[''] sm:group-hover:opacity-100"
|
|
562
575
|
aria-label={t("forms.formActions")}
|
|
563
576
|
>
|
|
564
577
|
<IconDots className="h-4 w-4" />
|
|
@@ -695,10 +708,12 @@ export function FormsListPage() {
|
|
|
695
708
|
</AlertDialogDescription>
|
|
696
709
|
</AlertDialogHeader>
|
|
697
710
|
<AlertDialogFooter>
|
|
698
|
-
<AlertDialogCancel
|
|
711
|
+
<AlertDialogCancel className="min-h-10 active:scale-[0.96] transition-[background-color,box-shadow,transform]">
|
|
712
|
+
{t("common.cancel")}
|
|
713
|
+
</AlertDialogCancel>
|
|
699
714
|
<AlertDialogAction
|
|
700
715
|
onClick={handlePurge}
|
|
701
|
-
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
|
716
|
+
className="min-h-10 bg-destructive text-destructive-foreground hover:bg-destructive/90 active:scale-[0.96] transition-[background-color,box-shadow,transform]"
|
|
702
717
|
>
|
|
703
718
|
{t("forms.deleteForever")}
|
|
704
719
|
</AlertDialogAction>
|
|
@@ -718,13 +733,16 @@ export function FormsListPage() {
|
|
|
718
733
|
</AlertDialogDescription>
|
|
719
734
|
</AlertDialogHeader>
|
|
720
735
|
<AlertDialogFooter>
|
|
721
|
-
<AlertDialogCancel
|
|
736
|
+
<AlertDialogCancel
|
|
737
|
+
disabled={bulkDeletePending}
|
|
738
|
+
className="min-h-10 active:scale-[0.96] transition-[background-color,box-shadow,transform]"
|
|
739
|
+
>
|
|
722
740
|
{t("common.cancel")}
|
|
723
741
|
</AlertDialogCancel>
|
|
724
742
|
<AlertDialogAction
|
|
725
743
|
onClick={() => handleBulkDelete(true)}
|
|
726
744
|
disabled={bulkDeletePending}
|
|
727
|
-
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
|
745
|
+
className="min-h-10 bg-destructive text-destructive-foreground hover:bg-destructive/90 active:scale-[0.96] transition-[background-color,box-shadow,transform]"
|
|
728
746
|
>
|
|
729
747
|
{t("forms.deleteForever")}
|
|
730
748
|
</AlertDialogAction>
|
|
@@ -52,7 +52,7 @@ function Metric({
|
|
|
52
52
|
detail?: string;
|
|
53
53
|
}) {
|
|
54
54
|
return (
|
|
55
|
-
<div className="min-w-0 rounded-
|
|
55
|
+
<div className="min-w-0 rounded-xl border border-border/80 bg-background px-3 py-3 shadow-sm">
|
|
56
56
|
<div className="text-[11px] font-medium uppercase tracking-normal text-muted-foreground">
|
|
57
57
|
{label}
|
|
58
58
|
</div>
|
|
@@ -97,7 +97,7 @@ function SubmissionBars({
|
|
|
97
97
|
<div className="flex h-40 w-full items-end rounded-sm bg-muted/40 px-0.5">
|
|
98
98
|
<div
|
|
99
99
|
className={cn(
|
|
100
|
-
"w-full rounded-sm bg-primary/80 transition-
|
|
100
|
+
"w-full rounded-sm bg-primary/80 shadow-sm transition-[height,background-color,box-shadow] duration-300 ease-out hover:bg-primary hover:shadow-md motion-reduce:transition-none",
|
|
101
101
|
point.submissions === 0 && "bg-muted-foreground/30",
|
|
102
102
|
)}
|
|
103
103
|
style={{ height }}
|
|
@@ -121,11 +121,11 @@ function LoadingState() {
|
|
|
121
121
|
<Skeleton className="h-10 w-72" />
|
|
122
122
|
<div className="forms-response-metrics-grid grid gap-3">
|
|
123
123
|
{Array.from({ length: 4 }).map((_, index) => (
|
|
124
|
-
<Skeleton key={index} className="h-20 rounded-
|
|
124
|
+
<Skeleton key={index} className="h-20 rounded-xl" />
|
|
125
125
|
))}
|
|
126
126
|
</div>
|
|
127
|
-
<Skeleton className="h-64 rounded-
|
|
128
|
-
<Skeleton className="h-72 rounded-
|
|
127
|
+
<Skeleton className="h-64 rounded-xl" />
|
|
128
|
+
<Skeleton className="h-72 rounded-xl" />
|
|
129
129
|
</div>
|
|
130
130
|
);
|
|
131
131
|
}
|
|
@@ -160,7 +160,7 @@ export function ResponseInsightsPage() {
|
|
|
160
160
|
type="button"
|
|
161
161
|
variant="outline"
|
|
162
162
|
size="sm"
|
|
163
|
-
className="gap-1.5"
|
|
163
|
+
className="min-h-10 gap-1.5 transition-[scale,background-color,border-color,color,box-shadow] duration-150 active:scale-[0.96] motion-reduce:transition-none"
|
|
164
164
|
onClick={() => refetch()}
|
|
165
165
|
>
|
|
166
166
|
<IconRefresh className="size-3.5" />
|
|
@@ -176,7 +176,12 @@ export function ResponseInsightsPage() {
|
|
|
176
176
|
<div className="flex min-h-full flex-col bg-background">
|
|
177
177
|
<header className="flex min-h-14 shrink-0 items-center justify-between gap-3 border-b border-border pl-12 pr-3 sm:px-4 md:pl-4">
|
|
178
178
|
<div className="flex min-w-0 items-center gap-2">
|
|
179
|
-
<Button
|
|
179
|
+
<Button
|
|
180
|
+
variant="ghost"
|
|
181
|
+
size="sm"
|
|
182
|
+
asChild
|
|
183
|
+
className="min-h-10 gap-1.5 transition-[scale,background-color,border-color,color,box-shadow] duration-150 active:scale-[0.96] motion-reduce:transition-none"
|
|
184
|
+
>
|
|
180
185
|
<Link to="/forms">
|
|
181
186
|
<IconArrowLeft className="size-3.5" />
|
|
182
187
|
Forms
|
|
@@ -196,7 +201,12 @@ export function ResponseInsightsPage() {
|
|
|
196
201
|
</div>
|
|
197
202
|
</div>
|
|
198
203
|
</div>
|
|
199
|
-
<Button
|
|
204
|
+
<Button
|
|
205
|
+
variant="outline"
|
|
206
|
+
size="sm"
|
|
207
|
+
asChild
|
|
208
|
+
className="min-h-10 gap-1.5 transition-[scale,background-color,border-color,color,box-shadow] duration-150 active:scale-[0.96] motion-reduce:transition-none"
|
|
209
|
+
>
|
|
200
210
|
<Link to={display.primaryAction.href}>
|
|
201
211
|
{display.primaryAction.label}
|
|
202
212
|
<IconExternalLink className="size-3.5" />
|
|
@@ -204,7 +214,7 @@ export function ResponseInsightsPage() {
|
|
|
204
214
|
</Button>
|
|
205
215
|
</header>
|
|
206
216
|
|
|
207
|
-
<main className="forms-response-insights-grid grid gap-4 p-4">
|
|
217
|
+
<main className="forms-response-insights-grid grid gap-4 bg-muted/20 p-4">
|
|
208
218
|
<section className="space-y-4">
|
|
209
219
|
<div className="forms-response-metrics-grid grid gap-3">
|
|
210
220
|
<Metric
|
|
@@ -233,7 +243,7 @@ export function ResponseInsightsPage() {
|
|
|
233
243
|
/>
|
|
234
244
|
</div>
|
|
235
245
|
|
|
236
|
-
<div className="rounded-
|
|
246
|
+
<div className="rounded-xl border border-border/80 bg-background p-4 shadow-sm">
|
|
237
247
|
<div className="mb-3 flex items-center justify-between gap-3">
|
|
238
248
|
<div>
|
|
239
249
|
<h2 className="text-sm font-semibold">{chartSeries.title}</h2>
|
|
@@ -249,7 +259,7 @@ export function ResponseInsightsPage() {
|
|
|
249
259
|
</div>
|
|
250
260
|
</section>
|
|
251
261
|
|
|
252
|
-
<section className="min-w-0 rounded-
|
|
262
|
+
<section className="min-w-0 overflow-hidden rounded-xl border border-border/80 bg-background shadow-sm">
|
|
253
263
|
<div className="flex min-h-12 items-center justify-between gap-3 border-b border-border px-3">
|
|
254
264
|
<div className="min-w-0">
|
|
255
265
|
<h2 className="truncate text-sm font-semibold">{table.title}</h2>
|
|
@@ -268,13 +278,13 @@ export function ResponseInsightsPage() {
|
|
|
268
278
|
) : (
|
|
269
279
|
<div className="max-h-[calc(100vh-15rem)] overflow-auto">
|
|
270
280
|
<Table>
|
|
271
|
-
<TableHeader className="sticky top-0 z-10 bg-background">
|
|
281
|
+
<TableHeader className="sticky top-0 z-10 bg-background shadow-sm">
|
|
272
282
|
<TableRow>
|
|
273
283
|
{table.columns.map((column) => (
|
|
274
284
|
<TableHead
|
|
275
285
|
key={column.key}
|
|
276
286
|
className={cn(
|
|
277
|
-
"h-
|
|
287
|
+
"h-11 whitespace-nowrap px-3 text-xs",
|
|
278
288
|
column.align === "right" && "text-right",
|
|
279
289
|
)}
|
|
280
290
|
>
|
|
@@ -285,12 +295,15 @@ export function ResponseInsightsPage() {
|
|
|
285
295
|
</TableHeader>
|
|
286
296
|
<TableBody>
|
|
287
297
|
{table.rows.map((row) => (
|
|
288
|
-
<TableRow
|
|
298
|
+
<TableRow
|
|
299
|
+
key={String(row.id)}
|
|
300
|
+
className="transition-[background-color] duration-150 hover:bg-muted/30 motion-reduce:transition-none"
|
|
301
|
+
>
|
|
289
302
|
{table.columns.map((column) => (
|
|
290
303
|
<TableCell
|
|
291
304
|
key={column.key}
|
|
292
305
|
className={cn(
|
|
293
|
-
"max-w-56 truncate px-3 py-
|
|
306
|
+
"max-w-56 truncate px-3 py-3 text-xs",
|
|
294
307
|
column.align === "right" && "text-right",
|
|
295
308
|
)}
|
|
296
309
|
title={formatCell(row[column.key])}
|
|
@@ -254,7 +254,7 @@ export function ResponsesPage() {
|
|
|
254
254
|
variant="outline"
|
|
255
255
|
size="sm"
|
|
256
256
|
onClick={() => refetch()}
|
|
257
|
-
className="gap-2"
|
|
257
|
+
className="min-h-10 gap-2 transition-[scale,background-color,border-color,color,box-shadow] duration-150 active:scale-[0.96] motion-reduce:transition-none"
|
|
258
258
|
>
|
|
259
259
|
<IconRefresh className="h-3.5 w-3.5" />
|
|
260
260
|
{t("common.retry")}
|
|
@@ -272,7 +272,7 @@ export function ResponsesPage() {
|
|
|
272
272
|
variant="ghost"
|
|
273
273
|
size="sm"
|
|
274
274
|
asChild
|
|
275
|
-
className="gap-1.5
|
|
275
|
+
className="min-h-10 shrink-0 gap-1.5 transition-[scale,background-color,border-color,color,box-shadow] duration-150 active:scale-[0.96] motion-reduce:transition-none"
|
|
276
276
|
>
|
|
277
277
|
<Link to={`/forms/${id}`}>
|
|
278
278
|
<IconArrowLeft className="h-3.5 w-3.5" />
|
|
@@ -305,14 +305,14 @@ export function ResponsesPage() {
|
|
|
305
305
|
value={search}
|
|
306
306
|
onChange={(e) => setSearch(e.target.value)}
|
|
307
307
|
placeholder={t("responses.filterPlaceholder")}
|
|
308
|
-
className="h-
|
|
308
|
+
className="h-10 w-48 pl-7 text-xs transition-[background-color,border-color,box-shadow] duration-150 motion-reduce:transition-none"
|
|
309
309
|
/>
|
|
310
310
|
</div>
|
|
311
311
|
) : null}
|
|
312
312
|
<Button
|
|
313
313
|
variant="outline"
|
|
314
314
|
size="sm"
|
|
315
|
-
className="gap-1.5 text-xs
|
|
315
|
+
className="min-h-10 shrink-0 gap-1.5 text-xs transition-[scale,background-color,border-color,color,box-shadow] duration-150 active:scale-[0.96] motion-reduce:transition-none"
|
|
316
316
|
onClick={exportCsv}
|
|
317
317
|
disabled={filteredSorted.length === 0}
|
|
318
318
|
>
|
|
@@ -332,7 +332,7 @@ export function ResponsesPage() {
|
|
|
332
332
|
value={search}
|
|
333
333
|
onChange={(e) => setSearch(e.target.value)}
|
|
334
334
|
placeholder={t("responses.filterPlaceholder")}
|
|
335
|
-
className="h-
|
|
335
|
+
className="h-10 pl-7 text-xs transition-[background-color,border-color,box-shadow] duration-150 motion-reduce:transition-none"
|
|
336
336
|
/>
|
|
337
337
|
</div>
|
|
338
338
|
</div>
|
|
@@ -355,10 +355,10 @@ export function ResponsesPage() {
|
|
|
355
355
|
</div>
|
|
356
356
|
) : (
|
|
357
357
|
<div className="flex-1 min-w-0 overflow-auto overscroll-x-contain">
|
|
358
|
-
<div className="min-w-full">
|
|
358
|
+
<div className="w-full min-w-full">
|
|
359
359
|
<table
|
|
360
|
-
className="min-w-full table-fixed text-sm"
|
|
361
|
-
style={{ minWidth: responseTableMinWidth }}
|
|
360
|
+
className="w-full min-w-full table-fixed text-sm"
|
|
361
|
+
style={{ width: "100%", minWidth: responseTableMinWidth }}
|
|
362
362
|
>
|
|
363
363
|
<colgroup>
|
|
364
364
|
<col className="w-16" />
|
|
@@ -366,15 +366,18 @@ export function ResponsesPage() {
|
|
|
366
366
|
{hasSubmitterEmail ? <col className="w-56" /> : null}
|
|
367
367
|
{hasPageUrl ? <col className="w-64" /> : null}
|
|
368
368
|
{hasClientSurface ? <col className="w-40" /> : null}
|
|
369
|
-
{fields.map((f) => (
|
|
370
|
-
<col
|
|
369
|
+
{fields.map((f, index) => (
|
|
370
|
+
<col
|
|
371
|
+
key={f.id}
|
|
372
|
+
className={index === fields.length - 1 ? "w-auto" : "w-80"}
|
|
373
|
+
/>
|
|
371
374
|
))}
|
|
372
375
|
</colgroup>
|
|
373
376
|
<thead>
|
|
374
|
-
<tr className="border-b border-border bg-muted/
|
|
377
|
+
<tr className="border-b border-border bg-muted/40">
|
|
375
378
|
<th
|
|
376
379
|
scope="col"
|
|
377
|
-
className="min-w-16 px-4 py-
|
|
380
|
+
className="min-w-16 px-4 py-3 text-left text-xs font-medium text-muted-foreground whitespace-nowrap"
|
|
378
381
|
>
|
|
379
382
|
#
|
|
380
383
|
</th>
|
|
@@ -423,7 +426,7 @@ export function ResponsesPage() {
|
|
|
423
426
|
{filteredSorted.map((response, idx) => (
|
|
424
427
|
<tr
|
|
425
428
|
key={response.id}
|
|
426
|
-
className="border-b border-border hover:bg-muted/20"
|
|
429
|
+
className="border-b border-border transition-[background-color] duration-150 hover:bg-muted/20 motion-reduce:transition-none"
|
|
427
430
|
>
|
|
428
431
|
<td className="px-4 py-2.5 text-xs text-muted-foreground">
|
|
429
432
|
{filteredSorted.length - idx}
|
|
@@ -525,27 +528,50 @@ function SortableHeader(props: {
|
|
|
525
528
|
}) {
|
|
526
529
|
const t = useT();
|
|
527
530
|
const { label, active, dir, onClick } = props;
|
|
528
|
-
const
|
|
529
|
-
?
|
|
531
|
+
const sortState: "neutral" | "asc" | "desc" = !active
|
|
532
|
+
? "neutral"
|
|
530
533
|
: dir === "asc"
|
|
531
|
-
?
|
|
532
|
-
:
|
|
534
|
+
? "asc"
|
|
535
|
+
: "desc";
|
|
536
|
+
const iconBase =
|
|
537
|
+
"absolute inset-0 transition-[opacity,scale,filter] duration-200 ease-[cubic-bezier(0.2,0,0,1)]";
|
|
538
|
+
const iconVisible = "scale-100 opacity-60 blur-none";
|
|
539
|
+
const iconHidden = "scale-[0.25] opacity-0 blur-[4px]";
|
|
533
540
|
return (
|
|
534
541
|
<th
|
|
535
542
|
scope="col"
|
|
536
|
-
className="min-w-40 px-4 py-
|
|
543
|
+
className="min-w-40 px-4 py-1 text-left text-xs font-medium text-muted-foreground whitespace-nowrap"
|
|
537
544
|
>
|
|
538
545
|
<button
|
|
539
546
|
type="button"
|
|
540
547
|
onClick={onClick}
|
|
541
548
|
className={cn(
|
|
542
|
-
"inline-flex items-center gap-1
|
|
549
|
+
"relative -mx-2 inline-flex min-h-10 cursor-pointer items-center gap-1 rounded-md px-2 transition-[scale,background-color,color,box-shadow] duration-150 ease-out hover:bg-accent hover:text-foreground active:scale-[0.96] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 motion-reduce:transition-none motion-reduce:active:scale-100 sm:min-h-0 sm:before:absolute sm:before:-inset-2.5 sm:before:content-['']",
|
|
543
550
|
active && "text-foreground",
|
|
544
551
|
)}
|
|
545
552
|
aria-label={t("responses.sortBy", { label })}
|
|
546
553
|
>
|
|
547
554
|
{label}
|
|
548
|
-
<
|
|
555
|
+
<span className="relative inline-block h-3 w-3 shrink-0">
|
|
556
|
+
<IconArrowsSort
|
|
557
|
+
className={cn(
|
|
558
|
+
iconBase,
|
|
559
|
+
sortState === "neutral" ? iconVisible : iconHidden,
|
|
560
|
+
)}
|
|
561
|
+
/>
|
|
562
|
+
<IconArrowUp
|
|
563
|
+
className={cn(
|
|
564
|
+
iconBase,
|
|
565
|
+
sortState === "asc" ? iconVisible : iconHidden,
|
|
566
|
+
)}
|
|
567
|
+
/>
|
|
568
|
+
<IconArrowDown
|
|
569
|
+
className={cn(
|
|
570
|
+
iconBase,
|
|
571
|
+
sortState === "desc" ? iconVisible : iconHidden,
|
|
572
|
+
)}
|
|
573
|
+
/>
|
|
574
|
+
</span>
|
|
549
575
|
</button>
|
|
550
576
|
</th>
|
|
551
577
|
);
|
|
@@ -54,7 +54,7 @@ export default function SettingsRoute() {
|
|
|
54
54
|
{t("settings.description")}
|
|
55
55
|
</p>
|
|
56
56
|
|
|
57
|
-
<Card id="language" className="scroll-mt-16">
|
|
57
|
+
<Card id="language" className="forms-settings-card scroll-mt-16">
|
|
58
58
|
<CardHeader>
|
|
59
59
|
<CardTitle className="text-base">
|
|
60
60
|
{t("settings.languageTitle")}
|
|
@@ -61,7 +61,9 @@ Detailed draft, queue, and contact-resolution patterns live in
|
|
|
61
61
|
(`draft-queue` skill), not `send-email` directly. The requester and reviewer
|
|
62
62
|
must both be members of the active organization; Slack intake resolves the
|
|
63
63
|
sender's real email via `users.info` (requires `users:read.email` bot scope)
|
|
64
|
-
before it will queue anything.
|
|
64
|
+
before it will queue anything. Managed installs request that scope through
|
|
65
|
+
the generated OAuth manifest; reconnect an existing Slack install after
|
|
66
|
+
granting it. Legacy bot-token installs must add the scope in Slack manually.
|
|
65
67
|
- Never edit the email store to change a draft the user is currently composing;
|
|
66
68
|
use `manage-draft` or the `compose-{id}` application-state key described in
|
|
67
69
|
`email-drafts`.
|
|
@@ -74,6 +74,7 @@ import {
|
|
|
74
74
|
formatShortcut,
|
|
75
75
|
} from "@/lib/utils";
|
|
76
76
|
|
|
77
|
+
import { buildEmailIframeDocument } from "./email-iframe-document";
|
|
77
78
|
import {
|
|
78
79
|
InlineReplyComposer,
|
|
79
80
|
type InlineReplyHandle,
|
|
@@ -2558,6 +2559,7 @@ function HtmlEmailBody({
|
|
|
2558
2559
|
const frameHostRef = useRef<HTMLDivElement>(null);
|
|
2559
2560
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
2560
2561
|
const [height, setHeight] = useState(200);
|
|
2562
|
+
const [iframeLoadVersion, setIframeLoadVersion] = useState(0);
|
|
2561
2563
|
const { resolvedTheme } = useTheme();
|
|
2562
2564
|
const isDark = getResolvedTheme(resolvedTheme) === "dark";
|
|
2563
2565
|
const sanitizedHtml = useMemo(() => sanitizeEmailHtml(html), [html]);
|
|
@@ -2603,6 +2605,14 @@ function HtmlEmailBody({
|
|
|
2603
2605
|
blockedCount: headBlockedCount + bodyBlockedCount,
|
|
2604
2606
|
};
|
|
2605
2607
|
}, [sanitizedHtml.headHtml, sanitizedHtml.bodyHtml, effectivePolicy]);
|
|
2608
|
+
const iframeDocument = useMemo(
|
|
2609
|
+
() =>
|
|
2610
|
+
buildEmailIframeDocument(
|
|
2611
|
+
processedEmailHtml.headHtml,
|
|
2612
|
+
processedEmailHtml.bodyHtml,
|
|
2613
|
+
),
|
|
2614
|
+
[processedEmailHtml.bodyHtml, processedEmailHtml.headHtml],
|
|
2615
|
+
);
|
|
2606
2616
|
|
|
2607
2617
|
const handleAlwaysTrust = () => {
|
|
2608
2618
|
if (!senderDomain) return;
|
|
@@ -2623,7 +2633,6 @@ function HtmlEmailBody({
|
|
|
2623
2633
|
const doc = iframe.contentDocument;
|
|
2624
2634
|
if (!doc) return;
|
|
2625
2635
|
|
|
2626
|
-
doc.open();
|
|
2627
2636
|
const iframeCss = useDarkIframeCss
|
|
2628
2637
|
? `
|
|
2629
2638
|
html, body {
|
|
@@ -2694,16 +2703,10 @@ function HtmlEmailBody({
|
|
|
2694
2703
|
.quote-toggle:hover, .sig-toggle:hover { color: rgba(0,0,0,0.7); }
|
|
2695
2704
|
`;
|
|
2696
2705
|
|
|
2697
|
-
doc.
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
${processedEmailHtml.headHtml}
|
|
2702
|
-
<style>${iframeCss} </style>
|
|
2703
|
-
</head>
|
|
2704
|
-
<body>${processedEmailHtml.bodyHtml}</body>
|
|
2705
|
-
</html>`);
|
|
2706
|
-
doc.close();
|
|
2706
|
+
const themeStyle = doc.createElement("style");
|
|
2707
|
+
themeStyle.setAttribute("data-mail-theme", "");
|
|
2708
|
+
themeStyle.textContent = iframeCss;
|
|
2709
|
+
doc.head.appendChild(themeStyle);
|
|
2707
2710
|
|
|
2708
2711
|
const resize = () => {
|
|
2709
2712
|
if (doc.body) {
|
|
@@ -3195,6 +3198,7 @@ function HtmlEmailBody({
|
|
|
3195
3198
|
clearTimeout(timer);
|
|
3196
3199
|
clearTimeout(timer2);
|
|
3197
3200
|
images.forEach((img) => img.removeEventListener("load", resize));
|
|
3201
|
+
themeStyle.remove();
|
|
3198
3202
|
};
|
|
3199
3203
|
}, [
|
|
3200
3204
|
processedEmailHtml.bodyHtml,
|
|
@@ -3202,6 +3206,7 @@ function HtmlEmailBody({
|
|
|
3202
3206
|
isDark,
|
|
3203
3207
|
useDarkIframeCss,
|
|
3204
3208
|
IFRAME_BG,
|
|
3209
|
+
iframeLoadVersion,
|
|
3205
3210
|
]);
|
|
3206
3211
|
|
|
3207
3212
|
// Inject / clear search highlights in the iframe whenever searchTerm or content changes
|
|
@@ -3268,7 +3273,7 @@ function HtmlEmailBody({
|
|
|
3268
3273
|
// Small delay to ensure iframe DOM is ready after a processedHtml rewrite
|
|
3269
3274
|
const timer = setTimeout(injectHighlights, 60);
|
|
3270
3275
|
return () => clearTimeout(timer);
|
|
3271
|
-
}, [searchTerm, processedEmailHtml.bodyHtml]);
|
|
3276
|
+
}, [searchTerm, processedEmailHtml.bodyHtml, iframeLoadVersion]);
|
|
3272
3277
|
|
|
3273
3278
|
// Update which mark is "active" and scroll it into view
|
|
3274
3279
|
useEffect(() => {
|
|
@@ -3289,7 +3294,7 @@ function HtmlEmailBody({
|
|
|
3289
3294
|
active.style.color = "#000";
|
|
3290
3295
|
active.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
3291
3296
|
}
|
|
3292
|
-
}, [activeLocalIdx, searchTerm]);
|
|
3297
|
+
}, [activeLocalIdx, searchTerm, iframeLoadVersion]);
|
|
3293
3298
|
|
|
3294
3299
|
const showBanner =
|
|
3295
3300
|
effectivePolicy === "block-all" &&
|
|
@@ -3330,6 +3335,8 @@ function HtmlEmailBody({
|
|
|
3330
3335
|
)}
|
|
3331
3336
|
<iframe
|
|
3332
3337
|
ref={iframeRef}
|
|
3338
|
+
data-agent-native-session-replay=""
|
|
3339
|
+
srcDoc={iframeDocument}
|
|
3333
3340
|
sandbox="allow-same-origin allow-popups allow-popups-to-escape-sandbox"
|
|
3334
3341
|
style={{
|
|
3335
3342
|
width: "100%",
|
|
@@ -3340,6 +3347,7 @@ function HtmlEmailBody({
|
|
|
3340
3347
|
borderRadius: hasDesignedBg && isDark ? "6px" : undefined,
|
|
3341
3348
|
}}
|
|
3342
3349
|
title={t("mail.thread.emailContent")}
|
|
3350
|
+
onLoad={() => setIframeLoadVersion((version) => version + 1)}
|
|
3343
3351
|
/>
|
|
3344
3352
|
</div>
|
|
3345
3353
|
);
|