@tylertech/forge-core 2.3.0 → 2.3.1

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.
@@ -1,4 +1,7 @@
1
1
  import { replaceElement, isArray, removeAllChildren, walkUpUntil } from '../utils';
2
+ export const CUSTOM_ELEMENT_STYLES_PROPERTY = '_forgeElementStyles';
3
+ /** Whether the browser supports constructable stylesheets */
4
+ export const supportsConstructableStyleSheets = window.ShadowRoot && 'adoptedStyleSheets' in Document.prototype && 'replace' in CSSStyleSheet.prototype;
2
5
  /**
3
6
  * Recursively defines a component as a custom elements and all of its dependencies.
4
7
  * @param component The component to import.
@@ -83,11 +86,14 @@ export function attachLightTemplate(componentInstance, template) {
83
86
  * @param {string} elementName The name of the element the shadow root is to be attached to.
84
87
  * @param {string} template The shadow root template HTML string.
85
88
  * @param {string | string[]} styles The shadow root styles string to be encapsulated by this shadow root.
86
- * @param {boolean} [delegatesFocus=false] Should the component delagate focus.
89
+ * @param {boolean} [delegatesFocus=false] Should the component delegate focus.
87
90
  */
88
91
  export function attachShadowTemplate(componentInstance, template, styles, delegatesFocus = false) {
89
- const templateElement = prepareShadowTemplate(template, styles);
92
+ const templateElement = prepareShadowTemplate(template);
90
93
  componentInstance.attachShadow({ mode: 'open', delegatesFocus });
94
+ if (styles) {
95
+ setShadowStyles(componentInstance, styles);
96
+ }
91
97
  setShadowTemplate(componentInstance, templateElement);
92
98
  }
93
99
  /**
@@ -101,10 +107,13 @@ export function replaceShadowTemplate(componentInstance, template, styles) {
101
107
  if (!componentInstance.shadowRoot) {
102
108
  throw new Error('This element does not contain a shadow root. Did you mean to call `attachShadowTemplate`?');
103
109
  }
104
- const templateElement = prepareShadowTemplate(template, styles);
110
+ const templateElement = prepareShadowTemplate(template);
105
111
  if (componentInstance.shadowRoot.children.length) {
106
112
  removeAllChildren(componentInstance.shadowRoot);
107
113
  }
114
+ if (styles) {
115
+ setShadowStyles(componentInstance, styles, { force: true });
116
+ }
108
117
  setShadowTemplate(componentInstance, templateElement);
109
118
  }
110
119
  /**
@@ -115,10 +124,16 @@ export function replaceShadowTemplate(componentInstance, template, styles) {
115
124
  */
