katalyst-govuk-formbuilder 1.30.1 → 2.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9117d661c2225e77188c2cd1b95df29bcdf27a0d507981bceca33477896f5a53
4
- data.tar.gz: 42e6309f7ea989a7a52f159bc2ec78466de4354378c3c10d61aba02198699de6
3
+ metadata.gz: bfaf577c810adcbb0beccb5c19593d351212fa47ac656eab727fddac588dbaa2
4
+ data.tar.gz: 498dc851c834e026add583e93c411496007d4bfc3905957686b9a02b854fcb51
5
5
  SHA512:
6
- metadata.gz: 26683a6307957c466fc712d11b6ec430424e64f5dcf24e1730a9b487c36e8ae5c2236a7c171c734c72bdb812cc40d6ac34562018b143f9b4e3c57776e16dfca4
7
- data.tar.gz: 9c88e639a61aee9fa049d399296e59fcc9da810ed0f7f5d718c9dbe2751a68144b0a1848b404701e2ff212786451f25e852e61a42672dfb2f8ffbf132cca1a6f
6
+ metadata.gz: a0534e3ca97f200c06440c6c2d5e698f8f3912ad3b804fbaac7627d0f2c46eea005191033289b7be1358f98e87763d171202e8af6d986a03614e05abd9510a4b
7
+ data.tar.gz: db9d235514210ce9a33f31abc660642837a1de680c84e32a968ac118705495b8de8383ebad0a82832da0a3da646e227bcd03c6402021deda7ecc421ec4db40c4
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # Katalyst::GOVUK::FormBuilder
2
2
 
