@schandlergarcia/sf-web-components 1.2.16 → 1.2.18

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.2.16",
3
+ "version": "1.2.18",
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",
@@ -122,14 +122,67 @@ HOME="src/pages/Home.tsx"
122
122
  echo "→ Updating ${HOME}..."
123
123
 
124
124
  cat > "$HOME" << 'HOME_EOF'
125
- import CommandCenter from "../components/pages/CommandCenter";
125
+ import { useState } from "react";
126
+ import { useNavigate } from "react-router";
127
+ import UIInput from '@/components/library/ui/UIInput';
128
+ import UIButton from '@/components/library/ui/UIButton';
129
+ import { Search } from "lucide-react";
130
+
131
+ export default function HomePage() {
132
+ const [searchQuery, setSearchQuery] = useState("");
133
+ const navigate = useNavigate();
134
+
135
+ const handleSearch = () => {
136
+ const trimmed = searchQuery.trim();
137
+ if (trimmed) {
138
+ navigate(`/accounts?search=${encodeURIComponent(trimmed)}`);
139
+ } else {
140
+ navigate('/accounts');
141
+ }
142
+ };
143
+
144
+ const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
145
+ if (e.key === "Enter") {
146
+ e.preventDefault();
147
+ handleSearch();
148
+ }
149
+ };
126
150
 
127
- export default function Home() {
128
- return <CommandCenter />;
151
+ return (
152
+ <div className="flex min-h-[80vh] items-center justify-center px-4 sm:px-6 lg:px-8 bg-slate-50 dark:bg-slate-950 transition-colors">
153
+ <div className="w-full max-w-4xl">
154
+ <div className="text-center mb-8">
155
+ <h1 className="text-4xl font-bold text-slate-900 dark:text-slate-50 mb-4">Search</h1>
156
+ <p className="text-lg text-slate-600 dark:text-slate-300">Find records across your organization.</p>
157
+ </div>
158
+ <div className="flex flex-col gap-4">
159
+ <div className="relative">
160
+ <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-5 w-5 text-slate-400" />
161
+ <UIInput
162
+ type="text"
163
+ value={searchQuery}
164
+ onChange={(e) => setSearchQuery(e.target.value)}
165
+ onKeyDown={handleKeyDown}
166
+ placeholder="Search..."
167
+ className="pl-10 w-full"
168
+ />
169
+ </div>
170
+ <div className="flex gap-3 justify-center">
171
+ <UIButton onClick={handleSearch} variant="primary">
172
+ Search
173
+ </UIButton>
174
+ <UIButton onClick={() => navigate('/accounts')} variant="secondary">
175
+ Browse All
176
+ </UIButton>
177
+ </div>
178
+ </div>
179
+ </div>
180
+ </div>
181
+ );
129
182
  }
130
183
  HOME_EOF
131
184
 
132
- echo " ✓ Home renders CommandCenter"
185
+ echo " ✓ Home renders search interface"
133
186
  echo ""
134
187
 
135
188
  # ── 5. Ensure Search.tsx page exists ─────────────────────────────────────────
@@ -138,17 +191,60 @@ SEARCH="src/pages/Search.tsx"
138
191
  echo "→ Updating ${SEARCH}..."
139
192
 
140
193
  cat > "$SEARCH" << 'SEARCH_EOF'
141
- import { GlobalSearchInput } from "../features/global-search/components/search/GlobalSearchInput";
194
+ import { useState } from "react";
195
+ import { useNavigate } from "react-router";
196
+ import UIInput from '@/components/library/ui/UIInput';
197
+ import UIButton from '@/components/library/ui/UIButton';
198
+ import { Search as SearchIcon } from "lucide-react";
142
199
 
143
200
  export default function Search() {
201
+ const [searchQuery, setSearchQuery] = useState("");
202
+ const navigate = useNavigate();
203
+
204
+ const handleSearch = () => {
205
+ const trimmed = searchQuery.trim();
206
+ if (trimmed) {
207
+ navigate(`/accounts?search=${encodeURIComponent(trimmed)}`);
208
+ } else {
209
+ navigate('/accounts');
210
+ }
211
+ };
212
+
213
+ const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
214
+ if (e.key === "Enter") {
215
+ e.preventDefault();
216
+ handleSearch();
217
+ }
218
+ };
219
+
144
220
  return (
145
- <div className="flex min-h-[80vh] items-center justify-center px-4 sm:px-6 lg:px-8">
221
+ <div className="flex min-h-[80vh] items-center justify-center px-4 sm:px-6 lg:px-8 bg-slate-50 dark:bg-slate-950 transition-colors">
146
222
  <div className="w-full max-w-4xl">
147
223
  <div className="text-center mb-8">
148
224
  <h1 className="text-4xl font-bold text-slate-900 dark:text-slate-50 mb-4">Search</h1>
149
225
  <p className="text-lg text-slate-600 dark:text-slate-300">Find records across your organization.</p>
150
226
  </div>
151
- <GlobalSearchInput />
227
+ <div className="flex flex-col gap-4">
228
+ <div className="relative">
229
+ <SearchIcon className="absolute left-3 top-1/2 -translate-y-1/2 h-5 w-5 text-slate-400" />
230
+ <UIInput
231
+ type="text"
232
+ value={searchQuery}
233
+ onChange={(e) => setSearchQuery(e.target.value)}
234
+ onKeyDown={handleKeyDown}
235
+ placeholder="Search..."
236
+ className="pl-10 w-full"
237
+ />
238
+ </div>
239
+ <div className="flex gap-3 justify-center">
240
+ <UIButton onClick={handleSearch} variant="primary">
241
+ Search
242
+ </UIButton>
243
+ <UIButton onClick={() => navigate('/accounts')} variant="secondary">
244
+ Browse All
245
+ </UIButton>
246
+ </div>
247
+ </div>
152
248
  </div>
153
249
  </div>
154
250
  );
@@ -165,178 +261,43 @@ echo "→ Updating ${ROUTES}..."
165
261
 
166
262
  cat > "$ROUTES" << 'ROUTES_EOF'
167
263
  import type { RouteObject } from 'react-router';
168
- import { lazy, Suspense } from "react";
169
-
170
- const AppLayout = lazy(() => import('./appLayout'));
171
- const Home = lazy(() => import('./pages/Home'));
172
- const Search = lazy(() => import('./pages/Search'));
173
- const NotFound = lazy(() => import('./pages/NotFound'));
174
- const TestAccPage = lazy(() => import("./pages/TestAccPage"));
175
- const GlobalSearch = lazy(() => import("./features/global-search/pages/GlobalSearch"));
176
- const DetailPage = lazy(() => import("./features/global-search/pages/DetailPage"));
177
-
178
- function SuspenseWrap({ children }: { children: React.ReactNode }) {
179
- return <Suspense fallback={<div className="flex min-h-screen items-center justify-center text-sm text-muted-foreground">Loading...</div>}>{children}</Suspense>;
180
- }
264
+ import Home from './pages/Home';
265
+ import NotFound from './pages/NotFound';
266
+ import AuthAppLayout from "./features/authentication/layouts/AuthAppLayout";
267
+ import AccountSearch from "./features/object-search/__examples__/pages/AccountSearch";
268
+ import AccountObjectDetail from "./features/object-search/__examples__/pages/AccountObjectDetailPage";
181
269
 
182
270
  export const routes: RouteObject[] = [
183
271
  {
184
272
  path: "/",
185
- element: (
186
- <SuspenseWrap>
187
- <AppLayout />
188
- </SuspenseWrap>
189
- ),
273
+ element: <AuthAppLayout />,
190
274
  children: [
191
275
  {
192
276
  index: true,
193
- element: <SuspenseWrap><Home /></SuspenseWrap>,
194
- handle: { showInNavigation: true, showNavBar: true, label: 'Home' }
195
- },
196
- {
197
- path: "search",
198
- element: <SuspenseWrap><Search /></SuspenseWrap>,
199
- handle: { showInNavigation: true, showNavBar: true, label: 'Search' }
200
- },
201
- {
202
- path: "test-acc",
203
- element: <SuspenseWrap><TestAccPage /></SuspenseWrap>,
204
- handle: { showInNavigation: true, label: "Test ACC" }
277
+ element: <Home />,
278
+ handle: { showInNavigation: true, showNavBar: true, label: "Home" }
205
279
  },
206
280
  {
207
- path: "global-search/:query",
208
- element: (
209
- <SuspenseWrap>
210
- <GlobalSearch />
211
- </SuspenseWrap>
212
- ),
213
- handle: { showInNavigation: false }
281
+ path: "accounts",
282
+ element: <AccountSearch />
214
283
  },
215
284
  {
216
- path: "object/:objectApiName/:recordId",
217
- element: (
218
- <SuspenseWrap>
219
- <DetailPage />
220
- </SuspenseWrap>
221
- ),
222
- handle: { showInNavigation: false }
285
+ path: "accounts/:recordId",
286
+ element: <AccountObjectDetail />
223
287
  },
224
288
  {
225
289
  path: '*',
226
- element: <SuspenseWrap><NotFound /></SuspenseWrap>
227
- },
290
+ element: <NotFound />
291
+ }
228
292
  ]
229
293
  }
230
294
  ];
231
295
  ROUTES_EOF
232
296
 
