@schandlergarcia/sf-web-components 1.9.67 → 1.9.68

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.
@@ -1,6 +1,6 @@
1
1
  # Engine Travel Command Center
2
2
 
3
- Product Requirements Document · TDX26 Demo Build
3
+ Product Requirements Document
4
4
 
5
5
  ---
6
6
 
@@ -8,28 +8,25 @@ Product Requirements Document · TDX26 Demo Build
8
8
 
9
9
  The Engine Travel Command Center is a real-time operations dashboard for corporate travel managers who use Engine (engine.com). It gives a single-screen view of every active traveler, booking, flight, policy flag, and agent interaction — built on Salesforce Data Cloud.
10
10
 
11
- It is not Engine's consumer-facing booking app. It is a personalized command center for one travel manager at one company.
12
-
13
- **Demo context:** Built live at TDX26 using Agentforce Vibes. The arc is: PRD → scaffold → data → agent → intelligence. Each build prompt maps to one beat.
11
+ **Build approach:** Incremental PRD scaffold data agent intelligence.
14
12
 
15
13
  ---
16
14
 
17
15
  ## 2. Users
18
16
 
19
17
  **Primary — Sarah Chen, Travel Manager at Acme Corp**
20
- Manages Acme's travel program: bookings, policy enforcement, exceptions, traveler monitoring. Before this dashboard she worked across Engine's booking interface, email, and Salesforce separately.
18
+ Manages Acme's travel program: bookings, policy enforcement, exceptions, traveler monitoring.
21
19
 
22
20
  **Secondary — Eva (Agentforce Agent)**
23
- Engine's Agentforce-powered AI agent. Handles traveler requests autonomously — booking changes, policy questions, itinerary lookups. Resolves ~30% of requests without human involvement. Surfaces in the dashboard via `ChatBar` (command palette).
21
+ Engine's Agentforce-powered AI agent. Handles traveler requests autonomously — booking changes, policy questions, itinerary lookups. Resolves ~30% of requests without human involvement. Surfaces via `ChatBar`.
24
22
 
25
23
  ---
26
24
 
27
25
  ## 3. Brand Tokens
28
26
 
29
- Update `src/styles/global.css` — replace the existing `--color-brand-*` palette inside the `@theme inline` block. Do not add new CSS variables or custom properties outside this block.
27
+ Update `src/styles/global.css` — replace the existing `--color-brand-*` palette inside the `@theme inline` block:
30
28
 
31
29
  ```css
32
- /* Engine teal brand palette */
33
30
  --color-brand-50: #ECFDF9;
34
31
  --color-brand-100: #D1FAF0;
35
32
  --color-brand-200: #A7F3E1;
@@ -41,185 +38,93 @@ Update `src/styles/global.css` — replace the existing `--color-brand-*` palett
41
38
  --color-brand-800: #115E59;
42
39
  --color-brand-900: #134E4A;
43
40
  --color-brand-950: #042F2E;
44
- ```
45
-
46
- Additionally, add a custom `--color-engine-savings` token for the green savings accent:
47
-
48
- ```css
49
41
  --color-engine-savings: #16A34A;
50
42
  ```
51
43
 
52
- All component styling uses `brand-*` Tailwind classes for primary UI and Tailwind built-in colors (green, amber, red) for status. No hardcoded hex values in components. No `bg-indigo-*` or raw color classes for brand elements.
44
+ Use `brand-*` Tailwind classes for brand elements. Tailwind built-in colors (green, amber, red) for status. No hardcoded hex in components.
53
45
 
54
- **Typography:** Inter (already configured as `--font-sans` in global.css). No changes needed.
55
-
56
- **Icons:** Heroicons 2 exclusively (`@heroicons/react`). No Lucide, Font Awesome, or other libraries inside command center pages.
46
+ **Typography:** Inter (already `--font-sans`). **Icons:** Heroicons 2 (`@heroicons/react`).
57
47
 
58
48
  ---
59
49
 
60
50
  ## 4. Architecture
61
51
 
