masoneffect 2.0.3 → 2.0.4

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 (39) hide show
  1. package/README.md +2 -2
  2. package/dist/core/typing/index.d.ts +5 -4
  3. package/dist/core/typing/index.d.ts.map +1 -1
  4. package/dist/count/core/typing/index.d.ts +5 -4
  5. package/dist/count/core/typing/index.d.ts.map +1 -1
  6. package/dist/index.cjs +1 -1
  7. package/dist/index.mjs +1 -1
  8. package/dist/react/core/typing/index.d.ts +5 -4
  9. package/dist/react/count/core/typing/index.d.ts +5 -4
  10. package/dist/react/count/core/typing/index.d.ts.map +1 -1
  11. package/dist/react/textToParticle/core/typing/index.d.ts +5 -4
  12. package/dist/react/textToParticle/core/typing/index.d.ts.map +1 -1
  13. package/dist/react/typing/core/typing/index.d.ts +5 -4
  14. package/dist/react/typing/core/typing/index.d.ts.map +1 -1
  15. package/dist/react/typing/index.cjs +1 -1
  16. package/dist/react/typing/index.mjs +1 -1
  17. package/dist/svelte/count/index.d.ts +5 -4
  18. package/dist/svelte/index.cjs +1 -1
  19. package/dist/svelte/index.d.ts +5 -4
  20. package/dist/svelte/index.mjs +57 -53
  21. package/dist/svelte/textToParticle/index.d.ts +5 -4
  22. package/dist/svelte/typing/index.cjs +1 -1
  23. package/dist/svelte/typing/index.d.ts +5 -4
  24. package/dist/svelte/typing/index.mjs +57 -53
  25. package/dist/textToParticle/core/typing/index.d.ts +5 -4
  26. package/dist/textToParticle/core/typing/index.d.ts.map +1 -1
  27. package/dist/typing/core/typing/index.d.ts +5 -4
  28. package/dist/typing/core/typing/index.d.ts.map +1 -1
  29. package/dist/typing/index.cjs +1 -1
  30. package/dist/typing/index.mjs +1 -1
  31. package/dist/vue/count/index.d.ts +5 -4
  32. package/dist/vue/index.cjs +1 -1
  33. package/dist/vue/index.d.ts +5 -4
  34. package/dist/vue/index.mjs +57 -53
  35. package/dist/vue/textToParticle/index.d.ts +5 -4
  36. package/dist/vue/typing/index.cjs +1 -1
  37. package/dist/vue/typing/index.d.ts +5 -4
  38. package/dist/vue/typing/index.mjs +57 -53
  39. package/package.json +1 -1
@@ -19,25 +19,48 @@ function decomposeHangul(char) {
19
19
  }
20
20
  return result;
21
21
  }
22
+ function composeHangul(initial, medial, final) {
23
+ const initialChars = ["ㄱ", "ㄲ", "ㄴ", "ㄷ", "ㄸ", "ㄹ", "ㅁ", "ㅂ", "ㅃ", "ㅅ", "ㅆ", "ㅇ", "ㅈ", "ㅉ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ"];
24
+ const medialChars = ["ㅏ", "ㅐ", "ㅑ", "ㅒ", "ㅓ", "ㅔ", "ㅕ", "ㅖ", "ㅗ", "ㅘ", "ㅙ", "ㅚ", "ㅛ", "ㅜ", "ㅝ", "ㅞ", "ㅟ", "ㅠ", "ㅡ", "ㅢ", "ㅣ"];
25
+ const finalChars = ["", "ㄱ", "ㄲ", "ㄳ", "ㄴ", "ㄵ", "ㄶ", "ㄷ", "ㄹ", "ㄺ", "ㄻ", "ㄼ", "ㄽ", "ㄾ", "ㄿ", "ㅀ", "ㅁ", "ㅂ", "ㅄ", "ㅅ", "ㅆ", "ㅇ", "ㅈ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ"];
26
+ const initialIndex = initialChars.indexOf(initial);
27
+ const medialIndex = medialChars.indexOf(medial);
28
+ const finalIndex = final ? finalChars.indexOf(final) : 0;
29
+ if (initialIndex === -1 || medialIndex === -1) {
30
+ return initial + (medial || "") + (final || "");
31
+ }
32
+ const code = 44032 + initialIndex * 21 * 28 + medialIndex * 28 + finalIndex;
33
+ return String.fromCharCode(code);
34
+ }
22
35
  function decomposeText(text) {
23
36
  const units = [];
37
+ const charUnitRanges = [];
24
38
  for (let i = 0; i < text.length; i++) {
25
39
  const char = text[i];
26
40
  const code = char.charCodeAt(0);
41
+ const startIndex = units.length;
27
42
  if (code >= 44032 && code <= 55203) {
28
43
  const decomposed = decomposeHangul(char);
29
44
  units.push(...decomposed);
45
+ charUnitRanges.push({
46
+ start: startIndex,
47
+ end: units.length,
48
+ isHangul: true
49
+ });
30
50
  } else {
31
51
  units.push(char);
52
+ charUnitRanges.push({
53
+ start: startIndex,
54
+ end: units.length,
55
+ isHangul: false
56
+ });
32
57
  }
33
58
  }
34
- return units;
59
+ return { units, charUnitRanges };
35
60
  }
