@carlonicora/nextjs-jsonapi 3.3.9 → 3.4.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 (175) hide show
  1. package/dist/{BlockNoteEditor-BYMRWUVG.mjs → BlockNoteEditor-3D5D7YL7.mjs} +2 -2
  2. package/dist/{BlockNoteEditor-USRMFZGP.js → BlockNoteEditor-F6TGKMTW.js} +9 -9
  3. package/dist/{BlockNoteEditor-USRMFZGP.js.map → BlockNoteEditor-F6TGKMTW.js.map} +1 -1
  4. package/dist/billing/index.js +347 -347
  5. package/dist/billing/index.js.map +1 -1
  6. package/dist/billing/index.mjs +27 -27
  7. package/dist/billing/index.mjs.map +1 -1
  8. package/dist/{chunk-CFZW6GU4.mjs → chunk-G5LSXG5K.mjs} +2572 -2482
  9. package/dist/chunk-G5LSXG5K.mjs.map +1 -0
  10. package/dist/{chunk-5WFYQE22.js → chunk-KT4CTWCV.js} +825 -735
  11. package/dist/chunk-KT4CTWCV.js.map +1 -0
  12. package/dist/client/index.d.mts +5 -0
  13. package/dist/client/index.d.ts +5 -0
  14. package/dist/client/index.js +2 -2
  15. package/dist/client/index.mjs +1 -1
  16. package/dist/components/index.d.mts +12 -6
  17. package/dist/components/index.d.ts +12 -6
  18. package/dist/components/index.js +2 -2
  19. package/dist/components/index.mjs +1 -1
  20. package/dist/contexts/index.d.mts +13 -1
  21. package/dist/contexts/index.d.ts +13 -1
  22. package/dist/contexts/index.js +6 -2
  23. package/dist/contexts/index.js.map +1 -1
  24. package/dist/contexts/index.mjs +5 -1
  25. package/dist/features/help/index.js +35 -35
  26. package/dist/features/help/index.js.map +1 -1
  27. package/dist/features/help/index.mjs +6 -6
  28. package/dist/features/help/index.mjs.map +1 -1
  29. package/dist/features/tokenusage/index.js +135 -129
  30. package/dist/features/tokenusage/index.js.map +1 -1
  31. package/dist/features/tokenusage/index.mjs +74 -68
  32. package/dist/features/tokenusage/index.mjs.map +1 -1
  33. package/package.json +2 -2
  34. package/scripts/check-rtl-classes.mjs +60 -0
  35. package/scripts/check-rtl-classes.test.ts +25 -0
  36. package/src/components/TableCellAvatar.tsx +1 -1
  37. package/src/components/containers/PageContainer.tsx +1 -1
  38. package/src/components/containers/ReactMarkdownContainer.tsx +20 -4
  39. package/src/components/containers/RoundPageContainer.tsx +7 -7
  40. package/src/components/contents/AttributeElement.tsx +1 -1
  41. package/src/components/editors/BlockNoteDiffInlineContent.tsx +2 -2
  42. package/src/components/editors/BlockNoteEditorMentionHoverCard.tsx +1 -0
  43. package/src/components/forms/CommonDeleter.tsx +1 -1
  44. package/src/components/forms/CommonEditorButtons.tsx +1 -1
  45. package/src/components/forms/DatePickerPopover.tsx +2 -2
  46. package/src/components/forms/DateRangeSelector.tsx +2 -2
  47. package/src/components/forms/EditorSheet.tsx +18 -9
  48. package/src/components/forms/EntityMultiSelector.tsx +7 -7
  49. package/src/components/forms/EntitySelector.tsx +8 -8
  50. package/src/components/forms/FileUploader.tsx +1 -0
  51. package/src/components/forms/FormCheckbox.tsx +3 -3
  52. package/src/components/forms/FormDateTime.tsx +3 -3
  53. package/src/components/forms/FormFieldWrapper.tsx +1 -1
  54. package/src/components/forms/FormPlaceAutocomplete.tsx +2 -2
  55. package/src/components/forms/GdprConsentCheckbox.tsx +1 -1
  56. package/src/components/forms/MultiFileUploader.tsx +1 -1
  57. package/src/components/forms/PasswordInput.tsx +1 -1
  58. package/src/components/forms/__tests__/FormCheckbox.test.tsx +4 -4
  59. package/src/components/navigations/Header.tsx +2 -2
  60. package/src/components/navigations/PageSection.tsx +1 -1
  61. package/src/components/pages/PageContainerContentDetails.tsx +1 -1
  62. package/src/components/pages/PageContentContainer.tsx +5 -2
  63. package/src/components/tables/ContentListTable.tsx +4 -4
  64. package/src/components/tables/ContentTableSearch.tsx +5 -5
  65. package/src/contexts/DirectionContext.tsx +25 -0
  66. package/src/contexts/__tests__/DirectionContext.test.tsx +22 -0
  67. package/src/contexts/index.ts +1 -0
  68. package/src/features/ai-connection/components/lists/AiConnectionTypeCard.tsx +1 -1
  69. package/src/features/assistant/components/containers/AssistantPageContainer.tsx +1 -1
  70. package/src/features/assistant/components/parts/AssistantBlockNoteComposer.tsx +2 -2
  71. package/src/features/assistant/components/parts/AssistantComposer.tsx +2 -2
  72. package/src/features/assistant/components/parts/AssistantEmptyState.tsx +1 -1
  73. package/src/features/assistant/components/parts/AssistantSidebar.tsx +3 -3
  74. package/src/features/assistant-action/components/ApprovalActionCard.tsx +1 -1
  75. package/src/features/assistant-action/components/AssistantContainerWithApprovals.tsx +1 -1
  76. package/src/features/assistant-message/components/MessageItem.tsx +3 -3
  77. package/src/features/assistant-message/components/__tests__/MessageItem.spec.tsx +1 -0
  78. package/src/features/assistant-message/components/parts/MessageSourcesPanel.tsx +2 -2
  79. package/src/features/assistant-message/components/parts/RelevanceMeter.tsx +1 -1
  80. package/src/features/assistant-message/components/parts/tabs/SuggestedQuestionsTab.tsx +1 -1
  81. package/src/features/auth/components/buttons/GoogleSignInButton.tsx +1 -1
  82. package/src/features/auth/components/forms/Register.tsx +2 -2
  83. package/src/features/auth/components/two-factor/BackupCodesDialog.tsx +3 -3
  84. package/src/features/auth/utils/__tests__/clearClientStorage.spec.ts +4 -4
  85. package/src/features/billing/components/cards/BillingUsageSummaryCard.tsx +1 -1
  86. package/src/features/billing/components/cards/CustomerInfoCard.tsx +1 -1
  87. package/src/features/billing/components/cards/InvoicesSummaryCard.tsx +1 -1
  88. package/src/features/billing/components/cards/PaymentMethodSummaryCard.tsx +1 -1
  89. package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +1 -1
  90. package/src/features/billing/components/containers/BillingDashboardContainer.tsx +1 -1
  91. package/src/features/billing/stripe-customer/components/details/PaymentMethodCard.tsx +1 -1
  92. package/src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx +6 -6
  93. package/src/features/billing/stripe-invoice/components/lists/InvoicesList.tsx +2 -2
  94. package/src/features/billing/stripe-price/hooks/useStripePriceTableStructure.tsx +3 -3
  95. package/src/features/billing/stripe-product/hooks/useStripeProductTableStructure.tsx +2 -2
  96. package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +4 -4
  97. package/src/features/billing/stripe-subscription/components/widgets/PricingCard.tsx +2 -2
  98. package/src/features/billing/stripe-subscription/components/widgets/SubscriptionConfirmation.tsx +1 -1
  99. package/src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx +2 -2
  100. package/src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx +2 -2
  101. package/src/features/company/components/forms/CompanyDeleter.tsx +4 -4
  102. package/src/features/content/hooks/useContentTableStructure.tsx +1 -1
  103. package/src/features/feature/components/forms/FormFeatures.tsx +2 -2
  104. package/src/features/help/components/HelpAssistantSheet.tsx +3 -2
  105. package/src/features/help/components/HelpHint.tsx +2 -2
  106. package/src/features/help/components/HelpTOC.tsx +1 -1
  107. package/src/features/how-to/components/containers/HowToCommand.tsx +2 -2
  108. package/src/features/how-to/components/containers/HowToCommandViewer.tsx +5 -5
  109. package/src/features/how-to/components/forms/HowToEditor.tsx +3 -3
  110. package/src/features/how-to/components/forms/HowToSelector.tsx +5 -5
  111. package/src/features/notification/components/lists/NotificationsList.tsx +2 -2
  112. package/src/features/notification/components/modals/NotificationModal.tsx +1 -1
  113. package/src/features/oauth/components/OAuthClientCard.tsx +2 -2
  114. package/src/features/oauth/components/OAuthClientDetail.tsx +2 -2
  115. package/src/features/oauth/components/OAuthClientList.tsx +3 -3
  116. package/src/features/oauth/components/OAuthRedirectUriInput.tsx +1 -1
  117. package/src/features/oauth/components/OAuthScopeSelector.tsx +2 -2
  118. package/src/features/onboarding/components/OnboardingCard.tsx +1 -7
  119. package/src/features/rbac/components/RbacByRoleContainer.tsx +3 -3
  120. package/src/features/rbac/components/RbacContainer.tsx +3 -3
  121. package/src/features/referral/components/ReferralWidget.tsx +1 -0
  122. package/src/features/role/components/forms/FormRoles.tsx +1 -1
  123. package/src/features/role/components/forms/RemoveUserFromRole.tsx +1 -1
  124. package/src/features/role/components/forms/UserRoleAdd.tsx +1 -1
  125. package/src/features/tokenusage/components/TokenUsageBreakdownTable.tsx +9 -9
  126. package/src/features/tokenusage/components/TokenUsageRankedBar.tsx +8 -3
  127. package/src/features/tokenusage/components/TokenUsageTimelineChart.tsx +5 -1
  128. package/src/features/user/components/details/UserStandaloneDetails.tsx +1 -1
  129. package/src/features/user/components/forms/UserReactivator.tsx +2 -2
  130. package/src/features/user/components/forms/UserResentInvitationEmail.tsx +1 -1
  131. package/src/features/user/components/forms/UserSelector.tsx +7 -7
  132. package/src/features/user/components/lists/ContributorsList.tsx +1 -1
  133. package/src/features/user/components/lists/UserListInAdd.tsx +1 -1
  134. package/src/features/user/components/widgets/UserSearchPopover.tsx +5 -5
  135. package/src/features/user/hooks/useUserTableStructure.tsx +1 -1
  136. package/src/features/waitlist/components/forms/WaitlistQuestionnaireRenderer.tsx +1 -1
  137. package/src/features/waitlist/hooks/useWaitlistTableStructure.tsx +1 -1
  138. package/src/hooks/useCustomD3Graph.tsx +16 -0
  139. package/src/lib/__tests__/direction.test.ts +18 -0
  140. package/src/lib/direction.ts +8 -0
  141. package/src/shadcnui/custom/multi-select.tsx +6 -6
  142. package/src/shadcnui/custom/multiple-selector.tsx +6 -2
  143. package/src/shadcnui/ui/accordion.tsx +1 -1
  144. package/src/shadcnui/ui/alert-dialog.tsx +2 -1
  145. package/src/shadcnui/ui/alert.tsx +2 -2
  146. package/src/shadcnui/ui/avatar.tsx +1 -1
  147. package/src/shadcnui/ui/badge.tsx +1 -1
  148. package/src/shadcnui/ui/breadcrumb.tsx +1 -1
  149. package/src/shadcnui/ui/button.tsx +4 -4
  150. package/src/shadcnui/ui/calendar.tsx +9 -8
  151. package/src/shadcnui/ui/carousel.tsx +18 -11
  152. package/src/shadcnui/ui/combobox.tsx +3 -3
  153. package/src/shadcnui/ui/command.tsx +2 -2
  154. package/src/shadcnui/ui/context-menu.tsx +15 -11
  155. package/src/shadcnui/ui/dialog.tsx +2 -1
  156. package/src/shadcnui/ui/drawer.tsx +19 -3
  157. package/src/shadcnui/ui/dropdown-menu.tsx +12 -10
  158. package/src/shadcnui/ui/field.tsx +2 -2
  159. package/src/shadcnui/ui/input-group.tsx +3 -3
  160. package/src/shadcnui/ui/input-otp.tsx +2 -0
  161. package/src/shadcnui/ui/navigation-menu.tsx +2 -2
  162. package/src/shadcnui/ui/progress.tsx +1 -1
  163. package/src/shadcnui/ui/radio-group.tsx +1 -0
  164. package/src/shadcnui/ui/resizable.tsx +1 -0
  165. package/src/shadcnui/ui/scroll-area.tsx +1 -1
  166. package/src/shadcnui/ui/select.tsx +2 -2
  167. package/src/shadcnui/ui/sheet.tsx +11 -4
  168. package/src/shadcnui/ui/sidebar.tsx +37 -20
  169. package/src/shadcnui/ui/sonner.tsx +6 -1
  170. package/src/shadcnui/ui/switch.tsx +1 -1
  171. package/src/shadcnui/ui/table.tsx +2 -2
  172. package/src/shadcnui/ui/tabs.tsx +1 -1
  173. package/dist/chunk-5WFYQE22.js.map +0 -1
  174. package/dist/chunk-CFZW6GU4.mjs.map +0 -1
  175. /package/dist/{BlockNoteEditor-BYMRWUVG.mjs.map → BlockNoteEditor-3D5D7YL7.mjs.map} +0 -0
