ai-design-system 0.1.111 → 0.1.112

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.
@@ -17,33 +17,82 @@ import {
17
17
  PopoverTrigger,
18
18
  } from "@/components/primitives/Popover"
19
19
 
20
- export interface Project {
20
+ export interface ProjectSwitcherItem {
21
21
  id: string
22
22
  name: string
23
+ [key: string]: unknown
23
24
  }
24
25
 
26
+ // Backwards compatibility alias
27
+ export type Project = ProjectSwitcherItem
28
+
25
29
  export interface ProjectSwitcherProps {
26
- projects: Project[]
30
+ /** List of projects / channels / workspaces to switch between */
31
+ projects?: ProjectSwitcherItem[]
32
+ /** Generic alias for projects */
33
+ items?: ProjectSwitcherItem[]
34
+ /** ID of the currently selected item */
27
35
  selectedProjectId?: string | null
28
- onSelectProject: (id: string) => void
29
- onCreateProject: () => void
36
+ /** Generic alias for selectedProjectId */
37
+ selectedId?: string | null
38
+ /** Callback fired when an item is selected */
39
+ onSelectProject?: (id: string) => void
40
+ /** Generic alias for onSelectProject */
41
+ onSelect?: (id: string) => void
42
+ /** Callback fired when creating a new item */
43
+ onCreateProject?: () => void
44
+ /** Generic alias for onCreateProject */
45
+ onCreate?: () => void
46
+ /** Custom CSS class names */
30
47
  className?: string
48
+ /**
49
+ * Domain entity name used to automatically derive labels (e.g. "Project", "Channel", "Workspace").
50
+ * @default "Project"
51
+ */
52
+ entityName?: string
53
+ /** Placeholder when nothing is selected. Defaults to "Select <entityName>..." */
54
+ placeholder?: string
55
+ /** Search input placeholder. Defaults to "Find <entityName>..." */
56
+ searchPlaceholder?: string
57
+ /** Empty state message. Defaults to "No <entityName.toLowerCase()>s, yet!" */
58
+ emptyMessage?: string
59
+ /** Create button label. Defaults to "Create <entityName>" */
60
+ createButtonText?: string
31
61
  }
32
62
 
33
63
  export const ProjectSwitcher = React.memo<ProjectSwitcherProps>(
34
64
  ({
35
- projects = [],
65
+ projects,
66
+ items,
36
67
  selectedProjectId,
37
- onSelectProject = () => {},
38
- onCreateProject = () => {},
68
+ selectedId,
69
+ onSelectProject,
70
+ onSelect,
71
+ onCreateProject,
72
+ onCreate,
39
73
  className,
74
+ entityName = "Project",
75
+ placeholder,
76
+ searchPlaceholder,
77
+ emptyMessage,
78
+ createButtonText,
40
79
  }) => {
41
80
  const [open, setOpen] = React.useState(false)
42
81
 
43
- const selectedProject = projects.find((p) => String(p.id) === String(selectedProjectId))
44
- const displayLabel = selectedProject ? selectedProject.name : "Select Project..."
82
+ const list = items ?? projects ?? []
83
+ const activeId = selectedId !== undefined ? selectedId : selectedProjectId
84
+ const handleSelect = onSelect ?? onSelectProject ?? (() => {})
85
+ const handleCreate = onCreate ?? onCreateProject ?? (() => {})
86
+
87
+ const resolvedPlaceholder = placeholder ?? `Select ${entityName}...`
88
+ const resolvedSearchPlaceholder = searchPlaceholder ?? `Find ${entityName}...`
89
+ const resolvedEmptyMessage = emptyMessage ?? `No ${entityName.toLowerCase()}s, yet!`
90
+ const resolvedCreateButtonText = createButtonText ?? `Create ${entityName}`
91
+
92
+ const selectedItem = list.find((p) => String(p.id) === String(activeId))
93
+ const displayLabel = selectedItem ? selectedItem.name : resolvedPlaceholder
45
94
 
46
- const defaultValue = selectedProject ? `${selectedProject.name}-${selectedProject.id}` : undefined
95
+ const defaultValue = selectedItem ? `${selectedItem.name}-${selectedItem.id}` : undefined
47
96
 
48
97
  return (
49
98
  <Popover open={open} onOpenChange={setOpen}>
@@ -64,7 +113,7 @@ export const ProjectSwitcher = React.memo<ProjectSwitcherProps>(
64
113
  <Command defaultValue={defaultValue}>
65
114
  <div className="flex items-center justify-between border-b border-neutral-600 px-3" cmdk-input-wrapper="">
66
115
  <CommandPrimitive.Input
67
- placeholder="Find Project..."
116
+ placeholder={resolvedSearchPlaceholder}
68
117
  className="flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
69
118
  />
70
119
  <kbd className="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border border-neutral-700 bg-neutral-800 px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100">Esc</kbd>
@@ -72,27 +121,28 @@ export const ProjectSwitcher = React.memo<ProjectSwitcherProps>(
72
121
  <CommandList className="max-h-[300px]">
73
122
  <CommandEmpty>
74
123
  <div className="flex flex-col items-center justify-center p-6 text-center text-sm text-muted-foreground">
75
- No projects, yet!
124
+ {resolvedEmptyMessage}
76
125
  </div>
77
126
  </CommandEmpty>
78
- {projects.length > 0 && (
127
+ {list.length > 0 && (
79
128
  <CommandGroup>
80
- {projects.map((project) => (
129
+ {list.map((item) => (
81
130
  <CommandItem
82
- key={project.id}
83
- value={`${project.name}-${project.id}`}
131
+ key={item.id}
132
+ value={`${item.name}-${item.id}`}
84
133
  onSelect={() => {
85
- onSelectProject(project.id)
134
+ handleSelect(item.id)
86
135
  setOpen(false)
87
136
  }}
88
137
  className="mb-1 last:mb-0 cursor-pointer flex items-center justify-between"
89
138
  >
90
139
  <div className="flex items-center">
91
- {project.name}
140
+ {item.name}
92
141
  </div>
93
- <Icon name="check"
142
+ <Icon
143
+ name="check"
94
144
  className={`h-4 w-4 ${
95
- String(selectedProjectId) === String(project.id) ? "opacity-100" : "opacity-0"
145
+ String(activeId) === String(item.id) ? "opacity-100" : "opacity-0"
96
146
  }`}
97
147
  />
98
148
  </CommandItem>
@@ -107,11 +157,11 @@ export const ProjectSwitcher = React.memo<ProjectSwitcherProps>(
107
157
  className="w-full justify-start text-sm font-normal"
108
158
  onClick={() => {
109
159
  setOpen(false)
110
- onCreateProject()
160
+ handleCreate()
111
161
  }}
112
162
  >
113
163
  <Icon name="plus" size="sm" className="mr-2 h-4 w-4" />
114
- Create Project
164
+ {resolvedCreateButtonText}
115
165
  </Button>
116
166
  </div>
117
167
  </Command>
@@ -196,7 +196,7 @@ export type { EmptyStateProps } from './EmptyState'
196
196
 
197
197
  // ProjectSwitcher Composite
198
198
  export { ProjectSwitcher } from './ProjectSwitcher'
199
- export type { ProjectSwitcherProps, Project } from './ProjectSwitcher'
199
+ export type { ProjectSwitcherProps, ProjectSwitcherItem, Project } from './ProjectSwitcher'
200
200
 
201
201
  // DashboardChart Composite
202
202
  export { DashboardChart } from './DashboardChart'
@@ -54,6 +54,7 @@ export type {
54
54
  ActionRequest,
55
55
  ReviewConfig,
56
56
  ProjectSwitcherProps,
57
+ ProjectSwitcherItem,
57
58
  Project,
58
59
  FormReportsDrawerFormProps,
59
60
  SessionHeaderProps,
package/dist/index.cjs CHANGED
@@ -2832,18 +2832,36 @@ var Popover2 = (props) => {
2832
2832
  Popover2.displayName = "Popover";
2833
2833
  var ProjectSwitcher = React3__namespace.memo(
2834
2834
  ({
2835
- projects = [],
2835
+ projects,
2836
+ items,
2836
2837
  selectedProjectId,
2837
- onSelectProject = () => {
2838
- },
2839
- onCreateProject = () => {
2840
- },
2841
- className
2838
+ selectedId,
2839
+ onSelectProject,
2840
+ onSelect,
2841
+ onCreateProject,
2842
+ onCreate,
2843
+ className,
2844
+ entityName = "Project",
2845
+ placeholder,
2846
+ searchPlaceholder,
2847
+ emptyMessage,
2848
+ createButtonText
2842
2849
  }) => {
2850
+ var _a, _b, _c;
2843
2851
  const [open, setOpen] = React3__namespace.useState(false);
2844
- const selectedProject = projects.find((p) => String(p.id) === String(selectedProjectId));
2845
- const displayLabel = selectedProject ? selectedProject.name : "Select Project...";
2846
- const defaultValue = selectedProject ? `${selectedProject.name}-${selectedProject.id}` : void 0;
2852
+ const list = (_a = items != null ? items : projects) != null ? _a : [];
2853
+ const activeId = selectedId !== void 0 ? selectedId : selectedProjectId;
2854
+ const handleSelect = (_b = onSelect != null ? onSelect : onSelectProject) != null ? _b : (() => {
2855
+ });
2856
+ const handleCreate = (_c = onCreate != null ? onCreate : onCreateProject) != null ? _c : (() => {
2857
+ });
2858
+ const resolvedPlaceholder = placeholder != null ? placeholder : `Select ${entityName}...`;
2859
+ const resolvedSearchPlaceholder = searchPlaceholder != null ? searchPlaceholder : `Find ${entityName}...`;
2860
+ const resolvedEmptyMessage = emptyMessage != null ? emptyMessage : `No ${entityName.toLowerCase()}s, yet!`;
2861
+ const resolvedCreateButtonText = createButtonText != null ? createButtonText : `Create ${entityName}`;
2862
+ const selectedItem = list.find((p) => String(p.id) === String(activeId));
2863
+ const displayLabel = selectedItem ? selectedItem.name : resolvedPlaceholder;
2864
+ const defaultValue = selectedItem ? `${selectedItem.name}-${selectedItem.id}` : void 0;
2847
2865
  return /* @__PURE__ */ jsxRuntime.jsxs(Popover2, { open, onOpenChange: setOpen, children: [
2848
2866
  /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
2849
2867
  Button2,
@@ -2863,35 +2881,35 @@ var ProjectSwitcher = React3__namespace.memo(
2863
2881
  /* @__PURE__ */ jsxRuntime.jsx(
2864
2882
  cmdk.Command.Input,
2865
2883
  {
2866
- placeholder: "Find Project...",
2884
+ placeholder: resolvedSearchPlaceholder,
2867
2885
  className: "flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
2868
2886
  }
2869
2887
  ),
2870
2888
  /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border border-neutral-700 bg-neutral-800 px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100", children: "Esc" })
2871
2889
  ] }),
2872
2890
  /* @__PURE__ */ jsxRuntime.jsxs(CommandList2, { className: "max-h-[300px]", children: [
2873
- /* @__PURE__ */ jsxRuntime.jsx(CommandEmpty2, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-center justify-center p-6 text-center text-sm text-muted-foreground", children: "No projects, yet!" }) }),
2874
- projects.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(CommandGroup2, { children: projects.map((project) => /* @__PURE__ */ jsxRuntime.jsxs(
2891
+ /* @__PURE__ */ jsxRuntime.jsx(CommandEmpty2, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-center justify-center p-6 text-center text-sm text-muted-foreground", children: resolvedEmptyMessage }) }),
2892
+ list.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(CommandGroup2, { children: list.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
2875
2893
  CommandItem2,
2876
2894
  {
2877
- value: `${project.name}-${project.id}`,
2895
+ value: `${item.name}-${item.id}`,
2878
2896
  onSelect: () => {
2879
- onSelectProject(project.id);
2897
+ handleSelect(item.id);
2880
2898
  setOpen(false);
2881
2899
  },
2882
2900
  className: "mb-1 last:mb-0 cursor-pointer flex items-center justify-between",
2883
2901
  children: [
2884
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: project.name }),
2902
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: item.name }),
2885
2903
  /* @__PURE__ */ jsxRuntime.jsx(
2886
2904
  Icon,
2887
2905
  {
2888
2906
  name: "check",
2889
- className: `h-4 w-4 ${String(selectedProjectId) === String(project.id) ? "opacity-100" : "opacity-0"}`
2907
+ className: `h-4 w-4 ${String(activeId) === String(item.id) ? "opacity-100" : "opacity-0"}`
2890
2908
  }
2891
2909
  )
2892
2910
  ]
2893
2911
  },
2894
- project.id
2912
+ item.id
2895
2913
  )) })
2896
2914
  ] }),
2897
2915
  /* @__PURE__ */ jsxRuntime.jsx(CommandSeparator2, {}),
@@ -2902,11 +2920,11 @@ var ProjectSwitcher = React3__namespace.memo(
2902
2920
  className: "w-full justify-start text-sm font-normal",
2903
2921
  onClick: () => {
2904
2922
  setOpen(false);
2905
- onCreateProject();
2923
+ handleCreate();
2906
2924
  },
2907
2925
  children: [
2908
2926
  /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "plus", size: "sm", className: "mr-2 h-4 w-4" }),
2909
- "Create Project"
2927
+ resolvedCreateButtonText
2910
2928
  ]
2911
2929
  }
2912
2930
  ) })