geez-input 1.0.5 → 1.0.6

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
@@ -166,7 +166,7 @@ Type a consonant followed by a vowel:
166
166
  ### Double Vowels
167
167
  Type the same vowel twice for alternate forms:
168
168
  - `ha` → ሃ
169
- - `lie` → ሌ
169
+ - `lee` → ሌ
170
170
 
171
171
  ### Punctuation
172
172
  - `:` → ፡ (word separator)
@@ -23,21 +23,16 @@ export interface GeezInputProps extends Omit<React.InputHTMLAttributes<HTMLInput
23
23
  * This is an alias for inputClassName for consistency with standard HTML inputs
24
24
  */
25
25
  className?: string;
26
- /**
27
- * Additional CSS classes to apply to the toggle button
28
- */
29
- buttonClassName?: string;
30
26
  }
31
27
  /**
32
- * Styled input component with built-in Geez phonetic keyboard support
28
+ * Input component with built-in Geez phonetic keyboard support
33
29
  *
34
30
  * Features:
35
- * - Toggle button to switch between Geez and English input modes
31
+ * - Press Cmd+Shift+S (or Ctrl+Shift+S) to toggle between Geez and English input modes
36
32
  * - Phonetic transformation (type 'hello' → 'ሀልሎ')
37
33
  * - Full support for controlled and uncontrolled component patterns
38
34
  * - Forward ref support for form libraries
39
- * - Styled with CSS classes that can be customized via className props
40
- * - Supports Tailwind CSS, CSS modules, or any CSS framework
35
+ * - Supports any CSS framework via className props
41
36
  *
42
37
  * @example
43
38
  * \`\`\`tsx
@@ -68,27 +63,5 @@ export interface GeezInputProps extends Omit<React.InputHTMLAttributes<HTMLInput
68
63
  * return <GeezInput {...register('name')} />
69
64
  * }
70
65
  * \`\`\`
71
- *
72
- * @example
73
- * \`\`\`tsx
74
- * // Custom styling with Tailwind CSS
75
- * <GeezInput
76
- * wrapperClassName="mb-4"
77
- * inputClassName="rounded-lg shadow-md"
78
- * buttonClassName="hover:opacity-80"
79
- * placeholder="Type here..."
80
- * />
81
- * \`\`\`
82
- *
83
- * @example
84
- * \`\`\`tsx
85
- * // Custom styling with CSS classes
86
- * <GeezInput
87
- * wrapperClassName="my-custom-wrapper"
88
- * inputClassName="my-custom-input"
89
- * buttonClassName="my-custom-button"
90
- * placeholder="Type here..."
91
- * />
92
- * \`\`\`
93
66
  */
94
67
  export declare const GeezInput: React.ForwardRefExoticComponent<GeezInputProps & React.RefAttributes<HTMLInputElement>>;
@@ -23,22 +23,16 @@ export interface GeezTextAreaProps extends Omit<React.TextareaHTMLAttributes<HTM
23
23
  * This is an alias for textareaClassName for consistency with standard HTML textareas
24
24
  */
25
25
  className?: string;
26
- /**
27
- * Additional CSS classes to apply to the toggle button
28
- */
29
- buttonClassName?: string;
30
26
  }
31
27
  /**
32
- * Styled textarea component with built-in Geez phonetic keyboard support
28
+ * Textarea component with built-in Geez phonetic keyboard support
33
29
  *
34
30
  * Features:
35
- * - Toggle button to switch between Geez and English input modes
31
+ * - Press Cmd+Shift+S (or Ctrl+Shift+S) to toggle between Geez and English input modes
36
32
  * - Phonetic transformation for longer text
37
33
  * - Full support for controlled and uncontrolled component patterns
38
34
  * - Forward ref support for form libraries
39
- * - Styled with CSS classes that can be customized via className props
40
- * - Supports Tailwind CSS, CSS modules, or any CSS framework
41
- * - Minimum height of 150px for comfortable writing
35
+ * - Supports any CSS framework via className props
42
36
  *
43
37
  * @example
44
38
  * \`\`\`tsx
@@ -66,27 +60,5 @@ export interface GeezTextAreaProps extends Omit<React.TextareaHTMLAttributes<HTM
66
60
  * // Start with English mode
67
61
  * <GeezTextArea defaultGeez={false} placeholder="Type here..." />
68
62
  * \`\`\`
69
- *
70
- * @example
71
- * \`\`\`tsx
72
- * // Custom styling with Tailwind CSS
73
- * <GeezTextArea
74
- * wrapperClassName="mb-4"
75
- * textareaClassName="rounded-lg shadow-md resize-none"
76
- * buttonClassName="hover:opacity-80"
77
- * placeholder="Write here..."
78
- * />
79
- * \`\`\`
80
- *
81
- * @example
82
- * \`\`\`tsx
83
- * // Custom styling with CSS classes
84
- * <GeezTextArea
85
- * wrapperClassName="my-custom-wrapper"
86
- * textareaClassName="my-custom-textarea"
87
- * buttonClassName="my-custom-button"
88
- * placeholder="Write here..."
89
- * />
90
- * \`\`\`
91
63
  */
