nucleus-core-ts 0.8.7 → 0.8.8

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 (203) hide show
  1. package/dist/client.js +1 -1
  2. package/dist/fe/components/AbstractAnimatedBackground/index.js +437 -0
  3. package/dist/fe/components/AuthorizationPage/components/AuthorizationPage.js +841 -0
  4. package/dist/fe/components/AuthorizationPage/components/ClaimList.js +100 -0
  5. package/dist/fe/components/AuthorizationPage/components/RoleClaimEditor.js +232 -0
  6. package/dist/fe/components/AuthorizationPage/components/RoleList.js +115 -0
  7. package/dist/fe/components/AuthorizationPage/index.js +6 -0
  8. package/dist/fe/components/AuthorizationPage/store/index.js +117 -0
  9. package/dist/fe/components/AuthorizationPage/theme/index.js +137 -0
  10. package/dist/fe/components/AuthorizationPage/types/index.js +1 -0
  11. package/dist/fe/components/Button/components/Button.js +158 -0
  12. package/dist/fe/components/Button/components/ButtonSpinner.js +52 -0
  13. package/dist/fe/components/Button/index.js +3 -0
  14. package/dist/fe/components/Button/theme/index.js +186 -0
  15. package/dist/fe/components/Button/types/index.js +1 -0
  16. package/dist/fe/components/Button/utils/cn.js +5 -0
  17. package/dist/fe/components/Captcha/components/Captcha.js +311 -0
  18. package/dist/fe/components/Captcha/index.js +2 -0
  19. package/dist/fe/components/Captcha/theme.js +52 -0
  20. package/dist/fe/components/Captcha/types.js +1 -0
  21. package/dist/fe/components/ChangePasswordPage/components/ChangePasswordForm.js +242 -0
  22. package/dist/fe/components/ChangePasswordPage/components/ChangePasswordHeader.js +39 -0
  23. package/dist/fe/components/ChangePasswordPage/components/ChangePasswordPage.js +60 -0
  24. package/dist/fe/components/ChangePasswordPage/index.js +5 -0
  25. package/dist/fe/components/ChangePasswordPage/store/index.js +44 -0
  26. package/dist/fe/components/ChangePasswordPage/theme/index.js +87 -0
  27. package/dist/fe/components/ChangePasswordPage/types/index.js +1 -0
  28. package/dist/fe/components/Checkbox/components/Checkbox.js +115 -0
  29. package/dist/fe/components/Checkbox/components/CheckboxIcon.js +119 -0
  30. package/dist/fe/components/Checkbox/components/SwitchTrack.js +178 -0
  31. package/dist/fe/components/Checkbox/index.js +4 -0
  32. package/dist/fe/components/Checkbox/theme/index.js +221 -0
  33. package/dist/fe/components/Checkbox/types/index.js +1 -0
  34. package/dist/fe/components/Checkbox/utils/cn.js +5 -0
  35. package/dist/fe/components/DataTable/DataTable.js +225 -0
  36. package/dist/fe/components/DataTable/components/ActionCell.js +26 -0
  37. package/dist/fe/components/DataTable/components/DataCell.js +76 -0
  38. package/dist/fe/components/DataTable/components/EditableCell.js +221 -0
  39. package/dist/fe/components/DataTable/components/EmptyState.js +29 -0
  40. package/dist/fe/components/DataTable/components/HeaderCell.js +64 -0
  41. package/dist/fe/components/DataTable/components/InfiniteScrollTrigger.js +66 -0
  42. package/dist/fe/components/DataTable/components/LoadingSpinner.js +19 -0
  43. package/dist/fe/components/DataTable/components/ResizeHandle.js +41 -0
  44. package/dist/fe/components/DataTable/components/SelectionCell.js +105 -0
  45. package/dist/fe/components/DataTable/components/SkeletonRow.js +56 -0
  46. package/dist/fe/components/DataTable/components/SkeletonTable.js +83 -0
  47. package/dist/fe/components/DataTable/components/SortIcon.js +39 -0
  48. package/dist/fe/components/DataTable/components/TableHeader.js +49 -0
  49. package/dist/fe/components/DataTable/components/TableRow.js +118 -0
  50. package/dist/fe/components/DataTable/components/index.js +14 -0
  51. package/dist/fe/components/DataTable/hooks/index.js +2 -0
  52. package/dist/fe/components/DataTable/hooks/useAutoFitColumn.js +23 -0
  53. package/dist/fe/components/DataTable/hooks/useResizeColumn.js +122 -0
  54. package/dist/fe/components/DataTable/index.js +3 -0
  55. package/dist/fe/components/DataTable/store/index.js +97 -0
  56. package/dist/fe/components/DataTable/theme/index.js +144 -0
  57. package/dist/fe/components/DataTable/types/index.js +1 -0
  58. package/dist/fe/components/DataTable/utils/cn.js +5 -0
  59. package/dist/fe/components/DatePicker/components/CalendarGrid.js +95 -0
  60. package/dist/fe/components/DatePicker/components/CalendarHeader.js +152 -0
  61. package/dist/fe/components/DatePicker/components/DatePicker.js +381 -0
  62. package/dist/fe/components/DatePicker/components/MonthYearSelector.js +93 -0
  63. package/dist/fe/components/DatePicker/index.js +7 -0
  64. package/dist/fe/components/DatePicker/locales/index.js +1113 -0
  65. package/dist/fe/components/DatePicker/theme/index.js +315 -0
  66. package/dist/fe/components/DatePicker/types/index.js +1 -0
  67. package/dist/fe/components/DatePicker/utils/cn.js +5 -0
  68. package/dist/fe/components/DatePicker/utils/date.js +132 -0
  69. package/dist/fe/components/DevicesPage/components/DeviceCard.js +251 -0
  70. package/dist/fe/components/DevicesPage/components/DevicesHeader.js +42 -0
  71. package/dist/fe/components/DevicesPage/components/DevicesPage.js +450 -0
  72. package/dist/fe/components/DevicesPage/index.js +5 -0
  73. package/dist/fe/components/DevicesPage/store/index.js +55 -0
  74. package/dist/fe/components/DevicesPage/theme/index.js +131 -0
  75. package/dist/fe/components/DevicesPage/types/index.js +1 -0
  76. package/dist/fe/components/ForgotPasswordPage/components/ForgotPasswordForm.js +214 -0
  77. package/dist/fe/components/ForgotPasswordPage/components/ForgotPasswordHeader.js +42 -0
  78. package/dist/fe/components/ForgotPasswordPage/components/ForgotPasswordPage.js +59 -0
  79. package/dist/fe/components/ForgotPasswordPage/index.js +5 -0
  80. package/dist/fe/components/ForgotPasswordPage/store/index.js +28 -0
  81. package/dist/fe/components/ForgotPasswordPage/theme/index.js +87 -0
  82. package/dist/fe/components/ForgotPasswordPage/types/index.js +1 -0
  83. package/dist/fe/components/FormBuilder/components/FormBuilder.js +156 -0
  84. package/dist/fe/components/FormBuilder/components/FormField.js +218 -0
  85. package/dist/fe/components/FormBuilder/hooks/useFormBuilder.js +152 -0
  86. package/dist/fe/components/FormBuilder/index.js +4 -0
  87. package/dist/fe/components/FormBuilder/theme/index.js +134 -0
  88. package/dist/fe/components/FormBuilder/types/index.js +1 -0
  89. package/dist/fe/components/FormBuilder/utils/cn.js +5 -0
  90. package/dist/fe/components/FormBuilder/utils/fieldMapping.js +216 -0
  91. package/dist/fe/components/FormBuilder/utils/validation.js +78 -0
  92. package/dist/fe/components/LoginPage/components/LoginForm.js +214 -0
  93. package/dist/fe/components/LoginPage/components/LoginHeader.js +24 -0
  94. package/dist/fe/components/LoginPage/components/LoginPage.js +138 -0
  95. package/dist/fe/components/LoginPage/index.js +5 -0
  96. package/dist/fe/components/LoginPage/store/index.js +59 -0
  97. package/dist/fe/components/LoginPage/theme/index.js +98 -0
  98. package/dist/fe/components/LoginPage/types/index.js +1 -0
  99. package/dist/fe/components/MagicLinkVerifyPage/components/MagicLinkVerifyPage.js +200 -0
  100. package/dist/fe/components/MagicLinkVerifyPage/index.js +3 -0
  101. package/dist/fe/components/MagicLinkVerifyPage/store.js +20 -0
  102. package/dist/fe/components/MagicLinkVerifyPage/theme.js +36 -0
  103. package/dist/fe/components/MagicLinkVerifyPage/types.js +1 -0
  104. package/dist/fe/components/NucleusEntityShowcase.js +1409 -0
  105. package/dist/fe/components/NucleusTextInput/components/FloatingLabel.js +56 -0
  106. package/dist/fe/components/NucleusTextInput/components/InputIcons.js +258 -0
  107. package/dist/fe/components/NucleusTextInput/components/NucleusTextInput.js +321 -0
  108. package/dist/fe/components/NucleusTextInput/components/PasswordStrengthIndicator.js +104 -0
  109. package/dist/fe/components/NucleusTextInput/components/TypewriterText.js +56 -0
  110. package/dist/fe/components/NucleusTextInput/index.js +7 -0
  111. package/dist/fe/components/NucleusTextInput/theme/index.js +121 -0
  112. package/dist/fe/components/NucleusTextInput/types/index.js +1 -0
  113. package/dist/fe/components/NucleusTextInput/utils/cn.js +5 -0
  114. package/dist/fe/components/NucleusTextInput/utils/format.js +62 -0
  115. package/dist/fe/components/NucleusTextInput/utils/validation.js +191 -0
  116. package/dist/fe/components/ProfilePage/components/AddressCard.js +196 -0
  117. package/dist/fe/components/ProfilePage/components/PhoneCard.js +206 -0
  118. package/dist/fe/components/ProfilePage/components/ProfileHeader.js +150 -0
  119. package/dist/fe/components/ProfilePage/components/ProfilePage.js +1336 -0
  120. package/dist/fe/components/ProfilePage/index.js +6 -0
  121. package/dist/fe/components/ProfilePage/store/index.js +115 -0
  122. package/dist/fe/components/ProfilePage/theme/index.js +168 -0
  123. package/dist/fe/components/ProfilePage/types/index.js +1 -0
  124. package/dist/fe/components/RangePicker/components/RangePicker.js +338 -0
  125. package/dist/fe/components/RangePicker/components/RangeThumb.js +68 -0
  126. package/dist/fe/components/RangePicker/components/RangeTooltip.js +45 -0
  127. package/dist/fe/components/RangePicker/components/RangeTrack.js +32 -0
  128. package/dist/fe/components/RangePicker/index.js +5 -0
  129. package/dist/fe/components/RangePicker/theme/index.js +88 -0
  130. package/dist/fe/components/RangePicker/types/index.js +1 -0
  131. package/dist/fe/components/RangePicker/utils/cn.js +3 -0
  132. package/dist/fe/components/RegisterPage/components/PasswordStrengthIndicator.js +107 -0
  133. package/dist/fe/components/RegisterPage/components/RegisterForm.js +322 -0
  134. package/dist/fe/components/RegisterPage/components/RegisterHeader.js +23 -0
  135. package/dist/fe/components/RegisterPage/components/RegisterPage.js +85 -0
  136. package/dist/fe/components/RegisterPage/index.js +6 -0
  137. package/dist/fe/components/RegisterPage/store/index.js +106 -0
  138. package/dist/fe/components/RegisterPage/theme/index.js +128 -0
  139. package/dist/fe/components/RegisterPage/types/index.js +1 -0
  140. package/dist/fe/components/ResetPasswordPage/components/ResetPasswordForm.js +347 -0
  141. package/dist/fe/components/ResetPasswordPage/components/ResetPasswordHeader.js +42 -0
  142. package/dist/fe/components/ResetPasswordPage/components/ResetPasswordPage.js +61 -0
  143. package/dist/fe/components/ResetPasswordPage/index.js +5 -0
  144. package/dist/fe/components/ResetPasswordPage/store/index.js +36 -0
  145. package/dist/fe/components/ResetPasswordPage/theme/index.js +99 -0
  146. package/dist/fe/components/ResetPasswordPage/types/index.js +1 -0
  147. package/dist/fe/components/SearchBox/components/SearchBox.js +271 -0
  148. package/dist/fe/components/SearchBox/components/SearchBoxDropdown.js +87 -0
  149. package/dist/fe/components/SearchBox/index.js +5 -0
  150. package/dist/fe/components/SearchBox/theme/index.js +184 -0
  151. package/dist/fe/components/SearchBox/types/index.js +1 -0
  152. package/dist/fe/components/SearchBox/utils/cn.js +5 -0
  153. package/dist/fe/components/SearchBox/utils/debounce.js +22 -0
  154. package/dist/fe/components/SearchBox/utils/sanitize.js +48 -0
  155. package/dist/fe/components/SelectBox/components/SelectBox.js +364 -0
  156. package/dist/fe/components/SelectBox/components/SelectDropdown.js +92 -0
  157. package/dist/fe/components/SelectBox/components/SelectOptionItem.js +43 -0
  158. package/dist/fe/components/SelectBox/components/SelectTrigger.js +22 -0
  159. package/dist/fe/components/SelectBox/index.js +5 -0
  160. package/dist/fe/components/SelectBox/theme/index.js +98 -0
  161. package/dist/fe/components/SelectBox/types/index.js +1 -0
  162. package/dist/fe/components/SelectBox/utils/cn.js +3 -0
  163. package/dist/fe/components/SetPasswordPage/components/PasswordStrengthIndicator.js +107 -0
  164. package/dist/fe/components/SetPasswordPage/components/SetPasswordForm.js +142 -0
  165. package/dist/fe/components/SetPasswordPage/components/SetPasswordHeader.js +23 -0
  166. package/dist/fe/components/SetPasswordPage/components/SetPasswordPage.js +263 -0
  167. package/dist/fe/components/SetPasswordPage/index.js +7 -0
  168. package/dist/fe/components/SetPasswordPage/store/index.js +79 -0
  169. package/dist/fe/components/SetPasswordPage/theme/index.js +98 -0
  170. package/dist/fe/components/SetPasswordPage/types/index.js +12 -0
  171. package/dist/fe/components/UsersPage/components/InviteUserModal.js +262 -0
  172. package/dist/fe/components/UsersPage/components/Pagination.js +147 -0
  173. package/dist/fe/components/UsersPage/components/RoleAssignmentModal.js +186 -0
  174. package/dist/fe/components/UsersPage/components/StatsCards.js +124 -0
  175. package/dist/fe/components/UsersPage/components/UserDetailDrawer.js +444 -0
  176. package/dist/fe/components/UsersPage/components/UserFilters.js +142 -0
  177. package/dist/fe/components/UsersPage/components/UserListItem.js +125 -0
  178. package/dist/fe/components/UsersPage/components/UserListSkeleton.js +40 -0
  179. package/dist/fe/components/UsersPage/components/UsersPage.js +556 -0
  180. package/dist/fe/components/UsersPage/index.js +10 -0
  181. package/dist/fe/components/UsersPage/store/index.js +151 -0
  182. package/dist/fe/components/UsersPage/theme/index.js +231 -0
  183. package/dist/fe/components/UsersPage/types/index.js +1 -0
  184. package/dist/fe/components/VerifyEmailPage/components/VerifyEmailPage.js +290 -0
  185. package/dist/fe/components/VerifyEmailPage/index.js +3 -0
  186. package/dist/fe/components/VerifyEmailPage/store/index.js +45 -0
  187. package/dist/fe/components/VerifyEmailPage/theme/index.js +52 -0
  188. package/dist/fe/components/VerifyEmailPage/types/index.js +1 -0
  189. package/dist/fe/hooks/useNucleusEntity.js +247 -0
  190. package/dist/fe/index.js +28 -157
  191. package/dist/fe/types/index.js +1 -0
  192. package/dist/fe/utils/cn.js +5 -0
  193. package/dist/fe/utils/columnUtils.js +189 -0
  194. package/dist/fe/utils/endpointKeys.js +44 -0
  195. package/dist/index.js +1 -1
  196. package/dist/src/Client/Proxy/httpProxy.js +1 -0
  197. package/dist/src/Client/Proxy/index.js +1 -1
  198. package/dist/src/Client/Proxy/server.js +1 -0
  199. package/dist/src/Client/Proxy/types.js +1 -0
  200. package/dist/src/Client/Proxy/utils.js +1 -0
  201. package/dist/src/Client/Proxy/wsProxy.js +1 -0
  202. package/package.json +1 -1
  203. package/scripts/build.ts +32 -16
