bard-attachment_field 0.4.2 → 0.4.3

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.
@@ -36,11 +36,9 @@ Gem::Specification.new do |spec|
36
36
  spec.add_development_dependency "cucumber"
37
37
  spec.add_development_dependency "cucumber-rails"
38
38
  spec.add_development_dependency "capybara"
39
- spec.add_development_dependency "cuprite"
40
- spec.add_development_dependency "cuprite-downloads"
39
+ spec.add_development_dependency "capybara-playwright-driver"
41
40
  spec.add_development_dependency "chop"
42
41
  spec.add_development_dependency "rspec"
43
- spec.add_development_dependency "capybara-shadowdom"
44
42
  spec.add_development_dependency "capybara-screenshot"
45
43
  spec.add_development_dependency "database_cleaner"
46
44
  spec.add_development_dependency "puma"
Binary file
@@ -11,7 +11,7 @@
11
11
  "scripts": {
12
12
  "prepublishOnly": "bun run build",
13
13
  "build": "bunx stencil build --docs && bun run bundle",
14
- "bundle": "bunx esbuild dist/components/index.js --bundle --format=esm --outfile=dist/input-attachment.esm.js --footer:js='defineCustomElements();'",
14
+ "bundle": "bunx esbuild src/entry.js --bundle --format=esm --outfile=dist/input-attachment.esm.js",
15
15
  "start": "bunx stencil build --docs --watch --serve",
16
16
  "test": "NODE_OPTIONS=--experimental-vm-modules bunx stencil test --spec --e2e --max-workers=1",
17
17
  "test:spec": "NODE_OPTIONS=--experimental-vm-modules bunx stencil test --spec --max-workers=1",
@@ -36,7 +36,7 @@
36
36
  "@botandrose/progress-bar": "^0.1.2",
37
37
  "@rails/activestorage": "^8.1.0",
38
38
  "@rails/request.js": "0.0.13",
39
- "@stencil/core": "^4.38.2",
39
+ "@stencil/core": "^4.43.2",
40
40
  "rails-request-json": "^0.2.0",
41
41
  "ts-jest": "^29.4.5"
42
42
  },
