pinstripe 0.33.0 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/README.md +1 -1
  2. package/lib/class.js +1 -63
  3. package/lib/component.js +123 -99
  4. package/lib/components/helpers.js +6 -5
  5. package/lib/components/index.js +12 -0
  6. package/lib/components/pinstripe_anchor.js +5 -4
  7. package/lib/components/pinstripe_body.js +13 -4
  8. package/lib/components/pinstripe_document.js +14 -2
  9. package/lib/components/pinstripe_form.js +36 -5
  10. package/lib/components/pinstripe_frame.js +30 -19
  11. package/lib/components/pinstripe_menu.js +33 -0
  12. package/lib/components/pinstripe_modal.js +94 -30
  13. package/lib/components/pinstripe_overlay.js +5 -7
  14. package/lib/components/pinstripe_popover.js +86 -0
  15. package/lib/components/pinstripe_progress_bar.js +6 -4
  16. package/lib/components/pinstripe_script.js +6 -3
  17. package/lib/components/pinstripe_skeleton.js +4 -2
  18. package/lib/constants.js +1 -26
  19. package/lib/index.js +0 -12
  20. package/lib/inflector.js +1 -187
  21. package/lib/initialize.js +1 -3
  22. package/lib/lru_cache.js +1 -52
  23. package/lib/proof_of_work.js +1 -83
  24. package/lib/registry.js +1 -137
  25. package/lib/trapify.js +1 -31
  26. package/lib/virtual_node.js +1 -171
  27. package/package.json +9 -41
  28. package/babel.config.cjs +0 -18
  29. package/cli.js +0 -36
  30. package/jest.config.cjs +0 -6
  31. package/lib/app.js +0 -37
  32. package/lib/apps/_file_importer.js +0 -1
  33. package/lib/apps/docs.js +0 -6
  34. package/lib/apps/main.js +0 -6
  35. package/lib/background_job.js +0 -42
  36. package/lib/background_jobs/_file_importer.js +0 -1
  37. package/lib/background_jobs/purge_used_hashes.js +0 -12
  38. package/lib/client.js +0 -20
  39. package/lib/command.js +0 -68
  40. package/lib/command.test.js +0 -32
  41. package/lib/commands/_file_importer.js +0 -1
  42. package/lib/commands/drop_database.js +0 -6
  43. package/lib/commands/generate_app.js +0 -43
  44. package/lib/commands/generate_background_job.js +0 -47
  45. package/lib/commands/generate_command.js +0 -39
  46. package/lib/commands/generate_component.js +0 -50
  47. package/lib/commands/generate_migration.js +0 -55
  48. package/lib/commands/generate_model.js +0 -40
  49. package/lib/commands/generate_project.js +0 -147
  50. package/lib/commands/generate_service.js +0 -34
  51. package/lib/commands/generate_static_site.js +0 -92
  52. package/lib/commands/generate_view.js +0 -80
  53. package/lib/commands/init_database.js +0 -9
  54. package/lib/commands/list_apps.js +0 -15
  55. package/lib/commands/list_background_jobs.js +0 -15
  56. package/lib/commands/list_commands.js +0 -21
  57. package/lib/commands/list_components.js +0 -16
  58. package/lib/commands/list_migrations.js +0 -15
  59. package/lib/commands/list_models.js +0 -15
  60. package/lib/commands/list_services.js +0 -15
  61. package/lib/commands/list_views.js +0 -19
  62. package/lib/commands/migrate_database.js +0 -6
  63. package/lib/commands/reset_database.js +0 -9
  64. package/lib/commands/run_background_job.js +0 -11
  65. package/lib/commands/seed_database.js +0 -6
  66. package/lib/commands/show_config.js +0 -6
  67. package/lib/commands/start_repl.js +0 -6
  68. package/lib/commands/start_server.js +0 -28
  69. package/lib/components/_file_importer.js +0 -1
  70. package/lib/context.js +0 -40
  71. package/lib/database/client.js +0 -322
  72. package/lib/database/column_reference.js +0 -13
  73. package/lib/database/constants.js +0 -99
  74. package/lib/database/index.js +0 -7
  75. package/lib/database/migration.js +0 -32
  76. package/lib/database/migrator.js +0 -28
  77. package/lib/database/row.js +0 -387
  78. package/lib/database/singleton.js +0 -12
  79. package/lib/database/table.js +0 -518
  80. package/lib/database/table_reference.js +0 -33
  81. package/lib/database/union.js +0 -130
  82. package/lib/database.js +0 -147
  83. package/lib/defer.js +0 -35
  84. package/lib/defer.test.js +0 -48
  85. package/lib/escape_html.js +0 -2
  86. package/lib/extensions/_file_importer.js +0 -1
  87. package/lib/extensions/multi-tenant/database/row.js +0 -48
  88. package/lib/extensions/multi-tenant/database/table.js +0 -30
  89. package/lib/extensions/multi-tenant/database.js +0 -18
  90. package/lib/extensions/multi-tenant/index.js +0 -4
  91. package/lib/extensions/multi-tenant/migrations/1627976174_create_tenant_table_and_add_tenant_id_to_existing_tables.js +0 -20
  92. package/lib/extensions/multi-tenant/migrations/_file_importer.js +0 -2
  93. package/lib/extensions/multi-tenant/models/_file_importer.js +0 -1
  94. package/lib/extensions/multi-tenant/models/tenant.js +0 -14
  95. package/lib/extensions/multi-tenant/services/_file_importer.js +0 -2
  96. package/lib/extensions/multi-tenant/services/database.js +0 -35
  97. package/lib/extensions/multi-tenant/services/run_background_job.js +0 -27
  98. package/lib/html.js +0 -72
  99. package/lib/import_all.js +0 -94
  100. package/lib/lru_cache.test.js +0 -45
  101. package/lib/markdown.js +0 -66
  102. package/lib/migrations/1708772281_create_used_hash.js +0 -9
  103. package/lib/migrations/_file_importer.js +0 -2
  104. package/lib/model.js +0 -110
  105. package/lib/models/_file_importer.js +0 -2
  106. package/lib/models/used_hash.js +0 -7
  107. package/lib/project.js +0 -70
  108. package/lib/service_consumer.js +0 -16
  109. package/lib/service_factory.js +0 -22
  110. package/lib/services/_file_importer.js +0 -1
  111. package/lib/services/app.js +0 -11
  112. package/lib/services/bot.js +0 -70
  113. package/lib/services/cli_utils.js +0 -25
  114. package/lib/services/client_builder.js +0 -70
  115. package/lib/services/config.js +0 -66
  116. package/lib/services/cookies.js +0 -19
  117. package/lib/services/create_model.js +0 -8
  118. package/lib/services/css_classes_for.js +0 -13
  119. package/lib/services/database.js +0 -14
  120. package/lib/services/defer.js +0 -8
  121. package/lib/services/docs.js +0 -93
  122. package/lib/services/fetch.js +0 -86
  123. package/lib/services/format_date.js +0 -8
  124. package/lib/services/fs_builder.js +0 -132
  125. package/lib/services/inflector.js +0 -8
  126. package/lib/services/initial_params.js +0 -13
  127. package/lib/services/only_once.js +0 -24
  128. package/lib/services/params.js +0 -13
  129. package/lib/services/parse_html.js +0 -8
  130. package/lib/services/project.js +0 -8
  131. package/lib/services/render_form.js +0 -120
  132. package/lib/services/render_html.js +0 -8
  133. package/lib/services/render_markdown.js +0 -9
  134. package/lib/services/render_table.js +0 -48
  135. package/lib/services/render_view.js +0 -6
  136. package/lib/services/repl.js +0 -54
  137. package/lib/services/run_background_job.js +0 -8
  138. package/lib/services/run_command.js +0 -8
  139. package/lib/services/run_in_new_workspace.js +0 -11
  140. package/lib/services/send_mail.js +0 -47
  141. package/lib/services/server.js +0 -105
  142. package/lib/services/trapify.js +0 -8
  143. package/lib/services/view.js +0 -6
  144. package/lib/singleton.js +0 -13
  145. package/lib/string_reader.js +0 -22
  146. package/lib/unescape_html.js +0 -2
  147. package/lib/unescape_html.test.js +0 -9
  148. package/lib/util.js +0 -12
  149. package/lib/validation_error.js +0 -7
  150. package/lib/view.js +0 -120
  151. package/lib/view_file_importers/js.js +0 -38
  152. package/lib/view_file_importers/md.js +0 -50
  153. package/lib/views/_file_importer.js +0 -1
  154. package/lib/views/docs/_404.js +0 -16
  155. package/lib/views/docs/_footer.js +0 -67
  156. package/lib/views/docs/_header.js +0 -17
  157. package/lib/views/docs/_hero.js +0 -59
  158. package/lib/views/docs/_layout.js +0 -118
  159. package/lib/views/docs/_navbar.js +0 -99
  160. package/lib/views/docs/_sidebar.js +0 -31
  161. package/lib/views/docs/default.js +0 -6
  162. package/lib/views/docs/docs/default.js +0 -24
  163. package/lib/views/docs/docs/guides/introduction.md +0 -18
  164. package/lib/views/docs/images/logo.svg +0 -7
  165. package/lib/views/docs/index.js +0 -16
  166. package/lib/views/shared/_button.js +0 -100
  167. package/lib/views/shared/_content.js +0 -81
  168. package/lib/views/shared/_danger_area.js +0 -78
  169. package/lib/views/shared/_editable_area.js +0 -37
  170. package/lib/views/shared/_form.js +0 -273
  171. package/lib/views/shared/_navbar.js +0 -110
  172. package/lib/views/shared/_pagination.js +0 -47
  173. package/lib/views/shared/_panel.js +0 -69
  174. package/lib/views/shared/_section.js +0 -45
  175. package/lib/views/shared/_shell/index.js +0 -26
  176. package/lib/views/shared/_shell/javascripts/all.js.js +0 -7
  177. package/lib/views/shared/_shell/javascripts/all.js.map.js +0 -7
  178. package/lib/views/shared/_shell/stylesheets/all.css +0 -4
  179. package/lib/views/shared/_shell/stylesheets/global.css +0 -126
  180. package/lib/views/shared/_shell/stylesheets/reset.css +0 -74
  181. package/lib/views/shared/_shell/stylesheets/vars.css +0 -25
  182. package/lib/views/shared/_shell/stylesheets/view.css.js +0 -43
  183. package/lib/views/shared/_table.js +0 -139
  184. package/lib/virtual_node.test.js +0 -28
  185. package/lib/workspace.js +0 -21
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  # Welcome to Pinstripe
3
3
 
