hotwire_combobox 0.1.19 → 0.1.21

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a775e0facfeadc8692735916fa883634dd6e27b8069f0222d019ac965301640
4
- data.tar.gz: 2961eb0baa6b5391e39f804037ece8e0ac7912d625a72bf52d280aa34da7fa41
3
+ metadata.gz: b2379931d2dd9ef8e6b6a4968f3c204d0c3626512276a5d16d680ad2972e1ae1
4
+ data.tar.gz: e41b852d34f7de2e1c43550b6b1ef5e2c9b961b9e1fa666829d9af0462c60745
5
5
  SHA512:
6
- metadata.gz: d01630a09a9ab1b665315613ed4e08c9d630c48c9d175f9d72c41284e9c7638cc6c7667f883676899342acb45d041688b1c1ea0cabe7e21269484bdbb7ba8c9e
7
- data.tar.gz: 99721fffb5e3a7c26da281024c6102b0c88767b1cd8fec296c6231a04608b3d31a2c6dcf22420314dfdd8b2a2fce7663b5ec5ecc065cc88063c6aa5eae7500e2
6
+ metadata.gz: b5a4066ae217cc3812f59ca32966812c917560562c2be0ed036cdcb8c8a8c8ecb9afd305029ca520cf456aaa20d90fcb42de62aaf045318bf9fbf1a770453eb8
7
+ data.tar.gz: ab66935eed08d18c5971e7e02883f089750024ce965c6f6db73567038e46ca6778a1e1e94558d85603cc153dc55c0885854436acfb9020e12520d1fd1d3800ed
@@ -0,0 +1,2 @@
1
+ //= link_directory ../stylesheets .css
2
+ //= link_tree ../javascripts .js
@@ -1,7 +1,7 @@
1
1
 
2
2
  import Combobox from "models/combobox/base"
3
3
  import { applyFilter, nextFrame, debounce } from "helpers"
4
- import { get } from "@rails/request.js"
4
+ import { get } from "vendor/requestjs"
5
5
 
