@flamingo-stack/openframe-frontend-core 0.0.240 → 0.0.241

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 (63) hide show
  1. package/dist/{chunk-ZYPOIFBS.js → chunk-2GMHLKEO.js} +2 -2
  2. package/dist/{chunk-POZHDJSK.js → chunk-5KAQW6Q3.js} +12 -3
  3. package/dist/chunk-5KAQW6Q3.js.map +1 -0
  4. package/dist/{chunk-B3NI3KT4.js → chunk-6IFN7F3C.js} +2 -2
  5. package/dist/{chunk-NE2DYD6K.cjs → chunk-EFT34DLB.cjs} +6 -2
  6. package/dist/chunk-EFT34DLB.cjs.map +1 -0
  7. package/dist/{chunk-XWUA273B.js → chunk-FEZSQQTH.js} +2 -2
  8. package/dist/{chunk-SI4LEFLR.cjs → chunk-GRD7M6IZ.cjs} +25 -25
  9. package/dist/{chunk-SI4LEFLR.cjs.map → chunk-GRD7M6IZ.cjs.map} +1 -1
  10. package/dist/{chunk-YY6S4T67.cjs → chunk-JEPYFYQP.cjs} +9 -9
  11. package/dist/{chunk-YY6S4T67.cjs.map → chunk-JEPYFYQP.cjs.map} +1 -1
  12. package/dist/{chunk-YH6KPNIH.js → chunk-KOHE4F6Q.js} +5 -1
  13. package/dist/chunk-KOHE4F6Q.js.map +1 -0
  14. package/dist/{chunk-CDLMGHSB.cjs → chunk-QJULZ4PB.cjs} +7 -7
  15. package/dist/{chunk-CDLMGHSB.cjs.map → chunk-QJULZ4PB.cjs.map} +1 -1
  16. package/dist/{chunk-5JTDFOYB.cjs → chunk-SWXWKVCC.cjs} +10 -10
  17. package/dist/{chunk-5JTDFOYB.cjs.map → chunk-SWXWKVCC.cjs.map} +1 -1
  18. package/dist/{chunk-TE6LSK2X.cjs → chunk-WKZS5HWH.cjs} +36 -27
  19. package/dist/chunk-WKZS5HWH.cjs.map +1 -0
  20. package/dist/{chunk-7BWJF43J.js → chunk-Z3657YGL.js} +2 -2
  21. package/dist/components/chat/index.cjs +2 -2
  22. package/dist/components/chat/index.js +1 -1
  23. package/dist/components/contact/index.cjs +3 -3
  24. package/dist/components/contact/index.js +2 -2
  25. package/dist/components/features/index.cjs +2 -2
  26. package/dist/components/features/index.js +1 -1
  27. package/dist/components/index.cjs +75 -75
  28. package/dist/components/index.js +5 -5
  29. package/dist/components/navigation/index.cjs +2 -2
  30. package/dist/components/navigation/index.js +1 -1
  31. package/dist/components/onboarding-guides/index.cjs +23 -23
  32. package/dist/components/onboarding-guides/index.js +3 -3
  33. package/dist/components/related-content/index.cjs +3 -3
  34. package/dist/components/related-content/index.js +2 -2
  35. package/dist/components/related-content/related-content-section.d.ts +8 -2
  36. package/dist/components/related-content/related-content-section.d.ts.map +1 -1
  37. package/dist/components/tickets/index.cjs +64 -64
  38. package/dist/components/tickets/index.js +4 -4
  39. package/dist/components/ui/index.cjs +2 -2
  40. package/dist/components/ui/index.js +1 -1
  41. package/dist/index.cjs +4 -2
  42. package/dist/index.cjs.map +1 -1
  43. package/dist/index.js +3 -1
  44. package/dist/utils/index.cjs +4 -0
  45. package/dist/utils/index.cjs.map +1 -1
  46. package/dist/utils/index.d.ts +1 -1
  47. package/dist/utils/index.d.ts.map +1 -1
  48. package/dist/utils/index.js +4 -1
  49. package/dist/utils/index.js.map +1 -1
  50. package/dist/utils/list-url.d.ts +6 -0
  51. package/dist/utils/list-url.d.ts.map +1 -1
  52. package/package.json +1 -1
  53. package/src/components/related-content/related-content-section.tsx +21 -3
  54. package/src/utils/index.ts +1 -1
  55. package/src/utils/list-url.ts +9 -0
  56. package/dist/chunk-NE2DYD6K.cjs.map +0 -1
  57. package/dist/chunk-POZHDJSK.js.map +0 -1
  58. package/dist/chunk-TE6LSK2X.cjs.map +0 -1
  59. package/dist/chunk-YH6KPNIH.js.map +0 -1
  60. /package/dist/{chunk-ZYPOIFBS.js.map → chunk-2GMHLKEO.js.map} +0 -0
  61. /package/dist/{chunk-B3NI3KT4.js.map → chunk-6IFN7F3C.js.map} +0 -0
  62. /package/dist/{chunk-XWUA273B.js.map → chunk-FEZSQQTH.js.map} +0 -0
  63. /package/dist/{chunk-7BWJF43J.js.map → chunk-Z3657YGL.js.map} +0 -0