62
- **Dashboard file:** `src/pages/EngineDashboard.tsx` (single file, `.tsx` — TypeScript project, React components MUST use `.tsx`)
63
-
64
- **Wiring:** `CommandCenter.tsx` imports and renders `EngineDashboard` inside the existing provider stack (`heroui-scope` → `AppThemeProvider` → `DataModeProvider` → `Toast.Provider`). Never recreate these providers in the dashboard.
65
-
66
- **Imports:** All components from `@/components/library` barrel. Theme access from `@/components/library/theme/AppThemeProvider`.
52
+ - **Dashboard file:** `src/pages/EngineDashboard.tsx`
53
+ - **Wiring:** `CommandCenter.tsx` imports and renders `EngineDashboard` inside the existing provider stack. Never recreate providers in the dashboard.
54
+ - **Imports:** Components from `@/components/library`. Theme from `@/components/library/theme/AppThemeProvider`.
67
55
 
68
56
  ---
69
57
 
70
- ## 5. Layout — Visualization-Hero Pattern
71
-
72
- This dashboard uses the **visualization-hero** layout. The live flight map is the signature element.
58
+ ## 5. Layout
73
59
 
74
- ### Structure (top to bottom)
60
+ Visualization-hero layout. Full-page scroll (no `h-screen`).
75
61
 
76
62
  ```
77
- ┌─────────────────────────────────────────────────────────────┐
78
- │ HEADER BAR (h-12, sticky)
79
- │ Engine logo + "Travel Command Center" | ChatBar | actions
80
- ├─────────────────────────────────────────────────────────────┤
81
- │ HERO MAP (h-[520px] or h-[600px], GeoMap)
82
- Full-page
83
- ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ↕ scroll
84
- │ KPI │ │ KPI │ │ KPI │ │ KPI │ ← glass
85
- overlay overlay │ overlay │ │ overlay │ overlays
86
- └─────────┘ └─────────┘ └─────────┘ └─────────┘
87
-
88
- │ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ← flight │ ↕
89
- BA286 NH109 │ LH431 │ │ SQ 37 │ status │ ↕
90
- └───────┘ └───────┘ └───────┘ └───────┘ strip
91
- ├─────────────────────────────────────────────────────────────┤
92
- DATA PANELS (px-4 py-5, space-y-6, natural flow)
93
-
94
- ┌─── 1/3 ───────┐ ┌─── 2/3 ────────────────────┐
95
- Disruptions │ │ Active Travelers │ │ ↕
96
- (custom panel) (expandable cards, scroll) │ ↕
97
- └────────────────┘ └────────────────────────────┘
98
-
99
- ┌─── 1/2 ───────┐ ┌─── 1/2 ────────────────────┐
100
- │ │ Escalations │ │ Travel Spend (Monthly) │ │ ↕
101
- │ │ (ActivityCard) │ │ (ChartCard + D3Chart line) │ │ ↕
102
- │ └────────────────┘ └────────────────────────────┘ │ ↕
103
- └─────────────────────────────────────────────────────────────┘
63
+ ┌──────────────────────────────────────────────────────────────┐
64
+ │ HEADER (h-12, sticky, bg-slate-900)
65
+ │ Engine logo + "Travel Command Center" | actions + toggle
66
+ ├──────────────────────────────────────────────────────────────┤
67
+ │ HERO MAP (h-[520px], GeoMap, relative)
68
+ ┌─ glass KPI overlays (absolute top-left) ───────────────┐ │
69
+ Active Travelers | Spend MTD | Compliance | Eva Resolved
70
+ └────────────────────────────────────────────────────────┘
71
+ ┌─ flight status strip (absolute bottom) ────────────────┐
72
+ BA 286 · In Air | NH 109 · In Air | LH 431 · Delayed
73
+ └────────────────────────────────────────────────────────┘
74
+ ├──────────────────────────────────────────────────────────────┤
75
+ DATA PANELS (px-4 py-5 space-y-6)
76
+
77
+ Row 1: grid grid-cols-1 items-start gap-4 lg:grid-cols-3 │
78
+ ┌── 2/3 (lg:col-span-2) ──────┐ ┌── 1/3 ───────────────┐
79
+ Escalations (ActivityCard) │ │ Disruptions (custom) │ │
80
+ └───────────────────────────────┘ └──────────────────────┘
81
+
82
+ Row 2: grid grid-cols-1 items-start gap-4 lg:grid-cols-3
83
+ ┌── 2/3 (lg:col-span-2) ──────┐ ┌── 1/3 ───────────────┐
84
+ Active Travelers (expandable) │ │ Travel Spend (chart) │ │
85
+ └───────────────────────────────┘ └──────────────────────┘
86
+ └──────────────────────────────────────────────────────────────┘
104
87
  ```
