@fluentui/react-provider 9.22.20 → 9.22.22

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/CHANGELOG.md CHANGED
@@ -1,12 +1,36 @@
1
1
  # Change Log - @fluentui/react-provider
2
2
 
3
- <!-- This log was last generated on Tue, 11 Aug 2026 17:16:02 GMT and should not be manually modified. -->
3
+ <!-- This log was last generated on Mon, 19 Oct 2026 14:49:10 GMT and should not be manually modified. -->
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## [9.22.22](https://github.com/microsoft/fluentui/tree/@fluentui/react-provider_v9.22.22)
8
+
9
+ Mon, 19 Oct 2026 14:49:10 GMT
10
+
11
+ ### Patches
12
+
13
+ - fix: block unsafe theme token syntax without a value-format allowlist ([PR #36830](https://github.com/microsoft/fluentui/pull/36830) by paliprandi@microsoft.com)
14
+ - Bump @fluentui/react-jsx-runtime to v9.4.7 ([commit](https://github.com/microsoft/fluentui/commit/undefined) by beachball)
15
+ - Bump @fluentui/react-tabster to v9.26.19 ([commit](https://github.com/microsoft/fluentui/commit/undefined) by beachball)
16
+ - Bump @fluentui/react-utilities to v9.27.0 ([commit](https://github.com/microsoft/fluentui/commit/undefined) by beachball)
17
+
18
+ ## [9.22.21](https://github.com/microsoft/fluentui/tree/@fluentui/react-provider_v9.22.21)
19
+
20
+ Tue, 22 Sep 2026 11:25:39 GMT
21
+ [Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-provider_v9.22.20..@fluentui/react-provider_v9.22.21)
22
+
23
+ ### Patches
24
+
25
+ - fix: remove unused react-dom and @types/react-dom peer dependencies, mark @types/react as optional ([PR #36559](https://github.com/microsoft/fluentui/pull/36559) by martinhochel@microsoft.com)
26
+ - Bump @fluentui/react-jsx-runtime to v9.4.6 ([commit](https://github.com/microsoft/fluentui/commit/undefined) by beachball)
27
+ - Bump @fluentui/react-shared-contexts to v9.26.4 ([commit](https://github.com/microsoft/fluentui/commit/undefined) by beachball)
28
+ - Bump @fluentui/react-tabster to v9.26.18 ([commit](https://github.com/microsoft/fluentui/commit/undefined) by beachball)
29
+ - Bump @fluentui/react-utilities to v9.26.7 ([commit](https://github.com/microsoft/fluentui/commit/undefined) by beachball)
30
+
7
31
  ## [9.22.20](https://github.com/microsoft/fluentui/tree/@fluentui/react-provider_v9.22.20)
8
32
 
9
- Tue, 11 Aug 2026 17:16:02 GMT
33
+ Tue, 11 Aug 2026 17:20:14 GMT
10
34
  [Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-provider_v9.22.19..@fluentui/react-provider_v9.22.20)
11
35
 
12
36
  ### Patches
package/dist/index.d.cts CHANGED
@@ -18,6 +18,8 @@ import type { TooltipVisibilityContextValue_unstable } from '@fluentui/react-sha
18
18
  * Creates a CSS rule from a theme object.
19
19
  *
20
20
  * Useful for scenarios when you want to apply theming statically to a top level elements like `body`.
21
+ * Values with blocked symbols or unsupported quotes/parentheses are omitted, not repaired.
22
+ * No function-name or value-format allowlist is used. Validate dynamic data against an application-specific schema.
21
23
  */
22
24
  export declare function createCSSRuleFromTheme(selector: string, theme: PartialTheme | undefined): string;
23
25
 
package/dist/index.d.ts CHANGED
@@ -18,6 +18,8 @@ import type { TooltipVisibilityContextValue_unstable } from '@fluentui/react-sha
18
18
  * Creates a CSS rule from a theme object.
19
19
  *
20
20
  * Useful for scenarios when you want to apply theming statically to a top level elements like `body`.
21
+ * Values with blocked symbols or unsupported quotes/parentheses are omitted, not repaired.
22
+ * No function-name or value-format allowlist is used. Validate dynamic data against an application-specific schema.
21
23
  */
22
24
  export declare function createCSSRuleFromTheme(selector: string, theme: PartialTheme | undefined): string;
23
25
 
@@ -1,28 +1,55 @@
1
- const CSS_ESCAPE_MAP = {
2
- '<': '\\3C ',
3
- '>': '\\3E '
4
- };
5
- /**
6
- * Escapes characters that could break out of a <style> tag during SSR.
7
- *
8
- * IMPORTANT: Do not strip quotes. Theme values legitimately include quoted font families and other CSS.
9
- * We only need to ensure the generated text cannot terminate the style tag and inject HTML.
10
- */ function escapeForStyleTag(value) {
11
- // Escape as CSS code points so the resulting CSS still represents the same characters.
12
- // Using CSS escapes prevents the HTML parser from seeing a literal '<' / '>' and closing <style>.
13
- return value.replace(/[<>]/g, (match)=>CSS_ESCAPE_MAP[match]);
1
+ const BLOCKLIST_NAME_PATTERN = /[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~\u0000-\u0020\u007F]/;
2
+ const BLOCKLIST_VALUE_PATTERN = /[!<>{};[\]\\\u0000-\u0008\u000B\u000E-\u001F\u007F]|\/\*/;
3
+ const CLOSED_PARTS_PATTERN = /"[^"\u0000-\u001F\u007F]*"|'[^'\u0000-\u001F\u007F]*'|\([^"'()]*\)/g;
4
+ const BLOCKLIST_UNMATCHED_DELIMITERS_PATTERN = /["'()]/;
5
+ function escapeCharacter(character) {
6
+ return `\\${character.charCodeAt(0).toString(16).toUpperCase()} `;
7
+ }
8
+ function escapeSelector(value) {
9
+ // Consume whole backslash runs so escaping preserves their parity and does not retry overlapping suffixes.
10
+ return value.replace(/\\+[<{}]?|[<{}]/g, (match)=>{
11
+ const character = match[match.length - 1];
12
+ if (!'<{}'.includes(character)) {
13
+ return match;
14
+ }
15
+ const backslashes = match.length - 1;
16
+ return match.slice(0, backslashes - backslashes % 2) + escapeCharacter(character);
17
+ });
18
+ }
19
+ function warnThemeToken(name, reason) {
20
+ if (process.env.NODE_ENV !== 'production') {
21
+ // eslint-disable-next-line no-console
22
+ console.warn(`@fluentui/react-provider: ${reason} for theme token ${JSON.stringify(name)}.`);
23
+ }
14
24
  }
15
25
  /**
16
26
  * Creates a CSS rule from a theme object.
17
27
  *
18
28
  * Useful for scenarios when you want to apply theming statically to a top level elements like `body`.
29
+ * Values with blocked symbols or unsupported quotes/parentheses are omitted, not repaired.
30
+ * No function-name or value-format allowlist is used. Validate dynamic data against an application-specific schema.
19
31
  */ export function createCSSRuleFromTheme(selector, theme) {
20
- const escapedSelector = escapeForStyleTag(selector);
32
+ const escapedSelector = escapeSelector(selector);
21
33
  if (theme) {
22
34
  const cssVarsAsString = Object.keys(theme).reduce((cssVarRule, cssVar)=>{
23
- return `${cssVarRule}--${cssVar}: ${theme[cssVar]}; `;
35
+ const tokenValue = theme[cssVar];
36
+ if (!cssVar || BLOCKLIST_NAME_PATTERN.test(cssVar)) {
37
+ warnThemeToken(cssVar, 'Ignoring an unsupported CSS custom property name');
38
+ return cssVarRule;
39
+ }
40
+ if (typeof tokenValue !== 'string' && (typeof tokenValue !== 'number' || !Number.isFinite(tokenValue))) {
41
+ warnThemeToken(cssVar, 'Ignoring an unsupported CSS custom property value');
42
+ return cssVarRule;
43
+ }
44
+ const value = String(tokenValue);
45
+ // Ignore complete strings and flat parentheses only while looking for leftover syntax; never rewrite the value.
46
+ if (BLOCKLIST_VALUE_PATTERN.test(value) || BLOCKLIST_UNMATCHED_DELIMITERS_PATTERN.test(value.replace(CLOSED_PARTS_PATTERN, ''))) {
47
+ warnThemeToken(cssVar, 'Ignoring an unsupported CSS custom property value');
48
+ return cssVarRule;
49
+ }
50
+ return `${cssVarRule}--${cssVar}: ${value}; `;
24
51
  }, '');
25
- return `${escapedSelector} { ${escapeForStyleTag(cssVarsAsString)} }`;
52
+ return `${escapedSelector} { ${cssVarsAsString} }`;
26
53
  }
27
54
  return `${escapedSelector} {}`;
28
55
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/FluentProvider/createCSSRuleFromTheme.ts"],"sourcesContent":["import type { PartialTheme } from '@fluentui/react-theme';\n\nconst CSS_ESCAPE_MAP = {\n '<': '\\\\3C ',\n '>': '\\\\3E ',\n};\n/**\n * Escapes characters that could break out of a <style> tag during SSR.\n *\n * IMPORTANT: Do not strip quotes. Theme values legitimately include quoted font families and other CSS.\n * We only need to ensure the generated text cannot terminate the style tag and inject HTML.\n */\nfunction escapeForStyleTag(value: string): string {\n // Escape as CSS code points so the resulting CSS still represents the same characters.\n // Using CSS escapes prevents the HTML parser from seeing a literal '<' / '>' and closing <style>.\n return value.replace(/[<>]/g, match => CSS_ESCAPE_MAP[match as keyof typeof CSS_ESCAPE_MAP]);\n}\n\n/**\n * Creates a CSS rule from a theme object.\n *\n * Useful for scenarios when you want to apply theming statically to a top level elements like `body`.\n */\nexport function createCSSRuleFromTheme(selector: string, theme: PartialTheme | undefined): string {\n const escapedSelector = escapeForStyleTag(selector);\n\n if (theme) {\n const cssVarsAsString = (Object.keys(theme) as (keyof typeof theme)[]).reduce((cssVarRule, cssVar) => {\n return `${cssVarRule}--${cssVar}: ${theme[cssVar]}; `;\n }, '');\n\n return `${escapedSelector} { ${escapeForStyleTag(cssVarsAsString)} }`;\n }\n\n return `${escapedSelector} {}`;\n}\n"],"names":["CSS_ESCAPE_MAP","escapeForStyleTag","value","replace","match","createCSSRuleFromTheme","selector","theme","escapedSelector","cssVarsAsString","Object","keys","reduce","cssVarRule","cssVar"],"mappings":"AAEA,MAAMA,iBAAiB;IACrB,KAAK;IACL,KAAK;AACP;AACA;;;;;CAKC,GACD,SAASC,kBAAkBC,KAAa;IACtC,uFAAuF;IACvF,kGAAkG;IAClG,OAAOA,MAAMC,OAAO,CAAC,SAASC,CAAAA,QAASJ,cAAc,CAACI,MAAqC;AAC7F;AAEA;;;;CAIC,GACD,OAAO,SAASC,uBAAuBC,QAAgB,EAAEC,KAA+B;IACtF,MAAMC,kBAAkBP,kBAAkBK;IAE1C,IAAIC,OAAO;QACT,MAAME,kBAAkB,AAACC,OAAOC,IAAI,CAACJ,OAAkCK,MAAM,CAAC,CAACC,YAAYC;YACzF,OAAO,GAAGD,WAAW,EAAE,EAAEC,OAAO,EAAE,EAAEP,KAAK,CAACO,OAAO,CAAC,EAAE,CAAC;QACvD,GAAG;QAEH,OAAO,GAAGN,gBAAgB,GAAG,EAAEP,kBAAkBQ,iBAAiB,EAAE,CAAC;IACvE;IAEA,OAAO,GAAGD,gBAAgB,GAAG,CAAC;AAChC"}
1
+ {"version":3,"sources":["../src/components/FluentProvider/createCSSRuleFromTheme.ts"],"sourcesContent":["import type { PartialTheme } from '@fluentui/react-theme';\n\nconst BLOCKLIST_NAME_PATTERN = /[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~\\u0000-\\u0020\\u007F]/;\nconst BLOCKLIST_VALUE_PATTERN = /[!<>{};[\\]\\\\\\u0000-\\u0008\\u000B\\u000E-\\u001F\\u007F]|\\/\\*/;\nconst CLOSED_PARTS_PATTERN = /\"[^\"\\u0000-\\u001F\\u007F]*\"|'[^'\\u0000-\\u001F\\u007F]*'|\\([^\"'()]*\\)/g;\nconst BLOCKLIST_UNMATCHED_DELIMITERS_PATTERN = /[\"'()]/;\n\nfunction escapeCharacter(character: string): string {\n return `\\\\${character.charCodeAt(0).toString(16).toUpperCase()} `;\n}\n\nfunction escapeSelector(value: string): string {\n // Consume whole backslash runs so escaping preserves their parity and does not retry overlapping suffixes.\n return value.replace(/\\\\+[<{}]?|[<{}]/g, match => {\n const character = match[match.length - 1];\n if (!'<{}'.includes(character)) {\n return match;\n }\n\n const backslashes = match.length - 1;\n return match.slice(0, backslashes - (backslashes % 2)) + escapeCharacter(character);\n });\n}\n\nfunction warnThemeToken(name: string, reason: string): void {\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.warn(`@fluentui/react-provider: ${reason} for theme token ${JSON.stringify(name)}.`);\n }\n}\n\n/**\n * Creates a CSS rule from a theme object.\n *\n * Useful for scenarios when you want to apply theming statically to a top level elements like `body`.\n * Values with blocked symbols or unsupported quotes/parentheses are omitted, not repaired.\n * No function-name or value-format allowlist is used. Validate dynamic data against an application-specific schema.\n */\nexport function createCSSRuleFromTheme(selector: string, theme: PartialTheme | undefined): string {\n const escapedSelector = escapeSelector(selector);\n\n if (theme) {\n const cssVarsAsString = (Object.keys(theme) as (keyof typeof theme)[]).reduce((cssVarRule, cssVar) => {\n const tokenValue: unknown = theme[cssVar];\n if (!cssVar || BLOCKLIST_NAME_PATTERN.test(cssVar)) {\n warnThemeToken(cssVar, 'Ignoring an unsupported CSS custom property name');\n return cssVarRule;\n }\n if (typeof tokenValue !== 'string' && (typeof tokenValue !== 'number' || !Number.isFinite(tokenValue))) {\n warnThemeToken(cssVar, 'Ignoring an unsupported CSS custom property value');\n return cssVarRule;\n }\n\n const value = String(tokenValue);\n // Ignore complete strings and flat parentheses only while looking for leftover syntax; never rewrite the value.\n if (\n BLOCKLIST_VALUE_PATTERN.test(value) ||\n BLOCKLIST_UNMATCHED_DELIMITERS_PATTERN.test(value.replace(CLOSED_PARTS_PATTERN, ''))\n ) {\n warnThemeToken(cssVar, 'Ignoring an unsupported CSS custom property value');\n return cssVarRule;\n }\n\n return `${cssVarRule}--${cssVar}: ${value}; `;\n }, '');\n\n return `${escapedSelector} { ${cssVarsAsString} }`;\n }\n\n return `${escapedSelector} {}`;\n}\n"],"names":["BLOCKLIST_NAME_PATTERN","BLOCKLIST_VALUE_PATTERN","CLOSED_PARTS_PATTERN","BLOCKLIST_UNMATCHED_DELIMITERS_PATTERN","escapeCharacter","character","charCodeAt","toString","toUpperCase","escapeSelector","value","replace","match","length","includes","backslashes","slice","warnThemeToken","name","reason","process","env","NODE_ENV","console","warn","JSON","stringify","createCSSRuleFromTheme","selector","theme","escapedSelector","cssVarsAsString","Object","keys","reduce","cssVarRule","cssVar","tokenValue","test","Number","isFinite","String"],"mappings":"AAEA,MAAMA,yBAAyB;AAC/B,MAAMC,0BAA0B;AAChC,MAAMC,uBAAuB;AAC7B,MAAMC,yCAAyC;AAE/C,SAASC,gBAAgBC,SAAiB;IACxC,OAAO,CAAC,EAAE,EAAEA,UAAUC,UAAU,CAAC,GAAGC,QAAQ,CAAC,IAAIC,WAAW,GAAG,CAAC,CAAC;AACnE;AAEA,SAASC,eAAeC,KAAa;IACnC,2GAA2G;IAC3G,OAAOA,MAAMC,OAAO,CAAC,oBAAoBC,CAAAA;QACvC,MAAMP,YAAYO,KAAK,CAACA,MAAMC,MAAM,GAAG,EAAE;QACzC,IAAI,CAAC,MAAMC,QAAQ,CAACT,YAAY;YAC9B,OAAOO;QACT;QAEA,MAAMG,cAAcH,MAAMC,MAAM,GAAG;QACnC,OAAOD,MAAMI,KAAK,CAAC,GAAGD,cAAeA,cAAc,KAAMX,gBAAgBC;IAC3E;AACF;AAEA,SAASY,eAAeC,IAAY,EAAEC,MAAc;IAClD,IAAIC,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;QACzC,sCAAsC;QACtCC,QAAQC,IAAI,CAAC,CAAC,0BAA0B,EAAEL,OAAO,iBAAiB,EAAEM,KAAKC,SAAS,CAACR,MAAM,CAAC,CAAC;IAC7F;AACF;AAEA;;;;;;CAMC,GACD,OAAO,SAASS,uBAAuBC,QAAgB,EAAEC,KAA+B;IACtF,MAAMC,kBAAkBrB,eAAemB;IAEvC,IAAIC,OAAO;QACT,MAAME,kBAAkB,AAACC,OAAOC,IAAI,CAACJ,OAAkCK,MAAM,CAAC,CAACC,YAAYC;YACzF,MAAMC,aAAsBR,KAAK,CAACO,OAAO;YACzC,IAAI,CAACA,UAAUpC,uBAAuBsC,IAAI,CAACF,SAAS;gBAClDnB,eAAemB,QAAQ;gBACvB,OAAOD;YACT;YACA,IAAI,OAAOE,eAAe,YAAa,CAAA,OAAOA,eAAe,YAAY,CAACE,OAAOC,QAAQ,CAACH,WAAU,GAAI;gBACtGpB,eAAemB,QAAQ;gBACvB,OAAOD;YACT;YAEA,MAAMzB,QAAQ+B,OAAOJ;YACrB,gHAAgH;YAChH,IACEpC,wBAAwBqC,IAAI,CAAC5B,UAC7BP,uCAAuCmC,IAAI,CAAC5B,MAAMC,OAAO,CAACT,sBAAsB,MAChF;gBACAe,eAAemB,QAAQ;gBACvB,OAAOD;YACT;YAEA,OAAO,GAAGA,WAAW,EAAE,EAAEC,OAAO,EAAE,EAAE1B,MAAM,EAAE,CAAC;QAC/C,GAAG;QAEH,OAAO,GAAGoB,gBAAgB,GAAG,EAAEC,gBAAgB,EAAE,CAAC;IACpD;IAEA,OAAO,GAAGD,gBAAgB,GAAG,CAAC;AAChC"}
@@ -8,27 +8,52 @@ Object.defineProperty(exports, "createCSSRuleFromTheme", {
8
8
  return createCSSRuleFromTheme;
9
9
  }
10
10
  });
11
- const CSS_ESCAPE_MAP = {
12
- '<': '\\3C ',
13
- '>': '\\3E '
14
- };
15
- /**
16
- * Escapes characters that could break out of a <style> tag during SSR.
17
- *
18
- * IMPORTANT: Do not strip quotes. Theme values legitimately include quoted font families and other CSS.
19
- * We only need to ensure the generated text cannot terminate the style tag and inject HTML.
20
- */ function escapeForStyleTag(value) {
21
- // Escape as CSS code points so the resulting CSS still represents the same characters.
22
- // Using CSS escapes prevents the HTML parser from seeing a literal '<' / '>' and closing <style>.
23
- return value.replace(/[<>]/g, (match)=>CSS_ESCAPE_MAP[match]);
11
+ const BLOCKLIST_NAME_PATTERN = /[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~\u0000-\u0020\u007F]/;
12
+ const BLOCKLIST_VALUE_PATTERN = /[!<>{};[\]\\\u0000-\u0008\u000B\u000E-\u001F\u007F]|\/\*/;
13
+ const CLOSED_PARTS_PATTERN = /"[^"\u0000-\u001F\u007F]*"|'[^'\u0000-\u001F\u007F]*'|\([^"'()]*\)/g;
14
+ const BLOCKLIST_UNMATCHED_DELIMITERS_PATTERN = /["'()]/;
15
+ function escapeCharacter(character) {
16
+ return `\\${character.charCodeAt(0).toString(16).toUpperCase()} `;
17
+ }
18
+ function escapeSelector(value) {
19
+ // Consume whole backslash runs so escaping preserves their parity and does not retry overlapping suffixes.
20
+ return value.replace(/\\+[<{}]?|[<{}]/g, (match)=>{
21
+ const character = match[match.length - 1];
22
+ if (!'<{}'.includes(character)) {
23
+ return match;
24
+ }
25
+ const backslashes = match.length - 1;
26
+ return match.slice(0, backslashes - backslashes % 2) + escapeCharacter(character);
27
+ });
28
+ }
29
+ function warnThemeToken(name, reason) {
30
+ if (process.env.NODE_ENV !== 'production') {
31
+ // eslint-disable-next-line no-console
32
+ console.warn(`@fluentui/react-provider: ${reason} for theme token ${JSON.stringify(name)}.`);
33
+ }
24
34
  }
25
35
  function createCSSRuleFromTheme(selector, theme) {
26
- const escapedSelector = escapeForStyleTag(selector);
36
+ const escapedSelector = escapeSelector(selector);
27
37
  if (theme) {
28
38
  const cssVarsAsString = Object.keys(theme).reduce((cssVarRule, cssVar)=>{
29
- return `${cssVarRule}--${cssVar}: ${theme[cssVar]}; `;
39
+ const tokenValue = theme[cssVar];
40
+ if (!cssVar || BLOCKLIST_NAME_PATTERN.test(cssVar)) {
41
+ warnThemeToken(cssVar, 'Ignoring an unsupported CSS custom property name');
42
+ return cssVarRule;
43
+ }
44
+ if (typeof tokenValue !== 'string' && (typeof tokenValue !== 'number' || !Number.isFinite(tokenValue))) {
45
+ warnThemeToken(cssVar, 'Ignoring an unsupported CSS custom property value');
46
+ return cssVarRule;
47
+ }
48
+ const value = String(tokenValue);
49
+ // Ignore complete strings and flat parentheses only while looking for leftover syntax; never rewrite the value.
50
+ if (BLOCKLIST_VALUE_PATTERN.test(value) || BLOCKLIST_UNMATCHED_DELIMITERS_PATTERN.test(value.replace(CLOSED_PARTS_PATTERN, ''))) {
51
+ warnThemeToken(cssVar, 'Ignoring an unsupported CSS custom property value');
52
+ return cssVarRule;
53
+ }
54
+ return `${cssVarRule}--${cssVar}: ${value}; `;
30
55
  }, '');
31
- return `${escapedSelector} { ${escapeForStyleTag(cssVarsAsString)} }`;
56
+ return `${escapedSelector} { ${cssVarsAsString} }`;
32
57
  }
33
58
  return `${escapedSelector} {}`;
34
59
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/FluentProvider/createCSSRuleFromTheme.ts"],"sourcesContent":["import type { PartialTheme } from '@fluentui/react-theme';\n\nconst CSS_ESCAPE_MAP = {\n '<': '\\\\3C ',\n '>': '\\\\3E ',\n};\n/**\n * Escapes characters that could break out of a <style> tag during SSR.\n *\n * IMPORTANT: Do not strip quotes. Theme values legitimately include quoted font families and other CSS.\n * We only need to ensure the generated text cannot terminate the style tag and inject HTML.\n */\nfunction escapeForStyleTag(value: string): string {\n // Escape as CSS code points so the resulting CSS still represents the same characters.\n // Using CSS escapes prevents the HTML parser from seeing a literal '<' / '>' and closing <style>.\n return value.replace(/[<>]/g, match => CSS_ESCAPE_MAP[match as keyof typeof CSS_ESCAPE_MAP]);\n}\n\n/**\n * Creates a CSS rule from a theme object.\n *\n * Useful for scenarios when you want to apply theming statically to a top level elements like `body`.\n */\nexport function createCSSRuleFromTheme(selector: string, theme: PartialTheme | undefined): string {\n const escapedSelector = escapeForStyleTag(selector);\n\n if (theme) {\n const cssVarsAsString = (Object.keys(theme) as (keyof typeof theme)[]).reduce((cssVarRule, cssVar) => {\n return `${cssVarRule}--${cssVar}: ${theme[cssVar]}; `;\n }, '');\n\n return `${escapedSelector} { ${escapeForStyleTag(cssVarsAsString)} }`;\n }\n\n return `${escapedSelector} {}`;\n}\n"],"names":["CSS_ESCAPE_MAP","escapeForStyleTag","value","replace","match","createCSSRuleFromTheme","selector","theme","escapedSelector","cssVarsAsString","Object","keys","reduce","cssVarRule","cssVar"],"mappings":";;;;+BAuBgBK;;;;;;AArBhB,MAAML,iBAAiB;IACrB,KAAK;IACL,KAAK;AACP;AACA;;;;;CAKC,GACD,SAASC,kBAAkBC,KAAa;IACtC,uFAAuF;IACvF,kGAAkG;IAClG,OAAOA,MAAMC,OAAO,CAAC,SAASC,CAAAA,QAASJ,cAAc,CAACI,MAAqC;AAC7F;AAOO,gCAAgCE,QAAgB,EAAEC,KAA+B;IACtF,MAAMC,kBAAkBP,kBAAkBK;IAE1C,IAAIC,OAAO;QACT,MAAME,kBAAmBC,OAAOC,IAAI,CAACJ,OAAkCK,MAAM,CAAC,CAACC,YAAYC;YACzF,OAAO,GAAGD,WAAW,EAAE,EAAEC,OAAO,EAAE,EAAEP,KAAK,CAACO,OAAO,CAAC,EAAE,CAAC;QACvD,GAAG;QAEH,OAAO,GAAGN,gBAAgB,GAAG,EAAEP,kBAAkBQ,iBAAiB,EAAE,CAAC;IACvE;IAEA,OAAO,GAAGD,gBAAgB,GAAG,CAAC;AAChC"}
1
+ {"version":3,"sources":["../src/components/FluentProvider/createCSSRuleFromTheme.ts"],"sourcesContent":["import type { PartialTheme } from '@fluentui/react-theme';\n\nconst BLOCKLIST_NAME_PATTERN = /[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~\\u0000-\\u0020\\u007F]/;\nconst BLOCKLIST_VALUE_PATTERN = /[!<>{};[\\]\\\\\\u0000-\\u0008\\u000B\\u000E-\\u001F\\u007F]|\\/\\*/;\nconst CLOSED_PARTS_PATTERN = /\"[^\"\\u0000-\\u001F\\u007F]*\"|'[^'\\u0000-\\u001F\\u007F]*'|\\([^\"'()]*\\)/g;\nconst BLOCKLIST_UNMATCHED_DELIMITERS_PATTERN = /[\"'()]/;\n\nfunction escapeCharacter(character: string): string {\n return `\\\\${character.charCodeAt(0).toString(16).toUpperCase()} `;\n}\n\nfunction escapeSelector(value: string): string {\n // Consume whole backslash runs so escaping preserves their parity and does not retry overlapping suffixes.\n return value.replace(/\\\\+[<{}]?|[<{}]/g, match => {\n const character = match[match.length - 1];\n if (!'<{}'.includes(character)) {\n return match;\n }\n\n const backslashes = match.length - 1;\n return match.slice(0, backslashes - (backslashes % 2)) + escapeCharacter(character);\n });\n}\n\nfunction warnThemeToken(name: string, reason: string): void {\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.warn(`@fluentui/react-provider: ${reason} for theme token ${JSON.stringify(name)}.`);\n }\n}\n\n/**\n * Creates a CSS rule from a theme object.\n *\n * Useful for scenarios when you want to apply theming statically to a top level elements like `body`.\n * Values with blocked symbols or unsupported quotes/parentheses are omitted, not repaired.\n * No function-name or value-format allowlist is used. Validate dynamic data against an application-specific schema.\n */\nexport function createCSSRuleFromTheme(selector: string, theme: PartialTheme | undefined): string {\n const escapedSelector = escapeSelector(selector);\n\n if (theme) {\n const cssVarsAsString = (Object.keys(theme) as (keyof typeof theme)[]).reduce((cssVarRule, cssVar) => {\n const tokenValue: unknown = theme[cssVar];\n if (!cssVar || BLOCKLIST_NAME_PATTERN.test(cssVar)) {\n warnThemeToken(cssVar, 'Ignoring an unsupported CSS custom property name');\n return cssVarRule;\n }\n if (typeof tokenValue !== 'string' && (typeof tokenValue !== 'number' || !Number.isFinite(tokenValue))) {\n warnThemeToken(cssVar, 'Ignoring an unsupported CSS custom property value');\n return cssVarRule;\n }\n\n const value = String(tokenValue);\n // Ignore complete strings and flat parentheses only while looking for leftover syntax; never rewrite the value.\n if (\n BLOCKLIST_VALUE_PATTERN.test(value) ||\n BLOCKLIST_UNMATCHED_DELIMITERS_PATTERN.test(value.replace(CLOSED_PARTS_PATTERN, ''))\n ) {\n warnThemeToken(cssVar, 'Ignoring an unsupported CSS custom property value');\n return cssVarRule;\n }\n\n return `${cssVarRule}--${cssVar}: ${value}; `;\n }, '');\n\n return `${escapedSelector} { ${cssVarsAsString} }`;\n }\n\n return `${escapedSelector} {}`;\n}\n"],"names":["BLOCKLIST_NAME_PATTERN","BLOCKLIST_VALUE_PATTERN","CLOSED_PARTS_PATTERN","BLOCKLIST_UNMATCHED_DELIMITERS_PATTERN","escapeCharacter","character","charCodeAt","toString","toUpperCase","escapeSelector","value","replace","match","length","includes","backslashes","slice","warnThemeToken","name","reason","process","env","NODE_ENV","console","warn","JSON","stringify","createCSSRuleFromTheme","selector","theme","escapedSelector","cssVarsAsString","Object","keys","reduce","cssVarRule","cssVar","tokenValue","test","Number","isFinite","String"],"mappings":";;;;+BAsCgB2B;;;;;;AApChB,MAAM3B,yBAAyB;AAC/B,MAAMC,0BAA0B;AAChC,MAAMC,uBAAuB;AAC7B,MAAMC,yCAAyC;AAE/C,SAASC,gBAAgBC,SAAiB;IACxC,OAAO,CAAC,EAAE,EAAEA,UAAUC,UAAU,CAAC,GAAGC,QAAQ,CAAC,IAAIC,WAAW,GAAG,CAAC,CAAC;AACnE;AAEA,SAASC,eAAeC,KAAa;IACnC,2GAA2G;IAC3G,OAAOA,MAAMC,OAAO,CAAC,oBAAoBC,CAAAA;QACvC,MAAMP,YAAYO,KAAK,CAACA,MAAMC,MAAM,GAAG,EAAE;QACzC,IAAI,CAAC,MAAMC,QAAQ,CAACT,YAAY;YAC9B,OAAOO;QACT;QAEA,MAAMG,cAAcH,MAAMC,MAAM,GAAG;QACnC,OAAOD,MAAMI,KAAK,CAAC,GAAGD,cAAeA,cAAc,KAAMX,gBAAgBC;IAC3E;AACF;AAEA,SAASY,eAAeC,IAAY,EAAEC,MAAc;IAClD,IAAIC,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;QACzC,sCAAsC;QACtCC,QAAQC,IAAI,CAAC,CAAC,0BAA0B,EAAEL,OAAO,iBAAiB,EAAEM,KAAKC,SAAS,CAACR,MAAM,CAAC,CAAC;IAC7F;AACF;AASO,gCAAgCU,QAAgB,EAAEC,KAA+B;IACtF,MAAMC,kBAAkBrB,eAAemB;IAEvC,IAAIC,OAAO;QACT,MAAME,kBAAmBC,OAAOC,IAAI,CAACJ,OAAkCK,MAAM,CAAC,CAACC,YAAYC;YACzF,MAAMC,aAAsBR,KAAK,CAACO,OAAO;YACzC,IAAI,CAACA,UAAUpC,uBAAuBsC,IAAI,CAACF,SAAS;gBAClDnB,eAAemB,QAAQ;gBACvB,OAAOD;YACT;YACA,IAAI,OAAOE,eAAe,YAAa,CAAA,OAAOA,eAAe,YAAY,CAACE,OAAOC,QAAQ,CAACH,WAAAA,CAAU,EAAI;gBACtGpB,eAAemB,QAAQ;gBACvB,OAAOD;YACT;YAEA,MAAMzB,QAAQ+B,OAAOJ;YACrB,gHAAgH;YAChH,IACEpC,wBAAwBqC,IAAI,CAAC5B,UAC7BP,uCAAuCmC,IAAI,CAAC5B,MAAMC,OAAO,CAACT,sBAAsB,MAChF;gBACAe,eAAemB,QAAQ;gBACvB,OAAOD;YACT;YAEA,OAAO,GAAGA,WAAW,EAAE,EAAEC,OAAO,EAAE,EAAE1B,MAAM,EAAE,CAAC;QAC/C,GAAG;QAEH,OAAO,GAAGoB,gBAAgB,GAAG,EAAEC,gBAAgB,EAAE,CAAC;IACpD;IAEA,OAAO,GAAGD,gBAAgB,GAAG,CAAC;AAChC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluentui/react-provider",
3
- "version": "9.22.20",
3
+ "version": "9.22.22",
4
4
  "description": "Fluent UI React provider component",
5
5
  "main": "lib-commonjs/index.cjs",
6
6
  "module": "lib/index.js",
@@ -13,20 +13,23 @@
13
13
  "license": "MIT",
14
14
  "dependencies": {
15
15
  "@fluentui/react-icons": "^2.0.245",
16
- "@fluentui/react-jsx-runtime": "^9.4.5",
17
- "@fluentui/react-shared-contexts": "^9.26.3",
18
- "@fluentui/react-tabster": "^9.26.17",
16
+ "@fluentui/react-jsx-runtime": "^9.4.7",
17
+ "@fluentui/react-shared-contexts": "^9.26.4",
18
+ "@fluentui/react-tabster": "^9.26.19",
19
19
  "@fluentui/react-theme": "^9.2.2",
20
- "@fluentui/react-utilities": "^9.26.6",
20
+ "@fluentui/react-utilities": "^9.27.0",
21
21
  "@griffel/core": "^1.16.0",
22
22
  "@griffel/react": "^1.5.32",
23
23
  "@swc/helpers": "^0.5.1"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "@types/react": ">=16.14.0 <20.0.0",
27
- "@types/react-dom": ">=16.9.0 <20.0.0",
28
- "react": ">=16.14.0 <20.0.0",
29
- "react-dom": ">=16.14.0 <20.0.0"
27
+ "react": ">=16.14.0 <20.0.0"
28
+ },
29
+ "peerDependenciesMeta": {
30
+ "@types/react": {
31
+ "optional": true
32
+ }
30
33
  },
31
34
  "beachball": {
32
35
  "disallowedChangeTypes": [