@schandlergarcia/sf-web-components 1.9.36 → 1.9.38

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schandlergarcia/sf-web-components",
3
- "version": "1.9.36",
3
+ "version": "1.9.38",
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",
@@ -3,7 +3,10 @@
3
3
  /**
4
4
  * Post-install script for @schandlergarcia/sf-web-components
5
5
  *
6
- * Automatically copies sample data to the consuming project's src/data directory
6
+ * Automatically copies to the consuming project:
7
+ * - Sample data (src/data/)
8
+ * - Skills (.a4drules/)
9
+ * - Scripts (scripts/)
7
10
  */
8
11
 
9
12
  import fs from 'fs';
@@ -20,97 +23,126 @@ const PACKAGE_ROOT = path.resolve(__dirname, '..');
20
23
  // Go up from node_modules/@schandlergarcia/sf-web-components
21
24
  const PROJECT_ROOT = path.resolve(PACKAGE_ROOT, '../../..');
22
25
 
23
- console.log('\nšŸ“¦ @schandlergarcia/sf-web-components post-install');
26
+ console.log('\nšŸ“¦ @schandlergarcia/sf-web-components post-install\n');
24
27
 
25
28
  // Check if we're in a node_modules context (not during package development)
26
29
  if (!PACKAGE_ROOT.includes('node_modules')) {
27
- console.log(' ā„¹ļø Running in development mode, skipping data copy');
30
+ console.log(' ā„¹ļø Running in development mode, skipping setup\n');
28
31
  process.exit(0);
29
32
  }
30
33
 
