@flamingo-stack/openframe-frontend-core 0.0.203 → 0.0.204-snapshot.20260523020255
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-27APPAJN.cjs +24 -0
- package/dist/chunk-27APPAJN.cjs.map +1 -0
- package/dist/{chunk-XGL5FKIK.js → chunk-D6BNDYZK.js} +114 -4
- package/dist/chunk-D6BNDYZK.js.map +1 -0
- package/dist/chunk-MJNXIEV2.js +24 -0
- package/dist/chunk-MJNXIEV2.js.map +1 -0
- package/dist/{chunk-25LVV26X.cjs → chunk-NLXY4QZE.cjs} +114 -4
- package/dist/chunk-NLXY4QZE.cjs.map +1 -0
- package/dist/{chunk-E6Q6UGDK.js → chunk-OFCRX24Y.js} +383 -569
- package/dist/chunk-OFCRX24Y.js.map +1 -0
- package/dist/{chunk-3YH2M76N.cjs → chunk-RDXOQWBY.cjs} +556 -742
- package/dist/chunk-RDXOQWBY.cjs.map +1 -0
- package/dist/components/announcement-bar.d.ts.map +1 -1
- package/dist/components/features/index.cjs +4 -3
- package/dist/components/features/index.cjs.map +1 -1
- package/dist/components/features/index.js +3 -2
- package/dist/components/index.cjs +4 -3
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +3 -2
- package/dist/components/navigation/index.cjs +4 -3
- package/dist/components/navigation/index.cjs.map +1 -1
- package/dist/components/navigation/index.js +3 -2
- package/dist/components/navigation/navigation-sidebar.d.ts.map +1 -1
- package/dist/components/shared/product-release/product-release-card-skeleton.d.ts +1 -1
- package/dist/components/shared/product-release/product-release-card-skeleton.d.ts.map +1 -1
- package/dist/components/shared/product-release/product-release-card.d.ts +19 -12
- package/dist/components/shared/product-release/product-release-card.d.ts.map +1 -1
- package/dist/components/ui/index.cjs +4 -3
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.js +3 -2
- package/dist/contexts/endpoints-runtime-context.d.ts +28 -0
- package/dist/contexts/endpoints-runtime-context.d.ts.map +1 -0
- package/dist/contexts/index.cjs +13 -0
- package/dist/contexts/index.cjs.map +1 -0
- package/dist/contexts/index.d.ts +24 -0
- package/dist/contexts/index.d.ts.map +1 -0
- package/dist/contexts/index.js +13 -0
- package/dist/contexts/index.js.map +1 -0
- package/dist/hooks/index.cjs +5 -2
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +4 -1
- package/dist/hooks/use-access-code-integration.d.ts +48 -0
- package/dist/hooks/use-access-code-integration.d.ts.map +1 -0
- package/dist/hooks/use-contact-submission.d.ts.map +1 -1
- package/dist/index.cjs +4 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7 -6
- package/dist/utils/access-code-client.d.ts +21 -37
- package/dist/utils/access-code-client.d.ts.map +1 -1
- package/dist/utils/index.cjs +10 -51
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.js +11 -47
- package/dist/utils/index.js.map +1 -1
- package/package.json +7 -1
- package/src/components/announcement-bar.tsx +25 -3
- package/src/components/navigation/navigation-sidebar.tsx +3 -1
- package/src/components/shared/product-release/product-release-card-skeleton.tsx +66 -70
- package/src/components/shared/product-release/product-release-card.tsx +194 -242
- package/src/contexts/endpoints-runtime-context.tsx +68 -0
- package/src/contexts/index.ts +29 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/use-access-code-integration.ts +107 -0
- package/src/hooks/use-contact-submission.ts +6 -2
- package/src/utils/access-code-client.ts +32 -75
- package/dist/chunk-25LVV26X.cjs.map +0 -1
- package/dist/chunk-3YH2M76N.cjs.map +0 -1
- package/dist/chunk-E6Q6UGDK.js.map +0 -1
- package/dist/chunk-XGL5FKIK.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flamingo-stack/openframe-frontend-core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.204-snapshot.20260523020255",
|
|
4
4
|
"description": "Shared design system and components for all Flamingo platforms",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
"require": "./dist/index.cjs",
|
|
19
19
|
"default": "./dist/index.js"
|
|
20
20
|
},
|
|
21
|
+
"./contexts": {
|
|
22
|
+
"types": "./dist/contexts/index.d.ts",
|
|
23
|
+
"import": "./dist/contexts/index.js",
|
|
24
|
+
"require": "./dist/contexts/index.cjs",
|
|
25
|
+
"default": "./dist/contexts/index.js"
|
|
26
|
+
},
|
|
21
27
|
"./components": {
|
|
22
28
|
"types": "./dist/components/index.d.ts",
|
|
23
29
|
"import": "./dist/components/index.js",
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from '../utils/announcement-storage';
|
|
13
13
|
import { Announcement } from '../types/announcement';
|
|
14
14
|
import { getAppType } from '../utils/app-config';
|
|
15
|
+
import { useEndpointsRuntime } from '../contexts/endpoints-runtime-context';
|
|
15
16
|
|
|
16
17
|
// Helper that defers to renderSvgIcon so we don't need local icon imports
|
|
17
18
|
const getSvgIcon = (
|
|
@@ -33,6 +34,15 @@ export function AnnouncementBar() {
|
|
|
33
34
|
// Get the platform type for platform-specific localStorage keys
|
|
34
35
|
const platform = getAppType();
|
|
35
36
|
|
|
37
|
+
// Optional endpoint runtime: when no provider is mounted (e.g. on a
|
|
38
|
+
// bare React-tree page that doesn't wrap with HubRuntimeProvider),
|
|
39
|
+
// the bar silently skips its fetch instead of throwing. Apps that DO
|
|
40
|
+
// mount the provider get the configured URL — typically
|
|
41
|
+
// '/api/announcements/active' in the hub, or a proxied path in an
|
|
42
|
+
// embedded host.
|
|
43
|
+
const endpoints = useEndpointsRuntime();
|
|
44
|
+
const announcementsUrl = endpoints?.announcementsUrl;
|
|
45
|
+
|
|
36
46
|
// Helper to determine dismissal key for localStorage
|
|
37
47
|
const getDismissKey = (id: string) => `${platform}-announcement-${id}-dismissed`;
|
|
38
48
|
|
|
@@ -41,9 +51,12 @@ export function AnnouncementBar() {
|
|
|
41
51
|
|
|
42
52
|
// Fetch active announcement from API and update state + LS
|
|
43
53
|
const fetchActiveAnnouncement = async () => {
|
|
54
|
+
// No provider mounted → no URL configured → skip fetch silently.
|
|
55
|
+
// Cached announcement from previous sessions still renders if present.
|
|
56
|
+
if (!announcementsUrl) return;
|
|
44
57
|
try {
|
|
45
58
|
// Server-side platform injection - no URL parameter needed
|
|
46
|
-
const response = await fetch(
|
|
59
|
+
const response = await fetch(announcementsUrl);
|
|
47
60
|
|
|
48
61
|
if (response.ok) {
|
|
49
62
|
const data = await response.json();
|
|
@@ -92,13 +105,22 @@ export function AnnouncementBar() {
|
|
|
92
105
|
setIsVisible(!isDismissed);
|
|
93
106
|
}
|
|
94
107
|
|
|
108
|
+
// No provider mounted → no URL → no fetch / no polling. Cached
|
|
109
|
+
// announcement still painted above. Skip scheduling the 5-min
|
|
110
|
+
// interval entirely to avoid an idle timer + repeated short-circuit
|
|
111
|
+
// calls.
|
|
112
|
+
if (!announcementsUrl) return;
|
|
113
|
+
|
|
95
114
|
// Always fetch latest on mount
|
|
96
115
|
fetchActiveAnnouncement();
|
|
97
116
|
|
|
98
|
-
// Schedule refresh every 5 minutes
|
|
117
|
+
// Schedule refresh every 5 minutes. When announcementsUrl flips
|
|
118
|
+
// (e.g. provider value swap), the effect re-runs and restarts the
|
|
119
|
+
// interval against the new URL — no stale captured fetch.
|
|
99
120
|
const interval = setInterval(fetchActiveAnnouncement, 300_000);
|
|
100
121
|
return () => clearInterval(interval);
|
|
101
|
-
|
|
122
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
123
|
+
}, [announcementsUrl]);
|
|
102
124
|
|
|
103
125
|
// helpers
|
|
104
126
|
const handleDismiss = () => {
|
|
@@ -83,7 +83,9 @@ export function NavigationSidebar({ config, disabled = false }: NavigationSideba
|
|
|
83
83
|
} else if (item.path) {
|
|
84
84
|
config.onNavigate?.(item.path)
|
|
85
85
|
}
|
|
86
|
-
|
|
86
|
+
|
|
87
|
+
if (isTablet) setTabletMinimized(true)
|
|
88
|
+
}, [config, isTablet])
|
|
87
89
|
|
|
88
90
|
const { primaryItems, secondaryItems } = useMemo(() => ({
|
|
89
91
|
primaryItems: config.items.filter(item => item.section !== 'secondary'),
|
|
@@ -8,23 +8,20 @@ export interface ProductReleaseCardSkeletonProps {
|
|
|
8
8
|
className?: string
|
|
9
9
|
/** Card density. Must match the loaded card's `size` prop so the loading
|
|
10
10
|
* height matches the resolved height (no layout shift on resolve). */
|
|
11
|
-
size?: '
|
|
11
|
+
size?: 'lg' | 'sm'
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export function ProductReleaseCardSkeleton({ className, size = '
|
|
15
|
-
// -----
|
|
14
|
+
export function ProductReleaseCardSkeleton({ className, size = 'lg' }: ProductReleaseCardSkeletonProps) {
|
|
15
|
+
// ----- LG branch — must match ProductReleaseCard size='lg'.
|
|
16
16
|
// Same outer frame (`bg-ods-system-greys-black border border-ods-border …
|
|
17
17
|
// p-6 gap-4`). Inner: hero (16:9 cover + version pill + title + summary),
|
|
18
|
-
// changelog strip placeholder
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
// The skeleton always renders the placeholder; net effect is a ~28px
|
|
26
|
-
// shrink on empty-changelog releases. Documented tradeoff.
|
|
27
|
-
if (size === 'catalog') {
|
|
18
|
+
// changelog strip placeholder, metadata-grid footer (4 cells via grid).
|
|
19
|
+
// Heights chosen to match the loaded card's rendered metrics so the
|
|
20
|
+
// 5-card slot grid in `ReleasesList` doesn't jump on resolve. The
|
|
21
|
+
// loaded card ALSO always renders the changelog strip + a fixed 4-cell
|
|
22
|
+
// grid (with em-dash placeholders for missing values), so this
|
|
23
|
+
// skeleton's shape matches exactly with zero load-to-resolve reflow.
|
|
24
|
+
if (size === 'lg') {
|
|
28
25
|
return (
|
|
29
26
|
<div
|
|
30
27
|
className={cn(
|
|
@@ -34,27 +31,62 @@ export function ProductReleaseCardSkeleton({ className, size = 'default' }: Prod
|
|
|
34
31
|
className,
|
|
35
32
|
)}
|
|
36
33
|
>
|
|
37
|
-
{/* HERO
|
|
34
|
+
{/* HERO — placeholders use `bg-ods-border` (#3a3a3a) so they
|
|
35
|
+
contrast against the card's `bg-ods-system-greys-black`
|
|
36
|
+
(#212121) container. The metadata grid cells below use
|
|
37
|
+
`bg-ods-card` containers so `bg-ods-bg` placeholders work
|
|
38
|
+
there, but in the hero the card IS `bg-ods-card`-equivalent —
|
|
39
|
+
`bg-ods-bg` (#161616) is only 6 hex points darker than the
|
|
40
|
+
card and renders nearly invisible.
|
|
41
|
+
|
|
42
|
+
CRITICAL: title + summary use the SAME min-h containers as
|
|
43
|
+
the loaded card so total card height is byte-identical
|
|
44
|
+
between skeleton state and loaded state. Without this,
|
|
45
|
+
individual placeholder heights underrun the loaded card's
|
|
46
|
+
min-h reservations and the page jumps on resolve. */}
|
|
38
47
|
<div className="flex flex-col md:flex-row gap-4 md:gap-6">
|
|
39
|
-
<div className="w-full md:w-[256px] aspect-[16/9] bg-ods-
|
|
48
|
+
<div className="w-full md:w-[256px] aspect-[16/9] bg-ods-border rounded-lg flex-shrink-0" />
|
|
40
49
|
<div className="flex-1 min-w-0 flex flex-col">
|
|
41
|
-
{/* Version pill
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<div className="
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
{/* Version pill — mirrors `flex items-center gap-3 mb-3` in
|
|
51
|
+
the loaded card. The loaded `<span text-lg>` renders at
|
|
52
|
+
line-height 28 px (Tailwind text-lg = 18 px / 28 px LH);
|
|
53
|
+
placeholder uses `h-7` (28 px) to match exactly. */}
|
|
54
|
+
<div className="flex items-center gap-3 mb-3">
|
|
55
|
+
<div className="h-7 w-20 bg-ods-border rounded" />
|
|
56
|
+
</div>
|
|
57
|
+
{/* Title container — SAME min-h as the loaded card so the
|
|
58
|
+
card height contributed by this region matches exactly. */}
|
|
59
|
+
<div className="min-h-[60px] md:min-h-[72px] flex flex-col gap-1.5 justify-start mb-3">
|
|
60
|
+
<div className="h-[25px] md:h-[30px] w-3/4 bg-ods-border rounded" />
|
|
61
|
+
<div className="h-[25px] md:h-[30px] w-1/2 bg-ods-border rounded" />
|
|
62
|
+
</div>
|
|
63
|
+
{/* Summary container — SAME min-h as the loaded card. The
|
|
64
|
+
3 placeholder lines mirror the rendered 3-line clamp;
|
|
65
|
+
`bg-ods-border/70` keeps summary placeholders slightly
|
|
66
|
+
dimmer than title placeholders (primary vs secondary
|
|
67
|
+
text hierarchy). */}
|
|
68
|
+
<div className="min-h-[68px] md:min-h-[78px] flex flex-col gap-2 justify-start">
|
|
69
|
+
<div className="h-3 w-full bg-ods-border/70 rounded" />
|
|
70
|
+
<div className="h-3 w-11/12 bg-ods-border/70 rounded" />
|
|
71
|
+
<div className="h-3 w-5/6 bg-ods-border/70 rounded" />
|
|
72
|
+
</div>
|
|
49
73
|
</div>
|
|
50
74
|
</div>
|
|
51
75
|
|
|
52
|
-
{/* CHANGELOG strip placeholder — always rendered
|
|
76
|
+
{/* CHANGELOG strip placeholder — always rendered. Inner
|
|
77
|
+
placeholder `h-5` mirrors the loaded strip's `text-sm`
|
|
78
|
+
line-height (20 px) so total height is consistent with the
|
|
79
|
+
loaded `border-t pt-3 + text content` (~32-33 px). */}
|
|
53
80
|
<div className="border-t border-ods-border pt-3">
|
|
54
|
-
<div className="h-
|
|
81
|
+
<div className="h-5 w-2/3 bg-ods-border/70 rounded" />
|
|
55
82
|
</div>
|
|
56
83
|
|
|
57
|
-
{/* METADATA GRID — 4-cell placeholder
|
|
84
|
+
{/* METADATA GRID — 4-cell placeholder. The grid cells use
|
|
85
|
+
`bg-ods-card` containers and `bg-ods-bg` placeholders, which
|
|
86
|
+
DO contrast correctly because the cells are brighter than
|
|
87
|
+
the placeholders. Inner content heights mirror the loaded
|
|
88
|
+
cells (`text-h4` ≈ 28 px + `DM_Sans 14px leading-20`) so
|
|
89
|
+
total grid height matches the loaded ~86 px. */}
|
|
58
90
|
<div className="grid grid-cols-1 md:grid-cols-4 border border-ods-border rounded-md overflow-hidden w-full">
|
|
59
91
|
{[0, 1, 2].map((i) => (
|
|
60
92
|
<div
|
|
@@ -62,8 +94,8 @@ export function ProductReleaseCardSkeleton({ className, size = 'default' }: Prod
|
|
|
62
94
|
className="bg-ods-card p-4 flex flex-col gap-3 border-b md:border-b-0 md:border-r border-ods-border"
|
|
63
95
|
>
|
|
64
96
|
<div className="flex flex-col gap-2">
|
|
65
|
-
<div className="h-
|
|
66
|
-
<div className="h-
|
|
97
|
+
<div className="h-7 w-24 bg-ods-bg rounded" />
|
|
98
|
+
<div className="h-4 w-16 bg-ods-bg/60 rounded" />
|
|
67
99
|
</div>
|
|
68
100
|
</div>
|
|
69
101
|
))}
|
|
@@ -71,8 +103,8 @@ export function ProductReleaseCardSkeleton({ className, size = 'default' }: Prod
|
|
|
71
103
|
<div className="bg-ods-card p-4 flex items-center gap-3">
|
|
72
104
|
<div className="h-10 w-10 rounded-full bg-ods-bg shrink-0" />
|
|
73
105
|
<div className="flex flex-col gap-2 flex-1 min-w-0">
|
|
74
|
-
<div className="h-
|
|
75
|
-
<div className="h-
|
|
106
|
+
<div className="h-5 w-3/4 bg-ods-bg rounded" />
|
|
107
|
+
<div className="h-4 w-1/2 bg-ods-bg/60 rounded" />
|
|
76
108
|
</div>
|
|
77
109
|
</div>
|
|
78
110
|
</div>
|
|
@@ -119,44 +151,8 @@ export function ProductReleaseCardSkeleton({ className, size = 'default' }: Prod
|
|
|
119
151
|
)
|
|
120
152
|
}
|
|
121
153
|
|
|
122
|
-
return
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
'flex flex-col md:flex-row',
|
|
127
|
-
'items-start md:items-center',
|
|
128
|
-
'gap-3 md:gap-4',
|
|
129
|
-
'p-4',
|
|
130
|
-
'animate-pulse',
|
|
131
|
-
className
|
|
132
|
-
)}
|
|
133
|
-
>
|
|
134
|
-
{/* Left column - content */}
|
|
135
|
-
<div className="flex-1 w-full md:w-auto min-w-0 flex flex-col justify-center gap-2">
|
|
136
|
-
{/* Title skeleton - 2 lines height */}
|
|
137
|
-
<div className="min-h-[48px] flex items-center">
|
|
138
|
-
<div className="flex flex-col gap-1 w-full">
|
|
139
|
-
<div className="h-[24px] w-3/4 bg-ods-border rounded" />
|
|
140
|
-
<div className="h-[24px] w-1/2 bg-ods-border rounded" />
|
|
141
|
-
</div>
|
|
142
|
-
</div>
|
|
143
|
-
{/* Description skeleton - 3 lines */}
|
|
144
|
-
<div className="flex flex-col gap-1">
|
|
145
|
-
<div className="h-[24px] w-full bg-ods-border rounded" />
|
|
146
|
-
<div className="h-[24px] w-full bg-ods-border rounded" />
|
|
147
|
-
<div className="h-[24px] w-2/3 bg-ods-border rounded" />
|
|
148
|
-
</div>
|
|
149
|
-
</div>
|
|
150
|
-
|
|
151
|
-
{/* Right column - version + date */}
|
|
152
|
-
<div className="flex items-center gap-2 w-full md:w-auto justify-start md:justify-end shrink-0">
|
|
153
|
-
<div className="w-[200px] flex flex-col justify-center gap-2">
|
|
154
|
-
<div className="h-[24px] w-20 bg-ods-border rounded" />
|
|
155
|
-
<div className="h-[20px] w-32 bg-ods-border rounded" />
|
|
156
|
-
</div>
|
|
157
|
-
{/* Icon column */}
|
|
158
|
-
<div className="h-6 w-6 bg-ods-border rounded shrink-0 mx-3" />
|
|
159
|
-
</div>
|
|
160
|
-
</div>
|
|
161
|
-
)
|
|
154
|
+
// Unreachable — `size` is typed `'lg' | 'sm'` and both branches return
|
|
155
|
+
// above. Kept as a defensive throw so a future variant addition that
|
|
156
|
+
// forgets to return doesn't silently render `undefined`.
|
|
157
|
+
throw new Error(`ProductReleaseCardSkeleton: unsupported size '${size as string}'`)
|
|
162
158
|
}
|