st-copy 0.1.0__tar.gz
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.
- st_copy-0.1.0/.gitignore +162 -0
- st_copy-0.1.0/LICENSE +21 -0
- st_copy-0.1.0/PKG-INFO +73 -0
- st_copy-0.1.0/README.md +63 -0
- st_copy-0.1.0/pyproject.toml +84 -0
- st_copy-0.1.0/st_copy/__init__.py +74 -0
- st_copy-0.1.0/st_copy/frontend/dist/assets/index-DbUWWM0T.js +72 -0
- st_copy-0.1.0/st_copy/frontend/dist/assets/index-rlKbC8Ov.css +1 -0
- st_copy-0.1.0/st_copy/frontend/dist/index.html +13 -0
- st_copy-0.1.0/st_copy/py.typed +0 -0
st_copy-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
### IDE
|
|
2
|
+
.idea
|
|
3
|
+
|
|
4
|
+
### Cache and Data
|
|
5
|
+
chroma_db/
|
|
6
|
+
docs/
|
|
7
|
+
.langgraph_api/
|
|
8
|
+
|
|
9
|
+
### Python template
|
|
10
|
+
# Byte-compiled / optimized / DLL files
|
|
11
|
+
__pycache__/
|
|
12
|
+
*.py[cod]
|
|
13
|
+
*$py.class
|
|
14
|
+
|
|
15
|
+
# C extensions
|
|
16
|
+
*.so
|
|
17
|
+
|
|
18
|
+
# Distribution / packaging
|
|
19
|
+
.Python
|
|
20
|
+
build/
|
|
21
|
+
develop-eggs/
|
|
22
|
+
dist/
|
|
23
|
+
downloads/
|
|
24
|
+
eggs/
|
|
25
|
+
.eggs/
|
|
26
|
+
lib/
|
|
27
|
+
lib64/
|
|
28
|
+
parts/
|
|
29
|
+
sdist/
|
|
30
|
+
var/
|
|
31
|
+
wheels/
|
|
32
|
+
share/python-wheels/
|
|
33
|
+
*.egg-info/
|
|
34
|
+
.installed.cfg
|
|
35
|
+
*.egg
|
|
36
|
+
MANIFEST
|
|
37
|
+
|
|
38
|
+
# PyInstaller
|
|
39
|
+
# Usually these files are written by a python script from a template
|
|
40
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
41
|
+
*.manifest
|
|
42
|
+
*.spec
|
|
43
|
+
|
|
44
|
+
# Installer logs
|
|
45
|
+
pip-log.txt
|
|
46
|
+
pip-delete-this-directory.txt
|
|
47
|
+
|
|
48
|
+
# Unit / coverage reports
|
|
49
|
+
htmlcov/
|
|
50
|
+
.tox/
|
|
51
|
+
.nox/
|
|
52
|
+
.coverage
|
|
53
|
+
.coverage.*
|
|
54
|
+
.cache
|
|
55
|
+
nosetests.xml
|
|
56
|
+
coverage.xml
|
|
57
|
+
*.cover
|
|
58
|
+
*.py,cover
|
|
59
|
+
.hypothesis/
|
|
60
|
+
.pytest_cache/
|
|
61
|
+
cover/
|
|
62
|
+
|
|
63
|
+
# Translations
|
|
64
|
+
*.mo
|
|
65
|
+
*.pot
|
|
66
|
+
|
|
67
|
+
# Django stuff:
|
|
68
|
+
*.log
|
|
69
|
+
local_settings.py
|
|
70
|
+
db.sqlite3
|
|
71
|
+
db.sqlite3-journal
|
|
72
|
+
|
|
73
|
+
# Flask stuff:
|
|
74
|
+
instance/
|
|
75
|
+
.webassets-cache
|
|
76
|
+
|
|
77
|
+
# Scrapy stuff:
|
|
78
|
+
.scrapy
|
|
79
|
+
|
|
80
|
+
# Sphinx documentation
|
|
81
|
+
docs/_build/
|
|
82
|
+
|
|
83
|
+
# PyBuilder
|
|
84
|
+
.pybuilder/
|
|
85
|
+
target/
|
|
86
|
+
|
|
87
|
+
# Jupyter Notebook
|
|
88
|
+
.ipynb_checkpoints
|
|
89
|
+
|
|
90
|
+
# IPython
|
|
91
|
+
profile_default/
|
|
92
|
+
ipython_config.py
|
|
93
|
+
|
|
94
|
+
# pyenv
|
|
95
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
96
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
97
|
+
# .python-version
|
|
98
|
+
|
|
99
|
+
# pipenv
|
|
100
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
101
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
102
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
103
|
+
# install all needed dependencies.
|
|
104
|
+
#Pipfile.lock
|
|
105
|
+
|
|
106
|
+
# poetry
|
|
107
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
108
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
109
|
+
# commonly ignored for libraries.
|
|
110
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
111
|
+
#poetry.lock
|
|
112
|
+
|
|
113
|
+
# pdm
|
|
114
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
115
|
+
#pdm.lock
|
|
116
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
117
|
+
# in version control.
|
|
118
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
119
|
+
.pdm.toml
|
|
120
|
+
|
|
121
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
122
|
+
__pypackages__/
|
|
123
|
+
|
|
124
|
+
# Celery stuff
|
|
125
|
+
celerybeat-schedule
|
|
126
|
+
celerybeat.pid
|
|
127
|
+
|
|
128
|
+
# SageMath parsed files
|
|
129
|
+
*.sage.py
|
|
130
|
+
|
|
131
|
+
# Environments
|
|
132
|
+
.env
|
|
133
|
+
.venv
|
|
134
|
+
env/
|
|
135
|
+
venv/
|
|
136
|
+
ENV/
|
|
137
|
+
env.bak/
|
|
138
|
+
venv.bak/
|
|
139
|
+
|
|
140
|
+
# Spyder project settings
|
|
141
|
+
.spyderproject
|
|
142
|
+
.spyproject
|
|
143
|
+
|
|
144
|
+
# Rope project settings
|
|
145
|
+
.ropeproject
|
|
146
|
+
|
|
147
|
+
# mkdocs documentation
|
|
148
|
+
/site
|
|
149
|
+
|
|
150
|
+
# mypy
|
|
151
|
+
.mypy_cache/
|
|
152
|
+
.dmypy.json
|
|
153
|
+
dmypy.json
|
|
154
|
+
|
|
155
|
+
# Pyre type checker
|
|
156
|
+
.pyre/
|
|
157
|
+
|
|
158
|
+
# pytype static type analyzer
|
|
159
|
+
.pytype/
|
|
160
|
+
|
|
161
|
+
# Cython debug symbols
|
|
162
|
+
cython_debug/
|
st_copy-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Aleksandr Filippov
|
|
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.
|
st_copy-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: st-copy
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Streamlit copy‑to‑clipboard button component
|
|
5
|
+
Author-email: Aleksandr Filippov <alex-feel.saga628@passmail.com>
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
Requires-Dist: streamlit>=0.79.0
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# Streamlit Copy-to-Clipboard Button Component
|
|
12
|
+
|
|
13
|
+
[](https://st-copy.streamlit.app/) [](https://conventionalcommits.org) [](https://github.com/alex-feel/st-copy/blob/main/pyproject.toml) [](https://github.com/alex-feel/st-copy/blob/main/LICENSE)
|
|
14
|
+
|
|
15
|
+
A **tiny, theme‑aware Streamlit component** that adds a one‑click "copy-to-clipboard" button to your app — perfect for the chat UI, URLs or any other text the user might need to copy.
|
|
16
|
+
|
|
17
|
+
## ✨ Features
|
|
18
|
+
- **Streamlit theme aware**: Adapts icon colour & tooltip style automatically; works in both light _and_ dark themes.
|
|
19
|
+
- **Tiny, zero‑dep frontend**: A single 2-KB bundle → instant load. No extra JS libraries.
|
|
20
|
+
- **Two icon styles**: Google *Material Symbols* (default) or the native Streamlit code‑block icon.
|
|
21
|
+
- **Custom tooltip & "Copied!" label**: Localised UI in one line.
|
|
22
|
+
- **Keyboard‑friendly**: Fully focusable, press **Enter/Space** to copy.
|
|
23
|
+
- **No server round‑trip**: Uses the browser Clipboard API, returns `True/False` to Python instantly.
|
|
24
|
+
- **Hot‑reload during development**: Set an env‑var and work against your Vite dev‑server with no wheel rebuilds.
|
|
25
|
+
|
|
26
|
+
## 🔧 Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install st-copy
|
|
30
|
+
````
|
|
31
|
+
|
|
32
|
+
## ⚡ Quick start
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
import streamlit as st
|
|
36
|
+
from st_copy import copy_button
|
|
37
|
+
|
|
38
|
+
st.title('Minimal demo')
|
|
39
|
+
|
|
40
|
+
copy_button('Hello, Streamlit!') # one line – that's it 🎉
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Run your script:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
streamlit run app.py
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 🛠 API
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
def copy_button(
|
|
53
|
+
text: str,
|
|
54
|
+
*,
|
|
55
|
+
icon: Literal['material_symbols', 'st'] = 'material_symbols',
|
|
56
|
+
tooltip: str = 'Copy',
|
|
57
|
+
copied_label: str = 'Copied!',
|
|
58
|
+
key: Optional[str] = None,
|
|
59
|
+
) -> Optional[bool]:
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
| Parameter | Type / Default | Description |
|
|
63
|
+
| -------------- | ------------------------------------------------------------------- |------------------------------------------------------------------------------------------------------------------|
|
|
64
|
+
| `text` | **str** | Text placed on the user’s clipboard. |
|
|
65
|
+
| `icon` | `Literal['material_symbols', 'st']`<br>default `'material_symbols'` | Icon style: Google Material **content\_copy** (`material_symbols`) or Streamlit’s native code‑block icon (`st`). |
|
|
66
|
+
| `tooltip` | **str**, default `'Copy'` | Tooltip shown on hover/focus. |
|
|
67
|
+
| `copied_label` | **str**, default `'Copied!'` | Small label displayed for ~1 s after a successful copy. |
|
|
68
|
+
| `key` | **str \| None**, default `None` | Unique component key; if omitted a random UUIDv4 is generated. |
|
|
69
|
+
| **Returns** | **bool \| None** | `True` – copy succeeded; `False` – Clipboard API failed; `None` – button not clicked yet. |
|
|
70
|
+
|
|
71
|
+
## 🎨 Examples
|
|
72
|
+
|
|
73
|
+
See [examples/app.py](./examples/app.py) for a chat‑style demo that showcases every argument and the deployed version at https://st-copy.streamlit.app/.
|
st_copy-0.1.0/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Streamlit Copy-to-Clipboard Button Component
|
|
2
|
+
|
|
3
|
+
[](https://st-copy.streamlit.app/) [](https://conventionalcommits.org) [](https://github.com/alex-feel/st-copy/blob/main/pyproject.toml) [](https://github.com/alex-feel/st-copy/blob/main/LICENSE)
|
|
4
|
+
|
|
5
|
+
A **tiny, theme‑aware Streamlit component** that adds a one‑click "copy-to-clipboard" button to your app — perfect for the chat UI, URLs or any other text the user might need to copy.
|
|
6
|
+
|
|
7
|
+
## ✨ Features
|
|
8
|
+
- **Streamlit theme aware**: Adapts icon colour & tooltip style automatically; works in both light _and_ dark themes.
|
|
9
|
+
- **Tiny, zero‑dep frontend**: A single 2-KB bundle → instant load. No extra JS libraries.
|
|
10
|
+
- **Two icon styles**: Google *Material Symbols* (default) or the native Streamlit code‑block icon.
|
|
11
|
+
- **Custom tooltip & "Copied!" label**: Localised UI in one line.
|
|
12
|
+
- **Keyboard‑friendly**: Fully focusable, press **Enter/Space** to copy.
|
|
13
|
+
- **No server round‑trip**: Uses the browser Clipboard API, returns `True/False` to Python instantly.
|
|
14
|
+
- **Hot‑reload during development**: Set an env‑var and work against your Vite dev‑server with no wheel rebuilds.
|
|
15
|
+
|
|
16
|
+
## 🔧 Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install st-copy
|
|
20
|
+
````
|
|
21
|
+
|
|
22
|
+
## ⚡ Quick start
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
import streamlit as st
|
|
26
|
+
from st_copy import copy_button
|
|
27
|
+
|
|
28
|
+
st.title('Minimal demo')
|
|
29
|
+
|
|
30
|
+
copy_button('Hello, Streamlit!') # one line – that's it 🎉
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Run your script:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
streamlit run app.py
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 🛠 API
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
def copy_button(
|
|
43
|
+
text: str,
|
|
44
|
+
*,
|
|
45
|
+
icon: Literal['material_symbols', 'st'] = 'material_symbols',
|
|
46
|
+
tooltip: str = 'Copy',
|
|
47
|
+
copied_label: str = 'Copied!',
|
|
48
|
+
key: Optional[str] = None,
|
|
49
|
+
) -> Optional[bool]:
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
| Parameter | Type / Default | Description |
|
|
53
|
+
| -------------- | ------------------------------------------------------------------- |------------------------------------------------------------------------------------------------------------------|
|
|
54
|
+
| `text` | **str** | Text placed on the user’s clipboard. |
|
|
55
|
+
| `icon` | `Literal['material_symbols', 'st']`<br>default `'material_symbols'` | Icon style: Google Material **content\_copy** (`material_symbols`) or Streamlit’s native code‑block icon (`st`). |
|
|
56
|
+
| `tooltip` | **str**, default `'Copy'` | Tooltip shown on hover/focus. |
|
|
57
|
+
| `copied_label` | **str**, default `'Copied!'` | Small label displayed for ~1 s after a successful copy. |
|
|
58
|
+
| `key` | **str \| None**, default `None` | Unique component key; if omitted a random UUIDv4 is generated. |
|
|
59
|
+
| **Returns** | **bool \| None** | `True` – copy succeeded; `False` – Clipboard API failed; `None` – button not clicked yet. |
|
|
60
|
+
|
|
61
|
+
## 🎨 Examples
|
|
62
|
+
|
|
63
|
+
See [examples/app.py](./examples/app.py) for a chat‑style demo that showcases every argument and the deployed version at https://st-copy.streamlit.app/.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "st-copy"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Streamlit copy‑to‑clipboard button component"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{ name = "Aleksandr Filippov", email = "alex-feel.saga628@passmail.com" }]
|
|
7
|
+
requires-python = ">=3.9"
|
|
8
|
+
# Streamlit version/features info
|
|
9
|
+
# components.v1.declare_component: 0.63.0 (custom‑component API; https://discuss.streamlit.io/t/introducing-streamlit-components/6115)
|
|
10
|
+
# theme data in `theme` arg: 0.79.0 (first theming release (light/dark, colours); https://docs.streamlit.io/develop/quick-reference/release-notes/2021#version-0790)
|
|
11
|
+
# (optional) st.chat_message – only in the demo app: 1.24.0 (chat elements introduced; https://docs.streamlit.io/1.24.0/develop/api-reference/chat/st.chat_message)
|
|
12
|
+
# (optional) streamlit.testing.v1.AppTest – only in test‑suite: 1.28.0 (AppTest helper first documented; https://docs.streamlit.io/1.28.0/develop/api-reference/app-testing/st.testing.v1.apptest)
|
|
13
|
+
dependencies = ["streamlit>=0.79.0"]
|
|
14
|
+
|
|
15
|
+
[build-system]
|
|
16
|
+
requires = ["hatchling>=1.27", "hatch-build-scripts"]
|
|
17
|
+
build-backend = "hatchling.build"
|
|
18
|
+
|
|
19
|
+
[tool.hatch.build]
|
|
20
|
+
sources = ["src"]
|
|
21
|
+
dev-mode-dirs = ["src"]
|
|
22
|
+
include = ["src/st_copy/frontend/dist/**", "src/st_copy/py.typed"]
|
|
23
|
+
exclude = [
|
|
24
|
+
"src/st_copy/frontend/node_modules/**",
|
|
25
|
+
"src/st_copy/frontend/src/**",
|
|
26
|
+
"src/st_copy/frontend/.gitignore",
|
|
27
|
+
"src/st_copy/frontend/*.css",
|
|
28
|
+
"src/st_copy/frontend/*.ts",
|
|
29
|
+
"src/st_copy/frontend/*.tsx",
|
|
30
|
+
"src/st_copy/frontend/*.js",
|
|
31
|
+
"src/st_copy/frontend/*.json",
|
|
32
|
+
"src/st_copy/frontend/*.html",
|
|
33
|
+
"src/st_copy/frontend/*.md",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[[tool.hatch.build.targets.sdist.hooks.build-scripts.scripts]]
|
|
37
|
+
work_dir = "src/st_copy/frontend"
|
|
38
|
+
out_dir = "src/st_copy/frontend/dist"
|
|
39
|
+
artifacts = []
|
|
40
|
+
commands = [
|
|
41
|
+
"npm install --no-audit --no-fund",
|
|
42
|
+
"npm run build",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[tool.hatch.build.targets.sdist]
|
|
46
|
+
packages = ["src/st_copy"]
|
|
47
|
+
ignore-vcs = true
|
|
48
|
+
|
|
49
|
+
[tool.hatch.build.targets.wheel]
|
|
50
|
+
packages = ["src/st_copy"]
|
|
51
|
+
|
|
52
|
+
[dependency-groups]
|
|
53
|
+
dev = [
|
|
54
|
+
"streamlit>=0.79.0",
|
|
55
|
+
"pre-commit>=4.2.0",
|
|
56
|
+
"pytest>=8.3.5",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
[tool.ruff]
|
|
60
|
+
# General settings
|
|
61
|
+
target-version = "py39"
|
|
62
|
+
line-length = 127
|
|
63
|
+
|
|
64
|
+
[tool.ruff.lint]
|
|
65
|
+
# Enable rule groups
|
|
66
|
+
select = [
|
|
67
|
+
"E", "W", "F", # basic Flake8
|
|
68
|
+
"I", # isort (import order)
|
|
69
|
+
"Q", # flake8‑quotes
|
|
70
|
+
"SIM", # flake8‑simplify
|
|
71
|
+
"N", # pep8‑naming
|
|
72
|
+
"ARG", # flake8‑unused‑arguments
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
# flake8‑quotes: prefer single quotes
|
|
76
|
+
[tool.ruff.lint.flake8-quotes]
|
|
77
|
+
inline-quotes = "single"
|
|
78
|
+
multiline-quotes = "single"
|
|
79
|
+
docstring-quotes = "double"
|
|
80
|
+
|
|
81
|
+
# isort subsection
|
|
82
|
+
[tool.ruff.lint.isort]
|
|
83
|
+
known-first-party = ["st_copy"]
|
|
84
|
+
force-single-line = true
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import uuid
|
|
3
|
+
from typing import Literal
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
import streamlit.components.v1 as components
|
|
7
|
+
|
|
8
|
+
RAW = os.getenv('ST_COPY_DEV_SERVER')
|
|
9
|
+
DEV_URL = (RAW or '').strip()
|
|
10
|
+
|
|
11
|
+
if DEV_URL:
|
|
12
|
+
if DEV_URL.lower() in {'auto', 'default'}:
|
|
13
|
+
DEV_URL = 'http://localhost:3001'
|
|
14
|
+
component = components.declare_component(
|
|
15
|
+
'st_copy',
|
|
16
|
+
url=DEV_URL
|
|
17
|
+
)
|
|
18
|
+
else:
|
|
19
|
+
parent_dir = os.path.dirname(os.path.abspath(__file__))
|
|
20
|
+
frontend_dir = os.path.join(parent_dir, 'frontend', 'dist')
|
|
21
|
+
component = components.declare_component(
|
|
22
|
+
'st_copy',
|
|
23
|
+
path=frontend_dir
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def copy_button(
|
|
28
|
+
text: str,
|
|
29
|
+
*,
|
|
30
|
+
icon: Literal['material_symbols', 'st'] = 'material_symbols',
|
|
31
|
+
tooltip: str = 'Copy',
|
|
32
|
+
copied_label: str = 'Copied!',
|
|
33
|
+
key: Optional[str] = None,
|
|
34
|
+
) -> Optional[bool]:
|
|
35
|
+
"""
|
|
36
|
+
Render a copy‑to‑clipboard button.
|
|
37
|
+
|
|
38
|
+
Parameters:
|
|
39
|
+
text : str
|
|
40
|
+
The text that will be placed on the user’s clipboard.
|
|
41
|
+
|
|
42
|
+
icon : {'material_symbols', 'st'}, default 'material_symbols'
|
|
43
|
+
Which icon to show:
|
|
44
|
+
|
|
45
|
+
* 'material_symbols' – Google Material content_copy glyph
|
|
46
|
+
* 'st' – the native Streamlit code‑block icon
|
|
47
|
+
|
|
48
|
+
tooltip : str, default 'Copy'
|
|
49
|
+
Tooltip shown on hover / focus.
|
|
50
|
+
|
|
51
|
+
copied_label : str, default 'Copied!'
|
|
52
|
+
Small text that appears next to the icon for ~1 second after a
|
|
53
|
+
successful copy operation.
|
|
54
|
+
|
|
55
|
+
key : str | None, optional
|
|
56
|
+
Streamlit component key. If None, a random
|
|
57
|
+
`uuid.uuid4()` string is generated.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
bool | None
|
|
61
|
+
* `True` – text copied successfully.
|
|
62
|
+
* `False` – browser blocked the Clipboard API.
|
|
63
|
+
* `None` – the button has not been clicked yet.
|
|
64
|
+
"""
|
|
65
|
+
if key is None:
|
|
66
|
+
key = str(uuid.uuid4())
|
|
67
|
+
|
|
68
|
+
return component(
|
|
69
|
+
text=text,
|
|
70
|
+
icon=icon,
|
|
71
|
+
tooltip=tooltip,
|
|
72
|
+
copied_label=copied_label,
|
|
73
|
+
key=key,
|
|
74
|
+
)
|