polaris_view_components 0.7.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/icons/polaris/AnalyticsMinor.svg +1 -0
  3. data/app/assets/icons/polaris/AppsMinor.svg +1 -0
  4. data/app/assets/icons/polaris/BlockMinor.svg +1 -0
  5. data/app/assets/icons/polaris/ButtonMinor.svg +1 -0
  6. data/app/assets/icons/polaris/CaretDownMinor.svg +1 -1
  7. data/app/assets/icons/polaris/CaretUpMinor.svg +1 -1
  8. data/app/assets/icons/polaris/CircleTickMinor.svg +1 -0
  9. data/app/assets/icons/polaris/Columns3Minor.svg +1 -0
  10. data/app/assets/icons/polaris/CustomersMinor.svg +1 -1
  11. data/app/assets/icons/polaris/DiscountsMinor.svg +1 -0
  12. data/app/assets/icons/polaris/DropdownMinor.svg +1 -1
  13. data/app/assets/icons/polaris/FinancesMajor.svg +1 -0
  14. data/app/assets/icons/polaris/FinancesMinor.svg +1 -0
  15. data/app/assets/icons/polaris/HomeMinor.svg +1 -0
  16. data/app/assets/icons/polaris/MarketingMinor.svg +1 -0
  17. data/app/assets/icons/polaris/OnlineStoreMinor.svg +1 -0
  18. data/app/assets/icons/polaris/OrdersMinor.svg +1 -0
  19. data/app/assets/icons/polaris/ProductsMinor.svg +1 -0
  20. data/app/assets/icons/polaris/QuestionMarkInverseMajor.svg +1 -0
  21. data/app/assets/icons/polaris/QuestionMarkInverseMinor.svg +1 -0
  22. data/app/assets/icons/polaris/SelectMinor.svg +1 -1
  23. data/app/assets/icons/polaris/TitleMinor.svg +1 -0
  24. data/app/assets/icons/polaris/WandMinor.svg +1 -0
  25. data/app/assets/javascripts/polaris_view_components/autocomplete_controller.js +32 -15
  26. data/app/assets/javascripts/polaris_view_components/collapsible_controller.js +19 -0
  27. data/app/assets/javascripts/polaris_view_components/dropzone_controller.js +495 -0
  28. data/app/assets/javascripts/polaris_view_components/index.js +4 -0
  29. data/app/assets/javascripts/polaris_view_components/polaris_controller.js +4 -0
  30. data/app/assets/javascripts/polaris_view_components/popover_controller.js +9 -2
  31. data/app/assets/javascripts/polaris_view_components/toast_controller.js +13 -2
  32. data/app/assets/javascripts/polaris_view_components/utils.js +23 -0
  33. data/app/assets/javascripts/polaris_view_components.js +560 -65
  34. data/app/assets/stylesheets/polaris_view_components/custom.css +38 -6
  35. data/app/assets/stylesheets/polaris_view_components.css +2107 -2021
  36. data/app/assets/stylesheets/polaris_view_components.postcss.css +1 -1
  37. data/app/components/polaris/action_list/item_component.rb +1 -1
  38. data/app/components/polaris/action_list/section_component.rb +1 -1
  39. data/app/components/polaris/action_list_component.rb +1 -1
  40. data/app/components/polaris/autocomplete/action_component.rb +1 -1
  41. data/app/components/polaris/autocomplete/option_component.rb +1 -1
  42. data/app/components/polaris/autocomplete/section_component.rb +1 -1
  43. data/app/components/polaris/autocomplete_component.rb +9 -2
  44. data/app/components/polaris/avatar_component.rb +1 -1
  45. data/app/components/polaris/badge_component.rb +1 -1
  46. data/app/components/polaris/banner_component.rb +2 -2
  47. data/app/components/polaris/base_button.rb +1 -1
  48. data/app/components/polaris/base_checkbox.rb +1 -1
  49. data/app/components/polaris/base_component.rb +1 -1
  50. data/app/components/polaris/base_radio_button.rb +1 -1
  51. data/app/components/polaris/button_group_component.rb +3 -3
  52. data/app/components/polaris/callout_card_component.rb +1 -1
  53. data/app/components/polaris/caption_component.rb +1 -1
  54. data/app/components/polaris/card/header_component.rb +1 -1
  55. data/app/components/polaris/card/section_component.rb +2 -2
  56. data/app/components/polaris/card_component.rb +1 -1
  57. data/app/components/polaris/checkbox_component.rb +1 -1
  58. data/app/components/polaris/choice_component.rb +1 -1
  59. data/app/components/polaris/choice_list_component.rb +1 -1
  60. data/app/components/polaris/collapsible_component.rb +37 -0
  61. data/app/components/polaris/component.rb +6 -1
  62. data/app/components/polaris/data_table/cell_component.rb +1 -1
  63. data/app/components/polaris/data_table/column_component.rb +1 -1
  64. data/app/components/polaris/data_table_component.rb +1 -1
  65. data/app/components/polaris/description_list_component.rb +2 -2
  66. data/app/components/polaris/display_text_component.rb +1 -1
  67. data/app/components/polaris/dropzone_component.html.erb +156 -0
  68. data/app/components/polaris/dropzone_component.rb +150 -0
  69. data/app/components/polaris/empty_state_component.rb +1 -1
  70. data/app/components/polaris/exception_list/item_component.rb +1 -1
  71. data/app/components/polaris/exception_list_component.rb +1 -1
  72. data/app/components/polaris/filters_component.rb +3 -3
  73. data/app/components/polaris/footer_help_component.rb +1 -1
  74. data/app/components/polaris/form_layout/group_component.rb +2 -2
  75. data/app/components/polaris/form_layout/item_component.rb +1 -1
  76. data/app/components/polaris/form_layout_component.rb +1 -1
  77. data/app/components/polaris/frame/save_bar_component.rb +1 -1
  78. data/app/components/polaris/frame/top_bar_component.rb +1 -1
  79. data/app/components/polaris/frame_component.rb +1 -1
  80. data/app/components/polaris/heading_component.rb +1 -1
  81. data/app/components/polaris/headless_button.rb +1 -1
  82. data/app/components/polaris/icon_component.rb +1 -1
  83. data/app/components/polaris/index_table/cell_component.rb +1 -1
  84. data/app/components/polaris/index_table/column_component.rb +1 -1
  85. data/app/components/polaris/index_table_component.rb +1 -1
  86. data/app/components/polaris/inline_error_component.rb +1 -1
  87. data/app/components/polaris/keyboard_key_component.rb +20 -0
  88. data/app/components/polaris/label_component.rb +1 -1
  89. data/app/components/polaris/labelled_component.rb +1 -1
  90. data/app/components/polaris/layout/annotated_section.rb +1 -1
  91. data/app/components/polaris/layout/section.rb +1 -1
  92. data/app/components/polaris/layout_component.rb +1 -1
  93. data/app/components/polaris/link_component.rb +1 -1
  94. data/app/components/polaris/list_component.rb +2 -2
  95. data/app/components/polaris/modal/section_component.rb +1 -1
  96. data/app/components/polaris/modal_component.rb +1 -1
  97. data/app/components/polaris/navigation/item_component.rb +2 -2
  98. data/app/components/polaris/navigation/section_component.rb +2 -2
  99. data/app/components/polaris/navigation_component.rb +1 -1
  100. data/app/components/polaris/option_list/checkbox_component.rb +1 -1
  101. data/app/components/polaris/option_list/option_component.rb +1 -1
  102. data/app/components/polaris/option_list/radio_button_component.rb +1 -1
  103. data/app/components/polaris/option_list/section_component.rb +1 -1
  104. data/app/components/polaris/option_list_component.rb +1 -1
  105. data/app/components/polaris/page_actions_component.rb +1 -1
  106. data/app/components/polaris/page_component.rb +1 -1
  107. data/app/components/polaris/pagination_component.rb +1 -1
  108. data/app/components/polaris/popover/pane_component.rb +1 -1
  109. data/app/components/polaris/popover/section_component.rb +1 -1
  110. data/app/components/polaris/popover_component.rb +10 -4
  111. data/app/components/polaris/progress_bar_component.rb +1 -1
  112. data/app/components/polaris/radio_button_component.rb +1 -1
  113. data/app/components/polaris/resource_item_component.rb +4 -2
  114. data/app/components/polaris/resource_list_component.rb +1 -1
  115. data/app/components/polaris/scrollable_component.rb +1 -1
  116. data/app/components/polaris/select_component.rb +1 -1
  117. data/app/components/polaris/setting_toggle_component.rb +1 -1
  118. data/app/components/polaris/shopify_navigation_component.rb +2 -2
  119. data/app/components/polaris/skeleton_body_text_component.rb +1 -1
  120. data/app/components/polaris/skeleton_display_text_component.rb +32 -0
  121. data/app/components/polaris/skeleton_thumbnail_component.rb +31 -0
  122. data/app/components/polaris/spacer_component.rb +1 -1
  123. data/app/components/polaris/spinner_component.rb +1 -1
  124. data/app/components/polaris/stack/item_component.rb +15 -0
  125. data/app/components/polaris/stack_component.rb +2 -18
  126. data/app/components/polaris/subheading_component.rb +1 -1
  127. data/app/components/polaris/tabs/tab_component.rb +1 -1
  128. data/app/components/polaris/tabs_component.rb +1 -1
  129. data/app/components/polaris/tag_component.rb +3 -2
  130. data/app/components/polaris/text_container_component.rb +1 -1
  131. data/app/components/polaris/text_field_component.rb +2 -2
  132. data/app/components/polaris/text_style_component.rb +1 -1
  133. data/app/components/polaris/thumbnail_component.rb +1 -1
  134. data/app/components/polaris/toast_component.rb +1 -1
  135. data/app/components/polaris/top_bar/user_menu_component.rb +1 -1
  136. data/app/components/polaris/visually_hidden_component.rb +1 -1
  137. data/app/helpers/polaris/form_builder.rb +14 -5
  138. data/app/helpers/polaris/view_helper.rb +6 -1
  139. data/config/locales/en.yml +6 -0
  140. data/lib/polaris/view_components/engine.rb +5 -1
  141. data/lib/polaris/view_components/version.rb +1 -1
  142. metadata +31 -21
  143. data/app/components/polaris/application_component.rb +0 -35
  144. data/app/components/polaris/dropzone/component.html.erb +0 -72
  145. data/app/components/polaris/dropzone/component.rb +0 -128
  146. data/app/components/polaris/dropzone/controller.js +0 -226
  147. data/app/components/polaris/dropzone/utils.js +0 -57
  148. data/app/components/polaris/new_component.rb +0 -10
  149. data/app/helpers/polaris/conditional_helper.rb +0 -11