116
125
  export function prepareShadowTemplate(template, styles) {
117
126
  const templateElement = parseTemplateString(template);
127
+ // Deprecated in favor of `setShadowStyles()`, leaving for backwards compatibility
128
+ // TODO: remove this in next major version, and remove `styles` argument above
118
129
  if (styles) {
119
130
  styles = styles instanceof Array ? styles : [styles];
120
131
  const styleElement = document.createElement('style');
121
- styleElement.type = 'text/css';
132
+ // eslint-disable-next-line @typescript-eslint/dot-notation
133
+ const nonce = window['forgeNonce'];
134
+ if (nonce) {
135
+ styleElement.setAttribute('nonce', nonce);
136
+ }
122
137
  styleElement.textContent = styles.join(' ');
123
138
  templateElement.content.appendChild(styleElement);
124
139
  }
@@ -132,6 +147,45 @@ export function prepareShadowTemplate(template, styles) {
132
147
  export function setShadowTemplate(componentInstance, templateElement) {
133
148
  componentInstance.shadowRoot.appendChild(templateElement.content.cloneNode(true));
134
149
  }
150
+ /**
151
+ * Applies styles to the shadow root of the provided element instance.
152
+ * @param {T} componentInstance A component instance.
153
+ * @param {string | string[]} styles The styles to be applied to the shadow root.
154
+ * @param options Options for setting the styles.
155
+ */
156
+ export function setShadowStyles(componentInstance, styles, { force } = { force: false }) {
157
+ const ctor = componentInstance.constructor;
158
+ if (!componentInstance.shadowRoot || !styles) {
159
+ if (supportsConstructableStyleSheets) {
160
+ if (ctor[CUSTOM_ELEMENT_STYLES_PROPERTY]) {
161
+ ctor[CUSTOM_ELEMENT_STYLES_PROPERTY] = [];
162
+ }
163
+ if (componentInstance.shadowRoot) {
164
+ componentInstance.shadowRoot.adoptedStyleSheets = [];
165
+ }
166
+ }
167
+ return;
168
+ }
169
+ styles = styles instanceof Array ? styles : [styles];
170
+ if (supportsConstructableStyleSheets) {
171
+ if (force || !ctor[CUSTOM_ELEMENT_STYLES_PROPERTY]) {
172
+ const sheet = new CSSStyleSheet();
173
+ sheet.replaceSync(styles.join(' '));
174
+ ctor[CUSTOM_ELEMENT_STYLES_PROPERTY] = [sheet];
175
+ }
176
+ componentInstance.shadowRoot.adoptedStyleSheets = ctor[CUSTOM_ELEMENT_STYLES_PROPERTY];
177
+ }
178
+ else {
179
+ const styleElement = document.createElement('style');
180
+ // eslint-disable-next-line @typescript-eslint/dot-notation
181
+ const nonce = window['forgeNonce'];
182
+ if (nonce) {
183
+ styleElement.setAttribute('nonce', nonce);
184
+ }
185
+ styleElement.textContent = styles.join(' ');
186
+ componentInstance.shadowRoot.appendChild(styleElement);
187
+ }
188
+ }
135
189
  /**
136
190
  * Copies style rules from the provided document stylesheets collection to the provided shadow root stylesheet.
137
191
  * @param {Document} fromDocument The document to find the style sheets in.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tylertech/forge-core",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "description": "A library of core web utilities that support Forge Web Component libraries.",
5
5
  "author": "Tyler Technologies, Inc.",
6
6
  "license": "Apache-2.0",
@@ -16,4 +16,4 @@
16
16
  "@floating-ui/dom": "^0.5.0",
17
17
  "tslib": "^2.3.1"
18
18
  }
19
- }
19
+ }
@@ -1,3 +1,6 @@
1
+ export declare const CUSTOM_ELEMENT_STYLES_PROPERTY = "_forgeElementStyles";
2
+ /** Whether the browser supports constructable stylesheets */
3
+ export declare const supportsConstructableStyleSheets: boolean;
1
4
  /**
2
5
  * Recursively defines a component as a custom elements and all of its dependencies.
3
6
  * @param component The component to import.
@@ -46,7 +49,7 @@ export declare function attachLightTemplate<T extends HTMLElement>(componentInst
46
49
  * @param {string} elementName The name of the element the shadow root is to be attached to.
47
50
  * @param {string} template The shadow root template HTML string.
48
51
  * @param {string | string[]} styles The shadow root styles string to be encapsulated by this shadow root.
49
- * @param {boolean} [delegatesFocus=false] Should the component delagate focus.
52
+ * @param {boolean} [delegatesFocus=false] Should the component delegate focus.
50
53
  */
51
54
  export declare function attachShadowTemplate<T extends HTMLElement>(componentInstance: T, template: string, styles?: string | string[], delegatesFocus?: boolean): void;
52
55
  /**
@@ -70,6 +73,15 @@ export declare function prepareShadowTemplate(template: string, styles?: string
70
73
  * @param {HTMLTemplateElement} templateElement A template element to be cloned.
71
74
  */
72
75
  export declare function setShadowTemplate<T extends HTMLElement>(componentInstance: T, templateElement: HTMLTemplateElement): void;
76
+ /**
77
+ * Applies styles to the shadow root of the provided element instance.
78
+ * @param {T} componentInstance A component instance.
79
+ * @param {string | string[]} styles The styles to be applied to the shadow root.
80
+ * @param options Options for setting the styles.
81
+ */
82
+ export declare function setShadowStyles<T extends HTMLElement>(componentInstance: T, styles: string | string[], { force }?: {
83
+ force: boolean;
84
+ }): void;
73
85
  /**
74
86
  * Copies style rules from the provided document stylesheets collection to the provided shadow root stylesheet.
75
87
  * @param {Document} fromDocument The document to find the style sheets in.
@@ -2,6 +2,12 @@ declare global {
2
2
  interface Window {
3
3
  __forgeFlags__autoDefine: any;
4
4
  }
5
+ interface ShadowRoot {
6
+ adoptedStyleSheets: CSSStyleSheet[];
7
+ }
8
+ interface CSSStyleSheet {
9
+ replaceSync(cssText: string): void;
10
+ }
5
11
  }
6
12
  export interface ICustomElementConfig {
7
13
  /** The name of the custom element tag. */