pinstripe 0.34.0 → 0.35.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.
package/lib/component.js CHANGED
@@ -54,6 +54,28 @@ export const Component = Class.extend().include({
54
54
  if(autofocus){
55
55
  this.setTimeout(() => this.node.focus());
56
56
  }
57
+
58
+ const { name } = this.constructor;
59
+
60
+ if(this.constructor.mixins[name]) return;
61
+
62
+ if(name.match(/^([a-z0-9]+|document-fragment)$/)) return;
63
+
64
+ const { componentBase } = this.document;
65
+ if(!componentBase) return;
66
+
67
+ this.shadow.patch(`
68
+ <pinstripe-global-styles></pinstripe-global-styles>
69
+ <pinstripe-frame use-cache="true" load-on-init="false"></pinstripe-frame>
70
+ `);
71
+ const frame = this.shadow.find('pinstripe-frame');
72
+
73
+ const url = new URL(`${componentBase}/${name}`, frame.url);
74
+ const { params } = this;
75
+ for(const [key, value] of Object.entries(params)){
76
+ url.searchParams.set(key, value);
77
+ }
78
+ frame.load(url);
57
79
  },
58
80
 
59
81
  get type(){
@@ -467,7 +489,7 @@ export const Component = Class.extend().include({
467
489
  }))
468
490
  }
469
491
  const promises = [
470
- this.document.httpProxy.fetch(normalizedUrl, { signal: abortController.signal, ...otherOptions }),
492
+ fetch(normalizedUrl, { signal: abortController.signal, ...otherOptions }),
471
493
  new Promise((resolve, reject) => {
472
494
  minimumDelayTimeout = setTimeout(resolve, minimumDelay);
473
495
  rejectMinimumDelay = reject;
@@ -565,7 +587,7 @@ function createVirtualNode(html){
565
587
  function patch(attributes, virtualChildren){
566
588
  const isFrame = this.type == 'pinstripe-frame' || this.attributes['data-component'] == 'pinstripe-frame';
567
589
  const isEmptyFrame = isFrame && virtualChildren.length == 0;
568
- if(isEmptyFrame && attributes['data-load-on-init'] === undefined){
590
+ if(isEmptyFrame && attributes['load-on-init'] === undefined && attributes['data-load-on-init'] === undefined){
569
591
  attributes['data-load-on-init'] = 'true';
570
592
  }
571
593
  patchAttributes.call(this, attributes);
@@ -4,10 +4,12 @@ import './pinstripe_body.js';
4
4
  import './pinstripe_document.js';
5
5
  import './pinstripe_form.js';
6
6
  import './pinstripe_frame.js';
7
+ import './pinstripe_global_styles.js';
7
8
  import './pinstripe_menu.js';
8
9
  import './pinstripe_modal.js';
9
10
  import './pinstripe_overlay.js';
10
11
  import './pinstripe_popover.js';
11
12
  import './pinstripe_progress_bar.js';
13
+ import './pinstripe_redirect.js';
12
14
  import './pinstripe_script.js';
13
15
  import './pinstripe_skeleton.js';
@@ -30,17 +30,6 @@ Component.register('pinstripe-document', {
30
30
 
31
31
  isDocument: true,
32
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
-
44
33
  get head(){
45
34
  if(!this._head){
46
35
  this._head = this.find('head');
@@ -63,6 +52,21 @@ Component.register('pinstripe-document', {
63
52
  return this.head.find('meta[name="pinstripe-load-cache-namespace"]')?.params.content ?? 'default';
64
53
  },
65
54
 
55
+ get globalStyles(){
56
+ if(!this._globalStyles){
57
+ try {
58
+ this._globalStyles = mergeCssStylesheets(this.node.styleSheets ?? []);
59
+ } catch (e) {
60
+ this._globalStyles = undefined;
61
+ }
62
+ }
63
+ return this._globalStyles;
64
+ },
65
+
66
+ get componentBase(){
67
+ return this.head.find('meta[name="pinstripe-component-base"]')?.params.content;
68
+ },
69
+
66
70
  async load(url = this.url.toString(), options = {}){
67
71
  const { replace, method = 'GET' } = options;
68
72
  const previousUrl = this.url.toString();
@@ -90,3 +94,21 @@ Component.register('pinstripe-document', {
90
94
  delete preloading[url.toString()];
91
95
  }
92
96
  });
97
+
98
+
99
+ export function mergeCssStylesheets(stylesheets, out = new CSSStyleSheet()) {
100
+ for(const sheet of stylesheets){
101
+ try {
102
+ for(const rule of sheet.cssRules) {
103
+ if(rule instanceof CSSImportRule) {
104
+ mergeCssStylesheets([ rule.styleSheet ], out);
105
+ } else {
106
+ out.insertRule(rule.cssText);
107
+ }
108
+ }
109
+ } catch (e) {
110
+ // Ignore errors from stylesheets that cannot be merged
111
+ }
112
+ }
113
+ return out;
114
+ }
@@ -44,9 +44,16 @@ Component.register('pinstripe-frame', {
44
44
  await clearEventLoop();
45
45
  this.status = 'loading';
46
46
  this.url = url;
47
- const { method = 'GET', placeholderUrl } = options;
47
+ const { method = 'GET', placeholderUrl, useCache = this.params.useCache == 'true' } = options;
48
48
  const cachedHtml = method == 'GET' ? loadCache.get(`${this.document.loadCacheNamespace}:${url}`) : undefined;
49
49
  if(cachedHtml) {
50
+ if(useCache){
51
+ this.status = 'complete';
52
+ this.patch(cachedHtml);
53
+ await clearEventLoop();
54
+ progressBar.stop();
55
+ return;
56
+ }
50
57
  this.status = 'using-cached-html';
51
58
  this.patch(cachedHtml);
52
59
  }
@@ -0,0 +1,13 @@
1
+
2
+ import { Component } from "../component.js";
3
+
4
+ Component.register('pinstripe-global-styles', {
5
+ initialize(...args){
6
+ this.constructor.parent.prototype.initialize.call(this, ...args);
7
+
8
+ const host = this.find('parents', el => el.node.shadowRoot );
9
+ if(!host) return;
10
+
11
+ host.shadow.node.adoptedStyleSheets = [ this.document.globalStyles ];
12
+ }
13
+ });
@@ -138,7 +138,10 @@ Component.register('pinstripe-modal', {
138
138
  </div>
139
139
  `);
140
140
 
141
- this.shadow.on('click', '.root, .container, .body, .close-button', () => this.trigger('close'));
141
+ this.shadow.on('click', '.root, .container, .body, .close-button', () => {
142
+ if(this.overlay.find('nextSiblings', 'pinstripe-overlay')) return;
143
+ this.trigger('close');
144
+ });
142
145
 
143
146
  this.on('clean', () => this.document.body.unclip());
144
147
 
@@ -0,0 +1,18 @@
1
+
2
+ import { Component } from "../component.js";
3
+ import { loadFrame, getFrame, normalizeUrl } from "./helpers.js";
4
+
5
+ Component.register('pinstripe-redirect', {
6
+ initialize(...args){
7
+ this.constructor.parent.prototype.initialize.call(this, ...args);
8
+
9
+ if(this.isFromCachedHtml) return;
10
+
11
+ const { delay = '0', confirm, target = '_self', method = 'GET', url, placeholder } = this.params;
12
+ this.setTimeout(() => {
13
+ if(target == '_blank') return;
14
+ if(normalizeUrl(url, window.location.href).host != window.location.host) return;
15
+ loadFrame.call(this, { confirm, target, method, url, placeholderUrl: placeholder });
16
+ }, parseInt(delay));
17
+ }
18
+ });
package/lib/initialize.js CHANGED
@@ -3,9 +3,17 @@ import './components/index.js';
3
3
  import { Component } from './component.js';
4
4
 
5
5
  if(typeof window != 'undefined'){
6
+ const originalDisplay = document.documentElement.style.display;
7
+ document.documentElement.style.display = 'none';
6
8
  window.addEventListener('DOMContentLoaded', () => {
7
9
  const documentComponent = Component.instanceFor(document);
8
10
  documentComponent.observe({ add: true }, component => component.descendants);
9
11
  documentComponent.patch(document.documentElement.outerHTML);
12
+
13
+ const interval = setInterval(() => {
14
+ documentComponent.progressBar.startCount == 0;
15
+ clearInterval(interval);
16
+ document.documentElement.style.display = originalDisplay;
17
+ }, 100);
10
18
  });
11
19
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "name": "pinstripe",
4
4
  "description": "A slick web framework for your browser.",
5
- "version": "0.34.0",
5
+ "version": "0.35.0",
6
6
  "author": "Jody Salt",
7
7
  "license": "MIT",
8
8
  "exports": {
@@ -12,7 +12,7 @@
12
12
  "clean": "rm -rf ./node_modules"
13
13
  },
14
14
  "dependencies": {
15
- "@sintra/utils": "^0.34.0"
15
+ "@sintra/utils": "^0.35.0"
16
16
  },
17
17
  "devDependencies": {
18
18
  "esbuild": "^0.25.1"