@@ -0,0 +1,495 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+ import { debounce, formatBytes } from './utils'
3
+
4
+ const dragEvents = ['dragover', 'dragenter', 'drop']
5
+ const SIZES = {
6
+ SMALL: 'small',
7
+ MEDIUM: 'medium',
8
+ LARGE: 'large',
9
+ EXTRA_LARGE: 'extraLarge',
10
+ }
11
+
12
+ // eslint-disable-next-line import/no-default-export
13
+ export default class extends Controller {
14
+ static targets = [
15
+ 'container',
16
+ 'fileUpload',
17
+ 'loader',
18
+ 'input',
19
+ 'preview',
20
+ 'previewTemplate',
21
+ 'itemTemplate',
22
+ 'overlay',
23
+ 'errorOverlay'
24
+ ]
25
+ static classes = ['disabled']
26
+ static values = {
27
+ accept: String,
28
+ allowMultiple: Boolean,
29
+ disabled: Boolean,
30
+ dropOnPage: Boolean,
31
+ focused: Boolean,
32
+ renderPreview: Boolean,
33
+ size: String
34
+ }
35
+
36
+ files = []
37
+ acceptedFiles = []
38
+ rejectedFiles = []
39
+ _dragging = false
40
+ dragTargets = []
41
+ previewRendered = false
42
+ _size = 'large'
43
+
44
+ connect () {
45
+ document.body.addEventListener('click', this.onExternalTriggerClick)
46
+ addEventListener('resize', this.onWindowResize)
47
+ addEventListener('direct-uploads:start', this.onDirectUploadsStart)
48
+ addEventListener('direct-uploads:end', this.onDirectUploadsEnd)
49
+ addEventListener('direct-upload:initialize', this.onDirectUploadInitialize)
50
+ addEventListener('direct-upload:start', this.onDirectUploadStart)
51
+ addEventListener('direct-upload:progress', this.onDirectUploadProgress)
52
+ addEventListener('direct-upload:error', this.onDirectUploadError)
53
+ addEventListener('direct-upload:end', this.onDirectUploadEnd)
54
+
55
+ this.onWindowResize()
56
+ }
57
+
58
+ disconnect () {
59
+ document.body.removeEventListener('click', this.onExternalTriggerClick)
60
+ removeEventListener('resize', this.onWindowResize)
61
+ removeEventListener('direct-uploads:start', this.onDirectUploadsStart)
62
+ removeEventListener('direct-uploads:end', this.onDirectUploadsEnd)
63
+ removeEventListener('direct-upload:initialize', this.onDirectUploadInitialize)
64
+ removeEventListener('direct-upload:start', this.onDirectUploadStart)
65
+ removeEventListener('direct-upload:progress', this.onDirectUploadProgress)
66
+ removeEventListener('direct-upload:error', this.onDirectUploadError)
67
+ removeEventListener('direct-upload:end', this.onDirectUploadEnd)
68
+ }
69
+
70
+ onExternalTriggerClick = (event) => {
71
+ const trigger = event.target.closest(`[data-${this.identifier}-external-target="trigger"]`)
72
+ if (!trigger) return
73
+
74
+ event.preventDefault()
75
+
76
+ this.onClick()
77
+ }
78
+
79
+ onWindowResize = debounce(() => {
80
+ const size = this.calculateSize()
81
+
82
+ if (size !== this.size) {
83
+ this.size = size
84
+ }
85
+ }, 50)
86
+
87
+ onBlur () {
88
+ this.focusedValue = false
89
+ }
90
+
91
+ onChange (e) {
92
+ this.stopEvent(e)
93
+ if (this.disabled) return
94
+
95
+ this.clearFiles()
96
+
97
+ const fileList = getDataTransferFiles(e)
98
+ const { files, acceptedFiles, rejectedFiles } = this.getValidatedFiles(fileList)
99
+ this.dragTargets = []
100
+
101
+ this.files = files
102
+ this.acceptedFiles = acceptedFiles
103
+ this.rejectedFiles = rejectedFiles
104
+
105
+ this.render()
106
+ }
107
+
108
+ onDragOver (e) {
109
+ this.stopEvent(e)
110
+ if (this.disabled) return
111
+ }
112
+
113
+ onDragEnter (e) {
114
+ this.stopEvent(e)
115
+ if (this.disabled) return
116
+
117
+ if (e.target && !this.dragTargets.includes(e.target)) {
118
+ this.dragTargets.push(e.target)
119
+ }
120
+
121
+ if (this.dragging) return
122
+
123
+ this.dragging = true
124
+ }
125
+
126
+ onDragLeave (e) {
127
+ this.stopEvent(e)
128
+ if (this.disabled) return
129
+
130
+ this.dragTargets = this.dragTargets.filter(el => {
131
+ const compareNode = this.element
132
+
133
+ return el !== e.target && compareNode && compareNode.contains(el)
134
+ })
135
+
136
+ if (this.dragTargets.length > 0) return
137
+
138
+ this.dragging = false
139
+ }
140
+
141
+ onDrop (e) {
142
+ this.stopEvent(e)
143
+ if (this.disabled) return
144
+
145
+ this.dragging = false
146
+
147
+ this.onChange(e)
148
+ }
149
+
150
+ onFocus () {
151
+ this.focusedValue = true
152
+ }
153
+
154
+ onClick () {
155
+ if (this.disabledValue) return
156
+
157
+ this.open()
158
+ }
159
+
160
+ onDirectUploadsStart = () => {
161
+ this.disable()
162
+ }
163
+
164
+ onDirectUploadsEnd = () => {
165
+ this.enable()
166
+ this.clearFiles()
167
+ this.loaderTarget.classList.remove("Polaris--hidden")
168
+ }
169
+
170
+ onDirectUploadInitialize = (event) => {
171
+ const { target, detail } = event
172
+ const { id, file } = detail
173
+ const dropzone = target.closest('.Polaris-DropZone')
174
+ if (!dropzone) return
175
+
176
+ const content = dropzone.querySelector(`[data-file-name="${file.name}"]`)
177
+ const progressBar = content.parentElement.querySelector('[data-target="progress-bar"]')
178
+ progressBar.id = `direct-upload-${id}`
179
+ }
180
+
181
+ onDirectUploadStart = (event) => {
182
+ const { id } = event.detail
183
+ const progressBar = document.getElementById(`direct-upload-${id}`)
184
+ if (!progressBar) return
185
+
186
+ progressBar.classList.remove("Polaris--hidden")
187
+ }
188
+
189
+ onDirectUploadProgress = (event) => {
190
+ const { id, progress } = event.detail
191
+ const progressBar = document.getElementById(`direct-upload-${id}`)
192
+ if (!progressBar) return
193
+
194
+ const progressElement = progressBar.querySelector('.Polaris-ProgressBar__Indicator')
195
+ progressElement.style.width = `${progress}%`
196
+ }
197
+
198
+ onDirectUploadError = (event) => {
199
+ const { id, error } = event.detail
200
+ const progressBar = document.getElementById(`direct-upload-${id}`)
201
+ if (!progressBar) return
202
+
203
+ event.preventDefault()
204
+ progressBar.classList.add("Polaris--hidden")
205
+ const uploadError = progressBar.parentElement.querySelector('[data-target="upload-error"]')
206
+ const errorIcon = uploadError.querySelector('.Polaris-InlineError__Icon')
207
+ if (errorIcon) errorIcon.remove()
208
+ uploadError.classList.remove("Polaris--hidden")
209
+ }
210
+
211
+ onDirectUploadEnd = (event) => {
212
+ const { id } = event.detail
213
+ const progressBar = document.getElementById(`direct-upload-${id}`)
214
+ if (!progressBar) return
215
+
216
+ progressBar.classList.add("Polaris-ProgressBar--colorSuccess")
217
+ }
218
+
219
+ open () {
220
+ this.inputTarget.click()
221
+ }
222
+
223
+ focusedValueChanged () {
224
+ this.element.classList.toggle('Polaris-DropZone--focused', this.focusedValue)
225
+ }
226
+
227
+ stopEvent (e) {
228
+ e.preventDefault()
229
+ e.stopPropagation()
230
+ }
231
+
232
+ getValidatedFiles (files) {
233
+ const acceptedFiles = []
234
+ const rejectedFiles = []
235
+
236
+ Array.from(files).forEach(file => {
237
+ if (fileAccepted(file, this.acceptValue)) {
238
+ acceptedFiles.push(file)
239
+ } else {
240
+ rejectedFiles.push(file)
241
+ }
242
+ })
243
+
244
+ if (!this.allowMultipleValue) {
245
+ acceptedFiles.splice(1, acceptedFiles.length)
246
+ rejectedFiles.push(...acceptedFiles.slice(1))
247
+ }
248
+
249
+ return { files, acceptedFiles, rejectedFiles }
250
+ }
251
+
252
+ render () {
253
+ if (this.files.length === 0) {
254
+ this.toggleFileUpload(true)
255
+ this.toggleErrorOverlay(false)
256
+ } else if (this.rejectedFiles.length > 0) {
257
+ this.toggleFileUpload(false)
258
+ this.toggleErrorOverlay(true)
259
+
260
+ const dropRejectedEvent = new CustomEvent('polaris-dropzone:drop-rejected', {
261
+ detail: { rejectedFiles: this.rejectedFiles }
262
+ })
263
+ this.element.dispatchEvent(dropRejectedEvent)
264
+ } else if (this.acceptedFiles.length > 0) {
265
+ if (this.renderPreviewValue) {
266
+ this.renderUploadedFiles()
267
+ this.toggleFileUpload(false)
268
+ }
269
+
270
+ this.toggleErrorOverlay(false)
271
+
272
+ const dropAcceptedEvent = new CustomEvent('polaris-dropzone:drop-accepted', {
273
+ detail: {acceptedFiles: this.acceptedFiles }
274
+ })
275
+ this.element.dispatchEvent(dropAcceptedEvent)
276
+ }
277
+
278
+ const dropEvent = new CustomEvent('polaris-dropzone:drop', {
279
+ detail: {
280
+ files: this.files,
281
+ acceptedFiles: this.acceptedFiles,
282
+ rejectedFiles: this.rejectedFiles
283
+ }
284
+ })
285
+ this.element.dispatchEvent(dropEvent)
286
+ }
287
+
288
+ renderUploadedFiles () {
289
+ if (this.acceptedFiles.length === 0) return
290
+
291
+ const clone = this.previewTemplateTarget.content.cloneNode(true)
292
+ const filesTarget = clone.querySelector('.target')
293
+ let files = this.acceptedFiles
294
+
295
+ if (this.sizeValue == 'small') files = [files[0]]
296
+
297
+ files
298
+ .map(file => this.renderFile(file))
299
+ .forEach(fragment => filesTarget.parentNode.appendChild(fragment))
300
+ filesTarget.remove()
301
+
302
+ this.containerTarget.prepend(clone)
303
+
304
+ this.previewRendered = true
305
+ }
306
+
307
+ toggleFileUpload (show = false) {
308
+ this.fileUploadTarget.classList.toggle('Polaris-VisuallyHidden', !show)
309
+ }
310
+
311
+ toggleErrorOverlay (show = false) {
312
+ this.errorOverlayTarget.classList.toggle('Polaris-VisuallyHidden', !show)
313
+ this.element.classList.toggle('Polaris-DropZone--hasError', show)
314
+ }
315
+
316
+ renderFile (file) {
317
+ const validImageTypes = ['image/gif', 'image/jpeg', 'image/png']
318
+ const clone = this.itemTemplateTarget.content.cloneNode(true)
319
+ const [icon, thumbnail, content, fileSize] = [
320
+ clone.querySelector('[data-target="icon"]'),
321
+ clone.querySelector('[data-target="thumbnail"]'),
322
+ clone.querySelector('[data-target="content"]'),
323
+ clone.querySelector('[data-target="file-size"]')
324
+ ]
325
+
326
+ if (validImageTypes.includes(file.type)) {
327
+ const img = thumbnail.querySelector('img')
328
+ img.alt = file.name
329
+ img.src = window.URL.createObjectURL(file)
330
+ icon.remove()
331
+ } else {
332
+ thumbnail.remove()
333
+ }
334
+
335
+ if (this.sizeValue != 'small') {
336
+ content.insertAdjacentText('afterbegin', file.name)
337
+ content.setAttribute('data-file-name', file.name)
338
+ fileSize.textContent = formatBytes(file.size)
339
+ }
340
+
341
+ return clone
342
+ }
343
+
344
+ clearFiles () {
345
+ if (!this.previewRendered) return
346
+
347
+ this.acceptedFiles = []
348
+ this.files = []
349
+ this.rejectedFiles = []
350
+
351
+ if (!this.hasPreviewTarget) return
352
+
353
+ this.previewTarget.remove()
354
+ this.previewRendered = false
355
+ }
356
+
357
+ calculateSize () {
358
+ const width = this.element.getBoundingClientRect().width
359
+
360
+ let size = SIZES.LARGE
361
+
362
+ if (width < 100) {
363
+ size = SIZES.SMALL
364
+ } else if (width < 160) {
365
+ size = SIZES.MEDIUM
366
+ } else if (width > 300) {
367
+ size = SIZES.EXTRA_LARGE
368
+ }
369
+
370
+ this.size = size
371
+
372
+ return size
373
+ }
374
+
375
+ getSizeClass (size = 'large') {
376
+ return this.sizeClassesSchema[size] || this.sizeClassesSchema.large
377
+ }
378
+
379
+ disable() {
380
+ this.disabled = true
381
+ this.element.classList.add(this.disabledClass)
382
+ this.inputTarget.disabled = true
383
+ }
384
+
385
+ enable() {
386
+ this.disabled = false
387
+ this.element.classList.remove(this.disabledClass)
388
+ this.inputTarget.disabled = false
389
+ }
390
+
391
+ get fileListRendered () {
392
+ return this.element.querySelector('[data-rendered]')
393
+ }
394
+
395
+ get dropNode () {
396
+ return this.dropOnPageValue ? document : this.element
397
+ }
398
+
399
+ get disabled () {
400
+ return this.disabledValue
401
+ }
402
+
403
+ set disabled (val) {
404
+ this.disabledValue = val
405
+ }
406
+
407
+ get dragging () {
408
+ return this._dragging
409
+ }
410
+
411
+ set dragging (val) {
412
+ this._dragging = val
413
+
414
+ this.element.classList.toggle('Polaris-DropZone--isDragging', val)
415
+ this.overlayTarget.classList.toggle('Polaris-VisuallyHidden', !val)
416
+ }
417
+
418
+ get sizeClassesSchema () {
419
+ return {
420
+ [SIZES.SMALL]: 'Polaris-DropZone--sizeSmall',
421
+ [SIZES.MEDIUM]: 'Polaris-DropZone--sizeMedium',
422
+ [SIZES.LARGE]: 'Polaris-DropZone--sizeLarge',
423
+ [SIZES.EXTRA_LARGE]: 'Polaris-DropZone--sizeExtraLarge',
424
+ }
425
+ }
426
+
427
+ get size () {
428
+ return this._size
429
+ }
430
+
431
+ set size (val) {
432
+ this._size = val
433
+
434
+ const sizeClassesToRemove = Object.values(this.sizeClassesSchema)
435
+ sizeClassesToRemove.forEach(className => this.element.classList.remove(className))
436
+
437
+ this.element.classList.add(this.getSizeClass(val))
438
+ }
439
+ }
440
+
441
+ export function fileAccepted (file, accept) {
442
+ return file.type === 'application/x-moz-file' || accepts(file, accept)
443
+ }
444
+
445
+ export function getDataTransferFiles (event) {
446
+ if (isDragEvent(event) && event.dataTransfer) {
447
+ const dt = event.dataTransfer
448
+
449
+ if (dt.files && dt.files.length) {
450
+ return Array.from(dt.files)
451
+ } else if (dt.items && dt.items.length) {
452
+ // Chrome is the only browser that allows to read the file list on drag
453
+ // events and uses `items` instead of `files` in this case.
454
+ return Array.from(dt.items)
455
+ }
456
+ } else if (isChangeEvent(event) && event.target.files) {
457
+ // Return files from even when a file was selected from an upload dialog
458
+ return Array.from(event.target.files)
459
+ }
460
+
461
+ return []
462
+ }
463
+
464
+ function accepts (file, acceptedFiles = ['']) {
465
+ if (file && acceptedFiles) {
466
+ const fileName = file.name || ''
467
+ const mimeType = file.type || ''
468
+ const baseMimeType = mimeType.replace(/\/.*$/, '')
469
+ const acceptedFilesArray = Array.isArray(acceptedFiles)
470
+ ? acceptedFiles
471
+ : acceptedFiles.split(',')
472
+
473
+ return acceptedFilesArray.some((type) => {
474
+ const validType = type.trim()
475
+ if (validType.startsWith('.')) {
476
+ return fileName.toLowerCase().endsWith(validType.toLowerCase())
477
+ } else if (validType.endsWith('/*')) {
478
+ // This is something like a image/* mime type
479
+ return baseMimeType === validType.replace(/\/.*$/, '')
480
+ }
481
+
482
+ return mimeType === validType
483
+ })
484
+ }
485
+
486
+ return true
487
+ }
488
+
489
+ function isDragEvent (event) {
490
+ return dragEvents.indexOf(event.type) > 0
491
+ }
492
+
493
+ function isChangeEvent (event) {
494
+ return event.type === 'change'
495
+ }
@@ -1,5 +1,7 @@
1
1
  import Autocomplete from './autocomplete_controller'