31
- // Find src/data directory in the consuming project
32
- const possiblePaths = [
33
- path.join(PROJECT_ROOT, 'src/data'),
34
- path.join(PROJECT_ROOT, 'force-app/main/default/webapplications/src/data'),
35
- ];
36
-
37
- // Try to find an existing src directory
38
- let targetDir = null;
39
- for (const p of possiblePaths) {
40
- const srcDir = path.dirname(p); // Get src directory
41
- if (fs.existsSync(srcDir)) {
42
- targetDir = p;
43
- break;
34
+ // Find webapp directory
35
+ function findWebappDir() {
36
+ // Try direct src/
37
+ if (fs.existsSync(path.join(PROJECT_ROOT, 'src'))) {
38
+ return PROJECT_ROOT;
44
39
  }
45
- }
46
40
 
47
- // If no src directory found, look for any webapp with src/
48
- const webappPattern = /force-app\/main\/default\/webapplications\/[^/]+$/;
49
- if (!targetDir) {
50
- try {
51
- const webappRoot = path.join(PROJECT_ROOT, 'force-app/main/default/webapplications');
52
- if (fs.existsSync(webappRoot)) {
53
- const webapps = fs.readdirSync(webappRoot, { withFileTypes: true });
54
- for (const webapp of webapps) {
55
- if (webapp.isDirectory()) {
56
- const srcDir = path.join(webappRoot, webapp.name, 'src');
57
- if (fs.existsSync(srcDir)) {
58
- targetDir = path.join(srcDir, 'data');
59
- break;
60
- }
41
+ // Try force-app structure
42
+ const webappRoot = path.join(PROJECT_ROOT, 'force-app/main/default/webapplications');
43
+ if (fs.existsSync(webappRoot)) {
44
+ const webapps = fs.readdirSync(webappRoot, { withFileTypes: true });
45
+ for (const webapp of webapps) {
46
+ if (webapp.isDirectory()) {
47
+ const webappDir = path.join(webappRoot, webapp.name);
48
+ if (fs.existsSync(path.join(webappDir, 'src'))) {
49
+ return webappDir;
61
50
  }
62
51
  }
63
52
  }
64
- } catch (err) {
65
- // Ignore errors
66
53
  }
54
+
55
+ return null;
67
56
  }
68
57
 
69
- if (!targetDir) {
70
- console.log(' āš ļø Could not find src/ directory in project');
71
- console.log(' ā„¹ļø To manually copy sample data, run:');
72
- console.log('');
73
- console.log(' mkdir -p src/data');
74
- console.log(' cp node_modules/@schandlergarcia/sf-web-components/data/engine-sample-data.js src/data/');
75
- console.log('');
58
+ const WEBAPP_DIR = findWebappDir();
59
+
60
+ if (!WEBAPP_DIR) {
61
+ console.log(' āš ļø Could not find webapp directory with src/');
62
+ console.log(' ā„¹ļø Skipping automated setup\n');
76
63
  process.exit(0);
77
64
  }
78
65
 
79
- // Create target directory if it doesn't exist
66
+ let copiedCount = 0;
67
+
68
+ // 1. Copy sample data
80
69
  try {
81
- if (!fs.existsSync(targetDir)) {
82
- fs.mkdirSync(targetDir, { recursive: true });
70
+ const dataDir = path.join(WEBAPP_DIR, 'src/data');
71
+ if (!fs.existsSync(dataDir)) {
72
+ fs.mkdirSync(dataDir, { recursive: true });
73
+ }
74
+
75
+ const sourceFile = path.join(PACKAGE_ROOT, 'data/engine-sample-data.js');
76
+ const targetFile = path.join(dataDir, 'engine-sample-data.js');
77
+
78
+ if (!fs.existsSync(targetFile)) {
79
+ fs.copyFileSync(sourceFile, targetFile);
80
+ console.log(' āœ… Sample data → src/data/engine-sample-data.js');
81
+ copiedCount++;
83
82
  }
84
83
  } catch (err) {
85
- console.error(' āŒ Failed to create data directory:', err.message);
86
- process.exit(0); // Don't fail the install
84
+ console.log(' āš ļø Could not copy sample data:', err.message);
87
85
  }
88
86
 
89
- // Copy sample data file
90
- const sourceFile = path.join(PACKAGE_ROOT, 'data/engine-sample-data.js');
91
- const targetFile = path.join(targetDir, 'engine-sample-data.js');
87
+ // 2. Copy .a4drules (skills)
88
+ try {
89
+ const targetRulesDir = path.join(WEBAPP_DIR, '.a4drules');
90
+ const sourceRulesDir = path.join(PACKAGE_ROOT, '.a4drules');
91
+
92
+ if (!fs.existsSync(targetRulesDir) && fs.existsSync(sourceRulesDir)) {
93
+ // Copy entire .a4drules directory recursively
94
+ function copyRecursive(src, dest) {
95
+ if (fs.statSync(src).isDirectory()) {
96
+ if (!fs.existsSync(dest)) {
97
+ fs.mkdirSync(dest, { recursive: true });
98
+ }
99
+ fs.readdirSync(src).forEach(file => {
100
+ copyRecursive(path.join(src, file), path.join(dest, file));
101
+ });
102
+ } else {
103
+ fs.copyFileSync(src, dest);
104
+ }
105
+ }
106
+
107
+ copyRecursive(sourceRulesDir, targetRulesDir);
108
+ console.log(' āœ… Skills → .a4drules/');
109
+ copiedCount++;
110
+ }
111
+ } catch (err) {
112
+ console.log(' āš ļø Could not copy skills:', err.message);
113
+ }
92
114
 
115
+ // 3. Copy scripts
93
116
  try {
94
- // Only copy if target doesn't exist (don't overwrite user's modifications)
95
- if (!fs.existsSync(targetFile)) {
96
- fs.copyFileSync(sourceFile, targetFile);
97
- console.log(' āœ… Sample data copied to:', path.relative(PROJECT_ROOT, targetFile));
98
- console.log('');
99
- console.log(' Import in your components:');
100
- console.log('');
101
- console.log(" import { MAP_MARKERS, METRICS } from '@/data/engine-sample-data';");
102
- console.log('');
103
- } else {
104
- console.log(' ā„¹ļø Sample data already exists (not overwriting)');
105
- console.log(' šŸ“', path.relative(PROJECT_ROOT, targetFile));
106
- console.log('');
117
+ const scriptsDir = path.join(WEBAPP_DIR, 'scripts');
118
+ if (!fs.existsSync(scriptsDir)) {
119
+ fs.mkdirSync(scriptsDir, { recursive: true });
120
+ }
121
+
122
+ const scriptsToCopy = ['reset-command-center.sh', 'validate-dashboard.sh'];
123
+ for (const script of scriptsToCopy) {
124
+ const sourceFile = path.join(PACKAGE_ROOT, 'scripts', script);
125
+ const targetFile = path.join(scriptsDir, script);
126
+
127
+ if (fs.existsSync(sourceFile) && !fs.existsSync(targetFile)) {
128
+ fs.copyFileSync(sourceFile, targetFile);
129
+ fs.chmodSync(targetFile, 0o755); // Make executable
130
+ console.log(` āœ… Script → scripts/${script}`);
131
+ copiedCount++;
132
+ }
107
133
  }
108
134
  } catch (err) {
109
- console.error(' āš ļø Could not copy sample data:', err.message);
110
- console.log(' ā„¹ļø To manually copy, run:');
111
- console.log('');
112
- console.log(' cp node_modules/@schandlergarcia/sf-web-components/data/engine-sample-data.js src/data/');
113
- console.log('');
135
+ console.log(' āš ļø Could not copy scripts:', err.message);
136
+ }
137
+
138
+ // Summary
139
+ if (copiedCount > 0) {
140
+ console.log(`\n šŸŽ‰ Setup complete! ${copiedCount} items copied\n`);
141
+ console.log(' Next steps:\n');
142
+ console.log(' npm run reset:command-center # Reset to baseline state');
143
+ console.log(' npm run dev # Start dev server\n');
144
+ } else {
145
+ console.log(' ā„¹ļø All files already exist (not overwriting)\n');
114
146
  }
115
147
 
116
148
  process.exit(0);
@@ -140,8 +140,6 @@ SEARCH="src/pages/Search.tsx"
140
140
  echo "→ Updating ${SEARCH}..."
141
141
 
142
142
  cat > "$SEARCH" << 'SEARCH_EOF'
143
- import { GlobalSearchInput } from "../features/global-search/components/search/GlobalSearchInput";
144
-
145
143
  export default function Search() {
146
144
  return (
147
145
  <div className="flex min-h-[80vh] items-center justify-center px-4 sm:px-6 lg:px-8">
@@ -150,7 +148,13 @@ export default function Search() {
150
148
  <h1 className="text-4xl font-bold text-slate-900 dark:text-slate-50 mb-4">Search</h1>
151
149
  <p className="text-lg text-slate-600 dark:text-slate-300">Find records across your organization.</p>
152
150
  </div>
153
- <GlobalSearchInput />
151
+ <div className="relative">
152
+ <input
153
+ type="text"
154
+ placeholder="Search..."
155
+ className="w-full px-4 py-3 text-lg border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-50"
156
+ />
157
+ </div>
154
158
  </div>
155
159
  </div>
156
160
  );
@@ -173,9 +177,6 @@ const AppLayout = lazy(() => import('./appLayout'));
173
177
  const Home = lazy(() => import('./pages/Home'));
174
178
  const Search = lazy(() => import('./pages/Search'));
175
179
  const NotFound = lazy(() => import('./pages/NotFound'));
176
- const TestAccPage = lazy(() => import("./pages/TestAccPage"));
177
- const GlobalSearch = lazy(() => import("./features/global-search/pages/GlobalSearch"));
178
- const DetailPage = lazy(() => import("./features/global-search/pages/DetailPage"));
179
180
 
180
181
  function SuspenseWrap({ children }: { children: React.ReactNode }) {
181
182
  return <Suspense fallback={<div className="flex min-h-screen items-center justify-center text-sm text-muted-foreground">Loading...</div>}>{children}</Suspense>;
@@ -200,29 +201,6 @@ export const routes: RouteObject[] = [
200
201
  element: <SuspenseWrap><Search /></SuspenseWrap>,
201
202
  handle: { showInNavigation: true, showNavBar: true, label: 'Search' }
202
203
  },
203
- {
204
- path: "test-acc",
205
- element: <SuspenseWrap><TestAccPage /></SuspenseWrap>,
206
- handle: { showInNavigation: true, label: "Test ACC" }
207
- },
208
- {
209
- path: "global-search/:query",
210
- element: (
211
- <SuspenseWrap>
212
- <GlobalSearch />
213
- </SuspenseWrap>
214
- ),
215
- handle: { showInNavigation: false }
216
- },
217
- {
218
- path: "object/:objectApiName/:recordId",
219
- element: (
220
- <SuspenseWrap>
221
- <DetailPage />
222
- </SuspenseWrap>
223
- ),
224
- handle: { showInNavigation: false }
225
- },
226
204
  {
227
205
  path: '*',
228
206
  element: <SuspenseWrap><NotFound /></SuspenseWrap>
@@ -329,7 +307,8 @@ export default function AppLayout() {
329
307
  </nav>
330
308
  )}
331
309
  <Outlet />
332
- <AgentforceConversationClient />
310
+ {/* Uncomment and configure when you have an Agentforce agent:
311
+ <AgentforceConversationClient agentId="your-agent-id" /> */}
333
312
  </>
334
313
  );
335
314
  }