react-pdf-rtl 0.1.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.
- package/README.md +234 -0
- package/dist/index.d.mts +259 -0
- package/dist/index.d.ts +259 -0
- package/dist/index.js +367 -0
- package/dist/index.mjs +320 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# react-pdf-rtl
|
|
2
|
+
|
|
3
|
+
> RTL (Hebrew & Arabic) support for [`@react-pdf/renderer`](https://react-pdf.org/)
|
|
4
|
+
|
|
5
|
+
`@react-pdf/renderer` is a fantastic library — but Hebrew and Arabic text rendering is broken out of the box. Mixed content like `"חפירה וביסוס - 3 מ״ק"` renders reversed. Currency `₪1,500` gets scrambled. Tables need `row-reverse` everywhere. Font setup is undocumented.
|
|
6
|
+
|
|
7
|
+
This library fixes all of that.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install react-pdf-rtl
|
|
15
|
+
# peer dependencies
|
|
16
|
+
npm install @react-pdf/renderer react
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { Document, Page } from "@react-pdf/renderer";
|
|
25
|
+
import {
|
|
26
|
+
setupHebrewPDF,
|
|
27
|
+
RTLText,
|
|
28
|
+
RTLTable,
|
|
29
|
+
RTLSummaryRow,
|
|
30
|
+
RTLDivider,
|
|
31
|
+
getRTLPageStyle,
|
|
32
|
+
} from "react-pdf-rtl";
|
|
33
|
+
|
|
34
|
+
// Register Rubik font + disable hyphenation — call once at module level
|
|
35
|
+
setupHebrewPDF();
|
|
36
|
+
|
|
37
|
+
const pageStyle = getRTLPageStyle("Rubik");
|
|
38
|
+
|
|
39
|
+
export function QuotePDF({ items, total }) {
|
|
40
|
+
return (
|
|
41
|
+
<Document>
|
|
42
|
+
<Page size="A4" style={pageStyle}>
|
|
43
|
+
<RTLText style={{ fontSize: 20, fontWeight: "bold" }}>
|
|
44
|
+
הצעת מחיר
|
|
45
|
+
</RTLText>
|
|
46
|
+
|
|
47
|
+
<RTLDivider marginVertical={12} />
|
|
48
|
+
|
|
49
|
+
<RTLTable
|
|
50
|
+
columns={[
|
|
51
|
+
{ header: "תיאור עבודה", key: "description", flex: 3 },
|
|
52
|
+
{ header: "כמות", key: "quantity", flex: 1, align: "center" },
|
|
53
|
+
{ header: "יחידה", key: "unit", flex: 1, align: "center" },
|
|
54
|
+
{ header: "מחיר יחידה", key: "unitPrice", flex: 1, isCurrency: true },
|
|
55
|
+
{ header: 'סה"כ', key: "total", flex: 1, isCurrency: true },
|
|
56
|
+
]}
|
|
57
|
+
data={items}
|
|
58
|
+
headerBg="#1F2937"
|
|
59
|
+
headerColor="#EAB308"
|
|
60
|
+
/>
|
|
61
|
+
|
|
62
|
+
<RTLDivider marginVertical={8} />
|
|
63
|
+
|
|
64
|
+
<RTLSummaryRow label='סה"כ לפני מע"מ' value={total} isCurrency />
|
|
65
|
+
<RTLSummaryRow label='מע"מ 18%' value={total * 0.18} isCurrency />
|
|
66
|
+
<RTLSummaryRow
|
|
67
|
+
label="סכום סופי לתשלום"
|
|
68
|
+
value={total * 1.18}
|
|
69
|
+
isCurrency
|
|
70
|
+
bold
|
|
71
|
+
/>
|
|
72
|
+
</Page>
|
|
73
|
+
</Document>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## API Reference
|
|
81
|
+
|
|
82
|
+
### Font Setup
|
|
83
|
+
|
|
84
|
+
#### `setupHebrewPDF(fontFamily?)`
|
|
85
|
+
One-shot setup. Registers font + disables hyphenation. Call once at module level.
|
|
86
|
+
```ts
|
|
87
|
+
setupHebrewPDF(); // defaults to "Rubik"
|
|
88
|
+
setupHebrewPDF("NotoSansHebrew");
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### `registerRubik()`
|
|
92
|
+
Registers Rubik (weights 300, 400, 500, 700) from Google Fonts CDN.
|
|
93
|
+
|
|
94
|
+
#### `registerNotoSansHebrew()`
|
|
95
|
+
Registers Noto Sans Hebrew from Google Fonts CDN.
|
|
96
|
+
|
|
97
|
+
#### `registerRTLFont(options)`
|
|
98
|
+
Register any custom font:
|
|
99
|
+
```ts
|
|
100
|
+
registerRTLFont({
|
|
101
|
+
family: "MyFont",
|
|
102
|
+
fonts: [
|
|
103
|
+
{ src: "/fonts/MyFont-Regular.ttf", fontWeight: "normal" },
|
|
104
|
+
{ src: "/fonts/MyFont-Bold.ttf", fontWeight: "bold" },
|
|
105
|
+
],
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
#### `disableHyphenation()`
|
|
110
|
+
Prevents Hebrew words from being split mid-word. Called automatically by `setupHebrewPDF`.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### Components
|
|
115
|
+
|
|
116
|
+
#### `<RTLText>`
|
|
117
|
+
Drop-in replacement for `<Text>` with automatic RTL detection and bidi wrapping.
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
<RTLText style={{ fontSize: 14 }}>חפירה וביסוס - 3 מ"ק</RTLText>
|
|
121
|
+
<RTLText direction="rtl">כותרת</RTLText>
|
|
122
|
+
<RTLText direction="ltr">English text</RTLText>
|
|
123
|
+
<RTLText direction="auto">auto-detected</RTLText> {/* default */}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
| Prop | Type | Default | Description |
|
|
127
|
+
|------|------|---------|-------------|
|
|
128
|
+
| `children` | `string \| number` | — | Text content |
|
|
129
|
+
| `style` | `Style` | — | react-pdf style |
|
|
130
|
+
| `direction` | `"rtl" \| "ltr" \| "auto"` | `"auto"` | Force or auto-detect direction |
|
|
131
|
+
| `wrap` | `boolean` | `true` | Allow text wrapping |
|
|
132
|
+
|
|
133
|
+
#### `<RTLView>`
|
|
134
|
+
A `<View>` pre-set with `flexDirection: "row-reverse"` and `textAlign: "right"`.
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
<RTLView style={{ gap: 8 }}>
|
|
138
|
+
<RTLText>תיאור</RTLText>
|
|
139
|
+
<Text>₪1,200</Text>
|
|
140
|
+
</RTLView>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### `<RTLTable>`
|
|
144
|
+
Full RTL-aware table. Columns rendered right-to-left. Hebrew cells auto-wrapped.
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
<RTLTable
|
|
148
|
+
columns={[
|
|
149
|
+
{ header: "תיאור", key: "description", flex: 3 },
|
|
150
|
+
{ header: "כמות", key: "qty", flex: 1, align: "center" },
|
|
151
|
+
{ header: "מחיר", key: "price", flex: 1, isCurrency: true },
|
|
152
|
+
]}
|
|
153
|
+
data={rows}
|
|
154
|
+
headerBg="#1F2937"
|
|
155
|
+
headerColor="#FFFFFF"
|
|
156
|
+
stripeBg="#F9FAFB"
|
|
157
|
+
/>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
| Column Prop | Type | Description |
|
|
161
|
+
|------------|------|-------------|
|
|
162
|
+
| `header` | `string` | Column header (auto RTL-wrapped) |
|
|
163
|
+
| `key` | `string` | Row data key |
|
|
164
|
+
| `flex` | `number` | Relative width |
|
|
165
|
+
| `width` | `number` | Fixed width in pts |
|
|
166
|
+
| `align` | `"right" \| "left" \| "center"` | Cell text alignment |
|
|
167
|
+
| `isCurrency` | `boolean` | Formats as `₪1,500` |
|
|
168
|
+
| `render` | `(value, row) => string` | Custom cell renderer |
|
|
169
|
+
|
|
170
|
+
#### `<RTLSummaryRow>`
|
|
171
|
+
Label + value row for totals, right-aligned label, left-aligned value.
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
<RTLSummaryRow label='סה"כ' value={12500} isCurrency bold />
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
#### `<RTLDivider>`
|
|
178
|
+
Simple horizontal rule.
|
|
179
|
+
```tsx
|
|
180
|
+
<RTLDivider color="#E5E7EB" thickness={1} marginVertical={8} />
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### `getRTLPageStyle(fontFamily?)`
|
|
184
|
+
Returns a base `Style` object for RTL pages.
|
|
185
|
+
```ts
|
|
186
|
+
const style = getRTLPageStyle("Rubik");
|
|
187
|
+
// { fontFamily: "Rubik", direction: "rtl", textAlign: "right", padding: ... }
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
### Utilities
|
|
193
|
+
|
|
194
|
+
#### `hasRTLChars(str)`
|
|
195
|
+
Returns `true` if string contains any Hebrew/Arabic characters.
|
|
196
|
+
|
|
197
|
+
#### `isRTLDominant(str)`
|
|
198
|
+
Returns `true` if the majority of alphabetic characters are RTL.
|
|
199
|
+
|
|
200
|
+
#### `wrapRTL(str)` / `wrapLTR(str)`
|
|
201
|
+
Manually wrap text in Unicode bidi markers (`\u202B...\u202C`).
|
|
202
|
+
|
|
203
|
+
#### `smartWrap(str)`
|
|
204
|
+
Auto-detect direction and wrap accordingly. Pure numbers are left unchanged.
|
|
205
|
+
|
|
206
|
+
#### `formatCurrencyRTL(amount, symbol?, locale?)`
|
|
207
|
+
Format a number as currency, ensuring `₪` and digits render correctly in RTL context.
|
|
208
|
+
```ts
|
|
209
|
+
formatCurrencyRTL(1500) // ₪1,500 (correct RTL direction)
|
|
210
|
+
formatCurrencyRTL(1500, "$", "en-US") // $1,500
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### `splitBidiSegments(str)`
|
|
214
|
+
Split mixed text into RTL/LTR/neutral segments:
|
|
215
|
+
```ts
|
|
216
|
+
splitBidiSegments("שלום world 123")
|
|
217
|
+
// [
|
|
218
|
+
// { text: "שלום ", direction: "rtl" },
|
|
219
|
+
// { text: "world ", direction: "ltr" },
|
|
220
|
+
// { text: "123", direction: "neutral" },
|
|
221
|
+
// ]
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Why This Exists
|
|
227
|
+
|
|
228
|
+
The [`diegomura/react-pdf`](https://github.com/diegomura/react-pdf) issue tracker has RTL/Hebrew bug reports dating back to 2019 ([#732](https://github.com/diegomura/react-pdf/issues/732), [#1571](https://github.com/diegomura/react-pdf/issues/1571), [#3010](https://github.com/diegomura/react-pdf/issues/3010)) with no official fix. This library provides a battle-tested layer on top.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## License
|
|
233
|
+
|
|
234
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Style } from '@react-pdf/types';
|
|
4
|
+
|
|
5
|
+
interface RTLTextProps {
|
|
6
|
+
children: string | number;
|
|
7
|
+
style?: Style | Style[];
|
|
8
|
+
/** Force direction instead of auto-detecting */
|
|
9
|
+
direction?: "rtl" | "ltr" | "auto";
|
|
10
|
+
wrap?: boolean;
|
|
11
|
+
debug?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Drop-in replacement for @react-pdf/renderer's <Text> with RTL support.
|
|
15
|
+
*
|
|
16
|
+
* Automatically:
|
|
17
|
+
* - Detects Hebrew/Arabic content and applies RLE bidi markers
|
|
18
|
+
* - Handles mixed content (Hebrew text + numbers) correctly
|
|
19
|
+
* - Preserves LTR content unchanged
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* <RTLText style={{ fontSize: 14 }}>חפירה וביסוס - 3 מ"ק</RTLText>
|
|
23
|
+
* <RTLText>Item description in English</RTLText>
|
|
24
|
+
*/
|
|
25
|
+
declare function RTLText({ children, style, direction, wrap, debug }: RTLTextProps): react_jsx_runtime.JSX.Element;
|
|
26
|
+
interface RTLViewProps {
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
style?: Style | Style[];
|
|
29
|
+
debug?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A <View> pre-configured for RTL layout.
|
|
33
|
+
* Sets flexDirection to "row-reverse" and textAlign to "right".
|
|
34
|
+
* Use as a wrapper for rows in RTL documents.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* <RTLView style={{ marginBottom: 8 }}>
|
|
38
|
+
* <RTLText>תיאור עבודה</RTLText>
|
|
39
|
+
* <Text>₪1,200</Text>
|
|
40
|
+
* </RTLView>
|
|
41
|
+
*/
|
|
42
|
+
declare function RTLView({ children, style, debug }: RTLViewProps): react_jsx_runtime.JSX.Element;
|
|
43
|
+
/**
|
|
44
|
+
* Returns base styles for an RTL page layout.
|
|
45
|
+
* Pass your fontFamily to get consistent defaults.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* const pageStyle = getRTLPageStyle("Rubik");
|
|
49
|
+
*/
|
|
50
|
+
declare function getRTLPageStyle(fontFamily?: string): Style;
|
|
51
|
+
interface RTLTableColumn {
|
|
52
|
+
/** Column header label */
|
|
53
|
+
header: string;
|
|
54
|
+
/** Key in the data row object */
|
|
55
|
+
key: string;
|
|
56
|
+
/** Flex width (like CSS flex) */
|
|
57
|
+
flex?: number;
|
|
58
|
+
/** Explicit width in pts */
|
|
59
|
+
width?: number;
|
|
60
|
+
/** Text alignment within the cell */
|
|
61
|
+
align?: "right" | "left" | "center";
|
|
62
|
+
/** If true, formats value as currency using formatCurrencyRTL */
|
|
63
|
+
isCurrency?: boolean;
|
|
64
|
+
/** Custom cell renderer */
|
|
65
|
+
render?: (value: unknown, row: Record<string, unknown>) => string;
|
|
66
|
+
}
|
|
67
|
+
interface RTLTableProps {
|
|
68
|
+
columns: RTLTableColumn[];
|
|
69
|
+
data: Record<string, unknown>[];
|
|
70
|
+
fontFamily?: string;
|
|
71
|
+
/** Header background color */
|
|
72
|
+
headerBg?: string;
|
|
73
|
+
/** Header text color */
|
|
74
|
+
headerColor?: string;
|
|
75
|
+
/** Row stripe color (alternating rows) */
|
|
76
|
+
stripeBg?: string;
|
|
77
|
+
/** Border color */
|
|
78
|
+
borderColor?: string;
|
|
79
|
+
/** Font size for table content */
|
|
80
|
+
fontSize?: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A fully RTL-aware table component for @react-pdf/renderer.
|
|
84
|
+
*
|
|
85
|
+
* Renders columns right-to-left, handles Hebrew text in cells,
|
|
86
|
+
* and supports currency formatting out of the box.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* <RTLTable
|
|
90
|
+
* columns={[
|
|
91
|
+
* { header: "תיאור", key: "description", flex: 3 },
|
|
92
|
+
* { header: "כמות", key: "quantity", flex: 1, align: "center" },
|
|
93
|
+
* { header: "מחיר יחידה", key: "unitPrice", flex: 1, isCurrency: true },
|
|
94
|
+
* { header: 'סה"כ', key: "total", flex: 1, isCurrency: true },
|
|
95
|
+
* ]}
|
|
96
|
+
* data={boqItems}
|
|
97
|
+
* headerBg="#1a1a1a"
|
|
98
|
+
* headerColor="#EAB308"
|
|
99
|
+
* />
|
|
100
|
+
*/
|
|
101
|
+
declare function RTLTable({ columns, data, fontFamily, headerBg, headerColor, stripeBg, borderColor, fontSize, }: RTLTableProps): react_jsx_runtime.JSX.Element;
|
|
102
|
+
interface RTLDividerProps {
|
|
103
|
+
color?: string;
|
|
104
|
+
thickness?: number;
|
|
105
|
+
marginVertical?: number;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* A simple horizontal divider for RTL PDF documents.
|
|
109
|
+
*/
|
|
110
|
+
declare function RTLDivider({ color, thickness, marginVertical }: RTLDividerProps): react_jsx_runtime.JSX.Element;
|
|
111
|
+
interface RTLSummaryRowProps {
|
|
112
|
+
label: string;
|
|
113
|
+
value: string | number;
|
|
114
|
+
isCurrency?: boolean;
|
|
115
|
+
bold?: boolean;
|
|
116
|
+
fontSize?: number;
|
|
117
|
+
color?: string;
|
|
118
|
+
fontFamily?: string;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* A label + value row for totals/summaries in RTL layout.
|
|
122
|
+
* Label on the right, value on the left — as expected in Hebrew documents.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* <RTLSummaryRow label='סה"כ לפני מע"מ' value={12500} isCurrency bold />
|
|
126
|
+
* <RTLSummaryRow label='מע"מ 18%' value={2250} isCurrency />
|
|
127
|
+
* <RTLSummaryRow label="סכום סופי" value={14750} isCurrency bold color="#EAB308" />
|
|
128
|
+
*/
|
|
129
|
+
declare function RTLSummaryRow({ label, value, isCurrency, bold, fontSize, color, fontFamily, }: RTLSummaryRowProps): react_jsx_runtime.JSX.Element;
|
|
130
|
+
|
|
131
|
+
type RTLFontWeight = "normal" | "bold" | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
|
|
132
|
+
interface RTLFontSource {
|
|
133
|
+
src: string;
|
|
134
|
+
fontWeight?: RTLFontWeight;
|
|
135
|
+
fontStyle?: "normal" | "italic";
|
|
136
|
+
}
|
|
137
|
+
interface RegisterRTLFontOptions {
|
|
138
|
+
/** Font family name, e.g. "Rubik" */
|
|
139
|
+
family: string;
|
|
140
|
+
/** Array of font sources (different weights/styles) */
|
|
141
|
+
fonts: RTLFontSource[];
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Registers a font family with @react-pdf/renderer.
|
|
145
|
+
* Wraps Font.register with sensible defaults for RTL fonts.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* registerRTLFont({
|
|
149
|
+
* family: "Rubik",
|
|
150
|
+
* fonts: [
|
|
151
|
+
* { src: "/fonts/Rubik-Regular.ttf", fontWeight: "normal" },
|
|
152
|
+
* { src: "/fonts/Rubik-Bold.ttf", fontWeight: "bold" },
|
|
153
|
+
* ],
|
|
154
|
+
* });
|
|
155
|
+
*/
|
|
156
|
+
declare function registerRTLFont(options: RegisterRTLFontOptions): void;
|
|
157
|
+
/**
|
|
158
|
+
* Registers the Rubik font from Google Fonts CDN.
|
|
159
|
+
* Rubik is the recommended font for Hebrew PDFs — designed for Hebrew,
|
|
160
|
+
* supports all weights, and renders cleanly in @react-pdf/renderer.
|
|
161
|
+
*
|
|
162
|
+
* Weights registered: 300 (Light), 400 (Regular), 500 (Medium), 700 (Bold)
|
|
163
|
+
*/
|
|
164
|
+
declare function registerRubik(): void;
|
|
165
|
+
/**
|
|
166
|
+
* Registers Noto Sans Hebrew from Google Fonts CDN.
|
|
167
|
+
* Good fallback if Rubik is not desired — extensive Hebrew glyph coverage.
|
|
168
|
+
*/
|
|
169
|
+
declare function registerNotoSansHebrew(): void;
|
|
170
|
+
/**
|
|
171
|
+
* Disables font hyphenation — critical for Hebrew text.
|
|
172
|
+
* Hebrew words should never be hyphenated mid-word.
|
|
173
|
+
*/
|
|
174
|
+
declare function disableHyphenation(): void;
|
|
175
|
+
/**
|
|
176
|
+
* One-shot setup: registers Rubik + disables hyphenation.
|
|
177
|
+
* This is the recommended setup for Hebrew PDFs.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* // At the top of your PDF component file:
|
|
181
|
+
* setupHebrewPDF();
|
|
182
|
+
*/
|
|
183
|
+
declare function setupHebrewPDF(fontFamily?: "Rubik" | "NotoSansHebrew"): void;
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Unicode bidi control characters
|
|
187
|
+
*/
|
|
188
|
+
declare const BIDI: {
|
|
189
|
+
/** Right-to-Left Embedding — forces RTL rendering for the embedded text */
|
|
190
|
+
readonly RLE: "";
|
|
191
|
+
/** Left-to-Right Embedding */
|
|
192
|
+
readonly LRE: "";
|
|
193
|
+
/** Pop Directional Formatting — ends the current embedding */
|
|
194
|
+
readonly PDF: "";
|
|
195
|
+
/** Right-to-Left Mark — invisible RTL directional mark */
|
|
196
|
+
readonly RLM: "";
|
|
197
|
+
/** Left-to-Right Mark */
|
|
198
|
+
readonly LRM: "";
|
|
199
|
+
/** Right-to-Left Override — strongly forces RTL */
|
|
200
|
+
readonly RLO: "";
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Returns true if the string contains any RTL characters (Hebrew, Arabic, etc.)
|
|
204
|
+
* FIX: coerces input to string — safe when called from JS without types
|
|
205
|
+
*/
|
|
206
|
+
declare function hasRTLChars(str: unknown): boolean;
|
|
207
|
+
/**
|
|
208
|
+
* Returns true if the MAJORITY of the string's alphabetic content is RTL.
|
|
209
|
+
* Useful for mixed strings like "מחיר: 120 ₪" — still considered RTL.
|
|
210
|
+
* FIX: coerces input to string — safe when called from JS without types
|
|
211
|
+
*/
|
|
212
|
+
declare function isRTLDominant(str: unknown): boolean;
|
|
213
|
+
/**
|
|
214
|
+
* Wraps text in RLE...PDF bidi markers so @react-pdf/renderer
|
|
215
|
+
* renders it right-to-left correctly, including mixed content.
|
|
216
|
+
*
|
|
217
|
+
* FIX: idempotent — guards against double-wrapping (broken bidi nesting)
|
|
218
|
+
*/
|
|
219
|
+
declare function wrapRTL(text: string): string;
|
|
220
|
+
/**
|
|
221
|
+
* Wraps text in LRE...PDF for explicit LTR segments inside an RTL document.
|
|
222
|
+
* FIX: idempotent — guards against double-wrapping
|
|
223
|
+
*/
|
|
224
|
+
declare function wrapLTR(text: string): string;
|
|
225
|
+
/**
|
|
226
|
+
* Smart wrap: auto-detects direction and wraps accordingly.
|
|
227
|
+
* FIX: accepts string | number | null | undefined — BoQ fields are often numbers
|
|
228
|
+
*/
|
|
229
|
+
declare function smartWrap(text: string | number | null | undefined): string;
|
|
230
|
+
/**
|
|
231
|
+
* Formats a currency amount for RTL display.
|
|
232
|
+
* Ensures the symbol (₪) and number don't get scrambled in bidi context.
|
|
233
|
+
*
|
|
234
|
+
* FIX: throws RangeError on NaN/Infinity with clear message
|
|
235
|
+
* FIX: handles negative amounts correctly (discounts, returns)
|
|
236
|
+
*/
|
|
237
|
+
declare function formatCurrencyRTL(amount: number, symbol?: string, locale?: string): string;
|
|
238
|
+
/**
|
|
239
|
+
* Splits mixed RTL/LTR text into segments with direction metadata.
|
|
240
|
+
* Reconstructs exactly: splitBidiSegments(s).map(s => s.text).join('') === s
|
|
241
|
+
*
|
|
242
|
+
* FIX: uses Array.from() to correctly handle surrogate pairs (emoji, rare Unicode)
|
|
243
|
+
*/
|
|
244
|
+
type TextSegment = {
|
|
245
|
+
text: string;
|
|
246
|
+
direction: "rtl" | "ltr" | "neutral";
|
|
247
|
+
};
|
|
248
|
+
declare function splitBidiSegments(text: string): TextSegment[];
|
|
249
|
+
/**
|
|
250
|
+
* Returns true if the string already contains bidi control characters.
|
|
251
|
+
*/
|
|
252
|
+
declare function hasBidiMarkers(text: string): boolean;
|
|
253
|
+
/**
|
|
254
|
+
* Strips all bidi control characters from a string.
|
|
255
|
+
* Use for: extracting plain text for storage, search, or logging.
|
|
256
|
+
*/
|
|
257
|
+
declare function stripBidiMarkers(text: string): string;
|
|
258
|
+
|
|
259
|
+
export { BIDI, RTLDivider, type RTLDividerProps, type RTLFontSource, type RTLFontWeight, RTLSummaryRow, type RTLSummaryRowProps, RTLTable, type RTLTableColumn, type RTLTableProps, RTLText, type RTLTextProps, RTLView, type RTLViewProps, type RegisterRTLFontOptions, type TextSegment, disableHyphenation, formatCurrencyRTL, getRTLPageStyle, hasBidiMarkers, hasRTLChars, isRTLDominant, registerNotoSansHebrew, registerRTLFont, registerRubik, setupHebrewPDF, smartWrap, splitBidiSegments, stripBidiMarkers, wrapLTR, wrapRTL };
|