105
88
 
106
- ### Layout Rules
89
+ ### Layout classes
107
90
 
108
- **CRITICAL: Full-page scroll, NOT viewport-locked sections.**
91
+ - **Outer:** `<div className="flex flex-col bg-slate-50 dark:bg-slate-950">`
92
+ - **Map:** `<div className="relative h-[520px]">`
93
+ - **Panels:** `<div className="px-4 py-5"><div className="space-y-6">...</div></div>`
94
+ - **Row 1:** `grid grid-cols-1 items-start gap-4 lg:grid-cols-3` — Escalations `lg:col-span-2`, Disruptions auto
95
+ - **Row 2:** `grid grid-cols-1 items-start gap-4 lg:grid-cols-3` — Travelers `lg:col-span-2`, Spend auto
109
96
 
110
- The entire dashboard scrolls as one page. Do NOT use `h-screen` or flex height constraints that lock sections to viewport.
97
+ ### Phase 1 placeholders
111
98
 
112
- - **Outer container:** `<div className="flex flex-col bg-slate-50 dark:bg-slate-950">` (NO `h-screen`)
113
- - **Hero map:** Fixed height `h-[520px]` or `h-[600px]` with `relative` positioning for glass overlays
114
- - **Data panels:** Natural flow with `px-4 py-5 space-y-6` (NO `overflow-y-auto`, NO flex height constraints)
115
- - **Row 1** - Disruptions + Travelers: `grid grid-cols-1 items-start gap-4 lg:grid-cols-3` (disruptions 1/3, travelers `lg:col-span-2`)
116
- - **Row 2** - Escalations + Chart: `grid grid-cols-1 items-start gap-4 lg:grid-cols-2`
117
- - All grids use `items-start` for different-height cards
118
-
119
- **Why full-page scroll:** Users need to see the map in context while scrolling through data. A fixed-height map that stays visible while data scrolls below creates a cramped, split-screen feeling. Full-page scroll is more natural and gives each section breathing room.
120
-
121
- ### Phase 1 Placeholder Rules
122
-
123
- **Phase 1 builds the complete layout structure** including header bar, hero map, glass KPI overlays, flight status strip, and data panels. The only "placeholders" are the **data panels** below the map.
124
-
125
- **What to build in Phase 1:**
126
- - ✅ Header bar (with logo, title, theme toggle) - **use slate scale colors, NOT text-white**
127
- - ✅ Hero map (GeoMap component with no markers/arcs/overlays props)
128
- - ✅ Glass KPI overlays (4 KPIs, hardcoded values, positioned absolutely over map)
129
- - ✅ Flight status strip (4 flights, hardcoded values, positioned at map bottom)
130
- - ✅ Data panels (BaseCard placeholders with centered text) - **these are the only placeholders**
131
-
132
- **Data panel placeholders** use `BaseCard` with centered text:
99
+ Phase 1 builds the header, map, glass overlays, and flight strip as real components. Only the 4 data panels below the map are placeholders:
133
100
 
