@flamingo-stack/openframe-frontend-core 0.0.724 → 0.0.726

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 (102) hide show
  1. package/dist/{chunk-N2PX26BZ.js → chunk-2MMZTACD.js} +2 -2
  2. package/dist/{chunk-2HLGX6JF.js → chunk-3UZET2G7.js} +5 -5
  3. package/dist/{chunk-NLZZUWR6.js → chunk-3XDVGHL4.js} +4 -4
  4. package/dist/{chunk-L5CAET76.cjs → chunk-4ND65E2B.cjs} +64 -64
  5. package/dist/{chunk-OFOBVPDV.js → chunk-4VRHDFF2.js} +2 -2
  6. package/dist/{chunk-QJ67GFF3.cjs → chunk-5SWQ2ZU5.cjs} +32 -32
  7. package/dist/{chunk-CJENFR5T.js → chunk-6EFNWQRY.js} +1 -1
  8. package/dist/{chunk-7CNGNPBI.js → chunk-AZKVHJA5.js} +3 -3
  9. package/dist/{chunk-QN3OXRTM.js → chunk-C5KMQLJP.js} +5 -5
  10. package/dist/{chunk-MU5F5QXJ.js → chunk-COFT3YPA.js} +6 -6
  11. package/dist/{chunk-ZKL52ALL.cjs → chunk-DXDLCYCM.cjs} +3 -3
  12. package/dist/{chunk-3MMKIVWZ.cjs → chunk-EHYAOIE4.cjs} +23 -23
  13. package/dist/{chunk-5CJGNPTT.cjs → chunk-FMFCPX3R.cjs} +35 -35
  14. package/dist/{chunk-DGNGABNG.cjs → chunk-HEQ4GPYE.cjs} +4 -4
  15. package/dist/{chunk-JKWQWHNV.cjs → chunk-IITB5TJR.cjs} +4 -1
  16. package/dist/{chunk-MRBPJ4NB.js → chunk-JXJFUGJY.js} +1 -1
  17. package/dist/{chunk-BWMEQ7IZ.js → chunk-JYJBL7GD.js} +1 -1
  18. package/dist/{chunk-YKV45BSJ.cjs → chunk-KLCOSY7B.cjs} +4 -4
  19. package/dist/{chunk-QUI7DKBW.cjs → chunk-KNLRL63O.cjs} +41 -41
  20. package/dist/{chunk-PF4WAKCS.js → chunk-MM66P4X4.js} +4 -4
  21. package/dist/{chunk-6QO6BIX7.js → chunk-MQ3ZM7FJ.js} +1 -1
  22. package/dist/{chunk-OWFDXYEO.js → chunk-MSPXMSMY.js} +1 -1
  23. package/dist/{chunk-SOTXV3T5.cjs → chunk-MZ3TMXIX.cjs} +3 -3
  24. package/dist/{chunk-BIWG3CYN.cjs → chunk-MZY6LBM5.cjs} +3 -3
  25. package/dist/{chunk-7AXOAA5T.cjs → chunk-NJV3LIDE.cjs} +3 -3
  26. package/dist/{chunk-IUQKIU5A.js → chunk-NLWIBA55.js} +6 -6
  27. package/dist/{chunk-4N5DLIEC.js → chunk-NZYMMYWN.js} +1 -1
  28. package/dist/{chunk-GRB5HVEV.cjs → chunk-Q2G7NVFH.cjs} +505 -505
  29. package/dist/{chunk-IPUDFAU5.cjs → chunk-R3BOJNZI.cjs} +31 -31
  30. package/dist/{chunk-SVDXNMBL.cjs → chunk-RSE3MU4G.cjs} +16 -16
  31. package/dist/{chunk-3NVSC3BU.cjs → chunk-RVSNXG6J.cjs} +246 -267
  32. package/dist/{chunk-S4SVKXHN.js → chunk-SBPPM65Y.js} +54 -75
  33. package/dist/{chunk-KKO4GRM3.js → chunk-SCTS3EMJ.js} +4 -4
  34. package/dist/{chunk-VLPGV5WH.js → chunk-TU5LEF6A.js} +1 -1
  35. package/dist/{chunk-N4NGKXUU.cjs → chunk-U6LRRG2E.cjs} +15 -15
  36. package/dist/{chunk-6BKDXUOQ.js → chunk-VKR56R3U.js} +6 -6
  37. package/dist/{chunk-FR4MFSH5.cjs → chunk-VPABPC2M.cjs} +19 -19
  38. package/dist/{chunk-2A4AGW7Z.cjs → chunk-X2PG6XWF.cjs} +11 -11
  39. package/dist/{chunk-JQ7A7PO5.cjs → chunk-XEIDJ6SL.cjs} +76 -76
  40. package/dist/{chunk-ZQKN2Z6W.js → chunk-YQDKVGKO.js} +4 -1
  41. package/dist/{chunk-XDTD6YGG.js → chunk-YVWJ3TRY.js} +7 -7
  42. package/dist/{chunk-A4WHVIYZ.cjs → chunk-Z3VAFLYK.cjs} +17 -17
  43. package/dist/{cloud-tenants-UMZJZTMB.cjs → cloud-tenants-5JTQ2ENQ.cjs} +7 -7
  44. package/dist/{cloud-tenants-5MINXS5J.js → cloud-tenants-NH7VE7KE.js} +6 -6
  45. package/dist/components/case-studies/index.cjs +20 -20
  46. package/dist/components/case-studies/index.js +7 -7
  47. package/dist/components/chat/entity-cards/dispatch.d.ts.map +1 -1
  48. package/dist/components/chat/index.cjs +5 -5
  49. package/dist/components/chat/index.js +4 -4
  50. package/dist/components/chat/utils/icon-library.d.ts.map +1 -1
  51. package/dist/components/contact/index.cjs +8 -8
  52. package/dist/components/contact/index.js +7 -7
  53. package/dist/components/docs/index.cjs +11 -11
  54. package/dist/components/docs/index.js +10 -10
  55. package/dist/components/embeds/index.cjs +8 -8
  56. package/dist/components/embeds/index.js +7 -7
  57. package/dist/components/faq/index.cjs +8 -8
  58. package/dist/components/faq/index.js +7 -7
  59. package/dist/components/features/index.cjs +7 -7
  60. package/dist/components/features/index.js +6 -6
  61. package/dist/components/help-center-pages/index.cjs +106 -106
  62. package/dist/components/help-center-pages/index.js +18 -18
  63. package/dist/components/index.cjs +55 -55
  64. package/dist/components/index.js +18 -18
  65. package/dist/components/meeting-scheduler/index.cjs +32 -32
  66. package/dist/components/meeting-scheduler/index.js +6 -6
  67. package/dist/components/navigation/index.cjs +10 -10
  68. package/dist/components/navigation/index.js +9 -9
  69. package/dist/components/onboarding-guides/index.cjs +10 -10
  70. package/dist/components/onboarding-guides/index.js +9 -9
  71. package/dist/components/product-demo/index.cjs +7 -7
  72. package/dist/components/product-demo/index.js +7 -7
  73. package/dist/components/related-content/index.cjs +4 -4
  74. package/dist/components/related-content/index.js +3 -3
  75. package/dist/components/tickets/index.cjs +11 -11
  76. package/dist/components/tickets/index.js +10 -10
  77. package/dist/components/ui/index.cjs +7 -7
  78. package/dist/components/ui/index.js +6 -6
  79. package/dist/{devices-FSSUAUQN.js → devices-OC7JEI6U.js} +6 -6
  80. package/dist/{devices-HOT7YSDN.cjs → devices-PV76NGQO.cjs} +8 -8
  81. package/dist/index.cjs +11 -11
  82. package/dist/index.js +10 -10
  83. package/dist/{knowledge-3N6HCFLU.cjs → knowledge-5AYFIVKD.cjs} +8 -8
  84. package/dist/{knowledge-7HRUJX26.js → knowledge-L7WQ7IEP.js} +6 -6
  85. package/dist/{logs-75M5YP6V.cjs → logs-4F77RJXJ.cjs} +15 -15
  86. package/dist/{logs-T25OE2QW.js → logs-MGFHGVIE.js} +6 -6
  87. package/dist/{policies-BTG7UJJC.cjs → policies-VCGM3C5Z.cjs} +11 -11
  88. package/dist/{policies-4OK4XTD4.js → policies-WRDZFNIB.js} +6 -6
  89. package/dist/{remote-session-4DTOM3QD.cjs → remote-session-CSX6ESSG.cjs} +5 -5
  90. package/dist/{remote-session-AZJXG7ZF.js → remote-session-ZBCWD5A5.js} +3 -3
  91. package/dist/{software-update-5SOV4FIR.js → software-update-WVG2GDZO.js} +6 -6
  92. package/dist/{software-update-OZURO4VK.cjs → software-update-YD2MNL3K.cjs} +11 -11
  93. package/dist/utils/index.cjs +17 -18
  94. package/dist/utils/index.js +17 -18
  95. package/dist/utils/source-grouping.d.ts +15 -5
  96. package/dist/utils/source-grouping.d.ts.map +1 -1
  97. package/package.json +1 -1
  98. package/src/components/chat/entity-cards/dispatch.tsx +47 -58
  99. package/src/components/chat/utils/icon-library.tsx +8 -3
  100. package/src/components/chat/utils/source-row-cta.ts +3 -3
  101. package/src/utils/source-grouping.ts +24 -14
  102. package/src/utils/source-icons.ts +16 -16