@@ -27,6 +27,12 @@
27
27
  * Pure + server-safe (no React, no browser APIs) so the hub's server-side
28
28
  * mappers can import it from `@flamingo-stack/openframe-frontend-core/utils`.
29
29
  */
30
+ /** Resolve a ContentRef rail-vocab type to its canonical `documentType`
31
+ * (registry vocabulary) — `blog_post_existing` → `blog_post`, everything
32
+ * else passes through. Exported so consumers comparing rail group keys to
33
+ * registry entityTypes (e.g. the related-content rail's same-type-first
34
+ * ordering) share THIS alias map instead of re-declaring it. */
35
+ export declare function canonicalContentRefType(contentRefType: string): string;
30
36
  /**
31
37
  * Build a list-API URL that returns full rows for the given ids, or `null`
32
38
  * when the type has no list endpoint (the caller skips fetching rather than
@@ -1 +1 @@
1
- {"version":3,"file":"list-url.d.ts","sourceRoot":"","sources":["../../src/utils/list-url.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAqCH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,IAAI,SAAK,GAAG,MAAM,GAAG,IAAI,CAa5F"}
1
+ {"version":3,"file":"list-url.d.ts","sourceRoot":"","sources":["../../src/utils/list-url.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAWH;;;;iEAIiE;AACjE,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAEtE;AA4BD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,IAAI,SAAK,GAAG,MAAM,GAAG,IAAI,CAa5F"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flamingo-stack/openframe-frontend-core",
3
- "version": "0.0.240",
3
+ "version": "0.0.241",
4
4
  "description": "Shared design system and components for all Flamingo platforms",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -52,7 +52,7 @@ import {
52
52
  import type { ContentRef, ContentRefWithReason } from '../../types/content-ref';
53
53
  import { useSelfFetch } from '../../hooks/use-self-fetch';
54
54
  import { extractItems } from '../../utils/extract-items';
55
- import { buildListUrl as libBuildListUrl } from '../../utils/list-url';
55
+ import { buildListUrl as libBuildListUrl, canonicalContentRefType } from '../../utils/list-url';
56
56
  import { buildSuggestionUrl } from '../../utils/suggestion-url';
57
57
  import { decideNewTab } from '../chat/utils/decide-new-tab';
58
58
  // DEEP card imports — NOT the `../chat` barrel (the barrel statically reaches
@@ -441,9 +441,15 @@ export interface RelatedContentSectionProps {
441
441
  * `contentRefs` is provided. */
442
442
  entityType?: string;
443
443
  entityId?: number | string;
444
- /** Maps to the suggestion API's `count` param. Absent param not sent
444
+ /** Maps to the suggestion API's `count` param the PER-TYPE fill target
445
+ * for every candidate type EXCEPT the host's own. Absent → param not sent
445
446
  * (server default applies). */