134
101
  ```tsx
135
- // ✅ Correct data panel placeholder
136
102
  <BaseCard>
137
103
  <div className="h-48 flex items-center justify-center text-slate-400">
138
- Disruptions Panel
104
+ Escalations Panel
139
105
  </div>
140
106
  </BaseCard>
141
-
142
- // ❌ Wrong - title causes text to run together
143
- <BaseCard title="Disruptions">
144
- <div className="text-slate-400">No disruptions detected</div>
145
- </BaseCard>
146
- ```
147
-
148
- **Hero map** (render actual GeoMap component in Phase 1):
149
-
150
- ```tsx
151
- // ✅ Correct - render actual GeoMap component (empty, no data)
152
- import { GeoMap } from "@/components/library";
153
- import { useThemeMode } from "@/components/library/theme/AppThemeProvider";
154
-
155
- export default function EngineDashboard() {
156
- const { mode } = useThemeMode();
157
-
158
- return (
159
- <div className="relative h-[520px]">
160
- <GeoMap
161
- width={960}
162
- height={520}
163
- theme={mode === "dark" ? "dark" : "light"}
164
- className="h-full w-full"
165
- />
166
- </div>
167
- );
168
- }
169
- ```
170
-
171
- In Phase 1:
172
- - GeoMap component renders with NO `markers`, `arcs`, or `overlays` props (these are GeoMap data props for Phase 2+)
173
- - GeoMap will render the base world map (land, sphere, graticule) even without data - this is NOT a placeholder, it's the actual map component
174
- - Glass KPI overlays and flight status strip ARE built in Phase 1 (as separate `<div>` elements positioned absolutely over the map)
175
- - Uses `useThemeMode()` to get dark/light mode for theme prop
176
- - **Verify:** You should see a blue world map (dark theme) or gray world map (light theme) with glass overlays on top
177
-
178
- // ❌ Wrong - wrapped in BaseCard
179
- <div className="relative h-[520px]">
180
- <BaseCard>
181
- <GeoMap ... />
182
- </BaseCard>
183
- </div>
184
-
185
- // ❌ Wrong - text placeholder instead of GeoMap component
186
- <div className="relative h-[520px]">
187
- <div className="flex h-full items-center justify-center bg-slate-100 dark:bg-slate-900">
188
- <span className="text-slate-400">Hero Map (GeoMap)</span>
189
- </div>
190
- </div>
191
107
  ```
192
108
 
193
- All data panel placeholders use: BaseCard, no title, centered text, `h-48`, `text-slate-400`.
194
-
195
- Hero map uses: actual GeoMap component (no markers/arcs/overlays in Phase 1), direct render, fills hero container.
109
+ The GeoMap renders the base world map with no data props. Glass overlays and flight strip use hardcoded values.
196
110
 
197
111
  ---
198
112
 
199
113
  ## 6. Header
200
114
 
201
- Compact `h-12` sticky header with dark background (`bg-slate-900 dark:bg-slate-950`).
202
-
203
- | Position | Content |
204
- |----------|---------|
205
- | Left | Engine logo (small square icon with `GlobeAltIcon` in `bg-brand-600`) + "ENGINE" wordmark + separator + "Travel Command Center" |
206
- | Right | `ChatBar` (Eva) + notification bell (with pending count badge) + theme toggle (sun/moon) |
115
+ Compact `h-12` sticky header (`bg-slate-900 dark:bg-slate-950`).
207
116
 
208
- The `ChatBar` replaces any FAB or sliding panel. It opens inline as a command palette overlay.
117
+ | Left | Right |
118
+ |------|-------|
119
+ | Engine logo (`GlobeAltIcon` in `bg-brand-600` square) + "ENGINE" wordmark + separator + "Travel Command Center" | ChatBar (Phase 4) + notification bell (badge count) + theme toggle (sun/moon) |
209
120
 
210
121
  ---
211
122
 
212
123
  ## 7. Hero Map
213
124
 
214
- **Component:** `GeoMap` (from `@/components/library`)
215
-
216
- **Phase 1:** Render GeoMap with NO data props (no markers/arcs/overlays)
217
- **Phase 2:** Add markers, arcs, and overlays from sample data to show where travelers are
125
+ **Component:** `GeoMap` from `@/components/library`
218
126
 
219
127
  ```tsx
220
- import { MAP_MARKERS, MAP_ARCS, MAP_OVERLAYS } from "@/data/engine-sample-data";
221
-
222
- // Phase 2 - with map data
223
128
  <GeoMap
224
129
  width={960}
225
130
  height={520}
@@ -232,52 +137,27 @@ import { MAP_MARKERS, MAP_ARCS, MAP_OVERLAYS } from "@/data/engine-sample-data";
232
137
  />