@@ -0,0 +1,841 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useGSAP } from "@gsap/react";
4
+ import gsap from "gsap";
5
+ import { useEffect, useEffectEvent, useRef, useState } from "react";
6
+ import { cn } from "../../../utils/cn";
7
+ import { useAuthorizationStore } from "../store";
8
+ gsap.registerPlugin(useGSAP);
9
+ const METHOD_COLORS = {
10
+ GET: "bg-blue-500/10 text-blue-600 dark:text-blue-400 border-blue-500/20",
11
+ POST: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-500/20",
12
+ PUT: "bg-amber-500/10 text-amber-600 dark:text-amber-400 border-amber-500/20",
13
+ PATCH: "bg-orange-500/10 text-orange-600 dark:text-orange-400 border-orange-500/20",
14
+ DELETE: "bg-red-500/10 text-red-600 dark:text-red-400 border-red-500/20"
15
+ };
16
+ export function AuthorizationPage({ title = "Authorization Management", subtitle, className, defaultEntityFilter = "all", defaultMethodFilter = "all", defaultShowAssignedOnly = false, getRolesAction, addRoleAction, updateRoleAction, deleteRoleAction, getClaimsAction, getRoleClaimsAction, addRoleClaimAction, updateRoleClaimAction, deleteRoleClaimAction, onRoleCreated, onRoleDeleted, onClaimToggled }) {
17
+ const store = useAuthorizationStore();
18
+ const containerRef = useRef(null);
19
+ const contentRef = useRef(null);
20
+ const [expandedEntities, setExpandedEntities] = useState(new Set());
21
+ const [localSearch, setLocalSearch] = useState("");
22
+ useGSAP(()=>{
23
+ if (!contentRef.current) return;
24
+ gsap.fromTo(contentRef.current, {
25
+ opacity: 0,
26
+ y: 10
27
+ }, {
28
+ opacity: 1,
29
+ y: 0,
30
+ duration: 0.3,
31
+ ease: "power2.out"
32
+ });
33
+ }, {
34
+ scope: containerRef
35
+ });
36
+ const fetchRoles = useEffectEvent(()=>{
37
+ getRolesAction.start({
38
+ payload: {
39
+ page: 1,
40
+ limit: 100
41
+ },
42
+ onAfterHandle: (data)=>{
43
+ if (data.data?.items) {
44
+ store.setRoles(data.data.items);
45
+ }
46
+ }
47
+ });
48
+ });
49
+ const fetchClaims = useEffectEvent(()=>{
50
+ getClaimsAction.start({
51
+ payload: {
52
+ page: 1,
53
+ limit: 1000
54
+ },
55
+ onAfterHandle: (data)=>{
56
+ if (data.data?.items) {
57
+ store.setClaims(data.data.items);
58
+ }
59
+ }
60
+ });
61
+ });
62
+ const fetchRoleClaims = useEffectEvent((roleId)=>{
63
+ getRoleClaimsAction.start({
64
+ payload: {
65
+ page: 1,
66
+ limit: 1000,
67
+ filters: [
68
+ {
69
+ field: "role_id",
70
+ operator: "eq",
71
+ value: roleId
72
+ }
73
+ ]
74
+ },
75
+ onAfterHandle: (data)=>{
76
+ if (data.data?.items) {
77
+ store.setRoleClaims(data.data.items);
78
+ }
79
+ }
80
+ });
81
+ });
82
+ useEffect(()=>{
83
+ fetchRoles();
84
+ fetchClaims();
85
+ }, []);
86
+ const initializeFilters = useEffectEvent(()=>{
87
+ store.setEntityFilter(defaultEntityFilter);
88
+ store.setMethodFilter(defaultMethodFilter);
89
+ store.setShowAssignedOnly(defaultShowAssignedOnly);
90
+ });
91
+ useEffect(()=>{
92
+ initializeFilters();
93
+ }, []);
94
+ useEffect(()=>{
95
+ if (store.selectedRole) {
96
+ fetchRoleClaims(store.selectedRole.id);
97
+ } else {
98
+ store.setRoleClaims([]);
99
+ }
100
+ }, [
101
+ store.selectedRole
102
+ ]);
103
+ const handleCreateRole = useEffectEvent(()=>{
104
+ if (!store.newRoleName.trim()) return;
105
+ const tempId = `temp-${Date.now()}`;
106
+ const optimisticRole = {
107
+ id: tempId,
108
+ name: store.newRoleName.trim(),
109
+ description: store.newRoleDescription.trim() || "",
110
+ createdAt: new Date(),
111
+ updatedAt: new Date()
112
+ };
113
+ store.addRole(optimisticRole);
114
+ store.resetForm();
115
+ addRoleAction.start({
116
+ payload: {
117
+ name: optimisticRole.name,
118
+ description: optimisticRole.description || undefined
119
+ },
120
+ onAfterHandle: (data)=>{
121
+ fetchRoles();
122
+ if (data.data) {
123
+ onRoleCreated?.(data.data);
124
+ }
125
+ },
126
+ onErrorHandle: ()=>{
127
+ store.removeRole(tempId);
128
+ }
129
+ });
130
+ });
131
+ const handleDeleteRole = useEffectEvent((roleId)=>{
132
+ const roleToDelete = store.roles.find((r)=>r.id === roleId);
133
+ if (!roleToDelete) return;
134
+ store.removeRole(roleId);
135
+ deleteRoleAction.start({
136
+ payload: {
137
+ id: roleId
138
+ },
139
+ onAfterHandle: ()=>{
140
+ fetchRoles();
141
+ onRoleDeleted?.(roleId);
142
+ },
143
+ onErrorHandle: ()=>{
144
+ if (roleToDelete) {
145
+ store.addRole(roleToDelete);
146
+ }
147
+ }
148
+ });
149
+ });
150
+ const handleStartEditRole = useEffectEvent((role)=>{
151
+ store.setEditingRoleId(role.id);
152
+ store.setEditRoleDescription(role.description || "");
153
+ });
154
+ const handleCancelEditRole = useEffectEvent(()=>{
155
+ store.setEditingRoleId(null);
156
+ });
157
+ const handleSaveRoleDescription = useEffectEvent(()=>{
158
+ const roleId = store.editingRoleId;
159
+ if (!roleId || !updateRoleAction) return;
160
+ const role = store.roles.find((r)=>r.id === roleId);
161
+ if (!role) return;
162
+ const oldDescription = role.description;
163
+ const newDescription = store.editRoleDescription;
164
+ store.updateRole(roleId, {
165
+ description: newDescription
166
+ });
167
+ store.setEditingRoleId(null);
168
+ updateRoleAction.start({
169
+ payload: {
170
+ id: roleId,
171
+ description: newDescription
172
+ },
173
+ onAfterHandle: ()=>{
174
+ fetchRoles();
175
+ },
176
+ onErrorHandle: ()=>{
177
+ store.updateRole(roleId, {
178
+ description: oldDescription
179
+ });
180
+ }
181
+ });
182
+ });
183
+ const handleToggleClaim = useEffectEvent((claim, isAssigned)=>{
184
+ const currentRole = store.selectedRole;
185
+ if (!currentRole) return;
186
+ const roleId = currentRole.id;
187
+ if (isAssigned) {
188
+ const existingRoleClaim = store.roleClaims.find((rc)=>rc.claimId === claim.id);
189
+ if (!existingRoleClaim) return;
190
+ store.removeRoleClaim(existingRoleClaim.id);
191
+ deleteRoleClaimAction.start({
192
+ payload: {
193
+ id: existingRoleClaim.id
194
+ },
195
+ onAfterHandle: ()=>{
196
+ fetchRoleClaims(roleId);
197
+ onClaimToggled?.(claim, false);
198
+ },
199
+ onErrorHandle: ()=>{
200
+ store.addRoleClaim(existingRoleClaim);
201
+ }
202
+ });
203
+ } else {
204
+ const tempId = `temp-${Date.now()}`;
205
+ const optimisticRoleClaim = {
206
+ id: tempId,
207
+ roleId: roleId,
208
+ claimId: claim.id,
209
+ scope: "",
210
+ createdAt: new Date(),
211
+ updatedAt: new Date()
212
+ };
213
+ store.addRoleClaim(optimisticRoleClaim);
214
+ addRoleClaimAction.start({
215
+ payload: {
216
+ roleId: roleId,
217
+ claimId: claim.id
218
+ },
219
+ onAfterHandle: ()=>{
220
+ fetchRoleClaims(roleId);
221
+ onClaimToggled?.(claim, true);
222
+ },
223
+ onErrorHandle: ()=>{
224
+ store.removeRoleClaim(tempId);
225
+ }
226
+ });
227
+ }
228
+ });
229
+ const handleSelectRole = useEffectEvent((role)=>{
230
+ store.setSelectedRole(role);
231
+ });
232
+ const handleSearchChange = useEffectEvent((value)=>{
233
+ store.setSearchClaim(value);
234
+ });
235
+ const handleEntityFilterChange = useEffectEvent((value)=>{
236
+ store.setEntityFilter(value || "all");
237
+ });
238
+ const handleMethodFilterChange = useEffectEvent((value)=>{
239
+ store.setMethodFilter(value || "all");
240
+ });
241
+ const handleAssignedToggle = useEffectEvent((value)=>{
242
+ store.setShowAssignedOnly(value);
243
+ });
244
+ const handleUpdateScope = useEffectEvent((roleClaimId, scope)=>{
245
+ if (!updateRoleClaimAction || !store.selectedRole) return;
246
+ store.updateRoleClaimScope(roleClaimId, scope);
247
+ updateRoleClaimAction.start({
248
+ payload: {
249
+ id: roleClaimId,
250
+ scope
251
+ },
252
+ onAfterHandle: ()=>{
253
+ fetchRoleClaims(store.selectedRole?.id || "");
254
+ },
255
+ onErrorHandle: ()=>{
256
+ fetchRoleClaims(store.selectedRole?.id || "");
257
+ }
258
+ });
259
+ });
260
+ const getClaimEntity = (action)=>{
261
+ const parts = action.split(".");
262
+ if (parts[1] === "bulk") {
263
+ return parts[2] || "bulk";
264
+ }
265
+ return parts[1] || "other";
266
+ };
267
+ const normalizedSearch = store.searchClaim.trim().toLowerCase();
268
+ const entityFilter = store.entityFilter.toLowerCase();
269
+ const methodFilter = store.methodFilter.toLowerCase();
270
+ const assignedOnlyActive = store.showAssignedOnly && !!store.selectedRole;
271
+ const assignedClaimIds = new Set(store.roleClaims.map((rc)=>rc.claimId));
272
+ const filteredClaims = store.claims.filter((claim)=>{
273
+ const matchesSearch = normalizedSearch ? claim.action.toLowerCase().includes(normalizedSearch) || claim.description.toLowerCase().includes(normalizedSearch) : true;
274
+ const claimEntity = getClaimEntity(claim.action).toLowerCase();
275
+ const matchesEntity = entityFilter === "all" || claimEntity === entityFilter;
276
+ const matchesMethod = methodFilter === "all" || claim.method.toLowerCase() === methodFilter;
277
+ const matchesAssigned = assignedOnlyActive ? assignedClaimIds.has(claim.id) : true;
278
+ return matchesSearch && matchesEntity && matchesMethod && matchesAssigned;
279
+ });
280
+ const entityOptions = [
281
+ {
282
+ value: "all",
283
+ label: "All Entities"
284
+ },
285
+ ...Array.from(new Set(store.claims.map((claim)=>getClaimEntity(claim.action)))).sort((a, b)=>a.localeCompare(b)).map((entity)=>({
286
+ value: entity,
287
+ label: entity
288
+ }))
289
+ ];
290
+ const methodOptions = [
291
+ {
292
+ value: "all",
293
+ label: "All Methods"
294
+ },
295
+ {
296
+ value: "get",
297
+ label: "GET"
298
+ },
299
+ {
300
+ value: "post",
301
+ label: "POST"
302
+ },
303
+ {
304
+ value: "put",
305
+ label: "PUT"
306
+ },
307
+ {
308
+ value: "patch",
309
+ label: "PATCH"
310
+ },
311
+ {
312
+ value: "delete",
313
+ label: "DELETE"
314
+ }
315
+ ];
316
+ const groupedFilteredClaims = filteredClaims.reduce((acc, claim)=>{
317
+ const entity = getClaimEntity(claim.action);
318
+ if (!acc[entity]) acc[entity] = [];
319
+ acc[entity].push(claim);
320
+ return acc;
321
+ }, {});
322
+ const sortedEntities = Object.keys(groupedFilteredClaims).sort((a, b)=>a.localeCompare(b));
323
+ const toggleEntity = (entity)=>{
324
+ setExpandedEntities((prev)=>{
325
+ const next = new Set(prev);
326
+ if (next.has(entity)) {
327
+ next.delete(entity);
328
+ } else {
329
+ next.add(entity);
330
+ }
331
+ return next;
332
+ });
333
+ };
334
+ const expandAll = ()=>{
335
+ setExpandedEntities(new Set(sortedEntities));
336
+ };
337
+ const collapseAll = ()=>{
338
+ setExpandedEntities(new Set());
339
+ };
340
+ const handleBulkAssign = (entity, assign)=>{
341
+ const entityClaims = groupedFilteredClaims[entity] || [];
342
+ for (const claim of entityClaims){
343
+ const isAssigned = assignedClaimIds.has(claim.id);
344
+ if (assign && !isAssigned) {
345
+ handleToggleClaim(claim, false);
346
+ } else if (!assign && isAssigned) {
347
+ handleToggleClaim(claim, true);
348
+ }
349
+ }
350
+ };
351
+ const getEntityAssignedCount = (entity)=>{
352
+ const entityClaims = groupedFilteredClaims[entity] || [];
353
+ return entityClaims.filter((c)=>assignedClaimIds.has(c.id)).length;
354
+ };
355
+ const getRoleClaimForClaim = (claimId)=>store.roleClaims.find((rc)=>rc.claimId === claimId);
356
+ const handleScopeSubmit = (roleClaimId)=>{
357
+ if (updateRoleClaimAction && store.scopeInputValue !== undefined) {
358
+ handleUpdateScope(roleClaimId, store.scopeInputValue);
359
+ store.setEditingScopeClaimId(null);
360
+ }
361
+ };
362
+ const startEditingScope = (claimId, currentScope)=>{
363
+ store.setScopeInputValue(currentScope || "");
364
+ store.setEditingScopeClaimId(claimId);
365
+ };
366
+ return /*#__PURE__*/ _jsx("main", {
367
+ ref: containerRef,
368
+ className: cn("min-h-screen bg-zinc-50 dark:bg-zinc-950 p-4 sm:p-6 lg:p-8", className),
369
+ children: /*#__PURE__*/ _jsxs("div", {
370
+ ref: contentRef,
371
+ className: "max-w-[1600px] mx-auto",
372
+ children: [
373
+ /*#__PURE__*/ _jsxs("header", {
374
+ className: "mb-6",
375
+ children: [
376
+ /*#__PURE__*/ _jsx("h1", {
377
+ className: "text-2xl sm:text-3xl font-bold text-zinc-900 dark:text-zinc-100",
378
+ children: title
379
+ }),
380
+ subtitle && /*#__PURE__*/ _jsx("p", {
381
+ className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400",
382
+ children: subtitle
383
+ })
384
+ ]
385
+ }),
386
+ /*#__PURE__*/ _jsxs("div", {
387
+ className: "grid grid-cols-1 xl:grid-cols-[320px_1fr] gap-6",
388
+ children: [
389
+ /*#__PURE__*/ _jsxs("aside", {
390
+ className: "space-y-4",
391
+ children: [
392
+ /*#__PURE__*/ _jsxs("div", {
393
+ className: "bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-4",
394
+ children: [
395
+ /*#__PURE__*/ _jsx("h2", {
396
+ className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100 mb-3",
397
+ children: "Roles"
398
+ }),
399
+ /*#__PURE__*/ _jsxs("div", {
400
+ className: "space-y-2 mb-4",
401
+ children: [
402
+ /*#__PURE__*/ _jsx("input", {
403
+ type: "text",
404
+ value: store.newRoleName,
405
+ onChange: (e)=>store.setNewRoleName(e.target.value),
406
+ placeholder: "New role name",
407
+ className: "w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-700 rounded-lg bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400"
408
+ }),
409
+ /*#__PURE__*/ _jsx("button", {
410
+ type: "button",
411
+ onClick: handleCreateRole,
412
+ disabled: !store.newRoleName.trim() || addRoleAction.state.isPending,
413
+ className: "w-full px-3 py-2 text-sm font-medium text-white bg-emerald-600 hover:bg-emerald-700 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg transition-colors",
414
+ children: addRoleAction.state.isPending ? "Creating..." : "Create Role"
415
+ })
416
+ ]
417
+ }),
418
+ /*#__PURE__*/ _jsx("div", {
419
+ className: "space-y-1 max-h-[300px] overflow-y-auto",
420
+ children: store.roles.map((role)=>/*#__PURE__*/ _jsxs("div", {
421
+ className: cn("w-full text-left px-3 py-2 rounded-lg text-sm transition-colors group", role.id.startsWith("temp-") && "opacity-50", store.selectedRole?.id === role.id ? "bg-emerald-100 dark:bg-emerald-900/30 text-emerald-900 dark:text-emerald-100" : "hover:bg-zinc-100 dark:hover:bg-zinc-800 text-zinc-700 dark:text-zinc-300"),
422
+ children: [
423
+ /*#__PURE__*/ _jsxs("div", {
424
+ className: "flex items-center justify-between",
425
+ children: [
426
+ /*#__PURE__*/ _jsx("button", {
427
+ type: "button",
428
+ onClick: ()=>handleSelectRole(role),
429
+ disabled: role.id.startsWith("temp-"),
430
+ className: "flex-1 text-left truncate disabled:cursor-not-allowed font-medium",
431
+ children: role.name
432
+ }),
433
+ /*#__PURE__*/ _jsxs("div", {
434
+ className: "flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity",
435
+ children: [
436
+ role.name !== "godmin" && !role.id.startsWith("temp-") && updateRoleAction && /*#__PURE__*/ _jsx("button", {
437
+ type: "button",
438
+ onClick: ()=>handleStartEditRole(role),
439
+ className: "p-1 text-zinc-500 hover:text-emerald-600 transition-colors",
440
+ title: "Edit description",
441
+ children: /*#__PURE__*/ _jsx("svg", {
442
+ className: "w-4 h-4",
443
+ fill: "none",
444
+ stroke: "currentColor",
445
+ viewBox: "0 0 24 24",
446
+ "aria-hidden": "true",
447
+ children: /*#__PURE__*/ _jsx("path", {
448
+ strokeLinecap: "round",
449
+ strokeLinejoin: "round",
450
+ strokeWidth: 2,
451
+ d: "M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
452
+ })
453
+ })
454
+ }),
455
+ role.name !== "godmin" && !role.id.startsWith("temp-") && /*#__PURE__*/ _jsx("button", {
456
+ type: "button",
457
+ onClick: ()=>handleDeleteRole(role.id),
458
+ className: "p-1 text-red-500 hover:text-red-700 transition-colors",
459
+ title: "Delete role",
460
+ children: /*#__PURE__*/ _jsx("svg", {
461
+ className: "w-4 h-4",
462
+ fill: "none",
463
+ stroke: "currentColor",
464
+ viewBox: "0 0 24 24",
465
+ "aria-hidden": "true",
466
+ children: /*#__PURE__*/ _jsx("path", {
467
+ strokeLinecap: "round",
468
+ strokeLinejoin: "round",
469
+ strokeWidth: 2,
470
+ d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
471
+ })
472
+ })
473
+ })
474
+ ]
475
+ })
476
+ ]
477
+ }),
478
+ store.editingRoleId === role.id ? /*#__PURE__*/ _jsxs("div", {
479
+ className: "mt-2 space-y-2",
480
+ children: [
481
+ /*#__PURE__*/ _jsx("textarea", {
482
+ value: store.editRoleDescription,
483
+ onChange: (e)=>store.setEditRoleDescription(e.target.value),
484
+ placeholder: "Enter description...",
485
+ rows: 2,
486
+ className: "w-full px-2 py-1.5 text-xs border border-zinc-200 dark:border-zinc-700 rounded bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 resize-none"
487
+ }),
488
+ /*#__PURE__*/ _jsxs("div", {
489
+ className: "flex gap-2",
490
+ children: [
491
+ /*#__PURE__*/ _jsx("button", {
492
+ type: "button",
493
+ onClick: handleSaveRoleDescription,
494
+ className: "flex-1 px-2 py-1 text-xs font-medium text-white bg-emerald-600 hover:bg-emerald-700 rounded transition-colors",
495
+ children: "Save"
496
+ }),
497
+ /*#__PURE__*/ _jsx("button", {
498
+ type: "button",
499
+ onClick: handleCancelEditRole,
500
+ className: "flex-1 px-2 py-1 text-xs font-medium text-zinc-600 dark:text-zinc-400 bg-zinc-100 dark:bg-zinc-800 hover:bg-zinc-200 dark:hover:bg-zinc-700 rounded transition-colors",
501
+ children: "Cancel"
502
+ })
503
+ ]
504
+ })
505
+ ]
506
+ }) : role.description && /*#__PURE__*/ _jsx("p", {
507
+ className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400 truncate",
508
+ children: role.description
509
+ })
510
+ ]
511
+ }, role.id))
512
+ })
513
+ ]
514
+ }),
515
+ /*#__PURE__*/ _jsxs("div", {
516
+ className: "bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-4",
517
+ children: [
518
+ /*#__PURE__*/ _jsx("h2", {
519
+ className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100 mb-3",
520
+ children: "Filters"
521
+ }),
522
+ /*#__PURE__*/ _jsxs("div", {
523
+ className: "space-y-3",
524
+ children: [
525
+ /*#__PURE__*/ _jsxs("div", {
526
+ children: [
527
+ /*#__PURE__*/ _jsx("label", {
528
+ htmlFor: "claim-search",
529
+ className: "block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1",
530
+ children: "Search"
531
+ }),
532
+ /*#__PURE__*/ _jsx("input", {
533
+ id: "claim-search",
534
+ type: "text",
535
+ value: localSearch,
536
+ onChange: (e)=>{
537
+ setLocalSearch(e.target.value);
538
+ handleSearchChange(e.target.value);
539
+ },
540
+ placeholder: "Search claims...",
541
+ className: "w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-700 rounded-lg bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400"
542
+ })
543
+ ]
544
+ }),
545
+ /*#__PURE__*/ _jsxs("div", {
546
+ children: [
547
+ /*#__PURE__*/ _jsx("label", {
548
+ htmlFor: "entity-filter",
549
+ className: "block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1",
550
+ children: "Entity"
551
+ }),
552
+ /*#__PURE__*/ _jsx("select", {
553
+ id: "entity-filter",
554
+ value: store.entityFilter,
555
+ onChange: (e)=>handleEntityFilterChange(e.target.value),
556
+ className: "w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-700 rounded-lg bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100",
557
+ children: entityOptions.map((opt)=>/*#__PURE__*/ _jsx("option", {
558
+ value: opt.value,
559
+ children: opt.label
560
+ }, opt.value))
561
+ })
562
+ ]
563
+ }),
564
+ /*#__PURE__*/ _jsxs("div", {
565
+ children: [
566
+ /*#__PURE__*/ _jsx("label", {
567
+ htmlFor: "method-filter",
568
+ className: "block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1",
569
+ children: "Method"
570
+ }),
571
+ /*#__PURE__*/ _jsx("select", {
572
+ id: "method-filter",
573
+ value: store.methodFilter,
574
+ onChange: (e)=>handleMethodFilterChange(e.target.value),
575
+ className: "w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-700 rounded-lg bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100",
576
+ children: methodOptions.map((opt)=>/*#__PURE__*/ _jsx("option", {
577
+ value: opt.value,
578
+ children: opt.label
579
+ }, opt.value))
580
+ })
581
+ ]
582
+ }),
583
+ /*#__PURE__*/ _jsxs("label", {
584
+ className: "flex items-center gap-2 cursor-pointer",
585
+ children: [
586
+ /*#__PURE__*/ _jsx("input", {
587
+ type: "checkbox",
588
+ checked: store.showAssignedOnly,
589
+ onChange: (e)=>handleAssignedToggle(e.target.checked),
590
+ disabled: !store.selectedRole,
591
+ className: "w-4 h-4 rounded border-zinc-300 dark:border-zinc-600 text-emerald-600 focus:ring-emerald-500 disabled:opacity-50"
592
+ }),
593
+ /*#__PURE__*/ _jsx("span", {
594
+ className: cn("text-sm", !store.selectedRole ? "text-zinc-400" : "text-zinc-700 dark:text-zinc-300"),
595
+ children: "Show assigned only"
596
+ })
597
+ ]
598
+ })
599
+ ]
600
+ })
601
+ ]
602
+ }),
603
+ store.selectedRole && /*#__PURE__*/ _jsxs("div", {
604
+ className: "bg-emerald-50 dark:bg-emerald-900/20 rounded-xl border border-emerald-200 dark:border-emerald-800 p-4",
605
+ children: [
606
+ /*#__PURE__*/ _jsx("div", {
607
+ className: "text-sm font-medium text-emerald-900 dark:text-emerald-100",
608
+ children: store.selectedRole.name
609
+ }),
610
+ /*#__PURE__*/ _jsx("div", {
611
+ className: "text-2xl font-bold text-emerald-600 dark:text-emerald-400 mt-1",
612
+ children: store.roleClaims.length
613
+ }),
614
+ /*#__PURE__*/ _jsx("div", {
615
+ className: "text-xs text-emerald-700 dark:text-emerald-300",
616
+ children: "claims assigned"
617
+ })
618
+ ]
619
+ })
620
+ ]
621
+ }),
622
+ /*#__PURE__*/ _jsxs("section", {
623
+ className: "bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800",
624
+ children: [
625
+ /*#__PURE__*/ _jsxs("div", {
626
+ className: "p-4 border-b border-zinc-200 dark:border-zinc-800 flex flex-wrap items-center justify-between gap-3",
627
+ children: [
628
+ /*#__PURE__*/ _jsxs("div", {
629
+ children: [
630
+ /*#__PURE__*/ _jsx("h2", {
631
+ className: "text-lg font-semibold text-zinc-900 dark:text-zinc-100",
632
+ children: "Claims"
633
+ }),
634
+ /*#__PURE__*/ _jsxs("p", {
635
+ className: "text-sm text-zinc-500 dark:text-zinc-400",
636
+ children: [
637
+ filteredClaims.length,
638
+ " of ",
639
+ store.claims.length,
640
+ " claims •",
641
+ " ",
642
+ sortedEntities.length,
643
+ " entities"
644
+ ]
645
+ })
646
+ ]
647
+ }),
648
+ /*#__PURE__*/ _jsxs("div", {
649
+ className: "flex items-center gap-2",
650
+ children: [
651
+ /*#__PURE__*/ _jsx("button", {
652
+ type: "button",
653
+ onClick: expandAll,
654
+ className: "px-3 py-1.5 text-xs font-medium text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 border border-zinc-200 dark:border-zinc-700 rounded-lg transition-colors",
655
+ children: "Expand All"
656
+ }),
657
+ /*#__PURE__*/ _jsx("button", {
658
+ type: "button",
659
+ onClick: collapseAll,
660
+ className: "px-3 py-1.5 text-xs font-medium text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 border border-zinc-200 dark:border-zinc-700 rounded-lg transition-colors",
661
+ children: "Collapse All"
662
+ })
663
+ ]
664
+ })
665
+ ]
666
+ }),
667
+ /*#__PURE__*/ _jsx("div", {
668
+ className: "max-h-[calc(100vh-280px)] overflow-y-auto",
669
+ children: sortedEntities.length === 0 ? /*#__PURE__*/ _jsx("div", {
670
+ className: "p-8 text-center text-zinc-500 dark:text-zinc-400",
671
+ children: "No claims match your filters"
672
+ }) : sortedEntities.map((entity)=>{
673
+ const entityClaims = groupedFilteredClaims[entity] || [];
674
+ const isExpanded = expandedEntities.has(entity);
675
+ const assignedCount = getEntityAssignedCount(entity);
676
+ const allAssigned = assignedCount === entityClaims.length;
677
+ return /*#__PURE__*/ _jsxs("div", {
678
+ className: "border-b border-zinc-100 dark:border-zinc-800 last:border-b-0",
679
+ children: [
680
+ /*#__PURE__*/ _jsx("button", {
681
+ type: "button",
682
+ className: "w-full flex items-center justify-between px-4 py-3 cursor-pointer hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors text-left",
683
+ onClick: ()=>toggleEntity(entity),
684
+ children: /*#__PURE__*/ _jsxs("div", {
685
+ className: "flex items-center gap-3",
686
+ children: [
687
+ /*#__PURE__*/ _jsx("svg", {
688
+ className: cn("w-4 h-4 text-zinc-400 transition-transform", isExpanded && "rotate-90"),
689
+ fill: "none",
690
+ stroke: "currentColor",
691
+ viewBox: "0 0 24 24",
692
+ "aria-hidden": "true",
693
+ children: /*#__PURE__*/ _jsx("path", {
694
+ strokeLinecap: "round",
695
+ strokeLinejoin: "round",
696
+ strokeWidth: 2,
697
+ d: "M9 5l7 7-7 7"
698
+ })
699
+ }),
700
+ /*#__PURE__*/ _jsx("span", {
701
+ className: "font-medium text-zinc-900 dark:text-zinc-100",
702
+ children: entity
703
+ }),
704
+ /*#__PURE__*/ _jsxs("span", {
705
+ className: "text-xs text-zinc-500 dark:text-zinc-400",
706
+ children: [
707
+ entityClaims.length,
708
+ " claims"
709
+ ]
710
+ }),
711
+ store.selectedRole && /*#__PURE__*/ _jsxs("span", {
712
+ className: cn("text-xs px-2 py-0.5 rounded-full", allAssigned ? "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400" : assignedCount > 0 ? "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400" : "bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"),
713
+ children: [
714
+ assignedCount,
715
+ "/",
716
+ entityClaims.length
717
+ ]
718
+ })
719
+ ]
720
+ })
721
+ }),
722
+ store.selectedRole && store.selectedRole.name !== "godmin" && /*#__PURE__*/ _jsxs("div", {
723
+ className: "flex items-center gap-2 px-4 pb-2",
724
+ children: [
725
+ /*#__PURE__*/ _jsx("button", {
726
+ type: "button",
727
+ onClick: ()=>handleBulkAssign(entity, true),
728
+ className: "px-2 py-1 text-xs font-medium text-emerald-600 hover:text-emerald-700 dark:text-emerald-400 dark:hover:text-emerald-300 border border-emerald-200 dark:border-emerald-800 rounded",
729
+ children: "Assign All"
730
+ }),
731
+ /*#__PURE__*/ _jsx("button", {
732
+ type: "button",
733
+ onClick: ()=>handleBulkAssign(entity, false),
734
+ className: "px-2 py-1 text-xs font-medium text-red-600 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 border border-red-200 dark:border-red-800 rounded",
735
+ children: "Remove All"
736
+ })
737
+ ]
738
+ }),
739
+ isExpanded && /*#__PURE__*/ _jsx("div", {
740
+ className: "px-4 pb-3",
741
+ children: /*#__PURE__*/ _jsx("div", {
742
+ className: "bg-zinc-50 dark:bg-zinc-800/50 rounded-lg divide-y divide-zinc-100 dark:divide-zinc-700/50",
743
+ children: entityClaims.map((claim)=>{
744
+ const isAssigned = assignedClaimIds.has(claim.id);
745
+ const roleClaim = getRoleClaimForClaim(claim.id);
746
+ const isEditingScope = store.editingScopeClaimId === claim.id;
747
+ const currentScope = roleClaim?.scope || "";
748
+ const isTemp = claim.id.startsWith("temp-") || roleClaim?.id.startsWith("temp-");
749
+ return /*#__PURE__*/ _jsx("div", {
750
+ className: cn("p-3 transition-colors", isAssigned && "bg-emerald-50/50 dark:bg-emerald-900/10"),
751
+ children: /*#__PURE__*/ _jsxs("div", {
752
+ className: "flex items-start gap-3",
753
+ children: [
754
+ /*#__PURE__*/ _jsx("input", {
755
+ type: "checkbox",
756
+ checked: isAssigned,
757
+ onChange: ()=>handleToggleClaim(claim, isAssigned),
758
+ disabled: !store.selectedRole || store.selectedRole.name === "godmin" || isTemp || addRoleClaimAction.state.isPending || deleteRoleClaimAction.state.isPending,
759
+ className: "mt-1 w-4 h-4 rounded border-zinc-300 dark:border-zinc-600 text-emerald-600 focus:ring-emerald-500 disabled:opacity-50"
760
+ }),
761
+ /*#__PURE__*/ _jsxs("div", {
762
+ className: "flex-1 min-w-0",
763
+ children: [
764
+ /*#__PURE__*/ _jsxs("div", {
765
+ className: "flex items-center gap-2 flex-wrap",
766
+ children: [
767
+ /*#__PURE__*/ _jsx("code", {
768
+ className: "text-sm text-zinc-900 dark:text-zinc-100",
769
+ children: claim.action
770
+ }),
771
+ /*#__PURE__*/ _jsx("span", {
772
+ className: cn("px-1.5 py-0.5 text-xs font-medium rounded border", METHOD_COLORS[claim.method] || "bg-zinc-100 text-zinc-600"),
773
+ children: claim.method
774
+ })
775
+ ]
776
+ }),
777
+ /*#__PURE__*/ _jsx("p", {
778
+ className: "text-xs text-zinc-500 dark:text-zinc-400 mt-0.5",
779
+ children: claim.description
780
+ }),
781
+ isAssigned && roleClaim && !isTemp && /*#__PURE__*/ _jsx("div", {
782
+ className: "mt-2",
783
+ children: isEditingScope ? /*#__PURE__*/ _jsxs("div", {
784
+ className: "flex items-center gap-2",
785
+ children: [
786
+ /*#__PURE__*/ _jsx("input", {
787
+ type: "text",
788
+ value: store.scopeInputValue,
789
+ onChange: (e)=>store.setScopeInputValue(e.target.value),
790
+ placeholder: "e.g. user_id=123&tenant_id=456",
791
+ className: "flex-1 px-2 py-1 text-xs border border-zinc-300 dark:border-zinc-600 rounded bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400"
792
+ }),
793
+ /*#__PURE__*/ _jsx("button", {
794
+ type: "button",
795
+ onClick: ()=>handleScopeSubmit(roleClaim.id),
796
+ className: "px-2 py-1 text-xs font-medium text-white bg-emerald-600 hover:bg-emerald-700 rounded transition-colors",
797
+ children: "Save"
798
+ }),
799
+ /*#__PURE__*/ _jsx("button", {
800
+ type: "button",
801
+ onClick: ()=>store.setEditingScopeClaimId(null),
802
+ className: "px-2 py-1 text-xs font-medium text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300 transition-colors",
803
+ children: "Cancel"
804
+ })
805
+ ]
806
+ }) : /*#__PURE__*/ _jsx("button", {
807
+ type: "button",
808
+ onClick: ()=>startEditingScope(claim.id, currentScope),
809
+ className: "text-xs text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 transition-colors",
810
+ children: currentScope ? /*#__PURE__*/ _jsxs("span", {
811
+ className: "font-mono bg-zinc-200 dark:bg-zinc-700 px-1.5 py-0.5 rounded",
812
+ children: [
813
+ "scope: ",
814
+ currentScope
815
+ ]
816
+ }) : /*#__PURE__*/ _jsx("span", {
817
+ className: "italic hover:underline",
818
+ children: "+ Add scope filter"
819
+ })
820
+ })
821
+ })
822
+ ]
823
+ })
824
+ ]
825
+ })
826
+ }, claim.id);
827
+ })
828
+ })
829
+ })
830
+ ]
831
+ }, entity);
832
+ })
833
+ })
834
+ ]
835
+ })
836
+ ]
837
+ })
838
+ ]
839
+ })
840
+ });
841
+ }