@@ -12,8 +12,10 @@ import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "
12
12
  import { Skeleton } from "@/components/ui/skeleton";
13
13
  import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
14
14
  import { useIsMobile } from "@/hooks/use-mobile";
15
+ import { resolvePhysicalSide } from "@/lib/direction";
15
16
  import { cn } from "@/lib/utils";
16
17
  import { PanelLeftIcon } from "lucide-react";
18
+ import { useDir } from "../../contexts/DirectionContext";
17
19
 
18
20
  const SIDEBAR_COOKIE_NAME = "sidebar_state";
19
21
  const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
@@ -134,18 +136,26 @@ function SidebarProvider({
134
136
  }
135
137
 
136
138
  function Sidebar({
137
- side = "left",
139
+ // Default is LOGICAL: the in-flow gap div follows text direction, so only a
140
+ // logical side keeps it and the fixed panel on the same physical edge in RTL.
141
+ // Explicit physical "left"/"right" callers keep the old behavior (LTR apps).
142
+ side: sideProp = "start",
138
143
  variant = "sidebar",
139
144
  collapsible = "offExamples",
140
145
  className,
141
146
  children,
142
147
  ...props
143
148
  }: React.ComponentProps<"div"> & {
144
- side?: "left" | "right";
149
+ side?: "left" | "right" | "start" | "end";
145
150
  variant?: "sidebar" | "floating" | "inset";
146
151
  collapsible?: "offExamples" | "icon" | "none";
147
152
  }) {
148
153
  const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
154
+ const dir = useDir();
155
+ // Logical "start"/"end" is resolved once, here. Everything downstream
156
+ // (data-side, the positioning ternaries, the mobile SheetContent) consumes
157
+ // the resolved PHYSICAL side, so "left"/"right" callers are unchanged.
158
+ const side = sideProp === "start" || sideProp === "end" ? resolvePhysicalSide(sideProp, dir) : sideProp;
149
159
 
150
160
  if (collapsible === "none") {
151
161
  return (
@@ -199,7 +209,7 @@ function Sidebar({
199
209
  className={cn(
200
210
  "transition-[width] duration-200 ease-linear relative w-(--sidebar-width) bg-transparent",
201
211
  "group-data-[collapsible=offExamples]:w-0",
202
- "group-data-[side=right]:rotate-180",
212
+ "group-data-[side=right]:rotate-180", // rtl-ok: keyed to resolved physical side
203
213
  variant === "floating" || variant === "inset"
204
214
  ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"
205
215
  : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)",
@@ -210,12 +220,12 @@ function Sidebar({
210
220
  className={cn(
211
221
  "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
212
222
  side === "left"
213
- ? "left-0 group-data-[collapsible=offExamples]:left-[calc(var(--sidebar-width)*-1)]"
214
- : "right-0 group-data-[collapsible=offExamples]:right-[calc(var(--sidebar-width)*-1)]",
223
+ ? "left-0 group-data-[collapsible=offExamples]:left-[calc(var(--sidebar-width)*-1)]" // rtl-ok: keyed to resolved physical side
224
+ : "right-0 group-data-[collapsible=offExamples]:right-[calc(var(--sidebar-width)*-1)]", // rtl-ok: keyed to resolved physical side
215
225
  // Adjust the padding for floating and inset variants.
216
226
  variant === "floating" || variant === "inset"
217
227
  ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
218
- : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
228
+ : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l", // rtl-ok: keyed to resolved physical side
219
229
  className,
220
230
  )}
221
231
  {...props}
@@ -248,7 +258,7 @@ function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<t
248
258
  }}
249
259
  {...props}
250
260
  >
251
- <PanelLeftIcon />
261
+ <PanelLeftIcon className="rtl:rotate-180" />
252
262
  <span className="sr-only">Toggle Sidebar</span>
253
263
  </Button>
254
264
  );
@@ -266,12 +276,13 @@ function SidebarRail({ className, ...props }: React.ComponentProps<"button">) {
266
276
  onClick={toggleSidebar}
267
277
  title="Toggle Sidebar"
268
278
  className={cn(
269
- "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex",
270
- "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
271
- "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
272
- "hover:group-data-[collapsible=offExamples]:bg-sidebar group-data-[collapsible=offExamples]:translate-x-0 group-data-[collapsible=offExamples]:after:left-full",
273
- "[[data-side=left][data-collapsible=offExamples]_&]:-right-2",
274
- "[[data-side=right][data-collapsible=offExamples]_&]:-left-2",
279
+ // rtl-ok: the whole rail block is keyed to the resolved physical side
280
+ "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex", // rtl-ok: keyed to resolved physical side
281
+ "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize", // rtl-ok: keyed to resolved physical side
282
+ "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", // rtl-ok: keyed to resolved physical side
283
+ "hover:group-data-[collapsible=offExamples]:bg-sidebar group-data-[collapsible=offExamples]:translate-x-0 group-data-[collapsible=offExamples]:after:left-full", // rtl-ok: keyed to resolved physical side
284
+ "[[data-side=left][data-collapsible=offExamples]_&]:-right-2", // rtl-ok: keyed to resolved physical side
285
+ "[[data-side=right][data-collapsible=offExamples]_&]:-left-2", // rtl-ok: keyed to resolved physical side
275
286
  className,
276
287
  )}
277
288
  {...props}
@@ -284,7 +295,7 @@ function SidebarInset({ className, ...props }: React.ComponentProps<"main">) {
284
295
  <main
285
296
  data-slot="sidebar-inset"
286
297
  className={cn(
287
- "bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2 relative flex w-full flex-1 flex-col",
298
+ "bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ms-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ms-2 relative flex w-full flex-1 flex-col",
288
299
  className,
289
300
  )}
290
301
  {...props}
@@ -395,7 +406,7 @@ function SidebarGroupAction({
395
406
  props: mergeProps<"button">(
396
407
  {
397
408
  className: cn(
398
- "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 w-5 rounded-md p-0 focus-visible:ring-2 [&>svg]:size-4 flex aspect-square items-center justify-center outline-hidden transition-transform [&>svg]:shrink-0 after:absolute after:-inset-2 md:after:hidden group-data-[collapsible=icon]:hidden",
409
+ "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 end-3 w-5 rounded-md p-0 focus-visible:ring-2 [&>svg]:size-4 flex aspect-square items-center justify-center outline-hidden transition-transform [&>svg]:shrink-0 after:absolute after:-inset-2 md:after:hidden group-data-[collapsible=icon]:hidden",
399
410
  className,
400
411
  ),
401
412
  },
@@ -443,7 +454,7 @@ function SidebarMenuItem({ className, ...props }: React.ComponentProps<"li">) {
443
454
  }
444
455
 
445
456
  const sidebarMenuButtonVariants = cva(
446
- "ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-[calc(var(--radius-sm)+2px)] p-2 text-left text-xs transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&_svg]:size-4 [&_svg]:shrink-0",
457
+ "ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-[calc(var(--radius-sm)+2px)] p-2 text-start text-xs transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pe-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&_svg]:size-4 [&_svg]:shrink-0",
447
458
  {
448
459
  variants: {
449
460
  variant: {
@@ -478,6 +489,7 @@ function SidebarMenuButton({
478
489
  tooltip?: string | React.ComponentProps<typeof TooltipContent>;
479
490
  } & VariantProps<typeof sidebarMenuButtonVariants>) {
480
491
  const { isMobile, state } = useSidebar();
492
+ const dir = useDir();
481
493
  const comp = useRender({
482
494
  defaultTagName: "button",
483
495
  props: mergeProps<"button">(
@@ -508,7 +520,12 @@ function SidebarMenuButton({
508
520
  return (
509
521
  <Tooltip>
510
522
  {comp}
511
- <TooltipContent side="right" align="center" hidden={state !== "collapsed" || isMobile} {...tooltip} />
523
+ <TooltipContent
524
+ side={dir === "rtl" ? "left" : "right"}
525
+ align="center"
526
+ hidden={state !== "collapsed" || isMobile}
527
+ {...tooltip}
528
+ />
512
529
  </Tooltip>
513
530
  );
514
531
  }
@@ -527,7 +544,7 @@ function SidebarMenuAction({
527
544
  props: mergeProps<"button">(
528
545
  {
529
546
  className: cn(
530
- "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute top-1.5 right-1 aspect-square w-5 rounded-[calc(var(--radius-sm)-2px)] p-0 peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 focus-visible:ring-2 [&>svg]:size-4 flex items-center justify-center outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 md:after:hidden [&>svg]:shrink-0",
547
+ "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute top-1.5 end-1 aspect-square w-5 rounded-[calc(var(--radius-sm)-2px)] p-0 peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 focus-visible:ring-2 [&>svg]:size-4 flex items-center justify-center outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 md:after:hidden [&>svg]:shrink-0",
531
548
  showOnHover &&
532
549
  "peer-data-active/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-open:opacity-100 md:opacity-0",
533
550
  className,
@@ -549,7 +566,7 @@ function SidebarMenuBadge({ className, ...props }: React.ComponentProps<"div">)
549
566
  data-slot="sidebar-menu-badge"
550
567
  data-sidebar="menu-badge"
551
568
  className={cn(
552
- "text-sidebar-foreground peer-hover/menu-button:text-sidebar-accent-foreground peer-data-active/menu-button:text-sidebar-accent-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 rounded-[calc(var(--radius-sm)-2px)] px-1 text-xs font-medium peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 flex items-center justify-center tabular-nums select-none group-data-[collapsible=icon]:hidden",
569
+ "text-sidebar-foreground peer-hover/menu-button:text-sidebar-accent-foreground peer-data-active/menu-button:text-sidebar-accent-foreground pointer-events-none absolute end-1 flex h-5 min-w-5 rounded-[calc(var(--radius-sm)-2px)] px-1 text-xs font-medium peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 flex items-center justify-center tabular-nums select-none group-data-[collapsible=icon]:hidden",
553
570
  className,
554
571
  )}
555
572
  {...props}
@@ -596,7 +613,7 @@ function SidebarMenuSub({ className, ...props }: React.ComponentProps<"ul">) {
596
613
  data-slot="sidebar-menu-sub"
597
614
  data-sidebar="menu-sub"
598
615
  className={cn(
599
- "border-sidebar-border mx-3.5 translate-x-px gap-1 border-l px-2.5 py-0.5 group-data-[collapsible=icon]:hidden flex min-w-0 flex-col",
616
+ "border-sidebar-border mx-3.5 translate-x-px gap-1 border-s px-2.5 py-0.5 group-data-[collapsible=icon]:hidden flex min-w-0 flex-col",
600
617
  className,
601
618
  )}
602
619
  {...props}
@@ -3,13 +3,18 @@
3
3
  import { useTheme } from "next-themes";
4
4
  import { Toaster as Sonner, type ToasterProps } from "sonner";
5
5
  import { CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from "lucide-react";
6
+ import { useDir } from "../../contexts/DirectionContext";
6
7
 
7
- const Toaster = ({ ...props }: ToasterProps) => {
8
+ const Toaster = ({ position, ...props }: ToasterProps) => {
8
9
  const { theme = "system" } = useTheme();
10
+ const dir = useDir();
9
11
 
10
12
  return (
11
13
  <Sonner
12
14
  theme={theme as ToasterProps["theme"]}
15
+ dir={dir}
16
+ // sonner's own default is "bottom-right"; mirror it in RTL.
17
+ position={position ?? (dir === "rtl" ? "bottom-left" : "bottom-right")}
13
18
  className="toaster group"
14
19
  icons={{
15
20
  success: <CircleCheckIcon className="size-4" />,
@@ -25,7 +25,7 @@ function Switch({
25
25
  <SwitchPrimitive.Thumb
26
26
  data-slot="switch-thumb"
27
27
  className={cn(
28
- "bg-background dark:data-unchecked:bg-foreground dark:data-checked:bg-primary-foreground rounded-full group-data-[size=default]/switch:size-3.5 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0 pointer-events-none block ring-0 transition-transform",
28
+ "bg-background dark:data-unchecked:bg-foreground dark:data-checked:bg-primary-foreground rounded-full group-data-[size=default]/switch:size-3.5 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] rtl:group-data-[size=default]/switch:data-checked:-translate-x-[calc(100%-2px)] rtl:group-data-[size=sm]/switch:data-checked:-translate-x-[calc(100%-2px)] group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0 pointer-events-none block ring-0 transition-transform",
29
29
  children && "flex items-center justify-center",
30
30
  )}
31
31
  >
@@ -45,7 +45,7 @@ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
45
45
  <th
46
46
  data-slot="table-head"
47
47
  className={cn(
48
- "text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0",
48
+ "text-foreground h-10 px-2 text-start align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pe-0",
49
49
  className,
50
50
  )}
51
51
  {...props}
@@ -57,7 +57,7 @@ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
57
57
  return (
58
58
  <td
59
59
  data-slot="table-cell"
60
- className={cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0", className)}
60
+ className={cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pe-0", className)}
61
61
  {...props}
62
62
  />
63
63
  );
@@ -77,7 +77,7 @@ function TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {
77
77
  "gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-xs font-medium group-data-vertical/tabs:py-[calc(--spacing(1.25))] [&_svg:not([class*='size-'])]:size-3.5 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
78
78
  "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent",
79
79
  "data-active:bg-background dark:data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 data-active:text-foreground",
80
- "after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100",
80
+ "after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-end-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100",
81
81
  className,
82
82
  )}
83
83
  {...props}