bard-file_field 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +7 -0
  2. data/.nvmrc +1 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +8 -0
  6. data/Gemfile.lock +98 -0
  7. data/LICENSE +21 -0
  8. data/README.md +29 -0
  9. data/Rakefile +4 -0
  10. data/app/assets/javascripts/bard-file.js +4913 -0
  11. data/app/controllers/bard/file_field/blobs_controller.rb +11 -0
  12. data/bard-file/.gitignore +1 -0
  13. data/bard-file/bun.lockb +0 -0
  14. data/bard-file/index.js +2 -0
  15. data/bard-file/package.json +20 -0
  16. data/bard-file/rollup.config.js +26 -0
  17. data/bard-file_field.gemspec +34 -0
  18. data/config/routes.rb +6 -0
  19. data/dummy/.gitattributes +7 -0
  20. data/dummy/.gitignore +36 -0
  21. data/dummy/Gemfile +29 -0
  22. data/dummy/Gemfile.lock +353 -0
  23. data/dummy/README.md +24 -0
  24. data/dummy/Rakefile +13 -0
  25. data/dummy/app/assets/config/manifest.js +3 -0
  26. data/dummy/app/assets/images/.keep +0 -0
  27. data/dummy/app/assets/stylesheets/application.css +22 -0
  28. data/dummy/app/controllers/application_controller.rb +2 -0
  29. data/dummy/app/controllers/concerns/.keep +0 -0
  30. data/dummy/app/controllers/edge_cases_controller.rb +23 -0
  31. data/dummy/app/controllers/posts_controller.rb +33 -0
  32. data/dummy/app/controllers/validations_controller.rb +18 -0
  33. data/dummy/app/helpers/application_helper.rb +2 -0
  34. data/dummy/app/javascript/application.js +2 -0
  35. data/dummy/app/javascript/controllers/application.js +9 -0
  36. data/dummy/app/javascript/controllers/index.js +11 -0
  37. data/dummy/app/models/application_record.rb +3 -0
  38. data/dummy/app/models/concerns/.keep +0 -0
  39. data/dummy/app/models/post.rb +9 -0
  40. data/dummy/app/views/edge_cases/rails_validation_error.html.erb +16 -0
  41. data/dummy/app/views/layouts/application.html.erb +18 -0
  42. data/dummy/app/views/layouts/mailer.html.erb +13 -0
  43. data/dummy/app/views/layouts/mailer.text.erb +1 -0
  44. data/dummy/app/views/posts/form.html.erb +39 -0
  45. data/dummy/app/views/posts/show.html.erb +16 -0
  46. data/dummy/app/views/validations/form.html.erb +19 -0
  47. data/dummy/app/views/validations/optional_file.html.erb +10 -0
  48. data/dummy/app/views/validations/optional_file_with_max_size.html.erb +10 -0
  49. data/dummy/app/views/validations/optional_image.html.erb +10 -0
  50. data/dummy/app/views/validations/required_file.html.erb +10 -0
  51. data/dummy/app/views/validations/required_media.html.erb +10 -0
  52. data/dummy/bin/bundle +114 -0
  53. data/dummy/bin/importmap +4 -0
  54. data/dummy/bin/rails +4 -0
  55. data/dummy/bin/rake +4 -0
  56. data/dummy/bin/setup +33 -0
  57. data/dummy/config/application.rb +22 -0
  58. data/dummy/config/boot.rb +4 -0
  59. data/dummy/config/cable.yml +10 -0
  60. data/dummy/config/credentials.yml.enc +1 -0
  61. data/dummy/config/cucumber.yml +2 -0
  62. data/dummy/config/database.yml +25 -0
  63. data/dummy/config/environment.rb +5 -0
  64. data/dummy/config/environments/development.rb +70 -0
  65. data/dummy/config/environments/production.rb +93 -0
  66. data/dummy/config/environments/test.rb +60 -0
  67. data/dummy/config/importmap.rb +4 -0
  68. data/dummy/config/initializers/assets.rb +12 -0
  69. data/dummy/config/initializers/content_security_policy.rb +25 -0
  70. data/dummy/config/initializers/filter_parameter_logging.rb +8 -0
  71. data/dummy/config/initializers/inflections.rb +16 -0
  72. data/dummy/config/initializers/permissions_policy.rb +11 -0
  73. data/dummy/config/locales/en.yml +33 -0
  74. data/dummy/config/puma.rb +43 -0
  75. data/dummy/config/routes.rb +7 -0
  76. data/dummy/config/storage.yml +34 -0
  77. data/dummy/config.ru +6 -0
  78. data/dummy/db/migrate/20231013175203_create_posts.rb +8 -0
  79. data/dummy/db/migrate/20231013175257_create_active_storage_tables.active_storage.rb +57 -0
  80. data/dummy/db/migrate/20231102131420_add_name_to_posts.rb +5 -0
  81. data/dummy/db/schema.rb +50 -0
  82. data/dummy/db/seeds.rb +7 -0
  83. data/dummy/features/edge_cases.feature +17 -0
  84. data/dummy/features/form-persistence.feature +40 -0
  85. data/dummy/features/form_bard_file_field_helper.feature +98 -0
  86. data/dummy/features/support/env.rb +21 -0
  87. data/dummy/features/support/fixtures/empty.3gpp +0 -0
  88. data/dummy/features/support/fixtures/empty.JPEG +0 -0
  89. data/dummy/features/support/fixtures/empty.M4V +0 -0
  90. data/dummy/features/support/fixtures/empty.avi +0 -0
  91. data/dummy/features/support/fixtures/empty.bmp +0 -0
  92. data/dummy/features/support/fixtures/empty.flv +0 -0
  93. data/dummy/features/support/fixtures/empty.gif +0 -0
  94. data/dummy/features/support/fixtures/empty.heic +0 -0
  95. data/dummy/features/support/fixtures/empty.jpeg +0 -0
  96. data/dummy/features/support/fixtures/empty.jpg +0 -0
  97. data/dummy/features/support/fixtures/empty.m4v +0 -0
  98. data/dummy/features/support/fixtures/empty.mkv +0 -0
  99. data/dummy/features/support/fixtures/empty.mov +0 -0
  100. data/dummy/features/support/fixtures/empty.mp4 +0 -0
  101. data/dummy/features/support/fixtures/empty.png +0 -0
  102. data/dummy/features/support/fixtures/empty.tiff +0 -0
  103. data/dummy/features/support/fixtures/empty.webm +0 -0
  104. data/dummy/features/support/fixtures/empty.wmv +0 -0
  105. data/dummy/features/support/fixtures/image.jpg +0 -0
  106. data/dummy/features/support/fixtures/image2.jpg +0 -0
  107. data/dummy/features/support/fixtures/video.mp4 +0 -0
  108. data/dummy/features/support/selectors.rb +63 -0
  109. data/dummy/features/support/step_definitions/download_steps.rb +4 -0
  110. data/dummy/features/support/step_definitions/web_steps.rb +94 -0
  111. data/dummy/features/validations.feature +71 -0
  112. data/dummy/lib/assets/.keep +0 -0
  113. data/dummy/lib/tasks/.keep +0 -0
  114. data/dummy/log/.keep +0 -0
  115. data/dummy/public/404.html +67 -0
  116. data/dummy/public/422.html +67 -0
  117. data/dummy/public/500.html +66 -0
  118. data/dummy/public/apple-touch-icon-precomposed.png +0 -0
  119. data/dummy/public/apple-touch-icon.png +0 -0
  120. data/dummy/public/favicon.ico +0 -0
  121. data/dummy/public/robots.txt +1 -0
  122. data/dummy/storage/.keep +0 -0
  123. data/dummy/test/application_system_test_case.rb +21 -0
  124. data/dummy/test/channels/application_cable/connection_test.rb +11 -0
  125. data/dummy/test/controllers/.keep +0 -0
  126. data/dummy/test/fixtures/files/.keep +0 -0
  127. data/dummy/test/helpers/.keep +0 -0
  128. data/dummy/test/integration/.keep +0 -0
  129. data/dummy/test/mailers/.keep +0 -0
  130. data/dummy/test/models/.keep +0 -0
  131. data/dummy/test/system/.keep +0 -0
  132. data/dummy/test/system/tests_test.rb +9 -0
  133. data/dummy/test/test_helper.rb +13 -0
  134. data/dummy/tmp/.keep +0 -0
  135. data/dummy/tmp/pids/.keep +0 -0
  136. data/dummy/tmp/storage/.keep +0 -0
  137. data/lib/bard/file_field/field.rb +27 -0
  138. data/lib/bard/file_field/form_builder.rb +12 -0
  139. data/lib/bard/file_field/version.rb +7 -0
  140. data/lib/bard/file_field.rb +20 -0
  141. metadata +197 -0
