@carlonicora/nextjs-jsonapi 3.3.9 → 3.4.1

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 +13 -7
  17. package/dist/components/index.d.ts +13 -7
  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 +35 -35
  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
@@ -103,7 +103,7 @@ export function CustomerInfoCard({ customer, loading, error }: CustomerInfoCardP
103
103
  )}
104
104
  <Button variant="outline" size="sm" className="mt-2" onClick={handlePortalClick} disabled={portalLoading}>
105
105
  {portalLoading ? "Loading..." : "Manage in Stripe Portal"}
106
- <ExternalLink className="h-4 w-4 ml-1" />
106
+ <ExternalLink className="h-4 w-4 ms-1" />
107
107
  </Button>
108
108
  </div>
109
109
  </CardContent>
@@ -103,7 +103,7 @@ export function InvoicesSummaryCard({ invoices, loading, error, onViewAllClick }
103
103
  {openInvoices.length > 0 && <span className="text-warning">{openInvoices.length} open</span>}
104
104
  <span className="flex items-center">
105
105
  View all
106
- <ChevronRight className="h-3 w-3 ml-1" />
106
+ <ChevronRight className="h-3 w-3 ms-1 rtl:rotate-180" />
107
107
  </span>
108
108
  </div>
109
109
  </div>
@@ -85,7 +85,7 @@ export function PaymentMethodSummaryCard({
85
85
  }}
86
86
  >
87
87
  Add Card
88
- <ChevronRight className="h-4 w-4 ml-1" />
88
+ <ChevronRight className="h-4 w-4 ms-1 rtl:rotate-180" />
89
89
  </Button>
90
90
  </div>
91
91
  ) : defaultMethod?.card ? (
@@ -106,7 +106,7 @@ export function SubscriptionSummaryCard({
106
106
  }}
107
107
  >
108
108
  View Plans
109
- <ChevronRight className="h-4 w-4 ml-1" />
109
+ <ChevronRight className="h-4 w-4 ms-1 rtl:rotate-180" />
110
110
  </Button>
111
111
  </div>
112
112
  ) : primarySubscription ? (
@@ -360,7 +360,7 @@ export function BillingDashboardContainer() {
360
360
  <Button onClick={handleCreateCustomer} disabled={creatingCustomer} size="lg">
361
361
  {creatingCustomer ? (
362
362
  <>
363
- <Loader2 className="mr-2 h-4 w-4 animate-spin" />
363
+ <Loader2 className="me-2 h-4 w-4 animate-spin" />
364
364
  Setting up...
365
365
  </>
366
366
  ) : (
@@ -91,7 +91,7 @@ export function PaymentMethodCard({ paymentMethod, onUpdate }: PaymentMethodCard
91
91
  <Card className="relative">
92
92
  {/* Default Badge */}
93
93
  {isDefault && (
94
- <Badge variant="softGreen" className="absolute right-2 top-2">
94
+ <Badge variant="softGreen" className="absolute end-2 top-2">
95
95
  Default
96
96
  </Badge>
97
97
  )}
@@ -95,14 +95,14 @@ export function InvoiceDetails({
95
95
  <table className="w-full">
96
96
  <thead className="bg-muted">
97
97
  <tr>
98
- <th className="text-left p-3 text-sm font-medium">Description</th>
99
- <th className="text-right p-3 text-sm font-medium">Amount</th>
98
+ <th className="text-start p-3 text-sm font-medium">Description</th>
99
+ <th className="text-end p-3 text-sm font-medium">Amount</th>
100
100
  </tr>
101
101
  </thead>
102
102
  <tbody>
103
103
  <tr className="border-t">
104
104
  <td className="p-3">{productName}</td>
105
- <td className="p-3 text-right">{formatCurrency(invoice.subtotal, invoice.currency)}</td>
105
+ <td className="p-3 text-end">{formatCurrency(invoice.subtotal, invoice.currency)}</td>
106
106
  </tr>
107
107
  </tbody>
108
108
  </table>
@@ -149,21 +149,21 @@ export function InvoiceDetails({
149
149
  <div className="flex flex-wrap gap-2 pt-4 border-t">
150
150
  {invoice.stripePdfUrl && (
151
151
  <Button variant="outline" onClick={handleDownloadPDF}>
152
- <Download className="mr-2 h-4 w-4" />
152
+ <Download className="me-2 h-4 w-4" />
153
153
  Download PDF
154
154
  </Button>
155
155
  )}
156
156
 
157
157
  {invoice.status === InvoiceStatus.OPEN && invoice.attempted && (
158
158
  <Button variant="default" onClick={handleRetryPayment}>
159
- <RefreshCw className="mr-2 h-4 w-4" />
159
+ <RefreshCw className="me-2 h-4 w-4" />
160
160
  Retry Payment
161
161
  </Button>
162
162
  )}
163
163
 
164
164
  {invoice.stripeHostedInvoiceUrl && (
165
165
  <Button variant="outline" onClick={handleViewInStripe}>
166
- <ExternalLink className="mr-2 h-4 w-4" />
166
+ <ExternalLink className="me-2 h-4 w-4" />
167
167
  View in Stripe
168
168
  </Button>
169
169
  )}
@@ -36,7 +36,7 @@ export function InvoicesList({ invoices, onInvoicesChange }: InvoicesListProps)
36
36
  <TableHead>Invoice #</TableHead>
37
37
  <TableHead>Date</TableHead>
38
38
  <TableHead>Status</TableHead>
39
- <TableHead className="text-right">Amount</TableHead>
39
+ <TableHead className="text-end">Amount</TableHead>
40
40
  <TableHead>Period</TableHead>
41
41
  </TableRow>
42
42
  </TableHeader>
@@ -58,7 +58,7 @@ export function InvoicesList({ invoices, onInvoicesChange }: InvoicesListProps)
58
58
  <TableCell>
59
59
  <InvoiceStatusBadge status={invoice.status} />
60
60
  </TableCell>
61
- <TableCell className="text-right font-medium">{amount}</TableCell>
61
+ <TableCell className="text-end font-medium">{amount}</TableCell>
62
62
  <TableCell className="text-muted-foreground text-xs">{period}</TableCell>
63
63
  </TableRow>
64
64
  );
@@ -49,9 +49,9 @@ export const useStripePriceTableStructure: UseTableStructureHook<StripePriceInte
49
49
  header: t("billing.admin.prices.fields.amount"),
50
50
  cell: ({ row }: { row: TableContent<StripePriceInterface> }) => {
51
51
  const price: StripePriceInterface = row.original.jsonApiData;
52
- // Typography role 15 (numeric): tabular-nums, right-aligned. NEVER font-mono.
52
+ // Typography role 15 (numeric): tabular-nums, end-aligned. NEVER font-mono.
53
53
  return (
54
- <span className="block text-xs tabular-nums text-right">
54
+ <span className="block text-xs tabular-nums text-end">
55
55
  {formatCurrency(price.unitAmount, price.currency)}
56
56
  </span>
57
57
  );
@@ -77,7 +77,7 @@ export const useStripePriceTableStructure: UseTableStructureHook<StripePriceInte
77
77
  header: t("billing.admin.prices.fields.token"),
78
78
  cell: ({ row }: { row: TableContent<StripePriceInterface> }) => {
79
79
  const price: StripePriceInterface = row.original.jsonApiData;
80
- return <span className="block text-xs tabular-nums text-right">{price.token ?? ""}</span>;
80
+ return <span className="block text-xs tabular-nums text-end">{price.token ?? ""}</span>;
81
81
  },
82
82
  enableSorting: false,
83
83
  enableHiding: false,
@@ -59,9 +59,9 @@ export const useStripeProductTableStructure: UseTableStructureHook<StripeProduct
59
59
  header: t("billing.admin.products.fields.prices"),
60
60
  cell: ({ row }: { row: TableContent<StripeProductInterface> }) => {
61
61
  const product: StripeProductInterface = row.original.jsonApiData;
62
- // Typography role 15 (numeric): tabular-nums, right-aligned. NEVER
62
+ // Typography role 15 (numeric): tabular-nums, end-aligned. NEVER
63
63
  // font-mono — no monospace font is loaded in these apps.
64
- return <span className="block text-xs tabular-nums text-right">{product.stripePrices.length}</span>;
64
+ return <span className="block text-xs tabular-nums text-end">{product.stripePrices.length}</span>;
65
65
  },
66
66
  enableSorting: false,
67
67
  enableHiding: false,
@@ -60,8 +60,8 @@ export function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChan
60
60
  <TableHead>Status</TableHead>
61
61
  <TableHead>Plan</TableHead>
62
62
  <TableHead>Period</TableHead>
63
- <TableHead className="text-right">Amount</TableHead>
64
- <TableHead className="text-right">Actions</TableHead>
63
+ <TableHead className="text-end">Amount</TableHead>
64
+ <TableHead className="text-end">Actions</TableHead>
65
65
  </TableRow>
66
66
  </TableHeader>
67
67
  <TableBody>
@@ -84,8 +84,8 @@ export function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChan
84
84
  </TableCell>
85
85
  <TableCell className="font-medium">{formatPlanName(price)}</TableCell>
86
86
  <TableCell className="text-muted-foreground text-sm">{period}</TableCell>
87
- <TableCell className="text-right font-medium">{amount}</TableCell>
88
- <TableCell className="text-right">
87
+ <TableCell className="text-end font-medium">{amount}</TableCell>
88
+ <TableCell className="text-end">
89
89
  {(subscription.status === SubscriptionStatus.ACTIVE ||
90
90
  subscription.status === SubscriptionStatus.TRIALING) &&
91
91
  onChangePlan && (
@@ -61,7 +61,7 @@ export function PricingCard({
61
61
  )}
62
62
  >
63
63
  {isCurrentPlan && (
64
- <Badge variant="secondary" className="absolute top-2 right-2">
64
+ <Badge variant="secondary" className="absolute top-2 end-2">
65
65
  Current
66
66
  </Badge>
67
67
  )}
@@ -73,7 +73,7 @@ export function PricingCard({
73
73
  <CardContent className="pb-4 grow">
74
74
  <div className="mb-4">
75
75
  <span className="text-3xl font-bold">{formattedPrice}</span>
76
- <span className="text-muted-foreground ml-1">{interval}</span>
76
+ <span className="text-muted-foreground ms-1">{interval}</span>
77
77
  </div>
78
78
 
79
79
  {features.length > 0 && (
@@ -54,7 +54,7 @@ export function SubscriptionConfirmation({ price, isLoading, onConfirm, onCancel
54
54
  <Button onClick={onConfirm} disabled={isLoading}>
55
55
  {isLoading ? (
56
56
  <>
57
- <Loader2 className="h-4 w-4 animate-spin mr-2" />
57
+ <Loader2 className="h-4 w-4 animate-spin me-2" />
58
58
  Processing...
59
59
  </>
60
60
  ) : (
@@ -127,7 +127,7 @@ export function WizardStepReview({
127
127
  <p className="font-medium">{selectedPrice.product?.name}</p>
128
128
  {selectedPrice.nickname && <p className="text-sm text-muted-foreground">{selectedPrice.nickname}</p>}
129
129
  </div>
130
- <div className="text-right">
130
+ <div className="text-end">
131
131
  {discountedPrice !== null ? (
132
132
  <>
133
133
  <p className="text-sm text-muted-foreground line-through">
@@ -168,7 +168,7 @@ export function WizardStepReview({
168
168
  <span className={`font-medium ${isTrialUpgrade ? "text-warning" : "text-foreground"}`}>
169
169
  {discountedImmediateCharge !== null ? (
170
170
  <>
171
- <span className="line-through text-muted-foreground mr-2">
171
+ <span className="line-through text-muted-foreground me-2">
172
172
  {formatCurrency(prorationPreview.immediateCharge, prorationPreview.currency)}
173
173
  </span>
174
174
  <span className="text-success">
@@ -47,7 +47,7 @@ export function UsageHistoryTable({ usageRecords }: UsageHistoryTableProps) {
47
47
  <TableRow>
48
48
  <TableHead>Date & Time</TableHead>
49
49
  <TableHead>Meter Event</TableHead>
50
- <TableHead className="text-right">Quantity</TableHead>
50
+ <TableHead className="text-end">Quantity</TableHead>
51
51
  <TableHead>Event ID</TableHead>
52
52
  </TableRow>
53
53
  </TableHeader>
@@ -60,7 +60,7 @@ export function UsageHistoryTable({ usageRecords }: UsageHistoryTableProps) {
60
60
  <TableRow key={record.id}>
61
61
  <TableCell className="font-medium">{dateTime}</TableCell>
62
62
  <TableCell className="text-muted-foreground">{record.meterEventName}</TableCell>
63
- <TableCell className="text-right font-medium">{quantity}</TableCell>
63
+ <TableCell className="text-end font-medium">{quantity}</TableCell>
64
64
  <TableCell className="text-muted-foreground text-sm tabular-nums">{record.stripeEventId}</TableCell>
65
65
  </TableRow>
66
66
  );
@@ -99,7 +99,7 @@ function CompanyDeleterInternal({ company, isAdministrator }: CompanyDeleterInte
99
99
  <div className="flex w-full flex-col">
100
100
  <Label className="flex items-center">
101
101
  {t(`company.fields.name.label`)}
102
- <span className="ml-1 text-destructive">*</span>
102
+ <span className="ms-1 text-destructive">*</span>
103
103
  </Label>
104
104
  <Input
105
105
  className={`w-full`}
@@ -109,7 +109,7 @@ function CompanyDeleterInternal({ company, isAdministrator }: CompanyDeleterInte
109
109
  </div>
110
110
  </div>
111
111
  <div className="flex justify-end">
112
- <Button className="mr-2" variant={"outline"} type={`button`} onClick={() => setOpen(false)}>
112
+ <Button className="me-2" variant={"outline"} type={`button`} onClick={() => setOpen(false)}>
113
113
  {t(`ui.buttons.cancel`)}
114
114
  </Button>
115
115
  <Button
@@ -136,7 +136,7 @@ function CompanyDeleterInternal({ company, isAdministrator }: CompanyDeleterInte
136
136
  </AlertDialogHeader>
137
137
  <div className="bg-destructive/10 border-destructive text-destructive rounded-md border p-4 text-sm">
138
138
  <p className="mb-3 font-semibold">{t(`common.delete.finalWarning.description`)}</p>
139
- <ul className="list-disc space-y-1 pl-5">
139
+ <ul className="list-disc space-y-1 ps-5">
140
140
  <li>{t(`common.delete.finalWarning.bullet1`)}</li>
141
141
  <li>{t(`common.delete.finalWarning.bullet2`)}</li>
142
142
  <li>{t(`common.delete.finalWarning.bullet3`)}</li>
@@ -145,7 +145,7 @@ function CompanyDeleterInternal({ company, isAdministrator }: CompanyDeleterInte
145
145
  </ul>
146
146
  </div>
147
147
  <div className="flex justify-end">
148
- <Button className="mr-2" variant={"outline"} type={`button`} onClick={handleGoBack} disabled={isDeleting}>
148
+ <Button className="me-2" variant={"outline"} type={`button`} onClick={handleGoBack} disabled={isDeleting}>
149
149
  {t(`ui.buttons.go_back`)}
150
150
  </Button>
151
151
  <Button
@@ -75,7 +75,7 @@ export const useContentTableStructure = <U extends string = ContentFields>(
75
75
  return (
76
76
  <div className="relative flex h-5 w-20 items-center justify-center overflow-clip rounded border text-center">
77
77
  <div
78
- className={`bg-accent absolute top-0 left-0 h-full opacity-${Math.round(content.relevance)}`}
78
+ className={`bg-accent absolute top-0 start-0 h-full opacity-${Math.round(content.relevance)}`}
79
79
  style={{ width: `${content.relevance}%` }}
80
80
  ></div>
81
81
  <span
@@ -37,7 +37,7 @@ export function FormFeatures({ form, name, features, featureField = "featureIds"
37
37
  </SectionHeader>
38
38
  )}
39
39
  <ScrollArea className="h-[40vh]">
40
- <div className="flex flex-col gap-y-2 pr-4">
40
+ <div className="flex flex-col gap-y-2 pe-4">
41
41
  {features
42
42
  .filter((feature) => !feature.isCore)
43
43
  .map((feature) => (
@@ -49,7 +49,7 @@ export function FormFeatures({ form, name, features, featureField = "featureIds"
49
49
  toggleFeature(feature, val === true);
50
50
  }}
51
51
  />
52
- <Label htmlFor={feature.id} className="ml-3 cursor-pointer font-normal">
52
+ <Label htmlFor={feature.id} className="ms-3 cursor-pointer font-normal">
53
53
  {feature.name}
54
54
  </Label>
55
55
  </div>
@@ -10,8 +10,9 @@ export function HelpAssistantSheet({ open, onOpenChange }: { open: boolean; onOp
10
10
  return (
11
11
  <Sheet open={open} onOpenChange={onOpenChange}>
12
12
  <SheetContent
13
- side="right"
14
- className="flex w-full flex-col data-[side=right]:sm:max-w-2xl data-[side=right]:lg:max-w-3xl"
13
+ side="end"
14
+ /* rtl-ok: keyed to the resolved physical side ("right" in LTR, "left" in RTL) */
15
+ className="flex w-full flex-col data-[side=right]:sm:max-w-2xl data-[side=right]:lg:max-w-3xl data-[side=left]:sm:max-w-2xl data-[side=left]:lg:max-w-3xl"
15
16
  >
16
17
  <AssistantProvider manageUrl={false}>
17
18
  <HelpAssistantSheetBody />
@@ -52,7 +52,7 @@ export function HelpHint({ contextKey }: { contextKey: string }) {
52
52
  <SheetTrigger render={<Button variant="ghost" size="icon-sm" aria-label={t("help.hint.trigger")} />}>
53
53
  <HelpCircleIcon className="h-4 w-4" />
54
54
  </SheetTrigger>
55
- <SheetContent side="right" className="w-full max-w-md sm:max-w-lg">
55
+ <SheetContent side="end" className="w-full max-w-md sm:max-w-lg">
56
56
  <SheetHeader>
57
57
  <SheetTitle>{active ? active.name : t("help.hint.pickArticle")}</SheetTitle>
58
58
  <SheetDescription>{active?.summary ?? ""}</SheetDescription>
@@ -71,7 +71,7 @@ export function HelpHint({ contextKey }: { contextKey: string }) {
71
71
  <button
72
72
  type="button"
73
73
  onClick={() => setPicked(a)}
74
- className="hover:bg-muted block w-full rounded px-2 py-1 text-left text-sm"
74
+ className="hover:bg-muted block w-full rounded px-2 py-1 text-start text-sm"
75
75
  >
76
76
  <div className="font-medium">{a.name}</div>
77
77
  <div className="text-muted-foreground text-xs">{a.summary}</div>
@@ -30,7 +30,7 @@ export function HelpTOC({ headings }: { headings: readonly HelpHeading[] }) {
30
30
  <MicroLabel className="mb-2">{t("help.toc.title")}</MicroLabel>
31
31
  <ul className="space-y-1 text-sm">
32
32
  {headings.map((h) => (
33
- <li key={h.slug} style={{ paddingLeft: `${(h.depth - 2) * 0.75}rem` }}>
33
+ <li key={h.slug} style={{ paddingInlineStart: `${(h.depth - 2) * 0.75}rem` }}>
34
34
  <a
35
35
  href={`#${h.slug}`}
36
36
  className={
@@ -184,7 +184,7 @@ export default function HowToCommand({ pathname, extraGroups, onStartChat }: How
184
184
  <CommandGroup heading={t(`howto.command.relevant`)}>
185
185
  {relevantHowTos.map((howTo: HowToInterface) => (
186
186
  <CommandItem key={howTo.id} onSelect={() => setSelectedHowTo(howTo)} className="cursor-pointer">
187
- <ArrowRight className="h-4 w-4" />
187
+ <ArrowRight className="h-4 w-4 rtl:rotate-180" />
188
188
  <span>{howTo.name}</span>
189
189
  </CommandItem>
190
190
  ))}
@@ -196,7 +196,7 @@ export default function HowToCommand({ pathname, extraGroups, onStartChat }: How
196
196
  <CommandGroup heading={searchTerm ? undefined : t(`howto.command.all`)}>
197
197
  {otherHowTos.map((howTo: HowToInterface) => (
198
198
  <CommandItem key={howTo.id} onSelect={() => setSelectedHowTo(howTo)} className="cursor-pointer">
199
- <ArrowRight className="h-4 w-4" />
199
+ <ArrowRight className="h-4 w-4 rtl:rotate-180" />
200
200
  <span>{howTo.name}</span>
201
201
  </CommandItem>
202
202
  ))}
@@ -27,8 +27,8 @@ export default function HowToCommandViewer({ howTo, onBack, onStartChat }: HowTo
27
27
  {/* Header with back button, title, and reading time */}
28
28
  <div className="flex items-center gap-3 border-b px-4 py-3">
29
29
  <Button variant="ghost" size="sm" onClick={onBack} className="h-8 px-2">
30
- <ArrowLeft className="h-4 w-4" />
31
- <span className="ml-1">{t("howto.command.back")}</span>
30
+ <ArrowLeft className="h-4 w-4 rtl:rotate-180" />
31
+ <span className="ms-1">{t("howto.command.back")}</span>
32
32
  </Button>
33
33
  <SectionHeader level={2} className="flex-1 truncate">
34
34
  {howTo.name}
@@ -43,14 +43,14 @@ export default function HowToCommandViewer({ howTo, onBack, onStartChat }: HowTo
43
43
  <div className="flex min-h-0 flex-1">
44
44
  {/* Left sidebar - table of contents */}
45
45
  {headings.length > 0 && (
46
- <div className="w-50 shrink-0 overflow-y-auto border-r p-4">
46
+ <div className="w-50 shrink-0 overflow-y-auto border-e p-4">
47
47
  <nav className="space-y-1">
48
48
  {headings.map((heading) => (
49
49
  <a
50
50
  key={heading.id}
51
51
  href={`#${heading.id}`}
52
52
  className="text-muted-foreground hover:text-foreground block truncate text-sm"
53
- style={{ paddingLeft: `${(heading.level - 1) * 0.75}rem` }}
53
+ style={{ paddingInlineStart: `${(heading.level - 1) * 0.75}rem` }}
54
54
  >
55
55
  {heading.text}
56
56
  </a>
@@ -69,7 +69,7 @@ export default function HowToCommandViewer({ howTo, onBack, onStartChat }: HowTo
69
69
  {onStartChat && (
70
70
  <div className="flex items-center justify-end gap-2 border-t px-4 py-3">
71
71
  <Button onClick={onStartChat} variant="default" size="sm">
72
- <MessageSquare className="mr-2 h-4 w-4" />
72
+ <MessageSquare className="me-2 h-4 w-4" />
73
73
  {t("howto.command.chat_button")}
74
74
  </Button>
75
75
  </div>
@@ -77,11 +77,11 @@ function PageSelector({
77
77
  <PopoverContent align="start" className="w-(--anchor-width) p-0">
78
78
  <Command shouldFilter={false}>
79
79
  <div className="relative w-full border-b">
80
- <SearchIcon className="text-muted-foreground absolute top-2.5 left-2.5 h-4 w-4" />
80
+ <SearchIcon className="text-muted-foreground absolute top-2.5 start-2.5 h-4 w-4" />
81
81
  <Input
82
82
  placeholder={placeholder}
83
83
  type="text"
84
- className="rounded-none border-0 pl-8 focus-visible:ring-0"
84
+ className="rounded-none border-0 ps-8 focus-visible:ring-0"
85
85
  onChange={(e) => setSearch(e.target.value)}
86
86
  value={search}
87
87
  />
@@ -339,7 +339,7 @@ function HowToEditorInternal({
339
339
  />
340
340
  ))}
341
341
  <Button type="button" variant="outline" size="sm" onClick={addPage}>
342
- <PlusIcon className="mr-2 h-4 w-4" />
342
+ <PlusIcon className="me-2 h-4 w-4" />
343
343
  {t(`howto.fields.pages.add`)}
344
344
  </Button>
345
345
  </div>
@@ -111,7 +111,7 @@ export default function HowToSelector({
111
111
  </PopoverTrigger>
112
112
  {field.value && (
113
113
  <CircleX
114
- className="text-muted hover:text-destructive ml-2 h-4 w-4 shrink-0 cursor-pointer"
114
+ className="text-muted hover:text-destructive ms-2 h-4 w-4 shrink-0 cursor-pointer"
115
115
  onClick={() => setHowTo()}
116
116
  />
117
117
  )}
@@ -119,19 +119,19 @@ export default function HowToSelector({
119
119
  <PopoverContent align="start" className="w-(--anchor-width)">
120
120
  <Command shouldFilter={false}>
121
121
  <div className="relative mb-2 w-full">
122
- <SearchIcon className="text-muted-foreground absolute top-2.5 left-2.5 h-4 w-4" />
122
+ <SearchIcon className="text-muted-foreground absolute top-2.5 start-2.5 h-4 w-4" />
123
123
  <Input
124
124
  placeholder={t(`generic.search.placeholder`, { type: t(`entities.howtos`, { count: 1 }) })}
125
125
  type="text"
126
- className="w-full pr-8 pl-8"
126
+ className="w-full pe-8 ps-8"
127
127
  onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSearchTerm(e.target.value)}
128
128
  value={searchTerm}
129
129
  />
130
130
  {isSearching ? (
131
- <RefreshCwIcon className="text-muted-foreground absolute top-2.5 right-2.5 h-4 w-4 animate-spin" />
131
+ <RefreshCwIcon className="text-muted-foreground absolute top-2.5 end-2.5 h-4 w-4 animate-spin" />
132
132
  ) : searchTermRef.current ? (
133
133
  <XIcon
134
- className={`absolute top-2.5 right-2.5 h-4 w-4 ${searchTermRef.current ? "cursor-pointer" : "text-muted-foreground"}`}
134
+ className={`absolute top-2.5 end-2.5 h-4 w-4 ${searchTermRef.current ? "cursor-pointer" : "text-muted-foreground"}`}
135
135
  onClick={() => {
136
136
  setSearchTerm("");
137
137
  search("");
@@ -44,7 +44,7 @@ export function NotificationsList({ archived }: NotificationsListProps) {
44
44
  <Card key={i}>
45
45
  <CardContent className="p-2">
46
46
  <div className="flex w-full flex-row items-center">
47
- <Skeleton className="mr-4 h-8 w-8 rounded-full" />
47
+ <Skeleton className="me-4 h-8 w-8 rounded-full" />
48
48
  <div className="flex-1 space-y-2">
49
49
  <Skeleton className="h-4 w-3/4" />
50
50
  <Skeleton className="h-3 w-1/2" />
@@ -108,7 +108,7 @@ export function NotificationsList({ archived }: NotificationsListProps) {
108
108
  e.stopPropagation();
109
109
  archiveNotification(notification);
110
110
  }}
111
- className="text-muted-foreground hover:text-destructive ml-2"
111
+ className="text-muted-foreground hover:text-destructive ms-2"
112
112
  >
113
113
  <ArchiveIcon className="h-4 w-4 cursor-pointer" />
114
114
  </Button>
@@ -200,7 +200,7 @@ function NotificationModalContent({ isOpen, setIsOpen }: NotificationModalProps)
200
200
  {t(`entities.notifications`, { count: 2 })}
201
201
  </SidebarMenuButton>
202
202
  </PopoverTrigger>
203
- <PopoverContent className="relative left-10 w-80 border-0 p-0 shadow-none">
203
+ <PopoverContent className="relative start-10 w-80 border-0 p-0 shadow-none">
204
204
  <Card>
205
205
  <CardHeader className="p-4">
206
206
  <CardTitle>{t(`entities.notifications`, { count: 2 })}</CardTitle>
@@ -68,7 +68,7 @@ export function OAuthClientCard({ client, onClick, onEdit, onDelete }: OAuthClie
68
68
  onEdit();
69
69
  }}
70
70
  >
71
- <Pencil className="h-4 w-4 mr-2" />
71
+ <Pencil className="h-4 w-4 me-2" />
72
72
  Edit
73
73
  </DropdownMenuItem>
74
74
  )}
@@ -80,7 +80,7 @@ export function OAuthClientCard({ client, onClick, onEdit, onDelete }: OAuthClie
80
80
  }}
81
81
  className="text-destructive"
82
82
  >
83
- <Trash2 className="h-4 w-4 mr-2" />
83
+ <Trash2 className="h-4 w-4 me-2" />
84
84
  Delete
85
85
  </DropdownMenuItem>
86
86
  )}
@@ -194,13 +194,13 @@ export function OAuthClientDetail({
194
194
  <div className="flex gap-3 pt-4">
195
195
  {onEdit && (
196
196
  <Button variant="outline" onClick={onEdit} disabled={isLoading}>
197
- <Pencil className="h-4 w-4 mr-2" />
197
+ <Pencil className="h-4 w-4 me-2" />
198
198
  Edit
199
199
  </Button>
200
200
  )}
201
201
  {onDelete && (
202
202
  <Button variant="destructive" onClick={() => setShowDeleteConfirm(true)} disabled={isLoading}>
203
- <Trash2 className="h-4 w-4 mr-2" />
203
+ <Trash2 className="h-4 w-4 me-2" />
204
204
  Delete
205
205
  </Button>
206
206
  )}
@@ -80,7 +80,7 @@ export function OAuthClientList({
80
80
  <SectionHeader level={2}>{title}</SectionHeader>
81
81
  {onCreateClick && (
82
82
  <Button onClick={onCreateClick}>
83
- <Plus className="h-4 w-4 mr-2" />
83
+ <Plus className="h-4 w-4 me-2" />
84
84
  New App
85
85
  </Button>
86
86
  )}
@@ -91,7 +91,7 @@ export function OAuthClientList({
91
91
  <p className="text-muted-foreground mb-4">{emptyStateMessage}</p>
92
92
  {onCreateClick && (
93
93
  <Button onClick={onCreateClick}>
94
- <Plus className="h-4 w-4 mr-2" />
94
+ <Plus className="h-4 w-4 me-2" />
95
95
  Create Application
96
96
  </Button>
97
97
  )}
@@ -107,7 +107,7 @@ export function OAuthClientList({
107
107
  <SectionHeader level={2}>{title}</SectionHeader>
108
108
  {onCreateClick && (
109
109
  <Button onClick={onCreateClick}>
110
- <Plus className="h-4 w-4 mr-2" />
110
+ <Plus className="h-4 w-4 me-2" />
111
111
  New App
112
112
  </Button>
113
113
  )}
@@ -135,7 +135,7 @@ export function OAuthRedirectUriInput({
135
135
  </div>
136
136
 
137
137
  <Button type="button" variant="outline" size="sm" onClick={handleAdd} disabled={disabled} className="mt-2">
138
- <Plus className="h-4 w-4 mr-2" />
138
+ <Plus className="h-4 w-4 me-2" />
139
139
  Add Redirect URI
140
140
  </Button>
141
141
 
@@ -78,7 +78,7 @@ export function OAuthScopeSelector({
78
78
  {Object.entries(groupedScopes).map(([groupName, scopes]) => (
79
79
  <div key={groupName} className="space-y-2">
80
80
  <h4 className="text-sm font-medium capitalize">{groupName}</h4>
81
- <div className="grid grid-cols-1 md:grid-cols-2 gap-2 pl-2">
81
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-2 ps-2">
82
82
  {scopes.map((scopeInfo) => {
83
83
  const isChecked = value.includes(scopeInfo.scope);
84
84
  const isAdmin = scopeInfo.scope === "admin";
@@ -99,7 +99,7 @@ export function OAuthScopeSelector({
99
99
  <div className="flex-1">
100
100
  <Label htmlFor={`scope-${scopeInfo.scope}`} className="cursor-pointer">
101
101
  {scopeInfo.name}
102
- {isAdmin && <span className="ml-2 text-xs text-destructive">(Dangerous)</span>}
102
+ {isAdmin && <span className="ms-2 text-xs text-destructive">(Dangerous)</span>}
103
103
  </Label>
104
104
  <p className="text-xs text-muted-foreground">{scopeInfo.description}</p>
105
105
  </div>
@@ -18,13 +18,7 @@ export function OnboardingCard({
18
18
  }: OnboardingCardRenderProps) {
19
19
  return (
20
20
  <Card className="w-[320px] relative" data-shepherd-card>
21
- <Button
22
- variant="ghost"
23
- size="icon"
24
- className="absolute right-2 top-2"
25
- onClick={onClose}
26
- aria-label={labels.close}
27
- >
21
+ <Button variant="ghost" size="icon" className="absolute end-2 top-2" onClick={onClose} aria-label={labels.close}>
28
22
  <X className="h-4 w-4" />
29
23
  </Button>
30
24
  <CardHeader>