@schandlergarcia/sf-web-components 1.9.88 → 2.1.0
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/.a4drules/features/command-center-dashboard-rule.md +1 -1
- package/.a4drules/skills/command-center-builder/SKILL.md +33 -36
- package/.a4drules/skills/command-center-builder/getting-started.md +64 -104
- package/.a4drules/skills/command-center-builder/improved-build-process.md +28 -34
- package/.a4drules/skills/command-center-guide/SKILL.md +9 -9
- package/.a4drules/skills/command-center-project/SKILL.md +4 -5
- package/.a4drules/skills/component-library/SKILL.md +8 -10
- package/.a4drules/skills/component-library/card-components.md +3 -3
- package/.a4drules/skills/component-library/chat-data.md +4 -6
- package/.a4drules/troubleshooting/codegen-overwrites-types.md +21 -162
- package/.a4drules/troubleshooting/graphql-introspection-failure.md +13 -264
- package/.a4drules/validation-requirements.md +3 -5
- package/.a4drules/webapp-data.md +1 -1
- package/CHANGELOG.md +33 -0
- package/CLAUDE.md +42 -39
- package/brands/engine/brand.css +40 -0
- package/brands/engine/global.css +234 -0
- package/dist/components/library/cards/ActivityCard.js +9 -9
- package/dist/components/library/cards/ActivityCard.js.map +1 -1
- package/dist/styles/base.css +112 -27
- package/dist/styles/global.css +15 -30
- package/package.json +7 -4
- package/scripts/apply-brand.mjs +178 -0
- package/scripts/postinstall.mjs +24 -201
- package/scripts/reset-command-center.sh +53 -411
- package/scripts/validate-dashboard.sh +4 -4
- package/src/components/library/cards/ActivityCard.jsx +2 -2
- package/src/styles/base.css +223 -0
- package/src/styles/global.css +223 -0
- package/src/templates/config/vite.config.ts.template +0 -18
- package/.a4drules/features/engine-dashboard-rule.md +0 -63
- package/.a4drules/features/phase2-data-pattern.md +0 -15
- package/data/README.md +0 -202
- package/data/USAGE.md +0 -81
- package/data/copy-to-webapp.sh +0 -61
- package/scripts/generate-schema-from-sample.mjs +0 -370
- /package/{data → brands/engine}/agentApiConfig.ts +0 -0
- /package/{data → brands/engine}/engine-command-center-prd.md +0 -0
- /package/{data → brands/engine}/engine-live-data.js +0 -0
- /package/{data → brands/engine}/engine-sample-data.js +0 -0
- /package/{assets/images → brands/engine}/engine_logo.png +0 -0
- /package/{data → brands/engine}/schema.graphql +0 -0
- /package/{data → brands/engine}/useEngineLiveData.ts +0 -0
- /package/{data → brands/engine}/useEvaAgent.ts +0 -0
|
@@ -13,274 +13,23 @@ This is an **org-level bug** where at least one field in the Salesforce org has
|
|
|
13
13
|
|
|
14
14
|
## What's Broken
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
- ❌ Full schema with all org objects and fields
|
|
18
|
-
- ❌ Some IDE autocomplete features that query the org directly
|
|
16
|
+
The GraphQL server attempts to enumerate every object and field in the org. If ANY field across any object has a null `getDataType()`, the entire introspection fails. This prevents `codegen` from generating types.
|
|
19
17
|
|
|
20
|
-
##
|
|
18
|
+
## Workaround
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
1. **Use a pre-built `schema.graphql`** — If you have one checked into the repo, keep using it
|
|
21
|
+
2. **Query specific objects** — Instead of full introspection, query only the objects you need:
|
|
22
|
+
```graphql
|
|
23
|
+
{ uiapi { query { Account { edges { node { Id Name { value } } } } } } }
|
|
24
|
+
```
|
|
25
|
+
3. **Run `get-graphql-schema.mjs`** — This script uses the Salesforce SDK to attempt introspection. If it fails, use the pre-built schema.
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
## Key Point
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
The `schema.graphql` file is **already checked into the repo** at the project root. It was generated from the sample data file and includes all Engine objects.
|
|
33
|
-
|
|
34
|
-
**You don't need to generate anything** — the schema is ready to use.
|
|
35
|
-
|
|
36
|
-
**What this provides:**
|
|
37
|
-
- ✅ `exploring-webapp-graphql-schema` skill works normally
|
|
38
|
-
- ✅ `generating-webapp-graphql-read-query` skill works normally
|
|
39
|
-
- ✅ `using-webapp-graphql` skill works normally
|
|
40
|
-
- ✅ IDE autocomplete and validation
|
|
41
|
-
- ✅ GraphQL codegen
|
|
42
|
-
- ✅ Normal Phase 3 workflow without manual workarounds
|
|
43
|
-
- ✅ Works in CI/CD without org access
|
|
44
|
-
|
|
45
|
-
**Schema contents:**
|
|
46
|
-
- Contact (travelers with custom fields)
|
|
47
|
-
- Trip__c, Flight__c, Booking__c, Disruption__c, Rebooking_Action__c, Travel_Policy__c
|
|
48
|
-
- All fields from `src/data/engine-sample-data.js`
|
|
49
|
-
|
|
50
|
-
## Regenerating the Schema (Optional)
|
|
51
|
-
|
|
52
|
-
If you need to update the schema (e.g., after adding new fields to sample data):
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
# From the webapp directory
|
|
56
|
-
npm run graphql:schema:sample
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
This regenerates `schema.graphql` from the current sample data file. Then commit the updated schema to git.
|
|
60
|
-
|
|
61
|
-
## Fallback: Copy Working Query Patterns (Manual)
|
|
62
|
-
|
|
63
|
-
Since introspection fails but queries work, you can implement GraphQL features by copying working patterns from elsewhere in the codebase.
|
|
64
|
-
|
|
65
|
-
### Step 1: Find a Working Query
|
|
66
|
-
|
|
67
|
-
Look for existing GraphQL implementations (e.g., Account search, Contact queries in other features):
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
cd force-app/main/default/webapplications/reactapp4
|
|
71
|
-
grep -r "uiapi {" src/
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Step 2: Copy the Pattern
|
|
75
|
-
|
|
76
|
-
The working pattern for UI API GraphQL queries:
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
import { createDataSDK, gql } from "@salesforce/sdk-data";
|
|
80
|
-
|
|
81
|
-
const GET_TRIPS = gql`
|
|
82
|
-
query GetTrips {
|
|
83
|
-
uiapi {
|
|
84
|
-
query {
|
|
85
|
-
Trip__c(first: 50) {
|
|
86
|
-
edges {
|
|
87
|
-
node {
|
|
88
|
-
Id
|
|
89
|
-
Trip_Name__c @optional { value }
|
|
90
|
-
Origin_City__c @optional { value }
|
|
91
|
-
Destination_City__c @optional { value }
|
|
92
|
-
Contact__c @optional { value }
|
|
93
|
-
Start_Date__c @optional { value }
|
|
94
|
-
End_Date__c @optional { value }
|
|
95
|
-
Status__c @optional { value }
|
|
96
|
-
Total_Cost__c @optional { value }
|
|
97
|
-
In_Policy__c @optional { value }
|
|
98
|
-
Has_Disruption__c @optional { value }
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
`;
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
**Critical elements:**
|
|
109
|
-
- `uiapi { query { ... } }` wrapper
|
|
110
|
-
- Object name matches Salesforce API name (e.g., `Trip__c`, `Contact`)
|
|
111
|
-
- `@optional` directive on ALL fields except `Id` (for FLS resilience)
|
|
112
|
-
- Nested field access: `FieldName { value }` for most fields
|
|
113
|
-
- Lookup fields: `RelatedObject__c { Name { value } }`
|
|
114
|
-
|
|
115
|
-
### Step 3: Implement Hooks
|
|
116
|
-
|
|
117
|
-
Create custom hooks using the Data SDK pattern:
|
|
118
|
-
|
|
119
|
-
```typescript
|
|
120
|
-
import { useState, useEffect } from "react";
|
|
121
|
-
import { createDataSDK } from "@salesforce/sdk-data";
|
|
122
|
-
|
|
123
|
-
export function useTrips() {
|
|
124
|
-
const [data, setData] = useState<any[] | null>(null);
|
|
125
|
-
const [loading, setLoading] = useState(true);
|
|
126
|
-
const [error, setError] = useState<Error | null>(null);
|
|
127
|
-
|
|
128
|
-
useEffect(() => {
|
|
129
|
-
let mounted = true;
|
|
130
|
-
|
|
131
|
-
async function fetchData() {
|
|
132
|
-
try {
|
|
133
|
-
const sdk = await createDataSDK();
|
|
134
|
-
const response = await sdk.graphql?.(GET_TRIPS);
|
|
135
|
-
|
|
136
|
-
if (!mounted) return;
|
|
137
|
-
|
|
138
|
-
if (response?.errors?.length) {
|
|
139
|
-
throw new Error(response.errors.map((e: any) => e.message).join("; "));
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const edges = response?.data?.uiapi?.query?.Trip__c?.edges ?? [];
|
|
143
|
-
const trips = edges.map((edge: any) => ({
|
|
144
|
-
Id: edge.node.Id,
|
|
145
|
-
Trip_Name__c: edge.node.Trip_Name__c?.value ?? null,
|
|
146
|
-
Origin_City__c: edge.node.Origin_City__c?.value ?? null,
|
|
147
|
-
// ... map all fields with optional chaining
|
|
148
|
-
}));
|
|
149
|
-
|
|
150
|
-
setData(trips);
|
|
151
|
-
setError(null);
|
|
152
|
-
} catch (err) {
|
|
153
|
-
if (mounted) {
|
|
154
|
-
setError(err instanceof Error ? err : new Error(String(err)));
|
|
155
|
-
}
|
|
156
|
-
} finally {
|
|
157
|
-
if (mounted) {
|
|
158
|
-
setLoading(false);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
fetchData();
|
|
164
|
-
|
|
165
|
-
return () => {
|
|
166
|
-
mounted = false;
|
|
167
|
-
};
|
|
168
|
-
}, []);
|
|
169
|
-
|
|
170
|
-
return { data, loading, error };
|
|
171
|
-
}
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
### Step 4: Get Field Names from Sample Data
|
|
175
|
-
|
|
176
|
-
The sample data file already has real Salesforce field names. Read `src/data/engine-sample-data.js` to see which fields exist:
|
|
177
|
-
|
|
178
|
-
```javascript
|
|
179
|
-
// File: src/data/engine-sample-data.js
|
|
180
|
-
export const TRIPS = [
|
|
181
|
-
{
|
|
182
|
-
Id: "a00xx000001",
|
|
183
|
-
Trip_Name__c: "Q1 Sales Conference - SF",
|
|
184
|
-
Origin_City__c: "New York",
|
|
185
|
-
Destination_City__c: "San Francisco",
|
|
186
|
-
// ... etc
|
|
187
|
-
}
|
|
188
|
-
];
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
Copy these exact field names into your GraphQL query.
|
|
192
|
-
|
|
193
|
-
### Step 5: Test Your Queries
|
|
194
|
-
|
|
195
|
-
Create a test script to verify queries work:
|
|
196
|
-
|
|
197
|
-
```javascript
|
|
198
|
-
// scripts/test-engine-query.mjs
|
|
199
|
-
import { getOrgInfo } from '@salesforce/webapp-experimental/app';
|
|
200
|
-
|
|
201
|
-
async function testQuery(query, objectName) {
|
|
202
|
-
const { rawInstanceUrl, apiVersion, accessToken } = await getOrgInfo();
|
|
203
|
-
|
|
204
|
-
const response = await fetch(
|
|
205
|
-
`${rawInstanceUrl}/services/data/v${apiVersion}/graphql`,
|
|
206
|
-
{
|
|
207
|
-
method: 'POST',
|
|
208
|
-
headers: {
|
|
209
|
-
Authorization: `Bearer ${accessToken}`,
|
|
210
|
-
'Content-Type': 'application/json',
|
|
211
|
-
'X-Chatter-Entity-Encoding': 'false',
|
|
212
|
-
},
|
|
213
|
-
body: JSON.stringify({ query }),
|
|
214
|
-
}
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
const result = await response.json();
|
|
218
|
-
|
|
219
|
-
if (result.errors) {
|
|
220
|
-
console.error(`❌ ${objectName} query failed:`, result.errors);
|
|
221
|
-
return false;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
console.log(`✅ ${objectName} query succeeded`);
|
|
225
|
-
console.log(` Records found: ${result.data?.uiapi?.query?.[objectName]?.edges?.length}`);
|
|
226
|
-
return true;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// Test your queries
|
|
230
|
-
await testQuery(`query { uiapi { query { Trip__c(first: 1) { edges { node { Id } } } } } }`, 'Trip__c');
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
Run: `node scripts/test-engine-query.mjs`
|
|
234
|
-
|
|
235
|
-
## For Agents Building the Dashboard
|
|
236
|
-
|
|
237
|
-
**The schema.graphql file is already in the repo.** Just use the GraphQL skills normally:
|
|
238
|
-
|
|
239
|
-
1. `exploring-webapp-graphql-schema` — Looks up field names
|
|
240
|
-
2. `generating-webapp-graphql-read-query` — Creates queries
|
|
241
|
-
3. `using-webapp-graphql` — Implements hooks
|
|
242
|
-
|
|
243
|
-
No schema generation needed during Phase 3.
|
|
244
|
-
|
|
245
|
-
## For Developers Adding Fields
|
|
246
|
-
|
|
247
|
-
If you add new fields to `src/data/engine-sample-data.js`, regenerate the schema:
|
|
248
|
-
|
|
249
|
-
```bash
|
|
250
|
-
cd force-app/main/default/webapplications/reactapp4
|
|
251
|
-
npm run graphql:schema:sample
|
|
252
|
-
git add ../../../../../../schema.graphql
|
|
253
|
-
git commit -m "Update schema with new fields"
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
## Decision Tree for Schema Updates
|
|
257
|
-
|
|
258
|
-
**Do you need to update schema.graphql?**
|
|
259
|
-
|
|
260
|
-
- ❌ Building dashboard from existing sample data? → No, use existing schema
|
|
261
|
-
- ✅ Added new fields to sample data? → Run `npm run graphql:schema:sample`
|
|
262
|
-
- ✅ Added new custom objects? → Update generation script first, then regenerate
|
|
263
|
-
- ✅ Want to try org introspection? → Run `npm run graphql:schema` (may fail)
|
|
264
|
-
|
|
265
|
-
## Prevention
|
|
266
|
-
|
|
267
|
-
This is an org-level bug that can't be prevented from the web app side. The org admin would need to identify and fix the field(s) with null data types. However, this workaround allows development to continue without waiting for org fixes.
|
|
29
|
+
The introspection failure does NOT affect runtime queries. You can still query any object via GraphQL — only the schema generation step is broken.
|
|
268
30
|
|
|
269
31
|
## Related Files
|
|
270
32
|
|
|
271
|
-
-
|
|
272
|
-
- `
|
|
273
|
-
- `
|
|
274
|
-
- `scripts/test-engine-query.mjs` — Test script to verify queries work despite introspection failure
|
|
275
|
-
|
|
276
|
-
## Success Indicators
|
|
277
|
-
|
|
278
|
-
You've successfully worked around the issue when:
|
|
279
|
-
|
|
280
|
-
- ✅ All custom hooks return data correctly (`{ data, loading, error }`)
|
|
281
|
-
- ✅ Dashboard displays live Salesforce data
|
|
282
|
-
- ✅ No GraphQL-related errors in browser console
|
|
283
|
-
- ✅ Test script shows all queries succeed
|
|
284
|
-
- ✅ Loading and error states work properly
|
|
285
|
-
|
|
286
|
-
The fact that schema.graphql doesn't exist is fine — it's only needed for introspection-based tooling, not for runtime queries.
|
|
33
|
+
- `scripts/get-graphql-schema.mjs` — The script that runs introspection
|
|
34
|
+
- `schema.graphql` — Pre-built schema (if available)
|
|
35
|
+
- `vite.config.ts` — Codegen plugin configuration (disabled by default to prevent issues)
|
|
@@ -176,12 +176,10 @@ Any other output means there are errors that MUST be fixed.
|
|
|
176
176
|
|
|
177
177
|
## Integration with Build Phases
|
|
178
178
|
|
|
179
|
-
|
|
179
|
+
Run the validator at the end of each build phase before proceeding to the next:
|
|
180
180
|
|
|
181
|
-
- **End of
|
|
182
|
-
- **
|
|
183
|
-
- **End of Phase 3:** Run validator, fix errors → proceed to Phase 4
|
|
184
|
-
- **End of Phase 4:** Run validator, fix errors → DONE
|
|
181
|
+
- **End of each phase:** Run validator, fix all errors → proceed to next phase
|
|
182
|
+
- **Final phase:** Run validator, fix all errors → DONE
|
|
185
183
|
|
|
186
184
|
## Do Not Run These Instead
|
|
187
185
|
|
package/.a4drules/webapp-data.md
CHANGED
|
@@ -64,7 +64,7 @@ const res = await sdk.fetch?.("/services/apexrest/my-resource");
|
|
|
64
64
|
|
|
65
65
|
The `schema.graphql` file is **already checked into the repo** at the SFDX project root. **Never open or parse it directly.**
|
|
66
66
|
|
|
67
|
-
- Pre-built from sample data, contains
|
|
67
|
+
- Pre-built from sample data, contains standard and custom objects
|
|
68
68
|
- No generation needed — just use it
|
|
69
69
|
- If you ever need to regenerate (after adding fields to sample data): `npm run graphql:schema:sample` from webapp dir
|
|
70
70
|
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,39 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.1.0] - 2026-04-04
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Brand system** — `npm run brand:engine` applies Engine branding (colors, sample data, PRD, hooks, logo) on top of the generic framework. `npm run brand:reset` reverts to neutral. `npm run brand:list` shows available brands.
|
|
12
|
+
- **`brands/engine/`** directory with Engine-branded `global.css` using official brand guidelines: Engine Black #0D1117, Cyan #7DCBD9, Green #1E9D6D, Blue #157DE5, Orange-Red #FD4B23, Amber #FFB200.
|
|
13
|
+
- **`scripts/apply-brand.mjs`** — brand application script that copies brand CSS, sample data, hooks, configs, PRD, schema, and logo into the consuming project.
|
|
14
|
+
- **`.brand` marker file** — tracks the active brand so `reset-command-center.sh` preserves it.
|
|
15
|
+
- **Brand-aware reset** — when a brand is active, `reset-command-center.sh` restores the brand's `global.css` instead of neutral.
|
|
16
|
+
- **Postinstall brand scripts** — `brand:engine`, `brand:reset`, `brand:list` npm scripts are automatically added to consuming projects.
|
|
17
|
+
|
|
18
|
+
## [2.0.0] - 2026-04-04
|
|
19
|
+
|
|
20
|
+
### Changed — Generic framework release
|
|
21
|
+
Stripped all Engine Travel-specific content to make the package a generic component framework anyone can use.
|
|
22
|
+
|
|
23
|
+
- **Postinstall** — removed Engine sample data, Engine PRD, Engine logo, useEvaAgent, agentApiConfig, useEngineLiveData, schema.graphql, and generate-schema-from-sample copies. Now only installs the generic component library, templates, config files, utility scripts, and .a4drules.
|
|
24
|
+
- **Reset script** — removed Engine brand CSS inline write (now copies neutral `global.css` from package), removed Engine data/hook/schema/PRD/logo restores, removed Engine-specific `KEEP_CLASSES` (TCC_TravelMetricsController) from Apex cleanup.
|
|
25
|
+
- **global.css** — replaced Engine brand palette (`--color-engine-*`, teal #5BC8C8) with neutral sky-blue brand tokens (`--color-brand-*`, #0EA5E9). Replaced Engine coral (#FF5722) with standard red (#EF4444) in `.heroui-scope`.
|
|
26
|
+
- **vite.config.ts.template** — removed hardcoded Salesforce org proxy rules (`/sf-oauth`, `/sf-agent` with tdx26-keynote-org URL).
|
|
27
|
+
- **package.json** — removed `data` and `assets` from `files` array. Added `src/styles`.
|
|
28
|
+
- **.a4drules** — deleted `engine-dashboard-rule.md` and `phase2-data-pattern.md`. Generalized all remaining files: removed Engine PRD/data references from SKILL.md, getting-started.md, improved-build-process.md, chat-data.md, webapp-data.md, validation-requirements.md, and command-center-dashboard-rule.md.
|
|
29
|
+
- **CLAUDE.md** — rewrote to describe generic framework without Engine references.
|
|
30
|
+
- **ActivityCard.jsx** — renamed `action.traveler` fallback to `action.description`.
|
|
31
|
+
- **validate-dashboard.sh** — renamed `TRAVEL_DIR` to `CUSTOM_DIR`.
|
|
32
|
+
|
|
33
|
+
### Removed
|
|
34
|
+
- `scripts/generate-schema-from-sample.mjs` (Engine-specific schema generator)
|
|
35
|
+
- `.a4drules/features/engine-dashboard-rule.md`
|
|
36
|
+
- `.a4drules/features/phase2-data-pattern.md`
|
|
37
|
+
|
|
38
|
+
### Note
|
|
39
|
+
The `data/` directory still exists in the repository for reference but is no longer published or copied by postinstall.
|
|
40
|
+
|
|
8
41
|
## [1.9.88] - 2026-04-07
|
|
9
42
|
|
|
10
43
|
### Fixed
|
package/CLAUDE.md
CHANGED
|
@@ -10,8 +10,7 @@ This file provides guidance to Claude Code when working with the sf-web-componen
|
|
|
10
10
|
2. **Templates** - Page templates (Home, Search, NotFound, BlankDashboard) and config templates (routes.tsx, vite.config.ts, dataStrategy.ts)
|
|
11
11
|
3. **Automation** - Postinstall script that sets up consuming projects automatically
|
|
12
12
|
4. **Documentation** - `.a4drules` skills and features for AI-assisted development
|
|
13
|
-
5. **
|
|
14
|
-
6. **Scripts** - Reset scripts, validation scripts, schema generation
|
|
13
|
+
5. **Scripts** - Reset scripts, validation scripts
|
|
15
14
|
|
|
16
15
|
**Primary use case:** Building Salesforce Web Applications with React, specifically for:
|
|
17
16
|
- Outer app pages (search, navigation) using shadcn/ui + Tailwind
|
|
@@ -31,18 +30,18 @@ The package supports **two distinct UI contexts** that must NOT be mixed:
|
|
|
31
30
|
- `Input` from `@/components/ui/input`
|
|
32
31
|
- etc.
|
|
33
32
|
- **Icons:** Lucide React (`lucide-react`)
|
|
34
|
-
- **Styling:** Neutral shadcn theme (slate colors
|
|
33
|
+
- **Styling:** Neutral shadcn theme (slate colors)
|
|
35
34
|
- **File type:** `.tsx`
|
|
36
35
|
|
|
37
36
|
#### 2. Command Center Context
|
|
38
|
-
- **Files:** Dashboard pages in `src/pages/` (e.g., BlankDashboard,
|
|
37
|
+
- **Files:** Dashboard pages in `src/pages/` (e.g., BlankDashboard, custom dashboards)
|
|
39
38
|
- **Rendered in:** CommandCenter wrapper with `.heroui-scope` class
|
|
40
39
|
- **Components:** Library components from `@/components/library`
|
|
41
40
|
- `UIButton` from `@/components/library/ui/UIButton`
|
|
42
41
|
- `UIInput` from `@/components/library/ui/UIInput`
|
|
43
42
|
- `MetricCard`, `ChartCard`, `ListCard`, `TableCard`, etc.
|
|
44
43
|
- **Icons:** Heroicons (`@heroicons/react`)
|
|
45
|
-
- **Styling:**
|
|
44
|
+
- **Styling:** Brand colors defined in `global.css` inside `.heroui-scope`
|
|
46
45
|
- **File type:** `.jsx` or `.tsx`
|
|
47
46
|
|
|
48
47
|
**Common mistake:** Using UIButton/UIInput in outer app pages or shadcn Button/Input in command center dashboards. Check `.a4drules/features/pre-code-checklist.md` for validation rules.
|
|
@@ -67,18 +66,17 @@ sf-web-components/
|
|
|
67
66
|
│ │ ├── lib/ # dataStrategy.ts.template
|
|
68
67
|
│ │ └── workspace/ # CommandCenter.tsx.template
|
|
69
68
|
│ ├── lib/ # Utilities (utils.ts)
|
|
70
|
-
│ └── styles/ # global.css with
|
|
69
|
+
│ └── styles/ # global.css with neutral brand tokens
|
|
70
|
+
├── brands/
|
|
71
|
+
│ └── engine/ # Engine brand (global.css, sample data, PRD, hooks)
|
|
71
72
|
├── scripts/
|
|
72
73
|
│ ├── postinstall.mjs # Runs after npm install in consuming projects
|
|
74
|
+
│ ├── apply-brand.mjs # Apply/reset brand themes
|
|
73
75
|
│ ├── reset-command-center.sh
|
|
74
76
|
│ ├── validate-dashboard.sh
|
|
75
77
|
│ └── verify-consistency.sh
|
|
76
|
-
├── data/
|
|
77
|
-
│ ├── engine-sample-data.js
|
|
78
|
-
│ ├── schema.graphql
|
|
79
|
-
│ └── engine-command-center-prd.md
|
|
80
78
|
└── .a4drules/
|
|
81
|
-
├── features/ # Dashboard rules,
|
|
79
|
+
├── features/ # Dashboard rules, pre-code checklist
|
|
82
80
|
├── skills/ # component-library, command-center-builder, etc.
|
|
83
81
|
├── troubleshooting/ # Common issues and solutions
|
|
84
82
|
├── validation-requirements.md
|
|
@@ -86,6 +84,26 @@ sf-web-components/
|
|
|
86
84
|
└── webapp-ui.md
|
|
87
85
|
```
|
|
88
86
|
|
|
87
|
+
## Brand System
|
|
88
|
+
|
|
89
|
+
The package ships with a **neutral theme** by default. Opt into a specific brand:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
npm run brand:engine # Apply Engine brand (colors, sample data, PRD, hooks)
|
|
93
|
+
npm run brand:reset # Revert to neutral theme
|
|
94
|
+
npm run brand:list # Show available brands
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
When a brand is active, the reset script (`npm run reset:command-center`) preserves the brand's `global.css` instead of restoring neutral. The `.brand` marker file tracks which brand is active.
|
|
98
|
+
|
|
99
|
+
### Engine Brand
|
|
100
|
+
- **Primary:** Engine Black `#0D1117`
|
|
101
|
+
- **Accent:** Cyan `#7DCBD9`, Green `#1E9D6D`, Blue `#157DE5`
|
|
102
|
+
- **Secondary:** Orange-Red `#FD4B23`, Amber `#FFB200`
|
|
103
|
+
- **Neutrals:** Dark Gray `#616368`, Mid Gray `#B0B1B3`, Light Gray `#F3F3F4`
|
|
104
|
+
|
|
105
|
+
Installs: Engine-branded `global.css`, sample data, live data, PRD, GraphQL schema, Eva agent hook, agent config, and Engine logo.
|
|
106
|
+
|
|
89
107
|
## Key Conventions
|
|
90
108
|
|
|
91
109
|
### Component Naming
|
|
@@ -103,9 +121,9 @@ sf-web-components/
|
|
|
103
121
|
```javascript
|
|
104
122
|
import useDataSource from "@/components/library/data/useDataSource";
|
|
105
123
|
|
|
106
|
-
const
|
|
107
|
-
sample:
|
|
108
|
-
live:
|
|
124
|
+
const items = useDataSource({
|
|
125
|
+
sample: SAMPLE_DATA,
|
|
126
|
+
live: liveData ?? []
|
|
109
127
|
});
|
|
110
128
|
```
|
|
111
129
|
- **Configuration:** `src/lib/dataStrategy.ts` controls `ENABLE_SAMPLE_DATA_CACHE`
|
|
@@ -149,12 +167,9 @@ When a project installs this package, `scripts/postinstall.mjs` automatically:
|
|
|
149
167
|
4. **Copies workspace files** to `src/components/workspace/`
|
|
150
168
|
5. **Installs page templates** to `src/pages/` (Home.tsx, Search.tsx, NotFound.tsx, BlankDashboard.tsx)
|
|
151
169
|
6. **Updates imports** in existing files (changes package imports to local `@/components/library` imports)
|
|
152
|
-
7. **
|
|
153
|
-
8. **
|
|
154
|
-
9. **Copies
|
|
155
|
-
10. **Installs config files** (routes.tsx, vite.config.ts, dataStrategy.ts) if they don't exist
|
|
156
|
-
11. **Adds npm scripts** to package.json (reset:command-center, validate:dashboard, graphql:schema:sample)
|
|
157
|
-
12. **Copies .a4drules** to project root for AI assistant discoverability
|
|
170
|
+
7. **Installs config files** (routes.tsx, vite.config.ts, dataStrategy.ts) if they don't exist
|
|
171
|
+
8. **Adds npm scripts** to package.json (reset:command-center, validate:dashboard)
|
|
172
|
+
9. **Copies .a4drules** to project root for AI assistant discoverability
|
|
158
173
|
|
|
159
174
|
**Important:** Templates are **always overwritten** to ensure latest versions, except for config files (vite.config.ts, dataStrategy.ts) which only install if missing.
|
|
160
175
|
|
|
@@ -170,8 +185,10 @@ The `scripts/reset-command-center.sh` provides a clean baseline for projects:
|
|
|
170
185
|
- Updates routes.tsx to include Home, /accounts, and /accounts/:recordId
|
|
171
186
|
- Updates appLayout.tsx with nav bar
|
|
172
187
|
- Clears Vite cache
|
|
173
|
-
- Restores
|
|
174
|
-
- Restores
|
|
188
|
+
- Restores neutral theme (global.css from package)
|
|
189
|
+
- Restores dataStrategy.ts
|
|
190
|
+
- Restores .a4drules
|
|
191
|
+
- Cleans Apex classes and platform events (if SFDX project)
|
|
175
192
|
|
|
176
193
|
## Important Files
|
|
177
194
|
|
|
@@ -184,22 +201,14 @@ Complete history of all changes. ALWAYS update when making changes. Include:
|
|
|
184
201
|
|
|
185
202
|
### .a4drules/
|
|
186
203
|
AI assistant documentation. Key files:
|
|
187
|
-
- `features/engine-dashboard-rule.md` - How to build Engine Travel Command Center
|
|
188
204
|
- `features/command-center-dashboard-rule.md` - Dashboard development rules
|
|
189
205
|
- `features/pre-code-checklist.md` - Pre-implementation validation
|
|
190
206
|
- `skills/component-library/` - Component API reference
|
|
207
|
+
- `skills/command-center-builder/` - How to build Command Center dashboards
|
|
191
208
|
- `validation-requirements.md` - Validation rules
|
|
192
209
|
- `webapp-data.md` - Data access patterns (GraphQL, REST, SDK usage)
|
|
193
210
|
- `webapp-ui.md` - UI platform rules
|
|
194
211
|
|
|
195
|
-
### data/engine-command-center-prd.md
|
|
196
|
-
Product Requirements Document for Engine Travel Command Center. Defines:
|
|
197
|
-
- Product overview and users
|
|
198
|
-
- Brand tokens (Engine teal #5BC8C8, etc.)
|
|
199
|
-
- Layout structure (visualization-hero pattern)
|
|
200
|
-
- Component sections and data model
|
|
201
|
-
- Phase-by-phase build instructions
|
|
202
|
-
|
|
203
212
|
### src/components/library/theme/AppThemeProvider.jsx
|
|
204
213
|
Theme provider with dark mode toggle. Exports:
|
|
205
214
|
- **Default:** `AppThemeProvider` component
|
|
@@ -235,7 +244,7 @@ Routes need `handle: { showInNavigation: true, showNavBar: true }` for nav bar t
|
|
|
235
244
|
## Testing
|
|
236
245
|
|
|
237
246
|
Before publishing:
|
|
238
|
-
1. Test in a real project
|
|
247
|
+
1. Test in a real project
|
|
239
248
|
2. Run `npm install @schandlergarcia/sf-web-components@latest`
|
|
240
249
|
3. Verify postinstall behavior
|
|
241
250
|
4. Check templates are correct
|
|
@@ -245,13 +254,7 @@ Before publishing:
|
|
|
245
254
|
|
|
246
255
|
## Version History
|
|
247
256
|
|
|
248
|
-
See CHANGELOG.md for complete history.
|
|
249
|
-
- v1.9.55 - Fixed UIButton/Button confusion in templates
|
|
250
|
-
- v1.9.56 - Fixed reset script 404 errors
|
|
251
|
-
- v1.9.57 - Restored "Browse All Accounts" button
|
|
252
|
-
- v1.9.58 - Fixed reset routes pointing to wrong Home file
|
|
253
|
-
- v1.9.59 - Restored navigation bar (showNavBar flag)
|
|
254
|
-
- v1.9.60-61 - Synced .a4drules and PRD from reactapp4
|
|
257
|
+
See CHANGELOG.md for complete history.
|
|
255
258
|
|
|
256
259
|
## Current Version
|
|
257
260
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Engine Brand Overrides
|
|
3
|
+
*
|
|
4
|
+
* Applied on top of the base global.css when `npm run brand:engine` is run.
|
|
5
|
+
* Colors sourced from the official Engine Brand Guidelines.
|
|
6
|
+
*
|
|
7
|
+
* Primary: Engine Black #0D1117, White #FFFFFF
|
|
8
|
+
* Secondary: Orange-Red #FD4B23, Amber #FFB200, Green #1E9D6D,
|
|
9
|
+
* Cyan #7DCBD9, Blue #157DE5
|
|
10
|
+
* Neutrals: Dark Gray #616368, Mid Gray #B0B1B3, Light Gray #F3F3F4
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/* ── Engine brand palette (injected into @theme inline block) ─────────────── */
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
--color-engine-black: #0D1117
|
|
17
|
+
--color-engine-cyan: #7DCBD9 (primary accent)
|
|
18
|
+
--color-engine-green: #1E9D6D (savings, FlexPro, Flex, BestPrice)
|
|
19
|
+
--color-engine-blue: #157DE5 (finance, Credit, Charge)
|
|
20
|
+
--color-engine-orange: #FD4B23 (secondary accent)
|
|
21
|
+
--color-engine-amber: #FFB200 (alerts, warnings)
|
|
22
|
+
--color-engine-bg: #F3F3F4 (light gray background)
|
|
23
|
+
--color-engine-border: #B0B1B3 (mid gray)
|
|
24
|
+
--color-engine-text: #0D1117 (engine black)
|
|
25
|
+
--color-engine-muted: #616368 (dark gray)
|
|
26
|
+
--color-engine-label: #B0B1B3 (mid gray)
|
|
27
|
+
|
|
28
|
+
Brand ramp (built from Cyan #7DCBD9):
|
|
29
|
+
--color-brand-50: #F0FAFB
|
|
30
|
+
--color-brand-100: #D9F2F5
|
|
31
|
+
--color-brand-200: #B3E5EB
|
|
32
|
+
--color-brand-300: #7DCBD9 (Cyan — primary)
|
|
33
|
+
--color-brand-400: #5BB8CA
|
|
34
|
+
--color-brand-500: #3AA0B5
|
|
35
|
+
--color-brand-600: #2D849A
|
|
36
|
+
--color-brand-700: #266B7E
|
|
37
|
+
--color-brand-800: #235768
|
|
38
|
+
--color-brand-900: #1F4858
|
|
39
|
+
--color-brand-950: #112E3A
|
|
40
|
+
*/
|