@@ -0,0 +1,4913 @@
1
+ /**
2
+ * A collection of default build flags for a Stencil project.
3
+ *
4
+ * This collection can be found throughout the Stencil codebase, often imported from the `@app-data` module like so:
5
+ * ```ts
6
+ * import { BUILD } from '@app-data';
7
+ * ```
8
+ * and is used to determine if a portion of the output of a Stencil _project_'s compilation step can be eliminated.
9
+ *
10
+ * e.g. When `BUILD.allRenderFn` evaluates to `false`, the compiler will eliminate conditional statements like:
11
+ * ```ts
12
+ * if (BUILD.allRenderFn) {
13
+ * // some code that will be eliminated if BUILD.allRenderFn is false
14
+ * }
15
+ * ```
16
+ *
17
+ * `@app-data`, the module that `BUILD` is imported from, is an alias for the `@stencil/core/internal/app-data`, and is
18
+ * partially referenced by {@link STENCIL_APP_DATA_ID}. The `src/compiler/bundle/app-data-plugin.ts` references
19
+ * `STENCIL_APP_DATA_ID` uses it to replace these defaults with {@link BuildConditionals} that are derived from a
20
+ * Stencil project's contents (i.e. metadata from the components). This replacement happens at a Stencil project's
21
+ * compile time. Such code can be found at `src/compiler/app-core/app-data.ts`.
22
+ */
23
+ const BUILD = {
24
+ allRenderFn: false,
25
+ cmpDidLoad: true,
26
+ cmpDidUnload: false,
27
+ cmpDidUpdate: true,
28
+ cmpDidRender: true,
29
+ cmpWillLoad: true,
30
+ cmpWillUpdate: true,
31
+ cmpWillRender: true,
32
+ connectedCallback: true,
33
+ disconnectedCallback: true,
34
+ element: true,
35
+ event: true,
36
+ hasRenderFn: true,
37
+ lifecycle: true,
38
+ hostListener: true,
39
+ hostListenerTargetWindow: true,
40
+ hostListenerTargetDocument: true,
41
+ hostListenerTargetBody: true,
42
+ hostListenerTargetParent: false,
43
+ hostListenerTarget: true,
44
+ member: true,
45
+ method: true,
46
+ mode: true,
47
+ observeAttribute: true,
48
+ prop: true,
49
+ propMutable: true,
50
+ reflect: true,
51
+ scoped: true,
52
+ shadowDom: true,
53
+ slot: true,
54
+ cssAnnotations: true,
55
+ state: true,
56
+ style: true,
57
+ formAssociated: false,
58
+ svg: true,
59
+ updatable: true,
60
+ vdomAttribute: true,
61
+ vdomXlink: true,
62
+ vdomClass: true,
63
+ vdomFunctional: true,
64
+ vdomKey: true,
65
+ vdomListener: true,
66
+ vdomRef: true,
67
+ vdomPropOrAttr: true,
68
+ vdomRender: true,
69
+ vdomStyle: true,
70
+ vdomText: true,
71
+ watchCallback: true,
72
+ taskQueue: true,
73
+ hotModuleReplacement: false,
74
+ isDebug: false,
75
+ isDev: false,
76
+ isTesting: false,
77
+ hydrateServerSide: false,
78
+ hydrateClientSide: false,
79
+ lifecycleDOMEvents: false,
80
+ lazyLoad: false,
81
+ profile: false,
82
+ slotRelocation: true,
83
+ // TODO(STENCIL-914): remove this option when `experimentalSlotFixes` is the default behavior
84
+ appendChildSlotFix: false,
85
+ // TODO(STENCIL-914): remove this option when `experimentalSlotFixes` is the default behavior
86
+ cloneNodeFix: false,
87
+ hydratedAttribute: false,
88
+ hydratedClass: true,
89
+ scriptDataOpts: false,
90
+ // TODO(STENCIL-914): remove this option when `experimentalSlotFixes` is the default behavior
91
+ scopedSlotTextContentFix: false,
92
+ // TODO(STENCIL-854): Remove code related to legacy shadowDomShim field
93
+ shadowDomShim: false,
94
+ // TODO(STENCIL-914): remove this option when `experimentalSlotFixes` is the default behavior
95
+ slotChildNodesFix: false,
96
+ invisiblePrehydration: true,
97
+ propBoolean: true,
98
+ propNumber: true,
99
+ propString: true,
100
+ constructableCSS: true,
101
+ cmpShouldUpdate: true,
102
+ devTools: false,
103
+ shadowDelegatesFocus: true,
104
+ initializeNextTick: false,
105
+ asyncLoading: false,
106
+ asyncQueue: false,
107
+ transformTagName: false,
108
+ attachStyles: true,
109
+ // TODO(STENCIL-914): remove this option when `experimentalSlotFixes` is the default behavior
110
+ experimentalSlotFixes: false,
111
+ };
112
+
113
+ /**
114
+ * Virtual DOM patching algorithm based on Snabbdom by
115
+ * Simon Friis Vindum (@paldepind)
116
+ * Licensed under the MIT License
117
+ * https://github.com/snabbdom/snabbdom/blob/master/LICENSE
118
+ *
119
+ * Modified for Stencil's renderer and slot projection
120
+ */
121
+ let scopeId;
122
+ let contentRef;
123
+ let hostTagName;
124
+ let useNativeShadowDom = false;
125
+ let checkSlotFallbackVisibility = false;
126
+ let checkSlotRelocate = false;
127
+ let isSvgMode = false;
128
+ let renderingRef = null;
129
+ let queuePending = false;
130
+ const createTime = (fnName, tagName = '') => {
131
+ {
132
+ return () => {
133
+ return;
134
+ };
135
+ }
136
+ };
137
+ /**
138
+ * Constant for styles to be globally applied to `slot-fb` elements for pseudo-slot behavior.
139
+ *
140
+ * Two cascading rules must be used instead of a `:not()` selector due to Stencil browser
141
+ * support as of Stencil v4.
142
+ */
143
+ const SLOT_FB_CSS = 'slot-fb{display:contents}slot-fb[hidden]{display:none}';
144
+ const XLINK_NS = 'http://www.w3.org/1999/xlink';
145
+ /**
146
+ * Default style mode id
147
+ */
148
+ /**
149
+ * Reusable empty obj/array
150
+ * Don't add values to these!!
151
+ */
152
+ const EMPTY_OBJ = {};
153
+ /**
154
+ * Namespaces
155
+ */
156
+ const SVG_NS = 'http://www.w3.org/2000/svg';
157
+ const HTML_NS = 'http://www.w3.org/1999/xhtml';
158
+ const isDef = (v) => v != null;
159
+ /**
160
+ * Check whether a value is a 'complex type', defined here as an object or a
161
+ * function.
162
+ *
163
+ * @param o the value to check
164
+ * @returns whether it's a complex type or not
165
+ */
166
+ const isComplexType = (o) => {
167
+ // https://jsperf.com/typeof-fn-object/5
168
+ o = typeof o;
169
+ return o === 'object' || o === 'function';
170
+ };
171
+ /**
172
+ * Helper method for querying a `meta` tag that contains a nonce value
173
+ * out of a DOM's head.
174
+ *
175
+ * @param doc The DOM containing the `head` to query against
176
+ * @returns The content of the meta tag representing the nonce value, or `undefined` if no tag
177
+ * exists or the tag has no content.
178
+ */
179
+ function queryNonceMetaTagContent(doc) {
180
+ var _a, _b, _c;
181
+ return (_c = (_b = (_a = doc.head) === null || _a === void 0 ? void 0 : _a.querySelector('meta[name="csp-nonce"]')) === null || _b === void 0 ? void 0 : _b.getAttribute('content')) !== null && _c !== void 0 ? _c : undefined;
182
+ }
183
+ /**
184
+ * Production h() function based on Preact by
185
+ * Jason Miller (@developit)
186
+ * Licensed under the MIT License
187
+ * https://github.com/developit/preact/blob/master/LICENSE
188
+ *
189
+ * Modified for Stencil's compiler and vdom
190
+ */
191
+ // export function h(nodeName: string | d.FunctionalComponent, vnodeData: d.PropsType, child?: d.ChildType): d.VNode;
192
+ // export function h(nodeName: string | d.FunctionalComponent, vnodeData: d.PropsType, ...children: d.ChildType[]): d.VNode;
193
+ const h = (nodeName, vnodeData, ...children) => {
194
+ let child = null;
195
+ let key = null;
196
+ let slotName = null;
197
+ let simple = false;
198
+ let lastSimple = false;
199
+ const vNodeChildren = [];
200
+ const walk = (c) => {
201
+ for (let i = 0; i < c.length; i++) {
202
+ child = c[i];
203
+ if (Array.isArray(child)) {
204
+ walk(child);
205
+ }
206
+ else if (child != null && typeof child !== 'boolean') {
207
+ if ((simple = typeof nodeName !== 'function' && !isComplexType(child))) {
208
+ child = String(child);
209
+ }
210
+ if (simple && lastSimple) {
211
+ // If the previous child was simple (string), we merge both
212
+ vNodeChildren[vNodeChildren.length - 1].$text$ += child;
213
+ }
214
+ else {
215
+ // Append a new vNode, if it's text, we create a text vNode
216
+ vNodeChildren.push(simple ? newVNode(null, child) : child);
217
+ }
218
+ lastSimple = simple;
219
+ }
220
+ }
221
+ };
222
+ walk(children);
223
+ if (vnodeData) {
224
+ if (vnodeData.key) {
225
+ key = vnodeData.key;
226
+ }
227
+ if (vnodeData.name) {
228
+ slotName = vnodeData.name;
229
+ }
230
+ // normalize class / className attributes
231
+ {
232
+ const classData = vnodeData.className || vnodeData.class;
233
+ if (classData) {
234
+ vnodeData.class =
235
+ typeof classData !== 'object'
236
+ ? classData
237
+ : Object.keys(classData)
238
+ .filter((k) => classData[k])
239
+ .join(' ');
240
+ }
241
+ }
242
+ }
243
+ if (typeof nodeName === 'function') {
244
+ // nodeName is a functional component
245
+ return nodeName(vnodeData === null ? {} : vnodeData, vNodeChildren, vdomFnUtils);
246
+ }
247
+ const vnode = newVNode(nodeName, null);
248
+ vnode.$attrs$ = vnodeData;
249
+ if (vNodeChildren.length > 0) {
250
+ vnode.$children$ = vNodeChildren;
251
+ }
252
+ {
253
+ vnode.$key$ = key;
254
+ }
255
+ {
256
+ vnode.$name$ = slotName;
257
+ }
258
+ return vnode;
259
+ };
260
+ /**
261
+ * A utility function for creating a virtual DOM node from a tag and some
262
+ * possible text content.
263
+ *
264
+ * @param tag the tag for this element
265
+ * @param text possible text content for the node
266
+ * @returns a newly-minted virtual DOM node
267
+ */
268
+ const newVNode = (tag, text) => {
269
+ const vnode = {
270
+ $flags$: 0,
271
+ $tag$: tag,
272
+ $text$: text,
273
+ $elm$: null,
274
+ $children$: null,
275
+ };
276
+ {
277
+ vnode.$attrs$ = null;
278
+ }
279
+ {
280
+ vnode.$key$ = null;
281
+ }
282
+ {
283
+ vnode.$name$ = null;
284
+ }
285
+ return vnode;
286
+ };
287
+ const Host = {};
288
+ /**
289
+ * Check whether a given node is a Host node or not
290
+ *
291
+ * @param node the virtual DOM node to check
292
+ * @returns whether it's a Host node or not
293
+ */
294
+ const isHost = (node) => node && node.$tag$ === Host;
295
+ /**
296
+ * Implementation of {@link d.FunctionalUtilities} for Stencil's VDom.
297
+ *
298
+ * Note that these functions convert from {@link d.VNode} to
299
+ * {@link d.ChildNode} to give functional component developers a friendly
300
+ * interface.
301
+ */
302
+ const vdomFnUtils = {
303
+ forEach: (children, cb) => children.map(convertToPublic).forEach(cb),
304
+ map: (children, cb) => children.map(convertToPublic).map(cb).map(convertToPrivate),
305
+ };
306
+ /**
307
+ * Convert a {@link d.VNode} to a {@link d.ChildNode} in order to present a
308
+ * friendlier public interface (hence, 'convertToPublic').
309
+ *
310
+ * @param node the virtual DOM node to convert
311
+ * @returns a converted child node
312
+ */
313
+ const convertToPublic = (node) => ({
314
+ vattrs: node.$attrs$,
315
+ vchildren: node.$children$,
316
+ vkey: node.$key$,
317
+ vname: node.$name$,
318
+ vtag: node.$tag$,
319
+ vtext: node.$text$,
320
+ });
321
+ /**
322
+ * Convert a {@link d.ChildNode} back to an equivalent {@link d.VNode} in
323
+ * order to use the resulting object in the virtual DOM. The initial object was
324
+ * likely created as part of presenting a public API, so converting it back
325
+ * involved making it 'private' again (hence, `convertToPrivate`).
326
+ *
327
+ * @param node the child node to convert
328
+ * @returns a converted virtual DOM node
329
+ */
330
+ const convertToPrivate = (node) => {
331
+ if (typeof node.vtag === 'function') {
332
+ const vnodeData = Object.assign({}, node.vattrs);
333
+ if (node.vkey) {
334
+ vnodeData.key = node.vkey;
335
+ }
336
+ if (node.vname) {
337
+ vnodeData.name = node.vname;
338
+ }
339
+ return h(node.vtag, vnodeData, ...(node.vchildren || []));
340
+ }
341
+ const vnode = newVNode(node.vtag, node.vtext);
342
+ vnode.$attrs$ = node.vattrs;
343
+ vnode.$children$ = node.vchildren;
344
+ vnode.$key$ = node.vkey;
345
+ vnode.$name$ = node.vname;
346
+ return vnode;
347
+ };
348
+ // Private
349
+ const computeMode = (elm) => modeResolutionChain.map((h) => h(elm)).find((m) => !!m);
350
+ /**
351
+ * Parse a new property value for a given property type.
352
+ *
353
+ * While the prop value can reasonably be expected to be of `any` type as far as TypeScript's type checker is concerned,
354
+ * it is not safe to assume that the string returned by evaluating `typeof propValue` matches:
355
+ * 1. `any`, the type given to `propValue` in the function signature
356
+ * 2. the type stored from `propType`.
357
+ *
358
+ * This function provides the capability to parse/coerce a property's value to potentially any other JavaScript type.
359
+ *
360
+ * Property values represented in TSX preserve their type information. In the example below, the number 0 is passed to
361
+ * a component. This `propValue` will preserve its type information (`typeof propValue === 'number'`). Note that is
362
+ * based on the type of the value being passed in, not the type declared of the class member decorated with `@Prop`.
363
+ * ```tsx
364
+ * <my-cmp prop-val={0}></my-cmp>
365
+ * ```
366
+ *
367
+ * HTML prop values on the other hand, will always a string
368
+ *
369
+ * @param propValue the new value to coerce to some type
370
+ * @param propType the type of the prop, expressed as a binary number
371
+ * @returns the parsed/coerced value
372
+ */
373
+ const parsePropertyValue = (propValue, propType) => {
374
+ // ensure this value is of the correct prop type
375
+ if (propValue != null && !isComplexType(propValue)) {
376
+ if (propType & 4 /* MEMBER_FLAGS.Boolean */) {
377
+ // per the HTML spec, any string value means it is a boolean true value
378
+ // but we'll cheat here and say that the string "false" is the boolean false
379
+ return propValue === 'false' ? false : propValue === '' || !!propValue;
380
+ }
381
+ if (propType & 2 /* MEMBER_FLAGS.Number */) {
382
+ // force it to be a number
383
+ return parseFloat(propValue);
384
+ }
385
+ if (propType & 1 /* MEMBER_FLAGS.String */) {
386
+ // could have been passed as a number or boolean
387
+ // but we still want it as a string
388
+ return String(propValue);
389
+ }
390
+ // redundant return here for better minification
391
+ return propValue;
392
+ }
393
+ // not sure exactly what type we want
394
+ // so no need to change to a different type
395
+ return propValue;
396
+ };
397
+ const getElement = (ref) => (ref);
398
+ const createEvent = (ref, name, flags) => {
399
+ const elm = getElement(ref);
400
+ return {
401
+ emit: (detail) => {
402
+ return emitEvent(elm, name, {
403
+ bubbles: !!(flags & 4 /* EVENT_FLAGS.Bubbles */),
404
+ composed: !!(flags & 2 /* EVENT_FLAGS.Composed */),
405
+ cancelable: !!(flags & 1 /* EVENT_FLAGS.Cancellable */),
406
+ detail,
407
+ });
408
+ },
409
+ };
410
+ };
411
+ /**
412
+ * Helper function to create & dispatch a custom Event on a provided target
413
+ * @param elm the target of the Event
414
+ * @param name the name to give the custom Event
415
+ * @param opts options for configuring a custom Event
416
+ * @returns the custom Event
417
+ */
418
+ const emitEvent = (elm, name, opts) => {
419
+ const ev = plt.ce(name, opts);
420
+ elm.dispatchEvent(ev);
421
+ return ev;
422
+ };
423
+ const rootAppliedStyles = /*@__PURE__*/ new WeakMap();
424
+ const registerStyle = (scopeId, cssText, allowCS) => {
425
+ let style = styles.get(scopeId);
426
+ if (supportsConstructableStylesheets && allowCS) {
427
+ style = (style || new CSSStyleSheet());
428
+ if (typeof style === 'string') {
429
+ style = cssText;
430
+ }
431
+ else {
432
+ style.replaceSync(cssText);
433
+ }
434
+ }
435
+ else {
436
+ style = cssText;
437
+ }
438
+ styles.set(scopeId, style);
439
+ };
440
+ const addStyle = (styleContainerNode, cmpMeta, mode) => {
441
+ var _a;
442
+ const scopeId = getScopeId(cmpMeta, mode);
443
+ const style = styles.get(scopeId);
444
+ // if an element is NOT connected then getRootNode() will return the wrong root node
445
+ // so the fallback is to always use the document for the root node in those cases
446
+ styleContainerNode = styleContainerNode.nodeType === 11 /* NODE_TYPE.DocumentFragment */ ? styleContainerNode : doc$1;
447
+ if (style) {
448
+ if (typeof style === 'string') {
449
+ styleContainerNode = styleContainerNode.head || styleContainerNode;
450
+ let appliedStyles = rootAppliedStyles.get(styleContainerNode);
451
+ let styleElm;
452
+ if (!appliedStyles) {
453
+ rootAppliedStyles.set(styleContainerNode, (appliedStyles = new Set()));
454
+ }
455
+ if (!appliedStyles.has(scopeId)) {
456
+ {
457
+ styleElm = doc$1.createElement('style');
458
+ styleElm.innerHTML = style;
459
+ // Apply CSP nonce to the style tag if it exists
460
+ const nonce = (_a = plt.$nonce$) !== null && _a !== void 0 ? _a : queryNonceMetaTagContent(doc$1);
461
+ if (nonce != null) {
462
+ styleElm.setAttribute('nonce', nonce);
463
+ }
464
+ styleContainerNode.insertBefore(styleElm, styleContainerNode.querySelector('link'));
465
+ }
466
+ // Add styles for `slot-fb` elements if we're using slots outside the Shadow DOM
467
+ if (cmpMeta.$flags$ & 4 /* CMP_FLAGS.hasSlotRelocation */) {
468
+ styleElm.innerHTML += SLOT_FB_CSS;
469
+ }
470
+ if (appliedStyles) {
471
+ appliedStyles.add(scopeId);
472
+ }
473
+ }
474
+ }
475
+ else if (!styleContainerNode.adoptedStyleSheets.includes(style)) {
476
+ styleContainerNode.adoptedStyleSheets = [...styleContainerNode.adoptedStyleSheets, style];
477
+ }
478
+ }
479
+ return scopeId;
480
+ };
481
+ const attachStyles = (hostRef) => {
482
+ const cmpMeta = hostRef.$cmpMeta$;
483
+ const elm = hostRef.$hostElement$;
484
+ const flags = cmpMeta.$flags$;
485
+ const endAttachStyles = createTime('attachStyles', cmpMeta.$tagName$);
486
+ const scopeId = addStyle(elm.shadowRoot ? elm.shadowRoot : elm.getRootNode(), cmpMeta, hostRef.$modeName$);
487
+ if (flags & 10 /* CMP_FLAGS.needsScopedEncapsulation */) {
488
+ // only required when we're NOT using native shadow dom (slot)
489
+ // or this browser doesn't support native shadow dom
490
+ // and this host element was NOT created with SSR
491
+ // let's pick out the inner content for slot projection
492
+ // create a node to represent where the original
493
+ // content was first placed, which is useful later on
494
+ // DOM WRITE!!
495
+ elm['s-sc'] = scopeId;
496
+ elm.classList.add(scopeId + '-h');
497
+ if (flags & 2 /* CMP_FLAGS.scopedCssEncapsulation */) {
498
+ elm.classList.add(scopeId + '-s');
499
+ }
500
+ }
501
+ endAttachStyles();
502
+ };
503
+ const getScopeId = (cmp, mode) => 'sc-' + (mode && cmp.$flags$ & 32 /* CMP_FLAGS.hasMode */ ? cmp.$tagName$ + '-' + mode : cmp.$tagName$);
504
+ /**
505
+ * Production setAccessor() function based on Preact by
506
+ * Jason Miller (@developit)
507
+ * Licensed under the MIT License
508
+ * https://github.com/developit/preact/blob/master/LICENSE
509
+ *
510
+ * Modified for Stencil's compiler and vdom
511
+ */
512
+ /**
513
+ * When running a VDom render set properties present on a VDom node onto the
514
+ * corresponding HTML element.
515
+ *
516
+ * Note that this function has special functionality for the `class`,
517
+ * `style`, `key`, and `ref` attributes, as well as event handlers (like
518
+ * `onClick`, etc). All others are just passed through as-is.
519
+ *
520
+ * @param elm the HTMLElement onto which attributes should be set
521
+ * @param memberName the name of the attribute to set
522
+ * @param oldValue the old value for the attribute
523
+ * @param newValue the new value for the attribute
524
+ * @param isSvg whether we're in an svg context or not
525
+ * @param flags bitflags for Vdom variables
526
+ */
527
+ const setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags) => {
528
+ if (oldValue !== newValue) {
529
+ let isProp = isMemberInElement(elm, memberName);
530
+ let ln = memberName.toLowerCase();
531
+ if (memberName === 'class') {
532
+ const classList = elm.classList;
533
+ const oldClasses = parseClassList(oldValue);
534
+ const newClasses = parseClassList(newValue);
535
+ classList.remove(...oldClasses.filter((c) => c && !newClasses.includes(c)));
536
+ classList.add(...newClasses.filter((c) => c && !oldClasses.includes(c)));
537
+ }
538
+ else if (memberName === 'style') {
539
+ // update style attribute, css properties and values
540
+ {
541
+ for (const prop in oldValue) {
542
+ if (!newValue || newValue[prop] == null) {
543
+ if (prop.includes('-')) {
544
+ elm.style.removeProperty(prop);
545
+ }
546
+ else {
547
+ elm.style[prop] = '';
548
+ }
549
+ }
550
+ }
551
+ }
552
+ for (const prop in newValue) {
553
+ if (!oldValue || newValue[prop] !== oldValue[prop]) {
554
+ if (prop.includes('-')) {
555
+ elm.style.setProperty(prop, newValue[prop]);
556
+ }
557
+ else {
558
+ elm.style[prop] = newValue[prop];
559
+ }
560
+ }
561
+ }
562
+ }
563
+ else if (memberName === 'key')
564
+ ;
565
+ else if (memberName === 'ref') {
566
+ // minifier will clean this up
567
+ if (newValue) {
568
+ newValue(elm);
569
+ }
570
+ }
571
+ else if ((!elm.__lookupSetter__(memberName)) &&
572
+ memberName[0] === 'o' &&
573
+ memberName[1] === 'n') {
574
+ // Event Handlers
575
+ // so if the member name starts with "on" and the 3rd characters is
576
+ // a capital letter, and it's not already a member on the element,
577
+ // then we're assuming it's an event listener
578
+ if (memberName[2] === '-') {
579
+ // on- prefixed events
580
+ // allows to be explicit about the dom event to listen without any magic
581
+ // under the hood:
582
+ // <my-cmp on-click> // listens for "click"
583
+ // <my-cmp on-Click> // listens for "Click"
584
+ // <my-cmp on-ionChange> // listens for "ionChange"
585
+ // <my-cmp on-EVENTS> // listens for "EVENTS"
586
+ memberName = memberName.slice(3);
587
+ }
588
+ else if (isMemberInElement(win, ln)) {
589
+ // standard event
590
+ // the JSX attribute could have been "onMouseOver" and the
591
+ // member name "onmouseover" is on the window's prototype
592
+ // so let's add the listener "mouseover", which is all lowercased
593
+ memberName = ln.slice(2);
594
+ }
595
+ else {
596
+ // custom event
597
+ // the JSX attribute could have been "onMyCustomEvent"
598
+ // so let's trim off the "on" prefix and lowercase the first character
599
+ // and add the listener "myCustomEvent"
600
+ // except for the first character, we keep the event name case
601
+ memberName = ln[2] + memberName.slice(3);
602
+ }
603
+ if (oldValue || newValue) {
604
+ // Need to account for "capture" events.
605
+ // If the event name ends with "Capture", we'll update the name to remove
606
+ // the "Capture" suffix and make sure the event listener is setup to handle the capture event.
607
+ const capture = memberName.endsWith(CAPTURE_EVENT_SUFFIX);
608
+ // Make sure we only replace the last instance of "Capture"
609
+ memberName = memberName.replace(CAPTURE_EVENT_REGEX, '');
610
+ if (oldValue) {
611
+ plt.rel(elm, memberName, oldValue, capture);
612
+ }
613
+ if (newValue) {
614
+ plt.ael(elm, memberName, newValue, capture);
615
+ }
616
+ }
617
+ }
618
+ else {
619
+ // Set property if it exists and it's not a SVG
620
+ const isComplex = isComplexType(newValue);
621
+ if ((isProp || (isComplex && newValue !== null)) && !isSvg) {
622
+ try {
623
+ if (!elm.tagName.includes('-')) {
624
+ const n = newValue == null ? '' : newValue;
625
+ // Workaround for Safari, moving the <input> caret when re-assigning the same valued
626
+ if (memberName === 'list') {
627
+ isProp = false;
628
+ }
629
+ else if (oldValue == null || elm[memberName] != n) {
630
+ elm[memberName] = n;
631
+ }
632
+ }
633
+ else {
634
+ elm[memberName] = newValue;
635
+ }
636
+ }
637
+ catch (e) {
638
+ /**
639
+ * in case someone tries to set a read-only property, e.g. "namespaceURI", we just ignore it
640
+ */
641
+ }
642
+ }
643
+ /**
644
+ * Need to manually update attribute if:
645
+ * - memberName is not an attribute
646
+ * - if we are rendering the host element in order to reflect attribute
647
+ * - if it's a SVG, since properties might not work in <svg>
648
+ * - if the newValue is null/undefined or 'false'.
649
+ */
650
+ let xlink = false;
651
+ {
652
+ if (ln !== (ln = ln.replace(/^xlink\:?/, ''))) {
653
+ memberName = ln;
654
+ xlink = true;
655
+ }
656
+ }
657
+ if (newValue == null || newValue === false) {
658
+ if (newValue !== false || elm.getAttribute(memberName) === '') {
659
+ if (xlink) {
660
+ elm.removeAttributeNS(XLINK_NS, memberName);
661
+ }
662
+ else {
663
+ elm.removeAttribute(memberName);
664
+ }
665
+ }
666
+ }
667
+ else if ((!isProp || flags & 4 /* VNODE_FLAGS.isHost */ || isSvg) && !isComplex) {
668
+ newValue = newValue === true ? '' : newValue;
669
+ if (xlink) {
670
+ elm.setAttributeNS(XLINK_NS, memberName, newValue);
671
+ }
672
+ else {
673
+ elm.setAttribute(memberName, newValue);
674
+ }
675
+ }
676
+ }
677
+ }
678
+ };
679
+ const parseClassListRegex = /\s/;
680
+ /**
681
+ * Parsed a string of classnames into an array
682
+ * @param value className string, e.g. "foo bar baz"
683
+ * @returns list of classes, e.g. ["foo", "bar", "baz"]
684
+ */
685
+ const parseClassList = (value) => (!value ? [] : value.split(parseClassListRegex));
686
+ const CAPTURE_EVENT_SUFFIX = 'Capture';
687
+ const CAPTURE_EVENT_REGEX = new RegExp(CAPTURE_EVENT_SUFFIX + '$');
688
+ const updateElement = (oldVnode, newVnode, isSvgMode, memberName) => {
689
+ // if the element passed in is a shadow root, which is a document fragment
690
+ // then we want to be adding attrs/props to the shadow root's "host" element
691
+ // if it's not a shadow root, then we add attrs/props to the same element
692
+ const elm = newVnode.$elm$.nodeType === 11 /* NODE_TYPE.DocumentFragment */ && newVnode.$elm$.host
693
+ ? newVnode.$elm$.host
694
+ : newVnode.$elm$;
695
+ const oldVnodeAttrs = (oldVnode && oldVnode.$attrs$) || EMPTY_OBJ;
696
+ const newVnodeAttrs = newVnode.$attrs$ || EMPTY_OBJ;
697
+ {
698
+ // remove attributes no longer present on the vnode by setting them to undefined
699
+ for (memberName in oldVnodeAttrs) {
700
+ if (!(memberName in newVnodeAttrs)) {
701
+ setAccessor(elm, memberName, oldVnodeAttrs[memberName], undefined, isSvgMode, newVnode.$flags$);
702
+ }
703
+ }
704
+ }
705
+ // add new & update changed attributes
706
+ for (memberName in newVnodeAttrs) {
707
+ setAccessor(elm, memberName, oldVnodeAttrs[memberName], newVnodeAttrs[memberName], isSvgMode, newVnode.$flags$);
708
+ }
709
+ };
710
+ /**
711
+ * Create a DOM Node corresponding to one of the children of a given VNode.
712
+ *
713
+ * @param oldParentVNode the parent VNode from the previous render
714
+ * @param newParentVNode the parent VNode from the current render
715
+ * @param childIndex the index of the VNode, in the _new_ parent node's
716
+ * children, for which we will create a new DOM node
717
+ * @param parentElm the parent DOM node which our new node will be a child of
718
+ * @returns the newly created node
719
+ */
720
+ const createElm = (oldParentVNode, newParentVNode, childIndex, parentElm) => {
721
+ var _a;
722
+ // tslint:disable-next-line: prefer-const
723
+ const newVNode = newParentVNode.$children$[childIndex];
724
+ let i = 0;
725
+ let elm;
726
+ let childNode;
727
+ let oldVNode;
728
+ if (!useNativeShadowDom) {
729
+ // remember for later we need to check to relocate nodes
730
+ checkSlotRelocate = true;
731
+ if (newVNode.$tag$ === 'slot') {
732
+ if (scopeId) {
733
+ // scoped css needs to add its scoped id to the parent element
734
+ parentElm.classList.add(scopeId + '-s');
735
+ }
736
+ newVNode.$flags$ |= newVNode.$children$
737
+ ? // slot element has fallback content
738
+ 2 /* VNODE_FLAGS.isSlotFallback */
739
+ : // slot element does not have fallback content
740
+ 1 /* VNODE_FLAGS.isSlotReference */;
741
+ }
742
+ }
743
+ if (newVNode.$text$ !== null) {
744
+ // create text node
745
+ elm = newVNode.$elm$ = doc$1.createTextNode(newVNode.$text$);
746
+ }
747
+ else if (newVNode.$flags$ & 1 /* VNODE_FLAGS.isSlotReference */) {
748
+ // create a slot reference node
749
+ elm = newVNode.$elm$ =
750
+ doc$1.createTextNode('');
751
+ }
752
+ else {
753
+ if (!isSvgMode) {
754
+ isSvgMode = newVNode.$tag$ === 'svg';
755
+ }
756
+ // create element
757
+ elm = newVNode.$elm$ = (doc$1.createElementNS(isSvgMode ? SVG_NS : HTML_NS, newVNode.$flags$ & 2 /* VNODE_FLAGS.isSlotFallback */
758
+ ? 'slot-fb'
759
+ : newVNode.$tag$)
760
+ );
761
+ if (isSvgMode && newVNode.$tag$ === 'foreignObject') {
762
+ isSvgMode = false;
763
+ }
764
+ // add css classes, attrs, props, listeners, etc.
765
+ {
766
+ updateElement(null, newVNode, isSvgMode);
767
+ }
768
+ if (isDef(scopeId) && elm['s-si'] !== scopeId) {
769
+ // if there is a scopeId and this is the initial render
770
+ // then let's add the scopeId as a css class
771
+ elm.classList.add((elm['s-si'] = scopeId));
772
+ }
773
+ if (newVNode.$children$) {
774
+ for (i = 0; i < newVNode.$children$.length; ++i) {
775
+ // create the node
776
+ childNode = createElm(oldParentVNode, newVNode, i, elm);
777
+ // return node could have been null
778
+ if (childNode) {
779
+ // append our new node
780
+ elm.appendChild(childNode);
781
+ }
782
+ }
783
+ }
784
+ {
785
+ if (newVNode.$tag$ === 'svg') {
786
+ // Only reset the SVG context when we're exiting <svg> element
787
+ isSvgMode = false;
788
+ }
789
+ else if (elm.tagName === 'foreignObject') {
790
+ // Reenter SVG context when we're exiting <foreignObject> element
791
+ isSvgMode = true;
792
+ }
793
+ }
794
+ }
795
+ {
796
+ elm['s-hn'] = hostTagName;
797
+ if (newVNode.$flags$ & (2 /* VNODE_FLAGS.isSlotFallback */ | 1 /* VNODE_FLAGS.isSlotReference */)) {
798
+ // remember the content reference comment
799
+ elm['s-sr'] = true;
800
+ // Persist the name of the slot that this slot was going to be projected into.
801
+ elm['s-fs'] = (_a = newVNode.$attrs$) === null || _a === void 0 ? void 0 : _a.slot;
802
+ // remember the content reference comment
803
+ elm['s-cr'] = contentRef;
804
+ // remember the slot name, or empty string for default slot
805
+ elm['s-sn'] = newVNode.$name$ || '';
806
+ // check if we've got an old vnode for this slot
807
+ oldVNode = oldParentVNode && oldParentVNode.$children$ && oldParentVNode.$children$[childIndex];
808
+ if (oldVNode && oldVNode.$tag$ === newVNode.$tag$ && oldParentVNode.$elm$) {
809
+ // we've got an old slot vnode and the wrapper is being replaced
810
+ // so let's move the old slot content back to it's original location
811
+ putBackInOriginalLocation(oldParentVNode.$elm$, false);
812
+ }
813
+ }
814
+ }
815
+ return elm;
816
+ };
817
+ const putBackInOriginalLocation = (parentElm, recursive) => {
818
+ var _a;
819
+ plt.$flags$ |= 1 /* PLATFORM_FLAGS.isTmpDisconnected */;
820
+ const oldSlotChildNodes = parentElm.childNodes;
821
+ for (let i = oldSlotChildNodes.length - 1; i >= 0; i--) {
822
+ const childNode = oldSlotChildNodes[i];
823
+ if (childNode['s-hn'] !== hostTagName && childNode['s-ol']) {
824
+ // // this child node in the old element is from another component
825
+ // // remove this node from the old slot's parent
826
+ // childNode.remove();
827
+ // and relocate it back to it's original location
828
+ parentReferenceNode(childNode).insertBefore(childNode, referenceNode(childNode));
829
+ // remove the old original location comment entirely
830
+ // later on the patch function will know what to do
831
+ // and move this to the correct spot if need be
832
+ childNode['s-ol'].remove();
833
+ childNode['s-ol'] = undefined;
834
+ // Reset so we can correctly move the node around again.
835
+ childNode['s-sh'] = undefined;
836
+ // When putting an element node back in its original location,
837
+ // we need to reset the `slot` attribute back to the value it originally had
838
+ // so we can correctly relocate it again in the future
839
+ if (childNode.nodeType === 1 /* NODE_TYPE.ElementNode */) {
840
+ childNode.setAttribute('slot', (_a = childNode['s-sn']) !== null && _a !== void 0 ? _a : '');
841
+ }
842
+ checkSlotRelocate = true;
843
+ }
844
+ if (recursive) {
845
+ putBackInOriginalLocation(childNode, recursive);
846
+ }
847
+ }
848
+ plt.$flags$ &= ~1 /* PLATFORM_FLAGS.isTmpDisconnected */;
849
+ };
850
+ /**
851
+ * Create DOM nodes corresponding to a list of {@link d.Vnode} objects and
852
+ * add them to the DOM in the appropriate place.
853
+ *
854
+ * @param parentElm the DOM node which should be used as a parent for the new
855
+ * DOM nodes
856
+ * @param before a child of the `parentElm` which the new children should be
857
+ * inserted before (optional)
858
+ * @param parentVNode the parent virtual DOM node
859
+ * @param vnodes the new child virtual DOM nodes to produce DOM nodes for
860
+ * @param startIdx the index in the child virtual DOM nodes at which to start
861
+ * creating DOM nodes (inclusive)
862
+ * @param endIdx the index in the child virtual DOM nodes at which to stop
863
+ * creating DOM nodes (inclusive)
864
+ */
865
+ const addVnodes = (parentElm, before, parentVNode, vnodes, startIdx, endIdx) => {
866
+ let containerElm = ((parentElm['s-cr'] && parentElm['s-cr'].parentNode) || parentElm);
867
+ let childNode;
868
+ if (containerElm.shadowRoot && containerElm.tagName === hostTagName) {
869
+ containerElm = containerElm.shadowRoot;
870
+ }
871
+ for (; startIdx <= endIdx; ++startIdx) {
872
+ if (vnodes[startIdx]) {
873
+ childNode = createElm(null, parentVNode, startIdx, parentElm);
874
+ if (childNode) {
875
+ vnodes[startIdx].$elm$ = childNode;
876
+ containerElm.insertBefore(childNode, referenceNode(before) );
877
+ }
878
+ }
879
+ }
880
+ };
881
+ /**
882
+ * Remove the DOM elements corresponding to a list of {@link d.VNode} objects.
883
+ * This can be used to, for instance, clean up after a list of children which
884
+ * should no longer be shown.
885
+ *
886
+ * This function also handles some of Stencil's slot relocation logic.
887
+ *
888
+ * @param vnodes a list of virtual DOM nodes to remove
889
+ * @param startIdx the index at which to start removing nodes (inclusive)
890
+ * @param endIdx the index at which to stop removing nodes (inclusive)
891
+ */
892
+ const removeVnodes = (vnodes, startIdx, endIdx) => {
893
+ for (let index = startIdx; index <= endIdx; ++index) {
894
+ const vnode = vnodes[index];
895
+ if (vnode) {
896
+ const elm = vnode.$elm$;
897
+ nullifyVNodeRefs(vnode);
898
+ if (elm) {
899
+ {
900
+ // we're removing this element
901
+ // so it's possible we need to show slot fallback content now
902
+ checkSlotFallbackVisibility = true;
903
+ if (elm['s-ol']) {
904
+ // remove the original location comment
905
+ elm['s-ol'].remove();
906
+ }
907
+ else {
908
+ // it's possible that child nodes of the node
909
+ // that's being removed are slot nodes
910
+ putBackInOriginalLocation(elm, true);
911
+ }
912
+ }
913
+ // remove the vnode's element from the dom
914
+ elm.remove();
915
+ }
916
+ }
917
+ }
918
+ };
919
+ /**
920
+ * Reconcile the children of a new VNode with the children of an old VNode by
921
+ * traversing the two collections of children, identifying nodes that are
922
+ * conserved or changed, calling out to `patch` to make any necessary
923
+ * updates to the DOM, and rearranging DOM nodes as needed.
924
+ *
925
+ * The algorithm for reconciling children works by analyzing two 'windows' onto
926
+ * the two arrays of children (`oldCh` and `newCh`). We keep track of the
927
+ * 'windows' by storing start and end indices and references to the
928
+ * corresponding array entries. Initially the two 'windows' are basically equal
929
+ * to the entire array, but we progressively narrow the windows until there are
930
+ * no children left to update by doing the following:
931
+ *
932
+ * 1. Skip any `null` entries at the beginning or end of the two arrays, so
933
+ * that if we have an initial array like the following we'll end up dealing
934
+ * only with a window bounded by the highlighted elements:
935
+ *
936
+ * [null, null, VNode1 , ... , VNode2, null, null]
937
+ * ^^^^^^ ^^^^^^
938
+ *
939
+ * 2. Check to see if the elements at the head and tail positions are equal
940
+ * across the windows. This will basically detect elements which haven't
941
+ * been added, removed, or changed position, i.e. if you had the following
942
+ * VNode elements (represented as HTML):
943
+ *
944
+ * oldVNode: `<div><p><span>HEY</span></p></div>`
945
+ * newVNode: `<div><p><span>THERE</span></p></div>`
946
+ *
947
+ * Then when comparing the children of the `<div>` tag we check the equality
948
+ * of the VNodes corresponding to the `<p>` tags and, since they are the
949
+ * same tag in the same position, we'd be able to avoid completely
950
+ * re-rendering the subtree under them with a new DOM element and would just
951
+ * call out to `patch` to handle reconciling their children and so on.
952
+ *
953
+ * 3. Check, for both windows, to see if the element at the beginning of the
954
+ * window corresponds to the element at the end of the other window. This is
955
+ * a heuristic which will let us identify _some_ situations in which
956
+ * elements have changed position, for instance it _should_ detect that the
957
+ * children nodes themselves have not changed but merely moved in the
958
+ * following example:
959
+ *
960
+ * oldVNode: `<div><element-one /><element-two /></div>`
961
+ * newVNode: `<div><element-two /><element-one /></div>`
962
+ *
963
+ * If we find cases like this then we also need to move the concrete DOM
964
+ * elements corresponding to the moved children to write the re-order to the
965
+ * DOM.
966
+ *
967
+ * 4. Finally, if VNodes have the `key` attribute set on them we check for any
968
+ * nodes in the old children which have the same key as the first element in
969
+ * our window on the new children. If we find such a node we handle calling
970
+ * out to `patch`, moving relevant DOM nodes, and so on, in accordance with
971
+ * what we find.
972
+ *
973
+ * Finally, once we've narrowed our 'windows' to the point that either of them
974
+ * collapse (i.e. they have length 0) we then handle any remaining VNode
975
+ * insertion or deletion that needs to happen to get a DOM state that correctly
976
+ * reflects the new child VNodes. If, for instance, after our window on the old
977
+ * children has collapsed we still have more nodes on the new children that
978
+ * we haven't dealt with yet then we need to add them, or if the new children
979
+ * collapse but we still have unhandled _old_ children then we need to make
980
+ * sure the corresponding DOM nodes are removed.
981
+ *
982
+ * @param parentElm the node into which the parent VNode is rendered
983
+ * @param oldCh the old children of the parent node
984
+ * @param newVNode the new VNode which will replace the parent
985
+ * @param newCh the new children of the parent node
986
+ */
987
+ const updateChildren = (parentElm, oldCh, newVNode, newCh) => {
988
+ let oldStartIdx = 0;
989
+ let newStartIdx = 0;
990
+ let idxInOld = 0;
991
+ let i = 0;
992
+ let oldEndIdx = oldCh.length - 1;
993
+ let oldStartVnode = oldCh[0];
994
+ let oldEndVnode = oldCh[oldEndIdx];
995
+ let newEndIdx = newCh.length - 1;
996
+ let newStartVnode = newCh[0];
997
+ let newEndVnode = newCh[newEndIdx];
998
+ let node;
999
+ let elmToMove;
1000
+ while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
1001
+ if (oldStartVnode == null) {
1002
+ // VNode might have been moved left
1003
+ oldStartVnode = oldCh[++oldStartIdx];
1004
+ }
1005
+ else if (oldEndVnode == null) {
1006
+ oldEndVnode = oldCh[--oldEndIdx];
1007
+ }
1008
+ else if (newStartVnode == null) {
1009
+ newStartVnode = newCh[++newStartIdx];
1010
+ }
1011
+ else if (newEndVnode == null) {
1012
+ newEndVnode = newCh[--newEndIdx];
1013
+ }
1014
+ else if (isSameVnode(oldStartVnode, newStartVnode)) {
1015
+ // if the start nodes are the same then we should patch the new VNode
1016
+ // onto the old one, and increment our `newStartIdx` and `oldStartIdx`
1017
+ // indices to reflect that. We don't need to move any DOM Nodes around
1018
+ // since things are matched up in order.
1019
+ patch(oldStartVnode, newStartVnode);
1020
+ oldStartVnode = oldCh[++oldStartIdx];
1021
+ newStartVnode = newCh[++newStartIdx];
1022
+ }
1023
+ else if (isSameVnode(oldEndVnode, newEndVnode)) {
1024
+ // likewise, if the end nodes are the same we patch new onto old and
1025
+ // decrement our end indices, and also likewise in this case we don't
1026
+ // need to move any DOM Nodes.
1027
+ patch(oldEndVnode, newEndVnode);
1028
+ oldEndVnode = oldCh[--oldEndIdx];
1029
+ newEndVnode = newCh[--newEndIdx];
1030
+ }
1031
+ else if (isSameVnode(oldStartVnode, newEndVnode)) {
1032
+ // case: "Vnode moved right"
1033
+ //
1034
+ // We've found that the last node in our window on the new children is
1035
+ // the same VNode as the _first_ node in our window on the old children
1036
+ // we're dealing with now. Visually, this is the layout of these two
1037
+ // nodes:
1038
+ //
1039
+ // newCh: [..., newStartVnode , ... , newEndVnode , ...]
1040
+ // ^^^^^^^^^^^
1041
+ // oldCh: [..., oldStartVnode , ... , oldEndVnode , ...]
1042
+ // ^^^^^^^^^^^^^
1043
+ //
1044
+ // In this situation we need to patch `newEndVnode` onto `oldStartVnode`
1045
+ // and move the DOM element for `oldStartVnode`.
1046
+ if ((oldStartVnode.$tag$ === 'slot' || newEndVnode.$tag$ === 'slot')) {
1047
+ putBackInOriginalLocation(oldStartVnode.$elm$.parentNode, false);
1048
+ }
1049
+ patch(oldStartVnode, newEndVnode);
1050
+ // We need to move the element for `oldStartVnode` into a position which
1051
+ // will be appropriate for `newEndVnode`. For this we can use
1052
+ // `.insertBefore` and `oldEndVnode.$elm$.nextSibling`. If there is a
1053
+ // sibling for `oldEndVnode.$elm$` then we want to move the DOM node for
1054
+ // `oldStartVnode` between `oldEndVnode` and it's sibling, like so:
1055
+ //
1056
+ // <old-start-node />
1057
+ // <some-intervening-node />
1058
+ // <old-end-node />
1059
+ // <!-- -> <-- `oldStartVnode.$elm$` should be inserted here
1060
+ // <next-sibling />
1061
+ //
1062
+ // If instead `oldEndVnode.$elm$` has no sibling then we just want to put
1063
+ // the node for `oldStartVnode` at the end of the children of
1064
+ // `parentElm`. Luckily, `Node.nextSibling` will return `null` if there
1065
+ // aren't any siblings, and passing `null` to `Node.insertBefore` will
1066
+ // append it to the children of the parent element.
1067
+ parentElm.insertBefore(oldStartVnode.$elm$, oldEndVnode.$elm$.nextSibling);
1068
+ oldStartVnode = oldCh[++oldStartIdx];
1069
+ newEndVnode = newCh[--newEndIdx];
1070
+ }
1071
+ else if (isSameVnode(oldEndVnode, newStartVnode)) {
1072
+ // case: "Vnode moved left"
1073
+ //
1074
+ // We've found that the first node in our window on the new children is
1075
+ // the same VNode as the _last_ node in our window on the old children.
1076
+ // Visually, this is the layout of these two nodes:
1077
+ //
1078
+ // newCh: [..., newStartVnode , ... , newEndVnode , ...]
1079
+ // ^^^^^^^^^^^^^
1080
+ // oldCh: [..., oldStartVnode , ... , oldEndVnode , ...]
1081
+ // ^^^^^^^^^^^
1082
+ //
1083
+ // In this situation we need to patch `newStartVnode` onto `oldEndVnode`
1084
+ // (which will handle updating any changed attributes, reconciling their
1085
+ // children etc) but we also need to move the DOM node to which
1086
+ // `oldEndVnode` corresponds.
1087
+ if ((oldStartVnode.$tag$ === 'slot' || newEndVnode.$tag$ === 'slot')) {
1088
+ putBackInOriginalLocation(oldEndVnode.$elm$.parentNode, false);
1089
+ }
1090
+ patch(oldEndVnode, newStartVnode);
1091
+ // We've already checked above if `oldStartVnode` and `newStartVnode` are
1092
+ // the same node, so since we're here we know that they are not. Thus we
1093
+ // can move the element for `oldEndVnode` _before_ the element for
1094
+ // `oldStartVnode`, leaving `oldStartVnode` to be reconciled in the
1095
+ // future.
1096
+ parentElm.insertBefore(oldEndVnode.$elm$, oldStartVnode.$elm$);
1097
+ oldEndVnode = oldCh[--oldEndIdx];
1098
+ newStartVnode = newCh[++newStartIdx];
1099
+ }
1100
+ else {
1101
+ // Here we do some checks to match up old and new nodes based on the
1102
+ // `$key$` attribute, which is set by putting a `key="my-key"` attribute
1103
+ // in the JSX for a DOM element in the implementation of a Stencil
1104
+ // component.
1105
+ //
1106
+ // First we check to see if there are any nodes in the array of old
1107
+ // children which have the same key as the first node in the new
1108
+ // children.
1109
+ idxInOld = -1;
1110
+ {
1111
+ for (i = oldStartIdx; i <= oldEndIdx; ++i) {
1112
+ if (oldCh[i] && oldCh[i].$key$ !== null && oldCh[i].$key$ === newStartVnode.$key$) {
1113
+ idxInOld = i;
1114
+ break;
1115
+ }
1116
+ }
1117
+ }
1118
+ if (idxInOld >= 0) {
1119
+ // We found a node in the old children which matches up with the first
1120
+ // node in the new children! So let's deal with that
1121
+ elmToMove = oldCh[idxInOld];
1122
+ if (elmToMove.$tag$ !== newStartVnode.$tag$) {
1123
+ // the tag doesn't match so we'll need a new DOM element
1124
+ node = createElm(oldCh && oldCh[newStartIdx], newVNode, idxInOld, parentElm);
1125
+ }
1126
+ else {
1127
+ patch(elmToMove, newStartVnode);
1128
+ // invalidate the matching old node so that we won't try to update it
1129
+ // again later on
1130
+ oldCh[idxInOld] = undefined;
1131
+ node = elmToMove.$elm$;
1132
+ }
1133
+ newStartVnode = newCh[++newStartIdx];
1134
+ }
1135
+ else {
1136
+ // We either didn't find an element in the old children that matches
1137
+ // the key of the first new child OR the build is not using `key`
1138
+ // attributes at all. In either case we need to create a new element
1139
+ // for the new node.
1140
+ node = createElm(oldCh && oldCh[newStartIdx], newVNode, newStartIdx, parentElm);
1141
+ newStartVnode = newCh[++newStartIdx];
1142
+ }
1143
+ if (node) {
1144
+ // if we created a new node then handle inserting it to the DOM
1145
+ {
1146
+ parentReferenceNode(oldStartVnode.$elm$).insertBefore(node, referenceNode(oldStartVnode.$elm$));
1147
+ }
1148
+ }
1149
+ }
1150
+ }
1151
+ if (oldStartIdx > oldEndIdx) {
1152
+ // we have some more new nodes to add which don't match up with old nodes
1153
+ addVnodes(parentElm, newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].$elm$, newVNode, newCh, newStartIdx, newEndIdx);
1154
+ }
1155
+ else if (newStartIdx > newEndIdx) {
1156
+ // there are nodes in the `oldCh` array which no longer correspond to nodes
1157
+ // in the new array, so lets remove them (which entails cleaning up the
1158
+ // relevant DOM nodes)
1159
+ removeVnodes(oldCh, oldStartIdx, oldEndIdx);
1160
+ }
1161
+ };
1162
+ /**
1163
+ * Compare two VNodes to determine if they are the same
1164
+ *
1165
+ * **NB**: This function is an equality _heuristic_ based on the available
1166
+ * information set on the two VNodes and can be misleading under certain
1167
+ * circumstances. In particular, if the two nodes do not have `key` attrs
1168
+ * (available under `$key$` on VNodes) then the function falls back on merely
1169
+ * checking that they have the same tag.
1170
+ *
1171
+ * So, in other words, if `key` attrs are not set on VNodes which may be
1172
+ * changing order within a `children` array or something along those lines then
1173
+ * we could obtain a false negative and then have to do needless re-rendering
1174
+ * (i.e. we'd say two VNodes aren't equal when in fact they should be).
1175
+ *
1176
+ * @param leftVNode the first VNode to check
1177
+ * @param rightVNode the second VNode to check
1178
+ * @returns whether they're equal or not
1179
+ */
1180
+ const isSameVnode = (leftVNode, rightVNode) => {
1181
+ // compare if two vnode to see if they're "technically" the same
1182
+ // need to have the same element tag, and same key to be the same
1183
+ if (leftVNode.$tag$ === rightVNode.$tag$) {
1184
+ if (leftVNode.$tag$ === 'slot') {
1185
+ return leftVNode.$name$ === rightVNode.$name$;
1186
+ }
1187
+ // this will be set if components in the build have `key` attrs set on them
1188
+ {
1189
+ return leftVNode.$key$ === rightVNode.$key$;
1190
+ }
1191
+ }
1192
+ return false;
1193
+ };
1194
+ const referenceNode = (node) => {
1195
+ // this node was relocated to a new location in the dom
1196
+ // because of some other component's slot
1197
+ // but we still have an html comment in place of where
1198
+ // it's original location was according to it's original vdom
1199
+ return (node && node['s-ol']) || node;
1200
+ };
1201
+ const parentReferenceNode = (node) => (node['s-ol'] ? node['s-ol'] : node).parentNode;
1202
+ /**
1203
+ * Handle reconciling an outdated VNode with a new one which corresponds to
1204
+ * it. This function handles flushing updates to the DOM and reconciling the
1205
+ * children of the two nodes (if any).
1206
+ *
1207
+ * @param oldVNode an old VNode whose DOM element and children we want to update
1208
+ * @param newVNode a new VNode representing an updated version of the old one
1209
+ */
1210
+ const patch = (oldVNode, newVNode) => {
1211
+ const elm = (newVNode.$elm$ = oldVNode.$elm$);
1212
+ const oldChildren = oldVNode.$children$;
1213
+ const newChildren = newVNode.$children$;
1214
+ const tag = newVNode.$tag$;
1215
+ const text = newVNode.$text$;
1216
+ let defaultHolder;
1217
+ if (text === null) {
1218
+ {
1219
+ // test if we're rendering an svg element, or still rendering nodes inside of one
1220
+ // only add this to the when the compiler sees we're using an svg somewhere
1221
+ isSvgMode = tag === 'svg' ? true : tag === 'foreignObject' ? false : isSvgMode;
1222
+ }
1223
+ {
1224
+ if (tag === 'slot')
1225
+ ;
1226
+ else {
1227
+ // either this is the first render of an element OR it's an update
1228
+ // AND we already know it's possible it could have changed
1229
+ // this updates the element's css classes, attrs, props, listeners, etc.
1230
+ updateElement(oldVNode, newVNode, isSvgMode);
1231
+ }
1232
+ }
1233
+ if (oldChildren !== null && newChildren !== null) {
1234
+ // looks like there's child vnodes for both the old and new vnodes
1235
+ // so we need to call `updateChildren` to reconcile them
1236
+ updateChildren(elm, oldChildren, newVNode, newChildren);
1237
+ }
1238
+ else if (newChildren !== null) {
1239
+ // no old child vnodes, but there are new child vnodes to add
1240
+ if (oldVNode.$text$ !== null) {
1241
+ // the old vnode was text, so be sure to clear it out
1242
+ elm.textContent = '';
1243
+ }
1244
+ // add the new vnode children
1245
+ addVnodes(elm, null, newVNode, newChildren, 0, newChildren.length - 1);
1246
+ }
1247
+ else if (oldChildren !== null) {
1248
+ // no new child vnodes, but there are old child vnodes to remove
1249
+ removeVnodes(oldChildren, 0, oldChildren.length - 1);
1250
+ }
1251
+ if (isSvgMode && tag === 'svg') {
1252
+ isSvgMode = false;
1253
+ }
1254
+ }
1255
+ else if ((defaultHolder = elm['s-cr'])) {
1256
+ // this element has slotted content
1257
+ defaultHolder.parentNode.textContent = text;
1258
+ }
1259
+ else if (oldVNode.$text$ !== text) {
1260
+ // update the text content for the text only vnode
1261
+ // and also only if the text is different than before
1262
+ elm.data = text;
1263
+ }
1264
+ };
1265
+ /**
1266
+ * Adjust the `.hidden` property as-needed on any nodes in a DOM subtree which
1267
+ * are slot fallbacks nodes.
1268
+ *
1269
+ * A slot fallback node should be visible by default. Then, it should be
1270
+ * conditionally hidden if:
1271
+ *
1272
+ * - it has a sibling with a `slot` property set to its slot name or if
1273
+ * - it is a default fallback slot node, in which case we hide if it has any
1274
+ * content
1275
+ *
1276
+ * @param elm the element of interest
1277
+ */
1278
+ const updateFallbackSlotVisibility = (elm) => {
1279
+ const childNodes = elm.childNodes;
1280
+ for (const childNode of childNodes) {
1281
+ if (childNode.nodeType === 1 /* NODE_TYPE.ElementNode */) {
1282
+ if (childNode['s-sr']) {
1283
+ // this is a slot fallback node
1284
+ // get the slot name for this slot reference node
1285
+ const slotName = childNode['s-sn'];
1286
+ // by default always show a fallback slot node
1287
+ // then hide it if there are other slots in the light dom
1288
+ childNode.hidden = false;
1289
+ // we need to check all of its sibling nodes in order to see if
1290
+ // `childNode` should be hidden
1291
+ for (const siblingNode of childNodes) {
1292
+ // Don't check the node against itself
1293
+ if (siblingNode !== childNode) {
1294
+ if (siblingNode['s-hn'] !== childNode['s-hn'] || slotName !== '') {
1295
+ // this sibling node is from a different component OR is a named
1296
+ // fallback slot node
1297
+ if (siblingNode.nodeType === 1 /* NODE_TYPE.ElementNode */ &&
1298
+ (slotName === siblingNode.getAttribute('slot') || slotName === siblingNode['s-sn'])) {
1299
+ childNode.hidden = true;
1300
+ break;
1301
+ }
1302
+ }
1303
+ else {
1304
+ // this is a default fallback slot node
1305
+ // any element or text node (with content)
1306
+ // should hide the default fallback slot node
1307
+ if (siblingNode.nodeType === 1 /* NODE_TYPE.ElementNode */ ||
1308
+ (siblingNode.nodeType === 3 /* NODE_TYPE.TextNode */ && siblingNode.textContent.trim() !== '')) {
1309
+ childNode.hidden = true;
1310
+ break;
1311
+ }
1312
+ }
1313
+ }
1314
+ }
1315
+ }
1316
+ // keep drilling down
1317
+ updateFallbackSlotVisibility(childNode);
1318
+ }
1319
+ }
1320
+ };
1321
+ /**
1322
+ * Component-global information about nodes which are either currently being
1323
+ * relocated or will be shortly.
1324
+ */
1325
+ const relocateNodes = [];
1326
+ /**
1327
+ * Mark the contents of a slot for relocation via adding references to them to
1328
+ * the {@link relocateNodes} data structure. The actual work of relocating them
1329
+ * will then be handled in {@link renderVdom}.
1330
+ *
1331
+ * @param elm a render node whose child nodes need to be relocated
1332
+ */
1333
+ const markSlotContentForRelocation = (elm) => {
1334
+ // tslint:disable-next-line: prefer-const
1335
+ let node;
1336
+ let hostContentNodes;
1337
+ let j;
1338
+ for (const childNode of elm.childNodes) {
1339
+ // we need to find child nodes which are slot references so we can then try
1340
+ // to match them up with nodes that need to be relocated
1341
+ if (childNode['s-sr'] && (node = childNode['s-cr']) && node.parentNode) {
1342
+ // first get the content reference comment node ('s-cr'), then we get
1343
+ // its parent, which is where all the host content is now
1344
+ hostContentNodes = node.parentNode.childNodes;
1345
+ const slotName = childNode['s-sn'];
1346
+ // iterate through all the nodes under the location where the host was
1347
+ // originally rendered
1348
+ for (j = hostContentNodes.length - 1; j >= 0; j--) {
1349
+ node = hostContentNodes[j];
1350
+ // check that the node is not a content reference node or a node
1351
+ // reference and then check that the host name does not match that of
1352
+ // childNode.
1353
+ // In addition, check that the slot either has not already been relocated, or
1354
+ // that its current location's host is not childNode's host. This is essentially
1355
+ // a check so that we don't try to relocate (and then hide) a node that is already
1356
+ // where it should be.
1357
+ if (!node['s-cn'] &&
1358
+ !node['s-nr'] &&
1359
+ node['s-hn'] !== childNode['s-hn'] &&
1360
+ (!BUILD.experimentalSlotFixes )) {
1361
+ // if `node` is located in the slot that `childNode` refers to (via the
1362
+ // `'s-sn'` property) then we need to relocate it from it's current spot
1363
+ // (under the host element parent) to the right slot location
1364
+ if (isNodeLocatedInSlot(node, slotName)) {
1365
+ // it's possible we've already decided to relocate this node
1366
+ let relocateNodeData = relocateNodes.find((r) => r.$nodeToRelocate$ === node);
1367
+ // made some changes to slots
1368
+ // let's make sure we also double check
1369
+ // fallbacks are correctly hidden or shown
1370
+ checkSlotFallbackVisibility = true;
1371
+ // ensure that the slot-name attr is correct
1372
+ node['s-sn'] = node['s-sn'] || slotName;
1373
+ if (relocateNodeData) {
1374
+ relocateNodeData.$nodeToRelocate$['s-sh'] = childNode['s-hn'];
1375
+ // we marked this node for relocation previously but didn't find
1376
+ // out the slot reference node to which it needs to be relocated
1377
+ // so write it down now!
1378
+ relocateNodeData.$slotRefNode$ = childNode;
1379
+ }
1380
+ else {
1381
+ node['s-sh'] = childNode['s-hn'];
1382
+ // add to our list of nodes to relocate
1383
+ relocateNodes.push({
1384
+ $slotRefNode$: childNode,
1385
+ $nodeToRelocate$: node,
1386
+ });
1387
+ }
1388
+ if (node['s-sr']) {
1389
+ relocateNodes.map((relocateNode) => {
1390
+ if (isNodeLocatedInSlot(relocateNode.$nodeToRelocate$, node['s-sn'])) {
1391
+ relocateNodeData = relocateNodes.find((r) => r.$nodeToRelocate$ === node);
1392
+ if (relocateNodeData && !relocateNode.$slotRefNode$) {
1393
+ relocateNode.$slotRefNode$ = relocateNodeData.$slotRefNode$;
1394
+ }
1395
+ }
1396
+ });
1397
+ }
1398
+ }
1399
+ else if (!relocateNodes.some((r) => r.$nodeToRelocate$ === node)) {
1400
+ // the node is not found within the slot (`childNode`) that we're
1401
+ // currently looking at, so we stick it into `relocateNodes` to
1402
+ // handle later. If we never find a home for this element then
1403
+ // we'll need to hide it
1404
+ relocateNodes.push({
1405
+ $nodeToRelocate$: node,
1406
+ });
1407
+ }
1408
+ }
1409
+ }
1410
+ }
1411
+ // if we're dealing with any type of element (capable of itself being a
1412
+ // slot reference or containing one) then we recur
1413
+ if (childNode.nodeType === 1 /* NODE_TYPE.ElementNode */) {
1414
+ markSlotContentForRelocation(childNode);
1415
+ }
1416
+ }
1417
+ };
1418
+ /**
1419
+ * Check whether a node is located in a given named slot.
1420
+ *
1421
+ * @param nodeToRelocate the node of interest
1422
+ * @param slotName the slot name to check
1423
+ * @returns whether the node is located in the slot or not
1424
+ */
1425
+ const isNodeLocatedInSlot = (nodeToRelocate, slotName) => {
1426
+ if (nodeToRelocate.nodeType === 1 /* NODE_TYPE.ElementNode */) {
1427
+ if (nodeToRelocate.getAttribute('slot') === null && slotName === '') {
1428
+ // if the node doesn't have a slot attribute, and the slot we're checking
1429
+ // is not a named slot, then we assume the node should be within the slot
1430
+ return true;
1431
+ }
1432
+ if (nodeToRelocate.getAttribute('slot') === slotName) {
1433
+ return true;
1434
+ }
1435
+ return false;
1436
+ }
1437
+ if (nodeToRelocate['s-sn'] === slotName) {
1438
+ return true;
1439
+ }
1440
+ return slotName === '';
1441
+ };
1442
+ /**
1443
+ * 'Nullify' any VDom `ref` callbacks on a VDom node or its children by calling
1444
+ * them with `null`. This signals that the DOM element corresponding to the VDom
1445
+ * node has been removed from the DOM.
1446
+ *
1447
+ * @param vNode a virtual DOM node
1448
+ */
1449
+ const nullifyVNodeRefs = (vNode) => {
1450
+ {
1451
+ vNode.$attrs$ && vNode.$attrs$.ref && vNode.$attrs$.ref(null);
1452
+ vNode.$children$ && vNode.$children$.map(nullifyVNodeRefs);
1453
+ }
1454
+ };
1455
+ /**
1456
+ * The main entry point for Stencil's virtual DOM-based rendering engine
1457
+ *
1458
+ * Given a {@link d.HostRef} container and some virtual DOM nodes, this
1459
+ * function will handle creating a virtual DOM tree with a single root, patching
1460
+ * the current virtual DOM tree onto an old one (if any), dealing with slot
1461
+ * relocation, and reflecting attributes.
1462
+ *
1463
+ * @param hostRef data needed to root and render the virtual DOM tree, such as
1464
+ * the DOM node into which it should be rendered.
1465
+ * @param renderFnResults the virtual DOM nodes to be rendered
1466
+ * @param isInitialLoad whether or not this is the first call after page load
1467
+ */
1468
+ const renderVdom = (hostRef, renderFnResults, isInitialLoad = false) => {
1469
+ var _a, _b;
1470
+ const hostElm = hostRef.$hostElement$;
1471
+ const cmpMeta = hostRef.$cmpMeta$;
1472
+ const oldVNode = hostRef.$vnode$ || newVNode(null, null);
1473
+ // if `renderFnResults` is a Host node then we can use it directly. If not,
1474
+ // we need to call `h` again to wrap the children of our component in a
1475
+ // 'dummy' Host node (well, an empty vnode) since `renderVdom` assumes
1476
+ // implicitly that the top-level vdom node is 1) an only child and 2)
1477
+ // contains attrs that need to be set on the host element.
1478
+ const rootVnode = isHost(renderFnResults) ? renderFnResults : h(null, null, renderFnResults);
1479
+ hostTagName = hostElm.tagName;
1480
+ if (cmpMeta.$attrsToReflect$) {
1481
+ rootVnode.$attrs$ = rootVnode.$attrs$ || {};
1482
+ cmpMeta.$attrsToReflect$.map(([propName, attribute]) => (rootVnode.$attrs$[attribute] = hostElm[propName]));
1483
+ }
1484
+ // On the first render and *only* on the first render we want to check for
1485
+ // any attributes set on the host element which are also set on the vdom
1486
+ // node. If we find them, we override the value on the VDom node attrs with
1487
+ // the value from the host element, which allows developers building apps
1488
+ // with Stencil components to override e.g. the `role` attribute on a
1489
+ // component even if it's already set on the `Host`.
1490
+ if (isInitialLoad && rootVnode.$attrs$) {
1491
+ for (const key of Object.keys(rootVnode.$attrs$)) {
1492
+ // We have a special implementation in `setAccessor` for `style` and
1493
+ // `class` which reconciles values coming from the VDom with values
1494
+ // already present on the DOM element, so we don't want to override those
1495
+ // attributes on the VDom tree with values from the host element if they
1496
+ // are present.
1497
+ //
1498
+ // Likewise, `ref` and `key` are special internal values for the Stencil
1499
+ // runtime and we don't want to override those either.
1500
+ if (hostElm.hasAttribute(key) && !['key', 'ref', 'style', 'class'].includes(key)) {
1501
+ rootVnode.$attrs$[key] = hostElm[key];
1502
+ }
1503
+ }
1504
+ }
1505
+ rootVnode.$tag$ = null;
1506
+ rootVnode.$flags$ |= 4 /* VNODE_FLAGS.isHost */;
1507
+ hostRef.$vnode$ = rootVnode;
1508
+ rootVnode.$elm$ = oldVNode.$elm$ = (hostElm.shadowRoot || hostElm );
1509
+ {
1510
+ scopeId = hostElm['s-sc'];
1511
+ }
1512
+ {
1513
+ contentRef = hostElm['s-cr'];
1514
+ useNativeShadowDom = (cmpMeta.$flags$ & 1 /* CMP_FLAGS.shadowDomEncapsulation */) !== 0;
1515
+ // always reset
1516
+ checkSlotFallbackVisibility = false;
1517
+ }
1518
+ // synchronous patch
1519
+ patch(oldVNode, rootVnode);
1520
+ {
1521
+ // while we're moving nodes around existing nodes, temporarily disable
1522
+ // the disconnectCallback from working
1523
+ plt.$flags$ |= 1 /* PLATFORM_FLAGS.isTmpDisconnected */;
1524
+ if (checkSlotRelocate) {
1525
+ markSlotContentForRelocation(rootVnode.$elm$);
1526
+ for (const relocateData of relocateNodes) {
1527
+ const nodeToRelocate = relocateData.$nodeToRelocate$;
1528
+ if (!nodeToRelocate['s-ol']) {
1529
+ // add a reference node marking this node's original location
1530
+ // keep a reference to this node for later lookups
1531
+ const orgLocationNode = doc$1.createTextNode('');
1532
+ orgLocationNode['s-nr'] = nodeToRelocate;
1533
+ nodeToRelocate.parentNode.insertBefore((nodeToRelocate['s-ol'] = orgLocationNode), nodeToRelocate);
1534
+ }
1535
+ }
1536
+ for (const relocateData of relocateNodes) {
1537
+ const nodeToRelocate = relocateData.$nodeToRelocate$;
1538
+ const slotRefNode = relocateData.$slotRefNode$;
1539
+ if (slotRefNode) {
1540
+ const parentNodeRef = slotRefNode.parentNode;
1541
+ // When determining where to insert content, the most simple case would be
1542
+ // to relocate the node immediately following the slot reference node. We do this
1543
+ // by getting a reference to the node immediately following the slot reference node
1544
+ // since we will use `insertBefore` to manipulate the DOM.
1545
+ //
1546
+ // If there is no node immediately following the slot reference node, then we will just
1547
+ // end up appending the node as the last child of the parent.
1548
+ let insertBeforeNode = slotRefNode.nextSibling;
1549
+ // If the node we're currently planning on inserting the new node before is an element,
1550
+ // we need to do some additional checks to make sure we're inserting the node in the correct order.
1551
+ // The use case here would be that we have multiple nodes being relocated to the same slot. So, we want
1552
+ // to make sure they get inserted into their new how in the same order they were declared in their original location.
1553
+ //
1554
+ // TODO(STENCIL-914): Remove `experimentalSlotFixes` check
1555
+ {
1556
+ let orgLocationNode = (_a = nodeToRelocate['s-ol']) === null || _a === void 0 ? void 0 : _a.previousSibling;
1557
+ while (orgLocationNode) {
1558
+ let refNode = (_b = orgLocationNode['s-nr']) !== null && _b !== void 0 ? _b : null;
1559
+ if (refNode && refNode['s-sn'] === nodeToRelocate['s-sn'] && parentNodeRef === refNode.parentNode) {
1560
+ refNode = refNode.nextSibling;
1561
+ if (!refNode || !refNode['s-nr']) {
1562
+ insertBeforeNode = refNode;
1563
+ break;
1564
+ }
1565
+ }
1566
+ orgLocationNode = orgLocationNode.previousSibling;
1567
+ }
1568
+ }
1569
+ if ((!insertBeforeNode && parentNodeRef !== nodeToRelocate.parentNode) ||
1570
+ nodeToRelocate.nextSibling !== insertBeforeNode) {
1571
+ // we've checked that it's worth while to relocate
1572
+ // since that the node to relocate
1573
+ // has a different next sibling or parent relocated
1574
+ if (nodeToRelocate !== insertBeforeNode) {
1575
+ if (!nodeToRelocate['s-hn'] && nodeToRelocate['s-ol']) {
1576
+ // probably a component in the index.html that doesn't have its hostname set
1577
+ nodeToRelocate['s-hn'] = nodeToRelocate['s-ol'].parentNode.nodeName;
1578
+ }
1579
+ // Add it back to the dom but in its new home
1580
+ // If we get to this point and `insertBeforeNode` is `null`, that means
1581
+ // we're just going to append the node as the last child of the parent. Passing
1582
+ // `null` as the second arg here will trigger that behavior.
1583
+ parentNodeRef.insertBefore(nodeToRelocate, insertBeforeNode);
1584
+ }
1585
+ }
1586
+ }
1587
+ else {
1588
+ // this node doesn't have a slot home to go to, so let's hide it
1589
+ if (nodeToRelocate.nodeType === 1 /* NODE_TYPE.ElementNode */) {
1590
+ nodeToRelocate.hidden = true;
1591
+ }
1592
+ }
1593
+ }
1594
+ }
1595
+ if (checkSlotFallbackVisibility) {
1596
+ updateFallbackSlotVisibility(rootVnode.$elm$);
1597
+ }
1598
+ // done moving nodes around
1599
+ // allow the disconnect callback to work again
1600
+ plt.$flags$ &= ~1 /* PLATFORM_FLAGS.isTmpDisconnected */;
1601
+ // always reset
1602
+ relocateNodes.length = 0;
1603
+ }
1604
+ };
1605
+ const attachToAncestor = (hostRef, ancestorComponent) => {
1606
+ };
1607
+ const scheduleUpdate = (hostRef, isInitialLoad) => {
1608
+ {
1609
+ hostRef.$flags$ |= 16 /* HOST_FLAGS.isQueuedForUpdate */;
1610
+ }
1611
+ attachToAncestor(hostRef, hostRef.$ancestorComponent$);
1612
+ // there is no ancestor component or the ancestor component
1613
+ // has already fired off its lifecycle update then
1614
+ // fire off the initial update
1615
+ const dispatch = () => dispatchHooks(hostRef, isInitialLoad);
1616
+ return writeTask(dispatch) ;
1617
+ };
1618
+ /**
1619
+ * Dispatch initial-render and update lifecycle hooks, enqueuing calls to
1620
+ * component lifecycle methods like `componentWillLoad` as well as
1621
+ * {@link updateComponent}, which will kick off the virtual DOM re-render.
1622
+ *
1623
+ * @param hostRef a reference to a host DOM node
1624
+ * @param isInitialLoad whether we're on the initial load or not
1625
+ * @returns an empty Promise which is used to enqueue a series of operations for
1626
+ * the component
1627
+ */
1628
+ const dispatchHooks = (hostRef, isInitialLoad) => {
1629
+ const elm = hostRef.$hostElement$;
1630
+ const endSchedule = createTime('scheduleUpdate', hostRef.$cmpMeta$.$tagName$);
1631
+ const instance = elm;
1632
+ // We're going to use this variable together with `enqueue` to implement a
1633
+ // little promise-based queue. We start out with it `undefined`. When we add
1634
+ // the first function to the queue we'll set this variable to be that
1635
+ // function's return value. When we attempt to add subsequent values to the
1636
+ // queue we'll check that value and, if it was a `Promise`, we'll then chain
1637
+ // the new function off of that `Promise` using `.then()`. This will give our
1638
+ // queue two nice properties:
1639
+ //
1640
+ // 1. If all functions added to the queue are synchronous they'll be called
1641
+ // synchronously right away.
1642
+ // 2. If all functions added to the queue are asynchronous they'll all be
1643
+ // called in order after `dispatchHooks` exits.
1644
+ let maybePromise;
1645
+ if (isInitialLoad) {
1646
+ {
1647
+ // If `componentWillLoad` returns a `Promise` then we want to wait on
1648
+ // whatever's going on in that `Promise` before we launch into
1649
+ // rendering the component, doing other lifecycle stuff, etc. So
1650
+ // in that case we assign the returned promise to the variable we
1651
+ // declared above to hold a possible 'queueing' Promise
1652
+ maybePromise = safeCall(instance, 'componentWillLoad');
1653
+ }
1654
+ }
1655
+ else {
1656
+ {
1657
+ // Like `componentWillLoad` above, we allow Stencil component
1658
+ // authors to return a `Promise` from this lifecycle callback, and
1659
+ // we specify that our runtime will wait for that `Promise` to
1660
+ // resolve before the component re-renders. So if the method
1661
+ // returns a `Promise` we need to keep it around!
1662
+ maybePromise = safeCall(instance, 'componentWillUpdate');
1663
+ }
1664
+ }
1665
+ {
1666
+ maybePromise = enqueue(maybePromise, () => safeCall(instance, 'componentWillRender'));
1667
+ }
1668
+ endSchedule();
1669
+ return enqueue(maybePromise, () => updateComponent(hostRef, instance, isInitialLoad));
1670
+ };
1671
+ /**
1672
+ * This function uses a Promise to implement a simple first-in, first-out queue
1673
+ * of functions to be called.
1674
+ *
1675
+ * The queue is ordered on the basis of the first argument. If it's
1676
+ * `undefined`, then nothing is on the queue yet, so the provided function can
1677
+ * be called synchronously (although note that this function may return a
1678
+ * `Promise`). The idea is that then the return value of that enqueueing
1679
+ * operation is kept around, so that if it was a `Promise` then subsequent
1680
+ * functions can be enqueued by calling this function again with that `Promise`
1681
+ * as the first argument.
1682
+ *
1683
+ * @param maybePromise either a `Promise` which should resolve before the next function is called or an 'empty' sentinel
1684
+ * @param fn a function to enqueue
1685
+ * @returns either a `Promise` or the return value of the provided function
1686
+ */
1687
+ const enqueue = (maybePromise, fn) => isPromisey(maybePromise) ? maybePromise.then(fn) : fn();
1688
+ /**
1689
+ * Check that a value is a `Promise`. To check, we first see if the value is an
1690
+ * instance of the `Promise` global. In a few circumstances, in particular if
1691
+ * the global has been overwritten, this is could be misleading, so we also do
1692
+ * a little 'duck typing' check to see if the `.then` property of the value is
1693
+ * defined and a function.
1694
+ *
1695
+ * @param maybePromise it might be a promise!
1696
+ * @returns whether it is or not
1697
+ */
1698
+ const isPromisey = (maybePromise) => maybePromise instanceof Promise ||
1699
+ (maybePromise && maybePromise.then && typeof maybePromise.then === 'function');
1700
+ /**
1701
+ * Update a component given reference to its host elements and so on.
1702
+ *
1703
+ * @param hostRef an object containing references to the element's host node,
1704
+ * VDom nodes, and other metadata
1705
+ * @param instance a reference to the underlying host element where it will be
1706
+ * rendered
1707
+ * @param isInitialLoad whether or not this function is being called as part of
1708
+ * the first render cycle
1709
+ */
1710
+ const updateComponent = async (hostRef, instance, isInitialLoad) => {
1711
+ const elm = hostRef.$hostElement$;
1712
+ const endUpdate = createTime('update', hostRef.$cmpMeta$.$tagName$);
1713
+ elm['s-rc'];
1714
+ if (isInitialLoad) {
1715
+ // DOM WRITE!
1716
+ attachStyles(hostRef);
1717
+ }
1718
+ const endRender = createTime('render', hostRef.$cmpMeta$.$tagName$);
1719
+ {
1720
+ callRender(hostRef, instance, elm, isInitialLoad);
1721
+ }
1722
+ endRender();
1723
+ endUpdate();
1724
+ {
1725
+ postUpdateComponent(hostRef);
1726
+ }
1727
+ };
1728
+ /**
1729
+ * Handle making the call to the VDom renderer with the proper context given
1730
+ * various build variables
1731
+ *
1732
+ * @param hostRef an object containing references to the element's host node,
1733
+ * VDom nodes, and other metadata
1734
+ * @param instance a reference to the underlying host element where it will be
1735
+ * rendered
1736
+ * @param elm the Host element for the component
1737
+ * @param isInitialLoad whether or not this function is being called as part of
1738
+ * @returns an empty promise
1739
+ */
1740
+ const callRender = (hostRef, instance, elm, isInitialLoad) => {
1741
+ // in order for bundlers to correctly tree-shake the BUILD object
1742
+ // we need to ensure BUILD is not deoptimized within a try/catch
1743
+ // https://rollupjs.org/guide/en/#treeshake tryCatchDeoptimization
1744
+ const allRenderFn = false;
1745
+ const lazyLoad = false;
1746
+ const taskQueue = true ;
1747
+ const updatable = true ;
1748
+ try {
1749
+ renderingRef = instance;
1750
+ /**
1751
+ * minification optimization: `allRenderFn` is `true` if all components have a `render`
1752
+ * method, so we can call the method immediately. If not, check before calling it.
1753
+ */
1754
+ instance = allRenderFn ? instance.render() : instance.render && instance.render();
1755
+ if (updatable && taskQueue) {
1756
+ hostRef.$flags$ &= ~16 /* HOST_FLAGS.isQueuedForUpdate */;
1757
+ }
1758
+ if (updatable || lazyLoad) {
1759
+ hostRef.$flags$ |= 2 /* HOST_FLAGS.hasRendered */;
1760
+ }
1761
+ if (BUILD.hasRenderFn || BUILD.reflect) {
1762
+ if (BUILD.vdomRender || BUILD.reflect) {
1763
+ // looks like we've got child nodes to render into this host element
1764
+ // or we need to update the css class/attrs on the host element
1765
+ // DOM WRITE!
1766
+ if (BUILD.hydrateServerSide) ;
1767
+ else {
1768
+ renderVdom(hostRef, instance, isInitialLoad);
1769
+ }
1770
+ }
1771
+ }
1772
+ }
1773
+ catch (e) {
1774
+ consoleError(e, hostRef.$hostElement$);
1775
+ }
1776
+ renderingRef = null;
1777
+ return null;
1778
+ };
1779
+ const postUpdateComponent = (hostRef) => {
1780
+ const tagName = hostRef.$cmpMeta$.$tagName$;
1781
+ const elm = hostRef.$hostElement$;
1782
+ const endPostUpdate = createTime('postUpdate', tagName);
1783
+ const instance = elm;
1784
+ hostRef.$ancestorComponent$;
1785
+ {
1786
+ safeCall(instance, 'componentDidRender');
1787
+ }
1788
+ if (!(hostRef.$flags$ & 64 /* HOST_FLAGS.hasLoadedComponent */)) {
1789
+ hostRef.$flags$ |= 64 /* HOST_FLAGS.hasLoadedComponent */;
1790
+ {
1791
+ safeCall(instance, 'componentDidLoad');
1792
+ }
1793
+ endPostUpdate();
1794
+ }
1795
+ else {
1796
+ {
1797
+ safeCall(instance, 'componentDidUpdate');
1798
+ }
1799
+ endPostUpdate();
1800
+ }
1801
+ // ( •_•)
1802
+ // ( •_•)>⌐■-■
1803
+ // (⌐■_■)
1804
+ };
1805
+ /**
1806
+ * Allows to safely call a method, e.g. `componentDidLoad`, on an instance,
1807
+ * e.g. custom element node. If a build figures out that e.g. no component
1808
+ * has a `componentDidLoad` method, the instance method gets removed from the
1809
+ * output bundle and this function returns `undefined`.
1810
+ * @param instance any object that may or may not contain methods
1811
+ * @param method method name
1812
+ * @param arg single arbitrary argument
1813
+ * @returns result of method call if it exists, otherwise `undefined`
1814
+ */
1815
+ const safeCall = (instance, method, arg) => {
1816
+ if (instance && instance[method]) {
1817
+ try {
1818
+ return instance[method](arg);
1819
+ }
1820
+ catch (e) {
1821
+ consoleError(e);
1822
+ }
1823
+ }
1824
+ return undefined;
1825
+ };
1826
+ const getValue = (ref, propName) => getHostRef(ref).$instanceValues$.get(propName);
1827
+ const setValue = (ref, propName, newVal, cmpMeta) => {
1828
+ // check our new property value against our internal value
1829
+ const hostRef = getHostRef(ref);
1830
+ const elm = ref;
1831
+ const oldVal = hostRef.$instanceValues$.get(propName);
1832
+ const flags = hostRef.$flags$;
1833
+ const instance = elm;
1834
+ newVal = parsePropertyValue(newVal, cmpMeta.$members$[propName][0]);
1835
+ // explicitly check for NaN on both sides, as `NaN === NaN` is always false
1836
+ const areBothNaN = Number.isNaN(oldVal) && Number.isNaN(newVal);
1837
+ const didValueChange = newVal !== oldVal && !areBothNaN;
1838
+ if (didValueChange) {
1839
+ // gadzooks! the property's value has changed!!
1840
+ // set our new value!
1841
+ hostRef.$instanceValues$.set(propName, newVal);
1842
+ {
1843
+ // get an array of method names of watch functions to call
1844
+ if (cmpMeta.$watchers$ && flags & 128 /* HOST_FLAGS.isWatchReady */) {
1845
+ const watchMethods = cmpMeta.$watchers$[propName];
1846
+ if (watchMethods) {
1847
+ // this instance is watching for when this property changed
1848
+ watchMethods.map((watchMethodName) => {
1849
+ try {
1850
+ // fire off each of the watch methods that are watching this property
1851
+ instance[watchMethodName](newVal, oldVal, propName);
1852
+ }
1853
+ catch (e) {
1854
+ consoleError(e, elm);
1855
+ }
1856
+ });
1857
+ }
1858
+ }
1859
+ if ((flags & (2 /* HOST_FLAGS.hasRendered */ | 16 /* HOST_FLAGS.isQueuedForUpdate */)) === 2 /* HOST_FLAGS.hasRendered */) {
1860
+ if (instance.componentShouldUpdate) {
1861
+ if (instance.componentShouldUpdate(newVal, oldVal, propName) === false) {
1862
+ return;
1863
+ }
1864
+ }
1865
+ // looks like this value actually changed, so we've got work to do!
1866
+ // but only if we've already rendered, otherwise just chill out
1867
+ // queue that we need to do an update, but don't worry about queuing
1868
+ // up millions cuz this function ensures it only runs once
1869
+ scheduleUpdate(hostRef, false);
1870
+ }
1871
+ }
1872
+ }
1873
+ };
1874
+ /**
1875
+ * Attach a series of runtime constructs to a compiled Stencil component
1876
+ * constructor, including getters and setters for the `@Prop` and `@State`
1877
+ * decorators, callbacks for when attributes change, and so on.
1878
+ *
1879
+ * @param Cstr the constructor for a component that we need to process
1880
+ * @param cmpMeta metadata collected previously about the component
1881
+ * @param flags a number used to store a series of bit flags
1882
+ * @returns a reference to the same constructor passed in (but now mutated)
1883
+ */
1884
+ const proxyComponent = (Cstr, cmpMeta, flags) => {
1885
+ var _a;
1886
+ const prototype = Cstr.prototype;
1887
+ if (cmpMeta.$members$) {
1888
+ if (Cstr.watchers) {
1889
+ cmpMeta.$watchers$ = Cstr.watchers;
1890
+ }
1891
+ // It's better to have a const than two Object.entries()
1892
+ const members = Object.entries(cmpMeta.$members$);
1893
+ members.map(([memberName, [memberFlags]]) => {
1894
+ if ((memberFlags & 31 /* MEMBER_FLAGS.Prop */ ||
1895
+ (memberFlags & 32 /* MEMBER_FLAGS.State */))) {
1896
+ // proxyComponent - prop
1897
+ Object.defineProperty(prototype, memberName, {
1898
+ get() {
1899
+ // proxyComponent, get value
1900
+ return getValue(this, memberName);
1901
+ },
1902
+ set(newValue) {
1903
+ // proxyComponent, set value
1904
+ setValue(this, memberName, newValue, cmpMeta);
1905
+ },
1906
+ configurable: true,
1907
+ enumerable: true,
1908
+ });
1909
+ }
1910
+ });
1911
+ {
1912
+ const attrNameToPropName = new Map();
1913
+ prototype.attributeChangedCallback = function (attrName, oldValue, newValue) {
1914
+ plt.jmp(() => {
1915
+ var _a;
1916
+ const propName = attrNameToPropName.get(attrName);
1917
+ // In a web component lifecycle the attributeChangedCallback runs prior to connectedCallback
1918
+ // in the case where an attribute was set inline.
1919
+ // ```html
1920
+ // <my-component some-attribute="some-value"></my-component>
1921
+ // ```
1922
+ //
1923
+ // There is an edge case where a developer sets the attribute inline on a custom element and then
1924
+ // programmatically changes it before it has been upgraded as shown below:
1925
+ //
1926
+ // ```html
1927
+ // <!-- this component has _not_ been upgraded yet -->
1928
+ // <my-component id="test" some-attribute="some-value"></my-component>
1929
+ // <script>
1930
+ // // grab non-upgraded component
1931
+ // el = document.querySelector("#test");
1932
+ // el.someAttribute = "another-value";
1933
+ // // upgrade component
1934
+ // customElements.define('my-component', MyComponent);
1935
+ // </script>
1936
+ // ```
1937
+ // In this case if we do not un-shadow here and use the value of the shadowing property, attributeChangedCallback
1938
+ // will be called with `newValue = "some-value"` and will set the shadowed property (this.someAttribute = "another-value")
1939
+ // to the value that was set inline i.e. "some-value" from above example. When
1940
+ // the connectedCallback attempts to un-shadow it will use "some-value" as the initial value rather than "another-value"
1941
+ //
1942
+ // The case where the attribute was NOT set inline but was not set programmatically shall be handled/un-shadowed
1943
+ // by connectedCallback as this attributeChangedCallback will not fire.
1944
+ //
1945
+ // https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties
1946
+ //
1947
+ // TODO(STENCIL-16) we should think about whether or not we actually want to be reflecting the attributes to
1948
+ // properties here given that this goes against best practices outlined here
1949
+ // https://developers.google.com/web/fundamentals/web-components/best-practices#avoid-reentrancy
1950
+ if (this.hasOwnProperty(propName)) {
1951
+ newValue = this[propName];
1952
+ delete this[propName];
1953
+ }
1954
+ else if (prototype.hasOwnProperty(propName) &&
1955
+ typeof this[propName] === 'number' &&
1956
+ this[propName] == newValue) {
1957
+ // if the propName exists on the prototype of `Cstr`, this update may be a result of Stencil using native
1958
+ // APIs to reflect props as attributes. Calls to `setAttribute(someElement, propName)` will result in
1959
+ // `propName` to be converted to a `DOMString`, which may not be what we want for other primitive props.
1960
+ return;
1961
+ }
1962
+ else if (propName == null) {
1963
+ // At this point we should know this is not a "member", so we can treat it like watching an attribute
1964
+ // on a vanilla web component
1965
+ const hostRef = getHostRef(this);
1966
+ const flags = hostRef === null || hostRef === void 0 ? void 0 : hostRef.$flags$;
1967
+ // We only want to trigger the callback(s) if:
1968
+ // 1. The instance is ready
1969
+ // 2. The watchers are ready
1970
+ // 3. The value has changed
1971
+ if (flags &&
1972
+ !(flags & 8 /* HOST_FLAGS.isConstructingInstance */) &&
1973
+ flags & 128 /* HOST_FLAGS.isWatchReady */ &&
1974
+ newValue !== oldValue) {
1975
+ const elm = this;
1976
+ const instance = elm;
1977
+ const entry = (_a = cmpMeta.$watchers$) === null || _a === void 0 ? void 0 : _a[attrName];
1978
+ entry === null || entry === void 0 ? void 0 : entry.forEach((callbackName) => {
1979
+ if (instance[callbackName] != null) {
1980
+ instance[callbackName].call(instance, newValue, oldValue, attrName);
1981
+ }
1982
+ });
1983
+ }
1984
+ return;
1985
+ }
1986
+ this[propName] = newValue === null && typeof this[propName] === 'boolean' ? false : newValue;
1987
+ });
1988
+ };
1989
+ // Create an array of attributes to observe
1990
+ // This list in comprised of all strings used within a `@Watch()` decorator
1991
+ // on a component as well as any Stencil-specific "members" (`@Prop()`s and `@State()`s).
1992
+ // As such, there is no way to guarantee type-safety here that a user hasn't entered
1993
+ // an invalid attribute.
1994
+ Cstr.observedAttributes = Array.from(new Set([
1995
+ ...Object.keys((_a = cmpMeta.$watchers$) !== null && _a !== void 0 ? _a : {}),
1996
+ ...members
1997
+ .filter(([_, m]) => m[0] & 15 /* MEMBER_FLAGS.HasAttribute */)
1998
+ .map(([propName, m]) => {
1999
+ var _a;
2000
+ const attrName = m[1] || propName;
2001
+ attrNameToPropName.set(attrName, propName);
2002
+ if (m[0] & 512 /* MEMBER_FLAGS.ReflectAttr */) {
2003
+ (_a = cmpMeta.$attrsToReflect$) === null || _a === void 0 ? void 0 : _a.push([propName, attrName]);
2004
+ }
2005
+ return attrName;
2006
+ }),
2007
+ ]));
2008
+ }
2009
+ }
2010
+ return Cstr;
2011
+ };
2012
+ /**
2013
+ * Initialize a Stencil component given a reference to its host element, its
2014
+ * runtime bookkeeping data structure, runtime metadata about the component,
2015
+ * and (optionally) an HMR version ID.
2016
+ *
2017
+ * @param elm a host element
2018
+ * @param hostRef the element's runtime bookkeeping object
2019
+ * @param cmpMeta runtime metadata for the Stencil component
2020
+ * @param hmrVersionId an (optional) HMR version ID
2021
+ */
2022
+ const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId) => {
2023
+ let Cstr;
2024
+ // initializeComponent
2025
+ if ((hostRef.$flags$ & 32 /* HOST_FLAGS.hasInitializedComponent */) === 0) {
2026
+ // Let the runtime know that the component has been initialized
2027
+ hostRef.$flags$ |= 32 /* HOST_FLAGS.hasInitializedComponent */;
2028
+ {
2029
+ // sync constructor component
2030
+ Cstr = elm.constructor;
2031
+ // wait for the CustomElementRegistry to mark the component as ready before setting `isWatchReady`. Otherwise,
2032
+ // watchers may fire prematurely if `customElements.get()`/`customElements.whenDefined()` resolves _before_
2033
+ // Stencil has completed instantiating the component.
2034
+ customElements.whenDefined(cmpMeta.$tagName$).then(() => (hostRef.$flags$ |= 128 /* HOST_FLAGS.isWatchReady */));
2035
+ }
2036
+ if (Cstr.style) {
2037
+ // this component has styles but we haven't registered them yet
2038
+ let style = Cstr.style;
2039
+ if (typeof style !== 'string') {
2040
+ style = style[(hostRef.$modeName$ = computeMode(elm))];
2041
+ }
2042
+ const scopeId = getScopeId(cmpMeta, hostRef.$modeName$);
2043
+ if (!styles.has(scopeId)) {
2044
+ const endRegisterStyles = createTime('registerStyles', cmpMeta.$tagName$);
2045
+ registerStyle(scopeId, style, !!(cmpMeta.$flags$ & 1 /* CMP_FLAGS.shadowDomEncapsulation */));
2046
+ endRegisterStyles();
2047
+ }
2048
+ }
2049
+ }
2050
+ // we've successfully created a lazy instance
2051
+ hostRef.$ancestorComponent$;
2052
+ const schedule = () => scheduleUpdate(hostRef, true);
2053
+ {
2054
+ schedule();
2055
+ }
2056
+ };
2057
+ const fireConnectedCallback = (instance) => {
2058
+ };
2059
+ const connectedCallback = (elm) => {
2060
+ if ((plt.$flags$ & 1 /* PLATFORM_FLAGS.isTmpDisconnected */) === 0) {
2061
+ const hostRef = getHostRef(elm);
2062
+ const cmpMeta = hostRef.$cmpMeta$;
2063
+ const endConnected = createTime('connectedCallback', cmpMeta.$tagName$);
2064
+ if (!(hostRef.$flags$ & 1 /* HOST_FLAGS.hasConnected */)) {
2065
+ // first time this component has connected
2066
+ hostRef.$flags$ |= 1 /* HOST_FLAGS.hasConnected */;
2067
+ {
2068
+ // initUpdate
2069
+ // if the slot polyfill is required we'll need to put some nodes
2070
+ // in here to act as original content anchors as we move nodes around
2071
+ // host element has been connected to the DOM
2072
+ if ((// TODO(STENCIL-854): Remove code related to legacy shadowDomShim field
2073
+ cmpMeta.$flags$ & (4 /* CMP_FLAGS.hasSlotRelocation */ | 8 /* CMP_FLAGS.needsShadowDomShim */))) {
2074
+ setContentReference(elm);
2075
+ }
2076
+ }
2077
+ // Lazy properties
2078
+ // https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties
2079
+ if (cmpMeta.$members$) {
2080
+ Object.entries(cmpMeta.$members$).map(([memberName, [memberFlags]]) => {
2081
+ if (memberFlags & 31 /* MEMBER_FLAGS.Prop */ && elm.hasOwnProperty(memberName)) {
2082
+ const value = elm[memberName];
2083
+ delete elm[memberName];
2084
+ elm[memberName] = value;
2085
+ }
2086
+ });
2087
+ }
2088
+ {
2089
+ initializeComponent(elm, hostRef, cmpMeta);
2090
+ }
2091
+ }
2092
+ else {
2093
+ // not the first time this has connected
2094
+ // reattach any event listeners to the host
2095
+ // since they would have been removed when disconnected
2096
+ addHostEventListeners(elm, hostRef, cmpMeta.$listeners$);
2097
+ // fire off connectedCallback() on component instance
2098
+ if (hostRef === null || hostRef === void 0 ? void 0 : hostRef.$lazyInstance$) {
2099
+ fireConnectedCallback(hostRef.$lazyInstance$);
2100
+ }
2101
+ else if (hostRef === null || hostRef === void 0 ? void 0 : hostRef.$onReadyPromise$) {
2102
+ hostRef.$onReadyPromise$.then(() => fireConnectedCallback(hostRef.$lazyInstance$));
2103
+ }
2104
+ }
2105
+ endConnected();
2106
+ }
2107
+ };
2108
+ const setContentReference = (elm) => {
2109
+ // only required when we're NOT using native shadow dom (slot)
2110
+ // or this browser doesn't support native shadow dom
2111
+ // and this host element was NOT created with SSR
2112
+ // let's pick out the inner content for slot projection
2113
+ // create a node to represent where the original
2114
+ // content was first placed, which is useful later on
2115
+ const contentRefElm = (elm['s-cr'] = doc$1.createComment(''));
2116
+ contentRefElm['s-cn'] = true;
2117
+ elm.insertBefore(contentRefElm, elm.firstChild);
2118
+ };
2119
+ const disconnectedCallback = async (elm) => {
2120
+ if ((plt.$flags$ & 1 /* PLATFORM_FLAGS.isTmpDisconnected */) === 0) {
2121
+ const hostRef = getHostRef(elm);
2122
+ {
2123
+ if (hostRef.$rmListeners$) {
2124
+ hostRef.$rmListeners$.map((rmListener) => rmListener());
2125
+ hostRef.$rmListeners$ = undefined;
2126
+ }
2127
+ }
2128
+ }
2129
+ };
2130
+ const proxyCustomElement = (Cstr, compactMeta) => {
2131
+ const cmpMeta = {
2132
+ $flags$: compactMeta[0],
2133
+ $tagName$: compactMeta[1],
2134
+ };
2135
+ {
2136
+ cmpMeta.$members$ = compactMeta[2];
2137
+ }
2138
+ {
2139
+ cmpMeta.$listeners$ = compactMeta[3];
2140
+ }
2141
+ {
2142
+ cmpMeta.$watchers$ = Cstr.$watchers$;
2143
+ }
2144
+ {
2145
+ cmpMeta.$attrsToReflect$ = [];
2146
+ }
2147
+ const originalConnectedCallback = Cstr.prototype.connectedCallback;
2148
+ const originalDisconnectedCallback = Cstr.prototype.disconnectedCallback;
2149
+ Object.assign(Cstr.prototype, {
2150
+ __registerHost() {
2151
+ registerHost(this, cmpMeta);
2152
+ },
2153
+ connectedCallback() {
2154
+ connectedCallback(this);
2155
+ if (originalConnectedCallback) {
2156
+ originalConnectedCallback.call(this);
2157
+ }
2158
+ },
2159
+ disconnectedCallback() {
2160
+ disconnectedCallback(this);
2161
+ if (originalDisconnectedCallback) {
2162
+ originalDisconnectedCallback.call(this);
2163
+ }
2164
+ },
2165
+ __attachShadow() {
2166
+ {
2167
+ {
2168
+ this.attachShadow({
2169
+ mode: 'open',
2170
+ delegatesFocus: !!(cmpMeta.$flags$ & 16 /* CMP_FLAGS.shadowDelegatesFocus */),
2171
+ });
2172
+ }
2173
+ }
2174
+ },
2175
+ });
2176
+ Cstr.is = cmpMeta.$tagName$;
2177
+ return proxyComponent(Cstr, cmpMeta);
2178
+ };
2179
+ const addHostEventListeners = (elm, hostRef, listeners, attachParentListeners) => {
2180
+ if (listeners) {
2181
+ listeners.map(([flags, name, method]) => {
2182
+ const target = getHostListenerTarget(elm, flags) ;
2183
+ const handler = hostListenerProxy(hostRef, method);
2184
+ const opts = hostListenerOpts(flags);
2185
+ plt.ael(target, name, handler, opts);
2186
+ (hostRef.$rmListeners$ = hostRef.$rmListeners$ || []).push(() => plt.rel(target, name, handler, opts));
2187
+ });
2188
+ }
2189
+ };
2190
+ const hostListenerProxy = (hostRef, methodName) => (ev) => {
2191
+ try {
2192
+ if (BUILD.lazyLoad) ;
2193
+ else {
2194
+ hostRef.$hostElement$[methodName](ev);
2195
+ }
2196
+ }
2197
+ catch (e) {
2198
+ consoleError(e);
2199
+ }
2200
+ };
2201
+ const getHostListenerTarget = (elm, flags) => {
2202
+ if (flags & 4 /* LISTENER_FLAGS.TargetDocument */)
2203
+ return doc$1;
2204
+ if (flags & 8 /* LISTENER_FLAGS.TargetWindow */)
2205
+ return win;
2206
+ if (flags & 16 /* LISTENER_FLAGS.TargetBody */)
2207
+ return doc$1.body;
2208
+ return elm;
2209
+ };
2210
+ // prettier-ignore
2211
+ const hostListenerOpts = (flags) => supportsListenerOptions
2212
+ ? ({
2213
+ passive: (flags & 1 /* LISTENER_FLAGS.Passive */) !== 0,
2214
+ capture: (flags & 2 /* LISTENER_FLAGS.Capture */) !== 0,
2215
+ })
2216
+ : (flags & 2 /* LISTENER_FLAGS.Capture */) !== 0;
2217
+ /**
2218
+ * A WeakMap mapping runtime component references to their corresponding host reference
2219
+ * instances.
2220
+ */
2221
+ const hostRefs = /*@__PURE__*/ new WeakMap();
2222
+ /**
2223
+ * Given a {@link d.RuntimeRef} retrieve the corresponding {@link d.HostRef}
2224
+ *
2225
+ * @param ref the runtime ref of interest
2226
+ * @returns the Host reference (if found) or undefined
2227
+ */
2228
+ const getHostRef = (ref) => hostRefs.get(ref);
2229
+ /**
2230
+ * Register a host element for a Stencil component, setting up various metadata
2231
+ * and callbacks based on {@link BUILD} flags as well as the component's runtime
2232
+ * metadata.
2233
+ *
2234
+ * @param hostElement the host element to register
2235
+ * @param cmpMeta runtime metadata for that component
2236
+ * @returns a reference to the host ref WeakMap
2237
+ */
2238
+ const registerHost = (hostElement, cmpMeta) => {
2239
+ const hostRef = {
2240
+ $flags$: 0,
2241
+ $hostElement$: hostElement,
2242
+ $cmpMeta$: cmpMeta,
2243
+ $instanceValues$: new Map(),
2244
+ };
2245
+ addHostEventListeners(hostElement, hostRef, cmpMeta.$listeners$);
2246
+ return hostRefs.set(hostElement, hostRef);
2247
+ };
2248
+ const isMemberInElement = (elm, memberName) => memberName in elm;
2249
+ const consoleError = (e, el) => (0, console.error)(e, el);
2250
+ const styles = /*@__PURE__*/ new Map();
2251
+ const modeResolutionChain = [];
2252
+ const win = typeof window !== 'undefined' ? window : {};
2253
+ const doc$1 = win.document || { head: {} };
2254
+ const H = (win.HTMLElement || class {
2255
+ });
2256
+ const plt = {
2257
+ $flags$: 0,
2258
+ $resourcesUrl$: '',
2259
+ jmp: (h) => h(),
2260
+ raf: (h) => requestAnimationFrame(h),
2261
+ ael: (el, eventName, listener, opts) => el.addEventListener(eventName, listener, opts),
2262
+ rel: (el, eventName, listener, opts) => el.removeEventListener(eventName, listener, opts),
2263
+ ce: (eventName, opts) => new CustomEvent(eventName, opts),
2264
+ };
2265
+ const supportsListenerOptions = /*@__PURE__*/ (() => {
2266
+ let supportsListenerOptions = false;
2267
+ try {
2268
+ doc$1.addEventListener('e', null, Object.defineProperty({}, 'passive', {
2269
+ get() {
2270
+ supportsListenerOptions = true;
2271
+ },
2272
+ }));
2273
+ }
2274
+ catch (e) { }
2275
+ return supportsListenerOptions;
2276
+ })();
2277
+ const promiseResolve = (v) => Promise.resolve(v);
2278
+ const supportsConstructableStylesheets = /*@__PURE__*/ (() => {
2279
+ try {
2280
+ new CSSStyleSheet();
2281
+ return typeof new CSSStyleSheet().replaceSync === 'function';
2282
+ }
2283
+ catch (e) { }
2284
+ return false;
2285
+ })()
2286
+ ;
2287
+ const queueDomReads = [];
2288
+ const queueDomWrites = [];
2289
+ const queueTask = (queue, write) => (cb) => {
2290
+ queue.push(cb);
2291
+ if (!queuePending) {
2292
+ queuePending = true;
2293
+ if (write && plt.$flags$ & 4 /* PLATFORM_FLAGS.queueSync */) {
2294
+ nextTick(flush);
2295
+ }
2296
+ else {
2297
+ plt.raf(flush);
2298
+ }
2299
+ }
2300
+ };
2301
+ const consume = (queue) => {
2302
+ for (let i = 0; i < queue.length; i++) {
2303
+ try {
2304
+ queue[i](performance.now());
2305
+ }
2306
+ catch (e) {
2307
+ consoleError(e);
2308
+ }
2309
+ }
2310
+ queue.length = 0;
2311
+ };
2312
+ const flush = () => {
2313
+ // always force a bunch of medium callbacks to run, but still have
2314
+ // a throttle on how many can run in a certain time
2315
+ // DOM READS!!!
2316
+ consume(queueDomReads);
2317
+ // DOM WRITES!!!
2318
+ {
2319
+ consume(queueDomWrites);
2320
+ if ((queuePending = queueDomReads.length > 0)) {
2321
+ // still more to do yet, but we've run out of time
2322
+ // let's let this thing cool off and try again in the next tick
2323
+ plt.raf(flush);
2324
+ }
2325
+ }
2326
+ };
2327
+ const nextTick = (cb) => promiseResolve().then(cb);
2328
+ const writeTask = /*@__PURE__*/ queueTask(queueDomWrites, true);
2329
+
2330
+ const filePreviewCss = ":host{display:block;font-size:13px}img,video{max-width:100%;margin-top:10px}";
2331
+
2332
+ const FilePreview$1 = /*@__PURE__*/ proxyCustomElement(class FilePreview extends H {
2333
+ constructor() {
2334
+ super();
2335
+ this.__registerHost();
2336
+ this.__attachShadow();
2337
+ this.src = undefined;
2338
+ this.filetype = undefined;
2339
+ }
2340
+ render() {
2341
+ return (h(Host, { class: this.computeClass() }, this.isImage() && h("img", { src: this.src }), this.isVideo() && h("video", { src: this.src, onClick: toggle }), this.isOther() && "This file does not offer a preview", h("slot", null)));
2342
+ }
2343
+ computeClass() {
2344
+ if (this.isImage())
2345
+ return "image";
2346
+ if (this.isVideo())
2347
+ return "video";
2348
+ return "other";
2349
+ }
2350
+ isImage() {
2351
+ return this.filetype == "image";
2352
+ }
2353
+ isVideo() {
2354
+ return this.filetype == "video";
2355
+ }
2356
+ isOther() {
2357
+ return !this.isImage() && !this.isVideo();
2358
+ }
2359
+ static get style() { return filePreviewCss; }
2360
+ }, [1, "file-preview", {
2361
+ "src": [513],
2362
+ "filetype": [513]
2363
+ }]);
2364
+ const toggle = function () { this.paused ? this.play() : this.pause(); return false; };
2365
+
2366
+ const progressBarCss = ":host{display:block;position:relative;padding:0 20px;border:1px solid rgba(0, 0, 0, 0.3);border-radius:3px;line-height:2;flex:1 0;box-sizing:border-box;text-align:left;font-size:13px}.bar{position:absolute;top:0;left:0;bottom:0;background:rgba(57, 137, 39, 1);transition:width 120ms ease-out, opacity 60ms 60ms ease-in;transform:translate3d(0, 0, 0)}.content{position:relative;color:#fff;font-size:1em}";
2367
+
2368
+ const ProgressBar$1 = /*@__PURE__*/ proxyCustomElement(class ProgressBar extends H {
2369
+ constructor() {
2370
+ super();
2371
+ this.__registerHost();
2372
+ this.__attachShadow();
2373
+ this.percent = 0;
2374
+ }
2375
+ render() {
2376
+ return (h(Host, null, h("div", { class: "bar", style: { width: `${this.percent}%` } }), h("span", { class: "content" }, h("slot", null))));
2377
+ }
2378
+ static get style() { return progressBarCss; }
2379
+ }, [1, "progress-bar", {
2380
+ "percent": [514]
2381
+ }]);
2382
+
2383
+ var sparkMd5 = {
2384
+ exports: {}
2385
+ };
2386
+
2387
+ (function(module, exports) {
2388
+ (function(factory) {
2389
+ {
2390
+ module.exports = factory();
2391
+ }
2392
+ })((function(undefined$1) {
2393
+ var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ];
2394
+ function md5cycle(x, k) {
2395
+ var a = x[0], b = x[1], c = x[2], d = x[3];
2396
+ a += (b & c | ~b & d) + k[0] - 680876936 | 0;
2397
+ a = (a << 7 | a >>> 25) + b | 0;
2398
+ d += (a & b | ~a & c) + k[1] - 389564586 | 0;
2399
+ d = (d << 12 | d >>> 20) + a | 0;
2400
+ c += (d & a | ~d & b) + k[2] + 606105819 | 0;
2401
+ c = (c << 17 | c >>> 15) + d | 0;
2402
+ b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
2403
+ b = (b << 22 | b >>> 10) + c | 0;
2404
+ a += (b & c | ~b & d) + k[4] - 176418897 | 0;
2405
+ a = (a << 7 | a >>> 25) + b | 0;
2406
+ d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
2407
+ d = (d << 12 | d >>> 20) + a | 0;
2408
+ c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
2409
+ c = (c << 17 | c >>> 15) + d | 0;
2410
+ b += (c & d | ~c & a) + k[7] - 45705983 | 0;
2411
+ b = (b << 22 | b >>> 10) + c | 0;
2412
+ a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
2413
+ a = (a << 7 | a >>> 25) + b | 0;
2414
+ d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
2415
+ d = (d << 12 | d >>> 20) + a | 0;
2416
+ c += (d & a | ~d & b) + k[10] - 42063 | 0;
2417
+ c = (c << 17 | c >>> 15) + d | 0;
2418
+ b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
2419
+ b = (b << 22 | b >>> 10) + c | 0;
2420
+ a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
2421
+ a = (a << 7 | a >>> 25) + b | 0;
2422
+ d += (a & b | ~a & c) + k[13] - 40341101 | 0;
2423
+ d = (d << 12 | d >>> 20) + a | 0;
2424
+ c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
2425
+ c = (c << 17 | c >>> 15) + d | 0;
2426
+ b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
2427
+ b = (b << 22 | b >>> 10) + c | 0;
2428
+ a += (b & d | c & ~d) + k[1] - 165796510 | 0;
2429
+ a = (a << 5 | a >>> 27) + b | 0;
2430
+ d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
2431
+ d = (d << 9 | d >>> 23) + a | 0;
2432
+ c += (d & b | a & ~b) + k[11] + 643717713 | 0;
2433
+ c = (c << 14 | c >>> 18) + d | 0;
2434
+ b += (c & a | d & ~a) + k[0] - 373897302 | 0;
2435
+ b = (b << 20 | b >>> 12) + c | 0;
2436
+ a += (b & d | c & ~d) + k[5] - 701558691 | 0;
2437
+ a = (a << 5 | a >>> 27) + b | 0;
2438
+ d += (a & c | b & ~c) + k[10] + 38016083 | 0;
2439
+ d = (d << 9 | d >>> 23) + a | 0;
2440
+ c += (d & b | a & ~b) + k[15] - 660478335 | 0;
2441
+ c = (c << 14 | c >>> 18) + d | 0;
2442
+ b += (c & a | d & ~a) + k[4] - 405537848 | 0;
2443
+ b = (b << 20 | b >>> 12) + c | 0;
2444
+ a += (b & d | c & ~d) + k[9] + 568446438 | 0;
2445
+ a = (a << 5 | a >>> 27) + b | 0;
2446
+ d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
2447
+ d = (d << 9 | d >>> 23) + a | 0;
2448
+ c += (d & b | a & ~b) + k[3] - 187363961 | 0;
2449
+ c = (c << 14 | c >>> 18) + d | 0;
2450
+ b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
2451
+ b = (b << 20 | b >>> 12) + c | 0;
2452
+ a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
2453
+ a = (a << 5 | a >>> 27) + b | 0;
2454
+ d += (a & c | b & ~c) + k[2] - 51403784 | 0;
2455
+ d = (d << 9 | d >>> 23) + a | 0;
2456
+ c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
2457
+ c = (c << 14 | c >>> 18) + d | 0;
2458
+ b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
2459
+ b = (b << 20 | b >>> 12) + c | 0;
2460
+ a += (b ^ c ^ d) + k[5] - 378558 | 0;
2461
+ a = (a << 4 | a >>> 28) + b | 0;
2462
+ d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
2463
+ d = (d << 11 | d >>> 21) + a | 0;
2464
+ c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
2465
+ c = (c << 16 | c >>> 16) + d | 0;
2466
+ b += (c ^ d ^ a) + k[14] - 35309556 | 0;
2467
+ b = (b << 23 | b >>> 9) + c | 0;
2468
+ a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
2469
+ a = (a << 4 | a >>> 28) + b | 0;
2470
+ d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
2471
+ d = (d << 11 | d >>> 21) + a | 0;
2472
+ c += (d ^ a ^ b) + k[7] - 155497632 | 0;
2473
+ c = (c << 16 | c >>> 16) + d | 0;
2474
+ b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
2475
+ b = (b << 23 | b >>> 9) + c | 0;
2476
+ a += (b ^ c ^ d) + k[13] + 681279174 | 0;
2477
+ a = (a << 4 | a >>> 28) + b | 0;
2478
+ d += (a ^ b ^ c) + k[0] - 358537222 | 0;
2479
+ d = (d << 11 | d >>> 21) + a | 0;
2480
+ c += (d ^ a ^ b) + k[3] - 722521979 | 0;
2481
+ c = (c << 16 | c >>> 16) + d | 0;
2482
+ b += (c ^ d ^ a) + k[6] + 76029189 | 0;
2483
+ b = (b << 23 | b >>> 9) + c | 0;
2484
+ a += (b ^ c ^ d) + k[9] - 640364487 | 0;
2485
+ a = (a << 4 | a >>> 28) + b | 0;
2486
+ d += (a ^ b ^ c) + k[12] - 421815835 | 0;
2487
+ d = (d << 11 | d >>> 21) + a | 0;
2488
+ c += (d ^ a ^ b) + k[15] + 530742520 | 0;
2489
+ c = (c << 16 | c >>> 16) + d | 0;
2490
+ b += (c ^ d ^ a) + k[2] - 995338651 | 0;
2491
+ b = (b << 23 | b >>> 9) + c | 0;
2492
+ a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
2493
+ a = (a << 6 | a >>> 26) + b | 0;
2494
+ d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
2495
+ d = (d << 10 | d >>> 22) + a | 0;
2496
+ c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
2497
+ c = (c << 15 | c >>> 17) + d | 0;
2498
+ b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
2499
+ b = (b << 21 | b >>> 11) + c | 0;
2500
+ a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
2501
+ a = (a << 6 | a >>> 26) + b | 0;
2502
+ d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
2503
+ d = (d << 10 | d >>> 22) + a | 0;
2504
+ c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
2505
+ c = (c << 15 | c >>> 17) + d | 0;
2506
+ b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
2507
+ b = (b << 21 | b >>> 11) + c | 0;
2508
+ a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
2509
+ a = (a << 6 | a >>> 26) + b | 0;
2510
+ d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
2511
+ d = (d << 10 | d >>> 22) + a | 0;
2512
+ c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
2513
+ c = (c << 15 | c >>> 17) + d | 0;
2514
+ b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
2515
+ b = (b << 21 | b >>> 11) + c | 0;
2516
+ a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
2517
+ a = (a << 6 | a >>> 26) + b | 0;
2518
+ d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
2519
+ d = (d << 10 | d >>> 22) + a | 0;
2520
+ c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
2521
+ c = (c << 15 | c >>> 17) + d | 0;
2522
+ b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
2523
+ b = (b << 21 | b >>> 11) + c | 0;
2524
+ x[0] = a + x[0] | 0;
2525
+ x[1] = b + x[1] | 0;
2526
+ x[2] = c + x[2] | 0;
2527
+ x[3] = d + x[3] | 0;
2528
+ }
2529
+ function md5blk(s) {
2530
+ var md5blks = [], i;
2531
+ for (i = 0; i < 64; i += 4) {
2532
+ md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
2533
+ }
2534
+ return md5blks;
2535
+ }
2536
+ function md5blk_array(a) {
2537
+ var md5blks = [], i;
2538
+ for (i = 0; i < 64; i += 4) {
2539
+ md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
2540
+ }
2541
+ return md5blks;
2542
+ }
2543
+ function md51(s) {
2544
+ var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
2545
+ for (i = 64; i <= n; i += 64) {
2546
+ md5cycle(state, md5blk(s.substring(i - 64, i)));
2547
+ }
2548
+ s = s.substring(i - 64);
2549
+ length = s.length;
2550
+ tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
2551
+ for (i = 0; i < length; i += 1) {
2552
+ tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
2553
+ }
2554
+ tail[i >> 2] |= 128 << (i % 4 << 3);
2555
+ if (i > 55) {
2556
+ md5cycle(state, tail);
2557
+ for (i = 0; i < 16; i += 1) {
2558
+ tail[i] = 0;
2559
+ }
2560
+ }
2561
+ tmp = n * 8;
2562
+ tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
2563
+ lo = parseInt(tmp[2], 16);
2564
+ hi = parseInt(tmp[1], 16) || 0;
2565
+ tail[14] = lo;
2566
+ tail[15] = hi;
2567
+ md5cycle(state, tail);
2568
+ return state;
2569
+ }
2570
+ function md51_array(a) {
2571
+ var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
2572
+ for (i = 64; i <= n; i += 64) {
2573
+ md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
2574
+ }
2575
+ a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0);
2576
+ length = a.length;
2577
+ tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
2578
+ for (i = 0; i < length; i += 1) {
2579
+ tail[i >> 2] |= a[i] << (i % 4 << 3);
2580
+ }
2581
+ tail[i >> 2] |= 128 << (i % 4 << 3);
2582
+ if (i > 55) {
2583
+ md5cycle(state, tail);
2584
+ for (i = 0; i < 16; i += 1) {
2585
+ tail[i] = 0;
2586
+ }
2587
+ }
2588
+ tmp = n * 8;
2589
+ tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
2590
+ lo = parseInt(tmp[2], 16);
2591
+ hi = parseInt(tmp[1], 16) || 0;
2592
+ tail[14] = lo;
2593
+ tail[15] = hi;
2594
+ md5cycle(state, tail);
2595
+ return state;
2596
+ }
2597
+ function rhex(n) {
2598
+ var s = "", j;
2599
+ for (j = 0; j < 4; j += 1) {
2600
+ s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];
2601
+ }
2602
+ return s;
2603
+ }
2604
+ function hex(x) {
2605
+ var i;
2606
+ for (i = 0; i < x.length; i += 1) {
2607
+ x[i] = rhex(x[i]);
2608
+ }
2609
+ return x.join("");
2610
+ }
2611
+ if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ;
2612
+ if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) {
2613
+ (function() {
2614
+ function clamp(val, length) {
2615
+ val = val | 0 || 0;
2616
+ if (val < 0) {
2617
+ return Math.max(val + length, 0);
2618
+ }
2619
+ return Math.min(val, length);
2620
+ }
2621
+ ArrayBuffer.prototype.slice = function(from, to) {
2622
+ var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray;
2623
+ if (to !== undefined$1) {
2624
+ end = clamp(to, length);
2625
+ }
2626
+ if (begin > end) {
2627
+ return new ArrayBuffer(0);
2628
+ }
2629
+ num = end - begin;
2630
+ target = new ArrayBuffer(num);
2631
+ targetArray = new Uint8Array(target);
2632
+ sourceArray = new Uint8Array(this, begin, num);
2633
+ targetArray.set(sourceArray);
2634
+ return target;
2635
+ };
2636
+ })();
2637
+ }
2638
+ function toUtf8(str) {
2639
+ if (/[\u0080-\uFFFF]/.test(str)) {
2640
+ str = unescape(encodeURIComponent(str));
2641
+ }
2642
+ return str;
2643
+ }
2644
+ function utf8Str2ArrayBuffer(str, returnUInt8Array) {
2645
+ var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i;
2646
+ for (i = 0; i < length; i += 1) {
2647
+ arr[i] = str.charCodeAt(i);
2648
+ }
2649
+ return returnUInt8Array ? arr : buff;
2650
+ }
2651
+ function arrayBuffer2Utf8Str(buff) {
2652
+ return String.fromCharCode.apply(null, new Uint8Array(buff));
2653
+ }
2654
+ function concatenateArrayBuffers(first, second, returnUInt8Array) {
2655
+ var result = new Uint8Array(first.byteLength + second.byteLength);
2656
+ result.set(new Uint8Array(first));
2657
+ result.set(new Uint8Array(second), first.byteLength);
2658
+ return returnUInt8Array ? result : result.buffer;
2659
+ }
2660
+ function hexToBinaryString(hex) {
2661
+ var bytes = [], length = hex.length, x;
2662
+ for (x = 0; x < length - 1; x += 2) {
2663
+ bytes.push(parseInt(hex.substr(x, 2), 16));
2664
+ }
2665
+ return String.fromCharCode.apply(String, bytes);
2666
+ }
2667
+ function SparkMD5() {
2668
+ this.reset();
2669
+ }
2670
+ SparkMD5.prototype.append = function(str) {
2671
+ this.appendBinary(toUtf8(str));
2672
+ return this;
2673
+ };
2674
+ SparkMD5.prototype.appendBinary = function(contents) {
2675
+ this._buff += contents;
2676
+ this._length += contents.length;
2677
+ var length = this._buff.length, i;
2678
+ for (i = 64; i <= length; i += 64) {
2679
+ md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
2680
+ }
2681
+ this._buff = this._buff.substring(i - 64);
2682
+ return this;
2683
+ };
2684
+ SparkMD5.prototype.end = function(raw) {
2685
+ var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret;
2686
+ for (i = 0; i < length; i += 1) {
2687
+ tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3);
2688
+ }
2689
+ this._finish(tail, length);
2690
+ ret = hex(this._hash);
2691
+ if (raw) {
2692
+ ret = hexToBinaryString(ret);
2693
+ }
2694
+ this.reset();
2695
+ return ret;
2696
+ };
2697
+ SparkMD5.prototype.reset = function() {
2698
+ this._buff = "";
2699
+ this._length = 0;
2700
+ this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
2701
+ return this;
2702
+ };
2703
+ SparkMD5.prototype.getState = function() {
2704
+ return {
2705
+ buff: this._buff,
2706
+ length: this._length,
2707
+ hash: this._hash.slice()
2708
+ };
2709
+ };
2710
+ SparkMD5.prototype.setState = function(state) {
2711
+ this._buff = state.buff;
2712
+ this._length = state.length;
2713
+ this._hash = state.hash;
2714
+ return this;
2715
+ };
2716
+ SparkMD5.prototype.destroy = function() {
2717
+ delete this._hash;
2718
+ delete this._buff;
2719
+ delete this._length;
2720
+ };
2721
+ SparkMD5.prototype._finish = function(tail, length) {
2722
+ var i = length, tmp, lo, hi;
2723
+ tail[i >> 2] |= 128 << (i % 4 << 3);
2724
+ if (i > 55) {
2725
+ md5cycle(this._hash, tail);
2726
+ for (i = 0; i < 16; i += 1) {
2727
+ tail[i] = 0;
2728
+ }
2729
+ }
2730
+ tmp = this._length * 8;
2731
+ tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
2732
+ lo = parseInt(tmp[2], 16);
2733
+ hi = parseInt(tmp[1], 16) || 0;
2734
+ tail[14] = lo;
2735
+ tail[15] = hi;
2736
+ md5cycle(this._hash, tail);
2737
+ };
2738
+ SparkMD5.hash = function(str, raw) {
2739
+ return SparkMD5.hashBinary(toUtf8(str), raw);
2740
+ };
2741
+ SparkMD5.hashBinary = function(content, raw) {
2742
+ var hash = md51(content), ret = hex(hash);
2743
+ return raw ? hexToBinaryString(ret) : ret;
2744
+ };
2745
+ SparkMD5.ArrayBuffer = function() {
2746
+ this.reset();
2747
+ };
2748
+ SparkMD5.ArrayBuffer.prototype.append = function(arr) {
2749
+ var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i;
2750
+ this._length += arr.byteLength;
2751
+ for (i = 64; i <= length; i += 64) {
2752
+ md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
2753
+ }
2754
+ this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
2755
+ return this;
2756
+ };
2757
+ SparkMD5.ArrayBuffer.prototype.end = function(raw) {
2758
+ var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret;
2759
+ for (i = 0; i < length; i += 1) {
2760
+ tail[i >> 2] |= buff[i] << (i % 4 << 3);
2761
+ }
2762
+ this._finish(tail, length);
2763
+ ret = hex(this._hash);
2764
+ if (raw) {
2765
+ ret = hexToBinaryString(ret);
2766
+ }
2767
+ this.reset();
2768
+ return ret;
2769
+ };
2770
+ SparkMD5.ArrayBuffer.prototype.reset = function() {
2771
+ this._buff = new Uint8Array(0);
2772
+ this._length = 0;
2773
+ this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
2774
+ return this;
2775
+ };
2776
+ SparkMD5.ArrayBuffer.prototype.getState = function() {
2777
+ var state = SparkMD5.prototype.getState.call(this);
2778
+ state.buff = arrayBuffer2Utf8Str(state.buff);
2779
+ return state;
2780
+ };
2781
+ SparkMD5.ArrayBuffer.prototype.setState = function(state) {
2782
+ state.buff = utf8Str2ArrayBuffer(state.buff, true);
2783
+ return SparkMD5.prototype.setState.call(this, state);
2784
+ };
2785
+ SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
2786
+ SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
2787
+ SparkMD5.ArrayBuffer.hash = function(arr, raw) {
2788
+ var hash = md51_array(new Uint8Array(arr)), ret = hex(hash);
2789
+ return raw ? hexToBinaryString(ret) : ret;
2790
+ };
2791
+ return SparkMD5;
2792
+ }));
2793
+ })(sparkMd5);
2794
+
2795
+ var SparkMD5 = sparkMd5.exports;
2796
+
2797
+ const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
2798
+
2799
+ class FileChecksum {
2800
+ static create(file, callback) {
2801
+ const instance = new FileChecksum(file);
2802
+ instance.create(callback);
2803
+ }
2804
+ constructor(file) {
2805
+ this.file = file;
2806
+ this.chunkSize = 2097152;
2807
+ this.chunkCount = Math.ceil(this.file.size / this.chunkSize);
2808
+ this.chunkIndex = 0;
2809
+ }
2810
+ create(callback) {
2811
+ this.callback = callback;
2812
+ this.md5Buffer = new SparkMD5.ArrayBuffer;
2813
+ this.fileReader = new FileReader;
2814
+ this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event)));
2815
+ this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event)));
2816
+ this.readNextChunk();
2817
+ }
2818
+ fileReaderDidLoad(event) {
2819
+ this.md5Buffer.append(event.target.result);
2820
+ if (!this.readNextChunk()) {
2821
+ const binaryDigest = this.md5Buffer.end(true);
2822
+ const base64digest = btoa(binaryDigest);
2823
+ this.callback(null, base64digest);
2824
+ }
2825
+ }
2826
+ fileReaderDidError(event) {
2827
+ this.callback(`Error reading ${this.file.name}`);
2828
+ }
2829
+ readNextChunk() {
2830
+ if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) {
2831
+ const start = this.chunkIndex * this.chunkSize;
2832
+ const end = Math.min(start + this.chunkSize, this.file.size);
2833
+ const bytes = fileSlice.call(this.file, start, end);
2834
+ this.fileReader.readAsArrayBuffer(bytes);
2835
+ this.chunkIndex++;
2836
+ return true;
2837
+ } else {
2838
+ return false;
2839
+ }
2840
+ }
2841
+ }
2842
+
2843
+ function getMetaValue(name) {
2844
+ const element = findElement(document.head, `meta[name="${name}"]`);
2845
+ if (element) {
2846
+ return element.getAttribute("content");
2847
+ }
2848
+ }
2849
+
2850
+ function findElements(root, selector) {
2851
+ if (typeof root == "string") {
2852
+ selector = root;
2853
+ root = document;
2854
+ }
2855
+ const elements = root.querySelectorAll(selector);
2856
+ return toArray(elements);
2857
+ }
2858
+
2859
+ function findElement(root, selector) {
2860
+ if (typeof root == "string") {
2861
+ selector = root;
2862
+ root = document;
2863
+ }
2864
+ return root.querySelector(selector);
2865
+ }
2866
+
2867
+ function dispatchEvent$1(element, type, eventInit = {}) {
2868
+ const {disabled: disabled} = element;
2869
+ const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit;
2870
+ const event = document.createEvent("Event");
2871
+ event.initEvent(type, bubbles || true, cancelable || true);
2872
+ event.detail = detail || {};
2873
+ try {
2874
+ element.disabled = false;
2875
+ element.dispatchEvent(event);
2876
+ } finally {
2877
+ element.disabled = disabled;
2878
+ }
2879
+ return event;
2880
+ }
2881
+
2882
+ function toArray(value) {
2883
+ if (Array.isArray(value)) {
2884
+ return value;
2885
+ } else if (Array.from) {
2886
+ return Array.from(value);
2887
+ } else {
2888
+ return [].slice.call(value);
2889
+ }
2890
+ }
2891
+
2892
+ class BlobRecord {
2893
+ constructor(file, checksum, url, customHeaders = {}) {
2894
+ this.file = file;
2895
+ this.attributes = {
2896
+ filename: file.name,
2897
+ content_type: file.type || "application/octet-stream",
2898
+ byte_size: file.size,
2899
+ checksum: checksum
2900
+ };
2901
+ this.xhr = new XMLHttpRequest;
2902
+ this.xhr.open("POST", url, true);
2903
+ this.xhr.responseType = "json";
2904
+ this.xhr.setRequestHeader("Content-Type", "application/json");
2905
+ this.xhr.setRequestHeader("Accept", "application/json");
2906
+ this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
2907
+ Object.keys(customHeaders).forEach((headerKey => {
2908
+ this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
2909
+ }));
2910
+ const csrfToken = getMetaValue("csrf-token");
2911
+ if (csrfToken != undefined) {
2912
+ this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
2913
+ }
2914
+ this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
2915
+ this.xhr.addEventListener("error", (event => this.requestDidError(event)));
2916
+ }
2917
+ get status() {
2918
+ return this.xhr.status;
2919
+ }
2920
+ get response() {
2921
+ const {responseType: responseType, response: response} = this.xhr;
2922
+ if (responseType == "json") {
2923
+ return response;
2924
+ } else {
2925
+ return JSON.parse(response);
2926
+ }
2927
+ }
2928
+ create(callback) {
2929
+ this.callback = callback;
2930
+ this.xhr.send(JSON.stringify({
2931
+ blob: this.attributes
2932
+ }));
2933
+ }
2934
+ requestDidLoad(event) {
2935
+ if (this.status >= 200 && this.status < 300) {
2936
+ const {response: response} = this;
2937
+ const {direct_upload: direct_upload} = response;
2938
+ delete response.direct_upload;
2939
+ this.attributes = response;
2940
+ this.directUploadData = direct_upload;
2941
+ this.callback(null, this.toJSON());
2942
+ } else {
2943
+ this.requestDidError(event);
2944
+ }
2945
+ }
2946
+ requestDidError(event) {
2947
+ this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`);
2948
+ }
2949
+ toJSON() {
2950
+ const result = {};
2951
+ for (const key in this.attributes) {
2952
+ result[key] = this.attributes[key];
2953
+ }
2954
+ return result;
2955
+ }
2956
+ }
2957
+
2958
+ class BlobUpload {
2959
+ constructor(blob) {
2960
+ this.blob = blob;
2961
+ this.file = blob.file;
2962
+ const {url: url, headers: headers} = blob.directUploadData;
2963
+ this.xhr = new XMLHttpRequest;
2964
+ this.xhr.open("PUT", url, true);
2965
+ this.xhr.responseType = "text";
2966
+ for (const key in headers) {
2967
+ this.xhr.setRequestHeader(key, headers[key]);
2968
+ }
2969
+ this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
2970
+ this.xhr.addEventListener("error", (event => this.requestDidError(event)));
2971
+ }
2972
+ create(callback) {
2973
+ this.callback = callback;
2974
+ this.xhr.send(this.file.slice());
2975
+ }
2976
+ requestDidLoad(event) {
2977
+ const {status: status, response: response} = this.xhr;
2978
+ if (status >= 200 && status < 300) {
2979
+ this.callback(null, response);
2980
+ } else {
2981
+ this.requestDidError(event);
2982
+ }
2983
+ }
2984
+ requestDidError(event) {
2985
+ this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`);
2986
+ }
2987
+ }
2988
+
2989
+ let id = 0;
2990
+
2991
+ class DirectUpload {
2992
+ constructor(file, url, delegate, customHeaders = {}) {
2993
+ this.id = ++id;
2994
+ this.file = file;
2995
+ this.url = url;
2996
+ this.delegate = delegate;
2997
+ this.customHeaders = customHeaders;
2998
+ }
2999
+ create(callback) {
3000
+ FileChecksum.create(this.file, ((error, checksum) => {
3001
+ if (error) {
3002
+ callback(error);
3003
+ return;
3004
+ }
3005
+ const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);
3006
+ notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
3007
+ blob.create((error => {
3008
+ if (error) {
3009
+ callback(error);
3010
+ } else {
3011
+ const upload = new BlobUpload(blob);
3012
+ notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr);
3013
+ upload.create((error => {
3014
+ if (error) {
3015
+ callback(error);
3016
+ } else {
3017
+ callback(null, blob.toJSON());
3018
+ }
3019
+ }));
3020
+ }
3021
+ }));
3022
+ }));
3023
+ }
3024
+ }
3025
+
3026
+ function notify(object, methodName, ...messages) {
3027
+ if (object && typeof object[methodName] == "function") {
3028
+ return object[methodName](...messages);
3029
+ }
3030
+ }
3031
+
3032
+ class DirectUploadController$1 {
3033
+ constructor(input, file) {
3034
+ this.input = input;
3035
+ this.file = file;
3036
+ this.directUpload = new DirectUpload(this.file, this.url, this);
3037
+ this.dispatch("initialize");
3038
+ }
3039
+ start(callback) {
3040
+ const hiddenInput = document.createElement("input");
3041
+ hiddenInput.type = "hidden";
3042
+ hiddenInput.name = this.input.name;
3043
+ this.input.insertAdjacentElement("beforebegin", hiddenInput);
3044
+ this.dispatch("start");
3045
+ this.directUpload.create(((error, attributes) => {
3046
+ if (error) {
3047
+ hiddenInput.parentNode.removeChild(hiddenInput);
3048
+ this.dispatchError(error);
3049
+ } else {
3050
+ hiddenInput.value = attributes.signed_id;
3051
+ }
3052
+ this.dispatch("end");
3053
+ callback(error);
3054
+ }));
3055
+ }
3056
+ uploadRequestDidProgress(event) {
3057
+ const progress = event.loaded / event.total * 100;
3058
+ if (progress) {
3059
+ this.dispatch("progress", {
3060
+ progress: progress
3061
+ });
3062
+ }
3063
+ }
3064
+ get url() {
3065
+ return this.input.getAttribute("data-direct-upload-url");
3066
+ }
3067
+ dispatch(name, detail = {}) {
3068
+ detail.file = this.file;
3069
+ detail.id = this.directUpload.id;
3070
+ return dispatchEvent$1(this.input, `direct-upload:${name}`, {
3071
+ detail: detail
3072
+ });
3073
+ }
3074
+ dispatchError(error) {
3075
+ const event = this.dispatch("error", {
3076
+ error: error
3077
+ });
3078
+ if (!event.defaultPrevented) {
3079
+ alert(error);
3080
+ }
3081
+ }
3082
+ directUploadWillCreateBlobWithXHR(xhr) {
3083
+ this.dispatch("before-blob-request", {
3084
+ xhr: xhr
3085
+ });
3086
+ }
3087
+ directUploadWillStoreFileWithXHR(xhr) {
3088
+ this.dispatch("before-storage-request", {
3089
+ xhr: xhr
3090
+ });
3091
+ xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
3092
+ }
3093
+ }
3094
+
3095
+ const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])";
3096
+
3097
+ class DirectUploadsController {
3098
+ constructor(form) {
3099
+ this.form = form;
3100
+ this.inputs = findElements(form, inputSelector).filter((input => input.files.length));
3101
+ }
3102
+ start(callback) {
3103
+ const controllers = this.createDirectUploadControllers();
3104
+ const startNextController = () => {
3105
+ const controller = controllers.shift();
3106
+ if (controller) {
3107
+ controller.start((error => {
3108
+ if (error) {
3109
+ callback(error);
3110
+ this.dispatch("end");
3111
+ } else {
3112
+ startNextController();
3113
+ }
3114
+ }));
3115
+ } else {
3116
+ callback();
3117
+ this.dispatch("end");
3118
+ }
3119
+ };
3120
+ this.dispatch("start");
3121
+ startNextController();
3122
+ }
3123
+ createDirectUploadControllers() {
3124
+ const controllers = [];
3125
+ this.inputs.forEach((input => {
3126
+ toArray(input.files).forEach((file => {
3127
+ const controller = new DirectUploadController$1(input, file);
3128
+ controllers.push(controller);
3129
+ }));
3130
+ }));
3131
+ return controllers;
3132
+ }
3133
+ dispatch(name, detail = {}) {
3134
+ return dispatchEvent$1(this.form, `direct-uploads:${name}`, {
3135
+ detail: detail
3136
+ });
3137
+ }
3138
+ }
3139
+
3140
+ const processingAttribute = "data-direct-uploads-processing";
3141
+
3142
+ const submitButtonsByForm = new WeakMap;
3143
+
3144
+ let started = false;
3145
+
3146
+ function start() {
3147
+ if (!started) {
3148
+ started = true;
3149
+ document.addEventListener("click", didClick, true);
3150
+ document.addEventListener("submit", didSubmitForm, true);
3151
+ document.addEventListener("ajax:before", didSubmitRemoteElement);
3152
+ }
3153
+ }
3154
+
3155
+ function didClick(event) {
3156
+ const {target: target} = event;
3157
+ if ((target.tagName == "INPUT" || target.tagName == "BUTTON") && target.type == "submit" && target.form) {
3158
+ submitButtonsByForm.set(target.form, target);
3159
+ }
3160
+ }
3161
+
3162
+ function didSubmitForm(event) {
3163
+ handleFormSubmissionEvent(event);
3164
+ }
3165
+
3166
+ function didSubmitRemoteElement(event) {
3167
+ if (event.target.tagName == "FORM") {
3168
+ handleFormSubmissionEvent(event);
3169
+ }
3170
+ }
3171
+
3172
+ function handleFormSubmissionEvent(event) {
3173
+ const form = event.target;
3174
+ if (form.hasAttribute(processingAttribute)) {
3175
+ event.preventDefault();
3176
+ return;
3177
+ }
3178
+ const controller = new DirectUploadsController(form);
3179
+ const {inputs: inputs} = controller;
3180
+ if (inputs.length) {
3181
+ event.preventDefault();
3182
+ form.setAttribute(processingAttribute, "");
3183
+ inputs.forEach(disable);
3184
+ controller.start((error => {
3185
+ form.removeAttribute(processingAttribute);
3186
+ if (error) {
3187
+ inputs.forEach(enable);
3188
+ } else {
3189
+ submitForm(form);
3190
+ }
3191
+ }));
3192
+ }
3193
+ }
3194
+
3195
+ function submitForm(form) {
3196
+ let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]");
3197
+ if (button) {
3198
+ const {disabled: disabled} = button;
3199
+ button.disabled = false;
3200
+ button.focus();
3201
+ button.click();
3202
+ button.disabled = disabled;
3203
+ } else {
3204
+ button = document.createElement("input");
3205
+ button.type = "submit";
3206
+ button.style.display = "none";
3207
+ form.appendChild(button);
3208
+ button.click();
3209
+ form.removeChild(button);
3210
+ }
3211
+ submitButtonsByForm.delete(form);
3212
+ }
3213
+
3214
+ function disable(input) {
3215
+ input.disabled = true;
3216
+ }
3217
+
3218
+ function enable(input) {
3219
+ input.disabled = false;
3220
+ }
3221
+
3222
+ function autostart() {
3223
+ if (window.ActiveStorage) {
3224
+ start();
3225
+ }
3226
+ }
3227
+
3228
+ setTimeout(autostart, 1);
3229
+
3230
+ class DirectUploadController {
3231
+ uploadedFile;
3232
+ file;
3233
+ directUpload;
3234
+ recordXHR;
3235
+ uploadXHR;
3236
+ callback = null;
3237
+ constructor(uploadedFile) {
3238
+ this.uploadedFile = uploadedFile;
3239
+ this.file = this.uploadedFile["file"];
3240
+ this.directUpload = new DirectUpload(this.file, this.uploadedFile.url, this);
3241
+ }
3242
+ cancel() {
3243
+ this.directUpload.url = null;
3244
+ this.abortXHR(this.recordXHR);
3245
+ this.abortXHR(this.uploadXHR);
3246
+ }
3247
+ abortXHR(xhr) {
3248
+ if (!xhr)
3249
+ return;
3250
+ xhr.addEventListener("abort", () => {
3251
+ this.complete("aborted", {});
3252
+ });
3253
+ xhr.abort();
3254
+ }
3255
+ start(callback) {
3256
+ this.callback = callback;
3257
+ this.dispatch("start");
3258
+ this.directUpload.create((error, attributes) => {
3259
+ this.complete(error, attributes);
3260
+ });
3261
+ }
3262
+ complete(error, _attributes) {
3263
+ if (error) {
3264
+ this.dispatchError(error);
3265
+ }
3266
+ this.dispatch("end");
3267
+ this.callback(error);
3268
+ }
3269
+ uploadRequestDidProgress(event) {
3270
+ const progress = event.loaded / event.total * 100;
3271
+ if (progress) {
3272
+ this.dispatch("progress", {
3273
+ progress: progress
3274
+ });
3275
+ }
3276
+ }
3277
+ dispatch(name, detail = {}) {
3278
+ return dispatchEvent(this.uploadedFile, `direct-upload:${name}`, {
3279
+ detail: {
3280
+ ...detail,
3281
+ file: this.file,
3282
+ id: this.directUpload.id,
3283
+ }
3284
+ });
3285
+ }
3286
+ dispatchError(error) {
3287
+ this.dispatch("error", {
3288
+ error: error
3289
+ });
3290
+ }
3291
+ directUploadWillCreateBlobWithXHR(xhr) {
3292
+ this.recordXHR = xhr;
3293
+ this.dispatch("before-blob-request", {
3294
+ xhr: xhr
3295
+ });
3296
+ }
3297
+ directUploadWillStoreFileWithXHR(xhr) {
3298
+ this.uploadXHR = xhr;
3299
+ this.uploadedFile.value = this.recordXHR.response.signed_id;
3300
+ this.dispatch("before-storage-request", {
3301
+ xhr: xhr
3302
+ });
3303
+ xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
3304
+ }
3305
+ }
3306
+ function dispatchEvent(element, type, eventInit = {}) {
3307
+ const { disabled: disabled } = element;
3308
+ const { bubbles: bubbles, cancelable: cancelable, detail: detail } = eventInit;
3309
+ const event = document.createEvent("Event");
3310
+ event.initEvent(type, bubbles || true, cancelable || true);
3311
+ event.detail = detail || {};
3312
+ try {
3313
+ element.disabled = false;
3314
+ element.dispatchEvent(event);
3315
+ }
3316
+ finally {
3317
+ element.disabled = disabled;
3318
+ }
3319
+ return event;
3320
+ }
3321
+
3322
+ class Max {
3323
+ uploadedFile;
3324
+ constructor(uploadedFile) {
3325
+ this.uploadedFile = uploadedFile;
3326
+ }
3327
+ get errors() {
3328
+ if (this.#errors)
3329
+ return this.#errors;
3330
+ this.#errors = [];
3331
+ if (!this.checkValidity()) {
3332
+ this.#errors.push(this.errorMessage);
3333
+ }
3334
+ return this.#errors;
3335
+ }
3336
+ #errors;
3337
+ checkValidity() {
3338
+ if (!this.uploadedFile.max)
3339
+ return true;
3340
+ return this.uploadedFile.size <= this.uploadedFile.max;
3341
+ }
3342
+ get errorMessage() {
3343
+ return [
3344
+ `Must be smaller than ${this.formatBytes(this.uploadedFile.max)},`,
3345
+ `and "${this.uploadedFile.filename}" is ${this.formatBytes(this.uploadedFile.size)}.`,
3346
+ `Please attach a smaller file.`,
3347
+ ].join(" ");
3348
+ }
3349
+ formatBytes(bytes, decimals = 2) {
3350
+ if (bytes === 0)
3351
+ return '0 Bytes';
3352
+ const k = 1024;
3353
+ const dm = decimals < 0 ? 0 : decimals;
3354
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
3355
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
3356
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + sizes[i];
3357
+ }
3358
+ }
3359
+
3360
+ class Accepts {
3361
+ uploadedFile;
3362
+ constructor(uploadedFile) {
3363
+ this.uploadedFile = uploadedFile;
3364
+ }
3365
+ get errors() {
3366
+ if (this.#errors)
3367
+ return this.#errors;
3368
+ this.#errors = [];
3369
+ const accepts = this.uploadedFile.accepts ? this.uploadedFile.accepts.split(/,\s*/) : [];
3370
+ if (accepts.length > 0 && !accepts.includes(this.uploadedFile.filetype)) {
3371
+ this.#errors.push(`Must be a ${this.joinWords(accepts)}.`);
3372
+ }
3373
+ return this.#errors;
3374
+ }
3375
+ #errors;
3376
+ joinWords(words) {
3377
+ if (words.length >= 3) {
3378
+ return (words.slice(0, -1) + [`or ${words.at(-1)}`]).join(", ");
3379
+ }
3380
+ else {
3381
+ return words.join(" or ");
3382
+ }
3383
+ }
3384
+ }
3385
+
3386
+ const Extensions = {
3387
+ image: ["ase", "art", "bmp", "blp", "cd5", "cit", "cpt", "cr2", "cut", "dds", "dib", "djvu", "egt", "exif", "gif", "gpl", "grf", "icns", "ico", "iff", "jng", "jpeg", "jpg", "jfif", "jp2", "jps", "lbm", "max", "miff", "mng", "msp", "nef", "nitf", "ota", "pbm", "pc1", "pc2", "pc3", "pcf", "pcx", "pdn", "pgm", "PI1", "PI2", "PI3", "pict", "pct", "pnm", "pns", "ppm", "psb", "psd", "pdd", "psp", "px", "pxm", "pxr", "qfx", "raw", "rle", "sct", "sgi", "rgb", "int", "bw", "tga", "tiff", "tif", "vtf", "xbm", "xcf", "xpm", "3dv", "amf", "ai", "awg", "cgm", "cdr", "cmx", "dxf", "e2d", "egt", "eps", "fs", "gbr", "odg", "svg", "stl", "vrml", "x3d", "sxd", "v2d", "vnd", "wmf", "emf", "art", "xar", "png", "webp", "jxr", "hdp", "wdp", "cur", "ecw", "iff", "lbm", "liff", "nrrd", "pam", "pcx", "pgf", "sgi", "rgb", "rgba", "bw", "int", "inta", "sid", "ras", "sun", "tga", "heic", "heif"],
3388
+ video: ["3g2", "3gp", "3gpp", "aaf", "asf", "avchd", "avi", "drc", "flv", "m2v", "m3u8", "m4p", "m4v", "mkv", "mng", "mov", "mp2", "mp4", "mpe", "mpeg", "mpg", "mpv", "mxf", "nsv", "ogg", "ogv", "qt", "rm", "rmvb", "roq", "svi", "vob", "webm", "wmv", "yuv"],
3389
+ pdf: ["pdf"],
3390
+ getFileType: function (filename) {
3391
+ const normalized = filename.toString().split(".").at(-1).toLowerCase().trim();
3392
+ if (this.video.includes(normalized))
3393
+ return "video";
3394
+ if (this.image.includes(normalized))
3395
+ return "image";
3396
+ if (this.pdf.includes(normalized))
3397
+ return "pdf";
3398
+ return "unknown";
3399
+ }
3400
+ };
3401
+
3402
+ class FetchResponse {
3403
+ constructor (response) {
3404
+ this.response = response;
3405
+ }
3406
+
3407
+ get statusCode () {
3408
+ return this.response.status
3409
+ }
3410
+
3411
+ get redirected () {
3412
+ return this.response.redirected
3413
+ }
3414
+
3415
+ get ok () {
3416
+ return this.response.ok
3417
+ }
3418
+
3419
+ get unauthenticated () {
3420
+ return this.statusCode === 401
3421
+ }
3422
+
3423
+ get unprocessableEntity () {
3424
+ return this.statusCode === 422
3425
+ }
3426
+
3427
+ get authenticationURL () {
3428
+ return this.response.headers.get('WWW-Authenticate')
3429
+ }
3430
+
3431
+ get contentType () {
3432
+ const contentType = this.response.headers.get('Content-Type') || '';
3433
+
3434
+ return contentType.replace(/;.*$/, '')
3435
+ }
3436
+
3437
+ get headers () {
3438
+ return this.response.headers
3439
+ }
3440
+
3441
+ get html () {
3442
+ if (this.contentType.match(/^(application|text)\/(html|xhtml\+xml)$/)) {
3443
+ return this.text
3444
+ }
3445
+
3446
+ return Promise.reject(new Error(`Expected an HTML response but got "${this.contentType}" instead`))
3447
+ }
3448
+
3449
+ get json () {
3450
+ if (this.contentType.match(/^application\/.*json$/)) {
3451
+ return this.responseJson || (this.responseJson = this.response.json())
3452
+ }
3453
+
3454
+ return Promise.reject(new Error(`Expected a JSON response but got "${this.contentType}" instead`))
3455
+ }
3456
+
3457
+ get text () {
3458
+ return this.responseText || (this.responseText = this.response.text())
3459
+ }
3460
+
3461
+ get isTurboStream () {
3462
+ return this.contentType.match(/^text\/vnd\.turbo-stream\.html/)
3463
+ }
3464
+
3465
+ async renderTurboStream () {
3466
+ if (this.isTurboStream) {
3467
+ if (window.Turbo) {
3468
+ await window.Turbo.renderStreamMessage(await this.text);
3469
+ } else {
3470
+ console.warn('You must set `window.Turbo = Turbo` to automatically process Turbo Stream events with request.js');
3471
+ }
3472
+ } else {
3473
+ return Promise.reject(new Error(`Expected a Turbo Stream response but got "${this.contentType}" instead`))
3474
+ }
3475
+ }
3476
+ }
3477
+
3478
+ class RequestInterceptor {
3479
+ static register (interceptor) {
3480
+ this.interceptor = interceptor;
3481
+ }
3482
+
3483
+ static get () {
3484
+ return this.interceptor
3485
+ }
3486
+
3487
+ static reset () {
3488
+ this.interceptor = undefined;
3489
+ }
3490
+ }
3491
+
3492
+ function getCookie (name) {
3493
+ const cookies = document.cookie ? document.cookie.split('; ') : [];
3494
+ const prefix = `${encodeURIComponent(name)}=`;
3495
+ const cookie = cookies.find(cookie => cookie.startsWith(prefix));
3496
+
3497
+ if (cookie) {
3498
+ const value = cookie.split('=').slice(1).join('=');
3499
+
3500
+ if (value) {
3501
+ return decodeURIComponent(value)
3502
+ }
3503
+ }
3504
+ }
3505
+
3506
+ function compact (object) {
3507
+ const result = {};
3508
+
3509
+ for (const key in object) {
3510
+ const value = object[key];
3511
+ if (value !== undefined) {
3512
+ result[key] = value;
3513
+ }
3514
+ }
3515
+
3516
+ return result
3517
+ }
3518
+
3519
+ function metaContent (name) {
3520
+ const element = document.head.querySelector(`meta[name="${name}"]`);
3521
+ return element && element.content
3522
+ }
3523
+
3524
+ function stringEntriesFromFormData (formData) {
3525
+ return [...formData].reduce((entries, [name, value]) => {
3526
+ return entries.concat(typeof value === 'string' ? [[name, value]] : [])
3527
+ }, [])
3528
+ }
3529
+
3530
+ function mergeEntries (searchParams, entries) {
3531
+ for (const [name, value] of entries) {
3532
+ if (value instanceof window.File) continue
3533
+
3534
+ if (searchParams.has(name)) {
3535
+ searchParams.delete(name);
3536
+ searchParams.set(name, value);
3537
+ } else {
3538
+ searchParams.append(name, value);
3539
+ }
3540
+ }
3541
+ }
3542
+
3543
+ class FetchRequest {
3544
+ constructor (method, url, options = {}) {
3545
+ this.method = method;
3546
+ this.options = options;
3547
+ this.originalUrl = url.toString();
3548
+ }
3549
+
3550
+ async perform () {
3551
+ try {
3552
+ const requestInterceptor = RequestInterceptor.get();
3553
+ if (requestInterceptor) {
3554
+ await requestInterceptor(this);
3555
+ }
3556
+ } catch (error) {
3557
+ console.error(error);
3558
+ }
3559
+
3560
+ const response = new FetchResponse(await window.fetch(this.url, this.fetchOptions));
3561
+
3562
+ if (response.unauthenticated && response.authenticationURL) {
3563
+ return Promise.reject(window.location.href = response.authenticationURL)
3564
+ }
3565
+
3566
+ if (response.ok && response.isTurboStream) {
3567
+ await response.renderTurboStream();
3568
+ }
3569
+
3570
+ return response
3571
+ }
3572
+
3573
+ addHeader (key, value) {
3574
+ const headers = this.additionalHeaders;
3575
+ headers[key] = value;
3576
+ this.options.headers = headers;
3577
+ }
3578
+
3579
+ get fetchOptions () {
3580
+ return {
3581
+ method: this.method.toUpperCase(),
3582
+ headers: this.headers,
3583
+ body: this.formattedBody,
3584
+ signal: this.signal,
3585
+ credentials: 'same-origin',
3586
+ redirect: this.redirect
3587
+ }
3588
+ }
3589
+
3590
+ get headers () {
3591
+ return compact(
3592
+ Object.assign({
3593
+ 'X-Requested-With': 'XMLHttpRequest',
3594
+ 'X-CSRF-Token': this.csrfToken,
3595
+ 'Content-Type': this.contentType,
3596
+ Accept: this.accept
3597
+ },
3598
+ this.additionalHeaders)
3599
+ )
3600
+ }
3601
+
3602
+ get csrfToken () {
3603
+ return getCookie(metaContent('csrf-param')) || metaContent('csrf-token')
3604
+ }
3605
+
3606
+ get contentType () {
3607
+ if (this.options.contentType) {
3608
+ return this.options.contentType
3609
+ } else if (this.body == null || this.body instanceof window.FormData) {
3610
+ return undefined
3611
+ } else if (this.body instanceof window.File) {
3612
+ return this.body.type
3613
+ }
3614
+
3615
+ return 'application/json'
3616
+ }
3617
+
3618
+ get accept () {
3619
+ switch (this.responseKind) {
3620
+ case 'html':
3621
+ return 'text/html, application/xhtml+xml'
3622
+ case 'turbo-stream':
3623
+ return 'text/vnd.turbo-stream.html, text/html, application/xhtml+xml'
3624
+ case 'json':
3625
+ return 'application/json, application/vnd.api+json'
3626
+ default:
3627
+ return '*/*'
3628
+ }
3629
+ }
3630
+
3631
+ get body () {
3632
+ return this.options.body
3633
+ }
3634
+
3635
+ get query () {
3636
+ const originalQuery = (this.originalUrl.split('?')[1] || '').split('#')[0];
3637
+ const params = new URLSearchParams(originalQuery);
3638
+
3639
+ let requestQuery = this.options.query;
3640
+ if (requestQuery instanceof window.FormData) {
3641
+ requestQuery = stringEntriesFromFormData(requestQuery);
3642
+ } else if (requestQuery instanceof window.URLSearchParams) {
3643
+ requestQuery = requestQuery.entries();
3644
+ } else {
3645
+ requestQuery = Object.entries(requestQuery || {});
3646
+ }
3647
+
3648
+ mergeEntries(params, requestQuery);
3649
+
3650
+ const query = params.toString();
3651
+ return (query.length > 0 ? `?${query}` : '')
3652
+ }
3653
+
3654
+ get url () {
3655
+ return (this.originalUrl.split('?')[0]).split('#')[0] + this.query
3656
+ }
3657
+
3658
+ get responseKind () {
3659
+ return this.options.responseKind || 'html'
3660
+ }
3661
+
3662
+ get signal () {
3663
+ return this.options.signal
3664
+ }
3665
+
3666
+ get redirect () {
3667
+ return this.options.redirect || 'follow'
3668
+ }
3669
+
3670
+ get additionalHeaders () {
3671
+ return this.options.headers || {}
3672
+ }
3673
+
3674
+ get formattedBody () {
3675
+ const bodyIsAString = Object.prototype.toString.call(this.body) === '[object String]';
3676
+ const contentTypeIsJson = this.headers['Content-Type'] === 'application/json';
3677
+
3678
+ if (contentTypeIsJson && !bodyIsAString) {
3679
+ return JSON.stringify(this.body)
3680
+ }
3681
+
3682
+ return this.body
3683
+ }
3684
+ }
3685
+
3686
+ const request = (verb, url, payload) => {
3687
+ const req = new FetchRequest(verb, url, {
3688
+ headers: { Accept: "application/json" },
3689
+ body: payload,
3690
+ });
3691
+ return req.perform().then(response => {
3692
+ if(response.response.ok) {
3693
+ return response.json
3694
+ } else {
3695
+ return response
3696
+ }
3697
+ })
3698
+ };
3699
+
3700
+ const get = (url, payload) => request('get', url, payload);
3701
+
3702
+ var DOCUMENT_FRAGMENT_NODE = 11;
3703
+
3704
+ function morphAttrs(fromNode, toNode) {
3705
+ var toNodeAttrs = toNode.attributes;
3706
+ var attr;
3707
+ var attrName;
3708
+ var attrNamespaceURI;
3709
+ var attrValue;
3710
+ var fromValue;
3711
+
3712
+ // document-fragments dont have attributes so lets not do anything
3713
+ if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE || fromNode.nodeType === DOCUMENT_FRAGMENT_NODE) {
3714
+ return;
3715
+ }
3716
+
3717
+ // update attributes on original DOM element
3718
+ for (var i = toNodeAttrs.length - 1; i >= 0; i--) {
3719
+ attr = toNodeAttrs[i];
3720
+ attrName = attr.name;
3721
+ attrNamespaceURI = attr.namespaceURI;
3722
+ attrValue = attr.value;
3723
+
3724
+ if (attrNamespaceURI) {
3725
+ attrName = attr.localName || attrName;
3726
+ fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName);
3727
+
3728
+ if (fromValue !== attrValue) {
3729
+ if (attr.prefix === 'xmlns'){
3730
+ attrName = attr.name; // It's not allowed to set an attribute with the XMLNS namespace without specifying the `xmlns` prefix
3731
+ }
3732
+ fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue);
3733
+ }
3734
+ } else {
3735
+ fromValue = fromNode.getAttribute(attrName);
3736
+
3737
+ if (fromValue !== attrValue) {
3738
+ fromNode.setAttribute(attrName, attrValue);
3739
+ }
3740
+ }
3741
+ }
3742
+
3743
+ // Remove any extra attributes found on the original DOM element that
3744
+ // weren't found on the target element.
3745
+ var fromNodeAttrs = fromNode.attributes;
3746
+
3747
+ for (var d = fromNodeAttrs.length - 1; d >= 0; d--) {
3748
+ attr = fromNodeAttrs[d];
3749
+ attrName = attr.name;
3750
+ attrNamespaceURI = attr.namespaceURI;
3751
+
3752
+ if (attrNamespaceURI) {
3753
+ attrName = attr.localName || attrName;
3754
+
3755
+ if (!toNode.hasAttributeNS(attrNamespaceURI, attrName)) {
3756
+ fromNode.removeAttributeNS(attrNamespaceURI, attrName);
3757
+ }
3758
+ } else {
3759
+ if (!toNode.hasAttribute(attrName)) {
3760
+ fromNode.removeAttribute(attrName);
3761
+ }
3762
+ }
3763
+ }
3764
+ }
3765
+
3766
+ var range; // Create a range object for efficently rendering strings to elements.
3767
+ var NS_XHTML = 'http://www.w3.org/1999/xhtml';
3768
+
3769
+ var doc = typeof document === 'undefined' ? undefined : document;
3770
+ var HAS_TEMPLATE_SUPPORT = !!doc && 'content' in doc.createElement('template');
3771
+ var HAS_RANGE_SUPPORT = !!doc && doc.createRange && 'createContextualFragment' in doc.createRange();
3772
+
3773
+ function createFragmentFromTemplate(str) {
3774
+ var template = doc.createElement('template');
3775
+ template.innerHTML = str;
3776
+ return template.content.childNodes[0];
3777
+ }
3778
+
3779
+ function createFragmentFromRange(str) {
3780
+ if (!range) {
3781
+ range = doc.createRange();
3782
+ range.selectNode(doc.body);
3783
+ }
3784
+
3785
+ var fragment = range.createContextualFragment(str);
3786
+ return fragment.childNodes[0];
3787
+ }
3788
+
3789
+ function createFragmentFromWrap(str) {
3790
+ var fragment = doc.createElement('body');
3791
+ fragment.innerHTML = str;
3792
+ return fragment.childNodes[0];
3793
+ }
3794
+
3795
+ /**
3796
+ * This is about the same
3797
+ * var html = new DOMParser().parseFromString(str, 'text/html');
3798
+ * return html.body.firstChild;
3799
+ *
3800
+ * @method toElement
3801
+ * @param {String} str
3802
+ */
3803
+ function toElement(str) {
3804
+ str = str.trim();
3805
+ if (HAS_TEMPLATE_SUPPORT) {
3806
+ // avoid restrictions on content for things like `<tr><th>Hi</th></tr>` which
3807
+ // createContextualFragment doesn't support
3808
+ // <template> support not available in IE
3809
+ return createFragmentFromTemplate(str);
3810
+ } else if (HAS_RANGE_SUPPORT) {
3811
+ return createFragmentFromRange(str);
3812
+ }
3813
+
3814
+ return createFragmentFromWrap(str);
3815
+ }
3816
+
3817
+ /**
3818
+ * Returns true if two node's names are the same.
3819
+ *
3820
+ * NOTE: We don't bother checking `namespaceURI` because you will never find two HTML elements with the same
3821
+ * nodeName and different namespace URIs.
3822
+ *
3823
+ * @param {Element} a
3824
+ * @param {Element} b The target element
3825
+ * @return {boolean}
3826
+ */
3827
+ function compareNodeNames(fromEl, toEl) {
3828
+ var fromNodeName = fromEl.nodeName;
3829
+ var toNodeName = toEl.nodeName;
3830
+ var fromCodeStart, toCodeStart;
3831
+
3832
+ if (fromNodeName === toNodeName) {
3833
+ return true;
3834
+ }
3835
+
3836
+ fromCodeStart = fromNodeName.charCodeAt(0);
3837
+ toCodeStart = toNodeName.charCodeAt(0);
3838
+
3839
+ // If the target element is a virtual DOM node or SVG node then we may
3840
+ // need to normalize the tag name before comparing. Normal HTML elements that are
3841
+ // in the "http://www.w3.org/1999/xhtml"
3842
+ // are converted to upper case
3843
+ if (fromCodeStart <= 90 && toCodeStart >= 97) { // from is upper and to is lower
3844
+ return fromNodeName === toNodeName.toUpperCase();
3845
+ } else if (toCodeStart <= 90 && fromCodeStart >= 97) { // to is upper and from is lower
3846
+ return toNodeName === fromNodeName.toUpperCase();
3847
+ } else {
3848
+ return false;
3849
+ }
3850
+ }
3851
+
3852
+ /**
3853
+ * Create an element, optionally with a known namespace URI.
3854
+ *
3855
+ * @param {string} name the element name, e.g. 'div' or 'svg'
3856
+ * @param {string} [namespaceURI] the element's namespace URI, i.e. the value of
3857
+ * its `xmlns` attribute or its inferred namespace.
3858
+ *
3859
+ * @return {Element}
3860
+ */
3861
+ function createElementNS(name, namespaceURI) {
3862
+ return !namespaceURI || namespaceURI === NS_XHTML ?
3863
+ doc.createElement(name) :
3864
+ doc.createElementNS(namespaceURI, name);
3865
+ }
3866
+
3867
+ /**
3868
+ * Copies the children of one DOM element to another DOM element
3869
+ */
3870
+ function moveChildren(fromEl, toEl) {
3871
+ var curChild = fromEl.firstChild;
3872
+ while (curChild) {
3873
+ var nextChild = curChild.nextSibling;
3874
+ toEl.appendChild(curChild);
3875
+ curChild = nextChild;
3876
+ }
3877
+ return toEl;
3878
+ }
3879
+
3880
+ function syncBooleanAttrProp(fromEl, toEl, name) {
3881
+ if (fromEl[name] !== toEl[name]) {
3882
+ fromEl[name] = toEl[name];
3883
+ if (fromEl[name]) {
3884
+ fromEl.setAttribute(name, '');
3885
+ } else {
3886
+ fromEl.removeAttribute(name);
3887
+ }
3888
+ }
3889
+ }
3890
+
3891
+ var specialElHandlers = {
3892
+ OPTION: function(fromEl, toEl) {
3893
+ var parentNode = fromEl.parentNode;
3894
+ if (parentNode) {
3895
+ var parentName = parentNode.nodeName.toUpperCase();
3896
+ if (parentName === 'OPTGROUP') {
3897
+ parentNode = parentNode.parentNode;
3898
+ parentName = parentNode && parentNode.nodeName.toUpperCase();
3899
+ }
3900
+ if (parentName === 'SELECT' && !parentNode.hasAttribute('multiple')) {
3901
+ if (fromEl.hasAttribute('selected') && !toEl.selected) {
3902
+ // Workaround for MS Edge bug where the 'selected' attribute can only be
3903
+ // removed if set to a non-empty value:
3904
+ // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12087679/
3905
+ fromEl.setAttribute('selected', 'selected');
3906
+ fromEl.removeAttribute('selected');
3907
+ }
3908
+ // We have to reset select element's selectedIndex to -1, otherwise setting
3909
+ // fromEl.selected using the syncBooleanAttrProp below has no effect.
3910
+ // The correct selectedIndex will be set in the SELECT special handler below.
3911
+ parentNode.selectedIndex = -1;
3912
+ }
3913
+ }
3914
+ syncBooleanAttrProp(fromEl, toEl, 'selected');
3915
+ },
3916
+ /**
3917
+ * The "value" attribute is special for the <input> element since it sets
3918
+ * the initial value. Changing the "value" attribute without changing the
3919
+ * "value" property will have no effect since it is only used to the set the
3920
+ * initial value. Similar for the "checked" attribute, and "disabled".
3921
+ */
3922
+ INPUT: function(fromEl, toEl) {
3923
+ syncBooleanAttrProp(fromEl, toEl, 'checked');
3924
+ syncBooleanAttrProp(fromEl, toEl, 'disabled');
3925
+
3926
+ if (fromEl.value !== toEl.value) {
3927
+ fromEl.value = toEl.value;
3928
+ }
3929
+
3930
+ if (!toEl.hasAttribute('value')) {
3931
+ fromEl.removeAttribute('value');
3932
+ }
3933
+ },
3934
+
3935
+ TEXTAREA: function(fromEl, toEl) {
3936
+ var newValue = toEl.value;
3937
+ if (fromEl.value !== newValue) {
3938
+ fromEl.value = newValue;
3939
+ }
3940
+
3941
+ var firstChild = fromEl.firstChild;
3942
+ if (firstChild) {
3943
+ // Needed for IE. Apparently IE sets the placeholder as the
3944
+ // node value and vise versa. This ignores an empty update.
3945
+ var oldValue = firstChild.nodeValue;
3946
+
3947
+ if (oldValue == newValue || (!newValue && oldValue == fromEl.placeholder)) {
3948
+ return;
3949
+ }
3950
+
3951
+ firstChild.nodeValue = newValue;
3952
+ }
3953
+ },
3954
+ SELECT: function(fromEl, toEl) {
3955
+ if (!toEl.hasAttribute('multiple')) {
3956
+ var selectedIndex = -1;
3957
+ var i = 0;
3958
+ // We have to loop through children of fromEl, not toEl since nodes can be moved
3959
+ // from toEl to fromEl directly when morphing.
3960
+ // At the time this special handler is invoked, all children have already been morphed
3961
+ // and appended to / removed from fromEl, so using fromEl here is safe and correct.
3962
+ var curChild = fromEl.firstChild;
3963
+ var optgroup;
3964
+ var nodeName;
3965
+ while(curChild) {
3966
+ nodeName = curChild.nodeName && curChild.nodeName.toUpperCase();
3967
+ if (nodeName === 'OPTGROUP') {
3968
+ optgroup = curChild;
3969
+ curChild = optgroup.firstChild;
3970
+ } else {
3971
+ if (nodeName === 'OPTION') {
3972
+ if (curChild.hasAttribute('selected')) {
3973
+ selectedIndex = i;
3974
+ break;
3975
+ }
3976
+ i++;
3977
+ }
3978
+ curChild = curChild.nextSibling;
3979
+ if (!curChild && optgroup) {
3980
+ curChild = optgroup.nextSibling;
3981
+ optgroup = null;
3982
+ }
3983
+ }
3984
+ }
3985
+
3986
+ fromEl.selectedIndex = selectedIndex;
3987
+ }
3988
+ }
3989
+ };
3990
+
3991
+ var ELEMENT_NODE = 1;
3992
+ var DOCUMENT_FRAGMENT_NODE$1 = 11;
3993
+ var TEXT_NODE = 3;
3994
+ var COMMENT_NODE = 8;
3995
+
3996
+ function noop() {}
3997
+
3998
+ function defaultGetNodeKey(node) {
3999
+ if (node) {
4000
+ return (node.getAttribute && node.getAttribute('id')) || node.id;
4001
+ }
4002
+ }
4003
+
4004
+ function morphdomFactory(morphAttrs) {
4005
+
4006
+ return function morphdom(fromNode, toNode, options) {
4007
+ if (!options) {
4008
+ options = {};
4009
+ }
4010
+
4011
+ if (typeof toNode === 'string') {
4012
+ if (fromNode.nodeName === '#document' || fromNode.nodeName === 'HTML' || fromNode.nodeName === 'BODY') {
4013
+ var toNodeHtml = toNode;
4014
+ toNode = doc.createElement('html');
4015
+ toNode.innerHTML = toNodeHtml;
4016
+ } else {
4017
+ toNode = toElement(toNode);
4018
+ }
4019
+ } else if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE$1) {
4020
+ toNode = toNode.firstElementChild;
4021
+ }
4022
+
4023
+ var getNodeKey = options.getNodeKey || defaultGetNodeKey;
4024
+ var onBeforeNodeAdded = options.onBeforeNodeAdded || noop;
4025
+ var onNodeAdded = options.onNodeAdded || noop;
4026
+ var onBeforeElUpdated = options.onBeforeElUpdated || noop;
4027
+ var onElUpdated = options.onElUpdated || noop;
4028
+ var onBeforeNodeDiscarded = options.onBeforeNodeDiscarded || noop;
4029
+ var onNodeDiscarded = options.onNodeDiscarded || noop;
4030
+ var onBeforeElChildrenUpdated = options.onBeforeElChildrenUpdated || noop;
4031
+ var skipFromChildren = options.skipFromChildren || noop;
4032
+ var addChild = options.addChild || function(parent, child){ return parent.appendChild(child); };
4033
+ var childrenOnly = options.childrenOnly === true;
4034
+
4035
+ // This object is used as a lookup to quickly find all keyed elements in the original DOM tree.
4036
+ var fromNodesLookup = Object.create(null);
4037
+ var keyedRemovalList = [];
4038
+
4039
+ function addKeyedRemoval(key) {
4040
+ keyedRemovalList.push(key);
4041
+ }
4042
+
4043
+ function walkDiscardedChildNodes(node, skipKeyedNodes) {
4044
+ if (node.nodeType === ELEMENT_NODE) {
4045
+ var curChild = node.firstChild;
4046
+ while (curChild) {
4047
+
4048
+ var key = undefined;
4049
+
4050
+ if (skipKeyedNodes && (key = getNodeKey(curChild))) {
4051
+ // If we are skipping keyed nodes then we add the key
4052
+ // to a list so that it can be handled at the very end.
4053
+ addKeyedRemoval(key);
4054
+ } else {
4055
+ // Only report the node as discarded if it is not keyed. We do this because
4056
+ // at the end we loop through all keyed elements that were unmatched
4057
+ // and then discard them in one final pass.
4058
+ onNodeDiscarded(curChild);
4059
+ if (curChild.firstChild) {
4060
+ walkDiscardedChildNodes(curChild, skipKeyedNodes);
4061
+ }
4062
+ }
4063
+
4064
+ curChild = curChild.nextSibling;
4065
+ }
4066
+ }
4067
+ }
4068
+
4069
+ /**
4070
+ * Removes a DOM node out of the original DOM
4071
+ *
4072
+ * @param {Node} node The node to remove
4073
+ * @param {Node} parentNode The nodes parent
4074
+ * @param {Boolean} skipKeyedNodes If true then elements with keys will be skipped and not discarded.
4075
+ * @return {undefined}
4076
+ */
4077
+ function removeNode(node, parentNode, skipKeyedNodes) {
4078
+ if (onBeforeNodeDiscarded(node) === false) {
4079
+ return;
4080
+ }
4081
+
4082
+ if (parentNode) {
4083
+ parentNode.removeChild(node);
4084
+ }
4085
+
4086
+ onNodeDiscarded(node);
4087
+ walkDiscardedChildNodes(node, skipKeyedNodes);
4088
+ }
4089
+
4090
+ // // TreeWalker implementation is no faster, but keeping this around in case this changes in the future
4091
+ // function indexTree(root) {
4092
+ // var treeWalker = document.createTreeWalker(
4093
+ // root,
4094
+ // NodeFilter.SHOW_ELEMENT);
4095
+ //
4096
+ // var el;
4097
+ // while((el = treeWalker.nextNode())) {
4098
+ // var key = getNodeKey(el);
4099
+ // if (key) {
4100
+ // fromNodesLookup[key] = el;
4101
+ // }
4102
+ // }
4103
+ // }
4104
+
4105
+ // // NodeIterator implementation is no faster, but keeping this around in case this changes in the future
4106
+ //
4107
+ // function indexTree(node) {
4108
+ // var nodeIterator = document.createNodeIterator(node, NodeFilter.SHOW_ELEMENT);
4109
+ // var el;
4110
+ // while((el = nodeIterator.nextNode())) {
4111
+ // var key = getNodeKey(el);
4112
+ // if (key) {
4113
+ // fromNodesLookup[key] = el;
4114
+ // }
4115
+ // }
4116
+ // }
4117
+
4118
+ function indexTree(node) {
4119
+ if (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE$1) {
4120
+ var curChild = node.firstChild;
4121
+ while (curChild) {
4122
+ var key = getNodeKey(curChild);
4123
+ if (key) {
4124
+ fromNodesLookup[key] = curChild;
4125
+ }
4126
+
4127
+ // Walk recursively
4128
+ indexTree(curChild);
4129
+
4130
+ curChild = curChild.nextSibling;
4131
+ }
4132
+ }
4133
+ }
4134
+
4135
+ indexTree(fromNode);
4136
+
4137
+ function handleNodeAdded(el) {
4138
+ onNodeAdded(el);
4139
+
4140
+ var curChild = el.firstChild;
4141
+ while (curChild) {
4142
+ var nextSibling = curChild.nextSibling;
4143
+
4144
+ var key = getNodeKey(curChild);
4145
+ if (key) {
4146
+ var unmatchedFromEl = fromNodesLookup[key];
4147
+ // if we find a duplicate #id node in cache, replace `el` with cache value
4148
+ // and morph it to the child node.
4149
+ if (unmatchedFromEl && compareNodeNames(curChild, unmatchedFromEl)) {
4150
+ curChild.parentNode.replaceChild(unmatchedFromEl, curChild);
4151
+ morphEl(unmatchedFromEl, curChild);
4152
+ } else {
4153
+ handleNodeAdded(curChild);
4154
+ }
4155
+ } else {
4156
+ // recursively call for curChild and it's children to see if we find something in
4157
+ // fromNodesLookup
4158
+ handleNodeAdded(curChild);
4159
+ }
4160
+
4161
+ curChild = nextSibling;
4162
+ }
4163
+ }
4164
+
4165
+ function cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey) {
4166
+ // We have processed all of the "to nodes". If curFromNodeChild is
4167
+ // non-null then we still have some from nodes left over that need
4168
+ // to be removed
4169
+ while (curFromNodeChild) {
4170
+ var fromNextSibling = curFromNodeChild.nextSibling;
4171
+ if ((curFromNodeKey = getNodeKey(curFromNodeChild))) {
4172
+ // Since the node is keyed it might be matched up later so we defer
4173
+ // the actual removal to later
4174
+ addKeyedRemoval(curFromNodeKey);
4175
+ } else {
4176
+ // NOTE: we skip nested keyed nodes from being removed since there is
4177
+ // still a chance they will be matched up later
4178
+ removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
4179
+ }
4180
+ curFromNodeChild = fromNextSibling;
4181
+ }
4182
+ }
4183
+
4184
+ function morphEl(fromEl, toEl, childrenOnly) {
4185
+ var toElKey = getNodeKey(toEl);
4186
+
4187
+ if (toElKey) {
4188
+ // If an element with an ID is being morphed then it will be in the final
4189
+ // DOM so clear it out of the saved elements collection
4190
+ delete fromNodesLookup[toElKey];
4191
+ }
4192
+
4193
+ if (!childrenOnly) {
4194
+ // optional
4195
+ if (onBeforeElUpdated(fromEl, toEl) === false) {
4196
+ return;
4197
+ }
4198
+
4199
+ // update attributes on original DOM element first
4200
+ morphAttrs(fromEl, toEl);
4201
+ // optional
4202
+ onElUpdated(fromEl);
4203
+
4204
+ if (onBeforeElChildrenUpdated(fromEl, toEl) === false) {
4205
+ return;
4206
+ }
4207
+ }
4208
+
4209
+ if (fromEl.nodeName !== 'TEXTAREA') {
4210
+ morphChildren(fromEl, toEl);
4211
+ } else {
4212
+ specialElHandlers.TEXTAREA(fromEl, toEl);
4213
+ }
4214
+ }
4215
+
4216
+ function morphChildren(fromEl, toEl) {
4217
+ var skipFrom = skipFromChildren(fromEl, toEl);
4218
+ var curToNodeChild = toEl.firstChild;
4219
+ var curFromNodeChild = fromEl.firstChild;
4220
+ var curToNodeKey;
4221
+ var curFromNodeKey;
4222
+
4223
+ var fromNextSibling;
4224
+ var toNextSibling;
4225
+ var matchingFromEl;
4226
+
4227
+ // walk the children
4228
+ outer: while (curToNodeChild) {
4229
+ toNextSibling = curToNodeChild.nextSibling;
4230
+ curToNodeKey = getNodeKey(curToNodeChild);
4231
+
4232
+ // walk the fromNode children all the way through
4233
+ while (!skipFrom && curFromNodeChild) {
4234
+ fromNextSibling = curFromNodeChild.nextSibling;
4235
+
4236
+ if (curToNodeChild.isSameNode && curToNodeChild.isSameNode(curFromNodeChild)) {
4237
+ curToNodeChild = toNextSibling;
4238
+ curFromNodeChild = fromNextSibling;
4239
+ continue outer;
4240
+ }
4241
+
4242
+ curFromNodeKey = getNodeKey(curFromNodeChild);
4243
+
4244
+ var curFromNodeType = curFromNodeChild.nodeType;
4245
+
4246
+ // this means if the curFromNodeChild doesnt have a match with the curToNodeChild
4247
+ var isCompatible = undefined;
4248
+
4249
+ if (curFromNodeType === curToNodeChild.nodeType) {
4250
+ if (curFromNodeType === ELEMENT_NODE) {
4251
+ // Both nodes being compared are Element nodes
4252
+
4253
+ if (curToNodeKey) {
4254
+ // The target node has a key so we want to match it up with the correct element
4255
+ // in the original DOM tree
4256
+ if (curToNodeKey !== curFromNodeKey) {
4257
+ // The current element in the original DOM tree does not have a matching key so
4258
+ // let's check our lookup to see if there is a matching element in the original
4259
+ // DOM tree
4260
+ if ((matchingFromEl = fromNodesLookup[curToNodeKey])) {
4261
+ if (fromNextSibling === matchingFromEl) {
4262
+ // Special case for single element removals. To avoid removing the original
4263
+ // DOM node out of the tree (since that can break CSS transitions, etc.),
4264
+ // we will instead discard the current node and wait until the next
4265
+ // iteration to properly match up the keyed target element with its matching
4266
+ // element in the original tree
4267
+ isCompatible = false;
4268
+ } else {
4269
+ // We found a matching keyed element somewhere in the original DOM tree.
4270
+ // Let's move the original DOM node into the current position and morph
4271
+ // it.
4272
+
4273
+ // NOTE: We use insertBefore instead of replaceChild because we want to go through
4274
+ // the `removeNode()` function for the node that is being discarded so that
4275
+ // all lifecycle hooks are correctly invoked
4276
+ fromEl.insertBefore(matchingFromEl, curFromNodeChild);
4277
+
4278
+ // fromNextSibling = curFromNodeChild.nextSibling;
4279
+
4280
+ if (curFromNodeKey) {
4281
+ // Since the node is keyed it might be matched up later so we defer
4282
+ // the actual removal to later
4283
+ addKeyedRemoval(curFromNodeKey);
4284
+ } else {
4285
+ // NOTE: we skip nested keyed nodes from being removed since there is
4286
+ // still a chance they will be matched up later
4287
+ removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
4288
+ }
4289
+
4290
+ curFromNodeChild = matchingFromEl;
4291
+ }
4292
+ } else {
4293
+ // The nodes are not compatible since the "to" node has a key and there
4294
+ // is no matching keyed node in the source tree
4295
+ isCompatible = false;
4296
+ }
4297
+ }
4298
+ } else if (curFromNodeKey) {
4299
+ // The original has a key
4300
+ isCompatible = false;
4301
+ }
4302
+
4303
+ isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild);
4304
+ if (isCompatible) {
4305
+ // We found compatible DOM elements so transform
4306
+ // the current "from" node to match the current
4307
+ // target DOM node.
4308
+ // MORPH
4309
+ morphEl(curFromNodeChild, curToNodeChild);
4310
+ }
4311
+
4312
+ } else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) {
4313
+ // Both nodes being compared are Text or Comment nodes
4314
+ isCompatible = true;
4315
+ // Simply update nodeValue on the original node to
4316
+ // change the text value
4317
+ if (curFromNodeChild.nodeValue !== curToNodeChild.nodeValue) {
4318
+ curFromNodeChild.nodeValue = curToNodeChild.nodeValue;
4319
+ }
4320
+
4321
+ }
4322
+ }
4323
+
4324
+ if (isCompatible) {
4325
+ // Advance both the "to" child and the "from" child since we found a match
4326
+ // Nothing else to do as we already recursively called morphChildren above
4327
+ curToNodeChild = toNextSibling;
4328
+ curFromNodeChild = fromNextSibling;
4329
+ continue outer;
4330
+ }
4331
+
4332
+ // No compatible match so remove the old node from the DOM and continue trying to find a
4333
+ // match in the original DOM. However, we only do this if the from node is not keyed
4334
+ // since it is possible that a keyed node might match up with a node somewhere else in the
4335
+ // target tree and we don't want to discard it just yet since it still might find a
4336
+ // home in the final DOM tree. After everything is done we will remove any keyed nodes
4337
+ // that didn't find a home
4338
+ if (curFromNodeKey) {
4339
+ // Since the node is keyed it might be matched up later so we defer
4340
+ // the actual removal to later
4341
+ addKeyedRemoval(curFromNodeKey);
4342
+ } else {
4343
+ // NOTE: we skip nested keyed nodes from being removed since there is
4344
+ // still a chance they will be matched up later
4345
+ removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
4346
+ }
4347
+
4348
+ curFromNodeChild = fromNextSibling;
4349
+ } // END: while(curFromNodeChild) {}
4350
+
4351
+ // If we got this far then we did not find a candidate match for
4352
+ // our "to node" and we exhausted all of the children "from"
4353
+ // nodes. Therefore, we will just append the current "to" node
4354
+ // to the end
4355
+ if (curToNodeKey && (matchingFromEl = fromNodesLookup[curToNodeKey]) && compareNodeNames(matchingFromEl, curToNodeChild)) {
4356
+ // MORPH
4357
+ if(!skipFrom){ addChild(fromEl, matchingFromEl); }
4358
+ morphEl(matchingFromEl, curToNodeChild);
4359
+ } else {
4360
+ var onBeforeNodeAddedResult = onBeforeNodeAdded(curToNodeChild);
4361
+ if (onBeforeNodeAddedResult !== false) {
4362
+ if (onBeforeNodeAddedResult) {
4363
+ curToNodeChild = onBeforeNodeAddedResult;
4364
+ }
4365
+
4366
+ if (curToNodeChild.actualize) {
4367
+ curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc);
4368
+ }
4369
+ addChild(fromEl, curToNodeChild);
4370
+ handleNodeAdded(curToNodeChild);
4371
+ }
4372
+ }
4373
+
4374
+ curToNodeChild = toNextSibling;
4375
+ curFromNodeChild = fromNextSibling;
4376
+ }
4377
+
4378
+ cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey);
4379
+
4380
+ var specialElHandler = specialElHandlers[fromEl.nodeName];
4381
+ if (specialElHandler) {
4382
+ specialElHandler(fromEl, toEl);
4383
+ }
4384
+ } // END: morphChildren(...)
4385
+
4386
+ var morphedNode = fromNode;
4387
+ var morphedNodeType = morphedNode.nodeType;
4388
+ var toNodeType = toNode.nodeType;
4389
+
4390
+ if (!childrenOnly) {
4391
+ // Handle the case where we are given two DOM nodes that are not
4392
+ // compatible (e.g. <div> --> <span> or <div> --> TEXT)
4393
+ if (morphedNodeType === ELEMENT_NODE) {
4394
+ if (toNodeType === ELEMENT_NODE) {
4395
+ if (!compareNodeNames(fromNode, toNode)) {
4396
+ onNodeDiscarded(fromNode);
4397
+ morphedNode = moveChildren(fromNode, createElementNS(toNode.nodeName, toNode.namespaceURI));
4398
+ }
4399
+ } else {
4400
+ // Going from an element node to a text node
4401
+ morphedNode = toNode;
4402
+ }
4403
+ } else if (morphedNodeType === TEXT_NODE || morphedNodeType === COMMENT_NODE) { // Text or comment node
4404
+ if (toNodeType === morphedNodeType) {
4405
+ if (morphedNode.nodeValue !== toNode.nodeValue) {
4406
+ morphedNode.nodeValue = toNode.nodeValue;
4407
+ }
4408
+
4409
+ return morphedNode;
4410
+ } else {
4411
+ // Text node to something else
4412
+ morphedNode = toNode;
4413
+ }
4414
+ }
4415
+ }
4416
+
4417
+ if (morphedNode === toNode) {
4418
+ // The "to node" was not compatible with the "from node" so we had to
4419
+ // toss out the "from node" and use the "to node"
4420
+ onNodeDiscarded(fromNode);
4421
+ } else {
4422
+ if (toNode.isSameNode && toNode.isSameNode(morphedNode)) {
4423
+ return;
4424
+ }
4425
+
4426
+ morphEl(morphedNode, toNode, childrenOnly);
4427
+
4428
+ // We now need to loop over any keyed nodes that might need to be
4429
+ // removed. We only do the removal if we know that the keyed node
4430
+ // never found a match. When a keyed node is matched up we remove
4431
+ // it out of fromNodesLookup and we use fromNodesLookup to determine
4432
+ // if a keyed node has been matched up or not
4433
+ if (keyedRemovalList) {
4434
+ for (var i=0, len=keyedRemovalList.length; i<len; i++) {
4435
+ var elToRemove = fromNodesLookup[keyedRemovalList[i]];
4436
+ if (elToRemove) {
4437
+ removeNode(elToRemove, elToRemove.parentNode, false);
4438
+ }
4439
+ }
4440
+ }
4441
+ }
4442
+
4443
+ if (!childrenOnly && morphedNode !== fromNode && fromNode.parentNode) {
4444
+ if (morphedNode.actualize) {
4445
+ morphedNode = morphedNode.actualize(fromNode.ownerDocument || doc);
4446
+ }
4447
+ // If we had to swap out the from node with a new node because the old
4448
+ // node was not compatible with the target node then we need to
4449
+ // replace the old DOM node in the original DOM tree. This is only
4450
+ // possible if the original DOM node was part of a DOM tree which
4451
+ // we know is the case if it has a parent node.
4452
+ fromNode.parentNode.replaceChild(morphedNode, fromNode);
4453
+ }
4454
+
4455
+ return morphedNode;
4456
+ };
4457
+ }
4458
+
4459
+ var morphdom = morphdomFactory(morphAttrs);
4460
+
4461
+ function html(html) {
4462
+ const el = document.createElement("div");
4463
+ morphdom(el, `<div>${html}</div>`);
4464
+ return el.children[0];
4465
+ }
4466
+ function arrayRemove(arr, e) {
4467
+ const index = arr.findIndex(x => x === e);
4468
+ if (index !== -1) {
4469
+ arr.splice(index, 1);
4470
+ }
4471
+ }
4472
+
4473
+ const uploadedFileCss = ":host{display:block;width:100%;max-width:100%;font-size:13px}figure{margin:0}.progress-details{position:relative;display:flex;align-items:center}progress-bar{flex:1 0;padding:0 10px}progress-bar.pending{opacity:0.5}progress-bar.complete{opacity:0.8}progress-bar:not(.complete)+.progress-icon{display:none}progress-bar.complete+.progress-icon{content:url('data:image/svg+xml;utf8,<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"0 0 20 20\" style=\"enable-background:new 0 0 20 20;\" xml:space=\"preserve\"><g><path d=\"M6.3,9.1c0.2,0,0.5,0.1,0.7,0.4c0.5,0.5,1,1,1.4,1.4c0.3,0.3,0.3,0.3,0.6,0c1.4-1.3,2.7-2.6,4-3.9c0.3-0.3,0.6-0.4,1-0.4 c0.5,0.1,0.9,0.6,0.7,1.1c-0.1,0.2-0.2,0.4-0.3,0.6c-1.6,1.6-3.2,3.2-4.8,4.8c-0.5,0.5-1,0.5-1.6,0c-0.8-0.7-1.5-1.5-2.3-2.3 c-0.3-0.3-0.5-0.6-0.3-1.1C5.5,9.3,5.8,9.1,6.3,9.1z\"/></g></svg>');filter:invert(100%)}.progress-icon{display:inline-block;flex:0 0 20px;width:28px;height:28px;background-size:contain;position:absolute;right:30px;z-index:1}progress-bar.error{background:#f8b3b1;background:rgba(74, 70, 70, 0.25);opacity:1}.progress-bar a{color:#fff}.download-link{padding-right:20px;color:#fff}.remove-media{display:inline-block;content:url('data:image/svg+xml;utf8,<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"0 0 40 40\" style=\"enable-background:new 0 0 40 40;\" xml:space=\"preserve\"><g><path d=\"M0,19.9C0.2,8.5,9.2-0.1,20.1,0C31.8,0.1,40.2,9.5,40,20.4c-0.2,11-8.9,19.7-20.1,19.6C8,39.9,0,30.5,0,19.9z M20,3.7 c-9,0-16.3,7-16.3,16.2C3.7,29,10.9,36.3,20,36.3c9,0,16.3-7.1,16.4-16.3C36.3,11,29.2,3.8,20,3.7z\"/><path d=\"M17.3,20c-0.2-0.2-0.3-0.4-0.5-0.6c-1-1-2-1.9-2.9-2.9c-0.5-0.5-0.8-1.1-0.7-1.9c0.1-0.7,0.5-1.2,1.2-1.4 c0.8-0.2,1.5,0,2.1,0.6c1,1,2,2,3,3.1c0.3,0.4,0.6,0.3,0.9,0c1-1,2-2,3-3c0.3-0.3,0.7-0.5,1.1-0.6c0.8-0.2,1.6,0.1,2,0.8 c0.4,0.8,0.3,1.7-0.4,2.4c-1,1-2,2-3,3c-0.2,0.2-0.3,0.4-0.5,0.6c1.2,1.2,2.3,2.3,3.4,3.4c0.6,0.6,0.9,1.3,0.6,2.2 c-0.4,1.1-1.7,1.6-2.6,1c-0.3-0.2-0.5-0.4-0.8-0.6c-1-1-1.9-1.9-2.9-2.9c-0.3-0.3-0.5-0.3-0.9,0c-1,1-2,2.1-3,3 c-0.4,0.4-1,0.6-1.5,0.8c-0.6,0.1-1.2-0.2-1.5-0.8c-0.4-0.6-0.5-1.3-0.1-1.9c0.2-0.3,0.4-0.5,0.6-0.7C15.1,22.3,16.2,21.2,17.3,20z \"/></g></svg>');flex:0 0 25px;width:25px;height:20px;align-items:center;opacity:0.25}.remove-media:hover{opacity:1;filter:invert(50%)sepia(100%)saturate(10000%)}.remove-media span{display:inline-block;text-indent:-9999px;color:transparent}";
4474
+
4475
+ let uid = 0;
4476
+ const UploadedFile$1 = /*@__PURE__*/ proxyCustomElement(class UploadedFile extends H {
4477
+ get el() { return this; }
4478
+ removeEvent;
4479
+ removeClicked = event => {
4480
+ event.stopPropagation();
4481
+ event.preventDefault();
4482
+ this.controller?.cancel();
4483
+ this.removeEvent.emit(this);
4484
+ };
4485
+ inputTarget;
4486
+ controller;
4487
+ _file;
4488
+ uid;
4489
+ constructor() {
4490
+ super();
4491
+ this.__registerHost();
4492
+ this.__attachShadow();
4493
+ this.removeEvent = createEvent(this, "uploaded-file:remove", 7);
4494
+ this.name = undefined;
4495
+ this.accepts = undefined;
4496
+ this.max = undefined;
4497
+ this.url = undefined;
4498
+ this.value = "";
4499
+ this.filename = undefined;
4500
+ this.src = undefined;
4501
+ this.filetype = undefined;
4502
+ this.size = undefined;
4503
+ this.state = "complete";
4504
+ this.percent = 100;
4505
+ this.preview = true;
4506
+ this.validationMessage = undefined;
4507
+ this.uid = uid++;
4508
+ this.inputTarget = html(`<input id="input-target-${this.uid}">`);
4509
+ }
4510
+ componentWillLoad() {
4511
+ this.el.appendChild(this.inputTarget);
4512
+ this.setMissingFiletype();
4513
+ }
4514
+ get file() {
4515
+ return this._file;
4516
+ }
4517
+ set file(file) {
4518
+ this.src = URL.createObjectURL(file);
4519
+ this.filename = file.name;
4520
+ this.size = file.size;
4521
+ this.state = "pending";
4522
+ this.percent = 0;
4523
+ this._file = file;
4524
+ }
4525
+ set signedId(val) {
4526
+ if (this.value !== val) {
4527
+ get(`/rails/active_storage/blobs/info/${val}`).then(blob => {
4528
+ this.src = `/rails/active_storage/blobs/redirect/${val}/${blob.filename}`;
4529
+ this.filename = blob.filename;
4530
+ this.size = blob.byte_size;
4531
+ this.state = "complete";
4532
+ this.percent = 100;
4533
+ this.value = val;
4534
+ });
4535
+ }
4536
+ }
4537
+ setMissingFiletype(_value, _previousValue) {
4538
+ if (!this.filetype && this.filename) {
4539
+ this.filetype = Extensions.getFileType(this.filename);
4540
+ }
4541
+ }
4542
+ start(_event) {
4543
+ this.state = "pending";
4544
+ this.percent = 0;
4545
+ }
4546
+ progress(event) {
4547
+ const { progress } = event.detail;
4548
+ this.percent = progress;
4549
+ }
4550
+ error(event) {
4551
+ event.preventDefault();
4552
+ const { error } = event.detail;
4553
+ this.state = "error";
4554
+ this.inputTarget.setCustomValidity(error);
4555
+ }
4556
+ end(_event) {
4557
+ if (this.state !== "error") {
4558
+ this.state = "complete";
4559
+ this.percent = 100;
4560
+ }
4561
+ }
4562
+ render() {
4563
+ return (h(Host, null, h("slot", null), h("figure", null, h("div", { class: "progress-details" }, h("progress-bar", { percent: this.percent, class: this.state }, h("a", { class: "download-link", href: this.src, download: this.filename, onClick: e => e.stopPropagation() }, this.filename)), h("span", { class: "progress-icon" }), h("a", { class: "remove-media", onClick: this.removeClicked, href: "#" }, h("span", null, "Remove media"))), this.preview ? h("file-preview", { src: this.src, filetype: this.filetype }) : '')));
4564
+ }
4565
+ componentDidRender() {
4566
+ morphdom(this.inputTarget, `
4567
+ <input
4568
+ id="input-target-${this.uid}"
4569
+ style="opacity: 0.01; width: 1px; height: 1px; z-index: -999; position: absolute;"
4570
+ name="${this.name}"
4571
+ value="${this.value}"
4572
+ >`);
4573
+ }
4574
+ componentDidLoad() {
4575
+ if (this.checkValidity() && this.state == "pending") {
4576
+ this.controller = new DirectUploadController(this.el);
4577
+ this.controller.dispatch("initialize", { controller: this.controller });
4578
+ }
4579
+ }
4580
+ checkValidity() {
4581
+ let errors = [];
4582
+ errors.push(...new Accepts(this).errors);
4583
+ errors.push(...new Max(this).errors);
4584
+ this.inputTarget.setCustomValidity(errors.join(" "));
4585
+ this.inputTarget.reportValidity();
4586
+ return errors.length === 0;
4587
+ }
4588
+ static get watchers() { return {
4589
+ "filename": ["setMissingFiletype"]
4590
+ }; }
4591
+ static get style() { return uploadedFileCss; }
4592
+ }, [1, "uploaded-file", {
4593
+ "name": [1537],
4594
+ "accepts": [1537],
4595
+ "max": [1538],
4596
+ "url": [1537],
4597
+ "value": [1537],
4598
+ "filename": [1537],
4599
+ "src": [1537],
4600
+ "filetype": [1537],
4601
+ "size": [1538],
4602
+ "state": [1537],
4603
+ "percent": [1538],
4604
+ "preview": [1540],
4605
+ "validationMessage": [1, "validation-message"]
4606
+ }, [[0, "direct-upload:initialize", "start"], [0, "direct-upload:start", "start"], [0, "direct-upload:progress", "progress"], [0, "direct-upload:error", "error"], [0, "direct-upload:end", "end"]], {
4607
+ "filename": ["setMissingFiletype"]
4608
+ }]);
4609
+
4610
+ const fileDropCss = "file-drop{display:flex;flex-direction:column;justify-content:center;align-items:center;box-sizing:border-box;min-height:60px;outline-offset:-10px;padding:20px;background:rgba(255, 255, 255, 0.25);text-align:center;transition:all 0.15s ease 0s;outline:rgba(0, 0, 0, 0.25) dashed 2px;font-size:13px}";
4611
+
4612
+ const FileDrop$1 = /*@__PURE__*/ proxyCustomElement(class FileDrop extends H {
4613
+ constructor() {
4614
+ super();
4615
+ this.__registerHost();
4616
+ this.for = undefined;
4617
+ }
4618
+ get el() { return this; }
4619
+ get fileTarget() {
4620
+ return document.querySelector(`#${this.for}`);
4621
+ }
4622
+ openFilePicker(_event) {
4623
+ this.fileTarget.click();
4624
+ }
4625
+ highlight(event) {
4626
+ event.preventDefault();
4627
+ this.el.classList.add("-dragover");
4628
+ }
4629
+ unhighlight(_event) {
4630
+ this.el.classList.remove("-dragover");
4631
+ }
4632
+ drop(event) {
4633
+ event.preventDefault();
4634
+ this.el.classList.remove("-dragover");
4635
+ this.fileTarget.files = event.dataTransfer.files;
4636
+ const changeEvent = new Event("change", { bubbles: true });
4637
+ this.fileTarget.dispatchEvent(changeEvent);
4638
+ }
4639
+ static get style() { return fileDropCss; }
4640
+ }, [0, "file-drop", {
4641
+ "for": [1537]
4642
+ }, [[0, "click", "openFilePicker"], [0, "dragover", "highlight"], [0, "dragleave", "unhighlight"], [0, "drop", "drop"]]]);
4643
+
4644
+ class FormController {
4645
+ static instance(form) {
4646
+ return form.bardFileFormController ||= new FormController(form);
4647
+ }
4648
+ progressContainerTarget;
4649
+ dialog;
4650
+ element;
4651
+ progressTargetMap;
4652
+ controllers;
4653
+ submitted;
4654
+ processing;
4655
+ errors;
4656
+ constructor(form) {
4657
+ this.element = form;
4658
+ this.progressTargetMap = {};
4659
+ this.controllers = [];
4660
+ this.submitted = false;
4661
+ this.processing = false;
4662
+ this.errors = false;
4663
+ this.element.insertAdjacentHTML("beforeend", `<dialog id="form-controller-dialog">
4664
+ <div class="direct-upload-wrapper">
4665
+ <div class="direct-upload-content">
4666
+ <h3>Uploading your media</h3>
4667
+ <div id="progress-container"></div>
4668
+ </div>
4669
+ </div>
4670
+ </dialog>`);
4671
+ this.dialog = this.element.querySelector("#form-controller-dialog");
4672
+ this.progressContainerTarget = this.dialog.querySelector("#progress-container");
4673
+ if (this.element.dataset.remote !== "true") {
4674
+ this.element.addEventListener("submit", event => this.submit(event));
4675
+ }
4676
+ window.addEventListener("beforeunload", event => this.beforeUnload(event));
4677
+ this.element.addEventListener("direct-upload:initialize", event => this.init(event));
4678
+ this.element.addEventListener("direct-upload:start", event => this.start(event));
4679
+ this.element.addEventListener("direct-upload:progress", event => this.progress(event));
4680
+ this.element.addEventListener("direct-upload:error", event => this.error(event));
4681
+ this.element.addEventListener("direct-upload:end", event => this.end(event));
4682
+ this.element.addEventListener("uploaded-file:remove", event => this.removeUploadedFile(event));
4683
+ }
4684
+ beforeUnload(event) {
4685
+ if (this.processing) {
4686
+ event.preventDefault();
4687
+ return (event.returnValue = "");
4688
+ }
4689
+ }
4690
+ submit(event) {
4691
+ event.preventDefault();
4692
+ this.submitted = true;
4693
+ this.startNextController();
4694
+ if (this.processing) {
4695
+ this.dialog.showModal();
4696
+ }
4697
+ }
4698
+ startNextController() {
4699
+ if (this.processing)
4700
+ return;
4701
+ const controller = this.controllers.shift();
4702
+ if (controller) {
4703
+ this.processing = true;
4704
+ controller.start(error => {
4705
+ if (error) {
4706
+ Array.from(this.element.querySelectorAll("input[type=file]"))
4707
+ .forEach((e) => e.disabled = false);
4708
+ }
4709
+ this.processing = false;
4710
+ this.startNextController();
4711
+ });
4712
+ }
4713
+ else {
4714
+ this.submitForm();
4715
+ }
4716
+ }
4717
+ submitForm() {
4718
+ if (this.submitted) {
4719
+ Array.from(this.element.querySelectorAll("input[type=file]"))
4720
+ .forEach((e) => e.disabled = true);
4721
+ window.setTimeout(() => {
4722
+ this.element.submit();
4723
+ }, 10);
4724
+ }
4725
+ }
4726
+ init(event) {
4727
+ const { id, file, controller } = event.detail;
4728
+ this.progressContainerTarget.insertAdjacentHTML("beforebegin", `
4729
+ <progress-bar id="direct-upload-${id}" class="direct-upload--pending">${file.name}</progress-bar>
4730
+ `);
4731
+ const progressTarget = document.getElementById(`direct-upload-${id}`);
4732
+ this.progressTargetMap[id] = progressTarget;
4733
+ this.controllers.push(controller);
4734
+ this.startNextController();
4735
+ }
4736
+ start(event) {
4737
+ this.progressTargetMap[event.detail.id].classList.remove("direct-upload--pending");
4738
+ }
4739
+ progress(event) {
4740
+ const { id, progress } = event.detail;
4741
+ this.progressTargetMap[id].percent = progress;
4742
+ }
4743
+ error(event) {
4744
+ event.preventDefault();
4745
+ const { id, error } = event.detail;
4746
+ const target = this.progressTargetMap[id];
4747
+ target.classList.add("direct-upload--error");
4748
+ target.title = error;
4749
+ }
4750
+ end(event) {
4751
+ this.progressTargetMap[event.detail.id].classList.add("direct-upload--complete");
4752
+ }
4753
+ removeUploadedFile(event) {
4754
+ const uploadedFile = event.detail;
4755
+ const id = uploadedFile.controller?.directUpload?.id;
4756
+ if (id) {
4757
+ document.getElementById(`direct-upload-${id}`).remove();
4758
+ delete this.progressTargetMap[id];
4759
+ }
4760
+ }
4761
+ }
4762
+
4763
+ const bardFileCss = ":host{display:block;padding:25px;color:var(--bard-file-text-color, #000);font-size:13px}:host *{box-sizing:border-box;position:relative}drag-and-drop{display:block;outline-offset:-10px;background:rgba(255,255,255, 0.25);margin:0;text-align:center;transition:all 0.15s;outline:2px dashed rgba(0,0,0,0.25);color:#444;font-size:14px}p{padding:10px 20px;margin:0}drag-and-drop.-full{width:100%}.-dragover{background:rgba(255,255,255,0.5);outline:2px dashed rgba(0,0,0,0.25)}.media-preview{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:center}// UPLOADER .direct-upload-wrapper{position:fixed;z-index:9999;top:0;left:0;width:100vw;height:100vh;display:flex;align-items:center;justify-content:center;background:rgba(#333, 0.9)}.direct-upload-content{display:block;background:#fcfcfc;padding:40px 60px 60px;border-radius:3px;width:60vw}.direct-upload-content h3{border-bottom:2px solid #1f1f1f;margin-bottom:20px}.separate-upload{padding:0 10px;margin-top:10px;font-size:0.9em}.direct-upload--pending{opacity:0.6}.direct-upload--complete{opacity:0.4}.direct-upload--error{border-color:red}input[type=file][data-direct-upload-url][disabled]{display:none}:host.separate-upload{padding:0 10px;margin-top:10px;font-size:0.9em}";
4764
+
4765
+ const BardFile$1 = /*@__PURE__*/ proxyCustomElement(class BardFile extends H {
4766
+ get el() { return this; }
4767
+ forceUpdate() { this._forceUpdate = !this._forceUpdate; }
4768
+ fileTargetId;
4769
+ fileTarget;
4770
+ hiddenTargetId;
4771
+ hiddenTarget;
4772
+ _files;
4773
+ constructor() {
4774
+ super();
4775
+ this.__registerHost();
4776
+ this.__attachShadow();
4777
+ this.name = undefined;
4778
+ this.directupload = undefined;
4779
+ this.multiple = false;
4780
+ this.required = false;
4781
+ this.accepts = undefined;
4782
+ this.max = undefined;
4783
+ this.preview = true;
4784
+ this._forceUpdate = false;
4785
+ this.fileTargetId = this.el.id;
4786
+ this.fileTarget = html(`<input id="${this.fileTargetId}">`);
4787
+ this.hiddenTargetId = `hidden-target-${this.el.getAttribute("name")}`;
4788
+ this.hiddenTarget = html(`<input id="${this.hiddenTargetId}">`);
4789
+ }
4790
+ componentWillLoad() {
4791
+ this.el.removeAttribute("id");
4792
+ FormController.instance(this.el.closest("form"));
4793
+ this.files = Array.from(this.el.children).filter(e => e.tagName == "UPLOADED-FILE");
4794
+ }
4795
+ // Methods
4796
+ get files() {
4797
+ return this._files;
4798
+ }
4799
+ set files(val) {
4800
+ this._files = val;
4801
+ if (!this.multiple)
4802
+ this._files = this._files.slice(-1);
4803
+ this.forceUpdate();
4804
+ this.fireChangeEvent();
4805
+ }
4806
+ get value() {
4807
+ return this.files.map(e => e.value);
4808
+ }
4809
+ set value(val) {
4810
+ const newValue = val || [];
4811
+ if (JSON.stringify(this.value) !== JSON.stringify(newValue)) { // this is insane. javascript is fucking garbage.
4812
+ this.files = newValue.map(signedId => Object.assign(new UploadedFile$1(), {
4813
+ name: this.name,
4814
+ preview: this.preview,
4815
+ signedId,
4816
+ }));
4817
+ }
4818
+ }
4819
+ fileTargetChanged(event) {
4820
+ if (event.target !== this.fileTarget)
4821
+ return;
4822
+ this.files.push(...Array.from(this.fileTarget.files).map(file => Object.assign(new UploadedFile$1(), {
4823
+ name: this.name,
4824
+ preview: this.preview,
4825
+ url: this.directupload,
4826
+ accepts: this.accepts,
4827
+ max: this.max,
4828
+ file,
4829
+ })));
4830
+ this.files = this.files;
4831
+ this.fileTarget.value = null;
4832
+ }
4833
+ removeUploadedFile(event) {
4834
+ arrayRemove(this.files, event.detail);
4835
+ this.files = this.files;
4836
+ }
4837
+ fireChangeEvent() {
4838
+ requestAnimationFrame(() => this.el.dispatchEvent(new Event("change", { bubbles: true })));
4839
+ }
4840
+ // Rendering
4841
+ render() {
4842
+ return (h(Host, null, h("file-drop", { for: this.fileTargetId }, h("p", { part: "title" }, h("strong", null, "Choose ", this.multiple ? "files" : "file", " "), h("span", null, "or drag ", this.multiple ? "them" : "it", " here.")), h("div", { class: `media-preview ${this.multiple ? '-stacked' : ''}` }, h("slot", null)))));
4843
+ }
4844
+ componentDidRender() {
4845
+ morphdom(this.fileTarget, `
4846
+ <input id="${this.fileTargetId}"
4847
+ type="file"
4848
+ ${this.multiple ? "multiple" : ""}
4849
+ ${this.required && this.files.length === 0 ? "required" : ""}
4850
+ style="opacity: 0.01; width: 1px; height: 1px; z-index: -999"
4851
+ >`);
4852
+ morphdom(this.hiddenTarget, `
4853
+ <input id="${this.hiddenTargetId}"
4854
+ type="hidden"
4855
+ name="${this.name}"
4856
+ ${this.files.length > 0 ? "disabled" : ""}
4857
+ >`);
4858
+ const wrapper = document.createElement("div");
4859
+ wrapper.replaceChildren(this.fileTarget, this.hiddenTarget, ...this.files);
4860
+ morphdom(this.el, wrapper, { childrenOnly: true });
4861
+ }
4862
+ // Validations
4863
+ checkValidity() {
4864
+ return this.fileTarget.checkValidity();
4865
+ }
4866
+ setCustomValidity(msg) {
4867
+ this.fileTarget.setCustomValidity(msg);
4868
+ }
4869
+ reportValidity() {
4870
+ this.fileTarget.reportValidity();
4871
+ }
4872
+ get validationMessage() {
4873
+ return this.fileTarget.validationMessage;
4874
+ }
4875
+ static get style() { return bardFileCss; }
4876
+ }, [1, "bard-file", {
4877
+ "name": [1],
4878
+ "directupload": [1],
4879
+ "multiple": [4],
4880
+ "required": [4],
4881
+ "accepts": [1],
4882
+ "max": [2],
4883
+ "preview": [4],
4884
+ "_forceUpdate": [32]
4885
+ }, [[0, "change", "fileTargetChanged"], [0, "uploaded-file:remove", "removeUploadedFile"], [0, "direct-upload:end", "fireChangeEvent"]]]);
4886
+
4887
+ const BardFile = BardFile$1;
4888
+
4889
+ const FileDrop = FileDrop$1;
4890
+
4891
+ const FilePreview = FilePreview$1;
4892
+
4893
+ const ProgressBar = ProgressBar$1;
4894
+
4895
+ const UploadedFile = UploadedFile$1;
4896
+
4897
+ const defineCustomElements = (opts) => {
4898
+ if (typeof customElements !== 'undefined') {
4899
+ [
4900
+ BardFile,
4901
+ FileDrop,
4902
+ FilePreview,
4903
+ ProgressBar,
4904
+ UploadedFile,
4905
+ ].forEach(cmp => {
4906
+ if (!customElements.get(cmp.is)) {
4907
+ customElements.define(cmp.is, cmp, opts);
4908
+ }
4909
+ });
4910
+ }
4911
+ };
4912
+
4913
+ defineCustomElements();