feedback_engine 0.3.0 → 0.4.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: 156ebb1c4481df5db12c92701ca07f5199f033aa967f264aa855caf327f4542a
4
- data.tar.gz: f59ef8d27b7539d16f03eaef38abc4d6ce51ee55cdd630a738433ca7f3463ef7
3
+ metadata.gz: 12457e35c33daf8032e5eae4336964217b969d4d45d8d8a13ca85f6706833e26
4
+ data.tar.gz: 82ce331114ef1a88718e9879f7a263c6ea89456d0fb32c098804431df8fa6106
5
5
  SHA512:
6
- metadata.gz: 827983bd43f6d4b9af39b6d526f2d14755365ce561cfdbb338e240e97a2a54afa2173e0efb645846078d107c7ee234de27356e9814acbdbd891f8d7116e6a30b
7
- data.tar.gz: 3f311aeb99159a9d538ddd87e8d346d7b2bd7d10b4521fcec6e864945801eba2ccf9a5e58bf2ebd65034189379647dabf50d60bc5e421924cb2b012468953481
6
+ metadata.gz: 16ab901cdc39fbd5dfa1c26ef896717610f8da85a2afd96348bfbaa1b13b196b4d9e12e6fb8d47f2194d0bd86e6ba46729f88e86a3e5089f853ab9dbdfff097c
7
+ data.tar.gz: ee81a5410c06cfaaea26f143ef0ce2bccde945d2d1826e68e30b90f154191e4178cac1f2b2f8279465ccf22b1f20810ca8f9aa2828f6ab184594e7582b56ec2a
data/CHANGELOG.md CHANGED
@@ -1,11 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0 (2026-07-22)
4
+
5
+ - Removed the clipboard-paste / drag-and-drop / file-chips screenshot intake
6
+ added in 0.3.0 — pasted files all arrive as `image.png` and the extra UI
7
+ wasn't worth its complexity. Screenshots are back to a plain file input.
8
+
3
9
  ## 0.3.0 (2026-07-22)
4
10
 
5
- - Screenshots can now be pasted (Cmd/Ctrl+V) or dragged & dropped anywhere on
11
+ - Screenshots can be pasted (Cmd/Ctrl+V) or dragged & dropped anywhere on
6
12
  the feedback form, not just picked via the file dialog. Selected files show
7
13
  as removable chips; non-images are ignored and the configured maximum is
8
- enforced at intake.
14
+ enforced at intake. (Removed again in 0.4.0.)
9
15
  - The dialog traps Tab focus while open and is labelled for screen readers
10
16
  (`aria-labelledby`).
11
17
  - Dashboard search across message, author, and section (case-insensitive,
data/README.md CHANGED
@@ -20,8 +20,7 @@ app.
20
20
  - **Trigger it your way.** Use the built-in floating button, or hide it and
21
21
  open the form from any element with a `data-feedback-engine-open` attribute.
22
22
  - **Screenshots included.** Users can attach up to 3 images (via Active
23
- Storage) — picked, pasted (Cmd/Ctrl+V), or dragged onto the form. Limits are
24
- configurable and enforced server-side.
23
+ Storage) — limits are configurable and enforced server-side.
25
24
  - **Pluggable gating and attribution.** You decide who can send feedback, who
26
25
  can read it, and how a submission is attributed to a user.
27
26
  - **Localized.** The widget follows your app's `I18n.locale`; translations ship
@@ -177,11 +176,9 @@ end
177
176
  ### Screenshots
178
177
 
179
178
  Uploads use Active Storage: `bin/rails active_storage:install` if you haven't
180
- already. Users can pick files, paste an image from the clipboard, or drag &
181
- drop onto the form; selected files show as removable chips. Limits
182
- (`max_screenshots`, `max_screenshot_size`) are enforced server-side and shown
183
- as a hint in the widget. If Active Storage isn't loaded, the upload control
184
- simply doesn't render and uploads are rejected.
179
+ already. Limits (`max_screenshots`, `max_screenshot_size`) are enforced
180
+ server-side and shown as a hint in the widget. If Active Storage isn't loaded,
181
+ the upload control simply doesn't render and uploads are rejected.
185
182
 
186
183
  ### Notifications
187
184
 
@@ -20,8 +20,6 @@
20
20
  var Z = 2147483000;
21
21
  var overlay = null;
22
22
  var lastFocused = null;
23
- var fileInput = null;
24
- var fileChips = null;
25
23
 
26
24
  function ready(fn) {
27
25
  if (document.readyState === "loading") {
@@ -114,25 +112,6 @@
114
112
  // Keep Tab (and Shift+Tab) cycling inside the dialog while it is open.
115
113
  overlay.addEventListener("keydown", trapFocus);
116
114
 
117
- // Screenshots can be pasted (Cmd/Ctrl+V) or dropped anywhere on the form —
118
- // the file picker is just one way in.
119
- if (config.screenshots.enabled) {
120
- dialog.addEventListener("paste", function (event) {
121
- var files = event.clipboardData && event.clipboardData.files;
122
- if (files && files.length) {
123
- event.preventDefault();
124
- addFiles(files);
125
- }
126
- });
127
- dialog.addEventListener("dragover", function (event) {
128
- event.preventDefault();
129
- });
130
- dialog.addEventListener("drop", function (event) {
131
- event.preventDefault();
132
- if (event.dataTransfer) addFiles(event.dataTransfer.files);
133
- });
134
- }
135
-
136
115
  var first = dialog.querySelector("select, textarea, input");
137
116
  if (first) first.focus();
138
117
  }
@@ -141,8 +120,6 @@
141
120
  if (!overlay) return;
142
121
  overlay.remove();
143
122
  overlay = null;
144
- fileInput = null;
145
- fileChips = null;
146
123
  if (lastFocused && lastFocused.focus) lastFocused.focus();
147
124
  }
