# 🎉 **CustomCTkDialog**

### *Beautiful dialogs, alerts, and native file pickers for CustomTkinter — powered by a lightweight Electron executable.*

<p align="center">
  <img src="https://img.shields.io/badge/python-3.11%2B-blue?style=for-the-badge" />
  <img src="https://img.shields.io/badge/customtkinter-5.2%2B-green?style=for-the-badge" />
  <img src="https://img.shields.io/badge/platform-windows-lightgray?style=for-the-badge" />
</p>

## ✨ Features

✔️ **Modern dialogs** that blend perfectly with CustomTkinter
✔️ **Custom alert boxes** with multiple alert types
✔️ **Native-feeling folder picker** powered by a lightweight Electron executable
✔️ Plug-and-play — no configuration required
✔️ Clean, Pythonic API
✔️ Automatic runtime download — no large `.exe` included in the package

## 🚀 Installation

```
pip install CustomCTkDialog
```

## 📦 Project Structure

```
CustomCTkDialog/
│
├── CustomCTkDialog/              # Python package
│   ├── __init__.py
│   ├── electron_loader.py        # Downloads Electron runtime on import
│   ├── dialog_main.py            # Main dialog system
│
├── js-folder-picker/             # JS workspace (developers only)
│   ├── folder-picker.js
│   ├── package.json
│   └── build scripts
│
├── example/
│   └── app.py                    # Example usage
│
├── README.md
└── pyproject.toml
```

📝 **Note:**
The `js-folder-picker/` folder is **not included** in the published Python package.

## 🔄 Runtime Logic with `electron_loader`

Previously, the Python package included a **large bundled `.exe`**, which made the package heavy and slowed down installation.

Now, `CustomCTkDialog` uses a **dynamic runtime loader**:

1. When the package is imported, `electron_loader.ensure_electron()` is executed automatically.
2. It checks if the **Electron-based folder picker** is already present.
3. If not, the user is prompted:

```
Some necessary files are required for CustomCTkDialog.folder_picker to work.
Download these files now? (Y/n):
```

4. If the user agrees (default Yes), the **ZIP distribution** of the folder picker is downloaded from the **GitHub releases page**.
5. The ZIP is extracted into the package folder.
6. Subsequent imports detect the runtime and **do not re-download**, making the process fast after the first run.

✅ Advantages:

* Lightweight PyPI package (no 100MB `.exe` inside)
* Automatic setup for users
* Updates can be released via GitHub without republishing the Python package

## 🧪 Example Usage

```python
from CustomCTkDialog import Dialog, folder_picker, file_picker, AlertType

# Prompt input
try:
    name = Dialog.prompt("Enter your name:", default_text="Alice")
    print("Prompt returned:", name)
except ValueError as error:
    print("Prompt canceled:", error)

# Confirm dialog
confirmed = Dialog.confirm("Do you want to continue?")
print("Confirm returned:", confirmed)

# Alert
Dialog.alert(AlertType.SUCCESS, "Test Alert", "This is a success alert!")

# File picker
files = file_picker(initialdir="D:/")
print("Selected files:", files)

# Folder picker (Electron runtime downloads automatically on first run)
directories = folder_picker(initialdir="D:/")
print("Selected folders:", directories)
```

## 🧰 API Reference

### `Dialog` class

| Method      | Description                                                   |
| ----------- | ------------------------------------------------------------- |
| `prompt()`  | Shows an input dialog, returns string or raises `ValueError`. |
| `confirm()` | Shows a yes/no dialog, returns boolean.                       |
| `alert()`   | Shows an alert with `AlertType`.                              |

### `folder_picker()`

Opens a native folder picker. Downloads the Electron runtime automatically if missing.

```python
paths = folder_picker()
```

### `file_picker()`

Wrapper around `tkinter.filedialog.askopenfilenames`.

```python
files = file_picker()
```

## 🛠 Development

### 1. Install Python dependencies

```
pip install -r requirements.txt
```

### 2. Run the example app

```
python example/app.py
```

### 3. Rebuild the JS folder-picker (developers only)

```
cd js-folder-picker
npm install
npm run build
```

* Upload the resulting ZIP to a **GitHub release**.
* `electron_loader` will download it automatically when the package is imported.

## 📦 Build & Publish (maintainers only)

### Build the package

```
python -m build --no-isolation
```

### Upload to TestPyPI

```
python -m twine upload --verbose --repository testpypi dist/*
```

## 🔒 TestPyPI & PyPI Upload Permissions

To maintain the integrity and security of the package, only the **project owner** and designated **maintainers** have permission to upload new versions to:

* **TestPyPI**
* **PyPI**

This ensures that releases are carefully reviewed and that users receive safe, consistent updates.

If you are not currently a maintainer, you will not be able to upload new versions, even if you have:

* Your own API token
* Your own TestPyPI or PyPI account
* A local project with the same package name

### How to become a maintainer

If you would like to assist with publishing or maintaining the project:

1. Open an issue on GitHub expressing your interest.
2. Contact the project owner to request maintainer access.
3. Once approved, you will be added under **Settings → Collaborators** and can use your API token to upload new releases.

We appreciate contributions from the community and want to ensure that all releases remain reliable and secure for everyone.

## 🤝 Contributing

* Pull requests welcome!
* For JS folder-picker improvements: modify `/js-folder-picker/` and rebuild the ZIP.
* Push new releases to GitHub so `electron_loader` can fetch them automatically.

## 📝 License

### **Creative Commons Attribution–NonCommercial 4.0 (CC BY-NC 4.0)**