gov-layout 1.0.0 → 1.1.0

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.mjs CHANGED
@@ -1,8 +1,39 @@
1
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
1
  import { useState, useRef, useEffect } from 'react';
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
 
4
- // src/sidebar/SidebarHeader.tsx
5
- function SidebarHeader({ orgLogo, orgName, orgSubtitle }) {
4
+ // src/sidebar/StaffSidebar.tsx
5
+ function SidebarHeader({ orgLogo, orgName, orgSubtitle, collapsed }) {
6
+ if (collapsed) {
7
+ return /* @__PURE__ */ jsx("div", { style: {
8
+ display: "flex",
9
+ alignItems: "center",
10
+ justifyContent: "center",
11
+ padding: "20px 8px"
12
+ }, children: orgLogo ? /* @__PURE__ */ jsx(
13
+ "img",
14
+ {
15
+ src: orgLogo,
16
+ alt: orgName,
17
+ style: {
18
+ width: "36px",
19
+ height: "36px",
20
+ borderRadius: "50%",
21
+ objectFit: "cover"
22
+ }
23
+ }
24
+ ) : /* @__PURE__ */ jsx("div", { style: {
25
+ width: "36px",
26
+ height: "36px",
27
+ borderRadius: "50%",
28
+ background: "var(--color-alias-color-brand-primary, #1e7d55)",
29
+ display: "flex",
30
+ alignItems: "center",
31
+ justifyContent: "center",
32
+ color: "#fff",
33
+ fontWeight: 700,
34
+ fontSize: "14px"
35
+ }, children: orgName.charAt(0) }) });
36
+ }
6
37
  return /* @__PURE__ */ jsxs("div", { style: {
7
38
  display: "flex",
8
39
  alignItems: "center",
@@ -50,8 +81,8 @@ function ChevronDownIcon({ isOpen }) {
50
81
  return /* @__PURE__ */ jsx(
51
82
  "svg",
52
83
  {
53
- width: "20",
54
- height: "20",
84
+ width: "16",
85
+ height: "16",
55
86
  viewBox: "0 0 20 20",
56
87
  fill: "none",
57
88
  stroke: "currentColor",
@@ -71,7 +102,8 @@ function MenuItemComponent({
71
102
  item,
72
103
  onItemClick,
73
104
  currentPath,
74
- depth = 0
105
+ depth = 0,
106
+ collapsed = false
75
107
  }) {
76
108
  const [isOpen, setIsOpen] = useState(false);
77
109
  const hasChildren = item.children && item.children.length > 0;
@@ -87,20 +119,58 @@ function MenuItemComponent({
87
119
  };
88
120
  const activeColor = "var(--color-alias-color-brand-primary, #1e7d55)";
89
121
  const hoverBg = "var(--color-foundations-fuji-pallet-light, #ebedf5)";
122
+ if (collapsed && depth === 0) {
123
+ return /* @__PURE__ */ jsxs("li", { children: [
124
+ /* @__PURE__ */ jsx(
125
+ "button",
126
+ {
127
+ onClick: handleClick,
128
+ title: item.title,
129
+ onMouseEnter: (e) => {
130
+ if (!isActive) e.currentTarget.style.backgroundColor = hoverBg;
131
+ },
132
+ onMouseLeave: (e) => {
133
+ if (!isActive) e.currentTarget.style.backgroundColor = "transparent";
134
+ },
135
+ style: {
136
+ width: "100%",
137
+ display: "flex",
138
+ alignItems: "center",
139
+ justifyContent: "center",
140
+ padding: "12px 0",
141
+ borderRadius: "8px",
142
+ border: "none",
143
+ background: isActive || isChildActive ? `color-mix(in srgb, ${activeColor} 10%, transparent)` : "transparent",
144
+ color: isActive || isChildActive ? activeColor : "var(--color-alias-text-colors-tertiary, #475272)",
145
+ cursor: "pointer",
146
+ transition: "background-color 0.15s ease"
147
+ },
148
+ children: item.icon && /* @__PURE__ */ jsx("span", { style: {
149
+ width: "24px",
150
+ height: "24px",
151
+ display: "flex",
152
+ alignItems: "center",
153
+ justifyContent: "center"
154
+ }, children: item.icon })
155
+ }
156
+ ),
157
+ item.dividerAfter && /* @__PURE__ */ jsx("hr", { style: {
158
+ border: "none",
159
+ borderTop: "1px solid var(--color-border-colors-neutral, #c8cedd)",
160
+ margin: "8px 4px"
161
+ } })
162
+ ] });
163
+ }
90
164
  return /* @__PURE__ */ jsxs(Fragment, { children: [
91
165
  /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
92
166
  "button",
93
167
  {
94
168
  onClick: handleClick,
95
169
  onMouseEnter: (e) => {
96
- if (!isActive) {
97
- e.currentTarget.style.backgroundColor = hoverBg;
98
- }
170
+ if (!isActive) e.currentTarget.style.backgroundColor = hoverBg;
99
171
  },
100
172
  onMouseLeave: (e) => {
101
- if (!isActive) {
102
- e.currentTarget.style.backgroundColor = "transparent";
103
- }
173
+ if (!isActive) e.currentTarget.style.backgroundColor = "transparent";
104
174
  },
105
175
  style: {
106
176
  width: "100%",
@@ -120,21 +190,15 @@ function MenuItemComponent({
120
190
  lineHeight: "22px"
121
191
  },
122
192
  children: [
123
- item.icon && /* @__PURE__ */ jsx(
124
- "span",
125
- {
126
- style: {
127
- width: "24px",
128
- height: "24px",
129
- display: "flex",
130
- alignItems: "center",
131
- justifyContent: "center",
132
- flexShrink: 0,
133
- color: isActive ? activeColor : "var(--color-alias-text-colors-tertiary, #475272)"
134
- },
135
- children: item.icon
136
- }
137
- ),
193
+ item.icon && /* @__PURE__ */ jsx("span", { style: {
194
+ width: "24px",
195
+ height: "24px",
196
+ display: "flex",
197
+ alignItems: "center",
198
+ justifyContent: "center",
199
+ flexShrink: 0,
200
+ color: isActive ? activeColor : "var(--color-alias-text-colors-tertiary, #475272)"
201
+ }, children: item.icon }),
138
202
  /* @__PURE__ */ jsx("span", { style: { flex: 1 }, children: item.title }),
139
203
  hasChildren && /* @__PURE__ */ jsx(ChevronDownIcon, { isOpen: expanded })
140
204
  ]
@@ -150,25 +214,32 @@ function MenuItemComponent({
150
214
  },
151
215
  child.id
152
216
  )) }),
153
- item.dividerAfter && /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
154
- "hr",
155
- {
156
- style: {
157
- border: "none",
158
- borderTop: "1px solid var(--color-border-colors-neutral, #c8cedd)",
159
- margin: "8px 0"
160
- }
161
- }
162
- ) })
217
+ item.dividerAfter && /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("hr", { style: {
218
+ border: "none",
219
+ borderTop: "1px solid var(--color-border-colors-neutral, #c8cedd)",
220
+ margin: "8px 0"
221
+ } }) })
163
222
  ] });
164
223
  }
165
- function SidebarMenu({ menuItems, onItemClick, currentPath }) {
166
- return /* @__PURE__ */ jsx("nav", { style: { flex: 1, padding: "8px 12px", overflowY: "auto" }, children: /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: "2px" }, children: menuItems.map((item) => /* @__PURE__ */ jsx(
224
+ function SidebarMenu({ menuItems, onItemClick, currentPath, collapsed }) {
225
+ return /* @__PURE__ */ jsx("nav", { style: {
226
+ flex: collapsed ? void 0 : 1,
227
+ padding: collapsed ? "8px 8px" : "8px 12px",
228
+ overflowY: "auto"
229
+ }, children: /* @__PURE__ */ jsx("ul", { style: {
230
+ listStyle: "none",
231
+ margin: 0,
232
+ padding: 0,
233
+ display: "flex",
234
+ flexDirection: "column",
235
+ gap: "2px"
236
+ }, children: menuItems.map((item) => /* @__PURE__ */ jsx(
167
237
  MenuItemComponent,
168
238
  {
169
239
  item,
170
240
  onItemClick,
171
- currentPath
241
+ currentPath,
242
+ collapsed
172
243
  },
173
244
  item.id
174
245
  )) }) });
@@ -196,7 +267,8 @@ function LogoutIcon() {
196
267
  function SidebarUserProfile({
197
268
  user,
198
269
  roleLabel,
199
- onLogout
270
+ onLogout,
271
+ collapsed
200
272
  }) {
201
273
  if (!user) return null;
202
274
  const getFullName = () => {
@@ -208,6 +280,76 @@ function SidebarUserProfile({
208
280
  const getInitial = () => {
209
281
  return user.firstName?.charAt(0) || user.lastName?.charAt(0) || "?";
210
282
  };
283
+ if (collapsed) {
284
+ return /* @__PURE__ */ jsxs("div", { style: {
285
+ padding: "12px 8px",
286
+ borderTop: "1px solid var(--color-border-colors-neutral, #c8cedd)",
287
+ display: "flex",
288
+ flexDirection: "column",
289
+ alignItems: "center",
290
+ gap: "12px"
291
+ }, children: [
292
+ user.pictureUrl ? /* @__PURE__ */ jsx(
293
+ "img",
294
+ {
295
+ src: user.pictureUrl,
296
+ alt: getFullName(),
297
+ title: getFullName(),
298
+ style: {
299
+ width: "36px",
300
+ height: "36px",
301
+ borderRadius: "50%",
302
+ objectFit: "cover"
303
+ }
304
+ }
305
+ ) : /* @__PURE__ */ jsx(
306
+ "div",
307
+ {
308
+ title: getFullName(),
309
+ style: {
310
+ width: "36px",
311
+ height: "36px",
312
+ borderRadius: "50%",
313
+ background: "var(--color-alias-color-brand-primary, #1e7d55)",
314
+ display: "flex",
315
+ alignItems: "center",
316
+ justifyContent: "center",
317
+ color: "#fff",
318
+ fontWeight: 700,
319
+ fontSize: "14px"
320
+ },
321
+ children: getInitial()
322
+ }
323
+ ),
324
+ /* @__PURE__ */ jsx(
325
+ "button",
326
+ {
327
+ onClick: onLogout,
328
+ title: "\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A",
329
+ onMouseEnter: (e) => {
330
+ e.currentTarget.style.backgroundColor = "var(--color-foundations-fuan-pallet-light, #ffd2d2)";
331
+ },
332
+ onMouseLeave: (e) => {
333
+ e.currentTarget.style.backgroundColor = "transparent";
334
+ },
335
+ style: {
336
+ width: "36px",
337
+ height: "36px",
338
+ borderRadius: "8px",
339
+ border: "none",
340
+ background: "transparent",
341
+ color: "var(--color-alias-semantic-critical, #f21515)",
342
+ cursor: "pointer",
343
+ display: "flex",
344
+ alignItems: "center",
345
+ justifyContent: "center",
346
+ transition: "background-color 0.15s ease"
347
+ },
348
+ children: /* @__PURE__ */ jsx(LogoutIcon, {})
349
+ }
350
+ )
351
+ ] });
352
+ }
211
353
  return /* @__PURE__ */ jsxs(
212
354
  "div",
213
355
  {
@@ -252,34 +394,22 @@ function SidebarUserProfile({
252
394
  }
253
395
  ),
254
396
  /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
255
- /* @__PURE__ */ jsx(
256
- "p",
257
- {
258
- style: {
259
- fontWeight: 600,
260
- fontSize: "14px",
261
- lineHeight: "20px",
262
- color: "var(--color-alias-text-colors-primary, #060d26)",
263
- margin: 0,
264
- overflow: "hidden",
265
- textOverflow: "ellipsis",
266
- whiteSpace: "nowrap"
267
- },
268
- children: getFullName()
269
- }
270
- ),
271
- /* @__PURE__ */ jsx(
272
- "p",
273
- {
274
- style: {
275
- fontSize: "12px",
276
- lineHeight: "16px",
277
- color: "var(--color-alias-text-colors-tertiary, #475272)",
278
- margin: 0
279
- },
280
- children: roleLabel
281
- }
282
- )
397
+ /* @__PURE__ */ jsx("p", { style: {
398
+ fontWeight: 600,
399
+ fontSize: "14px",
400
+ lineHeight: "20px",
401
+ color: "var(--color-alias-text-colors-primary, #060d26)",
402
+ margin: 0,
403
+ overflow: "hidden",
404
+ textOverflow: "ellipsis",
405
+ whiteSpace: "nowrap"
406
+ }, children: getFullName() }),
407
+ /* @__PURE__ */ jsx("p", { style: {
408
+ fontSize: "12px",
409
+ lineHeight: "16px",
410
+ color: "var(--color-alias-text-colors-tertiary, #475272)",
411
+ margin: 0
412
+ }, children: roleLabel })
283
413
  ] }),
284
414
  /* @__PURE__ */ jsx(
285
415
  "button",
@@ -315,6 +445,26 @@ function SidebarUserProfile({
315
445
  }
316
446
  );
317
447
  }
448
+ function ToggleIcon({ isOpen }) {
449
+ return /* @__PURE__ */ jsx(
450
+ "svg",
451
+ {
452
+ width: "18",
453
+ height: "18",
454
+ viewBox: "0 0 24 24",
455
+ fill: "none",
456
+ stroke: "currentColor",
457
+ strokeWidth: "2",
458
+ strokeLinecap: "round",
459
+ strokeLinejoin: "round",
460
+ style: {
461
+ transition: "transform 0.2s ease",
462
+ transform: isOpen ? "rotate(0deg)" : "rotate(180deg)"
463
+ },
464
+ children: /* @__PURE__ */ jsx("path", { d: "M15 18l-6-6 6-6" })
465
+ }
466
+ );
467
+ }
318
468
  function StaffSidebar({
319
469
  orgLogo,
320
470
  orgName,
@@ -327,61 +477,117 @@ function StaffSidebar({
327
477
  onLogout,
328
478
  currentPath,
329
479
  width = "280px",
330
- className
480
+ className,
481
+ collapsible = false,
482
+ isOpen: controlledIsOpen,
483
+ onToggle
331
484
  }) {
332
- return /* @__PURE__ */ jsxs(
333
- "aside",
334
- {
335
- className,
336
- style: {
337
- position: "fixed",
338
- top: 0,
339
- left: 0,
340
- height: "100vh",
341
- width,
342
- background: "#fff",
343
- borderRight: "1px solid var(--color-border-colors-neutral, #c8cedd)",
344
- display: "flex",
345
- flexDirection: "column",
346
- zIndex: 40,
347
- overflow: "hidden"
348
- },
349
- children: [
350
- /* @__PURE__ */ jsx(
351
- SidebarHeader,
352
- {
353
- orgLogo,
354
- orgName,
355
- orgSubtitle
356
- }
357
- ),
358
- /* @__PURE__ */ jsx(
359
- SidebarMenu,
360
- {
361
- menuItems,
362
- onItemClick: onNavigate,
363
- currentPath
364
- }
365
- ),
366
- bottomMenuItems && bottomMenuItems.length > 0 && /* @__PURE__ */ jsx(
367
- SidebarMenu,
368
- {
369
- menuItems: bottomMenuItems,
370
- onItemClick: onNavigate,
371
- currentPath
372
- }
373
- ),
374
- /* @__PURE__ */ jsx(
375
- SidebarUserProfile,
376
- {
377
- user,
378
- roleLabel,
379
- onLogout
380
- }
381
- )
382
- ]
485
+ const [internalOpen, setInternalOpen] = useState(true);
486
+ const sidebarOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalOpen;
487
+ const collapsed = collapsible && !sidebarOpen;
488
+ const collapsedWidth = "64px";
489
+ const currentWidth = collapsed ? collapsedWidth : width;
490
+ const handleToggle = () => {
491
+ if (onToggle) {
492
+ onToggle();
493
+ } else {
494
+ setInternalOpen(!internalOpen);
383
495
  }
384
- );
496
+ };
497
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
498
+ /* @__PURE__ */ jsxs(
499
+ "aside",
500
+ {
501
+ className,
502
+ style: {
503
+ position: "fixed",
504
+ top: 0,
505
+ left: 0,
506
+ height: "100vh",
507
+ width: currentWidth,
508
+ background: "#fff",
509
+ borderRight: "1px solid var(--color-border-colors-neutral, #c8cedd)",
510
+ display: "flex",
511
+ flexDirection: "column",
512
+ zIndex: 40,
513
+ overflow: "hidden",
514
+ transition: "width 0.3s ease"
515
+ },
516
+ children: [
517
+ /* @__PURE__ */ jsx(
518
+ SidebarHeader,
519
+ {
520
+ orgLogo,
521
+ orgName,
522
+ orgSubtitle,
523
+ collapsed
524
+ }
525
+ ),
526
+ /* @__PURE__ */ jsx(
527
+ SidebarMenu,
528
+ {
529
+ menuItems,
530
+ onItemClick: onNavigate,
531
+ currentPath,
532
+ collapsed
533
+ }
534
+ ),
535
+ bottomMenuItems && bottomMenuItems.length > 0 && /* @__PURE__ */ jsx(
536
+ SidebarMenu,
537
+ {
538
+ menuItems: bottomMenuItems,
539
+ onItemClick: onNavigate,
540
+ currentPath,
541
+ collapsed
542
+ }
543
+ ),
544
+ /* @__PURE__ */ jsx(
545
+ SidebarUserProfile,
546
+ {
547
+ user,
548
+ roleLabel,
549
+ onLogout,
550
+ collapsed
551
+ }
552
+ )
553
+ ]
554
+ }
555
+ ),
556
+ collapsible && /* @__PURE__ */ jsx(
557
+ "button",
558
+ {
559
+ onClick: handleToggle,
560
+ title: sidebarOpen ? "\u0E22\u0E48\u0E2D Sidebar" : "\u0E02\u0E22\u0E32\u0E22 Sidebar",
561
+ onMouseEnter: (e) => {
562
+ e.currentTarget.style.backgroundColor = "#f3f4f6";
563
+ },
564
+ onMouseLeave: (e) => {
565
+ e.currentTarget.style.backgroundColor = "#fff";
566
+ },
567
+ style: {
568
+ position: "fixed",
569
+ top: "50%",
570
+ left: currentWidth,
571
+ transform: "translateY(-50%)",
572
+ zIndex: 41,
573
+ width: "24px",
574
+ height: "48px",
575
+ borderRadius: "0 6px 6px 0",
576
+ border: "1px solid var(--color-border-colors-neutral, #c8cedd)",
577
+ borderLeft: "none",
578
+ background: "#fff",
579
+ cursor: "pointer",
580
+ display: "flex",
581
+ alignItems: "center",
582
+ justifyContent: "center",
583
+ boxShadow: "2px 0 8px rgba(0,0,0,0.06)",
584
+ transition: "left 0.3s ease",
585
+ color: "var(--color-alias-text-colors-tertiary, #475272)"
586
+ },
587
+ children: /* @__PURE__ */ jsx(ToggleIcon, { isOpen: sidebarOpen })
588
+ }
589
+ )
590
+ ] });
385
591
  }
386
592
  function BellIcon() {
387
593
  return /* @__PURE__ */ jsx("svg", { width: "22", height: "24", viewBox: "0 0 22 24", fill: "none", children: /* @__PURE__ */ jsx(
@@ -956,64 +1162,13 @@ function UserSidebar({
956
1162
  ] })
957
1163
  }
958
1164
  ),
959
- /* @__PURE__ */ jsx("nav", { style: { flex: 1, padding: "20px", overflowY: "auto" }, children: /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: "4px" }, children: menuItems.map((item) => /* @__PURE__ */ jsxs("li", { children: [
960
- /* @__PURE__ */ jsxs(
961
- "button",
962
- {
963
- onClick: () => item.path && handleMenuClick(item.path),
964
- onMouseEnter: (e) => {
965
- e.currentTarget.style.backgroundColor = "#f9fafb";
966
- },
967
- onMouseLeave: (e) => {
968
- e.currentTarget.style.backgroundColor = "transparent";
969
- },
970
- style: {
971
- width: "100%",
972
- display: "flex",
973
- alignItems: "center",
974
- gap: "16px",
975
- padding: "14px 16px",
976
- borderRadius: "8px",
977
- border: "none",
978
- background: "transparent",
979
- color: "var(--color-alias-text-colors-primary, #374151)",
980
- cursor: "pointer",
981
- transition: "background-color 0.15s ease",
982
- fontSize: "15px",
983
- fontWeight: 500,
984
- textAlign: "left"
985
- },
986
- children: [
987
- item.icon && /* @__PURE__ */ jsx(
988
- "span",
989
- {
990
- style: {
991
- width: "28px",
992
- height: "28px",
993
- display: "flex",
994
- alignItems: "center",
995
- justifyContent: "center",
996
- color: "var(--color-alias-text-colors-tertiary, #6b7280)",
997
- flexShrink: 0
998
- },
999
- children: item.icon
1000
- }
1001
- ),
1002
- /* @__PURE__ */ jsx("span", { style: { flex: 1 }, children: item.title })
1003
- ]
1004
- }
1005
- ),
1006
- item.dividerAfter && /* @__PURE__ */ jsx(
1007
- "hr",
1008
- {
1009
- style: {
1010
- border: "none",
1011
- borderTop: "1px solid var(--color-border-colors-neutral, #e5e7eb)",
1012
- margin: "8px 0"
1013
- }
1014
- }
1015
- )
1016
- ] }, item.id)) }) }),
1165
+ /* @__PURE__ */ jsx(
1166
+ SidebarMenu,
1167
+ {
1168
+ menuItems,
1169
+ onItemClick: handleMenuClick
1170
+ }
1171
+ ),
1017
1172
  /* @__PURE__ */ jsx(
1018
1173
  "div",
1019
1174
  {