django-kpforms 0.1.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.
- django_kpforms-0.1.0.dist-info/METADATA +414 -0
- django_kpforms-0.1.0.dist-info/RECORD +74 -0
- django_kpforms-0.1.0.dist-info/WHEEL +4 -0
- kpforms/README.md +390 -0
- kpforms/__init__.py +12 -0
- kpforms/admin.py +3 -0
- kpforms/apps.py +7 -0
- kpforms/form_schema.py +236 -0
- kpforms/helpers.py +379 -0
- kpforms/migrations/__init__.py +0 -0
- kpforms/models.py +77 -0
- kpforms/static/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- kpforms/static/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- kpforms/static/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- kpforms/static/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- kpforms/static/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- kpforms/static/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- kpforms/static/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- kpforms/static/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- kpforms/static/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- kpforms/static/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- kpforms/static/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- kpforms/static/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- kpforms/static/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- kpforms/static/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- kpforms/static/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- kpforms/static/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- kpforms/static/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- kpforms/static/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- kpforms/static/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- kpforms/static/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- kpforms/static/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- kpforms/static/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- kpforms/static/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- kpforms/static/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- kpforms/static/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- kpforms/static/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- kpforms/static/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- kpforms/static/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- kpforms/static/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- kpforms/static/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- kpforms/static/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- kpforms/static/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- kpforms/static/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- kpforms/static/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- kpforms/static/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- kpforms/static/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- kpforms/static/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- kpforms/static/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- kpforms/static/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- kpforms/static/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- kpforms/static/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- kpforms/static/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- kpforms/static/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- kpforms/static/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- kpforms/static/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- kpforms/static/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- kpforms/static/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- kpforms/static/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- kpforms/static/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- kpforms/static/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- kpforms/static/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- kpforms/static/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- kpforms/static/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- kpforms/static/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- kpforms/static/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- kpforms/static/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- kpforms/static/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- kpforms/static/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- kpforms/static/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- kpforms/static/html2pdf.bundle.min.js +3 -0
- kpforms/static/html2pdf.bundle.min.js.map +1 -0
- kpforms/static/kpforms.js +5500 -0
- kpforms/views.py +2 -0
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-kpforms
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Reusable Django app for dynamic form templates and submissions
|
|
5
|
+
Project-URL: Homepage, https://github.com/kodexprojects/django-kpforms
|
|
6
|
+
Project-URL: Bug Tracker, https://github.com/kodexprojects/django-kpforms/issues
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Classifier: Environment :: Web Environment
|
|
9
|
+
Classifier: Framework :: Django
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
17
|
+
Requires-Python: >=3.14
|
|
18
|
+
Requires-Dist: django>=5.0
|
|
19
|
+
Requires-Dist: pydantic>=2.0
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: pytest-django>=4.0; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# django-kpforms
|
|
26
|
+
|
|
27
|
+
A reusable Django application for **dynamic form templates and submissions**, powered by Lit-based web components.
|
|
28
|
+
|
|
29
|
+
- Define form templates with sections, groups, and typed fields (numeric, string, text, radio, checkbox, datetime, calculated, ranged-radio)
|
|
30
|
+
- Built-in tolerance checking for numeric and string fields
|
|
31
|
+
- Interactive web component (`<dynamic-form>`) for end-user submission
|
|
32
|
+
- Visual form-builder web component (`<dynamic-form-builder>`) for creating and editing templates
|
|
33
|
+
- Printable-form component for generating PDFs via `html2pdf.js`
|
|
34
|
+
- Full version history for form templates
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Table of Contents
|
|
39
|
+
|
|
40
|
+
1. [Requirements](#requirements)
|
|
41
|
+
2. [Installation](#installation)
|
|
42
|
+
3. [Quick Start](#quick-start)
|
|
43
|
+
4. [Django Models & Helpers](#django-models--helpers)
|
|
44
|
+
5. [Web Components](#web-components)
|
|
45
|
+
- [`<dynamic-form>`](#dynamic-form)
|
|
46
|
+
- [`<dynamic-form-builder>`](#dynamic-form-builder)
|
|
47
|
+
- [`<printable-form>`](#printable-form)
|
|
48
|
+
6. [CSS Customisation Variables](#css-customisation-variables)
|
|
49
|
+
- [Typography](#typography)
|
|
50
|
+
- [Colours](#colours)
|
|
51
|
+
- [Accent Colour](#accent-colour)
|
|
52
|
+
- [Status / Tolerance Colours](#status--tolerance-colours)
|
|
53
|
+
- [Layout](#layout)
|
|
54
|
+
7. [Contributing / Building from Source](#contributing--building-from-source)
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Requirements
|
|
59
|
+
|
|
60
|
+
- Python ≥ 3.14
|
|
61
|
+
- Django ≥ 5.0
|
|
62
|
+
- Pydantic ≥ 2.0
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Installation
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install django-kpforms
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Or with [uv](https://docs.astral.sh/uv/):
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
uv add django-kpforms
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Quick Start
|
|
81
|
+
|
|
82
|
+
### 1. Add to `INSTALLED_APPS`
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
# settings.py
|
|
86
|
+
INSTALLED_APPS = [
|
|
87
|
+
...
|
|
88
|
+
"kpforms",
|
|
89
|
+
]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 2. Run migrations
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
python manage.py migrate
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 3. Serve static files
|
|
99
|
+
|
|
100
|
+
`django-kpforms` ships with a compiled JavaScript bundle (`kpforms.js`) and
|
|
101
|
+
KaTeX font files under `kpforms/static/`.
|
|
102
|
+
|
|
103
|
+
Make sure Django's static-file serving is configured and `collectstatic` has
|
|
104
|
+
been run in production:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
python manage.py collectstatic
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 4. Load the bundle in your template
|
|
111
|
+
|
|
112
|
+
```html
|
|
113
|
+
{% load static %}
|
|
114
|
+
|
|
115
|
+
<!-- Load the kpforms web-component bundle -->
|
|
116
|
+
<script type="module" src="{% static 'kpforms.js' %}"></script>
|
|
117
|
+
|
|
118
|
+
<!-- Optional: load html2pdf for the printable-form component -->
|
|
119
|
+
<script src="{% static 'html2pdf.bundle.min.js' %}"></script>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Django Models & Helpers
|
|
125
|
+
|
|
126
|
+
### Models
|
|
127
|
+
|
|
128
|
+
| Model | Description |
|
|
129
|
+
|---|---|
|
|
130
|
+
| `FormTemplate` | A versioned form definition. The `schema` field holds a `FormTemplateSchema` JSON object. |
|
|
131
|
+
| `FormTemplateVersionHistory` | Immutable snapshot of a `FormTemplate` at each version. |
|
|
132
|
+
| `FormSubmission` | A single submission against a `FormTemplate`. Validates and stores tolerance results. |
|
|
133
|
+
|
|
134
|
+
### Helper functions (`kpforms.helpers`)
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from kpforms.helpers import (
|
|
138
|
+
create_form_template,
|
|
139
|
+
update_form_template,
|
|
140
|
+
submit_form_data,
|
|
141
|
+
get_form_by_template_id_and_version,
|
|
142
|
+
get_form_template_list,
|
|
143
|
+
get_form_template_list_paginated,
|
|
144
|
+
get_all_results_for_form_template,
|
|
145
|
+
)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
| Function | Description |
|
|
149
|
+
|---|---|
|
|
150
|
+
| `create_form_template(schema, user)` | Creates a new `FormTemplate` from a `CreateFormTemplateSchema`. |
|
|
151
|
+
| `update_form_template(schema, user)` | Saves a new version of an existing template. |
|
|
152
|
+
| `submit_form_data(template_id, form_data, user)` | Validates and saves a `FormSubmission`. |
|
|
153
|
+
| `get_form_by_template_id_and_version(id, version=None)` | Returns the `FormTemplateSchema` for a given ID and optional version. |
|
|
154
|
+
| `get_form_template_list(only_active=True)` | Returns a list of `{id, name, description}` dicts. |
|
|
155
|
+
| `get_form_template_list_paginated(page_size, only_active)` | Returns a Django `Paginator`. |
|
|
156
|
+
| `get_all_results_for_form_template(template_id)` | Returns all submissions with labelled field data. |
|
|
157
|
+
|
|
158
|
+
### Schema classes (`kpforms.form_schema`)
|
|
159
|
+
|
|
160
|
+
The core schema models are Pydantic models. The most important ones:
|
|
161
|
+
|
|
162
|
+
| Class | Description |
|
|
163
|
+
|---|---|
|
|
164
|
+
| `FormTemplateSchema` | Full form definition: `title`, `instruction`, `sections`. |
|
|
165
|
+
| `CreateFormTemplateSchema` | Input payload for creating a template. |
|
|
166
|
+
| `UpdateFormTemplateSchema` | Input payload for updating a template (adds `guid`). |
|
|
167
|
+
| `FormSubmissionSchema` | Submission payload: `data` (list of `{fieldId, value}`), `fieldsOutOfTolerance`. |
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Web Components
|
|
172
|
+
|
|
173
|
+
Include `kpforms.js` once on the page (see Quick Start above) — all components
|
|
174
|
+
are self-registering and require no additional setup.
|
|
175
|
+
|
|
176
|
+
### `<dynamic-form>`
|
|
177
|
+
|
|
178
|
+
Renders a form for end-user completion and submission.
|
|
179
|
+
|
|
180
|
+
```html
|
|
181
|
+
<dynamic-form id="my-form"></dynamic-form>
|
|
182
|
+
|
|
183
|
+
<script type="module">
|
|
184
|
+
const formEl = document.getElementById("my-form");
|
|
185
|
+
|
|
186
|
+
// Pass the form schema (FormSchema JSON) as a property
|
|
187
|
+
formEl.schema = {
|
|
188
|
+
guid: "...",
|
|
189
|
+
title: "My Form",
|
|
190
|
+
sections: [...],
|
|
191
|
+
generatePdfOption: false,
|
|
192
|
+
generatePdfString: "Generate PDF",
|
|
193
|
+
submitFormString: "Submit",
|
|
194
|
+
submittingString: "Submitting…",
|
|
195
|
+
apiConfig: {
|
|
196
|
+
url: "/api/forms/submit/",
|
|
197
|
+
method: "POST",
|
|
198
|
+
successMessage: "Form submitted!",
|
|
199
|
+
errorMessage: "Submission failed."
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
</script>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Properties / attributes:**
|
|
206
|
+
|
|
207
|
+
| Property | Type | Description |
|
|
208
|
+
|---|---|---|
|
|
209
|
+
| `schema` | `FormSchema` (object) | The full form schema to render. |
|
|
210
|
+
| `lang` | `string` | BCP-47 language tag for UI strings (e.g. `"en"`, `"sv"`). Defaults to `"en"`. |
|
|
211
|
+
|
|
212
|
+
### `<dynamic-form-builder>`
|
|
213
|
+
|
|
214
|
+
An interactive editor that lets users create and edit form templates.
|
|
215
|
+
|
|
216
|
+
```html
|
|
217
|
+
<dynamic-form-builder id="builder"></dynamic-form-builder>
|
|
218
|
+
|
|
219
|
+
<script type="module">
|
|
220
|
+
const builder = document.getElementById("builder");
|
|
221
|
+
|
|
222
|
+
// Optional: load an existing template for editing
|
|
223
|
+
builder.schema = { guid: "...", name: "...", formSchema: { ... } };
|
|
224
|
+
|
|
225
|
+
// Listen for save events
|
|
226
|
+
builder.addEventListener("form-save", (e) => {
|
|
227
|
+
const payload = e.detail; // CreateFormTemplateSchema | UpdateFormTemplateSchema
|
|
228
|
+
fetch("/api/forms/templates/", {
|
|
229
|
+
method: payload.guid ? "PUT" : "POST",
|
|
230
|
+
headers: { "Content-Type": "application/json" },
|
|
231
|
+
body: JSON.stringify(payload),
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
</script>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Properties / attributes:**
|
|
238
|
+
|
|
239
|
+
| Property | Type | Description |
|
|
240
|
+
|---|---|---|
|
|
241
|
+
| `schema` | `UpdateFormTemplateSchema` (object) | Optional existing template to edit. |
|
|
242
|
+
| `lang` | `string` | BCP-47 language tag. |
|
|
243
|
+
|
|
244
|
+
**Events emitted:**
|
|
245
|
+
|
|
246
|
+
| Event | `detail` | Description |
|
|
247
|
+
|---|---|---|
|
|
248
|
+
| `form-save` | `CreateFormTemplateSchema \| UpdateFormTemplateSchema` | Fired when the user clicks Save. |
|
|
249
|
+
|
|
250
|
+
### `<printable-form>`
|
|
251
|
+
|
|
252
|
+
Renders a read-only printable view of a submitted form that can be exported as a PDF using `html2pdf.js`.
|
|
253
|
+
|
|
254
|
+
```html
|
|
255
|
+
<printable-form id="print-form"></printable-form>
|
|
256
|
+
|
|
257
|
+
<script type="module">
|
|
258
|
+
const el = document.getElementById("print-form");
|
|
259
|
+
el.schema = { /* FormTemplateSchema */ };
|
|
260
|
+
el.submission = { /* FormSubmission data */ };
|
|
261
|
+
</script>
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Properties:**
|
|
265
|
+
|
|
266
|
+
| Property | Type | Description |
|
|
267
|
+
|---|---|---|
|
|
268
|
+
| `schema` | `FormTemplateSchema` (object) | The form template. |
|
|
269
|
+
| `submission` | `FormSubmissionSchema` (object) | The submission data to display. |
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## CSS Customisation Variables
|
|
274
|
+
|
|
275
|
+
All web components use CSS custom properties (variables) to control their appearance.
|
|
276
|
+
Set these on the element itself or any ancestor to theme the components.
|
|
277
|
+
|
|
278
|
+
The **public API** variables are prefixed `--df-*`. Internal variables map them
|
|
279
|
+
to `--form-*` and to [Shoelace](https://shoelace.style/) design tokens.
|
|
280
|
+
|
|
281
|
+
### Typography
|
|
282
|
+
|
|
283
|
+
| Variable | Default | Description |
|
|
284
|
+
|---|---|---|
|
|
285
|
+
| `--df-font-size-base` | `1rem` | Base font size. |
|
|
286
|
+
| `--df-font-size-h1` | `1.8rem` | Form title size. |
|
|
287
|
+
| `--df-font-size-h2` | `1.4rem` | Section heading size. |
|
|
288
|
+
| `--df-font-size-label` | `0.9rem` | Field label size. |
|
|
289
|
+
| `--df-font-size-description` | `0.85rem` | Field description / helper text size. |
|
|
290
|
+
|
|
291
|
+
### Colours
|
|
292
|
+
|
|
293
|
+
| Variable | Default | Description |
|
|
294
|
+
|---|---|---|
|
|
295
|
+
| `--df-color-text` | `#333` | Primary text colour. |
|
|
296
|
+
| `--df-color-input-text` | `#111` | Text colour inside input fields. |
|
|
297
|
+
| `--df-color-text-secondary` | `#555` | Secondary / description text colour. |
|
|
298
|
+
| `--df-color-text-label` | `#111` | Field label text colour. |
|
|
299
|
+
| `--df-color-background` | `#ffffff` | Component background. |
|
|
300
|
+
| `--df-color-background-input-base` | `#ffffff` | Input field background (resting). |
|
|
301
|
+
| `--df-color-background-input-focus` | `#ffffff` | Input field background on focus. |
|
|
302
|
+
| `--df-color-background-section` | `#f9f9f9` | Form section background. |
|
|
303
|
+
| `--df-color-border` | `#ccc` | Default border colour. |
|
|
304
|
+
|
|
305
|
+
### Accent Colour
|
|
306
|
+
|
|
307
|
+
Used for buttons, active tabs, focused borders, and Shoelace's primary palette.
|
|
308
|
+
|
|
309
|
+
| Variable | Default | Description |
|
|
310
|
+
|---|---|---|
|
|
311
|
+
| `--df-color-accent` | `#007bff` | Primary accent / brand colour. |
|
|
312
|
+
| `--df-color-accent-lighter` | `#66b3ff` | Lighter variant (e.g. hover states). |
|
|
313
|
+
| `--df-color-accent-darker` | `#0056b3` | Darker variant (e.g. active states). |
|
|
314
|
+
| `--df-color-accent-text` | `#ffffff` | Text on accent-coloured elements. |
|
|
315
|
+
| `--df-color-success` | `#28a745` | Success colour (Shoelace success palette). |
|
|
316
|
+
| `--df-color-success-darker` | `#1e7e34` | Darker success variant. |
|
|
317
|
+
| `--df-color-success-text` | `#ffffff` | Text on success-coloured elements. |
|
|
318
|
+
| `--df-color-warning` | `#fbb34e` | Warning colour. |
|
|
319
|
+
| `--df-color-warning-darker` | `#fea429` | Darker warning variant. |
|
|
320
|
+
| `--df-color-warning-text` | `#ffffff` | Text on warning-coloured elements. |
|
|
321
|
+
| `--df-color-neutral` | `#6c757d` | Neutral colour. |
|
|
322
|
+
| `--df-color-neutral-darker` | `#5a6268` | Darker neutral variant. |
|
|
323
|
+
| `--df-color-neutral-text` | `#ffffff` | Text on neutral-coloured elements. |
|
|
324
|
+
| `--df-color-error` | `#dc3545` | Error / danger colour. |
|
|
325
|
+
| `--df-color-error-lighter` | `#fa5969` | Lighter error variant. |
|
|
326
|
+
| `--df-color-error-text` | `#721c24` | Text on error-coloured elements. |
|
|
327
|
+
|
|
328
|
+
### Status / Tolerance Colours
|
|
329
|
+
|
|
330
|
+
These control how fields are highlighted when their values are within or outside
|
|
331
|
+
the defined tolerance range.
|
|
332
|
+
|
|
333
|
+
| Variable | Default | Description |
|
|
334
|
+
|---|---|---|
|
|
335
|
+
| `--df-color-required-star` | `#f98989` | Colour of the asterisk on required fields. |
|
|
336
|
+
| `--df-color-within-tolerance-border` | `#8fff8f` | Border colour when field value is within tolerance. |
|
|
337
|
+
| `--df-color-within-tolerance-background` | `#b9fb9f` | Background when field value is within tolerance. |
|
|
338
|
+
| `--df-color-within-tolerance-input-text` | `#214521` | Text colour in input when within tolerance. |
|
|
339
|
+
| `--df-color-within-tolerance-text` | `#3c763d` | Label/message text when within tolerance. |
|
|
340
|
+
| `--df-color-out-of-tolerance-border` | `#fdf8b2` | Border colour when field value is out of tolerance. |
|
|
341
|
+
| `--df-color-out-of-tolerance-text` | `#d9534f` | Text/label colour when out of tolerance. |
|
|
342
|
+
| `--df-color-has-error-border` | *(inherits error colour)* | Border colour when field has a validation error. |
|
|
343
|
+
| `--df-color-has-error-background` | `#d58d8b` | Background when field has a validation error. |
|
|
344
|
+
|
|
345
|
+
### Layout
|
|
346
|
+
|
|
347
|
+
| Variable | Default | Description |
|
|
348
|
+
|---|---|---|
|
|
349
|
+
| `--df-border-radius` | `4px` | Corner radius for inputs, sections, and the component itself. |
|
|
350
|
+
| `--df-spacing-medium` | `1rem` | Medium spacing unit used for padding/gaps. |
|
|
351
|
+
| `--df-spacing-large` | `1.5rem` | Large spacing unit used for section padding. |
|
|
352
|
+
| `--df-button-padding` | `0.3rem 1rem` | Padding applied to Shoelace `<sl-button>` elements. |
|
|
353
|
+
|
|
354
|
+
### Example: Dark Theme
|
|
355
|
+
|
|
356
|
+
```css
|
|
357
|
+
dynamic-form {
|
|
358
|
+
--df-color-background: #1e1e2e;
|
|
359
|
+
--df-color-background-section: #2a2a3e;
|
|
360
|
+
--df-color-background-input-base: #2d2d42;
|
|
361
|
+
--df-color-text: #cdd6f4;
|
|
362
|
+
--df-color-text-label: #cdd6f4;
|
|
363
|
+
--df-color-input-text: #cdd6f4;
|
|
364
|
+
--df-color-border: #45475a;
|
|
365
|
+
--df-color-accent: #89b4fa;
|
|
366
|
+
--df-color-accent-darker: #74a0e8;
|
|
367
|
+
--df-color-accent-text: #1e1e2e;
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Contributing / Building from Source
|
|
374
|
+
|
|
375
|
+
### Prerequisites
|
|
376
|
+
|
|
377
|
+
- Python ≥ 3.14 (with [uv](https://docs.astral.sh/uv/))
|
|
378
|
+
- Node.js ≥ 20 with npm
|
|
379
|
+
|
|
380
|
+
### Build
|
|
381
|
+
|
|
382
|
+
Use the included `build.sh` to produce a distributable wheel and sdist:
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
# Build both sdist and wheel (default)
|
|
386
|
+
./build.sh
|
|
387
|
+
|
|
388
|
+
# Build wheel only
|
|
389
|
+
./build.sh --wheel
|
|
390
|
+
|
|
391
|
+
# Build sdist only
|
|
392
|
+
./build.sh --sdist
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
The script will:
|
|
396
|
+
|
|
397
|
+
1. Run `npm run build` inside `kpforms/kpforms/` to compile the TypeScript
|
|
398
|
+
web components and copy the output into `kpforms/static/`.
|
|
399
|
+
2. Run `python manage.py makemigrations kpforms` to ensure migrations are
|
|
400
|
+
up-to-date.
|
|
401
|
+
3. Run `uv build` to produce the final packages in `dist/`.
|
|
402
|
+
|
|
403
|
+
### Running Tests
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
uv run pytest
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Licence
|
|
412
|
+
|
|
413
|
+
MIT — see [LICENSE](../LICENSE) for details.
|
|
414
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
kpforms/README.md,sha256=oCbi0fC96jJXUvG1oAyN8RnUfc1__P-IHwFTA-QytTs,12612
|
|
2
|
+
kpforms/__init__.py,sha256=PjNLYC0irZwO1xmWxj07Q4R6TLPPhYZiobc-17YPO0w,280
|
|
3
|
+
kpforms/admin.py,sha256=suMo4x8I3JBxAFBVIdE-5qnqZ6JAZV0FESABHOSc-vg,63
|
|
4
|
+
kpforms/apps.py,sha256=FrKCJl1PNTUQaNK8bvt_MjTCL5drpSG0oogE496BQQo,176
|
|
5
|
+
kpforms/form_schema.py,sha256=mGy4FSHjreBo-Mz352IehN0iUkJO-oQbtXFBJgUcYvs,5979
|
|
6
|
+
kpforms/helpers.py,sha256=-e__tIhZ7P7xRydKVRK3-Ktgn5eJgrlr103krWiptdY,14408
|
|
7
|
+
kpforms/models.py,sha256=qOB6FwjRrAdKaBaVoS8XsGH8JsPJfABabFnWV2fBKNY,3178
|
|
8
|
+
kpforms/views.py,sha256=Lk3T0-6uEckQ_Z-vPHvVe9eoJsoDZHww_6-jiRM8UR0,94
|
|
9
|
+
kpforms/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
kpforms/static/KaTeX_AMS-Regular-BQhdFMY1.woff2,sha256=DN04fJWQoan5eUVgAi27WWVKfYbxh6oMgUla1C06cwg,28076
|
|
11
|
+
kpforms/static/KaTeX_AMS-Regular-DMm9YOAa.woff,sha256=MNqR6EyJP4deJSaJ-uvcWQsocRReitx_mp1NvYzgslE,33516
|
|
12
|
+
kpforms/static/KaTeX_AMS-Regular-DRggAlZN.ttf,sha256=aFNIQLz90r_7bw6N60hoTdAefwTqKBMmdXevuQbeHRM,63632
|
|
13
|
+
kpforms/static/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf,sha256=B9jjA85PwStLtU8QBBcN0ZCh89tF1AD-aAYN8-CJcmg,12368
|
|
14
|
+
kpforms/static/KaTeX_Caligraphic-Bold-BEiXGLvX.woff,sha256=Gua9dHVZDpfn8UWongnM3jIvemvAuRYHsci47igpD-0,7716
|
|
15
|
+
kpforms/static/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2,sha256=3ncB5Czx9M8LdmwD-yeXcgfu4vT9XXb6ghiEBtpD6kw,6912
|
|
16
|
+
kpforms/static/KaTeX_Caligraphic-Regular-CTRA-rTL.woff,sha256=M5jdAjAlV6eT8oY_iOAtls4Q3yq_-gfI6fqQd1EW5lw,7656
|
|
17
|
+
kpforms/static/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2,sha256=XVPnCtYHwjUhYt7J4JI_tU7Nr6zL9gTNjc99APrLmJs,6908
|
|
18
|
+
kpforms/static/KaTeX_Caligraphic-Regular-wX97UBjC.ttf,sha256=7Qt0Ny_u_LucBmay4hDaN7fkn6f7vz7rEdtfaT2s-7c,12344
|
|
19
|
+
kpforms/static/KaTeX_Fraktur-Bold-BdnERNNW.ttf,sha256=kWPfnHEiQy5klbQin6kHHPmuhqdYrl78SSTsLhptvOE,19584
|
|
20
|
+
kpforms/static/KaTeX_Fraktur-Bold-BsDP51OF.woff,sha256=m-fOuIAEq4rRJAgiRvv8ykCR42OF1Oxu0d9nN12tUPs,13296
|
|
21
|
+
kpforms/static/KaTeX_Fraktur-Bold-CL6g_b3V.woff2,sha256=dERO_Vk8AF4_RXO0RSRwTArwqTf-kRzKnpQGjQ0UDT8,11348
|
|
22
|
+
kpforms/static/KaTeX_Fraktur-Regular-CB_wures.ttf,sha256=Hm-VeekOLKw3-PYKWXxDbgdcEUOFZSt8vrDewEISkbM,19572
|
|
23
|
+
kpforms/static/KaTeX_Fraktur-Regular-CTYiF6lA.woff2,sha256=UYFNJw0G_wJV26B5mZT6TYyE0R8JlR1HWV9Kux82Atw,11316
|
|
24
|
+
kpforms/static/KaTeX_Fraktur-Regular-Dxdc4cR9.woff,sha256=Xih1O-cX2sl_VZ9JvBC-nPPBJN3KvaZlnRHLaP68ZGM,13208
|
|
25
|
+
kpforms/static/KaTeX_Main-Bold-Cx986IdX.woff2,sha256=D2DRuJeTjskYyM4HMJJBG6-UOPZzlGVpP_GLD50gsCE,25324
|
|
26
|
+
kpforms/static/KaTeX_Main-Bold-Jm3AIy58.woff,sha256=x2xdaWKX1RucsWOcfaQzTw597IG0KxEhO14l72cbuCI,29912
|
|
27
|
+
kpforms/static/KaTeX_Main-Bold-waoOVXN0.ttf,sha256=E4rCjRZjswN-nF9SNx-lxj2DJPSjjSLNVz5uo6P9DPg,51336
|
|
28
|
+
kpforms/static/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2,sha256=mc1Co8By2Rjy9EmEqAfPeqFuE1Rf0IdfwHxsZfmecVs,16780
|
|
29
|
+
kpforms/static/KaTeX_Main-BoldItalic-DzxPMmG6.ttf,sha256=cO4fZKIPIEjCGUDvRtAUT9IVuqlTymmv0eMemFRPcI8,32968
|
|
30
|
+
kpforms/static/KaTeX_Main-BoldItalic-SpSLRI95.woff,sha256=pvfsDYRqx62XWtuJWcN-1JuUrLxK5DbbnOniAofkpkw,19412
|
|
31
|
+
kpforms/static/KaTeX_Main-Italic-3WenGoN9.ttf,sha256=DYWufMMPI3kKfxpYxKES_cqKrnaba6EUKa8dmLG2yzo,33580
|
|
32
|
+
kpforms/static/KaTeX_Main-Italic-BMLOBm91.woff,sha256=8dbvhvOxGlKL1RhRmb0kQ-yysN6tltiGdLWiwSviS98,19676
|
|
33
|
+
kpforms/static/KaTeX_Main-Italic-NWA7e6Wa.woff2,sha256=l0ecpszpBqvJYeyslvql-couYbjnZw1HWCa83umnwmc,16988
|
|
34
|
+
kpforms/static/KaTeX_Main-Regular-B22Nviop.woff2,sha256=wjQs2Lhp4BdSqTIdwXIT_EDU0Ex5aIwdQ_LPMWq9eGY,26272
|
|
35
|
+
kpforms/static/KaTeX_Main-Regular-Dr94JaBh.woff,sha256=xjaNh-iho6XTN2I9g9jcS4aPJCqa1HYjfW-NHg8WjNw,30772
|
|
36
|
+
kpforms/static/KaTeX_Main-Regular-ypZvNtVU.ttf,sha256=0DMvUoaDcP2Drn-kZHD5DI8uqy_PErxPiAgLNAyVqDA,53580
|
|
37
|
+
kpforms/static/KaTeX_Math-BoldItalic-B3XSjfu4.ttf,sha256=-Td6sCcc2lmvJLz_vUak0MijVy_6_bs43irV6nsNXuU,31196
|
|
38
|
+
kpforms/static/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2,sha256=3Ec0TbtstbZVyEYNVh9N9fUBuQyAStPGzsZf4yI1GrE,16400
|
|
39
|
+
kpforms/static/KaTeX_Math-BoldItalic-iY-2wyZ7.woff,sha256=hQwK9cIjhJf-uvXkYdiAv0WMNB9C9PMw8bGrVpixmY4,18668
|
|
40
|
+
kpforms/static/KaTeX_Math-Italic-DA0__PXp.woff,sha256=io0kRYE3GRK48_WiPiQ3yypZzZvK67A0bnIsBXN6JXE,18748
|
|
41
|
+
kpforms/static/KaTeX_Math-Italic-flOr_0UB.ttf,sha256=CM6Y5RsE1YlFowHmOeAraZivKf39Yae4r90Hu_xHnUo,31308
|
|
42
|
+
kpforms/static/KaTeX_Math-Italic-t53AETM-.woff2,sha256=evWMXsjxMqLd3pAnxteBTezOTTuCKhEZKkKiDi6XMmQ,16440
|
|
43
|
+
kpforms/static/KaTeX_SansSerif-Bold-CFMepnvq.ttf,sha256=Hs4D95-VJ31X3H9rQ1p04TebDUYQSoUwKGtg_0k2nqA,24504
|
|
44
|
+
kpforms/static/KaTeX_SansSerif-Bold-D1sUS0GD.woff2,sha256=6ZrlEUS_EjLvzBv-Wt02JixoZrD6qyT6dXQOG5hXemI,12216
|
|
45
|
+
kpforms/static/KaTeX_SansSerif-Bold-DbIhKOiC.woff,sha256=7OA8_YPiLCEs3vZv64RC0loIO-uYjbPxiD8_lzjXULo,14408
|
|
46
|
+
kpforms/static/KaTeX_SansSerif-Italic-C3H0VqGB.woff2,sha256=ALJqyCXiCVBWOW4FU7isJtP4rRWMOCbii0xFs4XEcUo,12028
|
|
47
|
+
kpforms/static/KaTeX_SansSerif-Italic-DN2j7dab.woff,sha256=ke5nUAzAEpqgrOOsXGH_FpIQLw8x0CtpNH-6Ndy3W_I,14112
|
|
48
|
+
kpforms/static/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf,sha256=OTHdgfrthroCG7K73Db1vtmjjWtPQHespZsmWqGwIIM,22364
|
|
49
|
+
kpforms/static/KaTeX_SansSerif-Regular-BNo7hRIc.ttf,sha256=826ol-GfSi5XHR6QDk43EOQ43rBahCSGBFugo-YWpK0,19436
|
|
50
|
+
kpforms/static/KaTeX_SansSerif-Regular-CS6fqUqJ.woff,sha256=EeTcimRx_21u5WHVPRD96PdInnmCV_9EnF03wZdDVgU,12316
|
|
51
|
+
kpforms/static/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2,sha256=aOjHPvQq_TzOxYvw-6MCzORIk45_wCCl4x-KlS7uE0I,10344
|
|
52
|
+
kpforms/static/KaTeX_Script-Regular-C5JkGWo-.ttf,sha256=HGfwaP6ouwm_CZwIixz2S9J1Fqbgf0aENEhzVku2amc,16648
|
|
53
|
+
kpforms/static/KaTeX_Script-Regular-D3wIWfF6.woff2,sha256=A21OlRSbaf-bzAzVV3Hv6yX_o5Ryk-aazXjVrDKMaEs,9644
|
|
54
|
+
kpforms/static/KaTeX_Script-Regular-D5yQViql.woff,sha256=2WzfKzvdTWSo_V90pMRn8SOopzkxzUNYifCP-vm_lHo,10588
|
|
55
|
+
kpforms/static/KaTeX_Size1-Regular-C195tn64.woff,sha256=yUPMmGOE9Z6GvqX9fcUKnE3-Vnp8BetA1nkHIN6tl8k,6496
|
|
56
|
+
kpforms/static/KaTeX_Size1-Regular-Dbsnue_I.ttf,sha256=lbbS8aUBc7_tuMY-HRyZsQQn0KTfQgHLRFE7ImlRois,12228
|
|
57
|
+
kpforms/static/KaTeX_Size1-Regular-mCD8mA8B.woff2,sha256=a0fEAWa22-IaXfyncYQT8hR_0jmb4bpgXYrTnO3yXf4,5468
|
|
58
|
+
kpforms/static/KaTeX_Size2-Regular-B7gKUWhC.ttf,sha256=prIJn7VVxg46DbOgiELr8dcyxutOS_RJE2E77U_E45s,11508
|
|
59
|
+
kpforms/static/KaTeX_Size2-Regular-Dy4dx90m.woff2,sha256=0ExUIZ-ersbU1P1C37KHhZdaR5TWsvxx5Wa5zW24Qt0,5208
|
|
60
|
+
kpforms/static/KaTeX_Size2-Regular-oD1tc_U0.woff,sha256=IBTFI8MhC8wWZkjE1MxX8Ft0ffB6JCd79xxR5n3Hnj0,6188
|
|
61
|
+
kpforms/static/KaTeX_Size3-Regular-CTq5MqoE.woff,sha256=ara2Lpti2uLADdkPeRvRCVC-Dsw0kNfWBF9Rwuj-CUk,4420
|
|
62
|
+
kpforms/static/KaTeX_Size3-Regular-DgpXs0kz.ttf,sha256=UA4E1U8NUWZjMsnSCJqoA74iqoeOylOeWfpTxuUisII,7588
|
|
63
|
+
kpforms/static/KaTeX_Size4-Regular-BF-4gkZK.woff,sha256=mfnGdQtInJRivwSQC9P5Od-bgpM52qqqme9Ulc3d6lg,5980
|
|
64
|
+
kpforms/static/KaTeX_Size4-Regular-DWFBv043.ttf,sha256=xkc2fR3U4WJGhxfQIOH8Dx3Fwm6_3_vlUmFxO_iMWHc,10364
|
|
65
|
+
kpforms/static/KaTeX_Size4-Regular-Dl5lxZxV.woff2,sha256=pK99QURAocF5CCXPtwDPnPQ7DyxLBPDrxSMBGtmFPsA,4928
|
|
66
|
+
kpforms/static/KaTeX_Typewriter-Regular-C0xS9mPB.woff,sha256=4U_tArGrp86fWv1YRLXQMhsiNR_rxyDg3ouHI1J2Cfc,16028
|
|
67
|
+
kpforms/static/KaTeX_Typewriter-Regular-CO6r4hn1.woff2,sha256=cdUX1ngneHz6vfGGkUzDNY7aU543kxlB8rL9SiH2jAs,13568
|
|
68
|
+
kpforms/static/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf,sha256=8B8-h9nGphwMCBzrV3q9hk6wCmEvesFiDdaRX60u9ao,27556
|
|
69
|
+
kpforms/static/html2pdf.bundle.min.js,sha256=lWPEXwMhecc0VCk6ZJkp5g_CTAWjJuirKBHPqPJcNgc,946030
|
|
70
|
+
kpforms/static/html2pdf.bundle.min.js.map,sha256=jUCuQBLnRZNTcsOb-2KGiBkI5OeteropdDfc3GtskIo,3025260
|
|
71
|
+
kpforms/static/kpforms.js,sha256=PtPFAI7QyM0NFjPBzUps2PQPfW6nkh6_vOwvzoJYS-Y,1041381
|
|
72
|
+
django_kpforms-0.1.0.dist-info/METADATA,sha256=4V7xL-zEzV3QVQVCDAvH3EyPT5DCNq_U8sA8LUFV8SE,13591
|
|
73
|
+
django_kpforms-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
74
|
+
django_kpforms-0.1.0.dist-info/RECORD,,
|