elismasilva commited on
Commit
c2578be
·
verified ·
1 Parent(s): d6a1c6a

Upload folder using huggingface_hub

Browse files
.gitignore ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .eggs/
2
+ dist/
3
+ *.pyc
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+ __tmp/*
8
+ *.pyi
9
+ .mypycache
10
+ .ruff_cache
11
+ node_modules
12
+ backend/**/templates/
README.md CHANGED
@@ -1,12 +1,254 @@
1
- ---
2
- title: Gradio Taggrouphelper
3
- emoji: 😻
4
- colorFrom: pink
5
- colorTo: red
6
- sdk: gradio
7
- sdk_version: 5.37.0
8
- app_file: app.py
9
- pinned: false
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ tags: [gradio-custom-component, ]
3
+ title: gradio_taggrouphelper
4
+ short_description: A fast prompt generator based on tagged words
5
+ colorFrom: blue
6
+ colorTo: yellow
7
+ sdk: gradio
8
+ pinned: false
9
+ app_file: space.py
10
+ ---
11
+
12
+ # `gradio_taggrouphelper`
13
+ <img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.1%20-%20orange">
14
+
15
+ A fast text generator based on tagged words
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install gradio_taggrouphelper
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ```python
26
+ #
27
+ # demo/app.py
28
+ #
29
+ import gradio as gr
30
+ from gradio_taggrouphelper import TagGroupHelper
31
+
32
+ # Example data structure for the tags and groups
33
+ TAG_DATA = {
34
+ "Quality": [
35
+ "best quality", "masterpiece", "high resolution", "4k", "8k",
36
+ "sharp focus", "detailed", "photorealistic"
37
+ ],
38
+ "Lighting": [
39
+ "cinematic lighting", "volumetric lighting", "god rays",
40
+ "golden hour", "studio lighting", "dramatic lighting"
41
+ ],
42
+ "Style": [
43
+ "anime style", "oil painting", "concept art", "fantasy",
44
+ "steampunk", "vaporwave", "line art"
45
+ ],
46
+ "Negative Prompts": [
47
+ "blurry", "noisy", "low resolution", "low quality", "watermark",
48
+ "text", "bad anatomy", "extra limbs", "disfigured"
49
+ ]
50
+ }
51
+
52
+ with gr.Blocks() as demo:
53
+ gr.Markdown("# Prompt Tag Helper Demo")
54
+ gr.Markdown("Click on the tags below to add them to the prompt textboxes.")
55
+
56
+ with gr.Row():
57
+ with gr.Column(scale=2): # Give more space to the textboxes
58
+ # Create the target Textbox and give it a unique `elem_id`.
59
+ positive_prompt_box = gr.Textbox(
60
+ label="Positive Prompt",
61
+ placeholder="Click tags from 'Prompt Keywords' to add them here...",
62
+ lines=5,
63
+ elem_id="positive-prompt-textbox" # This ID must be unique
64
+ )
65
+ negative_prompt_box = gr.Textbox(
66
+ label="Negative Prompt",
67
+ placeholder="Click tags from 'Negative Keywords' to add them here...",
68
+ lines=5,
69
+ elem_id="negative-prompt-textbox" # This ID must be unique
70
+ )
71
+
72
+ with gr.Column(scale=1): # Give less space to the helpers
73
+ # Create an instance of the TagGroupHelper for the Positive Prompt box.
74
+ TagGroupHelper(
75
+ label="Positive Prompt Keywords",
76
+ value={k: v for k, v in TAG_DATA.items() if "Negative" not in k},
77
+ target_textbox_id="positive-prompt-textbox"
78
+ )
79
+
80
+ # Create another instance for the Negative Prompt box.
81
+ TagGroupHelper(
82
+ label="Negative Prompt Keywords",
83
+ value={"Negative Prompts": TAG_DATA["Negative Prompts"]},
84
+ target_textbox_id="negative-prompt-textbox",
85
+ min_width=150
86
+ )
87
+
88
+ if __name__ == '__main__':
89
+ demo.launch()
90
+ ```
91
+
92
+ ## `TagGroupHelper`
93
+
94
+ ### Initialization
95
+
96
+ <table>
97
+ <thead>
98
+ <tr>
99
+ <th align="left">name</th>
100
+ <th align="left" style="width: 25%;">type</th>
101
+ <th align="left">default</th>
102
+ <th align="left">description</th>
103
+ </tr>
104
+ </thead>
105
+ <tbody>
106
+ <tr>
107
+ <td align="left"><code>value</code></td>
108
+ <td align="left" style="width: 25%;">
109
+
110
+ ```python
111
+ typing.Optional[typing.Dict[str, typing.List[str]]][
112
+ typing.Dict[str, typing.List[str]][
113
+ str, typing.List[str][str]
114
+ ],
115
+ None,
116
+ ]
117
+ ```
118
+
119
+ </td>
120
+ <td align="left"><code>None</code></td>
121
+ <td align="left">A dictionary where keys are group names and values are lists of tags.</td>
122
+ </tr>
123
+
124
+ <tr>
125
+ <td align="left"><code>target_textbox_id</code></td>
126
+ <td align="left" style="width: 25%;">
127
+
128
+ ```python
129
+ str | None
130
+ ```
131
+
132
+ </td>
133
+ <td align="left"><code>None</code></td>
134
+ <td align="left">The `elem_id` of the `gr.Textbox` component to target. Required.</td>
135
+ </tr>
136
+
137
+ <tr>
138
+ <td align="left"><code>label</code></td>
139
+ <td align="left" style="width: 25%;">
140
+
141
+ ```python
142
+ str | None
143
+ ```
144
+
145
+ </td>
146
+ <td align="left"><code>None</code></td>
147
+ <td align="left">The label for this component, displayed above the groups.</td>
148
+ </tr>
149
+
150
+ <tr>
151
+ <td align="left"><code>visible</code></td>
152
+ <td align="left" style="width: 25%;">
153
+
154
+ ```python
155
+ bool
156
+ ```
157
+
158
+ </td>
159
+ <td align="left"><code>True</code></td>
160
+ <td align="left">If False, the component will be hidden.</td>
161
+ </tr>
162
+
163
+ <tr>
164
+ <td align="left"><code>elem_id</code></td>
165
+ <td align="left" style="width: 25%;">
166
+
167
+ ```python
168
+ str | None
169
+ ```
170
+
171
+ </td>
172
+ <td align="left"><code>None</code></td>
173
+ <td align="left">An optional string that is assigned as the id of this component in the HTML DOM.</td>
174
+ </tr>
175
+
176
+ <tr>
177
+ <td align="left"><code>scale</code></td>
178
+ <td align="left" style="width: 25%;">
179
+
180
+ ```python
181
+ int | None
182
+ ```
183
+
184
+ </td>
185
+ <td align="left"><code>None</code></td>
186
+ <td align="left">The relative size of the component compared to others in a `gr.Row` or `gr.Column`.</td>
187
+ </tr>
188
+
189
+ <tr>
190
+ <td align="left"><code>min_width</code></td>
191
+ <td align="left" style="width: 25%;">
192
+
193
+ ```python
194
+ int | None
195
+ ```
196
+
197
+ </td>
198
+ <td align="left"><code>None</code></td>
199
+ <td align="left">The minimum-width of the component in pixels.</td>
200
+ </tr>
201
+
202
+ <tr>
203
+ <td align="left"><code>container</code></td>
204
+ <td align="left" style="width: 25%;">
205
+
206
+ ```python
207
+ bool
208
+ ```
209
+
210
+ </td>
211
+ <td align="left"><code>True</code></td>
212
+ <td align="left">If False, the component will not be wrapped in a container.</td>
213
+ </tr>
214
+
215
+ <tr>
216
+ <td align="left"><code>elem_classes</code></td>
217
+ <td align="left" style="width: 25%;">
218
+
219
+ ```python
220
+ list[str] | str | None
221
+ ```
222
+
223
+ </td>
224
+ <td align="left"><code>None</code></td>
225
+ <td align="left">An optional list of strings to assign as CSS classes to the component.</td>
226
+ </tr>
227
+ </tbody></table>
228
+
229
+
230
+
231
+
232
+ ### User function
233
+
234
+ The impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both).
235
+
236
+ - When used as an Input, the component only impacts the input signature of the user function.
237
+ - When used as an output, the component only impacts the return signature of the user function.
238
+
239
+ The code snippet below is accurate in cases where the component is used as both an input and an output.
240
+
241
+
242
+
243
+ ```python
244
+ def predict(
245
+ value: Any
246
+ ) -> typing.Optional[typing.Dict[str, typing.List[str]]][
247
+ typing.Dict[str, typing.List[str]][
248
+ str, typing.List[str][str]
249
+ ],
250
+ None,
251
+ ]:
252
+ return value
253
+ ```
254
+
__init__.py ADDED
File without changes
app.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # demo/app.py
3
+ #
4
+ import gradio as gr
5
+ from gradio_taggrouphelper import TagGroupHelper
6
+
7
+ # Example data structure for the tags and groups
8
+ TAG_DATA = {
9
+ "Quality": [
10
+ "best quality", "masterpiece", "high resolution", "4k", "8k",
11
+ "sharp focus", "detailed", "photorealistic"
12
+ ],
13
+ "Lighting": [
14
+ "cinematic lighting", "volumetric lighting", "god rays",
15
+ "golden hour", "studio lighting", "dramatic lighting"
16
+ ],
17
+ "Style": [
18
+ "anime style", "oil painting", "concept art", "fantasy",
19
+ "steampunk", "vaporwave", "line art"
20
+ ],
21
+ "Negative Prompts": [
22
+ "blurry", "noisy", "low resolution", "low quality", "watermark",
23
+ "text", "bad anatomy", "extra limbs", "disfigured"
24
+ ]
25
+ }
26
+
27
+ with gr.Blocks() as demo:
28
+ gr.Markdown("# Prompt Tag Helper Demo")
29
+ gr.Markdown("Click on the tags below to add them to the prompt textboxes.")
30
+
31
+ with gr.Row():
32
+ with gr.Column(scale=2): # Give more space to the textboxes
33
+ # Create the target Textbox and give it a unique `elem_id`.
34
+ positive_prompt_box = gr.Textbox(
35
+ label="Positive Prompt",
36
+ placeholder="Click tags from 'Prompt Keywords' to add them here...",
37
+ lines=5,
38
+ elem_id="positive-prompt-textbox" # This ID must be unique
39
+ )
40
+ negative_prompt_box = gr.Textbox(
41
+ label="Negative Prompt",
42
+ placeholder="Click tags from 'Negative Keywords' to add them here...",
43
+ lines=5,
44
+ elem_id="negative-prompt-textbox" # This ID must be unique
45
+ )
46
+
47
+ with gr.Column(scale=1): # Give less space to the helpers
48
+ # Create an instance of the TagGroupHelper for the Positive Prompt box.
49
+ TagGroupHelper(
50
+ label="Positive Prompt Keywords",
51
+ value={k: v for k, v in TAG_DATA.items() if "Negative" not in k},
52
+ target_textbox_id="positive-prompt-textbox"
53
+ )
54
+
55
+ # Create another instance for the Negative Prompt box.
56
+ TagGroupHelper(
57
+ label="Negative Prompt Keywords",
58
+ value={"Negative Prompts": TAG_DATA["Negative Prompts"]},
59
+ target_textbox_id="negative-prompt-textbox",
60
+ min_width=150
61
+ )
62
+
63
+ if __name__ == '__main__':
64
+ demo.launch()
css.css ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ html {
2
+ font-family: Inter;
3
+ font-size: 16px;
4
+ font-weight: 400;
5
+ line-height: 1.5;
6
+ -webkit-text-size-adjust: 100%;
7
+ background: #fff;
8
+ color: #323232;
9
+ -webkit-font-smoothing: antialiased;
10
+ -moz-osx-font-smoothing: grayscale;
11
+ text-rendering: optimizeLegibility;
12
+ }
13
+
14
+ :root {
15
+ --space: 1;
16
+ --vspace: calc(var(--space) * 1rem);
17
+ --vspace-0: calc(3 * var(--space) * 1rem);
18
+ --vspace-1: calc(2 * var(--space) * 1rem);
19
+ --vspace-2: calc(1.5 * var(--space) * 1rem);
20
+ --vspace-3: calc(0.5 * var(--space) * 1rem);
21
+ }
22
+
23
+ .app {
24
+ max-width: 748px !important;
25
+ }
26
+
27
+ .prose p {
28
+ margin: var(--vspace) 0;
29
+ line-height: var(--vspace * 2);
30
+ font-size: 1rem;
31
+ }
32
+
33
+ code {
34
+ font-family: "Inconsolata", sans-serif;
35
+ font-size: 16px;
36
+ }
37
+
38
+ h1,
39
+ h1 code {
40
+ font-weight: 400;
41
+ line-height: calc(2.5 / var(--space) * var(--vspace));
42
+ }
43
+
44
+ h1 code {
45
+ background: none;
46
+ border: none;
47
+ letter-spacing: 0.05em;
48
+ padding-bottom: 5px;
49
+ position: relative;
50
+ padding: 0;
51
+ }
52
+
53
+ h2 {
54
+ margin: var(--vspace-1) 0 var(--vspace-2) 0;
55
+ line-height: 1em;
56
+ }
57
+
58
+ h3,
59
+ h3 code {
60
+ margin: var(--vspace-1) 0 var(--vspace-2) 0;
61
+ line-height: 1em;
62
+ }
63
+
64
+ h4,
65
+ h5,
66
+ h6 {
67
+ margin: var(--vspace-3) 0 var(--vspace-3) 0;
68
+ line-height: var(--vspace);
69
+ }
70
+
71
+ .bigtitle,
72
+ h1,
73
+ h1 code {
74
+ font-size: calc(8px * 4.5);
75
+ word-break: break-word;
76
+ }
77
+
78
+ .title,
79
+ h2,
80
+ h2 code {
81
+ font-size: calc(8px * 3.375);
82
+ font-weight: lighter;
83
+ word-break: break-word;
84
+ border: none;
85
+ background: none;
86
+ }
87
+
88
+ .subheading1,
89
+ h3,
90
+ h3 code {
91
+ font-size: calc(8px * 1.8);
92
+ font-weight: 600;
93
+ border: none;
94
+ background: none;
95
+ letter-spacing: 0.1em;
96
+ text-transform: uppercase;
97
+ }
98
+
99
+ h2 code {
100
+ padding: 0;
101
+ position: relative;
102
+ letter-spacing: 0.05em;
103
+ }
104
+
105
+ blockquote {
106
+ font-size: calc(8px * 1.1667);
107
+ font-style: italic;
108
+ line-height: calc(1.1667 * var(--vspace));
109
+ margin: var(--vspace-2) var(--vspace-2);
110
+ }
111
+
112
+ .subheading2,
113
+ h4 {
114
+ font-size: calc(8px * 1.4292);
115
+ text-transform: uppercase;
116
+ font-weight: 600;
117
+ }
118
+
119
+ .subheading3,
120
+ h5 {
121
+ font-size: calc(8px * 1.2917);
122
+ line-height: calc(1.2917 * var(--vspace));
123
+
124
+ font-weight: lighter;
125
+ text-transform: uppercase;
126
+ letter-spacing: 0.15em;
127
+ }
128
+
129
+ h6 {
130
+ font-size: calc(8px * 1.1667);
131
+ font-size: 1.1667em;
132
+ font-weight: normal;
133
+ font-style: italic;
134
+ font-family: "le-monde-livre-classic-byol", serif !important;
135
+ letter-spacing: 0px !important;
136
+ }
137
+
138
+ #start .md > *:first-child {
139
+ margin-top: 0;
140
+ }
141
+
142
+ h2 + h3 {
143
+ margin-top: 0;
144
+ }
145
+
146
+ .md hr {
147
+ border: none;
148
+ border-top: 1px solid var(--block-border-color);
149
+ margin: var(--vspace-2) 0 var(--vspace-2) 0;
150
+ }
151
+ .prose ul {
152
+ margin: var(--vspace-2) 0 var(--vspace-1) 0;
153
+ }
154
+
155
+ .gap {
156
+ gap: 0;
157
+ }
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ gradio_taggrouphelper
space.py ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import gradio as gr
3
+ from app import demo as app
4
+ import os
5
+
6
+ _docs = {'TagGroupHelper': {'description': "A custom component that displays groups of clickable tags to help build prompts.\nWhen a tag is clicked, it's appended to a target Textbox component.\nThis component does not have a submittable value itself.", 'members': {'__init__': {'value': {'type': 'typing.Optional[typing.Dict[str, typing.List[str]]][\n typing.Dict[str, typing.List[str]][\n str, typing.List[str][str]\n ],\n None,\n]', 'default': 'None', 'description': 'A dictionary where keys are group names and values are lists of tags.'}, 'target_textbox_id': {'type': 'str | None', 'default': 'None', 'description': 'The `elem_id` of the `gr.Textbox` component to target. Required.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The label for this component, displayed above the groups.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': 'If False, the component will be hidden.'}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': 'An optional string that is assigned as the id of this component in the HTML DOM.'}, 'scale': {'type': 'int | None', 'default': 'None', 'description': 'The relative size of the component compared to others in a `gr.Row` or `gr.Column`.'}, 'min_width': {'type': 'int | None', 'default': 'None', 'description': 'The minimum-width of the component in pixels.'}, 'container': {'type': 'bool', 'default': 'True', 'description': 'If False, the component will not be wrapped in a container.'}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': 'An optional list of strings to assign as CSS classes to the component.'}}, 'postprocess': {'value': {'type': 'typing.Optional[typing.Dict[str, typing.List[str]]][\n typing.Dict[str, typing.List[str]][\n str, typing.List[str][str]\n ],\n None,\n]', 'description': None}}, 'preprocess': {'return': {'type': 'Any', 'description': None}, 'value': None}}, 'events': {}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'TagGroupHelper': []}}}
7
+
8
+ abs_path = os.path.join(os.path.dirname(__file__), "css.css")
9
+
10
+ with gr.Blocks(
11
+ css=abs_path,
12
+ theme=gr.themes.Default(
13
+ font_mono=[
14
+ gr.themes.GoogleFont("Inconsolata"),
15
+ "monospace",
16
+ ],
17
+ ),
18
+ ) as demo:
19
+ gr.Markdown(
20
+ """
21
+ # `gradio_taggrouphelper`
22
+
23
+ <div style="display: flex; gap: 7px;">
24
+ <img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.1%20-%20orange">
25
+ </div>
26
+
27
+ A fast text generator based on tagged words
28
+ """, elem_classes=["md-custom"], header_links=True)
29
+ app.render()
30
+ gr.Markdown(
31
+ """
32
+ ## Installation
33
+
34
+ ```bash
35
+ pip install gradio_taggrouphelper
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ ```python
41
+ #
42
+ # demo/app.py
43
+ #
44
+ import gradio as gr
45
+ from gradio_taggrouphelper import TagGroupHelper
46
+
47
+ # Example data structure for the tags and groups
48
+ TAG_DATA = {
49
+ "Quality": [
50
+ "best quality", "masterpiece", "high resolution", "4k", "8k",
51
+ "sharp focus", "detailed", "photorealistic"
52
+ ],
53
+ "Lighting": [
54
+ "cinematic lighting", "volumetric lighting", "god rays",
55
+ "golden hour", "studio lighting", "dramatic lighting"
56
+ ],
57
+ "Style": [
58
+ "anime style", "oil painting", "concept art", "fantasy",
59
+ "steampunk", "vaporwave", "line art"
60
+ ],
61
+ "Negative Prompts": [
62
+ "blurry", "noisy", "low resolution", "low quality", "watermark",
63
+ "text", "bad anatomy", "extra limbs", "disfigured"
64
+ ]
65
+ }
66
+
67
+ with gr.Blocks() as demo:
68
+ gr.Markdown("# Prompt Tag Helper Demo")
69
+ gr.Markdown("Click on the tags below to add them to the prompt textboxes.")
70
+
71
+ with gr.Row():
72
+ with gr.Column(scale=2): # Give more space to the textboxes
73
+ # Create the target Textbox and give it a unique `elem_id`.
74
+ positive_prompt_box = gr.Textbox(
75
+ label="Positive Prompt",
76
+ placeholder="Click tags from 'Prompt Keywords' to add them here...",
77
+ lines=5,
78
+ elem_id="positive-prompt-textbox" # This ID must be unique
79
+ )
80
+ negative_prompt_box = gr.Textbox(
81
+ label="Negative Prompt",
82
+ placeholder="Click tags from 'Negative Keywords' to add them here...",
83
+ lines=5,
84
+ elem_id="negative-prompt-textbox" # This ID must be unique
85
+ )
86
+
87
+ with gr.Column(scale=1): # Give less space to the helpers
88
+ # Create an instance of the TagGroupHelper for the Positive Prompt box.
89
+ TagGroupHelper(
90
+ label="Positive Prompt Keywords",
91
+ value={k: v for k, v in TAG_DATA.items() if "Negative" not in k},
92
+ target_textbox_id="positive-prompt-textbox"
93
+ )
94
+
95
+ # Create another instance for the Negative Prompt box.
96
+ TagGroupHelper(
97
+ label="Negative Prompt Keywords",
98
+ value={"Negative Prompts": TAG_DATA["Negative Prompts"]},
99
+ target_textbox_id="negative-prompt-textbox",
100
+ min_width=150
101
+ )
102
+
103
+ if __name__ == '__main__':
104
+ demo.launch()
105
+ ```
106
+ """, elem_classes=["md-custom"], header_links=True)
107
+
108
+
109
+ gr.Markdown("""
110
+ ## `TagGroupHelper`
111
+
112
+ ### Initialization
113
+ """, elem_classes=["md-custom"], header_links=True)
114
+
115
+ gr.ParamViewer(value=_docs["TagGroupHelper"]["members"]["__init__"], linkify=[])
116
+
117
+
118
+
119
+
120
+ gr.Markdown("""
121
+
122
+ ### User function
123
+
124
+ The impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both).
125
+
126
+ - When used as an Input, the component only impacts the input signature of the user function.
127
+ - When used as an output, the component only impacts the return signature of the user function.
128
+
129
+ The code snippet below is accurate in cases where the component is used as both an input and an output.
130
+
131
+
132
+
133
+ ```python
134
+ def predict(
135
+ value: Any
136
+ ) -> typing.Optional[typing.Dict[str, typing.List[str]]][
137
+ typing.Dict[str, typing.List[str]][
138
+ str, typing.List[str][str]
139
+ ],
140
+ None,
141
+ ]:
142
+ return value
143
+ ```
144
+ """, elem_classes=["md-custom", "TagGroupHelper-user-fn"], header_links=True)
145
+
146
+
147
+
148
+
149
+ demo.load(None, js=r"""function() {
150
+ const refs = {};
151
+ const user_fn_refs = {
152
+ TagGroupHelper: [], };
153
+ requestAnimationFrame(() => {
154
+
155
+ Object.entries(user_fn_refs).forEach(([key, refs]) => {
156
+ if (refs.length > 0) {
157
+ const el = document.querySelector(`.${key}-user-fn`);
158
+ if (!el) return;
159
+ refs.forEach(ref => {
160
+ el.innerHTML = el.innerHTML.replace(
161
+ new RegExp("\\b"+ref+"\\b", "g"),
162
+ `<a href="#h-${ref.toLowerCase()}">${ref}</a>`
163
+ );
164
+ })
165
+ }
166
+ })
167
+
168
+ Object.entries(refs).forEach(([key, refs]) => {
169
+ if (refs.length > 0) {
170
+ const el = document.querySelector(`.${key}`);
171
+ if (!el) return;
172
+ refs.forEach(ref => {
173
+ el.innerHTML = el.innerHTML.replace(
174
+ new RegExp("\\b"+ref+"\\b", "g"),
175
+ `<a href="#h-${ref.toLowerCase()}">${ref}</a>`
176
+ );
177
+ })
178
+ }
179
+ })
180
+ })
181
+ }
182
+
183
+ """)
184
+
185
+ demo.launch()
src/.gitignore ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .eggs/
2
+ dist/
3
+ *.pyc
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+ __tmp/*
8
+ *.pyi
9
+ .mypycache
10
+ .ruff_cache
11
+ node_modules
12
+ backend/**/templates/
src/README.md ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ tags: [gradio-custom-component, ]
3
+ title: gradio_taggrouphelper
4
+ short_description: A fast prompt generator based on tagged words
5
+ colorFrom: blue
6
+ colorTo: yellow
7
+ sdk: gradio
8
+ pinned: false
9
+ app_file: space.py
10
+ ---
11
+
12
+ # `gradio_taggrouphelper`
13
+ <img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.1%20-%20orange">
14
+
15
+ A fast text generator based on tagged words
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install gradio_taggrouphelper
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ```python
26
+ #
27
+ # demo/app.py
28
+ #
29
+ import gradio as gr
30
+ from gradio_taggrouphelper import TagGroupHelper
31
+
32
+ # Example data structure for the tags and groups
33
+ TAG_DATA = {
34
+ "Quality": [
35
+ "best quality", "masterpiece", "high resolution", "4k", "8k",
36
+ "sharp focus", "detailed", "photorealistic"
37
+ ],
38
+ "Lighting": [
39
+ "cinematic lighting", "volumetric lighting", "god rays",
40
+ "golden hour", "studio lighting", "dramatic lighting"
41
+ ],
42
+ "Style": [
43
+ "anime style", "oil painting", "concept art", "fantasy",
44
+ "steampunk", "vaporwave", "line art"
45
+ ],
46
+ "Negative Prompts": [
47
+ "blurry", "noisy", "low resolution", "low quality", "watermark",
48
+ "text", "bad anatomy", "extra limbs", "disfigured"
49
+ ]
50
+ }
51
+
52
+ with gr.Blocks() as demo:
53
+ gr.Markdown("# Prompt Tag Helper Demo")
54
+ gr.Markdown("Click on the tags below to add them to the prompt textboxes.")
55
+
56
+ with gr.Row():
57
+ with gr.Column(scale=2): # Give more space to the textboxes
58
+ # Create the target Textbox and give it a unique `elem_id`.
59
+ positive_prompt_box = gr.Textbox(
60
+ label="Positive Prompt",
61
+ placeholder="Click tags from 'Prompt Keywords' to add them here...",
62
+ lines=5,
63
+ elem_id="positive-prompt-textbox" # This ID must be unique
64
+ )
65
+ negative_prompt_box = gr.Textbox(
66
+ label="Negative Prompt",
67
+ placeholder="Click tags from 'Negative Keywords' to add them here...",
68
+ lines=5,
69
+ elem_id="negative-prompt-textbox" # This ID must be unique
70
+ )
71
+
72
+ with gr.Column(scale=1): # Give less space to the helpers
73
+ # Create an instance of the TagGroupHelper for the Positive Prompt box.
74
+ TagGroupHelper(
75
+ label="Positive Prompt Keywords",
76
+ value={k: v for k, v in TAG_DATA.items() if "Negative" not in k},
77
+ target_textbox_id="positive-prompt-textbox"
78
+ )
79
+
80
+ # Create another instance for the Negative Prompt box.
81
+ TagGroupHelper(
82
+ label="Negative Prompt Keywords",
83
+ value={"Negative Prompts": TAG_DATA["Negative Prompts"]},
84
+ target_textbox_id="negative-prompt-textbox",
85
+ min_width=150
86
+ )
87
+
88
+ if __name__ == '__main__':
89
+ demo.launch()
90
+ ```
91
+
92
+ ## `TagGroupHelper`
93
+
94
+ ### Initialization
95
+
96
+ <table>
97
+ <thead>
98
+ <tr>
99
+ <th align="left">name</th>
100
+ <th align="left" style="width: 25%;">type</th>
101
+ <th align="left">default</th>
102
+ <th align="left">description</th>
103
+ </tr>
104
+ </thead>
105
+ <tbody>
106
+ <tr>
107
+ <td align="left"><code>value</code></td>
108
+ <td align="left" style="width: 25%;">
109
+
110
+ ```python
111
+ typing.Optional[typing.Dict[str, typing.List[str]]][
112
+ typing.Dict[str, typing.List[str]][
113
+ str, typing.List[str][str]
114
+ ],
115
+ None,
116
+ ]
117
+ ```
118
+
119
+ </td>
120
+ <td align="left"><code>None</code></td>
121
+ <td align="left">A dictionary where keys are group names and values are lists of tags.</td>
122
+ </tr>
123
+
124
+ <tr>
125
+ <td align="left"><code>target_textbox_id</code></td>
126
+ <td align="left" style="width: 25%;">
127
+
128
+ ```python
129
+ str | None
130
+ ```
131
+
132
+ </td>
133
+ <td align="left"><code>None</code></td>
134
+ <td align="left">The `elem_id` of the `gr.Textbox` component to target. Required.</td>
135
+ </tr>
136
+
137
+ <tr>
138
+ <td align="left"><code>label</code></td>
139
+ <td align="left" style="width: 25%;">
140
+
141
+ ```python
142
+ str | None
143
+ ```
144
+
145
+ </td>
146
+ <td align="left"><code>None</code></td>
147
+ <td align="left">The label for this component, displayed above the groups.</td>
148
+ </tr>
149
+
150
+ <tr>
151
+ <td align="left"><code>visible</code></td>
152
+ <td align="left" style="width: 25%;">
153
+
154
+ ```python
155
+ bool
156
+ ```
157
+
158
+ </td>
159
+ <td align="left"><code>True</code></td>
160
+ <td align="left">If False, the component will be hidden.</td>
161
+ </tr>
162
+
163
+ <tr>
164
+ <td align="left"><code>elem_id</code></td>
165
+ <td align="left" style="width: 25%;">
166
+
167
+ ```python
168
+ str | None
169
+ ```
170
+
171
+ </td>
172
+ <td align="left"><code>None</code></td>
173
+ <td align="left">An optional string that is assigned as the id of this component in the HTML DOM.</td>
174
+ </tr>
175
+
176
+ <tr>
177
+ <td align="left"><code>scale</code></td>
178
+ <td align="left" style="width: 25%;">
179
+
180
+ ```python
181
+ int | None
182
+ ```
183
+
184
+ </td>
185
+ <td align="left"><code>None</code></td>
186
+ <td align="left">The relative size of the component compared to others in a `gr.Row` or `gr.Column`.</td>
187
+ </tr>
188
+
189
+ <tr>
190
+ <td align="left"><code>min_width</code></td>
191
+ <td align="left" style="width: 25%;">
192
+
193
+ ```python
194
+ int | None
195
+ ```
196
+
197
+ </td>
198
+ <td align="left"><code>None</code></td>
199
+ <td align="left">The minimum-width of the component in pixels.</td>
200
+ </tr>
201
+
202
+ <tr>
203
+ <td align="left"><code>container</code></td>
204
+ <td align="left" style="width: 25%;">
205
+
206
+ ```python
207
+ bool
208
+ ```
209
+
210
+ </td>
211
+ <td align="left"><code>True</code></td>
212
+ <td align="left">If False, the component will not be wrapped in a container.</td>
213
+ </tr>
214
+
215
+ <tr>
216
+ <td align="left"><code>elem_classes</code></td>
217
+ <td align="left" style="width: 25%;">
218
+
219
+ ```python
220
+ list[str] | str | None
221
+ ```
222
+
223
+ </td>
224
+ <td align="left"><code>None</code></td>
225
+ <td align="left">An optional list of strings to assign as CSS classes to the component.</td>
226
+ </tr>
227
+ </tbody></table>
228
+
229
+
230
+
231
+
232
+ ### User function
233
+
234
+ The impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both).
235
+
236
+ - When used as an Input, the component only impacts the input signature of the user function.
237
+ - When used as an output, the component only impacts the return signature of the user function.
238
+
239
+ The code snippet below is accurate in cases where the component is used as both an input and an output.
240
+
241
+
242
+
243
+ ```python
244
+ def predict(
245
+ value: Any
246
+ ) -> typing.Optional[typing.Dict[str, typing.List[str]]][
247
+ typing.Dict[str, typing.List[str]][
248
+ str, typing.List[str][str]
249
+ ],
250
+ None,
251
+ ]:
252
+ return value
253
+ ```
254
+
src/backend/gradio_taggrouphelper/__init__.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+
2
+ from .taggrouphelper import TagGroupHelper
3
+
4
+ __all__ = ['TagGroupHelper']
src/backend/gradio_taggrouphelper/taggrouphelper.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+ from gradio.components.base import Component
3
+ from typing import Any, Dict, List
4
+
5
+ class TagGroupHelper(Component):
6
+ """
7
+ A custom component that displays groups of clickable tags to help build prompts.
8
+ When a tag is clicked, it's appended to a target Textbox component.
9
+ This component does not have a submittable value itself.
10
+ """
11
+ EVENTS = []
12
+
13
+ def __init__(
14
+ self,
15
+ value: Dict[str, List[str]] | None = None,
16
+ *,
17
+ target_textbox_id: str | None = None,
18
+ label: str | None = None,
19
+ visible: bool = True,
20
+ elem_id: str | None = None,
21
+ scale: int | None = None,
22
+ min_width: int | None = None,
23
+ container: bool = True,
24
+ elem_classes: list[str] | str | None = None,
25
+
26
+ **kwargs,
27
+ ):
28
+ """
29
+ Initializes the TagGroupHelper component.
30
+
31
+ Parameters:
32
+ value: A dictionary where keys are group names and values are lists of tags.
33
+ target_textbox_id: The `elem_id` of the `gr.Textbox` component to target. Required.
34
+ label: The label for this component, displayed above the groups.
35
+ visible: If False, the component will be hidden.
36
+ elem_id: An optional string that is assigned as the id of this component in the HTML DOM.
37
+ scale: The relative size of the component compared to others in a `gr.Row` or `gr.Column`.
38
+ min_width: The minimum-width of the component in pixels.
39
+ container: If False, the component will not be wrapped in a container.
40
+ elem_classes: An optional list of strings to assign as CSS classes to the component.
41
+ """
42
+ if target_textbox_id is None:
43
+ raise ValueError("The 'target_textbox_id' parameter is required for the TagGroupHelper component.")
44
+
45
+ self.target_textbox_id = target_textbox_id
46
+
47
+ # Call the parent constructor with all the arguments it understands.
48
+ super().__init__(
49
+ label=label,
50
+ visible=visible,
51
+ elem_id=elem_id,
52
+ value=value,
53
+ scale=scale,
54
+ min_width=min_width,
55
+ container=container,
56
+ elem_classes=elem_classes,
57
+ **kwargs,
58
+ )
59
+
60
+ def preprocess(self, payload: Any) -> Any:
61
+ """This component does not process input from the user, so this is a no-op."""
62
+ return None
63
+
64
+ def postprocess(self, value: Dict[str, List[str]] | None) -> Dict[str, List[str]] | None:
65
+ """Passes the tag group dictionary (received as 'value') to the frontend."""
66
+ if value is None:
67
+ return {}
68
+ return value
69
+
70
+ def api_info(self) -> Dict[str, Any]:
71
+ """The API info for the component."""
72
+ return {"type": "object", "description": "A dictionary of string-to-string-list mappings for tag groups."}
73
+
74
+ def example_payload(self) -> Any:
75
+ """Returns an example of the data that this component expects as its value."""
76
+ return {
77
+ "Quality": ["best quality", "high resolution"],
78
+ "Style": ["anime", "photorealistic"],
79
+ "Negative": ["blurry", "noisy"]
80
+ }
src/backend/gradio_taggrouphelper/templates/component/index.js ADDED
The diff for this file is too large to render. See raw diff
 
