cubism 0.1.0 → 0.2.0

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: 2d27901ea284362fc9a9c6a933c5d8e6b21d7834912f0915f9286254f7ca6344
4
- data.tar.gz: 66aa8bbedf83f9805f1590b1a7d0c68a18da5392fee914041ce640415abc90b5
3
+ metadata.gz: 57b07ebb0e4be69fc3547a79061710ecbbae9718fbc369052e020dc4062967fe
4
+ data.tar.gz: bfedff76bdf839db5e58d96a9abb7f4a13f20f909154a1294c6d92eb3d965ed4
5
5
  SHA512:
6
- metadata.gz: 0cc1d2ceea24ac614a05af8e9245823c87a94402786c83d2690a4be0ccfb0ba466dc68278ce10401afe0c471a8dd6ffedb3298e14bc51d0131ccc769aac65733
7
- data.tar.gz: 96c7487bf84ed58fab65215b1e7c481a5116c82440b1d13cd687b1df04107d1e9b4532c80f539743a0e6f48d857f6850bf8112eb97cf17334350e702d90db56d
6
+ metadata.gz: 7e5240cf040e37c614a2f6a6e3313dc52ca3e361a1dd64a312070e1a8fb19ec3117de68357c67e266b9e28817aec051b02b0b759e67ba998731fa5a6afd56c52
7
+ data.tar.gz: fc43eb982192114e6e975b63b0468eafd37d049f5989ea16ffa7250b7c469700c4cd5e4611677164ede6d60f8a14cf3c094cfd57328ce1c3fc0af863ef921532
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cubism (0.1.0)
4
+ cubism (0.2.0)
5
5
  cable_ready (>= 5.0.0)
6
6
  kredis (>= 0.4)
7
7
  rails (>= 6.0)
@@ -9,124 +9,142 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- actioncable (7.0.4.3)
13
- actionpack (= 7.0.4.3)
14
- activesupport (= 7.0.4.3)
12
+ actioncable (7.1.3.2)
13
+ actionpack (= 7.1.3.2)
14
+ activesupport (= 7.1.3.2)
15
15
  nio4r (~> 2.0)
16
16
  websocket-driver (>= 0.6.1)
17
- actionmailbox (7.0.4.3)
18
- actionpack (= 7.0.4.3)
19
- activejob (= 7.0.4.3)
20
- activerecord (= 7.0.4.3)
21
- activestorage (= 7.0.4.3)
22
- activesupport (= 7.0.4.3)
17
+ zeitwerk (~> 2.6)
18
+ actionmailbox (7.1.3.2)
19
+ actionpack (= 7.1.3.2)
20
+ activejob (= 7.1.3.2)
21
+ activerecord (= 7.1.3.2)
22
+ activestorage (= 7.1.3.2)
23
+ activesupport (= 7.1.3.2)
23
24
  mail (>= 2.7.1)
24
25
  net-imap
25
26
  net-pop
26
27
  net-smtp
27
- actionmailer (7.0.4.3)
28
- actionpack (= 7.0.4.3)
29
- actionview (= 7.0.4.3)
30
- activejob (= 7.0.4.3)
31
- activesupport (= 7.0.4.3)
28
+ actionmailer (7.1.3.2)
29
+ actionpack (= 7.1.3.2)
30
+ actionview (= 7.1.3.2)
31
+ activejob (= 7.1.3.2)
32
+ activesupport (= 7.1.3.2)
32
33
  mail (~> 2.5, >= 2.5.4)
33
34
  net-imap
34
35
  net-pop
35
36
  net-smtp
36
- rails-dom-testing (~> 2.0)
37
- actionpack (7.0.4.3)
38
- actionview (= 7.0.4.3)
39
- activesupport (= 7.0.4.3)
40
- rack (~> 2.0, >= 2.2.0)
37
+ rails-dom-testing (~> 2.2)
38
+ actionpack (7.1.3.2)
39
+ actionview (= 7.1.3.2)
40
+ activesupport (= 7.1.3.2)
41
+ nokogiri (>= 1.8.5)
42
+ racc
43
+ rack (>= 2.2.4)
44
+ rack-session (>= 1.0.1)
41
45
  rack-test (>= 0.6.3)
42
- rails-dom-testing (~> 2.0)
43
- rails-html-sanitizer (~> 1.0, >= 1.2.0)
44
- actiontext (7.0.4.3)
45
- actionpack (= 7.0.4.3)
46
- activerecord (= 7.0.4.3)
47
- activestorage (= 7.0.4.3)
48
- activesupport (= 7.0.4.3)
46
+ rails-dom-testing (~> 2.2)
47
+ rails-html-sanitizer (~> 1.6)
48
+ actiontext (7.1.3.2)
49
+ actionpack (= 7.1.3.2)
50
+ activerecord (= 7.1.3.2)
51
+ activestorage (= 7.1.3.2)
52
+ activesupport (= 7.1.3.2)
49
53
  globalid (>= 0.6.0)
50
54
  nokogiri (>= 1.8.5)
51
- actionview (7.0.4.3)
52
- activesupport (= 7.0.4.3)
55
+ actionview (7.1.3.2)
56
+ activesupport (= 7.1.3.2)
53
57
  builder (~> 3.1)
54
- erubi (~> 1.4)
55
- rails-dom-testing (~> 2.0)
56
- rails-html-sanitizer (~> 1.1, >= 1.2.0)
57
- activejob (7.0.4.3)
58
- activesupport (= 7.0.4.3)
58
+ erubi (~> 1.11)
59
+ rails-dom-testing (~> 2.2)
60
+ rails-html-sanitizer (~> 1.6)
61
+ activejob (7.1.3.2)
62
+ activesupport (= 7.1.3.2)
59
63
  globalid (>= 0.3.6)
60
- activemodel (7.0.4.3)
61
- activesupport (= 7.0.4.3)
62
- activerecord (7.0.4.3)
63
- activemodel (= 7.0.4.3)
64
- activesupport (= 7.0.4.3)
65
- activestorage (7.0.4.3)
66
- actionpack (= 7.0.4.3)
67
- activejob (= 7.0.4.3)
68
- activerecord (= 7.0.4.3)
69
- activesupport (= 7.0.4.3)
64
+ activemodel (7.1.3.2)
65
+ activesupport (= 7.1.3.2)
66
+ activerecord (7.1.3.2)
67
+ activemodel (= 7.1.3.2)
68
+ activesupport (= 7.1.3.2)
69
+ timeout (>= 0.4.0)
70
+ activestorage (7.1.3.2)
71
+ actionpack (= 7.1.3.2)
72
+ activejob (= 7.1.3.2)
73
+ activerecord (= 7.1.3.2)
74
+ activesupport (= 7.1.3.2)
70
75
  marcel (~> 1.0)
71
- mini_mime (>= 1.1.0)
72
- activesupport (7.0.4.3)
76
+ activesupport (7.1.3.2)
77
+ base64
78
+ bigdecimal
73
79
  concurrent-ruby (~> 1.0, >= 1.0.2)
80
+ connection_pool (>= 2.2.5)
81
+ drb
74
82
  i18n (>= 1.6, < 2)
75
83
  minitest (>= 5.1)
84
+ mutex_m
76
85
  tzinfo (~> 2.0)
77
86
  appraisal (2.4.1)
78
87
  bundler
79
88
  rake
80
89
  thor (>= 0.14.0)
81
90
  ast (2.4.2)
91
+ base64 (0.2.0)
92
+ bigdecimal (3.1.7)
82
93
  builder (3.2.4)
83
- cable_ready (5.0.0)
94
+ cable_ready (5.0.3)
84
95
  actionpack (>= 5.2)
85
96
  actionview (>= 5.2)
86
97
  activesupport (>= 5.2)
87
98
  railties (>= 5.2)
88
99
  thread-local (>= 1.1.0)
89
100
  coderay (1.1.3)
90
- concurrent-ruby (1.2.2)
91
- connection_pool (2.4.0)
101
+ concurrent-ruby (1.2.3)
102
+ connection_pool (2.4.1)
92
103
  crass (1.0.6)
93
- date (3.3.3)
104
+ date (3.3.4)
105
+ drb (2.2.1)
94
106
  erubi (1.12.0)
95
- globalid (1.1.0)
96
- activesupport (>= 5.0)
97
- i18n (1.12.0)
107
+ globalid (1.2.1)
108
+ activesupport (>= 6.1)
109
+ i18n (1.14.4)
98
110
  concurrent-ruby (~> 1.0)
99
- kredis (1.3.0.1)
111
+ io-console (0.7.2)
112
+ irb (1.12.0)
113
+ rdoc
114
+ reline (>= 0.4.2)
115
+ kredis (1.7.0)
116
+ activemodel (>= 6.0.0)
100
117
  activesupport (>= 6.0.0)
101
118
  redis (>= 4.2, < 6)
102
- loofah (2.20.0)
119
+ loofah (2.22.0)
103
120
  crass (~> 1.0.2)
104
- nokogiri (>= 1.5.9)
121
+ nokogiri (>= 1.12.0)
105
122
  mail (2.8.1)
106
123
  mini_mime (>= 0.1.1)
107
124
  net-imap
108
125
  net-pop
109
126
  net-smtp
110
- marcel (1.0.2)
127
+ marcel (1.0.4)
111
128
  method_source (1.0.0)
112
- mini_mime (1.1.2)
113
- mini_portile2 (2.8.1)
114
- minitest (5.18.0)
129
+ mini_mime (1.1.5)
130
+ mini_portile2 (2.8.5)
131
+ minitest (5.22.3)
115
132
  mocha (1.13.0)
116
- net-imap (0.3.4)
133
+ mutex_m (0.2.0)
134
+ net-imap (0.3.7)
117
135
  date
118
136
  net-protocol
119
137
  net-pop (0.1.2)
120
138
  net-protocol
121
- net-protocol (0.2.1)
139
+ net-protocol (0.2.2)
122
140
  timeout
123
- net-smtp (0.3.3)
141
+ net-smtp (0.5.0)
124
142
  net-protocol
125
- nio4r (2.5.9)
126
- nokogiri (1.14.3)
127
- mini_portile2 (~> 2.8.0)
143
+ nio4r (2.7.1)
144
+ nokogiri (1.15.6)
145
+ mini_portile2 (~> 2.8.2)
128
146
  racc (~> 1.4)
129
- nokogiri (1.14.3-arm64-darwin)
147
+ nokogiri (1.15.6-arm64-darwin)
130
148
  racc (~> 1.4)
131
149
  parallel (1.21.0)
132
150
  parser (3.1.0.0)
@@ -134,43 +152,57 @@ GEM
134
152
  pry (0.14.1)
135
153
  coderay (~> 1.1)
136
154
  method_source (~> 1.0)
137
- racc (1.6.2)
138
- rack (2.2.6.4)
155
+ psych (5.1.2)
156
+ stringio
157
+ racc (1.7.3)
158
+ rack (3.0.10)
159
+ rack-session (2.0.0)
160
+ rack (>= 3.0.0)
139
161
  rack-test (2.1.0)
140
162
  rack (>= 1.3)
