hotwire_combobox 0.1.20 → 0.1.22

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: c9a3f3fe4f81cae0c51f95b6037012389fac56c391c0550fb9fe2c8e7343e5a6
4
- data.tar.gz: d6d4d3c408817ae41f702aa723711910e2e48e8b11ae67024a126f696295198c
3
+ metadata.gz: ab645f3a815ce20c339f0bf1227510c5de0bd6d590118d83536cf2f32126b0be
4
+ data.tar.gz: 735eddb274db3b6ccd7b774b6799a3259d7261114c3b9b710c7aefbb2c55f5b9
5
5
  SHA512:
6
- metadata.gz: 006ead653d067fbf6775600b889a3ec2fab2987f7796c64fe16df17a5806ea65bb8ef465b1e9d852b09109e567f00a093ab59189c66816add8cf0904adf934c7
7
- data.tar.gz: 3c5dc978a6ef14b3e8be7c3c8112aa3fd290a7103e4fd6849a2e387ae1df70b6b074e8351429e54d9f72664075932ffd0612576d4f944c2c919b5053ed5c5076
6
+ metadata.gz: 25c240ccd71c1c94d004011ca1ed1897b97e137f03886ec191ef1e69b678b674edd5d6c6af9c981ca0aac682424a37c8a9ba485c6d9421d3ec8822a6aee79e04
7
+ data.tar.gz: 373b3daf3510be12793192d4b88150930ef0f1f61c8cc0b84d4b1a5ffbe6bf01a2a08b7246d04a9e34d471682080010ec39630c81097c793e24ddb9a10b7d01b
@@ -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.
@@ -30,7 +30,7 @@
30
30
  --hw-line-height: 1.5rem;
31
31
 
32
32
  --hw-listbox-height: calc(var(--hw-line-height) * 10);
33
- --hw-listbox-offset-top: var(--hw-line-height);
33
+ --hw-listbox-offset-top: calc(var(--hw-line-height) * 1.625);
34
34
  --hw-listbox-z-index: 10;
35
35
 
36
36
  --hw-option-bg-color: #FFFFFF;
@@ -1,3 +1,3 @@
1
1
  module HotwireCombobox
2
- VERSION = "0.1.20"
2
+ VERSION = "0.1.22"
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.20
4
+ version: 0.1.22
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
@@ -109,6 +81,7 @@ files:
109
81
  - app/assets/javascripts/models/combobox/toggle.js
110
82
  - app/assets/javascripts/models/combobox/validity.js
111
83
  - app/assets/javascripts/vendor/bodyScrollLock.js
84
+ - app/assets/javascripts/vendor/requestjs.js
112
85
  - app/assets/stylesheets/hotwire_combobox.css
113
86
  - app/helpers/hotwire_combobox/helper.rb
114
87
  - app/presenters/hotwire_combobox/component.rb