polaris_view_components 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }