@idealyst/mcp-server 1.2.101 → 1.2.103

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/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  storageGuides,
8
8
  toolDefinitions,
9
9
  translateGuides
10
- } from "./chunk-SRNAGZJL.js";
10
+ } from "./chunk-74TE7CY7.js";
11
11
 
12
12
  // src/index.ts
13
13
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -467,6 +467,48 @@ UnistylesRegistry
467
467
  });
468
468
  \`\`\`
469
469
 
470
+ ## useTheme Hook
471
+
472
+ Access the current theme in your components with full TypeScript inference:
473
+
474
+ \`\`\`typescript
475
+ import { useTheme } from '@idealyst/theme';
476
+
477
+ function MyComponent() {
478
+ const theme = useTheme();
479
+
480
+ return (
481
+ <View style={{ backgroundColor: theme.colors.surface.primary }}>
482
+ <Text style={{ color: theme.colors.text.primary }}>
483
+ Hello
484
+ </Text>
485
+ </View>
486
+ );
487
+ }
488
+ \`\`\`
489
+
490
+ The hook returns the properly typed theme based on your registered theme type:
491
+
492
+ \`\`\`typescript
493
+ const theme = useTheme();
494
+
495
+ // Access intent colors
496
+ const primaryColor = theme.intents.primary.primary;
497
+ const successLight = theme.intents.success.light;
498
+
499
+ // Access sizes
500
+ const buttonPadding = theme.sizes.button.md.paddingHorizontal;
501
+
502
+ // Access radii
503
+ const borderRadius = theme.radii.md;
504
+
505
+ // Access surface colors
506
+ const screenBg = theme.colors.surface.screen;
507
+
508
+ // Access text colors
509
+ const textColor = theme.colors.text.primary;
510
+ \`\`\`
511
+
470
512
  ## Platform-Specific Styles
471
513
 
472
514
  \`\`\`typescript
@@ -804,12 +846,12 @@ import { View, Card, Text } from '@idealyst/components';
804
846
  ### Form Input Spacing
805
847
 
806
848
  \`\`\`tsx
807
- import { Input, Checkbox, View } from '@idealyst/components';
849
+ import { TextInput, Checkbox, View } from '@idealyst/components';
808
850
 
809
851
  // Use margin to space form fields
810
852
  <View>
811
- <Input placeholder="Email" marginVertical="sm" />
812
- <Input placeholder="Password" marginVertical="sm" />
853
+ <TextInput placeholder="Email" marginVertical="sm" />
854
+ <TextInput placeholder="Password" marginVertical="sm" />
813
855
  <Checkbox label="Remember me" marginVertical="md" />
814
856
  </View>
815
857
  \`\`\`
@@ -2144,6 +2186,8 @@ type TabBarScreenOptions = {
2144
2186
  } & ScreenOptions;
2145
2187
  \`\`\`
2146
2188
 
2189
+ > **Nested navigators:** When a Stack is nested inside a Tab, the **stack's root route** still uses \`TabBarScreenOptions\` for its \`options\` (it needs tabBarIcon/tabBarLabel for the tab bar). Type it as \`options: TabBarScreenOptions\` on the stack wrapper route.
2190
+
2147
2191
  Example:
2148
2192
  \`\`\`tsx
2149
2193
  {
@@ -2258,6 +2302,45 @@ Full paths are automatically computed:
2258
2302
  - \`/dashboard/reports\`
2259
2303
  - \`/settings\`
2260
2304
 
2305
+ ## Adding a New Screen to an Existing App
2306
+
2307
+ When adding a new screen to a scaffolded project, you must complete ALL three steps:
2308
+
2309
+ ### Step 1: Create the screen component
2310
+ \`\`\`tsx
2311
+ // packages/shared/src/screens/TodoListScreen.tsx
2312
+ import { View, Text } from '@idealyst/components';
2313
+
2314
+ export function TodoListScreen() {
2315
+ return <View padding="md"><Text typography="h5">Todo List</Text></View>;
2316
+ }
2317
+ \`\`\`
2318
+
2319
+ ### Step 2: Register in the route config
2320
+ \`\`\`tsx
2321
+ // In your AppRouter.ts or route configuration file
2322
+ import { TodoListScreen } from '../screens/TodoListScreen';
2323
+
2324
+ const appRouter: RouteParam = {
2325
+ path: "/",
2326
+ type: 'navigator',
2327
+ layout: 'stack',
2328
+ routes: [
2329
+ { path: "", type: 'screen', component: HomeScreen },
2330
+ { path: "todos", type: 'screen', component: TodoListScreen }, // Add this
2331
+ ]
2332
+ };
2333
+ \`\`\`
2334
+
2335
+ ### Step 3: Navigate to the new screen
2336
+ \`\`\`tsx
2337
+ // In any existing screen
2338
+ const { navigate } = useNavigator();
2339
+ <Button onPress={() => navigate({ path: '/todos' })}>View Todos</Button>
2340
+ \`\`\`
2341
+
2342
+ > **CRITICAL:** A screen component that is NOT registered in the route config is unreachable. Writing a screen without adding it to routes is a common mistake.
2343
+
2261
2344
  ## Best Practices
2262
2345
 
2263
2346
  1. **Use relative paths** for child routes
@@ -2528,7 +2611,7 @@ header={{
2528
2611
  height: 80,
2529
2612
  content: (
2530
2613
  <View style={{ flexDirection: 'row', justifyContent: 'space-between', padding: 16 }}>
2531
- <Text size="lg" weight="bold">Dashboard</Text>
2614
+ <Text typography="h6" weight="bold">Dashboard</Text>
2532
2615
  <UserMenu />
2533
2616
  </View>
2534
2617
  )
@@ -2723,7 +2806,7 @@ export const DashboardLayout: React.FC<StackLayoutProps> = ({
2723
2806
  alignItems: 'center',
2724
2807
  padding: 16
2725
2808
  }}>
2726
- <Text size="xl" weight="bold">Dashboard</Text>
2809
+ <Text typography="h5" weight="bold">Dashboard</Text>
2727
2810
  <View style={{ flexDirection: 'row', gap: 16 }}>
2728
2811
  <NotificationBell />
2729
2812
  <UserAvatar />
@@ -2868,15 +2951,21 @@ navigator.navigate({ path: '/new-location', replace: true });
2868
2951
 
2869
2952
  ## useParams Hook
2870
2953
 
2871
- Access current route path parameters:
2954
+ Access current route path parameters. Returns \`Record<string, string>\`.
2955
+
2956
+ > **WARNING:** \`useParams()\` does NOT accept generic type arguments. Do NOT write \`useParams<{ id: string }>()\` \u2014 this causes TS2558. Access params by key from the returned record instead.
2872
2957
 
2873
2958
  \`\`\`tsx
2874
2959
  import { useParams } from '@idealyst/navigation';
2875
2960
 
2876
2961
  function UserScreen() {
2962
+ // CORRECT \u2014 no type argument
2877
2963
  const params = useParams();
2878
2964
  const userId = params.id; // Path param from /user/:id
2879
2965
 
2966
+ // WRONG \u2014 useParams does NOT accept generics
2967
+ // const params = useParams<{ id: string }>(); // TS2558 error!
2968
+
2880
2969
  return <Text>User ID: {userId}</Text>;
2881
2970
  }
2882
2971
  \`\`\`
@@ -3232,7 +3321,7 @@ const { canGoBack, goBack } = useNavigator();
3232
3321
 
3233
3322
  {canGoBack() && (
3234
3323
  <Button
3235
- icon="arrow-left"
3324
+ leftIcon="arrow-left"
3236
3325
  onPress={goBack}
3237
3326
  >
3238
3327
  Back
@@ -3309,11 +3398,11 @@ import { NavigatorParam, NotFoundComponentProps } from '@idealyst/navigation';
3309
3398
  const NotFoundPage = ({ path, params }: NotFoundComponentProps) => (
3310
3399
  <Screen>
3311
3400
  <View style={{ alignItems: 'center', padding: 24 }}>
3312
- <Icon name="alert-circle" size={64} color="red" />
3313
- <Text size="xl">Page Not Found</Text>
3401
+ <Icon name="alert-circle" size="xl" intent="danger" />
3402
+ <Text typography="h5">Page Not Found</Text>
3314
3403
  <Text color="secondary">The path "{path}" doesn't exist.</Text>
3315
3404
  {params && Object.keys(params).length > 0 && (
3316
- <Text size="sm">Params: {JSON.stringify(params)}</Text>
3405
+ <Text typography="caption">Params: {JSON.stringify(params)}</Text>
3317
3406
  )}
3318
3407
  </View>
3319
3408
  </Screen>
@@ -3352,7 +3441,7 @@ const NotFoundPage = ({ path, params }: NotFoundComponentProps) => {
3352
3441
  return (
3353
3442
  <Screen>
3354
3443
  <View style={{ padding: 16, gap: 24 }}>
3355
- <Text size="xl">404 - Page Not Found</Text>
3444
+ <Text typography="h5">404 - Page Not Found</Text>
3356
3445
  <Text>Attempted: {path}</Text>
3357
3446
  {params?.id && <Text>User ID: {params.id}</Text>}
3358
3447
  <Button onPress={() => navigate({ path: '/', replace: true })}>
@@ -3418,7 +3507,7 @@ Each navigator can have its own 404 handling:
3418
3507
  const SettingsNotFound = ({ path }: NotFoundComponentProps) => (
3419
3508
  <Screen>
3420
3509
  <View style={{ alignItems: 'center' }}>
3421
- <Icon name="cog-off" size={48} color="orange" />
3510
+ <Icon name="cog-off" size="lg" intent="warning" />
3422
3511
  <Text>Settings page not found: {path}</Text>
3423
3512
  </View>
3424
3513
  </Screen>
@@ -3510,17 +3599,17 @@ const GlobalNotFound = ({ path, params }: NotFoundComponentProps) => {
3510
3599
  return (
3511
3600
  <Screen>
3512
3601
  <View style={{ padding: 24, gap: 24, alignItems: 'center', flex: 1, justifyContent: 'center' }}>
3513
- <Icon name="alert-circle-outline" size={64} color="red" />
3514
- <Text size="xl" weight="bold">Page Not Found</Text>
3602
+ <Icon name="alert-circle-outline" size="xl" intent="danger" />
3603
+ <Text typography="h5" weight="bold">Page Not Found</Text>
3515
3604
  <Text color="secondary">The page you're looking for doesn't exist.</Text>
3516
3605
 
3517
3606
  <Card style={{ marginTop: 16, padding: 16 }}>
3518
- <Text size="sm" weight="semibold">Attempted path:</Text>
3519
- <Text size="sm" color="secondary">{path}</Text>
3607
+ <Text typography="caption" weight="semibold">Attempted path:</Text>
3608
+ <Text typography="caption" color="secondary">{path}</Text>
3520
3609
  {params && Object.keys(params).length > 0 && (
3521
3610
  <>
3522
- <Text size="sm" weight="semibold" style={{ marginTop: 8 }}>Params:</Text>
3523
- <Text size="sm" color="secondary">{JSON.stringify(params)}</Text>
3611
+ <Text typography="caption" weight="semibold" style={{ marginTop: 8 }}>Params:</Text>
3612
+ <Text typography="caption" color="secondary">{JSON.stringify(params)}</Text>
3524
3613
  </>
3525
3614
  )}
3526
3615
  </Card>
@@ -3539,9 +3628,9 @@ const AdminNotFound = ({ path }: NotFoundComponentProps) => {
3539
3628
 
3540
3629
  return (
3541
3630
  <Screen>
3542
- <View padding={16} style={{ alignItems: 'center' }}>
3543
- <Icon name="shield-off" size={48} color="orange" />
3544
- <Text size="lg">Admin page not found</Text>
3631
+ <View padding="md" style={{ alignItems: 'center' }}>
3632
+ <Icon name="shield-off" size="lg" intent="warning" />
3633
+ <Text typography="h6">Admin page not found</Text>
3545
3634
  <Button
3546
3635
  type="outlined"
3547
3636
  size="sm"
@@ -3736,7 +3825,7 @@ export function StackLayout({ options, currentPath }: StackLayoutProps) {
3736
3825
  {/* Title - centered or left-aligned */}
3737
3826
  <View style={{ flex: 1 }}>
3738
3827
  {typeof options?.headerTitle === 'string' ? (
3739
- <Text variant="title">{options.headerTitle}</Text>
3828
+ <Text typography="h6" weight="bold">{options.headerTitle}</Text>
3740
3829
  ) : (
3741
3830
  options?.headerTitle
3742
3831
  )}
@@ -3821,16 +3910,17 @@ export function TabLayout({ routes, currentPath }: TabLayoutProps) {
3821
3910
  })}
3822
3911
  {options?.tabBarBadge && (
3823
3912
  <Badge
3824
- count={options.tabBarBadge}
3825
3913
  style={{ position: 'absolute', top: -4, right: -8 }}
3826
- />
3914
+ >
3915
+ {options.tabBarBadge}
3916
+ </Badge>
3827
3917
  )}
3828
3918
  </View>
3829
3919
 
3830
3920
  {/* Label */}
3831
3921
  {options?.tabBarLabel && (
3832
3922
  <Text
3833
- size="xs"
3923
+ typography="caption"
3834
3924
  style={{
3835
3925
  marginTop: 4,
3836
3926
  color: isActive ? '#007AFF' : '#8E8E93',
@@ -3882,7 +3972,7 @@ export function DrawerLayout({ routes, currentPath, options }: StackLayoutProps)
3882
3972
  }}>
3883
3973
  {/* Logo/Header */}
3884
3974
  <View style={{ height: 56, justifyContent: 'center', paddingHorizontal: 16 }}>
3885
- {!isCollapsed && <Text variant="title">My App</Text>}
3975
+ {!isCollapsed && <Text typography="h6" weight="bold">My App</Text>}
3886
3976
  </View>
3887
3977
 
3888
3978
  {/* Menu Items */}
@@ -3918,7 +4008,7 @@ export function DrawerLayout({ routes, currentPath, options }: StackLayoutProps)
3918
4008
  onPress={() => setIsCollapsed(!isCollapsed)}
3919
4009
  style={{ padding: 12, marginTop: 'auto' }}
3920
4010
  >
3921
- <Icon name={isCollapsed ? 'chevron-right' : 'chevron-left'} size={24} />
4011
+ <Icon name={isCollapsed ? 'chevron-right' : 'chevron-left'} size="sm" />
3922
4012
  </Pressable>
3923
4013
  </View>
3924
4014
 
@@ -3946,7 +4036,7 @@ export function AppLayout({ options, routes, currentPath, children }: StackLayou
3946
4036
  height: 56,
3947
4037
  content: (
3948
4038
  <View style={{ flexDirection: 'row', alignItems: 'center', flex: 1 }}>
3949
- <Text variant="title">{options?.headerTitle || 'App'}</Text>
4039
+ <Text typography="h6" weight="bold">{options?.headerTitle || 'App'}</Text>
3950
4040
  <View style={{ marginLeft: 'auto' }}>{options?.headerRight}</View>
3951
4041
  </View>
3952
4042
  ),
@@ -4091,15 +4181,59 @@ Idealyst uses Material Design Icons (@mdi/react) with **7,447 icons** available.
4091
4181
 
4092
4182
  ## Icon Usage
4093
4183
 
4094
- ### In Components
4184
+ ### TypeScript Type \u2014 CRITICAL
4185
+
4186
+ Icon names are typed as \`IconName\`, NOT \`string\`. Use **bare names** like \`'home'\`, \`'check-circle'\` \u2014 do NOT add an \`'mdi:'\` prefix.
4095
4187
 
4096
- Icons can be used by providing the icon name as a string:
4188
+ When you create helper functions that return icon names, you MUST type them as \`IconName\`:
4189
+
4190
+ \`\`\`tsx
4191
+ import type { IconName } from '@idealyst/components';
4192
+
4193
+ // CORRECT: return type is IconName
4194
+ function getStatusIcon(status: string): IconName {
4195
+ switch (status) {
4196
+ case 'active': return 'check-circle';
4197
+ case 'pending': return 'clock-outline';
4198
+ default: return 'help-circle';
4199
+ }
4200
+ }
4201
+
4202
+ // WRONG: return type 'string' will cause TS2322 error when passed to icon props
4203
+ // function getStatusIcon(status: string): string { ... } // \u274C
4204
+
4205
+ // For icon lookup maps, type the values as IconName:
4206
+ const FILE_TYPE_ICONS: Record<string, IconName> = {
4207
+ 'image': 'file-image',
4208
+ 'video': 'file-video',
4209
+ 'audio': 'file-music',
4210
+ 'document': 'file-document',
4211
+ 'default': 'file',
4212
+ };
4213
+
4214
+ function getFileIcon(type: string): IconName {
4215
+ return FILE_TYPE_ICONS[type] ?? FILE_TYPE_ICONS['default'];
4216
+ }
4217
+ \`\`\`
4218
+
4219
+ ### When to Import \`Icon\` vs Use \`IconName\` Type
4220
+
4221
+ - Import the \`Icon\` component only when rendering a standalone icon as JSX: \`<Icon name="home" />\`
4222
+ - For component props like \`leftIcon\` on Button, \`leading\`/\`trailing\` on ListItem \u2014 pass bare string names. Do NOT import the \`Icon\` component for this use.
4223
+ - Import ONLY the \`IconName\` type (not the component) when you need a typed variable for an icon name:
4224
+
4225
+ \`\`\`tsx
4226
+ import type { IconName } from '@idealyst/components';
4227
+ const myIcon: IconName = 'home'; // Correct: type-only import
4228
+ \`\`\`
4229
+
4230
+ ### In Components
4097
4231
 
4098
4232
  \`\`\`tsx
4099
4233
  import { Button, Icon, List, Badge } from '@idealyst/components';
4100
4234
 
4101
- // Button with icon
4102
- <Button icon="check">Save</Button>
4235
+ // Button with icon (use leftIcon, NOT icon)
4236
+ <Button leftIcon="check">Save</Button>
4103
4237
 
4104
4238
  // Standalone Icon
4105
4239
  <Icon name="home" size="md" color="primary" />
@@ -4115,7 +4249,7 @@ import { Button, Icon, List, Badge } from '@idealyst/components';
4115
4249
 
4116
4250
  \`\`\`tsx
4117
4251
  <Icon
4118
- name="home" // Icon name (required)
4252
+ name="home" // Icon name (required) \u2014 type: IconName
4119
4253
  size="xs|sm|md|lg|xl|number" // Icon size
4120
4254
  color="primary|secondary|..." // Theme color
4121
4255
  />
@@ -4340,11 +4474,12 @@ Icons follow naming patterns:
4340
4474
 
4341
4475
  ### Button Icons
4342
4476
  \`\`\`tsx
4343
- <Button icon="content-save">Save</Button>
4344
- <Button icon="delete" intent="danger">Delete</Button>
4345
- <Button icon="pencil">Edit</Button>
4346
- <Button icon="plus">Add New</Button>
4477
+ <Button leftIcon="content-save">Save</Button>
4478
+ <Button leftIcon="delete" intent="danger">Delete</Button>
4479
+ <Button leftIcon="pencil">Edit</Button>
4480
+ <Button leftIcon="plus">Add New</Button>
4347
4481
  \`\`\`
4482
+ > **Note:** Button uses \`leftIcon\` and \`rightIcon\` \u2014 NOT \`icon\`.
4348
4483
 
4349
4484
  ### List Icons
4350
4485
  \`\`\`tsx
@@ -4356,9 +4491,9 @@ Icons follow naming patterns:
4356
4491
 
4357
4492
  ### Navigation Icons
4358
4493
  \`\`\`tsx
4359
- <Button icon="arrow-left" variant="text">Back</Button>
4360
- <Button icon="menu" variant="text">Menu</Button>
4361
- <Button icon="close" variant="text">Close</Button>
4494
+ <Button leftIcon="arrow-left" type="text">Back</Button>
4495
+ <Button leftIcon="menu" type="text">Menu</Button>
4496
+ <Button leftIcon="close" type="text">Close</Button>
4362
4497
  \`\`\`
4363
4498
 
4364
4499
  ### Status Icons