@omnifyjp/shell 0.1.1

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.
Files changed (63) hide show
  1. package/README.md +476 -0
  2. package/dist/chunk-6JYWZJEY.js +123 -0
  3. package/dist/chunk-6JYWZJEY.js.map +1 -0
  4. package/dist/chunk-ACCHC3AM.js +57 -0
  5. package/dist/chunk-ACCHC3AM.js.map +1 -0
  6. package/dist/chunk-EJEVW4RO.js +49 -0
  7. package/dist/chunk-EJEVW4RO.js.map +1 -0
  8. package/dist/chunk-OHORC3F5.js +72 -0
  9. package/dist/chunk-OHORC3F5.js.map +1 -0
  10. package/dist/chunk-OMIE3Z5N.js +661 -0
  11. package/dist/chunk-OMIE3Z5N.js.map +1 -0
  12. package/dist/chunk-OYE3TXTK.js +37 -0
  13. package/dist/chunk-OYE3TXTK.js.map +1 -0
  14. package/dist/chunk-Q3QWQG6P.js +91 -0
  15. package/dist/chunk-Q3QWQG6P.js.map +1 -0
  16. package/dist/chunk-QNCYBLHC.js +189 -0
  17. package/dist/chunk-QNCYBLHC.js.map +1 -0
  18. package/dist/chunk-SHHZRZMM.js +83 -0
  19. package/dist/chunk-SHHZRZMM.js.map +1 -0
  20. package/dist/chunk-WCRLQ5M5.js +235 -0
  21. package/dist/chunk-WCRLQ5M5.js.map +1 -0
  22. package/dist/chunk-YVUVYTVZ.js +224 -0
  23. package/dist/chunk-YVUVYTVZ.js.map +1 -0
  24. package/dist/components/AppShell.d.ts +27 -0
  25. package/dist/components/AppShell.js +11 -0
  26. package/dist/components/AppShell.js.map +1 -0
  27. package/dist/components/Header.d.ts +11 -0
  28. package/dist/components/Header.js +6 -0
  29. package/dist/components/Header.js.map +1 -0
  30. package/dist/components/OrganizationSelector.d.ts +8 -0
  31. package/dist/components/OrganizationSelector.js +4 -0
  32. package/dist/components/OrganizationSelector.js.map +1 -0
  33. package/dist/components/OrganizationSetupModal.d.ts +5 -0
  34. package/dist/components/OrganizationSetupModal.js +4 -0
  35. package/dist/components/OrganizationSetupModal.js.map +1 -0
  36. package/dist/components/PageContainer.d.ts +105 -0
  37. package/dist/components/PageContainer.js +3 -0
  38. package/dist/components/PageContainer.js.map +1 -0
  39. package/dist/components/ServiceMenu.d.ts +11 -0
  40. package/dist/components/ServiceMenu.js +3 -0
  41. package/dist/components/ServiceMenu.js.map +1 -0
  42. package/dist/components/Sidebar.d.ts +11 -0
  43. package/dist/components/Sidebar.js +5 -0
  44. package/dist/components/Sidebar.js.map +1 -0
  45. package/dist/contexts/OrganizationContext.d.ts +26 -0
  46. package/dist/contexts/OrganizationContext.js +3 -0
  47. package/dist/contexts/OrganizationContext.js.map +1 -0
  48. package/dist/contexts/ThemeContext.d.ts +14 -0
  49. package/dist/contexts/ThemeContext.js +3 -0
  50. package/dist/contexts/ThemeContext.js.map +1 -0
  51. package/dist/hooks/useDateFormat.d.ts +28 -0
  52. package/dist/hooks/useDateFormat.js +4 -0
  53. package/dist/hooks/useDateFormat.js.map +1 -0
  54. package/dist/i18n.d.ts +38 -0
  55. package/dist/i18n.js +3 -0
  56. package/dist/i18n.js.map +1 -0
  57. package/dist/index.d.ts +17 -0
  58. package/dist/index.js +13 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/types.d.ts +89 -0
  61. package/dist/types.js +3 -0
  62. package/dist/types.js.map +1 -0
  63. package/package.json +63 -0
