trotl-modal 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/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # texteditor
2
+
3
+ A simple, flexible **modal editor UI** for React
4
+
5
+ ---
6
+ **DEMO:** [https://modal.linijart.eu/](https://modal.linijart.eu/)
7
+ ---
8
+
9
+ ## 🚀 Installation
10
+
11
+ ```bash
12
+ npm install trotl-modal
13
+ # or
14
+ yarn add trotl-modal
15
+ ```
16
+
17
+ ## Versions
18
+ ```js
19
+
20
+
21
+ 1.0.1 => initial release
22
+ ```
23
+
24
+ ## ⚡ Quick Start
25
+
26
+ ```jsx
27
+ import Editor from "trotl-modal";
28
+
29
+ export default function Demo() {
30
+ return (
31
+ <div>
32
+
33
+ </div>
34
+ );
35
+ }
36
+ ```
37
+
38
+ ## 🛠 Features
39
+
40
+
41
+ ## 📚 API Reference
42
+
43
+
44
+ ## 🌟 Context Hooks
45
+
46
+
47
+ ```js
48
+
49
+ ```
50
+
51
+ ## 🎨 Styling
52
+
53
+ ```css
54
+
55
+ ```
56
+
57
+ ## 🏆 License
58
+
59
+ MIT — free to use, modify, and share.
60
+
@@ -0,0 +1,149 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+
5
+ function Modal({
6
+ isOpen,
7
+ onClose,
8
+ title,
9
+ children
10
+ }) {
11
+ const modalRef = React.useRef(null);
12
+ const headerRef = React.useRef(null);
13
+ const [pos, setPos] = React.useState({
14
+ x: 0,
15
+ y: 0
16
+ });
17
+ const draggingRef = React.useRef(false);
18
+ const offsetRef = React.useRef({
19
+ x: 0,
20
+ y: 0
21
+ });
22
+ React.useEffect(() => {
23
+ if (isOpen) {
24
+ // center modal initially
25
+ const el = modalRef.current;
26
+ if (el) {
27
+ const {
28
+ innerWidth,
29
+ innerHeight
30
+ } = window;
31
+ const rect = el.getBoundingClientRect();
32
+ setPos({
33
+ x: (innerWidth - rect.width) / 2,
34
+ y: (innerHeight - rect.height) / 2
35
+ });
36
+ }
37
+ }
38
+ }, [isOpen]);
39
+ React.useEffect(() => {
40
+ function onMove(e) {
41
+ if (!draggingRef.current) return;
42
+ if (e.touches) e.preventDefault();
43
+ const clientX = e.touches ? e.touches[0].clientX : e.clientX;
44
+ const clientY = e.touches ? e.touches[0].clientY : e.clientY;
45
+ // compute desired position
46
+ const desiredX = clientX - offsetRef.current.x;
47
+ const desiredY = clientY - offsetRef.current.y;
48
+ // clamp to viewport so it can't be dragged fully offscreen
49
+ const el = modalRef.current;
50
+ if (el) {
51
+ const rect = el.getBoundingClientRect();
52
+ const maxX = window.innerWidth - rect.width;
53
+ const maxY = window.innerHeight - rect.height;
54
+ const clampedX = Math.min(Math.max(0, desiredX), Math.max(0, maxX));
55
+ const clampedY = Math.min(Math.max(0, desiredY), Math.max(0, maxY));
56
+ setPos({
57
+ x: clampedX,
58
+ y: clampedY
59
+ });
60
+ } else {
61
+ setPos({
62
+ x: desiredX,
63
+ y: desiredY
64
+ });
65
+ }
66
+ }
67
+ function onUp() {
68
+ draggingRef.current = false;
69
+ }
70
+ window.addEventListener('mousemove', onMove);
71
+ window.addEventListener('mouseup', onUp);
72
+ window.addEventListener('touchmove', onMove, {
73
+ passive: false
74
+ });
75
+ window.addEventListener('touchend', onUp);
76
+ return () => {
77
+ window.removeEventListener('mousemove', onMove);
78
+ window.removeEventListener('mouseup', onUp);
79
+ window.removeEventListener('touchmove', onMove);
80
+ window.removeEventListener('touchend', onUp);
81
+ };
82
+ }, []);
83
+ function startDrag(e) {
84
+ e.preventDefault();
85
+ draggingRef.current = true;
86
+ document.body.style.userSelect = 'none';
87
+ const clientX = e.touches ? e.touches[0].clientX : e.clientX;
88
+ const clientY = e.touches ? e.touches[0].clientY : e.clientY;
89
+ const rect = modalRef.current.getBoundingClientRect();
90
+ offsetRef.current = {
91
+ x: clientX - rect.left,
92
+ y: clientY - rect.top
93
+ };
94
+ }
95
+
96
+ // ensure we re-enable selection when drag ends
97
+ React.useEffect(() => {
98
+ function onUpCleanup() {
99
+ draggingRef.current = false;
100
+ document.body.style.userSelect = '';
101
+ // final clamp to ensure modal stays visible if window size changed
102
+ const el = modalRef.current;
103
+ if (el) {
104
+ const rect = el.getBoundingClientRect();
105
+ const maxX = window.innerWidth - rect.width;
106
+ const maxY = window.innerHeight - rect.height;
107
+ setPos(prev => ({
108
+ x: Math.min(Math.max(0, prev.x), Math.max(0, maxX)),
109
+ y: Math.min(Math.max(0, prev.y), Math.max(0, maxY))
110
+ }));
111
+ }
112
+ }
113
+ window.addEventListener('mouseup', onUpCleanup);
114
+ window.addEventListener('touchend', onUpCleanup);
115
+ return () => {
116
+ window.removeEventListener('mouseup', onUpCleanup);
117
+ window.removeEventListener('touchend', onUpCleanup);
118
+ };
119
+ }, []);
120
+ if (!isOpen) return null;
121
+ return /*#__PURE__*/React.createElement("div", {
122
+ className: "modal-overlay",
123
+ onMouseDown: e => {
124
+ if (e.target === e.currentTarget) onClose();
125
+ }
126
+ }, /*#__PURE__*/React.createElement("div", {
127
+ className: "modal",
128
+ ref: modalRef,
129
+ style: {
130
+ left: `${pos.x}px`,
131
+ top: `${pos.y}px`
132
+ }
133
+ }, /*#__PURE__*/React.createElement("div", {
134
+ className: "modal-header",
135
+ ref: headerRef,
136
+ onMouseDown: startDrag,
137
+ onTouchStart: startDrag
138
+ }, /*#__PURE__*/React.createElement("div", {
139
+ className: "modal-title"
140
+ }, title), /*#__PURE__*/React.createElement("button", {
141
+ className: "modal-close",
142
+ onClick: onClose
143
+ }, "\xD7")), /*#__PURE__*/React.createElement("div", {
144
+ className: "modal-body"
145
+ }, children)));
146
+ }
147
+
148
+ exports.Modal = Modal;
149
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/components/Modal.jsx"],"sourcesContent":["import React, {useEffect, useRef, useState} from 'react'\r\n\r\nexport default function Modal({isOpen, onClose, title, children}){\r\n const modalRef = useRef(null)\r\n const headerRef = useRef(null)\r\n const [pos, setPos] = useState({x: 0, y: 0})\r\n const draggingRef = useRef(false)\r\n const offsetRef = useRef({x:0,y:0})\r\n\r\n useEffect(()=>{\r\n if(isOpen){\r\n // center modal initially\r\n const el = modalRef.current\r\n if(el){\r\n const {innerWidth, innerHeight} = window\r\n const rect = el.getBoundingClientRect()\r\n setPos({x: (innerWidth - rect.width)/2, y: (innerHeight - rect.height)/2})\r\n }\r\n }\r\n },[isOpen])\r\n\r\n useEffect(()=>{\r\n function onMove(e){\r\n if(!draggingRef.current) return\r\n if (e.touches) e.preventDefault()\r\n const clientX = e.touches ? e.touches[0].clientX : e.clientX\r\n const clientY = e.touches ? e.touches[0].clientY : e.clientY\r\n // compute desired position\r\n const desiredX = clientX - offsetRef.current.x\r\n const desiredY = clientY - offsetRef.current.y\r\n // clamp to viewport so it can't be dragged fully offscreen\r\n const el = modalRef.current\r\n if(el){\r\n const rect = el.getBoundingClientRect()\r\n const maxX = window.innerWidth - rect.width\r\n const maxY = window.innerHeight - rect.height\r\n const clampedX = Math.min(Math.max(0, desiredX), Math.max(0, maxX))\r\n const clampedY = Math.min(Math.max(0, desiredY), Math.max(0, maxY))\r\n setPos({x: clampedX, y: clampedY})\r\n } else {\r\n setPos({x: desiredX, y: desiredY})\r\n }\r\n }\r\n function onUp(){ draggingRef.current = false }\r\n window.addEventListener('mousemove', onMove)\r\n window.addEventListener('mouseup', onUp)\r\n window.addEventListener('touchmove', onMove, {passive:false})\r\n window.addEventListener('touchend', onUp)\r\n return ()=>{\r\n window.removeEventListener('mousemove', onMove)\r\n window.removeEventListener('mouseup', onUp)\r\n window.removeEventListener('touchmove', onMove)\r\n window.removeEventListener('touchend', onUp)\r\n }\r\n },[])\r\n\r\n function startDrag(e){\r\n e.preventDefault()\r\n draggingRef.current = true\r\n document.body.style.userSelect = 'none'\r\n const clientX = e.touches ? e.touches[0].clientX : e.clientX\r\n const clientY = e.touches ? e.touches[0].clientY : e.clientY\r\n const rect = modalRef.current.getBoundingClientRect()\r\n offsetRef.current = {x: clientX - rect.left, y: clientY - rect.top}\r\n }\r\n\r\n // ensure we re-enable selection when drag ends\r\n useEffect(()=>{\r\n function onUpCleanup(){\r\n draggingRef.current = false\r\n document.body.style.userSelect = ''\r\n // final clamp to ensure modal stays visible if window size changed\r\n const el = modalRef.current\r\n if(el){\r\n const rect = el.getBoundingClientRect()\r\n const maxX = window.innerWidth - rect.width\r\n const maxY = window.innerHeight - rect.height\r\n setPos(prev => ({\r\n x: Math.min(Math.max(0, prev.x), Math.max(0, maxX)),\r\n y: Math.min(Math.max(0, prev.y), Math.max(0, maxY))\r\n }))\r\n }\r\n }\r\n window.addEventListener('mouseup', onUpCleanup)\r\n window.addEventListener('touchend', onUpCleanup)\r\n return ()=>{\r\n window.removeEventListener('mouseup', onUpCleanup)\r\n window.removeEventListener('touchend', onUpCleanup)\r\n }\r\n },[])\r\n\r\n if(!isOpen) return null\r\n\r\n return (\r\n <div className=\"modal-overlay\" onMouseDown={(e)=>{ if(e.target === e.currentTarget) onClose() }}>\r\n <div className=\"modal\" ref={modalRef} style={{left:`${pos.x}px`, top:`${pos.y}px`}}>\r\n <div className=\"modal-header\" ref={headerRef} onMouseDown={startDrag} onTouchStart={startDrag}>\r\n <div className=\"modal-title\">{title}</div>\r\n <button className=\"modal-close\" onClick={onClose}>×</button>\r\n </div>\r\n <div className=\"modal-body\">{children}</div>\r\n </div>\r\n </div>\r\n )\r\n}\r\n"],"names":["Modal","isOpen","onClose","title","children","modalRef","useRef","headerRef","pos","setPos","useState","x","y","draggingRef","offsetRef","useEffect","el","current","innerWidth","innerHeight","window","rect","getBoundingClientRect","width","height","onMove","e","touches","preventDefault","clientX","clientY","desiredX","desiredY","maxX","maxY","clampedX","Math","min","max","clampedY","onUp","addEventListener","passive","removeEventListener","startDrag","document","body","style","userSelect","left","top","onUpCleanup","prev","React","createElement","className","onMouseDown","target","currentTarget","ref","onTouchStart","onClick"],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ import React, { useRef, useState, useEffect } from 'react';
2
+
3
+ function Modal({
4
+ isOpen,
5
+ onClose,
6
+ title,
7
+ children
8
+ }) {
9
+ const modalRef = useRef(null);
10
+ const headerRef = useRef(null);
11
+ const [pos, setPos] = useState({
12
+ x: 0,
13
+ y: 0
14
+ });
15
+ const draggingRef = useRef(false);
16
+ const offsetRef = useRef({
17
+ x: 0,
18
+ y: 0
19
+ });
20
+ useEffect(() => {
21
+ if (isOpen) {
22
+ // center modal initially
23
+ const el = modalRef.current;
24
+ if (el) {
25
+ const {
26
+ innerWidth,
27
+ innerHeight
28
+ } = window;
29
+ const rect = el.getBoundingClientRect();
30
+ setPos({
31
+ x: (innerWidth - rect.width) / 2,
32
+ y: (innerHeight - rect.height) / 2
33
+ });
34
+ }
35
+ }
36
+ }, [isOpen]);
37
+ useEffect(() => {
38
+ function onMove(e) {
39
+ if (!draggingRef.current) return;
40
+ if (e.touches) e.preventDefault();
41
+ const clientX = e.touches ? e.touches[0].clientX : e.clientX;
42
+ const clientY = e.touches ? e.touches[0].clientY : e.clientY;
43
+ // compute desired position
44
+ const desiredX = clientX - offsetRef.current.x;
45
+ const desiredY = clientY - offsetRef.current.y;
46
+ // clamp to viewport so it can't be dragged fully offscreen
47
+ const el = modalRef.current;
48
+ if (el) {
49
+ const rect = el.getBoundingClientRect();
50
+ const maxX = window.innerWidth - rect.width;
51
+ const maxY = window.innerHeight - rect.height;
52
+ const clampedX = Math.min(Math.max(0, desiredX), Math.max(0, maxX));
53
+ const clampedY = Math.min(Math.max(0, desiredY), Math.max(0, maxY));
54
+ setPos({
55
+ x: clampedX,
56
+ y: clampedY
57
+ });
58
+ } else {
59
+ setPos({
60
+ x: desiredX,
61
+ y: desiredY
62
+ });
63
+ }
64
+ }
65
+ function onUp() {
66
+ draggingRef.current = false;
67
+ }
68
+ window.addEventListener('mousemove', onMove);
69
+ window.addEventListener('mouseup', onUp);
70
+ window.addEventListener('touchmove', onMove, {
71
+ passive: false
72
+ });
73
+ window.addEventListener('touchend', onUp);
74
+ return () => {
75
+ window.removeEventListener('mousemove', onMove);
76
+ window.removeEventListener('mouseup', onUp);
77
+ window.removeEventListener('touchmove', onMove);
78
+ window.removeEventListener('touchend', onUp);
79
+ };
80
+ }, []);
81
+ function startDrag(e) {
82
+ e.preventDefault();
83
+ draggingRef.current = true;
84
+ document.body.style.userSelect = 'none';
85
+ const clientX = e.touches ? e.touches[0].clientX : e.clientX;
86
+ const clientY = e.touches ? e.touches[0].clientY : e.clientY;
87
+ const rect = modalRef.current.getBoundingClientRect();
88
+ offsetRef.current = {
89
+ x: clientX - rect.left,
90
+ y: clientY - rect.top
91
+ };
92
+ }
93
+
94
+ // ensure we re-enable selection when drag ends
95
+ useEffect(() => {
96
+ function onUpCleanup() {
97
+ draggingRef.current = false;
98
+ document.body.style.userSelect = '';
99
+ // final clamp to ensure modal stays visible if window size changed
100
+ const el = modalRef.current;
101
+ if (el) {
102
+ const rect = el.getBoundingClientRect();
103
+ const maxX = window.innerWidth - rect.width;
104
+ const maxY = window.innerHeight - rect.height;
105
+ setPos(prev => ({
106
+ x: Math.min(Math.max(0, prev.x), Math.max(0, maxX)),
107
+ y: Math.min(Math.max(0, prev.y), Math.max(0, maxY))
108
+ }));
109
+ }
110
+ }
111
+ window.addEventListener('mouseup', onUpCleanup);
112
+ window.addEventListener('touchend', onUpCleanup);
113
+ return () => {
114
+ window.removeEventListener('mouseup', onUpCleanup);
115
+ window.removeEventListener('touchend', onUpCleanup);
116
+ };
117
+ }, []);
118
+ if (!isOpen) return null;
119
+ return /*#__PURE__*/React.createElement("div", {
120
+ className: "modal-overlay",
121
+ onMouseDown: e => {
122
+ if (e.target === e.currentTarget) onClose();
123
+ }
124
+ }, /*#__PURE__*/React.createElement("div", {
125
+ className: "modal",
126
+ ref: modalRef,
127
+ style: {
128
+ left: `${pos.x}px`,
129
+ top: `${pos.y}px`
130
+ }
131
+ }, /*#__PURE__*/React.createElement("div", {
132
+ className: "modal-header",
133
+ ref: headerRef,
134
+ onMouseDown: startDrag,
135
+ onTouchStart: startDrag
136
+ }, /*#__PURE__*/React.createElement("div", {
137
+ className: "modal-title"
138
+ }, title), /*#__PURE__*/React.createElement("button", {
139
+ className: "modal-close",
140
+ onClick: onClose
141
+ }, "\xD7")), /*#__PURE__*/React.createElement("div", {
142
+ className: "modal-body"
143
+ }, children)));
144
+ }
145
+
146
+ export { Modal };
147
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/components/Modal.jsx"],"sourcesContent":["import React, {useEffect, useRef, useState} from 'react'\r\n\r\nexport default function Modal({isOpen, onClose, title, children}){\r\n const modalRef = useRef(null)\r\n const headerRef = useRef(null)\r\n const [pos, setPos] = useState({x: 0, y: 0})\r\n const draggingRef = useRef(false)\r\n const offsetRef = useRef({x:0,y:0})\r\n\r\n useEffect(()=>{\r\n if(isOpen){\r\n // center modal initially\r\n const el = modalRef.current\r\n if(el){\r\n const {innerWidth, innerHeight} = window\r\n const rect = el.getBoundingClientRect()\r\n setPos({x: (innerWidth - rect.width)/2, y: (innerHeight - rect.height)/2})\r\n }\r\n }\r\n },[isOpen])\r\n\r\n useEffect(()=>{\r\n function onMove(e){\r\n if(!draggingRef.current) return\r\n if (e.touches) e.preventDefault()\r\n const clientX = e.touches ? e.touches[0].clientX : e.clientX\r\n const clientY = e.touches ? e.touches[0].clientY : e.clientY\r\n // compute desired position\r\n const desiredX = clientX - offsetRef.current.x\r\n const desiredY = clientY - offsetRef.current.y\r\n // clamp to viewport so it can't be dragged fully offscreen\r\n const el = modalRef.current\r\n if(el){\r\n const rect = el.getBoundingClientRect()\r\n const maxX = window.innerWidth - rect.width\r\n const maxY = window.innerHeight - rect.height\r\n const clampedX = Math.min(Math.max(0, desiredX), Math.max(0, maxX))\r\n const clampedY = Math.min(Math.max(0, desiredY), Math.max(0, maxY))\r\n setPos({x: clampedX, y: clampedY})\r\n } else {\r\n setPos({x: desiredX, y: desiredY})\r\n }\r\n }\r\n function onUp(){ draggingRef.current = false }\r\n window.addEventListener('mousemove', onMove)\r\n window.addEventListener('mouseup', onUp)\r\n window.addEventListener('touchmove', onMove, {passive:false})\r\n window.addEventListener('touchend', onUp)\r\n return ()=>{\r\n window.removeEventListener('mousemove', onMove)\r\n window.removeEventListener('mouseup', onUp)\r\n window.removeEventListener('touchmove', onMove)\r\n window.removeEventListener('touchend', onUp)\r\n }\r\n },[])\r\n\r\n function startDrag(e){\r\n e.preventDefault()\r\n draggingRef.current = true\r\n document.body.style.userSelect = 'none'\r\n const clientX = e.touches ? e.touches[0].clientX : e.clientX\r\n const clientY = e.touches ? e.touches[0].clientY : e.clientY\r\n const rect = modalRef.current.getBoundingClientRect()\r\n offsetRef.current = {x: clientX - rect.left, y: clientY - rect.top}\r\n }\r\n\r\n // ensure we re-enable selection when drag ends\r\n useEffect(()=>{\r\n function onUpCleanup(){\r\n draggingRef.current = false\r\n document.body.style.userSelect = ''\r\n // final clamp to ensure modal stays visible if window size changed\r\n const el = modalRef.current\r\n if(el){\r\n const rect = el.getBoundingClientRect()\r\n const maxX = window.innerWidth - rect.width\r\n const maxY = window.innerHeight - rect.height\r\n setPos(prev => ({\r\n x: Math.min(Math.max(0, prev.x), Math.max(0, maxX)),\r\n y: Math.min(Math.max(0, prev.y), Math.max(0, maxY))\r\n }))\r\n }\r\n }\r\n window.addEventListener('mouseup', onUpCleanup)\r\n window.addEventListener('touchend', onUpCleanup)\r\n return ()=>{\r\n window.removeEventListener('mouseup', onUpCleanup)\r\n window.removeEventListener('touchend', onUpCleanup)\r\n }\r\n },[])\r\n\r\n if(!isOpen) return null\r\n\r\n return (\r\n <div className=\"modal-overlay\" onMouseDown={(e)=>{ if(e.target === e.currentTarget) onClose() }}>\r\n <div className=\"modal\" ref={modalRef} style={{left:`${pos.x}px`, top:`${pos.y}px`}}>\r\n <div className=\"modal-header\" ref={headerRef} onMouseDown={startDrag} onTouchStart={startDrag}>\r\n <div className=\"modal-title\">{title}</div>\r\n <button className=\"modal-close\" onClick={onClose}>×</button>\r\n </div>\r\n <div className=\"modal-body\">{children}</div>\r\n </div>\r\n </div>\r\n )\r\n}\r\n"],"names":["Modal","isOpen","onClose","title","children","modalRef","useRef","headerRef","pos","setPos","useState","x","y","draggingRef","offsetRef","useEffect","el","current","innerWidth","innerHeight","window","rect","getBoundingClientRect","width","height","onMove","e","touches","preventDefault","clientX","clientY","desiredX","desiredY","maxX","maxY","clampedX","Math","min","max","clampedY","onUp","addEventListener","passive","removeEventListener","startDrag","document","body","style","userSelect","left","top","onUpCleanup","prev","React","createElement","className","onMouseDown","target","currentTarget","ref","onTouchStart","onClick"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "trotl-modal",
3
+ "version": "1.0.1",
4
+ "description": "Modal UI",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.cjs",
13
+ "default": "./dist/index.mjs"
14
+ },
15
+ "./dist/index.css": "./dist/index.css"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "dist/index.css"
20
+ ],
21
+ "scripts": {
22
+ "dev": "vite --config vite.dev.config.js",
23
+ "build": "rollup -c rollup.config.js",
24
+ "prepublishOnly": "npm run build"
25
+ },
26
+ "peerDependencies": {
27
+ "react": ">=17",
28
+ "react-dom": ">=17"
29
+ },
30
+ "author": "Dejan Trtnik",
31
+ "license": "MIT",
32
+ "type": "module",
33
+ "devDependencies": {
34
+ "@babel/preset-react": "^7.28.5",
35
+ "@eslint/js": "^9.39.1",
36
+ "@rollup/plugin-babel": "^6.1.0",
37
+ "@rollup/plugin-commonjs": "^29.0.0",
38
+ "@rollup/plugin-node-resolve": "^16.0.3",
39
+ "@types/react": "^19.2.5",
40
+ "@types/react-dom": "^19.2.3",
41
+ "@vitejs/plugin-react": "^5.1.1",
42
+ "eslint": "^9.39.1",
43
+ "eslint-plugin-react-hooks": "^7.0.1",
44
+ "eslint-plugin-react-refresh": "^0.4.24",
45
+ "globals": "^16.5.0",
46
+ "rollup": "^4.53.3",
47
+ "rollup-plugin-peer-deps-external": "^2.2.4",
48
+ "rollup-plugin-postcss": "^4.0.2",
49
+ "vite": "^7.2.4"
50
+ },
51
+ "dependencies": {},
52
+ "keywords": [
53
+ "react",
54
+ "ui-library"
55
+ ]
56
+ }