233
- echo " ✓ Routes updated (Home at /, Search at /search, nav on both)"
234
- echo ""
235
-
236
- # ── 7. Reset appLayout.tsx (nav on Home/Search only) ─────────────────────────
237
-
238
- LAYOUT="src/appLayout.tsx"
239
- echo "→ Updating ${LAYOUT}..."
240
-
241
- cat > "$LAYOUT" << 'LAYOUT_EOF'
242
- import { AgentforceConversationClient } from "./components/AgentforceConversationClient";
243
- import { Outlet, Link, useLocation, useMatches } from "react-router";
244
- import { getAllRoutes } from "./router-utils";
245
- import { useState } from "react";
246
-
247
- export default function AppLayout() {
248
- const [isOpen, setIsOpen] = useState(false);
249
- const location = useLocation();
250
- const matches = useMatches();
251
-
252
- const showNavBar = matches.some(
253
- (m) => (m.handle as Record<string, unknown>)?.showNavBar === true,
254
- );
255
-
256
- const isActive = (path: string) => location.pathname === path;
257
-
258
- const toggleMenu = () => setIsOpen(!isOpen);
259
-
260
- const navigationRoutes: { path: string; label: string }[] = getAllRoutes()
261
- .filter(
262
- (route) =>
263
- route.handle?.showInNavigation === true &&
264
- route.fullPath !== undefined &&
265
- route.handle?.label !== undefined,
266
- )
267
- .map(
268
- (route) =>
269
- ({
270
- path: route.fullPath,
271
- label: route.handle?.label,
272
- }) as { path: string; label: string },
273
- );
274
-
275
- return (
276
- <>
277
- {showNavBar && (
278
- <nav className="bg-white border-b border-gray-200">
279
- <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
280
- <div className="flex justify-between items-center h-16">
281
- <Link to="/" className="text-xl font-semibold text-gray-900">
282
- React App
283
- </Link>
284
- <button
285
- onClick={toggleMenu}
286
- className="p-2 rounded-md text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500"
287
- aria-label="Toggle menu"
288
- >
289
- <div className="w-6 h-6 flex flex-col justify-center space-y-1.5">
290
- <span
291
- className={`block h-0.5 w-6 bg-current transition-all ${
292
- isOpen ? "rotate-45 translate-y-2" : ""
293
- }`}
294
- />
295
- <span
296
- className={`block h-0.5 w-6 bg-current transition-all ${isOpen ? "opacity-0" : ""}`}
297
- />
298
- <span
299
- className={`block h-0.5 w-6 bg-current transition-all ${
300
- isOpen ? "-rotate-45 -translate-y-2" : ""
301
- }`}
302
- />
303
- </div>
304
- </button>
305
- </div>
306
- {isOpen && (
307
- <div className="pb-4">
308
- <div className="flex flex-col space-y-2">
309
- {navigationRoutes.map((item) => (
310
- <Link
311
- key={item.path}
312
- to={item.path}
313
- onClick={() => setIsOpen(false)}
314
- className={`px-3 py-2 rounded-md text-sm font-medium transition-colors ${
315
- isActive(item.path)
316
- ? "bg-blue-100 text-blue-700"
317
- : "text-gray-700 hover:bg-gray-100"
318
- }`}
319
- >
320
- {item.label}
321
- </Link>
322
- ))}
323
- </div>
324
- </div>
325
- )}
326
- </div>
327
- </nav>
328
- )}
329
- <Outlet />
330
- <AgentforceConversationClient />
331
- </>
332
- );
333
- }
334
- LAYOUT_EOF
335
-
336
- echo " ✓ Layout updated (nav bar on Home/Search pages)"
297
+ echo " ✓ Routes updated (Home at /)"
337
298
  echo ""
338
299
 
339
- # ── 8. Clear Vite cache ─────────────────────────────────────────────────────
300
+ # ── 7. Clear Vite cache ─────────────────────────────────────────────────────
340
301
 
341
302
  echo "→ Cleaning caches…"
342
303
  rm -rf node_modules/.vite 2>/dev/null && echo " ✓ Cleared Vite cache" || true
@@ -351,16 +312,19 @@ echo "║ Everything preserved: ║"
351
312
  echo "║ • Theme (global.css + initialMode) ║"
352
313
  echo "║ • Component library (cards, charts, etc.) ║"
353
314
  echo "║ • HeroUI wrappers & theme providers ║"
354
- echo "║ • Salesforce SDK stubs for local dev ║"
315
+ echo "║ • Authentication features ║"
355
316
  echo "║ • All styles & dependencies ║"
356
317
  echo "║ ║"
357
318
  echo "║ Layout: ║"
358
- echo "║ / → Home (CommandCenter dashboard) ║"
359
- echo "║ /search Search (global search input) ║"
360
- echo "║ Nav bar on Home + Search pages only ║"
319
+ echo "║ / → Home (Search interface) ║"
320
+ echo "║ /accounts Account search and browse ║"
321
+ echo "║ ║"
322
+ echo "║ Search functionality: ║"
323
+ echo "║ • Search button navigates to /accounts ║"
324
+ echo "║ • Enter key in search input triggers search║"
325
+ echo "║ • Browse All button shows all accounts ║"
361
326
  echo "║ ║"
362
327
  echo "║ Start building: ║"
363
- echo "║ Edit src/components/pages/BlankDashboard.jsx║"
364
328
  echo "║ npm run dev ║"
365
329
  echo "╚════════════════════════════════════════════════╝"
366
330
  echo ""