@flamingo-stack/openframe-frontend-core 0.0.847 → 0.0.849

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.
Files changed (188) hide show
  1. package/dist/build/export-map.json +1 -1
  2. package/dist/{case-study-card-DJOHIHYU.cjs → case-study-card-X2HKPKT7.cjs} +5 -5
  3. package/dist/{chunk-CNMXP77I.cjs → chunk-36DUCHI7.cjs} +4 -4
  4. package/dist/{chunk-MPVOPSU6.cjs → chunk-36XWCVSM.cjs} +96 -96
  5. package/dist/{chunk-J2IXYCEH.cjs → chunk-3W4ASAXN.cjs} +15 -15
  6. package/dist/{chunk-6LDL3UZE.cjs → chunk-4YBS4HIO.cjs} +20 -20
  7. package/dist/{chunk-ABL5OBSF.cjs → chunk-533QK4R6.cjs} +296 -250
  8. package/dist/{chunk-QK2A334V.cjs → chunk-5CBI2ZYV.cjs} +12 -12
  9. package/dist/{chunk-D5DMWXF2.cjs → chunk-5PIR77V5.cjs} +4 -4
  10. package/dist/{chunk-HPXET3LH.cjs → chunk-6AJYGXXS.cjs} +27 -27
  11. package/dist/{chunk-4R4HAFXI.cjs → chunk-ALRYVZ3E.cjs} +6 -6
  12. package/dist/{chunk-FLW4WULE.cjs → chunk-BU2PSRAS.cjs} +17 -61
  13. package/dist/{chunk-HBDLJUI3.cjs → chunk-C3P7IUTU.cjs} +39 -14
  14. package/dist/{chunk-SSSI2RBV.cjs → chunk-FNQWL4W4.cjs} +14 -14
  15. package/dist/{chunk-TBOWFTEN.cjs → chunk-FRG724DU.cjs} +22 -22
  16. package/dist/{chunk-SIFRIUPW.cjs → chunk-FXLROQUT.cjs} +345 -356
  17. package/dist/{chunk-3V5JWG27.cjs → chunk-GG466XFQ.cjs} +2 -2
  18. package/dist/{chunk-XCVH5BCZ.cjs → chunk-GRCOEICK.cjs} +6 -6
  19. package/dist/{chunk-5GBLXY5F.cjs → chunk-HTYJUMFB.cjs} +7 -7
  20. package/dist/{chunk-URP6GYTD.cjs → chunk-IG6ROHPS.cjs} +56 -56
  21. package/dist/{chunk-DGQDGCQH.cjs → chunk-IHY7E4EX.cjs} +2 -2
  22. package/dist/{chunk-WCK5T3UD.cjs → chunk-IKOL6NJY.cjs} +101 -69
  23. package/dist/{chunk-RAJ5FYFL.cjs → chunk-IN3LA2FU.cjs} +14 -14
  24. package/dist/{chunk-ZTO7KNYV.cjs → chunk-KXBZCUDW.cjs} +35 -35
  25. package/dist/{chunk-57JYB3E2.cjs → chunk-MC3L525K.cjs} +3 -3
  26. package/dist/{chunk-BIOSHDXQ.cjs → chunk-MDLT6D46.cjs} +61 -61
  27. package/dist/{chunk-3TOWCFIK.cjs → chunk-PMUCEUFQ.cjs} +13 -1
  28. package/dist/{chunk-PV3NKXWS.cjs → chunk-PV2XQJ2R.cjs} +99 -178
  29. package/dist/{chunk-J2ZSGOUC.cjs → chunk-R5JPZ6TY.cjs} +27 -27
  30. package/dist/{chunk-744JXTDP.cjs → chunk-SA2NNWIJ.cjs} +23 -23
  31. package/dist/{chunk-DEEQSVLX.cjs → chunk-SHQY4GOE.cjs} +90 -90
  32. package/dist/{chunk-BHOVF4KP.cjs → chunk-SOSIXRQ3.cjs} +2 -2
  33. package/dist/{chunk-Y2OEC7UW.cjs → chunk-TEKN6TJ5.cjs} +40 -40
  34. package/dist/{chunk-PZNWIJRZ.cjs → chunk-TIVPOVIM.cjs} +2 -2
  35. package/dist/{chunk-BZZE4KIV.cjs → chunk-TX4NTH22.cjs} +155 -136
  36. package/dist/{chunk-NFNSPLGC.cjs → chunk-W7OFAROY.cjs} +14 -9
  37. package/dist/{chunk-N2A24FDF.cjs → chunk-YLETC7LP.cjs} +994 -953
  38. package/dist/{chunk-YC52LSPP.cjs → chunk-YYHQY3K6.cjs} +40 -40
  39. package/dist/{chunk-2FUTZKLB.cjs → chunk-Z5UCDEKZ.cjs} +6 -6
  40. package/dist/{chunk-SWF6TNZ3.cjs → chunk-ZGEWT3SF.cjs} +2 -2
  41. package/dist/{chunk-PQDCSZ3W.cjs → chunk-ZY34R37A.cjs} +85 -85
  42. package/dist/{chunk-5SZ4ILU3.cjs → chunk-ZZDFMUEU.cjs} +3 -3
  43. package/dist/{cloud-tenants-XEUUMABT.cjs → cloud-tenants-HKUUEUAY.cjs} +21 -21
  44. package/dist/components/case-studies/index.cjs +36 -36
  45. package/dist/components/chat/chat-composer.d.ts.map +1 -1
  46. package/dist/components/chat/chat-composer.js +4 -3
  47. package/dist/components/chat/chat-container.d.ts.map +1 -1
  48. package/dist/components/chat/chat-container.js +2 -2
  49. package/dist/components/chat/entity-cards/design-doc-card.d.ts.map +1 -1
  50. package/dist/components/chat/entity-cards/design-doc-card.js +5 -17
  51. package/dist/components/chat/entity-cards/dispatch.d.ts.map +1 -1
  52. package/dist/components/chat/entity-cards/dispatch.js +5 -7
  53. package/dist/components/chat/index.cjs +15 -15
  54. package/dist/components/contact/index.cjs +22 -22
  55. package/dist/components/docs/doc-viewer.d.ts +7 -7
  56. package/dist/components/docs/doc-viewer.d.ts.map +1 -1
  57. package/dist/components/docs/doc-viewer.js +29 -16
  58. package/dist/components/docs/docs-hub-page.d.ts +1 -1
  59. package/dist/components/docs/docs-hub-page.d.ts.map +1 -1
  60. package/dist/components/docs/docs-hub-page.js +4 -11
  61. package/dist/components/docs/index.cjs +25 -25
  62. package/dist/components/docs/use-document-tree.d.ts.map +1 -1
  63. package/dist/components/docs/use-document-tree.js +24 -24
  64. package/dist/components/embeds/claude-embed.d.ts +2 -2
  65. package/dist/components/embeds/claude-embed.d.ts.map +1 -1
  66. package/dist/components/embeds/claude-embed.js +3 -3
  67. package/dist/components/embeds/embed-iframe.d.ts +5 -3
  68. package/dist/components/embeds/embed-iframe.d.ts.map +1 -1
  69. package/dist/components/embeds/embed-iframe.js +4 -3
  70. package/dist/components/embeds/embed-viewer-frame.d.ts +12 -9
  71. package/dist/components/embeds/embed-viewer-frame.d.ts.map +1 -1
  72. package/dist/components/embeds/embed-viewer-frame.js +21 -7
  73. package/dist/components/embeds/figma-embed.d.ts +4 -2
  74. package/dist/components/embeds/figma-embed.d.ts.map +1 -1
  75. package/dist/components/embeds/figma-embed.js +4 -3
  76. package/dist/components/embeds/file-download-card.d.ts +3 -1
  77. package/dist/components/embeds/file-download-card.d.ts.map +1 -1
  78. package/dist/components/embeds/file-download-card.js +18 -3
  79. package/dist/components/embeds/google-sheets-viewer.d.ts +3 -1
  80. package/dist/components/embeds/google-sheets-viewer.d.ts.map +1 -1
  81. package/dist/components/embeds/google-sheets-viewer.js +7 -4
  82. package/dist/components/embeds/index.cjs +22 -22
  83. package/dist/components/embeds/pdf-viewer.d.ts +3 -1
  84. package/dist/components/embeds/pdf-viewer.d.ts.map +1 -1
  85. package/dist/components/embeds/pdf-viewer.js +6 -2
  86. package/dist/components/faq/index.cjs +23 -23
  87. package/dist/components/features/index.cjs +21 -21
  88. package/dist/components/features/status-filter-component.d.ts +7 -1
  89. package/dist/components/features/status-filter-component.d.ts.map +1 -1
  90. package/dist/components/features/status-filter-component.js +9 -3
  91. package/dist/components/help-center-pages/index.cjs +140 -140
  92. package/dist/components/index.cjs +137 -135
  93. package/dist/components/layout/back-button.d.ts +7 -1
  94. package/dist/components/layout/back-button.d.ts.map +1 -1
  95. package/dist/components/layout/back-button.js +34 -2
  96. package/dist/components/loading/unified-skeleton.d.ts +6 -1
  97. package/dist/components/loading/unified-skeleton.d.ts.map +1 -1
  98. package/dist/components/loading/unified-skeleton.js +13 -1
  99. package/dist/components/meeting-scheduler/index.cjs +119 -119
  100. package/dist/components/navigation/index.cjs +24 -24
  101. package/dist/components/onboarding-guides/index.cjs +24 -24
  102. package/dist/components/product-demo/index.cjs +33 -33
  103. package/dist/components/related-content/index.cjs +11 -11
  104. package/dist/components/tickets/index.cjs +28 -28
  105. package/dist/components/ui/file-manager/file-manager-table.d.ts.map +1 -1
  106. package/dist/components/ui/file-manager/file-manager-table.js +59 -50
  107. package/dist/components/ui/file-manager/index.cjs +71 -62
  108. package/dist/components/ui/index.cjs +23 -21
  109. package/dist/components/ui/markdown/engine.d.ts +5 -4
  110. package/dist/components/ui/markdown/engine.d.ts.map +1 -1
  111. package/dist/components/ui/markdown/engine.js +15 -15
  112. package/dist/components/ui/markdown/rich/rich-markdown-renderer.d.ts.map +1 -1
  113. package/dist/components/ui/markdown/rich/rich-markdown-renderer.js +7 -3
  114. package/dist/components/ui/people-cell.d.ts +9 -2
  115. package/dist/components/ui/people-cell.d.ts.map +1 -1
  116. package/dist/components/ui/people-cell.js +39 -23
  117. package/dist/components/ui/progress-bar.d.ts +6 -0
  118. package/dist/components/ui/progress-bar.d.ts.map +1 -1
  119. package/dist/components/ui/progress-bar.js +2 -0
  120. package/dist/components/ui/tag.d.ts +8 -0
  121. package/dist/components/ui/tag.d.ts.map +1 -1
  122. package/dist/components/ui/tag.js +5 -0
  123. package/dist/{devices-7YDIHVVP.cjs → devices-P7M4Z7VP.cjs} +22 -22
  124. package/dist/embed-shims/index.cjs +3 -3
  125. package/dist/embed-shims/next-image.cjs +3 -3
  126. package/dist/{embeddable-chat-Z3S37SSM.cjs → embeddable-chat-322NDFP5.cjs} +94 -94
  127. package/dist/hooks/index.cjs +6 -6
  128. package/dist/index.cjs +32 -30
  129. package/dist/{knowledge-SQVPQSKM.cjs → knowledge-TC7JLOWI.cjs} +22 -22
  130. package/dist/{logs-M5DFGUBC.cjs → logs-GPOYCP4B.cjs} +28 -28
  131. package/dist/{policies-T3VQEJUD.cjs → policies-ZUHOUMDD.cjs} +25 -25
  132. package/dist/{remote-session-EE6477O3.cjs → remote-session-NT4NG7EF.cjs} +10 -10
  133. package/dist/{scripts-JFRFJKPH.cjs → scripts-FOEVDGTH.cjs} +28 -28
  134. package/dist/{software-update-E7W3AAIY.cjs → software-update-XGTMNFST.cjs} +25 -25
  135. package/dist/{tickets-board-44HO3LR4.cjs → tickets-board-7FLGQEHF.cjs} +10 -10
  136. package/dist/types/design-doc.d.ts +45 -8
  137. package/dist/types/design-doc.d.ts.map +1 -1
  138. package/dist/types/doc-source.d.ts +2 -2
  139. package/dist/types/doc-source.d.ts.map +1 -1
  140. package/dist/utils/design-doc-readiness.d.ts +17 -15
  141. package/dist/utils/design-doc-readiness.d.ts.map +1 -1
  142. package/dist/utils/design-doc-readiness.js +5 -11
  143. package/dist/utils/doc-tree-nav.d.ts +7 -0
  144. package/dist/utils/doc-tree-nav.d.ts.map +1 -1
  145. package/dist/utils/doc-tree-nav.js +19 -0
  146. package/dist/utils/index.cjs +30 -13
  147. package/dist/utils/list-url.d.ts.map +1 -1
  148. package/dist/utils/list-url.js +2 -1
  149. package/dist/utils/source-grouping.d.ts +2 -2
  150. package/dist/utils/source-grouping.d.ts.map +1 -1
  151. package/dist/utils/source-grouping.js +1 -1
  152. package/dist/utils/source-icons.d.ts.map +1 -1
  153. package/dist/utils/source-icons.js +3 -0
  154. package/package.json +1 -1
  155. package/src/components/chat/chat-composer.tsx +10 -3
  156. package/src/components/chat/chat-container.tsx +6 -4
  157. package/src/components/chat/entity-cards/design-doc-card.tsx +12 -17
  158. package/src/components/chat/entity-cards/dispatch.tsx +10 -10
  159. package/src/components/docs/doc-viewer.tsx +56 -35
  160. package/src/components/docs/docs-hub-page.tsx +13 -37
  161. package/src/components/docs/use-document-tree.ts +33 -23
  162. package/src/components/embeds/claude-embed.tsx +4 -4
  163. package/src/components/embeds/embed-iframe.tsx +8 -5
  164. package/src/components/embeds/embed-viewer-frame.tsx +35 -15
  165. package/src/components/embeds/figma-embed.tsx +9 -4
  166. package/src/components/embeds/file-download-card.tsx +28 -4
  167. package/src/components/embeds/google-sheets-viewer.tsx +9 -3
  168. package/src/components/embeds/pdf-viewer.tsx +9 -2
  169. package/src/components/features/status-filter-component.tsx +15 -0
  170. package/src/components/layout/back-button.tsx +54 -2
  171. package/src/components/loading/unified-skeleton.tsx +18 -2
  172. package/src/components/ui/file-manager/file-manager-table.tsx +8 -3
  173. package/src/components/ui/markdown/engine.tsx +21 -30
  174. package/src/components/ui/markdown/rich/rich-markdown-renderer.tsx +4 -0
  175. package/src/components/ui/people-cell.tsx +53 -17
  176. package/src/components/ui/progress-bar.tsx +8 -0
  177. package/src/components/ui/tag.tsx +14 -0
  178. package/src/types/design-doc.ts +59 -10
  179. package/src/types/doc-source.ts +2 -2
  180. package/src/utils/design-doc-readiness.ts +22 -23
  181. package/src/utils/doc-tree-nav.ts +27 -0
  182. package/src/utils/list-url.ts +2 -1
  183. package/src/utils/source-grouping.ts +2 -2
  184. package/src/utils/source-icons.ts +3 -0
  185. package/dist/components/docs/skeletons.d.ts +0 -25
  186. package/dist/components/docs/skeletons.d.ts.map +0 -1
  187. package/dist/components/docs/skeletons.js +0 -83
  188. package/src/components/docs/skeletons.tsx +0 -131
