@flamingo-stack/openframe-frontend-core 0.0.204 → 0.0.205
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/{chunk-4CWSZPXH.cjs → chunk-24KCAECR.cjs} +9 -9
- package/dist/{chunk-4CWSZPXH.cjs.map → chunk-24KCAECR.cjs.map} +1 -1
- package/dist/chunk-27APPAJN.cjs +24 -0
- package/dist/chunk-27APPAJN.cjs.map +1 -0
- package/dist/{chunk-UC43NICZ.cjs → chunk-664KA5FI.cjs} +2 -35
- package/dist/chunk-664KA5FI.cjs.map +1 -0
- package/dist/chunk-6RZYJICV.cjs +24 -0
- package/dist/chunk-6RZYJICV.cjs.map +1 -0
- package/dist/chunk-7L4DWM7P.js +24 -0
- package/dist/chunk-7L4DWM7P.js.map +1 -0
- package/dist/chunk-BZFW3FOF.cjs +21 -0
- package/dist/chunk-BZFW3FOF.cjs.map +1 -0
- package/dist/{chunk-N57KWHDB.js → chunk-CIPO6DXK.js} +5 -5
- package/dist/chunk-EL5YVPD5.js +21 -0
- package/dist/chunk-EL5YVPD5.js.map +1 -0
- package/dist/{chunk-ARQ4XP64.cjs → chunk-FDCFI7YT.cjs} +40080 -31492
- package/dist/chunk-FDCFI7YT.cjs.map +1 -0
- package/dist/chunk-G7UE6RKV.cjs +121 -0
- package/dist/chunk-G7UE6RKV.cjs.map +1 -0
- package/dist/{chunk-25LVV26X.cjs → chunk-JUZGUQMX.cjs} +178 -50
- package/dist/chunk-JUZGUQMX.cjs.map +1 -0
- package/dist/{chunk-SZPJ5R5B.js → chunk-KSOOKNBG.js} +1 -34
- package/dist/chunk-KSOOKNBG.js.map +1 -0
- package/dist/{chunk-RMB5DVED.cjs → chunk-KUZGEA7U.cjs} +83 -66
- package/dist/chunk-KUZGEA7U.cjs.map +1 -0
- package/dist/chunk-LXC6P2EO.js +63 -0
- package/dist/chunk-LXC6P2EO.js.map +1 -0
- package/dist/chunk-MJNXIEV2.js +24 -0
- package/dist/chunk-MJNXIEV2.js.map +1 -0
- package/dist/{chunk-CPXLQ57U.js → chunk-MVGGXOFA.js} +37 -20
- package/dist/chunk-MVGGXOFA.js.map +1 -0
- package/dist/{chunk-LY34ORX6.js → chunk-O55ZUAX7.js} +39920 -31332
- package/dist/chunk-O55ZUAX7.js.map +1 -0
- package/dist/chunk-OHPI2HRK.js +47 -0
- package/dist/chunk-OHPI2HRK.js.map +1 -0
- package/dist/chunk-PLJLE4A4.js +121 -0
- package/dist/chunk-PLJLE4A4.js.map +1 -0
- package/dist/{chunk-XGL5FKIK.js → chunk-SCN5WFIZ.js} +148 -20
- package/dist/chunk-SCN5WFIZ.js.map +1 -0
- package/dist/chunk-WBR7H6E3.cjs +47 -0
- package/dist/chunk-WBR7H6E3.cjs.map +1 -0
- package/dist/chunk-XL4V2PYG.cjs +63 -0
- package/dist/chunk-XL4V2PYG.cjs.map +1 -0
- package/dist/components/announcement-bar.d.ts.map +1 -1
- package/dist/components/chat/chat-attachment-bar.d.ts +66 -0
- package/dist/components/chat/chat-attachment-bar.d.ts.map +1 -0
- package/dist/components/chat/chat-container.d.ts +21 -1
- package/dist/components/chat/chat-container.d.ts.map +1 -1
- package/dist/components/chat/chat-input.d.ts.map +1 -1
- package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
- package/dist/components/chat/chat-message-list.d.ts.map +1 -1
- package/dist/components/chat/chat-panel-context.d.ts +9 -0
- package/dist/components/chat/chat-panel-context.d.ts.map +1 -0
- package/dist/components/chat/chat-ticket-list.d.ts +1 -1
- package/dist/components/chat/chat-ticket-list.d.ts.map +1 -1
- package/dist/components/chat/embeddable-chat.d.ts +42 -0
- package/dist/components/chat/embeddable-chat.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/admin-content-card.d.ts +34 -0
- package/dist/components/chat/entity-cards/admin-content-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/block-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/blog-card.d.ts +30 -0
- package/dist/components/chat/entity-cards/blog-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/blog-image-placeholder.d.ts +26 -0
- package/dist/components/chat/entity-cards/blog-image-placeholder.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/campaign-card-admin.d.ts +33 -0
- package/dist/components/chat/entity-cards/campaign-card-admin.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/case-study-card.d.ts +20 -0
- package/dist/components/chat/entity-cards/case-study-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/chat-ticket-item.d.ts.map +1 -0
- package/dist/components/chat/{chat-video-entity-card.d.ts → entity-cards/chat-video-entity-card.d.ts} +1 -1
- package/dist/components/chat/entity-cards/chat-video-entity-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/customer-interview-card.d.ts +19 -0
- package/dist/components/chat/entity-cards/customer-interview-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/data-room-doc-card.d.ts +47 -0
- package/dist/components/chat/entity-cards/data-room-doc-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/dispatch.d.ts +119 -0
- package/dist/components/chat/entity-cards/dispatch.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/entity-author-card.d.ts +87 -0
- package/dist/components/chat/entity-cards/entity-author-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/generic-entity-card.d.ts +42 -0
- package/dist/components/chat/entity-cards/generic-entity-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/github-activity-card.d.ts +37 -0
- package/dist/components/chat/entity-cards/github-activity-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/hubspot-ticket-card.d.ts +28 -0
- package/dist/components/chat/entity-cards/hubspot-ticket-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/index.d.ts +32 -0
- package/dist/components/chat/entity-cards/index.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/investor-update-card.d.ts +19 -0
- package/dist/components/chat/entity-cards/investor-update-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/onboarding-guide-card.d.ts +20 -0
- package/dist/components/chat/entity-cards/onboarding-guide-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/product-release-card-defaults.d.ts +21 -0
- package/dist/components/chat/entity-cards/product-release-card-defaults.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/product-release-card.d.ts +12 -0
- package/dist/components/chat/entity-cards/product-release-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/program-card-defaults.d.ts +32 -0
- package/dist/components/chat/entity-cards/program-card-defaults.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/program-card.d.ts +37 -0
- package/dist/components/chat/entity-cards/program-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/roadmap-card.d.ts +28 -0
- package/dist/components/chat/entity-cards/roadmap-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/roadmap-vote-button.d.ts +12 -0
- package/dist/components/chat/entity-cards/roadmap-vote-button.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/slack-message-card.d.ts +28 -0
- package/dist/components/chat/entity-cards/slack-message-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/task-type-icon.d.ts +6 -0
- package/dist/components/chat/entity-cards/task-type-icon.d.ts.map +1 -0
- package/dist/components/chat/hooks/index.d.ts +10 -0
- package/dist/components/chat/hooks/index.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-chat-attachment-image-gallery.d.ts +5 -0
- package/dist/components/chat/hooks/use-chat-attachment-image-gallery.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-chat-attachments.d.ts +33 -0
- package/dist/components/chat/hooks/use-chat-attachments.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-chat-card-item.d.ts +7 -0
- package/dist/components/chat/hooks/use-chat-card-item.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-chat-identity.d.ts +44 -0
- package/dist/components/chat/hooks/use-chat-identity.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-chat.d.ts +30 -0
- package/dist/components/chat/hooks/use-chat.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-close-on-navigation.d.ts +2 -0
- package/dist/components/chat/hooks/use-close-on-navigation.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-embedded-chat.d.ts +174 -0
- package/dist/components/chat/hooks/use-embedded-chat.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-proxied-image-url.d.ts +18 -0
- package/dist/components/chat/hooks/use-proxied-image-url.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-slash-commands.d.ts +32 -0
- package/dist/components/chat/hooks/use-slash-commands.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-sse.d.ts +57 -0
- package/dist/components/chat/hooks/use-sse.d.ts.map +1 -0
- package/dist/components/chat/index.cjs +393 -0
- package/dist/components/chat/index.cjs.map +1 -0
- package/dist/components/chat/index.d.ts +5 -3
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +393 -0
- package/dist/components/chat/index.js.map +1 -0
- package/dist/components/chat/nav-link-anchor-via-runtime.d.ts +33 -0
- package/dist/components/chat/nav-link-anchor-via-runtime.d.ts.map +1 -0
- package/dist/components/chat/source-action-button.d.ts +39 -0
- package/dist/components/chat/source-action-button.d.ts.map +1 -0
- package/dist/components/chat/types/chat.types.d.ts +36 -0
- package/dist/components/chat/types/chat.types.d.ts.map +1 -1
- package/dist/components/chat/types/component.types.d.ts +56 -11
- package/dist/components/chat/types/component.types.d.ts.map +1 -1
- package/dist/components/chat/types/entities/blog.d.ts +14 -0
- package/dist/components/chat/types/entities/blog.d.ts.map +1 -0
- package/dist/components/chat/types/entities/case-study.d.ts +10 -0
- package/dist/components/chat/types/entities/case-study.d.ts.map +1 -0
- package/dist/components/chat/types/entities/content-ref.d.ts +23 -0
- package/dist/components/chat/types/entities/content-ref.d.ts.map +1 -0
- package/dist/components/chat/types/entities/customer-interview.d.ts +10 -0
- package/dist/components/chat/types/entities/customer-interview.d.ts.map +1 -0
- package/dist/components/chat/types/entities/data-room-doc.d.ts +37 -0
- package/dist/components/chat/types/entities/data-room-doc.d.ts.map +1 -0
- package/dist/components/chat/types/entities/github-activity.d.ts +29 -0
- package/dist/components/chat/types/entities/github-activity.d.ts.map +1 -0
- package/dist/components/chat/types/entities/hubspot-ticket.d.ts +39 -0
- package/dist/components/chat/types/entities/hubspot-ticket.d.ts.map +1 -0
- package/dist/components/chat/types/entities/index.d.ts +28 -0
- package/dist/components/chat/types/entities/index.d.ts.map +1 -0
- package/dist/components/chat/types/entities/investor-update.d.ts +83 -0
- package/dist/components/chat/types/entities/investor-update.d.ts.map +1 -0
- package/dist/components/chat/types/entities/onboarding-guide.d.ts +79 -0
- package/dist/components/chat/types/entities/onboarding-guide.d.ts.map +1 -0
- package/dist/components/chat/types/entities/program-types.d.ts +303 -0
- package/dist/components/chat/types/entities/program-types.d.ts.map +1 -0
- package/dist/components/chat/types/entities/roadmap-item.d.ts +41 -0
- package/dist/components/chat/types/entities/roadmap-item.d.ts.map +1 -0
- package/dist/components/chat/types/entities/slack-message.d.ts +28 -0
- package/dist/components/chat/types/entities/slack-message.d.ts.map +1 -0
- package/dist/components/chat/types/index.d.ts +1 -0
- package/dist/components/chat/types/index.d.ts.map +1 -1
- package/dist/components/chat/utils/agent-status-message.d.ts +18 -0
- package/dist/components/chat/utils/agent-status-message.d.ts.map +1 -0
- package/dist/components/chat/utils/auto-continuation-directive.d.ts +38 -0
- package/dist/components/chat/utils/auto-continuation-directive.d.ts.map +1 -0
- package/dist/components/chat/utils/chat-attachment-markdown.d.ts +114 -0
- package/dist/components/chat/utils/chat-attachment-markdown.d.ts.map +1 -0
- package/dist/components/chat/utils/chat-authed-fetch.d.ts +13 -0
- package/dist/components/chat/utils/chat-authed-fetch.d.ts.map +1 -0
- package/dist/components/chat/utils/chat-nav-resolution.d.ts +72 -0
- package/dist/components/chat/utils/chat-nav-resolution.d.ts.map +1 -0
- package/dist/components/chat/utils/chat-proxy-auth-storage.d.ts +43 -0
- package/dist/components/chat/utils/chat-proxy-auth-storage.d.ts.map +1 -0
- package/dist/components/chat/utils/chip-action-class.d.ts +16 -0
- package/dist/components/chat/utils/chip-action-class.d.ts.map +1 -0
- package/dist/components/chat/utils/chip-styles.d.ts +32 -0
- package/dist/components/chat/utils/chip-styles.d.ts.map +1 -0
- package/dist/components/chat/utils/clickup-task-type-utils.d.ts +38 -0
- package/dist/components/chat/utils/clickup-task-type-utils.d.ts.map +1 -0
- package/dist/components/chat/utils/compact-card-classes.d.ts +50 -0
- package/dist/components/chat/utils/compact-card-classes.d.ts.map +1 -0
- package/dist/components/chat/utils/decide-new-tab.d.ts +39 -0
- package/dist/components/chat/utils/decide-new-tab.d.ts.map +1 -0
- package/dist/components/chat/utils/external-app-urls.d.ts +14 -0
- package/dist/components/chat/utils/external-app-urls.d.ts.map +1 -0
- package/dist/components/chat/utils/flatten-assistant-content.d.ts +25 -0
- package/dist/components/chat/utils/flatten-assistant-content.d.ts.map +1 -0
- package/dist/components/chat/utils/icon-registry.d.ts +67 -0
- package/dist/components/chat/utils/icon-registry.d.ts.map +1 -0
- package/dist/components/chat/utils/index.d.ts +21 -0
- package/dist/components/chat/utils/index.d.ts.map +1 -1
- package/dist/components/chat/utils/is-cross-origin-url.d.ts +22 -0
- package/dist/components/chat/utils/is-cross-origin-url.d.ts.map +1 -0
- package/dist/components/chat/utils/nav-anchor-props.d.ts +54 -0
- package/dist/components/chat/utils/nav-anchor-props.d.ts.map +1 -0
- package/dist/components/chat/utils/nav-click-handler.d.ts +51 -0
- package/dist/components/chat/utils/nav-click-handler.d.ts.map +1 -0
- package/dist/components/chat/utils/scroll-anchor.d.ts +30 -0
- package/dist/components/chat/utils/scroll-anchor.d.ts.map +1 -0
- package/dist/components/chat/utils/slash-dispatch-utils.d.ts +109 -0
- package/dist/components/chat/utils/slash-dispatch-utils.d.ts.map +1 -0
- package/dist/components/chat/utils/source-icons.d.ts +8 -0
- package/dist/components/chat/utils/source-icons.d.ts.map +1 -0
- package/dist/components/chat/utils/source-row-cta.d.ts +111 -0
- package/dist/components/chat/utils/source-row-cta.d.ts.map +1 -0
- package/dist/components/features/figma-prototype-viewer.d.ts.map +1 -1
- package/dist/components/features/index.cjs +12 -6
- package/dist/components/features/index.cjs.map +1 -1
- package/dist/components/features/index.js +11 -5
- package/dist/components/features/video.d.ts.map +1 -1
- package/dist/components/icons/index.cjs +3 -3
- package/dist/components/icons/index.js +2 -2
- package/dist/components/index.cjs +274 -8
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +273 -7
- package/dist/components/interactive-wrapper.d.ts +3 -3
- package/dist/components/navigation/index.cjs +12 -6
- package/dist/components/navigation/index.cjs.map +1 -1
- package/dist/components/navigation/index.js +11 -5
- package/dist/components/resizable.d.ts +1 -1
- package/dist/components/shared/product-release/product-release-card-skeleton.d.ts +1 -1
- package/dist/components/shared/product-release/product-release-card-skeleton.d.ts.map +1 -1
- package/dist/components/shared/product-release/product-release-card.d.ts +19 -12
- package/dist/components/shared/product-release/product-release-card.d.ts.map +1 -1
- package/dist/components/shared/product-release/release-detail-page.d.ts +2 -4
- package/dist/components/shared/product-release/release-detail-page.d.ts.map +1 -1
- package/dist/components/ui/button/button.d.ts +13 -0
- package/dist/components/ui/button/button.d.ts.map +1 -1
- package/dist/components/ui/dashboard-info-card.d.ts.map +1 -1
- package/dist/components/ui/entity-image.d.ts.map +1 -1
- package/dist/components/ui/file-manager/index.cjs +71 -70
- package/dist/components/ui/file-manager/index.cjs.map +1 -1
- package/dist/components/ui/file-manager/index.js +6 -5
- package/dist/components/ui/file-manager/index.js.map +1 -1
- package/dist/components/ui/hover-dropdown.d.ts +66 -0
- package/dist/components/ui/hover-dropdown.d.ts.map +1 -0
- package/dist/components/ui/index.cjs +276 -6
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.d.ts +1 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +278 -8
- package/dist/components/ui/simple-markdown-renderer.d.ts.map +1 -1
- package/dist/components/ui/square-avatar.d.ts.map +1 -1
- package/dist/contexts/chat-runtime-context.d.ts +109 -0
- package/dist/contexts/chat-runtime-context.d.ts.map +1 -0
- package/dist/contexts/endpoints-runtime-context.d.ts +28 -0
- package/dist/contexts/endpoints-runtime-context.d.ts.map +1 -0
- package/dist/contexts/index.cjs +30 -0
- package/dist/contexts/index.cjs.map +1 -0
- package/dist/contexts/index.d.ts +26 -0
- package/dist/contexts/index.d.ts.map +1 -0
- package/dist/contexts/index.js +30 -0
- package/dist/contexts/index.js.map +1 -0
- package/dist/contexts/use-outer-or-default.d.ts +29 -0
- package/dist/contexts/use-outer-or-default.d.ts.map +1 -0
- package/dist/embed-shims/index.cjs +51 -0
- package/dist/embed-shims/index.cjs.map +1 -0
- package/dist/embed-shims/index.d.ts +31 -0
- package/dist/embed-shims/index.d.ts.map +1 -0
- package/dist/embed-shims/index.js +51 -0
- package/dist/embed-shims/index.js.map +1 -0
- package/dist/embed-shims/next-dynamic.cjs +12 -0
- package/dist/embed-shims/next-dynamic.cjs.map +1 -0
- package/dist/embed-shims/next-dynamic.d.ts +47 -0
- package/dist/embed-shims/next-dynamic.d.ts.map +1 -0
- package/dist/embed-shims/next-dynamic.js +12 -0
- package/dist/embed-shims/next-dynamic.js.map +1 -0
- package/dist/embed-shims/next-image.cjs +12 -0
- package/dist/embed-shims/next-image.cjs.map +1 -0
- package/dist/embed-shims/next-image.d.ts +28 -0
- package/dist/embed-shims/next-image.d.ts.map +1 -0
- package/dist/embed-shims/next-image.js +12 -0
- package/dist/embed-shims/next-image.js.map +1 -0
- package/dist/embed-shims/next-link.cjs +14 -0
- package/dist/embed-shims/next-link.cjs.map +1 -0
- package/dist/embed-shims/next-link.d.ts +22 -0
- package/dist/embed-shims/next-link.d.ts.map +1 -0
- package/dist/embed-shims/next-link.js +14 -0
- package/dist/embed-shims/next-link.js.map +1 -0
- package/dist/embed-shims/next-navigation.cjs +30 -0
- package/dist/embed-shims/next-navigation.cjs.map +1 -0
- package/dist/embed-shims/next-navigation.d.ts +46 -0
- package/dist/embed-shims/next-navigation.d.ts.map +1 -0
- package/dist/embed-shims/next-navigation.js +30 -0
- package/dist/embed-shims/next-navigation.js.map +1 -0
- package/dist/hooks/index.cjs +10 -4
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +9 -3
- package/dist/hooks/use-access-code-integration.d.ts +48 -0
- package/dist/hooks/use-access-code-integration.d.ts.map +1 -0
- package/dist/hooks/use-contact-submission.d.ts.map +1 -1
- package/dist/hooks/use-og-placeholder.d.ts +31 -0
- package/dist/hooks/use-og-placeholder.d.ts.map +1 -0
- package/dist/hooks/use-toast.d.ts +1 -1
- package/dist/index.cjs +367 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +378 -18
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/access-code-client.d.ts +21 -37
- package/dist/utils/access-code-client.d.ts.map +1 -1
- package/dist/utils/cn.d.ts +0 -27
- package/dist/utils/cn.d.ts.map +1 -1
- package/dist/utils/color-analysis.d.ts +33 -0
- package/dist/utils/color-analysis.d.ts.map +1 -0
- package/dist/utils/date-formatters.d.ts +16 -5
- package/dist/utils/date-formatters.d.ts.map +1 -1
- package/dist/utils/fetch-priority.d.ts +3 -0
- package/dist/utils/fetch-priority.d.ts.map +1 -0
- package/dist/utils/format.d.ts +192 -1
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/image-proxy.d.ts +67 -2
- package/dist/utils/image-proxy.d.ts.map +1 -1
- package/dist/utils/index.cjs +1274 -155
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.ts +19 -3
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1200 -157
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/local-storage-adapter.d.ts +46 -0
- package/dist/utils/local-storage-adapter.d.ts.map +1 -0
- package/dist/utils/source-icons.d.ts +78 -0
- package/dist/utils/source-icons.d.ts.map +1 -0
- package/package.json +29 -2
- package/src/components/announcement-bar.tsx +26 -4
- package/src/components/categories-cart.tsx +1 -1
- package/src/components/chat/chat-attachment-bar.tsx +323 -0
- package/src/components/chat/chat-container.tsx +39 -5
- package/src/components/chat/chat-input.tsx +7 -1
- package/src/components/chat/chat-message-enhanced.tsx +32 -22
- package/src/components/chat/chat-message-list.tsx +53 -4
- package/src/components/chat/chat-panel-context.tsx +37 -0
- package/src/components/chat/chat-ticket-list.tsx +1 -1
- package/src/components/chat/embeddable-chat.tsx +1106 -0
- package/src/components/chat/entity-cards/admin-content-card.tsx +155 -0
- package/src/components/chat/entity-cards/blog-card.tsx +259 -0
- package/src/components/chat/entity-cards/blog-image-placeholder.tsx +52 -0
- package/src/components/chat/entity-cards/campaign-card-admin.tsx +113 -0
- package/src/components/chat/entity-cards/case-study-card.tsx +192 -0
- package/src/components/chat/{chat-ticket-item.tsx → entity-cards/chat-ticket-item.tsx} +2 -2
- package/src/components/chat/{chat-video-entity-card.tsx → entity-cards/chat-video-entity-card.tsx} +2 -2
- package/src/components/chat/entity-cards/customer-interview-card.tsx +211 -0
- package/src/components/chat/entity-cards/data-room-doc-card.tsx +120 -0
- package/src/components/chat/entity-cards/dispatch.tsx +1093 -0
- package/src/components/chat/entity-cards/entity-author-card.tsx +193 -0
- package/src/components/chat/entity-cards/generic-entity-card.tsx +144 -0
- package/src/components/chat/entity-cards/github-activity-card.tsx +305 -0
- package/src/components/chat/entity-cards/hubspot-ticket-card.tsx +205 -0
- package/src/components/chat/entity-cards/index.ts +125 -0
- package/src/components/chat/entity-cards/investor-update-card.tsx +150 -0
- package/src/components/chat/entity-cards/onboarding-guide-card.tsx +326 -0
- package/src/components/chat/entity-cards/product-release-card-defaults.ts +57 -0
- package/src/components/chat/entity-cards/product-release-card.tsx +19 -0
- package/src/components/chat/entity-cards/program-card-defaults.ts +62 -0
- package/src/components/chat/entity-cards/program-card.tsx +451 -0
- package/src/components/chat/entity-cards/roadmap-card.tsx +356 -0
- package/src/components/chat/entity-cards/roadmap-vote-button.tsx +54 -0
- package/src/components/chat/entity-cards/slack-message-card.tsx +182 -0
- package/src/components/chat/entity-cards/task-type-icon.tsx +60 -0
- package/src/components/chat/hooks/index.ts +22 -0
- package/src/components/chat/hooks/use-chat-attachment-image-gallery.tsx +114 -0
- package/src/components/chat/hooks/use-chat-attachments.ts +429 -0
- package/src/components/chat/hooks/use-chat-card-item.ts +102 -0
- package/src/components/chat/hooks/use-chat-identity.ts +139 -0
- package/src/components/chat/hooks/use-chat.ts +501 -0
- package/src/components/chat/hooks/use-close-on-navigation.ts +87 -0
- package/src/components/chat/hooks/use-embedded-chat.ts +1023 -0
- package/src/components/chat/hooks/use-proxied-image-url.ts +31 -0
- package/src/components/chat/hooks/use-slash-commands.ts +106 -0
- package/src/components/chat/hooks/use-sse.ts +143 -0
- package/src/components/chat/index.ts +30 -4
- package/src/components/chat/nav-link-anchor-via-runtime.tsx +72 -0
- package/src/components/chat/source-action-button.tsx +120 -0
- package/src/components/chat/types/chat.types.ts +61 -0
- package/src/components/chat/types/component.types.ts +57 -11
- package/src/components/chat/types/entities/blog.ts +27 -0
- package/src/components/chat/types/entities/case-study.ts +14 -0
- package/src/components/chat/types/entities/content-ref.ts +23 -0
- package/src/components/chat/types/entities/customer-interview.ts +15 -0
- package/src/components/chat/types/entities/data-room-doc.ts +37 -0
- package/src/components/chat/types/entities/github-activity.ts +36 -0
- package/src/components/chat/types/entities/hubspot-ticket.ts +39 -0
- package/src/components/chat/types/entities/index.ts +28 -0
- package/src/components/chat/types/entities/investor-update.ts +100 -0
- package/src/components/chat/types/entities/onboarding-guide.ts +101 -0
- package/src/components/chat/types/entities/program-types.ts +433 -0
- package/src/components/chat/types/entities/roadmap-item.ts +42 -0
- package/src/components/chat/types/entities/slack-message.ts +28 -0
- package/src/components/chat/types/index.ts +1 -0
- package/src/components/chat/utils/agent-status-message.ts +52 -0
- package/src/components/chat/utils/auto-continuation-directive.ts +70 -0
- package/src/components/chat/utils/chat-attachment-markdown.ts +190 -0
- package/src/components/chat/utils/chat-authed-fetch.ts +73 -0
- package/src/components/chat/utils/chat-nav-resolution.ts +151 -0
- package/src/components/chat/utils/chat-proxy-auth-storage.ts +148 -0
- package/src/components/chat/utils/chip-action-class.ts +19 -0
- package/src/components/chat/utils/chip-styles.ts +51 -0
- package/src/components/chat/utils/clickup-task-type-utils.ts +59 -0
- package/src/components/chat/utils/compact-card-classes.ts +97 -0
- package/src/components/chat/utils/decide-new-tab.ts +57 -0
- package/src/components/chat/utils/external-app-urls.ts +19 -0
- package/src/components/chat/utils/flatten-assistant-content.ts +35 -0
- package/src/components/chat/utils/icon-registry.ts +297 -0
- package/src/components/chat/utils/index.ts +133 -0
- package/src/components/chat/utils/is-cross-origin-url.ts +28 -0
- package/src/components/chat/utils/nav-anchor-props.ts +78 -0
- package/src/components/chat/utils/nav-click-handler.ts +81 -0
- package/src/components/chat/utils/scroll-anchor.ts +35 -0
- package/src/components/chat/utils/slash-dispatch-utils.ts +183 -0
- package/src/components/chat/utils/source-icons.ts +14 -0
- package/src/components/chat/utils/source-row-cta.ts +215 -0
- package/src/components/empty-state.tsx +1 -1
- package/src/components/features/board/ticket-card.tsx +1 -1
- package/src/components/features/figma-prototype-viewer.tsx +2 -1
- package/src/components/features/media-gallery-manager.tsx +1 -1
- package/src/components/features/parallax-image-showcase.tsx +1 -1
- package/src/components/features/release-media-manager.tsx +1 -1
- package/src/components/features/seo-editor-preview.tsx +1 -1
- package/src/components/features/video.tsx +54 -3
- package/src/components/footer-waitlist-button.tsx +1 -1
- package/src/components/navigation/header.tsx +1 -1
- package/src/components/shared/onboarding/onboarding-step-card.tsx +1 -1
- package/src/components/shared/product-release/product-release-card-skeleton.tsx +8 -44
- package/src/components/shared/product-release/product-release-card.tsx +31 -116
- package/src/components/shared/product-release/release-detail-page.tsx +12 -16
- package/src/components/ui/actions-menu.tsx +1 -1
- package/src/components/ui/button/button.tsx +41 -11
- package/src/components/ui/button/split-button.tsx +1 -1
- package/src/components/ui/dashboard-info-card.tsx +2 -3
- package/src/components/ui/data-table/data-table-row.tsx +1 -1
- package/src/components/ui/entity-image.tsx +2 -8
- package/src/components/ui/hover-dropdown.tsx +258 -0
- package/src/components/ui/image-gallery-modal.tsx +1 -1
- package/src/components/ui/index.ts +1 -0
- package/src/components/ui/markdown-editor.tsx +1 -1
- package/src/components/ui/more-actions-menu.tsx +1 -1
- package/src/components/ui/organization-card.tsx +1 -1
- package/src/components/ui/simple-markdown-renderer.tsx +53 -5
- package/src/components/ui/square-avatar.tsx +3 -12
- package/src/components/ui/tab-navigation.tsx +1 -1
- package/src/components/ui/table/table-row.tsx +1 -1
- package/src/components/unified-filter-logic.tsx +1 -1
- package/src/components/unified-pagination.tsx +1 -1
- package/src/components/user-summary-stub.tsx +1 -1
- package/src/components/vendor-display-button.tsx +1 -1
- package/src/components/vendor-icon.tsx +1 -1
- package/src/contexts/chat-runtime-context.tsx +163 -0
- package/src/contexts/endpoints-runtime-context.tsx +68 -0
- package/src/contexts/index.ts +38 -0
- package/src/contexts/use-outer-or-default.ts +42 -0
- package/src/embed-shims/index.ts +42 -0
- package/src/embed-shims/next-dynamic.tsx +70 -0
- package/src/embed-shims/next-image.tsx +114 -0
- package/src/embed-shims/next-link.tsx +91 -0
- package/src/embed-shims/next-navigation.tsx +201 -0
- package/src/hooks/index.ts +9 -0
- package/src/hooks/state/use-api-params.ts +1 -1
- package/src/hooks/state/use-query-params.ts +1 -1
- package/src/hooks/use-access-code-integration.ts +107 -0
- package/src/hooks/use-contact-submission.ts +7 -3
- package/src/hooks/use-og-placeholder.ts +45 -0
- package/src/stories/OnboardingStepCard.stories.tsx +140 -0
- package/src/styles/chat-animations.css +65 -0
- package/src/styles/index.css +1 -0
- package/src/utils/access-code-client.ts +32 -75
- package/src/utils/cn.ts +0 -65
- package/src/utils/color-analysis.ts +205 -0
- package/src/utils/date-formatters.ts +54 -11
- package/src/utils/fetch-priority.ts +41 -0
- package/src/utils/format.ts +525 -1
- package/src/utils/image-proxy.ts +127 -7
- package/src/utils/index.ts +145 -5
- package/src/utils/local-storage-adapter.ts +105 -0
- package/src/utils/source-icons.ts +219 -0
- package/dist/chunk-25LVV26X.cjs.map +0 -1
- package/dist/chunk-ARQ4XP64.cjs.map +0 -1
- package/dist/chunk-CPXLQ57U.js.map +0 -1
- package/dist/chunk-LY34ORX6.js.map +0 -1
- package/dist/chunk-RMB5DVED.cjs.map +0 -1
- package/dist/chunk-SZPJ5R5B.js.map +0 -1
- package/dist/chunk-UC43NICZ.cjs.map +0 -1
- package/dist/chunk-XGL5FKIK.js.map +0 -1
- package/dist/components/chat/block-card.d.ts.map +0 -1
- package/dist/components/chat/chat-ticket-item.d.ts.map +0 -1
- package/dist/components/chat/chat-video-entity-card.d.ts.map +0 -1
- package/dist/utils/dynamic-icons.d.ts +0 -26
- package/dist/utils/dynamic-icons.d.ts.map +0 -1
- package/dist/utils/format-relative-time.d.ts +0 -21
- package/dist/utils/format-relative-time.d.ts.map +0 -1
- package/src/utils/.dynamic-icons.md +0 -30
- package/src/utils/.format-relative-time.md +0 -36
- package/src/utils/dynamic-icons.tsx +0 -120
- package/src/utils/format-relative-time.ts +0 -52
- /package/dist/{chunk-N57KWHDB.js.map → chunk-CIPO6DXK.js.map} +0 -0
- /package/dist/components/chat/{block-card.d.ts → entity-cards/block-card.d.ts} +0 -0
- /package/dist/components/chat/{chat-ticket-item.d.ts → entity-cards/chat-ticket-item.d.ts} +0 -0
- /package/src/components/chat/{block-card.tsx → entity-cards/block-card.tsx} +0 -0
package/dist/utils/index.cjs
CHANGED
|
@@ -22,35 +22,6 @@ var twMerge = tailwindMerge.extendTailwindMerge({
|
|
|
22
22
|
function cn(...inputs) {
|
|
23
23
|
return twMerge(clsx.clsx(inputs));
|
|
24
24
|
}
|
|
25
|
-
function formatDate(date, options = {
|
|
26
|
-
year: "numeric",
|
|
27
|
-
month: "long",
|
|
28
|
-
day: "numeric"
|
|
29
|
-
}) {
|
|
30
|
-
const dateObj = typeof date === "string" ? new Date(date) : date;
|
|
31
|
-
if (isNaN(dateObj.getTime())) {
|
|
32
|
-
console.warn("Invalid date provided to formatDate:", date);
|
|
33
|
-
return "Invalid Date";
|
|
34
|
-
}
|
|
35
|
-
return dateObj.toLocaleDateString("en-US", options);
|
|
36
|
-
}
|
|
37
|
-
function formatNumber(num) {
|
|
38
|
-
return num.toLocaleString();
|
|
39
|
-
}
|
|
40
|
-
function formatPrice(price, currency = "USD") {
|
|
41
|
-
return new Intl.NumberFormat("en-US", {
|
|
42
|
-
style: "currency",
|
|
43
|
-
currency
|
|
44
|
-
}).format(price);
|
|
45
|
-
}
|
|
46
|
-
function formatBytes(bytes, decimals = 2) {
|
|
47
|
-
if (bytes === 0) return "0 Bytes";
|
|
48
|
-
const k = 1024;
|
|
49
|
-
const dm = decimals < 0 ? 0 : decimals;
|
|
50
|
-
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
51
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
52
|
-
return Number.parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
|
|
53
|
-
}
|
|
54
25
|
function getPlatformProductionUrl(platform) {
|
|
55
26
|
switch (platform) {
|
|
56
27
|
// *-hub platforms — env var convention: NEXT_PUBLIC_<NAME>_HUB_URL
|
|
@@ -133,6 +104,304 @@ function getBaseUrl(platform) {
|
|
|
133
104
|
}
|
|
134
105
|
return "https://www.openmsp.ai";
|
|
135
106
|
}
|
|
107
|
+
|
|
108
|
+
// src/utils/format.ts
|
|
109
|
+
function formatDate(date, options = {
|
|
110
|
+
year: "numeric",
|
|
111
|
+
month: "long",
|
|
112
|
+
day: "numeric"
|
|
113
|
+
}) {
|
|
114
|
+
const dateObj = typeof date === "string" ? new Date(date) : date;
|
|
115
|
+
if (isNaN(dateObj.getTime())) {
|
|
116
|
+
console.warn("Invalid date provided to formatDate:", date);
|
|
117
|
+
return "Invalid Date";
|
|
118
|
+
}
|
|
119
|
+
return dateObj.toLocaleDateString("en-US", options);
|
|
120
|
+
}
|
|
121
|
+
function formatNumber(num) {
|
|
122
|
+
return num.toLocaleString();
|
|
123
|
+
}
|
|
124
|
+
function formatPrice(price, currency = "USD") {
|
|
125
|
+
return new Intl.NumberFormat("en-US", {
|
|
126
|
+
style: "currency",
|
|
127
|
+
currency
|
|
128
|
+
}).format(price);
|
|
129
|
+
}
|
|
130
|
+
function formatBytes(bytes, decimals = 2) {
|
|
131
|
+
if (bytes === 0) return "0 Bytes";
|
|
132
|
+
const k = 1024;
|
|
133
|
+
const dm = decimals < 0 ? 0 : decimals;
|
|
134
|
+
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
135
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
136
|
+
return Number.parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
|
|
137
|
+
}
|
|
138
|
+
function formatBytesShort(bytes) {
|
|
139
|
+
if (bytes === 0) return "0 B";
|
|
140
|
+
const k = 1024;
|
|
141
|
+
const sizes = ["B", "KB", "MB", "GB", "TB"];
|
|
142
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
143
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
144
|
+
}
|
|
145
|
+
function formatLargeNumber(num) {
|
|
146
|
+
if (num === 0) return "0";
|
|
147
|
+
const isNegative = num < 0;
|
|
148
|
+
const absNum = Math.abs(num);
|
|
149
|
+
let result;
|
|
150
|
+
if (absNum >= 1e9) {
|
|
151
|
+
result = `${Math.floor(absNum / 1e9)}B`;
|
|
152
|
+
} else if (absNum >= 1e6) {
|
|
153
|
+
result = `${Math.floor(absNum / 1e6)}M`;
|
|
154
|
+
} else if (absNum >= 1e3) {
|
|
155
|
+
result = `${Math.floor(absNum / 1e3)}K`;
|
|
156
|
+
} else {
|
|
157
|
+
result = Math.floor(absNum).toString();
|
|
158
|
+
}
|
|
159
|
+
return isNegative ? `-${result}` : result;
|
|
160
|
+
}
|
|
161
|
+
function formatAbbreviatedNumber(n) {
|
|
162
|
+
if (n >= 1e9) {
|
|
163
|
+
const value = n / 1e9;
|
|
164
|
+
return `${Number.isInteger(value) ? value.toFixed(0) : value.toFixed(1)}B`;
|
|
165
|
+
}
|
|
166
|
+
if (n >= 1e6) {
|
|
167
|
+
const value = n / 1e6;
|
|
168
|
+
return `${Number.isInteger(value) ? value.toFixed(0) : value.toFixed(1)}M`;
|
|
169
|
+
}
|
|
170
|
+
if (n >= 1e3) {
|
|
171
|
+
const value = n / 1e3;
|
|
172
|
+
return `${Number.isInteger(value) ? value.toFixed(0) : value.toFixed(1)}K`;
|
|
173
|
+
}
|
|
174
|
+
return n.toLocaleString();
|
|
175
|
+
}
|
|
176
|
+
function getFirstLastInitials(name) {
|
|
177
|
+
if (!name) return "";
|
|
178
|
+
const words = name.trim().split(/\s+/);
|
|
179
|
+
if (words.length === 0 || !words[0]) return "";
|
|
180
|
+
if (words.length === 1) return words[0].charAt(0).toUpperCase();
|
|
181
|
+
return (words[0].charAt(0) + words[words.length - 1].charAt(0)).toUpperCase();
|
|
182
|
+
}
|
|
183
|
+
function nameInitials(name, fallback = "E") {
|
|
184
|
+
const source = typeof name === "string" ? name.trim() : "";
|
|
185
|
+
const words = source.length > 0 ? source.split(/\s+/) : [];
|
|
186
|
+
const letters = words.map((w) => w[0]).filter(Boolean).slice(0, 2).join("");
|
|
187
|
+
return (letters || fallback).toUpperCase();
|
|
188
|
+
}
|
|
189
|
+
function formatDurationMMSS(seconds) {
|
|
190
|
+
if (!seconds) return "";
|
|
191
|
+
const hours = Math.floor(seconds / 3600);
|
|
192
|
+
const minutes = Math.floor(seconds % 3600 / 60);
|
|
193
|
+
const secs = Math.floor(seconds % 60);
|
|
194
|
+
if (hours > 0) {
|
|
195
|
+
return `${hours}:${minutes.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
|
|
196
|
+
}
|
|
197
|
+
return `${minutes}:${secs.toString().padStart(2, "0")}`;
|
|
198
|
+
}
|
|
199
|
+
function formatDurationCompact(seconds) {
|
|
200
|
+
if (!seconds) return "";
|
|
201
|
+
const hours = Math.floor(seconds / 3600);
|
|
202
|
+
const minutes = Math.floor(seconds % 3600 / 60);
|
|
203
|
+
if (hours > 0) {
|
|
204
|
+
return `${hours}h ${minutes}m`;
|
|
205
|
+
}
|
|
206
|
+
return `${minutes} min`;
|
|
207
|
+
}
|
|
208
|
+
function formatTimeWithTimezone(date, timezone) {
|
|
209
|
+
if (!date) return "";
|
|
210
|
+
const dateObj = typeof date === "string" ? new Date(date) : date;
|
|
211
|
+
const timeStr = dateObj.toLocaleTimeString("en-US", {
|
|
212
|
+
hour: "numeric",
|
|
213
|
+
minute: "2-digit",
|
|
214
|
+
hour12: true
|
|
215
|
+
});
|
|
216
|
+
return timezone ? `${timeStr} ${timezone}` : timeStr;
|
|
217
|
+
}
|
|
218
|
+
function formatDurationFromRange(startAt, endAt) {
|
|
219
|
+
if (!startAt || !endAt) return "";
|
|
220
|
+
const start = typeof startAt === "string" ? new Date(startAt) : startAt;
|
|
221
|
+
const end = typeof endAt === "string" ? new Date(endAt) : endAt;
|
|
222
|
+
const durationMs = end.getTime() - start.getTime();
|
|
223
|
+
const minutes = Math.round(durationMs / 6e4);
|
|
224
|
+
if (minutes >= 60) {
|
|
225
|
+
const hours = Math.floor(minutes / 60);
|
|
226
|
+
const mins = minutes % 60;
|
|
227
|
+
return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
|
|
228
|
+
}
|
|
229
|
+
return `${minutes}m`;
|
|
230
|
+
}
|
|
231
|
+
function formatDateUTC(value, options = {}) {
|
|
232
|
+
const { fallback = "N/A", timezone = "UTC" } = options;
|
|
233
|
+
if (value === null || value === void 0 || value === "") return fallback;
|
|
234
|
+
let ms;
|
|
235
|
+
if (typeof value === "number") {
|
|
236
|
+
ms = value;
|
|
237
|
+
} else {
|
|
238
|
+
const n = Number(value);
|
|
239
|
+
if (Number.isFinite(n) && n > 0 && /^-?\d+(\.\d+)?$/.test(value.trim())) {
|
|
240
|
+
ms = n;
|
|
241
|
+
} else {
|
|
242
|
+
ms = Date.parse(value.includes("T") ? value : value + "T00:00:00Z");
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (!Number.isFinite(ms)) return fallback;
|
|
246
|
+
return new Date(ms).toLocaleDateString("en-US", {
|
|
247
|
+
year: "numeric",
|
|
248
|
+
month: "short",
|
|
249
|
+
day: "numeric",
|
|
250
|
+
timeZone: timezone === "local" ? void 0 : "UTC"
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
function formatLegalDate(dateInput) {
|
|
254
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
255
|
+
year: "numeric",
|
|
256
|
+
month: "2-digit",
|
|
257
|
+
day: "2-digit"
|
|
258
|
+
}).format(new Date(dateInput));
|
|
259
|
+
}
|
|
260
|
+
function formatCurrency(value) {
|
|
261
|
+
if (value == null) return "N/A";
|
|
262
|
+
return new Intl.NumberFormat("en-US", {
|
|
263
|
+
style: "currency",
|
|
264
|
+
currency: "USD",
|
|
265
|
+
maximumFractionDigits: 0
|
|
266
|
+
}).format(value);
|
|
267
|
+
}
|
|
268
|
+
function formatPercent(value) {
|
|
269
|
+
if (value == null) return "N/A";
|
|
270
|
+
return `${value.toFixed(2)}%`;
|
|
271
|
+
}
|
|
272
|
+
function formatWholeDollars(price, currency = "USD") {
|
|
273
|
+
return new Intl.NumberFormat("en-US", {
|
|
274
|
+
style: "currency",
|
|
275
|
+
currency,
|
|
276
|
+
maximumFractionDigits: 0
|
|
277
|
+
}).format(price);
|
|
278
|
+
}
|
|
279
|
+
function formatCompactMetric(value, format = "number", options) {
|
|
280
|
+
if (value === 0 || value === null || value === void 0) {
|
|
281
|
+
if (format === "currency") return `${options?.prefix || "$"}0`;
|
|
282
|
+
if (format === "percentage") return "0%";
|
|
283
|
+
if (format === "months") return `0 ${options?.suffix || "months"}`;
|
|
284
|
+
return "0";
|
|
285
|
+
}
|
|
286
|
+
const absValue = Math.abs(value);
|
|
287
|
+
const sign = value < 0 ? "-" : "";
|
|
288
|
+
if (format === "currency") {
|
|
289
|
+
const prefix = options?.prefix || "$";
|
|
290
|
+
const compact = (val, divisor, suffix) => {
|
|
291
|
+
const divided = val / divisor;
|
|
292
|
+
const formatted = divided % 1 === 0 ? divided.toFixed(0) : divided.toFixed(1);
|
|
293
|
+
return `${sign}${prefix}${formatted}${suffix}`;
|
|
294
|
+
};
|
|
295
|
+
if (absValue >= 1e9) return compact(absValue, 1e9, "B");
|
|
296
|
+
if (absValue >= 1e6) return compact(absValue, 1e6, "M");
|
|
297
|
+
if (absValue >= 1e3) return `${sign}${prefix}${(absValue / 1e3).toFixed(0)}K`;
|
|
298
|
+
return `${sign}${prefix}${absValue.toLocaleString()}`;
|
|
299
|
+
}
|
|
300
|
+
if (format === "percentage") {
|
|
301
|
+
return `${sign}${absValue}%`;
|
|
302
|
+
}
|
|
303
|
+
if (format === "months") {
|
|
304
|
+
const rounded = Math.round(value * 10) / 10;
|
|
305
|
+
return `${rounded} ${options?.suffix || "months"}`;
|
|
306
|
+
}
|
|
307
|
+
if (absValue >= 1e6) return `${sign}${(absValue / 1e6).toFixed(1)}M`;
|
|
308
|
+
if (absValue >= 1e3) return `${sign}${(absValue / 1e3).toFixed(1)}K`;
|
|
309
|
+
return value.toLocaleString();
|
|
310
|
+
}
|
|
311
|
+
function getTrendColors(direction, polarity = "positive") {
|
|
312
|
+
if (direction === "neutral" || polarity === "neutral") {
|
|
313
|
+
return {
|
|
314
|
+
textClass: "text-ods-text-secondary",
|
|
315
|
+
badgeClass: "bg-ods-border text-ods-text-secondary"
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
const isPositiveOutcome = direction === "up" && polarity === "positive" || direction === "down" && polarity === "negative";
|
|
319
|
+
if (isPositiveOutcome) {
|
|
320
|
+
return {
|
|
321
|
+
textClass: "text-ods-success",
|
|
322
|
+
badgeClass: "bg-ods-success-secondary text-ods-success"
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
textClass: "text-ods-error",
|
|
327
|
+
badgeClass: "bg-ods-error-secondary text-ods-error"
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
function formatDateRange(start, end) {
|
|
331
|
+
if (!start || !end) return "";
|
|
332
|
+
const fmt = (s) => {
|
|
333
|
+
const bareMatch = /^(\d{4})-(\d{2})-(\d{2})$/.exec(s);
|
|
334
|
+
const d = bareMatch ? new Date(Number(bareMatch[1]), Number(bareMatch[2]) - 1, Number(bareMatch[3])) : new Date(s);
|
|
335
|
+
if (Number.isNaN(d.getTime())) return s;
|
|
336
|
+
return d.toLocaleDateString(void 0, {
|
|
337
|
+
month: "short",
|
|
338
|
+
day: "numeric",
|
|
339
|
+
year: "numeric"
|
|
340
|
+
});
|
|
341
|
+
};
|
|
342
|
+
return `${fmt(start)} \u2014 ${fmt(end)}`;
|
|
343
|
+
}
|
|
344
|
+
function formatDateTimeAt(dateString) {
|
|
345
|
+
const date = new Date(dateString);
|
|
346
|
+
const dateStr = date.toLocaleDateString("en-US", {
|
|
347
|
+
month: "short",
|
|
348
|
+
day: "numeric",
|
|
349
|
+
year: "numeric"
|
|
350
|
+
});
|
|
351
|
+
const timeStr = date.toLocaleTimeString("en-US", {
|
|
352
|
+
hour: "numeric",
|
|
353
|
+
minute: "2-digit",
|
|
354
|
+
hour12: true
|
|
355
|
+
});
|
|
356
|
+
return `${dateStr} at ${timeStr}`;
|
|
357
|
+
}
|
|
358
|
+
function formatDurationFromMs(ms) {
|
|
359
|
+
if (!ms || isNaN(ms) || ms < 0) return "0ms";
|
|
360
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
361
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
362
|
+
return `${(ms / 6e4).toFixed(1)}m`;
|
|
363
|
+
}
|
|
364
|
+
function formatDuration(seconds) {
|
|
365
|
+
if (seconds < 60) return `${seconds} seconds`;
|
|
366
|
+
if (seconds < 3600) return `${Math.floor(seconds / 60)} minutes`;
|
|
367
|
+
const hours = Math.floor(seconds / 3600);
|
|
368
|
+
const minutes = Math.floor(seconds % 3600 / 60);
|
|
369
|
+
if (minutes === 0) return `${hours} hour${hours > 1 ? "s" : ""}`;
|
|
370
|
+
return `${hours} hour${hours > 1 ? "s" : ""} ${minutes} minute${minutes > 1 ? "s" : ""}`;
|
|
371
|
+
}
|
|
372
|
+
function formatUnderscoreText(text) {
|
|
373
|
+
return text.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
374
|
+
}
|
|
375
|
+
function stripHtml(html) {
|
|
376
|
+
let noTags = html;
|
|
377
|
+
let prev;
|
|
378
|
+
do {
|
|
379
|
+
prev = noTags;
|
|
380
|
+
noTags = noTags.replace(/<[^<>]*>/g, "");
|
|
381
|
+
} while (noTags !== prev);
|
|
382
|
+
return noTags.replace(/ /g, " ").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/'/g, "'").replace(/'/g, "'").replace(/&/g, "&").replace(/\s+/g, " ").trim();
|
|
383
|
+
}
|
|
384
|
+
function formatClassification(classification) {
|
|
385
|
+
const customMappings = {
|
|
386
|
+
openframe_selected: "OpenFrame Selected"
|
|
387
|
+
};
|
|
388
|
+
return customMappings[classification] || formatUnderscoreText(classification);
|
|
389
|
+
}
|
|
390
|
+
function formatPricingModel(pricingModel) {
|
|
391
|
+
const customMappings = {
|
|
392
|
+
one_time: "One-time Purchase",
|
|
393
|
+
self_hosted: "Self-hosted"
|
|
394
|
+
};
|
|
395
|
+
return customMappings[pricingModel] || formatUnderscoreText(pricingModel);
|
|
396
|
+
}
|
|
397
|
+
function formatBioText(aboutHtml, fallback = "") {
|
|
398
|
+
if (!aboutHtml || !aboutHtml.trim()) return fallback;
|
|
399
|
+
if (aboutHtml.includes("<p")) {
|
|
400
|
+
const paragraphs = aboutHtml.split(/<p[^<>]*>/).slice(1).map((part) => part.split("</p>")[0]).map((text) => stripHtml(text).trim()).filter((text) => text.length > 0);
|
|
401
|
+
if (paragraphs.length > 0) return paragraphs.join(" ");
|
|
402
|
+
}
|
|
403
|
+
return stripHtml(aboutHtml).trim() || fallback;
|
|
404
|
+
}
|
|
136
405
|
var PLAY_ICON_PATH = "M4.875 5.006c0-2.501 2.793-3.989 4.87-2.592l9.78 6.578c2.135 1.437 2.135 4.58 0 6.016l-9.78 6.579c-2.077 1.396-4.87-.091-4.87-2.593zm2.25 13.988c0 .7.783 1.118 1.364.727l9.78-6.58c.81-.545.81-1.738 0-2.283L8.488 4.28a.875.875 0 0 0-1.364.726v13.988Z";
|
|
137
406
|
|
|
138
407
|
// src/utils/ods-color-utils.ts
|
|
@@ -375,6 +644,25 @@ function ShellIcon({ className = "w-5 h-5", size = 22, color = "white" }) {
|
|
|
375
644
|
}
|
|
376
645
|
);
|
|
377
646
|
}
|
|
647
|
+
var GitHubIcon = ({
|
|
648
|
+
className = "",
|
|
649
|
+
width = 15,
|
|
650
|
+
height = 14,
|
|
651
|
+
color = "white"
|
|
652
|
+
}) => {
|
|
653
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
654
|
+
"svg",
|
|
655
|
+
{
|
|
656
|
+
width,
|
|
657
|
+
height,
|
|
658
|
+
viewBox: "0 0 15 14",
|
|
659
|
+
fill: "none",
|
|
660
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
661
|
+
className,
|
|
662
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7.18173 0.333008C3.40523 0.333008 0.346436 3.3918 0.346436 7.1683C0.346436 10.1929 2.30304 12.7476 5.02007 13.6533C5.36183 13.7131 5.48999 13.508 5.48999 13.3286C5.48999 13.1663 5.48145 12.628 5.48145 12.0555C3.76408 12.3717 3.31979 11.6369 3.18308 11.2524C3.10618 11.0559 2.77296 10.4492 2.48246 10.2869C2.24323 10.1587 1.90146 9.84261 2.47392 9.83406C3.0122 9.82552 3.39668 10.3296 3.52485 10.5347C4.14002 11.5685 5.1226 11.278 5.51563 11.0986C5.57543 10.6543 5.75486 10.3553 5.95137 10.1844C4.43052 10.0135 2.84132 9.42395 2.84132 6.80945C2.84132 6.06611 3.10618 5.45093 3.54193 4.97246C3.47358 4.80158 3.23435 4.10096 3.61029 3.16111C3.61029 3.16111 4.18274 2.98168 5.48999 3.86173C6.03682 3.70793 6.61782 3.63104 7.19882 3.63104C7.77982 3.63104 8.36082 3.70793 8.90764 3.86173C10.2149 2.97314 10.7873 3.16111 10.7873 3.16111C11.1633 4.10096 10.9241 4.80158 10.8557 4.97246C11.2914 5.45093 11.5563 6.05757 11.5563 6.80945C11.5563 9.43249 9.95856 10.0135 8.43771 10.1844C8.68549 10.398 8.8991 10.8081 8.8991 11.4489C8.8991 12.3631 8.89055 13.0979 8.89055 13.3286C8.89055 13.508 9.01871 13.7216 9.36048 13.6533C10.7174 13.1952 11.8965 12.3231 12.7318 11.1597C13.5671 9.99643 14.0166 8.60046 14.017 7.1683C14.017 3.3918 10.9582 0.333008 7.18173 0.333008Z", fill: color })
|
|
663
|
+
}
|
|
664
|
+
);
|
|
665
|
+
};
|
|
378
666
|
function SlackIcon({
|
|
379
667
|
width = 24,
|
|
380
668
|
height = 24,
|
|
@@ -427,6 +715,53 @@ function SlackIcon({
|
|
|
427
715
|
}
|
|
428
716
|
);
|
|
429
717
|
}
|
|
718
|
+
function ClickUpIcon({
|
|
719
|
+
width = 24,
|
|
720
|
+
height = 24,
|
|
721
|
+
className = ""
|
|
722
|
+
}) {
|
|
723
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
724
|
+
"svg",
|
|
725
|
+
{
|
|
726
|
+
width,
|
|
727
|
+
height,
|
|
728
|
+
viewBox: "0 0 54.8 65.8",
|
|
729
|
+
fill: "none",
|
|
730
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
731
|
+
className,
|
|
732
|
+
children: [
|
|
733
|
+
/* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
|
|
734
|
+
/* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "clickup-grad-1", gradientUnits: "userSpaceOnUse", x1: "0", y1: "15.0492", x2: "54.8446", y2: "15.0492", gradientTransform: "matrix(1 0 0 -1 0 69.3604)", children: [
|
|
735
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0", stopColor: "#8930FD" }),
|
|
736
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "1", stopColor: "#49CCF9" })
|
|
737
|
+
] }),
|
|
738
|
+
/* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "clickup-grad-2", gradientUnits: "userSpaceOnUse", x1: "1.1953", y1: "53.166", x2: "53.7447", y2: "53.166", gradientTransform: "matrix(1 0 0 -1 0 69.3604)", children: [
|
|
739
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0", stopColor: "#FF02F0" }),
|
|
740
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "1", stopColor: "#FFC800" })
|
|
741
|
+
] })
|
|
742
|
+
] }),
|
|
743
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
744
|
+
"path",
|
|
745
|
+
{
|
|
746
|
+
fillRule: "evenodd",
|
|
747
|
+
clipRule: "evenodd",
|
|
748
|
+
d: "M0,50.6l10.1-7.8c5.4,7,11.1,10.3,17.4,10.3c6.3,0,11.9-3.2,17-10.2l10.3,7.6c-7.4,10-16.6,15.3-27.3,15.3 C16.9,65.8,7.6,60.5,0,50.6z",
|
|
749
|
+
fill: "url(#clickup-grad-1)"
|
|
750
|
+
}
|
|
751
|
+
),
|
|
752
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
753
|
+
"path",
|
|
754
|
+
{
|
|
755
|
+
fillRule: "evenodd",
|
|
756
|
+
clipRule: "evenodd",
|
|
757
|
+
d: "M27.5,16.9l-18,15.5l-8.3-9.7L27.6,0l26.2,22.7l-8.4,9.6L27.5,16.9z",
|
|
758
|
+
fill: "url(#clickup-grad-2)"
|
|
759
|
+
}
|
|
760
|
+
)
|
|
761
|
+
]
|
|
762
|
+
}
|
|
763
|
+
);
|
|
764
|
+
}
|
|
430
765
|
function XLogo({ className = "", color = "white", ...props }) {
|
|
431
766
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
432
767
|
"svg",
|
|
@@ -445,6 +780,19 @@ function XLogo({ className = "", color = "white", ...props }) {
|
|
|
445
780
|
}
|
|
446
781
|
);
|
|
447
782
|
}
|
|
783
|
+
function HubspotIcon({ className, fill = "#FF7A59", ...props }) {
|
|
784
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
785
|
+
"svg",
|
|
786
|
+
{
|
|
787
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
788
|
+
viewBox: "0 0 512 512",
|
|
789
|
+
fill,
|
|
790
|
+
className: cn("inline-block", className),
|
|
791
|
+
...props,
|
|
792
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M266.197 216.109c-22.551 21.293-36.655 51.48-36.655 84.991 0 26.326 8.714 50.582 23.359 70.08l-44.473 44.74c-3.953-1.438-8.176-2.245-12.579-2.245-9.702 0-18.776 3.774-25.605 10.602-6.828 6.827-10.602 15.989-10.602 25.696 0 9.701 3.773 18.775 10.602 25.605 6.829 6.826 15.993 10.42 25.605 10.42 9.703 0 18.777-3.505 25.695-10.42 6.829-6.83 10.602-15.994 10.602-25.605 0-3.774-.538-7.369-1.707-10.873l44.923-45.102c19.765 15.183 44.381 24.169 71.244 24.169 64.599 0 116.797-52.38 116.797-116.977 0-58.578-42.854-107.093-99.007-115.628v-55.343c15.723-6.65 25.335-21.384 25.335-38.545 0-23.449-18.777-43.034-42.227-43.034-23.448 0-41.956 19.585-41.956 43.034 0 17.161 9.613 31.895 25.335 38.545v54.983c-13.655 1.887-26.593 6.019-38.362 12.219-24.796-18.778-105.565-76.997-151.746-112.126 1.078-3.953 1.798-8.085 1.798-12.397 0-25.875-21.113-46.898-47.078-46.898-25.875 0-46.898 21.023-46.898 46.898 0 25.965 21.023 46.988 46.898 46.988 8.805 0 16.98-2.606 24.078-6.828L266.197 216.109zM346.606 363.095c-34.229 0-61.991-27.763-61.991-61.994 0-34.229 27.762-61.99 61.991-61.99 34.23 0 61.992 27.761 61.992 61.99 0 34.231-27.762 61.994-61.992 61.994z" })
|
|
793
|
+
}
|
|
794
|
+
);
|
|
795
|
+
}
|
|
448
796
|
function LinkedInIcon({ className = "", size = 24, color = "white", ...props }) {
|
|
449
797
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
450
798
|
"svg",
|
|
@@ -866,9 +1214,11 @@ var OS_PLATFORMS = [
|
|
|
866
1214
|
{ id: "darwin", name: "MacOS", icon: MacOSIcon }
|
|
867
1215
|
];
|
|
868
1216
|
var DEFAULT_OS_PLATFORM = "windows";
|
|
869
|
-
|
|
1217
|
+
|
|
1218
|
+
// src/utils/access-code-client.ts
|
|
1219
|
+
async function validateAccessCode(email, code, endpoints) {
|
|
870
1220
|
try {
|
|
871
|
-
const response = await fetch(
|
|
1221
|
+
const response = await fetch(endpoints.validateUrl, {
|
|
872
1222
|
method: "POST",
|
|
873
1223
|
headers: {
|
|
874
1224
|
"Content-Type": "application/json"
|
|
@@ -887,9 +1237,9 @@ async function validateAccessCode(email, code) {
|
|
|
887
1237
|
};
|
|
888
1238
|
}
|
|
889
1239
|
}
|
|
890
|
-
async function consumeAccessCode(email, code) {
|
|
1240
|
+
async function consumeAccessCode(email, code, endpoints) {
|
|
891
1241
|
try {
|
|
892
|
-
const response = await fetch(
|
|
1242
|
+
const response = await fetch(endpoints.consumeUrl, {
|
|
893
1243
|
method: "POST",
|
|
894
1244
|
headers: {
|
|
895
1245
|
"Content-Type": "application/json"
|
|
@@ -909,56 +1259,18 @@ async function consumeAccessCode(email, code) {
|
|
|
909
1259
|
};
|
|
910
1260
|
}
|
|
911
1261
|
}
|
|
912
|
-
async function validateAndConsumeAccessCode(email, code) {
|
|
913
|
-
const validation = await validateAccessCode(email, code);
|
|
1262
|
+
async function validateAndConsumeAccessCode(email, code, endpoints) {
|
|
1263
|
+
const validation = await validateAccessCode(email, code, endpoints);
|
|
914
1264
|
if (!validation.valid) {
|
|
915
1265
|
return validation;
|
|
916
1266
|
}
|
|
917
|
-
const consumption = await consumeAccessCode(email, code);
|
|
1267
|
+
const consumption = await consumeAccessCode(email, code, endpoints);
|
|
918
1268
|
return {
|
|
919
1269
|
...validation,
|
|
920
1270
|
consumed: consumption.consumed,
|
|
921
1271
|
message: consumption.consumed ? `Access granted for ${validation.cohort_name}` : consumption.message || validation.message
|
|
922
1272
|
};
|
|
923
1273
|
}
|
|
924
|
-
function useAccessCodeIntegration() {
|
|
925
|
-
const [isValidating, setIsValidating] = React2__default.default.useState(false);
|
|
926
|
-
const [isConsuming, setIsConsuming] = React2__default.default.useState(false);
|
|
927
|
-
const validate = async (email, code) => {
|
|
928
|
-
setIsValidating(true);
|
|
929
|
-
try {
|
|
930
|
-
return await validateAccessCode(email, code);
|
|
931
|
-
} finally {
|
|
932
|
-
setIsValidating(false);
|
|
933
|
-
}
|
|
934
|
-
};
|
|
935
|
-
const consume = async (email, code) => {
|
|
936
|
-
setIsConsuming(true);
|
|
937
|
-
try {
|
|
938
|
-
return await consumeAccessCode(email, code);
|
|
939
|
-
} finally {
|
|
940
|
-
setIsConsuming(false);
|
|
941
|
-
}
|
|
942
|
-
};
|
|
943
|
-
const validateAndConsume = async (email, code) => {
|
|
944
|
-
setIsValidating(true);
|
|
945
|
-
setIsConsuming(true);
|
|
946
|
-
try {
|
|
947
|
-
return await validateAndConsumeAccessCode(email, code);
|
|
948
|
-
} finally {
|
|
949
|
-
setIsValidating(false);
|
|
950
|
-
setIsConsuming(false);
|
|
951
|
-
}
|
|
952
|
-
};
|
|
953
|
-
return {
|
|
954
|
-
validate,
|
|
955
|
-
consume,
|
|
956
|
-
validateAndConsume,
|
|
957
|
-
isValidating,
|
|
958
|
-
isConsuming,
|
|
959
|
-
isProcessing: isValidating || isConsuming
|
|
960
|
-
};
|
|
961
|
-
}
|
|
962
1274
|
|
|
963
1275
|
// src/utils/validation-utils.ts
|
|
964
1276
|
function isValidEmailDomain(domain) {
|
|
@@ -1073,51 +1385,173 @@ function getConfidenceLabel(confidence) {
|
|
|
1073
1385
|
}
|
|
1074
1386
|
|
|
1075
1387
|
// src/utils/date-formatters.ts
|
|
1388
|
+
var MONTHS_LONG = [
|
|
1389
|
+
"January",
|
|
1390
|
+
"February",
|
|
1391
|
+
"March",
|
|
1392
|
+
"April",
|
|
1393
|
+
"May",
|
|
1394
|
+
"June",
|
|
1395
|
+
"July",
|
|
1396
|
+
"August",
|
|
1397
|
+
"September",
|
|
1398
|
+
"October",
|
|
1399
|
+
"November",
|
|
1400
|
+
"December"
|
|
1401
|
+
];
|
|
1402
|
+
var MONTHS_SHORT = [
|
|
1403
|
+
"Jan",
|
|
1404
|
+
"Feb",
|
|
1405
|
+
"Mar",
|
|
1406
|
+
"Apr",
|
|
1407
|
+
"May",
|
|
1408
|
+
"Jun",
|
|
1409
|
+
"Jul",
|
|
1410
|
+
"Aug",
|
|
1411
|
+
"Sep",
|
|
1412
|
+
"Oct",
|
|
1413
|
+
"Nov",
|
|
1414
|
+
"Dec"
|
|
1415
|
+
];
|
|
1416
|
+
function splitYmd(dateString) {
|
|
1417
|
+
const head = dateString.split("T")[0];
|
|
1418
|
+
const parts = head.split("-");
|
|
1419
|
+
if (parts.length !== 3) return null;
|
|
1420
|
+
return [parts[0], parts[1], parts[2]];
|
|
1421
|
+
}
|
|
1076
1422
|
function formatReleaseDate(dateString) {
|
|
1077
|
-
const
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
];
|
|
1092
|
-
return `${
|
|
1423
|
+
const ymd = splitYmd(dateString);
|
|
1424
|
+
if (!ymd) return dateString;
|
|
1425
|
+
const [year, month, day] = ymd;
|
|
1426
|
+
return `${MONTHS_LONG[parseInt(month) - 1]} ${parseInt(day)}, ${year}`;
|
|
1427
|
+
}
|
|
1428
|
+
function formatDateShort(dateString) {
|
|
1429
|
+
const ymd = splitYmd(dateString);
|
|
1430
|
+
if (!ymd) return dateString;
|
|
1431
|
+
const [year, month, day] = ymd;
|
|
1432
|
+
return `${MONTHS_SHORT[parseInt(month) - 1]} ${parseInt(day)}, ${year}`;
|
|
1433
|
+
}
|
|
1434
|
+
function formatDateSlashUTC(dateString) {
|
|
1435
|
+
const ymd = splitYmd(dateString);
|
|
1436
|
+
if (!ymd) return dateString;
|
|
1437
|
+
const [year, month, day] = ymd;
|
|
1438
|
+
return `${month}/${day}/${year}`;
|
|
1439
|
+
}
|
|
1440
|
+
var OpenFrameLogoIcon = ({ className }) => React2.createElement(OpenFrameLogo, { className, upperPathColor: "currentColor" });
|
|
1441
|
+
var ICON_REGISTRY = {
|
|
1442
|
+
// lucide-react (kebab-case)
|
|
1443
|
+
activity: lucideReact.Activity,
|
|
1444
|
+
banknote: lucideReact.Banknote,
|
|
1445
|
+
bell: lucideReact.Bell,
|
|
1446
|
+
"book-open": lucideReact.BookOpen,
|
|
1447
|
+
box: lucideReact.Box,
|
|
1448
|
+
briefcase: lucideReact.Briefcase,
|
|
1449
|
+
calendar: lucideReact.Calendar,
|
|
1450
|
+
"check-square": lucideReact.CheckSquare,
|
|
1451
|
+
"dollar-sign": lucideReact.DollarSign,
|
|
1452
|
+
// For brand-vs-lucide variants the kebab key is the BRAND (most-common
|
|
1453
|
+
// social-platform intent); `'<name>-lucide'` carries the lucide outline.
|
|
1454
|
+
facebook: FacebookIcon,
|
|
1455
|
+
"facebook-lucide": lucideReact.Facebook,
|
|
1456
|
+
"file-text": lucideReact.FileText,
|
|
1457
|
+
// `'github-lucide'` is the lucide outline glyph (used by
|
|
1458
|
+
// `social_platforms.icon_name='Github'`); `'github'` is the brand icon
|
|
1459
|
+
// (used by `chat_admin_slash_commands.icon_name='github'`). The PascalCase
|
|
1460
|
+
// alias `'Github' → 'github-lucide'` routes the lucide glyph for
|
|
1461
|
+
// social-platform DB rows; `'GitHubIcon' → 'github'` keeps brand routing
|
|
1462
|
+
// consistent for callers that store the PascalCase component name.
|
|
1463
|
+
github: GitHubIcon,
|
|
1464
|
+
"github-lucide": lucideReact.Github,
|
|
1465
|
+
globe: lucideReact.Globe,
|
|
1466
|
+
"graduation-cap": lucideReact.GraduationCap,
|
|
1467
|
+
headphones: lucideReact.Headphones,
|
|
1468
|
+
info: lucideReact.Info,
|
|
1469
|
+
instagram: InstagramIcon,
|
|
1470
|
+
"instagram-lucide": lucideReact.Instagram,
|
|
1471
|
+
mail: lucideReact.Mail,
|
|
1472
|
+
megaphone: lucideReact.Megaphone,
|
|
1473
|
+
"message-circle": lucideReact.MessageCircle,
|
|
1474
|
+
"message-square": lucideReact.MessageSquare,
|
|
1475
|
+
newspaper: lucideReact.Newspaper,
|
|
1476
|
+
package: lucideReact.Package,
|
|
1477
|
+
"pen-square": lucideReact.PenSquare,
|
|
1478
|
+
rocket: lucideReact.Rocket,
|
|
1479
|
+
search: lucideReact.Search,
|
|
1480
|
+
send: lucideReact.Send,
|
|
1481
|
+
shield: lucideReact.Shield,
|
|
1482
|
+
star: lucideReact.Star,
|
|
1483
|
+
table: lucideReact.TableProperties,
|
|
1484
|
+
"trending-up": lucideReact.TrendingUp,
|
|
1485
|
+
twitter: lucideReact.Twitter,
|
|
1486
|
+
users: lucideReact.Users,
|
|
1487
|
+
video: lucideReact.Video,
|
|
1488
|
+
youtube: YouTubeIcon,
|
|
1489
|
+
"youtube-lucide": lucideReact.Youtube,
|
|
1490
|
+
// brand-only icons (no lucide variant in current use)
|
|
1491
|
+
slack: SlackIcon,
|
|
1492
|
+
clickup: ClickUpIcon,
|
|
1493
|
+
hubspot: HubspotIcon,
|
|
1494
|
+
linkedin: LinkedInIcon,
|
|
1495
|
+
x: XLogo,
|
|
1496
|
+
openframe: OpenFrameLogoIcon
|
|
1497
|
+
};
|
|
1498
|
+
var PASCAL_TO_KEBAB_ALIASES = {
|
|
1499
|
+
// Lucide PascalCase names → kebab equivalents
|
|
1500
|
+
Activity: "activity",
|
|
1501
|
+
Banknote: "banknote",
|
|
1502
|
+
Bell: "bell",
|
|
1503
|
+
BookOpen: "book-open",
|
|
1504
|
+
Box: "box",
|
|
1505
|
+
Briefcase: "briefcase",
|
|
1506
|
+
Calendar: "calendar",
|
|
1507
|
+
CheckSquare: "check-square",
|
|
1508
|
+
DollarSign: "dollar-sign",
|
|
1509
|
+
// Lucide PascalCase → the `-lucide` kebab variant (kebab default is the
|
|
1510
|
+
// brand icon for the social-platform names below).
|
|
1511
|
+
Facebook: "facebook-lucide",
|
|
1512
|
+
FileText: "file-text",
|
|
1513
|
+
Github: "github-lucide",
|
|
1514
|
+
Globe: "globe",
|
|
1515
|
+
GraduationCap: "graduation-cap",
|
|
1516
|
+
Headphones: "headphones",
|
|
1517
|
+
Info: "info",
|
|
1518
|
+
Instagram: "instagram-lucide",
|
|
1519
|
+
Mail: "mail",
|
|
1520
|
+
Megaphone: "megaphone",
|
|
1521
|
+
MessageCircle: "message-circle",
|
|
1522
|
+
MessageSquare: "message-square",
|
|
1523
|
+
Newspaper: "newspaper",
|
|
1524
|
+
Package: "package",
|
|
1525
|
+
PenSquare: "pen-square",
|
|
1526
|
+
Rocket: "rocket",
|
|
1527
|
+
Search: "search",
|
|
1528
|
+
Send: "send",
|
|
1529
|
+
Shield: "shield",
|
|
1530
|
+
Star: "star",
|
|
1531
|
+
TableProperties: "table",
|
|
1532
|
+
TrendingUp: "trending-up",
|
|
1533
|
+
Twitter: "twitter",
|
|
1534
|
+
Users: "users",
|
|
1535
|
+
Video: "video",
|
|
1536
|
+
Youtube: "youtube-lucide",
|
|
1537
|
+
// Brand-icon PascalCase exports → kebab (kebab default is the brand)
|
|
1538
|
+
SlackIcon: "slack",
|
|
1539
|
+
GitHubIcon: "github",
|
|
1540
|
+
ClickUpIcon: "clickup",
|
|
1541
|
+
HubspotIcon: "hubspot",
|
|
1542
|
+
LinkedInIcon: "linkedin",
|
|
1543
|
+
FacebookIcon: "facebook",
|
|
1544
|
+
InstagramIcon: "instagram",
|
|
1545
|
+
YouTubeIcon: "youtube",
|
|
1546
|
+
XLogo: "x",
|
|
1547
|
+
OpenFrameLogo: "openframe"
|
|
1548
|
+
};
|
|
1549
|
+
function normalizeIconKey(key) {
|
|
1550
|
+
return PASCAL_TO_KEBAB_ALIASES[key] ?? key;
|
|
1093
1551
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
if (!timestamp) return "Not scheduled";
|
|
1098
|
-
const date = new Date(timestamp);
|
|
1099
|
-
if (isNaN(date.getTime())) return "Invalid date";
|
|
1100
|
-
const now = /* @__PURE__ */ new Date();
|
|
1101
|
-
const diffMs = now.getTime() - date.getTime();
|
|
1102
|
-
const diffSecs = Math.floor(diffMs / 1e3);
|
|
1103
|
-
const diffMins = Math.floor(diffSecs / 60);
|
|
1104
|
-
const diffHours = Math.floor(diffMins / 60);
|
|
1105
|
-
const diffDays = Math.floor(diffHours / 24);
|
|
1106
|
-
if (diffMs < 0) {
|
|
1107
|
-
const absDiffSecs = Math.abs(diffSecs);
|
|
1108
|
-
const absDiffMins = Math.floor(absDiffSecs / 60);
|
|
1109
|
-
const absDiffHours = Math.floor(absDiffMins / 60);
|
|
1110
|
-
const absDiffDays = Math.floor(absDiffHours / 24);
|
|
1111
|
-
if (absDiffDays > 0) return `in ${absDiffDays} day${absDiffDays === 1 ? "" : "s"}`;
|
|
1112
|
-
if (absDiffHours > 0) return `in ${absDiffHours} hour${absDiffHours === 1 ? "" : "s"}`;
|
|
1113
|
-
if (absDiffMins > 0) return `in ${absDiffMins} minute${absDiffMins === 1 ? "" : "s"}`;
|
|
1114
|
-
return `in ${absDiffSecs} second${absDiffSecs === 1 ? "" : "s"}`;
|
|
1115
|
-
}
|
|
1116
|
-
if (diffDays > 0) return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
|
|
1117
|
-
if (diffHours > 0) return `${diffHours} hour${diffHours === 1 ? "" : "s"} ago`;
|
|
1118
|
-
if (diffMins > 0) return `${diffMins} minute${diffMins === 1 ? "" : "s"} ago`;
|
|
1119
|
-
if (diffSecs > 0) return `${diffSecs} second${diffSecs === 1 ? "" : "s"}`;
|
|
1120
|
-
return "just now";
|
|
1552
|
+
function getIconComponent(iconName) {
|
|
1553
|
+
if (!iconName) return lucideReact.FileText;
|
|
1554
|
+
return ICON_REGISTRY[normalizeIconKey(iconName)] ?? lucideReact.FileText;
|
|
1121
1555
|
}
|
|
1122
1556
|
var SIZE_CLASSES = {
|
|
1123
1557
|
xs: "w-3 h-3",
|
|
@@ -1132,52 +1566,28 @@ var SIZE_CLASSES = {
|
|
|
1132
1566
|
// 48px
|
|
1133
1567
|
};
|
|
1134
1568
|
var ICON_COLORS = {
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
OpenFrameLogo: {
|
|
1139
|
-
/* Uses component defaults */
|
|
1140
|
-
}
|
|
1141
|
-
};
|
|
1142
|
-
var ICON_REGISTRY = {
|
|
1143
|
-
// UI Kit social platform icons (from @flamingo/ui-kit/components/icons)
|
|
1144
|
-
LinkedInIcon,
|
|
1145
|
-
FacebookIcon,
|
|
1146
|
-
InstagramIcon,
|
|
1147
|
-
YouTubeIcon,
|
|
1148
|
-
SlackIcon,
|
|
1149
|
-
XLogo,
|
|
1150
|
-
// Lucide icons (from lucide-react)
|
|
1151
|
-
Globe: lucideReact.Globe,
|
|
1152
|
-
FileText: lucideReact.FileText,
|
|
1153
|
-
// Blog Posts icon (internal-blogging)
|
|
1154
|
-
PenSquare: lucideReact.PenSquare,
|
|
1155
|
-
// Alternative blog icon
|
|
1156
|
-
Github: lucideReact.Github,
|
|
1157
|
-
// GitHub platform
|
|
1158
|
-
MessageCircle: lucideReact.MessageCircle,
|
|
1159
|
-
// Discord platform
|
|
1160
|
-
Send: lucideReact.Send,
|
|
1161
|
-
// Telegram platform
|
|
1162
|
-
Video: lucideReact.Video,
|
|
1163
|
-
// TikTok platform
|
|
1164
|
-
Twitter: lucideReact.Twitter
|
|
1165
|
-
// Twitter/X platform
|
|
1569
|
+
linkedin: { color: "#0A66C2" },
|
|
1570
|
+
facebook: { color: "#1877F2" },
|
|
1571
|
+
youtube: { color: "#FF0000" }
|
|
1166
1572
|
};
|
|
1167
1573
|
function getDynamicIcon(iconName, size = "md", className) {
|
|
1168
1574
|
if (!iconName) {
|
|
1169
1575
|
console.warn("[getDynamicIcon] No iconName provided, using Globe fallback");
|
|
1170
|
-
return
|
|
1576
|
+
return React2.createElement(lucideReact.Globe, { className: SIZE_CLASSES[size] });
|
|
1171
1577
|
}
|
|
1172
1578
|
const sizeClass = SIZE_CLASSES[size];
|
|
1173
1579
|
const finalClassName = className ? `${sizeClass} ${className}` : sizeClass;
|
|
1174
|
-
const
|
|
1580
|
+
const canonicalKey = normalizeIconKey(iconName);
|
|
1581
|
+
const IconComponent = ICON_REGISTRY[canonicalKey];
|
|
1175
1582
|
if (IconComponent) {
|
|
1176
|
-
const colorConfig = ICON_COLORS[
|
|
1177
|
-
return
|
|
1583
|
+
const colorConfig = ICON_COLORS[canonicalKey] || {};
|
|
1584
|
+
return React2.createElement(IconComponent, { className: finalClassName, ...colorConfig });
|
|
1178
1585
|
}
|
|
1179
|
-
console.error(
|
|
1180
|
-
|
|
1586
|
+
console.error(
|
|
1587
|
+
`[getDynamicIcon] Icon NOT found in registry: "${iconName}" (normalized to "${canonicalKey}"). Available icons:`,
|
|
1588
|
+
Object.keys(ICON_REGISTRY)
|
|
1589
|
+
);
|
|
1590
|
+
return React2.createElement(lucideReact.Globe, { className: finalClassName });
|
|
1181
1591
|
}
|
|
1182
1592
|
|
|
1183
1593
|
// src/types/tool.types.ts
|
|
@@ -1667,38 +2077,729 @@ function isGenericWebsiteDomain(website) {
|
|
|
1667
2077
|
return isGenericDomain(normalizeDomain(website));
|
|
1668
2078
|
}
|
|
1669
2079
|
|
|
2080
|
+
// src/utils/color-analysis.ts
|
|
2081
|
+
var DESIGN_PALETTE = [
|
|
2082
|
+
{ name: "yellow", hex: "#FFC008", rgb: [255, 192, 8] },
|
|
2083
|
+
{ name: "black", hex: "#161616", rgb: [22, 22, 22] },
|
|
2084
|
+
{ name: "gray", hex: "#888888", rgb: [136, 136, 136] }
|
|
2085
|
+
];
|
|
2086
|
+
function hexToRgb(hex) {
|
|
2087
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
2088
|
+
return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : [0, 0, 0];
|
|
2089
|
+
}
|
|
2090
|
+
function getLuminance(rgb) {
|
|
2091
|
+
const [r, g, b] = rgb.map((c) => {
|
|
2092
|
+
c = c / 255;
|
|
2093
|
+
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
2094
|
+
});
|
|
2095
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
2096
|
+
}
|
|
2097
|
+
function getContrastRatio(color1, color2) {
|
|
2098
|
+
const lum1 = getLuminance(color1);
|
|
2099
|
+
const lum2 = getLuminance(color2);
|
|
2100
|
+
const brightest = Math.max(lum1, lum2);
|
|
2101
|
+
const darkest = Math.min(lum1, lum2);
|
|
2102
|
+
return (brightest + 0.05) / (darkest + 0.05);
|
|
2103
|
+
}
|
|
2104
|
+
function extractDominantColor(canvas) {
|
|
2105
|
+
const ctx = canvas.getContext("2d");
|
|
2106
|
+
if (!ctx) return [128, 128, 128];
|
|
2107
|
+
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
2108
|
+
const data = imageData.data;
|
|
2109
|
+
const sampleSize = Math.max(1, Math.floor(data.length / (4 * 1e3)));
|
|
2110
|
+
const colorCounts = {};
|
|
2111
|
+
for (let i = 0; i < data.length; i += 4 * sampleSize) {
|
|
2112
|
+
const r = data[i];
|
|
2113
|
+
const g = data[i + 1];
|
|
2114
|
+
const b = data[i + 2];
|
|
2115
|
+
const alpha = data[i + 3];
|
|
2116
|
+
if (alpha < 128) continue;
|
|
2117
|
+
const bucketR = Math.round(r / 32) * 32;
|
|
2118
|
+
const bucketG = Math.round(g / 32) * 32;
|
|
2119
|
+
const bucketB = Math.round(b / 32) * 32;
|
|
2120
|
+
const key = `${bucketR},${bucketG},${bucketB}`;
|
|
2121
|
+
colorCounts[key] = (colorCounts[key] || 0) + 1;
|
|
2122
|
+
}
|
|
2123
|
+
let maxCount = 0;
|
|
2124
|
+
let dominantColor = [128, 128, 128];
|
|
2125
|
+
for (const [colorKey, count] of Object.entries(colorCounts)) {
|
|
2126
|
+
if (count > maxCount) {
|
|
2127
|
+
maxCount = count;
|
|
2128
|
+
const [r, g, b] = colorKey.split(",").map(Number);
|
|
2129
|
+
dominantColor = [r, g, b];
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
return dominantColor;
|
|
2133
|
+
}
|
|
2134
|
+
function getBestContrastColor(imageColor) {
|
|
2135
|
+
let bestColor = DESIGN_PALETTE[0];
|
|
2136
|
+
let bestContrast = 0;
|
|
2137
|
+
for (const color of DESIGN_PALETTE) {
|
|
2138
|
+
const contrast = getContrastRatio(imageColor, color.rgb);
|
|
2139
|
+
if (contrast > bestContrast) {
|
|
2140
|
+
bestContrast = contrast;
|
|
2141
|
+
bestColor = color;
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
return bestContrast >= 3 ? bestColor : DESIGN_PALETTE.find((c) => c.name === "black") || bestColor;
|
|
2145
|
+
}
|
|
2146
|
+
function analyzeImageColor(imageSrc) {
|
|
2147
|
+
return new Promise((resolve, reject) => {
|
|
2148
|
+
const img = new Image();
|
|
2149
|
+
img.crossOrigin = "anonymous";
|
|
2150
|
+
img.onload = () => {
|
|
2151
|
+
try {
|
|
2152
|
+
const canvas = document.createElement("canvas");
|
|
2153
|
+
const ctx = canvas.getContext("2d");
|
|
2154
|
+
if (!ctx) {
|
|
2155
|
+
reject(new Error("Could not get canvas context"));
|
|
2156
|
+
return;
|
|
2157
|
+
}
|
|
2158
|
+
const maxSize = 100;
|
|
2159
|
+
const scale = Math.min(maxSize / img.width, maxSize / img.height);
|
|
2160
|
+
canvas.width = img.width * scale;
|
|
2161
|
+
canvas.height = img.height * scale;
|
|
2162
|
+
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
|
2163
|
+
const dominantColor = extractDominantColor(canvas);
|
|
2164
|
+
const bestContrastColor = getBestContrastColor(dominantColor);
|
|
2165
|
+
resolve(bestContrastColor);
|
|
2166
|
+
} catch (error) {
|
|
2167
|
+
reject(error);
|
|
2168
|
+
}
|
|
2169
|
+
};
|
|
2170
|
+
img.onerror = () => reject(new Error("Failed to load image"));
|
|
2171
|
+
img.src = imageSrc;
|
|
2172
|
+
});
|
|
2173
|
+
}
|
|
2174
|
+
async function extractImageEdgeColorAsync(imageUrl) {
|
|
2175
|
+
return new Promise((resolve) => {
|
|
2176
|
+
if (typeof window === "undefined") {
|
|
2177
|
+
resolve("#000000");
|
|
2178
|
+
return;
|
|
2179
|
+
}
|
|
2180
|
+
const img = new Image();
|
|
2181
|
+
img.crossOrigin = "anonymous";
|
|
2182
|
+
img.onload = () => {
|
|
2183
|
+
try {
|
|
2184
|
+
const canvas = document.createElement("canvas");
|
|
2185
|
+
const ctx = canvas.getContext("2d");
|
|
2186
|
+
if (!ctx) {
|
|
2187
|
+
resolve("#000000");
|
|
2188
|
+
return;
|
|
2189
|
+
}
|
|
2190
|
+
const maxSize = 50;
|
|
2191
|
+
const scale = Math.min(maxSize / img.naturalWidth, maxSize / img.naturalHeight);
|
|
2192
|
+
const w = Math.round(img.naturalWidth * scale);
|
|
2193
|
+
const h = Math.round(img.naturalHeight * scale);
|
|
2194
|
+
canvas.width = w;
|
|
2195
|
+
canvas.height = h;
|
|
2196
|
+
ctx.drawImage(img, 0, 0, w, h);
|
|
2197
|
+
const data = ctx.getImageData(0, 0, w, h).data;
|
|
2198
|
+
const edgeW = Math.max(2, Math.round(w * 0.15));
|
|
2199
|
+
const edgeH = Math.max(2, Math.round(h * 0.15));
|
|
2200
|
+
const bucketSize = 32;
|
|
2201
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
2202
|
+
for (let y = 0; y < h; y++) {
|
|
2203
|
+
for (let x = 0; x < w; x++) {
|
|
2204
|
+
if (!(x < edgeW || x >= w - edgeW || y < edgeH || y >= h - edgeH)) continue;
|
|
2205
|
+
const i = (y * w + x) * 4;
|
|
2206
|
+
if (data[i + 3] < 128) continue;
|
|
2207
|
+
const br = Math.floor(data[i] / bucketSize) * bucketSize;
|
|
2208
|
+
const bg = Math.floor(data[i + 1] / bucketSize) * bucketSize;
|
|
2209
|
+
const bb = Math.floor(data[i + 2] / bucketSize) * bucketSize;
|
|
2210
|
+
const key = `${br},${bg},${bb}`;
|
|
2211
|
+
const existing = buckets.get(key);
|
|
2212
|
+
if (existing) {
|
|
2213
|
+
existing.r += data[i];
|
|
2214
|
+
existing.g += data[i + 1];
|
|
2215
|
+
existing.b += data[i + 2];
|
|
2216
|
+
existing.count++;
|
|
2217
|
+
} else {
|
|
2218
|
+
buckets.set(key, { r: data[i], g: data[i + 1], b: data[i + 2], count: 1 });
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
let best = { r: 0, g: 0, b: 0, count: 0 };
|
|
2223
|
+
for (const b2 of buckets.values()) {
|
|
2224
|
+
if (b2.count > best.count) best = b2;
|
|
2225
|
+
}
|
|
2226
|
+
if (best.count === 0) {
|
|
2227
|
+
resolve("#000000");
|
|
2228
|
+
return;
|
|
2229
|
+
}
|
|
2230
|
+
const r = Math.round(best.r / best.count), g = Math.round(best.g / best.count), b = Math.round(best.b / best.count);
|
|
2231
|
+
resolve(`#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`);
|
|
2232
|
+
} catch {
|
|
2233
|
+
resolve("#000000");
|
|
2234
|
+
}
|
|
2235
|
+
};
|
|
2236
|
+
img.onerror = () => resolve("#000000");
|
|
2237
|
+
img.src = imageUrl;
|
|
2238
|
+
});
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
// src/utils/image-proxy.ts
|
|
2242
|
+
function getProxiedImageUrl(imageUrl, options) {
|
|
2243
|
+
if (!imageUrl) return null;
|
|
2244
|
+
const proxyPrefix = options?.proxyPrefix;
|
|
2245
|
+
const skipDomains = options?.skipDomains ?? [];
|
|
2246
|
+
const directHttps = options?.directHttps ?? false;
|
|
2247
|
+
if (proxyPrefix && imageUrl.includes(proxyPrefix)) {
|
|
2248
|
+
return imageUrl;
|
|
2249
|
+
}
|
|
2250
|
+
if (!imageUrl.startsWith("http://") && !imageUrl.startsWith("https://")) {
|
|
2251
|
+
return imageUrl;
|
|
2252
|
+
}
|
|
2253
|
+
if (directHttps && imageUrl.startsWith("https://")) {
|
|
2254
|
+
return imageUrl;
|
|
2255
|
+
}
|
|
2256
|
+
if (!proxyPrefix) {
|
|
2257
|
+
return imageUrl;
|
|
2258
|
+
}
|
|
2259
|
+
for (const domain of skipDomains) {
|
|
2260
|
+
if (imageUrl.includes(domain)) {
|
|
2261
|
+
return imageUrl;
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
return `${proxyPrefix}?url=${encodeURIComponent(imageUrl)}`;
|
|
2265
|
+
}
|
|
2266
|
+
function urlPathLooksLikeSvg(imageUrl) {
|
|
2267
|
+
try {
|
|
2268
|
+
return /\.svg$/i.test(new URL(imageUrl).pathname);
|
|
2269
|
+
} catch {
|
|
2270
|
+
return /\.svg(\?|#|$)/i.test(imageUrl);
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
function shouldProxyImage(imageUrl, proxyPrefix) {
|
|
2274
|
+
if (!imageUrl) return false;
|
|
2275
|
+
if (!imageUrl.startsWith("http://") && !imageUrl.startsWith("https://")) return false;
|
|
2276
|
+
if (proxyPrefix && imageUrl.includes(proxyPrefix)) return false;
|
|
2277
|
+
return true;
|
|
2278
|
+
}
|
|
2279
|
+
function generateImageSizes(_url) {
|
|
2280
|
+
return `(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw`;
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2283
|
+
// src/utils/date-utils.ts
|
|
2284
|
+
function formatRelativeTime(timestamp) {
|
|
2285
|
+
const now = /* @__PURE__ */ new Date();
|
|
2286
|
+
const targetTime = typeof timestamp === "string" ? new Date(timestamp) : timestamp;
|
|
2287
|
+
if (isNaN(targetTime.getTime())) {
|
|
2288
|
+
console.warn("\u26A0\uFE0F Invalid timestamp in formatRelativeTime:", timestamp);
|
|
2289
|
+
return "Unknown time";
|
|
2290
|
+
}
|
|
2291
|
+
const diffInMs = now.getTime() - targetTime.getTime();
|
|
2292
|
+
const diffInMinutes = Math.floor(diffInMs / (1e3 * 60));
|
|
2293
|
+
if (diffInMinutes < 0) {
|
|
2294
|
+
return "Just now";
|
|
2295
|
+
}
|
|
2296
|
+
if (diffInMinutes < 1) return "Just now";
|
|
2297
|
+
if (diffInMinutes < 60) return `${diffInMinutes}m ago`;
|
|
2298
|
+
const diffInHours = Math.floor(diffInMinutes / 60);
|
|
2299
|
+
if (diffInHours < 24) return `${diffInHours}h ago`;
|
|
2300
|
+
const diffInDays = Math.floor(diffInHours / 24);
|
|
2301
|
+
if (diffInDays < 7) return `${diffInDays}d ago`;
|
|
2302
|
+
if (diffInDays < 30) {
|
|
2303
|
+
const weeks = Math.floor(diffInDays / 7);
|
|
2304
|
+
return `${weeks}w ago`;
|
|
2305
|
+
}
|
|
2306
|
+
return targetTime.toLocaleDateString("en-US", {
|
|
2307
|
+
month: "short",
|
|
2308
|
+
day: "numeric",
|
|
2309
|
+
year: targetTime.getFullYear() !== now.getFullYear() ? "numeric" : void 0
|
|
2310
|
+
});
|
|
2311
|
+
}
|
|
2312
|
+
function formatAbsoluteDate(timestamp, options = {}) {
|
|
2313
|
+
const targetTime = typeof timestamp === "string" ? new Date(timestamp) : timestamp;
|
|
2314
|
+
if (isNaN(targetTime.getTime())) {
|
|
2315
|
+
console.warn("\u26A0\uFE0F Invalid timestamp in formatAbsoluteDate:", timestamp);
|
|
2316
|
+
return "Invalid date";
|
|
2317
|
+
}
|
|
2318
|
+
const defaultOptions = {
|
|
2319
|
+
year: "numeric",
|
|
2320
|
+
month: "short",
|
|
2321
|
+
day: "numeric",
|
|
2322
|
+
...options
|
|
2323
|
+
};
|
|
2324
|
+
return targetTime.toLocaleDateString("en-US", defaultOptions);
|
|
2325
|
+
}
|
|
2326
|
+
function formatDateTime(timestamp, options = {}) {
|
|
2327
|
+
const targetTime = typeof timestamp === "string" ? new Date(timestamp) : timestamp;
|
|
2328
|
+
if (isNaN(targetTime.getTime())) {
|
|
2329
|
+
console.warn("\u26A0\uFE0F Invalid timestamp in formatDateTime:", timestamp);
|
|
2330
|
+
return "Invalid date";
|
|
2331
|
+
}
|
|
2332
|
+
const defaultOptions = {
|
|
2333
|
+
year: "numeric",
|
|
2334
|
+
month: "short",
|
|
2335
|
+
day: "numeric",
|
|
2336
|
+
hour: "numeric",
|
|
2337
|
+
minute: "2-digit",
|
|
2338
|
+
...options
|
|
2339
|
+
};
|
|
2340
|
+
return targetTime.toLocaleDateString("en-US", defaultOptions);
|
|
2341
|
+
}
|
|
2342
|
+
function getDetailedTimeDifference(timestamp) {
|
|
2343
|
+
const now = /* @__PURE__ */ new Date();
|
|
2344
|
+
const targetTime = typeof timestamp === "string" ? new Date(timestamp) : timestamp;
|
|
2345
|
+
if (isNaN(targetTime.getTime())) {
|
|
2346
|
+
return "Invalid date";
|
|
2347
|
+
}
|
|
2348
|
+
const diffInMs = now.getTime() - targetTime.getTime();
|
|
2349
|
+
const diffInSeconds = Math.floor(diffInMs / 1e3);
|
|
2350
|
+
const diffInMinutes = Math.floor(diffInSeconds / 60);
|
|
2351
|
+
const diffInHours = Math.floor(diffInMinutes / 60);
|
|
2352
|
+
const diffInDays = Math.floor(diffInHours / 24);
|
|
2353
|
+
if (diffInSeconds < 60) return `${diffInSeconds} seconds ago`;
|
|
2354
|
+
if (diffInMinutes < 60) return `${diffInMinutes} minutes ago`;
|
|
2355
|
+
if (diffInHours < 24) return `${diffInHours} hours ago`;
|
|
2356
|
+
if (diffInDays < 30) return `${diffInDays} days ago`;
|
|
2357
|
+
const diffInMonths = Math.floor(diffInDays / 30);
|
|
2358
|
+
if (diffInMonths < 12) return `${diffInMonths} months ago`;
|
|
2359
|
+
const diffInYears = Math.floor(diffInDays / 365);
|
|
2360
|
+
return `${diffInYears} years ago`;
|
|
2361
|
+
}
|
|
2362
|
+
function isToday(timestamp) {
|
|
2363
|
+
const today = /* @__PURE__ */ new Date();
|
|
2364
|
+
const targetTime = typeof timestamp === "string" ? new Date(timestamp) : timestamp;
|
|
2365
|
+
return today.toDateString() === targetTime.toDateString();
|
|
2366
|
+
}
|
|
2367
|
+
function isWithinMinutes(timestamp, minutes) {
|
|
2368
|
+
const now = /* @__PURE__ */ new Date();
|
|
2369
|
+
const targetTime = typeof timestamp === "string" ? new Date(timestamp) : timestamp;
|
|
2370
|
+
const diffInMs = now.getTime() - targetTime.getTime();
|
|
2371
|
+
const diffInMinutes = diffInMs / (1e3 * 60);
|
|
2372
|
+
return diffInMinutes <= minutes && diffInMinutes >= 0;
|
|
2373
|
+
}
|
|
2374
|
+
function createUTCTimestamp() {
|
|
2375
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2378
|
+
// src/utils/source-icons.ts
|
|
2379
|
+
var SOURCE_ICON_NAMES = {
|
|
2380
|
+
// Doc tables
|
|
2381
|
+
"openframe-docs": "openframe",
|
|
2382
|
+
"data-room-docs": "shield",
|
|
2383
|
+
// CMS / programs
|
|
2384
|
+
"blog-posts": "newspaper",
|
|
2385
|
+
"product-releases": "rocket",
|
|
2386
|
+
"case-studies": "briefcase",
|
|
2387
|
+
"onboarding-guides": "graduation-cap",
|
|
2388
|
+
webinars: "video",
|
|
2389
|
+
events: "calendar",
|
|
2390
|
+
podcasts: "headphones",
|
|
2391
|
+
"customer-interviews": "users",
|
|
2392
|
+
// Financials
|
|
2393
|
+
"investor-updates": "mail",
|
|
2394
|
+
"financial-kpis": "activity",
|
|
2395
|
+
"financial-cap-table": "table",
|
|
2396
|
+
"financial-pnl": "trending-up",
|
|
2397
|
+
"financial-balance-sheet": "dollar-sign",
|
|
2398
|
+
"financial-cash-flow": "banknote",
|
|
2399
|
+
// ClickUp
|
|
2400
|
+
"clickup-roadmap": "clickup",
|
|
2401
|
+
"clickup-delivery": "clickup",
|
|
2402
|
+
"clickup-tasks-internal": "clickup",
|
|
2403
|
+
// GitHub
|
|
2404
|
+
"github-commits": "github",
|
|
2405
|
+
"github-pull-requests": "github",
|
|
2406
|
+
"github-pr-reviews": "github",
|
|
2407
|
+
"github-commits-public": "github",
|
|
2408
|
+
"github-pull-requests-public": "github",
|
|
2409
|
+
"github-pr-reviews-public": "github",
|
|
2410
|
+
// HubSpot
|
|
2411
|
+
"hubspot-tickets": "hubspot",
|
|
2412
|
+
"hubspot-tickets-anon": "hubspot",
|
|
2413
|
+
"hubspot-tickets-self": "hubspot",
|
|
2414
|
+
// Communications
|
|
2415
|
+
"slack-messages": "slack"
|
|
2416
|
+
};
|
|
2417
|
+
function getSourceIconName(tableId) {
|
|
2418
|
+
if (!tableId) return void 0;
|
|
2419
|
+
return SOURCE_ICON_NAMES[tableId];
|
|
2420
|
+
}
|
|
2421
|
+
var SOURCE_LABELS_BY_TABLE = {
|
|
2422
|
+
// Doc tables
|
|
2423
|
+
"openframe-docs": "OpenFrame Docs",
|
|
2424
|
+
"data-room-docs": "Data Room",
|
|
2425
|
+
// CMS / programs
|
|
2426
|
+
"blog-posts": "Blog Posts",
|
|
2427
|
+
"product-releases": "Product Releases",
|
|
2428
|
+
"case-studies": "Case Studies",
|
|
2429
|
+
"onboarding-guides": "Onboarding Guides",
|
|
2430
|
+
webinars: "Webinars",
|
|
2431
|
+
events: "Events",
|
|
2432
|
+
podcasts: "Podcasts",
|
|
2433
|
+
"customer-interviews": "Customer Interviews",
|
|
2434
|
+
// Financials
|
|
2435
|
+
"investor-updates": "Investor Updates",
|
|
2436
|
+
"financial-kpis": "Financial KPIs",
|
|
2437
|
+
"financial-cap-table": "Cap Table",
|
|
2438
|
+
"financial-pnl": "Profit & Loss",
|
|
2439
|
+
"financial-balance-sheet": "Balance Sheet",
|
|
2440
|
+
"financial-cash-flow": "Cash Flow",
|
|
2441
|
+
// ClickUp
|
|
2442
|
+
"clickup-roadmap": "ClickUp Roadmap",
|
|
2443
|
+
"clickup-delivery": "ClickUp Delivery",
|
|
2444
|
+
"clickup-tasks-internal": "ClickUp Tasks",
|
|
2445
|
+
// GitHub
|
|
2446
|
+
"github-commits": "GitHub Commits",
|
|
2447
|
+
"github-pull-requests": "GitHub Pull Requests",
|
|
2448
|
+
"github-pr-reviews": "GitHub PR Reviews",
|
|
2449
|
+
"github-commits-public": "OpenFrame Commits",
|
|
2450
|
+
"github-pull-requests-public": "OpenFrame Pull Requests",
|
|
2451
|
+
"github-pr-reviews-public": "OpenFrame PR Reviews",
|
|
2452
|
+
// HubSpot
|
|
2453
|
+
"hubspot-tickets": "HubSpot Tickets",
|
|
2454
|
+
"hubspot-tickets-anon": "Known Issues",
|
|
2455
|
+
"hubspot-tickets-self": "My Tickets",
|
|
2456
|
+
// Communications
|
|
2457
|
+
"slack-messages": "OpenMSP Community"
|
|
2458
|
+
};
|
|
2459
|
+
function getSourceLabel(tableId) {
|
|
2460
|
+
return SOURCE_LABELS_BY_TABLE[tableId] ?? tableId;
|
|
2461
|
+
}
|
|
2462
|
+
|
|
2463
|
+
// src/components/chat/utils/chat-attachment-markdown.ts
|
|
2464
|
+
var CHAT_ATTACHMENT_VIEW_URL_PREFIX = "/api/storage/view/chat-attachments/";
|
|
2465
|
+
var CHAT_ATTACHMENT_VIEW_TOKEN_QUERY_PARAM = "t";
|
|
2466
|
+
var ANTHROPIC_SUPPORTED_IMAGE_MIME = [
|
|
2467
|
+
"image/jpeg",
|
|
2468
|
+
"image/png",
|
|
2469
|
+
"image/webp",
|
|
2470
|
+
"image/gif"
|
|
2471
|
+
];
|
|
2472
|
+
function buildChatAttachmentViewUrl(viewUrlPrefix, storagePath, viewToken) {
|
|
2473
|
+
return `${viewUrlPrefix}${storagePath}?${CHAT_ATTACHMENT_VIEW_TOKEN_QUERY_PARAM}=${encodeURIComponent(viewToken)}`;
|
|
2474
|
+
}
|
|
2475
|
+
function escapeMarkdownInline(text) {
|
|
2476
|
+
return text.replace(/[[\]()\\\n\r<>"]/g, (ch) => {
|
|
2477
|
+
switch (ch) {
|
|
2478
|
+
case "\n":
|
|
2479
|
+
return " ";
|
|
2480
|
+
case "\r":
|
|
2481
|
+
return "";
|
|
2482
|
+
default:
|
|
2483
|
+
return `\\${ch}`;
|
|
2484
|
+
}
|
|
2485
|
+
});
|
|
2486
|
+
}
|
|
2487
|
+
function formatChatAttachmentMarkdownForBubble(att, viewUrlPrefix) {
|
|
2488
|
+
const safeName = escapeMarkdownInline(att.fileName);
|
|
2489
|
+
const url = buildChatAttachmentViewUrl(viewUrlPrefix, att.storagePath, att.viewToken);
|
|
2490
|
+
const isImage = ANTHROPIC_SUPPORTED_IMAGE_MIME.includes(att.contentType);
|
|
2491
|
+
return isImage ? `
|
|
2492
|
+
|
|
2493
|
+
` : `
|
|
2494
|
+
|
|
2495
|
+
[Attached: ${safeName}](${url})`;
|
|
2496
|
+
}
|
|
2497
|
+
var CHAT_ATTACHMENT_VIEW_URL_PREFIX_REGEX_ESCAPED = CHAT_ATTACHMENT_VIEW_URL_PREFIX.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2498
|
+
var CHAT_ATTACHMENT_MARKDOWN_PATTERN = new RegExp(
|
|
2499
|
+
`^\\s*!?\\[[^\\]]*\\]\\(${CHAT_ATTACHMENT_VIEW_URL_PREFIX_REGEX_ESCAPED}[^)]+\\)\\s*$`,
|
|
2500
|
+
"gm"
|
|
2501
|
+
);
|
|
2502
|
+
function stripChatAttachmentMarkdown(text) {
|
|
2503
|
+
const storagePaths = [];
|
|
2504
|
+
const pathExtract = new RegExp(
|
|
2505
|
+
`\\(${CHAT_ATTACHMENT_VIEW_URL_PREFIX_REGEX_ESCAPED}([^?)]+)`
|
|
2506
|
+
);
|
|
2507
|
+
const stripped = text.replace(CHAT_ATTACHMENT_MARKDOWN_PATTERN, (match) => {
|
|
2508
|
+
const m = match.match(pathExtract);
|
|
2509
|
+
if (m && m[1]) storagePaths.push(m[1]);
|
|
2510
|
+
return "";
|
|
2511
|
+
});
|
|
2512
|
+
return {
|
|
2513
|
+
stripped: stripped.replace(/\n{3,}/g, "\n\n").trim(),
|
|
2514
|
+
storagePaths
|
|
2515
|
+
};
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
// src/components/chat/utils/auto-continuation-directive.ts
|
|
2519
|
+
var AUTO_CONTINUATION_DIRECTIVE_PREFIX = "[internal-auto-continuation]";
|
|
2520
|
+
function buildAutoContinuationDirective(toolName, opts = {}) {
|
|
2521
|
+
const ticketRef = opts.ticketId ? ` (ticket #${opts.ticketId})` : "";
|
|
2522
|
+
const ticketHash = opts.ticketId ? ` #${opts.ticketId}` : "";
|
|
2523
|
+
const isClose = toolName === "update_ticket" && opts.status?.toUpperCase() === "CLOSED";
|
|
2524
|
+
if (toolName === "create_ticket") {
|
|
2525
|
+
return `${AUTO_CONTINUATION_DIRECTIVE_PREFIX} The user just approved create_ticket${ticketRef}. Per ticket-protocol \xA71a, ask 2-4 SHORT, issue-specific diagnostic follow-up questions tailored to the symptom they reported in their original message. When they answer, propose an update_ticket with content_addendum carrying a clean Q&A digest. Do NOT call any tool in this turn \u2014 just write the questions as prose.`;
|
|
2526
|
+
}
|
|
2527
|
+
if (isClose) {
|
|
2528
|
+
return `${AUTO_CONTINUATION_DIRECTIVE_PREFIX} The user just approved closing ticket${ticketHash}. Per ticket-protocol \xA71b, ask ONE short question: "How was this resolved? I'll add it to the ticket as a closing note." Phrase kindly even if the user was curt. When they answer, propose an update_ticket with content_addendum="[Resolution] <their words>". Do NOT call any tool in this turn \u2014 just write the prose ask.`;
|
|
2529
|
+
}
|
|
2530
|
+
return `${AUTO_CONTINUATION_DIRECTIVE_PREFIX} The user just approved update_ticket${ticketHash}. Acknowledge the change in ONE short sentence; if anything else looks like it needs attention, ask. Do NOT call any tool in this turn.`;
|
|
2531
|
+
}
|
|
2532
|
+
|
|
2533
|
+
// src/components/chat/utils/flatten-assistant-content.ts
|
|
2534
|
+
function flattenAssistantContent(raw) {
|
|
2535
|
+
if (typeof raw === "string") return raw;
|
|
2536
|
+
if (!Array.isArray(raw)) return "";
|
|
2537
|
+
const parts = [];
|
|
2538
|
+
for (const seg of raw) {
|
|
2539
|
+
if (seg && typeof seg === "object" && seg.type === "text") {
|
|
2540
|
+
const t = seg.text;
|
|
2541
|
+
if (typeof t === "string" && t.length > 0) parts.push(t);
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2544
|
+
return parts.join("\n\n");
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
// src/components/chat/types/message.types.ts
|
|
2548
|
+
var SCROLL_ANCHOR = { TOP: "top", BOTTOM: "bottom" };
|
|
2549
|
+
|
|
2550
|
+
// src/components/chat/utils/scroll-anchor.ts
|
|
2551
|
+
var SCROLL_ANCHOR_WIRE_KEY = "scrollAnchor";
|
|
2552
|
+
function parseScrollAnchor(raw) {
|
|
2553
|
+
return raw === SCROLL_ANCHOR.TOP || raw === SCROLL_ANCHOR.BOTTOM ? raw : null;
|
|
2554
|
+
}
|
|
2555
|
+
|
|
2556
|
+
// src/components/chat/utils/slash-dispatch-utils.ts
|
|
2557
|
+
var WIRE_TABLE_ID_REGEX = /^[a-z][a-z0-9-]*$/;
|
|
2558
|
+
var WIRE_ID_REGEX = /^[A-Za-z0-9._:/-]+$/;
|
|
2559
|
+
var WIRE_TABLE_ID_MAX = 60;
|
|
2560
|
+
var WIRE_ID_MAX = 200;
|
|
2561
|
+
var WIRE_QUERY_MAX = 2e3;
|
|
2562
|
+
function parseWireCommandOverride(raw) {
|
|
2563
|
+
if (!raw || typeof raw !== "object") return null;
|
|
2564
|
+
const out = {};
|
|
2565
|
+
const r = raw;
|
|
2566
|
+
if (r.entityIdFilter && typeof r.entityIdFilter === "object") {
|
|
2567
|
+
const f = r.entityIdFilter;
|
|
2568
|
+
if (typeof f.tableId === "string" && f.tableId.length > 0 && f.tableId.length <= WIRE_TABLE_ID_MAX && WIRE_TABLE_ID_REGEX.test(f.tableId) && typeof f.id === "string" && f.id.length > 0 && f.id.length <= WIRE_ID_MAX && WIRE_ID_REGEX.test(f.id)) {
|
|
2569
|
+
out.entityIdFilter = { tableId: f.tableId, id: f.id };
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
if (typeof r.retrievalQueryOverride === "string" && r.retrievalQueryOverride.length > 0 && r.retrievalQueryOverride.length <= WIRE_QUERY_MAX) {
|
|
2573
|
+
out.retrievalQueryOverride = r.retrievalQueryOverride;
|
|
2574
|
+
}
|
|
2575
|
+
if (out.entityIdFilter === void 0 && out.retrievalQueryOverride === void 0) {
|
|
2576
|
+
return null;
|
|
2577
|
+
}
|
|
2578
|
+
return out;
|
|
2579
|
+
}
|
|
2580
|
+
function sanitizeTitleForChat(value) {
|
|
2581
|
+
return (value ?? "").replace(/[\r\n\t]+/g, " ").trim();
|
|
2582
|
+
}
|
|
2583
|
+
function formatSingularLookupInvocation(cmdId, value) {
|
|
2584
|
+
const safe = sanitizeTitleForChat(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
2585
|
+
return safe ? `/${cmdId} "${safe}"` : `/${cmdId}`;
|
|
2586
|
+
}
|
|
2587
|
+
function extractEntityIdFilter(override, expectedTableId) {
|
|
2588
|
+
const f = override?.entityIdFilter;
|
|
2589
|
+
if (!f) return null;
|
|
2590
|
+
const tableId = typeof f.tableId === "string" ? f.tableId : "";
|
|
2591
|
+
const id = typeof f.id === "string" ? f.id : "";
|
|
2592
|
+
if (!tableId || !id) return null;
|
|
2593
|
+
if (expectedTableId && tableId !== expectedTableId) return null;
|
|
2594
|
+
return { tableId, id };
|
|
2595
|
+
}
|
|
2596
|
+
function buildDiscussAddendum(args) {
|
|
2597
|
+
const idTag = args.id.length > 24 ? args.id.slice(0, 24) + "\u2026" : args.id;
|
|
2598
|
+
return `Ask drill-in for row id="${args.id}" in table "${args.tableId}". Focus the answer on this single record. If retrieval returns 0 rows (privacy filter), say so plainly per Rule 5b.
|
|
2599
|
+
|
|
2600
|
+
OPEN with the inline card on the FIRST line, immediately followed by the chip and a mono-font id tag \u2014 no prose before the card:
|
|
2601
|
+
[card://<type>:${args.id}] [N] \`${args.tableId} \xB7 ${idTag}\`
|
|
2602
|
+
Use the EXACT <type> from the row's <document type="..." id="${args.id}"> tag.
|
|
2603
|
+
|
|
2604
|
+
SURFACE EVERY FIELD PRESENT in the retrieved record \u2014 the user already knows the title from the card; the value of Ask is the BODY (description, status, vote counts, dates, linked URLs, \u2026). Walk each non-empty field. Don't invent fields, don't hallucinate values, silently omit absent fields.
|
|
2605
|
+
|
|
2606
|
+
FORMAT: card+chip+id-tag opener, then ONE framing sentence, then a compact bulleted "**Field** \u2014 value" list. Don't restate fields already in the list.`;
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
// src/components/chat/utils/clickup-task-type-utils.ts
|
|
2610
|
+
var CUSTOM_ITEM_ID = {
|
|
2611
|
+
TASK: 1e3,
|
|
2612
|
+
MILESTONE: 1001,
|
|
2613
|
+
RECURRING: 1002,
|
|
2614
|
+
SUBTASK: 1003,
|
|
2615
|
+
FORM: 1004,
|
|
2616
|
+
PLAN: 1006,
|
|
2617
|
+
STRATEGY: 1007,
|
|
2618
|
+
BUG: 1008,
|
|
2619
|
+
REQUEST: 1009,
|
|
2620
|
+
FEATURE: 1010,
|
|
2621
|
+
STORY: 1011,
|
|
2622
|
+
EPIC: 1012,
|
|
2623
|
+
COMPONENT: 1013,
|
|
2624
|
+
INITIATIVE: 1014
|
|
2625
|
+
};
|
|
2626
|
+
function getTaskTypeLabel(customItemId) {
|
|
2627
|
+
switch (customItemId) {
|
|
2628
|
+
case CUSTOM_ITEM_ID.TASK:
|
|
2629
|
+
return "Task";
|
|
2630
|
+
case CUSTOM_ITEM_ID.MILESTONE:
|
|
2631
|
+
return "Milestone";
|
|
2632
|
+
case CUSTOM_ITEM_ID.RECURRING:
|
|
2633
|
+
return "Recurring";
|
|
2634
|
+
case CUSTOM_ITEM_ID.SUBTASK:
|
|
2635
|
+
return "Subtask";
|
|
2636
|
+
case CUSTOM_ITEM_ID.FORM:
|
|
2637
|
+
return "Form";
|
|
2638
|
+
case CUSTOM_ITEM_ID.PLAN:
|
|
2639
|
+
return "Plan";
|
|
2640
|
+
case CUSTOM_ITEM_ID.STRATEGY:
|
|
2641
|
+
return "Strategy";
|
|
2642
|
+
case CUSTOM_ITEM_ID.BUG:
|
|
2643
|
+
return "Bug";
|
|
2644
|
+
case CUSTOM_ITEM_ID.REQUEST:
|
|
2645
|
+
return "Request";
|
|
2646
|
+
case CUSTOM_ITEM_ID.FEATURE:
|
|
2647
|
+
return "Feature";
|
|
2648
|
+
case CUSTOM_ITEM_ID.STORY:
|
|
2649
|
+
return "Story";
|
|
2650
|
+
case CUSTOM_ITEM_ID.EPIC:
|
|
2651
|
+
return "Epic";
|
|
2652
|
+
case CUSTOM_ITEM_ID.COMPONENT:
|
|
2653
|
+
return "Component";
|
|
2654
|
+
case CUSTOM_ITEM_ID.INITIATIVE:
|
|
2655
|
+
return "Initiative";
|
|
2656
|
+
default:
|
|
2657
|
+
return null;
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
|
|
2661
|
+
// src/components/chat/utils/agent-status-message.ts
|
|
2662
|
+
function getStatusColorScheme(status) {
|
|
2663
|
+
const s = status?.toLowerCase() || "";
|
|
2664
|
+
switch (status) {
|
|
2665
|
+
case "completed":
|
|
2666
|
+
case "success":
|
|
2667
|
+
case "active":
|
|
2668
|
+
return "success";
|
|
2669
|
+
case "failed":
|
|
2670
|
+
case "failure":
|
|
2671
|
+
case "cancelled":
|
|
2672
|
+
case "error":
|
|
2673
|
+
return "error";
|
|
2674
|
+
case "running":
|
|
2675
|
+
case "processing":
|
|
2676
|
+
case "closed":
|
|
2677
|
+
return "cyan";
|
|
2678
|
+
case "pending":
|
|
2679
|
+
case "warning":
|
|
2680
|
+
return "warning";
|
|
2681
|
+
case "draft":
|
|
2682
|
+
// review cycles not yet opened to reviewers
|
|
2683
|
+
case "info":
|
|
2684
|
+
return "default";
|
|
2685
|
+
}
|
|
2686
|
+
if (s.includes("complete") || s.includes("done")) return "success";
|
|
2687
|
+
if (s.includes("review")) return "cyan";
|
|
2688
|
+
if (s.includes("working") || s.includes("progress")) return "warning";
|
|
2689
|
+
if (s.includes("blocked") || s.includes("failed")) return "error";
|
|
2690
|
+
return "default";
|
|
2691
|
+
}
|
|
2692
|
+
|
|
2693
|
+
// src/components/chat/utils/external-app-urls.ts
|
|
2694
|
+
var CLICKUP_APP_BASE = "https://app.clickup.com";
|
|
2695
|
+
function clickupTaskUrl(externalId) {
|
|
2696
|
+
if (!externalId) return null;
|
|
2697
|
+
return `${CLICKUP_APP_BASE}/t/${externalId}`;
|
|
2698
|
+
}
|
|
2699
|
+
|
|
2700
|
+
// src/components/chat/utils/is-cross-origin-url.ts
|
|
2701
|
+
function isCrossOriginUrl(url) {
|
|
2702
|
+
if (!url) return false;
|
|
2703
|
+
if (url.startsWith("/") && !url.startsWith("//")) return false;
|
|
2704
|
+
return true;
|
|
2705
|
+
}
|
|
2706
|
+
var REACT_MAJOR = parseInt((React2__default.default.version || "0").split(".")[0], 10);
|
|
2707
|
+
var USE_CAMEL_CASE_FETCH_PRIORITY = REACT_MAJOR >= 19;
|
|
2708
|
+
function fetchPriorityProp(priority) {
|
|
2709
|
+
const value = priority === void 0 ? "auto" : typeof priority === "boolean" ? priority ? "high" : "low" : priority;
|
|
2710
|
+
return USE_CAMEL_CASE_FETCH_PRIORITY ? { fetchPriority: value } : { fetchpriority: value };
|
|
2711
|
+
}
|
|
2712
|
+
|
|
2713
|
+
exports.ANTHROPIC_SUPPORTED_IMAGE_MIME = ANTHROPIC_SUPPORTED_IMAGE_MIME;
|
|
2714
|
+
exports.AUTO_CONTINUATION_DIRECTIVE_PREFIX = AUTO_CONTINUATION_DIRECTIVE_PREFIX;
|
|
2715
|
+
exports.CHAT_ATTACHMENT_MARKDOWN_PATTERN = CHAT_ATTACHMENT_MARKDOWN_PATTERN;
|
|
2716
|
+
exports.CHAT_ATTACHMENT_VIEW_TOKEN_QUERY_PARAM = CHAT_ATTACHMENT_VIEW_TOKEN_QUERY_PARAM;
|
|
2717
|
+
exports.CHAT_ATTACHMENT_VIEW_URL_PREFIX = CHAT_ATTACHMENT_VIEW_URL_PREFIX;
|
|
2718
|
+
exports.CHAT_ATTACHMENT_VIEW_URL_PREFIX_REGEX_ESCAPED = CHAT_ATTACHMENT_VIEW_URL_PREFIX_REGEX_ESCAPED;
|
|
2719
|
+
exports.CUSTOM_ITEM_ID = CUSTOM_ITEM_ID;
|
|
1670
2720
|
exports.DEFAULT_OS_PLATFORM = DEFAULT_OS_PLATFORM;
|
|
2721
|
+
exports.DESIGN_PALETTE = DESIGN_PALETTE;
|
|
1671
2722
|
exports.GENERIC_EMAIL_DOMAINS = GENERIC_EMAIL_DOMAINS;
|
|
2723
|
+
exports.ICON_REGISTRY = ICON_REGISTRY;
|
|
1672
2724
|
exports.OS_PLATFORMS = OS_PLATFORMS;
|
|
1673
2725
|
exports.PLAY_ICON_PATH = PLAY_ICON_PATH;
|
|
2726
|
+
exports.SCROLL_ANCHOR = SCROLL_ANCHOR;
|
|
2727
|
+
exports.SCROLL_ANCHOR_WIRE_KEY = SCROLL_ANCHOR_WIRE_KEY;
|
|
2728
|
+
exports.SOURCE_ICON_NAMES = SOURCE_ICON_NAMES;
|
|
2729
|
+
exports.SOURCE_LABELS_BY_TABLE = SOURCE_LABELS_BY_TABLE;
|
|
2730
|
+
exports.analyzeImageColor = analyzeImageColor;
|
|
2731
|
+
exports.buildAutoContinuationDirective = buildAutoContinuationDirective;
|
|
2732
|
+
exports.buildChatAttachmentViewUrl = buildChatAttachmentViewUrl;
|
|
2733
|
+
exports.buildDiscussAddendum = buildDiscussAddendum;
|
|
1674
2734
|
exports.cleanEmailDomain = cleanEmailDomain;
|
|
2735
|
+
exports.clickupTaskUrl = clickupTaskUrl;
|
|
1675
2736
|
exports.cn = cn;
|
|
1676
2737
|
exports.consumeAccessCode = consumeAccessCode;
|
|
2738
|
+
exports.createUTCTimestamp = createUTCTimestamp;
|
|
1677
2739
|
exports.deepClone = deepClone;
|
|
1678
2740
|
exports.delay = delay;
|
|
2741
|
+
exports.escapeMarkdownInline = escapeMarkdownInline;
|
|
1679
2742
|
exports.extractDomainFromEmail = extractDomainFromEmail;
|
|
2743
|
+
exports.extractDominantColor = extractDominantColor;
|
|
2744
|
+
exports.extractEntityIdFilter = extractEntityIdFilter;
|
|
2745
|
+
exports.extractImageEdgeColorAsync = extractImageEdgeColorAsync;
|
|
2746
|
+
exports.fetchPriorityProp = fetchPriorityProp;
|
|
2747
|
+
exports.flattenAssistantContent = flattenAssistantContent;
|
|
2748
|
+
exports.formatAbbreviatedNumber = formatAbbreviatedNumber;
|
|
2749
|
+
exports.formatAbsoluteDate = formatAbsoluteDate;
|
|
2750
|
+
exports.formatBioText = formatBioText;
|
|
1680
2751
|
exports.formatBytes = formatBytes;
|
|
2752
|
+
exports.formatBytesShort = formatBytesShort;
|
|
2753
|
+
exports.formatChatAttachmentMarkdownForBubble = formatChatAttachmentMarkdownForBubble;
|
|
2754
|
+
exports.formatClassification = formatClassification;
|
|
2755
|
+
exports.formatCompactMetric = formatCompactMetric;
|
|
2756
|
+
exports.formatCurrency = formatCurrency;
|
|
1681
2757
|
exports.formatDate = formatDate;
|
|
2758
|
+
exports.formatDateRange = formatDateRange;
|
|
2759
|
+
exports.formatDateShort = formatDateShort;
|
|
2760
|
+
exports.formatDateSlashUTC = formatDateSlashUTC;
|
|
2761
|
+
exports.formatDateTime = formatDateTime;
|
|
2762
|
+
exports.formatDateTimeAt = formatDateTimeAt;
|
|
2763
|
+
exports.formatDateUTC = formatDateUTC;
|
|
2764
|
+
exports.formatDuration = formatDuration;
|
|
2765
|
+
exports.formatDurationCompact = formatDurationCompact;
|
|
2766
|
+
exports.formatDurationFromMs = formatDurationFromMs;
|
|
2767
|
+
exports.formatDurationFromRange = formatDurationFromRange;
|
|
2768
|
+
exports.formatDurationMMSS = formatDurationMMSS;
|
|
2769
|
+
exports.formatLargeNumber = formatLargeNumber;
|
|
2770
|
+
exports.formatLegalDate = formatLegalDate;
|
|
1682
2771
|
exports.formatNumber = formatNumber;
|
|
2772
|
+
exports.formatPercent = formatPercent;
|
|
1683
2773
|
exports.formatPhoneE164 = formatPhoneE164;
|
|
1684
2774
|
exports.formatPrice = formatPrice;
|
|
2775
|
+
exports.formatPricingModel = formatPricingModel;
|
|
1685
2776
|
exports.formatRelativeTime = formatRelativeTime;
|
|
1686
2777
|
exports.formatReleaseDate = formatReleaseDate;
|
|
2778
|
+
exports.formatSingularLookupInvocation = formatSingularLookupInvocation;
|
|
2779
|
+
exports.formatTimeWithTimezone = formatTimeWithTimezone;
|
|
2780
|
+
exports.formatUnderscoreText = formatUnderscoreText;
|
|
2781
|
+
exports.formatWholeDollars = formatWholeDollars;
|
|
2782
|
+
exports.generateImageSizes = generateImageSizes;
|
|
1687
2783
|
exports.generateRandomString = generateRandomString;
|
|
1688
2784
|
exports.getAllPlatformBaseDomains = getAllPlatformBaseDomains;
|
|
1689
2785
|
exports.getBaseUrl = getBaseUrl;
|
|
2786
|
+
exports.getBestContrastColor = getBestContrastColor;
|
|
1690
2787
|
exports.getConfidenceBgClass = getConfidenceBgClass;
|
|
1691
2788
|
exports.getConfidenceBorderClass = getConfidenceBorderClass;
|
|
1692
2789
|
exports.getConfidenceColorClass = getConfidenceColorClass;
|
|
1693
2790
|
exports.getConfidenceLabel = getConfidenceLabel;
|
|
1694
2791
|
exports.getConfidenceLevel = getConfidenceLevel;
|
|
1695
2792
|
exports.getConfidenceTextClass = getConfidenceTextClass;
|
|
2793
|
+
exports.getContrastRatio = getContrastRatio;
|
|
1696
2794
|
exports.getCountryByCode = getCountryByCode;
|
|
1697
2795
|
exports.getCountryPhoneData = getCountryPhoneData;
|
|
1698
2796
|
exports.getCurrentPlatform = getCurrentPlatform;
|
|
1699
2797
|
exports.getDefaultColorForPlatform = getDefaultColorForPlatform;
|
|
1700
2798
|
exports.getDefaultIconForPlatform = getDefaultIconForPlatform;
|
|
2799
|
+
exports.getDetailedTimeDifference = getDetailedTimeDifference;
|
|
1701
2800
|
exports.getDynamicIcon = getDynamicIcon;
|
|
2801
|
+
exports.getFirstLastInitials = getFirstLastInitials;
|
|
2802
|
+
exports.getIconComponent = getIconComponent;
|
|
1702
2803
|
exports.getOSIcon = getOSIcon;
|
|
1703
2804
|
exports.getOSLabel = getOSLabel;
|
|
1704
2805
|
exports.getOSPlatformId = getOSPlatformId;
|
|
@@ -1712,22 +2813,36 @@ exports.getPlatformIconComponent = getPlatformIconComponent;
|
|
|
1712
2813
|
exports.getPlatformLogo = getPlatformIconComponent;
|
|
1713
2814
|
exports.getPlatformProductionUrl = getPlatformProductionUrl;
|
|
1714
2815
|
exports.getPlatformSlogan = getPlatformSlogan;
|
|
2816
|
+
exports.getProxiedImageUrl = getProxiedImageUrl;
|
|
1715
2817
|
exports.getShellIcon = getShellIcon;
|
|
1716
2818
|
exports.getShellLabel = getShellLabel;
|
|
1717
2819
|
exports.getSlackCommunityJoinUrl = getSlackCommunityJoinUrl;
|
|
1718
2820
|
exports.getSmallPlatformIcon = getSmallPlatformIcon;
|
|
2821
|
+
exports.getSourceIconName = getSourceIconName;
|
|
2822
|
+
exports.getSourceLabel = getSourceLabel;
|
|
2823
|
+
exports.getStatusColorScheme = getStatusColorScheme;
|
|
2824
|
+
exports.getTaskTypeLabel = getTaskTypeLabel;
|
|
1719
2825
|
exports.getToolLabel = getToolLabel;
|
|
1720
2826
|
exports.getToolTypeAliases = getToolTypeAliases;
|
|
2827
|
+
exports.getTrendColors = getTrendColors;
|
|
1721
2828
|
exports.hasGenericEmailDomain = hasGenericEmailDomain;
|
|
2829
|
+
exports.hexToRgb = hexToRgb;
|
|
2830
|
+
exports.isCrossOriginUrl = isCrossOriginUrl;
|
|
1722
2831
|
exports.isGenericDomain = isGenericDomain;
|
|
1723
2832
|
exports.isGenericWebsiteDomain = isGenericWebsiteDomain;
|
|
1724
2833
|
exports.isOSPlatform = isOSPlatform;
|
|
2834
|
+
exports.isToday = isToday;
|
|
1725
2835
|
exports.isValidEmailDomain = isValidEmailDomain;
|
|
1726
2836
|
exports.isValidToolType = isValidToolType;
|
|
2837
|
+
exports.isWithinMinutes = isWithinMinutes;
|
|
2838
|
+
exports.nameInitials = nameInitials;
|
|
1727
2839
|
exports.normalizeDomain = normalizeDomain;
|
|
2840
|
+
exports.normalizeIconKey = normalizeIconKey;
|
|
1728
2841
|
exports.normalizeOSType = normalizeOSType;
|
|
1729
2842
|
exports.normalizeToolType = normalizeToolType;
|
|
1730
2843
|
exports.normalizeToolTypeWithFallback = normalizeToolTypeWithFallback;
|
|
2844
|
+
exports.parseScrollAnchor = parseScrollAnchor;
|
|
2845
|
+
exports.parseWireCommandOverride = parseWireCommandOverride;
|
|
1731
2846
|
exports.platformColors = platformColors;
|
|
1732
2847
|
exports.platformDescriptions = platformDescriptions;
|
|
1733
2848
|
exports.platformDisplayNames = platformDisplayNames;
|
|
@@ -1735,10 +2850,14 @@ exports.platformHexColors = platformHexColors;
|
|
|
1735
2850
|
exports.platformIconNames = platformIconNames;
|
|
1736
2851
|
exports.platformIcons = platformIcons;
|
|
1737
2852
|
exports.platformSlogans = platformSlogans;
|
|
2853
|
+
exports.sanitizeTitleForChat = sanitizeTitleForChat;
|
|
2854
|
+
exports.shouldProxyImage = shouldProxyImage;
|
|
2855
|
+
exports.stripChatAttachmentMarkdown = stripChatAttachmentMarkdown;
|
|
2856
|
+
exports.stripHtml = stripHtml;
|
|
1738
2857
|
exports.toToolLabel = toToolLabel;
|
|
1739
2858
|
exports.transformPlatformConfigsToOptions = transformPlatformConfigsToOptions;
|
|
1740
2859
|
exports.truncateString = truncateString;
|
|
1741
|
-
exports.
|
|
2860
|
+
exports.urlPathLooksLikeSvg = urlPathLooksLikeSvg;
|
|
1742
2861
|
exports.validateAccessCode = validateAccessCode;
|
|
1743
2862
|
exports.validateAndConsumeAccessCode = validateAndConsumeAccessCode;
|
|
1744
2863
|
exports.validateEmailDomain = validateEmailDomain;
|