mesdan 1.0.3 → 1.1.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/README.md CHANGED
@@ -1,42 +1,218 @@
1
- # Osmani membasının gayesi nedir?
1
+ # Mesdan (مسدان)
2
2
 
3
- Latin harflerinin bulunduğu mesdanla Osmanlı Türkçesi yazabilmek için hazırlanmıştır.
4
- Mesdandan basılan harfin yerine Osmanî dengini yazar.
3
+ [![NPM Version](https://img.shields.io/npm/v/mesdan.svg)](https://www.npmjs.com/package/mesdan)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![React](https://img.shields.io/badge/react-%3E%3D18-blue.svg)](https://reactjs.org/)
5
6
 
6
- ## Nasıl Kullanılır?
7
+ _Mesdan_ kelimesi tuş (touch) takımı yani **keyboard** demektir.
7
8
 
8
- Bu memba **React** ile hazırlanan sahifelerde kullanılmak için geliştirilmiştir.
9
- Sırası ile aşağıdaki adımları takip edelim:
9
+ İşbu menba Latin hurufatlı mesdanları kullanarak Osmanlı Türkçesi yazabilmek için hazırlanmıştır.
10
+ Kancaya tanıtılan `<textarea>` ya `<input>` unsurlarının idâresini ele alıp yazma, silme, belleme (copy), koparma (cut), yerleme (paste) ilh.
11
+ amelleri Osmanlı Türkçesiyle çalışacak şekilde îfâ eder.
10
12
 
11
- Membayı tarhımıza dahil edelim:
13
+ ---
12
14
 
15
+ <details>
16
+ <summary><strong>Click here for the English version</strong></summary>
17
+
18
+ # Mesdan (مسدان)
19
+
20
+ The word _Mesdan_ is an old Turkish word for **keyboard**.
21
+
22
+ This React hook is designed to facilitate writing Ottoman Turkish text using a standard Latin keyboard. It takes control of a given `<textarea>` or `<input>` element to ensure that actions like typing, deleting, copying, cutting, and pasting work correctly for the Ottoman script.
23
+
24
+ </details>
25
+
26
+ ---
27
+
28
+ ## Kurma (Installation)
29
+
30
+ ```bash
31
+ npm install mesdan
32
+ # ya / or
33
+ yarn add mesdan
34
+ ```
35
+
36
+ ## Temel Kullanım (Basic Usage)
37
+
38
+ `useMesdan` kancasını unsura (component) dahil edin ve dönen `metin` ile `metinSahasıİması` değerlerini alâkalı unsura tanıtın.
39
+
40
+ - `metin`: Unsurun `value` hassasına verilecek olan metindir.
41
+ - `metinSahasıİması`: Unsurun `ref` hassasına verilecek olan delîldir.
42
+
43
+ ```tsx
44
+ import React from 'react';
45
+ import { useMesdan } from 'mesdan';
46
+
47
+ const TemelMesdan = () => {
48
+ const [metin, metinSahasıİması] = useMesdan<HTMLInputElement>({
49
+ ibtidaiMetin: '',
50
+ tekSatırMı: true, // `true` ise <input>, `false` ise <textarea>
51
+ });
52
+
53
+ return (
54
+ <input
55
+ ref={metinSahasıİması}
56
+ dir="rtl"
57
+ value={metin}
58
+ onChange={() => {}} // Kanca metni kendi idare ettiği için boş bırakılabilir
59
+ />
60
+ );
61
+ };
62
+
63
+ export default TemelMesdan;
13
64
  ```
14
- npm install mesdan
65
+
66
+ > **Şerh:** `onChange` vaqası (event) kanca tarafından dâhilen idare edildiği için boş bırakılabilir. React, `value` hassası olan unsurlarda bir `onChange` ameli beklediği için ekledik ama lâzım değil.
67
+
68
+ ## Kancanın Hassaları (Hook Props)
69
+
70
+ `useMesdan` kancası bir nesne (object) alır. İşte bu nesnenin alabileceği hassalar:
71
+
72
+ | Hususiyet (Prop) | Nev (Type) | Mecburi mi? (Required?) | İzah (Description) |
73
+ | -------------------- | ----------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
74
+ | `ibtidaiMetin` | `string` | Yo (No) | Metin sahasının ilk değeridir. Varsayılan (default) `''`. |
75
+ | `tekSatırMı` | `boolean` | He (Yes) | `true` ise tek satırlı (`<input>`) gibi çalışır ve `Enter` tuşuna basılınca `aramaTalepEdilince` amelini tetikler. `false` ise yeni satır ekler. |
76
+ | `latiniMi` | `boolean` | Yo (No) | `true` ise kanca âtıl hale gelir ve Alfabe ile yazmağa başlar. Varsayılan `false`. |
77
+ | `aramaTalepEdilince` | `() => void` | Yo (No) | `tekSatırMı` `true` iken `Enter` tuşuna basıldığında koşulan ameldir. |
78
+ | `metin` | `string` | Yo (No) | Kancanın idâresini harice verir. `tayinMetin` ile beraber kullanılır. |
79
+ | `tayinMetin` | `(yeniMetin: string) => void` | Yo (No) | Kancanın idâresini harice verir. `metin` ile beraber kullanılır. |
80
+
81
+ ## Kancanın Vâsılatı (Return Values)
82
+
83
+ Kanca, dört unsurdan müteşekkil bir dizi (array) döndürür:
84
+
85
+ ```ts
86
+ type MesdanVasılatı<T> = [
87
+ metin: string,
88
+ metinSahasıİması: RefObject<T | null>,
89
+ tebdilMetin: (yeniMetin: string) => void,
90
+ tebdilLatiniMi: (latiniMi: boolean) => void,
91
+ ];
15
92
  ```
16
93
 
17
- **useMesdan** kancasını unsura dahil edelim:
94
+ 1. **`metin`** (`string`):
95
+ Metin sahasının cârî değeri.
96
+
97
+ 2. **`metinSahasıİması`** (`RefObject`):
98
+ `input` veya `textarea` unsuruna banılacak olan `ref`. (ba-mak => bağlamak, rapt etmek)
99
+
100
+ 3. **`tebdilMetin`** (`(yeniMetin: string) => void`):
101
+ Metni haricen (programmatically) değiştirir.
102
+
103
+ 4. **`tebdilLatiniMi`** (`(latiniMi: boolean) => void`):
104
+ Haleti Elifba ile Alfabe değiştirmek için kullanılır.
105
+
106
+ ## İleri Seviye Kullanım Misâlleri (Advanced Usage Examples)
107
+
108
+ ### 1. Çok Satırlı Metin Sahası (`<textarea>`)
18
109
 
110
+ `tekSatırMı` hassasını `false` yaparak adid satırlı metin girişi sağlayabilirsiniz. Bu halde `Enter` mesine basmak yeni bir satır ekler.
111
+
112
+ ```tsx
113
+ import { useMesdan } from 'mesdan';
114
+
115
+ const AdidSatırlıMesdan = () => {
116
+ const [metin, metinSahasıİması] = useMesdan<HTMLTextAreaElement>({
117
+ ibtidaiMetin: '',
118
+ tekSatırMı: false,
119
+ });
120
+
121
+ return <textarea ref={metinSahasıİması} dir="rtl" value={metin} onChange={() => {}} rows={5} />;
122
+ };
19
123
  ```
20
- const [kelime, metinSahasıİması] = useMesdan<HTMLInputElement>({
21
- ibtidaiKelime: "",
124
+
125
+ ### 2. Hâriçten İdâreli Unsur (Controlled Component)
126
+
127
+ Metin vaziyetini (state) kancanın hâricinden idâre etmek isterseniz, `metin` ve `tayinMetin` hassalarını kullanabilirsiniz.
128
+
129
+ ```tsx
130
+ import { useState } from 'react';
131
+ import { useMesdan } from 'mesdan';
132
+
133
+ const HariçtenİdareliMesdan = () => {
134
+ const [hariciMetin, tayinHariciMetin] = useState('');
135
+
136
+ const [, metinSahasıİması] = useMesdan<HTMLInputElement>({
22
137
  tekSatırMı: true,
138
+
139
+ metin: hariciMetin,
140
+ tayinMetin: tayinHariciMetin,
23
141
  });
142
+
143
+ return (
144
+ <div>
145
+ <input ref={metinSahasıİması} dir="rtl" value={hariciMetin} onChange={() => {}} />
146
+ <button onClick={() => tayinHariciMetin('')}>Metni İmhâ Et</button>
147
+ <p>Hârici Metin: {hariciMetin}</p>
148
+ </div>
149
+ );
150
+ };
24
151
  ```
25
152
 
26
- Bu kanca **[kelime, metinSahasıİması]** dizisini cevaben iletir.
27
- **metinSahasıİması**, **input** unsurunun **ref** hususiyetine tanıtılmalıdır.
28
- Bu sayede **useMesdan** **input** sahası seçiliyken basılan harfleri dinleyecek ve işbu harfleri
29
- Osmanî denkleri ile değiştirecektir. Osmani Elifba ile yazılmış **kelime** evvelki dizi ile
30
- kancaldan alınmıştı. **input** sahasının **value** kısmına işbu **kelime** tanıtılmalıdır.
31
- İlaveten, **onChange** dinleyicisi de aşağıdaki gibi hazır edilmelidir.
153
+ ### 3. Yazım Haletini Zirleme (Toggling Input Mode)
154
+
155
+ Kullanıcının Elifba ve Alfabe yazım arasında geçiş yapmasını sağlamak için `tebdilLatiniMi` amelini kullanabilirsiniz.
156
+
157
+ ```tsx
158
+ import { useState } from 'react';
159
+ import { useMesdan } from 'mesdan';
160
+
161
+ const LisanZirliMesdan = () => {
162
+ const [latiniMi, tayinLatiniMi] = useState(false);
32
163
 
164
+ const [metin, metinSahasıİması, , tebdilLatiniMi] = useMesdan<HTMLInputElement>({
165
+ ibtidaiMetin: '',
166
+ tekSatırMı: true,
167
+ latiniMi: latiniMi,
168
+ });
169
+
170
+ const ifaZir = () => {
171
+ const yeniHalet = !latiniMi;
172
+ tayinLatiniMi(yeniHalet);
173
+ tebdilLatiniMi(yeniHalet);
174
+ };
175
+
176
+ return (
177
+ <div>
178
+ <input
179
+ ref={metinSahasıİması}
180
+ value={metin}
181
+ onChange={() => {}}
182
+ dir={latiniMi ? 'ltr' : 'rtl'}
183
+ placeholder={latiniMi ? 'Alfabe ile yaz...' : 'الفبا ايله‌ ياز...'}
184
+ />
185
+ <button onClick={ifaZir}>{latiniMi ? "Elifba'ya geç" : "Alfabe'ye geç"}</button>
186
+ </div>
187
+ );
188
+ };
33
189
  ```
34
- <input
35
- ref={metinSahasıİması}
36
- dir="rtl"
37
- type="text"
38
- placeholder="كلمه"
39
- value={kelime}
40
- onChange={hadise => { }}
41
- />
190
+
191
+ ### 4. Metni Haricen Değiştirme (Programmatically Setting Text)
192
+
193
+ `tebdilMetin` fonksiyonu ile metni bir vaqaya (event) bağlı olarak değiştirebilirsiniz.
194
+
195
+ ```tsx
196
+ import { useMesdan } from 'mesdan';
197
+
198
+ const HariçtenMetinTebdilliMesdan = () => {
199
+ const [metin, metinSahasıİması, tebdilMetin] = useMesdan<HTMLTextAreaElement>({
200
+ tekSatırMı: false,
201
+ });
202
+
203
+ return (
204
+ <div>
205
+ <textarea ref={metinSahasıİması} dir="rtl" value={metin} onChange={() => {}} rows={5} />
206
+ <button onClick={() => tebdilMetin('السلام عليكم')}>Selam Ver</button>
207
+ </div>
208
+ );
209
+ };
42
210
  ```
211
+
212
+ ## Anahtar Kelimeler (Keywords)
213
+
214
+ osmanlıca, türkçe, türki, osmani, turkish, elifba, keyboard, tercüme, ottoman, latini, react, hook
215
+
216
+ ## Ruhsat (License)
217
+
218
+ Bu menba MIT Ruhsatlıdır.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mesdan",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "description": "Latinî mesdan ile Osmanî metin yazmak için hazırlanmış bir alettir.",
5
5
  "keywords": [
6
6
  "osmanlıca",
@@ -4,6 +4,8 @@ type MesdanHususları = {
4
4
  tekSatırMı: boolean;
5
5
  latiniMi?: boolean;
6
6
  aramaTalepEdilince?: () => void;
7
+ metin?: string;
8
+ tayinMetin?: (yeniMetin: string) => void;
7
9
  };
8
10
  type MesdanCevabı<T> = [
9
11
  metin: string,
@@ -11,6 +13,6 @@ type MesdanCevabı<T> = [
11
13
  tebdilMetin: (yeniMetin: string) => void,
12
14
  tebdilLatiniMi: (latiniMi: boolean) => void
13
15
  ];
14
- export declare const useMesdan: <T extends HTMLInputElement | HTMLTextAreaElement>({ ibtidaiMetin, tekSatırMı, latiniMi: ibtidaiLatiniMi, aramaTalepEdilince, }: MesdanHususları) => MesdanCevabı<T>;
16
+ export declare const useMesdan: <T extends HTMLInputElement | HTMLTextAreaElement>({ ibtidaiMetin, tekSatırMı, latiniMi: ibtidaiLatiniMi, aramaTalepEdilince, metin: metinHarici, tayinMetin: tayinMetinHarici, }: MesdanHususları) => MesdanCevabı<T>;
15
17
  export {};
16
18
  //# sourceMappingURL=use-mesdan.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-mesdan.d.ts","sourceRoot":"","sources":["../../memba/kanca/use-mesdan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA6D,MAAM,OAAO,CAAC;AAU7F,KAAK,eAAe,GAAG;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;CACjC,CAAC;AAEF,KAAK,YAAY,CAAC,CAAC,IAAI;IACrB,KAAK,EAAE,MAAM;IACb,gBAAgB,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI;IACxC,cAAc,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI;CAC5C,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,gBAAgB,GAAG,mBAAmB,gFAKvE,eAAe,KAAG,YAAY,CAAC,CAAC,CA6LlC,CAAC"}
1
+ {"version":3,"file":"use-mesdan.d.ts","sourceRoot":"","sources":["../../memba/kanca/use-mesdan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA6D,MAAM,OAAO,CAAC;AAU7F,KAAK,eAAe,GAAG;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAEhC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C,CAAC;AAEF,KAAK,YAAY,CAAC,CAAC,IAAI;IACrB,KAAK,EAAE,MAAM;IACb,gBAAgB,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI;IACxC,cAAc,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI;CAC5C,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,gBAAgB,GAAG,mBAAmB,kIAOvE,eAAe,KAAG,YAAY,CAAC,CAAC,CA4MlC,CAAC"}
@@ -3,9 +3,19 @@ import { harfBüyükMü } from '../aletler/harf-buyuk-mu';
3
3
  import { hazırlaAlemMevkisini, hazırlaAlemMevkisiniMenzilli } from '../nev/alem-mevkisi';
4
4
  import { TadiliMetinEmri } from '../nev/tadili-metin-emri';
5
5
  import { Talimat_MetniTadilEt } from '../nuve/tadil-et-metni';
6
- export const useMesdan = ({ ibtidaiMetin = '', tekSatırMı, latiniMi: ibtidaiLatiniMi = false, aramaTalepEdilince, }) => {
7
- const [metin, setMetin] = useState(ibtidaiMetin);
8
- const [isLatin, setIsLatin] = useState(ibtidaiLatiniMi);
6
+ export const useMesdan = ({ ibtidaiMetin = '', tekSatırMı, latiniMi: ibtidaiLatiniMi = false, aramaTalepEdilince, metin: metinHarici, tayinMetin: tayinMetinHarici, }) => {
7
+ const [metinDahili, tayinMetinDahili] = useState(ibtidaiMetin);
8
+ const [latiniMi, tayinLatiniMi] = useState(ibtidaiLatiniMi);
9
+ const kontrollüMü = metinHarici !== undefined && tayinMetinHarici !== undefined;
10
+ const metin = kontrollüMü ? metinHarici : metinDahili;
11
+ const tayinMetin = useCallback((yeniMetin) => {
12
+ if (kontrollüMü) {
13
+ tayinMetinHarici(yeniMetin);
14
+ }
15
+ else {
16
+ tayinMetinDahili(yeniMetin);
17
+ }
18
+ }, [kontrollüMü, tayinMetinHarici]);
9
19
  const metinSahasıİması = useRef(null);
10
20
  const alemMevkisiİması = useRef(hazırlaAlemMevkisini(ibtidaiMetin.length));
11
21
  const aramaTalepEdilinceRef = useRef(aramaTalepEdilince);
@@ -64,7 +74,7 @@ export const useMesdan = ({ ibtidaiMetin = '', tekSatırMı, latiniMi: ibtidaiLa
64
74
  }
65
75
  const netice = await Talimat_MetniTadilEt(metinSahası, currentMetin, alemMevkisi, tadiliMetinEmri, mesHadisesi, true);
66
76
  alemMevkisiİması.current = netice.alemMevkisiTadilSonrası;
67
- setMetin(netice.metinTadilSonrası);
77
+ tayinMetin(netice.metinTadilSonrası);
68
78
  }, [tekSatırMı]);
69
79
  const handlePaste = useCallback(async (hadise) => {
70
80
  const metinSahası = metinSahasıİması.current;
@@ -75,7 +85,7 @@ export const useMesdan = ({ ibtidaiMetin = '', tekSatırMı, latiniMi: ibtidaiLa
75
85
  const alemMevkisi = hazırlaAlemMevkisiniMenzilli(metinSahası.selectionStart || 0, metinSahası.selectionEnd || 0);
76
86
  const netice = await Talimat_MetniTadilEt(metinSahası, currentMetin, alemMevkisi, TadiliMetinEmri.YERLE, { latiniHarf: '', shiftBasılıMı: false, altBasılıMı: false, capsLockBasılıMı: false }, true);
77
87
  alemMevkisiİması.current = netice.alemMevkisiTadilSonrası;
78
- setMetin(netice.metinTadilSonrası);
88
+ tayinMetin(netice.metinTadilSonrası);
79
89
  }, []);
80
90
  const handleBeforeInput = useCallback((hadise) => {
81
91
  const metinSahası = metinSahasıİması.current;
@@ -112,11 +122,11 @@ export const useMesdan = ({ ibtidaiMetin = '', tekSatırMı, latiniMi: ibtidaiLa
112
122
  const alemMevkisi = hazırlaAlemMevkisiniMenzilli(alemMevkisiEvveli.current.baş, alemMevkisiEvveli.current.son);
113
123
  const netice = await Talimat_MetniTadilEt(metinSahası, currentMetin, alemMevkisi, tadiliMetinEmri, mesHadisesi, false);
114
124
  alemMevkisiİması.current = netice.alemMevkisiTadilSonrası;
115
- setMetin(netice.metinTadilSonrası);
125
+ tayinMetin(netice.metinTadilSonrası);
116
126
  }, [tekSatırMı]);
117
127
  useEffect(() => {
118
128
  const metinSahası = metinSahasıİması.current;
119
- if (!metinSahası || isLatin) {
129
+ if (!metinSahası || latiniMi) {
120
130
  if (metinSahası) {
121
131
  metinSahası.setAttribute('spellcheck', 'true');
122
132
  }
@@ -155,19 +165,19 @@ export const useMesdan = ({ ibtidaiMetin = '', tekSatırMı, latiniMi: ibtidaiLa
155
165
  metinSahası.removeEventListener('keydown', keydownListener);
156
166
  metinSahası.removeEventListener('paste', pasteListener);
157
167
  };
158
- }, [isLatin, tekSatırMı]);
168
+ }, [latiniMi, tekSatırMı]);
159
169
  useLayoutEffect(() => {
160
170
  const metinSahası = metinSahasıİması.current;
161
- if (metinSahası && !isLatin) {
171
+ if (metinSahası && !latiniMi) {
162
172
  const { başMevki, sonMevki } = alemMevkisiİması.current;
163
173
  if (başMevki <= metinSahası.value.length && sonMevki <= metinSahası.value.length) {
164
174
  metinSahası.setSelectionRange(başMevki, sonMevki);
165
175
  }
166
176
  }
167
- }, [metin, isLatin]);
168
- const DışarıdanMetniTebdilEt = useCallback((yeniMetin) => {
169
- setMetin(yeniMetin);
177
+ }, [metin, latiniMi]);
178
+ const tebdilMetin = useCallback((yeniMetin) => {
179
+ tayinMetin(yeniMetin);
170
180
  alemMevkisiİması.current = hazırlaAlemMevkisini(yeniMetin.length);
171
181
  }, []);
172
- return [metin, metinSahasıİması, DışarıdanMetniTebdilEt, setIsLatin];
182
+ return [metin, metinSahasıİması, tebdilMetin, tayinLatiniMi];
173
183
  };
package/talimat-2.md DELETED
@@ -1,297 +0,0 @@
1
- Excellent! Setting up a local development workflow to test your NPM package is a crucial step before publishing. It allows you to use your `mesdan` hook in a real application (like one made with Create React App, Vite, or Next.js) as if it were installed from the registry.
2
-
3
- Here are the best methods to do this, starting with the most common and recommended approach.
4
-
5
- ### Method 1: `npm link` (Recommended for Active Development)
6
-
7
- This is the standard and most efficient way to test a local package. It works by creating a symbolic link (a "symlink," which is like a shortcut) between your consumer project's `node_modules` folder and your `mesdan` package's source code.
8
-
9
- This means any changes you make in your `mesdan` project are **instantly** reflected in your test project (after you rebuild, of course), without needing to reinstall anything.
10
-
11
- **Here's the step-by-step process:**
12
-
13
- **Step 1: In your `mesdan` package directory**
14
-
15
- 1. **Build your package.** Your `package.json` has a `kur` script that compiles your TypeScript into JavaScript in the `teshir/` directory. This is the code that will actually be used by the other project.
16
- ```bash
17
- # In your /path/to/mesdan project folder
18
- npm run kur
19
- ```
20
-
21
- 2. **Register a global link.** This command tells NPM to create a global link on your computer that points to this project directory.
22
- ```bash
23
- npm link
24
- ```
25
- You should see a success message confirming the link was created for `mesdan@1.0.2`.
26
-
27
- **Step 2: In your local test project (e.g., a Create React App)**
28
-
29
- 1. **Create a test project** if you don't have one.
30
- ```bash
31
- # For example, using Vite (recommended for speed)
32
- npm create vite@latest my-test-app -- --template react-ts
33
- cd my-test-app
34
- npm install
35
- ```
36
-
37
- 2. **Link the `mesdan` package.** This command creates a symlink inside `my-test-app/node_modules/` that points to the global link you created in Step 1.
38
- ```bash
39
- # In your /path/to/my-test-app folder
40
- npm link mesdan
41
- ```
42
- Now, if you look inside `my-test-app/node_modules/`, you'll see that `mesdan` is a shortcut to your original project folder.
43
-
44
- **Step 3: Use the hook in your test project**
45
-
46
- Now you can import and use your hook just like any other package.
47
-
48
- ```tsx
49
- // In my-test-app/src/App.tsx
50
-
51
- import { useRef } from 'react';
52
- import { useMesdan } from 'mesdan'; // It works!
53
-
54
- function App() {
55
- const inputRef = useRef<HTMLInputElement>(null);
56
-
57
- const [metin, metinSahasıİması, tebdilMetin, tebdilLatiniMi] = useMesdan<HTMLInputElement>({
58
- ibtidaiMetin: "",
59
- tekSatırMı: true,
60
- latiniMi: false,
61
- aramaTalepEdilince: () => alert("Arama talep edildi!"),
62
- });
63
-
64
- return (
65
- <div>
66
- <h1>Mesdan Test Sahası</h1>
67
- <p>Aşağıdaki sahaya Osmanî metin yazmayı deneyin:</p>
68
- <input
69
- ref={metinSahasıİması}
70
- value={metin}
71
- onChange={(e) => tebdilMetin(e.target.value)} // Controlled component
72
- style={{ width: '300px', padding: '8px', direction: 'rtl', fontFamily: 'Amiri, serif', fontSize: '1.5rem' }}
73
- />
74
- <hr />
75
- <button onClick={() => tebdilLatiniMi(true)}>Latini Moda Geç</button>
76
- <button onClick={() => tebdilLatiniMi(false)}>Osmanî Moda Geç</button>
77
- </div>
78
- );
79
- }
80
-
81
- export default App;
82
- ```
83
-
84
- #### ⚠️ Important Gotcha: The "Invalid Hook Call" Error
85
-
86
- When using `npm link` with React libraries, you might encounter the dreaded "Invalid Hook Call" error. This happens because the symlink can cause your setup to have **two different copies of React** loaded: one from your test app's `node_modules` and another from your `mesdan` project's `node_modules`.
87
-
88
- **The Fix:** Tell your `mesdan` project to use the `react` from your test project.
89
-
90
- From within your `mesdan` project directory, run this command:
91
- ```bash
92
- # In your /path/to/mesdan project folder
93
- npm link ../my-test-app/node_modules/react
94
- ```
95
- This creates a symlink inside `mesdan/node_modules/` pointing to the single React instance in your test app, resolving the conflict.
96
-
97
- ---
98
-
99
- ### Method 2: `npm pack` (The "Real-World Simulation")
100
-
101
- This method is less convenient for rapid development but is an excellent way to do a final check before publishing. It creates a compressed `.tgz` file, which is the exact file that gets uploaded to the NPM registry.
102
-
103
- 1. **Build your `mesdan` project.**
104
- ```bash
105
- # In /path/to/mesdan
106
- npm run kur
107
- ```
108
-
109
- 2. **Pack it.**
110
- ```bash
111
- # In /path/to/mesdan
112
- npm pack
113
- ```
114
- This will create a file named `mesdan-1.0.2.tgz` in your project's root directory.
115
-
116
- 3. **Install the file in your test project.**
117
- ```bash
118
- # In /path/to/my-test-app
119
- # Use a relative or absolute path to the .tgz file
120
- npm install ../mesdan/mesdan-1.0.2.tgz
121
- ```
122
- This will install the package just as if it came from NPM.
123
-
124
- **Downside:** Every time you make a change to `mesdan`, you must re-build, re-pack, and re-install it in your test project.
125
-
126
- ---
127
-
128
- ### Summary and Recommendation
129
-
130
- | Method | Pros | Cons | Best for... |
131
- | :--- | :--- | :--- | :--- |
132
- | **`npm link`** | **Instant updates** (after rebuild). Fast development cycle. | Can cause React duplication issues (but it's fixable). Requires cleanup (`npm unlink`). | **Active, day-to-day development and testing.** |
133
- | **`npm pack`** | **Perfectly simulates** a real NPM installation. No weird dependency issues. | **Slow workflow.** Requires re-packing and re-installing for every change. | **Final sanity check** before you run `npm publish`. |
134
-
135
- **My advice:**
136
- Use **`npm link`** for your development. Just be ready to apply the fix for the "Invalid Hook Call" error if it appears. It's the most productive workflow by far. Then, before you publish a new version, use **`npm pack`** once as a final test to be 100% sure everything is configured correctly.
137
-
138
-
139
- ---------------------------------------------
140
-
141
- Of course! This is a very common and essential workflow for package development. Your `tercefzar` project is the perfect "consumer" application to test your local `mesdan` hook.
142
-
143
- The process involves uninstalling the version from NPM and then creating a symbolic link (`symlink`) to your local `mesdan` project folder. Here's the step-by-step guide using the recommended `npm link` method.
144
-
145
- ### Step 1: Prepare Your Local `mesdan` Package
146
-
147
- First, go to the directory where you are developing the `mesdan` hook.
148
-
149
- 1. **Build the project:** Make sure your latest TypeScript changes are compiled into JavaScript in the `teshir/` directory. Your `kur` script handles this.
150
- ```bash
151
- # Navigate to your mesdan project folder
152
- cd /path/to/your/local/mesdan
153
-
154
- # Run the build script
155
- npm run kur
156
- ```
157
-
158
- 2. **Create a global link:** This command tells your computer to create a global "shortcut" to this specific project folder, making it available to be linked by other projects.
159
- ```bash
160
- npm link
161
- ```
162
- You should see a success message indicating that a global link for `mesdan` was created.
163
-
164
- ### Step 2: Update Your `tercefzar` Project
165
-
166
- Now, go to your `tercefzar` project to remove the old package and link the new one.
167
-
168
- 1. **Uninstall the NPM version:** This removes the `mesdan` package from your `node_modules` and its entry from your `package-lock.json`.
169
- ```bash
170
- # Navigate to your tercefzar project folder
171
- cd /path/to/your/tercefzar
172
-
173
- # Uninstall the package
174
- npm uninstall mesdan
175
- ```
176
- This step is crucial to avoid conflicts.
177
-
178
- 2. **Link to your local `mesdan`:** This command looks for the global link you created in Step 1 and creates a symlink inside `tercefzar/node_modules/` that points directly to your local `mesdan` project folder.
179
- ```bash
180
- npm link mesdan
181
- ```
182
-
183
- ### Step 3: Verification and Development
184
-
185
- 1. **Check `node_modules`:** If you look inside `tercefzar/node_modules/`, you will now see that `mesdan` has a small arrow icon next to it (in many terminals and file explorers), indicating it's a symlink.
186
-
187
- 2. **Run your dev server:** Start your `tercefzar` application as usual.
188
- ```bash
189
- # In the tercefzar folder
190
- npm run çat
191
- ```
192
- Your application will now be using the code directly from your local `/path/to/your/local/mesdan` folder.
193
-
194
- ### The Development Workflow From Now On
195
-
196
- This is where `npm link` is so powerful. To test new changes:
197
-
198
- 1. Make any code changes you want in your `mesdan` project's source files (`.ts` files).
199
- 2. In the `mesdan` project terminal, **re-run your build script**.
200
- ```bash
201
- # In the mesdan folder
202
- npm run kur
203
- ```
204
- 3. Vite's development server in your `tercefzar` project will detect the changes in the linked `node_modules` directory and **automatically hot-reload** your application.
205
-
206
- You **do not** need to run `npm link` again. The link is permanent until you break it.
207
-
208
- ### ⚠️ Important: Fixing the "Invalid Hook Call" Error
209
-
210
- As mentioned previously, this setup can lead to an "Invalid Hook Call" error because you might have two copies of React—one in `tercefzar/node_modules` and one in `mesdan/node_modules`.
211
-
212
- **To fix this proactively:**
213
- Go back to your `mesdan` project folder and tell it to use the `react` from your `tercefzar` project.
214
-
215
- ```bash
216
- # In your /path/to/your/local/mesdan folder
217
- npm link ../tercefzar/node_modules/react
218
- ```
219
- *(Adjust the relative path `../tercefzar` if your projects are in different locations)*.
220
-
221
- This ensures both your hook and your application are using the exact same React instance.
222
-
223
- ### How to Revert Back to the NPM Version
224
-
225
- When you're done with local development and want to go back to using the official package from the NPM registry:
226
-
227
- 1. **Unlink the local package** in your `tercefzar` project. The `--no-save` flag is important as it prevents `npm` from removing `mesdan` from your `package.json` dependencies.
228
- ```bash
229
- # In the tercefzar folder
230
- npm unlink --no-save mesdan
231
- ```
232
-
233
- 2. **Re-install the package** from the registry.
234
- ```bash
235
- # In the tercefzar folder
236
- npm install
237
- ```
238
- This will read your `package.json` and pull the specified version of `mesdan` from NPM, restoring the original state.
239
-
240
-
241
- -------------------------------------------
242
-
243
- Excellent questions. This touches on the core behavior of `npm link` and how it interacts with `package.json` and the `node_modules` directory.
244
-
245
- ### Question 1: "mesdan not visible in package.json. How can we keep track of it?"
246
-
247
- You are correct, `npm link` **does not** modify your `package.json`. This is by design.
248
-
249
- The purpose of `npm link` is to create a temporary, local development setup. It's not meant to be a permanent dependency declaration. Your `package.json` should always reflect the dependencies that a user (or a CI/CD pipeline) would install from the NPM registry.
250
-
251
- **How to keep track of linked packages:**
252
-
253
- 1. **The `ls` command with `-g`:** You can see all globally linked packages on your system.
254
- ```bash
255
- npm ls -g --depth=0 --link=true
256
- ```
257
- This command lists all packages that you have run `npm link` on *in their source directories*. It will show you that `mesdan` is available globally for linking.
258
-
259
- 2. **The `ls` command in your project:** Inside your `tercefzar` project, you can see which dependencies are symlinked.
260
- ```bash
261
- npm ls
262
- ```
263
- In the output tree, a linked package will be clearly marked, often with an arrow `->` pointing to the absolute path of its source code on your machine. For example:
264
- ```
265
- tercefzar@0.0.1 /path/to/your/tercefzar
266
- └── mesdan@1.0.2 -> /path/to/your/local/mesdan
267
- ```
268
-
269
- 3. **Check `node_modules` directly:** In your file explorer or using `ls -l node_modules` in the terminal, you will see that `mesdan` is a symbolic link, not a regular directory.
270
-
271
- **In summary:** The "source of truth" for knowing a package is linked is the state of your `node_modules` directory, not `package.json`.
272
-
273
- ### Question 2: "What will happen if I run `npm install mesdan` without unlinking?"
274
-
275
- This is a great "what-if" scenario. If you run `npm install mesdan` while the symlink is active, **npm will overwrite the symlink.**
276
-
277
- Here's the sequence of events:
278
-
279
- 1. **npm sees `mesdan` in `package.json`:** Your `tercefzar` project's `package.json` still has `"mesdan": "^1.0.2"` listed as a dependency.
280
- 2. **npm checks `node_modules`:** It finds a folder (which is actually a symlink) named `mesdan`.
281
- 3. **npm replaces it:** npm will remove the existing symlink and install the `mesdan` package from the NPM registry, downloading the version specified in your `package.json` (or the latest compatible version).
282
- 4. **`package.json` and `package-lock.json` are updated:** The command will ensure your `package.json` and `package-lock.json` are consistent with the newly installed version from the registry.
283
-
284
- **The outcome:** Your local development link is broken, and you are back to using the official published version of the package.
285
-
286
- This is actually a very simple way to revert your setup. Instead of running `npm unlink --no-save mesdan` followed by `npm install`, you could just run `npm install` (or `npm install mesdan`), and it would effectively do the same thing: restore the dependency from the NPM registry.
287
-
288
- ### Recommended Workflow Summary
289
-
290
- | Action | Command in `tercefzar` | What it Does | Effect on `package.json` |
291
- | :--- | :--- | :--- | :--- |
292
- | **Start Local Dev** | 1. `npm uninstall mesdan` <br> 2. `npm link mesdan` | Removes NPM version, creates symlink to local `mesdan`. | `mesdan` is removed from dependencies. |
293
- | **A Better Start** | 1. `npm link mesdan` | *If `mesdan` is already in `package.json`*, this command just creates the link. No need to uninstall first. | No change. |
294
- | **End Local Dev** | `npm unlink --no-save mesdan` | Removes the symlink but keeps the dependency listed in `package.json`. | No change. |
295
- | **Restore from NPM** | `npm install` | Removes the symlink and installs the package from the NPM registry based on `package.json`. | No change. |
296
-
297
- **Pro Tip:** To avoid accidentally removing the dependency from your `package.json`, it's often best to just run `npm link mesdan` to start. If it's already installed from NPM, the link will replace it. When you're done, running `npm install` is the most reliable way to restore everything to its "official" state based on your `package.json`.