@campfire-interactive/shell-header 0.9.1 → 0.12.0
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/index.d.ts +6 -0
- package/dist/index.js +87 -15
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -141,6 +141,12 @@ interface BugReportContext {
|
|
|
141
141
|
url?: string;
|
|
142
142
|
appVersion?: string;
|
|
143
143
|
apiVersion?: string;
|
|
144
|
+
/**
|
|
145
|
+
* URL of the suite issues list (dms webapp `/issues`). When set, the
|
|
146
|
+
* dialog links to it ("View known issues") so reporters can check whether
|
|
147
|
+
* their bug is already filed. Opens in a new tab.
|
|
148
|
+
*/
|
|
149
|
+
issuesUrl?: string;
|
|
144
150
|
}
|
|
145
151
|
/**
|
|
146
152
|
* What the modal hands to `onSubmit`. Field names (minus `screenshot`)
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@ function styleInject(css, { insertAt } = {}) {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// src/styles.css
|
|
27
|
-
styleInject(".cfi-sh-header {\n display: flex;\n align-items: center;\n height: var(--cfi-shell-header-height, 48px);\n padding: 0 var(--cfi-spacing-md, 1rem);\n background: white;\n color: var(--cfi-color-gray-900, #111827);\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n position: relative;\n z-index: 1000;\n}\n.cfi-sh-left {\n display: flex;\n align-items: center;\n flex: 1;\n gap: var(--cfi-spacing-md, 1rem);\n overflow: hidden;\n}\n.cfi-sh-app-brand {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n flex-shrink: 0;\n}\n.cfi-sh-app-badge {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n color: white;\n font-size: 14px;\n font-weight: 700;\n font-family: inherit;\n border-radius: var(--cfi-radius-md, 0.375rem);\n flex-shrink: 0;\n}\n.cfi-sh-app-title {\n font-weight: 600;\n font-size: var(--cfi-font-size-base, 1rem);\n color: var(--cfi-color-gray-900, #111827);\n white-space: nowrap;\n}\n.cfi-sh-suite-logo {\n height: 22px;\n width: auto;\n display: block;\n}\n.cfi-sh-right {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n flex-shrink: 0;\n}\n.cfi-sh-icon-btn {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: transparent;\n border: none;\n border-radius: 50%;\n color: var(--cfi-color-gray-600, #4b5563);\n cursor: pointer;\n transition: background 150ms;\n}\n.cfi-sh-icon-btn:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--cfi-color-error, #ef4444);\n color: white;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n border-radius: 99px;\n}\n.cfi-sh-app-switcher {\n position: relative;\n}\n.cfi-sh-app-grid {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: var(--cfi-spacing-xs, 0.25rem);\n padding: var(--cfi-spacing-sm, 0.5rem);\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n min-width: 280px;\n}\n.cfi-sh-app-grid-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-xs, 0.25rem);\n border-radius: var(--cfi-radius-md, 0.375rem);\n color: var(--cfi-color-gray-700, #374151);\n text-decoration: none;\n cursor: pointer;\n transition: background 100ms;\n font-family: inherit;\n}\n.cfi-sh-app-grid-item:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-app-grid-item-active {\n background: var(--cfi-color-primary-50, #fff7ed);\n color: var(--cfi-color-primary-700, #c2410c);\n}\n.cfi-sh-app-grid-item-active:hover {\n background: var(--cfi-color-primary-100, #ffedd5);\n}\n.cfi-sh-app-grid-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n}\n.cfi-sh-app-grid-label {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-align: center;\n line-height: 1.35;\n max-width: 80px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n white-space: normal;\n overflow: hidden;\n min-height: 2.7em;\n}\n.cfi-sh-user-menu {\n position: relative;\n}\n.cfi-sh-avatar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n background: var(--cfi-color-primary-600, #ea580c);\n border: none;\n border-radius: 50%;\n cursor: pointer;\n transition: opacity 150ms;\n}\n.cfi-sh-avatar-btn:hover {\n opacity: 0.85;\n}\n.cfi-sh-avatar-img {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n object-fit: cover;\n}\n.cfi-sh-avatar-initials {\n color: white;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-weight: 600;\n font-family: inherit;\n}\n.cfi-sh-user-dropdown {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n min-width: 200px;\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n}\n.cfi-sh-user-header {\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n display: flex;\n flex-direction: column;\n}\n.cfi-sh-user-name {\n font-weight: 500;\n color: var(--cfi-color-gray-900, #111827);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n}\n.cfi-sh-user-email {\n color: var(--cfi-color-gray-500, #6b7280);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n}\n.cfi-sh-divider {\n height: 1px;\n background: var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-menu-item {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n width: 100%;\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n background: none;\n border: none;\n color: var(--cfi-color-gray-700, #374151);\n cursor: pointer;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-family: inherit;\n transition: background 100ms;\n}\n.cfi-sh-menu-item:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-menu-item:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.cfi-sh-locale-switcher {\n position: relative;\n}\n.cfi-sh-locale-btn {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n height: 32px;\n padding: 0 var(--cfi-spacing-sm, 0.5rem);\n background: transparent;\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-md, 0.375rem);\n color: var(--cfi-color-gray-700, #374151);\n cursor: pointer;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-weight: 600;\n font-family: inherit;\n transition: background 100ms;\n}\n.cfi-sh-locale-btn:hover:not(:disabled) {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-locale-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.cfi-sh-locale-label {\n letter-spacing: 0.02em;\n}\n.cfi-sh-locale-dropdown {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n min-width: 180px;\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n padding: var(--cfi-spacing-xs, 0.25rem) 0;\n}\n.cfi-sh-locale-dropdown .cfi-sh-menu-item {\n justify-content: space-between;\n}\n.cfi-sh-locale-item-active {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-locale-item-label {\n flex: 1;\n text-align: left;\n}\n.cfi-sh-locale-item-code {\n color: var(--cfi-color-gray-400, #9ca3af);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-weight: 600;\n letter-spacing: 0.02em;\n}\n.cfi-sh-locale-row {\n justify-content: flex-start;\n}\n.cfi-sh-locale-row-label {\n flex: 1;\n text-align: left;\n}\n.cfi-sh-locale-row-current {\n color: var(--cfi-color-gray-500, #6b7280);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n margin-right: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-locale-chevron {\n transition: transform 150ms ease;\n flex-shrink: 0;\n}\n.cfi-sh-locale-chevron-open {\n transform: rotate(180deg);\n}\n.cfi-sh-locale-sublist {\n border-top: 1px solid var(--cfi-color-gray-100, #f3f4f6);\n background: var(--cfi-color-gray-50, #f9fafb);\n}\n.cfi-sh-locale-sub-item {\n padding-left: calc(var(--cfi-spacing-md, 1rem) + var(--cfi-spacing-md, 1rem));\n justify-content: space-between;\n}\n.cfi-sh-tenant-static {\n cursor: default;\n pointer-events: none;\n}\n.cfi-sh-tenant-check {\n color: var(--cfi-color-violet-600, #7c3aed);\n}\n.cfi-sh-notif {\n position: relative;\n}\n.cfi-sh-notif-dropdown {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n width: 360px;\n max-height: 480px;\n display: flex;\n flex-direction: column;\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n overflow: hidden;\n}\n.cfi-sh-notif-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n flex-shrink: 0;\n}\n.cfi-sh-notif-title {\n font-weight: 600;\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-notif-mark-all {\n background: none;\n border: none;\n color: var(--cfi-color-primary-600, #ea580c);\n cursor: pointer;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-family: inherit;\n padding: 0;\n}\n.cfi-sh-notif-mark-all:hover {\n text-decoration: underline;\n}\n.cfi-sh-notif-list {\n overflow-y: auto;\n flex: 1;\n}\n.cfi-sh-notif-empty {\n padding: var(--cfi-spacing-lg, 1.5rem) var(--cfi-spacing-md, 1rem);\n color: var(--cfi-color-gray-500, #6b7280);\n text-align: center;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n}\n.cfi-sh-notif-item {\n display: flex;\n align-items: flex-start;\n gap: var(--cfi-spacing-sm, 0.5rem);\n width: 100%;\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n background: none;\n border: none;\n border-bottom: 1px solid var(--cfi-color-gray-100, #f3f4f6);\n text-align: left;\n cursor: pointer;\n font-family: inherit;\n transition: background 100ms;\n}\n.cfi-sh-notif-item:hover {\n background: var(--cfi-color-gray-50, #f9fafb);\n}\n.cfi-sh-notif-item:last-child {\n border-bottom: none;\n}\n.cfi-sh-notif-dot {\n flex-shrink: 0;\n width: 8px;\n height: 8px;\n margin-top: 6px;\n background: var(--cfi-color-primary-600, #ea580c);\n border-radius: 50%;\n}\n.cfi-sh-notif-dot-placeholder {\n flex-shrink: 0;\n width: 8px;\n height: 8px;\n margin-top: 6px;\n}\n.cfi-sh-notif-content {\n flex: 1;\n min-width: 0;\n}\n.cfi-sh-notif-item-title {\n font-weight: 500;\n color: var(--cfi-color-gray-900, #111827);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n margin-bottom: 2px;\n}\n.cfi-sh-notif-item-unread .cfi-sh-notif-item-title {\n font-weight: 600;\n}\n.cfi-sh-notif-item-body {\n color: var(--cfi-color-gray-600, #4b5563);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.cfi-sh-notif-item-time {\n color: var(--cfi-color-gray-400, #9ca3af);\n font-size: 11px;\n margin-top: 4px;\n}\n.cfi-sh-about-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1100;\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n}\n.cfi-sh-about-card {\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);\n min-width: 360px;\n max-width: 500px;\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-about-header {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n padding: var(--cfi-spacing-md, 1rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-about-title {\n font-weight: 600;\n font-size: var(--cfi-font-size-lg, 1.125rem);\n flex: 1;\n}\n.cfi-sh-about-env {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n background: var(--cfi-color-gray-100, #f3f4f6);\n color: var(--cfi-color-gray-700, #374151);\n padding: 2px 8px;\n border-radius: var(--cfi-radius-sm, 0.25rem);\n font-weight: 600;\n}\n.cfi-sh-about-close {\n background: none;\n border: none;\n font-size: 1.5rem;\n line-height: 1;\n cursor: pointer;\n color: var(--cfi-color-gray-500, #6b7280);\n padding: 0 4px;\n font-family: inherit;\n}\n.cfi-sh-about-close:hover {\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-about-body {\n padding: var(--cfi-spacing-md, 1rem);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-md, 1rem);\n}\n.cfi-sh-about-section-title {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-weight: 600;\n color: var(--cfi-color-gray-500, #6b7280);\n margin-bottom: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-about-list {\n display: grid;\n grid-template-columns: auto 1fr;\n gap: var(--cfi-spacing-xs, 0.25rem) var(--cfi-spacing-md, 1rem);\n margin: 0;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n}\n.cfi-sh-about-list dt {\n color: var(--cfi-color-gray-600, #4b5563);\n font-weight: 500;\n}\n.cfi-sh-about-list dd {\n margin: 0;\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-about-list code {\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Consolas,\n monospace;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n background: var(--cfi-color-gray-100, #f3f4f6);\n padding: 1px 6px;\n border-radius: var(--cfi-radius-sm, 0.25rem);\n}\n.cfi-sh-about-date {\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-about-footer {\n display: flex;\n justify-content: flex-end;\n padding: var(--cfi-spacing-md, 1rem);\n border-top: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-about-copy {\n background: var(--cfi-color-gray-100, #f3f4f6);\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-900, #111827);\n padding: 6px 12px;\n border-radius: var(--cfi-radius-md, 0.375rem);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-weight: 500;\n cursor: pointer;\n font-family: inherit;\n transition: background 150ms;\n}\n.cfi-sh-about-copy:hover {\n background: var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1100;\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n}\n.cfi-sh-bug-card {\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);\n width: 480px;\n max-width: calc(100vw - 32px);\n color: var(--cfi-color-gray-900, #111827);\n display: flex;\n flex-direction: column;\n}\n.cfi-sh-bug-card-wide {\n width: min(1100px, calc(100vw - 64px));\n}\n.cfi-sh-bug-header {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n padding: var(--cfi-spacing-md, 1rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-title {\n font-weight: 600;\n font-size: var(--cfi-font-size-lg, 1.125rem);\n flex: 1;\n}\n.cfi-sh-bug-env {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n background: var(--cfi-color-gray-100, #f3f4f6);\n color: var(--cfi-color-gray-700, #374151);\n padding: 2px 8px;\n border-radius: var(--cfi-radius-sm, 0.25rem);\n font-weight: 600;\n}\n.cfi-sh-bug-close {\n background: none;\n border: none;\n font-size: 1.5rem;\n line-height: 1;\n cursor: pointer;\n color: var(--cfi-color-gray-500, #6b7280);\n padding: 0 4px;\n font-family: inherit;\n}\n.cfi-sh-bug-close:hover {\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-bug-body {\n padding: var(--cfi-spacing-md, 1rem);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 0.5rem);\n}\n.cfi-sh-bug-label {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-weight: 600;\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-input,\n.cfi-sh-bug-textarea {\n font-family: inherit;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n color: var(--cfi-color-gray-900, #111827);\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-md, 0.375rem);\n padding: 8px 10px;\n outline: none;\n}\n.cfi-sh-bug-input:focus,\n.cfi-sh-bug-textarea:focus {\n border-color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-textarea {\n resize: vertical;\n min-height: 72px;\n}\n.cfi-sh-bug-shot {\n display: flex;\n align-items: flex-start;\n gap: var(--cfi-spacing-sm, 0.5rem);\n flex-wrap: wrap;\n padding-top: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-thumb {\n max-width: 200px;\n max-height: 120px;\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-sm, 0.25rem);\n display: block;\n}\n.cfi-sh-bug-shot-actions {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-meta {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--cfi-spacing-sm, 0.5rem);\n}\n.cfi-sh-bug-modes {\n display: flex;\n gap: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-hint {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-canvas-wrap {\n overflow: auto;\n max-height: 65vh;\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-sm, 0.25rem);\n background: var(--cfi-color-gray-100, #f3f4f6);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.cfi-sh-bug-canvas {\n max-width: 100%;\n max-height: 65vh;\n cursor: crosshair;\n touch-action: none;\n display: block;\n}\n.cfi-sh-bug-footer {\n display: flex;\n justify-content: flex-end;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n padding: var(--cfi-spacing-md, 1rem);\n border-top: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-btn {\n background: var(--cfi-color-gray-100, #f3f4f6);\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-900, #111827);\n padding: 6px 12px;\n border-radius: var(--cfi-radius-md, 0.375rem);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-weight: 500;\n cursor: pointer;\n font-family: inherit;\n transition: background 150ms;\n}\n.cfi-sh-bug-btn:hover {\n background: var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-btn:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.cfi-sh-bug-btn-primary {\n background: var(--cfi-color-gray-900, #111827);\n border-color: var(--cfi-color-gray-900, #111827);\n color: white;\n}\n.cfi-sh-bug-btn-primary:hover:not(:disabled) {\n background: var(--cfi-color-gray-700, #374151);\n}\n.cfi-sh-bug-btn-active {\n background: var(--cfi-color-gray-900, #111827);\n border-color: var(--cfi-color-gray-900, #111827);\n color: white;\n}\n.cfi-sh-bug-error {\n color: var(--cfi-color-red-600, #dc2626);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n margin-right: auto;\n}\n.cfi-sh-bug-success {\n color: var(--cfi-color-green-600, #16a34a);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-weight: 500;\n}\n");
|
|
27
|
+
styleInject(".cfi-sh-header {\n display: flex;\n align-items: center;\n height: var(--cfi-shell-header-height, 48px);\n padding: 0 var(--cfi-spacing-md, 1rem);\n background: white;\n color: var(--cfi-color-gray-900, #111827);\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n position: relative;\n z-index: 1000;\n}\n.cfi-sh-left {\n display: flex;\n align-items: center;\n flex: 1;\n gap: var(--cfi-spacing-md, 1rem);\n overflow: hidden;\n}\n.cfi-sh-app-brand {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n flex-shrink: 0;\n}\n.cfi-sh-app-badge {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n color: white;\n font-size: 14px;\n font-weight: 700;\n font-family: inherit;\n border-radius: var(--cfi-radius-md, 0.375rem);\n flex-shrink: 0;\n}\n.cfi-sh-app-title {\n font-weight: 600;\n font-size: var(--cfi-font-size-base, 1rem);\n color: var(--cfi-color-gray-900, #111827);\n white-space: nowrap;\n}\n.cfi-sh-suite-logo {\n height: 22px;\n width: auto;\n display: block;\n}\n.cfi-sh-right {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n flex-shrink: 0;\n}\n.cfi-sh-icon-btn {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: transparent;\n border: none;\n border-radius: 50%;\n color: var(--cfi-color-gray-600, #4b5563);\n cursor: pointer;\n transition: background 150ms;\n}\n.cfi-sh-icon-btn:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--cfi-color-error, #ef4444);\n color: white;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n border-radius: 99px;\n}\n.cfi-sh-app-switcher {\n position: relative;\n}\n.cfi-sh-app-grid {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: var(--cfi-spacing-xs, 0.25rem);\n padding: var(--cfi-spacing-sm, 0.5rem);\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n min-width: 280px;\n}\n.cfi-sh-app-grid-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-xs, 0.25rem);\n border-radius: var(--cfi-radius-md, 0.375rem);\n color: var(--cfi-color-gray-700, #374151);\n text-decoration: none;\n cursor: pointer;\n transition: background 100ms;\n font-family: inherit;\n}\n.cfi-sh-app-grid-item:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-app-grid-item-active {\n background: var(--cfi-color-primary-50, #fff7ed);\n color: var(--cfi-color-primary-700, #c2410c);\n}\n.cfi-sh-app-grid-item-active:hover {\n background: var(--cfi-color-primary-100, #ffedd5);\n}\n.cfi-sh-app-grid-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n}\n.cfi-sh-app-grid-label {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-align: center;\n line-height: 1.35;\n max-width: 80px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n white-space: normal;\n overflow: hidden;\n min-height: 2.7em;\n}\n.cfi-sh-user-menu {\n position: relative;\n}\n.cfi-sh-avatar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n background: var(--cfi-color-primary-600, #ea580c);\n border: none;\n border-radius: 50%;\n cursor: pointer;\n transition: opacity 150ms;\n}\n.cfi-sh-avatar-btn:hover {\n opacity: 0.85;\n}\n.cfi-sh-avatar-img {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n object-fit: cover;\n}\n.cfi-sh-avatar-initials {\n color: white;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-weight: 600;\n font-family: inherit;\n}\n.cfi-sh-user-dropdown {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n min-width: 200px;\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n}\n.cfi-sh-user-header {\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n display: flex;\n flex-direction: column;\n}\n.cfi-sh-user-name {\n font-weight: 500;\n color: var(--cfi-color-gray-900, #111827);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n}\n.cfi-sh-user-email {\n color: var(--cfi-color-gray-500, #6b7280);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n}\n.cfi-sh-divider {\n height: 1px;\n background: var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-menu-item {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n width: 100%;\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n background: none;\n border: none;\n color: var(--cfi-color-gray-700, #374151);\n cursor: pointer;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-family: inherit;\n transition: background 100ms;\n}\n.cfi-sh-menu-item:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-menu-item:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.cfi-sh-locale-switcher {\n position: relative;\n}\n.cfi-sh-locale-btn {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n height: 32px;\n padding: 0 var(--cfi-spacing-sm, 0.5rem);\n background: transparent;\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-md, 0.375rem);\n color: var(--cfi-color-gray-700, #374151);\n cursor: pointer;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-weight: 600;\n font-family: inherit;\n transition: background 100ms;\n}\n.cfi-sh-locale-btn:hover:not(:disabled) {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-locale-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.cfi-sh-locale-label {\n letter-spacing: 0.02em;\n}\n.cfi-sh-locale-dropdown {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n min-width: 180px;\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n padding: var(--cfi-spacing-xs, 0.25rem) 0;\n}\n.cfi-sh-locale-dropdown .cfi-sh-menu-item {\n justify-content: space-between;\n}\n.cfi-sh-locale-item-active {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-locale-item-label {\n flex: 1;\n text-align: left;\n}\n.cfi-sh-locale-item-code {\n color: var(--cfi-color-gray-400, #9ca3af);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-weight: 600;\n letter-spacing: 0.02em;\n}\n.cfi-sh-locale-row {\n justify-content: flex-start;\n}\n.cfi-sh-locale-row-label {\n flex: 1;\n text-align: left;\n}\n.cfi-sh-locale-row-current {\n color: var(--cfi-color-gray-500, #6b7280);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n margin-right: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-locale-chevron {\n transition: transform 150ms ease;\n flex-shrink: 0;\n}\n.cfi-sh-locale-chevron-open {\n transform: rotate(180deg);\n}\n.cfi-sh-locale-sublist {\n border-top: 1px solid var(--cfi-color-gray-100, #f3f4f6);\n background: var(--cfi-color-gray-50, #f9fafb);\n}\n.cfi-sh-locale-sub-item {\n padding-left: calc(var(--cfi-spacing-md, 1rem) + var(--cfi-spacing-md, 1rem));\n justify-content: space-between;\n}\n.cfi-sh-tenant-static {\n cursor: default;\n pointer-events: none;\n}\n.cfi-sh-tenant-check {\n color: var(--cfi-color-violet-600, #7c3aed);\n}\n.cfi-sh-notif {\n position: relative;\n}\n.cfi-sh-notif-dropdown {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n width: 360px;\n max-height: 480px;\n display: flex;\n flex-direction: column;\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n overflow: hidden;\n}\n.cfi-sh-notif-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n flex-shrink: 0;\n}\n.cfi-sh-notif-title {\n font-weight: 600;\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-notif-mark-all {\n background: none;\n border: none;\n color: var(--cfi-color-primary-600, #ea580c);\n cursor: pointer;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-family: inherit;\n padding: 0;\n}\n.cfi-sh-notif-mark-all:hover {\n text-decoration: underline;\n}\n.cfi-sh-notif-list {\n overflow-y: auto;\n flex: 1;\n}\n.cfi-sh-notif-empty {\n padding: var(--cfi-spacing-lg, 1.5rem) var(--cfi-spacing-md, 1rem);\n color: var(--cfi-color-gray-500, #6b7280);\n text-align: center;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n}\n.cfi-sh-notif-item {\n display: flex;\n align-items: flex-start;\n gap: var(--cfi-spacing-sm, 0.5rem);\n width: 100%;\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n background: none;\n border: none;\n border-bottom: 1px solid var(--cfi-color-gray-100, #f3f4f6);\n text-align: left;\n cursor: pointer;\n font-family: inherit;\n transition: background 100ms;\n}\n.cfi-sh-notif-item:hover {\n background: var(--cfi-color-gray-50, #f9fafb);\n}\n.cfi-sh-notif-item:last-child {\n border-bottom: none;\n}\n.cfi-sh-notif-dot {\n flex-shrink: 0;\n width: 8px;\n height: 8px;\n margin-top: 6px;\n background: var(--cfi-color-primary-600, #ea580c);\n border-radius: 50%;\n}\n.cfi-sh-notif-dot-placeholder {\n flex-shrink: 0;\n width: 8px;\n height: 8px;\n margin-top: 6px;\n}\n.cfi-sh-notif-content {\n flex: 1;\n min-width: 0;\n}\n.cfi-sh-notif-item-title {\n font-weight: 500;\n color: var(--cfi-color-gray-900, #111827);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n margin-bottom: 2px;\n}\n.cfi-sh-notif-item-unread .cfi-sh-notif-item-title {\n font-weight: 600;\n}\n.cfi-sh-notif-item-body {\n color: var(--cfi-color-gray-600, #4b5563);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.cfi-sh-notif-item-time {\n color: var(--cfi-color-gray-400, #9ca3af);\n font-size: 11px;\n margin-top: 4px;\n}\n.cfi-sh-about-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1100;\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n}\n.cfi-sh-about-card {\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);\n min-width: 360px;\n max-width: 500px;\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-about-header {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n padding: var(--cfi-spacing-md, 1rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-about-title {\n font-weight: 600;\n font-size: var(--cfi-font-size-lg, 1.125rem);\n flex: 1;\n}\n.cfi-sh-about-env {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n background: var(--cfi-color-gray-100, #f3f4f6);\n color: var(--cfi-color-gray-700, #374151);\n padding: 2px 8px;\n border-radius: var(--cfi-radius-sm, 0.25rem);\n font-weight: 600;\n}\n.cfi-sh-about-close {\n background: none;\n border: none;\n font-size: 1.5rem;\n line-height: 1;\n cursor: pointer;\n color: var(--cfi-color-gray-500, #6b7280);\n padding: 0 4px;\n font-family: inherit;\n}\n.cfi-sh-about-close:hover {\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-about-body {\n padding: var(--cfi-spacing-md, 1rem);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-md, 1rem);\n}\n.cfi-sh-about-section-title {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-weight: 600;\n color: var(--cfi-color-gray-500, #6b7280);\n margin-bottom: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-about-list {\n display: grid;\n grid-template-columns: auto 1fr;\n gap: var(--cfi-spacing-xs, 0.25rem) var(--cfi-spacing-md, 1rem);\n margin: 0;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n}\n.cfi-sh-about-list dt {\n color: var(--cfi-color-gray-600, #4b5563);\n font-weight: 500;\n}\n.cfi-sh-about-list dd {\n margin: 0;\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-about-list code {\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Consolas,\n monospace;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n background: var(--cfi-color-gray-100, #f3f4f6);\n padding: 1px 6px;\n border-radius: var(--cfi-radius-sm, 0.25rem);\n}\n.cfi-sh-about-date {\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-about-footer {\n display: flex;\n justify-content: flex-end;\n padding: var(--cfi-spacing-md, 1rem);\n border-top: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-about-copy {\n background: var(--cfi-color-gray-100, #f3f4f6);\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-900, #111827);\n padding: 6px 12px;\n border-radius: var(--cfi-radius-md, 0.375rem);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-weight: 500;\n cursor: pointer;\n font-family: inherit;\n transition: background 150ms;\n}\n.cfi-sh-about-copy:hover {\n background: var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1100;\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n}\n.cfi-sh-bug-card {\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);\n width: 480px;\n max-width: calc(100vw - 32px);\n color: var(--cfi-color-gray-900, #111827);\n display: flex;\n flex-direction: column;\n}\n.cfi-sh-bug-card-wide {\n width: min(1100px, calc(100vw - 64px));\n}\n.cfi-sh-bug-header {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n padding: var(--cfi-spacing-md, 1rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-title {\n font-weight: 600;\n font-size: var(--cfi-font-size-lg, 1.125rem);\n flex: 1;\n}\n.cfi-sh-bug-env {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n background: var(--cfi-color-gray-100, #f3f4f6);\n color: var(--cfi-color-gray-700, #374151);\n padding: 2px 8px;\n border-radius: var(--cfi-radius-sm, 0.25rem);\n font-weight: 600;\n}\n.cfi-sh-bug-close {\n background: none;\n border: none;\n font-size: 1.5rem;\n line-height: 1;\n cursor: pointer;\n color: var(--cfi-color-gray-500, #6b7280);\n padding: 0 4px;\n font-family: inherit;\n}\n.cfi-sh-bug-close:hover {\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-bug-body {\n padding: var(--cfi-spacing-md, 1rem);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 0.5rem);\n}\n.cfi-sh-bug-label {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-weight: 600;\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-input,\n.cfi-sh-bug-textarea {\n font-family: inherit;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n color: var(--cfi-color-gray-900, #111827);\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-md, 0.375rem);\n padding: 8px 10px;\n outline: none;\n}\n.cfi-sh-bug-input:focus,\n.cfi-sh-bug-textarea:focus {\n border-color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-textarea {\n resize: vertical;\n min-height: 72px;\n}\n.cfi-sh-bug-shot {\n display: flex;\n align-items: flex-start;\n gap: var(--cfi-spacing-sm, 0.5rem);\n flex-wrap: wrap;\n padding-top: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-thumb {\n max-width: 200px;\n max-height: 120px;\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-sm, 0.25rem);\n display: block;\n}\n.cfi-sh-bug-shot-actions {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-meta {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--cfi-spacing-sm, 0.5rem);\n}\n.cfi-sh-bug-modes {\n display: flex;\n gap: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-hint {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-canvas-wrap {\n overflow: auto;\n max-height: 65vh;\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-sm, 0.25rem);\n background: var(--cfi-color-gray-100, #f3f4f6);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.cfi-sh-bug-canvas {\n max-width: 100%;\n max-height: 65vh;\n cursor: crosshair;\n touch-action: none;\n display: block;\n}\n.cfi-sh-bug-footer {\n display: flex;\n justify-content: flex-end;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n padding: var(--cfi-spacing-md, 1rem);\n border-top: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-btn {\n background: var(--cfi-color-gray-100, #f3f4f6);\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-900, #111827);\n padding: 6px 12px;\n border-radius: var(--cfi-radius-md, 0.375rem);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-weight: 500;\n cursor: pointer;\n font-family: inherit;\n transition: background 150ms;\n}\n.cfi-sh-bug-btn:hover {\n background: var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-btn:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.cfi-sh-bug-btn-primary {\n background: var(--cfi-color-gray-900, #111827);\n border-color: var(--cfi-color-gray-900, #111827);\n color: white;\n}\n.cfi-sh-bug-btn-primary:hover:not(:disabled) {\n background: var(--cfi-color-gray-700, #374151);\n}\n.cfi-sh-bug-btn-active {\n background: var(--cfi-color-gray-900, #111827);\n border-color: var(--cfi-color-gray-900, #111827);\n color: white;\n}\n.cfi-sh-bug-error {\n color: var(--cfi-color-red-600, #dc2626);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n margin-right: auto;\n}\n.cfi-sh-bug-success {\n color: var(--cfi-color-green-600, #16a34a);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-weight: 500;\n}\n.cfi-sh-bug-issues-link {\n color: var(--cfi-color-gray-600, #4b5563);\n text-decoration: underline;\n}\n.cfi-sh-bug-issues-link:hover {\n color: var(--cfi-color-gray-900, #111827);\n}\n");
|
|
28
28
|
|
|
29
29
|
// src/appCatalog.ts
|
|
30
30
|
var appCatalog = [
|
|
@@ -604,6 +604,9 @@ function UserMenu({
|
|
|
604
604
|
] });
|
|
605
605
|
}
|
|
606
606
|
|
|
607
|
+
// src/ShellHeader.tsx
|
|
608
|
+
import { useRef as useRef6, useState as useState7 } from "react";
|
|
609
|
+
|
|
607
610
|
// src/AboutModal.tsx
|
|
608
611
|
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
609
612
|
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
@@ -872,7 +875,7 @@ function normalizeRect(x0, y0, x1, y1) {
|
|
|
872
875
|
h: Math.abs(y1 - y0)
|
|
873
876
|
};
|
|
874
877
|
}
|
|
875
|
-
function BugReportModal({ config, onClose }) {
|
|
878
|
+
function BugReportModal({ config, initialScreenshot, onClose }) {
|
|
876
879
|
const [view, setView] = useState6("form");
|
|
877
880
|
const [title, setTitle] = useState6("");
|
|
878
881
|
const [description, setDescription] = useState6("");
|
|
@@ -886,6 +889,21 @@ function BugReportModal({ config, onClose }) {
|
|
|
886
889
|
const displayCanvasRef = useRef4(null);
|
|
887
890
|
const dragStartRef = useRef4(null);
|
|
888
891
|
const [mode, setMode] = useState6("crop");
|
|
892
|
+
const initialLoadedRef = useRef4(false);
|
|
893
|
+
useEffect6(() => {
|
|
894
|
+
if (!initialScreenshot || initialLoadedRef.current) return;
|
|
895
|
+
initialLoadedRef.current = true;
|
|
896
|
+
let cancelled = false;
|
|
897
|
+
void blobToCanvas(initialScreenshot).then((image) => {
|
|
898
|
+
if (cancelled) return;
|
|
899
|
+
originalRef.current = cloneCanvas(image);
|
|
900
|
+
workCanvasRef.current = image;
|
|
901
|
+
setView("editor");
|
|
902
|
+
});
|
|
903
|
+
return () => {
|
|
904
|
+
cancelled = true;
|
|
905
|
+
};
|
|
906
|
+
}, [initialScreenshot]);
|
|
889
907
|
const closeUnlessBusy = useCallback(() => {
|
|
890
908
|
if (submitState === "submitting" || capturing) return;
|
|
891
909
|
if (screenshot) URL.revokeObjectURL(screenshot.previewUrl);
|
|
@@ -1074,10 +1092,10 @@ function BugReportModal({ config, onClose }) {
|
|
|
1074
1092
|
className: "cfi-sh-bug-overlay",
|
|
1075
1093
|
role: "dialog",
|
|
1076
1094
|
"aria-modal": "true",
|
|
1077
|
-
"aria-label": "Report
|
|
1095
|
+
"aria-label": "Report an issue",
|
|
1078
1096
|
children: /* @__PURE__ */ jsxs6("div", { className: `cfi-sh-bug-card${view === "editor" ? " cfi-sh-bug-card-wide" : ""}`, children: [
|
|
1079
1097
|
/* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-header", children: [
|
|
1080
|
-
/* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-title", children: "Report
|
|
1098
|
+
/* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-title", children: "Report an issue" }),
|
|
1081
1099
|
/* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-env", children: config.context.environment }),
|
|
1082
1100
|
/* @__PURE__ */ jsx6("button", { className: "cfi-sh-bug-close", type: "button", onClick: closeUnlessBusy, "aria-label": "Close", children: "\xD7" })
|
|
1083
1101
|
] }),
|
|
@@ -1156,11 +1174,41 @@ function BugReportModal({ config, onClose }) {
|
|
|
1156
1174
|
] }) : /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: handleCapture, children: "Capture screenshot" }),
|
|
1157
1175
|
captureError && /* @__PURE__ */ jsx6("div", { className: "cfi-sh-bug-error", children: captureError })
|
|
1158
1176
|
] }),
|
|
1159
|
-
/* @__PURE__ */
|
|
1177
|
+
/* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-meta", children: [
|
|
1178
|
+
"Includes: URL, app version, recent console errors and failed requests.",
|
|
1179
|
+
config.context.issuesUrl && /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
1180
|
+
" ",
|
|
1181
|
+
/* @__PURE__ */ jsx6(
|
|
1182
|
+
"a",
|
|
1183
|
+
{
|
|
1184
|
+
className: "cfi-sh-bug-issues-link",
|
|
1185
|
+
href: config.context.issuesUrl,
|
|
1186
|
+
target: "_blank",
|
|
1187
|
+
rel: "noreferrer",
|
|
1188
|
+
children: "View known issues"
|
|
1189
|
+
}
|
|
1190
|
+
)
|
|
1191
|
+
] })
|
|
1192
|
+
] })
|
|
1160
1193
|
] }),
|
|
1161
1194
|
view === "form" && /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-footer", children: [
|
|
1162
1195
|
submitState === "error" && submitError && /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-error", children: submitError }),
|
|
1163
|
-
submitState === "success" ? /* @__PURE__ */
|
|
1196
|
+
submitState === "success" ? /* @__PURE__ */ jsxs6("span", { className: "cfi-sh-bug-success", children: [
|
|
1197
|
+
"Report submitted \u2014 thank you!",
|
|
1198
|
+
config.context.issuesUrl && /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
1199
|
+
" ",
|
|
1200
|
+
/* @__PURE__ */ jsx6(
|
|
1201
|
+
"a",
|
|
1202
|
+
{
|
|
1203
|
+
className: "cfi-sh-bug-issues-link",
|
|
1204
|
+
href: config.context.issuesUrl,
|
|
1205
|
+
target: "_blank",
|
|
1206
|
+
rel: "noreferrer",
|
|
1207
|
+
children: "View it on the issues page"
|
|
1208
|
+
}
|
|
1209
|
+
)
|
|
1210
|
+
] })
|
|
1211
|
+
] }) : /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
1164
1212
|
/* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: closeUnlessBusy, children: "Cancel" }),
|
|
1165
1213
|
/* @__PURE__ */ jsx6(
|
|
1166
1214
|
"button",
|
|
@@ -1199,9 +1247,10 @@ function cloneCanvas(source) {
|
|
|
1199
1247
|
}
|
|
1200
1248
|
|
|
1201
1249
|
// src/useBugReportShortcut.ts
|
|
1202
|
-
import { useEffect as useEffect7,
|
|
1203
|
-
function useBugReportShortcut(enabled) {
|
|
1204
|
-
const
|
|
1250
|
+
import { useEffect as useEffect7, useRef as useRef5 } from "react";
|
|
1251
|
+
function useBugReportShortcut(enabled, onShortcut) {
|
|
1252
|
+
const handlerRef = useRef5(onShortcut);
|
|
1253
|
+
handlerRef.current = onShortcut;
|
|
1205
1254
|
useEffect7(() => {
|
|
1206
1255
|
if (!enabled) return;
|
|
1207
1256
|
function handleKeyDown(e) {
|
|
@@ -1214,12 +1263,11 @@ function useBugReportShortcut(enabled) {
|
|
|
1214
1263
|
if (tag === "INPUT" || tag === "TEXTAREA" || target.isContentEditable) return;
|
|
1215
1264
|
}
|
|
1216
1265
|
e.preventDefault();
|
|
1217
|
-
|
|
1266
|
+
handlerRef.current();
|
|
1218
1267
|
}
|
|
1219
1268
|
document.addEventListener("keydown", handleKeyDown);
|
|
1220
1269
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1221
1270
|
}, [enabled]);
|
|
1222
|
-
return [isOpen, setIsOpen];
|
|
1223
1271
|
}
|
|
1224
1272
|
|
|
1225
1273
|
// src/assets/campfire-wordmark.png
|
|
@@ -1257,7 +1305,21 @@ function ShellHeader({
|
|
|
1257
1305
|
}) {
|
|
1258
1306
|
const currentApp = appCatalog.find((a) => a.id === appId);
|
|
1259
1307
|
const [aboutOpen, setAboutOpen] = useAboutShortcut(about !== void 0);
|
|
1260
|
-
const [bugOpen, setBugOpen] =
|
|
1308
|
+
const [bugOpen, setBugOpen] = useState7(false);
|
|
1309
|
+
const [bugShot, setBugShot] = useState7(null);
|
|
1310
|
+
const bugCaptureBusy = useRef6(false);
|
|
1311
|
+
useBugReportShortcut(bugReport !== void 0, () => {
|
|
1312
|
+
if (bugOpen) {
|
|
1313
|
+
setBugOpen(false);
|
|
1314
|
+
return;
|
|
1315
|
+
}
|
|
1316
|
+
if (bugCaptureBusy.current) return;
|
|
1317
|
+
bugCaptureBusy.current = true;
|
|
1318
|
+
captureTabScreenshot().then((shot) => setBugShot(shot)).catch(() => setBugShot(null)).finally(() => {
|
|
1319
|
+
bugCaptureBusy.current = false;
|
|
1320
|
+
setBugOpen(true);
|
|
1321
|
+
});
|
|
1322
|
+
});
|
|
1261
1323
|
const brandStyle = brandWidth ? { width: `${brandWidth}px`, flexShrink: 0, boxSizing: "border-box" } : void 0;
|
|
1262
1324
|
return /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
1263
1325
|
/* @__PURE__ */ jsxs7("header", { className: "cfi-sh-header", children: [
|
|
@@ -1302,17 +1364,27 @@ function ShellHeader({
|
|
|
1302
1364
|
] })
|
|
1303
1365
|
] }),
|
|
1304
1366
|
about && aboutOpen && /* @__PURE__ */ jsx7(AboutModal, { about, onClose: () => setAboutOpen(false) }),
|
|
1305
|
-
bugReport && bugOpen && /* @__PURE__ */ jsx7(
|
|
1367
|
+
bugReport && bugOpen && /* @__PURE__ */ jsx7(
|
|
1368
|
+
BugReportModal,
|
|
1369
|
+
{
|
|
1370
|
+
config: bugReport,
|
|
1371
|
+
initialScreenshot: bugShot,
|
|
1372
|
+
onClose: () => {
|
|
1373
|
+
setBugOpen(false);
|
|
1374
|
+
setBugShot(null);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
)
|
|
1306
1378
|
] });
|
|
1307
1379
|
}
|
|
1308
1380
|
|
|
1309
1381
|
// src/LocaleSwitcher.tsx
|
|
1310
|
-
import { useState as useState8, useRef as
|
|
1382
|
+
import { useState as useState8, useRef as useRef7, useEffect as useEffect8 } from "react";
|
|
1311
1383
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1312
1384
|
function LocaleSwitcher({ currentLocale, supportedLocales, onLocaleChange }) {
|
|
1313
1385
|
const [open, setOpen] = useState8(false);
|
|
1314
1386
|
const [updating, setUpdating] = useState8(false);
|
|
1315
|
-
const ref =
|
|
1387
|
+
const ref = useRef7(null);
|
|
1316
1388
|
useEffect8(() => {
|
|
1317
1389
|
function handleClickOutside(e) {
|
|
1318
1390
|
if (ref.current && !ref.current.contains(e.target)) {
|