hazo_auth 0.1.0 → 0.3.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.
Files changed (194) hide show
  1. package/hazo_auth_config.example.ini +36 -0
  2. package/package.json +3 -1
  3. package/public/profile_pictures/library/Cars/001 - bugatti.jpeg +0 -0
  4. package/public/profile_pictures/library/Cars/002 - lamborgini.jpeg +0 -0
  5. package/public/profile_pictures/library/Cars/004 - chevrolet_silverado.jpeg +0 -0
  6. package/public/profile_pictures/library/Cars/007 - tesla_model_3.jpeg +0 -0
  7. package/public/profile_pictures/library/Cars/012 - subaru_outback.jpeg +0 -0
  8. package/public/profile_pictures/library/Cars/014 - ford_explorer.jpeg +0 -0
  9. package/public/profile_pictures/library/Cars/016 - gmc_sierra.jpeg +0 -0
  10. package/public/profile_pictures/library/Cars/021 - audi_a4.jpeg +0 -0
  11. package/public/profile_pictures/library/Cars/024 - audi_a6.jpeg +0 -0
  12. package/public/profile_pictures/library/Cars/025 - mercedes_benz_e_class.jpeg +0 -0
  13. package/public/profile_pictures/library/Cars/027 - porsche_911.jpeg +0 -0
  14. package/public/profile_pictures/library/Cars/031 - opel_corsa.jpeg +0 -0
  15. package/public/profile_pictures/library/Cars/036 - nissan_qashqai.jpeg +0 -0
  16. package/public/profile_pictures/library/Cars/037 - mini_hatch.jpeg +0 -0
  17. package/public/profile_pictures/library/Cars/040 - land_rover_range_rover_evoque.jpeg +0 -0
  18. package/public/profile_pictures/library/Cars/042 - land_rover_defender.jpeg +0 -0
  19. package/public/profile_pictures/library/Cars/050 - citroe/314/210n_c3.jpeg +0 -0
  20. package/public/profile_pictures/library/Cars/051 - renault_captur.jpeg +0 -0
  21. package/public/profile_pictures/library/Cars/059 - fiat_500.jpeg +0 -0
  22. package/public/profile_pictures/library/Cars/060 - lancia_ypsilon.jpeg +0 -0
  23. package/public/profile_pictures/library/Cars/062 - maserati_ghibli.jpeg +0 -0
  24. package/public/profile_pictures/library/Cars/063 - ferrari_488.jpeg +0 -0
  25. package/public/profile_pictures/library/Cars/064 - lamborghini_huraca/314/201n.jpeg +0 -0
  26. package/public/profile_pictures/library/Cars/065 - ferrari_sf90.jpeg +0 -0
  27. package/public/profile_pictures/library/Cars/066 - fiat_tipo.jpeg +0 -0
  28. package/public/profile_pictures/library/Cars/071 - seat_ateca.jpeg +0 -0
  29. package/public/profile_pictures/library/Cars/075 - hyundai_kona.jpeg +0 -0
  30. package/public/profile_pictures/library/Cars/078 - tesla_model_y.jpeg +0 -0
  31. package/public/profile_pictures/library/Cars/081 - bmw_i3.jpeg +0 -0
  32. package/public/profile_pictures/library/Cars/084 - fiat_500e.jpeg +0 -0
  33. package/public/profile_pictures/library/Cars/087 - polestar_2.jpeg +0 -0
  34. package/public/profile_pictures/library/Cars/088 - toyota_corolla.jpeg +0 -0
  35. package/public/profile_pictures/library/Cars/090 - bmw_x5.jpeg +0 -0
  36. package/public/profile_pictures/library/Cars/091 - ford_mustang.jpeg +0 -0
  37. package/public/profile_pictures/library/Cars/093 - audi_tt.jpeg +0 -0
  38. package/public/profile_pictures/library/Cars/094 - mercedes_benz_s_class.jpeg +0 -0
  39. package/public/profile_pictures/library/Cars/095 - volvo_xc60.jpeg +0 -0
  40. package/public/profile_pictures/library/Cars/097 - peugeot_5008.jpeg +0 -0
  41. package/public/profile_pictures/library/Cars/099 - citroe/314/210n_2cv_(classic).jpeg +0 -0
  42. package/public/profile_pictures/library/Cars/100 - vw_beetle_(classic).jpeg +0 -0
  43. package/public/profile_pictures/library/Cars/101 - range_rover_sport.jpeg +0 -0
  44. package/public/profile_pictures/library/Cars/104 - audi_a8.jpeg +0 -0
  45. package/public/profile_pictures/library/Cars/106 - mercedes_benz_g_class.jpeg +0 -0
  46. package/public/profile_pictures/library/Cars/110 - bmw_i7.jpeg +0 -0
  47. package/public/profile_pictures/library/Cars/111 - audi_e_tron_gt.jpeg +0 -0
  48. package/public/profile_pictures/library/Cars/112 - rolls_royce_phantom.jpeg +0 -0
  49. package/public/profile_pictures/library/Cars/113 - bentley_continental_gt.jpeg +0 -0
  50. package/public/profile_pictures/library/Cars/115 - aston_martin_dbx.jpeg +0 -0
  51. package/public/profile_pictures/library/Cars/116 - jaguar_xj.jpeg +0 -0
  52. package/public/profile_pictures/library/Cars/117 - maserati_quattroporte.jpeg +0 -0
  53. package/public/profile_pictures/library/Cars/118 - ferrari_roma.jpeg +0 -0
  54. package/public/profile_pictures/library/Cars/119 - lamborghini_urus.jpeg +0 -0
  55. package/public/profile_pictures/library/Cars/120 - cadillac_escalade.jpeg +0 -0
  56. package/public/profile_pictures/library/Cars/122 - ferrari_sf90_stradale.jpeg +0 -0
  57. package/public/profile_pictures/library/Cars/123 - lamborghini_aventador_svj.jpeg +0 -0
  58. package/public/profile_pictures/library/Cars/124 - mclaren_720s.jpeg +0 -0
  59. package/public/profile_pictures/library/Cars/125 - porsche_911_gt3_rs.jpeg +0 -0
  60. package/public/profile_pictures/library/Cars/126 - bugatti_chiron.jpeg +0 -0
  61. package/public/profile_pictures/library/Cars/127 - aston_martin_valkyrie.jpeg +0 -0
  62. package/public/profile_pictures/library/Cars/128 - koenigsegg_jesko.jpeg +0 -0
  63. package/public/profile_pictures/library/Cars/129 - pagani_huayra.jpeg +0 -0
  64. package/public/profile_pictures/library/Cars/130 - ferrari_812_superfast.jpeg +0 -0
  65. package/public/profile_pictures/library/Cars/131 - lamborghini_huraca/314/201n_sto.jpeg +0 -0
  66. package/public/profile_pictures/library/Cars/132 - mclaren_p1.jpeg +0 -0
  67. package/public/profile_pictures/library/Cars/133 - bugatti_veyron.jpeg +0 -0
  68. package/public/profile_pictures/library/Cars/134 - rimac_nevera.jpeg +0 -0
  69. package/public/profile_pictures/library/Cars/135 - maserati_mc20.jpeg +0 -0
  70. package/public/profile_pictures/library/Cars/136 - chevrolet_corvette_z06_(c8).jpeg +0 -0
  71. package/public/profile_pictures/library/Cars/137 - lotus_evija.jpeg +0 -0
  72. package/public/profile_pictures/library/Cars/138 - ford_gt.jpeg +0 -0
  73. package/public/profile_pictures/library/Cars/139 - ferrari_laferrari.jpeg +0 -0
  74. package/public/profile_pictures/library/Cars/140 - lamborghini_sian.jpeg +0 -0
  75. package/public/profile_pictures/library/Cars/141 - zenvo_tsr_s.jpeg +0 -0
  76. package/public/profile_pictures/library/Cars/142 - toyota_tacoma.jpeg +0 -0
  77. package/public/profile_pictures/library/Cars/143 - suzuki_swift.jpeg +0 -0
  78. package/public/profile_pictures/library/Cars/144 - skoda_fabia_.jpeg +0 -0
  79. package/public/profile_pictures/library/Cars/145 - nissan_micra.jpeg +0 -0
  80. package/public/profile_pictures/library/Cars/146 - chevrolet_equinox.jpeg +0 -0
  81. package/public/profile_pictures/library/Cars/147 - hyundai_elantra.jpeg +0 -0
  82. package/public/profile_pictures/library/Cars/148 - peugeot_301.jpeg +0 -0
  83. package/public/profile_pictures/library/Cars/149 - renault_duster.jpeg +0 -0
  84. package/public/profile_pictures/library/Cars/150 - tesla_roadster.jpeg +0 -0
  85. package/public/profile_pictures/library/Cars/151 - gogo_mobile_dart.jpeg +0 -0
  86. package/public/profile_pictures/library/README.md +23 -0
  87. package/public/profile_pictures/library/Young Cartoons/001-Zoe.jpeg +0 -0
  88. package/public/profile_pictures/library/Young Cartoons/002-Nora.jpeg +0 -0
  89. package/public/profile_pictures/library/Young Cartoons/003-Aria.jpeg +0 -0
  90. package/public/profile_pictures/library/Young Cartoons/004-Reagan.jpeg +0 -0
  91. package/public/profile_pictures/library/Young Cartoons/005-Violet.jpeg +0 -0
  92. package/public/profile_pictures/library/Young Cartoons/006-Alexa.jpeg +0 -0
  93. package/public/profile_pictures/library/Young Cartoons/007-Brooklyn.jpeg +0 -0
  94. package/public/profile_pictures/library/Young Cartoons/008-Kinsley.jpeg +0 -0
  95. package/public/profile_pictures/library/Young Cartoons/009-Quinn.jpeg +0 -0
  96. package/public/profile_pictures/library/Young Cartoons/010-Emilia.jpeg +0 -0
  97. package/public/profile_pictures/library/Young Cartoons/011-Mackenzie.jpeg +0 -0
  98. package/public/profile_pictures/library/Young Cartoons/012-Isabella.jpeg +0 -0
  99. package/public/profile_pictures/library/Young Cartoons/013-Sophia.jpeg +0 -0
  100. package/public/profile_pictures/library/Young Cartoons/014-Layla.jpeg +0 -0
  101. package/public/profile_pictures/library/Young Cartoons/015-Sarah.jpeg +0 -0
  102. package/public/profile_pictures/library/Young Cartoons/016-Hadley.jpeg +0 -0
  103. package/public/profile_pictures/library/Young Cartoons/017-Skylar.jpeg +0 -0
  104. package/public/profile_pictures/library/Young Cartoons/018-Brielle.jpeg +0 -0
  105. package/public/profile_pictures/library/Young Cartoons/019-Hailey.jpeg +0 -0
  106. package/public/profile_pictures/library/Young Cartoons/020-Paisley.jpeg +0 -0
  107. package/public/profile_pictures/library/Young Cartoons/021-Nova.jpeg +0 -0
  108. package/public/profile_pictures/library/Young Cartoons/022-Lucy.jpeg +0 -0
  109. package/public/profile_pictures/library/Young Cartoons/023-Ivy.jpeg +0 -0
  110. package/public/profile_pictures/library/Young Cartoons/024-Melanie.jpeg +0 -0
  111. package/public/profile_pictures/library/Young Cartoons/025-Addison.jpeg +0 -0
  112. package/public/profile_pictures/library/Young Cartoons/026-Genesis.jpeg +0 -0
  113. package/public/profile_pictures/library/Young Cartoons/027-Cora.jpeg +0 -0
  114. package/public/profile_pictures/library/Young Cartoons/028-Delilah.jpeg +0 -0
  115. package/public/profile_pictures/library/Young Cartoons/029-Liliana.jpeg +0 -0
  116. package/public/profile_pictures/library/Young Cartoons/030-Savannah.jpeg +0 -0
  117. package/public/profile_pictures/library/Young Cartoons/031-Ava.jpeg +0 -0
  118. package/public/profile_pictures/library/Young Cartoons/032-Aaliyah.jpeg +0 -0
  119. package/public/profile_pictures/library/Young Cartoons/033-Arianna.jpeg +0 -0
  120. package/public/profile_pictures/library/Young Cartoons/034-Abigail.jpeg +0 -0
  121. package/public/profile_pictures/library/Young Cartoons/035-Sophie.jpeg +0 -0
  122. package/public/profile_pictures/library/Young Cartoons/036-Ayla.jpeg +0 -0
  123. package/public/profile_pictures/library/Young Cartoons/037-Gianna.jpeg +0 -0
  124. package/public/profile_pictures/library/Young Cartoons/038-Ella.jpeg +0 -0
  125. package/public/profile_pictures/library/Young Cartoons/039-Mia.jpeg +0 -0
  126. package/public/profile_pictures/library/Young Cartoons/040-Autumn.jpeg +0 -0
  127. package/public/profile_pictures/library/Young Cartoons/041-Luna.jpeg +0 -0
  128. package/public/profile_pictures/library/Young Cartoons/042-Aurora.jpeg +0 -0
  129. package/public/profile_pictures/library/Young Cartoons/043-Samantha.jpeg +0 -0
  130. package/public/profile_pictures/library/Young Cartoons/044-Ariana.jpeg +0 -0
  131. package/public/profile_pictures/library/Young Cartoons/045-Gabriella.jpeg +0 -0
  132. package/public/profile_pictures/library/Young Cartoons/046-Serenity.jpeg +0 -0
  133. package/public/profile_pictures/library/Young Cartoons/047-Caroline.jpeg +0 -0
  134. package/public/profile_pictures/library/Young Cartoons/048-Emma.jpeg +0 -0
  135. package/public/profile_pictures/library/Young Cartoons/049-Piper.jpeg +0 -0
  136. package/public/profile_pictures/library/Young Cartoons/050-Madeline.jpeg +0 -0
  137. package/public/profile_pictures/library/Young Cartoons/051-Elijah.jpeg +0 -0
  138. package/public/profile_pictures/library/Young Cartoons/052-Lucas.jpeg +0 -0
  139. package/public/profile_pictures/library/Young Cartoons/053-Elias.jpeg +0 -0
  140. package/public/profile_pictures/library/Young Cartoons/054-Oliver.jpeg +0 -0
  141. package/public/profile_pictures/library/Young Cartoons/055-Ian.jpeg +0 -0
  142. package/public/profile_pictures/library/Young Cartoons/056-Ryan.jpeg +0 -0
  143. package/public/profile_pictures/library/Young Cartoons/057-Wesley.jpeg +0 -0
  144. package/public/profile_pictures/library/Young Cartoons/058-Joshua.jpeg +0 -0
  145. package/public/profile_pictures/library/Young Cartoons/059-Nicholas.jpeg +0 -0
  146. package/public/profile_pictures/library/Young Cartoons/060-Aiden.jpeg +0 -0
  147. package/public/profile_pictures/library/Young Cartoons/061-Cameron.jpeg +0 -0
  148. package/public/profile_pictures/library/Young Cartoons/062-Logan.jpeg +0 -0
  149. package/public/profile_pictures/library/Young Cartoons/063-Silas.jpeg +0 -0
  150. package/public/profile_pictures/library/Young Cartoons/064-Mateo.jpeg +0 -0
  151. package/public/profile_pictures/library/Young Cartoons/065-Hunter.jpeg +0 -0
  152. package/public/profile_pictures/library/Young Cartoons/066-Colton.jpeg +0 -0
  153. package/public/profile_pictures/library/Young Cartoons/067-Owen.jpeg +0 -0
  154. package/public/profile_pictures/library/Young Cartoons/068-Josiah.jpeg +0 -0
  155. package/public/profile_pictures/library/Young Cartoons/069-Santiago.jpeg +0 -0
  156. package/public/profile_pictures/library/Young Cartoons/070-Lincoln.jpeg +0 -0
  157. package/public/profile_pictures/library/Young Cartoons/071-Samuel.jpeg +0 -0
  158. package/public/profile_pictures/library/Young Cartoons/072-Thomas.jpeg +0 -0
  159. package/public/profile_pictures/library/Young Cartoons/073-Jaxson.jpeg +0 -0
  160. package/public/profile_pictures/library/Young Cartoons/074-Gabriel.jpeg +0 -0
  161. package/public/profile_pictures/library/Young Cartoons/075-Dominic.jpeg +0 -0
  162. package/public/profile_pictures/library/Young Cartoons/076-Grayson.jpeg +0 -0
  163. package/public/profile_pictures/library/Young Cartoons/077-Liam.jpeg +0 -0
  164. package/public/profile_pictures/library/Young Cartoons/078-Ethan.jpeg +0 -0
  165. package/public/profile_pictures/library/Young Cartoons/079-Jaxon.jpeg +0 -0
  166. package/public/profile_pictures/library/Young Cartoons/080-Jackson.jpeg +0 -0
  167. package/public/profile_pictures/library/Young Cartoons/081-Kai.jpeg +0 -0
  168. package/public/profile_pictures/library/Young Cartoons/082-Henry.jpeg +0 -0
  169. package/public/profile_pictures/library/Young Cartoons/083-Hudson.jpeg +0 -0
  170. package/public/profile_pictures/library/Young Cartoons/084-Isaiah.jpeg +0 -0
  171. package/public/profile_pictures/library/Young Cartoons/085-Benjamin.jpeg +0 -0
  172. package/public/profile_pictures/library/Young Cartoons/086-Christopher.jpeg +0 -0
  173. package/public/profile_pictures/library/Young Cartoons/087-Eli.jpeg +0 -0
  174. package/public/profile_pictures/library/Young Cartoons/088-Mason.jpeg +0 -0
  175. package/public/profile_pictures/library/Young Cartoons/089-Jack.jpeg +0 -0
  176. package/public/profile_pictures/library/Young Cartoons/090-Jordan.jpeg +0 -0
  177. package/public/profile_pictures/library/Young Cartoons/091-Easton.jpeg +0 -0
  178. package/public/profile_pictures/library/Young Cartoons/092-Miles.jpeg +0 -0
  179. package/public/profile_pictures/library/Young Cartoons/093-Caleb.jpeg +0 -0
  180. package/public/profile_pictures/library/Young Cartoons/094-Jameson.jpeg +0 -0
  181. package/public/profile_pictures/library/Young Cartoons/095-Kayden.jpeg +0 -0
  182. package/public/profile_pictures/library/Young Cartoons/096-Maverick.jpeg +0 -0
  183. package/public/profile_pictures/library/Young Cartoons/097-Julian.jpeg +0 -0
  184. package/public/profile_pictures/library/Young Cartoons/098-James.jpeg +0 -0
  185. package/public/profile_pictures/library/Young Cartoons/099-Greyson.jpeg +0 -0
  186. package/public/profile_pictures/library/Young Cartoons/100-Robert.jpeg +0 -0
  187. package/public/profile_pictures/library/Young Cartoons/101-Bella.jpeg +0 -0
  188. package/src/app/api/auth/library_photos/route.ts +3 -0
  189. package/src/components/layouts/my_settings/components/profile_picture_library_tab.tsx +33 -4
  190. package/src/components/layouts/shared/components/profile_pic_menu.tsx +321 -0
  191. package/src/components/layouts/shared/components/profile_pic_menu_wrapper.tsx +40 -0
  192. package/src/components/layouts/shared/components/sidebar_layout_wrapper.tsx +4 -66
  193. package/src/components/ui/dropdown-menu.tsx +201 -0
  194. package/src/lib/profile_pic_menu_config.server.ts +138 -0
