thunderous 1.0.0 → 1.0.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/dist/index.cjs +42 -44
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +42 -44
- package/package.json +10 -6
package/dist/index.cjs
CHANGED
@@ -469,6 +469,21 @@ if (typeof window !== "undefined") {
|
|
469
469
|
window.CustomElementRegistry = TrackableCustomElementRegistry;
|
470
470
|
}
|
471
471
|
|
472
|
+
// src/constants.ts
|
473
|
+
var DEFAULT_RENDER_OPTIONS = {
|
474
|
+
formAssociated: false,
|
475
|
+
observedAttributes: [],
|
476
|
+
attributesAsProperties: [],
|
477
|
+
attachShadow: true,
|
478
|
+
shadowRootOptions: {
|
479
|
+
mode: "closed",
|
480
|
+
delegatesFocus: false,
|
481
|
+
clonable: false,
|
482
|
+
serializable: false,
|
483
|
+
slotAssignment: "named"
|
484
|
+
}
|
485
|
+
};
|
486
|
+
|
472
487
|
// src/signals.ts
|
473
488
|
var subscriber = null;
|
474
489
|
var updateQueue = /* @__PURE__ */ new Set();
|
@@ -480,7 +495,7 @@ var createSignal = (initVal, options) => {
|
|
480
495
|
if (subscriber !== null) {
|
481
496
|
subscribers.add(subscriber);
|
482
497
|
}
|
483
|
-
if (options?.debugMode || getterOptions?.debugMode) {
|
498
|
+
if (options?.debugMode === true || getterOptions?.debugMode === true) {
|
484
499
|
queueMicrotask(() => {
|
485
500
|
let label = "anonymous signal";
|
486
501
|
if (options?.label !== void 0) {
|
@@ -514,7 +529,7 @@ var createSignal = (initVal, options) => {
|
|
514
529
|
console.error("Error in subscriber:", { error, oldValue, newValue, fn });
|
515
530
|
}
|
516
531
|
}
|
517
|
-
if (options?.debugMode || setterOptions?.debugMode) {
|
532
|
+
if (options?.debugMode === true || setterOptions?.debugMode === true) {
|
518
533
|
let label = "anonymous signal";
|
519
534
|
if (options?.label !== void 0) {
|
520
535
|
label = `(${options.label})`;
|
@@ -554,6 +569,9 @@ var createEffect = (fn) => {
|
|
554
569
|
subscriber = null;
|
555
570
|
};
|
556
571
|
|
572
|
+
// src/utilities.ts
|
573
|
+
var NOOP = () => void 0;
|
574
|
+
|
557
575
|
// src/server-side.ts
|
558
576
|
var isServer = typeof window === "undefined";
|
559
577
|
var serverDefineFns = /* @__PURE__ */ new Set();
|
@@ -610,29 +628,21 @@ var getServerRenderArgs = (tagName, registry) => ({
|
|
610
628
|
}
|
611
629
|
});
|
612
630
|
},
|
613
|
-
attributeChangedCallback:
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
},
|
623
|
-
formResetCallback: () => {
|
624
|
-
},
|
625
|
-
formStateRestoreCallback: () => {
|
626
|
-
},
|
627
|
-
formAssociatedCallback: () => {
|
628
|
-
},
|
629
|
-
clientOnlyCallback: () => {
|
630
|
-
},
|
631
|
+
attributeChangedCallback: NOOP,
|
632
|
+
connectedCallback: NOOP,
|
633
|
+
disconnectedCallback: NOOP,
|
634
|
+
adoptedCallback: NOOP,
|
635
|
+
formDisabledCallback: NOOP,
|
636
|
+
formResetCallback: NOOP,
|
637
|
+
formStateRestoreCallback: NOOP,
|
638
|
+
formAssociatedCallback: NOOP,
|
639
|
+
clientOnlyCallback: NOOP,
|
631
640
|
customCallback: () => `{{callback:unavailable-on-server}}`,
|
632
641
|
attrSignals: new Proxy({}, { get: (_, attr) => createSignal(`{{attr:${String(attr)}}}`) }),
|
633
642
|
propSignals: new Proxy({}, { get: () => createSignal(null) }),
|
634
643
|
refs: {},
|
635
|
-
// @ts-expect-error // this
|
644
|
+
// @ts-expect-error // this will be a string for SSR, but this is true for internal cases only.
|
645
|
+
// The end user will see the public type, which is either a CSSStyleSheet or HTMLStyleElement.
|
636
646
|
adoptStyleSheet: (cssStr) => {
|
637
647
|
const _serverCss = registry !== void 0 ? registry.__serverCss : serverCss;
|
638
648
|
const cssArr = _serverCss.get(tagName) ?? [];
|
@@ -663,8 +673,9 @@ var wrapTemplate = ({ tagName, serverRender, options }) => {
|
|
663
673
|
};
|
664
674
|
var insertTemplates = (tagName, template, inputString) => {
|
665
675
|
return inputString.replace(new RegExp(`(<s*${tagName}([^>]*)>)`, "gm"), ($1, _, $3) => {
|
666
|
-
const attrs = $3.split(/(
|
667
|
-
const [
|
676
|
+
const attrs = $3.split(/(?<=")\s+/).filter((attr) => attr.trim() !== "").map((attr) => {
|
677
|
+
const [_key, _value] = attr.split("=");
|
678
|
+
const key = _key.trim();
|
668
679
|
const value = _value?.replace(/"/g, "") ?? "";
|
669
680
|
return [key, value];
|
670
681
|
});
|
@@ -760,7 +771,7 @@ var html = (strings, ...values) => {
|
|
760
771
|
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : void 0;
|
761
772
|
const value = signal !== void 0 ? signal() : text;
|
762
773
|
if (value === null) hasNull = true;
|
763
|
-
newText += value;
|
774
|
+
newText += String(value);
|
764
775
|
}
|
765
776
|
if (hasNull && newText === "null") {
|
766
777
|
child.removeAttribute(attr.name);
|
@@ -809,19 +820,20 @@ var css = (strings, ...values) => {
|
|
809
820
|
if (isServer) {
|
810
821
|
return cssText;
|
811
822
|
}
|
812
|
-
|
823
|
+
const stylesheet = adoptedStylesSupported ? new CSSStyleSheet() : document.createElement("style");
|
813
824
|
const textList = cssText.split(signalBindingRegex);
|
814
825
|
createEffect(() => {
|
815
826
|
const newCSSTextList = [];
|
816
827
|
for (const text of textList) {
|
817
828
|
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
818
829
|
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
819
|
-
const
|
830
|
+
const newValue = signal !== null ? signal() : text;
|
831
|
+
const newText = String(newValue);
|
820
832
|
newCSSTextList.push(newText);
|
821
833
|
}
|
822
834
|
const newCSSText = newCSSTextList.join("");
|
823
835
|
if (isCSSStyleSheet(stylesheet)) {
|
824
|
-
stylesheet.replace(newCSSText);
|
836
|
+
stylesheet.replace(newCSSText).catch(console.error);
|
825
837
|
} else {
|
826
838
|
stylesheet.textContent = newCSSText;
|
827
839
|
}
|
@@ -830,19 +842,6 @@ var css = (strings, ...values) => {
|
|
830
842
|
};
|
831
843
|
|
832
844
|
// src/custom-element.ts
|
833
|
-
var DEFAULT_RENDER_OPTIONS = {
|
834
|
-
formAssociated: false,
|
835
|
-
observedAttributes: [],
|
836
|
-
attributesAsProperties: [],
|
837
|
-
attachShadow: true,
|
838
|
-
shadowRootOptions: {
|
839
|
-
mode: "closed",
|
840
|
-
delegatesFocus: false,
|
841
|
-
clonable: false,
|
842
|
-
serializable: false,
|
843
|
-
slotAssignment: "named"
|
844
|
-
}
|
845
|
-
};
|
846
845
|
var customElement = (render, options) => {
|
847
846
|
const _options = { ...DEFAULT_RENDER_OPTIONS, ...options };
|
848
847
|
const {
|
@@ -927,8 +926,7 @@ var customElement = (render, options) => {
|
|
927
926
|
if (mutation.type !== "attributes" || attrName === null) continue;
|
928
927
|
if (!(attrName in this.#attrSignals)) this.#attrSignals[attrName] = createSignal(null);
|
929
928
|
const [getter, setter] = this.#attrSignals[attrName];
|
930
|
-
const
|
931
|
-
const oldValue = _oldValue === null ? null : _oldValue;
|
929
|
+
const oldValue = getter();
|
932
930
|
const newValue = this.getAttribute(attrName);
|
933
931
|
setter(newValue);
|
934
932
|
for (const fn of this.#attributeChangedFns) {
|
@@ -1039,7 +1037,7 @@ You must set an initial value before calling a property signal's getter.
|
|
1039
1037
|
tempContainer.append(fragment.cloneNode(true));
|
1040
1038
|
const fragmentContent = tempContainer.innerHTML;
|
1041
1039
|
root.innerHTML = fragmentContent;
|
1042
|
-
if (registry
|
1040
|
+
if (registry?.__tagNames !== void 0) {
|
1043
1041
|
for (const tagName of registry.__tagNames) {
|
1044
1042
|
const upgradedElements = root.querySelectorAll(tagName);
|
1045
1043
|
const nonUpgradedElements = fragment.querySelectorAll(tagName);
|
@@ -1152,7 +1150,7 @@ You must set an initial value before calling a property signal's getter.
|
|
1152
1150
|
let _registry;
|
1153
1151
|
const elementResult = {
|
1154
1152
|
define(tagName, options2) {
|
1155
|
-
const registry = _registry
|
1153
|
+
const registry = _registry ?? customElements;
|
1156
1154
|
const nativeRegistry = "eject" in registry ? registry.eject() : registry;
|
1157
1155
|
if (nativeRegistry.get(tagName) !== void 0) {
|
1158
1156
|
console.warn(`Custom element "${tagName}" was already defined. Skipping...`);
|
package/dist/index.d.cts
CHANGED
@@ -645,6 +645,8 @@ type ServerRenderFunction = (args: RenderArgs<CustomElementProps>) => string;
|
|
645
645
|
|
646
646
|
type ServerRenderOptions = { serverRender: ServerRenderFunction } & RenderOptions;
|
647
647
|
|
648
|
+
type ServerDefineFn = (tagName: string, htmlString: string) => void;
|
649
|
+
|
648
650
|
type RegistryResult = {
|
649
651
|
__serverCss: Map<string, string[]>;
|
650
652
|
__serverRenderOpts: Map<string, ServerRenderOptions>;
|
@@ -699,7 +701,6 @@ declare const customElement: <Props extends CustomElementProps>(render: RenderFu
|
|
699
701
|
*/
|
700
702
|
declare const createRegistry: (args?: RegistryArgs) => RegistryResult;
|
701
703
|
|
702
|
-
type ServerDefineFn = (tagName: string, htmlString: string) => void;
|
703
704
|
declare const onServerDefine: (fn: ServerDefineFn) => void;
|
704
705
|
declare const insertTemplates: (tagName: string, template: string, inputString: string) => string;
|
705
706
|
declare const clientOnlyCallback: (fn: (() => void) | (() => Promise<void>)) => void | Promise<void>;
|
package/dist/index.d.ts
CHANGED
@@ -645,6 +645,8 @@ type ServerRenderFunction = (args: RenderArgs<CustomElementProps>) => string;
|
|
645
645
|
|
646
646
|
type ServerRenderOptions = { serverRender: ServerRenderFunction } & RenderOptions;
|
647
647
|
|
648
|
+
type ServerDefineFn = (tagName: string, htmlString: string) => void;
|
649
|
+
|
648
650
|
type RegistryResult = {
|
649
651
|
__serverCss: Map<string, string[]>;
|
650
652
|
__serverRenderOpts: Map<string, ServerRenderOptions>;
|
@@ -699,7 +701,6 @@ declare const customElement: <Props extends CustomElementProps>(render: RenderFu
|
|
699
701
|
*/
|
700
702
|
declare const createRegistry: (args?: RegistryArgs) => RegistryResult;
|
701
703
|
|
702
|
-
type ServerDefineFn = (tagName: string, htmlString: string) => void;
|
703
704
|
declare const onServerDefine: (fn: ServerDefineFn) => void;
|
704
705
|
declare const insertTemplates: (tagName: string, template: string, inputString: string) => string;
|
705
706
|
declare const clientOnlyCallback: (fn: (() => void) | (() => Promise<void>)) => void | Promise<void>;
|
package/dist/index.js
CHANGED
@@ -434,6 +434,21 @@ if (typeof window !== "undefined") {
|
|
434
434
|
window.CustomElementRegistry = TrackableCustomElementRegistry;
|
435
435
|
}
|
436
436
|
|
437
|
+
// src/constants.ts
|
438
|
+
var DEFAULT_RENDER_OPTIONS = {
|
439
|
+
formAssociated: false,
|
440
|
+
observedAttributes: [],
|
441
|
+
attributesAsProperties: [],
|
442
|
+
attachShadow: true,
|
443
|
+
shadowRootOptions: {
|
444
|
+
mode: "closed",
|
445
|
+
delegatesFocus: false,
|
446
|
+
clonable: false,
|
447
|
+
serializable: false,
|
448
|
+
slotAssignment: "named"
|
449
|
+
}
|
450
|
+
};
|
451
|
+
|
437
452
|
// src/signals.ts
|
438
453
|
var subscriber = null;
|
439
454
|
var updateQueue = /* @__PURE__ */ new Set();
|
@@ -445,7 +460,7 @@ var createSignal = (initVal, options) => {
|
|
445
460
|
if (subscriber !== null) {
|
446
461
|
subscribers.add(subscriber);
|
447
462
|
}
|
448
|
-
if (options?.debugMode || getterOptions?.debugMode) {
|
463
|
+
if (options?.debugMode === true || getterOptions?.debugMode === true) {
|
449
464
|
queueMicrotask(() => {
|
450
465
|
let label = "anonymous signal";
|
451
466
|
if (options?.label !== void 0) {
|
@@ -479,7 +494,7 @@ var createSignal = (initVal, options) => {
|
|
479
494
|
console.error("Error in subscriber:", { error, oldValue, newValue, fn });
|
480
495
|
}
|
481
496
|
}
|
482
|
-
if (options?.debugMode || setterOptions?.debugMode) {
|
497
|
+
if (options?.debugMode === true || setterOptions?.debugMode === true) {
|
483
498
|
let label = "anonymous signal";
|
484
499
|
if (options?.label !== void 0) {
|
485
500
|
label = `(${options.label})`;
|
@@ -519,6 +534,9 @@ var createEffect = (fn) => {
|
|
519
534
|
subscriber = null;
|
520
535
|
};
|
521
536
|
|
537
|
+
// src/utilities.ts
|
538
|
+
var NOOP = () => void 0;
|
539
|
+
|
522
540
|
// src/server-side.ts
|
523
541
|
var isServer = typeof window === "undefined";
|
524
542
|
var serverDefineFns = /* @__PURE__ */ new Set();
|
@@ -575,29 +593,21 @@ var getServerRenderArgs = (tagName, registry) => ({
|
|
575
593
|
}
|
576
594
|
});
|
577
595
|
},
|
578
|
-
attributeChangedCallback:
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
},
|
588
|
-
formResetCallback: () => {
|
589
|
-
},
|
590
|
-
formStateRestoreCallback: () => {
|
591
|
-
},
|
592
|
-
formAssociatedCallback: () => {
|
593
|
-
},
|
594
|
-
clientOnlyCallback: () => {
|
595
|
-
},
|
596
|
+
attributeChangedCallback: NOOP,
|
597
|
+
connectedCallback: NOOP,
|
598
|
+
disconnectedCallback: NOOP,
|
599
|
+
adoptedCallback: NOOP,
|
600
|
+
formDisabledCallback: NOOP,
|
601
|
+
formResetCallback: NOOP,
|
602
|
+
formStateRestoreCallback: NOOP,
|
603
|
+
formAssociatedCallback: NOOP,
|
604
|
+
clientOnlyCallback: NOOP,
|
596
605
|
customCallback: () => `{{callback:unavailable-on-server}}`,
|
597
606
|
attrSignals: new Proxy({}, { get: (_, attr) => createSignal(`{{attr:${String(attr)}}}`) }),
|
598
607
|
propSignals: new Proxy({}, { get: () => createSignal(null) }),
|
599
608
|
refs: {},
|
600
|
-
// @ts-expect-error // this
|
609
|
+
// @ts-expect-error // this will be a string for SSR, but this is true for internal cases only.
|
610
|
+
// The end user will see the public type, which is either a CSSStyleSheet or HTMLStyleElement.
|
601
611
|
adoptStyleSheet: (cssStr) => {
|
602
612
|
const _serverCss = registry !== void 0 ? registry.__serverCss : serverCss;
|
603
613
|
const cssArr = _serverCss.get(tagName) ?? [];
|
@@ -628,8 +638,9 @@ var wrapTemplate = ({ tagName, serverRender, options }) => {
|
|
628
638
|
};
|
629
639
|
var insertTemplates = (tagName, template, inputString) => {
|
630
640
|
return inputString.replace(new RegExp(`(<s*${tagName}([^>]*)>)`, "gm"), ($1, _, $3) => {
|
631
|
-
const attrs = $3.split(/(
|
632
|
-
const [
|
641
|
+
const attrs = $3.split(/(?<=")\s+/).filter((attr) => attr.trim() !== "").map((attr) => {
|
642
|
+
const [_key, _value] = attr.split("=");
|
643
|
+
const key = _key.trim();
|
633
644
|
const value = _value?.replace(/"/g, "") ?? "";
|
634
645
|
return [key, value];
|
635
646
|
});
|
@@ -725,7 +736,7 @@ var html = (strings, ...values) => {
|
|
725
736
|
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : void 0;
|
726
737
|
const value = signal !== void 0 ? signal() : text;
|
727
738
|
if (value === null) hasNull = true;
|
728
|
-
newText += value;
|
739
|
+
newText += String(value);
|
729
740
|
}
|
730
741
|
if (hasNull && newText === "null") {
|
731
742
|
child.removeAttribute(attr.name);
|
@@ -774,19 +785,20 @@ var css = (strings, ...values) => {
|
|
774
785
|
if (isServer) {
|
775
786
|
return cssText;
|
776
787
|
}
|
777
|
-
|
788
|
+
const stylesheet = adoptedStylesSupported ? new CSSStyleSheet() : document.createElement("style");
|
778
789
|
const textList = cssText.split(signalBindingRegex);
|
779
790
|
createEffect(() => {
|
780
791
|
const newCSSTextList = [];
|
781
792
|
for (const text of textList) {
|
782
793
|
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
783
794
|
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
784
|
-
const
|
795
|
+
const newValue = signal !== null ? signal() : text;
|
796
|
+
const newText = String(newValue);
|
785
797
|
newCSSTextList.push(newText);
|
786
798
|
}
|
787
799
|
const newCSSText = newCSSTextList.join("");
|
788
800
|
if (isCSSStyleSheet(stylesheet)) {
|
789
|
-
stylesheet.replace(newCSSText);
|
801
|
+
stylesheet.replace(newCSSText).catch(console.error);
|
790
802
|
} else {
|
791
803
|
stylesheet.textContent = newCSSText;
|
792
804
|
}
|
@@ -795,19 +807,6 @@ var css = (strings, ...values) => {
|
|
795
807
|
};
|
796
808
|
|
797
809
|
// src/custom-element.ts
|
798
|
-
var DEFAULT_RENDER_OPTIONS = {
|
799
|
-
formAssociated: false,
|
800
|
-
observedAttributes: [],
|
801
|
-
attributesAsProperties: [],
|
802
|
-
attachShadow: true,
|
803
|
-
shadowRootOptions: {
|
804
|
-
mode: "closed",
|
805
|
-
delegatesFocus: false,
|
806
|
-
clonable: false,
|
807
|
-
serializable: false,
|
808
|
-
slotAssignment: "named"
|
809
|
-
}
|
810
|
-
};
|
811
810
|
var customElement = (render, options) => {
|
812
811
|
const _options = { ...DEFAULT_RENDER_OPTIONS, ...options };
|
813
812
|
const {
|
@@ -892,8 +891,7 @@ var customElement = (render, options) => {
|
|
892
891
|
if (mutation.type !== "attributes" || attrName === null) continue;
|
893
892
|
if (!(attrName in this.#attrSignals)) this.#attrSignals[attrName] = createSignal(null);
|
894
893
|
const [getter, setter] = this.#attrSignals[attrName];
|
895
|
-
const
|
896
|
-
const oldValue = _oldValue === null ? null : _oldValue;
|
894
|
+
const oldValue = getter();
|
897
895
|
const newValue = this.getAttribute(attrName);
|
898
896
|
setter(newValue);
|
899
897
|
for (const fn of this.#attributeChangedFns) {
|
@@ -1004,7 +1002,7 @@ You must set an initial value before calling a property signal's getter.
|
|
1004
1002
|
tempContainer.append(fragment.cloneNode(true));
|
1005
1003
|
const fragmentContent = tempContainer.innerHTML;
|
1006
1004
|
root.innerHTML = fragmentContent;
|
1007
|
-
if (registry
|
1005
|
+
if (registry?.__tagNames !== void 0) {
|
1008
1006
|
for (const tagName of registry.__tagNames) {
|
1009
1007
|
const upgradedElements = root.querySelectorAll(tagName);
|
1010
1008
|
const nonUpgradedElements = fragment.querySelectorAll(tagName);
|
@@ -1117,7 +1115,7 @@ You must set an initial value before calling a property signal's getter.
|
|
1117
1115
|
let _registry;
|
1118
1116
|
const elementResult = {
|
1119
1117
|
define(tagName, options2) {
|
1120
|
-
const registry = _registry
|
1118
|
+
const registry = _registry ?? customElements;
|
1121
1119
|
const nativeRegistry = "eject" in registry ? registry.eject() : registry;
|
1122
1120
|
if (nativeRegistry.get(tagName) !== void 0) {
|
1123
1121
|
console.warn(`Custom element "${tagName}" was already defined. Skipping...`);
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "thunderous",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.1",
|
4
4
|
"description": "",
|
5
5
|
"type": "module",
|
6
6
|
"main": "./dist/index.cjs",
|
@@ -32,13 +32,17 @@
|
|
32
32
|
"scripts": {
|
33
33
|
"demo": "cd demo && npm start",
|
34
34
|
"www": "cd www && npm run dev",
|
35
|
-
"build": "tsup src/index.ts --format cjs,esm --dts --no-clean"
|
35
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --no-clean",
|
36
|
+
"test": "find src -name '*.test.ts' | xargs c8 node --import tsx --test",
|
37
|
+
"lint": "eslint ."
|
36
38
|
},
|
37
39
|
"devDependencies": {
|
38
40
|
"@types/dompurify": "^3.2.0",
|
39
41
|
"@types/eslint": "^8.56.10",
|
40
|
-
"@
|
41
|
-
"@typescript-eslint/
|
42
|
+
"@types/node": "^22.10.1",
|
43
|
+
"@typescript-eslint/eslint-plugin": "^8.17.0",
|
44
|
+
"@typescript-eslint/parser": "^8.17.0",
|
45
|
+
"c8": "^10.1.2",
|
42
46
|
"eslint": "^8.57.0",
|
43
47
|
"eslint-plugin-import": "^2.31.0",
|
44
48
|
"eslint-plugin-node": "^11.1.0",
|
@@ -46,7 +50,7 @@
|
|
46
50
|
"express": "^4.17.1",
|
47
51
|
"prettier": "^3.3.3",
|
48
52
|
"tsup": "^8.3.0",
|
49
|
-
"
|
50
|
-
"
|
53
|
+
"tsx": "^4.19.2",
|
54
|
+
"typescript": "^5.7.2"
|
51
55
|
}
|
52
56
|
}
|