mini-style 1.0.0__py3-none-any.whl

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.
mini_style/__init__.py ADDED
@@ -0,0 +1,280 @@
1
+ import webview
2
+ import os
3
+ import json
4
+
5
+ __author__ = "Скворцов Сергей Александрович"
6
+ __version__ = "1.0.0"
7
+ __license__ = "MIT (non-commercial) / Commercial License Required"
8
+ __github__ = "https://github.com/serskvortsov386/mini-style"
9
+
10
+ class App:
11
+ """
12
+ Mini-Style App - создание стильных десктопных приложений на Python
13
+
14
+ Автор: Скворцов Сергей Александрович
15
+ GitHub: https://github.com/serskvortsov386/
16
+ Лицензия: MIT для некоммерческого использования.
17
+ Для коммерческого использования требуется лицензия.
18
+ """
19
+
20
+ def __init__(self, title="Mini-Style App", width=480, height=650, resizable=False):
21
+ """
22
+ Инициализация приложения
23
+
24
+ Args:
25
+ title (str): Заголовок окна
26
+ width (int): Ширина окна
27
+ height (int): Высота окна
28
+ resizable (bool): Можно ли изменять размер окна
29
+ """
30
+ self.title = title
31
+ self.width = width
32
+ self.height = height
33
+ self.resizable = resizable
34
+ self.elements = []
35
+ self.window = None
36
+ self.callbacks = {}
37
+ self._element_counter = 0
38
+
39
+ def _add_element(self, html_code):
40
+ """Добавление HTML-элемента в интерфейс"""
41
+ self.elements.append(html_code)
42
+
43
+ def _generate_id(self, prefix="el"):
44
+ """Генерация уникального ID для элементов"""
45
+ self._element_counter += 1
46
+ return f"{prefix}_{self._element_counter}"
47
+
48
+ def add_label(self, text, label_id=None):
49
+ """
50
+ Добавление текстовой метки
51
+
52
+ Args:
53
+ text (str): Текст метки
54
+ label_id (str, optional): ID элемента
55
+ """
56
+ if not label_id:
57
+ label_id = self._generate_id("label")
58
+ self._add_element(f'<div id="{label_id}" class="ms-label">{text}</div>')
59
+ return label_id
60
+
61
+ def add_button(self, text="Кнопка", action=None, button_id=None):
62
+ """
63
+ Добавление стильной кнопки
64
+
65
+ Args:
66
+ text (str): Текст на кнопке
67
+ action (callable): Функция при нажатии
68
+ button_id (str, optional): ID элемента
69
+ """
70
+ if not button_id:
71
+ button_id = self._generate_id("btn")
72
+ if action:
73
+ self.callbacks[button_id] = action
74
+ self._add_element(f'''
75
+ <button id="{button_id}" class="ms-btn-primary" onclick="pywebview.api.trigger(\'{button_id}\')">
76
+ {text}
77
+ </button>
78
+ ''')
79
+ return button_id
80
+
81
+ def add_danger_button(self, text="Удалить", action=None, button_id=None):
82
+ """
83
+ Добавление кнопки для опасных действий (красная)
84
+
85
+ Args:
86
+ text (str): Текст на кнопке
87
+ action (callable): Функция при нажатии
88
+ button_id (str, optional): ID элемента
89
+ """
90
+ if not button_id:
91
+ button_id = self._generate_id("danger_btn")
92
+ if action:
93
+ self.callbacks[button_id] = action
94
+ self._add_element(f'''
95
+ <button id="{button_id}" class="ms-btn-danger" onclick="pywebview.api.trigger(\'{button_id}\')">
96
+ {text}
97
+ </button>
98
+ ''')
99
+ return button_id
100
+
101
+ def add_input(self, placeholder="Введите данные...", input_id=None, default_value=""):
102
+ """
103
+ Добавление поля ввода
104
+
105
+ Args:
106
+ placeholder (str): Плейсхолдер
107
+ input_id (str, optional): ID элемента
108
+ default_value (str): Значение по умолчанию
109
+ """
110
+ if not input_id:
111
+ input_id = self._generate_id("input")
112
+ self._add_element(f'''
113
+ <input type="text" id="{input_id}" class="ms-input" placeholder="{placeholder}" value="{default_value}">
114
+ ''')
115
+ return input_id
116
+
117
+ def add_progress(self, percentage=0, progress_id=None):
118
+ """
119
+ Добавление прогресс-бара
120
+
121
+ Args:
122
+ percentage (int): Начальное значение (0-100)
123
+ progress_id (str, optional): ID элемента
124
+ """
125
+ if not progress_id:
126
+ progress_id = self._generate_id("progress")
127
+ percentage = max(0, min(100, percentage))
128
+ self._add_element(f"""
129
+ <div class="ms-progress-bg">
130
+ <div id="{progress_id}" class="ms-progress-fill" style="width: {percentage}%;"></div>
131
+ </div>
132
+ """)
133
+ return progress_id
134
+
135
+ def add_slider(self, min_val=0, max_val=100, default=50, slider_id=None, action=None):
136
+ """
137
+ Добавление слайдера (ползунка)
138
+
139
+ Args:
140
+ min_val (int): Минимальное значение
141
+ max_val (int): Максимальное значение
142
+ default (int): Значение по умолчанию
143
+ slider_id (str, optional): ID элемента
144
+ action (callable): Функция при изменении значения
145
+ """
146
+ if not slider_id:
147
+ slider_id = self._generate_id("slider")
148
+ if action:
149
+ self.callbacks[slider_id] = action
150
+ self._add_element(f"""
151
+ <div class="ms-slider-wrapper">
152
+ <input type="range" id="{slider_id}" min="{min_val}" max="{max_val}" value="{default}" class="ms-slider"
153
+ oninput="document.getElementById('{slider_id}_val').innerText = this.value; pywebview.api.trigger_slider('{slider_id}', this.value)">
154
+ <span id="{slider_id}_val" class="ms-slider-val">{default}</span>
155
+ </div>
156
+ """)
157
+ return slider_id
158
+
159
+ def add_card(self, content_func=None):
160
+ """
161
+ Добавление карточки для группировки элементов
162
+
163
+ Args:
164
+ content_func (callable): Функция, добавляющая элементы внутрь карточки
165
+ """
166
+ self._add_element('<div class="ms-card">')
167
+ if content_func:
168
+ content_func()
169
+ self._add_element('</div>')
170
+
171
+ # --- Функции управления в реальном времени ---
172
+ def set_progress(self, progress_id, percentage):
173
+ """
174
+ Обновление прогресс-бара в реальном времени
175
+
176
+ Args:
177
+ progress_id (str): ID прогресс-бара
178
+ percentage (int): Новое значение (0-100)
179
+ """
180
+ if self.window:
181
+ percentage = max(0, min(100, percentage))
182
+ self.window.evaluate_js(f"document.getElementById('{progress_id}').style.width = '{percentage}%';")
183
+
184
+ def get_input_value(self, input_id):
185
+ """
186
+ Получение значения из поля ввода
187
+
188
+ Args:
189
+ input_id (str): ID поля ввода
190
+
191
+ Returns:
192
+ str: Значение из поля
193
+ """
194
+ if self.window:
195
+ return self.window.evaluate_js(f"document.getElementById('{input_id}').value")
196
+ return ""
197
+
198
+ def set_input_value(self, input_id, value):
199
+ """
200
+ Установка значения в поле ввода
201
+
202
+ Args:
203
+ input_id (str): ID поля ввода
204
+ value (str): Новое значение
205
+ """
206
+ if self.window:
207
+ self.window.evaluate_js(f"document.getElementById('{input_id}').value = '{value}';")
208
+
209
+ def set_label_text(self, label_id, text):
210
+ """
211
+ Изменение текста метки
212
+
213
+ Args:
214
+ label_id (str): ID метки
215
+ text (str): Новый текст
216
+ """
217
+ if self.window:
218
+ self.window.evaluate_js(f"document.getElementById('{label_id}').textContent = '{text}';")
219
+
220
+ def run(self):
221
+ """
222
+ Запуск приложения
223
+ """
224
+ current_dir = os.path.dirname(__file__)
225
+ with open(os.path.join(current_dir, 'theme.css'), 'r', encoding='utf-8') as f:
226
+ css_content = f.read()
227
+
228
+ body_elements = "\n".join(self.elements)
229
+
230
+ # Полный HTML-шаблон
231
+ html_template = f"""
232
+ <!DOCTYPE html>
233
+ <html>
234
+ <head>
235
+ <meta charset="UTF-8">
236
+ <style>{css_content}</style>
237
+ </head>
238
+ <body>
239
+ <div class="ms-header">
240
+ <div class="ms-title">{self.title}</div>
241
+ <button class="ms-close-btn" onclick="pywebview.api.close_app()" title="Закрыть"></button>
242
+ </div>
243
+ <div class="ms-container">
244
+ {body_elements}
245
+ </div>
246
+ </body>
247
+ </html>
248
+ """
249
+
250
+ class BridgeAPI:
251
+ def __init__(self, app_instance):
252
+ self.app = app_instance
253
+
254
+ def trigger(self, cmd_id):
255
+ if cmd_id in self.app.callbacks:
256
+ try:
257
+ self.app.callbacks[cmd_id]()
258
+ except Exception as e:
259
+ print(f"[Mini-Style] Ошибка в callback {cmd_id}: {e}")
260
+
261
+ def trigger_slider(self, slider_id, value):
262
+ if slider_id in self.app.callbacks:
263
+ try:
264
+ self.app.callbacks[slider_id](int(value))
265
+ except Exception as e:
266
+ print(f"[Mini-Style] Ошибка в slider callback {slider_id}: {e}")
267
+
268
+ def close_app(self):
269
+ self.app.window.destroy()
270
+
271
+ self.window = webview.create_window(
272
+ self.title,
273
+ html=html_template,
274
+ width=self.width,
275
+ height=self.height,
276
+ frameless=True,
277
+ easy_drag=True,
278
+ resizable=self.resizable
279
+ )
280
+ webview.start(BridgeAPI(self))
mini_style/theme.css ADDED
@@ -0,0 +1,184 @@
1
+ /* Базовые настройки и красивый скроллбар */
2
+ * {
3
+ box-sizing: border-box;
4
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
5
+ }
6
+ ::-webkit-scrollbar {
7
+ width: 6px;
8
+ }
9
+ ::-webkit-scrollbar-thumb {
10
+ background: #1f2833;
11
+ border-radius: 10px;
12
+ }
13
+
14
+ body {
15
+ background-color: #0b0c10;
16
+ color: #c5c6c7;
17
+ font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
18
+ margin: 0;
19
+ padding: 0;
20
+ display: flex;
21
+ flex-direction: column;
22
+ height: 100vh;
23
+ overflow: hidden;
24
+ user-select: none;
25
+ }
26
+
27
+ /* 1. Кастомная верхняя панель (Header) */
28
+ .ms-header {
29
+ background-color: #1f2833;
30
+ height: 35px;
31
+ display: flex;
32
+ justify-content: space-between;
33
+ align-items: center;
34
+ padding: 0 15px;
35
+ border-bottom: 1px solid rgba(255,255,255,0.05);
36
+ }
37
+ .ms-title {
38
+ font-size: 12px;
39
+ font-weight: 600;
40
+ letter-spacing: 1px;
41
+ color: #66fcf1;
42
+ text-transform: uppercase;
43
+ }
44
+ .ms-close-btn {
45
+ width: 20px;
46
+ height: 20px;
47
+ border-radius: 50%;
48
+ background-color: #ff5f56;
49
+ border: none;
50
+ cursor: pointer;
51
+ }
52
+ .ms-close-btn:hover {
53
+ background-color: #ff3b30;
54
+ box-shadow: 0 0 8px #ff3b30;
55
+ }
56
+
57
+ /* Основной контейнер для контента */
58
+ .ms-container {
59
+ padding: 25px;
60
+ display: flex;
61
+ flex-direction: column;
62
+ gap: 20px;
63
+ overflow-y: auto;
64
+ flex-grow: 1;
65
+ }
66
+
67
+ /* 2. Карточка (Фрейм для группировки) */
68
+ .ms-card {
69
+ background: linear-gradient(145deg, #151922, #11141a);
70
+ border: 1px solid rgba(255, 255, 255, 0.03);
71
+ border-radius: 16px;
72
+ padding: 20px;
73
+ display: flex;
74
+ flex-direction: column;
75
+ gap: 15px;
76
+ box-shadow: 0 10px 30px rgba(0,0,0,0.5);
77
+ }
78
+
79
+ /* Текст внутри интерфейса */
80
+ .ms-label {
81
+ font-size: 14px;
82
+ color: #909296;
83
+ font-weight: 500;
84
+ }
85
+
86
+ /* 3. Кнопка: Платиновый Градиент */
87
+ .ms-btn-primary {
88
+ background: linear-gradient(135deg, #ffffff 0%, #e2e8f0 60%, #cbd5e1 100%);
89
+ color: #0f172a;
90
+ border: none;
91
+ padding: 12px 24px;
92
+ font-size: 14px;
93
+ font-weight: 700;
94
+ border-radius: 10px;
95
+ cursor: pointer;
96
+ box-shadow: 0 4px 14px rgba(255,255,255,0.1);
97
+ width: fit-content;
98
+ }
99
+ .ms-btn-primary:hover {
100
+ transform: translateY(-2px);
101
+ box-shadow: 0 6px 20px rgba(255,255,255,0.2);
102
+ filter: brightness(1.05);
103
+ }
104
+
105
+ /* 4. Кнопка «Удалить» (Винно-красная) */
106
+ .ms-btn-danger {
107
+ background: linear-gradient(135deg, #631c1c 0%, #4a1414 100%);
108
+ color: #fca5a5;
109
+ border: 1px solid #7f1d1d;
110
+ padding: 12px 24px;
111
+ font-size: 14px;
112
+ font-weight: 600;
113
+ border-radius: 10px;
114
+ cursor: pointer;
115
+ width: fit-content;
116
+ }
117
+ .ms-btn-danger:hover {
118
+ transform: translateY(-2px);
119
+ background: linear-gradient(135deg, #991b1b 0%, #7f1d1d 100%);
120
+ box-shadow: 0 0 15px rgba(239, 68, 68, 0.4);
121
+ color: white;
122
+ }
123
+
124
+ /* 5. Поле ввода */
125
+ .ms-input {
126
+ background-color: #1f2833;
127
+ border: 1px solid #45a29e;
128
+ color: #ffffff;
129
+ padding: 12px 16px;
130
+ font-size: 14px;
131
+ border-radius: 8px;
132
+ outline: none;
133
+ width: 100%;
134
+ }
135
+ .ms-input:focus {
136
+ border-color: #00f5d4;
137
+ box-shadow: 0 0 10px rgba(0, 245, 212, 0.2);
138
+ }
139
+
140
+ /* 6. Прогресс-бар */
141
+ .ms-progress-bg {
142
+ width: 100%;
143
+ background-color: #151922;
144
+ border-radius: 8px;
145
+ padding: 3px;
146
+ border: 1px solid rgba(255,255,255,0.02);
147
+ }
148
+ .ms-progress-fill {
149
+ height: 10px;
150
+ background: linear-gradient(90deg, #00f5d4, #00bbf9);
151
+ border-radius: 6px;
152
+ box-shadow: 0 0 10px rgba(0, 245, 212, 0.5);
153
+ }
154
+
155
+ /* 7. Ползунок (Слайдер) */
156
+ .ms-slider-wrapper {
157
+ display: flex;
158
+ align-items: center;
159
+ gap: 15px;
160
+ }
161
+ .ms-slider {
162
+ -webkit-appearance: none;
163
+ width: 100%;
164
+ height: 6px;
165
+ border-radius: 5px;
166
+ background: #1f2833;
167
+ outline: none;
168
+ }
169
+ .ms-slider::-webkit-slider-thumb {
170
+ -webkit-appearance: none;
171
+ appearance: none;
172
+ width: 16px;
173
+ height: 16px;
174
+ border-radius: 50%;
175
+ background: #00f5d4;
176
+ cursor: pointer;
177
+ box-shadow: 0 0 8px #00f5d4;
178
+ }
179
+ .ms-slider-val {
180
+ font-size: 12px;
181
+ font-weight: bold;
182
+ color: #00f5d4;
183
+ min-width: 30px;
184
+ }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Скворцов Сергей Александрович
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,131 @@
1
+ Metadata-Version: 2.1
2
+ Name: mini-style
3
+ Version: 1.0.0
4
+ Summary: A minimalist, opinionated GUI library for Python powered by web technologies
5
+ Author-email: Скворцов Сергей Александрович <ser.skvortsov.386@gmail.com>
6
+ Project-URL: Homepage, https://github.com/serskvortsov386/mini-style
7
+ Project-URL: Repository, https://github.com/serskvortsov386/mini-style
8
+ Project-URL: Issues, https://github.com/serskvortsov386/mini-style/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: Other/Proprietary License
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.7
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: pywebview >=5.0
16
+
17
+ # Mini-Style
18
+
19
+ > Превращает скучные Python-скрипты в стильные приложения премиум-уровня.
20
+
21
+ ---
22
+
23
+ ## 👨‍💻 Автор
24
+
25
+ **Скворцов Сергей Александрович**
26
+ * **GitHub:** [serskvortsov386](https://github.com/serskvortsov386/)
27
+ * **Другие проекты:** [rusmenu](https://github.com/serskvortsov386/rusmenu/)
28
+
29
+ ---
30
+
31
+ ## 📋 Лицензия
32
+
33
+ Это программное обеспечение распространяется по лицензии **MIT для некоммерческого использования**.
34
+
35
+ ⚠️ **Для коммерческого использования требуется приобретение лицензии.**
36
+ По вопросам лицензирования: ser.skvortsov.386@gmail.com
37
+
38
+ ---
39
+
40
+ ## 📦 Установка
41
+
42
+ ```bash
43
+ pip install mini-style
44
+ ```
45
+
46
+ ---
47
+
48
+ ## 🚀 Быстрый старт
49
+
50
+ ```python
51
+ import mini_style
52
+
53
+ app = mini_style.App(title="Моё приложение", width=480, height=650)
54
+
55
+ app.add_label("Привет, мир!")
56
+ app.add_button("Нажми меня", action=lambda: print("Кнопка нажата!"))
57
+
58
+ app.run()
59
+ ```
60
+
61
+ ---
62
+
63
+ ## ✨ Возможности
64
+
65
+ * **Минималистичный дизайн** — современный темный интерфейс «из коробки».
66
+ * **Безрамочное окно** — выглядит как профессиональное премиум-приложение.
67
+ * **Готовые компоненты** — кнопки, поля ввода, слайдеры, прогресс-бары.
68
+ * **Живое обновление** — динамическое управление интерфейсом в реальном времени.
69
+ * **Чистый Python** — вся логика пишется только на Python, без использования HTML/CSS.
70
+
71
+ ---
72
+
73
+ ## 🧩 Компоненты
74
+
75
+ | Метод | Описание |
76
+ | :--- | :--- |
77
+ | `add_label(text)` | Текстовая метка |
78
+ | `add_button(text, action)` | Стильная стандартная кнопка |
79
+ | `add_danger_button(text, action)` | Кнопка для опасных/акцентных действий |
80
+ | `add_input(placeholder, input_id)` | Поле ввода текста |
81
+ | `add_progress(percentage, progress_id)` | Прогресс-бар (шкала загрузки) |
82
+ | `add_slider(min, max, default, slider_id, action)` | Ползунок для выбора значений |
83
+
84
+ ---
85
+
86
+ ## ⚙️ Управление в реальном времени
87
+
88
+ ```python
89
+ # Обновить прогресс-бар
90
+ app.set_progress("my_progress", 75)
91
+
92
+ # Получить значение из поля ввода
93
+ value = app.get_input_value("my_input")
94
+ ```
95
+
96
+ ---
97
+
98
+ ## 💡 Пример использования
99
+
100
+ ```python
101
+ import mini_style
102
+ import time
103
+
104
+ app = mini_style.App(title="Система Оптимизации", width=450, height=600)
105
+
106
+ def start_optimization():
107
+ name = app.get_input_value("username_field")
108
+ print(f"Запуск для пользователя: {name}")
109
+
110
+ for percent in range(0, 101, 20):
111
+ app.set_progress("bar_clean", percent)
112
+ time.sleep(0.15)
113
+
114
+ app.add_label("Введите ваше имя:")
115
+ app.add_input(placeholder="Имя...", input_id="username_field")
116
+ app.add_progress(percentage=0, progress_id="bar_clean")
117
+ app.add_button("Запустить", action=start_optimization)
118
+
119
+ app.run()
120
+ ```
121
+
122
+ ---
123
+
124
+ ## 🤝 Поддержка
125
+
126
+ Если вам понравился проект, поддержите автора:
127
+ * ⭐ Поставьте звезду на **GitHub**
128
+ * 🔔 Подпишитесь на обновления профиля
129
+ * 💼 Приобретите **коммерческую лицензию** для своих бизнес-проектов
130
+
131
+ © 2026 Скворцов Сергей Александрович · ser.skvortsov.386@gmail.com
@@ -0,0 +1,7 @@
1
+ mini_style/__init__.py,sha256=FPL4ZIOPy64fKhJq91WsNRTV6VrpYu1LqFYIEPpj8hM,10780
2
+ mini_style/theme.css,sha256=dmCUJ93rDOACmV4D8QraPPeUjufpGhLlQp5MGF4WAe8,4426
3
+ mini_style-1.0.0.dist-info/LICENSE,sha256=MsTcLL-rOR2EHDykJp2nXF7DZ644dhvZZtEf51ePxNo,1132
4
+ mini_style-1.0.0.dist-info/METADATA,sha256=VZevUQLsamYzg0ZSh6MtryP37kY1MHcVxF3H9BfA_S0,4813
5
+ mini_style-1.0.0.dist-info/WHEEL,sha256=BNRMDyzLkkcmlv0J8ppDQkk2VED33SesJDynr9ED1gc,91
6
+ mini_style-1.0.0.dist-info/top_level.txt,sha256=8VnILv-mxjGTcCD8d1zCv5J5lVKCKrY7G9ACkIzcdY4,11
7
+ mini_style-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.3.4)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ mini_style