36
61
  class Typing {
37
62
  // 원본 텍스트
38
63
  constructor(container, options) {
39
- this.originalChars = [];
40
- this.charUnitMap = [];
41
64
  this.container = typeof container === "string" ? document.querySelector(container) : container;
42
65
  if (!this.container) {
43
66
  throw new Error("Container element not found");
@@ -56,10 +79,9 @@ class Typing {
56
79
  onUpdate: options.onUpdate || null,
57
80
  onComplete: options.onComplete || null
58
81
  };
59
- this.textUnits = decomposeText(this.config.text);
60
- this.originalChars = [];
61
- this.charUnitMap = [];
62
- this.initializeTextStructure();
82
+ const decomposed = decomposeText(this.config.text);
83
+ this.textUnits = decomposed.units;
84
+ this.charUnitRanges = decomposed.charUnitRanges;
63
85
  this.currentIndex = 0;
64
86
  this.displayedText = "";
65
87
  this.timeoutId = null;
@@ -102,54 +124,36 @@ class Typing {
102
124
  );
103
125
  this.intersectionObserver.observe(this.container);
104
126
  }
105
- // 글자에 해당하는 단위 개수
106
- initializeTextStructure() {
107
- this.originalChars = [];
108
- this.charUnitMap = [];
109
- for (let i = 0; i < this.originalText.length; i++) {
110
- const char = this.originalText[i];
111
- const code = char.charCodeAt(0);
112
- this.originalChars.push(char);
113
- if (code >= 44032 && code <= 55203) {
114
- const decomposed = decomposeHangul(char);
115
- this.charUnitMap.push(decomposed.length);
116
- } else {
117
- this.charUnitMap.push(1);
127
+ // 단위들을 다시 합쳐서 실제 표시할 텍스트 생성
128
+ // 한글의 경우 자음/모음이 하나씩 보이도록 합성
129
+ buildTextFromUnits(unitCount) {
130
+ if (unitCount === 0) return "";
131
+ let result = "";
132
+ for (let charIndex = 0; charIndex < this.charUnitRanges.length; charIndex++) {
133
+ const range = this.charUnitRanges[charIndex];
134
+ if (range.start >= unitCount) {
135
+ break;
118
136
  }
119
- }
120
- }
121
- // 단위 인덱스를 원본 텍스트의 글자 인덱스로 변환
122
- // unitIndex: 현재까지 입력된 단위 개수 (0부터 시작)
123
- // 반환: 표시할 글자 개수 (0부터 시작, exclusive)
124
- getCharIndexFromUnitIndex(unitIndex) {
125
- if (unitIndex === 0) return 0;
126
- let charIndex = 0;
127
- let currentUnits = 0;
128
- for (let i = 0; i < this.charUnitMap.length; i++) {
129
- const unitsForChar = this.charUnitMap[i];
130
- currentUnits += unitsForChar;
131
- if (unitIndex >= currentUnits) {
132
- charIndex = i + 1;
137
+ const unitsEntered = Math.min(unitCount - range.start, range.end - range.start);
138
+ if (unitsEntered <= 0) {
139
+ break;
140
+ }
141
+ if (range.isHangul) {
142
+ const charUnits = this.textUnits.slice(range.start, range.start + unitsEntered);
143
+ if (charUnits.length === 1) {
144
+ result += charUnits[0];
145
+ } else if (charUnits.length === 2) {
146
+ result += composeHangul(charUnits[0], charUnits[1]);
147
+ } else if (charUnits.length >= 3) {
148
+ result += composeHangul(charUnits[0], charUnits[1], charUnits[2]);
149
+ }
133
150
  } else {
134
- const unitsEntered = unitIndex - (currentUnits - unitsForChar);
135
151
  if (unitsEntered > 0) {
136
- const isHangul = this.originalChars[i] && this.originalChars[i].charCodeAt(0) >= 44032 && this.originalChars[i].charCodeAt(0) <= 55203;
137
- if (isHangul && unitsEntered >= 2) {
138
- charIndex = i + 1;
139
- } else if (!isHangul && unitsEntered >= 1) {
140
- charIndex = i + 1;
141
- }
152
+ result += this.textUnits[range.start];
142
153
  }
143
- break;
144
154
  }
145
155
  }
146
- return charIndex;
147
- }
148
- // 단위들을 다시 합쳐서 실제 표시할 텍스트 생성
149
- buildTextFromUnits(units) {
150
- if (units.length === 0) return "";
151
- const charIndex = this.getCharIndexFromUnitIndex(units.length);
152
- return this.originalText.substring(0, charIndex);
156
+ return result;
153
157
  }
154
158
  start() {
155
159
  if (this.isRunning) return;
@@ -169,8 +173,7 @@ class Typing {
169
173
  }
170
174
  return;
171
175
  }
172
- const unitsToShow = this.textUnits.slice(0, this.currentIndex + 1);
173
- this.displayedText = this.buildTextFromUnits(unitsToShow);
176
+ this.displayedText = this.buildTextFromUnits(this.currentIndex + 1);
174
177
  let displayText = this.displayedText;
175
178
  if (this.config.showCursor) {
176
179
  displayText += this.config.cursorChar;
@@ -205,8 +208,9 @@ class Typing {
205
208
  setText(newText) {
206
209
  this.originalText = newText;
207
210
  this.config.text = newText;
208
- this.textUnits = decomposeText(newText);
209
- this.initializeTextStructure();
211
+ const decomposed = decomposeText(newText);
212
+ this.textUnits = decomposed.units;
213
+ this.charUnitRanges = decomposed.charUnitRanges;
210
214
  this.reset();
211
215
  if (this.config.enabled) {
212
216
  setTimeout(() => this.start(), this.config.delay);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "masoneffect",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "description": "A collection of animation effects library. Supports React, Vue, Svelte, and vanilla JavaScript with Tree-shaking support.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",