@@ -53,10 +53,10 @@ p{
53
53
  @media (prefers-color-scheme: dark) {
54
54
  :host {
55
55
  --input-attachment-text-color: #e0e0e0;
56
- --input-attachment-drop-bg: rgba(255,255,255, 0.08);
56
+ --input-attachment-drop-bg: #333;
57
57
  --input-attachment-drop-border: rgba(255,255,255, 0.25);
58
58
  --input-attachment-drop-color: #bbb;
59
- --input-attachment-drop-bg-active: rgba(255,255,255, 0.15);
59
+ --input-attachment-drop-bg-active: #444;
60
60
  --input-attachment-error-color: #f66;
61
61
  }
62
62
  }
@@ -20,7 +20,7 @@ describe('input-attachment', () => {
20
20
  expect(page.root).toEqualHtml(`
21
21
  <input-attachment>
22
22
  <mock:shadow-root>
23
- <input type="file" style="opacity: 0.01; width: 1px; height: 1px; z-index: -999;">
23
+ <input aria-label="Choose file" type="file" style="opacity: 0.01; width: 1px; height: 1px; z-index: -999;">
24
24
  <file-drop>
25
25
  <p part="title">
26
26
  <strong>Choose file </strong>
@@ -188,6 +188,7 @@ export class InputAttachment {
188
188
  <input
189
189
  ref={el => this.fileInput = el}
190
190
  type="file"
191
+ aria-label={`Choose ${this.multiple ? "files" : "file"}`}
191
192
  multiple={this.multiple}
192
193
  accept={this.accepts}
193
194
  required={this.required && this.files.length === 0}
@@ -165,6 +165,10 @@ declare namespace LocalJSX {
165
165
  * @default false
166
166
  */
167
167
  "disabled"?: boolean;
168
+ /**
169
+ * The `id` of a `<form>` element to associate this element with.
170
+ */
171
+ "form"?: string;
168
172
  "max"?: number;
169
173
  /**
170
174
  * @default false
@@ -186,10 +190,42 @@ declare namespace LocalJSX {
186
190
  }
187
191
  interface UploadDialog {
188
192
  }
193
+
194
+ interface AttachmentFileAttributes {
195
+ "name": string;
196
+ "accepts": string;
197
+ "max": number;
198
+ "url": string;
199
+ "value": string;
200
+ "filename": string;
201
+ "src": string;
202
+ "filetype": string;
203
+ "size": number;
204
+ "state": string;
205
+ "percent": number;
206
+ "preview": boolean;
207
+ "validationMessage": string;
208
+ }
209
+ interface AttachmentPreviewAttributes {
210
+ "src": string;
211
+ "filetype": string;
212
+ }
213
+ interface InputAttachmentAttributes {
214
+ "name": string;
215
+ "directupload": string;
216
+ "multiple": boolean;
217
+ "required": boolean;
218
+ "accepts": string;
219
+ "max": number;
220
+ "preview": boolean;
221
+ "disabled": boolean;
222
+ "uploadDialog": boolean;
223
+ }
224
+
189
225
  interface IntrinsicElements {
190
- "attachment-file": AttachmentFile;
191
- "attachment-preview": AttachmentPreview;
192
- "input-attachment": InputAttachment;
226
+ "attachment-file": Omit<AttachmentFile, keyof AttachmentFileAttributes> & { [K in keyof AttachmentFile & keyof AttachmentFileAttributes]?: AttachmentFile[K] } & { [K in keyof AttachmentFile & keyof AttachmentFileAttributes as `attr:${K}`]?: AttachmentFileAttributes[K] } & { [K in keyof AttachmentFile & keyof AttachmentFileAttributes as `prop:${K}`]?: AttachmentFile[K] };
227
+ "attachment-preview": Omit<AttachmentPreview, keyof AttachmentPreviewAttributes> & { [K in keyof AttachmentPreview & keyof AttachmentPreviewAttributes]?: AttachmentPreview[K] } & { [K in keyof AttachmentPreview & keyof AttachmentPreviewAttributes as `attr:${K}`]?: AttachmentPreviewAttributes[K] } & { [K in keyof AttachmentPreview & keyof AttachmentPreviewAttributes as `prop:${K}`]?: AttachmentPreview[K] };
228
+ "input-attachment": Omit<InputAttachment, keyof InputAttachmentAttributes> & { [K in keyof InputAttachment & keyof InputAttachmentAttributes]?: InputAttachment[K] } & { [K in keyof InputAttachment & keyof InputAttachmentAttributes as `attr:${K}`]?: InputAttachmentAttributes[K] } & { [K in keyof InputAttachment & keyof InputAttachmentAttributes as `prop:${K}`]?: InputAttachment[K] };
193
229
  "upload-dialog": UploadDialog;
194
230
  }
195
231
  }
@@ -197,10 +233,10 @@ export { LocalJSX as JSX };
197
233
  declare module "@stencil/core" {
198
234
  export namespace JSX {
199
235
  interface IntrinsicElements {
200
- "attachment-file": LocalJSX.AttachmentFile & JSXBase.HTMLAttributes<HTMLAttachmentFileElement>;
201
- "attachment-preview": LocalJSX.AttachmentPreview & JSXBase.HTMLAttributes<HTMLAttachmentPreviewElement>;
202
- "input-attachment": LocalJSX.InputAttachment & JSXBase.HTMLAttributes<HTMLInputAttachmentElement>;
203
- "upload-dialog": LocalJSX.UploadDialog & JSXBase.HTMLAttributes<HTMLUploadDialogElement>;
236
+ "attachment-file": LocalJSX.IntrinsicElements["attachment-file"] & JSXBase.HTMLAttributes<HTMLAttachmentFileElement>;
237
+ "attachment-preview": LocalJSX.IntrinsicElements["attachment-preview"] & JSXBase.HTMLAttributes<HTMLAttachmentPreviewElement>;
238
+ "input-attachment": LocalJSX.IntrinsicElements["input-attachment"] & JSXBase.HTMLAttributes<HTMLInputAttachmentElement>;
239
+ "upload-dialog": LocalJSX.IntrinsicElements["upload-dialog"] & JSXBase.HTMLAttributes<HTMLUploadDialogElement>;
204
240
  }
205
241
  }
206
242
  }
@@ -0,0 +1,3 @@
1
+ export * from "../dist/components/index.js"
2
+ import { defineCustomElements } from "../dist/components/index.js"
3
+ defineCustomElements()
@@ -4,9 +4,9 @@
4
4
  #
5
5
  # Provides step definitions and helpers for testing attachment fields.
6
6
  #
7
- # Note: CDP's DOM.setFileInputFiles silently fails for file inputs inside shadow DOM.
8
- # This integration uses a workaround that creates a temporary regular DOM input to
9
- # receive files via CDP, then transfers them to the component via its addFiles() method.
7
+ # Note: Browser automation APIs can't reliably set files on inputs inside shadow DOM.
8
+ # This integration uses a workaround that creates a temporary regular DOM input,
9
+ # sets files on it, then transfers them to the component via its addFiles() method.
10
10
 
11
11
  require "active_support/core_ext/module/attribute_accessors"
12
12
  require "chop"
@@ -33,17 +33,17 @@ module Bard::AttachmentField::TestHelper
33
33
  session.find("input-attachment##{element_id}")
34
34
  end
35
35
 
36
- # CDP's setFileInputFiles fails silently for file inputs inside shadow DOM,
36
+ # File inputs inside shadow DOM can't be set directly by browser automation,
37
37
  # so we use a temp regular DOM input and transfer files via JavaScript.
38
38
  def attach_files(session, element_id, file_paths)
39
- session.execute_script("document.body.insertAdjacentHTML('beforeend', '<input type=\"file\" id=\"_cdp_file_helper\" multiple style=\"display:none\">')")
39
+ session.execute_script("document.body.insertAdjacentHTML('beforeend', '<input type=\"file\" id=\"_pw_file_helper\" multiple style=\"opacity:0;position:absolute;pointer-events:none\">')")
40
40
 
41
- temp_input = session.document.find("#_cdp_file_helper", visible: :all)
42
- temp_input.native.node.select_file(file_paths)
41
+ temp_input = session.document.find("#_pw_file_helper", visible: :all)
42
+ temp_input.set(file_paths)
43
43
 
44
44
  session.execute_script(<<~JS)
45
45
  (() => {
46
- const temp = document.getElementById('_cdp_file_helper');
46
+ const temp = document.getElementById('_pw_file_helper');
47
47
  const host = document.getElementById('#{element_id}');
48
48
  host.addFiles(temp.files);
49
49
  temp.remove();
@@ -236,14 +236,14 @@ When "I drag the file {string} onto the {string} attachment field" do |path, fie
236
236
  element = Bard::AttachmentField::TestHelper.find_field(page, field)
237
237
  file_path_full = Bard::AttachmentField::TestHelper.resolve_fixture_path(path)
238
238
 
239
- # Create temp input to get File objects via CDP, then dispatch drop event on file-drop
240
- page.execute_script("document.body.insertAdjacentHTML('beforeend', '<input type=\"file\" id=\"_cdp_file_helper\" multiple style=\"display:none\">')")
241
- temp_input = page.find("#_cdp_file_helper", visible: :all)
242
- temp_input.native.node.select_file([file_path_full])
239
+ # Create temp input to get File objects, then dispatch drop event on file-drop
240
+ page.execute_script("document.body.insertAdjacentHTML('beforeend', '<input type=\"file\" id=\"_pw_file_helper\" multiple style=\"opacity:0;position:absolute;pointer-events:none\">')")
241
+ temp_input = page.find("#_pw_file_helper", visible: :all)
242
+ temp_input.set([file_path_full])
243
243
 
244
244
  page.execute_script(<<~JS, element[:id])
245
245
  ((elementId) => {
246
- const temp = document.getElementById('_cdp_file_helper');
246
+ const temp = document.getElementById('_pw_file_helper');
247
247
  const host = document.getElementById(elementId);
248
248
  const fileDrop = host.shadowRoot.querySelector('file-drop');
249
249
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Bard
4
4
  module AttachmentField
5
- VERSION = "0.4.2"
5
+ VERSION = "0.4.3"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bard-attachment_field
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Micah Geisel
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-03-18 00:00:00.000000000 Z
11
+ date: 2026-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activestorage
@@ -109,21 +109,7 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: cuprite
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: cuprite-downloads
112
+ name: capybara-playwright-driver
127
113
  requirement: !ruby/object:Gem::Requirement
128
114
  requirements:
129
115
  - - ">="
@@ -164,20 +150,6 @@ dependencies:
164
150
  - - ">="
165
151
  - !ruby/object:Gem::Version
166
152
  version: '0'
167
- - !ruby/object:Gem::Dependency
168
- name: capybara-shadowdom
169
- requirement: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - ">="
172
- - !ruby/object:Gem::Version
173
- version: '0'
174
- type: :development
175
- prerelease: false
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - ">="
179
- - !ruby/object:Gem::Version
180
- version: '0'
181
153
  - !ruby/object:Gem::Dependency
182
154
  name: capybara-screenshot
183
155
  requirement: !ruby/object:Gem::Requirement
@@ -371,6 +343,7 @@ files:
371
343
  - input-attachment/src/components/upload-dialog/readme.md
372
344
  - input-attachment/src/components/upload-dialog/upload-dialog.css
373
345
  - input-attachment/src/components/upload-dialog/upload-dialog.tsx
346
+ - input-attachment/src/entry.js
374
347
  - input-attachment/src/global.d.ts
375
348
  - input-attachment/src/images/example.jpg
376
349
  - input-attachment/src/index.html