4
- A slick web framework for Node.js.
4
+ A slick web framework for your browser.
5
5
 
6
6
  ## License
7
7
 
package/lib/class.js CHANGED
@@ -1,64 +1,2 @@
1
1
 
2
- export class Class {
3
-
4
- static extend(){
5
- return class extends this {};
6
- }
7
-
8
- static include(...includes){
9
- includes.forEach(include => {
10
- if(typeof include.meta == 'function') include.meta.call(this);
11
- this.prototype.assignProps(include, name => name != 'meta');
12
- });
13
- return this;
14
- }
15
-
16
- static assignProps(...sources){
17
- return assignProps(this, ...sources);
18
- }
19
-
20
- static new(...args){
21
- return new this(...args);
22
- }
23
-
24
- static get parent(){
25
- return this.__proto__;
26
- }
27
-
28
- constructor(...args){
29
- let out = this.initialize(...args);
30
- if(typeof out?.then == 'function'){
31
- return out.then(out => out || this);
32
- }
33
- return out || this;
34
- }
35
-
36
- initialize(){
37
-
38
- }
39
-
40
- assignProps(...sources){
41
- return assignProps(this, ...sources);
42
- }
43
- }
44
-
45
- const assignProps = (target, ...sources) => {
46
- const fn = typeof sources[sources.length - 1] == 'function' ? sources.pop() : () => true;
47
-
48
- sources.forEach(source => {
49
- Object.getOwnPropertyNames(source).forEach(name => {
50
- if(!fn(name)){
51
- return;
52
- }
53
- const descriptor = { ...Object.getOwnPropertyDescriptor(source, name) };
54
- const { get: targetGet, set: targetSet } = (Object.getOwnPropertyDescriptor(target, name) || {});
55
- const { get = targetGet, set = targetSet } = descriptor;
56
-
57
- if(get) descriptor.get = get;
58
- if(set) descriptor.set = set;
59
-
60
- Object.defineProperty(target, name, descriptor);
61
- });
62
- });
63
- return target;
64
- };
2
+ export { Class } from '@sintra/utils';
package/lib/component.js CHANGED
@@ -1,13 +1,10 @@
1
1
 