@@ -35,7 +35,11 @@ import type { PluggableList } from 'unified';
35
35
  import type { ResolveLinkResult } from '../../../types/doc-source';
36
36
  import { readAppOrigins, SERVER_APP_ORIGINS, subscribeAppOrigins } from '../../../utils/app-origins';
37
37
  import { cn } from '../../../utils/cn';
38
- import { TextLineSkeleton } from '../../loading/unified-skeleton';
38
+ import {
39
+ TextLineSkeleton,
40
+ TextLinesByBreakpointSkeleton,
41
+ type TextLinesByBreakpoint,
42
+ } from '../../loading/unified-skeleton';
39
43
  import { LoadingItems, useLoadingScope } from '../loading-scope';
40
44
  import { buildBaseComponents, MARKDOWN_H1_CLASS, MARKDOWN_H2_CLASS, MARKDOWN_PARAGRAPH_CLASS } from './base-components';
41
45
  import { MarkdownMediaOriginsContext } from './external-media-notice';
@@ -193,8 +197,8 @@ export interface MarkdownEngineProps {
193
197
  * sections, each a heading and its paragraphs. Unset, one paragraph of `skeletonLines` lines.
194
198
  */
195
199
  skeletonSections?: number;
196
- /** Lines of the one paragraph a loading body draws when it names no sections. Default 3. */
197
- skeletonLines?: number;
200
+ /** Lines of the one paragraph a loading body draws when it names no sections, per width. Default 3 at every width. */
201
+ skeletonLines?: TextLinesByBreakpoint;
198
202
  /** A loading body opens with its own `# ` title (a legal document's): its title row is drawn first. */
199
203
  skeletonTitle?: boolean;
200
204
  /** The content is still being read: the body draws its skeleton (the `skeleton*` shape). A loading scope does the
@@ -203,16 +207,19 @@ export interface MarkdownEngineProps {
203
207
  }
204
208
 
205
209
  /** Lines a loading body draws when its caller names no shape. */
206
- export const MARKDOWN_SKELETON_LINES = 3;
210
+ export const MARKDOWN_SKELETON_LINES: TextLinesByBreakpoint = { phone: 3, md: 3, lg: 3 };
207
211
  /** Paragraphs under each heading of a loading body, and their lines. */
208
- const SKELETON_SECTION_PARAGRAPHS = [3, 2] as const;
212
+ const SKELETON_SECTION_PARAGRAPHS: readonly TextLinesByBreakpoint[] = [
213
+ { phone: 3, md: 3, lg: 3 },
214
+ { phone: 2, md: 2, lg: 2 },
215
+ ];
209
216
  /**
210
- * Lines a typical body's opening line set takes, on a phone (below `content-md`) and from `content-md`: a document's
217
+ * Lines a typical body's opening line set takes, per width: a document's
211
218
  * `# ` title wraps on a phone, and the opening paragraph every post and legal document starts with runs a few lines.
212
219
  * Typical lengths, never one record's: a longer record growing past them is a settle below its own lines.
213
220
  */
214
- const SKELETON_TITLE_LINES = { phone: 2, wide: 1 } as const;
215
- const SKELETON_LEAD_LINES = { phone: 5, wide: 3 } as const;
221
+ const SKELETON_TITLE_LINES: TextLinesByBreakpoint = { phone: 2, md: 1, lg: 1 };
222
+ const SKELETON_LEAD_LINES: TextLinesByBreakpoint = { phone: 5, md: 3, lg: 3 };
216
223
  /** The renderer's own frame: read by the engine and by its skeleton. */
217
224
  /** The renderer's root class, on the rendered document and on every skeleton of one: it names a markdown body. */
218
225
  export const MARKDOWN_RENDERER_CLASS = 'simple-markdown-renderer';
@@ -467,31 +474,15 @@ export const MarkdownEngine = memo(function MarkdownEngineGate(props: MarkdownEn
467
474
  return <MarkdownEngineImpl {...props} />;
468
475
  });
469
476
 
470
- /** A paragraph of `lines` lines at the body's own paragraph type, as one bar of its line height. */
471
- function ParagraphBar({ lines, className }: { lines: number; className: string }) {
477
+ /** A paragraph of its `lines` per width at the body's own paragraph type. */
478
+ function ParagraphBar({ lines, className }: { lines: TextLinesByBreakpoint; className: string }) {
472
479
  return (
473
480
  <div className={className}>
474
- <TextLineSkeleton type="inherit" lines={lines} className="w-full" />
481
+ <TextLinesByBreakpointSkeleton lines={lines} />
475
482
  </div>
476
483
  );
477
484
  }
478
485
 
479
- /** Lines of a text run per breakpoint: on a phone, and from `content-md`. */
480
- interface SkeletonLinesByBreakpoint {
481
- phone: number;
482
- wide: number;
483
- }
484
-
485
- /** A text run of the lines it takes on a phone and from `content-md` (the content area's own steps). */
486
- function LinesByBreakpoint({ lines, as = 'div' }: { lines: SkeletonLinesByBreakpoint; as?: 'div' | 'span' }) {
487
- return (
488
- <>
489
- <TextLineSkeleton type="inherit" as={as} lines={lines.phone} className="w-full content-md:hidden" />
490
- <TextLineSkeleton type="inherit" as={as} lines={lines.wide} className="hidden w-full content-md:flex" />
491
- </>
492
- );
493
- }
494
-
495
486
  /**
496
487
  * A markdown body while it is read: the renderer's own frame and type. With `sections`, the body's opening paragraph
497
488
  * (a typical length per breakpoint), then each section a REAL `<h2>` (the renderer's heading classes) holding a bar,
@@ -506,7 +497,7 @@ export function MarkdownEngineSkeleton({
506
497
  className = '',
507
498
  }: {
508
499
  sections?: number;
509
- lines?: number;
500
+ lines?: TextLinesByBreakpoint;
510
501
  textSize?: TextSizeConfig;
511
502
  /** The body opens with its own `# ` title (a legal document's, demoted to an `h2`): its H1 row is drawn first. */
512
503
  title?: boolean;
@@ -522,12 +513,12 @@ export function MarkdownEngineSkeleton({
522
513
  <div className={ARTICLE_CLASS}>
523
514
  {title && (
524
515
  <h2 className={cn(MARKDOWN_H1_CLASS, textSizes.h1)}>
525
- <LinesByBreakpoint lines={SKELETON_TITLE_LINES} as="span" />
516
+ <TextLinesByBreakpointSkeleton lines={SKELETON_TITLE_LINES} as="span" />
526
517
  </h2>
527
518
  )}
528
519
  {sections ? (
529
520
  <div className={paragraphClass}>
530
- <LinesByBreakpoint lines={SKELETON_LEAD_LINES} />
521
+ <TextLinesByBreakpointSkeleton lines={SKELETON_LEAD_LINES} />
531
522
  </div>
532
523
  ) : null}
533
524
  {sections ? (
@@ -101,6 +101,7 @@ const RichMarkdownInner: React.FC<InnerProps> = ({
101
101
  demoteMarkdownH1ToH2,
102
102
  skeletonSections,
103
103
  skeletonLines,
104
+ skeletonTitle,
104
105
  }) => {
105
106
  const { ogScraperUrl } = useRichMarkdownRuntime();
106
107
 
@@ -158,6 +159,7 @@ const RichMarkdownInner: React.FC<InnerProps> = ({
158
159
  allowRemoteMedia
159
160
  skeletonSections={skeletonSections}
160
161
  skeletonLines={skeletonLines}
162
+ skeletonTitle={skeletonTitle}
161
163
  />
162
164
  );
163
165
  };
@@ -174,6 +176,7 @@ const RichMarkdownRendererImpl: React.FC<RichMarkdownRendererProps> = ({
174
176
  demoteMarkdownH1ToH2 = false,
175
177
  skeletonSections,
176
178
  skeletonLines,
179
+ skeletonTitle,
177
180
  // Runtime overrides; provider fills the defaults
178
181
  redditProxyUrl,
179
182
  twitterProxyUrl,
@@ -199,6 +202,7 @@ const RichMarkdownRendererImpl: React.FC<RichMarkdownRendererProps> = ({
199
202
  demoteMarkdownH1ToH2={demoteMarkdownH1ToH2}
200
203
  skeletonSections={skeletonSections}
201
204
  skeletonLines={skeletonLines}
205
+ skeletonTitle={skeletonTitle}
202
206
  />
203
207
  </RichMarkdownRuntimeProvider>
204
208
  );
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { cn } from '../../utils/cn';
3
4
  import { personFirstName } from '../../utils/format';
4
5
  import { TextLineSkeleton } from '../loading/unified-skeleton';
5
6
  import { AvatarStack } from './avatar-stack';
@@ -48,6 +49,11 @@ export interface PersonCellProps {
48
49
  size?: 'sm' | 'lg';
49
50
  /** The person is still being read: the cell draws its skeleton at its size. A loading scope does the same. */
50
51
  loading?: boolean;
52
+ /**
53
+ * `2` (default): the name and its second line. `1`: the name alone, one line, with the second line in a tooltip:
54
+ * for a table whose rows are one line in every column but the first.
55
+ */
56
+ lines?: 1 | 2;
51
57
  }
52
58
 
53
59
  const PERSON_CELL_SIZE = {
@@ -67,29 +73,35 @@ export function PersonCell({
67
73
  actionTitle,
68
74
  size = 'sm',
69
75
  loading,
76
+ lines = 2,
70
77
  }: PersonCellProps) {
71
78
  // In a page's loading state (or while the host reads the person) the cell is its skeleton.
72
- if (useLoadingScope() || loading) return <PersonCellSkeleton size={size} />;
79
+ if (useLoadingScope() || loading) return <PersonCellSkeleton size={size} lines={lines} />;
73
80
  const displayName = name || fallbackName;
74
81
  const scale = PERSON_CELL_SIZE[size];
82
+ const nameLine = (
83
+ <TruncateText
84
+ variant={scale.primary}
85
+ className={onClick ? 'text-ods-accent group-hover/person-cell:underline' : undefined}
86
+ >
87
+ {displayName}
88
+ </TruncateText>
89
+ );
75
90
  const row = (
76
91
  <div className={`group/person-cell ${PERSON_ROW_CLASS} ${scale.gap}`}>
77
92
  <SquareAvatar size={scale.avatar} src={avatarUrl ?? undefined} alt={displayName} fallback={displayName} />
78
93
  <div className="min-w-0 flex-1">
79
- <TruncateText
80
- variant={scale.primary}
81
- className={onClick ? 'text-ods-accent group-hover/person-cell:underline' : undefined}
82
- >
83
- {displayName}
84
- </TruncateText>
85
- <TruncateText variant="h6" tone="secondary">
86
- {secondary === undefined ? ' ' : secondary || '·'}
87
- </TruncateText>
94
+ {nameLine}
95
+ {lines === 2 ? (
96
+ <TruncateText variant="h6" tone="secondary">
97
+ {secondary === undefined ? ' ' : secondary || '·'}
98
+ </TruncateText>
99
+ ) : null}
88
100
  </div>
89
101
  </div>
90
102
  );
91
- if (!onClick) return row;
92
- return (
103
+ // A clickable cell is a button in both layouts, so `onClick` and `actionTitle` are never dropped by `lines`.
104
+ const cell = onClick ? (
93
105
  <Button
94
106
  variant="transparent"
95
107
  onClick={onClick}
@@ -100,18 +112,34 @@ export function PersonCell({
100
112
  >
101
113
  {row}
102
114
  </Button>
115
+ ) : (
116
+ row
117
+ );
118
+ // One line: the second line is not drawn, so it is the cell's tooltip.
119
+ return lines === 1 && secondary ? (
120
+ <FloatingTooltip content={`${displayName} · ${secondary}`} triggerClassName="min-w-0 max-w-full">
121
+ {cell}
122
+ </FloatingTooltip>
123
+ ) : (
124
+ cell
103
125
  );
104
126
  }
105
127
 
106
128
  /** The cell while it loads: the SAME avatar box, gap and two lines (the name's type step, then the caption's). */
107
- function PersonCellSkeleton({ size = 'sm' }: { size?: PersonCellProps['size'] }) {
129
+ function PersonCellSkeleton({
130
+ size = 'sm',
131
+ lines = 2,
132
+ }: {
133
+ size?: PersonCellProps['size'];
134
+ lines?: PersonCellProps['lines'];
135
+ }) {
108
136
  const scale = PERSON_CELL_SIZE[size];
109
137
  return (
110
138
  <div className={`${PERSON_ROW_CLASS} ${scale.gap}`} aria-hidden>
111
139
  <SquareAvatar loading size={scale.avatar} />
112
140
  <div className="flex min-w-0 flex-1 flex-col">
113
141
  <TextLineSkeleton type={scale.primary} className="w-3/4" />
114
- <TextLineSkeleton type="h6" className="w-1/2" />
142
+ {lines === 2 ? <TextLineSkeleton type="h6" className="w-1/2" /> : null}
115
143
  </div>
116
144
  </div>
117
145
  );
@@ -130,14 +158,16 @@ export interface PeopleCellProps {
130
158
  people: PeopleCellPerson[];
131
159
  /** Shown when the list is empty — the same slot `PersonCell` fills. */
132
160
  fallbackName?: string;
161
+ /** `1`: one line for one person or several (see `PersonCellProps.lines`). */
162
+ lines?: 1 | 2;
133
163
  }
134
164
 
135
165
  /** Positions the multi-person stack reserves: two faces, or one face and "+N". */
136
166
  const PEOPLE_CELL_STACK_SLOTS = 2;
137
167
 
138
- export function PeopleCell({ people, fallbackName = 'Unassigned' }: PeopleCellProps) {
168
+ export function PeopleCell({ people, fallbackName = 'Unassigned', lines = 2 }: PeopleCellProps) {
139
169
  // In a page's loading state the people are read: the cell is a person cell's skeleton.
140
- if (useLoadingScope()) return <PersonCellSkeleton />;
170
+ if (useLoadingScope()) return <PersonCellSkeleton lines={lines} />;
141
171
  if (people.length <= 1) {
142
172
  const [person] = people;
143
173
  return (
@@ -146,6 +176,7 @@ export function PeopleCell({ people, fallbackName = 'Unassigned' }: PeopleCellPr
146
176
  avatarUrl={person?.avatarUrl}
147
177
  secondary={person ? person.secondary : undefined}
148
178
  fallbackName={fallbackName}
179
+ lines={lines}
149
180
  />
150
181
  );
151
182
  }
@@ -163,7 +194,12 @@ export function PeopleCell({ people, fallbackName = 'Unassigned' }: PeopleCellPr
163
194
  people={people.map(p => ({ key: p.key, name: p.name || 'Unknown', avatarUrl: p.avatarUrl }))}
164
195
  />
165
196
  </div>
166
- <p className="line-clamp-2 min-w-0 flex-1 break-words text-ods-text-primary text-h6">
197
+ <p
198
+ className={cn(
199
+ 'min-w-0 flex-1 break-words text-ods-text-primary text-h6',
200
+ lines === 1 ? 'line-clamp-1' : 'line-clamp-2',
201
+ )}
202
+ >
167
203
  <span aria-hidden>{people.map(p => personFirstName(p.name, 'Unknown')).join(' & ')}</span>
168
204
  <span className="sr-only">{fullNames}</span>
169
205
  </p>
@@ -27,6 +27,12 @@ type ProgressBarProps = {
27
27
  height?: number; // desktop height (px)
28
28
  mobileHeight?: number; // mobile height (px)
29
29
  inverted?: boolean; // if true, high values are good (green), low values are bad (red)
30
+ /**
31
+ * `threshold` (default): the fill takes the success, warning or error colour by the thresholds. `neutral`: the fill
32
+ * is the secondary text colour at every value, for a count that is progress, not a health reading (a sign-off
33
+ * count), so a partial bar never reads as an error.
34
+ */
35
+ tone?: 'threshold' | 'neutral';
30
36
  /** The value is still being read: the bar draws its `ProgressBarSkeleton` at its own height. A loading scope does
31
37
  * the same. */
32
38
  loading?: boolean;
@@ -42,6 +48,7 @@ export const ProgressBar: React.FC<ProgressBarProps> = ({
42
48
  height = PROGRESS_BAR_HEIGHT.desktop,
43
49
  mobileHeight = PROGRESS_BAR_HEIGHT.mobile,
44
50
  inverted = false,
51
+ tone = 'threshold',
45
52
  loading: loadingProp,
46
53
  }) => {
47
54
  // ONE switch: in a page's loading state (or while the host reads the value) the bar is its skeleton.
@@ -76,6 +83,7 @@ export const ProgressBar: React.FC<ProgressBarProps> = ({
76
83
 
77
84
  // Pick color based on thresholds using ODS design tokens
78
85
  const getColor = () => {
86
+ if (tone === 'neutral') return 'var(--color-text-secondary)';
79
87
  if (inverted) {
80
88
  // Inverted: high values = good (green), low values = bad (red)
81
89
  // For battery health: 100% = green, <30% = red
@@ -201,6 +201,20 @@ function isEmptyTagLabel(label: React.ReactNode): boolean {
201
201
  return label == null || label === false || (typeof label === 'string' && label.trim() === '');
202
202
  }
203
203
 
204
+ /** The tones a badge colour keeps when it is drawn as a tag. */
205
+ const BADGE_COLOR_TAG_TONES = ['success', 'warning', 'error'] as const;
206
+
207
+ /**
208
+ * THE tag variant for a badge colour that is data (a `StatusBadge` colour scheme a vocabulary row stores): the three
209
+ * semantic tones carry over, every other colour reads grey. Every card that draws such a colour as a tag reads it
210
+ * here, so a status is the same tone in a badge and in a chat card.
211
+ */
212
+ export function tagVariantForBadgeColor(
213
+ color: string | null | undefined,
214
+ ): (typeof BADGE_COLOR_TAG_TONES)[number] | 'grey' {
215
+ return BADGE_COLOR_TAG_TONES.find(tone => tone === color) ?? 'grey';
216
+ }
217
+
204
218
  export { Tag, tagVariants };
205
219
 
206
220
  /**
@@ -3,9 +3,11 @@
3
3
  //
4
4
  // Participant sections are keyed by the employee DEPARTMENT (FK to the ONE
5
5
  // `departments` table — see department.ts); there is no function enum.
6
- // A doc has no status: it is READY when every section is signed off and no
7
- // blocking comment is open. That math lives in the hub's
6
+ // A doc's READINESS is derived: it is ready when every section is signed off and
7
+ // no blocking comment is open. That math lives in the hub's
8
8
  // `lib/utils/design-doc-gate.ts` (isomorphic, shared by server + client).
9
+ // Beside it a PERSON may set a lifecycle status (`lifecycle_status`: postponed,
10
+ // shipped, archived), which replaces readiness on every surface while it is set.
9
11
 
10
12
  // MIGRATION NOTE (2026-09-11). This file dropped `status`, `DesignDocStatus`,
11
13
  // `DesignDocStatusTransition`, `approved_at`, `dri_vacated_by`, `by_status` and
@@ -53,7 +55,15 @@ import type { EntityAuthor } from './entity-author';
53
55
  /** One value of `design_doc_vocabulary.kind` — the STRUCTURAL list (one per
54
56
  * value column), the only design-doc vocabulary that is code. */
55
57
  export type DesignDocVocabularyKind =
56
- 'tier' | 'spec_mode' | 'participant_status' | 'comment_type' | 'comment_status' | 'link_type' | 'media_type';
58
+ | 'tier'
59
+ | 'spec_mode'
60
+ | 'participant_status'
61
+ | 'comment_type'
62
+ | 'comment_status'
63
+ | 'link_type'
64
+ | 'media_type'
65
+ | 'lifecycle_status'
66
+ | 'readiness';
57
67
 
58
68
  /** A `design_doc_vocabulary` row, as the DAL and the vocabulary API return it. */
59
69
  export interface DesignDocVocabularyOption {
@@ -107,6 +117,24 @@ export type DesignDocCommentStatus = string;
107
117
  export type DesignDocLinkType = string;
108
118
  /** A `design_doc_vocabulary.value` of kind `media_type`. */
109
119
  export type DesignDocMediaType = string;
120
+ /**
121
+ * A `design_doc_vocabulary.value` of kind `lifecycle_status`: a status a PERSON sets (postponed, shipped, archived),
122
+ * beside the readiness the sign-offs decide. Null on a doc = active, and its readiness shows.
123
+ */
124
+ export type DesignDocLifecycleStatus = string;
125
+ /**
126
+ * A `design_doc_vocabulary.value` of kind `readiness`: the stage the sign-offs put a doc in (not ready, in active
127
+ * work, blocked, ready to build). The hub picks the row by its role; the words and the colour are the row's.
128
+ */
129
+ export type DesignDocReadiness = string;
130
+
131
+ /** A vocabulary value as a card shows it, resolved by the hub so a surface without the vocabulary can draw it. */
132
+ export interface DesignDocVocabularyDisplay {
133
+ value: string;
134
+ label: string;
135
+ /** A `StatusBadge` colorScheme name. */
136
+ color_scheme: string;
137
+ }
110
138
 
111
139
  // ---------------------------------------------------------------------------
112
140
  // Rows (as returned by the hub DAL — hydrated)
@@ -258,6 +286,15 @@ export interface DesignDoc {
258
286
  comments: DesignDocComment[];
259
287
  completion: DesignDocCompletion;
260
288
  my_open_work?: DesignDocMyOpenWork;
289
+ /** The status a person set (postponed, shipped, archived); null = active, its readiness shows. */
290
+ lifecycle_status: DesignDocLifecycleStatus | null;
291
+ /** That status as the vocabulary words it, resolved by the hub (null when none is set). */
292
+ lifecycle?: DesignDocVocabularyDisplay | null;
293
+ /** When the status was last set or cleared, and by whom. */
294
+ lifecycle_status_changed_at: string | null;
295
+ lifecycle_status_changed_by?: DesignDocPerson | null;
296
+ /** The stage its sign-offs put it in, as the vocabulary words it, resolved by the hub. */
297
+ readiness?: DesignDocVocabularyDisplay | null;
261
298
  }
262
299
 
263
300
  // ---------------------------------------------------------------------------
@@ -328,6 +365,8 @@ export interface UpdateDesignDocData {
328
365
  */
329
366
  feature_lead_ids?: string[];
330
367
  links?: DesignDocLinkInput[];
368
+ /** A `lifecycle_status` value, or null to make the doc active again. Anyone who may edit the doc may set it. */
369
+ lifecycle_status?: DesignDocLifecycleStatus | null;
331
370
  /** OCC token — the `updated_at` the editor seeded from; mismatch → 409. */
332
371
  expected_updated_at?: string;
333
372
  }
@@ -358,10 +397,18 @@ export interface AddDesignDocCommentData {
358
397
  body: string;
359
398
  }
360
399
 
361
- /** The dashboard's readiness filter (`?ready=`). */
362
- export type DesignDocReadyFilter = 'ready' | 'not_ready';
400
+ /** The dashboard's readiness filter (`?ready=`): one `readiness` value. */
401
+ export type DesignDocReadyFilter = DesignDocReadiness;
402
+
403
+ /**
404
+ * The dashboard's status filter (`?status=`): `active` (no lifecycle status set, the default) or one
405
+ * `lifecycle_status` value.
406
+ */
407
+ export type DesignDocLifecycleFilter = 'active' | DesignDocLifecycleStatus;
363
408
 
364
409
  export interface DesignDocFilters {
410
+ /** Defaults to `active`: a doc a person postponed, shipped or archived is listed only under its own status. */
411
+ lifecycle?: DesignDocLifecycleFilter;
365
412
  ready?: DesignDocReadyFilter;
366
413
  /** One or more `spec_mode` values (CSV on the wire). */
367
414
  spec_mode?: string;
@@ -378,16 +425,18 @@ export interface DesignDocListResponse {
378
425
  * filter itself — so a filtered row still shows what the other value holds. */
379
426
  facets: {
380
427
  spec_mode: Record<string, number>;
381
- /** The same over readiness (`ready` / `not_ready`), MINUS the ready filter itself: the filter row's options. */
382
- ready: Record<'ready' | 'not_ready', number>;
428
+ /** The same over readiness (each `readiness` value), MINUS the ready filter itself: the filter row's options. */
429
+ ready: Record<DesignDocReadiness, number>;
430
+ /** The same over the status filter (`active` and each `lifecycle_status` value), MINUS the status filter itself. */
431
+ lifecycle: Record<string, number>;
383
432
  };
384
433
  }
385
434
 
435
+ /** Counted over ACTIVE docs (no lifecycle status), so postponed, shipped and archived docs never inflate open work. */
386
436
  export interface DesignDocStats {
387
437
  total: number;
388
- /** Docs whose every section is signed off with no open blocking comment. */
389
- ready: number;
390
- not_ready: number;
438
+ /** How many active docs each `readiness` value holds, zeros included. */
439
+ readiness: Record<DesignDocReadiness, number>;
391
440
  waiting_on_me_docs: number;
392
441
  waiting_on_me_tasks: number;
393
442
  }
@@ -75,12 +75,12 @@ export interface DocSourceDal<Client = unknown> {
75
75
  * Doc-source registry id. The lib's `<DocViewer>` is generic over this union
76
76
  * — the hub's `DOC_SOURCES` registry defines the actual ids. Listed here as a
77
77
  * type-only union so the lib can flow the id into `DocRenderHandlers.sourceId`
78
- * without callers having to cast `string` → `'openframe-docs' | 'data-room-docs'`.
78
+ * without callers having to cast `string` to the union.
79
79
  *
80
80
  * Adding a new source = add the id here AND register it in the hub. The lib
81
81
  * never reaches into the registry — this is purely a type-narrowing handle.
82
82
  */
83
- export type DocSourceId = 'openframe-docs' | 'data-room-docs';
83
+ export type DocSourceId = 'openframe-docs' | 'data-room-docs' | 'company-policies';
84
84
 
85
85
  /**
86
86
  * Result returned by the resolve-link endpoint. Discriminator-style: `success`
@@ -1,34 +1,33 @@
1
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.
2
+ * A design doc's status as every surface draws it (the hub's design-docs screens, its doc page, the lib's design-doc
3
+ * cards), and its sign-off caption.
4
+ *
5
+ * Both halves of the status are vocabulary rows the hub resolves onto the doc, so no surface holds a word or a colour:
6
+ * - its READINESS (`doc.readiness`): the stage the sign-offs put it in (not ready, in active work, blocked, ready to
7
+ * build), picked by the hub from the `readiness` rows by role;
8
+ * - a LIFECYCLE status a person set (`doc.lifecycle`: postponed, shipped, archived). While one is set it is what the
9
+ * doc shows; cleared, the readiness shows again.
10
+ *
11
+ * The sign-off caption is counts only ("4/6 signed off · 1 blocking"): the status has its own badge.
12
+ * Pure, zero-import beyond the type.
5
13
  */
6
- import type { DesignDocCompletion } from '../types/design-doc';
14
+ import type { DesignDoc, DesignDocCompletion, DesignDocVocabularyDisplay } from '../types/design-doc';
7
15
 
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';
16
+ /** What the doc's status badge says: its lifecycle status when a person set one, else its readiness (null from a hub
17
+ * that resolves neither). */
18
+ export function designDocStatusDisplay(
19
+ doc: Pick<DesignDoc, 'lifecycle' | 'readiness'>,
20
+ ): DesignDocVocabularyDisplay | null {
21
+ return doc.lifecycle ?? doc.readiness ?? null;
22
+ }
23
23
 
24
- /** "4/6 reviews signed off" */
24
+ /** "4/6 signed off" */
25
25
  export function formatCompletionLabel(completion: Pick<DesignDocCompletion, 'total' | 'completed'>): string {
26
- return `${completion.completed}/${completion.total} reviews signed off`;
26
+ return `${completion.completed}/${completion.total} signed off`;
27
27
  }
28
28
 
29
- /** The SAME label plus readiness and the blocking veto (the dashboard row, the doc page, the card). */
29
+ /** The SAME count plus the blocking veto ("4/6 signed off · 1 blocking"): the dashboard row, the doc page, the card. */
30
30
  export function formatCompletionLabelWithBlockers(completion: DesignDocCompletion): string {
31
31
  const base = formatCompletionLabel(completion);
32
- if (completion.isComplete) return `${DESIGN_DOC_READINESS_DISPLAY.ready.label} · ${base}`;
33
32
  return completion.openBlocking > 0 ? `${base} · ${completion.openBlocking} blocking` : base;
34
33
  }
@@ -102,3 +102,30 @@ export function getDocSourceDefaultPath(
102
102
  const firstFolderWithReadme = structure.find(node => node.type === 'folder' && node.hasReadme && !!node.path);
103
103
  return firstFolderWithReadme?.path ?? null;
104
104
  }
105
+
106
+ /** The first document under a folder (its own files first, then each subfolder's, in order), never a diagram source. */
107
+ export function findFirstDocPath(folder: DocNode): string | null {
108
+ const children = folder.children ?? [];
109
+ for (const child of children) {
110
+ if (child.type === 'file' && !child.path.toLowerCase().endsWith('.mmd')) return child.path;
111
+ }
112
+ for (const child of children) {
113
+ if (child.type === 'folder') {
114
+ const nested = findFirstDocPath(child);
115
+ if (nested) return nested;
116
+ }
117
+ }
118
+ return null;
119
+ }
120
+
121
+ /**
122
+ * The document a source's root shows: its folder index when the tree has one, else its first document (the rule a
123
+ * folder with no README follows), else null (a tree with no document at all).
124
+ */
125
+ export function rootDocumentPath(
126
+ structure: DocNode[],
127
+ folderIndexFile: string = DEFAULT_FOLDER_INDEX_FILE,
128
+ ): string | null {
129
+ if (structure.some(node => node.type === 'file' && node.path === folderIndexFile)) return folderIndexFile;
130
+ return findFirstDocPath({ id: '', name: '', slug: '', path: '', type: 'folder', children: structure });
131
+ }
@@ -99,7 +99,8 @@ const BUILDERS: Record<string, (ids: string[], base: string) => string> = {
99
99
  slack_message: (ids, b) => `${b}/api/slack-community/messages?ids=${ids.join(',')}`,
100
100
  hubspot_ticket: (ids, b) => `${b}/api/tickets/internal?ids=${ids.join(',')}`,
101
101
  hubspot_ticket_anon: (ids, b) => `${b}/api/tickets/known-issues?ids=${ids.join(',')}`,
102
- data_room_doc: (ids, b) => `${b}/api/data-room/documents?ids=${ids.join(',')}`,
102
+ data_room_doc: (ids, b) => `${b}/api/libraries/data-room/documents?ids=${ids.join(',')}`,
103
+ policy_doc: (ids, b) => `${b}/api/libraries/company-policies/documents?ids=${ids.join(',')}`,
103
104
  markdown: (ids, b) => `${b}/api/docs/pages?ids=${ids.join(',')}`,
104
105
  financial_kpi: (ids, b) => `${b}/api/financials/kpis?ids=${ids.join(',')}`,
105
106
  cap_table: (ids, b) => `${b}/api/financials/cap-table?ids=${ids.join(',')}`,
@@ -27,13 +27,13 @@ import { defaultDocumentTypeForTableId, getSourceLabel } from './source-icons';
27
27
 
28
28
  /**
29
29
  * Doc-table documentTypes: whole documents with their own viewer (markdown =
30
- * product docs, data_room_doc = data room). They carry an in-app `path` (handed
30
+ * product docs, data_room_doc = data room, policy_doc = company policies). They carry an in-app `path` (handed
31
31
  * to the host's composer as the slug), and a server never folds them
32
32
  * into one citation (`groupsByTable`); the strip still draws them as one chip
33
33
  * per table. The hub's per-source contract test pins this list to its
34
34
  * doc-table configs.
35
35
  */
36
- export const DOC_TABLE_TYPES = ['markdown', 'data_room_doc'] as const;
36
+ export const DOC_TABLE_TYPES = ['markdown', 'data_room_doc', 'policy_doc'] as const;
37
37
 
38
38
  /**
39
39
  * Which tables a SERVER folds into one citation: rows of a knowledge table
@@ -29,6 +29,7 @@ export const SOURCE_ICON_NAMES: Record<string, string> = {
29
29
  // Doc tables
30
30
  'openframe-docs': 'openframe',
31
31
  'data-room-docs': 'shield',
32
+ 'company-policies': 'book-open',
32
33
 
33
34
  // CMS / programs
34
35
  'blog-posts': 'newspaper',
@@ -136,6 +137,7 @@ export const SOURCE_LABELS_BY_TABLE: Record<string, string> = {
136
137
  // Doc tables
137
138
  'openframe-docs': 'OpenFrame Docs',
138
139
  'data-room-docs': 'Data Room',
140
+ 'company-policies': 'Company Policies',
139
141
 
140
142
  // CMS / programs
141
143
  'blog-posts': 'Blog Posts',
@@ -242,6 +244,7 @@ export const DEFAULT_DOCUMENT_TYPE_TO_TABLE_ID: Record<string, string> = {
242
244
  // Doc tables
243
245
  markdown: 'openframe-docs',
244
246
  data_room_doc: 'data-room-docs',
247
+ policy_doc: 'company-policies',
245
248
 
246
249
  // CMS / programs
247
250
  blog_post: 'blog-posts',
@@ -1,25 +0,0 @@
1
- export declare function MarkdownSkeleton({ region, }?: {
2
- /** The loading state announces itself (`LoadingRegion`). `false` inside another loading region. Default `true`. */
3
- region?: boolean;
4
- }): import("react").JSX.Element;
5
- /**
6
- * Embed-style skeleton — matches the iframe loading state for `pdf`,
7
- * `google_sheet`, `figma`, and `file` document types. Used by
8
- * `<DocsHubPage>` as the default for non-markdown documentTypes.
9
- *
10
- * The skeleton is documentType-aware so its layout matches the actual
11
- * viewer that will replace it:
12
- * - `pdf` → header with title + TWO buttons (Preview, Download)
13
- * - `google_sheet`/`figma` → header with title + ONE button/toggle
14
- * - `file` → centered FileDownloadCard-style box
15
- * - undefined / others → generic (1-button header)
16
- */
17
- export interface EmbedSkeletonProps {
18
- /** When provided, the header layout matches the eventual viewer's
19
- * button count + arrangement, so the layout doesn't shift on load. */
20
- documentType?: 'pdf' | 'google_sheet' | 'figma' | 'file' | string;
21
- /** The loading state announces itself (`LoadingRegion`). `false` inside another loading region. Default `true`. */
22
- region?: boolean;
23
- }
24
- export declare function EmbedSkeleton({ documentType, region }?: EmbedSkeletonProps): import("react").JSX.Element;
25
- //# sourceMappingURL=skeletons.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skeletons.d.ts","sourceRoot":"","sources":["../../../src/components/docs/skeletons.tsx"],"names":[],"mappings":"AA2BA,wBAAgB,gBAAgB,CAAC,EAC/B,MAAa,GACd,GAAE;IACD,mHAAmH;IACnH,MAAM,CAAC,EAAE,OAAO,CAAC;CACb,+BA2BL;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAkB;IACjC;2EACuE;IACvE,YAAY,CAAC,EAAE,KAAK,GAAG,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAClE,mHAAmH;IACnH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,aAAa,CAAC,EAAE,YAAY,EAAE,MAAa,EAAE,GAAE,kBAAuB,+BAiDrF"}