@@ -3573,11 +3573,11 @@ var SOURCE_ICON_NAMES = {
3573
3573
  vendors: "package-search",
3574
3574
  // Financials
3575
3575
  "investor-updates": "mail",
3576
- "financial-kpis": "activity",
3577
- "financial-cap-table": "table",
3578
- "financial-pnl": "trending-up",
3579
- "financial-balance-sheet": "dollar-sign",
3580
- "financial-cash-flow": "banknote",
3576
+ "financial-kpis": "chart-bar-01-ver",
3577
+ "financial-cap-table": "chart-pie",
3578
+ "financial-pnl": "money-bill-dollar",
3579
+ "financial-balance-sheet": "bank",
3580
+ "financial-cash-flow": "coins-exchange-currency",
3581
3581
  // ClickUp
3582
3582
  "clickup-roadmap": "clickup",
3583
3583
  "clickup-delivery": "clickup",
@@ -3596,22 +3596,22 @@ var SOURCE_ICON_NAMES = {
3596
3596
  // Communications
3597
3597
  "slack-messages": "slack",
3598
3598
  // People-hub employee content
3599
- "what-i-shipped": "package",
3600
- "how-i-work": "book-open",
3601
- "ai-prompts": "message-square",
3599
+ "what-i-shipped": "rocket-02",
3600
+ "how-i-work": "clipboard-list",
3601
+ "ai-prompts": "chat-quote",
3602
3602
  // Product-hub internal
3603
3603
  "design-docs": "file-text",
3604
3604
  "openframe-tenants": "openframe",
3605
- "prospect-calls": "phone",
3605
+ "prospect-calls": "call",
3606
3606
  // Code intelligence
3607
- "code-rules": "check-square",
3608
- "code-graph-repos": "github",
3607
+ "code-rules": "bracket-curly-check",
3608
+ "code-graph-repos": "coding-branch",
3609
3609
  "code-graph-deployments": "package",
3610
- "code-graph-files": "file-text",
3611
- "code-symbols": "box",
3612
- "code-duplicates": "search",
3613
- "code-impact": "activity",
3614
- "change-sets": "coding-branch"
3610
+ "code-graph-files": "file-code",
3611
+ "code-symbols": "code-square",
3612
+ "code-duplicates": "copy-01",
3613
+ "code-impact": "coding-pull-request",
3614
+ "change-sets": "coding-merge"
3615
3615
  };
3616
3616
  function getSourceIconName(tableId) {
3617
3617
  if (!tableId) return void 0;
@@ -3785,8 +3785,7 @@ function typeOf(source) {
3785
3785
  return source.documentType || defaultDocumentTypeForTableId(source.sourceRepo) || "";
3786
3786
  }
3787
3787
  function joinsTableChip(source) {
3788
- if (!source.sourceRepo) return false;
3789
- return groupsByTable(typeOf({ ...source, sourceRepo: source.sourceRepo }));
3788
+ return !!source.sourceRepo;
3790
3789
  }
3791
3790
  function rowsOf(source) {
3792
3791
  if (isGroupedChip(source)) return source.items ?? [];
@@ -25,13 +25,22 @@ import type { ChatSource } from '../components/chat/types/message.types';
25
25
  /**
26
26
  * Doc-table documentTypes: whole documents with their own viewer (markdown =
27
27
  * product docs, data_room_doc = data room). They carry an in-app `path`, an
28
- * embedder keys `docPlatformTargets` by them, and they NEVER group: one chip
29
- * per document. The hub's per-source contract test pins this list to its
28
+ * embedder keys `docPlatformTargets` by them, and a server never folds them
29
+ * into one citation (`groupsByTable`); the strip still draws them as one chip
30
+ * per table. The hub's per-source contract test pins this list to its
30
31
  * doc-table configs.
31
32
  */
32
33
  export declare const DOC_TABLE_TYPES: readonly ["markdown", "data_room_doc"];
33
- /** THE rule: rows of a knowledge table share one chip unless they are whole
34
- * documents. Decided by `documentType`, the one fact every producer has. */
34
+ /**
35
+ * Which tables a SERVER folds into one citation: rows of a knowledge table
36
+ * share one number (and reach the model as one table) unless they are whole
37
+ * documents, which each keep their own number and are read in full. Decided by
38
+ * `documentType`, the one fact every producer has.
39
+ *
40
+ * This is not the strip's rule. The strip (`groupSourcesByTable`) draws ONE chip
41
+ * per table for every source, documents included: a document keeps its own
42
+ * citation number inside its table's chip.
43
+ */
35
44
  export declare function groupsByTable(documentType: string | null | undefined): boolean;
36
45
  /** `(1 record)` / `(14 records)`: the count every grouped chip states. */
37
46
  export declare function recordCountLabel(count: number): string;
@@ -71,7 +80,8 @@ export declare function buildGroupedSource(spec: {
71
80
  * table's only source. When flat rows of the same table arrive beside it (a
72
81
  * hub-injected chip plus MCP-cited rows in one answer), they merge into it:
73
82
  * its rows first, its chip-level link kept, the count restated. Whole
74
- * documents and rows naming no table pass through as their own chips.
83
+ * documents group under their table too, each row keeping its own citation
84
+ * number; only a row naming no table passes through as its own chip.
75
85
  */
76
86
  export declare function groupSourcesByTable(sources: ChatSource[]): ChatSource[];
77
87
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"source-grouping.d.ts","sourceRoot":"","sources":["../../src/utils/source-grouping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAGzE;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,wCAAyC,CAAC;AAEtE;6EAC6E;AAC7E,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE9E;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,KAAK,WAAW,GAAG,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D;2EAC2E;AAC3E,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC;AAE3C;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,gBAAgB,EAAE,CAAC;IACzB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,GAAG,UAAU,CAcb;AA0DD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAqCvE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAU/D"}
1
+ {"version":3,"file":"source-grouping.d.ts","sourceRoot":"","sources":["../../src/utils/source-grouping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAGzE;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,wCAAyC,CAAC;AAEtE;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE9E;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,KAAK,WAAW,GAAG,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D;2EAC2E;AAC3E,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC;AAE3C;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,gBAAgB,EAAE,CAAC;IACzB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,GAAG,UAAU,CAcb;AA0DD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAqCvE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAU/D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flamingo-stack/openframe-frontend-core",
3
- "version": "0.0.724",
3
+ "version": "0.0.726",
4
4
  "description": "Shared design system and components for all Flamingo platforms",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -61,29 +61,14 @@ import { MingoIcon } from '../../icons';
61
61
  import { ArrowRightUpIcon } from '../../icons-v2-generated/arrows/arrow-right-up-icon';
62
62
  import { ClickupLogoIcon } from '../../icons-v2-generated/brand-logos/clickup-logo-icon';
63
63
  import { SlackLogoGreyIcon } from '../../icons-v2-generated/brand-logos/slack-logo-grey-icon';
64
- import { ChartBar01VerIcon } from '../../icons-v2-generated/charts/chart-bar-01-ver-icon';
65
- import { ChartPieIcon } from '../../icons-v2-generated/charts/chart-pie-icon';
66
64
  import { PresentationBarIcon } from '../../icons-v2-generated/charts/presentation-bar-icon';
67
65
  import { PresentationLineIcon } from '../../icons-v2-generated/charts/presentation-line-icon';
68
- import { BracketCurlyCheckIcon } from '../../icons-v2-generated/coding/bracket-curly-check-icon';
69
66
  import { CodeIcon } from '../../icons-v2-generated/coding/code-icon';
70
- import { CodeSquareIcon } from '../../icons-v2-generated/coding/code-square-icon';
71
- import { CodingBranchIcon } from '../../icons-v2-generated/coding/coding-branch-icon';
72
67
  import { CodingCommitIcon } from '../../icons-v2-generated/coding/coding-commit-icon';
73
- import { CodingMergeIcon } from '../../icons-v2-generated/coding/coding-merge-icon';
74
68
  import { CodingPullRequestIcon } from '../../icons-v2-generated/coding/coding-pull-request-icon';
75
- import { PackageIcon } from '../../icons-v2-generated/coding/package-icon';
76
- import { CallIcon } from '../../icons-v2-generated/communication/call-icon';
77
- import { ChatQuoteIcon } from '../../icons-v2-generated/communication/chat-quote-icon';
78
69
  import { CalendarIcon } from '../../icons-v2-generated/date-and-time/calendar-icon';
79
- import { ClipboardListIcon } from '../../icons-v2-generated/documents/clipboard-list-icon';
80
- import { Copy01Icon } from '../../icons-v2-generated/documents/copy-01-icon';
81
- import { FileCodeIcon } from '../../icons-v2-generated/documents/file-code-icon';
82
70
  import { FileContentIcon } from '../../icons-v2-generated/documents/file-content-icon';
83
71
  import { NewspaperIcon } from '../../icons-v2-generated/documents/newspaper-icon';
84
- import { BankIcon } from '../../icons-v2-generated/finance/bank-icon';
85
- import { CoinsExchangeCurrencyIcon } from '../../icons-v2-generated/finance/coins-exchange-currency-icon';
86
- import { MoneyBillDollarIcon } from '../../icons-v2-generated/finance/money-bill-dollar-icon';
87
72
  import { MicrophoneIcon } from '../../icons-v2-generated/household/microphone-icon';
88
73
  import { AlertTriangleIcon } from '../../icons-v2-generated/interface/alert-triangle-icon';
89
74
  import { EyeIcon } from '../../icons-v2-generated/interface/eye-icon';
@@ -113,10 +98,9 @@ import { resolveCardDestination } from '../utils/card-destination';
113
98
  import { resolveHrefForRuntime } from '../utils/chat-nav-resolution';
114
99
  import { executeNavigation } from '../utils/execute-navigation';
115
100
  import { clickupTaskUrl } from '../utils/external-app-urls';
116
- import { resolveIcon } from '../utils/icon-library';
117
101
  import { computeIsNewTab, buildAnchorProps } from '../utils/nav-anchor-props';
118
102
  import { readFetchedCardTitle } from '../utils/resolve-fetched-card-href';
119
- import { getSourceLabel, SOURCE_ICON_NAMES } from '../utils/source-icons';
103
+ import { defaultTableIdForDocumentType, getSourceLabel, SOURCE_ICON_NAMES } from '../utils/source-icons';
120
104
  import { resolveSourceIcon, sourceRowCtxFromRuntime } from '../utils/source-row-cta';
121
105
  import { BlockCard } from './block-card';
122
106
  import { BlogCardSkeleton } from './blog-card';
@@ -1393,18 +1377,16 @@ function refHydratedEntry(
1393
1377
  };
1394
1378
  }
1395
1379
 
1380
+ /** The leading glyph carries the type signal (the badge pill is dropped); it is the SOURCE's icon (`sourceGlyph`). */
1396
1381
  interface FinancialCardConfig {
1397
1382
  label: string;
1398
- /** Per-type leading glyph — carries the type signal now that the
1399
- * badge pill is dropped. */
1400
- icon: () => React.ReactNode;
1401
1383
  }
1402
1384
  const FINANCIAL_CARD_CONFIGS: Record<string, FinancialCardConfig> = {
1403
- financial_kpi: { label: 'Financial KPI', icon: () => <ChartBar01VerIcon size={24} /> },
1404
- cap_table: { label: 'Cap table entry', icon: () => <ChartPieIcon size={24} /> },
1405
- profit_loss: { label: 'P&L period', icon: () => <MoneyBillDollarIcon size={24} /> },
1406
- balance_sheet: { label: 'Balance sheet', icon: () => <BankIcon size={24} /> },
1407
- cash_flow: { label: 'Cash flow', icon: () => <CoinsExchangeCurrencyIcon size={24} /> },
1385
+ financial_kpi: { label: 'Financial KPI' },
1386
+ cap_table: { label: 'Cap table entry' },
1387
+ profit_loss: { label: 'P&L period' },
1388
+ balance_sheet: { label: 'Balance sheet' },
1389
+ cash_flow: { label: 'Cash flow' },
1408
1390
  };
1409
1391
  /** Expand a per-family config map into registry entries — ONE loop shell
1410
1392
  * for every card family (financial, github, program, roadmap); adding a
@@ -1423,7 +1405,7 @@ function financialRegistryEntries(): Record<string, ChatCardRegistryEntry> {
1423
1405
  refHydratedEntry(docType, cfg.label, (displayRef, opts) => (
1424
1406
  <GenericFinancialChatCard
1425
1407
  chatRef={displayRef}
1426
- icon={cfg.icon()}
1408
+ icon={sourceGlyph(docType)}
1427
1409
  isNewTab={opts.isNewTab}
1428
1410
  discuss={opts.discuss}
1429
1411
  />
@@ -1463,11 +1445,13 @@ const GITHUB_CARD_CONFIGS: Record<string, GitHubCardConfig> = {
1463
1445
  interface GlyphCardConfig {
1464
1446
  label: string;
1465
1447
  /**
1466
- * The card's leading glyph. It is handed the hydrated ref, so a type whose
1467
- * records carry their own mark (a vendor's logo, a page's menu icon) draws
1468
- * that and keeps a generic glyph for a record without one.
1448
+ * ONLY for a type whose records carry their own mark (a vendor's logo, a
1449
+ * page's menu icon): it is handed the hydrated ref and draws that mark.
1450
+ * Every other type leaves it out and gets its SOURCE's icon
1451
+ * (`sourceGlyph`): the one `SOURCE_ICON_NAMES` entry its chip draws too, so
1452
+ * a card and its chip can never show different icons.
1469
1453
  */
1470
- icon: (ref?: ChatRef) => React.ReactNode;
1454
+ icon?: (ref?: ChatRef) => React.ReactNode;
1471
1455
  /**
1472
1456
  * Video-bearing ref types: render the media card (cover from the ref's
1473
1457
  * `metadata.videoPoster`, else the host's OG placeholder; the type label as the
@@ -1481,41 +1465,51 @@ interface GlyphCardConfig {
1481
1465
  * (`/api/design-docs`, `/api/openframe-tenants`, `/api/prospect-calls` — ChatRef-shaped items,
1482
1466
  * same preset as github / slack). Adding one = one line here + the
1483
1467
  * `list-url.ts` builder + the `source-icons.ts` label / icon / type entries. */
1484
- /** The OpenFrame logo every OpenFrame surface uses (the `openframe` icon name). */
1485
- const OpenFrameGlyph = resolveIcon('openframe');
1486
1468
  const REF_GLYPH_CARD_CONFIGS: Record<string, GlyphCardConfig> = {
1487
- openframe_tenant: { label: 'OpenFrame tenant', icon: () => <OpenFrameGlyph size={24} /> },
1488
- prospect_call: { label: 'Prospect call', icon: () => <CallIcon size={24} />, media: true },
1469
+ openframe_tenant: { label: 'OpenFrame tenant' },
1470
+ prospect_call: { label: 'Prospect call', media: true },
1489
1471
  // Code intelligence (product-hub internal): the review rules a repository is
1490
1472
  // held to, the repositories themselves, and one row per deployment
1491
1473
  // environment. Glyph cards like their siblings — none of the three has a
1492
1474
  // cover image, and a rule is read in the admin screen it links to.
1493
- code_rule: { label: 'Code rule', icon: () => <BracketCurlyCheckIcon size={24} /> },
1494
- code_repo: { label: 'Repository', icon: () => <CodingBranchIcon size={24} /> },
1495
- code_deployment: { label: 'Deployment', icon: () => <PackageIcon size={24} /> },
1475
+ code_rule: { label: 'Code rule' },
1476
+ code_repo: { label: 'Repository' },
1477
+ code_deployment: { label: 'Deployment' },
1496
1478
  // The graph's own objects: one source file's public surface, one public
1497
1479
  // symbol, a near-duplicate cluster, and a pull request's blast radius.
1498
1480
  // Glyph cards for the same reason as their three siblings — none carries a
1499
1481
  // cover image, and each links to the admin screen that renders it in full.
1500
- code_file: { label: 'Code file', icon: () => <FileCodeIcon size={24} /> },
1501
- code_symbol: { label: 'Code symbol', icon: () => <CodeSquareIcon size={24} /> },
1502
- code_duplicate: { label: 'Duplicate code', icon: () => <Copy01Icon size={24} /> },
1503
- code_impact: { label: 'Change impact', icon: () => <CodingPullRequestIcon size={24} /> },
1482
+ code_file: { label: 'Code file' },
1483
+ code_symbol: { label: 'Code symbol' },
1484
+ code_duplicate: { label: 'Duplicate code' },
1485
+ code_impact: { label: 'Change impact' },
1504
1486
  // A change set: pull requests across repositories declared as one change, with the ClickUp tasks and design
1505
1487
  // docs its pull requests are attached to. ONE card for it wherever a set is shown (chat, a design doc's page).
1506
- change_set: { label: 'Change set', icon: () => <CodingMergeIcon size={24} /> },
1488
+ change_set: { label: 'Change set' },
1507
1489
  // A page of the public website (pricing, product, legal, and every page the navigation lists), read live
1508
1490
  // from the data the page shows. A glyph card: a page has no cover of its own, and the card opens the page.
1509
1491
  site_page: { label: 'Website page', icon: ref => <SitePageGlyph iconName={refText(ref, 'icon_name')} /> },
1510
1492
  // What OpenFrame charges, read live from its billing: the plan in force, or one AI model's token exchange
1511
1493
  // rate. A glyph card; it opens the pricing page.
1512
- openframe_price: { label: 'OpenFrame price', icon: () => <OpenFrameGlyph size={24} /> },
1494
+ openframe_price: { label: 'OpenFrame price' },
1513
1495
  // A vendor (product) of the OpenMSP directory. A glyph card; it opens the vendor's page there.
1514
1496
  vendor: { label: 'Vendor', icon: ref => <VendorGlyph title={ref?.title ?? ''} logoUrl={refText(ref, 'logo_url')} /> },
1515
1497
  };
1498
+ /**
1499
+ * A card type's icon: its SOURCE's, resolved exactly as the source's chip
1500
+ * resolves it (`resolveSourceIcon` over `SOURCE_ICON_NAMES`). One name per
1501
+ * source, one resolver, so a card and its chip always match.
1502
+ */
1503
+ function sourceGlyph(docType: string): React.ReactNode {
1504
+ const { Icon } = resolveSourceIcon({ sourceRepo: defaultTableIdForDocumentType(docType), documentType: docType });
1505
+ return <Icon className="size-6" />;
1506
+ }
1507
+
1516
1508
  function refGlyphRegistryEntries(): Record<string, ChatCardRegistryEntry> {
1517
- return registryEntries(REF_GLYPH_CARD_CONFIGS, (cfg, docType) =>
1518
- refHydratedEntry(docType, cfg.label, (displayRef, opts) =>
1509
+ return registryEntries(REF_GLYPH_CARD_CONFIGS, (config, docType) => {
1510
+ const glyph = config.icon ?? (() => sourceGlyph(docType));
1511
+ const cfg = config;
1512
+ return refHydratedEntry(docType, cfg.label, (displayRef, opts) =>
1519
1513
  cfg.media ? (
1520
1514
  <EntityMingoCard
1521
1515
  title={displayRef.title}
@@ -1524,7 +1518,7 @@ function refGlyphRegistryEntries(): Record<string, ChatCardRegistryEntry> {
1524
1518
  displayRef.metadata?.videoPoster,
1525
1519
  opts.extras?.buildOgPlaceholderUrl?.(displayRef.title ?? '') ?? null,
1526
1520
  )}
1527
- fallbackIcon={cfg.icon(displayRef)}
1521
+ fallbackIcon={glyph(displayRef)}
1528
1522
  status={{ label: cfg.label, variant: 'grey' }}
1529
1523
  chatRef={displayRef}
1530
1524
  isNewTab={opts.isNewTab}
@@ -1532,15 +1526,10 @@ function refGlyphRegistryEntries(): Record<string, ChatCardRegistryEntry> {
1532
1526
  menuAriaLabel={`${cfg.label} actions`}
1533
1527
  />
1534
1528
  ) : (
1535
- <GlyphChatCard
1536
- chatRef={displayRef}
1537
- icon={cfg.icon(displayRef)}
1538
- isNewTab={opts.isNewTab}
1539
- discuss={opts.discuss}
1540
- />
1529
+ <GlyphChatCard chatRef={displayRef} icon={glyph(displayRef)} isNewTab={opts.isNewTab} discuss={opts.discuss} />
1541
1530
  ),
1542
- ),
1543
- );
1531
+ );
1532
+ });
1544
1533
  }
1545
1534
 
1546
1535
  /** People-hub employee feeds hydrate from their EXISTING list APIs
@@ -1558,9 +1547,9 @@ function fetchedEmployeeEntryDisplayRef(item: unknown, chatRef: ChatRef): ChatRe
1558
1547
  return { ...chatRef, title, preview: preview.length > 0 ? preview : chatRef.preview };
1559
1548
  }
1560
1549
  const EMPLOYEE_ENTRY_CARD_CONFIGS: Record<string, GlyphCardConfig> = {
1561
- what_i_shipped: { label: 'What I Shipped', icon: () => <Rocket02Icon size={24} /> },
1562
- how_i_work: { label: 'How I Work', icon: () => <ClipboardListIcon size={24} /> },
1563
- ai_prompt: { label: 'Squawkbox', icon: () => <ChatQuoteIcon size={24} /> },
1550
+ what_i_shipped: { label: 'What I Shipped' },
1551
+ how_i_work: { label: 'How I Work' },
1552
+ ai_prompt: { label: 'Squawkbox' },
1564
1553
  };
1565
1554
  function employeeEntryRegistryEntries(): Record<string, ChatCardRegistryEntry> {
1566
1555
  return registryEntries(EMPLOYEE_ENTRY_CARD_CONFIGS, (cfg, docType) => ({
@@ -1571,7 +1560,7 @@ function employeeEntryRegistryEntries(): Record<string, ChatCardRegistryEntry> {
1571
1560
  render: (item, chatRef, opts) => (
1572
1561
  <GlyphChatCard
1573
1562
  chatRef={fetchedEmployeeEntryDisplayRef(item, chatRef)}
1574
- icon={cfg.icon()}
1563
+ icon={sourceGlyph(docType)}
1575
1564
  isNewTab={opts.isNewTab}
1576
1565
  discuss={opts.discuss}
1577
1566
  />
@@ -57,7 +57,7 @@ import { MiamiCyberGangLogoFaceOnly } from '../../icons/miami-cyber-gang-logo-fa
57
57
  import { MlgLogo } from '../../icons/mlg-logo';
58
58
  import { OpenFrameLogo } from '../../icons/openframe-logo';
59
59
  import { OpenmspLogo } from '../../icons/openmsp-logo';
60
- import { getIconComponent } from './icon-registry';
60
+ import { ICON_REGISTRY, getIconComponent, normalizeIconKey } from './icon-registry';
61
61
 
62
62
  /** Shape used by every icon registered here (matches `icons-v2-generated`). */
63
63
  export type IconComponent = ComponentType<{
@@ -288,8 +288,13 @@ export function resolveIcon(
288
288
  opts?: { variant?: 'design' | 'brand' },
289
289
  ): IconComponent {
290
290
  if (opts?.variant === 'brand') {
291
- // Brand variant — delegate to the registry resolver (same glyph as before).
292
- return getIconComponent(iconName) as IconComponent;
291
+ // The brand set first. A name it does not hold is drawn from the design
292
+ // set, so a source whose icon lives only there is never shown as the file
293
+ // glyph; a name neither holds keeps the registry's own fallback.
294
+ const brand = iconName ? ICON_REGISTRY[normalizeIconKey(iconName)] : undefined;
295
+ if (brand) return brand as IconComponent;
296
+ const design = iconName ? (ICON_ALIASES[iconName] ?? resolveFromLibrary(iconName)) : undefined;
297
+ return design ?? (getIconComponent(iconName) as IconComponent);
293
298
  }
294
299
  if (!iconName) return FileIcon;
295
300
  return ICON_ALIASES[iconName] ?? resolveFromLibrary(iconName) ?? FileIcon;
@@ -29,7 +29,7 @@ import { canonicalContentRefType } from '../../../utils/list-url';
29
29
  import { DOC_TABLE_TYPES } from '../../../utils/source-grouping';
30
30
  import type { ChatRef } from '../chat-ref.types';
31
31
  import { safeHref } from './compact-card-classes';
32
- import { getIconComponent } from './icon-registry';
32
+ import { resolveIcon } from './icon-library';
33
33
  import { getSourceIconName } from './source-icons';
34
34
 
35
35
  /** Path sanitization — keep alphanumerics, slash, dash, dot, underscore;
@@ -146,11 +146,11 @@ export function sourceRowCtxFromRuntime(
146
146
  /**
147
147
  * Pure icon-resolution helper — `sourceRepo` (RagTableConfig.id) →
148
148
  * icon_name via `SOURCE_ICON_NAMES`, then icon_name → React component
149
- * via `ICON_REGISTRY`.
149
+ * via `resolveIcon` (the brand set, else the design set).
150
150
  */
151
151
  function pickSourceIcon(sourceRepo: string | null, documentType: string | null | undefined) {
152
152
  const iconName = sourceRepo ? getSourceIconName(sourceRepo) : undefined;
153
- const icon = iconName ? getIconComponent(iconName) : FileText;
153
+ const icon = iconName ? resolveIcon(iconName, { variant: 'brand' }) : FileText;
154
154
  const iconLabel = documentType ?? 'Source';
155
155
  return { icon, iconLabel };
156
156
  }
@@ -28,14 +28,23 @@ import { defaultDocumentTypeForTableId, getSourceLabel } from './source-icons';
28
28
  /**
29
29
  * Doc-table documentTypes: whole documents with their own viewer (markdown =
30
30
  * product docs, data_room_doc = data room). They carry an in-app `path`, an
31
- * embedder keys `docPlatformTargets` by them, and they NEVER group: one chip
32
- * per document. The hub's per-source contract test pins this list to its
31
+ * embedder keys `docPlatformTargets` by them, and a server never folds them
32
+ * into one citation (`groupsByTable`); the strip still draws them as one chip
33
+ * per table. The hub's per-source contract test pins this list to its
33
34
  * doc-table configs.
34
35
  */
35
36
  export const DOC_TABLE_TYPES = ['markdown', 'data_room_doc'] as const;
36
37
 
37
- /** THE rule: rows of a knowledge table share one chip unless they are whole
38
- * documents. Decided by `documentType`, the one fact every producer has. */
38
+ /**
39
+ * Which tables a SERVER folds into one citation: rows of a knowledge table
40
+ * share one number (and reach the model as one table) unless they are whole
41
+ * documents, which each keep their own number and are read in full. Decided by
42
+ * `documentType`, the one fact every producer has.
43
+ *
44
+ * This is not the strip's rule. The strip (`groupSourcesByTable`) draws ONE chip
45
+ * per table for every source, documents included: a document keeps its own
46
+ * citation number inside its table's chip.
47
+ */
39
48
  export function groupsByTable(documentType: string | null | undefined): boolean {
40
49
  return !(DOC_TABLE_TYPES as readonly string[]).includes(documentType ?? '');
41
50
  }
@@ -98,16 +107,16 @@ function typeOf(source: TableSource): string {
98
107
  return source.documentType || defaultDocumentTypeForTableId(source.sourceRepo) || '';
99
108
  }
100
109
 
101
- /** A source that belongs to its table's chip: it names its table and is not a
102
- * whole document. Both shapes qualify, a flat row AND a chip the server
103
- * already grouped, so one table is never drawn twice. Naming the table is the
104
- * ONLY requirement: a row with no `id`, or no `documentType`, still joins (as
105
- * the hub's server-side chips do). Leaving it out would split one table
106
- * across a group AND a stray chip. What it lacks only limits its dropdown
107
- * row: no `id` or no type means Open-only, no Ask. */
110
+ /** A source that belongs to its table's chip: it names its table. Whole
111
+ * documents join their table's chip like every other record (each keeps its
112
+ * own citation number as a dropdown row). Both shapes qualify, a flat row AND
113
+ * a chip the server already grouped, so one table is never drawn twice.
114
+ * Naming the table is the ONLY requirement: a row with no `id`, or no
115
+ * `documentType`, still joins (as the hub's server-side chips do). Leaving it
116
+ * out would split one table across a group AND a stray chip. What it lacks
117
+ * only limits its dropdown row: no `id` or no type means Open-only, no Ask. */
108
118
  function joinsTableChip(source: ChatSource): source is TableSource {
109
- if (!source.sourceRepo) return false;
110
- return groupsByTable(typeOf({ ...source, sourceRepo: source.sourceRepo }));
119
+ return !!source.sourceRepo;
111
120
  }
112
121
 
113
122
  /** A source's dropdown rows: a grouped chip's own items, or the flat row itself. */
@@ -154,7 +163,8 @@ function uniqueRows(rows: GroupedSourceRow[]): GroupedSourceRow[] {
154
163
  * table's only source. When flat rows of the same table arrive beside it (a
155
164
  * hub-injected chip plus MCP-cited rows in one answer), they merge into it:
156
165
  * its rows first, its chip-level link kept, the count restated. Whole
157
- * documents and rows naming no table pass through as their own chips.
166
+ * documents group under their table too, each row keeping its own citation
167
+ * number; only a row naming no table passes through as its own chip.
158
168
  */
159
169
  export function groupSourcesByTable(sources: ChatSource[]): ChatSource[] {
160
170
  const membersByTable = new Map<string, TableSource[]>();
@@ -64,11 +64,11 @@ export const SOURCE_ICON_NAMES: Record<string, string> = {
64
64
 
65
65
  // Financials
66
66
  'investor-updates': 'mail',
67
- 'financial-kpis': 'activity',
68
- 'financial-cap-table': 'table',
69
- 'financial-pnl': 'trending-up',
70
- 'financial-balance-sheet': 'dollar-sign',
71
- 'financial-cash-flow': 'banknote',
67
+ 'financial-kpis': 'chart-bar-01-ver',
68
+ 'financial-cap-table': 'chart-pie',
69
+ 'financial-pnl': 'money-bill-dollar',
70
+ 'financial-balance-sheet': 'bank',
71
+ 'financial-cash-flow': 'coins-exchange-currency',
72
72
 
73
73
  // ClickUp
74
74
  'clickup-roadmap': 'clickup',
@@ -92,24 +92,24 @@ export const SOURCE_ICON_NAMES: Record<string, string> = {
92
92
  'slack-messages': 'slack',
93
93
 
94
94
  // People-hub employee content
95
- 'what-i-shipped': 'package',
96
- 'how-i-work': 'book-open',
97
- 'ai-prompts': 'message-square',
95
+ 'what-i-shipped': 'rocket-02',
96
+ 'how-i-work': 'clipboard-list',
97
+ 'ai-prompts': 'chat-quote',
98
98
 
99
99
  // Product-hub internal
100
100
  'design-docs': 'file-text',
101
101
  'openframe-tenants': 'openframe',
102
- 'prospect-calls': 'phone',
102
+ 'prospect-calls': 'call',
103
103
 
104
104
  // Code intelligence
105
- 'code-rules': 'check-square',
106
- 'code-graph-repos': 'github',
105
+ 'code-rules': 'bracket-curly-check',
106
+ 'code-graph-repos': 'coding-branch',
107
107
  'code-graph-deployments': 'package',
108
- 'code-graph-files': 'file-text',
109
- 'code-symbols': 'box',
110
- 'code-duplicates': 'search',
111
- 'code-impact': 'activity',
112
- 'change-sets': 'coding-branch',
108
+ 'code-graph-files': 'file-code',
109
+ 'code-symbols': 'code-square',
110
+ 'code-duplicates': 'copy-01',
111
+ 'code-impact': 'coding-pull-request',
112
+ 'change-sets': 'coding-merge',
113
113
  };
114
114
 
115
115
  /** Lookup an icon name by RagTableConfig.id. Returns undefined when