148
125
 
@@ -265,69 +242,19 @@
265
242
  }
266
243
 
267
244
  function screenshotsField() {
268
- fileInput = document.createElement("input");
269
- fileInput.type = "file";
270
- fileInput.name = "screenshots";
271
- fileInput.multiple = true;
272
- fileInput.accept = "image/*";
273
- fileInput.addEventListener("change", renderFileChips);
274
- var wrap = field(config.labels.screenshots, fileInput);
245
+ var input = document.createElement("input");
246
+ input.type = "file";
247
+ input.name = "screenshots";
248
+ input.multiple = true;
249
+ input.accept = "image/*";
250
+ var wrap = field(config.labels.screenshots, input);
275
251
  var hint = document.createElement("span");
276
252
  hint.className = "fbe-hint";
277
253
  hint.textContent = config.labels.screenshotsHint;
278
254
  wrap.appendChild(hint);
279
- fileChips = document.createElement("ul");
280
- fileChips.className = "fbe-chips";
281
- wrap.appendChild(fileChips);
282
255
  return wrap;
283
256
  }
284
257
 
285
- // Merge pasted/dropped images into the file input (the single source of
286
- // truth for what gets uploaded), capped at the configured maximum.
287
- function addFiles(files) {
288
- if (!fileInput) return;
289
- var transfer = new DataTransfer();
290
- var current = Array.prototype.slice.call(fileInput.files);
291
- var incoming = Array.prototype.slice.call(files).filter(function (file) {
292
- return /^image\//.test(file.type);
293
- });
294
- current.concat(incoming).slice(0, config.screenshots.max).forEach(function (file) {
295
- transfer.items.add(file);
296
- });
297
- fileInput.files = transfer.files;
298
- renderFileChips();
299
- }
300
-
301
- function removeFile(index) {
302
- if (!fileInput) return;
303
- var transfer = new DataTransfer();
304
- Array.prototype.slice.call(fileInput.files).forEach(function (file, i) {
305
- if (i !== index) transfer.items.add(file);
306
- });
307
- fileInput.files = transfer.files;
308
- renderFileChips();
309
- }
310
-
311
- function renderFileChips() {
312
- if (!fileChips) return;
313
- fileChips.textContent = "";
314
- Array.prototype.slice.call(fileInput.files).forEach(function (file, index) {
315
- var chip = document.createElement("li");
316
- var name = document.createElement("span");
317
- name.textContent = file.name;
318
- var remove = document.createElement("button");
319
- remove.type = "button";
320
- remove.setAttribute("aria-label", config.labels.close + " " + file.name);
321
- remove.textContent = "×";
322
- remove.addEventListener("click", function () {
323
- removeFile(index);
324
- });
325
- chip.appendChild(name);
326
- chip.appendChild(remove);
327
- fileChips.appendChild(chip);
328
- });
329
- }
330
-
331
258
  // --- submit -------------------------------------------------------------------
332
259
 
333
260
  function submit(form) {
@@ -436,12 +363,6 @@
436
363
  "border:1px solid #d1d5db;border-radius:6px;background:none;color:#1c2024;font:inherit;cursor:pointer}",
437
364
  "#fbe-dialog textarea{resize:vertical}",
438
365
  "#fbe-dialog .fbe-hint{display:block;margin-top:4px;font-size:12px;color:#6b7280;font-weight:400}",
439
- "#fbe-dialog .fbe-chips{list-style:none;margin:6px 0 0;padding:0;display:flex;flex-wrap:wrap;gap:6px}",
440
- "#fbe-dialog .fbe-chips li{display:flex;align-items:center;gap:4px;max-width:100%;",
441
- "padding:2px 4px 2px 10px;border:1px solid #d1d5db;border-radius:999px;font-size:12px;font-weight:400}",
442
- "#fbe-dialog .fbe-chips span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}",
443
- "#fbe-dialog .fbe-chips button{border:0;background:none;color:inherit;cursor:pointer;",
444
- "font-size:14px;line-height:1;padding:2px 6px}",
445
366
  "#fbe-dialog .fbe-error{color:#dc2626;margin:0 0 12px}",
446
367
  "#fbe-dialog .fbe-actions{display:flex;justify-content:flex-end;gap:8px}",
447
368
  "#fbe-dialog button{padding:8px 14px;border-radius:8px;cursor:pointer;font:inherit}",
@@ -454,7 +375,6 @@
454
375
  "#fbe-dialog select,#fbe-dialog textarea,#fbe-dialog input[type=file]{border-color:#2a313a}",
455
376
  "#fbe-dialog input[type=file]{color:#9aa2ab}",
456
377
  "#fbe-dialog input[type=file]::file-selector-button{border-color:#2a313a;color:#e6e8ea}",
457
- "#fbe-dialog .fbe-chips li{border-color:#2a313a}",
458
378
  "#fbe-dialog .fbe-secondary{border-color:#2a313a}",
459
379
  "#fbe-dialog .fbe-hint{color:#9aa2ab}",
460
380
  "}"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FeedbackEngine
4
- VERSION = '0.3.0'
4
+ VERSION = '0.4.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: feedback_engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yaroslav Shmarov