2
2
  import Button from './button_controller'
3
+ import Collapsible from './collapsible_controller'
4
+ import Dropzone from './dropzone_controller'
3
5
  import Frame from './frame_controller'
4
6
  import Modal from './modal_controller'
5
7
  import OptionList from './option_list_controller'
@@ -16,6 +18,8 @@ export { Frame, Modal, Polaris, Popover, ResourceItem, Scrollable, Select, TextF
16
18
  export function registerPolarisControllers(application) {
17
19
  application.register('polaris-autocomplete', Autocomplete)
18
20
  application.register('polaris-button', Button)
21
+ application.register('polaris-collapsible', Collapsible)
22
+ application.register('polaris-dropzone', Dropzone)
19
23
  application.register('polaris-frame', Frame)
20
24
  application.register('polaris-modal', Modal)
21
25
  application.register('polaris-option-list', OptionList)
@@ -17,6 +17,10 @@ export default class extends Controller {
17
17
  this.findElement("toast").show()
18
18
  }
19
19
 
20
+ toggleCollapsible() {
21
+ this.findElement("collapsible").toggle()
22
+ }
23
+
20
24
  // Private
21
25
 
22
26
  findElement(type) {
@@ -10,7 +10,7 @@ export default class extends Controller {
10
10
  }
11
11
 
12
12
  connect() {
13
- createPopper(this.activatorTarget, this.popoverTarget, {
13
+ this.popper = createPopper(this.activatorTarget, this.popoverTarget, {
14
14
  placement: this.placementValue,
15
15
  modifiers: [
16
16
  {
@@ -19,6 +19,12 @@ export default class extends Controller {
19
19
  offset: [0, 5],
20
20
  },
21
21
  },
22
+ {
23
+ name: 'flip',
24
+ options: {
25
+ allowedAutoPlacements: ['top-start', 'bottom-start', 'top-end', 'bottom-end']
26
+ },
27
+ }
22
28
  ]
23
29
  })
24
30
  if (this.activeValue) {
@@ -31,9 +37,10 @@ export default class extends Controller {
31
37
  this.popoverTarget.classList.toggle(this.openClass)
32
38
  }
33
39
 
34
- show() {
40
+ async show() {
35
41
  this.popoverTarget.classList.remove(this.closedClass)
36
42
  this.popoverTarget.classList.add(this.openClass)
43
+ await this.popper.update()
37
44
  }
38
45
 
39
46
  hide(event) {
@@ -37,8 +37,10 @@ export default class extends Controller {
37
37
  }
38
38
 
39
39
  getStyle(position) {
40
- const translateIn = -80 * position
41
- const translateOut = 150 - (80 * position)
40
+ const height = this.element.offsetHeight + this.heightOffset
41
+ const translateIn = height * -1
42
+ const translateOut = 150 - height
43
+
42
44
  return `--toast-translate-y-in: ${translateIn}px; --toast-translate-y-out: ${translateOut}px;`
43
45
  }
44
46
 
@@ -65,4 +67,13 @@ export default class extends Controller {
65
67
  get position() {
66
68
  return this.visibleToasts.filter(el => !this.element.isEqualNode(el)).length + 1
67
69
  }
70
+
71
+ get heightOffset() {
72
+ return this.visibleToasts
73
+ .filter(el => {
74
+ return !this.element.isEqualNode(el) && this.element.dataset.position > el.dataset.position
75
+ })
76
+ .map(el => el.offsetHeight)
77
+ .reduce((a, b) => a + b, 0)
78
+ }
68
79
  }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @param {Function} fn
3
+ * @param {number} wait
4
+ *
5
+ * @return {Function}
6
+ */
7
+ export function debounce (fn, wait) {
8
+ let timeoutId
9
+
10
+ return (...args) => {
11
+ clearTimeout(timeoutId)
12
+ timeoutId = setTimeout(() => fn.apply(this, args), wait)
13
+ }
14
+ }
15
+
16
+ export function formatBytes (bytes, decimals) {
17
+ if (bytes == 0) return '0 Bytes'
18
+ const k = 1024,
19
+ dm = decimals || 2,
20
+ sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
21
+ i = Math.floor(Math.log(bytes) / Math.log(k))
22
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
23
+ }