92
64
  export declare const GeezTextArea: React.ForwardRefExoticComponent<GeezTextAreaProps & React.RefAttributes<HTMLTextAreaElement>>;
package/dist/main.js CHANGED
@@ -1,6 +1,6 @@
1
- import { jsxs as v, jsx as f } from "react/jsx-runtime";
2
- import { useCallback as T, forwardRef as N, useState as S } from "react";
3
- import './assets/main.css';const E = {
1
+ import { jsx as y } from "react/jsx-runtime";
2
+ import { useCallback as N, forwardRef as v, useState as D } from "react";
3
+ const g = {
4
4
  h: "ህ",
5
5
  l: "ል",
6
6
  m: "ም",
@@ -40,7 +40,7 @@ import './assets/main.css';const E = {
40
40
  A: "ኣ",
41
41
  E: "ኤ",
42
42
  O: "ዖ"
43
- }, z = {
43
+ }, p = {
44
44
  አ: {
45
45
  e: "አ",
46
46
  u: "ኡ",
@@ -321,13 +321,13 @@ import './assets/main.css';const E = {
321
321
  o: "ቮ",
322
322
  ua: "ቯ"
323
323
  }
324
- }, y = {
324
+ }, K = {
325
325
  ስh: "ሽ",
326
326
  ችh: "ች",
327
327
  ንy: "ኝ",
328
328
  ዝh: "ዥ",
329
329
  ጽh: "ፁ"
330
- }, h = {
330
+ }, b = {
331
331
  ":": "፡",
332
332
  "፡:": "።",
333
333
  "።:": "፡",
@@ -335,7 +335,7 @@ import './assets/main.css';const E = {
335
335
  "፣,": "፤",
336
336
  ";": "፤"
337
337
  };
338
- class G {
338
+ class z {
339
339
  /**
340
340
  * Transform input text based on a new key press
341
341
  *
@@ -367,54 +367,66 @@ class G {
367
367
  * // → { transformedValue: 'ሽ', newCursorPosition: 1, isReplacement: true }
368
368
  * \`\`\`
369
369
  */
370
- static transform(e, n, a) {
371
- const i = e.slice(-1), s = i + a;
372
- if (h[s])
370
+ static transform(e, t, i) {
371
+ const a = e.slice(-1), l = a + i;
372
+ if (b[l])
373
373
  return {
374
- transformedValue: e.slice(0, -1) + h[s] + n,
374
+ transformedValue: e.slice(0, -1) + b[l] + t,
375
375
  newCursorPosition: e.length,
376
376
  isReplacement: !0
377
377
  };
378
- if (h[a])
378
+ if (b[i])
379
379
  return {
380
- transformedValue: e + h[a] + n,
380
+ transformedValue: e + b[i] + t,
381
381
  newCursorPosition: e.length + 1,
382
382
  isReplacement: !1
383
383
  };
384
- if (y[s])
384
+ if (K[l])
385
385
  return {
386
- transformedValue: e.slice(0, -1) + y[s] + n,
386
+ transformedValue: e.slice(0, -1) + K[l] + t,
387
387
  newCursorPosition: e.length,
388
388
  isReplacement: !0
389
389
  };
390
- const t = z[i];
391
- if (t && t[a])
390
+ const s = p[a];
391
+ if (s && s[i])
392
392
  return {
393
- transformedValue: e.slice(0, -1) + t[a] + n,
393
+ transformedValue: e.slice(0, -1) + s[i] + t,
394
394
  newCursorPosition: e.length,
395
395
  isReplacement: !0
396
396
  };
397
- if (["a", "e", "i"].includes(a)) {
398
- const l = this.findSadisBase(i);
399
- if (l) {
400
- const w = z[l];
401
- if (w) {
402
- const d = a + a, o = w[d];
403
- if (o)
397
+ if (i === "e" && a) {
398
+ const o = this.findSadisBase(a);
399
+ if (o && o !== a) {
400
+ const u = p[o];
401
+ if (u && u.ee)
402
+ return {
403
+ transformedValue: e.slice(0, -1) + u.ee + t,
404
+ newCursorPosition: e.length,
405
+ isReplacement: !0
406
+ };
407
+ }
408
+ }
409
+ if (["a", "i"].includes(i)) {
410
+ const o = this.findSadisBase(a);
411
+ if (o) {
412
+ const u = p[o];
413
+ if (u) {
414
+ const c = i + i, r = u[c];
415
+ if (r)
404
416
  return {
405
- transformedValue: e.slice(0, -1) + o + n,
417
+ transformedValue: e.slice(0, -1) + r + t,
406
418
  newCursorPosition: e.length,
407
419
  isReplacement: !0
408
420
  };
409
421
  }
410
422
  }
411
423
  }
412
- return E[a] ? {
413
- transformedValue: e + E[a] + n,
424
+ return g[i] ? {
425
+ transformedValue: e + g[i] + t,
414
426
  newCursorPosition: e.length + 1,
415
427
  isReplacement: !1
416
428
  } : {
417
- transformedValue: e + a + n,
429
+ transformedValue: e + i + t,
418
430
  newCursorPosition: e.length + 1,
419
431
  isReplacement: !1
420
432
  };
@@ -437,15 +449,15 @@ class G {
437
449
  * \`\`\`
438
450
  */
439
451
  static findSadisBase(e) {
440
- for (const [n, a] of Object.entries(z))
441
- if (n === e || Object.values(a).includes(e)) return n;
452
+ for (const [t, i] of Object.entries(p))
453
+ if (t === e || Object.values(i).includes(e)) return t;
442
454
  return null;
443
455
  }
444
456
  }
445
- const D = (r = {}) => {
446
- const { enabled: e = !0, onTransform: n } = r;
447
- return { onKeyDown: T(
448
- (i) => {
457
+ const E = (w = {}) => {
458
+ const { enabled: e = !0, onTransform: t } = w;
459
+ return { onKeyDown: N(
460
+ (a) => {
449
461
  if (!e || [
450
462
  "Backspace",
451
463
  "Delete",
@@ -460,112 +472,82 @@ const D = (r = {}) => {
460
472
  "Escape",
461
473
  "PageUp",
462
474
  "PageDown"
463
- ].includes(i.key) || i.ctrlKey || i.metaKey || i.key.length !== 1 || i.altKey) return;
464
- i.preventDefault();
465
- const t = i.currentTarget, { selectionStart: l, selectionEnd: w, value: d } = t, o = d.substring(0, l || 0), b = d.substring(w || 0), c = G.transform(o, b, i.key), g = Object.getOwnPropertyDescriptor(t.constructor.prototype, "value");
466
- g && g.set ? g.set.bind(t)(c.transformedValue) : t.value = c.transformedValue;
467
- let p;
468
- typeof InputEvent < "u" ? p = new InputEvent("input", {
475
+ ].includes(a.key) || a.ctrlKey || a.metaKey || a.key.length !== 1 || a.altKey) return;
476
+ a.preventDefault();
477
+ const s = a.currentTarget, { selectionStart: o, selectionEnd: u, value: c } = s, r = c.substring(0, o || 0), m = c.substring(u || 0), d = z.transform(r, m, a.key), f = Object.getOwnPropertyDescriptor(s.constructor.prototype, "value");
478
+ f && f.set ? f.set.bind(s)(d.transformedValue) : s.value = d.transformedValue;
479
+ let n;
480
+ typeof InputEvent < "u" ? n = new InputEvent("input", {
469
481
  bubbles: !0,
470
482
  cancelable: !0,
471
483
  inputType: "insertText",
472
- data: i.key
473
- }) : p = new Event("input", { bubbles: !0, cancelable: !0 }), t.dispatchEvent(p);
474
- const u = new Event("change", {
484
+ data: a.key
485
+ }) : n = new Event("input", { bubbles: !0, cancelable: !0 }), s.dispatchEvent(n);
486
+ const h = new Event("change", {
475
487
  bubbles: !0,
476
488
  cancelable: !0
477
489
  });
478
- t.dispatchEvent(u), requestAnimationFrame(() => {
479
- if (document.activeElement === t)
490
+ s.dispatchEvent(h), requestAnimationFrame(() => {
491
+ if (document.activeElement === s)
480
492
  try {
481
- t.setSelectionRange(c.newCursorPosition, c.newCursorPosition);
493
+ s.setSelectionRange(d.newCursorPosition, d.newCursorPosition);
482
494
  } catch {
483
495
  }
484
- }), n && n(c);
496
+ }), t && t(d);
485
497
  },
486
- [e, n]
498
+ [e, t]
487
499
  ) };
488
- };
489
- function m(...r) {
490
- return r.filter(Boolean).join(" ");
491
- }
492
- const P = N(
493
- ({ defaultGeez: r = !0, wrapperClassName: e, inputClassName: n, buttonClassName: a, className: i, onChange: s, onKeyDown: t, value: l, ...w }, d) => {
494
- const [o, b] = S(r), { onKeyDown: c } = D({ enabled: o }), g = (u) => {
495
- c(u), t && t(u);
496
- }, p = (u) => {
497
- s && s(u);
498
- };
499
- return /* @__PURE__ */ v("div", { className: m("geez-input-wrapper", e), children: [
500
- /* @__PURE__ */ f(
501
- "input",
502
- {
503
- ...w,
504
- ...l !== void 0 && { value: l },
505
- ref: d,
506
- onKeyDown: g,
507
- onChange: p,
508
- className: m("geez-input-field", i, n)
509
- }
510
- ),
511
- /* @__PURE__ */ f(
512
- "button",
513
- {
514
- type: "button",
515
- onClick: () => b(!o),
516
- className: m(
517
- "geez-input-toggle",
518
- o ? "geez-input-toggle--active" : "geez-input-toggle--inactive",
519
- a
520
- ),
521
- title: o ? "Switch to English" : "Switch to Ge'ez",
522
- tabIndex: -1,
523
- children: o ? "አማ" : "EN"
524
- }
525
- )
526
- ] });
500
+ }, P = v(
501
+ ({ defaultGeez: w = !0, wrapperClassName: e, inputClassName: t, className: i, onChange: a, onKeyDown: l, value: s, ...o }, u) => {
502
+ const [c, r] = D(w), { onKeyDown: m } = E({ enabled: c });
503
+ return /* @__PURE__ */ y("div", { className: e, children: /* @__PURE__ */ y(
504
+ "input",
505
+ {
506
+ ...o,
507
+ ...s !== void 0 && { value: s },
508
+ ref: u,
509
+ onKeyDown: (n) => {
510
+ if ((n.metaKey || n.ctrlKey) && n.shiftKey && n.key === "S") {
511
+ n.preventDefault(), r((h) => !h);
512
+ return;
513
+ }
514
+ m(n), l && l(n);
515
+ },
516
+ onChange: (n) => {
517
+ a && a(n);
518
+ },
519
+ className: i || t
520
+ }
521
+ ) });
527
522
  }
528
523
  );
529
524
  P.displayName = "GeezInput";
530
- const R = N(
531
- ({ defaultGeez: r = !0, wrapperClassName: e, textareaClassName: n, buttonClassName: a, className: i, onChange: s, onKeyDown: t, value: l, ...w }, d) => {
532
- const [o, b] = S(r), { onKeyDown: c } = D({ enabled: o }), g = (u) => {
533
- c(u), t && t(u);
534
- }, p = (u) => {
535
- s && s(u);
536
- };
537
- return /* @__PURE__ */ v("div", { className: m("geez-textarea-wrapper", e), children: [
538
- /* @__PURE__ */ f(
539
- "textarea",
540
- {
541
- ...w,
542
- ...l !== void 0 && { value: l },
543
- ref: d,
544
- onKeyDown: g,
545
- onChange: p,
546
- className: m("geez-textarea-field", i, n)
547
- }
548
- ),
549
- /* @__PURE__ */ f(
550
- "button",
551
- {
552
- type: "button",
553
- onClick: () => b(!o),
554
- className: m(
555
- "geez-textarea-toggle",
556
- o ? "geez-textarea-toggle--active" : "geez-textarea-toggle--inactive",
557
- a
558
- ),
559
- title: o ? "Switch to English" : "Switch to Ge'ez",
560
- tabIndex: -1,
561
- children: o ? "አማ" : "EN"
562
- }
563
- )
564
- ] });
525
+ const T = v(
526
+ ({ defaultGeez: w = !0, wrapperClassName: e, textareaClassName: t, className: i, onChange: a, onKeyDown: l, value: s, ...o }, u) => {
527
+ const [c, r] = D(w), { onKeyDown: m } = E({ enabled: c });
528
+ return /* @__PURE__ */ y("div", { className: e, children: /* @__PURE__ */ y(
529
+ "textarea",
530
+ {
531
+ ...o,
532
+ ...s !== void 0 && { value: s },
533
+ ref: u,
534
+ onKeyDown: (n) => {
535
+ if ((n.metaKey || n.ctrlKey) && n.shiftKey && n.key === "S") {
536
+ n.preventDefault(), r((h) => !h);
537
+ return;
538
+ }
539
+ m(n), l && l(n);
540
+ },
541
+ onChange: (n) => {
542
+ a && a(n);
543
+ },
544
+ className: i || t
545
+ }
546
+ ) });
565
547
  }
566
548
  );
567
- R.displayName = "GeezTextArea";
549
+ T.displayName = "GeezTextArea";
568
550
  export {
569
551
  P as GeezInput,
570
- R as GeezTextArea
552
+ T as GeezTextArea
571
553
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geez-input",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Type-safe React library for Geez (Ethiopic) script input with phonetic keyboard support",
5
5
  "keywords": [
6
6
  "geez",
@@ -1 +0,0 @@
1
- .geez-input-wrapper{position:relative;width:100%}.geez-input-field{width:100%;background-color:var(--geez-bg-paper, #fefefe);border:2px solid var(--geez-border-gold, rgba(212, 175, 55, .2));outline:none;padding:1rem;font-family:var(--geez-font-serif, Georgia, serif);font-size:1.125rem;transition:all .2s ease}.geez-input-field:focus{border-color:var(--geez-border-crimson, #dc143c)}.geez-input-toggle{position:absolute;right:1rem;top:50%;transform:translateY(-50%);padding:.375rem .75rem;border-radius:.375rem;transition:all .2s ease;z-index:10;font-weight:600;font-size:.875rem;border:none;cursor:pointer}.geez-input-toggle--active{background-color:var(--geez-bg-crimson, #dc143c);color:var(--geez-text-white, #ffffff)}.geez-input-toggle--inactive{background-color:var(--geez-bg-gold-light, rgba(212, 175, 55, .1));color:var(--geez-text-gold, #d4af37)}.geez-textarea-wrapper{position:relative;width:100%}.geez-textarea-field{width:100%;background-color:var(--geez-bg-paper, #fefefe);border:2px solid var(--geez-border-gold, rgba(212, 175, 55, .2));outline:none;padding:1.5rem;font-family:var(--geez-font-serif, Georgia, serif);font-size:1.125rem;line-height:1.75;transition:all .2s ease;min-height:150px}.geez-textarea-field:focus{border-color:var(--geez-border-crimson, #dc143c)}.geez-textarea-toggle{position:absolute;right:1rem;top:1rem;padding:.375rem .75rem;border-radius:.375rem;transition:all .2s ease;z-index:10;font-weight:600;font-size:.875rem;border:none;cursor:pointer}.geez-textarea-toggle--active{background-color:var(--geez-bg-crimson, #dc143c);color:var(--geez-text-white, #ffffff)}.geez-textarea-toggle--inactive{background-color:var(--geez-bg-gold-light, rgba(212, 175, 55, .1));color:var(--geez-text-gold, #d4af37)}