233
138
  ```
234
139
 
235
- **Markers:** One per city (origin and destination). Each marker: `{ id, lon, lat, label, active: true }`. Shows where travelers are located.
140
+ - **Markers:** One per city. `{ id, lon, lat, label, active: true }`
141
+ - **Arcs:** One per flight route. `{ id, from: [lon, lat], to: [lon, lat], progress: 0–1, danger: boolean }`. `danger: true` on disrupted routes.
142
+ - **Overlays:** Weather zones. `{ id, center: [lon, lat], radius: number }`
143
+ - **Phase 1:** Render GeoMap with no data props (map renders base world automatically)
144
+ - **Phase 2:** Add `MAP_MARKERS`, `MAP_ARCS`, `MAP_OVERLAYS` from `@/data/engine-sample-data`
236
145
 
237
- **Arcs:** One per active flight route. Each arc: `{ id, from: [lon, lat], to: [lon, lat], progress: 0–1 }`. Set `danger: true` on disrupted routes (delayed 60+ min or grounded). The `progress` value places an animated pulsing dot showing the flight's current position along the great circle arc.
146
+ **Glass KPI overlays** 4 pills, `absolute left-3 top-3`:
147
+ Active Travelers (count), Spend MTD (`fmtK()`), Compliance %, Eva Resolved (count + "resolved").
148
+ Style: `bg-black/40 backdrop-blur-md border border-white/10 rounded-lg px-3 py-1.5`
238
149
 
239
- **Overlays:** Weather/disruption zones as pulsing circles. Each overlay: `{ id, center: [lon, lat], radius: number }`.
240
-
241
- **Glass KPI overlays:** Four pills floating `absolute left-3 top-3` on the map:
242
- - Active Travelers (count)
243
- - Spend MTD (formatted with `fmtK()`)
244
- - Compliance %
245
- - Eva Resolved (count + "resolved")
246
-
247
- Each pill: `bg-black/40 backdrop-blur-md border border-white/10 rounded-lg px-3 py-1.5` with white text and icon.
248
-
249
- **Flight status strip:** Floating `absolute bottom-3 left-3 right-3`, horizontal scroll. One pill per active flight showing flight number + status chip (On Time = green, Delayed = amber, Grounded/Boarding = contextual). Same glass styling as KPI overlays.
150
+ **Flight status strip** `absolute bottom-3 left-3 right-3`, horizontal scroll. One pill per flight: flight number + status chip (green=On Time, amber=Delayed, contextual=Boarding). Same glass styling.
250
151
 
251
152
  ---
252
153
 
253
154
  ## 8. Data Panels
254
155
 
255
- **CRITICAL: Panel titles MUST match PRD exactly, even if data export has different name.**
256
-
257
- For example: Panel titled "Escalations" uses data exported as `EVA_ACTIONS` or `ESCALATION_CARDS` (both are aliases). The PRD panel title takes precedence over data export names.
258
-
259
- ### 8a. Disruptions Panel (1/3 width)
260
-
261
- Custom inline component inside a `BaseCard`. Shows only flights that are delayed 60+ min or grounded.
262
-
263
- Each disruption card:
264
- - Severity dot (rose for grounded, amber for delayed) + flight number + severity label + delay minutes
265
- - Route + affected traveler name
266
- - Reason text
267
- - Eva action line with `SparklesIcon` showing what Eva is doing about it
268
-
269
- ### 8b. Active Travelers (2/3 width)
270
-
271
- `BaseCard` with `maxBodyHeight={420}` for internal scroll. Expandable traveler cards.
272
-
273
- Each traveler row:
274
- - `Avatar` (initials) + name + department + origin → destination
275
- - `UIChip` for policy status (success = compliant, warning = exception)
276
- - Click to expand: 4-col grid showing Flight, Hotel, Return date, Destination
156
+ 4 panels in 2 rows. Sample data imported from `src/data/engine-sample-data.js`.
277
157
 
278
- ### 8c. Escalations (1/2 width)
158
+ ### 8a. Escalations (Row 1, 2/3 width)
279
159
 
280
- **CRITICAL: ActivityCard has no card styling by default. Must wrap in BaseCard for visible card background.**
160
+ ActivityCard wrapped in BaseCard:
281
161
 
282
162
  ```tsx
283
163
  <BaseCard>
@@ -288,30 +168,35 @@ Each traveler row:
288
168
  </BaseCard>
