@flamingo-stack/openframe-frontend-core 0.0.668 → 0.0.669-snapshot.20260927145656
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-B5UP36KY.cjs → chunk-22E6CSIS.cjs} +12 -12
- package/dist/{chunk-B5UP36KY.cjs.map → chunk-22E6CSIS.cjs.map} +1 -1
- package/dist/{chunk-6KJV6GAJ.js → chunk-5IP7FYUN.js} +4 -4
- package/dist/{chunk-GF6WJ4MG.js → chunk-5Q6BE56A.js} +6 -6
- package/dist/{chunk-NZD2WTJ2.cjs → chunk-5ZVYPAFQ.cjs} +3 -3
- package/dist/{chunk-NZD2WTJ2.cjs.map → chunk-5ZVYPAFQ.cjs.map} +1 -1
- package/dist/{chunk-Z3HUP4G7.cjs → chunk-635CAJ36.cjs} +32 -32
- package/dist/{chunk-Z3HUP4G7.cjs.map → chunk-635CAJ36.cjs.map} +1 -1
- package/dist/{chunk-GO63IT6K.js → chunk-6P335PRA.js} +5 -5
- package/dist/{chunk-5V3LERVC.js → chunk-6X66J23J.js} +4 -4
- package/dist/{chunk-6W4LUHMY.cjs → chunk-7VZZ5S5V.cjs} +206 -206
- package/dist/{chunk-6W4LUHMY.cjs.map → chunk-7VZZ5S5V.cjs.map} +1 -1
- package/dist/{chunk-EV2KJ4D2.cjs → chunk-7WK544AC.cjs} +7 -7
- package/dist/{chunk-EV2KJ4D2.cjs.map → chunk-7WK544AC.cjs.map} +1 -1
- package/dist/{chunk-FOH4MNOZ.js → chunk-C5CTLTKJ.js} +3 -3
- package/dist/{chunk-TFVUM6KK.cjs → chunk-CK4BZRVJ.cjs} +10 -10
- package/dist/{chunk-TFVUM6KK.cjs.map → chunk-CK4BZRVJ.cjs.map} +1 -1
- package/dist/{chunk-Z3GN3MIW.cjs → chunk-D2HYPVYQ.cjs} +81 -81
- package/dist/{chunk-Z3GN3MIW.cjs.map → chunk-D2HYPVYQ.cjs.map} +1 -1
- package/dist/{chunk-WVCDX7FE.cjs → chunk-DAMA3A5Z.cjs} +15 -15
- package/dist/{chunk-WVCDX7FE.cjs.map → chunk-DAMA3A5Z.cjs.map} +1 -1
- package/dist/{chunk-P6IJXAEE.js → chunk-DLJGCDHX.js} +2 -1
- package/dist/{chunk-P6IJXAEE.js.map → chunk-DLJGCDHX.js.map} +1 -1
- package/dist/{chunk-IJPV7OMA.js → chunk-EHB5LETA.js} +591 -466
- package/dist/chunk-EHB5LETA.js.map +1 -0
- package/dist/{chunk-CFUUVLYQ.cjs → chunk-GXKKWFZR.cjs} +33 -33
- package/dist/{chunk-CFUUVLYQ.cjs.map → chunk-GXKKWFZR.cjs.map} +1 -1
- package/dist/{chunk-IZ6F7LOE.js → chunk-IHOSMLBC.js} +3 -3
- package/dist/{chunk-DK3BHDUZ.js → chunk-INIITSC3.js} +3 -3
- package/dist/{chunk-ZHRIFUN3.cjs → chunk-L5TTJXLU.cjs} +28 -28
- package/dist/{chunk-ZHRIFUN3.cjs.map → chunk-L5TTJXLU.cjs.map} +1 -1
- package/dist/{chunk-7UW2BBFI.cjs → chunk-LGIBMKRM.cjs} +59 -59
- package/dist/{chunk-7UW2BBFI.cjs.map → chunk-LGIBMKRM.cjs.map} +1 -1
- package/dist/{chunk-IBQT4RTS.js → chunk-O3PPPILJ.js} +3 -3
- package/dist/{chunk-CWK4QHVF.js → chunk-OABFQXAI.js} +3 -3
- package/dist/{chunk-VEQWH5KH.cjs → chunk-OHLOPLOM.cjs} +30 -30
- package/dist/{chunk-VEQWH5KH.cjs.map → chunk-OHLOPLOM.cjs.map} +1 -1
- package/dist/{chunk-PHLBRU5P.js → chunk-P7FKI2UW.js} +3 -3
- package/dist/{chunk-YH3BUB4W.js → chunk-PTZKMV35.js} +5 -5
- package/dist/{chunk-E5HUHKHH.js → chunk-QGHMHW7R.js} +7 -7
- package/dist/{chunk-VJ4XBTR5.cjs → chunk-QH6PMRGF.cjs} +22 -22
- package/dist/{chunk-VJ4XBTR5.cjs.map → chunk-QH6PMRGF.cjs.map} +1 -1
- package/dist/{chunk-37NYF4W2.cjs → chunk-QRUW4UXB.cjs} +2 -1
- package/dist/chunk-QRUW4UXB.cjs.map +1 -0
- package/dist/{chunk-LJOELK7P.js → chunk-RG7XYHN7.js} +2 -2
- package/dist/{chunk-Y7SFGCF4.cjs → chunk-RRJ6EL63.cjs} +20 -20
- package/dist/{chunk-Y7SFGCF4.cjs.map → chunk-RRJ6EL63.cjs.map} +1 -1
- package/dist/{chunk-FJNX67W2.cjs → chunk-SEW23M5X.cjs} +5 -5
- package/dist/{chunk-FJNX67W2.cjs.map → chunk-SEW23M5X.cjs.map} +1 -1
- package/dist/{chunk-K4WYWTQV.cjs → chunk-TLMPNPYS.cjs} +6 -6
- package/dist/{chunk-K4WYWTQV.cjs.map → chunk-TLMPNPYS.cjs.map} +1 -1
- package/dist/{chunk-SHGMDYCR.js → chunk-VEAA5C5X.js} +2 -2
- package/dist/{chunk-5CC33IJ7.js → chunk-VXRWR56S.js} +6 -6
- package/dist/{chunk-NNYND3I4.js → chunk-XUHLWFEM.js} +3 -3
- package/dist/{chunk-QHL4GYYY.cjs → chunk-ZYFDPD73.cjs} +577 -452
- package/dist/chunk-ZYFDPD73.cjs.map +1 -0
- package/dist/components/case-studies/index.cjs +16 -16
- package/dist/components/case-studies/index.js +4 -4
- package/dist/components/chat/entity-cards/design-doc-card.d.ts +23 -0
- package/dist/components/chat/entity-cards/design-doc-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/dispatch.d.ts.map +1 -1
- package/dist/components/chat/entity-cards/index.d.ts +1 -0
- package/dist/components/chat/entity-cards/index.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +11 -3
- package/dist/components/chat/index.cjs.map +1 -1
- package/dist/components/chat/index.js +10 -2
- package/dist/components/contact/index.cjs +5 -5
- package/dist/components/contact/index.js +4 -4
- package/dist/components/docs/index.cjs +8 -8
- package/dist/components/docs/index.js +7 -7
- package/dist/components/embeds/index.cjs +5 -5
- package/dist/components/embeds/index.js +4 -4
- package/dist/components/faq/index.cjs +5 -5
- package/dist/components/faq/index.js +4 -4
- package/dist/components/features/index.cjs +4 -4
- package/dist/components/features/index.js +3 -3
- package/dist/components/help-center-pages/index.cjs +197 -89
- package/dist/components/help-center-pages/index.cjs.map +1 -1
- package/dist/components/help-center-pages/index.d.ts +1 -1
- package/dist/components/help-center-pages/index.d.ts.map +1 -1
- package/dist/components/help-center-pages/index.js +143 -35
- package/dist/components/help-center-pages/index.js.map +1 -1
- package/dist/components/help-center-pages/trust-center-page.d.ts +6 -0
- package/dist/components/help-center-pages/trust-center-page.d.ts.map +1 -1
- package/dist/components/help-center-pages/trust-center-sections.d.ts +17 -2
- package/dist/components/help-center-pages/trust-center-sections.d.ts.map +1 -1
- package/dist/components/index.cjs +62 -54
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +23 -15
- package/dist/components/index.js.map +1 -1
- package/dist/components/meeting-scheduler/index.cjs +40 -40
- package/dist/components/meeting-scheduler/index.js +3 -3
- package/dist/components/navigation/index.cjs +7 -7
- package/dist/components/navigation/index.js +6 -6
- package/dist/components/onboarding-guides/index.cjs +7 -7
- package/dist/components/onboarding-guides/index.js +6 -6
- package/dist/components/related-content/index.cjs +3 -3
- package/dist/components/related-content/index.js +2 -2
- package/dist/components/tickets/index.cjs +8 -8
- package/dist/components/tickets/index.js +7 -7
- package/dist/components/ui/index.cjs +12 -4
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.js +11 -3
- package/dist/index.cjs +27 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +25 -7
- package/dist/index.js.map +1 -1
- package/dist/utils/design-doc-readiness.d.ts +20 -0
- package/dist/utils/design-doc-readiness.d.ts.map +1 -0
- package/dist/utils/index.cjs +28 -3
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +24 -4
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/list-url.d.ts.map +1 -1
- package/dist/utils/source-icons.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/chat/entity-cards/design-doc-card.tsx +114 -0
- package/src/components/chat/entity-cards/dispatch.tsx +62 -1
- package/src/components/chat/entity-cards/index.ts +7 -0
- package/src/components/help-center-pages/__tests__/trust-center-page.test.tsx +28 -1
- package/src/components/help-center-pages/index.ts +1 -1
- package/src/components/help-center-pages/trust-center-page.tsx +59 -16
- package/src/components/help-center-pages/trust-center-sections.tsx +159 -8
- package/src/utils/design-doc-readiness.ts +34 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/list-url.ts +1 -0
- package/src/utils/source-icons.ts +3 -0
- package/dist/chunk-37NYF4W2.cjs.map +0 -1
- package/dist/chunk-IJPV7OMA.js.map +0 -1
- package/dist/chunk-QHL4GYYY.cjs.map +0 -1
- /package/dist/{chunk-6KJV6GAJ.js.map → chunk-5IP7FYUN.js.map} +0 -0
- /package/dist/{chunk-GF6WJ4MG.js.map → chunk-5Q6BE56A.js.map} +0 -0
- /package/dist/{chunk-GO63IT6K.js.map → chunk-6P335PRA.js.map} +0 -0
- /package/dist/{chunk-5V3LERVC.js.map → chunk-6X66J23J.js.map} +0 -0
- /package/dist/{chunk-FOH4MNOZ.js.map → chunk-C5CTLTKJ.js.map} +0 -0
- /package/dist/{chunk-IZ6F7LOE.js.map → chunk-IHOSMLBC.js.map} +0 -0
- /package/dist/{chunk-DK3BHDUZ.js.map → chunk-INIITSC3.js.map} +0 -0
- /package/dist/{chunk-IBQT4RTS.js.map → chunk-O3PPPILJ.js.map} +0 -0
- /package/dist/{chunk-CWK4QHVF.js.map → chunk-OABFQXAI.js.map} +0 -0
- /package/dist/{chunk-PHLBRU5P.js.map → chunk-P7FKI2UW.js.map} +0 -0
- /package/dist/{chunk-YH3BUB4W.js.map → chunk-PTZKMV35.js.map} +0 -0
- /package/dist/{chunk-E5HUHKHH.js.map → chunk-QGHMHW7R.js.map} +0 -0
- /package/dist/{chunk-LJOELK7P.js.map → chunk-RG7XYHN7.js.map} +0 -0
- /package/dist/{chunk-SHGMDYCR.js.map → chunk-VEAA5C5X.js.map} +0 -0
- /package/dist/{chunk-5CC33IJ7.js.map → chunk-VXRWR56S.js.map} +0 -0
- /package/dist/{chunk-NNYND3I4.js.map → chunk-XUHLWFEM.js.map} +0 -0
|
@@ -19,6 +19,7 @@ import { useDebounce } from '../../hooks/ui/use-debounce';
|
|
|
19
19
|
import { useSelfFetch } from '../../hooks/use-self-fetch';
|
|
20
20
|
import {
|
|
21
21
|
TRUST_CENTER_SEARCH_DEBOUNCE_MS,
|
|
22
|
+
TRUST_CENTER_SECTIONS,
|
|
22
23
|
normalizeTrustControlQuery,
|
|
23
24
|
trustCenterControlsUrl,
|
|
24
25
|
trustFrameworkBadge,
|
|
@@ -28,6 +29,7 @@ import {
|
|
|
28
29
|
type TrustCenterControlsPage,
|
|
29
30
|
type TrustCenterDocument,
|
|
30
31
|
type TrustCenterFramework,
|
|
32
|
+
type TrustCenterSectionId,
|
|
31
33
|
type TrustCenterSubprocessor,
|
|
32
34
|
type TrustFrameworkMonitoringEntry,
|
|
33
35
|
} from '../../types/trust-center';
|
|
@@ -43,8 +45,7 @@ import { ShieldCheckIcon } from '../icons-v2-generated/security/shield-check-ico
|
|
|
43
45
|
import { CheckIcon } from '../icons-v2-generated/signs-and-symbols/check-icon';
|
|
44
46
|
import { SECTION_HEADING_CLASS } from '../layout/page-heading';
|
|
45
47
|
import { ListEmptyState } from '../list-empty-state';
|
|
46
|
-
import {
|
|
47
|
-
import { TextSkeleton } from '../loading/unified-skeleton';
|
|
48
|
+
import { TextSkeleton, UnifiedSkeleton } from '../loading/unified-skeleton';
|
|
48
49
|
import { Button } from '../ui/button/button';
|
|
49
50
|
import { ComplianceLogo } from '../ui/compliance-badge';
|
|
50
51
|
import { EntityImage } from '../ui/entity-image';
|
|
@@ -62,8 +63,27 @@ const FRAMEWORK_ICONS: Record<TrustFrameworkMonitoringEntry['icon'], typeof Shie
|
|
|
62
63
|
'file-shield': FileShieldIcon,
|
|
63
64
|
};
|
|
64
65
|
|
|
65
|
-
const STACK_CLASSES = 'flex flex-col gap-[var(--spacing-system-l)]';
|
|
66
66
|
const BODY_TEXT = 'text-h6 text-ods-text-secondary';
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The page body's layout, ONE copy for the loaded page and its skeleton, so the
|
|
70
|
+
* skeleton cannot drift from what replaces it: the status row, then the sections
|
|
71
|
+
* beside the section rail.
|
|
72
|
+
*/
|
|
73
|
+
export const TRUST_STATUS_ROW_CLASS =
|
|
74
|
+
'flex flex-col gap-[var(--spacing-system-xs)] md:flex-row md:items-center md:justify-between';
|
|
75
|
+
export const TRUST_BODY_GRID_CLASS =
|
|
76
|
+
'grid grid-cols-1 gap-[var(--spacing-system-xl)] lg:grid-cols-[minmax(0,1fr)_12rem]';
|
|
77
|
+
export const TRUST_SECTIONS_COLUMN_CLASS = 'flex min-w-0 flex-col gap-[var(--spacing-system-xxl)]';
|
|
78
|
+
|
|
79
|
+
/** Each section's one-line lead under its heading (the page and its skeleton read the same copy). */
|
|
80
|
+
export const TRUST_SECTION_LEADS: Partial<Record<TrustCenterSectionId, string>> = {
|
|
81
|
+
compliance: 'Frameworks we are audited against, and what is next.',
|
|
82
|
+
controls: 'Security controls currently passing in continuous monitoring (via Vanta).',
|
|
83
|
+
documents: 'Public documents open directly. Gated documents are shared under NDA after one short request.',
|
|
84
|
+
subprocessors: 'Third parties that process customer data on our behalf.',
|
|
85
|
+
ai: 'How customer data is handled by the AI in our products.',
|
|
86
|
+
};
|
|
67
87
|
/**
|
|
68
88
|
* The right-hand action / status column: ONE width from tablet up, so every
|
|
69
89
|
* panel's rows line up; on phones it hugs its content so the title keeps the room.
|
|
@@ -540,12 +560,143 @@ export function ContactSection({ onContact }: { onContact: () => void }) {
|
|
|
540
560
|
);
|
|
541
561
|
}
|
|
542
562
|
|
|
543
|
-
|
|
544
|
-
|
|
563
|
+
// ---------------------------------------------------------------------------
|
|
564
|
+
// Skeleton
|
|
565
|
+
// ---------------------------------------------------------------------------
|
|
566
|
+
|
|
567
|
+
/** A section's heading and lead, exactly as `TrustSection` renders them (real text: it does not load). */
|
|
568
|
+
function SkeletonSection({ id, children }: { id: TrustCenterSectionId; children: ReactNode }) {
|
|
569
|
+
const label = TRUST_CENTER_SECTIONS.find(section => section.id === id)?.label ?? id;
|
|
570
|
+
const lead = TRUST_SECTION_LEADS[id];
|
|
545
571
|
return (
|
|
546
|
-
<
|
|
547
|
-
<
|
|
548
|
-
|
|
572
|
+
<section aria-hidden="true" className="flex flex-col gap-[var(--spacing-system-m)]">
|
|
573
|
+
<div className="flex min-w-0 flex-col gap-[var(--spacing-system-xxs)]">
|
|
574
|
+
<h2 className={SECTION_HEADING_CLASS}>{label}</h2>
|
|
575
|
+
{lead ? <p className={BODY_TEXT}>{lead}</p> : null}
|
|
576
|
+
</div>
|
|
577
|
+
{children}
|
|
578
|
+
</section>
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Rows of the REAL `StackedRowsPanel` (its own row heights and borders) whose
|
|
584
|
+
* cells hold bars: a mark (a 40px compliance logo or a 24px glyph), a value over
|
|
585
|
+
* a label, and the right-hand badge or button in the page's `ACTION_COLUMN`.
|
|
586
|
+
*/
|
|
587
|
+
function skeletonRows(count: number, shape: { mark: 'logo' | 'glyph'; action: 'badge' | 'button' }): PanelRow[] {
|
|
588
|
+
return Array.from({ length: count }, (_, index) => ({
|
|
589
|
+
id: `skeleton-${index}`,
|
|
590
|
+
columns: [
|
|
591
|
+
{
|
|
592
|
+
key: 'item',
|
|
593
|
+
content: (
|
|
594
|
+
<div className="flex w-full items-center gap-[var(--spacing-system-s)]">
|
|
595
|
+
<UnifiedSkeleton
|
|
596
|
+
className={shape.mark === 'logo' ? 'size-10 shrink-0 rounded-full' : 'size-6 shrink-0 rounded'}
|
|
597
|
+
/>
|
|
598
|
+
<div className="flex min-w-0 flex-1 flex-col gap-[var(--spacing-system-xxs)]">
|
|
599
|
+
<UnifiedSkeleton variant="text" className="h-5 w-1/3 md:h-6" />
|
|
600
|
+
<TextSkeleton.Body className="w-1/2" />
|
|
601
|
+
</div>
|
|
602
|
+
</div>
|
|
603
|
+
),
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
key: 'action',
|
|
607
|
+
width: ACTION_COLUMN,
|
|
608
|
+
align: 'right',
|
|
609
|
+
content:
|
|
610
|
+
shape.action === 'badge' ? (
|
|
611
|
+
<UnifiedSkeleton className="h-4 w-28 rounded" />
|
|
612
|
+
) : (
|
|
613
|
+
<UnifiedSkeleton className="h-6 w-16 rounded md:h-8" />
|
|
614
|
+
),
|
|
615
|
+
},
|
|
616
|
+
],
|
|
617
|
+
}));
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/** The Controls section while loading: its tab strip, its summary and search, and the list box's own skeleton. */
|
|
621
|
+
function ControlsSectionSkeleton() {
|
|
622
|
+
return (
|
|
623
|
+
<div className="flex flex-col gap-[var(--spacing-system-m)]">
|
|
624
|
+
<div className="flex items-center gap-[var(--spacing-system-xxs)] overflow-hidden">
|
|
625
|
+
{[0, 1, 2, 3].map(index => (
|
|
626
|
+
<div key={index} className="shrink-0 p-[var(--spacing-system-m)]">
|
|
627
|
+
<UnifiedSkeleton variant="text" className="h-5 w-36 md:h-6" />
|
|
628
|
+
</div>
|
|
629
|
+
))}
|
|
630
|
+
</div>
|
|
631
|
+
<div className="flex flex-col gap-[var(--spacing-system-s)] md:flex-row md:items-center md:justify-between">
|
|
632
|
+
<TextSkeleton.Body className="w-48" />
|
|
633
|
+
<UnifiedSkeleton className="h-11 w-full rounded-[6px] md:h-12 md:w-80" />
|
|
634
|
+
</div>
|
|
635
|
+
<div className={CONTROLS_LIST_HEIGHT}>
|
|
636
|
+
<ControlsListSkeleton />
|
|
637
|
+
</div>
|
|
638
|
+
</div>
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/** The section rail while loading: `StickySectionNav`'s line and its 40px items. */
|
|
643
|
+
function SectionRailSkeleton() {
|
|
644
|
+
return (
|
|
645
|
+
<div className="sticky" style={{ top: STICKY_HEADER_OFFSET_PX }}>
|
|
646
|
+
<div className="relative">
|
|
647
|
+
<div
|
|
648
|
+
className="absolute -left-0.5 top-0 w-px bg-ods-border"
|
|
649
|
+
style={{ height: TRUST_CENTER_SECTIONS.length * 40 }}
|
|
650
|
+
/>
|
|
651
|
+
{TRUST_CENTER_SECTIONS.map(section => (
|
|
652
|
+
<div key={section.id} className="flex h-10 items-center px-3 py-2">
|
|
653
|
+
<TextSkeleton.Body className="w-24" />
|
|
654
|
+
</div>
|
|
655
|
+
))}
|
|
656
|
+
</div>
|
|
549
657
|
</div>
|
|
550
658
|
);
|
|
551
659
|
}
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* The page BODY while the trust center loads: built on the loaded body's own
|
|
663
|
+
* layout classes and the real section headings and panels, so nothing moves when
|
|
664
|
+
* the content replaces it. The status row, then Compliance, Controls and
|
|
665
|
+
* Documents (what fills the first screens), beside the section rail.
|
|
666
|
+
*/
|
|
667
|
+
export function TrustCenterSkeleton() {
|
|
668
|
+
return (
|
|
669
|
+
<>
|
|
670
|
+
<div className={TRUST_STATUS_ROW_CLASS} aria-hidden="true">
|
|
671
|
+
<div className="flex items-center gap-1.5">
|
|
672
|
+
<UnifiedSkeleton className="size-3 rounded-full" />
|
|
673
|
+
<TextSkeleton.Body className="w-44" />
|
|
674
|
+
</div>
|
|
675
|
+
{/* `DataAttribution`'s own layout: two lines below `sm`, one row above it. */}
|
|
676
|
+
<div className="flex shrink-0 flex-col gap-[var(--spacing-system-xxs)] sm:flex-row sm:items-center sm:gap-[var(--spacing-system-sf)]">
|
|
677
|
+
<div className="flex items-center gap-[var(--spacing-system-xsf)]">
|
|
678
|
+
<UnifiedSkeleton className="size-4 rounded" />
|
|
679
|
+
<TextSkeleton.Body className="w-36" />
|
|
680
|
+
</div>
|
|
681
|
+
<TextSkeleton.Body className="w-44" />
|
|
682
|
+
</div>
|
|
683
|
+
</div>
|
|
684
|
+
<div className={TRUST_BODY_GRID_CLASS} aria-busy="true" aria-label="Loading the trust center">
|
|
685
|
+
<div className={TRUST_SECTIONS_COLUMN_CLASS}>
|
|
686
|
+
<SkeletonSection id="compliance">
|
|
687
|
+
<StackedRowsPanel rows={skeletonRows(3, { mark: 'logo', action: 'badge' })} />
|
|
688
|
+
</SkeletonSection>
|
|
689
|
+
<SkeletonSection id="controls">
|
|
690
|
+
<ControlsSectionSkeleton />
|
|
691
|
+
</SkeletonSection>
|
|
692
|
+
<SkeletonSection id="documents">
|
|
693
|
+
<StackedRowsPanel rows={skeletonRows(2, { mark: 'glyph', action: 'button' })} />
|
|
694
|
+
</SkeletonSection>
|
|
695
|
+
</div>
|
|
696
|
+
<aside className="hidden lg:block" aria-hidden="true">
|
|
697
|
+
<SectionRailSkeleton />
|
|
698
|
+
</aside>
|
|
699
|
+
</div>
|
|
700
|
+
</>
|
|
701
|
+
);
|
|
702
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A design doc's readiness in words — THE wording every surface prints (the hub's design-docs screens, its doc
|
|
3
|
+
* page, the lib's design-doc card): "Ready to build" once every department section is signed off and no blocking
|
|
4
|
+
* comment is open, else "Not ready", and the sign-off caption beside it. Pure, zero-import beyond the type.
|
|
5
|
+
*/
|
|
6
|
+
import type { DesignDocCompletion } from '../types/design-doc';
|
|
7
|
+
|
|
8
|
+
export const DESIGN_DOC_READINESS = ['ready', 'not_ready'] as const;
|
|
9
|
+
export type DesignDocReadiness = (typeof DESIGN_DOC_READINESS)[number];
|
|
10
|
+
|
|
11
|
+
/** Each readiness's label and badge colour (a `StatusBadge` scheme). */
|
|
12
|
+
export const DESIGN_DOC_READINESS_DISPLAY: Record<
|
|
13
|
+
DesignDocReadiness,
|
|
14
|
+
{ label: string; scheme: 'success' | 'default' }
|
|
15
|
+
> = {
|
|
16
|
+
ready: { label: 'Ready to build', scheme: 'success' },
|
|
17
|
+
not_ready: { label: 'Not ready', scheme: 'default' },
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/** Ready to build ⇔ `completion.isComplete` (every section signed off, no open blocking comment). */
|
|
21
|
+
export const designDocReadiness = (completion: Pick<DesignDocCompletion, 'isComplete'>): DesignDocReadiness =>
|
|
22
|
+
completion.isComplete ? 'ready' : 'not_ready';
|
|
23
|
+
|
|
24
|
+
/** "4/6 reviews signed off" */
|
|
25
|
+
export function formatCompletionLabel(completion: Pick<DesignDocCompletion, 'total' | 'completed'>): string {
|
|
26
|
+
return `${completion.completed}/${completion.total} reviews signed off`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** The SAME label plus readiness and the blocking veto (the dashboard row, the doc page, the card). */
|
|
30
|
+
export function formatCompletionLabelWithBlockers(completion: DesignDocCompletion): string {
|
|
31
|
+
const base = formatCompletionLabel(completion);
|
|
32
|
+
if (completion.isComplete) return `${DESIGN_DOC_READINESS_DISPLAY.ready.label} · ${base}`;
|
|
33
|
+
return completion.openBlocking > 0 ? `${base} · ${completion.openBlocking} blocking` : base;
|
|
34
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -57,6 +57,7 @@ export { SEO_DESCRIPTION_MAX_LENGTH } from './seo-description';
|
|
|
57
57
|
// Brand silhouette SVG registry (CSS mask-image tinting) — centralized so
|
|
58
58
|
// consumers (e.g. company-hub deck) don't ship their own copies of the marks.
|
|
59
59
|
export * from './brand-marks';
|
|
60
|
+
export * from './design-doc-readiness';
|
|
60
61
|
export * from './platform-config';
|
|
61
62
|
export * from './os-platforms';
|
|
62
63
|
export * from './access-code-client';
|
package/src/utils/list-url.ts
CHANGED
|
@@ -128,6 +128,7 @@ const BUILDERS: Record<string, (ids: string[], base: string) => string> = {
|
|
|
128
128
|
code_symbol: (ids, b) => `${b}/api/code-graph/symbols?ids=${ids.join(',')}`,
|
|
129
129
|
code_duplicate: (ids, b) => `${b}/api/code-graph/duplicates?ids=${ids.join(',')}`,
|
|
130
130
|
code_impact: (ids, b) => `${b}/api/code-graph/impacts?ids=${ids.join(',')}`,
|
|
131
|
+
change_set: (ids, b) => `${b}/api/code-graph/change-sets?ids=${ids.join(',')}`,
|
|
131
132
|
// Single-record live source: the route ignores `?ids=` and returns the ONE
|
|
132
133
|
// `TrustCenterPublic` object (card id `TRUST_CENTER_CARD_ID`); see
|
|
133
134
|
// `extractCardItems` for how the loader matches it back.
|
|
@@ -91,6 +91,7 @@ export const SOURCE_ICON_NAMES: Record<string, string> = {
|
|
|
91
91
|
'code-symbols': 'box',
|
|
92
92
|
'code-duplicates': 'search',
|
|
93
93
|
'code-impact': 'activity',
|
|
94
|
+
'change-sets': 'coding-branch',
|
|
94
95
|
};
|
|
95
96
|
|
|
96
97
|
/** Lookup an icon name by RagTableConfig.id. Returns undefined when
|
|
@@ -185,6 +186,7 @@ export const SOURCE_LABELS_BY_TABLE: Record<string, string> = {
|
|
|
185
186
|
'code-symbols': 'Code Symbols',
|
|
186
187
|
'code-duplicates': 'Duplicates',
|
|
187
188
|
'code-impact': 'Change Impact',
|
|
189
|
+
'change-sets': 'Change Sets',
|
|
188
190
|
};
|
|
189
191
|
|
|
190
192
|
/** Lookup a human-readable label by RagTableConfig.id. Falls back
|
|
@@ -281,6 +283,7 @@ export const DEFAULT_DOCUMENT_TYPE_TO_TABLE_ID: Record<string, string> = {
|
|
|
281
283
|
code_symbol: 'code-symbols',
|
|
282
284
|
code_duplicate: 'code-duplicates',
|
|
283
285
|
code_impact: 'code-impact',
|
|
286
|
+
change_set: 'change-sets',
|
|
284
287
|
};
|
|
285
288
|
|
|
286
289
|
/**
|