@dvirus-js/utils 0.0.1 → 0.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/CHANGELOG.md CHANGED
@@ -1,3 +1,47 @@
1
+ ## 0.0.5 (2026-05-20)
2
+
3
+ This was a version bump only for utils to align it with other projects, there were no code changes.
4
+
5
+ ## 0.0.4 (2026-05-19)
6
+
7
+ ### 🩹 Fixes
8
+
9
+ - minor formatting updates ([3dbc3e6](https://github.com/Dvirus97/dvirus-js/commit/3dbc3e6))
10
+
11
+ ### ❤️ Thank You
12
+
13
+ - Dvir Cohen
14
+
15
+ ## 0.0.3 (2026-05-19)
16
+
17
+ ### 🩹 Fixes
18
+
19
+ - ensure consistent trailing newlines in package exports ([866782e](https://github.com/Dvirus97/dvirus-js/commit/866782e))
20
+
21
+ ### ❤️ Thank You
22
+
23
+ - Dvir Cohen
24
+
25
+ ## 0.0.2 (2026-05-19)
26
+
27
+ ### 🩹 Fixes
28
+
29
+ - check all package ([3e145c9](https://github.com/Dvirus97/dvirus-js/commit/3e145c9))
30
+
31
+ ### ❤️ Thank You
32
+
33
+ - Dvir Cohen
34
+
35
+ ## 1.1.8 (2026-05-14)
36
+
37
+ ### 🩹 Fixes
38
+
39
+ - swap parseRichText to return BlockGroup by default ([ef7c103](https://github.com/Dvirus97/dvirus-js/commit/ef7c103))
40
+
41
+ ### ❤️ Thank You
42
+
43
+ - Dvir Cohen
44
+
1
45
  ## 1.1.7 (2026-05-06)
2
46
 
3
47
  ### 🩹 Fixes
package/index.js CHANGED
@@ -1,8 +1,8 @@
1
- function D(t) {
1
+ function G(t) {
2
2
  return t.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").toLowerCase().replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
3
3
  }
4
4
  function W(t, r) {
5
- const e = D(t);
5
+ const e = G(t);
6
6
  switch (r) {
7
7
  case "lowercase":
8
8
  return e.toLowerCase();
@@ -56,7 +56,7 @@ function E(t) {
56
56
  return [null, r];
57
57
  }
58
58
  }
59
- const F = {
59
+ const ee = {
60
60
  /**
61
61
  * Makes a GET request to the specified URL.
62
62
  *
@@ -67,7 +67,7 @@ const F = {
67
67
  */
68
68
  get: async function(t, r) {
69
69
  const e = await fetch(t, r);
70
- return await S(e);
70
+ return await C(e);
71
71
  },
72
72
  /**
73
73
  * Makes a POST request to the specified URL with the given data.
@@ -89,7 +89,7 @@ const F = {
89
89
  body: JSON.stringify(r),
90
90
  ...e
91
91
  });
92
- return await S(n);
92
+ return await C(n);
93
93
  },
94
94
  /**
95
95
  * Makes a DELETE request to the specified URL with the given ID.
@@ -111,7 +111,7 @@ const F = {
111
111
  body: JSON.stringify({ id: r }),
112
112
  ...e
113
113
  });
114
- return await S(n);
114
+ return await C(n);
115
115
  },
116
116
  /**
117
117
  * Makes a PATCH request to the specified URL with the given data.
@@ -133,7 +133,7 @@ const F = {
133
133
  body: JSON.stringify(r),
134
134
  ...e
135
135
  });
136
- return await S(n);
136
+ return await C(n);
137
137
  },
138
138
  /**
139
139
  * Makes a PUT request to the specified URL with the given data.
@@ -155,33 +155,39 @@ const F = {
155
155
  body: JSON.stringify(r),
156
156
  ...e
157
157
  });
158
- return await S(n);
158
+ return await C(n);
159
159
  }
160
160
  };
161
- async function S(t) {
161
+ async function C(t) {
162
162
  if (!t.ok) throw new Error(`Error: ${t.statusText}`);
163
163
  return await t.json();
164
164
  }
165
- function ee(t, r) {
165
+ function te(t, r) {
166
166
  const e = {};
167
167
  return t?.forEach((n, o) => {
168
168
  const s = r(n, o, t)?.toString();
169
169
  s && (e[s] ??= [], e[s].push(n));
170
170
  }), e;
171
171
  }
172
- async function te(t) {
172
+ async function re(t) {
173
173
  return await new Promise((r) => setTimeout(r, t));
174
174
  }
175
- function re(t, r, e) {
175
+ function ne(t, r, e) {
176
176
  return r < t ? t : r > e ? e : r;
177
177
  }
178
- function ne(t, r) {
179
- let e;
180
- return (...n) => {
181
- clearTimeout(e), e = setTimeout(() => t(...n), r);
182
- };
178
+ function se(t, r, e) {
179
+ let n;
180
+ return e?.isLoadingFn?.(!1), Object.assign((...s) => {
181
+ clearTimeout(n), e?.isLoadingFn?.(!0), n = setTimeout(() => {
182
+ e?.isLoadingFn?.(!1), t(...s);
183
+ }, r);
184
+ }, {
185
+ cancel() {
186
+ clearTimeout(n), e?.isLoadingFn?.(!1);
187
+ }
188
+ });
183
189
  }
184
- function se(t, r) {
190
+ function oe(t, r) {
185
191
  if (!r || typeof r != "string" || typeof t != "object" || t === null)
186
192
  return;
187
193
  const e = r.split(".");
@@ -194,7 +200,7 @@ function se(t, r) {
194
200
  }
195
201
  return n(e, t);
196
202
  }
197
- class g {
203
+ class m {
198
204
  #e = null;
199
205
  #t = null;
200
206
  /**
@@ -203,7 +209,7 @@ class g {
203
209
  * @returns {Result<T, never>} A Result instance representing a success.
204
210
  */
205
211
  static ok(r) {
206
- return new g(r, null);
212
+ return new m(r, null);
207
213
  }
208
214
  /**
209
215
  * Creates a failed result.
@@ -211,7 +217,7 @@ class g {
211
217
  * @returns {Result<never, E>} A Result instance representing a failure.
212
218
  */
213
219
  static err(r) {
214
- return typeof r == "string" ? new g(null, new Error(r)) : new g(null, r);
220
+ return typeof r == "string" ? new m(null, new Error(r)) : new m(null, r);
215
221
  }
216
222
  /**
217
223
  * Wraps a promise in a Result.
@@ -219,7 +225,7 @@ class g {
219
225
  * @returns {Promise<Result<T, E>>} A promise that resolves to a Result.
220
226
  */
221
227
  static async promise(r) {
222
- return r.then((e) => g.ok(e ?? "void")).catch((e) => g.err(e));
228
+ return r.then((e) => m.ok(e ?? "__void__")).catch((e) => m.err(e));
223
229
  }
224
230
  /**
225
231
  * Wraps a function call in a Result.
@@ -230,9 +236,9 @@ class g {
230
236
  static func(r, ...e) {
231
237
  try {
232
238
  const n = r(...e);
233
- return g.ok(n);
239
+ return m.ok(n);
234
240
  } catch (n) {
235
- return g.err(n);
241
+ return m.err(n);
236
242
  }
237
243
  }
238
244
  /**
@@ -242,9 +248,13 @@ class g {
242
248
  */
243
249
  constructor(r, e) {
244
250
  if (!r && !e)
245
- throw new Error("Result must be initialized with either an ok or an err value");
251
+ throw new Error(
252
+ "Result must be initialized with either an ok or an err value"
253
+ );
246
254
  if (r && e)
247
- throw new Error("Result can't be initialized with both an ok and an err value");
255
+ throw new Error(
256
+ "Result can't be initialized with both an ok and an err value"
257
+ );
248
258
  r != null ? this.#e = r : this.#t = e;
249
259
  }
250
260
  /**
@@ -311,21 +321,21 @@ class g {
311
321
  return this.#t;
312
322
  }
313
323
  }
314
- function oe(t, r = []) {
324
+ function ae(t, r = []) {
315
325
  return t == null ? r : Array.isArray(t) ? t : [t];
316
326
  }
317
- const z = /* @__PURE__ */ Symbol("SIGNAL"), ae = (t) => typeof t == "function" && z in t, h = [], ie = (t) => {
318
- const r = h.splice(0, h.length);
327
+ const z = /* @__PURE__ */ Symbol("SIGNAL"), ie = (t) => typeof t == "function" && z in t, p = [], ce = (t) => {
328
+ const r = p.splice(0, p.length);
319
329
  try {
320
330
  return t();
321
331
  } finally {
322
- h.push(...r);
332
+ p.push(...r);
323
333
  }
324
334
  }, A = (t, r) => {
325
335
  const e = /* @__PURE__ */ new Set();
326
336
  let n = 0;
327
337
  const o = () => {
328
- const l = h[h.length - 1];
338
+ const l = p[p.length - 1];
329
339
  l && (e.add(l.setDirty), l.addSource(() => {
330
340
  e.delete(l.setDirty);
331
341
  }));
@@ -338,7 +348,7 @@ const z = /* @__PURE__ */ Symbol("SIGNAL"), ae = (t) => typeof t == "function" &
338
348
  e.delete(l), n--;
339
349
  })
340
350
  }), notify: s, hasSubscribers: a };
341
- }, C = (t) => {
351
+ }, S = (t) => {
342
352
  let r = t;
343
353
  const { read: e, notify: n } = A(() => r);
344
354
  return Object.assign(e, {
@@ -360,12 +370,12 @@ const z = /* @__PURE__ */ Symbol("SIGNAL"), ae = (t) => typeof t == "function" &
360
370
  const a = (i) => {
361
371
  n = i;
362
372
  };
363
- h.push({
373
+ p.push({
364
374
  setDirty: () => {
365
375
  !e && !o && (o = !0, queueMicrotask(s));
366
376
  },
367
377
  addSource: (i) => r.add(i)
368
- }), t(a), h.pop();
378
+ }), t(a), p.pop();
369
379
  };
370
380
  return s(), {
371
381
  destroy() {
@@ -377,7 +387,7 @@ const z = /* @__PURE__ */ Symbol("SIGNAL"), ae = (t) => typeof t == "function" &
377
387
  let e, n = !0, o = () => {
378
388
  };
379
389
  const s = () => {
380
- r.forEach((c) => c()), r.clear(), h.push({
390
+ r.forEach((c) => c()), r.clear(), p.push({
381
391
  setDirty: () => {
382
392
  if (n) return;
383
393
  n = !0;
@@ -385,7 +395,7 @@ const z = /* @__PURE__ */ Symbol("SIGNAL"), ae = (t) => typeof t == "function" &
385
395
  s(), e !== c && o(e);
386
396
  },
387
397
  addSource: (c) => r.add(c)
388
- }), e = t(), n = !1, h.pop();
398
+ }), e = t(), n = !1, p.pop();
389
399
  }, { read: a, notify: i } = A(
390
400
  () => (n && s(), e),
391
401
  () => {
@@ -394,12 +404,12 @@ const z = /* @__PURE__ */ Symbol("SIGNAL"), ae = (t) => typeof t == "function" &
394
404
  );
395
405
  return o = i, a;
396
406
  };
397
- function ce(t) {
407
+ function le(t) {
398
408
  const r = typeof t == "function", e = r ? void 0 : t.source, n = r ? t : t.computation, o = /* @__PURE__ */ new Set();
399
409
  let s, a = !0, i = !1, c, l = () => {
400
410
  };
401
411
  const y = () => {
402
- if (o.forEach((u) => u()), o.clear(), h.push({
412
+ if (o.forEach((u) => u()), o.clear(), p.push({
403
413
  setDirty: () => {
404
414
  if (a) return;
405
415
  a = !0, i = !1;
@@ -413,7 +423,7 @@ function ce(t) {
413
423
  const u = e?.();
414
424
  s = n(u, c), c = { source: u, value: s };
415
425
  }
416
- a = !1, h.pop();
426
+ a = !1, p.pop();
417
427
  }, { read: v, notify: d } = A(
418
428
  () => (a && !i && y(), s),
419
429
  () => {
@@ -432,17 +442,17 @@ function ce(t) {
432
442
  });
433
443
  return b;
434
444
  }
435
- class G extends Error {
445
+ class F extends Error {
436
446
  constructor(r) {
437
447
  const e = r instanceof Error ? `:
438
448
  ${r.message}` : "";
439
449
  super(`Cannot read resource value while in error state${e}`, { cause: r }), this.name = "ResourceErrorState";
440
450
  }
441
451
  }
442
- function le(t) {
443
- const r = C(void 0), e = C("idle"), n = C(void 0), o = L(() => e() === "loading"), s = C(0), a = L(() => {
452
+ function ue(t) {
453
+ const r = S(void 0), e = S("idle"), n = S(void 0), o = L(() => e() === "loading"), s = S(0), a = L(() => {
444
454
  if (e() === "error")
445
- throw new G(n());
455
+ throw new F(n());
446
456
  return r();
447
457
  }), i = (d) => {
448
458
  r.set(d), n.set(void 0), e.set("resolved");
@@ -450,23 +460,23 @@ function le(t) {
450
460
  r.update(d), n.set(void 0), e.set("resolved");
451
461
  }, l = "params" in t;
452
462
  if ("stream" in t) {
453
- const d = C(void 0), b = k((p) => {
463
+ const d = S(void 0), b = k((g) => {
454
464
  s();
455
465
  const f = new AbortController();
456
- p(() => f.abort());
457
- const I = l ? t.params() : void 0;
466
+ g(() => f.abort());
467
+ const D = l ? t.params() : void 0;
458
468
  e.set("loading"), n.set(void 0);
459
- const N = t.stream, _ = N(l ? {
460
- params: I,
469
+ const $ = t.stream, I = $(l ? {
470
+ params: D,
461
471
  abortSignal: f.signal
462
472
  } : {
463
473
  abortSignal: f.signal
464
474
  });
465
- d.set(_);
475
+ d.set(I);
466
476
  }), u = k(() => {
467
- const p = d();
468
- if (!p) return;
469
- const f = p();
477
+ const g = d();
478
+ if (!g) return;
479
+ const f = g();
470
480
  f && ("error" in f && f.error !== void 0 ? (n.set(f.error), e.set("error")) : "value" in f && (r.set(f.value), e.set("resolved")));
471
481
  });
472
482
  return {
@@ -477,7 +487,7 @@ function le(t) {
477
487
  set: i,
478
488
  update: c,
479
489
  reload: () => {
480
- s.update((p) => p + 1);
490
+ s.update((g) => g + 1);
481
491
  },
482
492
  destroy: () => {
483
493
  b.destroy(), u.destroy();
@@ -490,8 +500,8 @@ function le(t) {
490
500
  e.set("loading"), n.set(void 0);
491
501
  const u = new AbortController();
492
502
  d(() => u.abort());
493
- const p = l ? { params: b, abortSignal: u.signal } : { abortSignal: u.signal };
494
- t.loader(p).then(
503
+ const g = l ? { params: b, abortSignal: u.signal } : { abortSignal: u.signal };
504
+ t.loader(g).then(
495
505
  (f) => {
496
506
  u.signal.aborted || (r.set(f), e.set("resolved"));
497
507
  },
@@ -513,7 +523,7 @@ function le(t) {
513
523
  destroy: () => v.destroy()
514
524
  };
515
525
  }
516
- const $ = /* @__PURE__ */ new Map([
526
+ const x = /* @__PURE__ */ new Map([
517
527
  ["b", "b"],
518
528
  ["i", "i"],
519
529
  ["u", "u"],
@@ -531,6 +541,7 @@ const $ = /* @__PURE__ */ new Map([
531
541
  ["h5", "h5"],
532
542
  ["h6", "h6"],
533
543
  ["code", "code"],
544
+ ["span", "span"],
534
545
  ["p", "p"],
535
546
  ["div", "div"],
536
547
  ["ul", "ul"],
@@ -550,7 +561,7 @@ const $ = /* @__PURE__ */ new Map([
550
561
  "h6"
551
562
  ]);
552
563
  let O = "rtp-";
553
- function x() {
564
+ function N() {
554
565
  return O;
555
566
  }
556
567
  function V(t) {
@@ -660,9 +671,9 @@ const j = /* @__PURE__ */ new Map([
660
671
  s.flatMap((i) => Array.from(w.get(i) ?? []))
661
672
  ),
662
673
  containerTagNames: a,
663
- cssClass: s.map((i) => `${x()}${i}`).join(" ")
674
+ cssClass: s.map((i) => `${N()}${i}`).join(" ")
664
675
  };
665
- }, J = () => [...$.keys()].join("|"), H = () => [...j.keys()].join("|"), Z = () => new RegExp(
676
+ }, J = () => [...x.keys()].join("|"), H = () => [...j.keys()].join("|"), Z = () => new RegExp(
666
677
  `<\\/?(${J()})>|<(${H()})\\s*/?>`,
667
678
  "gi"
668
679
  );
@@ -670,13 +681,13 @@ function P(t, r) {
670
681
  const e = w.get(t) ?? /* @__PURE__ */ new Map();
671
682
  Object.entries(r).forEach(([n, o]) => e.set(n, o)), w.set(t, e);
672
683
  }
673
- function B() {
684
+ function R() {
674
685
  const t = [];
675
686
  for (const [r, e] of w) {
676
687
  if (e.size === 0) continue;
677
688
  const n = [...e.entries()].map(([o, s]) => ` ${o}: ${s};`).join(`
678
689
  `);
679
- t.push(`.${x()}${r} {
690
+ t.push(`.${N()}${r} {
680
691
  ${n}
681
692
  }`);
682
693
  }
@@ -685,7 +696,7 @@ ${n}
685
696
  }
686
697
  function q() {
687
698
  if ("document" in globalThis) {
688
- const t = B(), r = globalThis, e = r.document.getElementById(
699
+ const t = R(), r = globalThis, e = r.document.getElementById(
689
700
  "html-text-parser-styles"
690
701
  );
691
702
  if (e) {
@@ -707,7 +718,7 @@ function X(t) {
707
718
  const o = n.containerTagNames.join(","), s = e?.containerTagNames.join(",");
708
719
  o !== s && (e = {
709
720
  containerTagNames: n.containerTagNames,
710
- cssClass: n.containerTagNames.map((a) => `${x()}${a}`).join(" "),
721
+ cssClass: n.containerTagNames.map((a) => `${N()}${a}`).join(" "),
711
722
  style: n.containerTagNames.map(
712
723
  (a) => [...w.get(a)?.entries() ?? []].map(([i, c]) => `${i}: ${c}`).join("; ")
713
724
  ).filter(Boolean).join("; "),
@@ -721,7 +732,37 @@ function X(t) {
721
732
  }
722
733
  return r;
723
734
  }
724
- function m(t) {
735
+ function K(t, r, e) {
736
+ if (!("document" in globalThis)) {
737
+ console.warn(
738
+ "[html-text-parser] Cannot append segments: document is not available."
739
+ );
740
+ return;
741
+ }
742
+ if (!t || !("appendChild" in t)) {
743
+ console.warn(
744
+ "[html-text-parser] Cannot append segments: provided element does not support appendChild."
745
+ );
746
+ return;
747
+ }
748
+ e = { useClasses: !0, useStyles: !1, ...e };
749
+ const n = t, o = globalThis.document;
750
+ for (const s of r) {
751
+ const a = o.createElement(
752
+ s.containerTagNames[0] || "span"
753
+ );
754
+ e.useClasses && (a.className = s.cssClass), e.useStyles && a.setAttribute("style", s.style);
755
+ for (const i of s.segments) {
756
+ const c = o.createElement("span");
757
+ c.textContent = i.text, e.useClasses && (c.className = i.cssClass), e.useStyles && c.setAttribute("style", i.style), a.appendChild(c);
758
+ }
759
+ n.appendChild(a);
760
+ }
761
+ }
762
+ function h(t) {
763
+ return X(_(t));
764
+ }
765
+ function _(t) {
725
766
  const r = [], e = /* @__PURE__ */ new Map();
726
767
  let n = 0;
727
768
  for (const o of t.matchAll(Z())) {
@@ -742,7 +783,7 @@ function m(t) {
742
783
  ), n = s + o[0].length;
743
784
  continue;
744
785
  }
745
- const i = o[0][1] === "/", c = $.get(o[1]?.toLowerCase() ?? "") ?? "";
786
+ const i = o[0][1] === "/", c = x.get(o[1]?.toLowerCase() ?? "") ?? "";
746
787
  if (i) {
747
788
  const l = (e.get(c) ?? 1) - 1;
748
789
  l <= 0 ? e.delete(c) : e.set(c, l);
@@ -759,15 +800,15 @@ function m(t) {
759
800
  )
760
801
  ), r;
761
802
  }
762
- function R(t) {
803
+ function B(t) {
763
804
  if (Array.isArray(t)) {
764
805
  t.forEach((e) => {
765
- R(e);
806
+ B(e);
766
807
  });
767
808
  return;
768
809
  }
769
810
  const r = t.tagName ?? t.tag;
770
- $.set(t.tag, r), t.style != null && Object.keys(t.style).length && P(r, t.style);
811
+ x.set(t.tag, r), t.style != null && Object.keys(t.style).length && P(r, t.style);
771
812
  }
772
813
  function U(t) {
773
814
  if (Array.isArray(t)) {
@@ -779,15 +820,16 @@ function U(t) {
779
820
  const r = t.tagName ?? t.tag;
780
821
  j.set(t.tag, r), t.style != null && Object.keys(t.style).length && P(r, t.style);
781
822
  }
782
- m.setTag = R;
783
- m.setSelfClosingTag = U;
784
- m.setBlockTag = (t) => T.add(t);
785
- m.removeBlockTag = (t) => T.delete(t);
786
- m.setCssClassPrefix = V;
787
- "document" in globalThis && (m.generateStylesheet = q);
788
- m.getStylesheet = B;
789
- m.groupByBlocks = X;
790
- function K(t, r, e) {
823
+ h.setTag = B;
824
+ h.setSelfClosingTag = U;
825
+ h.setBlockTag = (t) => T.add(t);
826
+ h.removeBlockTag = (t) => T.delete(t);
827
+ h.setCssClassPrefix = V;
828
+ h.getStylesheet = R;
829
+ h.flat = _;
830
+ h.generateStylesheet = q;
831
+ h.appendToDom = K;
832
+ function Q(t, r, e) {
791
833
  function n(o) {
792
834
  const [s, a] = E(() => e ? e(o) : o);
793
835
  if (a) throw new Error(`Error transforming value for ${t}: ${a.message}`);
@@ -803,35 +845,40 @@ function K(t, r, e) {
803
845
  return r(s);
804
846
  }, n;
805
847
  }
806
- const Q = /^\d+$/, ue = K(
848
+ const fe = Q(
807
849
  "NumericString",
808
- (t) => Q.test(String(t)),
850
+ (t) => (
851
+ // checks that a given value is:
852
+ // - a number, and the number is neither positive Infinity, negative Infinity, nor NaN.
853
+ typeof t == "string" && t.trim() !== "" && Number.isFinite(Number(t))
854
+ ),
809
855
  (t) => String(t)
810
856
  );
811
857
  export {
812
- ue as NumericString,
813
- g as Result,
858
+ fe as NumericString,
859
+ m as Result,
814
860
  z as SIGNAL,
815
- re as clamp,
861
+ ne as clamp,
816
862
  L as computed,
817
863
  W as convertCase,
818
- K as createBrand,
819
- ne as debounce,
820
- te as delay,
864
+ Q as createBrand,
865
+ se as debounce,
866
+ re as delay,
821
867
  k as effect,
822
- se as getProp,
823
- ee as groupBy,
824
- F as http,
825
- ae as isSignal,
826
- ce as linkedSignal,
827
- D as normalizeString,
828
- m as parseRichText,
829
- le as resource,
830
- R as setRichTextTag,
868
+ oe as getProp,
869
+ te as groupBy,
870
+ ee as http,
871
+ ie as isSignal,
872
+ le as linkedSignal,
873
+ G as normalizeString,
874
+ h as parseRichText,
875
+ _ as parseRichTextFlat,
876
+ ue as resource,
877
+ B as setRichTextTag,
831
878
  U as setSelfClosingTag,
832
- C as signal,
833
- oe as toArray,
879
+ S as signal,
880
+ ae as toArray,
834
881
  E as tryCatch,
835
882
  Y as tryCatchAsync,
836
- ie as untracked
883
+ ce as untracked
837
884
  };
@@ -1,14 +1,19 @@
1
1
  import { Brand } from './brand-factory';
2
2
  /**
3
- * A branded string type that only contains digit characters (`0-9`).
3
+ * A branded string type whose value can be safely converted to a finite number.
4
4
  *
5
5
  * At runtime this is just a plain `string` — no wrapper objects.
6
6
  * The brand prevents accidental assignment of arbitrary strings at compile time.
7
7
  *
8
+ * Accepts: integers, decimals, negatives, leading zeros (e.g. `"007"`).
9
+ * Rejects: empty strings, whitespace-only, `"Infinity"`, `"NaN"`, mixed strings like `"3px"`.
10
+ *
8
11
  * @example
9
12
  * ```ts
10
- * const id: NumericString = NumericString('123'); // ok
11
- * const id: NumericString = '123'; // compile error
13
+ * const n: NumericString = NumericString('3.14'); // ok
14
+ * const n: NumericString = NumericString(-7); // ok
15
+ * const n: NumericString = NumericString('abc'); // throws
16
+ * const n: NumericString = '3.14'; // compile error
12
17
  * ```
13
18
  */
14
19
  export type NumericString = Brand<string, 'NumericString'>;
package/lib/delay.d.ts CHANGED
@@ -12,10 +12,16 @@ export declare function delay(ms: number): Promise<unknown>;
12
12
  * @returns Clamped value
13
13
  */
14
14
  export declare function clamp(min: number, value: number, max: number): number;
15
+ export interface Debounce<TFn extends (...args: any[]) => void> {
16
+ (...args: Parameters<TFn>): void;
17
+ cancel: () => void;
18
+ }
15
19
  /**
16
20
  * Debounce a function
17
21
  * @param func - Function to debounce
18
22
  * @param delay - Delay in milliseconds
19
23
  * @returns Debounced function
20
24
  */
21
- export declare function debounce<T extends (...args: any[]) => void>(func: T, delay: number): (...args: Parameters<T>) => void;
25
+ export declare function debounce<TFn extends (...args: any[]) => void = (...args: any[]) => void>(func: TFn, delay: number, config?: {
26
+ isLoadingFn?: (isLoading: boolean) => void;
27
+ }): Debounce<TFn>;
@@ -1,7 +1,10 @@
1
- import { TextSegment } from './types';
1
+ import { TextSegment, BlockGroup } from './types';
2
2
  /**
3
- * Parses a string containing supported inline tags into typed segments.
3
+ * Parses a string containing supported inline tags into block groups.
4
4
  * Supports nested tags. All other content is treated as plain text.
5
+ * Returns segments grouped by their block/container context.
6
+ *
7
+ * For a flat array of segments without block grouping, use `parseRichText.flat()`.
5
8
  *
6
9
  * Supported tags (add more in `RICH_TEXT_TAGS`):
7
10
  * `<b>` / `<strong>`, `<i>` / `<em>`, `<u>`, `<s>`, `<mark>`, `<small>`,
@@ -13,22 +16,38 @@ import { TextSegment } from './types';
13
16
  * @example
14
17
  * parseRichText('Hello <b>world</b>!')
15
18
  * // [
16
- * // { text: 'Hello ', styles: [], cssClass: '' },
17
- * // { text: 'world', styles: ['bold'] },
18
- * // { text: '!', styles: [] },
19
+ * // { containerTagNames: [], cssClass: '', style: '', styleObject: {}, segments: [
20
+ * // { text: 'Hello ', ... },
21
+ * // { text: 'world', ... },
22
+ * // { text: '!', ... },
23
+ * // ]},
19
24
  * // ]
20
25
  */
21
- export declare function parseRichText(input: string): TextSegment[];
26
+ export declare function parseRichText(input: string): BlockGroup[];
22
27
  export declare namespace parseRichText {
23
28
  var setTag: typeof setRichTextTag;
24
29
  var setSelfClosingTag: typeof import("./html-text-parser").setSelfClosingTag;
25
30
  var setBlockTag: (tag: string) => Set<string>;
26
31
  var removeBlockTag: (tag: string) => boolean;
27
32
  var setCssClassPrefix: typeof import("./constant").setCssClassPrefix;
28
- var generateStylesheet: typeof import("./methods").generateStylesheet;
29
33
  var getStylesheet: typeof import("./methods").getStylesheet;
30
- var groupByBlocks: typeof import("./methods").groupByBlocks;
34
+ var flat: typeof parseRichTextFlat;
35
+ var generateStylesheet: typeof import("./methods").generateStylesheet;
36
+ var appendToDom: typeof import("./methods").appendToDom;
31
37
  }
38
+ /**
39
+ * Parses a string containing supported inline tags into a flat array of typed segments.
40
+ * Supports nested tags. All other content is treated as plain text.
41
+ *
42
+ * @example
43
+ * parseRichTextFlat('Hello <b>world</b>!')
44
+ * // [
45
+ * // { text: 'Hello ', tagNames: '', cssClass: '' },
46
+ * // { text: 'world', tagNames: 'b', cssClass: 'rtp-b' },
47
+ * // { text: '!', tagNames: '', cssClass: '' },
48
+ * // ]
49
+ */
50
+ export declare function parseRichTextFlat(input: string): TextSegment[];
32
51
  export declare function setRichTextTag(tag: {
33
52
  tag: string;
34
53
  tagName?: string;
@@ -26,3 +26,26 @@ export declare function generateStylesheet(): void;
26
26
  * // ]
27
27
  */
28
28
  export declare function groupByBlocks(segments: TextSegment[]): BlockGroup[];
29
+ /**
30
+ * Appends parsed rich text segments to a DOM element, creating nested elements
31
+ * for each block group and its inline segments.
32
+ *
33
+ * @param htmlElement - The target DOM element to append content to. Must support `appendChild`.
34
+ * @param segments - An array of `BlockGroup` objects (e.g. from `groupByBlocks`).
35
+ * @param config - Optional configuration for styling behavior.
36
+ * @param config.useClasses - Whether to apply CSS class names to elements. Defaults to `true`.
37
+ * @param config.useStyles - Whether to apply inline styles to elements. Defaults to `false`.
38
+ *
39
+ * @example
40
+ * const el = document.getElementById('output');
41
+ * const groups = groupByBlocks(parseRichText('<b>Hello</b> <i>world</i>'));
42
+ * appendToDom(el, groups);
43
+ *
44
+ * @example
45
+ * // With inline styles instead of classes
46
+ * appendToDom(el, groups, { useClasses: false, useStyles: true });
47
+ */
48
+ export declare function appendToDom<T extends object>(htmlElement: T, segments: BlockGroup[], config?: {
49
+ useClasses?: boolean;
50
+ useStyles?: boolean;
51
+ }): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dvirus-js/utils",
3
- "version": "0.0.1",
3
+ "version": "0.0.6",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",