289
169
  ```
290
170
 
291
- **Data source:** Import `ESCALATION_CARDS` from sample data (alias of `EVA_ACTIONS`)
171
+ Each escalation: title, subtitle, status (`"working"` | `"pending"` | `"complete"`), timestamp.
172
+
173
+ ### 8b. Disruptions (Row 1, 1/3 width)
174
+
175
+ Custom inline component in BaseCard. Shows flights delayed 60+ min or grounded.
176
+
177
+ Each disruption card:
178
+ - Severity dot (rose=grounded, amber=delayed) + flight number + delay minutes
179
+ - Route + traveler name
180
+ - Reason text
181
+ - Eva action line with `SparklesIcon`
182
+
183
+ Data: `DISRUPTION_CARDS` from sample data.
292
184
 
293
- Each escalation has:
294
- - Title (issue description)
295
- - Subtitle (details + context)
296
- - Status: `"working"` (Eva is handling), `"pending"` (needs review), or `"complete"` (resolved)
297
- - Timestamp
185
+ ### 8c. Active Travelers (Row 2, 2/3 width)
298
186
 
299
- Examples from sample data:
300
- - "Processing approval for Omar Hassan" - subtitle: "Paris trip over budget · escalated to manager" (status: pending)
301
- - "Monitoring weather delay for Elena Rodriguez" - subtitle: "AF 99 · CDG arrival delayed 45 min · No action yet" (status: working)
302
- - "Rebooked cancelled flight for Priya Patel" - subtitle: "LH 431 → LH 433 · Same fare class" (status: complete)
187
+ BaseCard with `maxBodyHeight={420}`. Expandable traveler cards.
303
188
 
304
- ### 8d. Monthly Spend Trend (1/2 width)
189
+ Each row: `Avatar` (initials) + name + department + origin → destination + `UIChip` (compliant/exception).
190
+ Expand: 4-col grid — Flight, Hotel, Return, Destination.
305
191
 
306
- `ChartCard` wrapping a `D3Chart` with `D3ChartTemplates.groupedBarChart` (lineChart doesn't support categorical x-axis).
192
+ Data: `TRAVELER_CARDS` from sample data.
307
193
 
308
- **CRITICAL: Use this exact code structure:**
194
+ ### 8d. Monthly Spend Trend (Row 2, 1/3 width)
309
195
 
310
196
  ```tsx
