@schandlergarcia/sf-web-components 1.9.9 β 1.9.11
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/README.md
CHANGED
|
@@ -1,103 +1,424 @@
|
|
|
1
1
|
# @schandlergarcia/sf-web-components
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Comprehensive React component library for Salesforce web applications with 100+ TypeScript components, built on Tailwind CSS v4 and shadcn/ui.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- β
**102+ TypeScript Components** - Cards, charts, forms, filters, chat UI, and more
|
|
8
|
+
- β
**Zero-Config Installation** - Postinstall script handles everything automatically
|
|
9
|
+
- β
**Complete Dashboard Framework** - Pre-built layouts, metric cards, and data visualization
|
|
10
|
+
- β
**Account Search & Detail** - Full example pages with filtering, sorting, and pagination
|
|
11
|
+
- β
**Tailwind CSS v4** - Modern styling with dark mode support
|
|
12
|
+
- β
**Type-Safe** - Full TypeScript support with exported interfaces
|
|
13
|
+
|
|
14
|
+
---
|
|
6
15
|
|
|
7
16
|
## Installation
|
|
8
17
|
|
|
18
|
+
### Prerequisites
|
|
19
|
+
|
|
20
|
+
- Salesforce web application generated with `sf webapp generate --template react-ts`
|
|
21
|
+
- Node.js 18+ and npm
|
|
22
|
+
- Tailwind CSS v4 configured in your project
|
|
23
|
+
|
|
24
|
+
### Steps
|
|
25
|
+
|
|
9
26
|
```bash
|
|
10
|
-
|
|
27
|
+
# 1. Navigate to your web application directory
|
|
28
|
+
cd force-app/main/default/webapplications/YOUR_APP_NAME
|
|
29
|
+
|
|
30
|
+
# 2. Install the component library
|
|
31
|
+
npm install @schandlergarcia/sf-web-components@latest
|
|
32
|
+
|
|
33
|
+
# 3. Run postinstall script (npm sometimes skips automatic postinstall)
|
|
34
|
+
node node_modules/@schandlergarcia/sf-web-components/scripts/postinstall.mjs
|
|
35
|
+
|
|
36
|
+
# 4. Install required type definitions for D3 charts
|
|
37
|
+
npm install --save-dev @types/d3 @types/topojson-client
|
|
38
|
+
|
|
39
|
+
# 5. Build to verify installation
|
|
40
|
+
npm run build
|
|
41
|
+
|
|
42
|
+
# 6. Start development server
|
|
43
|
+
npm run dev
|
|
11
44
|
```
|
|
12
45
|
|
|
13
|
-
|
|
46
|
+
### What Gets Installed
|
|
47
|
+
|
|
48
|
+
The postinstall script automatically:
|
|
49
|
+
|
|
50
|
+
β
**Copies 102 component files** to `src/components/library/`
|
|
51
|
+
- UI components (buttons, inputs, cards, alerts)
|
|
52
|
+
- HeroUI wrappers (modals, dropdowns, tabs)
|
|
53
|
+
- Charts (D3 visualizations, bar/line charts, geo maps)
|
|
54
|
+
- Cards (metric cards, chart cards, table cards, status cards)
|
|
55
|
+
- Forms (form renderer, form fields, validation)
|
|
56
|
+
- Filters (search, date range, multi-select, numeric range)
|
|
57
|
+
- Chat components (message UI, typing indicators, suggestions)
|
|
14
58
|
|
|
15
|
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
59
|
+
β
**Installs complete routes configuration** at `src/routes.tsx`
|
|
60
|
+
- Home page with account search
|
|
61
|
+
- `/accounts` - Account search with filters and sorting
|
|
62
|
+
- `/accounts/:recordId` - Account detail page
|
|
63
|
+
- NotFound page
|
|
19
64
|
|
|
20
|
-
|
|
65
|
+
β
**Installs 4 page templates** to `src/pages/`
|
|
66
|
+
- `Home.tsx` - Search interface with UIButton and UIInput
|
|
67
|
+
- `NotFound.tsx` - 404 error page
|
|
68
|
+
- `Search.tsx` - Generic search page
|
|
69
|
+
- `BlankDashboard.tsx` - Empty dashboard template
|
|
21
70
|
|
|
22
|
-
|
|
71
|
+
β
**Copies type definitions** to `src/types/`
|
|
72
|
+
- `conversation.ts` - Types for AgentforceConversationClient
|
|
73
|
+
|
|
74
|
+
β
**Copies utility files** to `src/lib/`
|
|
75
|
+
- `utils.ts` - Helper functions (cn, etc.)
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Using the Dashboard Framework
|
|
80
|
+
|
|
81
|
+
### Quick Start - Building a Dashboard
|
|
23
82
|
|
|
24
83
|
```tsx
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
84
|
+
import { MetricCard, ChartCard, TableCard } from '@/components/library';
|
|
85
|
+
import { PageContainer } from '@/components/library/layout/PageContainer';
|
|
27
86
|
|
|
28
|
-
function
|
|
87
|
+
export default function Dashboard() {
|
|
29
88
|
return (
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
89
|
+
<PageContainer>
|
|
90
|
+
{/* Metrics Row */}
|
|
91
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
|
|
92
|
+
<MetricCard
|
|
93
|
+
title="Total Revenue"
|
|
94
|
+
value="$1.2M"
|
|
95
|
+
change="+12.5%"
|
|
96
|
+
changeType="positive"
|
|
97
|
+
/>
|
|
98
|
+
<MetricCard
|
|
99
|
+
title="Active Users"
|
|
100
|
+
value={1284}
|
|
101
|
+
change="+8.2%"
|
|
102
|
+
changeType="positive"
|
|
103
|
+
/>
|
|
104
|
+
<MetricCard
|
|
105
|
+
title="Conversion Rate"
|
|
106
|
+
value="3.2%"
|
|
107
|
+
change="-0.5%"
|
|
108
|
+
changeType="negative"
|
|
109
|
+
/>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
{/* Charts Row */}
|
|
113
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
114
|
+
<ChartCard
|
|
115
|
+
title="Revenue Trend"
|
|
116
|
+
description="Last 6 months"
|
|
117
|
+
chartType="line"
|
|
118
|
+
data={revenueData}
|
|
119
|
+
/>
|
|
120
|
+
<TableCard
|
|
121
|
+
title="Top Accounts"
|
|
122
|
+
columns={columns}
|
|
123
|
+
data={accountsData}
|
|
124
|
+
/>
|
|
125
|
+
</div>
|
|
126
|
+
</PageContainer>
|
|
33
127
|
);
|
|
34
128
|
}
|
|
35
129
|
```
|
|
36
130
|
|
|
37
|
-
###
|
|
131
|
+
### Available Components
|
|
38
132
|
|
|
39
|
-
|
|
133
|
+
#### UI Components (`@/components/library/ui/`)
|
|
134
|
+
```tsx
|
|
135
|
+
import { UIButton, UIInput, Card, Alert, EmptyState, Checkbox, Label } from '@/components/library';
|
|
40
136
|
|
|
41
|
-
|
|
42
|
-
|
|
137
|
+
<UIButton variant="primary">Click Me</UIButton>
|
|
138
|
+
<UIInput placeholder="Search..." />
|
|
139
|
+
<Alert variant="success">Success message</Alert>
|
|
43
140
|
```
|
|
44
141
|
|
|
45
|
-
|
|
142
|
+
#### Cards (`@/components/library/cards/`)
|
|
143
|
+
```tsx
|
|
144
|
+
import { MetricCard, ChartCard, TableCard, StatusCard, ListCard } from '@/components/library';
|
|
145
|
+
|
|
146
|
+
<MetricCard title="Revenue" value="$1.2M" change="+12%" changeType="positive" />
|
|
147
|
+
<ChartCard title="Sales" chartType="bar" data={data} />
|
|
148
|
+
<TableCard title="Accounts" columns={cols} data={rows} />
|
|
149
|
+
```
|
|
46
150
|
|
|
47
|
-
|
|
151
|
+
#### Charts (`@/components/library/charts/`)
|
|
152
|
+
```tsx
|
|
153
|
+
import { D3Chart, D3ChartTemplates } from '@/components/library';
|
|
154
|
+
|
|
155
|
+
<D3Chart
|
|
156
|
+
data={data}
|
|
157
|
+
width={600}
|
|
158
|
+
height={400}
|
|
159
|
+
chartType="bar"
|
|
160
|
+
xKey="month"
|
|
161
|
+
yKey="revenue"
|
|
162
|
+
/>
|
|
163
|
+
```
|
|
48
164
|
|
|
49
|
-
|
|
50
|
-
|
|
165
|
+
#### Filters (`@/components/library/filters/`)
|
|
166
|
+
```tsx
|
|
167
|
+
import { SearchFilter, SelectFilter, DateRangeFilter, FilterBar } from '@/components/library';
|
|
51
168
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
theme: {
|
|
58
|
-
extend: {}
|
|
59
|
-
}
|
|
60
|
-
} satisfies Config;
|
|
169
|
+
<FilterBar>
|
|
170
|
+
<SearchFilter field="name" placeholder="Search accounts..." />
|
|
171
|
+
<SelectFilter field="industry" options={industries} />
|
|
172
|
+
<DateRangeFilter field="createdDate" />
|
|
173
|
+
</FilterBar>
|
|
61
174
|
```
|
|
62
175
|
|
|
63
|
-
|
|
176
|
+
#### Forms (`@/components/library/forms/`)
|
|
177
|
+
```tsx
|
|
178
|
+
import { FormRenderer, FormField, FormModal } from '@/components/library';
|
|
179
|
+
|
|
180
|
+
<FormRenderer
|
|
181
|
+
fields={fields}
|
|
182
|
+
values={values}
|
|
183
|
+
onChange={handleChange}
|
|
184
|
+
onSubmit={handleSubmit}
|
|
185
|
+
/>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Common Patterns
|
|
64
189
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
190
|
+
#### Dashboard with Filters
|
|
191
|
+
```tsx
|
|
192
|
+
import { PageContainer } from '@/components/library/layout/PageContainer';
|
|
193
|
+
import { MetricCard } from '@/components/library/cards/MetricCard';
|
|
194
|
+
import { FilterBar, SearchFilter, SelectFilter } from '@/components/library/filters';
|
|
195
|
+
|
|
196
|
+
export default function FilteredDashboard() {
|
|
197
|
+
const [filters, setFilters] = useState({});
|
|
72
198
|
|
|
73
|
-
|
|
199
|
+
return (
|
|
200
|
+
<PageContainer>
|
|
201
|
+
<FilterBar>
|
|
202
|
+
<SearchFilter field="search" onChange={setFilters} />
|
|
203
|
+
<SelectFilter field="status" options={statusOptions} onChange={setFilters} />
|
|
204
|
+
</FilterBar>
|
|
205
|
+
|
|
206
|
+
<div className="grid grid-cols-3 gap-6">
|
|
207
|
+
<MetricCard title="Total" value={data.total} />
|
|
208
|
+
<MetricCard title="Active" value={data.active} />
|
|
209
|
+
<MetricCard title="Pending" value={data.pending} />
|
|
210
|
+
</div>
|
|
211
|
+
</PageContainer>
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
```
|
|
74
215
|
|
|
216
|
+
#### Data Table with Actions
|
|
75
217
|
```tsx
|
|
76
|
-
import {
|
|
218
|
+
import { TableCard } from '@/components/library/cards/TableCard';
|
|
219
|
+
import { UIButton } from '@/components/library/ui/UIButton';
|
|
220
|
+
|
|
221
|
+
const columns = [
|
|
222
|
+
{ key: 'name', label: 'Name' },
|
|
223
|
+
{ key: 'status', label: 'Status' },
|
|
224
|
+
{
|
|
225
|
+
key: 'actions',
|
|
226
|
+
label: 'Actions',
|
|
227
|
+
render: (row) => <UIButton onClick={() => handleEdit(row)}>Edit</UIButton>
|
|
228
|
+
}
|
|
229
|
+
];
|
|
230
|
+
|
|
231
|
+
<TableCard title="Accounts" columns={columns} data={accounts} />
|
|
232
|
+
```
|
|
77
233
|
|
|
78
|
-
|
|
79
|
-
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Resetting Your App
|
|
237
|
+
|
|
238
|
+
If you need to remove the component library and start fresh:
|
|
239
|
+
|
|
240
|
+
### Option 1: Remove Components Only
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
# Run the removal script
|
|
244
|
+
node node_modules/@schandlergarcia/sf-web-components/scripts/remove-local-components.mjs
|
|
245
|
+
|
|
246
|
+
# This removes:
|
|
247
|
+
# - src/components/library/
|
|
248
|
+
# - src/pages/Home.tsx, Search.tsx, BlankDashboard.tsx (keeps NotFound.tsx)
|
|
249
|
+
# - src/types/conversation.ts
|
|
250
|
+
# - Reverts routes.tsx to minimal default
|
|
80
251
|
```
|
|
81
252
|
|
|
82
|
-
|
|
253
|
+
### Option 2: Full Reset
|
|
83
254
|
|
|
84
255
|
```bash
|
|
85
|
-
#
|
|
256
|
+
# 1. Uninstall the package
|
|
257
|
+
npm uninstall @schandlergarcia/sf-web-components
|
|
258
|
+
|
|
259
|
+
# 2. Manually delete installed files
|
|
260
|
+
rm -rf src/components/library
|
|
261
|
+
rm -rf src/types/conversation.ts
|
|
262
|
+
rm src/pages/Home.tsx src/pages/Search.tsx src/pages/BlankDashboard.tsx
|
|
263
|
+
|
|
264
|
+
# 3. Restore default routes.tsx
|
|
265
|
+
cat > src/routes.tsx << 'EOF'
|
|
266
|
+
import type { RouteObject } from 'react-router';
|
|
267
|
+
import AppLayout from './appLayout';
|
|
268
|
+
import NotFound from './pages/NotFound';
|
|
269
|
+
|
|
270
|
+
export const routes: RouteObject[] = [
|
|
271
|
+
{
|
|
272
|
+
path: "/",
|
|
273
|
+
element: <AppLayout />,
|
|
274
|
+
children: [
|
|
275
|
+
{
|
|
276
|
+
path: '*',
|
|
277
|
+
element: <NotFound />
|
|
278
|
+
}
|
|
279
|
+
]
|
|
280
|
+
}
|
|
281
|
+
];
|
|
282
|
+
EOF
|
|
283
|
+
|
|
284
|
+
# 4. Clean install
|
|
86
285
|
npm install
|
|
286
|
+
npm run build
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Reset Command Center (All Apps)
|
|
290
|
+
|
|
291
|
+
This script resets any app back to the blank dashboard baseline state:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
# This script resets the command center to the blank dashboard template
|
|
295
|
+
npm run reset:command-center
|
|
296
|
+
|
|
297
|
+
# Or run directly:
|
|
298
|
+
bash node_modules/@schandlergarcia/sf-web-components/scripts/reset-command-center.sh
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
**What it does:**
|
|
302
|
+
- Removes custom dashboard pages
|
|
303
|
+
- Restalls BlankDashboard.tsx with EmptyState
|
|
304
|
+
- Resets CommandCenter.tsx (preserves theme mode)
|
|
305
|
+
- Updates Home.tsx to search interface
|
|
306
|
+
- Resets routes to baseline configuration
|
|
307
|
+
- Preserves: component library, authentication, all dependencies
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## Troubleshooting
|
|
312
|
+
|
|
313
|
+
### Postinstall didn't run automatically
|
|
314
|
+
|
|
315
|
+
**Problem:** After `npm install`, component library isn't copied and routes aren't updated.
|
|
316
|
+
|
|
317
|
+
**Solution:** Run postinstall manually:
|
|
318
|
+
```bash
|
|
319
|
+
node node_modules/@schandlergarcia/sf-web-components/scripts/postinstall.mjs
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Build errors about missing D3 types
|
|
323
|
+
|
|
324
|
+
**Problem:** TypeScript errors about `module 'd3'` or `module 'topojson-client'`.
|
|
87
325
|
|
|
88
|
-
|
|
326
|
+
**Solution:** Install type definitions:
|
|
327
|
+
```bash
|
|
328
|
+
npm install --save-dev @types/d3 @types/topojson-client
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Buttons appear blank/invisible
|
|
332
|
+
|
|
333
|
+
**Problem:** UIButton text is invisible (white text on transparent background).
|
|
334
|
+
|
|
335
|
+
**Solution:** This was fixed in v1.9.7+. Update to the latest version:
|
|
336
|
+
```bash
|
|
337
|
+
npm install @schandlergarcia/sf-web-components@latest
|
|
338
|
+
node node_modules/@schandlergarcia/sf-web-components/scripts/postinstall.mjs
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### "Old UI" still showing after install
|
|
342
|
+
|
|
343
|
+
**Problem:** Home page shows the scaffolded UI instead of component library UI.
|
|
344
|
+
|
|
345
|
+
**Solution:** Fixed in v1.9.9+. Update and re-run postinstall:
|
|
346
|
+
```bash
|
|
347
|
+
npm install @schandlergarcia/sf-web-components@latest
|
|
348
|
+
node node_modules/@schandlergarcia/sf-web-components/scripts/postinstall.mjs
|
|
89
349
|
npm run build
|
|
350
|
+
```
|
|
90
351
|
|
|
91
|
-
|
|
92
|
-
|
|
352
|
+
### Account detail pages show 404
|
|
353
|
+
|
|
354
|
+
**Problem:** Clicking on an account in search results shows 404.
|
|
355
|
+
|
|
356
|
+
**Solution:** Routes template includes account detail route. Re-run postinstall:
|
|
357
|
+
```bash
|
|
358
|
+
node node_modules/@schandlergarcia/sf-web-components/scripts/postinstall.mjs
|
|
93
359
|
```
|
|
94
360
|
|
|
95
|
-
|
|
361
|
+
### ESLint errors about `.sfdx` directory
|
|
362
|
+
|
|
363
|
+
**Problem:** ESLint errors about files in `src/components/library/.sfdx/`.
|
|
364
|
+
|
|
365
|
+
**Solution:** Fixed in v1.9.6+. The postinstall script now skips hidden directories.
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## Package Scripts
|
|
370
|
+
|
|
371
|
+
Available npm scripts in the consuming application:
|
|
96
372
|
|
|
97
373
|
```bash
|
|
98
|
-
|
|
374
|
+
# Development
|
|
375
|
+
npm run dev # Start Vite dev server
|
|
376
|
+
npm run build # TypeScript check + Vite build
|
|
377
|
+
npm run lint # Run ESLint
|
|
378
|
+
|
|
379
|
+
# GraphQL (if using)
|
|
380
|
+
npm run graphql:schema # Fetch GraphQL schema from Salesforce org
|
|
381
|
+
npm run graphql:codegen # Generate TypeScript types from schema
|
|
382
|
+
|
|
383
|
+
# Testing
|
|
384
|
+
npm run test # Run Vitest tests
|
|
99
385
|
```
|
|
100
386
|
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
## Component Documentation
|
|
390
|
+
|
|
391
|
+
For detailed component API documentation, see:
|
|
392
|
+
- [Component Library Reference](https://github.com/schandlergarcia/sf-web-components/blob/main/COMPONENTS.md)
|
|
393
|
+
- [TypeScript Migration Guide](https://github.com/schandlergarcia/sf-web-components/blob/main/docs/TYPESCRIPT_MIGRATION.md)
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## Version History
|
|
398
|
+
|
|
399
|
+
### Latest: v1.9.9 (2026-03-29)
|
|
400
|
+
- Fixed routes template importing wrong Home page
|
|
401
|
+
- Now uses installed Home.tsx with component library UI
|
|
402
|
+
|
|
403
|
+
### v1.9.8 (2026-03-29)
|
|
404
|
+
- Added complete routes.tsx template with account search & detail
|
|
405
|
+
- Zero-config installation
|
|
406
|
+
|
|
407
|
+
### v1.9.7 (2026-03-29)
|
|
408
|
+
- Fixed UIButton using non-existent brand colors
|
|
409
|
+
- Changed to standard blue colors
|
|
410
|
+
|
|
411
|
+
### v1.9.6 (2026-03-29)
|
|
412
|
+
- Fixed AgentforceConversationClient type definitions
|
|
413
|
+
- Postinstall now skips hidden directories
|
|
414
|
+
|
|
415
|
+
### v1.9.5 (2026-03-29)
|
|
416
|
+
- Updated glob dependency to v13.0.6
|
|
417
|
+
- Fixed security vulnerabilities
|
|
418
|
+
|
|
419
|
+
See [CHANGELOG.md](./CHANGELOG.md) for full version history.
|
|
420
|
+
|
|
421
|
+
---
|
|
101
422
|
|
|
102
423
|
## π€ AI Agent Skills
|
|
103
424
|
|
|
@@ -120,7 +441,15 @@ When you install this package, Claude Code automatically discovers the skills an
|
|
|
120
441
|
|
|
121
442
|
Check `.a4drules/skills/` for the full list of included agent skills.
|
|
122
443
|
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Support
|
|
447
|
+
|
|
448
|
+
- **Issues:** [GitHub Issues](https://github.com/schandlergarcia/sf-web-components/issues)
|
|
449
|
+
- **Package:** [npm](https://www.npmjs.com/package/@schandlergarcia/sf-web-components)
|
|
450
|
+
|
|
451
|
+
---
|
|
123
452
|
|
|
124
453
|
## License
|
|
125
454
|
|
|
126
|
-
MIT
|
|
455
|
+
MIT License - See LICENSE.txt for details
|
package/package.json
CHANGED
package/scripts/postinstall.mjs
CHANGED
|
@@ -105,6 +105,35 @@ if (fs.existsSync(sourceWorkspaceDir)) {
|
|
|
105
105
|
console.log(` β Copied ${workspaceFilesCopied} workspace files\n`);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
// Copy workspace templates (CommandCenter, etc.)
|
|
109
|
+
const workspaceTemplatesDir = path.join(packageRoot, 'src/templates/workspace');
|
|
110
|
+
if (fs.existsSync(workspaceTemplatesDir)) {
|
|
111
|
+
if (!fs.existsSync(targetWorkspaceDir)) {
|
|
112
|
+
fs.mkdirSync(targetWorkspaceDir, { recursive: true });
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const workspaceTemplates = fs.readdirSync(workspaceTemplatesDir).filter(f => f.endsWith('.template'));
|
|
116
|
+
let workspaceTemplatesCopied = 0;
|
|
117
|
+
|
|
118
|
+
for (const template of workspaceTemplates) {
|
|
119
|
+
const sourcePath = path.join(workspaceTemplatesDir, template);
|
|
120
|
+
const targetFileName = template.replace('.template', '');
|
|
121
|
+
const targetPath = path.join(targetWorkspaceDir, targetFileName);
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const content = fs.readFileSync(sourcePath, 'utf-8');
|
|
125
|
+
fs.writeFileSync(targetPath, content, 'utf-8');
|
|
126
|
+
workspaceTemplatesCopied++;
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.error(` β Failed to copy ${targetFileName}: ${error.message}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (workspaceTemplatesCopied > 0) {
|
|
133
|
+
console.log(` β Copied ${workspaceTemplatesCopied} workspace template files\n`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
108
137
|
// Copy pages directory (sample pages, etc.)
|
|
109
138
|
const sourcePagesDir = path.join(packageRoot, 'src/components/pages');
|
|
110
139
|
const targetComponentPagesDir = path.join(cwd, 'src/components/pages');
|
|
@@ -218,4 +247,5 @@ console.log('\nπ Summary:');
|
|
|
218
247
|
console.log(` - Copied ${componentsCopied} UI components`);
|
|
219
248
|
console.log(` - Updated ${filesUpdated} files`);
|
|
220
249
|
console.log(` - Installed ${templatesInstalled} page templates`);
|
|
250
|
+
console.log(` - Installed CommandCenter.tsx for dashboard management`);
|
|
221
251
|
console.log('\nβ
Setup complete! UI components are now local for optimal Tailwind scanning\n');
|
|
@@ -37,8 +37,9 @@ echo ""
|
|
|
37
37
|
echo "β Removing custom dashboardsβ¦"
|
|
38
38
|
|
|
39
39
|
removed=0
|
|
40
|
-
for f in src/
|
|
41
|
-
|
|
40
|
+
for f in src/pages/*Dashboard*.tsx src/pages/*Dashboard*.jsx; do
|
|
41
|
+
# Don't remove BlankDashboard
|
|
42
|
+
if [ -f "$f" ] && [[ "$(basename "$f")" != "BlankDashboard"* ]]; then
|
|
42
43
|
rm "$f"
|
|
43
44
|
echo " β Removed $(basename "$f")"
|
|
44
45
|
removed=$((removed + 1))
|
|
@@ -52,11 +53,10 @@ echo ""
|
|
|
52
53
|
|
|
53
54
|
# ββ 2. Write the blank starter dashboard ββββββββββββββββββββββββββββββββββββ
|
|
54
55
|
|
|
55
|
-
BLANK="src/
|
|
56
|
+
BLANK="src/pages/BlankDashboard.tsx"
|
|
56
57
|
echo "β Creating ${BLANK}..."
|
|
57
58
|
|
|
58
59
|
cat > "$BLANK" << 'DASHBOARD_EOF'
|
|
59
|
-
import React from "react";
|
|
60
60
|
import { RocketLaunchIcon } from "@heroicons/react/24/outline";
|
|
61
61
|
import { EmptyState } from "@/components/library";
|
|
62
62
|
|
|
@@ -80,9 +80,12 @@ echo ""
|
|
|
80
80
|
# ββ 3. Update CommandCenter.tsx to use BlankDashboard ββββββββββββββββββββββββ
|
|
81
81
|
# Preserves theme initialMode if previously customized.
|
|
82
82
|
|
|
83
|
-
WRAPPER="src/components/
|
|
83
|
+
WRAPPER="src/components/workspace/CommandCenter.tsx"
|
|
84
84
|
echo "β Updating ${WRAPPER}..."
|
|
85
85
|
|
|
86
|
+
# Create workspace directory if it doesn't exist
|
|
87
|
+
mkdir -p "src/components/workspace"
|
|
88
|
+
|
|
86
89
|
# Extract existing initialMode from AppThemeProvider (default: "light")
|
|
87
90
|
THEME_MODE="light"
|
|
88
91
|
if [ -f "$WRAPPER" ]; then
|
|
@@ -96,19 +99,17 @@ fi
|
|
|
96
99
|
cat > "$WRAPPER" << WRAPPER_EOF
|
|
97
100
|
import AppThemeProvider from "@/components/library/theme/AppThemeProvider";
|
|
98
101
|
import DataModeProvider from "@/components/library/data/DataModeProvider";
|
|
99
|
-
import {
|
|
100
|
-
import BlankDashboard from "
|
|
102
|
+
import { Toaster } from "sonner";
|
|
103
|
+
import BlankDashboard from "../../pages/BlankDashboard";
|
|
101
104
|
|
|
102
105
|
export default function CommandCenter() {
|
|
103
106
|
return (
|
|
104
|
-
<
|
|
105
|
-
<
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
</AppThemeProvider>
|
|
111
|
-
</div>
|
|
107
|
+
<AppThemeProvider initialMode="${THEME_MODE}">
|
|
108
|
+
<DataModeProvider initialMode="sample">
|
|
109
|
+
<BlankDashboard />
|
|
110
|
+
<Toaster position="bottom-right" />
|
|
111
|
+
</DataModeProvider>
|
|
112
|
+
</AppThemeProvider>
|
|
112
113
|
);
|
|
113
114
|
}
|
|
114
115
|
WRAPPER_EOF
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import AppThemeProvider from "@/components/library/theme/AppThemeProvider";
|
|
2
|
+
import DataModeProvider from "@/components/library/data/DataModeProvider";
|
|
3
|
+
import { Toaster } from "sonner";
|
|
4
|
+
import BlankDashboard from "../pages/BlankDashboard";
|
|
5
|
+
|
|
6
|
+
export default function CommandCenter() {
|
|
7
|
+
return (
|
|
8
|
+
<AppThemeProvider initialMode="light">
|
|
9
|
+
<DataModeProvider initialMode="sample">
|
|
10
|
+
<BlankDashboard />
|
|
11
|
+
<Toaster position="bottom-right" />
|
|
12
|
+
</DataModeProvider>
|
|
13
|
+
</AppThemeProvider>
|
|
14
|
+
);
|
|
15
|
+
}
|