6
6
  Combobox.Filtering = Base => class extends Base {
7
7
  filter(event) {
@@ -0,0 +1,298 @@
1
+ class FetchResponse {
2
+ constructor(response) {
3
+ this.response = response;
4
+ }
5
+ get statusCode() {
6
+ return this.response.status;
7
+ }
8
+ get redirected() {
9
+ return this.response.redirected;
10
+ }
11
+ get ok() {
12
+ return this.response.ok;
13
+ }
14
+ get unauthenticated() {
15
+ return this.statusCode === 401;
16
+ }
17
+ get unprocessableEntity() {
18
+ return this.statusCode === 422;
19
+ }
20
+ get authenticationURL() {
21
+ return this.response.headers.get("WWW-Authenticate");
22
+ }
23
+ get contentType() {
24
+ const contentType = this.response.headers.get("Content-Type") || "";
25
+ return contentType.replace(/;.*$/, "");
26
+ }
27
+ get headers() {
28
+ return this.response.headers;
29
+ }
30
+ get html() {
31
+ if (this.contentType.match(/^(application|text)\/(html|xhtml\+xml)$/)) {
32
+ return this.text;
33
+ }
34
+ return Promise.reject(new Error(`Expected an HTML response but got "${this.contentType}" instead`));
35
+ }
36
+ get json() {
37
+ if (this.contentType.match(/^application\/.*json$/)) {
38
+ return this.responseJson || (this.responseJson = this.response.json());
39
+ }
40
+ return Promise.reject(new Error(`Expected a JSON response but got "${this.contentType}" instead`));
41
+ }
42
+ get text() {
43
+ return this.responseText || (this.responseText = this.response.text());
44
+ }
45
+ get isTurboStream() {
46
+ return this.contentType.match(/^text\/vnd\.turbo-stream\.html/);
47
+ }
48
+ async renderTurboStream() {
49
+ if (this.isTurboStream) {
50
+ if (window.Turbo) {
51
+ await window.Turbo.renderStreamMessage(await this.text);
52
+ } else {
53
+ console.warn("You must set `window.Turbo = Turbo` to automatically process Turbo Stream events with request.js");
54
+ }
55
+ } else {
56
+ return Promise.reject(new Error(`Expected a Turbo Stream response but got "${this.contentType}" instead`));
57
+ }
58
+ }
59
+ }
60
+
61
+ class RequestInterceptor {
62
+ static register(interceptor) {
63
+ this.interceptor = interceptor;
64
+ }
65
+ static get() {
66
+ return this.interceptor;
67
+ }
68
+ static reset() {
69
+ this.interceptor = undefined;
70
+ }
71
+ }
72
+
73
+ function getCookie(name) {
74
+ const cookies = document.cookie ? document.cookie.split("; ") : [];
75
+ const prefix = `${encodeURIComponent(name)}=`;
76
+ const cookie = cookies.find((cookie => cookie.startsWith(prefix)));
77
+ if (cookie) {
78
+ const value = cookie.split("=").slice(1).join("=");
79
+ if (value) {
80
+ return decodeURIComponent(value);
81
+ }
82
+ }
83
+ }
84
+
85
+ function compact(object) {
86
+ const result = {};
87
+ for (const key in object) {
88
+ const value = object[key];
89
+ if (value !== undefined) {
90
+ result[key] = value;
91
+ }
92
+ }
93
+ return result;
94
+ }
95
+
96
+ function metaContent(name) {
97
+ const element = document.head.querySelector(`meta[name="${name}"]`);
98
+ return element && element.content;
99
+ }
100
+
101
+ function stringEntriesFromFormData(formData) {
102
+ return [ ...formData ].reduce(((entries, [name, value]) => entries.concat(typeof value === "string" ? [ [ name, value ] ] : [])), []);
103
+ }
104
+
105
+ function mergeEntries(searchParams, entries) {
106
+ for (const [name, value] of entries) {
107
+ if (value instanceof window.File) continue;
108
+ if (searchParams.has(name) && !name.includes("[]")) {
109
+ searchParams.delete(name);
110
+ searchParams.set(name, value);
111
+ } else {
112
+ searchParams.append(name, value);
113
+ }
114
+ }
115
+ }
116
+
117
+ class FetchRequest {
118
+ constructor(method, url, options = {}) {
119
+ this.method = method;
120
+ this.options = options;
121
+ this.originalUrl = url.toString();
122
+ }
123
+ async perform() {
124
+ try {
125
+ const requestInterceptor = RequestInterceptor.get();
126
+ if (requestInterceptor) {
127
+ await requestInterceptor(this);
128
+ }
129
+ } catch (error) {
130
+ console.error(error);
131
+ }
132
+ const response = new FetchResponse(await window.fetch(this.url, this.fetchOptions));
133
+ if (response.unauthenticated && response.authenticationURL) {
134
+ return Promise.reject(window.location.href = response.authenticationURL);
135
+ }
136
+ const responseStatusIsTurboStreamable = response.ok || response.unprocessableEntity;
137
+ if (responseStatusIsTurboStreamable && response.isTurboStream) {
138
+ await response.renderTurboStream();
139
+ }
140
+ return response;
141
+ }
142
+ addHeader(key, value) {
143
+ const headers = this.additionalHeaders;
144
+ headers[key] = value;
145
+ this.options.headers = headers;
146
+ }
147
+ sameHostname() {
148
+ if (!this.originalUrl.startsWith("http:")) {
149
+ return true;
150
+ }
151
+ try {
152
+ return new URL(this.originalUrl).hostname === window.location.hostname;
153
+ } catch (_) {
154
+ return true;
155
+ }
156
+ }
157
+ get fetchOptions() {
158
+ return {
159
+ method: this.method.toUpperCase(),
160
+ headers: this.headers,
161
+ body: this.formattedBody,
162
+ signal: this.signal,
163
+ credentials: this.credentials,
164
+ redirect: this.redirect
165
+ };
166
+ }
167
+ get headers() {
168
+ const baseHeaders = {
169
+ "X-Requested-With": "XMLHttpRequest",
170
+ "Content-Type": this.contentType,
171
+ Accept: this.accept
172
+ };
173
+ if (this.sameHostname()) {
174
+ baseHeaders["X-CSRF-Token"] = this.csrfToken;
175
+ }
176
+ return compact(Object.assign(baseHeaders, this.additionalHeaders));
177
+ }
178
+ get csrfToken() {
179
+ return getCookie(metaContent("csrf-param")) || metaContent("csrf-token");
180
+ }
181
+ get contentType() {
182
+ if (this.options.contentType) {
183
+ return this.options.contentType;
184
+ } else if (this.body == null || this.body instanceof window.FormData) {
185
+ return undefined;
186
+ } else if (this.body instanceof window.File) {
187
+ return this.body.type;
188
+ }
189
+ return "application/json";
190
+ }
191
+ get accept() {
192
+ switch (this.responseKind) {
193
+ case "html":
194
+ return "text/html, application/xhtml+xml";
195
+
196
+ case "turbo-stream":
197
+ return "text/vnd.turbo-stream.html, text/html, application/xhtml+xml";
198
+
199
+ case "json":
200
+ return "application/json, application/vnd.api+json";
201
+
202
+ default:
203
+ return "*/*";
204
+ }
205
+ }
206
+ get body() {
207
+ return this.options.body;
208
+ }
209
+ get query() {
210
+ const originalQuery = (this.originalUrl.split("?")[1] || "").split("#")[0];
211
+ const params = new URLSearchParams(originalQuery);
212
+ let requestQuery = this.options.query;
213
+ if (requestQuery instanceof window.FormData) {
214
+ requestQuery = stringEntriesFromFormData(requestQuery);
215
+ } else if (requestQuery instanceof window.URLSearchParams) {
216
+ requestQuery = requestQuery.entries();
217
+ } else {
218
+ requestQuery = Object.entries(requestQuery || {});
219
+ }
220
+ mergeEntries(params, requestQuery);
221
+ const query = params.toString();
222
+ return query.length > 0 ? `?${query}` : "";
223
+ }
224
+ get url() {
225
+ return this.originalUrl.split("?")[0].split("#")[0] + this.query;
226
+ }
227
+ get responseKind() {
228
+ return this.options.responseKind || "html";
229
+ }
230
+ get signal() {
231
+ return this.options.signal;
232
+ }
233
+ get redirect() {
234
+ return this.options.redirect || "follow";
235
+ }
236
+ get credentials() {
237
+ return this.options.credentials || "same-origin";
238
+ }
239
+ get additionalHeaders() {
240
+ return this.options.headers || {};
241
+ }
242
+ get formattedBody() {
243
+ const bodyIsAString = Object.prototype.toString.call(this.body) === "[object String]";
244
+ const contentTypeIsJson = this.headers["Content-Type"] === "application/json";
245
+ if (contentTypeIsJson && !bodyIsAString) {
246
+ return JSON.stringify(this.body);
247
+ }
248
+ return this.body;
249
+ }
250
+ }
251
+
252
+ async function get(url, options) {
253
+ const request = new FetchRequest("get", url, options);
254
+ return request.perform();
255
+ }
256
+
257
+ async function post(url, options) {
258
+ const request = new FetchRequest("post", url, options);
259
+ return request.perform();
260
+ }
261
+
262
+ async function put(url, options) {
263
+ const request = new FetchRequest("put", url, options);
264
+ return request.perform();
265
+ }
266
+
267
+ async function patch(url, options) {
268
+ const request = new FetchRequest("patch", url, options);
269
+ return request.perform();
270
+ }
271
+
272
+ async function destroy(url, options) {
273
+ const request = new FetchRequest("delete", url, options);
274
+ return request.perform();
275
+ }
276
+
277
+ export { FetchRequest, FetchResponse, RequestInterceptor, destroy, get, patch, post, put };
278
+
279
+ // Copyright (c) 2021 Marcelo Lauxen
280
+
281
+ // Permission is hereby granted, free of charge, to any person obtaining
282
+ // a copy of this software and associated documentation files (the
283
+ // "Software"), to deal in the Software without restriction, including
284
+ // without limitation the rights to use, copy, modify, merge, publish,
285
+ // distribute, sublicense, and/or sell copies of the Software, and to
286
+ // permit persons to whom the Software is furnished to do so, subject to
287
+ // the following conditions:
288
+
289
+ // The above copyright notice and this permission notice shall be
290
+ // included in all copies or substantial portions of the Software.
291
+
292
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
293
+ // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
294
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
295
+ // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
296
+ // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
297
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
298
+ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -26,10 +26,7 @@ module HotwireCombobox
26
26
 
27
27
  initializer "hotwire_combobox.assets.precompile" do |app|
28
28
  if Rails.application.config.respond_to?(:assets)
29
- Dir.glob(Engine.root.join("app/assets/**/*.{js,css}")).each do |path|
30
- logical_path = Pathname.new(path).relative_path_from(Pathname.new(Engine.root.join("app/assets"))).to_s
31
- app.config.assets.precompile << logical_path
32
- end
29
+ app.config.assets.precompile << "hw_combobox_manifest.js"
33
30
  end
34
31
  end
35
32
  end
@@ -1,3 +1,3 @@
1
1
  module HotwireCombobox
2
- VERSION = "0.1.19"
2
+ VERSION = "0.1.21"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hotwire_combobox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.19
4
+ version: 0.1.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jose Farias
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 7.0.7.2
27
- - !ruby/object:Gem::Dependency
28
- name: importmap-rails
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '1.2'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '1.2'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: stimulus-rails
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -66,20 +52,6 @@ dependencies:
66
52
  - - ">="
67
53
  - !ruby/object:Gem::Version
68
54
  version: '1.2'
69
- - !ruby/object:Gem::Dependency
70
- name: requestjs-rails
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: 0.0.11
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: 0.0.11
83
55
  description: A combobox implementation for Ruby on Rails apps using Hotwire.
84
56
  email:
85
57
  - jose@farias.mx
@@ -90,6 +62,7 @@ files:
90
62
  - MIT-LICENSE
91
63
  - README.md
92
64
  - Rakefile
65
+ - app/assets/config/hw_combobox_manifest.js
93
66
  - app/assets/javascripts/controllers/application.js
94
67
  - app/assets/javascripts/controllers/hw_combobox_controller.js
95
68
  - app/assets/javascripts/controllers/index.js
@@ -108,6 +81,7 @@ files:
108
81
  - app/assets/javascripts/models/combobox/toggle.js
109
82
  - app/assets/javascripts/models/combobox/validity.js
110
83
  - app/assets/javascripts/vendor/bodyScrollLock.js
84
+ - app/assets/javascripts/vendor/requestjs.js
111
85
  - app/assets/stylesheets/hotwire_combobox.css
112
86
  - app/helpers/hotwire_combobox/helper.rb
113
87
  - app/presenters/hotwire_combobox/component.rb