src/backend/gradio_taggrouphelper/templates/component/style.css ADDED
The diff for this file is too large to render. See raw diff
 
src/backend/gradio_taggrouphelper/templates/example/index.js ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const {
2
+ SvelteComponent: f,
3
+ append_hydration: r,
4
+ attr: u,
5
+ children: o,
6
+ claim_element: h,
7
+ claim_text: g,
8
+ detach: d,
9
+ element: v,
10
+ init: m,
11
+ insert_hydration: y,
12
+ noop: _,
13
+ safe_not_equal: b,
14
+ set_data: w,
15
+ text: E,
16
+ toggle_class: s
17
+ } = window.__gradio__svelte__internal;
18
+ function q(a) {
19
+ let e, n;
20
+ return {
21
+ c() {
22
+ e = v("div"), n = E(
23
+ /*value*/
24
+ a[0]
25
+ ), this.h();
26
+ },
27
+ l(t) {
28
+ e = h(t, "DIV", { class: !0 });
29
+ var l = o(e);
30
+ n = g(
31
+ l,
32
+ /*value*/
33
+ a[0]
34
+ ), l.forEach(d), this.h();
35
+ },
36
+ h() {
37
+ u(e, "class", "svelte-1gecy8w"), s(
38
+ e,
39
+ "table",
40
+ /*type*/
41
+ a[1] === "table"
42
+ ), s(
43
+ e,
44
+ "gallery",
45
+ /*type*/
46
+ a[1] === "gallery"
47
+ ), s(
48
+ e,
49
+ "selected",
50
+ /*selected*/
51
+ a[2]
52
+ );
53
+ },
54
+ m(t, l) {
55
+ y(t, e, l), r(e, n);
56
+ },
57
+ p(t, [l]) {
58
+ l & /*value*/
59
+ 1 && w(
60
+ n,
61
+ /*value*/
62
+ t[0]
63
+ ), l & /*type*/
64
+ 2 && s(
65
+ e,
66
+ "table",
67
+ /*type*/
68
+ t[1] === "table"
69
+ ), l & /*type*/
70
+ 2 && s(
71
+ e,
72
+ "gallery",
73
+ /*type*/
74
+ t[1] === "gallery"
75
+ ), l & /*selected*/
76
+ 4 && s(
77
+ e,
78
+ "selected",
79
+ /*selected*/
80
+ t[2]
81
+ );
82
+ },
83
+ i: _,
84
+ o: _,
85
+ d(t) {
86
+ t && d(e);
87
+ }
88
+ };
89
+ }
90
+ function C(a, e, n) {
91
+ let { value: t } = e, { type: l } = e, { selected: c = !1 } = e;
92
+ return a.$$set = (i) => {
93
+ "value" in i && n(0, t = i.value), "type" in i && n(1, l = i.type), "selected" in i && n(2, c = i.selected);
94
+ }, [t, l, c];
95
+ }
96
+ class D extends f {
97
+ constructor(e) {
98
+ super(), m(this, e, C, q, b, { value: 0, type: 1, selected: 2 });
99
+ }
100
+ }
101
+ export {
102
+ D as default
103
+ };
src/backend/gradio_taggrouphelper/templates/example/style.css ADDED
@@ -0,0 +1 @@
 
 
1
+ .gallery.svelte-1gecy8w{padding:var(--size-1) var(--size-2)}
src/demo/__init__.py ADDED
File without changes
src/demo/app.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # demo/app.py
3
+ #
4
+ import gradio as gr
5
+ from gradio_taggrouphelper import TagGroupHelper
6
+
7
+ # Example data structure for the tags and groups
8
+ TAG_DATA = {
9
+ "Quality": [
10
+ "best quality", "masterpiece", "high resolution", "4k", "8k",
11
+ "sharp focus", "detailed", "photorealistic"
12
+ ],
13
+ "Lighting": [
14
+ "cinematic lighting", "volumetric lighting", "god rays",
15
+ "golden hour", "studio lighting", "dramatic lighting"
16
+ ],
17
+ "Style": [
18
+ "anime style", "oil painting", "concept art", "fantasy",
19
+ "steampunk", "vaporwave", "line art"
20
+ ],
21
+ "Negative Prompts": [
22
+ "blurry", "noisy", "low resolution", "low quality", "watermark",
23
+ "text", "bad anatomy", "extra limbs", "disfigured"
24
+ ]
25
+ }
26
+
27
+ with gr.Blocks() as demo:
28
+ gr.Markdown("# Prompt Tag Helper Demo")
29
+ gr.Markdown("Click on the tags below to add them to the prompt textboxes.")
30
+
31
+ with gr.Row():
32
+ with gr.Column(scale=2): # Give more space to the textboxes
33
+ # Create the target Textbox and give it a unique `elem_id`.
34
+ positive_prompt_box = gr.Textbox(
35
+ label="Positive Prompt",
36
+ placeholder="Click tags from 'Prompt Keywords' to add them here...",
37
+ lines=5,
38
+ elem_id="positive-prompt-textbox" # This ID must be unique
39
+ )
40
+ negative_prompt_box = gr.Textbox(
41
+ label="Negative Prompt",
42
+ placeholder="Click tags from 'Negative Keywords' to add them here...",
43
+ lines=5,
44
+ elem_id="negative-prompt-textbox" # This ID must be unique
45
+ )
46
+
47
+ with gr.Column(scale=1): # Give less space to the helpers
48
+ # Create an instance of the TagGroupHelper for the Positive Prompt box.
49
+ TagGroupHelper(
50
+ label="Positive Prompt Keywords",
51
+ value={k: v for k, v in TAG_DATA.items() if "Negative" not in k},
52
+ target_textbox_id="positive-prompt-textbox"
53
+ )
54
+
55
+ # Create another instance for the Negative Prompt box.
56
+ TagGroupHelper(
57
+ label="Negative Prompt Keywords",
58
+ value={"Negative Prompts": TAG_DATA["Negative Prompts"]},
59
+ target_textbox_id="negative-prompt-textbox",
60
+ min_width=150
61
+ )
62
+
63
+ if __name__ == '__main__':
64
+ demo.launch()
src/demo/css.css ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ html {
2
+ font-family: Inter;
3
+ font-size: 16px;
4
+ font-weight: 400;
5
+ line-height: 1.5;
6
+ -webkit-text-size-adjust: 100%;
7
+ background: #fff;
8
+ color: #323232;
9
+ -webkit-font-smoothing: antialiased;
10
+ -moz-osx-font-smoothing: grayscale;
11
+ text-rendering: optimizeLegibility;
12
+ }
13
+
14
+ :root {
15
+ --space: 1;
16
+ --vspace: calc(var(--space) * 1rem);
17
+ --vspace-0: calc(3 * var(--space) * 1rem);
18
+ --vspace-1: calc(2 * var(--space) * 1rem);
19
+ --vspace-2: calc(1.5 * var(--space) * 1rem);
20
+ --vspace-3: calc(0.5 * var(--space) * 1rem);
21
+ }
22
+
23
+ .app {
24
+ max-width: 748px !important;
25
+ }
26
+
27
+ .prose p {
28
+ margin: var(--vspace) 0;
29
+ line-height: var(--vspace * 2);
30
+ font-size: 1rem;
31
+ }
32
+
33
+ code {
34
+ font-family: "Inconsolata", sans-serif;
35
+ font-size: 16px;
36
+ }
37
+
38
+ h1,
39
+ h1 code {
40
+ font-weight: 400;
41
+ line-height: calc(2.5 / var(--space) * var(--vspace));
42
+ }
43
+
44
+ h1 code {
45
+ background: none;
46
+ border: none;
47
+ letter-spacing: 0.05em;
48
+ padding-bottom: 5px;
49
+ position: relative;
50
+ padding: 0;
51
+ }
52
+
53
+ h2 {
54
+ margin: var(--vspace-1) 0 var(--vspace-2) 0;
55
+ line-height: 1em;
56
+ }
57
+
58
+ h3,
59
+ h3 code {
60
+ margin: var(--vspace-1) 0 var(--vspace-2) 0;
61
+ line-height: 1em;
62
+ }
63
+
64
+ h4,
65
+ h5,
66
+ h6 {
67
+ margin: var(--vspace-3) 0 var(--vspace-3) 0;
68
+ line-height: var(--vspace);
69
+ }
70
+
71
+ .bigtitle,
72
+ h1,
73
+ h1 code {
74
+ font-size: calc(8px * 4.5);
75
+ word-break: break-word;
76
+ }
77
+
78
+ .title,
79
+ h2,
80
+ h2 code {
81
+ font-size: calc(8px * 3.375);
82
+ font-weight: lighter;
83
+ word-break: break-word;
84
+ border: none;
85
+ background: none;
86
+ }
87
+
88
+ .subheading1,
89
+ h3,
90
+ h3 code {
91
+ font-size: calc(8px * 1.8);
92
+ font-weight: 600;
93
+ border: none;
94
+ background: none;
95
+ letter-spacing: 0.1em;
96
+ text-transform: uppercase;
97
+ }
98
+
99
+ h2 code {
100
+ padding: 0;
101
+ position: relative;
102
+ letter-spacing: 0.05em;
103
+ }
104
+
105
+ blockquote {
106
+ font-size: calc(8px * 1.1667);
107
+ font-style: italic;
108
+ line-height: calc(1.1667 * var(--vspace));
109
+ margin: var(--vspace-2) var(--vspace-2);
110
+ }
111
+
112
+ .subheading2,
113
+ h4 {
114
+ font-size: calc(8px * 1.4292);
115
+ text-transform: uppercase;
116
+ font-weight: 600;
117
+ }
118
+
119
+ .subheading3,
120
+ h5 {
121
+ font-size: calc(8px * 1.2917);
122
+ line-height: calc(1.2917 * var(--vspace));
123
+
124
+ font-weight: lighter;
125
+ text-transform: uppercase;
126
+ letter-spacing: 0.15em;
127
+ }
128
+
129
+ h6 {
130
+ font-size: calc(8px * 1.1667);
131
+ font-size: 1.1667em;
132
+ font-weight: normal;
133
+ font-style: italic;
134
+ font-family: "le-monde-livre-classic-byol", serif !important;
135
+ letter-spacing: 0px !important;
136
+ }
137
+
138
+ #start .md > *:first-child {
139
+ margin-top: 0;
140
+ }
141
+
142
+ h2 + h3 {
143
+ margin-top: 0;
144
+ }
145
+
146
+ .md hr {
147
+ border: none;
148
+ border-top: 1px solid var(--block-border-color);
149
+ margin: var(--vspace-2) 0 var(--vspace-2) 0;
150
+ }
151
+ .prose ul {
152
+ margin: var(--vspace-2) 0 var(--vspace-1) 0;
153
+ }
154
+
155
+ .gap {
156
+ gap: 0;
157
+ }
src/demo/requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ gradio_taggrouphelper
src/demo/space.py ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import gradio as gr
3
+ from app import demo as app
4
+ import os
5
+
6
+ _docs = {'TagGroupHelper': {'description': "A custom component that displays groups of clickable tags to help build prompts.\nWhen a tag is clicked, it's appended to a target Textbox component.\nThis component does not have a submittable value itself.", 'members': {'__init__': {'value': {'type': 'typing.Optional[typing.Dict[str, typing.List[str]]][\n typing.Dict[str, typing.List[str]][\n str, typing.List[str][str]\n ],\n None,\n]', 'default': 'None', 'description': 'A dictionary where keys are group names and values are lists of tags.'}, 'target_textbox_id': {'type': 'str | None', 'default': 'None', 'description': 'The `elem_id` of the `gr.Textbox` component to target. Required.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The label for this component, displayed above the groups.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': 'If False, the component will be hidden.'}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': 'An optional string that is assigned as the id of this component in the HTML DOM.'}, 'scale': {'type': 'int | None', 'default': 'None', 'description': 'The relative size of the component compared to others in a `gr.Row` or `gr.Column`.'}, 'min_width': {'type': 'int | None', 'default': 'None', 'description': 'The minimum-width of the component in pixels.'}, 'container': {'type': 'bool', 'default': 'True', 'description': 'If False, the component will not be wrapped in a container.'}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': 'An optional list of strings to assign as CSS classes to the component.'}}, 'postprocess': {'value': {'type': 'typing.Optional[typing.Dict[str, typing.List[str]]][\n typing.Dict[str, typing.List[str]][\n str, typing.List[str][str]\n ],\n None,\n]', 'description': None}}, 'preprocess': {'return': {'type': 'Any', 'description': None}, 'value': None}}, 'events': {}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'TagGroupHelper': []}}}
7
+
8
+ abs_path = os.path.join(os.path.dirname(__file__), "css.css")
9
+
10
+ with gr.Blocks(
11
+ css=abs_path,
12
+ theme=gr.themes.Default(
13
+ font_mono=[
14
+ gr.themes.GoogleFont("Inconsolata"),
15
+ "monospace",
16
+ ],
17
+ ),
18
+ ) as demo:
19
+ gr.Markdown(
20
+ """
21
+ # `gradio_taggrouphelper`
22
+
23
+ <div style="display: flex; gap: 7px;">
24
+ <img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.1%20-%20orange">
25
+ </div>
26
+
27
+ A fast text generator based on tagged words
28
+ """, elem_classes=["md-custom"], header_links=True)
29
+ app.render()
30
+ gr.Markdown(
31
+ """
32
+ ## Installation
33
+
34
+ ```bash
35
+ pip install gradio_taggrouphelper
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ ```python
41
+ #
42
+ # demo/app.py
43
+ #
44
+ import gradio as gr
45
+ from gradio_taggrouphelper import TagGroupHelper
46
+
47
+ # Example data structure for the tags and groups
48
+ TAG_DATA = {
49
+ "Quality": [
50
+ "best quality", "masterpiece", "high resolution", "4k", "8k",
51
+ "sharp focus", "detailed", "photorealistic"
52
+ ],
53
+ "Lighting": [
54
+ "cinematic lighting", "volumetric lighting", "god rays",
55
+ "golden hour", "studio lighting", "dramatic lighting"
56
+ ],
57
+ "Style": [
58
+ "anime style", "oil painting", "concept art", "fantasy",
59
+ "steampunk", "vaporwave", "line art"
60
+ ],
61
+ "Negative Prompts": [
62
+ "blurry", "noisy", "low resolution", "low quality", "watermark",
63
+ "text", "bad anatomy", "extra limbs", "disfigured"
64
+ ]
65
+ }
66
+
67
+ with gr.Blocks() as demo:
68
+ gr.Markdown("# Prompt Tag Helper Demo")
69
+ gr.Markdown("Click on the tags below to add them to the prompt textboxes.")
70
+
71
+ with gr.Row():
72
+ with gr.Column(scale=2): # Give more space to the textboxes
73
+ # Create the target Textbox and give it a unique `elem_id`.
74
+ positive_prompt_box = gr.Textbox(
75
+ label="Positive Prompt",
76
+ placeholder="Click tags from 'Prompt Keywords' to add them here...",
77
+ lines=5,
78
+ elem_id="positive-prompt-textbox" # This ID must be unique
79
+ )
80
+ negative_prompt_box = gr.Textbox(
81
+ label="Negative Prompt",
82
+ placeholder="Click tags from 'Negative Keywords' to add them here...",
83
+ lines=5,
84
+ elem_id="negative-prompt-textbox" # This ID must be unique
85
+ )
86
+
87
+ with gr.Column(scale=1): # Give less space to the helpers
88
+ # Create an instance of the TagGroupHelper for the Positive Prompt box.
89
+ TagGroupHelper(
90
+ label="Positive Prompt Keywords",
91
+ value={k: v for k, v in TAG_DATA.items() if "Negative" not in k},
92
+ target_textbox_id="positive-prompt-textbox"
93
+ )
94
+
95
+ # Create another instance for the Negative Prompt box.
96
+ TagGroupHelper(
97
+ label="Negative Prompt Keywords",
98
+ value={"Negative Prompts": TAG_DATA["Negative Prompts"]},
99
+ target_textbox_id="negative-prompt-textbox",
100
+ min_width=150
101
+ )
102
+
103
+ if __name__ == '__main__':
104
+ demo.launch()
105
+ ```
106
+ """, elem_classes=["md-custom"], header_links=True)
107
+
108
+
109
+ gr.Markdown("""
110
+ ## `TagGroupHelper`
111
+
112
+ ### Initialization
113
+ """, elem_classes=["md-custom"], header_links=True)
114
+
115
+ gr.ParamViewer(value=_docs["TagGroupHelper"]["members"]["__init__"], linkify=[])
116
+
117
+
118
+
119
+
120
+ gr.Markdown("""
121
+
122
+ ### User function
123
+
124
+ The impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both).
125
+
126
+ - When used as an Input, the component only impacts the input signature of the user function.
127
+ - When used as an output, the component only impacts the return signature of the user function.
128
+
129
+ The code snippet below is accurate in cases where the component is used as both an input and an output.
130
+
131
+
132
+
133
+ ```python
134
+ def predict(
135
+ value: Any
136
+ ) -> typing.Optional[typing.Dict[str, typing.List[str]]][
137
+ typing.Dict[str, typing.List[str]][
138
+ str, typing.List[str][str]
139
+ ],
140
+ None,
141
+ ]:
142
+ return value
143
+ ```
144
+ """, elem_classes=["md-custom", "TagGroupHelper-user-fn"], header_links=True)
145
+
146
+
147
+
148
+
149
+ demo.load(None, js=r"""function() {
150
+ const refs = {};
151
+ const user_fn_refs = {
152
+ TagGroupHelper: [], };
153
+ requestAnimationFrame(() => {
154
+
155
+ Object.entries(user_fn_refs).forEach(([key, refs]) => {
156
+ if (refs.length > 0) {
157
+ const el = document.querySelector(`.${key}-user-fn`);
158
+ if (!el) return;
159
+ refs.forEach(ref => {
160
+ el.innerHTML = el.innerHTML.replace(
161
+ new RegExp("\\b"+ref+"\\b", "g"),
162
+ `<a href="#h-${ref.toLowerCase()}">${ref}</a>`
163
+ );
164
+ })
165
+ }
166
+ })
167
+
168
+ Object.entries(refs).forEach(([key, refs]) => {
169
+ if (refs.length > 0) {
170
+ const el = document.querySelector(`.${key}`);
171
+ if (!el) return;
172
+ refs.forEach(ref => {
173
+ el.innerHTML = el.innerHTML.replace(
174
+ new RegExp("\\b"+ref+"\\b", "g"),
175
+ `<a href="#h-${ref.toLowerCase()}">${ref}</a>`
176
+ );
177
+ })
178
+ }
179
+ })
180
+ })
181
+ }
182
+
183
+ """)
184
+
185
+ demo.launch()
src/frontend/Example.svelte ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ export let value: string;
3
+ export let type: "gallery" | "table";
4
+ export let selected = false;
5
+ </script>
6
+
7
+ <div
8
+ class:table={type === "table"}
9
+ class:gallery={type === "gallery"}
10
+ class:selected
11
+ >
12
+ {value}
13
+ </div>
14
+
15
+ <style>
16
+ .gallery {
17
+ padding: var(--size-1) var(--size-2);
18
+ }
19
+ </style>
src/frontend/Index.svelte ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import type { Gradio } from "@gradio/utils";
3
+ import { Block } from "@gradio/atoms";
4
+ import { StatusTracker } from "@gradio/statustracker";
5
+ import type { LoadingStatus } from "@gradio/statustracker";
6
+
7
+ export let value: Record<string, string[]> = {};
8
+ export let target_textbox_id: string;
9
+
10
+ export let label: string;
11
+ export let visible: boolean = true;
12
+ export let elem_id: string = "";
13
+ export let elem_classes: string[] = [];
14
+ export let container: boolean = true;
15
+ export let scale: number | null = null;
16
+ export let min_width: number | undefined = undefined;
17
+ export let loading_status: LoadingStatus;
18
+ export let gradio: Gradio<{ clear_status: LoadingStatus; }>;
19
+
20
+ let groupVisibility: Record<string, boolean> = {};
21
+
22
+ const tagColors = ["#d8b4fe", "#bbf7d0", "#fde047", "#fca5a5", "#93c5fd"];
23
+
24
+ $: {
25
+ if (value) {
26
+ for (const groupName in value) {
27
+ if (groupVisibility[groupName] === undefined) {
28
+ groupVisibility[groupName] = true;
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+ function toggleGroup(groupName: string) {
35
+ groupVisibility[groupName] = !groupVisibility[groupName];
36
+ }
37
+
38
+ function addTagToPrompt(tag: string) {
39
+ if (!target_textbox_id) {
40
+ console.error("TagGroupHelper: `target_textbox_id` prop is not set.");
41
+ return;
42
+ }
43
+
44
+ const targetTextarea = document.querySelector<HTMLTextAreaElement>(
45
+ `#${target_textbox_id} textarea`
46
+ );
47
+
48
+ if (!targetTextarea) {
49
+ console.error(`TagGroupHelper: Could not find textarea with id: #${target_textbox_id} textarea`);
50
+ return;
51
+ }
52
+
53
+ let currentValue = targetTextarea.value.trim();
54
+
55
+ if (currentValue === "" || currentValue.endsWith(",")) {
56
+ // If the field is empty or already ends with a comma,
57
+ // add the tag. If it ends with a comma, add a space first.
58
+ targetTextarea.value = currentValue.endsWith(",")
59
+ ? `${currentValue} ${tag}`
60
+ : tag;
61
+ } else {
62
+ // If the field has text, append a comma, a space, and the new tag.
63
+ targetTextarea.value = `${currentValue}, ${tag}`;
64
+ }
65
+
66
+ targetTextarea.dispatchEvent(new Event('input', { bubbles: true }));
67
+ }
68
+ </script>
69
+
70
+ <!-- The main structure uses the standard Gradio <Block> component. -->
71
+ <Block {visible} {elem_id} {elem_classes} {container} {scale} {min_width}>
72
+ {#if loading_status}
73
+ <StatusTracker
74
+ autoscroll={gradio.autoscroll}
75
+ i18n={gradio.i18n}
76
+ {...loading_status}
77
+ on:clear_status={() => gradio.dispatch("clear_status", loading_status)}
78
+ />
79
+ {/if}
80
+
81
+ {#if label}
82
+ <span class="label">{label}</span>
83
+ {/if}
84
+ <div class="container">
85
+ <!-- We iterate over the 'value' prop, which contains our tag groups -->
86
+ {#if value}
87
+ {#each Object.entries(value) as [groupName, tags]}
88
+ <div class="group">
89
+ <button class="group-header" on:click={() => toggleGroup(groupName)}>
90
+ <span class="group-title">{groupName}</span>
91
+ <span class="group-toggle-icon">{groupVisibility[groupName] ? '−' : '+'}</span>
92
+ </button>
93
+
94
+ {#if groupVisibility[groupName]}
95
+ <div class="tags-container">
96
+ <!-- Apply background color dynamically to each tag -->
97
+ {#each tags as tag, i}
98
+ <button
99
+ class="tag-button"
100
+ style="background-color: {tagColors[i % tagColors.length]};"
101
+ on:click={() => addTagToPrompt(tag)}
102
+ >
103
+ {tag}
104
+ </button>
105
+ {/each}
106
+ </div>
107
+ {/if}
108
+ </div>
109
+ {/each}
110
+ {/if}
111
+ </div>
112
+ </Block>
113
+
114
+ <style>
115
+ .container {
116
+ border: 1px solid var(--border-color-primary);
117
+ border-radius: var(--radius-lg);
118
+ padding: 8px;
119
+ background: var(--background-fill-secondary);
120
+ }
121
+ .label {
122
+ display: block;
123
+ margin-bottom: 8px;
124
+ font-size: 14px;
125
+ color: var(--body-text-color-subdued);
126
+ font-weight: 600;
127
+ }
128
+ .group {
129
+ margin-bottom: 8px;
130
+ }
131
+ .group:last-child {
132
+ margin-bottom: 0;
133
+ }
134
+
135
+ .group-header {
136
+ display: flex;
137
+ justify-content: space-between;
138
+ align-items: center;
139
+ width: 100%;
140
+ padding: 8px 12px;
141
+ background-color: var(--neutral-100, #f3f4f6);
142
+ color: var(--neutral-700, #374151);
143
+ border: 1px solid var(--border-color-primary);
144
+ border-radius: var(--radius-md);
145
+ text-align: left;
146
+ cursor: pointer;
147
+ font-size: 1rem;
148
+ transition: background-color 0.2s;
149
+ }
150
+ .group-header:hover {
151
+ background-color: var(--neutral-200, #e5e7eb);
152
+ }
153
+
154
+ .group-title {
155
+ font-weight: 600;
156
+ }
157
+ .group-toggle-icon {
158
+ font-size: 1.2rem;
159
+ font-weight: bold;
160
+ }
161
+ .tags-container {
162
+ display: flex;
163
+ flex-wrap: wrap;
164
+ gap: 8px;
165
+ padding: 12px 8px;
166
+ }
167
+ .tag-button {
168
+ padding: 4px 10px;
169
+ border: 1px solid #d1d5db;
170
+ border-radius: 12px;
171
+ font-size: 0.875rem;
172
+ cursor: pointer;
173
+ transition: filter 0.2s;
174
+ color: #1f2937;
175
+ }
176
+ .tag-button:hover {
177
+ filter: brightness(0.95);
178
+ }
179
+ </style>
src/frontend/gradio.config.js ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ export default {
2
+ plugins: [],
3
+ svelte: {
4
+ preprocess: [],
5
+ },
6
+ build: {
7
+ target: "modules",
8
+ },
9
+ };
src/frontend/package.json ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "gradio_taggrouphelper",
3
+ "version": "0.4.23",
4
+ "description": "Gradio UI packages",
5
+ "type": "module",
6
+ "author": "",
7
+ "license": "ISC",
8
+ "private": false,
9
+ "main_changeset": true,
10
+ "exports": {
11
+ ".": {
12
+ "gradio": "./Index.svelte",
13
+ "svelte": "./dist/Index.svelte",
14
+ "types": "./dist/Index.svelte.d.ts"
15
+ },
16
+ "./example": {
17
+ "gradio": "./Example.svelte",
18
+ "svelte": "./dist/Example.svelte",
19
+ "types": "./dist/Example.svelte.d.ts"
20
+ },
21
+ "./package.json": "./package.json"
22
+ },
23
+ "dependencies": {
24
+ "@gradio/atoms": "0.16.2",
25
+ "@gradio/statustracker": "0.10.13",
26
+ "@gradio/utils": "0.10.2",
27
+ "@zerodevx/svelte-json-view": "^1.0.7"
28
+ },
29
+ "devDependencies": {
30
+ "@gradio/preview": "0.13.2"
31
+ },
32
+ "peerDependencies": {
33
+ "svelte": "^4.0.0"
34
+ },
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/gradio-app/gradio.git",
38
+ "directory": "js/fallback"
39
+ }
40
+ }
src/frontend/tsconfig.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "allowJs": true,
4
+ "checkJs": true,
5
+ "esModuleInterop": true,
6
+ "forceConsistentCasingInFileNames": true,
7
+ "resolveJsonModule": true,
8
+ "skipLibCheck": true,
9
+ "sourceMap": true,
10
+ "strict": true,
11
+ "verbatimModuleSyntax": true
12
+ },
13
+ "exclude": ["node_modules", "dist", "./gradio.config.js"]
14
+ }
src/pyproject.toml ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [build-system]
2
+ requires = [
3
+ "hatchling",
4
+ "hatch-requirements-txt",
5
+ "hatch-fancy-pypi-readme>=22.5.0",
6
+ ]
7
+ build-backend = "hatchling.build"
8
+
9
+ [project]
10
+ name = "gradio_taggrouphelper"
11
+ version = "0.0.1"
12
+ description = "A fast text generator based on tagged words"
13
+ readme = "README.md"
14
+ license = "apache-2.0"
15
+ requires-python = ">=3.10"
16
+ authors = [{ name = "Eliseu Silva", email = "[email protected]" }]
17
+ keywords = ["gradio-custom-component", "gradio-template-Fallback"]
18
+ # Add dependencies here
19
+ dependencies = ["gradio>=4.0,<6.0"]
20
+ classifiers = [
21
+ 'Development Status :: 3 - Alpha',
22
+ 'Operating System :: OS Independent',
23
+ 'Programming Language :: Python :: 3',
24
+ 'Programming Language :: Python :: 3 :: Only',
25
+ 'Programming Language :: Python :: 3.8',
26
+ 'Programming Language :: Python :: 3.9',
27
+ 'Programming Language :: Python :: 3.10',
28
+ 'Programming Language :: Python :: 3.11',
29
+ 'Topic :: Scientific/Engineering',
30
+ 'Topic :: Scientific/Engineering :: Artificial Intelligence',
31
+ 'Topic :: Scientific/Engineering :: Visualization',
32
+ ]
33
+
34
+ # The repository and space URLs are optional, but recommended.
35
+ # Adding a repository URL will create a badge in the auto-generated README that links to the repository.
36
+ # Adding a space URL will create a badge in the auto-generated README that links to the space.
37
+ # This will make it easy for people to find your deployed demo or source code when they
38
+ # encounter your project in the wild.
39
+
40
+ # [project.urls]
41
+ # repository = "your github repository"
42
+ # space = "your space url"
43
+
44
+ [project.optional-dependencies]
45
+ dev = ["build", "twine"]
46
+
47
+ [tool.hatch.build]
48
+ artifacts = ["/backend/gradio_taggrouphelper/templates", "*.pyi", "/\\backend\\gradio_taggrouphelper\\templates"]
49
+
50
+ [tool.hatch.build.targets.wheel]
51
+ packages = ["/backend/gradio_taggrouphelper"]