@@ -0,0 +1,235 @@
1
+ import { useOrganization } from './chunk-SHHZRZMM.js';
2
+ import { useState } from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { Button } from '@omnifyjp/ui/components/button';
5
+ import { Input } from '@omnifyjp/ui/components/input';
6
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@omnifyjp/ui/components/dialog';
7
+ import { ArrowLeftRight, Building2, ArrowRight, MapPin, Check, Search } from 'lucide-react';
8
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
9
+
10
+ function OrganizationSelector({ variant = "header" }) {
11
+ const {
12
+ organizations,
13
+ selectedOrganization,
14
+ selectedBranch,
15
+ setSelectedOrganization,
16
+ setSelectedBranch,
17
+ getBranchesByOrg
18
+ } = useOrganization();
19
+ const { t } = useTranslation("shell");
20
+ const [showChangeModal, setShowChangeModal] = useState(false);
21
+ const [step, setStep] = useState("organization");
22
+ const [tempOrgId, setTempOrgId] = useState("");
23
+ const [tempBranchId, setTempBranchId] = useState("");
24
+ const [branchSearch, setBranchSearch] = useState("");
25
+ const handleOpenChange = () => {
26
+ setShowChangeModal(true);
27
+ setStep("organization");
28
+ setTempOrgId(selectedOrganization?.id || "");
29
+ setTempBranchId("");
30
+ setBranchSearch("");
31
+ };
32
+ const handleOrganizationNext = () => {
33
+ const org = organizations.find((o) => o.id === tempOrgId);
34
+ if (org) {
35
+ setSelectedOrganization(org);
36
+ setStep("branch");
37
+ setTempBranchId("");
38
+ setBranchSearch("");
39
+ }
40
+ };
41
+ const handleBranchComplete = () => {
42
+ const branch = getBranchesByOrg(selectedOrganization.id).find((b) => b.id === tempBranchId);
43
+ if (branch) {
44
+ setSelectedBranch(branch);
45
+ setShowChangeModal(false);
46
+ }
47
+ };
48
+ const availableBranches = selectedOrganization ? getBranchesByOrg(selectedOrganization.id) : [];
49
+ const filteredBranches = availableBranches.filter(
50
+ (b) => b.name.toLowerCase().includes(branchSearch.toLowerCase()) || b.location?.toLowerCase().includes(branchSearch.toLowerCase())
51
+ );
52
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
53
+ variant === "header" ? /* @__PURE__ */ jsxs(
54
+ Button,
55
+ {
56
+ variant: "outline",
57
+ onClick: handleOpenChange,
58
+ className: "gap-2 px-3",
59
+ children: [
60
+ selectedOrganization && /* @__PURE__ */ jsx(
61
+ "div",
62
+ {
63
+ className: "w-5 h-5 rounded flex items-center justify-center text-white font-bold text-[10px] flex-shrink-0",
64
+ style: { backgroundColor: selectedOrganization.color },
65
+ children: selectedOrganization.shortName
66
+ }
67
+ ),
68
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 min-w-0", children: [
69
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium truncate max-w-[120px]", children: selectedOrganization?.name || t("org.noOrgSelected") }),
70
+ selectedBranch && /* @__PURE__ */ jsxs(Fragment, { children: [
71
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "/" }),
72
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground truncate max-w-[100px]", children: selectedBranch.name })
73
+ ] })
74
+ ] }),
75
+ /* @__PURE__ */ jsx(ArrowLeftRight, { className: "w-3.5 h-3.5 text-muted-foreground flex-shrink-0" })
76
+ ]
77
+ }
78
+ ) : /* @__PURE__ */ jsxs(
79
+ "div",
80
+ {
81
+ className: "flex items-center justify-between gap-2 cursor-pointer hover:bg-sidebar-accent transition-colors rounded-md px-4 py-3",
82
+ onClick: handleOpenChange,
83
+ children: [
84
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-1 min-w-0", children: [
85
+ selectedOrganization && /* @__PURE__ */ jsx(
86
+ "div",
87
+ {
88
+ className: "w-8 h-8 rounded-lg flex items-center justify-center text-white font-bold text-xs flex-shrink-0",
89
+ style: { backgroundColor: selectedOrganization.color },
90
+ children: selectedOrganization.shortName
91
+ }
92
+ ),
93
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
94
+ /* @__PURE__ */ jsx("div", { className: "font-semibold text-sm truncate", children: selectedOrganization?.name || t("org.noOrgSelected") }),
95
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground truncate mt-0.5", children: selectedBranch?.name || t("org.noBranchSelected") })
96
+ ] })
97
+ ] }),
98
+ /* @__PURE__ */ jsx(ArrowLeftRight, { className: "w-3.5 h-3.5 text-muted-foreground flex-shrink-0" })
99
+ ]
100
+ }
101
+ ),
102
+ /* @__PURE__ */ jsx(Dialog, { open: showChangeModal, onOpenChange: setShowChangeModal, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-[520px]", children: [
103
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
104
+ /* @__PURE__ */ jsx(DialogTitle, { className: "text-xl font-semibold", children: step === "organization" ? t("org.selectOrg") : t("org.selectBranch") }),
105
+ /* @__PURE__ */ jsx(DialogDescription, { className: "text-sm", children: step === "organization" ? t("org.selectOrgDesc") : t("org.selectBranchDesc") })
106
+ ] }),
107
+ /* @__PURE__ */ jsxs("div", { className: "mt-4", children: [
108
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-6", children: [
109
+ /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-2 px-3 py-1.5 rounded-md text-sm font-medium ${step === "organization" ? "bg-blue-50 text-blue-700 dark:bg-blue-500/15 dark:text-blue-400" : "bg-muted text-muted-foreground"}`, children: [
110
+ /* @__PURE__ */ jsx(Building2, { className: "w-4 h-4" }),
111
+ t("org.orgStep")
112
+ ] }),
113
+ /* @__PURE__ */ jsx(ArrowRight, { className: "w-4 h-4 text-muted-foreground" }),
114
+ /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-2 px-3 py-1.5 rounded-md text-sm font-medium ${step === "branch" ? "bg-blue-50 text-blue-700 dark:bg-blue-500/15 dark:text-blue-400" : "bg-muted text-muted-foreground"}`, children: [
115
+ /* @__PURE__ */ jsx(MapPin, { className: "w-4 h-4" }),
116
+ t("org.branchStep")
117
+ ] })
118
+ ] }),
119
+ step === "organization" && /* @__PURE__ */ jsxs("div", { children: [
120
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: organizations.map((org) => /* @__PURE__ */ jsxs(
121
+ "div",
122
+ {
123
+ className: `relative flex items-center gap-3 rounded-lg border-2 p-4 cursor-pointer transition-all ${tempOrgId === org.id ? "border-blue-500 bg-blue-50/50 dark:bg-blue-500/10" : "border-border hover:border-muted-foreground/30 hover:bg-accent"}`,
124
+ onClick: () => setTempOrgId(org.id),
125
+ children: [
126
+ /* @__PURE__ */ jsx(
127
+ "div",
128
+ {
129
+ className: "w-10 h-10 rounded-lg flex items-center justify-center text-white font-bold text-sm flex-shrink-0",
130
+ style: { backgroundColor: org.color },
131
+ children: org.shortName
132
+ }
133
+ ),
134
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
135
+ /* @__PURE__ */ jsx("div", { className: "font-semibold text-base", children: org.name }),
136
+ org.description && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: org.description }),
137
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground mt-1", children: t("org.branchCount", { count: getBranchesByOrg(org.id).length }) })
138
+ ] }),
139
+ tempOrgId === org.id && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 w-6 h-6 rounded-full bg-blue-500 flex items-center justify-center", children: /* @__PURE__ */ jsx(Check, { className: "w-4 h-4 text-white" }) })
140
+ ]
141
+ },
142
+ org.id
143
+ )) }),
144
+ /* @__PURE__ */ jsx("div", { className: "mt-6 flex justify-end", children: /* @__PURE__ */ jsxs(
145
+ Button,
146
+ {
147
+ onClick: handleOrganizationNext,
148
+ disabled: !tempOrgId,
149
+ size: "lg",
150
+ className: "gap-2",
151
+ children: [
152
+ t("common.next"),
153
+ /* @__PURE__ */ jsx(ArrowRight, { className: "w-4 h-4" })
154
+ ]
155
+ }
156
+ ) })
157
+ ] }),
158
+ step === "branch" && selectedOrganization && /* @__PURE__ */ jsxs("div", { children: [
159
+ /* @__PURE__ */ jsxs("div", { className: "mb-4 p-3 bg-muted rounded-lg border border-border", children: [
160
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground mb-1.5", children: t("org.selectedOrg") }),
161
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
162
+ /* @__PURE__ */ jsx(
163
+ "div",
164
+ {
165
+ className: "w-8 h-8 rounded-lg flex items-center justify-center text-white font-bold text-xs",
166
+ style: { backgroundColor: selectedOrganization.color },
167
+ children: selectedOrganization.shortName
168
+ }
169
+ ),
170
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: selectedOrganization.name })
171
+ ] })
172
+ ] }),
173
+ /* @__PURE__ */ jsxs("div", { className: "relative mb-3", children: [
174
+ /* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" }),
175
+ /* @__PURE__ */ jsx(
176
+ Input,
177
+ {
178
+ placeholder: t("org.searchBranch"),
179
+ value: branchSearch,
180
+ onChange: (e) => setBranchSearch(e.target.value),
181
+ className: "pl-9"
182
+ }
183
+ )
184
+ ] }),
185
+ /* @__PURE__ */ jsx("div", { className: "space-y-2 max-h-[280px] overflow-y-auto", children: filteredBranches.length === 0 ? /* @__PURE__ */ jsx("div", { className: "py-6 text-center text-sm text-muted-foreground", children: t("org.noBranchFound") }) : filteredBranches.map((branch) => /* @__PURE__ */ jsxs(
186
+ "div",
187
+ {
188
+ className: `relative flex items-center gap-3 rounded-lg border-2 p-4 cursor-pointer transition-all ${tempBranchId === branch.id ? "border-blue-500 bg-blue-50/50 dark:bg-blue-500/10" : "border-border hover:border-muted-foreground/30 hover:bg-accent"}`,
189
+ onClick: () => setTempBranchId(branch.id),
190
+ children: [
191
+ /* @__PURE__ */ jsx("div", { className: "w-10 h-10 rounded-lg bg-muted flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx(MapPin, { className: "w-5 h-5 text-muted-foreground" }) }),
192
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
193
+ /* @__PURE__ */ jsx("div", { className: "font-semibold text-base", children: branch.name }),
194
+ branch.location && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: branch.location })
195
+ ] }),
196
+ tempBranchId === branch.id && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 w-6 h-6 rounded-full bg-blue-500 flex items-center justify-center", children: /* @__PURE__ */ jsx(Check, { className: "w-4 h-4 text-white" }) })
197
+ ]
198
+ },
199
+ branch.id
200
+ )) }),
201
+ /* @__PURE__ */ jsxs("div", { className: "mt-6 flex justify-between", children: [
202
+ /* @__PURE__ */ jsx(
203
+ Button,
204
+ {
205
+ variant: "outline",
206
+ onClick: () => {
207
+ setStep("organization");
208
+ setTempOrgId(selectedOrganization.id);
209
+ },
210
+ children: t("common.back")
211
+ }
212
+ ),
213
+ /* @__PURE__ */ jsxs(
214
+ Button,
215
+ {
216
+ onClick: handleBranchComplete,
217
+ disabled: !tempBranchId,
218
+ size: "lg",
219
+ className: "gap-2",
220
+ children: [
221
+ t("common.complete"),
222
+ /* @__PURE__ */ jsx(ArrowRight, { className: "w-4 h-4" })
223
+ ]
224
+ }
225
+ )
226
+ ] })
227
+ ] })
228
+ ] })
229
+ ] }) })
230
+ ] });
231
+ }
232
+
233
+ export { OrganizationSelector };
234
+ //# sourceMappingURL=chunk-WCRLQ5M5.js.map
235
+ //# sourceMappingURL=chunk-WCRLQ5M5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/OrganizationSelector.tsx"],"names":[],"mappings":"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","file":"chunk-WCRLQ5M5.js","sourcesContent":["import { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useOrganization } from '../contexts/OrganizationContext';\nimport { Button } from '@omnifyjp/ui/components/button';\nimport { Input } from '@omnifyjp/ui/components/input';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '@omnifyjp/ui/components/dialog';\nimport { Building2, ArrowLeftRight, Check, Search, MapPin, ArrowRight } from 'lucide-react';\n\ninterface OrganizationSelectorProps {\n variant?: 'header' | 'sidebar';\n}\n\nexport function OrganizationSelector({ variant = 'header' }: OrganizationSelectorProps) {\n const {\n organizations,\n selectedOrganization,\n selectedBranch,\n setSelectedOrganization,\n setSelectedBranch,\n getBranchesByOrg,\n } = useOrganization();\n\n const { t } = useTranslation('shell');\n\n const [showChangeModal, setShowChangeModal] = useState(false);\n const [step, setStep] = useState<'organization' | 'branch'>('organization');\n const [tempOrgId, setTempOrgId] = useState<string>('');\n const [tempBranchId, setTempBranchId] = useState<string>('');\n const [branchSearch, setBranchSearch] = useState('');\n\n const handleOpenChange = () => {\n setShowChangeModal(true);\n setStep('organization');\n setTempOrgId(selectedOrganization?.id || '');\n setTempBranchId('');\n setBranchSearch('');\n };\n\n const handleOrganizationNext = () => {\n const org = organizations.find(o => o.id === tempOrgId);\n if (org) {\n setSelectedOrganization(org);\n setStep('branch');\n setTempBranchId('');\n setBranchSearch('');\n }\n };\n\n const handleBranchComplete = () => {\n const branch = getBranchesByOrg(selectedOrganization!.id).find(b => b.id === tempBranchId);\n if (branch) {\n setSelectedBranch(branch);\n setShowChangeModal(false);\n }\n };\n\n const availableBranches = selectedOrganization ? getBranchesByOrg(selectedOrganization.id) : [];\n const filteredBranches = availableBranches.filter((b) =>\n b.name.toLowerCase().includes(branchSearch.toLowerCase()) ||\n b.location?.toLowerCase().includes(branchSearch.toLowerCase())\n );\n\n return (\n <>\n {variant === 'header' ? (\n <Button\n variant=\"outline\"\n onClick={handleOpenChange}\n className=\"gap-2 px-3\"\n >\n {selectedOrganization && (\n <div\n className=\"w-5 h-5 rounded flex items-center justify-center text-white font-bold text-[10px] flex-shrink-0\"\n style={{ backgroundColor: selectedOrganization.color }}\n >\n {selectedOrganization.shortName}\n </div>\n )}\n <div className=\"flex items-center gap-1.5 min-w-0\">\n <span className=\"text-sm font-medium truncate max-w-[120px]\">\n {selectedOrganization?.name || t('org.noOrgSelected')}\n </span>\n {selectedBranch && (\n <>\n <span className=\"text-muted-foreground\">/</span>\n <span className=\"text-sm text-muted-foreground truncate max-w-[100px]\">\n {selectedBranch.name}\n </span>\n </>\n )}\n </div>\n <ArrowLeftRight className=\"w-3.5 h-3.5 text-muted-foreground flex-shrink-0\" />\n </Button>\n ) : (\n <div\n className=\"flex items-center justify-between gap-2 cursor-pointer hover:bg-sidebar-accent transition-colors rounded-md px-4 py-3\"\n onClick={handleOpenChange}\n >\n <div className=\"flex items-center gap-2 flex-1 min-w-0\">\n {selectedOrganization && (\n <div\n className=\"w-8 h-8 rounded-lg flex items-center justify-center text-white font-bold text-xs flex-shrink-0\"\n style={{ backgroundColor: selectedOrganization.color }}\n >\n {selectedOrganization.shortName}\n </div>\n )}\n <div className=\"flex-1 min-w-0\">\n <div className=\"font-semibold text-sm truncate\">\n {selectedOrganization?.name || t('org.noOrgSelected')}\n </div>\n <div className=\"text-xs text-muted-foreground truncate mt-0.5\">\n {selectedBranch?.name || t('org.noBranchSelected')}\n </div>\n </div>\n </div>\n <ArrowLeftRight className=\"w-3.5 h-3.5 text-muted-foreground flex-shrink-0\" />\n </div>\n )}\n\n <Dialog open={showChangeModal} onOpenChange={setShowChangeModal}>\n <DialogContent className=\"sm:max-w-[520px]\">\n <DialogHeader>\n <DialogTitle className=\"text-xl font-semibold\">\n {step === 'organization' ? t('org.selectOrg') : t('org.selectBranch')}\n </DialogTitle>\n <DialogDescription className=\"text-sm\">\n {step === 'organization'\n ? t('org.selectOrgDesc')\n : t('org.selectBranchDesc')}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"mt-4\">\n <div className=\"flex items-center gap-2 mb-6\">\n <div className={`flex items-center gap-2 px-3 py-1.5 rounded-md text-sm font-medium ${\n step === 'organization' ? 'bg-blue-50 text-blue-700 dark:bg-blue-500/15 dark:text-blue-400' : 'bg-muted text-muted-foreground'\n }`}>\n <Building2 className=\"w-4 h-4\" />\n {t('org.orgStep')}\n </div>\n <ArrowRight className=\"w-4 h-4 text-muted-foreground\" />\n <div className={`flex items-center gap-2 px-3 py-1.5 rounded-md text-sm font-medium ${\n step === 'branch' ? 'bg-blue-50 text-blue-700 dark:bg-blue-500/15 dark:text-blue-400' : 'bg-muted text-muted-foreground'\n }`}>\n <MapPin className=\"w-4 h-4\" />\n {t('org.branchStep')}\n </div>\n </div>\n\n {step === 'organization' && (\n <div>\n <div className=\"space-y-2\">\n {organizations.map((org) => (\n <div\n key={org.id}\n className={`relative flex items-center gap-3 rounded-lg border-2 p-4 cursor-pointer transition-all ${\n tempOrgId === org.id\n ? 'border-blue-500 bg-blue-50/50 dark:bg-blue-500/10'\n : 'border-border hover:border-muted-foreground/30 hover:bg-accent'\n }`}\n onClick={() => setTempOrgId(org.id)}\n >\n <div\n className=\"w-10 h-10 rounded-lg flex items-center justify-center text-white font-bold text-sm flex-shrink-0\"\n style={{ backgroundColor: org.color }}\n >\n {org.shortName}\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"font-semibold text-base\">{org.name}</div>\n {org.description && (\n <div className=\"text-sm text-muted-foreground\">{org.description}</div>\n )}\n <div className=\"text-xs text-muted-foreground mt-1\">\n {t('org.branchCount', { count: getBranchesByOrg(org.id).length })}\n </div>\n </div>\n {tempOrgId === org.id && (\n <div className=\"flex-shrink-0 w-6 h-6 rounded-full bg-blue-500 flex items-center justify-center\">\n <Check className=\"w-4 h-4 text-white\" />\n </div>\n )}\n </div>\n ))}\n </div>\n\n <div className=\"mt-6 flex justify-end\">\n <Button\n onClick={handleOrganizationNext}\n disabled={!tempOrgId}\n size=\"lg\"\n className=\"gap-2\"\n >\n {t('common.next')}\n <ArrowRight className=\"w-4 h-4\" />\n </Button>\n </div>\n </div>\n )}\n\n {step === 'branch' && selectedOrganization && (\n <div>\n <div className=\"mb-4 p-3 bg-muted rounded-lg border border-border\">\n <div className=\"text-xs text-muted-foreground mb-1.5\">{t('org.selectedOrg')}</div>\n <div className=\"flex items-center gap-2\">\n <div\n className=\"w-8 h-8 rounded-lg flex items-center justify-center text-white font-bold text-xs\"\n style={{ backgroundColor: selectedOrganization.color }}\n >\n {selectedOrganization.shortName}\n </div>\n <span className=\"font-semibold\">{selectedOrganization.name}</span>\n </div>\n </div>\n\n <div className=\"relative mb-3\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground\" />\n <Input\n placeholder={t('org.searchBranch')}\n value={branchSearch}\n onChange={(e) => setBranchSearch(e.target.value)}\n className=\"pl-9\"\n />\n </div>\n\n <div className=\"space-y-2 max-h-[280px] overflow-y-auto\">\n {filteredBranches.length === 0 ? (\n <div className=\"py-6 text-center text-sm text-muted-foreground\">\n {t('org.noBranchFound')}\n </div>\n ) : (\n filteredBranches.map((branch) => (\n <div\n key={branch.id}\n className={`relative flex items-center gap-3 rounded-lg border-2 p-4 cursor-pointer transition-all ${\n tempBranchId === branch.id\n ? 'border-blue-500 bg-blue-50/50 dark:bg-blue-500/10'\n : 'border-border hover:border-muted-foreground/30 hover:bg-accent'\n }`}\n onClick={() => setTempBranchId(branch.id)}\n >\n <div className=\"w-10 h-10 rounded-lg bg-muted flex items-center justify-center flex-shrink-0\">\n <MapPin className=\"w-5 h-5 text-muted-foreground\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"font-semibold text-base\">{branch.name}</div>\n {branch.location && (\n <div className=\"text-sm text-muted-foreground\">{branch.location}</div>\n )}\n </div>\n {tempBranchId === branch.id && (\n <div className=\"flex-shrink-0 w-6 h-6 rounded-full bg-blue-500 flex items-center justify-center\">\n <Check className=\"w-4 h-4 text-white\" />\n </div>\n )}\n </div>\n ))\n )}\n </div>\n\n <div className=\"mt-6 flex justify-between\">\n <Button\n variant=\"outline\"\n onClick={() => {\n setStep('organization');\n setTempOrgId(selectedOrganization.id);\n }}\n >\n {t('common.back')}\n </Button>\n <Button\n onClick={handleBranchComplete}\n disabled={!tempBranchId}\n size=\"lg\"\n className=\"gap-2\"\n >\n {t('common.complete')}\n <ArrowRight className=\"w-4 h-4\" />\n </Button>\n </div>\n </div>\n )}\n </div>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n"]}
@@ -0,0 +1,224 @@
1
+ import { OrganizationSelector } from './chunk-WCRLQ5M5.js';
2
+ import { useOrganization } from './chunk-SHHZRZMM.js';
3
+ import { useState } from 'react';
4
+ import { useLocation, useParams, Link } from 'react-router';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { Button } from '@omnifyjp/ui/components/button';
7
+ import { Separator } from '@omnifyjp/ui/components/separator';
8
+ import { Popover, PopoverTrigger, PopoverContent } from '@omnifyjp/ui/components/popover';
9
+ import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '@omnifyjp/ui/components/tooltip';
10
+ import { ChevronsUpDown, Search, ChevronsRight, ChevronsLeft, ChevronRight } from 'lucide-react';
11
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
12
+
13
+ function Sidebar({ config }) {
14
+ const location = useLocation();
15
+ const params = useParams();
16
+ const [collapsed, setCollapsed] = useState(false);
17
+ const [contextSwitcherOpen, setContextSwitcherOpen] = useState(false);
18
+ const [contextSearch, setContextSearch] = useState("");
19
+ const [expandedGroups, setExpandedGroups] = useState(/* @__PURE__ */ new Set());
20
+ const { t } = useTranslation("shell");
21
+ const { selectedOrganization, selectedBranch } = useOrganization();
22
+ const { app, sidebar } = config;
23
+ const contextParamValue = sidebar.contextMenu ? params[sidebar.contextMenu.paramName] : void 0;
24
+ const isInContext = !!contextParamValue;
25
+ const isActive = (path) => {
26
+ return location.pathname === path || location.pathname.startsWith(path + "/");
27
+ };
28
+ const renderMenuItem = (item, active) => {
29
+ const Icon = item.icon;
30
+ const path = item.path;
31
+ const content = /* @__PURE__ */ jsxs(
32
+ Link,
33
+ {
34
+ to: path,
35
+ className: `flex items-center ${collapsed ? "justify-center" : "gap-2"} px-3 py-2 rounded-md text-sm transition-colors ${active ? "bg-blue-50 text-blue-600 dark:bg-blue-500/15 dark:text-blue-400 font-medium" : "text-sidebar-foreground hover:bg-sidebar-accent"}`,
36
+ children: [
37
+ /* @__PURE__ */ jsx(Icon, { className: "w-4 h-4 flex-shrink-0" }),
38
+ !collapsed && /* @__PURE__ */ jsx("span", { children: item.label }),
39
+ !collapsed && item.badge !== void 0 && item.badge > 0 && /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs bg-muted text-muted-foreground px-1.5 py-0.5 rounded-full", children: item.badge })
40
+ ]
41
+ }
42
+ );
43
+ if (collapsed) {
44
+ return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
45
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: content }),
46
+ /* @__PURE__ */ jsx(TooltipContent, { side: "right", className: "font-medium", children: item.label })
47
+ ] }) }, path);
48
+ }
49
+ return /* @__PURE__ */ jsx("div", { children: content }, path);
50
+ };
51
+ const isGroupActive = (item) => {
52
+ if (item.children) {
53
+ return item.children.some((child) => child.path ? isActive(child.path) : false);
54
+ }
55
+ return item.path ? isActive(item.path) : false;
56
+ };
57
+ const toggleGroup = (label) => {
58
+ setExpandedGroups((prev) => {
59
+ const next = new Set(prev);
60
+ if (next.has(label)) {
61
+ next.delete(label);
62
+ } else {
63
+ next.add(label);
64
+ }
65
+ return next;
66
+ });
67
+ };
68
+ const renderMenuItemOrGroup = (item) => {
69
+ if (!item.children) {
70
+ return renderMenuItem(item, item.path ? isActive(item.path) : false);
71
+ }
72
+ const groupActive = isGroupActive(item);
73
+ const isExpanded = expandedGroups.has(item.label) || groupActive;
74
+ const Icon = item.icon;
75
+ if (collapsed) {
76
+ return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
77
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
78
+ "button",
79
+ {
80
+ onClick: () => toggleGroup(item.label),
81
+ className: `flex items-center justify-center w-full px-3 py-2 rounded-md text-sm transition-colors ${groupActive ? "bg-blue-50 text-blue-600 dark:bg-blue-500/15 dark:text-blue-400 font-medium" : "text-sidebar-foreground hover:bg-sidebar-accent"}`,
82
+ children: /* @__PURE__ */ jsx(Icon, { className: "w-4 h-4 flex-shrink-0" })
83
+ }
84
+ ) }),
85
+ /* @__PURE__ */ jsx(TooltipContent, { side: "right", className: "font-medium", children: item.label })
86
+ ] }) }, item.label);
87
+ }
88
+ return /* @__PURE__ */ jsxs("div", { children: [
89
+ /* @__PURE__ */ jsxs(
90
+ "button",
91
+ {
92
+ onClick: () => toggleGroup(item.label),
93
+ className: `flex items-center gap-2 w-full px-3 py-2 rounded-md text-sm transition-colors ${groupActive ? "text-blue-600 dark:text-blue-400 font-medium" : "text-sidebar-foreground hover:bg-sidebar-accent"}`,
94
+ children: [
95
+ /* @__PURE__ */ jsx(Icon, { className: "w-4 h-4 flex-shrink-0" }),
96
+ /* @__PURE__ */ jsx("span", { children: item.label }),
97
+ /* @__PURE__ */ jsx(ChevronRight, { className: `w-3.5 h-3.5 ml-auto text-muted-foreground transition-transform duration-200 ${isExpanded ? "rotate-90" : ""}` })
98
+ ]
99
+ }
100
+ ),
101
+ isExpanded && /* @__PURE__ */ jsx("div", { className: "ml-4 pl-2 border-l border-sidebar-border space-y-0.5 mt-0.5", children: item.children.map((child) => renderMenuItem(child, child.path ? isActive(child.path) : false)) })
102
+ ] }, item.label);
103
+ };
104
+ const contextMenuItems = isInContext && sidebar.contextMenu ? sidebar.contextMenu.getItems(contextParamValue) : [];
105
+ const contextHeader = isInContext && sidebar.contextMenu?.getHeader ? sidebar.contextMenu.getHeader(contextParamValue) : null;
106
+ const footerItems = isInContext && sidebar.contextMenu?.getFooterItems ? sidebar.contextMenu.getFooterItems() : [];
107
+ return /* @__PURE__ */ jsxs("aside", { className: `${collapsed ? "w-16" : "w-64"} bg-sidebar border-r border-sidebar-border flex flex-col transition-all duration-300`, children: [
108
+ /* @__PURE__ */ jsx("div", { className: `h-header border-b border-sidebar-border flex items-center ${collapsed ? "justify-center" : "px-4"} transition-all duration-300`, children: /* @__PURE__ */ jsxs(Link, { to: "/", className: "flex items-center gap-2", children: [
109
+ /* @__PURE__ */ jsx("div", { className: `w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0 ${app.logo.color ? "" : "bg-blue-600"}`, style: app.logo.color ? { backgroundColor: app.logo.color } : void 0, children: /* @__PURE__ */ jsx(app.logo.icon, { className: "w-4 h-4 text-white" }) }),
110
+ !collapsed && /* @__PURE__ */ jsx("span", { className: "font-bold text-sm", children: app.logo.text })
111
+ ] }) }),
112
+ /* @__PURE__ */ jsx("nav", { className: "flex-1 px-3 py-3 overflow-y-auto", children: isInContext ? /* @__PURE__ */ jsxs(Fragment, { children: [
113
+ contextHeader && !collapsed ? /* @__PURE__ */ jsxs(Popover, { open: contextSwitcherOpen, onOpenChange: (open) => {
114
+ setContextSwitcherOpen(open);
115
+ if (!open) setContextSearch("");
116
+ }, children: [
117
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs("button", { className: "w-full mb-3 px-3 py-2 flex items-center gap-2 rounded-md hover:bg-sidebar-accent transition-colors text-left", children: [
118
+ contextHeader,
119
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "w-3.5 h-3.5 text-muted-foreground flex-shrink-0" })
120
+ ] }) }),
121
+ /* @__PURE__ */ jsx(PopoverContent, { side: "right", align: "start", className: "w-72 p-0", children: /* @__PURE__ */ jsx("div", { className: "p-2 border-b", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
122
+ /* @__PURE__ */ jsx(Search, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground" }),
123
+ /* @__PURE__ */ jsx(
124
+ "input",
125
+ {
126
+ className: "w-full pl-8 pr-3 py-1.5 text-sm border rounded-md outline-none focus:ring-1 focus:ring-blue-500 bg-background",
127
+ placeholder: t("sidebar.searchProject"),
128
+ value: contextSearch,
129
+ onChange: (e) => setContextSearch(e.target.value),
130
+ autoFocus: true
131
+ }
132
+ )
133
+ ] }) }) })
134
+ ] }) : contextHeader && collapsed ? /* @__PURE__ */ jsx("div", { className: "mb-3 w-full flex justify-center py-1 rounded-md hover:bg-sidebar-accent transition-colors", children: contextHeader }) : null,
135
+ !collapsed && contextHeader && /* @__PURE__ */ jsx(Separator, { className: "my-3" }),
136
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: contextMenuItems.map((item) => {
137
+ const active = item.path ? isActive(item.path) : false;
138
+ return renderMenuItem(item, active);
139
+ }) }),
140
+ footerItems.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
141
+ !collapsed && /* @__PURE__ */ jsx(Separator, { className: "my-3" }),
142
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: footerItems.map((item) => renderMenuItem(item, false)) })
143
+ ] })
144
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
145
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: sidebar.menuItems.map((item) => renderMenuItemOrGroup(item)) }),
146
+ sidebar.recentItems && /* @__PURE__ */ jsxs(Fragment, { children: [
147
+ !collapsed && /* @__PURE__ */ jsx(Separator, { className: "my-3" }),
148
+ !collapsed ? /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
149
+ /* @__PURE__ */ jsx("h3", { className: "px-3 py-1 text-xs font-medium text-muted-foreground uppercase tracking-wider", children: sidebar.recentItems.title }),
150
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: sidebar.recentItems.items.map((item) => /* @__PURE__ */ jsxs(
151
+ Link,
152
+ {
153
+ to: item.path,
154
+ className: "flex items-center gap-2 px-3 py-2 rounded-md text-sm text-sidebar-foreground hover:bg-sidebar-accent",
155
+ children: [
156
+ item.color && /* @__PURE__ */ jsx(
157
+ "div",
158
+ {
159
+ className: "w-5 h-5 rounded flex items-center justify-center text-white text-[9px] font-bold flex-shrink-0",
160
+ style: { backgroundColor: item.color },
161
+ children: item.badge
162
+ }
163
+ ),
164
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: item.label })
165
+ ]
166
+ },
167
+ item.path
168
+ )) })
169
+ ] }) : /* @__PURE__ */ jsx("div", { className: "space-y-0.5 mt-3", children: sidebar.recentItems.items.map((item) => /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
170
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
171
+ Link,
172
+ {
173
+ to: item.path,
174
+ className: "flex justify-center px-3 py-2 rounded-md text-sidebar-foreground hover:bg-sidebar-accent",
175
+ children: item.color && /* @__PURE__ */ jsx(
176
+ "div",
177
+ {
178
+ className: "w-5 h-5 rounded flex items-center justify-center text-white text-[9px] font-bold",
179
+ style: { backgroundColor: item.color },
180
+ children: item.badge
181
+ }
182
+ )
183
+ }
184
+ ) }),
185
+ /* @__PURE__ */ jsx(TooltipContent, { side: "right", children: /* @__PURE__ */ jsx("p", { className: "font-medium text-sm", children: item.label }) })
186
+ ] }) }, item.path)) })
187
+ ] })
188
+ ] }) }),
189
+ /* @__PURE__ */ jsx("div", { className: "px-3 py-2 border-t border-sidebar-border", children: /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
190
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
191
+ Button,
192
+ {
193
+ variant: "ghost",
194
+ size: "sm",
195
+ onClick: () => setCollapsed(!collapsed),
196
+ className: `w-full h-8 ${collapsed ? "px-0 justify-center" : "justify-start"} hover:bg-sidebar-accent`,
197
+ children: collapsed ? /* @__PURE__ */ jsx(ChevronsRight, { className: "w-3.5 h-3.5 text-muted-foreground" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
198
+ /* @__PURE__ */ jsx(ChevronsLeft, { className: "w-3.5 h-3.5 text-muted-foreground mr-2" }),
199
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: t("sidebar.collapse") })
200
+ ] })
201
+ }
202
+ ) }),
203
+ /* @__PURE__ */ jsx(TooltipContent, { side: "right", children: collapsed ? t("sidebar.expandSidebar") : t("sidebar.collapseSidebar") })
204
+ ] }) }) }),
205
+ !collapsed ? /* @__PURE__ */ jsx("div", { className: "border-t border-sidebar-border", children: /* @__PURE__ */ jsx(OrganizationSelector, { variant: "sidebar" }) }) : selectedOrganization && /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
206
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("div", { className: "px-3 py-3 border-t border-sidebar-border flex justify-center cursor-pointer hover:bg-sidebar-accent transition-colors", children: /* @__PURE__ */ jsx(
207
+ "div",
208
+ {
209
+ className: "w-8 h-8 rounded-lg flex items-center justify-center text-white font-bold text-xs",
210
+ style: { backgroundColor: selectedOrganization.color },
211
+ children: selectedOrganization.shortName
212
+ }
213
+ ) }) }),
214
+ /* @__PURE__ */ jsxs(TooltipContent, { side: "right", children: [
215
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-sm", children: selectedOrganization.name }),
216
+ selectedBranch && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: selectedBranch.name })
217
+ ] })
218
+ ] }) })
219
+ ] });
220
+ }
221
+
222
+ export { Sidebar };
223
+ //# sourceMappingURL=chunk-YVUVYTVZ.js.map
224
+ //# sourceMappingURL=chunk-YVUVYTVZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Sidebar.tsx"],"names":[],"mappings":"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","file":"chunk-YVUVYTVZ.js","sourcesContent":["import { useState } from 'react';\nimport { useLocation, useParams, Link } from 'react-router';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@omnifyjp/ui/components/button';\nimport { Separator } from '@omnifyjp/ui/components/separator';\nimport { Popover, PopoverContent, PopoverTrigger } from '@omnifyjp/ui/components/popover';\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from '@omnifyjp/ui/components/tooltip';\nimport {\n ChevronsLeft,\n ChevronsRight,\n ChevronsUpDown,\n ChevronRight,\n Search,\n} from 'lucide-react';\nimport { useOrganization } from '../contexts/OrganizationContext';\nimport { OrganizationSelector } from './OrganizationSelector';\nimport type { ShellConfig, SidebarMenuItem } from '../types';\n\ninterface SidebarProps {\n config: ShellConfig;\n}\n\nexport function Sidebar({ config }: SidebarProps) {\n const location = useLocation();\n const params = useParams();\n const [collapsed, setCollapsed] = useState(false);\n const [contextSwitcherOpen, setContextSwitcherOpen] = useState(false);\n const [contextSearch, setContextSearch] = useState('');\n const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set());\n const { t } = useTranslation('shell');\n const { selectedOrganization, selectedBranch } = useOrganization();\n\n const { app, sidebar } = config;\n\n // Determine if we're in context mode (e.g., inside a project)\n const contextParamValue = sidebar.contextMenu\n ? params[sidebar.contextMenu.paramName] as string | undefined\n : undefined;\n const isInContext = !!contextParamValue;\n\n const isActive = (path: string) => {\n return location.pathname === path || location.pathname.startsWith(path + '/');\n };\n\n const renderMenuItem = (item: SidebarMenuItem, active: boolean) => {\n const Icon = item.icon;\n const path = item.path!;\n const content = (\n <Link\n to={path}\n className={`flex items-center ${collapsed ? 'justify-center' : 'gap-2'} px-3 py-2 rounded-md text-sm transition-colors ${\n active\n ? 'bg-blue-50 text-blue-600 dark:bg-blue-500/15 dark:text-blue-400 font-medium'\n : 'text-sidebar-foreground hover:bg-sidebar-accent'\n }`}\n >\n <Icon className=\"w-4 h-4 flex-shrink-0\" />\n {!collapsed && <span>{item.label}</span>}\n {!collapsed && item.badge !== undefined && item.badge > 0 && (\n <span className=\"ml-auto text-xs bg-muted text-muted-foreground px-1.5 py-0.5 rounded-full\">\n {item.badge}\n </span>\n )}\n </Link>\n );\n\n if (collapsed) {\n return (\n <TooltipProvider key={path} delayDuration={0}>\n <Tooltip>\n <TooltipTrigger asChild>\n {content}\n </TooltipTrigger>\n <TooltipContent side=\"right\" className=\"font-medium\">\n {item.label}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n }\n\n return <div key={path}>{content}</div>;\n };\n\n const isGroupActive = (item: SidebarMenuItem): boolean => {\n if (item.children) {\n return item.children.some(child => child.path ? isActive(child.path) : false);\n }\n return item.path ? isActive(item.path) : false;\n };\n\n const toggleGroup = (label: string) => {\n setExpandedGroups(prev => {\n const next = new Set(prev);\n if (next.has(label)) {\n next.delete(label);\n } else {\n next.add(label);\n }\n return next;\n });\n };\n\n const renderMenuItemOrGroup = (item: SidebarMenuItem) => {\n if (!item.children) {\n return renderMenuItem(item, item.path ? isActive(item.path) : false);\n }\n\n const groupActive = isGroupActive(item);\n const isExpanded = expandedGroups.has(item.label) || groupActive;\n const Icon = item.icon;\n\n if (collapsed) {\n return (\n <TooltipProvider key={item.label} delayDuration={0}>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={() => toggleGroup(item.label)}\n className={`flex items-center justify-center w-full px-3 py-2 rounded-md text-sm transition-colors ${\n groupActive\n ? 'bg-blue-50 text-blue-600 dark:bg-blue-500/15 dark:text-blue-400 font-medium'\n : 'text-sidebar-foreground hover:bg-sidebar-accent'\n }`}\n >\n <Icon className=\"w-4 h-4 flex-shrink-0\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"right\" className=\"font-medium\">\n {item.label}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n }\n\n return (\n <div key={item.label}>\n <button\n onClick={() => toggleGroup(item.label)}\n className={`flex items-center gap-2 w-full px-3 py-2 rounded-md text-sm transition-colors ${\n groupActive\n ? 'text-blue-600 dark:text-blue-400 font-medium'\n : 'text-sidebar-foreground hover:bg-sidebar-accent'\n }`}\n >\n <Icon className=\"w-4 h-4 flex-shrink-0\" />\n <span>{item.label}</span>\n <ChevronRight className={`w-3.5 h-3.5 ml-auto text-muted-foreground transition-transform duration-200 ${isExpanded ? 'rotate-90' : ''}`} />\n </button>\n {isExpanded && (\n <div className=\"ml-4 pl-2 border-l border-sidebar-border space-y-0.5 mt-0.5\">\n {item.children.map(child => renderMenuItem(child, child.path ? isActive(child.path) : false))}\n </div>\n )}\n </div>\n );\n };\n\n // Get context menu items if in context mode\n const contextMenuItems = isInContext && sidebar.contextMenu\n ? sidebar.contextMenu.getItems(contextParamValue!)\n : [];\n\n const contextHeader = isInContext && sidebar.contextMenu?.getHeader\n ? sidebar.contextMenu.getHeader(contextParamValue!)\n : null;\n\n const footerItems = isInContext && sidebar.contextMenu?.getFooterItems\n ? sidebar.contextMenu.getFooterItems()\n : [];\n\n return (\n <aside className={`${collapsed ? 'w-16' : 'w-64'} bg-sidebar border-r border-sidebar-border flex flex-col transition-all duration-300`}>\n {/* Logo */}\n <div className={`h-header border-b border-sidebar-border flex items-center ${collapsed ? 'justify-center' : 'px-4'} transition-all duration-300`}>\n <Link to=\"/\" className=\"flex items-center gap-2\">\n <div className={`w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0 ${app.logo.color ? '' : 'bg-blue-600'}`} style={app.logo.color ? { backgroundColor: app.logo.color } : undefined}>\n <app.logo.icon className=\"w-4 h-4 text-white\" />\n </div>\n {!collapsed && <span className=\"font-bold text-sm\">{app.logo.text}</span>}\n </Link>\n </div>\n\n {/* Menu */}\n <nav className=\"flex-1 px-3 py-3 overflow-y-auto\">\n {isInContext ? (\n <>\n {/* Context Switcher (e.g., project switcher) */}\n {contextHeader && !collapsed ? (\n <Popover open={contextSwitcherOpen} onOpenChange={(open) => { setContextSwitcherOpen(open); if (!open) setContextSearch(''); }}>\n <PopoverTrigger asChild>\n <button className=\"w-full mb-3 px-3 py-2 flex items-center gap-2 rounded-md hover:bg-sidebar-accent transition-colors text-left\">\n {contextHeader}\n <ChevronsUpDown className=\"w-3.5 h-3.5 text-muted-foreground flex-shrink-0\" />\n </button>\n </PopoverTrigger>\n <PopoverContent side=\"right\" align=\"start\" className=\"w-72 p-0\">\n <div className=\"p-2 border-b\">\n <div className=\"relative\">\n <Search className=\"absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground\" />\n <input\n className=\"w-full pl-8 pr-3 py-1.5 text-sm border rounded-md outline-none focus:ring-1 focus:ring-blue-500 bg-background\"\n placeholder={t('sidebar.searchProject')}\n value={contextSearch}\n onChange={(e) => setContextSearch(e.target.value)}\n autoFocus\n />\n </div>\n </div>\n </PopoverContent>\n </Popover>\n ) : contextHeader && collapsed ? (\n <div className=\"mb-3 w-full flex justify-center py-1 rounded-md hover:bg-sidebar-accent transition-colors\">\n {contextHeader}\n </div>\n ) : null}\n\n {!collapsed && contextHeader && <Separator className=\"my-3\" />}\n\n {/* Context Menu Items */}\n <div className=\"space-y-1\">\n {contextMenuItems.map((item) => {\n const active = item.path ? isActive(item.path) : false;\n return renderMenuItem(item, active);\n })}\n </div>\n\n {footerItems.length > 0 && (\n <>\n {!collapsed && <Separator className=\"my-3\" />}\n <div className=\"space-y-1\">\n {footerItems.map((item) => renderMenuItem(item, false))}\n </div>\n </>\n )}\n </>\n ) : (\n <>\n {/* Main Menu Items */}\n <div className=\"space-y-1\">\n {sidebar.menuItems.map((item) => renderMenuItemOrGroup(item))}\n </div>\n\n {sidebar.recentItems && (\n <>\n {!collapsed && <Separator className=\"my-3\" />}\n\n {!collapsed ? (\n <div className=\"space-y-1\">\n <h3 className=\"px-3 py-1 text-xs font-medium text-muted-foreground uppercase tracking-wider\">\n {sidebar.recentItems.title}\n </h3>\n <div className=\"space-y-0.5\">\n {sidebar.recentItems.items.map((item) => (\n <Link\n key={item.path}\n to={item.path}\n className=\"flex items-center gap-2 px-3 py-2 rounded-md text-sm text-sidebar-foreground hover:bg-sidebar-accent\"\n >\n {item.color && (\n <div\n className=\"w-5 h-5 rounded flex items-center justify-center text-white text-[9px] font-bold flex-shrink-0\"\n style={{ backgroundColor: item.color }}\n >\n {item.badge}\n </div>\n )}\n <span className=\"truncate\">{item.label}</span>\n </Link>\n ))}\n </div>\n </div>\n ) : (\n <div className=\"space-y-0.5 mt-3\">\n {sidebar.recentItems.items.map((item) => (\n <TooltipProvider key={item.path} delayDuration={0}>\n <Tooltip>\n <TooltipTrigger asChild>\n <Link\n to={item.path}\n className=\"flex justify-center px-3 py-2 rounded-md text-sidebar-foreground hover:bg-sidebar-accent\"\n >\n {item.color && (\n <div\n className=\"w-5 h-5 rounded flex items-center justify-center text-white text-[9px] font-bold\"\n style={{ backgroundColor: item.color }}\n >\n {item.badge}\n </div>\n )}\n </Link>\n </TooltipTrigger>\n <TooltipContent side=\"right\">\n <p className=\"font-medium text-sm\">{item.label}</p>\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n ))}\n </div>\n )}\n </>\n )}\n </>\n )}\n </nav>\n\n {/* Collapse Toggle Button */}\n <div className=\"px-3 py-2 border-t border-sidebar-border\">\n <TooltipProvider delayDuration={0}>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setCollapsed(!collapsed)}\n className={`w-full h-8 ${collapsed ? 'px-0 justify-center' : 'justify-start'} hover:bg-sidebar-accent`}\n >\n {collapsed ? (\n <ChevronsRight className=\"w-3.5 h-3.5 text-muted-foreground\" />\n ) : (\n <>\n <ChevronsLeft className=\"w-3.5 h-3.5 text-muted-foreground mr-2\" />\n <span className=\"text-xs text-muted-foreground\">{t('sidebar.collapse')}</span>\n </>\n )}\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"right\">\n {collapsed ? t('sidebar.expandSidebar') : t('sidebar.collapseSidebar')}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n </div>\n\n {/* Organization & Branch selector */}\n {!collapsed ? (\n <div className=\"border-t border-sidebar-border\">\n <OrganizationSelector variant=\"sidebar\" />\n </div>\n ) : (\n selectedOrganization && (\n <TooltipProvider delayDuration={0}>\n <Tooltip>\n <TooltipTrigger asChild>\n <div className=\"px-3 py-3 border-t border-sidebar-border flex justify-center cursor-pointer hover:bg-sidebar-accent transition-colors\">\n <div\n className=\"w-8 h-8 rounded-lg flex items-center justify-center text-white font-bold text-xs\"\n style={{ backgroundColor: selectedOrganization.color }}\n >\n {selectedOrganization.shortName}\n </div>\n </div>\n </TooltipTrigger>\n <TooltipContent side=\"right\">\n <p className=\"font-semibold text-sm\">{selectedOrganization.name}</p>\n {selectedBranch && (\n <p className=\"text-xs text-muted-foreground\">{selectedBranch.name}</p>\n )}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )\n )}\n </aside>\n );\n}\n"]}
@@ -0,0 +1,27 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ import { ShellConfig } from '../types.js';
4
+ import 'lucide-react';
5
+
6
+ interface AppShellProps {
7
+ config: ShellConfig;
8
+ /** Extra content to render alongside the main content (e.g., ChatWidget) */
9
+ extra?: ReactNode;
10
+ }
11
+ /**
12
+ * The main application shell.
13
+ * Use as a route layout element in React Router:
14
+ *
15
+ * ```tsx
16
+ * const router = createBrowserRouter([{
17
+ * path: '/',
18
+ * element: <AppShell config={config} />,
19
+ * children: [
20
+ * { index: true, element: <Dashboard /> },
21
+ * ],
22
+ * }]);
23
+ * ```
24
+ */
25
+ declare function AppShell({ config, extra }: AppShellProps): react_jsx_runtime.JSX.Element;
26
+
27
+ export { AppShell };
@@ -0,0 +1,11 @@
1
+ export { AppShell } from '../chunk-OYE3TXTK.js';
2
+ import '../chunk-EJEVW4RO.js';
3
+ import '../chunk-OMIE3Z5N.js';
4
+ import '../chunk-YVUVYTVZ.js';
5
+ import '../chunk-Q3QWQG6P.js';
6
+ import '../chunk-ACCHC3AM.js';
7
+ import '../chunk-WCRLQ5M5.js';
8
+ import '../chunk-QNCYBLHC.js';
9
+ import '../chunk-SHHZRZMM.js';
10
+ //# sourceMappingURL=AppShell.js.map
11
+ //# sourceMappingURL=AppShell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"AppShell.js"}
@@ -0,0 +1,11 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ShellConfig } from '../types.js';
3
+ import 'react';
4
+ import 'lucide-react';
5
+
6
+ interface HeaderProps {
7
+ config: ShellConfig;
8
+ }
9
+ declare function Header({ config }: HeaderProps): react_jsx_runtime.JSX.Element;
10
+
11
+ export { Header };