@carlonicora/nextjs-jsonapi 1.36.1 → 1.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{BlockNoteEditor-4MDHRUS2.js → BlockNoteEditor-3S2B36O3.js} +15 -15
- package/dist/{BlockNoteEditor-4MDHRUS2.js.map → BlockNoteEditor-3S2B36O3.js.map} +1 -1
- package/dist/{BlockNoteEditor-SZWO3MDO.mjs → BlockNoteEditor-WQUJTVJL.mjs} +5 -5
- package/dist/BlockNoteEditor-WQUJTVJL.mjs.map +1 -0
- package/dist/billing/index.d.mts +15 -5
- package/dist/billing/index.d.ts +15 -5
- package/dist/billing/index.js +750 -520
- package/dist/billing/index.js.map +1 -1
- package/dist/billing/index.mjs +665 -435
- package/dist/billing/index.mjs.map +1 -1
- package/dist/{chunk-53IPQJVH.js → chunk-3EZX4G2E.js} +147 -23
- package/dist/chunk-3EZX4G2E.js.map +1 -0
- package/dist/{chunk-I7DFEJFF.mjs → chunk-4PHADEKA.mjs} +738 -1418
- package/dist/chunk-4PHADEKA.mjs.map +1 -0
- package/dist/{chunk-E6PQQTWF.js → chunk-T2JCZYWK.js} +999 -1679
- package/dist/chunk-T2JCZYWK.js.map +1 -0
- package/dist/{chunk-P7R2DPD6.mjs → chunk-TQ5GRRTM.mjs} +125 -1
- package/dist/chunk-TQ5GRRTM.mjs.map +1 -0
- package/dist/client/index.js +3 -3
- package/dist/client/index.mjs +2 -2
- package/dist/components/index.d.mts +23 -8
- package/dist/components/index.d.ts +23 -8
- package/dist/components/index.js +3 -3
- package/dist/components/index.mjs +2 -2
- package/dist/contexts/index.d.mts +1 -1
- package/dist/contexts/index.d.ts +1 -1
- package/dist/contexts/index.js +3 -3
- package/dist/contexts/index.mjs +2 -2
- package/dist/core/index.d.mts +47 -3
- package/dist/core/index.d.ts +47 -3
- package/dist/core/index.js +8 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +7 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -1
- package/dist/server/index.js +3 -3
- package/dist/server/index.mjs +1 -1
- package/dist/{stripe-subscription.interface-DK7BJaNd.d.ts → stripe-promotion-code.interface-BcJty0rv.d.ts} +18 -1
- package/dist/{stripe-subscription.interface-C8uhCYIZ.d.mts → stripe-promotion-code.interface-Dnm2DJKQ.d.mts} +18 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/billing/index.ts +1 -0
- package/src/client/context/JsonApiProvider.tsx +1 -5
- package/src/client/hooks/__tests__/useJsonApiGet.test.tsx +9 -9
- package/src/client/hooks/__tests__/useJsonApiMutation.test.tsx +11 -11
- package/src/client/hooks/__tests__/useRehydration.test.ts +13 -34
- package/src/components/editors/BlockNoteEditor.tsx +2 -2
- package/src/components/forms/CommonEditorTrigger.tsx +1 -1
- package/src/components/forms/FormCheckbox.tsx +2 -12
- package/src/components/forms/FormDate.tsx +1 -6
- package/src/components/forms/FormInput.tsx +1 -1
- package/src/components/forms/FormPassword.tsx +1 -7
- package/src/components/forms/FormSelect.tsx +2 -8
- package/src/components/forms/FormSlider.tsx +1 -5
- package/src/components/forms/FormSwitch.tsx +1 -5
- package/src/components/forms/GdprConsentCheckbox.tsx +2 -8
- package/src/components/forms/PasswordInput.tsx +28 -26
- package/src/components/forms/__tests__/FormCheckbox.test.tsx +16 -18
- package/src/components/forms/__tests__/FormDate.test.tsx +14 -30
- package/src/components/forms/__tests__/FormInput.test.tsx +21 -37
- package/src/components/forms/__tests__/FormSelect.test.tsx +15 -21
- package/src/components/tables/ContentListTable.tsx +1 -1
- package/src/components/tables/__tests__/ContentListTable.test.tsx +17 -89
- package/src/components/tables/cells/cell.component.tsx +1 -1
- package/src/contexts/HeaderChildrenContext.tsx +3 -1
- package/src/core/endpoint/__tests__/EndpointCreator.test.ts +2 -7
- package/src/core/factories/__tests__/JsonApiDataFactory.test.ts +3 -3
- package/src/core/factories/__tests__/RehydrationFactory.test.ts +4 -6
- package/src/core/index.ts +1 -0
- package/src/core/registry/ModuleRegistry.ts +1 -0
- package/src/core/registry/__tests__/DataClassRegistry.test.ts +5 -15
- package/src/core/registry/__tests__/ModuleRegistrar.test.ts +5 -15
- package/src/features/auth/components/GdprConsentSection.tsx +1 -6
- package/src/features/auth/components/details/LandingComponent.tsx +6 -1
- package/src/features/auth/components/forms/AcceptInvitation.tsx +1 -1
- package/src/features/auth/components/forms/ResetPassword.tsx +1 -1
- package/src/features/billing/components/cards/PaymentMethodSummaryCard.tsx +13 -18
- package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +12 -17
- package/src/features/billing/components/modals/BillingDetailModal.tsx +2 -13
- package/src/features/billing/stripe-customer/components/details/PaymentMethodCard.tsx +8 -1
- package/src/features/billing/stripe-customer/components/forms/PaymentMethodEditor.tsx +2 -13
- package/src/features/billing/stripe-customer/components/forms/PaymentMethodForm.tsx +2 -12
- package/src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx +6 -1
- package/src/features/billing/stripe-invoice/data/stripe-invoice.interface.ts +1 -0
- package/src/features/billing/stripe-price/components/lists/PricesList.tsx +13 -5
- package/src/features/billing/stripe-product/components/lists/ProductsList.tsx +5 -5
- package/src/features/billing/stripe-promotion-code/components/PromoCodeInput.tsx +108 -0
- package/src/features/billing/stripe-promotion-code/components/index.ts +1 -0
- package/src/features/billing/stripe-promotion-code/data/index.ts +3 -0
- package/src/features/billing/stripe-promotion-code/data/stripe-promotion-code.interface.ts +14 -0
- package/src/features/billing/stripe-promotion-code/data/stripe-promotion-code.service.ts +64 -0
- package/src/features/billing/stripe-promotion-code/data/stripe-promotion-code.ts +66 -0
- package/src/features/billing/stripe-promotion-code/index.ts +2 -0
- package/src/features/billing/stripe-promotion-code/stripe-promotion-code.module.ts +9 -0
- package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +1 -3
- package/src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx +4 -1
- package/src/features/billing/stripe-subscription/components/forms/CancelSubscriptionDialog.tsx +1 -1
- package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +24 -4
- package/src/features/billing/stripe-subscription/components/widgets/PricingCard.tsx +9 -2
- package/src/features/billing/stripe-subscription/components/widgets/SubscriptionStatusBadge.tsx +3 -1
- package/src/features/billing/stripe-subscription/components/wizards/SubscriptionWizard.tsx +7 -7
- package/src/features/billing/stripe-subscription/components/wizards/WizardProgressIndicator.tsx +2 -10
- package/src/features/billing/stripe-subscription/components/wizards/WizardStepPaymentMethod.tsx +3 -13
- package/src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx +134 -23
- package/src/features/billing/stripe-subscription/data/stripe-subscription.interface.ts +2 -0
- package/src/features/billing/stripe-subscription/data/stripe-subscription.ts +8 -0
- package/src/features/billing/stripe-subscription/hooks/useSubscriptionWizard.ts +93 -7
- package/src/features/billing/stripe-usage/components/details/UsageSummaryCard.tsx +1 -1
- package/src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx +1 -1
- package/src/features/company/components/details/CompanyDetails.tsx +2 -2
- package/src/features/company/components/forms/CompanyConfigurationSecurityForm.tsx +1 -1
- package/src/features/index.ts +1 -0
- package/src/features/notification/components/containers/NotificationsListContainer.tsx +1 -1
- package/src/features/notification/components/modals/NotificationModal.tsx +6 -2
- package/src/features/notification/contexts/NotificationContext.tsx +1 -3
- package/src/features/oauth/components/OAuthClientCard.tsx +15 -17
- package/src/features/oauth/components/OAuthClientDetail.tsx +7 -19
- package/src/features/oauth/components/OAuthClientForm.tsx +4 -13
- package/src/features/oauth/components/OAuthClientSecretDisplay.tsx +4 -20
- package/src/features/oauth/components/OAuthRedirectUriInput.tsx +5 -12
- package/src/features/oauth/components/OAuthScopeSelector.tsx +17 -23
- package/src/features/oauth/components/consent/OAuthConsentActions.tsx +3 -16
- package/src/features/oauth/components/consent/OAuthConsentHeader.tsx +3 -12
- package/src/features/oauth/components/consent/OAuthConsentScreen.tsx +5 -20
- package/src/features/oauth/components/consent/OAuthScopeList.tsx +3 -18
- package/src/features/onboarding/contexts/OnboardingContext.tsx +3 -3
- package/src/features/role/components/forms/FormRoles.tsx +1 -7
- package/src/features/user/components/containers/UserContainer.tsx +1 -1
- package/src/features/user/components/details/UserDetails.tsx +1 -1
- package/src/features/user/components/forms/UserDeleter.tsx +1 -1
- package/src/features/user/components/forms/UserEditor.tsx +1 -1
- package/src/features/user/components/forms/UserMultiSelect.tsx +7 -7
- package/src/features/user/components/lists/UserListInAdd.tsx +2 -2
- package/src/features/user/components/lists/UsersList.tsx +7 -1
- package/src/features/user/contexts/CurrentUserContext.tsx +36 -33
- package/src/hooks/__tests__/useDataListRetriever.test.ts +15 -21
- package/src/hooks/__tests__/useDebounce.test.ts +2 -7
- package/src/hooks/useCustomD3Graph.tsx +2 -2
- package/src/shadcnui/custom/multi-select.tsx +28 -2
- package/src/shadcnui/ui/accordion.tsx +21 -23
- package/src/shadcnui/ui/alert-dialog.tsx +45 -62
- package/src/shadcnui/ui/alert.tsx +25 -41
- package/src/shadcnui/ui/avatar.tsx +23 -36
- package/src/shadcnui/ui/badge.tsx +13 -11
- package/src/shadcnui/ui/breadcrumb.tsx +21 -55
- package/src/shadcnui/ui/button.tsx +17 -18
- package/src/shadcnui/ui/calendar.tsx +44 -93
- package/src/shadcnui/ui/carousel.tsx +72 -100
- package/src/shadcnui/ui/chart.tsx +102 -161
- package/src/shadcnui/ui/checkbox.tsx +8 -9
- package/src/shadcnui/ui/combobox.tsx +52 -83
- package/src/shadcnui/ui/command.tsx +43 -77
- package/src/shadcnui/ui/context-menu.tsx +47 -86
- package/src/shadcnui/ui/dialog.tsx +34 -60
- package/src/shadcnui/ui/drawer.tsx +32 -53
- package/src/shadcnui/ui/dropdown-menu.tsx +48 -65
- package/src/shadcnui/ui/field.tsx +39 -48
- package/src/shadcnui/ui/hover-card.tsx +9 -14
- package/src/shadcnui/ui/input-group.tsx +44 -55
- package/src/shadcnui/ui/input-otp.tsx +22 -26
- package/src/shadcnui/ui/input.tsx +6 -6
- package/src/shadcnui/ui/label.tsx +6 -6
- package/src/shadcnui/ui/navigation-menu.tsx +36 -60
- package/src/shadcnui/ui/popover.tsx +15 -38
- package/src/shadcnui/ui/progress.tsx +12 -29
- package/src/shadcnui/ui/radio-group.tsx +9 -15
- package/src/shadcnui/ui/resizable.tsx +14 -24
- package/src/shadcnui/ui/scroll-area.tsx +12 -27
- package/src/shadcnui/ui/select.tsx +41 -65
- package/src/shadcnui/ui/separator.tsx +7 -11
- package/src/shadcnui/ui/sheet.tsx +30 -55
- package/src/shadcnui/ui/sidebar.tsx +141 -189
- package/src/shadcnui/ui/skeleton.tsx +3 -9
- package/src/shadcnui/ui/slider.tsx +11 -23
- package/src/shadcnui/ui/switch.tsx +8 -8
- package/src/shadcnui/ui/tabs.tsx +14 -21
- package/src/shadcnui/ui/textarea.tsx +5 -5
- package/src/shadcnui/ui/toggle.tsx +8 -14
- package/src/shadcnui/ui/tooltip.tsx +11 -23
- package/src/testing/providers/MockJsonApiProvider.tsx +1 -5
- package/src/testing/utils/renderWithProviders.tsx +6 -10
- package/dist/BlockNoteEditor-SZWO3MDO.mjs.map +0 -1
- package/dist/chunk-53IPQJVH.js.map +0 -1
- package/dist/chunk-E6PQQTWF.js.map +0 -1
- package/dist/chunk-I7DFEJFF.mjs.map +0 -1
- package/dist/chunk-P7R2DPD6.mjs.map +0 -1
|
@@ -51,7 +51,7 @@ export const CurrentUserProvider = ({ children }: { children: React.ReactNode })
|
|
|
51
51
|
if (!token && dehydratedUser) setDehydratedUser(null);
|
|
52
52
|
}, [dehydratedUser, setDehydratedUser]);
|
|
53
53
|
|
|
54
|
-
const matchUrlToModule = (
|
|
54
|
+
const matchUrlToModule = (_params?: { path: string }): ModuleWithPermissions | undefined => {
|
|
55
55
|
const moduleKeys = Object.getOwnPropertyNames(Modules).filter(
|
|
56
56
|
(key) => key !== "prototype" && key !== "_factory" && key !== "length" && key !== "name",
|
|
57
57
|
);
|
|
@@ -138,41 +138,44 @@ export const CurrentUserProvider = ({ children }: { children: React.ReactNode })
|
|
|
138
138
|
// Function to refresh user data from the API
|
|
139
139
|
// skipCookieUpdate: When true, only updates React state without calling the Server Action
|
|
140
140
|
// This prevents page reloads when refresh is triggered by WebSocket events
|
|
141
|
-
const refreshUser = useCallback(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
141
|
+
const refreshUser = useCallback(
|
|
142
|
+
async (options?: { skipCookieUpdate?: boolean }): Promise<void> => {
|
|
143
|
+
if (isRefreshing) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
145
146
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
147
|
+
setIsRefreshing(true);
|
|
148
|
+
try {
|
|
149
|
+
const fullUser = await UserService.findFullUser();
|
|
150
|
+
if (fullUser) {
|
|
151
|
+
const dehydrated = fullUser.dehydrate();
|
|
152
|
+
|
|
153
|
+
setDehydratedUser(dehydrated as any);
|
|
154
|
+
setUser(fullUser);
|
|
155
|
+
|
|
156
|
+
// Update authentication cookies with fresh user data
|
|
157
|
+
// Skip when triggered by WebSocket to prevent page reload (Server Actions modify cookies)
|
|
158
|
+
if (!options?.skipCookieUpdate) {
|
|
159
|
+
await getTokenHandler()?.updateToken({
|
|
160
|
+
userId: fullUser.id,
|
|
161
|
+
companyId: fullUser.company?.id,
|
|
162
|
+
roles: fullUser.roles.map((role) => role.id),
|
|
163
|
+
features: fullUser.company?.features?.map((feature) => feature.id) ?? [],
|
|
164
|
+
modules: fullUser.modules.map((module) => ({
|
|
165
|
+
id: module.id,
|
|
166
|
+
permissions: module.permissions,
|
|
167
|
+
})),
|
|
168
|
+
});
|
|
169
|
+
}
|
|
168
170
|
}
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.error("Failed to refresh user data:", error);
|
|
173
|
+
} finally {
|
|
174
|
+
setIsRefreshing(false);
|
|
169
175
|
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
setIsRefreshing(false);
|
|
174
|
-
}
|
|
175
|
-
}, [isRefreshing, setDehydratedUser]);
|
|
176
|
+
},
|
|
177
|
+
[isRefreshing, setDehydratedUser],
|
|
178
|
+
);
|
|
176
179
|
|
|
177
180
|
// WebSocket integration for real-time token updates
|
|
178
181
|
const { socket, isConnected } = useSocketContext();
|
|
@@ -22,7 +22,7 @@ describe("useDataListRetriever", () => {
|
|
|
22
22
|
useDataListRetriever({
|
|
23
23
|
retriever,
|
|
24
24
|
module: mockModule,
|
|
25
|
-
})
|
|
25
|
+
}),
|
|
26
26
|
);
|
|
27
27
|
|
|
28
28
|
// Wait for async operations to settle
|
|
@@ -42,7 +42,7 @@ describe("useDataListRetriever", () => {
|
|
|
42
42
|
retriever,
|
|
43
43
|
module: mockModule,
|
|
44
44
|
ready: false,
|
|
45
|
-
})
|
|
45
|
+
}),
|
|
46
46
|
);
|
|
47
47
|
|
|
48
48
|
expect(result.current.ready).toBe(false);
|
|
@@ -63,7 +63,7 @@ describe("useDataListRetriever", () => {
|
|
|
63
63
|
useDataListRetriever({
|
|
64
64
|
retriever,
|
|
65
65
|
module: mockModule,
|
|
66
|
-
})
|
|
66
|
+
}),
|
|
67
67
|
);
|
|
68
68
|
|
|
69
69
|
await waitFor(() => {
|
|
@@ -82,7 +82,7 @@ describe("useDataListRetriever", () => {
|
|
|
82
82
|
useDataListRetriever({
|
|
83
83
|
retriever,
|
|
84
84
|
module: mockModule,
|
|
85
|
-
})
|
|
85
|
+
}),
|
|
86
86
|
);
|
|
87
87
|
|
|
88
88
|
await waitFor(() => {
|
|
@@ -96,16 +96,14 @@ describe("useDataListRetriever", () => {
|
|
|
96
96
|
|
|
97
97
|
describe("search", () => {
|
|
98
98
|
it("should search and call retriever with search term", async () => {
|
|
99
|
-
const mockData = [
|
|
100
|
-
createMockApiData({ type: "articles", id: "1", attributes: { title: "Search Result" } }),
|
|
101
|
-
];
|
|
99
|
+
const mockData = [createMockApiData({ type: "articles", id: "1", attributes: { title: "Search Result" } })];
|
|
102
100
|
const retriever = vi.fn().mockResolvedValue(mockData);
|
|
103
101
|
|
|
104
102
|
const { result } = renderHook(() =>
|
|
105
103
|
useDataListRetriever({
|
|
106
104
|
retriever,
|
|
107
105
|
module: mockModule,
|
|
108
|
-
})
|
|
106
|
+
}),
|
|
109
107
|
);
|
|
110
108
|
|
|
111
109
|
await waitFor(() => {
|
|
@@ -133,7 +131,7 @@ describe("useDataListRetriever", () => {
|
|
|
133
131
|
useDataListRetriever({
|
|
134
132
|
retriever,
|
|
135
133
|
module: mockModule,
|
|
136
|
-
})
|
|
134
|
+
}),
|
|
137
135
|
);
|
|
138
136
|
|
|
139
137
|
await waitFor(() => {
|
|
@@ -161,7 +159,7 @@ describe("useDataListRetriever", () => {
|
|
|
161
159
|
useDataListRetriever({
|
|
162
160
|
retriever,
|
|
163
161
|
module: mockModule,
|
|
164
|
-
})
|
|
162
|
+
}),
|
|
165
163
|
);
|
|
166
164
|
|
|
167
165
|
await waitFor(() => {
|
|
@@ -189,7 +187,7 @@ describe("useDataListRetriever", () => {
|
|
|
189
187
|
retriever,
|
|
190
188
|
module: mockModule,
|
|
191
189
|
ready: false,
|
|
192
|
-
})
|
|
190
|
+
}),
|
|
193
191
|
);
|
|
194
192
|
|
|
195
193
|
expect(result.current.ready).toBe(false);
|
|
@@ -209,16 +207,14 @@ describe("useDataListRetriever", () => {
|
|
|
209
207
|
|
|
210
208
|
describe("element management", () => {
|
|
211
209
|
it("should update element with setRefreshedElement", async () => {
|
|
212
|
-
const mockData = [
|
|
213
|
-
createMockApiData({ type: "articles", id: "1", attributes: { title: "Original" } }),
|
|
214
|
-
];
|
|
210
|
+
const mockData = [createMockApiData({ type: "articles", id: "1", attributes: { title: "Original" } })];
|
|
215
211
|
const retriever = vi.fn().mockResolvedValue(mockData);
|
|
216
212
|
|
|
217
213
|
const { result } = renderHook(() =>
|
|
218
214
|
useDataListRetriever({
|
|
219
215
|
retriever,
|
|
220
216
|
module: mockModule,
|
|
221
|
-
})
|
|
217
|
+
}),
|
|
222
218
|
);
|
|
223
219
|
|
|
224
220
|
await waitFor(() => {
|
|
@@ -250,7 +246,7 @@ describe("useDataListRetriever", () => {
|
|
|
250
246
|
useDataListRetriever({
|
|
251
247
|
retriever,
|
|
252
248
|
module: mockModule,
|
|
253
|
-
})
|
|
249
|
+
}),
|
|
254
250
|
);
|
|
255
251
|
|
|
256
252
|
await waitFor(() => {
|
|
@@ -276,7 +272,7 @@ describe("useDataListRetriever", () => {
|
|
|
276
272
|
useDataListRetriever({
|
|
277
273
|
retriever,
|
|
278
274
|
module: mockModule,
|
|
279
|
-
})
|
|
275
|
+
}),
|
|
280
276
|
);
|
|
281
277
|
|
|
282
278
|
await waitFor(() => {
|
|
@@ -288,9 +284,7 @@ describe("useDataListRetriever", () => {
|
|
|
288
284
|
});
|
|
289
285
|
|
|
290
286
|
await waitFor(() => {
|
|
291
|
-
expect(retriever).toHaveBeenCalledWith(
|
|
292
|
-
expect.objectContaining({ filter: "active" })
|
|
293
|
-
);
|
|
287
|
+
expect(retriever).toHaveBeenCalledWith(expect.objectContaining({ filter: "active" }));
|
|
294
288
|
});
|
|
295
289
|
});
|
|
296
290
|
|
|
@@ -301,7 +295,7 @@ describe("useDataListRetriever", () => {
|
|
|
301
295
|
useDataListRetriever({
|
|
302
296
|
retriever,
|
|
303
297
|
module: mockModule,
|
|
304
|
-
})
|
|
298
|
+
}),
|
|
305
299
|
);
|
|
306
300
|
|
|
307
301
|
await waitFor(() => {
|
|
@@ -92,9 +92,7 @@ describe("useDebounce", () => {
|
|
|
92
92
|
|
|
93
93
|
it("should pass multiple arguments to callback", () => {
|
|
94
94
|
const callback = vi.fn();
|
|
95
|
-
const { result } = renderHook(() =>
|
|
96
|
-
useDebounce((a: string, b: number, c: boolean) => callback(a, b, c), 500)
|
|
97
|
-
);
|
|
95
|
+
const { result } = renderHook(() => useDebounce((a: string, b: number, c: boolean) => callback(a, b, c), 500));
|
|
98
96
|
|
|
99
97
|
act(() => {
|
|
100
98
|
result.current("hello", 42, true);
|
|
@@ -111,10 +109,7 @@ describe("useDebounce", () => {
|
|
|
111
109
|
const callback1 = vi.fn();
|
|
112
110
|
const callback2 = vi.fn();
|
|
113
111
|
|
|
114
|
-
const { result, rerender } = renderHook(
|
|
115
|
-
({ cb }) => useDebounce(cb, 500),
|
|
116
|
-
{ initialProps: { cb: callback1 } }
|
|
117
|
-
);
|
|
112
|
+
const { result, rerender } = renderHook(({ cb }) => useDebounce(cb, 500), { initialProps: { cb: callback1 } });
|
|
118
113
|
|
|
119
114
|
act(() => {
|
|
120
115
|
result.current("test");
|
|
@@ -269,7 +269,7 @@ export function useCustomD3Graph(
|
|
|
269
269
|
}
|
|
270
270
|
});
|
|
271
271
|
|
|
272
|
-
for (const [
|
|
272
|
+
for (const [_nodeId, node] of nodeHierarchy.entries()) {
|
|
273
273
|
if (node.depth === 1 && node.angle !== undefined && node.x !== undefined && node.y !== undefined) {
|
|
274
274
|
const childAngle = node.angle;
|
|
275
275
|
const childX = node.x;
|
|
@@ -527,7 +527,7 @@ export function useCustomD3Graph(
|
|
|
527
527
|
const Icon = d.icon as React.FC<{ size: number; color: string }>;
|
|
528
528
|
const iconSvg = renderToStaticMarkup(<Icon size={nodeRadius / 2} color="white" />);
|
|
529
529
|
|
|
530
|
-
const
|
|
530
|
+
const _iconGroup = d3
|
|
531
531
|
.select(this)
|
|
532
532
|
.append("g")
|
|
533
533
|
.html(iconSvg)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
-
import { CheckIcon, ChevronDown, WandSparkles, XCircle, XIcon } from "lucide-react";
|
|
4
|
+
import { CheckIcon, ChevronDown, Loader2, WandSparkles, XCircle, XIcon } from "lucide-react";
|
|
5
5
|
import * as React from "react";
|
|
6
6
|
|
|
7
7
|
import { cn } from "../../utils/cn";
|
|
@@ -108,6 +108,24 @@ interface MultiSelectProps
|
|
|
108
108
|
* Optional, receives the search string.
|
|
109
109
|
*/
|
|
110
110
|
onSearchChange?: (search: string) => void;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Whether the component is in a loading state (e.g., during search).
|
|
114
|
+
* Optional, defaults to false.
|
|
115
|
+
*/
|
|
116
|
+
loading?: boolean;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Text to display when loading.
|
|
120
|
+
* Optional, defaults to "Searching...".
|
|
121
|
+
*/
|
|
122
|
+
loadingText?: string;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Text to display when no results are found.
|
|
126
|
+
* Optional, defaults to "No results found.".
|
|
127
|
+
*/
|
|
128
|
+
emptyText?: string;
|
|
111
129
|
}
|
|
112
130
|
|
|
113
131
|
export const MultiSelect = React.forwardRef<HTMLButtonElement, MultiSelectProps>(
|
|
@@ -124,6 +142,9 @@ export const MultiSelect = React.forwardRef<HTMLButtonElement, MultiSelectProps>
|
|
|
124
142
|
modalPopover = false,
|
|
125
143
|
className,
|
|
126
144
|
onSearchChange,
|
|
145
|
+
loading = false,
|
|
146
|
+
loadingText = "Searching...",
|
|
147
|
+
emptyText = "No results found.",
|
|
127
148
|
...props
|
|
128
149
|
},
|
|
129
150
|
_ref,
|
|
@@ -293,8 +314,13 @@ export const MultiSelect = React.forwardRef<HTMLButtonElement, MultiSelectProps>
|
|
|
293
314
|
onKeyDown={handleInputKeyDown}
|
|
294
315
|
onValueChange={onSearchChange}
|
|
295
316
|
/>
|
|
317
|
+
{loading && (
|
|
318
|
+
<div className="flex items-center justify-center py-2">
|
|
319
|
+
<Loader2 className="text-muted-foreground h-4 w-4 animate-spin" />
|
|
320
|
+
</div>
|
|
321
|
+
)}
|
|
296
322
|
<CommandList>
|
|
297
|
-
<CommandEmpty>
|
|
323
|
+
<CommandEmpty>{loading ? loadingText : emptyText}</CommandEmpty>
|
|
298
324
|
<CommandGroup>
|
|
299
325
|
<CommandItem
|
|
300
326
|
key="all"
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"use client"
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion"
|
|
3
|
+
import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion";
|
|
4
4
|
|
|
5
|
-
import { cn } from "@/lib/utils"
|
|
6
|
-
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
|
7
7
|
|
|
8
8
|
function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {
|
|
9
9
|
return (
|
|
@@ -12,7 +12,7 @@ function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {
|
|
|
12
12
|
className={cn("overflow-hidden rounded-md border flex w-full flex-col", className)}
|
|
13
13
|
{...props}
|
|
14
14
|
/>
|
|
15
|
-
)
|
|
15
|
+
);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {
|
|
@@ -22,37 +22,35 @@ function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {
|
|
|
22
22
|
className={cn("data-open:bg-muted/50 not-last:border-b", className)}
|
|
23
23
|
{...props}
|
|
24
24
|
/>
|
|
25
|
-
)
|
|
25
|
+
);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
function AccordionTrigger({
|
|
29
|
-
className,
|
|
30
|
-
children,
|
|
31
|
-
...props
|
|
32
|
-
}: AccordionPrimitive.Trigger.Props) {
|
|
28
|
+
function AccordionTrigger({ className, children, ...props }: AccordionPrimitive.Trigger.Props) {
|
|
33
29
|
return (
|
|
34
30
|
<AccordionPrimitive.Header className="flex">
|
|
35
31
|
<AccordionPrimitive.Trigger
|
|
36
32
|
data-slot="accordion-trigger"
|
|
37
33
|
className={cn(
|
|
38
34
|
"**:data-[slot=accordion-trigger-icon]:text-muted-foreground gap-6 p-2 text-left text-xs/relaxed font-medium hover:underline **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 group/accordion-trigger relative flex flex-1 items-start justify-between border border-transparent transition-all outline-none disabled:pointer-events-none disabled:opacity-50",
|
|
39
|
-
className
|
|
35
|
+
className,
|
|
40
36
|
)}
|
|
41
37
|
{...props}
|
|
42
38
|
>
|
|
43
39
|
{children}
|
|
44
|
-
<ChevronDownIcon
|
|
45
|
-
|
|
40
|
+
<ChevronDownIcon
|
|
41
|
+
data-slot="accordion-trigger-icon"
|
|
42
|
+
className="pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden"
|
|
43
|
+
/>
|
|
44
|
+
<ChevronUpIcon
|
|
45
|
+
data-slot="accordion-trigger-icon"
|
|
46
|
+
className="pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline"
|
|
47
|
+
/>
|
|
46
48
|
</AccordionPrimitive.Trigger>
|
|
47
49
|
</AccordionPrimitive.Header>
|
|
48
|
-
)
|
|
50
|
+
);
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
function AccordionContent({
|
|
52
|
-
className,
|
|
53
|
-
children,
|
|
54
|
-
...props
|
|
55
|
-
}: AccordionPrimitive.Panel.Props) {
|
|
53
|
+
function AccordionContent({ className, children, ...props }: AccordionPrimitive.Panel.Props) {
|
|
56
54
|
return (
|
|
57
55
|
<AccordionPrimitive.Panel
|
|
58
56
|
data-slot="accordion-content"
|
|
@@ -62,13 +60,13 @@ function AccordionContent({
|
|
|
62
60
|
<div
|
|
63
61
|
className={cn(
|
|
64
62
|
"pt-0 pb-4 [&_a]:hover:text-foreground h-(--accordion-panel-height) data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4",
|
|
65
|
-
className
|
|
63
|
+
className,
|
|
66
64
|
)}
|
|
67
65
|
>
|
|
68
66
|
{children}
|
|
69
67
|
</div>
|
|
70
68
|
</AccordionPrimitive.Panel>
|
|
71
|
-
)
|
|
69
|
+
);
|
|
72
70
|
}
|
|
73
71
|
|
|
74
|
-
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
|
72
|
+
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
|
|
@@ -1,41 +1,34 @@
|
|
|
1
|
-
"use client"
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog"
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog";
|
|
5
5
|
|
|
6
|
-
import { cn } from "@/lib/utils"
|
|
7
|
-
import { Button } from "@/components/ui/button"
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
import { Button } from "@/components/ui/button";
|
|
8
8
|
|
|
9
9
|
function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {
|
|
10
|
-
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props}
|
|
10
|
+
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {
|
|
14
|
-
return
|
|
15
|
-
<AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
|
|
16
|
-
)
|
|
14
|
+
return <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />;
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {
|
|
20
|
-
return
|
|
21
|
-
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
|
|
22
|
-
)
|
|
18
|
+
return <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />;
|
|
23
19
|
}
|
|
24
20
|
|
|
25
|
-
function AlertDialogOverlay({
|
|
26
|
-
className,
|
|
27
|
-
...props
|
|
28
|
-
}: AlertDialogPrimitive.Backdrop.Props) {
|
|
21
|
+
function AlertDialogOverlay({ className, ...props }: AlertDialogPrimitive.Backdrop.Props) {
|
|
29
22
|
return (
|
|
30
23
|
<AlertDialogPrimitive.Backdrop
|
|
31
24
|
data-slot="alert-dialog-overlay"
|
|
32
25
|
className={cn(
|
|
33
26
|
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50",
|
|
34
|
-
className
|
|
27
|
+
className,
|
|
35
28
|
)}
|
|
36
29
|
{...props}
|
|
37
30
|
/>
|
|
38
|
-
)
|
|
31
|
+
);
|
|
39
32
|
}
|
|
40
33
|
|
|
41
34
|
function AlertDialogContent({
|
|
@@ -43,7 +36,7 @@ function AlertDialogContent({
|
|
|
43
36
|
size = "default",
|
|
44
37
|
...props
|
|
45
38
|
}: AlertDialogPrimitive.Popup.Props & {
|
|
46
|
-
size?: "default" | "sm"
|
|
39
|
+
size?: "default" | "sm";
|
|
47
40
|
}) {
|
|
48
41
|
return (
|
|
49
42
|
<AlertDialogPortal>
|
|
@@ -53,67 +46,64 @@ function AlertDialogContent({
|
|
|
53
46
|
data-size={size}
|
|
54
47
|
className={cn(
|
|
55
48
|
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 gap-3 rounded-xl p-4 ring-1 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-64 data-[size=default]:sm:max-w-sm group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 outline-none",
|
|
56
|
-
className
|
|
49
|
+
className,
|
|
57
50
|
)}
|
|
58
51
|
{...props}
|
|
59
52
|
/>
|
|
60
53
|
</AlertDialogPortal>
|
|
61
|
-
)
|
|
54
|
+
);
|
|
62
55
|
}
|
|
63
56
|
|
|
64
|
-
function AlertDialogHeader({
|
|
65
|
-
className,
|
|
66
|
-
...props
|
|
67
|
-
}: React.ComponentProps<"div">) {
|
|
57
|
+
function AlertDialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
68
58
|
return (
|
|
69
59
|
<div
|
|
70
60
|
data-slot="alert-dialog-header"
|
|
71
|
-
className={cn(
|
|
61
|
+
className={cn(
|
|
62
|
+
"grid grid-rows-[auto_1fr] place-items-center gap-1 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
|
|
63
|
+
className,
|
|
64
|
+
)}
|
|
72
65
|
{...props}
|
|
73
66
|
/>
|
|
74
|
-
)
|
|
67
|
+
);
|
|
75
68
|
}
|
|
76
69
|
|
|
77
|
-
function AlertDialogFooter({
|
|
78
|
-
className,
|
|
79
|
-
...props
|
|
80
|
-
}: React.ComponentProps<"div">) {
|
|
70
|
+
function AlertDialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
81
71
|
return (
|
|
82
72
|
<div
|
|
83
73
|
data-slot="alert-dialog-footer"
|
|
84
74
|
className={cn(
|
|
85
75
|
"flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
|
|
86
|
-
className
|
|
76
|
+
className,
|
|
87
77
|
)}
|
|
88
78
|
{...props}
|
|
89
79
|
/>
|
|
90
|
-
)
|
|
80
|
+
);
|
|
91
81
|
}
|
|
92
82
|
|
|
93
|
-
function AlertDialogMedia({
|
|
94
|
-
className,
|
|
95
|
-
...props
|
|
96
|
-
}: React.ComponentProps<"div">) {
|
|
83
|
+
function AlertDialogMedia({ className, ...props }: React.ComponentProps<"div">) {
|
|
97
84
|
return (
|
|
98
85
|
<div
|
|
99
86
|
data-slot="alert-dialog-media"
|
|
100
|
-
className={cn(
|
|
87
|
+
className={cn(
|
|
88
|
+
"bg-muted mb-2 inline-flex size-8 items-center justify-center rounded-md sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-4",
|
|
89
|
+
className,
|
|
90
|
+
)}
|
|
101
91
|
{...props}
|
|
102
92
|
/>
|
|
103
|
-
)
|
|
93
|
+
);
|
|
104
94
|
}
|
|
105
95
|
|
|
106
|
-
function AlertDialogTitle({
|
|
107
|
-
className,
|
|
108
|
-
...props
|
|
109
|
-
}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
|
|
96
|
+
function AlertDialogTitle({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
|
|
110
97
|
return (
|
|
111
98
|
<AlertDialogPrimitive.Title
|
|
112
99
|
data-slot="alert-dialog-title"
|
|
113
|
-
className={cn(
|
|
100
|
+
className={cn(
|
|
101
|
+
"text-sm font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
|
|
102
|
+
className,
|
|
103
|
+
)}
|
|
114
104
|
{...props}
|
|
115
105
|
/>
|
|
116
|
-
)
|
|
106
|
+
);
|
|
117
107
|
}
|
|
118
108
|
|
|
119
109
|
function AlertDialogDescription({
|
|
@@ -123,23 +113,17 @@ function AlertDialogDescription({
|
|
|
123
113
|
return (
|
|
124
114
|
<AlertDialogPrimitive.Description
|
|
125
115
|
data-slot="alert-dialog-description"
|
|
126
|
-
className={cn(
|
|
116
|
+
className={cn(
|
|
117
|
+
"text-muted-foreground *:[a]:hover:text-foreground text-xs/relaxed text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3",
|
|
118
|
+
className,
|
|
119
|
+
)}
|
|
127
120
|
{...props}
|
|
128
121
|
/>
|
|
129
|
-
)
|
|
122
|
+
);
|
|
130
123
|
}
|
|
131
124
|
|
|
132
|
-
function AlertDialogAction({
|
|
133
|
-
className
|
|
134
|
-
...props
|
|
135
|
-
}: React.ComponentProps<typeof Button>) {
|
|
136
|
-
return (
|
|
137
|
-
<Button
|
|
138
|
-
data-slot="alert-dialog-action"
|
|
139
|
-
className={cn(className)}
|
|
140
|
-
{...props}
|
|
141
|
-
/>
|
|
142
|
-
)
|
|
125
|
+
function AlertDialogAction({ className, ...props }: React.ComponentProps<typeof Button>) {
|
|
126
|
+
return <Button data-slot="alert-dialog-action" className={cn(className)} {...props} />;
|
|
143
127
|
}
|
|
144
128
|
|
|
145
129
|
function AlertDialogCancel({
|
|
@@ -147,8 +131,7 @@ function AlertDialogCancel({
|
|
|
147
131
|
variant = "outline",
|
|
148
132
|
size = "default",
|
|
149
133
|
...props
|
|
150
|
-
}: AlertDialogPrimitive.Close.Props &
|
|
151
|
-
Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
|
|
134
|
+
}: AlertDialogPrimitive.Close.Props & Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
|
|
152
135
|
return (
|
|
153
136
|
<AlertDialogPrimitive.Close
|
|
154
137
|
data-slot="alert-dialog-cancel"
|
|
@@ -156,7 +139,7 @@ function AlertDialogCancel({
|
|
|
156
139
|
render={<Button variant={variant} size={size} />}
|
|
157
140
|
{...props}
|
|
158
141
|
/>
|
|
159
|
-
)
|
|
142
|
+
);
|
|
160
143
|
}
|
|
161
144
|
|
|
162
145
|
export {
|
|
@@ -172,4 +155,4 @@ export {
|
|
|
172
155
|
AlertDialogPortal,
|
|
173
156
|
AlertDialogTitle,
|
|
174
157
|
AlertDialogTrigger,
|
|
175
|
-
}
|
|
158
|
+
};
|