446
447
  minResults?: number;
448
+ /** Maps to the suggestion API's `sameTypeCount` param — the budget for the
449
+ * candidate type MATCHING the host's own `entityType` (same-type boost:
450
+ * a blog post's rail leads with more blog posts). Absent → param not
451
+ * sent (host's type uses the server's `count`). */
452
+ sameTypeMinResults?: number;
447
453
  /** SSR hydrate for suggestion mode — the server page ran the engine and
448
454
  * drills the refs here; the first client fetch is skipped (useSelfFetch
449
455
  * initialData contract). */
@@ -493,6 +499,7 @@ export function RelatedContentSection({
493
499
  entityType,
494
500
  entityId,
495
501
  minResults,
502
+ sameTypeMinResults,
496
503
  initialItems,
497
504
  title = 'Related Content',
498
505
  columns = 2,
@@ -517,6 +524,7 @@ export function RelatedContentSection({
517
524
  entityId,
518
525
  count: minResults,
519
526
  extraParams: {
527
+ sameTypeCount: sameTypeMinResults !== undefined ? String(sameTypeMinResults) : undefined,
520
528
  excludeTypes: excludeTypes && excludeTypes.length > 0 ? excludeTypes.join(',') : undefined,
521
529
  },
522
530
  })
@@ -558,7 +566,17 @@ export function RelatedContentSection({
558
566
  // Registered types in CONTENT_REF_GROUPS order, then any unregistered
559
567
  // types appended (same shape the investor-email builder uses — both
560
568
  // consume `orderContentRefTypes` so cross-surface ordering matches).
561
- const orderedTypes = orderContentRefTypes(Object.keys(grouped));
569
+ // SAME-TYPE FIRST: when a host entityType is known (suggestion / SSR
570
+ // modes), its own content-type group is hoisted to the top — a blog
571
+ // post's rail leads with blog posts. Rail group keys are compared via
572
+ // the shared alias canonicalizer (blog_post_existing ↔ blog_post).
573
+ let orderedTypes = orderContentRefTypes(Object.keys(grouped));
574
+ if (entityType) {
575
+ const sameType = orderedTypes.filter((t) => canonicalContentRefType(t) === entityType);
576
+ if (sameType.length > 0) {
577
+ orderedTypes = [...sameType, ...orderedTypes.filter((t) => canonicalContentRefType(t) !== entityType)];
578
+ }
579
+ }
562
580
 
563
581
  return (
564
582
  <div className="space-y-8">
@@ -235,7 +235,7 @@ export {
235
235
  // delegate here (byte-parity test guards the migration); embedders wire
236
236
  // `endpoints.buildListUrl = (t, ids) => buildListUrl(t, ids, '/content')`.
237
237
  // Pure + server-safe (the hub imports it server-side from this barrel).
238
- export { buildListUrl } from './list-url'
238
+ export { buildListUrl, canonicalContentRefType } from './list-url'
239
239
 
240
240
  // Content-ref group registry (labels/order/layout per rail type) + list-API
241
241
  // response normalizers + the shared suggestion-fetch URL composer — all
@@ -37,6 +37,15 @@
37
37
  */
38
38
  const ALIASES: Record<string, string> = { blog_post_existing: 'blog_post' }
39
39
 
40
+ /** Resolve a ContentRef rail-vocab type to its canonical `documentType`
41
+ * (registry vocabulary) — `blog_post_existing` → `blog_post`, everything
42
+ * else passes through. Exported so consumers comparing rail group keys to
43
+ * registry entityTypes (e.g. the related-content rail's same-type-first
44
+ * ordering) share THIS alias map instead of re-declaring it. */
45
+ export function canonicalContentRefType(contentRefType: string): string {
46
+ return ALIASES[contentRefType] ?? contentRefType
47
+ }
48
+
40
49
  /**
41
50
  * One builder per fetch-mode `contentRefType`, keyed by the canonical
42
51
  * `documentType`. Each body is copied VERBATIM from the matching hub