141
- rails (7.0.4.3)
142
- actioncable (= 7.0.4.3)
143
- actionmailbox (= 7.0.4.3)
144
- actionmailer (= 7.0.4.3)
145
- actionpack (= 7.0.4.3)
146
- actiontext (= 7.0.4.3)
147
- actionview (= 7.0.4.3)
148
- activejob (= 7.0.4.3)
149
- activemodel (= 7.0.4.3)
150
- activerecord (= 7.0.4.3)
151
- activestorage (= 7.0.4.3)
152
- activesupport (= 7.0.4.3)
163
+ rackup (2.1.0)
164
+ rack (>= 3)
165
+ webrick (~> 1.8)
166
+ rails (7.1.3.2)
167
+ actioncable (= 7.1.3.2)
168
+ actionmailbox (= 7.1.3.2)
169
+ actionmailer (= 7.1.3.2)
170
+ actionpack (= 7.1.3.2)
171
+ actiontext (= 7.1.3.2)
172
+ actionview (= 7.1.3.2)
173
+ activejob (= 7.1.3.2)
174
+ activemodel (= 7.1.3.2)
175
+ activerecord (= 7.1.3.2)
176
+ activestorage (= 7.1.3.2)
177
+ activesupport (= 7.1.3.2)
153
178
  bundler (>= 1.15.0)
154
- railties (= 7.0.4.3)
155
- rails-dom-testing (2.0.3)
156
- activesupport (>= 4.2.0)
179
+ railties (= 7.1.3.2)
180
+ rails-dom-testing (2.2.0)
181
+ activesupport (>= 5.0.0)
182
+ minitest
157
183
  nokogiri (>= 1.6)
158
- rails-html-sanitizer (1.5.0)
159
- loofah (~> 2.19, >= 2.19.1)
160
- railties (7.0.4.3)
161
- actionpack (= 7.0.4.3)
162
- activesupport (= 7.0.4.3)
163
- method_source
184
+ rails-html-sanitizer (1.6.0)
185
+ loofah (~> 2.21)
186
+ nokogiri (~> 1.14)
187
+ railties (7.1.3.2)
188
+ actionpack (= 7.1.3.2)
189
+ activesupport (= 7.1.3.2)
190
+ irb
191
+ rackup (>= 1.0.0)
164
192
  rake (>= 12.2)
165
- thor (~> 1.0)
166
- zeitwerk (~> 2.5)
193
+ thor (~> 1.0, >= 1.2.2)
194
+ zeitwerk (~> 2.6)
167
195
  rainbow (3.0.0)
168
- rake (13.0.6)
169
- redis (5.0.6)
170
- redis-client (>= 0.9.0)
171
- redis-client (0.14.1)
196
+ rake (13.1.0)
197
+ rdoc (6.6.3.1)
198
+ psych (>= 4.0.0)
199
+ redis (5.1.0)
200
+ redis-client (>= 0.17.0)
201
+ redis-client (0.21.1)
172
202
  connection_pool
173
203
  regexp_parser (2.2.0)
204
+ reline (0.5.0)
205
+ io-console (~> 0.5)
174
206
  rexml (3.2.5)
175
207
  rubocop (1.23.0)
176
208
  parallel (~> 1.10)
@@ -191,16 +223,18 @@ GEM
191
223
  standard (1.5.0)
192
224
  rubocop (= 1.23.0)
193
225
  rubocop-performance (= 1.12.0)
194
- thor (1.2.1)
226
+ stringio (3.1.0)
227
+ thor (1.3.1)
195
228
  thread-local (1.1.0)
196
- timeout (0.3.2)
229
+ timeout (0.4.1)
197
230
  tzinfo (2.0.6)
198
231
  concurrent-ruby (~> 1.0)
199
232
  unicode-display_width (2.1.0)
200
- websocket-driver (0.7.5)
233
+ webrick (1.8.1)
234
+ websocket-driver (0.7.6)
201
235
  websocket-extensions (>= 0.1.0)
202
236
  websocket-extensions (0.1.5)
203
- zeitwerk (2.6.7)
237
+ zeitwerk (2.6.13)
204
238
 
205
239
  PLATFORMS
206
240
  arm64-darwin-21