@@ -0,0 +1,201 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
5
+ import { Check, ChevronRight, Circle } from "lucide-react"
6
+
7
+ import { cn } from "@/lib/utils"
8
+
9
+ const DropdownMenu = DropdownMenuPrimitive.Root
10
+
11
+ const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
12
+
13
+ const DropdownMenuGroup = DropdownMenuPrimitive.Group
14
+
15
+ const DropdownMenuPortal = DropdownMenuPrimitive.Portal
16
+
17
+ const DropdownMenuSub = DropdownMenuPrimitive.Sub
18
+
19
+ const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
20
+
21
+ const DropdownMenuSubTrigger = React.forwardRef<
22
+ React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
23
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
24
+ inset?: boolean
25
+ }
26
+ >(({ className, inset, children, ...props }, ref) => (
27
+ <DropdownMenuPrimitive.SubTrigger
28
+ ref={ref}
29
+ className={cn(
30
+ "flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
31
+ inset && "pl-8",
32
+ className
33
+ )}
34
+ {...props}
35
+ >
36
+ {children}
37
+ <ChevronRight className="ml-auto" />
38
+ </DropdownMenuPrimitive.SubTrigger>
39
+ ))
40
+ DropdownMenuSubTrigger.displayName =
41
+ DropdownMenuPrimitive.SubTrigger.displayName
42
+
43
+ const DropdownMenuSubContent = React.forwardRef<
44
+ React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
45
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
46
+ >(({ className, ...props }, ref) => (
47
+ <DropdownMenuPrimitive.SubContent
48
+ ref={ref}
49
+ className={cn(
50
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
51
+ className
52
+ )}
53
+ {...props}
54
+ />
55
+ ))
56
+ DropdownMenuSubContent.displayName =
57
+ DropdownMenuPrimitive.SubContent.displayName
58
+
59
+ const DropdownMenuContent = React.forwardRef<
60
+ React.ElementRef<typeof DropdownMenuPrimitive.Content>,
61
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
62
+ >(({ className, sideOffset = 4, ...props }, ref) => (
63
+ <DropdownMenuPrimitive.Portal>
64
+ <DropdownMenuPrimitive.Content
65
+ ref={ref}
66
+ sideOffset={sideOffset}
67
+ className={cn(
68
+ "z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
69
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
70
+ className
71
+ )}
72
+ {...props}
73
+ />
74
+ </DropdownMenuPrimitive.Portal>
75
+ ))
76
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
77
+
78
+ const DropdownMenuItem = React.forwardRef<
79
+ React.ElementRef<typeof DropdownMenuPrimitive.Item>,
80
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
81
+ inset?: boolean
82
+ }
83
+ >(({ className, inset, ...props }, ref) => (
84
+ <DropdownMenuPrimitive.Item
85
+ ref={ref}
86
+ className={cn(
87
+ "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
88
+ inset && "pl-8",
89
+ className
90
+ )}
91
+ {...props}
92
+ />
93
+ ))
94
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
95
+
96
+ const DropdownMenuCheckboxItem = React.forwardRef<
97
+ React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
98
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
99
+ >(({ className, children, checked, ...props }, ref) => (
100
+ <DropdownMenuPrimitive.CheckboxItem
101
+ ref={ref}
102
+ className={cn(
103
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
104
+ className
105
+ )}
106
+ checked={checked}
107
+ {...props}
108
+ >
109
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
110
+ <DropdownMenuPrimitive.ItemIndicator>
111
+ <Check className="h-4 w-4" />
112
+ </DropdownMenuPrimitive.ItemIndicator>
113
+ </span>
114
+ {children}
115
+ </DropdownMenuPrimitive.CheckboxItem>
116
+ ))
117
+ DropdownMenuCheckboxItem.displayName =
118
+ DropdownMenuPrimitive.CheckboxItem.displayName
119
+
120
+ const DropdownMenuRadioItem = React.forwardRef<
121
+ React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
122
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
123
+ >(({ className, children, ...props }, ref) => (
124
+ <DropdownMenuPrimitive.RadioItem
125
+ ref={ref}
126
+ className={cn(
127
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
128
+ className
129
+ )}
130
+ {...props}
131
+ >
132
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
133
+ <DropdownMenuPrimitive.ItemIndicator>
134
+ <Circle className="h-2 w-2 fill-current" />
135
+ </DropdownMenuPrimitive.ItemIndicator>
136
+ </span>
137
+ {children}
138
+ </DropdownMenuPrimitive.RadioItem>
139
+ ))
140
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
141
+
142
+ const DropdownMenuLabel = React.forwardRef<
143
+ React.ElementRef<typeof DropdownMenuPrimitive.Label>,
144
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
145
+ inset?: boolean
146
+ }
147
+ >(({ className, inset, ...props }, ref) => (
148
+ <DropdownMenuPrimitive.Label
149
+ ref={ref}
150
+ className={cn(
151
+ "px-2 py-1.5 text-sm font-semibold",
152
+ inset && "pl-8",
153
+ className
154
+ )}
155
+ {...props}
156
+ />
157
+ ))
158
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
159
+
160
+ const DropdownMenuSeparator = React.forwardRef<
161
+ React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
162
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
163
+ >(({ className, ...props }, ref) => (
164
+ <DropdownMenuPrimitive.Separator
165
+ ref={ref}
166
+ className={cn("-mx-1 my-1 h-px bg-muted", className)}
167
+ {...props}
168
+ />
169
+ ))
170
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
171
+
172
+ const DropdownMenuShortcut = ({
173
+ className,
174
+ ...props
175
+ }: React.HTMLAttributes<HTMLSpanElement>) => {
176
+ return (
177
+ <span
178
+ className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
179
+ {...props}
180
+ />
181
+ )
182
+ }
183
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
184
+
185
+ export {
186
+ DropdownMenu,
187
+ DropdownMenuTrigger,
188
+ DropdownMenuContent,
189
+ DropdownMenuItem,
190
+ DropdownMenuCheckboxItem,
191
+ DropdownMenuRadioItem,
192
+ DropdownMenuLabel,
193
+ DropdownMenuSeparator,
194
+ DropdownMenuShortcut,
195
+ DropdownMenuGroup,
196
+ DropdownMenuPortal,
197
+ DropdownMenuSub,
198
+ DropdownMenuSubContent,
199
+ DropdownMenuSubTrigger,
200
+ DropdownMenuRadioGroup,
201
+ }
@@ -0,0 +1,138 @@
1
+ // file_description: server-only helper to read profile picture menu configuration from hazo_auth_config.ini
2
+ // section: imports
3
+ import { get_config_value, get_config_boolean, get_config_array } from "./config/config_loader.server";
4
+
5
+ // section: types
6
+ // Note: These types are also used in client components, but TypeScript types are erased at runtime
7
+ // so importing from a server file is safe for type-only imports
8
+ export type MenuItemType = "info" | "link" | "separator";
9
+
10
+ export type ProfilePicMenuMenuItem = {
11
+ type: MenuItemType;
12
+ label?: string; // For info and link types
13
+ value?: string; // For info type (e.g., user name, email)
14
+ href?: string; // For link type
15
+ order: number; // Ordering within type group
16
+ id: string; // Unique identifier for the item
17
+ };
18
+
19
+ export type ProfilePicMenuConfig = {
20
+ show_single_button: boolean;
21
+ sign_up_label: string;
22
+ sign_in_label: string;
23
+ register_path: string;
24
+ login_path: string;
25
+ settings_path: string;
26
+ logout_path: string;
27
+ custom_menu_items: ProfilePicMenuMenuItem[];
28
+ };
29
+
30
+ // section: helpers
31
+ /**
32
+ * Parses custom menu items from config string
33
+ * Format: "type:label:order" or "type:label:href:order" for links
34
+ * Example: "link:My Custom Link:/custom:3"
35
+ * @param items_string - Comma-separated string of menu items
36
+ * @returns Array of parsed menu items
37
+ */
38
+ function parse_custom_menu_items(items_string: string[]): ProfilePicMenuMenuItem[] {
39
+ const items: ProfilePicMenuMenuItem[] = [];
40
+
41
+ items_string.forEach((item_string, index) => {
42
+ const parts = item_string.split(":").map((p) => p.trim());
43
+
44
+ if (parts.length < 3) {
45
+ return; // Invalid format, skip
46
+ }
47
+
48
+ const type = parts[0] as MenuItemType;
49
+ if (type !== "info" && type !== "link" && type !== "separator") {
50
+ return; // Invalid type, skip
51
+ }
52
+
53
+ if (type === "separator") {
54
+ const order = parseInt(parts[1] || "1", 10);
55
+ items.push({
56
+ type: "separator",
57
+ order: isNaN(order) ? 1 : order,
58
+ id: `custom_separator_${index}`,
59
+ });
60
+ return;
61
+ }
62
+
63
+ if (type === "info") {
64
+ const label = parts[1] || "";
65
+ const value = parts[2] || "";
66
+ const order = parseInt(parts[3] || "1", 10);
67
+
68
+ if (!label || !value) {
69
+ return; // Invalid format, skip
70
+ }
71
+
72
+ items.push({
73
+ type: "info",
74
+ label,
75
+ value,
76
+ order: isNaN(order) ? 1 : order,
77
+ id: `custom_info_${index}`,
78
+ });
79
+ return;
80
+ }
81
+
82
+ if (type === "link") {
83
+ const label = parts[1] || "";
84
+ const href = parts[2] || "";
85
+ const order = parseInt(parts[3] || "1", 10);
86
+
87
+ if (!label || !href) {
88
+ return; // Invalid format, skip
89
+ }
90
+
91
+ items.push({
92
+ type: "link",
93
+ label,
94
+ href,
95
+ order: isNaN(order) ? 1 : order,
96
+ id: `custom_link_${index}`,
97
+ });
98
+ }
99
+ });
100
+
101
+ return items;
102
+ }
103
+
104
+ /**
105
+ * Reads profile picture menu configuration from hazo_auth_config.ini file
106
+ * Falls back to defaults if hazo_auth_config.ini is not found or section is missing
107
+ * @returns Profile picture menu configuration options
108
+ */
109
+ export function get_profile_pic_menu_config(): ProfilePicMenuConfig {
110
+ const section = "hazo_auth__profile_pic_menu";
111
+
112
+ // Read button configuration
113
+ const show_single_button = get_config_boolean(section, "show_single_button", false);
114
+ const sign_up_label = get_config_value(section, "sign_up_label", "Sign Up");
115
+ const sign_in_label = get_config_value(section, "sign_in_label", "Sign In");
116
+ const register_path = get_config_value(section, "register_path", "/register");
117
+ const login_path = get_config_value(section, "login_path", "/login");
118
+
119
+ // Read menu paths
120
+ const settings_path = get_config_value(section, "settings_path", "/my_settings");
121
+ const logout_path = get_config_value(section, "logout_path", "/api/auth/logout");
122
+
123
+ // Read custom menu items
124
+ const custom_items_string = get_config_array(section, "custom_menu_items", []);
125
+ const custom_menu_items = parse_custom_menu_items(custom_items_string);
126
+
127
+ return {
128
+ show_single_button,
129
+ sign_up_label,
130
+ sign_in_label,
131
+ register_path,
132
+ login_path,
133
+ settings_path,
134
+ logout_path,
135
+ custom_menu_items,
136
+ };
137
+ }
138
+