@flamingo-stack/openframe-frontend-core 0.0.213 → 0.0.214-snapshot.20260528192313
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-35XIT2CF.cjs → chunk-2G3NXF6J.cjs} +17 -17
- package/dist/{chunk-35XIT2CF.cjs.map → chunk-2G3NXF6J.cjs.map} +1 -1
- package/dist/{chunk-IK2X5YJU.js → chunk-7PCP7YQR.js} +2 -2
- package/dist/{chunk-ZDF6F7ED.cjs → chunk-D4MNFY67.cjs} +4 -3
- package/dist/chunk-D4MNFY67.cjs.map +1 -0
- package/dist/{chunk-OTKJASSX.cjs → chunk-NGFP4RVL.cjs} +24 -24
- package/dist/{chunk-OTKJASSX.cjs.map → chunk-NGFP4RVL.cjs.map} +1 -1
- package/dist/{chunk-3JWIJJ44.js → chunk-R6MLPU4A.js} +2 -2
- package/dist/{chunk-ZTJVRSN5.js → chunk-WQZP3JIZ.js} +4 -3
- package/dist/chunk-WQZP3JIZ.js.map +1 -0
- package/dist/components/chat/index.cjs +2 -2
- package/dist/components/chat/index.js +1 -1
- package/dist/components/contact/index.cjs +3 -3
- package/dist/components/contact/index.js +2 -2
- package/dist/components/features/index.cjs +2 -2
- package/dist/components/features/index.js +1 -1
- package/dist/components/index.cjs +49 -49
- package/dist/components/index.js +2 -2
- package/dist/components/navigation/index.cjs +2 -2
- package/dist/components/navigation/index.js +1 -1
- package/dist/components/tickets/index.cjs +61 -61
- package/dist/components/tickets/index.js +3 -3
- package/dist/components/ui/index.cjs +2 -2
- package/dist/components/ui/index.js +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/.index.md +36 -34
- package/src/components/.alert-dialog.md +27 -23
- package/src/components/.announcement-bar.md +26 -21
- package/src/components/.breadcrumb.md +19 -15
- package/src/components/.calendar.md +24 -19
- package/src/components/.categories-cart.md +29 -24
- package/src/components/.checkbox.md +23 -25
- package/src/components/.chevron-button.md +37 -32
- package/src/components/.comment-card.md +32 -62
- package/src/components/.dialog.md +26 -26
- package/src/components/.dynamic-skeleton.md +54 -57
- package/src/components/.empty-state.md +42 -51
- package/src/components/.faq-accordion.md +27 -21
- package/src/components/.filter-chip.md +41 -24
- package/src/components/.flamingo-logo.md +20 -23
- package/src/components/.footer-waitlist-button.md +29 -22
- package/src/components/.footer.md +32 -32
- package/src/components/.icons-block.md +27 -17
- package/src/components/.image-cropper.md +41 -32
- package/src/components/.index.md +33 -39
- package/src/components/.input.md +31 -35
- package/src/components/.logs-list.md +31 -20
- package/src/components/.media-carousel.md +35 -36
- package/src/components/.open-source-features.md +33 -16
- package/src/components/.pagination.md +52 -51
- package/src/components/.provider-button.md +21 -23
- package/src/components/.select.md +31 -20
- package/src/components/.sidebar.md +34 -24
- package/src/components/.smooth-accordion.md +29 -24
- package/src/components/.social-icon-row.md +36 -32
- package/src/components/.textarea.md +25 -31
- package/src/components/.tool-icon.md +24 -26
- package/src/components/.unified-filter-logic.md +37 -30
- package/src/components/.unified-pagination.md +23 -22
- package/src/components/.user-summary-stub.md +38 -22
- package/src/components/.vendor-display-button.md +25 -25
- package/src/components/.vendor-icon.md +33 -25
- package/src/components/.why-it-matters.md +28 -25
- package/src/components/chat/.approval-batch-message.md +51 -0
- package/src/components/chat/.approval-request-message.md +35 -34
- package/src/components/chat/.chat-attachment-bar.md +64 -0
- package/src/components/chat/.chat-container.md +36 -18
- package/src/components/chat/.chat-input.md +37 -20
- package/src/components/chat/.chat-message-enhanced.md +30 -49
- package/src/components/chat/.chat-message-list.md +45 -32
- package/src/components/chat/.chat-message-skeleton.md +26 -22
- package/src/components/chat/.chat-panel-context.md +52 -0
- package/src/components/chat/.chat-ref.types.md +42 -0
- package/src/components/chat/.chat-sidebar-skeleton.md +34 -25
- package/src/components/chat/.chat-sidebar.md +31 -26
- package/src/components/chat/.chat-ticket-list.md +39 -0
- package/src/components/chat/.context-compaction-display.md +36 -0
- package/src/components/chat/.cycling-phrase.md +52 -0
- package/src/components/chat/.embeddable-chat.md +48 -0
- package/src/components/chat/.expand-chevron.md +24 -0
- package/src/components/chat/.index.md +31 -35
- package/src/components/chat/.mingo-onboarding-card-skeleton.md +44 -0
- package/src/components/chat/.mingo-onboarding-card.md +62 -0
- package/src/components/chat/.model-display.md +32 -30
- package/src/components/chat/.nav-link-anchor-via-runtime.md +40 -0
- package/src/components/chat/.remark-card-links.md +38 -0
- package/src/components/chat/.slash-command-suggestions.md +47 -0
- package/src/components/chat/.source-action-button.md +48 -0
- package/src/components/chat/.thinking-display.md +42 -0
- package/src/components/chat/.tool-call-blocks.md +45 -0
- package/src/components/chat/.tool-execution-display.md +44 -36
- package/src/components/chat/chat-container.tsx +1 -1
- package/src/components/chat/entity-cards/.admin-content-card.md +43 -0
- package/src/components/chat/entity-cards/.block-card.md +47 -0
- package/src/components/chat/entity-cards/.blog-card.md +52 -0
- package/src/components/chat/entity-cards/.blog-image-placeholder.md +39 -0
- package/src/components/chat/entity-cards/.campaign-card-admin.md +47 -0
- package/src/components/chat/entity-cards/.case-study-card.md +58 -0
- package/src/components/chat/entity-cards/.chat-ticket-item.md +40 -0
- package/src/components/chat/entity-cards/.chat-video-entity-card.md +43 -0
- package/src/components/chat/entity-cards/.customer-interview-card.md +53 -0
- package/src/components/chat/entity-cards/.data-room-doc-card.md +47 -0
- package/src/components/chat/entity-cards/.dispatch.md +39 -0
- package/src/components/chat/entity-cards/.entity-author-card.md +51 -0
- package/src/components/chat/entity-cards/.generic-entity-card.md +62 -0
- package/src/components/chat/entity-cards/.github-activity-card.md +61 -0
- package/src/components/chat/entity-cards/.hubspot-ticket-card.md +53 -0
- package/src/components/chat/entity-cards/.index.md +66 -0
- package/src/components/chat/entity-cards/.investor-update-card.md +47 -0
- package/src/components/chat/entity-cards/.onboarding-guide-card.md +58 -0
- package/src/components/chat/entity-cards/.product-release-card-defaults.md +31 -0
- package/src/components/chat/entity-cards/.product-release-card.md +29 -0
- package/src/components/chat/entity-cards/.program-card-defaults.md +41 -0
- package/src/components/chat/entity-cards/.program-card.md +59 -0
- package/src/components/chat/entity-cards/.roadmap-card.md +46 -0
- package/src/components/chat/entity-cards/.roadmap-vote-button.md +52 -0
- package/src/components/chat/entity-cards/.slack-message-card.md +48 -0
- package/src/components/chat/entity-cards/.task-type-icon.md +47 -0
- package/src/components/chat/hooks/.index.md +36 -21
- package/src/components/chat/hooks/.use-chat-attachment-image-gallery.md +51 -0
- package/src/components/chat/hooks/.use-chat-attachments.md +48 -0
- package/src/components/chat/hooks/.use-chat-card-item.md +39 -0
- package/src/components/chat/hooks/.use-chat-identity.md +45 -0
- package/src/components/chat/hooks/.use-chat.md +58 -0
- package/src/components/chat/hooks/.use-chunk-catchup.md +46 -48
- package/src/components/chat/hooks/.use-close-on-navigation.md +44 -0
- package/src/components/chat/hooks/.use-collapsible.md +48 -0
- package/src/components/chat/hooks/.use-embedded-chat.md +32 -0
- package/src/components/chat/hooks/.use-jetstream-dialog-subscription.md +40 -0
- package/src/components/chat/hooks/.use-nats-chat-adapter.md +52 -0
- package/src/components/chat/hooks/.use-nats-dialog-subscription.md +49 -30
- package/src/components/chat/hooks/.use-proxied-image-url.md +40 -0
- package/src/components/chat/hooks/.use-realtime-chunk-processor.md +43 -40
- package/src/components/chat/hooks/.use-slash-commands.md +46 -0
- package/src/components/chat/hooks/.use-sse-chat-adapter.md +34 -0
- package/src/components/chat/hooks/.use-sse.md +60 -0
- package/src/components/chat/hooks/.use-unified-chat.md +57 -0
- package/src/components/chat/types/.api.types.md +52 -38
- package/src/components/chat/types/.chat.types.md +43 -34
- package/src/components/chat/types/.component.types.md +47 -48
- package/src/components/chat/types/.index.md +20 -27
- package/src/components/chat/types/.message.types.md +58 -48
- package/src/components/chat/types/.network.types.md +57 -31
- package/src/components/chat/types/.processing.types.md +49 -31
- package/src/components/chat/types/.unified-chat-state.types.md +41 -0
- package/src/components/chat/types/entities/.blog.md +43 -0
- package/src/components/chat/types/entities/.case-study.md +26 -0
- package/src/components/chat/types/entities/.content-ref.md +41 -0
- package/src/components/chat/types/entities/.customer-interview.md +28 -0
- package/src/components/chat/types/entities/.data-room-doc.md +36 -0
- package/src/components/chat/types/entities/.github-activity.md +43 -0
- package/src/components/chat/types/entities/.hubspot-ticket.md +53 -0
- package/src/components/chat/types/entities/.index.md +42 -0
- package/src/components/chat/types/entities/.investor-update.md +45 -0
- package/src/components/chat/types/entities/.onboarding-guide.md +50 -0
- package/src/components/chat/types/entities/.program-types.md +57 -0
- package/src/components/chat/types/entities/.roadmap-item.md +58 -0
- package/src/components/chat/types/entities/.slack-message.md +35 -0
- package/src/components/chat/utils/.agent-status-message.md +45 -0
- package/src/components/chat/utils/.auto-continuation-directive.md +58 -0
- package/src/components/chat/utils/.chat-attachment-markdown.md +54 -0
- package/src/components/chat/utils/.chat-authed-fetch.md +25 -0
- package/src/components/chat/utils/.chat-nav-resolution.md +46 -0
- package/src/components/chat/utils/.chat-proxy-auth-storage.md +38 -0
- package/src/components/chat/utils/.chip-action-class.md +34 -0
- package/src/components/chat/utils/.chip-styles.md +46 -0
- package/src/components/chat/utils/.chunk-parser.md +38 -28
- package/src/components/chat/utils/.clickup-task-type-utils.md +48 -0
- package/src/components/chat/utils/.compact-card-classes.md +62 -0
- package/src/components/chat/utils/.decide-new-tab.md +51 -0
- package/src/components/chat/utils/.external-app-urls.md +29 -0
- package/src/components/chat/utils/.extract-incomplete-message-state.md +25 -29
- package/src/components/chat/utils/.flatten-assistant-content.md +34 -0
- package/src/components/chat/utils/.icon-registry.md +46 -0
- package/src/components/chat/utils/.index.md +37 -32
- package/src/components/chat/utils/.is-cross-origin-url.md +35 -0
- package/src/components/chat/utils/.message-segment-accumulator.md +25 -34
- package/src/components/chat/utils/.nav-anchor-props.md +44 -0
- package/src/components/chat/utils/.nav-click-handler.md +47 -0
- package/src/components/chat/utils/.onboarding-icons.md +28 -0
- package/src/components/chat/utils/.process-historical-messages.md +46 -35
- package/src/components/chat/utils/.scroll-anchor.md +40 -0
- package/src/components/chat/utils/.slash-dispatch-utils.md +44 -0
- package/src/components/chat/utils/.source-icons.md +35 -0
- package/src/components/chat/utils/.source-row-cta.md +54 -0
- package/src/components/chat/utils/.tool-call-helpers.md +42 -0
- package/src/components/contact/.contact-form.md +43 -0
- package/src/components/contact/.index.md +27 -0
- package/src/components/features/.array-entry-manager.md +36 -45
- package/src/components/features/.changelog-manager.md +47 -21
- package/src/components/features/.changelog-sections-manager.md +21 -26
- package/src/components/features/.command-box.md +31 -28
- package/src/components/features/.entity-summary-editor.md +46 -0
- package/src/components/features/.entity-video-section.md +51 -0
- package/src/components/features/.figma-prototype-viewer.md +48 -29
- package/src/components/features/.filters-dropdown.md +33 -46
- package/src/components/features/.highlight-config-section.md +42 -0
- package/src/components/features/.highlight-generation-section.md +46 -0
- package/src/components/features/.highlight-video-combined-section.md +47 -0
- package/src/components/features/.highlight-video-preview.md +44 -0
- package/src/components/features/.highlight-video-section.md +47 -0
- package/src/components/features/.index.md +40 -66
- package/src/components/features/.media-gallery-manager.md +48 -38
- package/src/components/features/.more-about-button.md +22 -19
- package/src/components/features/.og-editor-preview.md +40 -36
- package/src/components/features/.parallax-image-showcase.md +33 -26
- package/src/components/features/.paths-display.md +42 -43
- package/src/components/features/.platform-badge.md +37 -36
- package/src/components/features/.platform-filter.md +23 -16
- package/src/components/features/.policy-configuration-panel.md +48 -56
- package/src/components/features/.provider-button.md +33 -36
- package/src/components/features/.push-button-selector.md +40 -29
- package/src/components/features/.release-media-manager.md +46 -31
- package/src/components/features/.section-selector.md +26 -31
- package/src/components/features/.select-button.md +35 -25
- package/src/components/features/.seo-editor-preview.md +41 -44
- package/src/components/features/.social-links-manager.md +25 -19
- package/src/components/features/.start-with-openframe-button.md +37 -29
- package/src/components/features/.status-filter-component.md +36 -20
- package/src/components/features/.tags-selector.md +40 -24
- package/src/components/features/.transcribe-and-summarize-combined-section.md +45 -0
- package/src/components/features/.transcribe-summarize-section.md +48 -0
- package/src/components/features/.transcript-summary-editor.md +53 -0
- package/src/components/features/.video-bites-display.md +46 -0
- package/src/components/features/.video-clips-section.md +41 -0
- package/src/components/features/.video-ratio-tabs.md +56 -0
- package/src/components/features/.video-source-selector.md +60 -0
- package/src/components/features/.video.md +44 -0
- package/src/components/features/.waitlist-form.md +60 -0
- package/src/components/features/ai-enrich/.AIEnrichButton.md +30 -27
- package/src/components/features/ai-enrich/.AIEnrichSection.md +46 -42
- package/src/components/features/board/.board-column-header.md +38 -0
- package/src/components/features/board/.board-column.md +43 -0
- package/src/components/features/board/.board.md +51 -0
- package/src/components/features/board/.color-utils.md +26 -0
- package/src/components/features/board/.index.md +56 -0
- package/src/components/features/board/.ticket-card-skeleton.md +38 -0
- package/src/components/features/board/.ticket-card.md +47 -0
- package/src/components/features/board/.types.md +45 -0
- package/src/components/features/board/.use-board-collapse.md +34 -0
- package/src/components/features/notifications/.index.md +57 -0
- package/src/components/features/notifications/.notification-drawer.md +34 -0
- package/src/components/features/notifications/.notification-tile.md +39 -0
- package/src/components/features/notifications/.notifications-context.md +73 -0
- package/src/components/features/notifications/.types.md +45 -0
- package/src/components/icons/.about-icon.md +20 -28
- package/src/components/icons/.ai-robot-icon.md +15 -17
- package/src/components/icons/.bash-icon.md +16 -23
- package/src/components/icons/.buildings-icon.md +10 -24
- package/src/components/icons/.capterra-icon.md +30 -26
- package/src/components/icons/.carta-icon.md +29 -0
- package/src/components/icons/.clickup-icon.md +26 -0
- package/src/components/icons/.cmd-icon.md +15 -22
- package/src/components/icons/.coins-icon.md +17 -25
- package/src/components/icons/.community-hub-icon.md +19 -25
- package/src/components/icons/.community-icon.md +24 -21
- package/src/components/icons/.compare-icon.md +32 -19
- package/src/components/icons/.copy-icon.md +29 -15
- package/src/components/icons/.custom-external-link-icon.md +19 -17
- package/src/components/icons/.custom-fork-icon.md +32 -21
- package/src/components/icons/.custom-license-icon.md +29 -25
- package/src/components/icons/.custom-star-icon.md +20 -28
- package/src/components/icons/.custom-time-icon.md +21 -22
- package/src/components/icons/.cut-vendor-costs-icon.md +6 -19
- package/src/components/icons/.dashboard-icon.md +13 -18
- package/src/components/icons/.deno-icon.md +16 -23
- package/src/components/icons/.donut-icon.md +12 -23
- package/src/components/icons/.double-chevron-icon.md +28 -36
- package/src/components/icons/.elestio-logo.md +13 -23
- package/src/components/icons/.empty-vendor-icon.md +16 -18
- package/src/components/icons/.explore-categories-icon.md +18 -29
- package/src/components/icons/.eye-icon.md +16 -26
- package/src/components/icons/.facebook-icon.md +9 -20
- package/src/components/icons/.figma-icon.md +8 -17
- package/src/components/icons/.filter-icon.md +15 -17
- package/src/components/icons/.flamingo-logo.md +28 -27
- package/src/components/icons/.folder-shield-icon.md +28 -19
- package/src/components/icons/.g2-icon.md +22 -21
- package/src/components/icons/.getapp-icon.md +25 -21
- package/src/components/icons/.github-icon.md +13 -25
- package/src/components/icons/.globe-icon.md +14 -19
- package/src/components/icons/.google-gemini-icon.md +16 -19
- package/src/components/icons/.google-logo.md +15 -21
- package/src/components/icons/.grid-view-icon.md +30 -19
- package/src/components/icons/.hamburger-icon.md +22 -20
- package/src/components/icons/.hand-dollar-icon.md +24 -34
- package/src/components/icons/.hotel-icon.md +27 -21
- package/src/components/icons/.icon-utils.md +28 -29
- package/src/components/icons/.image-icon.md +15 -22
- package/src/components/icons/.index.md +25 -28
- package/src/components/icons/.info-circle-icon.md +29 -30
- package/src/components/icons/.instagram-icon.md +10 -24
- package/src/components/icons/.jump-in-icon.md +18 -18
- package/src/components/icons/.linux-icon.md +18 -18
- package/src/components/icons/.log-out-icon.md +15 -23
- package/src/components/icons/.logs-icon.md +14 -23
- package/src/components/icons/.margin-crisis-icon.md +21 -20
- package/src/components/icons/.menu-icon.md +18 -19
- package/src/components/icons/.miami-cyber-gang-logo-face-only.md +18 -21
- package/src/components/icons/.miami-cyber-gang-logo.md +22 -14
- package/src/components/icons/.mlg-logo.md +18 -16
- package/src/components/icons/.moon-icon.md +32 -22
- package/src/components/icons/.ms-icon.md +30 -19
- package/src/components/icons/.nushell-icon.md +7 -21
- package/src/components/icons/.open-source-icon.md +19 -23
- package/src/components/icons/.openai-icon.md +9 -24
- package/src/components/icons/.openframe-ai-icons.md +25 -26
- package/src/components/icons/.openframe-logo.md +28 -22
- package/src/components/icons/.openframe-text.md +24 -27
- package/src/components/icons/.openmsp-logo.md +26 -23
- package/src/components/icons/.pilot-icon.md +23 -0
- package/src/components/icons/.powershell-icon.md +17 -22
- package/src/components/icons/.python-icon.md +16 -23
- package/src/components/icons/.queries-icon.md +13 -21
- package/src/components/icons/.reddit-icon.md +28 -24
- package/src/components/icons/.remote-control-icon.md +13 -17
- package/src/components/icons/.script-icon.md +27 -19
- package/src/components/icons/.search-icon.md +21 -21
- package/src/components/icons/.send-icon.md +14 -16
- package/src/components/icons/.settings-icon.md +30 -19
- package/src/components/icons/.shape-circle-dash-icon.md +16 -21
- package/src/components/icons/.shell-icon.md +15 -19
- package/src/components/icons/.shield-check-icon.md +18 -31
- package/src/components/icons/.shield-key-icon.md +25 -25
- package/src/components/icons/.shield-lock-icon.md +8 -18
- package/src/components/icons/.slack-icon.md +28 -32
- package/src/components/icons/.sparkles-icon.md +18 -23
- package/src/components/icons/.sso-configuration-icon.md +29 -16
- package/src/components/icons/.sun-icon.md +20 -18
- package/src/components/icons/.table-view-icon.md +17 -19
- package/src/components/icons/.telegram-icon.md +8 -22
- package/src/components/icons/.thumbs-down-icon.md +10 -19
- package/src/components/icons/.thumbs-up-icon.md +8 -17
- package/src/components/icons/.tool-directory-icons.md +24 -28
- package/src/components/icons/.trustpilot-icon.md +25 -22
- package/src/components/icons/.user-icon.md +26 -28
- package/src/components/icons/.users-group-icon.md +28 -24
- package/src/components/icons/.vendor-showcase-icons.md +21 -29
- package/src/components/icons/.vendors-icon.md +18 -22
- package/src/components/icons/.whatsapp-icon.md +30 -14
- package/src/components/icons/.x-icon.md +18 -23
- package/src/components/icons/.x-logo.md +13 -38
- package/src/components/icons/.youtube-icon.md +8 -19
- package/src/components/icons/device-type-icons/.get-device-type-icon.md +26 -34
- package/src/components/icons-v2-generated/.index.md +52 -0
- package/src/components/icons-v2-generated/alphabet/.index.md +33 -0
- package/src/components/icons-v2-generated/arrows/.index.md +39 -0
- package/src/components/icons-v2-generated/audio-and-visual/.index.md +40 -0
- package/src/components/icons-v2-generated/brand-logos/.elestio-logo-icon.md +40 -0
- package/src/components/icons-v2-generated/brand-logos/.gemini-logo-icon.md +37 -0
- package/src/components/icons-v2-generated/brand-logos/.google-gemini-logo-icon.md +33 -0
- package/src/components/icons-v2-generated/brand-logos/.index.md +38 -0
- package/src/components/icons-v2-generated/brand-logos/.meshcentral-logo-grey-icon.md +35 -0
- package/src/components/icons-v2-generated/brand-logos/.meshcentral-logo-icon.md +36 -0
- package/src/components/icons-v2-generated/buildings/.index.md +48 -0
- package/src/components/icons-v2-generated/charts/.index.md +40 -0
- package/src/components/icons-v2-generated/clothes/.index.md +48 -0
- package/src/components/icons-v2-generated/coding/.index.md +42 -0
- package/src/components/icons-v2-generated/communication/.index.md +39 -0
- package/src/components/icons-v2-generated/date-and-time/.index.md +29 -0
- package/src/components/icons-v2-generated/design/.index.md +39 -0
- package/src/components/icons-v2-generated/devices/.index.md +38 -0
- package/src/components/icons-v2-generated/documents/.index.md +38 -0
- package/src/components/icons-v2-generated/finance/.index.md +34 -0
- package/src/components/icons-v2-generated/food-and-drinks/.index.md +34 -0
- package/src/components/icons-v2-generated/food-and-drinks/.leafy-green-icon.md +36 -0
- package/src/components/icons-v2-generated/food-and-drinks/.strawberry-icon.md +39 -0
- package/src/components/icons-v2-generated/health/.index.md +40 -0
- package/src/components/icons-v2-generated/household/.index.md +45 -0
- package/src/components/icons-v2-generated/interface/.index.md +36 -0
- package/src/components/icons-v2-generated/map-and-travel/.index.md +41 -0
- package/src/components/icons-v2-generated/media-playback/.index.md +51 -0
- package/src/components/icons-v2-generated/number/.index.md +41 -0
- package/src/components/icons-v2-generated/school/.index.md +37 -0
- package/src/components/icons-v2-generated/security/.fingerprint-icon.md +38 -0
- package/src/components/icons-v2-generated/security/.index.md +39 -0
- package/src/components/icons-v2-generated/shopping/.index.md +42 -0
- package/src/components/icons-v2-generated/signs-and-symbols/.index.md +32 -0
- package/src/components/icons-v2-generated/sort-and-filter/.index.md +35 -0
- package/src/components/icons-v2-generated/sport/.index.md +41 -0
- package/src/components/icons-v2-generated/text-editor/.index.md +44 -0
- package/src/components/icons-v2-generated/users/.index.md +45 -0
- package/src/components/icons-v2-generated/vehicles-and-delivery/.index.md +36 -0
- package/src/components/icons-v2-generated/weather-and-nature/.flower-sakura-icon.md +36 -0
- package/src/components/icons-v2-generated/weather-and-nature/.index.md +34 -0
- package/src/components/layout/.article-detail-layout.md +43 -0
- package/src/components/layout/.back-button.md +40 -0
- package/src/components/layout/.list-page-layout.md +35 -26
- package/src/components/layout/.page-container.md +27 -38
- package/src/components/layout/.page-layout.md +50 -0
- package/src/components/layout/.title-block.md +42 -0
- package/src/components/loading/.card-skeleton.md +38 -29
- package/src/components/loading/.device-card-skeleton.md +29 -25
- package/src/components/loading/.index.md +39 -46
- package/src/components/loading/.margin-report-skeleton.md +45 -34
- package/src/components/loading/.organization-card-skeleton.md +39 -44
- package/src/components/loading/.page-layout-skeleton.md +34 -45
- package/src/components/loading/.unified-skeleton.md +62 -36
- package/src/components/navigation/.app-header.md +40 -29
- package/src/components/navigation/.app-layout.md +25 -26
- package/src/components/navigation/.header-global-search.md +34 -37
- package/src/components/navigation/.header-organization-filter.md +23 -22
- package/src/components/navigation/.header.md +31 -35
- package/src/components/navigation/.mobile-burger-menu.md +39 -47
- package/src/components/navigation/.mobile-nav-panel.md +51 -32
- package/src/components/navigation/.navigation-sidebar-header.md +36 -0
- package/src/components/navigation/.navigation-sidebar-item.md +45 -0
- package/src/components/navigation/.navigation-sidebar-toggle.md +38 -0
- package/src/components/navigation/.navigation-sidebar.md +33 -34
- package/src/components/navigation/.sliding-sidebar.md +52 -41
- package/src/components/navigation/.sticky-section-nav.md +56 -48
- package/src/components/platform/.ScriptArguments.md +39 -25
- package/src/components/platform/.ScriptInfoSection.md +30 -26
- package/src/components/platform/.ShellTypeBadge.md +18 -13
- package/src/components/platform/.SoftwareInfo.md +23 -27
- package/src/components/platform/.SoftwareSourceBadge.md +28 -19
- package/src/components/platform/.ToolBadge.md +25 -26
- package/src/components/platform/ShellTypeBadge.tsx +2 -2
- package/src/components/providers/.theme-provider.md +52 -0
- package/src/components/shared/delivery/.delivery-lists.md +39 -0
- package/src/components/shared/delivery/.delivery-row.md +41 -0
- package/src/components/shared/delivery/.delivery-table.md +41 -0
- package/src/components/shared/delivery/.index.md +38 -0
- package/src/components/shared/dev-section/.dev-card-row.md +60 -0
- package/src/components/shared/dev-section/.dev-section-page.md +48 -0
- package/src/components/shared/dev-section/.dev-section-view.md +43 -0
- package/src/components/shared/dev-section/.index.md +38 -0
- package/src/components/shared/legal-document/.index.md +40 -0
- package/src/components/shared/legal-document/.legal-document-page.md +50 -0
- package/src/components/shared/legal-document/.use-legal-docs.md +42 -0
- package/src/components/shared/onboarding/.onboarding-step-card.md +32 -31
- package/src/components/shared/onboarding/.onboarding-walkthrough.md +39 -43
- package/src/components/shared/product-release/.index.md +28 -30
- package/src/components/shared/product-release/.product-release-card-skeleton.md +28 -28
- package/src/components/shared/product-release/.product-release-card.md +45 -27
- package/src/components/shared/product-release/.release-detail-page.md +23 -24
- package/src/components/shared/roadmap/.index.md +37 -0
- package/src/components/shared/roadmap/.roadmap-grid-skeleton.md +39 -0
- package/src/components/shared/roadmap/.roadmap-grid.md +66 -0
- package/src/components/shared/roadmap/.use-roadmap-voting.md +68 -0
- package/src/components/tickets/.help-center-card.md +51 -0
- package/src/components/tickets/.help-center-create-form.md +38 -0
- package/src/components/tickets/.help-center-list.md +40 -0
- package/src/components/tickets/.index.md +65 -0
- package/src/components/tickets/.ticket-center.md +51 -0
- package/src/components/tickets/.ticket-detail-drawer.md +48 -0
- package/src/components/tickets/.ticket-linked-delivery-card.md +36 -0
- package/src/components/tickets/.ticket-open-form.md +50 -0
- package/src/components/tickets/.ticket-row.md +30 -0
- package/src/components/tickets/.types.md +57 -0
- package/src/components/tickets/hooks/.use-ticket-actions.md +77 -0
- package/src/components/tickets/hooks/.use-ticket-engagements.md +42 -0
- package/src/components/tickets/hooks/.use-tickets-list.md +54 -0
- package/src/components/ui/.actions-menu.md +66 -41
- package/src/components/ui/.alert-dialog.md +29 -26
- package/src/components/ui/.allowed-domains-input.md +29 -21
- package/src/components/ui/.assignee-dropdown.md +45 -0
- package/src/components/ui/.autocomplete.md +47 -41
- package/src/components/ui/.benefit-card.md +51 -36
- package/src/components/ui/.brand-association-card.md +30 -27
- package/src/components/ui/.breadcrumb.md +17 -15
- package/src/components/ui/.checkbox-block.md +39 -35
- package/src/components/ui/.checkbox-with-description.md +23 -16
- package/src/components/ui/.checkbox.md +31 -23
- package/src/components/ui/.circular-progress.md +49 -19
- package/src/components/ui/.content-loader.md +32 -20
- package/src/components/ui/.cursor-pagination.md +41 -52
- package/src/components/ui/.dashboard-info-card.md +33 -26
- package/src/components/ui/.date-picker.md +27 -25
- package/src/components/ui/.device-card-compact.md +28 -29
- package/src/components/ui/.device-card.md +27 -27
- package/src/components/ui/.dialog.md +25 -16
- package/src/components/ui/.drawer.md +86 -0
- package/src/components/ui/.dropdown-button.md +45 -0
- package/src/components/ui/.entity-image.md +46 -0
- package/src/components/ui/.error-state.md +41 -28
- package/src/components/ui/.feature-card.md +35 -31
- package/src/components/ui/.feature-list.md +48 -0
- package/src/components/ui/.field-wrapper.md +47 -0
- package/src/components/ui/.file-upload.md +42 -0
- package/src/components/ui/.filter-checkbox-item.md +43 -0
- package/src/components/ui/.filter-list.md +57 -0
- package/src/components/ui/.filter-modal.md +59 -0
- package/src/components/ui/.floating-tooltip.md +43 -26
- package/src/components/ui/.hidden-tags-popup.md +49 -0
- package/src/components/ui/.hover-dropdown.md +54 -0
- package/src/components/ui/.image-gallery-modal.md +41 -34
- package/src/components/ui/.image-uploader.md +53 -0
- package/src/components/ui/.index.md +40 -34
- package/src/components/ui/.info-card.md +31 -31
- package/src/components/ui/.info-row.md +31 -27
- package/src/components/ui/.input-trigger.md +44 -0
- package/src/components/ui/.input.md +37 -31
- package/src/components/ui/.markdown-editor.md +57 -0
- package/src/components/ui/.modal-v2.md +51 -0
- package/src/components/ui/.modal.md +32 -31
- package/src/components/ui/.more-actions-menu.md +45 -38
- package/src/components/ui/.organization-card.md +31 -37
- package/src/components/ui/.page-actions.md +44 -54
- package/src/components/ui/.phone-input.md +54 -0
- package/src/components/ui/.progress-bar.md +35 -27
- package/src/components/ui/.radio-group.md +39 -27
- package/src/components/ui/.release-changelog-section.md +34 -34
- package/src/components/ui/.search-input.md +48 -0
- package/src/components/ui/.select.md +54 -34
- package/src/components/ui/.service-card.md +42 -40
- package/src/components/ui/.sheet.md +27 -18
- package/src/components/ui/.simple-markdown-renderer.md +29 -31
- package/src/components/ui/.sort-column-item.md +42 -0
- package/src/components/ui/.square-avatar.md +34 -24
- package/src/components/ui/.status-badge.md +26 -38
- package/src/components/ui/.switch.md +22 -35
- package/src/components/ui/.tab-navigation.md +56 -53
- package/src/components/ui/.tab-selector.md +40 -0
- package/src/components/ui/.tag-key-value-filter.md +56 -0
- package/src/components/ui/.tag-search-input.md +53 -0
- package/src/components/ui/.tag.md +49 -31
- package/src/components/ui/.tags-manager.md +60 -0
- package/src/components/ui/.textarea.md +44 -34
- package/src/components/ui/.ticket-attachments-list.md +45 -0
- package/src/components/ui/.ticket-detail-section.md +29 -0
- package/src/components/ui/.ticket-info-section.md +56 -0
- package/src/components/ui/.ticket-note-card.md +53 -0
- package/src/components/ui/.ticket-notes-section.md +54 -0
- package/src/components/ui/.ticket-status-tag.md +49 -0
- package/src/components/ui/.title-content-block.md +25 -26
- package/src/components/ui/.toaster.md +40 -28
- package/src/components/ui/.tooltip.md +22 -11
- package/src/components/ui/.truncate-text.md +39 -0
- package/src/components/ui/button/.button-styles.md +35 -0
- package/src/components/ui/button/.button.md +53 -0
- package/src/components/ui/button/.split-button.md +48 -0
- package/src/components/ui/data-table/.data-table-body.md +48 -0
- package/src/components/ui/data-table/.data-table-column-filter.md +45 -0
- package/src/components/ui/data-table/.data-table-cursor-footer.md +45 -0
- package/src/components/ui/data-table/.data-table-empty.md +43 -0
- package/src/components/ui/data-table/.data-table-header.md +55 -0
- package/src/components/ui/data-table/.data-table-infinite-footer.md +44 -0
- package/src/components/ui/data-table/.data-table-row-count.md +43 -0
- package/src/components/ui/data-table/.data-table-row.md +47 -0
- package/src/components/ui/data-table/.data-table-skeleton.md +42 -0
- package/src/components/ui/data-table/.data-table.md +47 -0
- package/src/components/ui/data-table/.index.md +55 -0
- package/src/components/ui/data-table/.types.md +54 -0
- package/src/components/ui/data-table/.use-data-table.md +45 -0
- package/src/components/ui/data-table/.utils.md +38 -0
- package/src/components/ui/file-manager/.file-manager-action-bar.md +39 -30
- package/src/components/ui/file-manager/.file-manager-breadcrumb.md +29 -27
- package/src/components/ui/file-manager/.file-manager-context-menu.md +38 -42
- package/src/components/ui/file-manager/.file-manager-empty.md +26 -39
- package/src/components/ui/file-manager/.file-manager-table-row.md +33 -41
- package/src/components/ui/file-manager/.file-manager.md +35 -31
- package/src/components/ui/query-report-table/.index.md +43 -0
- package/src/components/ui/query-report-table/.query-report-table-header.md +36 -0
- package/src/components/ui/query-report-table/.query-report-table-row.md +40 -0
- package/src/components/ui/query-report-table/.query-report-table-skeleton.md +44 -0
- package/src/components/ui/query-report-table/.query-report-table.md +47 -0
- package/src/components/ui/query-report-table/.types.md +41 -0
- package/src/components/ui/query-report-table/.utils.md +35 -0
- package/src/components/ui/table/.index.md +27 -48
- package/src/components/ui/table/.table-cell.md +18 -27
- package/src/components/ui/table/.table-column-filter-dropdown.md +40 -0
- package/src/components/ui/table/.table-description-cell.md +24 -14
- package/src/components/ui/table/.table-empty-state.md +21 -22
- package/src/components/ui/table/.table-header.md +25 -40
- package/src/components/ui/table/.table-row.md +22 -40
- package/src/components/ui/table/.table-skeleton.md +33 -26
- package/src/components/ui/table/.table-timestamp-cell.md +26 -16
- package/src/components/ui/table/.table.md +39 -59
- package/src/components/ui/table/.types.md +44 -36
- package/src/components/ui/table/.utils.md +18 -20
- package/src/contexts/.chat-runtime-context.md +54 -0
- package/src/contexts/.endpoints-runtime-context.md +58 -0
- package/src/contexts/.index.md +53 -0
- package/src/contexts/.use-outer-or-default.md +36 -0
- package/src/embed-shims/.index.md +45 -0
- package/src/embed-shims/.next-dynamic.md +43 -0
- package/src/embed-shims/.next-image.md +45 -0
- package/src/embed-shims/.next-link.md +59 -0
- package/src/embed-shims/.next-navigation.md +59 -0
- package/src/hooks/.index.md +34 -29
- package/src/hooks/.use-access-code-integration.md +49 -0
- package/src/hooks/.use-contact-submission.md +37 -26
- package/src/hooks/.use-copy-to-clipboard.md +42 -0
- package/src/hooks/.use-near-viewport.md +44 -0
- package/src/hooks/.use-og-placeholder.md +51 -0
- package/src/hooks/.use-toast.md +36 -35
- package/src/hooks/state/.use-api-params.md +29 -46
- package/src/hooks/state/.use-query-params.md +37 -33
- package/src/hooks/ui/.index.md +33 -32
- package/src/hooks/ui/.use-auto-limit-tags.md +54 -0
- package/src/hooks/ui/.use-horizontal-scrollbar.md +74 -0
- package/src/hooks/ui/.use-image-edge-color.md +42 -0
- package/src/hooks/ui/.use-media-query.md +33 -25
- package/src/hooks/ui/.use-search.md +51 -0
- package/src/nats/.nats.md +49 -28
- package/src/schemas/.contact-schema.md +45 -0
- package/src/stories/.AnnouncementBar.stories.md +45 -0
- package/src/stories/.AppLayout.stories.md +20 -21
- package/src/stories/.Autocomplete.stories.md +48 -34
- package/src/stories/.Board.stories.md +35 -0
- package/src/stories/.Button.stories.md +36 -33
- package/src/stories/.ChatTicketList.stories.md +33 -0
- package/src/stories/.CheckboxBlock.stories.md +40 -28
- package/src/stories/.ContentLoader.stories.md +47 -0
- package/src/stories/.DashboardInfoCard.stories.md +57 -0
- package/src/stories/.DataTable.stories.md +41 -0
- package/src/stories/.DatePicker.stories.md +66 -52
- package/src/stories/.DeviceCard.stories.md +41 -40
- package/src/stories/.DeviceCardCompact.stories.md +41 -0
- package/src/stories/.DotsLoaderIcon.stories.md +36 -0
- package/src/stories/.Drawer.stories.md +58 -0
- package/src/stories/.EmbeddableChat.stories.md +41 -0
- package/src/stories/.FileManager.stories.md +41 -0
- package/src/stories/.FileManagerActionBar.stories.md +38 -0
- package/src/stories/.FileUpload.stories.md +53 -0
- package/src/stories/.FilterList.stories.md +54 -0
- package/src/stories/.FilterModal.stories.md +72 -0
- package/src/stories/.FiltersDropdown.stories.md +57 -0
- package/src/stories/.Header.stories.md +48 -0
- package/src/stories/.ImageUploader.stories.md +49 -0
- package/src/stories/.InfoCard.stories.md +54 -0
- package/src/stories/.Input.stories.md +48 -30
- package/src/stories/.ListPageLayout.stories.md +56 -43
- package/src/stories/.MingoOnboardingCard.stories.md +42 -0
- package/src/stories/.MingoOnboardingCardSkeleton.stories.md +35 -0
- package/src/stories/.Modal.stories.md +40 -31
- package/src/stories/.NotificationDrawer.stories.md +55 -0
- package/src/stories/.OnboardingStepCard.stories.md +41 -0
- package/src/stories/.OrganizationCard.stories.md +61 -0
- package/src/stories/.PageActions.stories.md +52 -49
- package/src/stories/.PageContainer.stories.md +41 -35
- package/src/stories/.PageLayout.stories.md +60 -0
- package/src/stories/.ParallaxImageShowcase.stories.md +49 -0
- package/src/stories/.PhoneInput.stories.md +53 -0
- package/src/stories/.QueryReportTable.stories.md +44 -0
- package/src/stories/.RadioGroup.stories.md +46 -0
- package/src/stories/.RadioGroupBlock.stories.md +45 -0
- package/src/stories/.Select.stories.md +29 -15
- package/src/stories/.SlashCommandSuggestions.stories.md +41 -0
- package/src/stories/.SplitButton.stories.md +62 -0
- package/src/stories/.TabNavigation.stories.md +47 -38
- package/src/stories/.TabSelector.stories.md +65 -0
- package/src/stories/.Table.stories.md +38 -46
- package/src/stories/.TableColumnFilterDropdown.stories.md +46 -0
- package/src/stories/.Tag.stories.md +43 -32
- package/src/stories/.TagKeyValueFilter.stories.md +44 -0
- package/src/stories/.TagSearchInput.stories.md +61 -0
- package/src/stories/.Textarea.stories.md +49 -26
- package/src/stories/.Theme.stories.md +41 -0
- package/src/stories/.TicketAttachmentsList.stories.md +39 -0
- package/src/stories/.TicketDescriptionViewer.stories.md +39 -0
- package/src/stories/.TicketInfoSection.stories.md +40 -0
- package/src/stories/.TicketKnowledgeBaseList.stories.md +36 -0
- package/src/stories/.TicketNotesSection.stories.md +50 -0
- package/src/stories/.Toaster.stories.md +40 -0
- package/src/stories/.ToolExecutionDisplay.stories.md +41 -0
- package/src/stories/.Tooltip.stories.md +41 -0
- package/src/stories/.UserSummary.stories.md +41 -0
- package/src/stories/.WaitlistForm.stories.md +42 -0
- package/src/stories/BlogCard.stories.tsx +61 -0
- package/src/stories/CampaignCardAdmin.stories.tsx +52 -0
- package/src/stories/CaseStudyCard.stories.tsx +42 -0
- package/src/stories/ChatContainer.stories.tsx +186 -0
- package/src/stories/ChatInlineVideoPill.stories.tsx +63 -0
- package/src/stories/CustomerInterviewCard.stories.tsx +42 -0
- package/src/stories/DataRoomDocCard.stories.tsx +52 -0
- package/src/stories/GenericEntityCard.stories.tsx +66 -0
- package/src/stories/GitHubActivityCard.stories.tsx +61 -0
- package/src/stories/HubspotTicketCard.stories.tsx +98 -0
- package/src/stories/InvestorUpdateCard.stories.tsx +42 -0
- package/src/stories/OnboardingGuideCard.stories.tsx +52 -0
- package/src/stories/ProductReleaseCard.stories.tsx +61 -0
- package/src/stories/ProgramCard.stories.tsx +79 -0
- package/src/stories/RoadmapCard.stories.tsx +75 -0
- package/src/stories/SlackMessageCard.stories.tsx +41 -0
- package/src/stories/__fixtures__/chat-cards.ts +604 -0
- package/src/types/.blog.md +53 -29
- package/src/types/.case-study.md +44 -27
- package/src/types/.customer-interview.md +66 -44
- package/src/types/.delivery.md +40 -0
- package/src/types/.employee.md +24 -30
- package/src/types/.index.md +33 -47
- package/src/types/.marketing.md +49 -44
- package/src/types/.navigation.md +33 -25
- package/src/types/.os.types.md +32 -27
- package/src/types/.platform.md +31 -28
- package/src/types/.product-release.md +65 -38
- package/src/types/.supabase.md +37 -29
- package/src/types/.team.md +41 -33
- package/src/types/.video-processing.md +54 -0
- package/src/types/.waitlist.md +40 -36
- package/src/utils/.access-code-client.md +37 -36
- package/src/utils/.cn.md +31 -23
- package/src/utils/.color-analysis.md +35 -0
- package/src/utils/.country-phone-utils.md +39 -0
- package/src/utils/.date-formatters.md +19 -18
- package/src/utils/.embed-authed-fetch.md +39 -0
- package/src/utils/.embed-proxy-auth-storage.md +38 -0
- package/src/utils/.fetch-priority.md +41 -0
- package/src/utils/.format.md +74 -25
- package/src/utils/.generic-domain-utils.md +42 -0
- package/src/utils/.image-proxy.md +59 -23
- package/src/utils/.index.md +42 -49
- package/src/utils/.local-storage-adapter.md +50 -0
- package/src/utils/.ods-color-utils.md +55 -38
- package/src/utils/.platform-config.md +45 -25
- package/src/utils/.scroll-into-view.md +40 -0
- package/src/utils/.source-icons.md +53 -0
- package/src/utils/.sse-decision-frame.md +46 -0
- package/src/utils/dev-sections/.index.md +34 -0
- package/src/utils/dev-sections/.openframe-dev-sections.md +49 -0
- package/dist/chunk-ZDF6F7ED.cjs.map +0 -1
- package/dist/chunk-ZTJVRSN5.js.map +0 -1
- package/src/components/.card.md +0 -42
- package/src/components/.contact-button.md +0 -30
- package/src/components/.drawer.md +0 -46
- package/src/components/.fixed-layout-container.md +0 -47
- package/src/components/.footer-waitlist-card.md +0 -29
- package/src/components/.join-waitlist-cta.md +0 -29
- package/src/components/.sheet.md +0 -47
- package/src/components/.sliding-panel.md +0 -48
- package/src/components/.tooltip.md +0 -48
- package/src/components/.use-mobile.md +0 -42
- package/src/components/.vendor-compact-card.md +0 -66
- package/src/components/.x-button.md +0 -42
- package/src/components/features/.github-repo-button.md +0 -40
- package/src/components/features/.organization-icon.md +0 -47
- package/src/components/features/.organization-selector.md +0 -45
- package/src/components/icons/.fleet-icon.md +0 -39
- package/src/components/icons/.meshcentral-icon.md +0 -35
- package/src/components/icons/.refresh-icon.md +0 -34
- package/src/components/icons/.tactical-icon.md +0 -35
- package/src/components/ui/.button.md +0 -69
- package/src/components/ui/.log-table-row.md +0 -47
- package/src/components/ui/.selectable-device-card.md +0 -46
- package/src/hooks/.api-hooks-stub.md +0 -45
- package/src/hooks/api/.use-product-releases.md +0 -53
- package/src/stories/.OrganizationSelector.stories.md +0 -42
- package/src/stories/.SelectableDeviceCard.stories.md +0 -30
- package/src/utils/.lite-youtube-embed-stub.md +0 -37
- package/src/utils/.lite-youtube-embed.md +0 -33
- /package/dist/{chunk-IK2X5YJU.js.map → chunk-7PCP7YQR.js.map} +0 -0
- /package/dist/{chunk-3JWIJJ44.js.map → chunk-R6MLPU4A.js.map} +0 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<!-- source-hash: f066f48b7e750fe429b96a6f9a50da79 -->
|
|
2
|
+
A `localStorage`-backed React hook providing optimistic up/down voting for roadmap cards, with one vote per task per user, automatic vote toggling/switching, and server sync via a configurable API endpoint.
|
|
3
|
+
|
|
4
|
+
## Key Components
|
|
5
|
+
|
|
6
|
+
### Types
|
|
7
|
+
|
|
8
|
+
| Type | Description |
|
|
9
|
+
|------|-------------|
|
|
10
|
+
| `VoteType` | `'up' \| 'down' \| null` — current vote state for a task |
|
|
11
|
+
| `VoteState` | Record mapping `taskId → VoteType` |
|
|
12
|
+
| `UseRoadmapVotingOptions` | Configuration interface for endpoint and storage key |
|
|
13
|
+
|
|
14
|
+
### Hook Return Values
|
|
15
|
+
|
|
16
|
+
| Value | Type | Description |
|
|
17
|
+
|-------|------|-------------|
|
|
18
|
+
| `votes` | `VoteState` | All current votes keyed by `taskId` |
|
|
19
|
+
| `isLoading` | `boolean` | `true` while hydrating from `localStorage` |
|
|
20
|
+
| `getVote` | `(taskId) => VoteType` | Returns current vote for a task |
|
|
21
|
+
| `toggleVote` | `async (taskId, voteType) => result` | Casts or removes a vote with optimistic update |
|
|
22
|
+
| `clearVotes` | `() => void` | Clears all votes from state and `localStorage` |
|
|
23
|
+
|
|
24
|
+
### Core Behavior
|
|
25
|
+
|
|
26
|
+
- **Optimistic updates** — UI reflects vote immediately; reverts on API failure
|
|
27
|
+
- **Toggle semantics** — clicking the active vote removes it; switching direction sends a remove + add pair to keep server totals consistent
|
|
28
|
+
- **Namespace isolation** — `storageKey` option allows multiple roadmap surfaces on the same origin without vote cross-contamination
|
|
29
|
+
- **Key change safety** — state resets and re-hydrates whenever `storageKey` changes mid-lifecycle
|
|
30
|
+
|
|
31
|
+
## Usage Example
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { useRoadmapVoting } from './use-roadmap-voting';
|
|
35
|
+
|
|
36
|
+
function RoadmapCard({ taskId }: { taskId: string }) {
|
|
37
|
+
const { getVote, toggleVote, isLoading } = useRoadmapVoting({
|
|
38
|
+
voteApiEndpoint: '/api/roadmap/vote',
|
|
39
|
+
storageKey: 'roadmap_votes_v1_main',
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const currentVote = getVote(taskId);
|
|
43
|
+
|
|
44
|
+
const handleVote = async (type: 'up' | 'down') => {
|
|
45
|
+
const { success, newVote } = await toggleVote(taskId, type);
|
|
46
|
+
if (!success) console.warn('Vote failed, reverted to:', newVote);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
if (isLoading) return <span>Loading...</span>;
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div>
|
|
53
|
+
<button
|
|
54
|
+
onClick={() => handleVote('up')}
|
|
55
|
+
style={{ fontWeight: currentVote === 'up' ? 'bold' : 'normal' }}
|
|
56
|
+
>
|
|
57
|
+
👍
|
|
58
|
+
</button>
|
|
59
|
+
<button
|
|
60
|
+
onClick={() => handleVote('down')}
|
|
61
|
+
style={{ fontWeight: currentVote === 'down' ? 'bold' : 'normal' }}
|
|
62
|
+
>
|
|
63
|
+
👎
|
|
64
|
+
</button>
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<!-- source-hash: a4fe8194703f767fe2216ee1b9351f99 -->
|
|
2
|
+
A client-side React component that renders a single support ticket row in the Help Center list, featuring a toggleable expanded drawer for full ticket interaction.
|
|
3
|
+
|
|
4
|
+
## Key Components
|
|
5
|
+
|
|
6
|
+
### `HelpCenterCard` (default export)
|
|
7
|
+
The primary component rendering a ticket summary row as a clickable `<button>` that toggles a `<TicketDetailDrawer>` below it. Key behaviors:
|
|
8
|
+
|
|
9
|
+
- **Optimistic rows** are rendered as non-expandable (dimmed, `opacity-60`) until the server confirms the ticket ID
|
|
10
|
+
- **Scroll-on-expand** uses `scrollElementIntoView` with a cross-row layout-shift correction — compensates when a sibling drawer above collapses simultaneously, shifting the page Y position
|
|
11
|
+
- **Sticky header offset** (`STICKY_HEADER_OFFSET_PX = 96`) is applied both as `scrollMarginTop` inline style (for browser/anchor scrolls) and as `headerOffset` (for programmatic scroll), keeping them in sync from a single constant
|
|
12
|
+
|
|
13
|
+
### `HelpCenterCardProps`
|
|
14
|
+
```typescript
|
|
15
|
+
interface HelpCenterCardProps {
|
|
16
|
+
ticket: AnyTicket
|
|
17
|
+
expanded: boolean
|
|
18
|
+
onToggle: (id: string) => void
|
|
19
|
+
busy: boolean
|
|
20
|
+
supportSystemDown: boolean
|
|
21
|
+
onSendMessage: TicketDetailDrawerProps['onSendMessage']
|
|
22
|
+
onClose: TicketDetailDrawerProps['onClose']
|
|
23
|
+
onReopen: TicketDetailDrawerProps['onReopen']
|
|
24
|
+
onActionCollapsed: () => void
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### `mapPriorityScheme` (internal)
|
|
29
|
+
Maps ticket priority strings to `StatusBadge` color schemes. Kept separate from the shared `getStatusColorScheme` to avoid conflating workflow status with severity.
|
|
30
|
+
|
|
31
|
+
| Priority | Color Scheme |
|
|
32
|
+
|----------|-------------|
|
|
33
|
+
| `HIGH` / `URGENT` | `error` (red) |
|
|
34
|
+
| `MEDIUM` | `warning` (yellow) |
|
|
35
|
+
| `LOW` / unknown | `default` |
|
|
36
|
+
|
|
37
|
+
## Usage Example
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
<HelpCenterCard
|
|
41
|
+
ticket={ticket}
|
|
42
|
+
expanded={expandedId === ticket.id}
|
|
43
|
+
onToggle={(id) => setExpandedId(prev => prev === id ? null : id)}
|
|
44
|
+
busy={isBusy}
|
|
45
|
+
supportSystemDown={false}
|
|
46
|
+
onSendMessage={handleSendMessage}
|
|
47
|
+
onClose={handleCloseTicket}
|
|
48
|
+
onReopen={handleReopenTicket}
|
|
49
|
+
onActionCollapsed={() => setExpandedId(null)}
|
|
50
|
+
/>
|
|
51
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<!-- source-hash: a34cdabdcffe2227fd25cb927e40e785 -->
|
|
2
|
+
Thin wrapper around `<ContactForm />` that preconfigures it for Help Center ticket creation, plus a pixel-accurate loading skeleton.
|
|
3
|
+
|
|
4
|
+
## Key Components
|
|
5
|
+
|
|
6
|
+
### `HelpCenterCreateForm`
|
|
7
|
+
The primary export. Wraps `<ContactForm />` with ticket-specific configuration:
|
|
8
|
+
- Hides irrelevant contact fields (`name`, `email`, `companySize`, `referralSource`, `helpCategory`)
|
|
9
|
+
- Injects a locally-managed `Subject` input via `extraTopField`
|
|
10
|
+
- Pre-fills hidden fields from session identity to satisfy Zod validators
|
|
11
|
+
- Wires `onCustomSubmit` to `actions.submitTicket(...)` with subject validation before delegating
|
|
12
|
+
|
|
13
|
+
### `HelpCenterCreateFormSkeleton`
|
|
14
|
+
A loading placeholder that mirrors the real form's dimensions pixel-for-pixel (verified at `lg` breakpoint: 556px wrapper height). Includes 4 hidden `<input type="hidden">` elements to replicate Tailwind's `space-y-*` sibling spacing behavior — omitting them shifts the visible stack up by 24px on page load.
|
|
15
|
+
|
|
16
|
+
### `HelpCenterCreateFormProps`
|
|
17
|
+
| Prop | Type | Description |
|
|
18
|
+
|------|------|-------------|
|
|
19
|
+
| `actions` | `UseTicketActionsReturn` | Full actions bag; `submitTicket` is consumed |
|
|
20
|
+
| `sessionName` | `string` | Pre-resolved identity name from parent |
|
|
21
|
+
| `sessionEmail` | `string` | Pre-resolved identity email from parent |
|
|
22
|
+
| `supportSystemDown` | `boolean` | Disables all inputs when HubSpot is unavailable |
|
|
23
|
+
|
|
24
|
+
## Usage Example
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
<HelpCenterCreateForm
|
|
28
|
+
actions={ticketActions}
|
|
29
|
+
sessionName={identity.name}
|
|
30
|
+
sessionEmail={identity.email}
|
|
31
|
+
supportSystemDown={ticketActions.onSupportSystemDown}
|
|
32
|
+
/>
|
|
33
|
+
|
|
34
|
+
// While identity.isLoading:
|
|
35
|
+
<HelpCenterCreateFormSkeleton />
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
> **Note:** `sessionName`/`sessionEmail` must be passed from the parent rather than re-calling `useChatIdentity` inside this component — a second hook call mounts with `user = null`, causing react-hook-form to lock `defaultValues.email` to an empty string for the form's lifetime, silently failing Zod validation on submit.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<!-- source-hash: 827d4c23e1bcd10b78b97232f2822fa0 -->
|
|
2
|
+
Renders the full Help Center surface for authenticated users, providing ticket listing, creation, filtering, pagination, and optimistic UI updates. Serves as the primary component mounted on the `/tickets` route in OpenFrame.
|
|
3
|
+
|
|
4
|
+
## Key Components
|
|
5
|
+
|
|
6
|
+
- **`HelpCenterList`** — Public entry point. Guards against unauthenticated access (renders skeleton during identity load, `EmptyState` for anon users), then delegates to `HelpCenterListAuthed`.
|
|
7
|
+
- **`HelpCenterListAuthed`** — Internal component handling all authenticated state: merges optimistic + server tickets, manages expanded row, wires mutation callbacks, and composes the full page layout via `<DevSectionPage>`.
|
|
8
|
+
- **`HelpCenterListProps`** — Accepts an optional `toast` override for testability.
|
|
9
|
+
|
|
10
|
+
**Key hooks used:**
|
|
11
|
+
- `useTicketsList` — fetches paginated tickets by `search`, `status`, `page`
|
|
12
|
+
- `useTicketActions` — mutations (submit, close, reopen, send message) with optimistic callbacks
|
|
13
|
+
- `useChatIdentity` — resolves session email/name; guards the auth gate
|
|
14
|
+
|
|
15
|
+
## Usage Example
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// Mounted directly on the /tickets page (OpenFrame):
|
|
19
|
+
import { HelpCenterList } from './help-center-list'
|
|
20
|
+
|
|
21
|
+
export default function TicketsPage() {
|
|
22
|
+
return <HelpCenterList />
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// With toast override for testing:
|
|
26
|
+
import { mockToast } from '../test-utils'
|
|
27
|
+
|
|
28
|
+
render(<HelpCenterList toast={mockToast} />)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## State Model
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
URL params → search, status, page (read by useTicketsList)
|
|
35
|
+
optimisticTickets → local useState (prepend on submit, remove on settle)
|
|
36
|
+
expandedTicketId → local useState (single drawer open at a time)
|
|
37
|
+
supportSystemDown → local useState (disables create form on error)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
> **Note:** Optimistic placeholders are kept in local state (not the TanStack query cache) so URL filter changes don't discard in-flight submissions mid-render.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<!-- source-hash: 9ab6eac897ae7fbb7ae6454201513bed -->
|
|
2
|
+
Barrel export file for the tickets feature module, re-exporting all public components, hooks, and types related to ticket management and the Help Center UI.
|
|
3
|
+
|
|
4
|
+
## Key Components
|
|
5
|
+
|
|
6
|
+
### Components
|
|
7
|
+
| Export | Description |
|
|
8
|
+
|--------|-------------|
|
|
9
|
+
| `TicketCenter` | Main ticket management surface |
|
|
10
|
+
| `TicketOpenForm` | Form for opening new tickets |
|
|
11
|
+
| `TicketRow` | Individual ticket row renderer |
|
|
12
|
+
| `TicketDetailDrawer` | Slide-out drawer for ticket details |
|
|
13
|
+
| `TicketLinkedDeliveryCard` | Card linking a ticket to a delivery |
|
|
14
|
+
| `HelpCenterList` | Full-page customer-facing ticket list, used by OpenFrame's `/tickets` route |
|
|
15
|
+
| `HelpCenterCard` | Expandable card for a single Help Center entry |
|
|
16
|
+
| `HelpCenterCreateForm` / `HelpCenterCreateFormSkeleton` | Ticket creation form with loading skeleton |
|
|
17
|
+
|
|
18
|
+
### Hooks
|
|
19
|
+
| Export | Description |
|
|
20
|
+
|--------|-------------|
|
|
21
|
+
| `useTicketsList` | Fetches and manages the tickets list state |
|
|
22
|
+
| `useTicketActions` | Provides ticket mutation actions; `mapTicketActionError` maps error codes |
|
|
23
|
+
| `useTicketEngagements` | Manages ticket engagement threads and file attachments |
|
|
24
|
+
|
|
25
|
+
### Types & Constants
|
|
26
|
+
| Export | Description |
|
|
27
|
+
|--------|-------------|
|
|
28
|
+
| `TicketData`, `AnyTicket`, `OptimisticTicket` | Core ticket data shapes |
|
|
29
|
+
| `TicketClickupSummary` | ClickUp-specific ticket summary |
|
|
30
|
+
| `TicketActionErrorCode`, `MappedTicketActionError` | Typed error handling |
|
|
31
|
+
| `TICKET_TOAST_COPY` | Toast notification copy constants |
|
|
32
|
+
| `isOptimistic` | Type guard for optimistic ticket entries |
|
|
33
|
+
| `TicketRef`, `TicketEngagement`, `TicketEngagementFile` | Supporting types |
|
|
34
|
+
|
|
35
|
+
## Usage Example
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import {
|
|
39
|
+
HelpCenterList,
|
|
40
|
+
TicketDetailDrawer,
|
|
41
|
+
useTicketsList,
|
|
42
|
+
useTicketActions,
|
|
43
|
+
isOptimistic,
|
|
44
|
+
type AnyTicket,
|
|
45
|
+
} from '@/features/tickets'
|
|
46
|
+
|
|
47
|
+
function TicketsPage() {
|
|
48
|
+
const { tickets } = useTicketsList()
|
|
49
|
+
const { closeTicket } = useTicketActions()
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<HelpCenterList>
|
|
53
|
+
{tickets.map((ticket: AnyTicket) => (
|
|
54
|
+
<TicketDetailDrawer
|
|
55
|
+
key={isOptimistic(ticket) ? ticket.optimisticId : ticket.id}
|
|
56
|
+
ticket={ticket}
|
|
57
|
+
onClose={() => closeTicket(ticket.id)}
|
|
58
|
+
/>
|
|
59
|
+
))}
|
|
60
|
+
</HelpCenterList>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
> **Note:** Third-party embedders can mount `<HelpCenterList />` inside their own `<PageShell>` to get the full Help Center UX without the OpenFrame route wrapper.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<!-- source-hash: 342918f6f476b195a4bfc05a9be396e0 -->
|
|
2
|
+
Customer-facing ticket management surface that renders a full ticket workflow (open, view, reply, close, reopen) for authenticated users, and an identity-gated sign-in prompt for anonymous visitors.
|
|
3
|
+
|
|
4
|
+
## Key Components
|
|
5
|
+
|
|
6
|
+
| Export / Symbol | Description |
|
|
7
|
+
|---|---|
|
|
8
|
+
| `TicketCenter` | Root exported component; handles identity resolution and delegates to `TicketCenterAuthed` or fallback states |
|
|
9
|
+
| `TicketCenterAuthed` | Inner authenticated shell; owns optimistic state, query cache mutations, and composes the form + list |
|
|
10
|
+
| `TicketCenterSkeleton` | Full-page skeleton shown during the first-mount identity resolution window |
|
|
11
|
+
| `TicketListSkeleton` | List-only skeleton shown while ticket data is loading |
|
|
12
|
+
| `TicketCenterProps` | Public prop interface — only exposes a `toast` override for testability |
|
|
13
|
+
|
|
14
|
+
## Usage Example
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
// Minimal embed — relies on a QueryClientProvider + ChatRuntimeContext.Provider
|
|
18
|
+
// already mounted at the app root (same pattern as <EmbeddableChat />)
|
|
19
|
+
import { TicketCenter } from '@/components/ticket-center/ticket-center'
|
|
20
|
+
|
|
21
|
+
export function SupportPage() {
|
|
22
|
+
return (
|
|
23
|
+
<main>
|
|
24
|
+
<TicketCenter />
|
|
25
|
+
</main>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Test-friendly override — inject a mock toast to assert notifications
|
|
30
|
+
import { TicketCenter } from '@/components/ticket-center/ticket-center'
|
|
31
|
+
import { mockToast } from '@/test/helpers'
|
|
32
|
+
|
|
33
|
+
render(<TicketCenter toast={mockToast} />)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Identity Gate Behavior
|
|
37
|
+
|
|
38
|
+
```mermaid
|
|
39
|
+
flowchart TD
|
|
40
|
+
A["TicketCenter mounts"] --> B{"identity.isLoading?"}
|
|
41
|
+
B -->|yes| C["TicketCenterSkeleton"]
|
|
42
|
+
B -->|no| D{"authTier === anon\nor no email?"}
|
|
43
|
+
D -->|yes| E["EmptyState: Sign in prompt"]
|
|
44
|
+
D -->|no| F["TicketCenterAuthed"]
|
|
45
|
+
F --> G["TicketOpenForm"]
|
|
46
|
+
F --> H["TicketRow list\noptimistic + server merged"]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Optimistic Update Strategy
|
|
50
|
+
|
|
51
|
+
Optimistic tickets are kept in **local state** (not the React Query cache) so a background refetch cannot overwrite pending placeholders mid-flight. The merged view is always `[...optimisticTickets, ...serverTickets]`, placing new pending rows at the top until the server response confirms or rejects them.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<!-- source-hash: 8a7542421be9aaeac5211827f8967375 -->
|
|
2
|
+
Expanded drawer component for a single ticket's detail view, rendering the conversation timeline, metadata, and status-dependent actions (reply/close/reopen).
|
|
3
|
+
|
|
4
|
+
## Key Components
|
|
5
|
+
|
|
6
|
+
### `TicketDetailDrawer` (main export)
|
|
7
|
+
The root drawer component that composes the full expanded ticket view:
|
|
8
|
+
- Renders optional linked ClickUp delivery card
|
|
9
|
+
- Delegates conversation rendering to `TicketTimelinePanel`
|
|
10
|
+
- Conditionally renders `OpenActions` or `ReopenAction` based on ticket status
|
|
11
|
+
|
|
12
|
+
### `TicketTimelinePanel`
|
|
13
|
+
Internal component that builds a chronological conversation thread:
|
|
14
|
+
- Splits legacy `ticket.body` on ` --- ` separators for historical compatibility
|
|
15
|
+
- Fetches Note engagements via `useTicketEngagements`
|
|
16
|
+
- Resolves customer identity with a 4-level precedence chain (live identity → mirror name → email → "You")
|
|
17
|
+
- Shows skeleton loader during initial fetch; `EmptyState` when no content exists
|
|
18
|
+
|
|
19
|
+
### `TicketRef`
|
|
20
|
+
Minimal identity bundle (`id` + `external_id`) threaded through mutation callbacks — `external_id` targets HubSpot, `id` drives React/TanStack cache keys.
|
|
21
|
+
|
|
22
|
+
## Usage Example
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
<TicketDetailDrawer
|
|
26
|
+
ticket={ticket}
|
|
27
|
+
busy={isMutating}
|
|
28
|
+
supportSystemDown={false}
|
|
29
|
+
onSendMessage={async (ref, text, attachments) => {
|
|
30
|
+
await sendNoteEngagement(ref.external_id, text, attachments)
|
|
31
|
+
return true
|
|
32
|
+
}}
|
|
33
|
+
onClose={async (ref, resolution) => {
|
|
34
|
+
await closeTicket(ref.external_id, resolution)
|
|
35
|
+
return true
|
|
36
|
+
}}
|
|
37
|
+
onReopen={async (ref) => {
|
|
38
|
+
await reopenTicket(ref.external_id)
|
|
39
|
+
return true
|
|
40
|
+
}}
|
|
41
|
+
onActionCollapsed={() => setDrawerOpen(false)}
|
|
42
|
+
/>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Notes
|
|
46
|
+
- All local state (composer text, attachments, close-confirm dialog) is owned here; parent owns ticket data and mutation callbacks
|
|
47
|
+
- Optimistic tickets (pre-server-confirmation) skip the engagement fetch until a real `external_id` is available
|
|
48
|
+
- The timeline intentionally has no inner scroll — content flows with the page to avoid competing scroll surfaces
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<!-- source-hash: 73401c7b99510ec750c43323cc9caed2 -->
|
|
2
|
+
Renders a ClickUp delivery task linked to a HubSpot ticket as a single `<DeliveryRow />` tile, using the same primitive as the `/bug-fixes-and-enhancements` list view.
|
|
3
|
+
|
|
4
|
+
## Key Components
|
|
5
|
+
|
|
6
|
+
- **`TicketLinkedDeliveryCard`** — Main component that maps a `TicketClickupSummary` onto a `DeliveryItem` and renders it inside a bordered card container
|
|
7
|
+
- **`TicketLinkedDeliveryCardProps`** — Props interface accepting a `clickup` summary object and optional `className`
|
|
8
|
+
- **`DeliveryItem`** — Normalized shape passed to `<DeliveryRow />`, with fallbacks for all optional ClickUp fields
|
|
9
|
+
- **`DeliveryRow`** — Shared primitive that handles display and navigation, receiving the pre-built `delivery_href` for deep-linking
|
|
10
|
+
|
|
11
|
+
## Navigation Behavior
|
|
12
|
+
|
|
13
|
+
Navigation uses `clickup.delivery_href`, built server-side via `buildDevSectionUrl('delivery', external_id)`. The URL includes `?search=<external_id>` to filter the destination list to the exact task — the same deep-link mechanism used by chat-inline delivery cards. Soft-nav via the env-aware `next/link` shim preserves React state and TanStack-Query cache on back-navigation.
|
|
14
|
+
|
|
15
|
+
## Usage Example
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { TicketLinkedDeliveryCard } from './ticket-linked-delivery-card'
|
|
19
|
+
|
|
20
|
+
const clickupSummary: TicketClickupSummary = {
|
|
21
|
+
external_id: 'task-abc123',
|
|
22
|
+
title: 'Migrate auth service to OAuth2',
|
|
23
|
+
description: 'Refactor legacy token logic...',
|
|
24
|
+
status: 'in progress',
|
|
25
|
+
status_color: '#4eccc4',
|
|
26
|
+
task_type: 'Feature',
|
|
27
|
+
delivery_href: '/delivery?search=task-abc123',
|
|
28
|
+
clickup_url: 'https://app.clickup.com/t/abc123',
|
|
29
|
+
date_opened: 1710000000000,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
<TicketLinkedDeliveryCard
|
|
33
|
+
clickup={clickupSummary}
|
|
34
|
+
className="mt-4"
|
|
35
|
+
/>
|
|
36
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<!-- source-hash: b30cd8d851756508ef3f90328778876a -->
|
|
2
|
+
A client-side React form component for creating new support tickets, rendered at the top of the `<TicketCenter />` view. Composes existing OSS-lib primitives for subject input, message textarea, file attachments, and submit action with multi-condition gating.
|
|
3
|
+
|
|
4
|
+
## Key Components
|
|
5
|
+
|
|
6
|
+
### `TicketOpenFormProps`
|
|
7
|
+
| Prop | Type | Description |
|
|
8
|
+
|------|------|-------------|
|
|
9
|
+
| `onSubmit` | `(input) => Promise<boolean>` | Wired to `useTicketActions().submitTicket`; returns `true` on success to trigger form reset |
|
|
10
|
+
| `isSubmitting` | `boolean` | Parent-owned single-flight submission flag |
|
|
11
|
+
| `supportSystemDown` | `boolean` | Disables all inputs and submit when the support system is offline |
|
|
12
|
+
|
|
13
|
+
### Submit Gating (`canSubmit`)
|
|
14
|
+
The submit button is enabled only when **all** conditions pass:
|
|
15
|
+
|
|
16
|
+
```mermaid
|
|
17
|
+
graph TD
|
|
18
|
+
A["canSubmit?"] --> B["not isSubmitting"]
|
|
19
|
+
A --> C["not supportSystemDown"]
|
|
20
|
+
A --> D["not hasInflightUploads"]
|
|
21
|
+
A --> E["subject.trim() not empty"]
|
|
22
|
+
A --> F["content.trim() not empty"]
|
|
23
|
+
A --> G["content within TICKET_TEXT_MAX_CHARS"]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Internal State
|
|
27
|
+
- `subject` / `content` — controlled inputs, cleared on successful submit
|
|
28
|
+
- `attachments` — managed via `useChatAttachments()`, sharing the same upload pipeline as the chat composer
|
|
29
|
+
|
|
30
|
+
## Usage Example
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { TicketOpenForm } from './ticket-open-form'
|
|
34
|
+
import { useTicketActions } from './hooks/use-ticket-actions'
|
|
35
|
+
|
|
36
|
+
function TicketCenter() {
|
|
37
|
+
const { submitTicket, isSubmitting } = useTicketActions()
|
|
38
|
+
const supportSystemDown = false
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<TicketOpenForm
|
|
42
|
+
onSubmit={submitTicket}
|
|
43
|
+
isSubmitting={isSubmitting}
|
|
44
|
+
supportSystemDown={supportSystemDown}
|
|
45
|
+
/>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
> A character counter appears once content reaches 80% of `TICKET_TEXT_MAX_CHARS` and turns red if the limit is exceeded, blocking submission.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<!-- source-hash: a4bd0ac033c0ff89f6d4e4e0f75efebc -->
|
|
2
|
+
Renders a single ticket row with an expandable inline drawer, combining a compact summary tile with a collapsible detail panel for the `TicketCenter` embed.
|
|
3
|
+
|
|
4
|
+
## Key Components
|
|
5
|
+
|
|
6
|
+
- **`TicketRow`** — Main export. Composes a `<ChatTicketItem>` summary tile and a `<CollapsibleContent>` wrapping `<TicketDetailDrawer>`. Controlled via `expanded`/`onToggle` props owned by the parent `<TicketCenter>`.
|
|
7
|
+
- **`TicketRowProps`** — Interface defining ticket data, expansion state, action handlers (`onSendMessage`, `onClose`, `onReopen`, `onActionCollapsed`), and UI flags (`busy`, `supportSystemDown`).
|
|
8
|
+
- **`handleClick`** — Memoized click handler that toggles expansion and smooth-scrolls the row into view, pre-adjusting target Y position to account for any drawer above that is simultaneously collapsing.
|
|
9
|
+
- **`tileData`** — Derived `ChatTicketItemData` object mapping raw `AnyTicket` fields to display values, including HubSpot pipeline stage label, relative timestamps, and ClickUp linked task status chips.
|
|
10
|
+
|
|
11
|
+
## Usage Example
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
<TicketRow
|
|
15
|
+
ticket={ticket}
|
|
16
|
+
expanded={expandedTicketId === ticket.id}
|
|
17
|
+
onToggle={(id) => setExpandedTicketId((prev) => (prev === id ? null : id))}
|
|
18
|
+
busy={isBusy}
|
|
19
|
+
supportSystemDown={false}
|
|
20
|
+
onSendMessage={handleSendMessage}
|
|
21
|
+
onClose={handleClose}
|
|
22
|
+
onReopen={handleReopen}
|
|
23
|
+
onActionCollapsed={() => setExpandedTicketId(null)}
|
|
24
|
+
/>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Notes
|
|
28
|
+
|
|
29
|
+
- Optimistic tickets (pre-server-confirmation) disable click interaction and suppress drawer rendering since a real ticket ID is not yet available.
|
|
30
|
+
- The scroll adjustment logic mirrors `<HelpCenterCard>` — queries `div[id^="ticket-drawer-"]` to find an open drawer above the clicked row and subtracts its height from the raw scroll target, ensuring the final scroll position matches the post-collapse layout.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<!-- source-hash: 63b1778d9923d2e7914bfaebf859d9ff -->
|
|
2
|
+
Defines the shared type contract for the ticket management feature, including wire shapes for ticket data returned from the `POST /api/chat/agent/find-ticket` endpoint, optimistic UI helpers, error handling types, and UI constants.
|
|
3
|
+
|
|
4
|
+
## Key Components
|
|
5
|
+
|
|
6
|
+
| Export | Kind | Description |
|
|
7
|
+
|--------|------|-------------|
|
|
8
|
+
| `TicketData` | Interface | Wire shape of a ticket row from the find-ticket API, mirroring the server's `FindTicketResult` projection |
|
|
9
|
+
| `TicketClickupSummary` | Interface | Compact projection of a linked ClickUp task for the ticket drawer's delivery card |
|
|
10
|
+
| `OptimisticTicket` | Interface | Extends `TicketData` with `_optimistic: true` for pre-flight UI placeholders |
|
|
11
|
+
| `AnyTicket` | Type | Union of `TicketData \| OptimisticTicket` |
|
|
12
|
+
| `isOptimistic()` | Type Guard | Narrows `AnyTicket` to `OptimisticTicket` |
|
|
13
|
+
| `TicketActionErrorCode` | Type | Discriminated string union of stable server-side error codes |
|
|
14
|
+
| `MappedTicketActionError` | Interface | Structured error envelope with toast copy, cache hints, and retry metadata |
|
|
15
|
+
| `TICKET_TEXT_MAX_CHARS` | Constant | Client-side cap of `5000` chars for ticket text inputs |
|
|
16
|
+
| `TOAST_COPY` | Constant | Centralized `as const` map of all user-visible toast strings |
|
|
17
|
+
|
|
18
|
+
## Usage Example
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import {
|
|
22
|
+
AnyTicket,
|
|
23
|
+
isOptimistic,
|
|
24
|
+
MappedTicketActionError,
|
|
25
|
+
TICKET_TEXT_MAX_CHARS,
|
|
26
|
+
TOAST_COPY,
|
|
27
|
+
} from './types'
|
|
28
|
+
|
|
29
|
+
// Narrow optimistic rows before rendering the drawer
|
|
30
|
+
function renderTicket(ticket: AnyTicket) {
|
|
31
|
+
if (isOptimistic(ticket)) {
|
|
32
|
+
return <SkeletonDrawer />
|
|
33
|
+
}
|
|
34
|
+
return <TicketDrawer data={ticket} />
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Validate user input before submission
|
|
38
|
+
if (content.length > TICKET_TEXT_MAX_CHARS) {
|
|
39
|
+
throw new Error(`Max ${TICKET_TEXT_MAX_CHARS} characters allowed`)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Handle a mapped server error
|
|
43
|
+
function handleError(err: MappedTicketActionError) {
|
|
44
|
+
if (err.supportSystemDown) {
|
|
45
|
+
showSupportDownBanner()
|
|
46
|
+
}
|
|
47
|
+
if (err.removeRowFromCache) {
|
|
48
|
+
removeTicketFromList(ticketId)
|
|
49
|
+
}
|
|
50
|
+
toast({ title: err.message })
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Use centralized toast copy on success
|
|
54
|
+
toast(TOAST_COPY.open_success)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
> **Note:** `TicketData` is intentionally duplicated from the server's `FindTicketResult`. If `FIND_TICKET_SELECT` gains a new column server-side, this interface must be updated to match.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<!-- source-hash: 6164b984e1688be647fedf5037a794eb -->
|
|
2
|
+
Brief description of the file's purpose: This hook encapsulates all ticket write operations (create, update, close, reopen, reply) for the Flamingo/OpenFrame tickets UI, routing them through a single `/api/chat/agent/ticket-action` endpoint with single-flight protection, per-row mutexes, a serialization queue, and mirror-sync retry logic.
|
|
3
|
+
|
|
4
|
+
## Key Components
|
|
5
|
+
|
|
6
|
+
### `useTicketActions(options: UseTicketActionsOptions): UseTicketActionsReturn`
|
|
7
|
+
The primary exported hook. Accepts callback options from the parent and returns ticket action handlers plus loading state selectors.
|
|
8
|
+
|
|
9
|
+
### `UseTicketActionsOptions`
|
|
10
|
+
Configuration interface injected by the parent component:
|
|
11
|
+
- `prependOptimistic` — adds an optimistic placeholder row to the QueryClient cache before the server roundtrip
|
|
12
|
+
- `removeOptimistic` — removes the placeholder on mirror-sync failure or real ticket arrival
|
|
13
|
+
- `removeTicketFromCache` — silent cache removal on `TICKET_NOT_FOUND`
|
|
14
|
+
- `toast` — notification helper (injected for testability)
|
|
15
|
+
- `onSupportSystemDown` — called on `412 HUBSPOT_DISCONNECTED`
|
|
16
|
+
|
|
17
|
+
### `UseTicketActionsReturn`
|
|
18
|
+
Returned handler surface:
|
|
19
|
+
- `submitTicket(input)` — creates a new ticket with subject, content, and optional attachments
|
|
20
|
+
- `sendMessage(ticket, text, attachments)` — sends a combined reply note
|
|
21
|
+
- `closeTicket(ticket, resolution?)` — closes a ticket
|
|
22
|
+
- `reopenTicket(ticket)` — reopens a closed ticket
|
|
23
|
+
- `isSubmittingForm` — boolean loading state for form-level submission
|
|
24
|
+
- `isRowBusy(localId)` — per-row busy predicate for UI disabling
|
|
25
|
+
|
|
26
|
+
### `TicketRef`
|
|
27
|
+
Decouples the local mirror UUID (`id`) from the HubSpot external id (`external_id`), both required for correct mutex and server routing.
|
|
28
|
+
|
|
29
|
+
### Internal Mechanisms
|
|
30
|
+
| Mechanism | Purpose |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `formInFlightRef` + `isSubmittingForm` | Prevents duplicate form submits across async ticks |
|
|
33
|
+
| `busyRowsRef` + `busyRows` | Per-row mutex preventing fan-out on the same ticket row |
|
|
34
|
+
| `queueRef` / `enqueue` | Depth-1 serial queue preventing server rate-limit stampedes |
|
|
35
|
+
| `watchMirrorSync` | 3s/6s/12s backoff refetch loop when `mirror_synced === false`; drops placeholder after 30s cap |
|
|
36
|
+
| `watcherControllersRef` | `AbortController` map; aborted on unmount and on duplicate-submit replacement |
|
|
37
|
+
|
|
38
|
+
## Usage Example
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
const {
|
|
42
|
+
submitTicket,
|
|
43
|
+
sendMessage,
|
|
44
|
+
closeTicket,
|
|
45
|
+
reopenTicket,
|
|
46
|
+
isSubmittingForm,
|
|
47
|
+
isRowBusy,
|
|
48
|
+
} = useTicketActions({
|
|
49
|
+
prependOptimistic: (placeholder) => {
|
|
50
|
+
queryClient.setQueryData(['tickets'], (old: TicketData) => ({
|
|
51
|
+
...old,
|
|
52
|
+
tickets: [placeholder, ...(old?.tickets ?? [])],
|
|
53
|
+
}))
|
|
54
|
+
},
|
|
55
|
+
removeOptimistic: (id) => {
|
|
56
|
+
queryClient.setQueryData(['tickets'], (old: TicketData) => ({
|
|
57
|
+
...old,
|
|
58
|
+
tickets: old?.tickets.filter((t) => t.id !== id) ?? [],
|
|
59
|
+
}))
|
|
60
|
+
},
|
|
61
|
+
removeTicketFromCache: (ticketId) => { /* cache mutation */ },
|
|
62
|
+
toast,
|
|
63
|
+
onSupportSystemDown: () => setSupportSystemDown(true),
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
// Create a ticket
|
|
67
|
+
const ok = await submitTicket({
|
|
68
|
+
subject: 'VPN not connecting',
|
|
69
|
+
content: 'Unable to connect since this morning.',
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
// Close a ticket
|
|
73
|
+
await closeTicket(
|
|
74
|
+
{ id: ticket.id, external_id: ticket.external_id },
|
|
75
|
+
'Resolved by restarting the VPN client.'
|
|
76
|
+
)
|
|
77
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<!-- source-hash: 14e8fee946105e4d0d83a53313cfd255 -->
|
|
2
|
+
Fetches the conversation timeline (notes, messages, and attachments) for a single HubSpot ticket, powering the ticket drawer's timeline view. Intentionally separate from the ticket list hook since engagements require expensive multi-stage API calls and are only loaded on demand.
|
|
3
|
+
|
|
4
|
+
## Key Components
|
|
5
|
+
|
|
6
|
+
### Interfaces
|
|
7
|
+
|
|
8
|
+
| Interface | Description |
|
|
9
|
+
|---|---|
|
|
10
|
+
| `TicketEngagementFile` | Attachment metadata: `id`, `name`, `url`, `mime`, `size` |
|
|
11
|
+
| `TicketEngagement` | A single timeline entry with body, author info (`authorRole`, `authorName`, `authorEmail`, `authorAvatarUrl`), timestamp, and attachments |
|
|
12
|
+
| `UseTicketEngagementsReturn` | Return shape: `engagements`, `isLoading`, `isFetching`, `error`, `refetch` |
|
|
13
|
+
|
|
14
|
+
### Hook
|
|
15
|
+
|
|
16
|
+
**`useTicketEngagements(externalTicketId, enabled?)`** — Queries `/api/chat/agent/list-engagements` via `embedAuthedFetch`. Skips execution for anonymous users, missing ticket IDs, and optimistic `temp-*` placeholders. Caching is intentionally disabled (`staleTime: 0`, `gcTime: 0`) so every drawer-open reflects live HubSpot state.
|
|
17
|
+
|
|
18
|
+
## Usage Example
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
const { engagements, isLoading, error, refetch } = useTicketEngagements(ticket.externalId)
|
|
22
|
+
|
|
23
|
+
if (isLoading) return <Spinner />
|
|
24
|
+
if (error) return <ErrorBanner message={error.message} />
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<Timeline>
|
|
28
|
+
{engagements.map(e => (
|
|
29
|
+
<TimelineEntry
|
|
30
|
+
key={e.id}
|
|
31
|
+
body={e.body}
|
|
32
|
+
role={e.authorRole} // 'customer' | 'support'
|
|
33
|
+
author={e.authorName}
|
|
34
|
+
avatarUrl={e.authorAvatarUrl}
|
|
35
|
+
attachments={e.attachments}
|
|
36
|
+
/>
|
|
37
|
+
))}
|
|
38
|
+
</Timeline>
|
|
39
|
+
)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
> **Security note:** The server-side route enforces ticket ownership via `ticketBelongsToCustomer` before returning notes — customers cannot enumerate another customer's timeline by guessing ticket IDs.
|