3
3
  Repacking of [GOV.UK Frontend](https://frontend.design-system.service.gov.uk) and
4
- [GOV.UK form components](https://govuk-form-builder.netlify.app) for use in Katalyst projects.
4
+ [GOV.UK form components](https://govuk-form-builder.netlify.app) for use in Katalyst projects,
5
+ extended with ActiveStorage-backed attachment fields: previews, drag-and-drop, async direct
6
+ uploads, and a complete no-JavaScript fallback.
5
7
 
6
8
  ## Installation
7
9
 
@@ -21,6 +23,14 @@ Or install it yourself as:
21
23
 
22
24
  ## Usage
23
25
 
26
+ Use the GOV.UK form builder for your forms, most simply as the application default:
27
+
28
+ ```ruby
29
+ class ApplicationController < ActionController::Base
30
+ default_form_builder GOVUKDesignSystemFormBuilder::FormBuilder
31
+ end
32
+ ```
33
+
24
34
  Add the stylesheet to your default layout:
25
35
 
26
36
  ```erb
@@ -33,38 +43,154 @@ You can also add it to your SASS build:
33
43
  @use "katalyst/govuk/formbuilder";
34
44
  ```
35
45
 
36
- Some GOVUK components require javascript enhancements
37
- (see [GOVUK docs](https://frontend.design-system.service.gov.uk/get-started/#5-get-the-javascript-working)).
46
+ ### JavaScript
47
+
48
+ The attachment and file upload fields are Stimulus-powered. Load the gem's
49
+ controllers into your Stimulus application:
50
+
51
+ ```js
52
+ import { Application } from "@hotwired/stimulus";
53
+
54
+ const application = Application.start();
55
+
56
+ import GOVUK from "@katalyst/govuk-formbuilder";
57
+ GOVUK.start(application);
58
+ ```
38
59
 
39
- You can use the provided helper to load the formbuilder esm from importmaps and enhance your form:
60
+ If you want to keep GOVUK enhancements separate from your main app's Stimulus
61
+ application, you can inject the bootstrap JS module into your body instead:
40
62
 
41
63
  ```erb
42
- <%= form_with ... %>
43
64
  <%= govuk_formbuilder_init %>
44
65
  ```
45
66
 
46
- You'll need to include the helper to make this method available, which you can add to your `ApplicationController`:
67
+ You'll need to include the helper to make this method available, which you can add
68
+ to your `ApplicationController`:
47
69
 
48
70
  ```ruby
49
71
  helper Katalyst::GOVUK::FormBuilder::Frontend
50
72
  ```
51
73
 
52
- ## Extensions
74
+ The snippet marks the page as JavaScript-capable and calls the module's `initAll()`,
75
+ but will not survive a new page render (including Turbo navigation). Use this
76
+ approach if you are only using GOVUK sparingly.
53
77
 
54
- We include some optional extensions for integrating with gems that we (Katalyst) commonly use.
78
+ #### JavaScript dependencies
55
79
 
56
- These require additional steps to use.
80
+ The formbuilder module imports `@hotwired/stimulus` and `@rails/activestorage`. With
81
+ importmaps the gem pins itself and `@rails/activestorage` for you. It does not pin
82
+ `@hotwired/stimulus` — your app provides that (`stimulus-rails` does this in a
83
+ standard Rails app). If you use jsbundling or similar, you'll need both packages
84
+ available at runtime; the wiring is the same `GOVUK.start(application)` shown above,
85
+ from your own bundle.
57
86
 
58
- ### File inputs
87
+ ## Attachment fields
59
88
 
60
- We've added image and document fields designed for use with Koi. These will not be suitable for
61
- every project. If you want to use these, you'll need to import and load their stimulus controllers:
89
+ `govuk_image_field` and `govuk_document_field` render an upload field for
90
+ `has_one_attached` / `has_many_attached` attributes. With JavaScript, files upload
91
+ asynchronously as soon as they are chosen or dropped, each showing a preview figure
92
+ with progress, retry on failure, and a remove control. Without JavaScript the same
93
+ field is a plain file input plus a keep/remove select per attached file — no
94
+ functionality is lost, only polish.
62
95
 
63
- ```js
64
- import govuk from "@katalyst/govuk-formbuilder";
65
- application.load(govuk);
96
+ ```erb
97
+ <%= f.govuk_image_field :avatar %>
98
+ <%= f.govuk_document_field :cv %>
99
+ <%= f.govuk_attachment_field :recording, accept: "audio/*" %>
66
100
  ```
67
101
 
102
+ Both fields delegate to `govuk_attachment_field`; they differ only in the mime types
103
+ they accept (`config.image_mime_types` / `config.document_mime_types`).
104
+
105
+ - The attribute's value must be an `ActiveStorage::Attached`; anything else raises
106
+ `ArgumentError` at render. For plain multipart uploads without ActiveStorage, use
107
+ the upstream `govuk_file_field`.
108
+ - `multiple` is inferred from the association (`has_many_attached` → multiple), and
109
+ an explicit `multiple:` argument is respected.
110
+ - Attachments round-trip as blob signed ids: when validation fails, the re-rendered
111
+ form retains every attachment — stored, direct-uploaded, or pending multipart — so
112
+ a failed submit never loses an upload.
113
+ - Removal is always offered. A required attachment should say so with a presence
114
+ validation; the form does not hide removal on its behalf.
115
+ - Direct uploads post to `rails_direct_uploads_url` by default. Pass
116
+ `direct_upload_url:` to use a different endpoint, or `direct_upload: false` to
117
+ leave chosen files in the input and submit them as ordinary multipart.
118
+ - Fields accept the standard GOV.UK options (`label:`, `hint:`, `caption:`,
119
+ `form_group:`, `before_input:`, `after_input:`) and a block for supplemental
120
+ content rendered inside the form group.
121
+
122
+ Preview thumbnails are generated lazily through ActiveStorage's representation
123
+ route. The transformation is configurable:
124
+
125
+ ```ruby
126
+ GOVUKDesignSystemFormBuilder.config.attachment_preview_representation =
127
+ { resize_to_fill: [256, 256] } # the default
128
+ ```
129
+
130
+ ### Strings and internationalisation
131
+
132
+ All user-facing strings resolve through Rails i18n under `katalyst.govuk.attachment.*`
133
+ (`upload_succeeded`, `upload_failed`, `retry_button`, `file_removed`, `remove_button`,
134
+ `remove_button_content`), alongside govuk-frontend's FileUpload strings. Each has a
135
+ per-field text option (`upload_succeeded_text`, `upload_failed_text`,
136
+ `retry_button_text`, `file_removed_text`, `remove_button_text`,
137
+ `remove_button_content_text`, `choose_files_button_text`, `drop_instruction_text`,
138
+ `no_file_chosen_text`, `multiple_files_chosen_text`, `entered_drop_zone_text`,
139
+ `left_drop_zone_text`). Strings reach the JavaScript enhancement via the field's
140
+ `data-i18n.*` attributes, with the locale taken from the closest `lang` attribute.
141
+
142
+ ## Upgrading from 1.x
143
+
144
+ This major version replaces the image/document field implementations with the
145
+ attachment field described above.
146
+
147
+ - `govuk_image_field` / `govuk_document_field` now require an
148
+ `ActiveStorage::Attached` value and raise `ArgumentError` otherwise. The legacy
149
+ fields rendered a plain enhanced input for other values (e.g. form objects) — for
150
+ those, use `govuk_file_field`.
151
+ - The `optional:` argument no longer does anything: removal is always offered, and
152
+ submitting the remove option detaches on save. A required attachment must be
153
+ guarded by a presence validation.
154
+ - Dropped files are no longer filtered by mime type on the client. The `accept`
155
+ attribute remains a file-picker courtesy; your model's validations are the
156
+ authority on content.
157
+ - `application.load(govuk)` no longer works — the default export is no longer the
158
+ controller definitions array, and Stimulus raises a `TypeError` at boot. Replace it
159
+ with `GOVUK.start(application)` (see JavaScript above), which registers the
160
+ controllers and keeps enhancement running across Turbo visits.
161
+ - Remove any `turbo:render` / `turbo:frame-load` re-initialisation wiring —
162
+ enhancement now observes the DOM and owns re-enhancement; repeated calls are
163
+ harmless no-ops.
164
+ - Text options on file fields are now honoured by the JavaScript. Previously they
165
+ rendered but were never read, so non-English sites got English announcements.
166
+ - Brand (`GOVUKDesignSystemFormBuilder.brand`) now affects CSS classes only:
167
+ Stimulus identifiers, `data-controller`/`data-action` wiring, and events are
168
+ always `govuk-*`. The gem's compiled CSS remains govuk-prefixed — a non-default
169
+ brand presumes a consumer-supplied frontend build.
170
+
171
+ As a transitional escape hatch, the legacy implementations remain available behind a
172
+ flag:
173
+
174
+ ```ruby
175
+ GOVUKDesignSystemFormBuilder.config.use_legacy_file_fields = true # default false
176
+ ```
177
+
178
+ The flag flips `govuk_image_field` / `govuk_document_field` back to the legacy
179
+ elements. It exists to stage a migration, not to stay on: the flag and the legacy
180
+ code will be removed together in a subsequent release.
181
+
182
+ ## Extensions
183
+
184
+ We include some optional extensions for integrating with gems that we (Katalyst)
185
+ commonly use. These require additional steps to use.
186
+
187
+ ### Rich text area
188
+
189
+ `govuk_rich_textarea` renders a Trix editor with GOV.UK form conventions. It
190
+ requires ActionText to be set up in your application (`rails action_text:install`),
191
+ including its JavaScript (`trix` and `@rails/actiontext`) in your bundle or
192
+ importmap.
193
+
68
194
  ### Hotwire Combobox
69
195
 
70
196
  [Hotwire Combobox](https://hotwirecombobox.com) is a promising option for adding asynchronous multi-select inputs to
@@ -995,6 +995,83 @@
995
995
  }
996
996
  }
997
997
 
998
+ :where(.govuk-attachment) {
999
+ display: grid;
1000
+ grid-template-areas: "preview caption actions";
1001
+ grid-template-columns: auto 1fr auto;
1002
+ margin: 0;
1003
+ padding: 15px 15px;
1004
+ grid-gap: 10px;
1005
+ background-color: #f3f3f3;
1006
+ border: 2px solid var(--govuk-border-colour, #cecece);
1007
+ }
1008
+ :where(.govuk-attachment) .preview {
1009
+ grid-area: preview;
1010
+ max-width: 4rem;
1011
+ aspect-ratio: 1/1;
1012
+ object-fit: cover;
1013
+ }
1014
+ :where(.govuk-attachment) .caption {
1015
+ display: flex;
1016
+ flex-direction: column;
1017
+ grid-area: caption;
1018
+ font-family: "Open Sans", sans-serif;
1019
+ -webkit-font-smoothing: antialiased;
1020
+ -moz-osx-font-smoothing: grayscale;
1021
+ }
1022
+ @media print {
1023
+ :where(.govuk-attachment) .caption {
1024
+ font-family: sans-serif;
1025
+ }
1026
+ }
1027
+ :where(.govuk-attachment) .caption {
1028
+ font-weight: 400;
1029
+ font-size: 1rem;
1030
+ line-height: 1.25;
1031
+ }
1032
+ @media print {
1033
+ :where(.govuk-attachment) .caption {
1034
+ font-size: 14pt;
1035
+ line-height: 1.25;
1036
+ }
1037
+ }
1038
+ :where(.govuk-attachment) .filename {
1039
+ font-weight: 700;
1040
+ }
1041
+ :where(.govuk-attachment) .size {
1042
+ color: var(--govuk-secondary-text-colour, #484949);
1043
+ }
1044
+ :where(.govuk-attachment) .actions {
1045
+ grid-area: actions;
1046
+ }
1047
+ :where(.govuk-attachment) .actions button {
1048
+ display: none;
1049
+ }
1050
+ :where(.govuk-attachment)[data-state=upload-successful] .status {
1051
+ color: var(--govuk-success-colour, #0f7a52);
1052
+ }
1053
+ :where(.govuk-attachment)[data-state=upload-failed] {
1054
+ border-color: var(--govuk-error-colour, #ca3535);
1055
+ }
1056
+ :where(.govuk-attachment)[data-state=upload-failed] .status {
1057
+ color: var(--govuk-error-colour, #ca3535);
1058
+ }
1059
+
1060
+ .govuk-attachment {
1061
+ margin-bottom: 10px;
1062
+ }
1063
+
1064
+ .govuk-frontend-supported :where(.govuk-attachment) .actions select {
1065
+ display: none;
1066
+ }
1067
+ .govuk-frontend-supported :where(.govuk-attachment) .actions button {
1068
+ display: revert;
1069
+ }
1070
+
1071
+ .govuk-file-upload-wrapper:has(input[type=file]:not([multiple])) .govuk-attachment:has(+ .govuk-attachment) {
1072
+ display: none;
1073
+ }
1074
+
998
1075
  .govuk-error-message {
999
1076
  font-family: "Open Sans", sans-serif;
1000
1077
  -webkit-font-smoothing: antialiased;