@@ -25,7 +25,7 @@ class Cubicle extends SubscribingElement {
25
25
  this.appearTriggers = this.getAttribute("appear-trigger") ? this.getAttribute("appear-trigger").split(",") : [];
26
26
  this.disappearTriggers = this.getAttribute("disappear-trigger") ? this.getAttribute("disappear-trigger").split(",") : [];
27
27
  this.triggerRootSelector = this.getAttribute("trigger-root");
28
- this.consumer = await CableReady.consumer;
28
+ this.consumer = await CableReady.cable.getConsumer();
29
29
  this.channel = this.createSubscription();
30
30
  this.appearanceIntersectionObserver = new IntersectionObserver(((entries, observer) => {
31
31
  entries.forEach((entry => {
@@ -1,2 +1,2 @@
1
- import e,{SubscribingElement as t}from"cable_ready";customElements.define("cubicle-element",class extends t{constructor(){super();this.attachShadow({mode:"open"}).innerHTML="\n<style>\n :host {\n display: block;\n }\n</style>\n<slot></slot>\n",this.triggerRoot=this,this.present=!1}async connectedCallback(){this.preview||(this.appear=function(e,t=250){let r;return(...i)=>{r&&clearTimeout(r),r=setTimeout((()=>e.apply(this,i)),t)}}(this.appear.bind(this),50),this.appearTriggers=this.getAttribute("appear-trigger")?this.getAttribute("appear-trigger").split(","):[],this.disappearTriggers=this.getAttribute("disappear-trigger")?this.getAttribute("disappear-trigger").split(","):[],this.triggerRootSelector=this.getAttribute("trigger-root"),this.consumer=await e.consumer,this.channel=this.createSubscription(),this.appearanceIntersectionObserver=new IntersectionObserver(((e,t)=>{e.forEach((e=>{e.target===this.triggerRoot&&(e.isIntersecting?this.present||this.appear():this.present&&this.disappear())}))}),{threshold:0}),this.mutationObserver=new MutationObserver(((e,t)=>{if(this.triggerRootSelector)for(const t of e){const e=document.querySelector(this.triggerRootSelector);e&&(this.uninstall(),this.triggerRoot=e,this.install())}this.mutationObserver.disconnect()})),this.mutationObserver.observe(document,{subtree:!0,childList:!0}))}disconnectedCallback(){this.disappear(),super.disconnectedCallback()}install(){this.appearTriggers.includes("connect")&&this.appear(),this.appearTriggers.filter((e=>"intersect"===e)).forEach((()=>{this.appearanceIntersectionObserver.observe(this.triggerRoot)})),this.appearTriggers.filter((e=>"connect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.addEventListener(e,this.appear.bind(this))})),this.disappearTriggers.filter((e=>"disconnect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.addEventListener(e,this.disappear.bind(this))})),this.disappearTriggers.filter((e=>"intersect"===e)).forEach((()=>{}))}uninstall(){this.appearTriggers.filter((e=>"intersect"===e)).forEach((()=>{this.appearanceIntersectionObserver.unobserve(this.triggerRoot)})),this.appearTriggers.filter((e=>"connect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.removeEventListener(e,this.appear.bind(this))})),this.disappearTriggers.filter((e=>"intersect"===e)).forEach((()=>{})),this.disappearTriggers.filter((e=>"disconnect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.removeEventListener(e,this.disappear.bind(this))}))}appear(){this.channel&&(this.present=!0,this.channel.perform("appear"))}disappear(){this.channel&&(this.present=!1,this.channel.perform("disappear"))}performOperations(t){t.cableReady&&e.perform(t.operations)}createSubscription(){if(this.consumer)return this.consumer.subscriptions.create({channel:this.channelName,identifier:this.getAttribute("identifier"),element_id:this.id,scope:this.getAttribute("scope"),exclude_current_user:"true"===this.getAttribute("exclude-current-user")},{connected:()=>{this.install()},disconnected:()=>{this.disappear(),this.uninstall()},rejected:()=>{this.uninstall()},received:this.performOperations.bind(this)});console.error("The `cubicle-element` helper cannot connect without an ActionCable consumer.")}get channelName(){return"Cubism::PresenceChannel"}});
1
+ import e,{SubscribingElement as t}from"cable_ready";customElements.define("cubicle-element",class extends t{constructor(){super();this.attachShadow({mode:"open"}).innerHTML="\n<style>\n :host {\n display: block;\n }\n</style>\n<slot></slot>\n",this.triggerRoot=this,this.present=!1}async connectedCallback(){this.preview||(this.appear=function(e,t=250){let r;return(...i)=>{r&&clearTimeout(r),r=setTimeout((()=>e.apply(this,i)),t)}}(this.appear.bind(this),50),this.appearTriggers=this.getAttribute("appear-trigger")?this.getAttribute("appear-trigger").split(","):[],this.disappearTriggers=this.getAttribute("disappear-trigger")?this.getAttribute("disappear-trigger").split(","):[],this.triggerRootSelector=this.getAttribute("trigger-root"),this.consumer=await e.cable.getConsumer(),this.channel=this.createSubscription(),this.appearanceIntersectionObserver=new IntersectionObserver(((e,t)=>{e.forEach((e=>{e.target===this.triggerRoot&&(e.isIntersecting?this.present||this.appear():this.present&&this.disappear())}))}),{threshold:0}),this.mutationObserver=new MutationObserver(((e,t)=>{if(this.triggerRootSelector)for(const t of e){const e=document.querySelector(this.triggerRootSelector);e&&(this.uninstall(),this.triggerRoot=e,this.install())}this.mutationObserver.disconnect()})),this.mutationObserver.observe(document,{subtree:!0,childList:!0}))}disconnectedCallback(){this.disappear(),super.disconnectedCallback()}install(){this.appearTriggers.includes("connect")&&this.appear(),this.appearTriggers.filter((e=>"intersect"===e)).forEach((()=>{this.appearanceIntersectionObserver.observe(this.triggerRoot)})),this.appearTriggers.filter((e=>"connect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.addEventListener(e,this.appear.bind(this))})),this.disappearTriggers.filter((e=>"disconnect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.addEventListener(e,this.disappear.bind(this))})),this.disappearTriggers.filter((e=>"intersect"===e)).forEach((()=>{}))}uninstall(){this.appearTriggers.filter((e=>"intersect"===e)).forEach((()=>{this.appearanceIntersectionObserver.unobserve(this.triggerRoot)})),this.appearTriggers.filter((e=>"connect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.removeEventListener(e,this.appear.bind(this))})),this.disappearTriggers.filter((e=>"intersect"===e)).forEach((()=>{})),this.disappearTriggers.filter((e=>"disconnect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.removeEventListener(e,this.disappear.bind(this))}))}appear(){this.channel&&(this.present=!0,this.channel.perform("appear"))}disappear(){this.channel&&(this.present=!1,this.channel.perform("disappear"))}performOperations(t){t.cableReady&&e.perform(t.operations)}createSubscription(){if(this.consumer)return this.consumer.subscriptions.create({channel:this.channelName,identifier:this.getAttribute("identifier"),element_id:this.id,scope:this.getAttribute("scope"),exclude_current_user:"true"===this.getAttribute("exclude-current-user")},{connected:()=>{this.install()},disconnected:()=>{this.disappear(),this.uninstall()},rejected:()=>{this.uninstall()},received:this.performOperations.bind(this)});console.error("The `cubicle-element` helper cannot connect without an ActionCable consumer.")}get channelName(){return"Cubism::PresenceChannel"}});
2
2
  //# sourceMappingURL=cubism.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cubism.min.js","sources":["../../../javascript/elements/index.js","../../../javascript/elements/cubicle.js","../../../../cable_ready/javascript/utils.js"],"sourcesContent":["/* global customElements */\n\nimport { Cubicle } from './cubicle'\n\nexport * from './cubicle'\n\ncustomElements.define('cubicle-element', Cubicle)\n","/* eslint-disable no-undef */\nimport CableReady, { SubscribingElement } from 'cable_ready'\nimport { debounce } from 'cable_ready/javascript/utils'\n\nexport class Cubicle extends SubscribingElement {\n constructor () {\n super()\n const shadowRoot = this.attachShadow({ mode: 'open' })\n shadowRoot.innerHTML = `\n<style>\n :host {\n display: block;\n }\n</style>\n<slot></slot>\n`\n\n this.triggerRoot = this\n this.present = false\n }\n\n async connectedCallback () {\n if (this.preview) return\n\n this.appear = debounce(this.appear.bind(this), 50)\n\n this.appearTriggers = this.getAttribute('appear-trigger')\n ? this.getAttribute('appear-trigger').split(',')\n : []\n this.disappearTriggers = this.getAttribute('disappear-trigger')\n ? this.getAttribute('disappear-trigger').split(',')\n : []\n this.triggerRootSelector = this.getAttribute('trigger-root')\n\n this.consumer = await CableReady.consumer\n\n this.channel = this.createSubscription()\n\n this.appearanceIntersectionObserver = new IntersectionObserver(\n (entries, observer) => {\n entries.forEach(entry => {\n if (entry.target !== this.triggerRoot) return\n if (entry.isIntersecting) {\n if (!this.present) {\n this.appear()\n }\n } else {\n if (this.present) {\n this.disappear()\n }\n }\n })\n },\n { threshold: 0 }\n )\n\n this.mutationObserver = new MutationObserver((mutationsList, observer) => {\n if (this.triggerRootSelector) {\n // eslint-disable-next-line no-unused-vars\n for (const mutation of mutationsList) {\n const root = document.querySelector(this.triggerRootSelector)\n if (root) {\n this.uninstall()\n this.triggerRoot = root\n this.install()\n }\n }\n }\n this.mutationObserver.disconnect()\n })\n\n this.mutationObserver.observe(document, {\n subtree: true,\n childList: true\n })\n }\n\n disconnectedCallback () {\n this.disappear()\n super.disconnectedCallback()\n }\n\n install () {\n if (this.appearTriggers.includes('connect')) {\n this.appear()\n }\n\n this.appearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {\n this.appearanceIntersectionObserver.observe(this.triggerRoot)\n })\n\n this.appearTriggers\n .filter(eventName => eventName !== 'connect' && eventName !== 'intersect')\n .forEach(eventName => {\n this.triggerRoot.addEventListener(eventName, this.appear.bind(this))\n })\n\n this.disappearTriggers\n .filter(\n eventName => eventName !== 'disconnect' && eventName !== 'intersect'\n )\n .forEach(eventName => {\n this.triggerRoot.addEventListener(eventName, this.disappear.bind(this))\n })\n\n this.disappearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {})\n }\n\n uninstall () {\n this.appearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {\n this.appearanceIntersectionObserver.unobserve(this.triggerRoot)\n })\n\n this.appearTriggers\n .filter(eventName => eventName !== 'connect' && eventName !== 'intersect')\n .forEach(eventName => {\n this.triggerRoot.removeEventListener(eventName, this.appear.bind(this))\n })\n\n this.disappearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {})\n\n this.disappearTriggers\n .filter(\n eventName => eventName !== 'disconnect' && eventName !== 'intersect'\n )\n .forEach(eventName => {\n this.triggerRoot.removeEventListener(\n eventName,\n this.disappear.bind(this)\n )\n })\n }\n\n appear () {\n if (this.channel) {\n this.present = true\n this.channel.perform('appear')\n }\n }\n\n disappear () {\n if (this.channel) {\n this.present = false\n this.channel.perform('disappear')\n }\n }\n\n performOperations (data) {\n if (data.cableReady) {\n CableReady.perform(data.operations)\n }\n }\n\n createSubscription () {\n if (!this.consumer) {\n console.error(\n 'The `cubicle-element` helper cannot connect without an ActionCable consumer.'\n )\n return\n }\n\n return this.consumer.subscriptions.create(\n {\n channel: this.channelName,\n identifier: this.getAttribute('identifier'),\n element_id: this.id,\n scope: this.getAttribute('scope'),\n exclude_current_user:\n this.getAttribute('exclude-current-user') === 'true'\n },\n {\n connected: () => {\n this.install()\n },\n disconnected: () => {\n this.disappear()\n this.uninstall()\n },\n rejected: () => {\n this.uninstall()\n },\n received: this.performOperations.bind(this)\n }\n )\n }\n\n get channelName () {\n return 'Cubism::PresenceChannel'\n }\n}\n","import { inputTags, textInputTypes } from './enums'\nimport ActiveElement from './active_element'\n\n// Indicates if the passed element is considered a text input.\n//\nconst isTextInput = element => {\n return inputTags[element.tagName] && textInputTypes[element.type]\n}\n\n// Assigns focus to the appropriate element... preferring the explicitly passed selector\n//\n// * selector - a CSS selector for the element that should have focus\n//\nconst assignFocus = selector => {\n const element =\n selector && selector.nodeType === Node.ELEMENT_NODE\n ? selector\n : document.querySelector(selector)\n const focusElement = element || ActiveElement.element\n if (focusElement && focusElement.focus) focusElement.focus()\n}\n\n// Dispatches an event on the passed element\n//\n// * element - the element\n// * name - the name of the event\n// * detail - the event detail\n//\nconst dispatch = (element, name, detail = {}) => {\n const init = { bubbles: true, cancelable: true, detail }\n const event = new CustomEvent(name, init)\n element.dispatchEvent(event)\n if (window.jQuery) window.jQuery(element).trigger(name, detail)\n}\n\n// Accepts an xPath query and returns the element found at that position in the DOM\n//\nconst xpathToElement = xpath => {\n return document.evaluate(\n xpath,\n document,\n null,\n XPathResult.FIRST_ORDERED_NODE_TYPE,\n null\n ).singleNodeValue\n}\n\n// Accepts an xPath query and returns all matching elements in the DOM\n//\nconst xpathToElementArray = (xpath, reverse = false) => {\n const snapshotList = document.evaluate(\n xpath,\n document,\n null,\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\n null\n )\n const snapshots = []\n\n for (let i = 0; i < snapshotList.snapshotLength; i++) {\n snapshots.push(snapshotList.snapshotItem(i))\n }\n\n return reverse ? snapshots.reverse() : snapshots\n}\n\n// Return an array with the class names to be used\n//\n// * names - could be a string or an array of strings for multiple classes.\n//\nconst getClassNames = names => Array.from(names).flat()\n\n// Perform operation for either the first or all of the elements returned by CSS selector\n//\n// * operation - the instruction payload from perform\n// * callback - the operation function to run for each element\n//\nconst processElements = (operation, callback) => {\n Array.from(\n operation.selectAll ? operation.element : [operation.element]\n ).forEach(callback)\n}\n\n// convert string to kebab-case\n// most other implementations (lodash) are focused on camelCase to kebab-case\n// instead, this uses word token boundaries to produce readable URL slugs and keys\n// this implementation will not support Emoji or other non-ASCII characters\n//\nconst kebabize = createCompounder(function (result, word, index) {\n return result + (index ? '-' : '') + word.toLowerCase()\n})\n\nfunction createCompounder (callback) {\n return function (str) {\n return words(str).reduce(callback, '')\n }\n}\n\nconst words = str => {\n str = str == null ? '' : str\n return str.match(/([A-Z]{2,}|[0-9]+|[A-Z]?[a-z]+|[A-Z])/g) || []\n}\n\n// Provide a standardized pipeline of checks and modifications to all operations based on provided options\n// Currently skips execution if cancelled and implements an optional delay\n//\nconst operate = (operation, callback) => {\n if (!operation.cancel) {\n operation.delay ? setTimeout(callback, operation.delay) : callback()\n return true\n }\n return false\n}\n\n// Dispatch life-cycle events with standardized naming\nconst before = (target, operation) =>\n dispatch(\n target,\n `cable-ready:before-${kebabize(operation.operation)}`,\n operation\n )\n\nconst after = (target, operation) =>\n dispatch(\n target,\n `cable-ready:after-${kebabize(operation.operation)}`,\n operation\n )\n\nfunction debounce (fn, delay = 250) {\n let timer\n return (...args) => {\n const callback = () => fn.apply(this, args)\n if (timer) clearTimeout(timer)\n timer = setTimeout(callback, delay)\n }\n}\n\nfunction handleErrors (response) {\n if (!response.ok) throw Error(response.statusText)\n return response\n}\n\nfunction safeScalar (val) {\n if (\n val !== undefined &&\n !['string', 'number', 'boolean'].includes(typeof val)\n )\n console.warn(\n `Operation expects a string, number or boolean, but got ${val} (${typeof val})`\n )\n return val != null ? val : ''\n}\n\nfunction safeString (str) {\n if (str !== undefined && typeof str !== 'string')\n console.warn(`Operation expects a string, but got ${str} (${typeof str})`)\n\n return str != null ? String(str) : ''\n}\n\nfunction safeArray (arr) {\n if (arr !== undefined && !Array.isArray(arr))\n console.warn(`Operation expects an array, but got ${arr} (${typeof arr})`)\n return arr != null ? Array.from(arr) : []\n}\n\nfunction safeObject (obj) {\n if (obj !== undefined && typeof obj !== 'object')\n console.warn(`Operation expects an object, but got ${obj} (${typeof obj})`)\n return obj != null ? Object(obj) : {}\n}\n\nfunction safeStringOrArray (elem) {\n if (elem !== undefined && !Array.isArray(elem) && typeof elem !== 'string')\n console.warn(`Operation expects an Array or a String, but got ${elem} (${typeof elem})`)\n\n return elem == null ? '' : Array.isArray(elem) ? Array.from(elem) : String(elem)\n}\n\nfunction fragmentToString (fragment) {\n return new XMLSerializer().serializeToString(fragment)\n}\n\n// A proxy method to wrap a fetch call in error handling\n//\n// * url - the URL to fetch\n// * additionalHeaders - an object of additional headers passed to fetch\n//\nasync function graciouslyFetch (url, additionalHeaders) {\n try {\n const response = await fetch(url, {\n headers: {\n 'X-REQUESTED-WITH': 'XmlHttpRequest',\n ...additionalHeaders\n }\n })\n if (response == undefined) return\n\n handleErrors(response)\n\n return response\n } catch (e) {\n console.error(`Could not fetch ${url}`)\n }\n}\n\nexport {\n isTextInput,\n assignFocus,\n dispatch,\n xpathToElement,\n xpathToElementArray,\n getClassNames,\n processElements,\n operate,\n before,\n after,\n debounce,\n handleErrors,\n graciouslyFetch,\n kebabize,\n safeScalar,\n safeString,\n safeArray,\n safeObject,\n safeStringOrArray,\n fragmentToString\n}\n"],"names":["customElements","define","SubscribingElement","constructor","super","this","attachShadow","mode","innerHTML","triggerRoot","present","async","preview","appear","fn","delay","timer","args","clearTimeout","setTimeout","apply","debounce","bind","appearTriggers","getAttribute","split","disappearTriggers","triggerRootSelector","consumer","CableReady","channel","createSubscription","appearanceIntersectionObserver","IntersectionObserver","entries","observer","forEach","entry","target","isIntersecting","disappear","threshold","mutationObserver","MutationObserver","mutationsList","mutation","root","document","querySelector","uninstall","install","disconnect","observe","subtree","childList","disconnectedCallback","includes","filter","eventName","addEventListener","unobserve","removeEventListener","perform","performOperations","data","cableReady","operations","subscriptions","create","channelName","identifier","element_id","id","scope","exclude_current_user","connected","disconnected","rejected","received","console","error"],"mappings":"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"}
1
+ {"version":3,"file":"cubism.min.js","sources":["../../../javascript/elements/index.js","../../../javascript/elements/cubicle.js","../../../../cable_ready/javascript/utils.js"],"sourcesContent":["/* global customElements */\n\nimport { Cubicle } from './cubicle'\n\nexport * from './cubicle'\n\ncustomElements.define('cubicle-element', Cubicle)\n","/* eslint-disable no-undef */\nimport CableReady, { SubscribingElement } from 'cable_ready'\nimport { debounce } from 'cable_ready/javascript/utils'\n\nexport class Cubicle extends SubscribingElement {\n constructor () {\n super()\n const shadowRoot = this.attachShadow({ mode: 'open' })\n shadowRoot.innerHTML = `\n<style>\n :host {\n display: block;\n }\n</style>\n<slot></slot>\n`\n\n this.triggerRoot = this\n this.present = false\n }\n\n async connectedCallback () {\n if (this.preview) return\n\n this.appear = debounce(this.appear.bind(this), 50)\n\n this.appearTriggers = this.getAttribute('appear-trigger')\n ? this.getAttribute('appear-trigger').split(',')\n : []\n this.disappearTriggers = this.getAttribute('disappear-trigger')\n ? this.getAttribute('disappear-trigger').split(',')\n : []\n this.triggerRootSelector = this.getAttribute('trigger-root')\n\n this.consumer = await CableReady.cable.getConsumer()\n\n this.channel = this.createSubscription()\n\n this.appearanceIntersectionObserver = new IntersectionObserver(\n (entries, observer) => {\n entries.forEach(entry => {\n if (entry.target !== this.triggerRoot) return\n if (entry.isIntersecting) {\n if (!this.present) {\n this.appear()\n }\n } else {\n if (this.present) {\n this.disappear()\n }\n }\n })\n },\n { threshold: 0 }\n )\n\n this.mutationObserver = new MutationObserver((mutationsList, observer) => {\n if (this.triggerRootSelector) {\n // eslint-disable-next-line no-unused-vars\n for (const mutation of mutationsList) {\n const root = document.querySelector(this.triggerRootSelector)\n if (root) {\n this.uninstall()\n this.triggerRoot = root\n this.install()\n }\n }\n }\n this.mutationObserver.disconnect()\n })\n\n this.mutationObserver.observe(document, {\n subtree: true,\n childList: true\n })\n }\n\n disconnectedCallback () {\n this.disappear()\n super.disconnectedCallback()\n }\n\n install () {\n if (this.appearTriggers.includes('connect')) {\n this.appear()\n }\n\n this.appearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {\n this.appearanceIntersectionObserver.observe(this.triggerRoot)\n })\n\n this.appearTriggers\n .filter(eventName => eventName !== 'connect' && eventName !== 'intersect')\n .forEach(eventName => {\n this.triggerRoot.addEventListener(eventName, this.appear.bind(this))\n })\n\n this.disappearTriggers\n .filter(\n eventName => eventName !== 'disconnect' && eventName !== 'intersect'\n )\n .forEach(eventName => {\n this.triggerRoot.addEventListener(eventName, this.disappear.bind(this))\n })\n\n this.disappearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {})\n }\n\n uninstall () {\n this.appearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {\n this.appearanceIntersectionObserver.unobserve(this.triggerRoot)\n })\n\n this.appearTriggers\n .filter(eventName => eventName !== 'connect' && eventName !== 'intersect')\n .forEach(eventName => {\n this.triggerRoot.removeEventListener(eventName, this.appear.bind(this))\n })\n\n this.disappearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {})\n\n this.disappearTriggers\n .filter(\n eventName => eventName !== 'disconnect' && eventName !== 'intersect'\n )\n .forEach(eventName => {\n this.triggerRoot.removeEventListener(\n eventName,\n this.disappear.bind(this)\n )\n })\n }\n\n appear () {\n if (this.channel) {\n this.present = true\n this.channel.perform('appear')\n }\n }\n\n disappear () {\n if (this.channel) {\n this.present = false\n this.channel.perform('disappear')\n }\n }\n\n performOperations (data) {\n if (data.cableReady) {\n CableReady.perform(data.operations)\n }\n }\n\n createSubscription () {\n if (!this.consumer) {\n console.error(\n 'The `cubicle-element` helper cannot connect without an ActionCable consumer.'\n )\n return\n }\n\n return this.consumer.subscriptions.create(\n {\n channel: this.channelName,\n identifier: this.getAttribute('identifier'),\n element_id: this.id,\n scope: this.getAttribute('scope'),\n exclude_current_user:\n this.getAttribute('exclude-current-user') === 'true'\n },\n {\n connected: () => {\n this.install()\n },\n disconnected: () => {\n this.disappear()\n this.uninstall()\n },\n rejected: () => {\n this.uninstall()\n },\n received: this.performOperations.bind(this)\n }\n )\n }\n\n get channelName () {\n return 'Cubism::PresenceChannel'\n }\n}\n","import { inputTags, textInputTypes } from './enums'\nimport ActiveElement from './active_element'\n\n// Indicates if the passed element is considered a text input.\n//\nconst isTextInput = element => {\n return inputTags[element.tagName] && textInputTypes[element.type]\n}\n\n// Assigns focus to the appropriate element... preferring the explicitly passed selector\n//\n// * selector - a CSS selector for the element that should have focus\n//\nconst assignFocus = selector => {\n const element =\n selector && selector.nodeType === Node.ELEMENT_NODE\n ? selector\n : document.querySelector(selector)\n const focusElement = element || ActiveElement.element\n if (focusElement && focusElement.focus) focusElement.focus()\n}\n\n// Dispatches an event on the passed element\n//\n// * element - the element\n// * name - the name of the event\n// * detail - the event detail\n//\nconst dispatch = (element, name, detail = {}) => {\n const init = { bubbles: true, cancelable: true, detail }\n const event = new CustomEvent(name, init)\n element.dispatchEvent(event)\n if (window.jQuery) window.jQuery(element).trigger(name, detail)\n}\n\n// Accepts an xPath query and returns the element found at that position in the DOM\n//\nconst xpathToElement = xpath => {\n return document.evaluate(\n xpath,\n document,\n null,\n XPathResult.FIRST_ORDERED_NODE_TYPE,\n null\n ).singleNodeValue\n}\n\n// Accepts an xPath query and returns all matching elements in the DOM\n//\nconst xpathToElementArray = (xpath, reverse = false) => {\n const snapshotList = document.evaluate(\n xpath,\n document,\n null,\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\n null\n )\n const snapshots = []\n\n for (let i = 0; i < snapshotList.snapshotLength; i++) {\n snapshots.push(snapshotList.snapshotItem(i))\n }\n\n return reverse ? snapshots.reverse() : snapshots\n}\n\n// Return an array with the class names to be used\n//\n// * names - could be a string or an array of strings for multiple classes.\n//\nconst getClassNames = names => Array.from(names).flat()\n\n// Perform operation for either the first or all of the elements returned by CSS selector\n//\n// * operation - the instruction payload from perform\n// * callback - the operation function to run for each element\n//\nconst processElements = (operation, callback) => {\n Array.from(\n operation.selectAll ? operation.element : [operation.element]\n ).forEach(callback)\n}\n\n// convert string to kebab-case\n// most other implementations (lodash) are focused on camelCase to kebab-case\n// instead, this uses word token boundaries to produce readable URL slugs and keys\n// this implementation will not support Emoji or other non-ASCII characters\n//\nconst kebabize = createCompounder(function (result, word, index) {\n return result + (index ? '-' : '') + word.toLowerCase()\n})\n\nfunction createCompounder (callback) {\n return function (str) {\n return words(str).reduce(callback, '')\n }\n}\n\nconst words = str => {\n str = str == null ? '' : str\n return str.match(/([A-Z]{2,}|[0-9]+|[A-Z]?[a-z]+|[A-Z])/g) || []\n}\n\n// Provide a standardized pipeline of checks and modifications to all operations based on provided options\n// Currently skips execution if cancelled and implements an optional delay\n//\nconst operate = (operation, callback) => {\n if (!operation.cancel) {\n operation.delay ? setTimeout(callback, operation.delay) : callback()\n return true\n }\n return false\n}\n\n// Dispatch life-cycle events with standardized naming\nconst before = (target, operation) =>\n dispatch(\n target,\n `cable-ready:before-${kebabize(operation.operation)}`,\n operation\n )\n\nconst after = (target, operation) =>\n dispatch(\n target,\n `cable-ready:after-${kebabize(operation.operation)}`,\n operation\n )\n\nfunction debounce (fn, delay = 250) {\n let timer\n return (...args) => {\n const callback = () => fn.apply(this, args)\n if (timer) clearTimeout(timer)\n timer = setTimeout(callback, delay)\n }\n}\n\nfunction handleErrors (response) {\n if (!response.ok) throw Error(response.statusText)\n return response\n}\n\nfunction safeScalar (val) {\n if (\n val !== undefined &&\n !['string', 'number', 'boolean'].includes(typeof val)\n )\n console.warn(\n `Operation expects a string, number or boolean, but got ${val} (${typeof val})`\n )\n return val != null ? val : ''\n}\n\nfunction safeString (str) {\n if (str !== undefined && typeof str !== 'string')\n console.warn(`Operation expects a string, but got ${str} (${typeof str})`)\n\n return str != null ? String(str) : ''\n}\n\nfunction safeArray (arr) {\n if (arr !== undefined && !Array.isArray(arr))\n console.warn(`Operation expects an array, but got ${arr} (${typeof arr})`)\n return arr != null ? Array.from(arr) : []\n}\n\nfunction safeObject (obj) {\n if (obj !== undefined && typeof obj !== 'object')\n console.warn(`Operation expects an object, but got ${obj} (${typeof obj})`)\n return obj != null ? Object(obj) : {}\n}\n\nfunction safeStringOrArray (elem) {\n if (elem !== undefined && !Array.isArray(elem) && typeof elem !== 'string')\n console.warn(`Operation expects an Array or a String, but got ${elem} (${typeof elem})`)\n\n return elem == null ? '' : Array.isArray(elem) ? Array.from(elem) : String(elem)\n}\n\nfunction fragmentToString (fragment) {\n return new XMLSerializer().serializeToString(fragment)\n}\n\n// A proxy method to wrap a fetch call in error handling\n//\n// * url - the URL to fetch\n// * additionalHeaders - an object of additional headers passed to fetch\n//\nasync function graciouslyFetch (url, additionalHeaders) {\n try {\n const response = await fetch(url, {\n headers: {\n 'X-REQUESTED-WITH': 'XmlHttpRequest',\n ...additionalHeaders\n }\n })\n if (response == undefined) return\n\n handleErrors(response)\n\n return response\n } catch (e) {\n console.error(`Could not fetch ${url}`)\n }\n}\n\nclass BoundedQueue {\n constructor (maxSize) {\n this.maxSize = maxSize\n this.queue = []\n }\n\n push (item) {\n if (this.isFull()) {\n // Remove the oldest item to make space for the new one\n this.shift()\n }\n this.queue.push(item)\n }\n\n shift () {\n return this.queue.shift()\n }\n\n isFull () {\n return this.queue.length === this.maxSize\n }\n}\n\nexport {\n isTextInput,\n assignFocus,\n dispatch,\n xpathToElement,\n xpathToElementArray,\n getClassNames,\n processElements,\n operate,\n before,\n after,\n debounce,\n handleErrors,\n graciouslyFetch,\n kebabize,\n safeScalar,\n safeString,\n safeArray,\n safeObject,\n safeStringOrArray,\n fragmentToString,\n BoundedQueue\n}\n"],"names":["customElements","define","SubscribingElement","constructor","super","this","attachShadow","mode","innerHTML","triggerRoot","present","async","preview","appear","fn","delay","timer","args","clearTimeout","setTimeout","apply","debounce","bind","appearTriggers","getAttribute","split","disappearTriggers","triggerRootSelector","consumer","CableReady","cable","getConsumer","channel","createSubscription","appearanceIntersectionObserver","IntersectionObserver","entries","observer","forEach","entry","target","isIntersecting","disappear","threshold","mutationObserver","MutationObserver","mutationsList","mutation","root","document","querySelector","uninstall","install","disconnect","observe","subtree","childList","disconnectedCallback","includes","filter","eventName","addEventListener","unobserve","removeEventListener","perform","performOperations","data","cableReady","operations","subscriptions","create","channelName","identifier","element_id","id","scope","exclude_current_user","connected","disconnected","rejected","received","console","error"],"mappings":"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"}
@@ -33,7 +33,7 @@
33
33
  this.appearTriggers = this.getAttribute("appear-trigger") ? this.getAttribute("appear-trigger").split(",") : [];
34
34
  this.disappearTriggers = this.getAttribute("disappear-trigger") ? this.getAttribute("disappear-trigger").split(",") : [];
35
35
  this.triggerRootSelector = this.getAttribute("trigger-root");
36
- this.consumer = await CableReady__default["default"].consumer;
36
+ this.consumer = await CableReady__default["default"].cable.getConsumer();
37
37
  this.channel = this.createSubscription();
38
38
  this.appearanceIntersectionObserver = new IntersectionObserver(((entries, observer) => {
39
39
  entries.forEach((entry => {
@@ -1,2 +1,2 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(require("cable_ready")):"function"==typeof define&&define.amd?define(["cable_ready"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).CableReady)}(this,(function(e){"use strict";function t(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var i=t(e);class r extends e.SubscribingElement{constructor(){super();this.attachShadow({mode:"open"}).innerHTML="\n<style>\n :host {\n display: block;\n }\n</style>\n<slot></slot>\n",this.triggerRoot=this,this.present=!1}async connectedCallback(){this.preview||(this.appear=function(e,t=250){let i;return(...r)=>{i&&clearTimeout(i),i=setTimeout((()=>e.apply(this,r)),t)}}(this.appear.bind(this),50),this.appearTriggers=this.getAttribute("appear-trigger")?this.getAttribute("appear-trigger").split(","):[],this.disappearTriggers=this.getAttribute("disappear-trigger")?this.getAttribute("disappear-trigger").split(","):[],this.triggerRootSelector=this.getAttribute("trigger-root"),this.consumer=await i.default.consumer,this.channel=this.createSubscription(),this.appearanceIntersectionObserver=new IntersectionObserver(((e,t)=>{e.forEach((e=>{e.target===this.triggerRoot&&(e.isIntersecting?this.present||this.appear():this.present&&this.disappear())}))}),{threshold:0}),this.mutationObserver=new MutationObserver(((e,t)=>{if(this.triggerRootSelector)for(const t of e){const e=document.querySelector(this.triggerRootSelector);e&&(this.uninstall(),this.triggerRoot=e,this.install())}this.mutationObserver.disconnect()})),this.mutationObserver.observe(document,{subtree:!0,childList:!0}))}disconnectedCallback(){this.disappear(),super.disconnectedCallback()}install(){this.appearTriggers.includes("connect")&&this.appear(),this.appearTriggers.filter((e=>"intersect"===e)).forEach((()=>{this.appearanceIntersectionObserver.observe(this.triggerRoot)})),this.appearTriggers.filter((e=>"connect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.addEventListener(e,this.appear.bind(this))})),this.disappearTriggers.filter((e=>"disconnect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.addEventListener(e,this.disappear.bind(this))})),this.disappearTriggers.filter((e=>"intersect"===e)).forEach((()=>{}))}uninstall(){this.appearTriggers.filter((e=>"intersect"===e)).forEach((()=>{this.appearanceIntersectionObserver.unobserve(this.triggerRoot)})),this.appearTriggers.filter((e=>"connect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.removeEventListener(e,this.appear.bind(this))})),this.disappearTriggers.filter((e=>"intersect"===e)).forEach((()=>{})),this.disappearTriggers.filter((e=>"disconnect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.removeEventListener(e,this.disappear.bind(this))}))}appear(){this.channel&&(this.present=!0,this.channel.perform("appear"))}disappear(){this.channel&&(this.present=!1,this.channel.perform("disappear"))}performOperations(e){e.cableReady&&i.default.perform(e.operations)}createSubscription(){if(this.consumer)return this.consumer.subscriptions.create({channel:this.channelName,identifier:this.getAttribute("identifier"),element_id:this.id,scope:this.getAttribute("scope"),exclude_current_user:"true"===this.getAttribute("exclude-current-user")},{connected:()=>{this.install()},disconnected:()=>{this.disappear(),this.uninstall()},rejected:()=>{this.uninstall()},received:this.performOperations.bind(this)});console.error("The `cubicle-element` helper cannot connect without an ActionCable consumer.")}get channelName(){return"Cubism::PresenceChannel"}}customElements.define("cubicle-element",r)}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(require("cable_ready")):"function"==typeof define&&define.amd?define(["cable_ready"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).CableReady)}(this,(function(e){"use strict";function t(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var i=t(e);class r extends e.SubscribingElement{constructor(){super();this.attachShadow({mode:"open"}).innerHTML="\n<style>\n :host {\n display: block;\n }\n</style>\n<slot></slot>\n",this.triggerRoot=this,this.present=!1}async connectedCallback(){this.preview||(this.appear=function(e,t=250){let i;return(...r)=>{i&&clearTimeout(i),i=setTimeout((()=>e.apply(this,r)),t)}}(this.appear.bind(this),50),this.appearTriggers=this.getAttribute("appear-trigger")?this.getAttribute("appear-trigger").split(","):[],this.disappearTriggers=this.getAttribute("disappear-trigger")?this.getAttribute("disappear-trigger").split(","):[],this.triggerRootSelector=this.getAttribute("trigger-root"),this.consumer=await i.default.cable.getConsumer(),this.channel=this.createSubscription(),this.appearanceIntersectionObserver=new IntersectionObserver(((e,t)=>{e.forEach((e=>{e.target===this.triggerRoot&&(e.isIntersecting?this.present||this.appear():this.present&&this.disappear())}))}),{threshold:0}),this.mutationObserver=new MutationObserver(((e,t)=>{if(this.triggerRootSelector)for(const t of e){const e=document.querySelector(this.triggerRootSelector);e&&(this.uninstall(),this.triggerRoot=e,this.install())}this.mutationObserver.disconnect()})),this.mutationObserver.observe(document,{subtree:!0,childList:!0}))}disconnectedCallback(){this.disappear(),super.disconnectedCallback()}install(){this.appearTriggers.includes("connect")&&this.appear(),this.appearTriggers.filter((e=>"intersect"===e)).forEach((()=>{this.appearanceIntersectionObserver.observe(this.triggerRoot)})),this.appearTriggers.filter((e=>"connect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.addEventListener(e,this.appear.bind(this))})),this.disappearTriggers.filter((e=>"disconnect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.addEventListener(e,this.disappear.bind(this))})),this.disappearTriggers.filter((e=>"intersect"===e)).forEach((()=>{}))}uninstall(){this.appearTriggers.filter((e=>"intersect"===e)).forEach((()=>{this.appearanceIntersectionObserver.unobserve(this.triggerRoot)})),this.appearTriggers.filter((e=>"connect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.removeEventListener(e,this.appear.bind(this))})),this.disappearTriggers.filter((e=>"intersect"===e)).forEach((()=>{})),this.disappearTriggers.filter((e=>"disconnect"!==e&&"intersect"!==e)).forEach((e=>{this.triggerRoot.removeEventListener(e,this.disappear.bind(this))}))}appear(){this.channel&&(this.present=!0,this.channel.perform("appear"))}disappear(){this.channel&&(this.present=!1,this.channel.perform("disappear"))}performOperations(e){e.cableReady&&i.default.perform(e.operations)}createSubscription(){if(this.consumer)return this.consumer.subscriptions.create({channel:this.channelName,identifier:this.getAttribute("identifier"),element_id:this.id,scope:this.getAttribute("scope"),exclude_current_user:"true"===this.getAttribute("exclude-current-user")},{connected:()=>{this.install()},disconnected:()=>{this.disappear(),this.uninstall()},rejected:()=>{this.uninstall()},received:this.performOperations.bind(this)});console.error("The `cubicle-element` helper cannot connect without an ActionCable consumer.")}get channelName(){return"Cubism::PresenceChannel"}}customElements.define("cubicle-element",r)}));
2
2
  //# sourceMappingURL=cubism.umd.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cubism.umd.min.js","sources":["../../../javascript/elements/cubicle.js","../../../../cable_ready/javascript/utils.js","../../../javascript/elements/index.js"],"sourcesContent":["/* eslint-disable no-undef */\nimport CableReady, { SubscribingElement } from 'cable_ready'\nimport { debounce } from 'cable_ready/javascript/utils'\n\nexport class Cubicle extends SubscribingElement {\n constructor () {\n super()\n const shadowRoot = this.attachShadow({ mode: 'open' })\n shadowRoot.innerHTML = `\n<style>\n :host {\n display: block;\n }\n</style>\n<slot></slot>\n`\n\n this.triggerRoot = this\n this.present = false\n }\n\n async connectedCallback () {\n if (this.preview) return\n\n this.appear = debounce(this.appear.bind(this), 50)\n\n this.appearTriggers = this.getAttribute('appear-trigger')\n ? this.getAttribute('appear-trigger').split(',')\n : []\n this.disappearTriggers = this.getAttribute('disappear-trigger')\n ? this.getAttribute('disappear-trigger').split(',')\n : []\n this.triggerRootSelector = this.getAttribute('trigger-root')\n\n this.consumer = await CableReady.consumer\n\n this.channel = this.createSubscription()\n\n this.appearanceIntersectionObserver = new IntersectionObserver(\n (entries, observer) => {\n entries.forEach(entry => {\n if (entry.target !== this.triggerRoot) return\n if (entry.isIntersecting) {\n if (!this.present) {\n this.appear()\n }\n } else {\n if (this.present) {\n this.disappear()\n }\n }\n })\n },\n { threshold: 0 }\n )\n\n this.mutationObserver = new MutationObserver((mutationsList, observer) => {\n if (this.triggerRootSelector) {\n // eslint-disable-next-line no-unused-vars\n for (const mutation of mutationsList) {\n const root = document.querySelector(this.triggerRootSelector)\n if (root) {\n this.uninstall()\n this.triggerRoot = root\n this.install()\n }\n }\n }\n this.mutationObserver.disconnect()\n })\n\n this.mutationObserver.observe(document, {\n subtree: true,\n childList: true\n })\n }\n\n disconnectedCallback () {\n this.disappear()\n super.disconnectedCallback()\n }\n\n install () {\n if (this.appearTriggers.includes('connect')) {\n this.appear()\n }\n\n this.appearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {\n this.appearanceIntersectionObserver.observe(this.triggerRoot)\n })\n\n this.appearTriggers\n .filter(eventName => eventName !== 'connect' && eventName !== 'intersect')\n .forEach(eventName => {\n this.triggerRoot.addEventListener(eventName, this.appear.bind(this))\n })\n\n this.disappearTriggers\n .filter(\n eventName => eventName !== 'disconnect' && eventName !== 'intersect'\n )\n .forEach(eventName => {\n this.triggerRoot.addEventListener(eventName, this.disappear.bind(this))\n })\n\n this.disappearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {})\n }\n\n uninstall () {\n this.appearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {\n this.appearanceIntersectionObserver.unobserve(this.triggerRoot)\n })\n\n this.appearTriggers\n .filter(eventName => eventName !== 'connect' && eventName !== 'intersect')\n .forEach(eventName => {\n this.triggerRoot.removeEventListener(eventName, this.appear.bind(this))\n })\n\n this.disappearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {})\n\n this.disappearTriggers\n .filter(\n eventName => eventName !== 'disconnect' && eventName !== 'intersect'\n )\n .forEach(eventName => {\n this.triggerRoot.removeEventListener(\n eventName,\n this.disappear.bind(this)\n )\n })\n }\n\n appear () {\n if (this.channel) {\n this.present = true\n this.channel.perform('appear')\n }\n }\n\n disappear () {\n if (this.channel) {\n this.present = false\n this.channel.perform('disappear')\n }\n }\n\n performOperations (data) {\n if (data.cableReady) {\n CableReady.perform(data.operations)\n }\n }\n\n createSubscription () {\n if (!this.consumer) {\n console.error(\n 'The `cubicle-element` helper cannot connect without an ActionCable consumer.'\n )\n return\n }\n\n return this.consumer.subscriptions.create(\n {\n channel: this.channelName,\n identifier: this.getAttribute('identifier'),\n element_id: this.id,\n scope: this.getAttribute('scope'),\n exclude_current_user:\n this.getAttribute('exclude-current-user') === 'true'\n },\n {\n connected: () => {\n this.install()\n },\n disconnected: () => {\n this.disappear()\n this.uninstall()\n },\n rejected: () => {\n this.uninstall()\n },\n received: this.performOperations.bind(this)\n }\n )\n }\n\n get channelName () {\n return 'Cubism::PresenceChannel'\n }\n}\n","import { inputTags, textInputTypes } from './enums'\nimport ActiveElement from './active_element'\n\n// Indicates if the passed element is considered a text input.\n//\nconst isTextInput = element => {\n return inputTags[element.tagName] && textInputTypes[element.type]\n}\n\n// Assigns focus to the appropriate element... preferring the explicitly passed selector\n//\n// * selector - a CSS selector for the element that should have focus\n//\nconst assignFocus = selector => {\n const element =\n selector && selector.nodeType === Node.ELEMENT_NODE\n ? selector\n : document.querySelector(selector)\n const focusElement = element || ActiveElement.element\n if (focusElement && focusElement.focus) focusElement.focus()\n}\n\n// Dispatches an event on the passed element\n//\n// * element - the element\n// * name - the name of the event\n// * detail - the event detail\n//\nconst dispatch = (element, name, detail = {}) => {\n const init = { bubbles: true, cancelable: true, detail }\n const event = new CustomEvent(name, init)\n element.dispatchEvent(event)\n if (window.jQuery) window.jQuery(element).trigger(name, detail)\n}\n\n// Accepts an xPath query and returns the element found at that position in the DOM\n//\nconst xpathToElement = xpath => {\n return document.evaluate(\n xpath,\n document,\n null,\n XPathResult.FIRST_ORDERED_NODE_TYPE,\n null\n ).singleNodeValue\n}\n\n// Accepts an xPath query and returns all matching elements in the DOM\n//\nconst xpathToElementArray = (xpath, reverse = false) => {\n const snapshotList = document.evaluate(\n xpath,\n document,\n null,\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\n null\n )\n const snapshots = []\n\n for (let i = 0; i < snapshotList.snapshotLength; i++) {\n snapshots.push(snapshotList.snapshotItem(i))\n }\n\n return reverse ? snapshots.reverse() : snapshots\n}\n\n// Return an array with the class names to be used\n//\n// * names - could be a string or an array of strings for multiple classes.\n//\nconst getClassNames = names => Array.from(names).flat()\n\n// Perform operation for either the first or all of the elements returned by CSS selector\n//\n// * operation - the instruction payload from perform\n// * callback - the operation function to run for each element\n//\nconst processElements = (operation, callback) => {\n Array.from(\n operation.selectAll ? operation.element : [operation.element]\n ).forEach(callback)\n}\n\n// convert string to kebab-case\n// most other implementations (lodash) are focused on camelCase to kebab-case\n// instead, this uses word token boundaries to produce readable URL slugs and keys\n// this implementation will not support Emoji or other non-ASCII characters\n//\nconst kebabize = createCompounder(function (result, word, index) {\n return result + (index ? '-' : '') + word.toLowerCase()\n})\n\nfunction createCompounder (callback) {\n return function (str) {\n return words(str).reduce(callback, '')\n }\n}\n\nconst words = str => {\n str = str == null ? '' : str\n return str.match(/([A-Z]{2,}|[0-9]+|[A-Z]?[a-z]+|[A-Z])/g) || []\n}\n\n// Provide a standardized pipeline of checks and modifications to all operations based on provided options\n// Currently skips execution if cancelled and implements an optional delay\n//\nconst operate = (operation, callback) => {\n if (!operation.cancel) {\n operation.delay ? setTimeout(callback, operation.delay) : callback()\n return true\n }\n return false\n}\n\n// Dispatch life-cycle events with standardized naming\nconst before = (target, operation) =>\n dispatch(\n target,\n `cable-ready:before-${kebabize(operation.operation)}`,\n operation\n )\n\nconst after = (target, operation) =>\n dispatch(\n target,\n `cable-ready:after-${kebabize(operation.operation)}`,\n operation\n )\n\nfunction debounce (fn, delay = 250) {\n let timer\n return (...args) => {\n const callback = () => fn.apply(this, args)\n if (timer) clearTimeout(timer)\n timer = setTimeout(callback, delay)\n }\n}\n\nfunction handleErrors (response) {\n if (!response.ok) throw Error(response.statusText)\n return response\n}\n\nfunction safeScalar (val) {\n if (\n val !== undefined &&\n !['string', 'number', 'boolean'].includes(typeof val)\n )\n console.warn(\n `Operation expects a string, number or boolean, but got ${val} (${typeof val})`\n )\n return val != null ? val : ''\n}\n\nfunction safeString (str) {\n if (str !== undefined && typeof str !== 'string')\n console.warn(`Operation expects a string, but got ${str} (${typeof str})`)\n\n return str != null ? String(str) : ''\n}\n\nfunction safeArray (arr) {\n if (arr !== undefined && !Array.isArray(arr))\n console.warn(`Operation expects an array, but got ${arr} (${typeof arr})`)\n return arr != null ? Array.from(arr) : []\n}\n\nfunction safeObject (obj) {\n if (obj !== undefined && typeof obj !== 'object')\n console.warn(`Operation expects an object, but got ${obj} (${typeof obj})`)\n return obj != null ? Object(obj) : {}\n}\n\nfunction safeStringOrArray (elem) {\n if (elem !== undefined && !Array.isArray(elem) && typeof elem !== 'string')\n console.warn(`Operation expects an Array or a String, but got ${elem} (${typeof elem})`)\n\n return elem == null ? '' : Array.isArray(elem) ? Array.from(elem) : String(elem)\n}\n\nfunction fragmentToString (fragment) {\n return new XMLSerializer().serializeToString(fragment)\n}\n\n// A proxy method to wrap a fetch call in error handling\n//\n// * url - the URL to fetch\n// * additionalHeaders - an object of additional headers passed to fetch\n//\nasync function graciouslyFetch (url, additionalHeaders) {\n try {\n const response = await fetch(url, {\n headers: {\n 'X-REQUESTED-WITH': 'XmlHttpRequest',\n ...additionalHeaders\n }\n })\n if (response == undefined) return\n\n handleErrors(response)\n\n return response\n } catch (e) {\n console.error(`Could not fetch ${url}`)\n }\n}\n\nexport {\n isTextInput,\n assignFocus,\n dispatch,\n xpathToElement,\n xpathToElementArray,\n getClassNames,\n processElements,\n operate,\n before,\n after,\n debounce,\n handleErrors,\n graciouslyFetch,\n kebabize,\n safeScalar,\n safeString,\n safeArray,\n safeObject,\n safeStringOrArray,\n fragmentToString\n}\n","/* global customElements */\n\nimport { Cubicle } from './cubicle'\n\nexport * from './cubicle'\n\ncustomElements.define('cubicle-element', Cubicle)\n"],"names":["Cubicle","SubscribingElement","constructor","super","this","attachShadow","mode","innerHTML","triggerRoot","present","async","preview","appear","fn","delay","timer","args","clearTimeout","setTimeout","apply","debounce","bind","appearTriggers","getAttribute","split","disappearTriggers","triggerRootSelector","consumer","CableReady","channel","createSubscription","appearanceIntersectionObserver","IntersectionObserver","entries","observer","forEach","entry","target","isIntersecting","disappear","threshold","mutationObserver","MutationObserver","mutationsList","mutation","root","document","querySelector","uninstall","install","disconnect","observe","subtree","childList","disconnectedCallback","includes","filter","eventName","addEventListener","unobserve","removeEventListener","perform","performOperations","data","cableReady","operations","subscriptions","create","channelName","identifier","element_id","id","scope","exclude_current_user","connected","disconnected","rejected","received","console","error","customElements","define"],"mappings":"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"}
1
+ {"version":3,"file":"cubism.umd.min.js","sources":["../../../javascript/elements/cubicle.js","../../../../cable_ready/javascript/utils.js","../../../javascript/elements/index.js"],"sourcesContent":["/* eslint-disable no-undef */\nimport CableReady, { SubscribingElement } from 'cable_ready'\nimport { debounce } from 'cable_ready/javascript/utils'\n\nexport class Cubicle extends SubscribingElement {\n constructor () {\n super()\n const shadowRoot = this.attachShadow({ mode: 'open' })\n shadowRoot.innerHTML = `\n<style>\n :host {\n display: block;\n }\n</style>\n<slot></slot>\n`\n\n this.triggerRoot = this\n this.present = false\n }\n\n async connectedCallback () {\n if (this.preview) return\n\n this.appear = debounce(this.appear.bind(this), 50)\n\n this.appearTriggers = this.getAttribute('appear-trigger')\n ? this.getAttribute('appear-trigger').split(',')\n : []\n this.disappearTriggers = this.getAttribute('disappear-trigger')\n ? this.getAttribute('disappear-trigger').split(',')\n : []\n this.triggerRootSelector = this.getAttribute('trigger-root')\n\n this.consumer = await CableReady.cable.getConsumer()\n\n this.channel = this.createSubscription()\n\n this.appearanceIntersectionObserver = new IntersectionObserver(\n (entries, observer) => {\n entries.forEach(entry => {\n if (entry.target !== this.triggerRoot) return\n if (entry.isIntersecting) {\n if (!this.present) {\n this.appear()\n }\n } else {\n if (this.present) {\n this.disappear()\n }\n }\n })\n },\n { threshold: 0 }\n )\n\n this.mutationObserver = new MutationObserver((mutationsList, observer) => {\n if (this.triggerRootSelector) {\n // eslint-disable-next-line no-unused-vars\n for (const mutation of mutationsList) {\n const root = document.querySelector(this.triggerRootSelector)\n if (root) {\n this.uninstall()\n this.triggerRoot = root\n this.install()\n }\n }\n }\n this.mutationObserver.disconnect()\n })\n\n this.mutationObserver.observe(document, {\n subtree: true,\n childList: true\n })\n }\n\n disconnectedCallback () {\n this.disappear()\n super.disconnectedCallback()\n }\n\n install () {\n if (this.appearTriggers.includes('connect')) {\n this.appear()\n }\n\n this.appearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {\n this.appearanceIntersectionObserver.observe(this.triggerRoot)\n })\n\n this.appearTriggers\n .filter(eventName => eventName !== 'connect' && eventName !== 'intersect')\n .forEach(eventName => {\n this.triggerRoot.addEventListener(eventName, this.appear.bind(this))\n })\n\n this.disappearTriggers\n .filter(\n eventName => eventName !== 'disconnect' && eventName !== 'intersect'\n )\n .forEach(eventName => {\n this.triggerRoot.addEventListener(eventName, this.disappear.bind(this))\n })\n\n this.disappearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {})\n }\n\n uninstall () {\n this.appearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {\n this.appearanceIntersectionObserver.unobserve(this.triggerRoot)\n })\n\n this.appearTriggers\n .filter(eventName => eventName !== 'connect' && eventName !== 'intersect')\n .forEach(eventName => {\n this.triggerRoot.removeEventListener(eventName, this.appear.bind(this))\n })\n\n this.disappearTriggers\n .filter(eventName => eventName === 'intersect')\n .forEach(() => {})\n\n this.disappearTriggers\n .filter(\n eventName => eventName !== 'disconnect' && eventName !== 'intersect'\n )\n .forEach(eventName => {\n this.triggerRoot.removeEventListener(\n eventName,\n this.disappear.bind(this)\n )\n })\n }\n\n appear () {\n if (this.channel) {\n this.present = true\n this.channel.perform('appear')\n }\n }\n\n disappear () {\n if (this.channel) {\n this.present = false\n this.channel.perform('disappear')\n }\n }\n\n performOperations (data) {\n if (data.cableReady) {\n CableReady.perform(data.operations)\n }\n }\n\n createSubscription () {\n if (!this.consumer) {\n console.error(\n 'The `cubicle-element` helper cannot connect without an ActionCable consumer.'\n )\n return\n }\n\n return this.consumer.subscriptions.create(\n {\n channel: this.channelName,\n identifier: this.getAttribute('identifier'),\n element_id: this.id,\n scope: this.getAttribute('scope'),\n exclude_current_user:\n this.getAttribute('exclude-current-user') === 'true'\n },\n {\n connected: () => {\n this.install()\n },\n disconnected: () => {\n this.disappear()\n this.uninstall()\n },\n rejected: () => {\n this.uninstall()\n },\n received: this.performOperations.bind(this)\n }\n )\n }\n\n get channelName () {\n return 'Cubism::PresenceChannel'\n }\n}\n","import { inputTags, textInputTypes } from './enums'\nimport ActiveElement from './active_element'\n\n// Indicates if the passed element is considered a text input.\n//\nconst isTextInput = element => {\n return inputTags[element.tagName] && textInputTypes[element.type]\n}\n\n// Assigns focus to the appropriate element... preferring the explicitly passed selector\n//\n// * selector - a CSS selector for the element that should have focus\n//\nconst assignFocus = selector => {\n const element =\n selector && selector.nodeType === Node.ELEMENT_NODE\n ? selector\n : document.querySelector(selector)\n const focusElement = element || ActiveElement.element\n if (focusElement && focusElement.focus) focusElement.focus()\n}\n\n// Dispatches an event on the passed element\n//\n// * element - the element\n// * name - the name of the event\n// * detail - the event detail\n//\nconst dispatch = (element, name, detail = {}) => {\n const init = { bubbles: true, cancelable: true, detail }\n const event = new CustomEvent(name, init)\n element.dispatchEvent(event)\n if (window.jQuery) window.jQuery(element).trigger(name, detail)\n}\n\n// Accepts an xPath query and returns the element found at that position in the DOM\n//\nconst xpathToElement = xpath => {\n return document.evaluate(\n xpath,\n document,\n null,\n XPathResult.FIRST_ORDERED_NODE_TYPE,\n null\n ).singleNodeValue\n}\n\n// Accepts an xPath query and returns all matching elements in the DOM\n//\nconst xpathToElementArray = (xpath, reverse = false) => {\n const snapshotList = document.evaluate(\n xpath,\n document,\n null,\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\n null\n )\n const snapshots = []\n\n for (let i = 0; i < snapshotList.snapshotLength; i++) {\n snapshots.push(snapshotList.snapshotItem(i))\n }\n\n return reverse ? snapshots.reverse() : snapshots\n}\n\n// Return an array with the class names to be used\n//\n// * names - could be a string or an array of strings for multiple classes.\n//\nconst getClassNames = names => Array.from(names).flat()\n\n// Perform operation for either the first or all of the elements returned by CSS selector\n//\n// * operation - the instruction payload from perform\n// * callback - the operation function to run for each element\n//\nconst processElements = (operation, callback) => {\n Array.from(\n operation.selectAll ? operation.element : [operation.element]\n ).forEach(callback)\n}\n\n// convert string to kebab-case\n// most other implementations (lodash) are focused on camelCase to kebab-case\n// instead, this uses word token boundaries to produce readable URL slugs and keys\n// this implementation will not support Emoji or other non-ASCII characters\n//\nconst kebabize = createCompounder(function (result, word, index) {\n return result + (index ? '-' : '') + word.toLowerCase()\n})\n\nfunction createCompounder (callback) {\n return function (str) {\n return words(str).reduce(callback, '')\n }\n}\n\nconst words = str => {\n str = str == null ? '' : str\n return str.match(/([A-Z]{2,}|[0-9]+|[A-Z]?[a-z]+|[A-Z])/g) || []\n}\n\n// Provide a standardized pipeline of checks and modifications to all operations based on provided options\n// Currently skips execution if cancelled and implements an optional delay\n//\nconst operate = (operation, callback) => {\n if (!operation.cancel) {\n operation.delay ? setTimeout(callback, operation.delay) : callback()\n return true\n }\n return false\n}\n\n// Dispatch life-cycle events with standardized naming\nconst before = (target, operation) =>\n dispatch(\n target,\n `cable-ready:before-${kebabize(operation.operation)}`,\n operation\n )\n\nconst after = (target, operation) =>\n dispatch(\n target,\n `cable-ready:after-${kebabize(operation.operation)}`,\n operation\n )\n\nfunction debounce (fn, delay = 250) {\n let timer\n return (...args) => {\n const callback = () => fn.apply(this, args)\n if (timer) clearTimeout(timer)\n timer = setTimeout(callback, delay)\n }\n}\n\nfunction handleErrors (response) {\n if (!response.ok) throw Error(response.statusText)\n return response\n}\n\nfunction safeScalar (val) {\n if (\n val !== undefined &&\n !['string', 'number', 'boolean'].includes(typeof val)\n )\n console.warn(\n `Operation expects a string, number or boolean, but got ${val} (${typeof val})`\n )\n return val != null ? val : ''\n}\n\nfunction safeString (str) {\n if (str !== undefined && typeof str !== 'string')\n console.warn(`Operation expects a string, but got ${str} (${typeof str})`)\n\n return str != null ? String(str) : ''\n}\n\nfunction safeArray (arr) {\n if (arr !== undefined && !Array.isArray(arr))\n console.warn(`Operation expects an array, but got ${arr} (${typeof arr})`)\n return arr != null ? Array.from(arr) : []\n}\n\nfunction safeObject (obj) {\n if (obj !== undefined && typeof obj !== 'object')\n console.warn(`Operation expects an object, but got ${obj} (${typeof obj})`)\n return obj != null ? Object(obj) : {}\n}\n\nfunction safeStringOrArray (elem) {\n if (elem !== undefined && !Array.isArray(elem) && typeof elem !== 'string')\n console.warn(`Operation expects an Array or a String, but got ${elem} (${typeof elem})`)\n\n return elem == null ? '' : Array.isArray(elem) ? Array.from(elem) : String(elem)\n}\n\nfunction fragmentToString (fragment) {\n return new XMLSerializer().serializeToString(fragment)\n}\n\n// A proxy method to wrap a fetch call in error handling\n//\n// * url - the URL to fetch\n// * additionalHeaders - an object of additional headers passed to fetch\n//\nasync function graciouslyFetch (url, additionalHeaders) {\n try {\n const response = await fetch(url, {\n headers: {\n 'X-REQUESTED-WITH': 'XmlHttpRequest',\n ...additionalHeaders\n }\n })\n if (response == undefined) return\n\n handleErrors(response)\n\n return response\n } catch (e) {\n console.error(`Could not fetch ${url}`)\n }\n}\n\nclass BoundedQueue {\n constructor (maxSize) {\n this.maxSize = maxSize\n this.queue = []\n }\n\n push (item) {\n if (this.isFull()) {\n // Remove the oldest item to make space for the new one\n this.shift()\n }\n this.queue.push(item)\n }\n\n shift () {\n return this.queue.shift()\n }\n\n isFull () {\n return this.queue.length === this.maxSize\n }\n}\n\nexport {\n isTextInput,\n assignFocus,\n dispatch,\n xpathToElement,\n xpathToElementArray,\n getClassNames,\n processElements,\n operate,\n before,\n after,\n debounce,\n handleErrors,\n graciouslyFetch,\n kebabize,\n safeScalar,\n safeString,\n safeArray,\n safeObject,\n safeStringOrArray,\n fragmentToString,\n BoundedQueue\n}\n","/* global customElements */\n\nimport { Cubicle } from './cubicle'\n\nexport * from './cubicle'\n\ncustomElements.define('cubicle-element', Cubicle)\n"],"names":["Cubicle","SubscribingElement","constructor","super","this","attachShadow","mode","innerHTML","triggerRoot","present","async","preview","appear","fn","delay","timer","args","clearTimeout","setTimeout","apply","debounce","bind","appearTriggers","getAttribute","split","disappearTriggers","triggerRootSelector","consumer","CableReady","cable","getConsumer","channel","createSubscription","appearanceIntersectionObserver","IntersectionObserver","entries","observer","forEach","entry","target","isIntersecting","disappear","threshold","mutationObserver","MutationObserver","mutationsList","mutation","root","document","querySelector","uninstall","install","disconnect","observe","subtree","childList","disconnectedCallback","includes","filter","eventName","addEventListener","unobserve","removeEventListener","perform","performOperations","data","cableReady","operations","subscriptions","create","channelName","identifier","element_id","id","scope","exclude_current_user","connected","disconnected","rejected","received","console","error","customElements","define"],"mappings":"qVAIO,MAAMA,UAAgBC,EAAAA,mBAC3BC,cACEC,QACmBC,KAAKC,aAAa,CAAEC,KAAM,SAClCC,UAAY,4EASvBH,KAAKI,YAAcJ,KACnBA,KAAKK,SAAU,EAGjBC,0BACMN,KAAKO,UAETP,KAAKQ,OCyGT,SAAmBC,EAAIC,EAAQ,KAC7B,IAAIC,EACJ,MAAO,IAAIC,KAELD,GAAOE,aAAaF,GACxBA,EAAQG,YAFS,IAAML,EAAGM,MAAMf,KAAMY,IAETF,ID9GfM,CAAShB,KAAKQ,OAAOS,KAAKjB,MAAO,IAE/CA,KAAKkB,eAAiBlB,KAAKmB,aAAa,kBACpCnB,KAAKmB,aAAa,kBAAkBC,MAAM,KAC1C,GACJpB,KAAKqB,kBAAoBrB,KAAKmB,aAAa,qBACvCnB,KAAKmB,aAAa,qBAAqBC,MAAM,KAC7C,GACJpB,KAAKsB,oBAAsBtB,KAAKmB,aAAa,gBAE7CnB,KAAKuB,eAAiBC,UAAWC,MAAMC,cAEvC1B,KAAK2B,QAAU3B,KAAK4B,qBAEpB5B,KAAK6B,+BAAiC,IAAIC,sBACxC,CAACC,EAASC,KACRD,EAAQE,SAAQC,IACVA,EAAMC,SAAWnC,KAAKI,cACtB8B,EAAME,eACHpC,KAAKK,SACRL,KAAKQ,SAGHR,KAAKK,SACPL,KAAKqC,kBAKb,CAAEC,UAAW,IAGftC,KAAKuC,iBAAmB,IAAIC,kBAAiB,CAACC,EAAeT,KAC3D,GAAIhC,KAAKsB,oBAEP,IAAK,MAAMoB,KAAYD,EAAe,CACpC,MAAME,EAAOC,SAASC,cAAc7C,KAAKsB,qBACrCqB,IACF3C,KAAK8C,YACL9C,KAAKI,YAAcuC,EACnB3C,KAAK+C,WAIX/C,KAAKuC,iBAAiBS,gBAGxBhD,KAAKuC,iBAAiBU,QAAQL,SAAU,CACtCM,SAAS,EACTC,WAAW,KAIfC,uBACEpD,KAAKqC,YACLtC,MAAMqD,uBAGRL,UACM/C,KAAKkB,eAAemC,SAAS,YAC/BrD,KAAKQ,SAGPR,KAAKkB,eACFoC,QAAOC,GAA2B,cAAdA,IACpBtB,SAAQ,KACPjC,KAAK6B,+BAA+BoB,QAAQjD,KAAKI,gBAGrDJ,KAAKkB,eACFoC,QAAOC,GAA2B,YAAdA,GAAyC,cAAdA,IAC/CtB,SAAQsB,IACPvD,KAAKI,YAAYoD,iBAAiBD,EAAWvD,KAAKQ,OAAOS,KAAKjB,UAGlEA,KAAKqB,kBACFiC,QACCC,GAA2B,eAAdA,GAA4C,cAAdA,IAE5CtB,SAAQsB,IACPvD,KAAKI,YAAYoD,iBAAiBD,EAAWvD,KAAKqC,UAAUpB,KAAKjB,UAGrEA,KAAKqB,kBACFiC,QAAOC,GAA2B,cAAdA,IACpBtB,SAAQ,SAGba,YACE9C,KAAKkB,eACFoC,QAAOC,GAA2B,cAAdA,IACpBtB,SAAQ,KACPjC,KAAK6B,+BAA+B4B,UAAUzD,KAAKI,gBAGvDJ,KAAKkB,eACFoC,QAAOC,GAA2B,YAAdA,GAAyC,cAAdA,IAC/CtB,SAAQsB,IACPvD,KAAKI,YAAYsD,oBAAoBH,EAAWvD,KAAKQ,OAAOS,KAAKjB,UAGrEA,KAAKqB,kBACFiC,QAAOC,GAA2B,cAAdA,IACpBtB,SAAQ,SAEXjC,KAAKqB,kBACFiC,QACCC,GAA2B,eAAdA,GAA4C,cAAdA,IAE5CtB,SAAQsB,IACPvD,KAAKI,YAAYsD,oBACfH,EACAvD,KAAKqC,UAAUpB,KAAKjB,UAK5BQ,SACMR,KAAK2B,UACP3B,KAAKK,SAAU,EACfL,KAAK2B,QAAQgC,QAAQ,WAIzBtB,YACMrC,KAAK2B,UACP3B,KAAKK,SAAU,EACfL,KAAK2B,QAAQgC,QAAQ,cAIzBC,kBAAmBC,GACbA,EAAKC,YACPtC,UAAWmC,QAAQE,EAAKE,YAI5BnC,qBACE,GAAK5B,KAAKuB,SAOV,OAAOvB,KAAKuB,SAASyC,cAAcC,OACjC,CACEtC,QAAS3B,KAAKkE,YACdC,WAAYnE,KAAKmB,aAAa,cAC9BiD,WAAYpE,KAAKqE,GACjBC,MAAOtE,KAAKmB,aAAa,SACzBoD,qBACgD,SAA9CvE,KAAKmB,aAAa,yBAEtB,CACEqD,UAAW,KACTxE,KAAK+C,WAEP0B,aAAc,KACZzE,KAAKqC,YACLrC,KAAK8C,aAEP4B,SAAU,KACR1E,KAAK8C,aAEP6B,SAAU3E,KAAK4D,kBAAkB3C,KAAKjB,QA1BxC4E,QAAQC,MACN,gFA8BFX,kBACF,MAAO,2BE7LXY,eAAeC,OAAO,kBAAmBnF"}
@@ -21,10 +21,14 @@ class Cubism::PresenceChannel < ActionCable::Channel::Base
21
21
 
22
22
  def appear
23
23
  resource.set_present_users_for_scope(resource.present_users_for_scope(scope).add(user.id), scope) if scope
24
+ rescue ActiveRecord::RecordNotFound
25
+ # do nothing if the user wasn't found
24
26
  end
25
27
 
26
28
  def disappear
27
29
  resource.set_present_users_for_scope(resource.present_users_for_scope(scope).delete(user.id), scope) if scope
30
+ rescue ActiveRecord::RecordNotFound
31
+ # do nothing if the user wasn't found
28
32
  end
29
33
 
30
34
  private
data/cubism.gemspec~ CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.add_dependency "rails", ">= 6.0"
28
28
  spec.add_dependency "kredis", ">= 0.4"
29
- spec.add_dependency "cable_ready", "= 5.0.0.rc2"
29
+ spec.add_dependency "cable_ready", ">= 5.0.0"
30
30
 
31
31
  spec.add_development_dependency "standard"
32
32
  spec.add_development_dependency "nokogiri"
@@ -14,6 +14,7 @@ module Cubism
14
14
  begin
15
15
  do_parse
16
16
  rescue NameError
17
+ # TODO we need a better way to handle this, leads to false negatives
17
18
  # we ignore any name errors from unset instance variables or local assigns here
18
19
  end
19
20
 
@@ -23,11 +24,21 @@ module Cubism
23
24
  private
24
25
 
25
26
  def do_parse
26
- ActionView::Template::Handlers::ERB::Erubi.new(@source).evaluate(@view_context)
27
+ erubi = ActionView::Template::Handlers::ERB::Erubi.new(@source)
28
+
29
+ evaluate_view(erubi, @view_context)
27
30
  rescue SyntaxError
28
31
  end_at_end = /(<%\s+end\s+%>)\z/.match(@source)
29
32
  @source = end_at_end ? @source[..-(end_at_end[0].length + 1)] : @source[..-2]
30
33
  do_parse
31
34
  end
35
+
36
+ def evaluate_view(erubi, view_context)
37
+ view = Class.new(ActionView::Base) {
38
+ include view_context._routes.url_helpers
39
+ class_eval("define_method(:_template) { |local_assigns, output_buffer| #{erubi.src} }", erubi.filename.nil? ? "(erubi)" : erubi.filename, 0)
40
+ }.empty
41
+ view._run(:_template, nil, {}, ActionView::OutputBuffer.new)
42
+ end
32
43
  end
33
44
  end
@@ -1,3 +1,3 @@
1
1
  module Cubism
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minthesize/cubism",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Lightweight Resource-Based Presence Solution with CableReady.",
5
5
  "main": "./dist/cubism.umd.min.js",
6
6
  "module": "./dist/cubism.min.js",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cubism
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Rubisch
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-14 00:00:00.000000000 Z
11
+ date: 2024-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -217,7 +217,7 @@ licenses:
217
217
  metadata:
218
218
  homepage_uri: https://github.com/julianrubisch/cubism
219
219
  source_code_uri: https://github.com/julianrubisch/cubism.git
220
- post_install_message:
220
+ post_install_message:
221
221
  rdoc_options: []
222
222
  require_paths:
223
223
  - lib
@@ -233,7 +233,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
233
233
  version: '0'
234
234
  requirements: []
235
235
  rubygems_version: 3.1.4
236
- signing_key:
236
+ signing_key:
237
237
  specification_version: 4
238
238
  summary: Lightweight Resource-Based Presence Solution with CableReady
239
239
  test_files: