@sikka/hawa 0.1.17 → 0.1.20

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 (38) hide show
  1. package/README.md +2 -16
  2. package/dist/styles.css +78 -3
  3. package/es/elements/Button.d.ts +1 -1
  4. package/es/elements/HawaRadio.d.ts +1 -0
  5. package/es/elements/InterfaceSettings.d.ts +2 -0
  6. package/es/elements/Popover.d.ts +1 -0
  7. package/es/index.es.js +3 -3
  8. package/es/layout/AppLayout.d.ts +49 -0
  9. package/es/layout/Sidebar.d.ts +36 -0
  10. package/es/layout/Sidebar2.d.ts +20 -0
  11. package/es/layout/index.d.ts +2 -0
  12. package/lib/elements/Button.d.ts +1 -1
  13. package/lib/elements/HawaRadio.d.ts +1 -0
  14. package/lib/elements/InterfaceSettings.d.ts +2 -0
  15. package/lib/elements/Popover.d.ts +1 -0
  16. package/lib/index.js +3 -3
  17. package/lib/layout/AppLayout.d.ts +49 -0
  18. package/lib/layout/Sidebar.d.ts +36 -0
  19. package/lib/layout/Sidebar2.d.ts +20 -0
  20. package/lib/layout/index.d.ts +2 -0
  21. package/package.json +2 -1
  22. package/src/blocks/AuthForms/SignInBlock.tsx +0 -2
  23. package/src/blocks/AuthForms/SignInForm.tsx +1 -1
  24. package/src/elements/Button.tsx +1 -0
  25. package/src/elements/DropdownMenu.tsx +0 -2
  26. package/src/elements/HawaRadio.tsx +8 -2
  27. package/src/elements/InterfaceSettings.tsx +15 -2
  28. package/src/elements/Label.tsx +0 -2
  29. package/src/elements/Popover.tsx +28 -22
  30. package/src/elements/Select.tsx +0 -2
  31. package/src/elements/Tooltip.tsx +1 -106
  32. package/src/layout/AppLayout.tsx +445 -0
  33. package/src/layout/HawaAppLayoutSimplified.tsx +78 -98
  34. package/src/layout/Sidebar.tsx +224 -0
  35. package/src/layout/Sidebar2.tsx +77 -0
  36. package/src/layout/index.ts +3 -0
  37. package/src/styles.css +78 -3
  38. package/tailwind.config.js +20 -1
@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react"
2
2
  import clsx from "clsx"
3
3
  import useDiscloser from "../hooks/useDiscloser"
4
4
  import useBreakpoint from "../hooks/useBreakpoint"
5
- import { Button, DropdownMenu, HawaMenu, Tooltip } from "../elements"
5
+ import { Button, DropdownMenu, Tooltip } from "../elements"
6
6
 
7
7
  type HawaAppLayoutTypes = {
8
8
  /** The pages of the side drawer */
@@ -39,19 +39,13 @@ type SubItem = {
39
39
  value: string
40
40
  highlighted?: boolean
41
41
  }
42
-
43
42
  type Item = {
44
43
  label: string
45
44
  value: string
46
45
  highlighted?: boolean
47
46
  subitems?: SubItem[] // Note the use of the optional modifier
48
47
  }
49
- // type MenuItems = {
50
- // icon?: JSX.Element
51
- // label: string
52
- // action?: (e: any) => void
53
- // isButton?: boolean
54
- // }
48
+
55
49
  export const HawaAppLayoutSimplified: React.FunctionComponent<
56
50
  HawaAppLayoutTypes
57
51
  > = ({
@@ -195,18 +189,6 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
195
189
  </div>
196
190
  ) : null}
197
191
  {/* Profile Icon & Menu */}
198
- {/* <HawaMenu
199
- direction={direction}
200
- withHeader={size > 600 ? false : true}
201
- headerTitle={size > 600 ? "" : props.username}
202
- headerSubtitle={size > 600 ? "" : props.email}
203
- menuItems={props.profileMenuItems}
204
- position={"bottom-left"}
205
- >
206
- <div className="relative mx-2 h-8 w-8 cursor-pointer overflow-hidden rounded-full ring-1 ring-buttonPrimary-500 dark:bg-gray-600">
207
- <AvatarIcon />
208
- </div>
209
- </HawaMenu> */}
210
192
  <DropdownMenu
211
193
  triggerClassname="mx-2"
212
194
  align="end"
@@ -221,11 +203,15 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
221
203
  }
222
204
  items={props.profileMenuItems}
223
205
  onItemSelect={(e) => console.log("selecting item ", e)}
224
- />{" "}
206
+ />
225
207
  </div>
226
208
  </div>
227
209
  )}
228
- {/* Drawer Container */}
210
+ {/*
211
+ * ----------------------------------------------------------------------------------------------------
212
+ * Drawer Container
213
+ * ----------------------------------------------------------------------------------------------------
214
+ */}
229
215
  <div
230
216
  className={clsx(
231
217
  "fixed top-0 z-40 flex h-full flex-col justify-between overflow-x-clip transition-all",
@@ -249,7 +235,11 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
249
235
  }
250
236
  ref={ref}
251
237
  >
252
- {/* Drawer Header */}
238
+ {/*
239
+ * ----------------------------------------------------------------------------------------------------
240
+ * Drawer Header
241
+ * ----------------------------------------------------------------------------------------------------
242
+ */}
253
243
  <div
254
244
  dir={direction}
255
245
  className={clsx(
@@ -262,7 +252,11 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
262
252
  : `${openSideMenu ? openDrawerWidth : 0}px`,
263
253
  }}
264
254
  >
265
- {/* Full Logo */}
255
+ {/*
256
+ * ----------------------------------------------------------------------------------------------------
257
+ * Full Logo
258
+ * ----------------------------------------------------------------------------------------------------
259
+ */}
266
260
  <img
267
261
  className={clsx(
268
262
  "h-9 opacity-0 transition-all",
@@ -277,8 +271,11 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
277
271
  // )}
278
272
  src={props.logoLink}
279
273
  />
280
-
281
- {/* Logo Symbol */}
274
+ {/*
275
+ * ----------------------------------------------------------------------------------------------------
276
+ * Logo Symbol
277
+ * ----------------------------------------------------------------------------------------------------
278
+ */}
282
279
  {size > 600 ? (
283
280
  <img
284
281
  className={clsx(
@@ -290,7 +287,11 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
290
287
  />
291
288
  ) : null}
292
289
  </div>
293
- {/* Drawer Content Container */}
290
+ {/*
291
+ * ----------------------------------------------------------------------------------------------------
292
+ * Drawer Content Container
293
+ * ----------------------------------------------------------------------------------------------------
294
+ */}
294
295
  <div
295
296
  className={clsx(
296
297
  // "no-scrollbar", TODO: make this optional to hide scrollbar or not
@@ -306,7 +307,12 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
306
307
  : `${openSideMenu ? openDrawerWidth : 0}px`,
307
308
  }}
308
309
  >
309
- {/* Drawer Items */}
310
+ {/*
311
+ * ----------------------------------------------------------------------------------------------------
312
+ * Drawer Items
313
+ * ----------------------------------------------------------------------------------------------------
314
+ */}
315
+
310
316
  {props.drawerItems?.map((dSection, dIndex) => (
311
317
  <div
312
318
  key={dIndex}
@@ -419,16 +425,19 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
419
425
  )
420
426
  })}
421
427
  {dIndex !== props.drawerItems.length - 1 && (
422
- <div className="my-2 h-[1px] w-10/12 self-center bg-buttonPrimary-500 text-center "></div>
428
+ <div className="my-2 h-[1px] w-10/12 self-center bg-buttonPrimary-500 bg-red-500 text-center "></div>
423
429
  )}
424
430
  </div>
425
431
  ))}
426
432
  </div>
427
- {/* Drawer Footer */}
433
+ {/*
434
+ * ----------------------------------------------------------------------------------------------------
435
+ * Drawer Footer
436
+ * ----------------------------------------------------------------------------------------------------
437
+ */}
428
438
  <div
429
439
  className={clsx(
430
- "fixed bottom-0 flex h-14 w-full items-center justify-center gap-2 overflow-clip bg-primary-foreground transition-all",
431
-
440
+ "fixed bottom-0 flex h-14 w-full items-center justify-center gap-2 overflow-clip bg-primary-foreground transition-all",
432
441
  direction === "rtl" ? "flex-row-reverse" : "flex-row"
433
442
  )}
434
443
  style={{
@@ -438,85 +447,56 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
438
447
  : `${openSideMenu ? openDrawerWidth : 0}px`,
439
448
  }}
440
449
  >
441
- {size > 600 && DrawerFooterActions && openSideMenu ? (
450
+ {DrawerFooterActions && openSideMenu ? (
442
451
  <>{DrawerFooterActions}</>
443
452
  ) : null}
444
453
 
445
454
  {/* Expand Button */}
446
455
  {size > 600 && openSideMenu ? (
447
- <div
448
- className={clsx("w-fit transition-all")}
449
- style={
450
- isRTL
451
- ? {
452
- right: `${
453
- drawerSizeStyle[openSideMenu ? "opened" : "closed"][
454
- drawerSize
455
- ] - 35
456
- }px`,
457
- }
458
- : {
459
- left: `${
460
- drawerSizeStyle[openSideMenu ? "opened" : "closed"][
461
- drawerSize
462
- ] - 35
463
- }px`,
464
- }
456
+ <Tooltip
457
+ side={"left"}
458
+ delayDuration={500}
459
+ content={
460
+ keepOpen
461
+ ? props.texts?.collapseSidebar || "Collapse Sidebar"
462
+ : props.texts?.expandSidebar || "Expand Sidebar"
465
463
  }
466
464
  >
467
- <div
468
- dir={direction}
469
- className={clsx(
470
- "relative left-0 top-0 transition-all",
471
- openSideMenu ? " opacity-100" : " opacity-0"
472
- )}
465
+ <Button
466
+ variant="light"
467
+ onClick={() => setKeepOpen(!keepOpen)}
468
+ size="smallIcon"
473
469
  >
474
- <Tooltip
475
- side={"left"}
476
- delayDuration={300}
477
- content={
470
+ <svg
471
+ className={clsx(
472
+ "h-6 w-6 shrink-0 text-primary transition-all disabled:bg-gray-200 ",
478
473
  keepOpen
479
- ? props.texts?.collapseSidebar || "Collapse Sidebar"
480
- : props.texts?.expandSidebar || "Expand Sidebar"
481
- // || "Expand Sidebar"
482
- }
474
+ ? isRTL
475
+ ? "-rotate-90"
476
+ : "rotate-90"
477
+ : isRTL
478
+ ? "rotate-90"
479
+ : "-rotate-90"
480
+ )}
481
+ fill="currentColor"
482
+ viewBox="0 0 20 20"
483
483
  >
484
- <Button
485
- variant="light"
486
- onClick={() => setKeepOpen(!keepOpen)}
487
- size="icon"
488
- >
489
- <svg
490
- className={clsx(
491
- "h-8 w-8 shrink-0 text-primary transition-all disabled:bg-gray-200 ",
492
- // directionStyle
493
- keepOpen
494
- ? isRTL
495
- ? "-rotate-90"
496
- : "rotate-90"
497
- : isRTL
498
- ? "rotate-90"
499
- : "-rotate-90"
500
- )}
501
- fill="currentColor"
502
- viewBox="0 0 20 20"
503
- >
504
- <path
505
- fillRule="evenodd"
506
- d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
507
- clipRule="evenodd"
508
- ></path>
509
- </svg>
510
- </Button>
511
- </Tooltip>
512
- </div>
513
- </div>
484
+ <path
485
+ fillRule="evenodd"
486
+ d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
487
+ clipRule="evenodd"
488
+ ></path>
489
+ </svg>
490
+ </Button>
491
+ </Tooltip>
514
492
  ) : null}
515
493
  </div>
516
494
  </div>
517
- {/*
518
-
519
- {/* Children Container */}
495
+ {/*
496
+ * ----------------------------------------------------------------------------------------------------
497
+ * Children Container
498
+ * ----------------------------------------------------------------------------------------------------
499
+ */}
520
500
  <div
521
501
  className="fixed overflow-y-auto"
522
502
  style={
@@ -0,0 +1,224 @@
1
+ import * as React from "react"
2
+ import * as AccordionPrimitive from "@radix-ui/react-accordion"
3
+
4
+ import { cn } from "../util"
5
+
6
+ const Accordion = AccordionPrimitive.Root
7
+
8
+ let triggerStyles =
9
+ "flex flex-1 items-center cursor-pointer bg-primary-foreground rounded justify-between p-2 px-3 font-medium transition-all [&[data-state=open]>svg]:-rotate-90"
10
+ const AccordionItem = React.forwardRef<
11
+ React.ElementRef<typeof AccordionPrimitive.Item>,
12
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
13
+ >(({ className, ...props }, ref) => (
14
+ <AccordionPrimitive.Item ref={ref} className={cn(className)} {...props} />
15
+ ))
16
+ AccordionItem.displayName = "AccordionItem"
17
+
18
+ const AccordionTrigger = React.forwardRef<
19
+ React.ElementRef<typeof AccordionPrimitive.Trigger>,
20
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
21
+ >(({ className, children, ...props }, ref) => (
22
+ <AccordionPrimitive.Header className="flex">
23
+ <AccordionPrimitive.Trigger
24
+ ref={ref}
25
+ className={cn(triggerStyles, className)}
26
+ {...props}
27
+ >
28
+ {children}
29
+ <svg
30
+ aria-label="Chevron Right Icon"
31
+ stroke="currentColor"
32
+ fill="currentColor"
33
+ stroke-width="1"
34
+ viewBox="0 0 16 16"
35
+ height="1em"
36
+ width="1em"
37
+ className="h-4 w-4 shrink-0 rotate-90 transition-transform duration-200"
38
+ >
39
+ <path
40
+ fill-rule="evenodd"
41
+ d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"
42
+ ></path>
43
+ </svg>
44
+ </AccordionPrimitive.Trigger>
45
+ </AccordionPrimitive.Header>
46
+ ))
47
+ AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
48
+
49
+ const AccordionContent = React.forwardRef<
50
+ React.ElementRef<typeof AccordionPrimitive.Content>,
51
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
52
+ >(({ className, children, ...props }, ref) => (
53
+ <AccordionPrimitive.Content
54
+ ref={ref}
55
+ className={cn(
56
+ "overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
57
+ className
58
+ )}
59
+ {...props}
60
+ >
61
+ <div>{children}</div>
62
+ </AccordionPrimitive.Content>
63
+ ))
64
+ AccordionContent.displayName = AccordionPrimitive.Content.displayName
65
+
66
+ type Item = {
67
+ value: string
68
+ label: string
69
+ icon?: any
70
+ subitems?: SubItem[]
71
+ onClick?: () => void
72
+ }
73
+ type SubItem = {
74
+ value: string
75
+ label: string
76
+ icon?: any
77
+ onClick?: () => void
78
+ }
79
+ interface SidebarGroupProps {
80
+ title?: string
81
+ items: Item[]
82
+ collapsed?: any
83
+ selectedItem?: any
84
+ isOpen?: boolean
85
+ onItemClick?: (value: string[]) => void
86
+ onSubItemClick?: (values: string[]) => void
87
+ }
88
+ interface SidebarRootProps {
89
+ children: any
90
+ }
91
+
92
+ const SidebarRoot: React.FC<SidebarRootProps> = ({ children }) => (
93
+ <div className="flex flex-col gap-2">{children}</div>
94
+ )
95
+ const SidebarGroup: React.FC<SidebarGroupProps> = ({
96
+ title,
97
+ items,
98
+ selectedItem,
99
+ collapsed,
100
+ onItemClick,
101
+ onSubItemClick,
102
+ isOpen,
103
+ }) => {
104
+ React.useEffect(() => {
105
+ if (collapsed) {
106
+ // Logic to close all groups
107
+ }
108
+ }, [collapsed])
109
+
110
+ return (
111
+ <div>
112
+ {title && <h3 className="mb-1 font-bold">{title}</h3>}
113
+ <ul className="flex flex-col gap-2">
114
+ <Accordion
115
+ type="single"
116
+ // defaultValue="item-1"
117
+ collapsible
118
+ className="flex flex-col gap-1"
119
+ >
120
+ {items.map((item, idx) => (
121
+ <SidebarItem
122
+ isOpen={isOpen}
123
+ isSelected={selectedItem}
124
+ key={idx}
125
+ item={item}
126
+ onItemClick={onItemClick}
127
+ onSubItemClick={onSubItemClick}
128
+ />
129
+ ))}
130
+ </Accordion>
131
+ </ul>
132
+ </div>
133
+ )
134
+ }
135
+ const SidebarItem: React.FC<{
136
+ item: Item
137
+ isSelected: any
138
+ onItemClick?: (value: string[]) => void
139
+ onSubItemClick?: (values: string[]) => void
140
+ isOpen?: boolean
141
+ }> = ({ item, isSelected, onItemClick, onSubItemClick, isOpen = true }) => {
142
+ const getSelectedStyle = (value: string, index: number) => {
143
+ return isSelected && isSelected[index] === value
144
+ ? "bg-primary text-primary-foreground cursor-default"
145
+ : ""
146
+ }
147
+ if (item.subitems) {
148
+ return (
149
+ <AccordionItem value={item.value} className="overflow-x-clip">
150
+ <AccordionTrigger
151
+ className={cn(getSelectedStyle(item.value, 0), "hover:bg-primary/30")}
152
+ >
153
+ <div className={"flex flex-row items-center gap-2 "}>
154
+ {item.icon}
155
+ {/* {isOpen ? item.label : ""} */}
156
+
157
+ <span
158
+ className={cn(
159
+ "transition-all",
160
+ isOpen ? "opacity-100" : "opacity-0"
161
+ )}
162
+ >
163
+ {item.label}
164
+ </span>
165
+ </div>
166
+ </AccordionTrigger>
167
+ {item.subitems && (
168
+ <AccordionContent className=" mt-1 h-full rounded ">
169
+ <div
170
+ className={cn("flex h-full flex-col gap-2 bg-foreground/5 p-1")}
171
+ >
172
+ {item.subitems.map((subitem, idx) => (
173
+ <li
174
+ onClick={(e) => {
175
+ e.stopPropagation()
176
+ if (onSubItemClick) {
177
+ onSubItemClick([item.value, subitem.value])
178
+ }
179
+ }}
180
+ className={cn(
181
+ "flex h-full cursor-pointer flex-row items-center gap-2 rounded bg-foreground/10 p-2 transition-all hover:bg-foreground/30",
182
+ getSelectedStyle(subitem.value, 1)
183
+ )}
184
+ key={idx}
185
+ >
186
+ {subitem.icon}
187
+ {subitem.label}
188
+ </li>
189
+ ))}
190
+ </div>
191
+ </AccordionContent>
192
+ )}
193
+ </AccordionItem>
194
+ )
195
+ } else {
196
+ return (
197
+ <div
198
+ onClick={() => {
199
+ if (onItemClick) {
200
+ onItemClick([item.value])
201
+ }
202
+ }}
203
+ className={cn(
204
+ triggerStyles,
205
+ getSelectedStyle(item.value, 0),
206
+ "overflow-x-clip hover:bg-primary/30"
207
+ )}
208
+ >
209
+ <div className={"flex flex-row items-center gap-2 "}>
210
+ {item.icon}
211
+ <span
212
+ className={cn(
213
+ "transition-all",
214
+ isOpen ? "opacity-100" : "opacity-0"
215
+ )}
216
+ >
217
+ {item.label}
218
+ </span>
219
+ </div>
220
+ </div>
221
+ )
222
+ }
223
+ }
224
+ export { SidebarRoot, SidebarGroup, SidebarItem }
@@ -0,0 +1,77 @@
1
+ import {
2
+ AccordionItem,
3
+ AccordionTrigger,
4
+ AccordionContent,
5
+ Accordion,
6
+ } from "@radix-ui/react-accordion"
7
+ import React from "react"
8
+ import { cn } from "../util"
9
+
10
+ type Item = {
11
+ value: string
12
+ label: string
13
+ icon?: any
14
+ subitems?: Item[]
15
+ }
16
+
17
+ interface SidebarGroupProps {
18
+ title: string
19
+ items: Item[]
20
+ }
21
+ interface SidebarRootProps {
22
+ children: any
23
+ }
24
+
25
+ const SidebarRoot: React.FC<SidebarRootProps> = ({ children }) => (
26
+ <div className="flex flex-col gap-2 rounded bg-red-200 p-2">{children}</div>
27
+ )
28
+
29
+ const SidebarGroup: React.FC<SidebarGroupProps> = ({ title, items }) => (
30
+ <div>
31
+ <h3 className="mb-1 font-bold">{title}</h3>
32
+ <ul className="flex flex-col gap-2">
33
+ {items.map((item, idx) => (
34
+ <SidebarItem key={idx} item={item} />
35
+ ))}
36
+ </ul>
37
+ </div>
38
+ )
39
+
40
+ const SidebarItem: React.FC<{ item: Item }> = ({ item }) => (
41
+ // <li className="rounded bg-red-400 p-2">
42
+ <Accordion
43
+ // className="bg-mauve6 w-[300px] rounded-md shadow-[0_2px_10px] shadow-black/5"
44
+ type="single"
45
+ defaultValue="item-1"
46
+ collapsible
47
+ >
48
+ <AccordionItem value={item.value}>
49
+ <AccordionTrigger
50
+ className={cn()
51
+ // "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
52
+ // className
53
+ }
54
+ >
55
+ <div className="flex flex-row items-center gap-2">
56
+ {item.icon}
57
+ {item.label}
58
+ </div>
59
+ </AccordionTrigger>
60
+
61
+ {item.subitems && (
62
+ <AccordionContent
63
+ // className="flex flex-col gap-1 bg-blue-400"
64
+ >
65
+ {item.subitems.map((subitem, idx) => (
66
+ <li className="rounded bg-yellow-300 p-1" key={idx}>
67
+ {subitem.label}
68
+ </li>
69
+ ))}
70
+ </AccordionContent>
71
+ )}
72
+ </AccordionItem>
73
+ </Accordion>
74
+ // </li>
75
+ )
76
+
77
+ export { SidebarRoot, SidebarGroup, SidebarItem }
@@ -1,6 +1,7 @@
1
1
  export * from "./Box"
2
2
  export * from "./HawaBottomAppBar"
3
3
  export * from "./HawaSiteLayout"
4
+ export * from "./AppLayout"
4
5
  export * from "./HawaAppLayout"
5
6
  export * from "./HawaAppLayoutSimplified"
6
7
  export * from "./HawaContainer"
@@ -8,3 +9,5 @@ export * from "./HawaGrid"
8
9
  export * from "./AppSidebar"
9
10
  export * from "./Footer"
10
11
  export * from "./Banner"
12
+ // export * from "./Sidebar2"
13
+ export * from "./Sidebar"