2
- import { fileURLToPath } from 'url'; // pinstripe-if-client: const fileURLToPath = undefined;
3
-
4
2
  import { Class } from './class.js';
5
3
  import { TEXT_ONLY_TAGS } from './constants.js';
6
4
  import { Inflector } from './inflector.js';
7
5
  import { VirtualNode } from './virtual_node.js';
8
6
  import { Registry } from './registry.js';
9
7
  import { ComponentEvent } from './component_event.js';
10
- import { Client } from './client.js'; // pinstripe-if-client: const Client = undefined;
11
8
  import { generateProofOfWork } from './proof_of_work.js';
12
9
 
13
10
  export const Component = Class.extend().include({
@@ -24,7 +21,7 @@ export const Component = Class.extend().include({
24
21
  node._component.attributes['data-component'] || (node._component.type == '#document' ? 'pinstripe-document' : node._component.type),
25
22
  node
26
23
  );
27
- (node._component.attributes.class || '').trim().split(/\s+/).forEach((className) => {
24
+ if(!this.isFromCachedHtml) (node._component.attributes.class || '').trim().split(/\s+/).forEach((className) => {
28
25
  const decoratorMethodName = `.${className}`;
29
26
  if(typeof node._component[decoratorMethodName] == 'function'){
30
27
  node._component[decoratorMethodName]();
@@ -39,38 +36,11 @@ export const Component = Class.extend().include({
39
36
  return Inflector.instance.dasherize(name);
40
37
  }
41
38
  });
42
-
43
- this.FileImporter.register('js', {
44
- meta(){
45
- const { importFile } = this.prototype;
46
-
47
- this.include({
48
- async importFile(params){
49
- const { filePath, relativeFilePathWithoutExtension } = params;
50
- if((await import(filePath)).default){
51
- Client.instance.addModule(`
52
- import { Component } from ${JSON.stringify(fileURLToPath(`${import.meta.url}/../index.js`))};
53
- import include from ${JSON.stringify(filePath)};
54
- Component.register(${JSON.stringify(relativeFilePathWithoutExtension)}, include);
55
- `);
56
- } else {
57
- Client.instance.addModule(`
58
- import ${JSON.stringify(filePath)};
59
- `);
60
- }
61
- return importFile.call(this, params);
62
- }
63
- });
64
- }
65
- });
66
39
  },
67
40
 
68
41
  initialize(node, skipInit = false){
69
42
  this.node = node;
70
- this._registeredEventListeners = [];
71
- this._registeredObservers = [];
72
- this._registeredTimers = [];
73
- this._registeredAbortControllers = [];
43
+ this._managedResources = [];
74
44
  this._virtualNodeFilters = [];
75
45
 
76
46
  this.addVirtualNodeFilter(function(){
@@ -290,6 +260,14 @@ export const Component = Class.extend().include({
290
260
  return Component.instanceFor(this.node.shadowRoot);
291
261
  },
292
262
 
263
+ get isFromPlaceholderHtml(){
264
+ return this.frame?.status == 'using-placeholder-html';
265
+ },
266
+
267
+ get isFromCachedHtml(){
268
+ return this.frame?.status == 'using-cached-html';
269
+ },
270
+
293
271
  focus(){
294
272
  this.node.focus();
295
273
  return this;
@@ -306,6 +284,20 @@ export const Component = Class.extend().include({
306
284
  }
307
285
  },
308
286
 
287
+ manage(resource){
288
+ const destroy = resource.destroy;
289
+ const that = this;
290
+ Object.assign(resource, {
291
+ destroy(){
292
+ const out = destroy.call(this);
293
+ that._managedResources = that._managedResources.filter(item => item !== this);
294
+ return out;
295
+ }
296
+ });
297
+ this._managedResources.push(resource);
298
+ return resource;
299
+ },
300
+
309
301
  on(name, ...args){
310
302
  const fn = args.pop()
311
303
  const selector = args.pop()
@@ -323,9 +315,9 @@ export const Component = Class.extend().include({
323
315
 
324
316
  this.node.addEventListener(name, wrapperFn);
325
317
 
326
- this._registeredEventListeners.push([name, wrapperFn]);
327
-
328
- return this;
318
+ return this.manage({
319
+ destroy: () => this.node.removeEventListener(name, wrapperFn)
320
+ });
329
321
  },
330
322
 
331
323
  trigger(name, options = {}){
@@ -345,16 +337,22 @@ export const Component = Class.extend().include({
345
337
  return this;
346
338
  },
347
339
 
348
- setTimeout(...args){
349
- const out = setTimeout(...args);
350
- this._registeredTimers.push(out);
340
+ setTimeout(fn, ...args){
341
+ const timeout = setTimeout(() => {
342
+ fn();
343
+ out.destroy();
344
+ }, ...args);
345
+ const out = this.manage({
346
+ destroy: () => clearTimeout(timeout)
347
+ });
351
348
  return out;
352
349
  },
353
350
 
354
351
  setInterval(...args){
355
- const out = setInterval(...args);
356
- this._registeredTimers.push(out);
357
- return out;
352
+ const interval = setInterval(...args);
353
+ return this.manage({
354
+ destroy: () => clearInterval(interval)
355
+ });
358
356
  },
359
357
 
360
358
  remove(){
@@ -442,53 +440,57 @@ export const Component = Class.extend().include({
442
440
  subtree: true
443
441
  });
444
442
 
445
- this._registeredObservers.push(observer);
446
-
447
- return this;
443
+ return this.manage({
444
+ destroy: () => observer.disconnect()
445
+ });
448
446
  },
449
447
 
450
- async fetch(url, options = {}){
451
- const { minimumDelay = 0, requiresProofOfWork = false, ...otherOptions } = options;
452
- const { progressBar } = this.document;
453
- const frame = this.frame || this;
454
- const normalizedUrl = new URL(url, frame.url);
448
+ fetch(url, options = {}){
455
449
  const abortController = new AbortController();
456
- this._registeredAbortControllers.push(abortController);
457
- progressBar.start();
458
450
  let minimumDelayTimeout;
459
- const cleanUp = () => {
460
- clearTimeout(minimumDelayTimeout);
461
- this._registeredAbortControllers = this._registeredAbortControllers.filter(item => item !== abortController);
462
- progressBar.stop();
463
- };
464
- try {
465
- if(requiresProofOfWork){
466
- if(!(otherOptions.body instanceof FormData)) throw new Error(`Proof of work requires form data to be present`);
467
- const values = {};
468
- otherOptions.body.forEach((value, key) => values[key] = value);
469
- otherOptions.body.append('_proofOfWork', await generateProofOfWork(values, {
470
- abortSignal: abortController.signal,
471
- onProgress: progress => this.trigger('proofOfWorkProgress', { data: progress, bubbles: false })
472
- }))
451
+ let rejectMinimumDelay;
452
+ let isSuccess = false;
453
+
454
+ const promise = (async () => {
455
+ const { minimumDelay = 0, requiresProofOfWork = false, ...otherOptions } = options;
456
+ const frame = this.frame || this;
457
+ const normalizedUrl = new URL(url, frame.url);
458
+
459
+ try {
460
+ if(requiresProofOfWork){
461
+ if(!(otherOptions.body instanceof FormData)) throw new Error(`Proof of work requires form data to be present`);
462
+ const values = {};
463
+ otherOptions.body.forEach((value, key) => values[key] = value);
464
+ otherOptions.body.append('_proofOfWork', await generateProofOfWork(values, {
465
+ abortSignal: abortController.signal,
466
+ onProgress: progress => this.trigger('proofOfWorkProgress', { data: progress, bubbles: false })
467
+ }))
468
+ }
469
+ const promises = [
470
+ this.document.httpProxy.fetch(normalizedUrl, { signal: abortController.signal, ...otherOptions }),
471
+ new Promise((resolve, reject) => {
472
+ minimumDelayTimeout = setTimeout(resolve, minimumDelay);
473
+ rejectMinimumDelay = reject;
474
+ })
475
+ ];
476
+ const [ out ] = await Promise.all(promises);
477
+ isSuccess = true;
478
+ promise.destroy();
479
+ return out;
480
+ } catch(e){
481
+ promise.destroy();
482
+ throw e;
473
483
  }
474
- const promises = [
475
- fetch(normalizedUrl, { signal: abortController.signal, ...otherOptions }),
476
- new Promise(resolve => minimumDelayTimeout = setTimeout(resolve, minimumDelay))
477
- ];
478
- const [ out ] = await Promise.all(promises);
479
- cleanUp();
480
- return out;
481
- } catch(e){
482
- cleanUp();
483
- throw e;
484
- }
485
- },
486
-
487
- abort(){
488
- while(this._registeredAbortControllers.length){
489
- this._registeredAbortControllers.pop().abort();
490
- }
491
- return this;
484
+ })();
485
+
486
+ return this.manage(Object.assign(promise, {
487
+ destroy: () => {
488
+ if(isSuccess) return;
489
+ if(!abortController.signal.aborted) abortController.abort(`Request aborted`);
490
+ clearTimeout(minimumDelayTimeout);
491
+ if(rejectMinimumDelay) rejectMinimumDelay();
492
+ }
493
+ }));
492
494
  },
493
495
 
494
496
  find(...args){
@@ -526,29 +528,15 @@ function clean(){
526
528
 
527
529
  [...this.node.childNodes].forEach(node => node._component && clean.call(node._component));
528
530
 
529
- while(this._registeredEventListeners.length){
530
- this.node.removeEventListener(...this._registeredEventListeners.pop());
531
+ while(this._managedResources.length){
532
+ this._managedResources.pop().destroy();
531
533
  }
532
534
 
533
- while(this._registeredObservers.length){
534
- this._registeredObservers.pop().disconnect();
535
- }
536
-
537
- clearTimers.call(this);
538
-
539
- this.abort();
540
-
541
535
  if(this._overlayChild) this._overlayChild.remove();
542
536
 
543
537
  delete this.node._component;
544
538
  }
545
539
 
546
- function clearTimers(){
547
- while(this._registeredTimers.length){
548
- clearTimeout(this._registeredTimers.pop());
549
- }
550
- }
551
-
552
540
  function initChildren(){
553
541
  if(this.node.shadowRoot){
554
542
  this.shadow.children.forEach(child => initChildren.call(child));
@@ -614,6 +602,8 @@ function patchAttributes(attributes){
614
602
  }
615
603
 
616
604
  function patchChildren(virtualChildren){
605
+ if(this.type == 'head') return patchHeadChildren.call(this, virtualChildren);
606
+
617
607
  const children = [...this.node.childNodes].map(
618
608
  node => new Component(node, true)
619
609
  );
@@ -646,6 +636,40 @@ function patchChildren(virtualChildren){
646
636
  }
647
637
  }
648
638
 
639
+ function patchHeadChildren(virtualChildren){
640
+ const children = [...this.node.childNodes].map(
641
+ node => new Component(node, true)
642
+ );
643
+
644
+ const stylesheets = {};
645
+ for(let i = 0; i < virtualChildren.length; i++){
646
+ const virtualChild = virtualChildren[i];
647
+ if(virtualChild.type != 'link') continue;
648
+ if(virtualChild.attributes.rel != 'stylesheet') continue;
649
+ const href = virtualChild.attributes.href;
650
+ stylesheets[href] = virtualChild;
651
+ }
652
+ while(children.length > 0){
653
+ const child = children.shift();
654
+ if(child.type == 'link' && child.attributes.rel == 'stylesheet'){
655
+ const { href } = child.attributes;
656
+ const stylesheet = stylesheets[href];
657
+ if(stylesheet){
658
+ patch.call(child, stylesheet.attributes, stylesheet.children);
659
+ continue;
660
+ }
661
+ }
662
+ remove.call(child);
663
+ }
664
+
665
+ for(let i = 0; i < virtualChildren.length; i++){
666
+ const virtualChild = virtualChildren[i];
667
+ if(virtualChild.type == 'script') continue;
668
+ if(virtualChild.type == 'link' && virtualChild.attributes.rel == 'stylesheet' && stylesheets[virtualChild.attributes.href]) continue;
669
+ insert.call(this, virtualChild, null, false);
670
+ }
671
+ }
672
+
649
673
  function insert(virtualNode, referenceChild, returnComponent = true){
650
674
  const { type, attributes, children } = virtualNode;
651
675
 
@@ -3,7 +3,7 @@ import { LruCache } from '../lru_cache.js';
3
3
 
4
4
  export const loadCache = LruCache.new();
5
5
 
6
- export function loadFrame(confirm, target, method, url, placeholderUrl, requiresProofOfWork = false){
6
+ export function loadFrame({ confirm, target, method, url, placeholderUrl, requiresProofOfWork = false, values = this.values }){
7
7
  if(confirm && !window.confirm(confirm)){
8
8
  return;
9
9
  }
@@ -11,15 +11,17 @@ export function loadFrame(confirm, target, method, url, placeholderUrl, requires
11
11
  let frame;
12
12
 
13
13
  if(target == '_overlay'){
14
- this.document.body.clip();
15
14
  frame = this.document.descendants.find(node => node.is('body')).append(`<pinstripe-overlay load-on-init="false"></pinstripe-overlay>`).pop();
16
15
  frame._parent = this;
17
16
  this._overlayChild = frame;
18
- } else {
17
+ } else if(target) {
19
18
  frame = getFrame.call(this, target);
20
- if(!frame) return;
19
+ } else if(this.isFrame) {
20
+ frame = this;
21
21
  }
22
22
 
23
+ if(!frame) return;
24
+
23
25
  url = normalizeUrl(url || frame.url, this.frame.url);
24
26
  if(url.protocol != 'data:' && (url.host != frame.url.host || url.port != frame.url.port)){
25
27
  return;
@@ -29,7 +31,6 @@ export function loadFrame(confirm, target, method, url, placeholderUrl, requires
29
31
 
30
32
  if(method.match(/POST|PUT|PATCH/i)){
31
33
  const formData = new FormData();
32
- const values = this.values;
33
34
  Object.keys(values).forEach((name) => formData.append(name, values[name]));
34
35
  frame.load(url, { method, body: formData, placeholderUrl, requiresProofOfWork });
35
36
  } else {
@@ -1 +1,13 @@
1
1
 
2
+ import './pinstripe_anchor.js';
3
+ import './pinstripe_body.js';
4
+ import './pinstripe_document.js';
5
+ import './pinstripe_form.js';
6
+ import './pinstripe_frame.js';
7
+ import './pinstripe_menu.js';
8
+ import './pinstripe_modal.js';
9
+ import './pinstripe_overlay.js';
10
+ import './pinstripe_popover.js';
11
+ import './pinstripe_progress_bar.js';
12
+ import './pinstripe_script.js';
13
+ import './pinstripe_skeleton.js';
@@ -1,15 +1,16 @@
1
1
 
2
+ import { Component } from "../component.js";
2
3
  import { loadFrame, getFrame, normalizeUrl } from "./helpers.js";
3
4
 
4
- export default {
5
+ Component.register('pinstripe-anchor', {
5
6
  initialize(...args){
6
7
  this.constructor.parent.prototype.initialize.call(this, ...args);
7
8
  this.on('click', (event) => {
8
9
  const { confirm, target = '_self', method = 'GET', href, placeholder } = this.params;
10
+ if(target == '_blank') return;
9
11
  if(normalizeUrl(href, window.location.href).host != window.location.host) return;
10
12
  event.preventDefault();
11
- event.stopPropagation();
12
- loadFrame.call(this, confirm, target, method, href, placeholder);
13
+ loadFrame.call(this, { confirm, target, method, url: href, placeholderUrl: placeholder });
13
14
  });
14
15
 
15
16
  const { target = '_self', method = 'GET', href, placeholder, preload } = this.params;
@@ -21,4 +22,4 @@ export default {
21
22
 
22
23
  if(this.is('input, textarea')) this.on('keyup', (event) => this.trigger('click'));
23
24
  }
24
- };
25
+ });
@@ -1,5 +1,7 @@
1
1
 
2
- export default {
2
+ import { Component } from "../component.js";
3
+
4
+ Component.register('pinstripe-body', {
3
5
  initialize(...args){
4
6
  this.constructor.parent.prototype.initialize.call(this, ...args);
5
7
 
@@ -8,6 +10,8 @@ export default {
8
10
  <slot>
9
11
  <div class="styles"></div>
10
12
  `);
13
+
14
+ this.clipCounter = 0;
11
15
  },
12
16
 
13
17
  get progressBar(){
@@ -18,7 +22,8 @@ export default {
18
22
  },
19
23
 
20
24
  clip(){
21
- this.shadow.find('.styles').patch(`
25
+ this.clipCounter++;
26
+ if(this.clipCounter == 1) this.shadow.find('.styles').patch(`
22
27
  <style>
23
28
  :host {
24
29
  overflow: hidden !important;
@@ -28,6 +33,10 @@ export default {
28
33
  },
29
34
 
30
35
  unclip(){
31
- this.shadow.find('.styles').patch('');
36
+ this.clipCounter--;
37
+ if(this.clipCounter <= 0){
38
+ this.clipCounter = 0;
39
+ this.shadow.find('.styles').patch('');
40
+ }
32
41
  }
33
- };
42
+ });
@@ -1,9 +1,10 @@
1
1
 
2
+ import { Component } from "../component.js";
2
3
  import { loadCache, normalizeUrl } from "./helpers.js";
3
4
 
4
5
  const preloading = {};
5
6
 
6
- export default {
7
+ Component.register('pinstripe-document', {
7
8
  meta(){
8
9
  this.include('pinstripe-frame');
9
10
 
@@ -29,6 +30,17 @@ export default {
29
30
 
30
31
  isDocument: true,
31
32
 
33
+ get httpProxy(){
34
+ if(!this._httpProxy){
35
+ this._httpProxy = {
36
+ fetch(...args){
37
+ return fetch(...args);
38
+ }
39
+ };
40
+ }
41
+ return this._httpProxy;
42
+ },
43
+
32
44
  get head(){
33
45
  if(!this._head){
34
46
  this._head = this.find('head');
@@ -77,4 +89,4 @@ export default {
77
89
  loadCache.put(`${this.document.loadCacheNamespace}:${url}`, html);
78
90
  delete preloading[url.toString()];
79
91
  }
80
- };
92
+ });
@@ -1,12 +1,14 @@
1
1
 
2
+ import { Component } from "../component.js";
2
3
  import { loadFrame, getFrame, normalizeUrl } from "./helpers.js";
3
4
 
4
- export default {
5
+ Component.register('pinstripe-form', {
5
6
  initialize(...args){
6
7
  this.constructor.parent.prototype.initialize.call(this, ...args);
7
8
 
8
9
  const { confirm, target = '_self', method = 'GET', action, placeholder, requiresProofOfWork, disabled } = this.params;
9
-
10
+ const frame = target == '_overlay' ? this.frame : getFrame.call(this, target);
11
+
10
12
  this.on('submit', (event) => {
11
13
  event.preventDefault();
12
14
  event.stopPropagation();
@@ -16,14 +18,31 @@ export default {
16
18
  ...this.attributes,
17
19
  [this.params.component ? 'data-loading' : 'loading']: 'true'
18
20
  });
21
+
22
+ delete frame._previousHash;
23
+ this._watchInterval?.destroy();
19
24
 
20
- loadFrame.call(this, confirm, target, method, action, placeholder, requiresProofOfWork == 'true');
25
+ loadFrame.call(this, { confirm, target, method, url: action, placeholderUrl: placeholder, requiresProofOfWork: requiresProofOfWork == 'true' });
21
26
  });
22
27
 
23
28
  this._initialHash = JSON.stringify(this.values);
24
29
 
25
- const frame = target == '_overlay' ? this.frame : getFrame.call(this, target);
30
+ if(this.isFromPlaceholderHtml) return;
31
+
26
32
  if(placeholder != undefined) this.document.preload(normalizeUrl(placeholder, frame.url));
33
+
34
+ const hasValuesToWatch = Object.keys(valuesToWatch.call(this)).length > 0;
35
+ if(!hasValuesToWatch) return;
36
+
37
+ frame._previousHash ||= JSON.stringify(valuesToWatch.call(this));
38
+
39
+ this._watchInterval = this.setInterval(() => {
40
+ const currentHash = JSON.stringify(valuesToWatch.call(this));
41
+ if(frame._previousHash == currentHash) return;
42
+ console.log(`${frame._previousHash} != ${currentHash}`)
43
+ frame._previousHash = currentHash;
44
+ loadFrame.call(this, { target, method: 'PATCH', url: action });
45
+ }, 100);
27
46
  },
28
47
 
29
48
  isForm: true,
@@ -31,4 +50,16 @@ export default {
31
50
  get hasUnsavedChanges(){
32
51
  return this.params.hasUnsavedChanges == 'true' || JSON.stringify(this.values) != this._initialHash;
33
52
  }
34
- };
53
+ });
54
+
55
+ function valuesToWatch(){
56
+ const out = {}
57
+ this.inputs.forEach(input => {
58
+ if(input.params.watch != 'true') return;
59
+ const value = input.value;
60
+ if(value !== undefined){
61
+ out[input.name] = value
62
+ }
63
+ })
64
+ return out;
65
+ }