311
- // Transform data to chart format
312
- const spendChartData = useDataSource({
313
- sample: MONTHLY_SPEND.map(m => ({ x: m.month, spend: m.amount })),
314
- live: []
197
+ const spendChartData = useDataSource({
198
+ sample: MONTHLY_SPEND.map(m => ({ x: m.month, spend: m.amount })),
199
+ live: [],
315
200
  });
316
201
 
317
202
  <ChartCard
@@ -336,145 +221,72 @@ const spendChartData = useDataSource({
336
221
  />
337
222
  ```
338
223
 
339
- **Data source:** Import `MONTHLY_SPEND` from sample data, transform to chart format
340
-
341
- **Requirements:**
342
- - X-axis: month names (Oct through Mar) - categorical
343
- - Y-axis: spend amount in dollars (will show as thousands: 98000, 128000, etc.)
344
- - Height: 320px
345
- - Bar color: Engine teal (#5BC8C8)
346
- - Bar radius: 6 for rounded corners
347
- - **Data transformation:** map `{ month, amount }` to `{ x, spend }` format inline
348
- - responsive={true}
349
-
350
- **Why this chart:** Shows spend trends over time so travel managers can spot anomalies, budget overruns, or seasonal patterns. Using bars instead of line because D3 lineChart requires numeric x-axis.
351
-
352
- **That's it!** Only 4 panels total: Disruptions, Active Travelers, Escalations, and Monthly Spend Trend.
353
-
354
224
  ---
355
225
 
356
- ## 9. Eva — ChatBar
226
+ ## 9. Eva — ChatBar (Phase 4)
357
227
 
358
- Eva surfaces as a `ChatBar` in the header. Not a FAB. Not a sliding panel. Not a `ChatPanel` in the grid.
228
+ ChatBar in the header. Not a FAB or sliding panel.
359
229
 
360
- ```jsx
230
+ ```tsx
361
231
  <ChatBar
362
232
  title="Eva"
363
233
  placeholder="Ask about travelers, bookings, policy, spend…"
364
- suggestions={suggestions}
234
+ suggestions={CHAT_SUGGESTIONS}
365
235
  onSend={handleChat}
366
236
  />
367
237
  ```
368
238
 
369
- **Starter suggestions (3–5):**
370
- - "Who's traveling internationally right now?"
371
- - "Show bookings pending approval"
372
- - "What has Eva resolved today?"
373
- - "Travelers returning this week"
239
+ Suggestions: "Who's traveling internationally right now?", "Show bookings pending approval", "What has Eva resolved today?", "Travelers returning this week"
374
240
 
375
- **Agent responses:** Return structured `components` arrays for data (MetricCard, DataTable, StatusCard) — never markdown tables in text content.
376
-
377
- **Handler:** Define `handleChat` and `CHAT_SUGGESTIONS` at module scope (outside the component body) so they can be shared if an "open in tab" feature is added later.
241
+ Define `handleChat` and `CHAT_SUGGESTIONS` at module scope.
378
242
 
379
243
  ---
380
244
 
381
- ## 10. Salesforce Signals (Phase 4 Only)
382
-
383
- **⚠️ These are added in Phase 4, NOT Phase 1.** Phase 1 has only the Engine logo and "Travel Command Center" title.
245
+ ## 10. Salesforce Signals (Phase 4)
384
246
 
385
- Subtle, contextual indicators — like "Sent from iPhone", not promotional banners.
247
+ Subtle indicators, not banners.
386
248
 
387
- | Signal | Location | Implementation | Phase |
388
- |--------|----------|----------------|-------|
389
- | "View in Salesforce" | Traveler expanded view, booking rows | Micro-link, muted text | Phase 4 |
390
- | "Salesforce updated" | After rebook/approve actions | `toast()` with success tone | Phase 4 |
391
- | "Powered by Agentforce" | ChatBar title or subtitle area | Small badge/chip | Phase 4 |
249
+ | Signal | Location |
250
+ |--------|----------|
251
+ | "View in Salesforce" | Traveler expanded view, booking rows (micro-link, muted text) |
252
+ | "Salesforce updated" | After rebook/approve actions (`toast()`) |
253
+ | "Powered by Agentforce" | ChatBar subtitle area (small badge) |
392
254
 
393
255
  ---
394
256
 
395
257
  ## 11. Dark Mode
396
258
 
397
- Mandatory on every element. The dashboard must work in both light and dark mode with no visual bugs.
398
-
399
- - Use the standard dark mode pairs from the builder rules (bg-white/dark:bg-slate-900, etc.)
400
- - The GeoMap has built-in dark/light themes — pass `theme={mode === "dark" ? "dark" : "light"}`
401
- - Glass overlays use `bg-black/40 backdrop-blur-md` which works in both modes
402
- - Custom inline components (disruption cards, flight chips) must include `dark:` variants on every color class
403
- - Never use `text-black` or `text-white` directly — use the slate scale
404
- - Theme toggle button in the header (sun/moon icon)
259
+ Every element supports light and dark. GeoMap: `theme={mode === "dark" ? "dark" : "light"}`. Glass overlays work in both modes. Use slate scale (no `text-white` or `text-black`). Theme toggle in header.
405
260
 
406
261
  ---
407
262
 
408
263
  ## 12. Data Model
409
264
 
410
- **Traveler** — `id`, `name`, `department`, `destination`, `origin`, `hotel`, `flight`, `return`, `status`, `policyStatus` (compliant | exception)
411
-
412
- **Flight** — `id`, `flight` (number), `route`, `dep` (time), `status` (On Time | Delayed | Boarding | In Air | Landed), `traveler`, `delayMin`
413
-
414
- **Disruption** — `id`, `flight`, `route`, `traveler`, `severity` (grounded | delayed), `delayMin`, `reason`, `evaAction`
415
-
416
- **Map Coordinates** — City name → `[lon, lat]` lookup object. Markers derived from coordinates. Arcs derived from flight origin/destination pairs.
417
-
418
- **Booking** — `id`, `traveler`, `type`, `destination`, `dates`, `cost`, `status` (Confirmed | Pending approval), `policy` (In policy | Over budget | Exception granted)
419
-
420
- **Policy Item** — `id`, `title`, `description`, `status` (operational | degraded), `timestamp`
421
-
422
- **Escalation** — `id`, `title`, `subtitle`, `status` (complete | working | pending), `timestamp`
423
-
424
- **Monthly Spend** — `{ month: string, amount: number }` array. Six months of travel spend data (Oct through Mar). Amounts in dollars, typically $98K-$156K range.
425
-
426
- **Sample data:** 8–10 travelers, 8 flights, 4 disruptions, 8 bookings, 5 policy items, 8 escalations, 6 months of spend. All deterministic (no `Math.random()`). Include realistic names, routes, dollar amounts, and a mix of all status types.
265
+ - **Traveler** — `id`, `name`, `department`, `destination`, `origin`, `hotel`, `flight`, `return`, `policyStatus` (compliant | exception)
266
+ - **Flight** — `id`, `flight`, `route`, `dep`, `status` (On Time | Delayed | Boarding | In Air | Landed), `traveler`, `delayMin`
267
+ - **Disruption** — `id`, `flight`, `route`, `traveler`, `severity` (grounded | delayed), `delayMin`, `reason`, `evaAction`
268
+ - **Escalation** — `id`, `title`, `subtitle`, `status` (complete | working | pending), `timestamp`
269
+ - **Monthly Spend** — `{ month, amount }` array, 6 months (Oct–Mar), $98K–$156K range
270
+ - **Sample data:** Pre-built in `src/data/engine-sample-data.js`. 8 travelers, 8 flights, 4 disruptions, 8 escalations, 6 months spend. All deterministic.
427
271
 
428
272
  ---
429
273
 
430
274
  ## 13. Build Prompts
431
275
 
432
- Build in 4 incremental phases. Each prompt maps to one beat of the demo arc.
433
-
434
- ---
276
+ Build in 4 incremental phases.
435
277
 
436
278
  ### Phase 1: Layout & Structure
437
279
 
438
280
  > Scaffold the Engine Travel Command Center skeleton. Build the visualization-hero layout from section 5 with the header, hero map, glass KPI overlays, flight status strip, and placeholder cards for the data panels.
439
281
 
440
- ---
441
-
442
282
  ### Phase 2: Components & Sample Data
443
283
 
444
- > Replace the placeholders with real components and wire up the sample data. Build the 4 data panels from section 8 — Disruptions, Active Travelers, Escalations, and Monthly Spend Trend. Add map markers, arcs, and overlays from the sample data so we can see where travelers are.
445
-
446
- ---
284
+ > Replace the placeholders with real components and wire up the sample data. Build the 4 data panels from section 8 — Escalations, Disruptions, Active Travelers, and Monthly Spend Trend. Add map markers, arcs, and overlays from the sample data so we can see where travelers are.
447
285
 
448
286
  ### Phase 3: Real Data Integration
449
287
 
450
288
  > Connect the dashboard to live Salesforce data using GraphQL. Read the sample data file to see which fields are needed, then build queries and hooks for each object. The UI should stay identical — just swap the data source.
451
289
 
452
- ---
453
-
454
290
  ### Phase 4: Agentforce Integration
455
291
 
456
292
  > Add Eva to the header as a ChatBar. Add subtle Salesforce signals throughout — "View in Salesforce" links, success toasts, "Powered by Agentforce" badge.
457
-
458
- ---
459
-
460
- ## 14. What NOT to Do
461
-
462
- These are explicit anti-patterns. If any prompt output includes these, it must be corrected:
463
-
464
- - Do not use `react-simple-maps`, Recharts, or any charting library other than the built-in `D3Chart` + `D3ChartTemplates`
465
- - Do not use Lucide icons, Font Awesome, or any icon library other than Heroicons 2
466
- - Do not import from `src/components/ui/` (shadcn) — use `@/components/library` exclusively
467
- - Do not use `cn()` helper — that belongs to the outer app
468
- - Do not recreate `AppThemeProvider`, `DataModeProvider`, or `Toast.Provider` — `CommandCenter.tsx` provides them
469
- - Do not build a FAB or sliding chat panel — use `ChatBar` in the header
470
- - Do not hardcode hex color values in component JSX — use `brand-*` Tailwind classes and Tailwind built-in colors for status
471
- - Do not use `bg-indigo-*` for brand — use `brand-*`
472
- - Do not use `text-black` or `text-white` — use the slate scale
473
- - Do not put more than 4 KPIs in a row
474
- - Do not squeeze the map into a grid column — it must be full-width hero
475
- - Do not wrap GeoMap in ChartCard — render it directly
476
- - Do not use `Math.random()` in sample data
477
- - Do not skip dark mode on any visible element
478
- - Do not use inline `style={{}}` for layout except the flex properties on the hero/panel containers
479
- - Do not put `ChatPanel` in the dashboard grid
480
- - Do not use `position: fixed` without `createPortal` to `document.body`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schandlergarcia/sf-web-components",
3
- "version": "1.9.67",
3
+ "version": "1.9.68",
4
4
  "description": "Reusable Salesforce web components library with Tailwind CSS v4 and shadcn/ui",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",