@wise/components-theming 0.0.0-experimental-15bed93 → 0.0.0-experimental-9fc22a2

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 +1 @@
1
- {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../src/ThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAkC,MAAM,OAAO,CAAC;AAG1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAKvC,KAAK,kBAAkB,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAK9E,eAAO,MAAM,aAAa,GAAI,gEAM3B,kBAAkB,gCAkCpB,CAAC"}
1
+ {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../src/ThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAkC,MAAM,OAAO,CAAC;AAG1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAKvC,KAAK,kBAAkB,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAK9E,eAAO,MAAM,aAAa,GAAI,gEAM3B,kBAAkB,gCAqCpB,CAAC"}
@@ -13,29 +13,31 @@ const ThemeProvider = ({
13
13
  screenMode = _const.DEFAULT_SCREEN_MODE,
14
14
  children,
15
15
  className = undefined,
16
- isNotRootProvider = undefined
16
+ isNotRootProvider = false
17
17
  }) => {
18
- const contextExists = react.useContext(ThemeProviderContext.ThemeContext) !== undefined;
19
- const isContextRoot = isNotRootProvider !== undefined ? !isNotRootProvider : !contextExists;
18
+ const isContextRoot = react.useContext(ThemeProviderContext.ThemeContext) === undefined;
20
19
  // useEffect hook used to apply the theme class to the HTML element
21
20
  react.useEffect(() => {
22
- if (isContextRoot) {
21
+ if (!isNotRootProvider && isContextRoot) {
23
22
  // Remove all the theme classes from the documentElement
24
23
  document.documentElement.className.match(themeClass)?.forEach(item => {
25
24
  document.documentElement.classList.remove(item);
26
25
  });
27
26
  const themeClasses = helpers.getThemeClassName(theme, screenMode).split(' ');
27
+ // Auto-detection: Add np-theme-personal for business and platform themes when this is a root provider (page wrapper)
28
+ const isBusinessTheme = theme === 'business' || theme?.startsWith('business');
29
+ const isPlatformTheme = theme === 'platform' || theme?.startsWith('platform');
30
+ const shouldAddPersonalClass = (isBusinessTheme || isPlatformTheme) && !isNotRootProvider;
31
+ // Apply theme classes
28
32
  themeClasses.forEach(item => {
29
33
  document.documentElement.classList.add(item);
30
34
  });
31
- // Add np-theme-personal for business and platform themes at root level only
32
- const isBusinessTheme = theme === 'business' || theme?.startsWith('business');
33
- const isPlatformTheme = theme === 'platform' || theme?.startsWith('platform');
34
- if (isBusinessTheme || isPlatformTheme) {
35
+ // Add np-theme-personal for business and platform themes only in root provider (page wrapper)
36
+ if (shouldAddPersonalClass) {
35
37
  document.documentElement.classList.add('np-theme-personal');
36
38
  }
37
39
  }
38
- }, [isContextRoot, theme, screenMode]);
40
+ }, [isNotRootProvider, isContextRoot, theme, screenMode]);
39
41
  const contextValue = react.useMemo(() => ({
40
42
  theme,
41
43
  screenMode
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.js","sources":["../src/ThemeProvider.tsx"],"sourcesContent":["import { PropsWithChildren, useContext, useEffect, useMemo } from 'react';\n\nimport { ThemedChildren } from './ThemedChildren';\nimport type { Theming } from './const';\nimport { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { getThemeClassName } from './helpers';\nimport { ThemeContext } from './ThemeProviderContext';\n\ntype ThemeProviderProps = PropsWithChildren<Theming> & { className?: string };\n\n// RegEx to check for `np-theme-` class name\nconst themeClass = /\\bnp-theme-[a-z-]+\\b/g;\n\nexport const ThemeProvider = ({\n theme = DEFAULT_BASE_THEME,\n screenMode = DEFAULT_SCREEN_MODE,\n children,\n className = undefined,\n isNotRootProvider = undefined,\n}: ThemeProviderProps) => {\n const contextExists = useContext(ThemeContext) !== undefined;\n const isContextRoot = isNotRootProvider !== undefined ? !isNotRootProvider : !contextExists;\n\n // useEffect hook used to apply the theme class to the HTML element\n useEffect(() => {\n if (isContextRoot) {\n // Remove all the theme classes from the documentElement\n document.documentElement.className.match(themeClass)?.forEach((item) => {\n document.documentElement.classList.remove(item);\n });\n\n const themeClasses = getThemeClassName(theme, screenMode).split(' ');\n themeClasses.forEach((item) => {\n document.documentElement.classList.add(item);\n });\n\n // Add np-theme-personal for business and platform themes at root level only\n const isBusinessTheme = theme === 'business' || theme?.startsWith('business');\n const isPlatformTheme = theme === 'platform' || theme?.startsWith('platform');\n\n if (isBusinessTheme || isPlatformTheme) {\n document.documentElement.classList.add('np-theme-personal');\n }\n }\n }, [isContextRoot, theme, screenMode]);\n\n const contextValue = useMemo(() => ({ theme, screenMode }), [screenMode, theme]);\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemedChildren className={className}>{children}</ThemedChildren>\n </ThemeContext.Provider>\n );\n};\n"],"names":["themeClass","ThemeProvider","theme","DEFAULT_BASE_THEME","screenMode","DEFAULT_SCREEN_MODE","children","className","undefined","isNotRootProvider","contextExists","useContext","ThemeContext","isContextRoot","useEffect","document","documentElement","match","forEach","item","classList","remove","themeClasses","getThemeClassName","split","add","isBusinessTheme","startsWith","isPlatformTheme","contextValue","useMemo","_jsx","Provider","value","ThemedChildren"],"mappings":";;;;;;;;;AAWA,MAAMA,UAAU,GAAG,uBAAuB;AAEnC,MAAMC,aAAa,GAAGA,CAAC;AAC5BC,EAAAA,KAAK,GAAGC,yBAAkB;AAC1BC,EAAAA,UAAU,GAAGC,0BAAmB;EAChCC,QAAQ;AACRC,EAAAA,SAAS,GAAGC,SAAS;AACrBC,EAAAA,iBAAiB,GAAGD;AAAS,CACV,KAAI;AACvB,EAAA,MAAME,aAAa,GAAGC,gBAAU,CAACC,iCAAY,CAAC,KAAKJ,SAAS;EAC5D,MAAMK,aAAa,GAAGJ,iBAAiB,KAAKD,SAAS,GAAG,CAACC,iBAAiB,GAAG,CAACC,aAAa;AAE3F;AACAI,EAAAA,eAAS,CAAC,MAAK;AACb,IAAA,IAAID,aAAa,EAAE;AACjB;AACAE,MAAAA,QAAQ,CAACC,eAAe,CAACT,SAAS,CAACU,KAAK,CAACjB,UAAU,CAAC,EAAEkB,OAAO,CAAEC,IAAI,IAAI;QACrEJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACC,MAAM,CAACF,IAAI,CAAC;AACjD,MAAA,CAAC,CAAC;AAEF,MAAA,MAAMG,YAAY,GAAGC,yBAAiB,CAACrB,KAAK,EAAEE,UAAU,CAAC,CAACoB,KAAK,CAAC,GAAG,CAAC;AACpEF,MAAAA,YAAY,CAACJ,OAAO,CAAEC,IAAI,IAAI;QAC5BJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACK,GAAG,CAACN,IAAI,CAAC;AAC9C,MAAA,CAAC,CAAC;AAEF;MACA,MAAMO,eAAe,GAAGxB,KAAK,KAAK,UAAU,IAAIA,KAAK,EAAEyB,UAAU,CAAC,UAAU,CAAC;MAC7E,MAAMC,eAAe,GAAG1B,KAAK,KAAK,UAAU,IAAIA,KAAK,EAAEyB,UAAU,CAAC,UAAU,CAAC;MAE7E,IAAID,eAAe,IAAIE,eAAe,EAAE;QACtCb,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACK,GAAG,CAAC,mBAAmB,CAAC;AAC7D,MAAA;AACF,IAAA;EACF,CAAC,EAAE,CAACZ,aAAa,EAAEX,KAAK,EAAEE,UAAU,CAAC,CAAC;AAEtC,EAAA,MAAMyB,YAAY,GAAGC,aAAO,CAAC,OAAO;IAAE5B,KAAK;AAAEE,IAAAA;AAAU,GAAE,CAAC,EAAE,CAACA,UAAU,EAAEF,KAAK,CAAC,CAAC;AAEhF,EAAA,oBACE6B,cAAA,CAACnB,iCAAY,CAACoB,QAAQ,EAAA;AAACC,IAAAA,KAAK,EAAEJ,YAAa;IAAAvB,QAAA,eACzCyB,cAAA,CAACG,6BAAc,EAAA;AAAC3B,MAAAA,SAAS,EAAEA,SAAU;AAAAD,MAAAA,QAAA,EAAEA;KAAyB;AAClE,GAAuB,CAAC;AAE5B;;;;"}
1
+ {"version":3,"file":"ThemeProvider.js","sources":["../src/ThemeProvider.tsx"],"sourcesContent":["import { PropsWithChildren, useContext, useEffect, useMemo } from 'react';\n\nimport { ThemedChildren } from './ThemedChildren';\nimport type { Theming } from './const';\nimport { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { getThemeClassName } from './helpers';\nimport { ThemeContext } from './ThemeProviderContext';\n\ntype ThemeProviderProps = PropsWithChildren<Theming> & { className?: string };\n\n// RegEx to check for `np-theme-` class name\nconst themeClass = /\\bnp-theme-[a-z-]+\\b/g;\n\nexport const ThemeProvider = ({\n theme = DEFAULT_BASE_THEME,\n screenMode = DEFAULT_SCREEN_MODE,\n children,\n className = undefined,\n isNotRootProvider = false,\n}: ThemeProviderProps) => {\n const isContextRoot = useContext(ThemeContext) === undefined;\n\n // useEffect hook used to apply the theme class to the HTML element\n useEffect(() => {\n if (!isNotRootProvider && isContextRoot) {\n // Remove all the theme classes from the documentElement\n document.documentElement.className.match(themeClass)?.forEach((item) => {\n document.documentElement.classList.remove(item);\n });\n\n const themeClasses = getThemeClassName(theme, screenMode).split(' ');\n\n // Auto-detection: Add np-theme-personal for business and platform themes when this is a root provider (page wrapper)\n const isBusinessTheme = theme === 'business' || theme?.startsWith('business');\n const isPlatformTheme = theme === 'platform' || theme?.startsWith('platform');\n const shouldAddPersonalClass = (isBusinessTheme || isPlatformTheme) && !isNotRootProvider;\n\n // Apply theme classes\n themeClasses.forEach((item) => {\n document.documentElement.classList.add(item);\n });\n\n // Add np-theme-personal for business and platform themes only in root provider (page wrapper)\n if (shouldAddPersonalClass) {\n document.documentElement.classList.add('np-theme-personal');\n }\n }\n }, [isNotRootProvider, isContextRoot, theme, screenMode]);\n\n const contextValue = useMemo(() => ({ theme, screenMode }), [screenMode, theme]);\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemedChildren className={className}>{children}</ThemedChildren>\n </ThemeContext.Provider>\n );\n};\n"],"names":["themeClass","ThemeProvider","theme","DEFAULT_BASE_THEME","screenMode","DEFAULT_SCREEN_MODE","children","className","undefined","isNotRootProvider","isContextRoot","useContext","ThemeContext","useEffect","document","documentElement","match","forEach","item","classList","remove","themeClasses","getThemeClassName","split","isBusinessTheme","startsWith","isPlatformTheme","shouldAddPersonalClass","add","contextValue","useMemo","_jsx","Provider","value","ThemedChildren"],"mappings":";;;;;;;;;AAWA,MAAMA,UAAU,GAAG,uBAAuB;AAEnC,MAAMC,aAAa,GAAGA,CAAC;AAC5BC,EAAAA,KAAK,GAAGC,yBAAkB;AAC1BC,EAAAA,UAAU,GAAGC,0BAAmB;EAChCC,QAAQ;AACRC,EAAAA,SAAS,GAAGC,SAAS;AACrBC,EAAAA,iBAAiB,GAAG;AAAK,CACN,KAAI;AACvB,EAAA,MAAMC,aAAa,GAAGC,gBAAU,CAACC,iCAAY,CAAC,KAAKJ,SAAS;AAE5D;AACAK,EAAAA,eAAS,CAAC,MAAK;AACb,IAAA,IAAI,CAACJ,iBAAiB,IAAIC,aAAa,EAAE;AACvC;AACAI,MAAAA,QAAQ,CAACC,eAAe,CAACR,SAAS,CAACS,KAAK,CAAChB,UAAU,CAAC,EAAEiB,OAAO,CAAEC,IAAI,IAAI;QACrEJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACC,MAAM,CAACF,IAAI,CAAC;AACjD,MAAA,CAAC,CAAC;AAEF,MAAA,MAAMG,YAAY,GAAGC,yBAAiB,CAACpB,KAAK,EAAEE,UAAU,CAAC,CAACmB,KAAK,CAAC,GAAG,CAAC;AAEpE;MACA,MAAMC,eAAe,GAAGtB,KAAK,KAAK,UAAU,IAAIA,KAAK,EAAEuB,UAAU,CAAC,UAAU,CAAC;MAC7E,MAAMC,eAAe,GAAGxB,KAAK,KAAK,UAAU,IAAIA,KAAK,EAAEuB,UAAU,CAAC,UAAU,CAAC;MAC7E,MAAME,sBAAsB,GAAG,CAACH,eAAe,IAAIE,eAAe,KAAK,CAACjB,iBAAiB;AAEzF;AACAY,MAAAA,YAAY,CAACJ,OAAO,CAAEC,IAAI,IAAI;QAC5BJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACS,GAAG,CAACV,IAAI,CAAC;AAC9C,MAAA,CAAC,CAAC;AAEF;AACA,MAAA,IAAIS,sBAAsB,EAAE;QAC1Bb,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACS,GAAG,CAAC,mBAAmB,CAAC;AAC7D,MAAA;AACF,IAAA;EACF,CAAC,EAAE,CAACnB,iBAAiB,EAAEC,aAAa,EAAER,KAAK,EAAEE,UAAU,CAAC,CAAC;AAEzD,EAAA,MAAMyB,YAAY,GAAGC,aAAO,CAAC,OAAO;IAAE5B,KAAK;AAAEE,IAAAA;AAAU,GAAE,CAAC,EAAE,CAACA,UAAU,EAAEF,KAAK,CAAC,CAAC;AAEhF,EAAA,oBACE6B,cAAA,CAACnB,iCAAY,CAACoB,QAAQ,EAAA;AAACC,IAAAA,KAAK,EAAEJ,YAAa;IAAAvB,QAAA,eACzCyB,cAAA,CAACG,6BAAc,EAAA;AAAC3B,MAAAA,SAAS,EAAEA,SAAU;AAAAD,MAAAA,QAAA,EAAEA;KAAyB;AAClE,GAAuB,CAAC;AAE5B;;;;"}
@@ -11,29 +11,31 @@ const ThemeProvider = ({
11
11
  screenMode = DEFAULT_SCREEN_MODE,
12
12
  children,
13
13
  className = undefined,
14
- isNotRootProvider = undefined
14
+ isNotRootProvider = false
15
15
  }) => {
16
- const contextExists = useContext(ThemeContext) !== undefined;
17
- const isContextRoot = isNotRootProvider !== undefined ? !isNotRootProvider : !contextExists;
16
+ const isContextRoot = useContext(ThemeContext) === undefined;
18
17
  // useEffect hook used to apply the theme class to the HTML element
19
18
  useEffect(() => {
20
- if (isContextRoot) {
19
+ if (!isNotRootProvider && isContextRoot) {
21
20
  // Remove all the theme classes from the documentElement
22
21
  document.documentElement.className.match(themeClass)?.forEach(item => {
23
22
  document.documentElement.classList.remove(item);
24
23
  });
25
24
  const themeClasses = getThemeClassName(theme, screenMode).split(' ');
25
+ // Auto-detection: Add np-theme-personal for business and platform themes when this is a root provider (page wrapper)
26
+ const isBusinessTheme = theme === 'business' || theme?.startsWith('business');
27
+ const isPlatformTheme = theme === 'platform' || theme?.startsWith('platform');
28
+ const shouldAddPersonalClass = (isBusinessTheme || isPlatformTheme) && !isNotRootProvider;
29
+ // Apply theme classes
26
30
  themeClasses.forEach(item => {
27
31
  document.documentElement.classList.add(item);
28
32
  });
29
- // Add np-theme-personal for business and platform themes at root level only
30
- const isBusinessTheme = theme === 'business' || theme?.startsWith('business');
31
- const isPlatformTheme = theme === 'platform' || theme?.startsWith('platform');
32
- if (isBusinessTheme || isPlatformTheme) {
33
+ // Add np-theme-personal for business and platform themes only in root provider (page wrapper)
34
+ if (shouldAddPersonalClass) {
33
35
  document.documentElement.classList.add('np-theme-personal');
34
36
  }
35
37
  }
36
- }, [isContextRoot, theme, screenMode]);
38
+ }, [isNotRootProvider, isContextRoot, theme, screenMode]);
37
39
  const contextValue = useMemo(() => ({
38
40
  theme,
39
41
  screenMode
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.mjs","sources":["../src/ThemeProvider.tsx"],"sourcesContent":["import { PropsWithChildren, useContext, useEffect, useMemo } from 'react';\n\nimport { ThemedChildren } from './ThemedChildren';\nimport type { Theming } from './const';\nimport { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { getThemeClassName } from './helpers';\nimport { ThemeContext } from './ThemeProviderContext';\n\ntype ThemeProviderProps = PropsWithChildren<Theming> & { className?: string };\n\n// RegEx to check for `np-theme-` class name\nconst themeClass = /\\bnp-theme-[a-z-]+\\b/g;\n\nexport const ThemeProvider = ({\n theme = DEFAULT_BASE_THEME,\n screenMode = DEFAULT_SCREEN_MODE,\n children,\n className = undefined,\n isNotRootProvider = undefined,\n}: ThemeProviderProps) => {\n const contextExists = useContext(ThemeContext) !== undefined;\n const isContextRoot = isNotRootProvider !== undefined ? !isNotRootProvider : !contextExists;\n\n // useEffect hook used to apply the theme class to the HTML element\n useEffect(() => {\n if (isContextRoot) {\n // Remove all the theme classes from the documentElement\n document.documentElement.className.match(themeClass)?.forEach((item) => {\n document.documentElement.classList.remove(item);\n });\n\n const themeClasses = getThemeClassName(theme, screenMode).split(' ');\n themeClasses.forEach((item) => {\n document.documentElement.classList.add(item);\n });\n\n // Add np-theme-personal for business and platform themes at root level only\n const isBusinessTheme = theme === 'business' || theme?.startsWith('business');\n const isPlatformTheme = theme === 'platform' || theme?.startsWith('platform');\n\n if (isBusinessTheme || isPlatformTheme) {\n document.documentElement.classList.add('np-theme-personal');\n }\n }\n }, [isContextRoot, theme, screenMode]);\n\n const contextValue = useMemo(() => ({ theme, screenMode }), [screenMode, theme]);\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemedChildren className={className}>{children}</ThemedChildren>\n </ThemeContext.Provider>\n );\n};\n"],"names":["themeClass","ThemeProvider","theme","DEFAULT_BASE_THEME","screenMode","DEFAULT_SCREEN_MODE","children","className","undefined","isNotRootProvider","contextExists","useContext","ThemeContext","isContextRoot","useEffect","document","documentElement","match","forEach","item","classList","remove","themeClasses","getThemeClassName","split","add","isBusinessTheme","startsWith","isPlatformTheme","contextValue","useMemo","_jsx","Provider","value","ThemedChildren"],"mappings":";;;;;;;AAWA,MAAMA,UAAU,GAAG,uBAAuB;AAEnC,MAAMC,aAAa,GAAGA,CAAC;AAC5BC,EAAAA,KAAK,GAAGC,kBAAkB;AAC1BC,EAAAA,UAAU,GAAGC,mBAAmB;EAChCC,QAAQ;AACRC,EAAAA,SAAS,GAAGC,SAAS;AACrBC,EAAAA,iBAAiB,GAAGD;AAAS,CACV,KAAI;AACvB,EAAA,MAAME,aAAa,GAAGC,UAAU,CAACC,YAAY,CAAC,KAAKJ,SAAS;EAC5D,MAAMK,aAAa,GAAGJ,iBAAiB,KAAKD,SAAS,GAAG,CAACC,iBAAiB,GAAG,CAACC,aAAa;AAE3F;AACAI,EAAAA,SAAS,CAAC,MAAK;AACb,IAAA,IAAID,aAAa,EAAE;AACjB;AACAE,MAAAA,QAAQ,CAACC,eAAe,CAACT,SAAS,CAACU,KAAK,CAACjB,UAAU,CAAC,EAAEkB,OAAO,CAAEC,IAAI,IAAI;QACrEJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACC,MAAM,CAACF,IAAI,CAAC;AACjD,MAAA,CAAC,CAAC;AAEF,MAAA,MAAMG,YAAY,GAAGC,iBAAiB,CAACrB,KAAK,EAAEE,UAAU,CAAC,CAACoB,KAAK,CAAC,GAAG,CAAC;AACpEF,MAAAA,YAAY,CAACJ,OAAO,CAAEC,IAAI,IAAI;QAC5BJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACK,GAAG,CAACN,IAAI,CAAC;AAC9C,MAAA,CAAC,CAAC;AAEF;MACA,MAAMO,eAAe,GAAGxB,KAAK,KAAK,UAAU,IAAIA,KAAK,EAAEyB,UAAU,CAAC,UAAU,CAAC;MAC7E,MAAMC,eAAe,GAAG1B,KAAK,KAAK,UAAU,IAAIA,KAAK,EAAEyB,UAAU,CAAC,UAAU,CAAC;MAE7E,IAAID,eAAe,IAAIE,eAAe,EAAE;QACtCb,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACK,GAAG,CAAC,mBAAmB,CAAC;AAC7D,MAAA;AACF,IAAA;EACF,CAAC,EAAE,CAACZ,aAAa,EAAEX,KAAK,EAAEE,UAAU,CAAC,CAAC;AAEtC,EAAA,MAAMyB,YAAY,GAAGC,OAAO,CAAC,OAAO;IAAE5B,KAAK;AAAEE,IAAAA;AAAU,GAAE,CAAC,EAAE,CAACA,UAAU,EAAEF,KAAK,CAAC,CAAC;AAEhF,EAAA,oBACE6B,GAAA,CAACnB,YAAY,CAACoB,QAAQ,EAAA;AAACC,IAAAA,KAAK,EAAEJ,YAAa;IAAAvB,QAAA,eACzCyB,GAAA,CAACG,cAAc,EAAA;AAAC3B,MAAAA,SAAS,EAAEA,SAAU;AAAAD,MAAAA,QAAA,EAAEA;KAAyB;AAClE,GAAuB,CAAC;AAE5B;;;;"}
1
+ {"version":3,"file":"ThemeProvider.mjs","sources":["../src/ThemeProvider.tsx"],"sourcesContent":["import { PropsWithChildren, useContext, useEffect, useMemo } from 'react';\n\nimport { ThemedChildren } from './ThemedChildren';\nimport type { Theming } from './const';\nimport { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { getThemeClassName } from './helpers';\nimport { ThemeContext } from './ThemeProviderContext';\n\ntype ThemeProviderProps = PropsWithChildren<Theming> & { className?: string };\n\n// RegEx to check for `np-theme-` class name\nconst themeClass = /\\bnp-theme-[a-z-]+\\b/g;\n\nexport const ThemeProvider = ({\n theme = DEFAULT_BASE_THEME,\n screenMode = DEFAULT_SCREEN_MODE,\n children,\n className = undefined,\n isNotRootProvider = false,\n}: ThemeProviderProps) => {\n const isContextRoot = useContext(ThemeContext) === undefined;\n\n // useEffect hook used to apply the theme class to the HTML element\n useEffect(() => {\n if (!isNotRootProvider && isContextRoot) {\n // Remove all the theme classes from the documentElement\n document.documentElement.className.match(themeClass)?.forEach((item) => {\n document.documentElement.classList.remove(item);\n });\n\n const themeClasses = getThemeClassName(theme, screenMode).split(' ');\n\n // Auto-detection: Add np-theme-personal for business and platform themes when this is a root provider (page wrapper)\n const isBusinessTheme = theme === 'business' || theme?.startsWith('business');\n const isPlatformTheme = theme === 'platform' || theme?.startsWith('platform');\n const shouldAddPersonalClass = (isBusinessTheme || isPlatformTheme) && !isNotRootProvider;\n\n // Apply theme classes\n themeClasses.forEach((item) => {\n document.documentElement.classList.add(item);\n });\n\n // Add np-theme-personal for business and platform themes only in root provider (page wrapper)\n if (shouldAddPersonalClass) {\n document.documentElement.classList.add('np-theme-personal');\n }\n }\n }, [isNotRootProvider, isContextRoot, theme, screenMode]);\n\n const contextValue = useMemo(() => ({ theme, screenMode }), [screenMode, theme]);\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemedChildren className={className}>{children}</ThemedChildren>\n </ThemeContext.Provider>\n );\n};\n"],"names":["themeClass","ThemeProvider","theme","DEFAULT_BASE_THEME","screenMode","DEFAULT_SCREEN_MODE","children","className","undefined","isNotRootProvider","isContextRoot","useContext","ThemeContext","useEffect","document","documentElement","match","forEach","item","classList","remove","themeClasses","getThemeClassName","split","isBusinessTheme","startsWith","isPlatformTheme","shouldAddPersonalClass","add","contextValue","useMemo","_jsx","Provider","value","ThemedChildren"],"mappings":";;;;;;;AAWA,MAAMA,UAAU,GAAG,uBAAuB;AAEnC,MAAMC,aAAa,GAAGA,CAAC;AAC5BC,EAAAA,KAAK,GAAGC,kBAAkB;AAC1BC,EAAAA,UAAU,GAAGC,mBAAmB;EAChCC,QAAQ;AACRC,EAAAA,SAAS,GAAGC,SAAS;AACrBC,EAAAA,iBAAiB,GAAG;AAAK,CACN,KAAI;AACvB,EAAA,MAAMC,aAAa,GAAGC,UAAU,CAACC,YAAY,CAAC,KAAKJ,SAAS;AAE5D;AACAK,EAAAA,SAAS,CAAC,MAAK;AACb,IAAA,IAAI,CAACJ,iBAAiB,IAAIC,aAAa,EAAE;AACvC;AACAI,MAAAA,QAAQ,CAACC,eAAe,CAACR,SAAS,CAACS,KAAK,CAAChB,UAAU,CAAC,EAAEiB,OAAO,CAAEC,IAAI,IAAI;QACrEJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACC,MAAM,CAACF,IAAI,CAAC;AACjD,MAAA,CAAC,CAAC;AAEF,MAAA,MAAMG,YAAY,GAAGC,iBAAiB,CAACpB,KAAK,EAAEE,UAAU,CAAC,CAACmB,KAAK,CAAC,GAAG,CAAC;AAEpE;MACA,MAAMC,eAAe,GAAGtB,KAAK,KAAK,UAAU,IAAIA,KAAK,EAAEuB,UAAU,CAAC,UAAU,CAAC;MAC7E,MAAMC,eAAe,GAAGxB,KAAK,KAAK,UAAU,IAAIA,KAAK,EAAEuB,UAAU,CAAC,UAAU,CAAC;MAC7E,MAAME,sBAAsB,GAAG,CAACH,eAAe,IAAIE,eAAe,KAAK,CAACjB,iBAAiB;AAEzF;AACAY,MAAAA,YAAY,CAACJ,OAAO,CAAEC,IAAI,IAAI;QAC5BJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACS,GAAG,CAACV,IAAI,CAAC;AAC9C,MAAA,CAAC,CAAC;AAEF;AACA,MAAA,IAAIS,sBAAsB,EAAE;QAC1Bb,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACS,GAAG,CAAC,mBAAmB,CAAC;AAC7D,MAAA;AACF,IAAA;EACF,CAAC,EAAE,CAACnB,iBAAiB,EAAEC,aAAa,EAAER,KAAK,EAAEE,UAAU,CAAC,CAAC;AAEzD,EAAA,MAAMyB,YAAY,GAAGC,OAAO,CAAC,OAAO;IAAE5B,KAAK;AAAEE,IAAAA;AAAU,GAAE,CAAC,EAAE,CAACA,UAAU,EAAEF,KAAK,CAAC,CAAC;AAEhF,EAAA,oBACE6B,GAAA,CAACnB,YAAY,CAACoB,QAAQ,EAAA;AAACC,IAAAA,KAAK,EAAEJ,YAAa;IAAAvB,QAAA,eACzCyB,GAAA,CAACG,cAAc,EAAA;AAAC3B,MAAAA,SAAS,EAAEA,SAAU;AAAAD,MAAAA,QAAA,EAAEA;KAAyB;AAClE,GAAuB,CAAC;AAE5B;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wise/components-theming",
3
- "version": "0.0.0-experimental-15bed93",
3
+ "version": "0.0.0-experimental-9fc22a2",
4
4
  "description": "Provides theming support for the Wise Design system components",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -77,6 +77,140 @@ describe('ThemeProvider', () => {
77
77
  );
78
78
  });
79
79
 
80
+ it('adds personal class for business theme when isNotRootProvider=false (default)', () => {
81
+ const mockClassList = {
82
+ add: jest.fn(),
83
+ remove: jest.fn(),
84
+ };
85
+
86
+ Object.defineProperty(document, 'documentElement', {
87
+ value: { className: '', classList: mockClassList },
88
+ writable: true,
89
+ });
90
+
91
+ render(
92
+ <ThemeProvider theme="business">
93
+ <div>business-auto-fix</div>
94
+ </ThemeProvider>,
95
+ );
96
+
97
+ expect(mockClassList.add).toHaveBeenCalledWith('np-theme-personal');
98
+ expect(mockClassList.add).toHaveBeenCalledWith('np-theme-business');
99
+ });
100
+
101
+ it('does not add personal class for business theme with isNotRootProvider=true', () => {
102
+ const mockClassList = {
103
+ add: jest.fn(),
104
+ remove: jest.fn(),
105
+ };
106
+
107
+ Object.defineProperty(document, 'documentElement', {
108
+ value: { className: '', classList: mockClassList },
109
+ writable: true,
110
+ });
111
+
112
+ render(
113
+ <ThemeProvider theme="business" isNotRootProvider>
114
+ <div>business-component</div>
115
+ </ThemeProvider>,
116
+ );
117
+
118
+ expect(mockClassList.add).not.toHaveBeenCalledWith('np-theme-personal');
119
+ expect(mockClassList.add).not.toHaveBeenCalled();
120
+
121
+ // The component wrapper should still get the business theme class via ThemedChildren
122
+ expect(screen.getByText('business-component')).toBeInTheDocument();
123
+ // Note: We can't easily test the wrapper class without direct node access,
124
+ // but the functionality is verified by the existing integration tests
125
+ });
126
+
127
+ it('adds personal class for personal theme', () => {
128
+ const mockClassList = {
129
+ add: jest.fn(),
130
+ remove: jest.fn(),
131
+ };
132
+
133
+ Object.defineProperty(document, 'documentElement', {
134
+ value: { className: '', classList: mockClassList },
135
+ writable: true,
136
+ });
137
+
138
+ render(
139
+ <ThemeProvider theme="personal">
140
+ <div>personal</div>
141
+ </ThemeProvider>,
142
+ );
143
+
144
+ expect(mockClassList.add).toHaveBeenCalledWith('np-theme-personal');
145
+ });
146
+
147
+ it('does not add personal class for light theme', () => {
148
+ const mockClassList = {
149
+ add: jest.fn(),
150
+ remove: jest.fn(),
151
+ };
152
+
153
+ Object.defineProperty(document, 'documentElement', {
154
+ value: { className: '', classList: mockClassList },
155
+ writable: true,
156
+ });
157
+
158
+ render(
159
+ <ThemeProvider theme="light">
160
+ <div>light</div>
161
+ </ThemeProvider>,
162
+ );
163
+
164
+ expect(mockClassList.add).toHaveBeenCalledWith('np-theme-light');
165
+ expect(mockClassList.add).not.toHaveBeenCalledWith('np-theme-personal');
166
+ });
167
+
168
+ it('adds personal class for platform theme when isNotRootProvider=false (default)', () => {
169
+ const mockClassList = {
170
+ add: jest.fn(),
171
+ remove: jest.fn(),
172
+ };
173
+
174
+ Object.defineProperty(document, 'documentElement', {
175
+ value: { className: '', classList: mockClassList },
176
+ writable: true,
177
+ });
178
+
179
+ render(
180
+ <ThemeProvider theme="platform">
181
+ <div>platform-auto-fix</div>
182
+ </ThemeProvider>,
183
+ );
184
+
185
+ expect(mockClassList.add).toHaveBeenCalledWith('np-theme-personal');
186
+ expect(mockClassList.add).toHaveBeenCalledWith('np-theme-platform');
187
+ });
188
+
189
+ it('does not add personal class for platform theme with isNotRootProvider=true', () => {
190
+ const mockClassList = {
191
+ add: jest.fn(),
192
+ remove: jest.fn(),
193
+ };
194
+
195
+ Object.defineProperty(document, 'documentElement', {
196
+ value: { className: '', classList: mockClassList },
197
+ writable: true,
198
+ });
199
+
200
+ render(
201
+ <ThemeProvider theme="platform" isNotRootProvider>
202
+ <div>platform-component</div>
203
+ </ThemeProvider>,
204
+ );
205
+
206
+ expect(mockClassList.add).not.toHaveBeenCalledWith('np-theme-personal');
207
+ expect(mockClassList.add).not.toHaveBeenCalled();
208
+
209
+ // The component wrapper should still get the platform theme class via ThemedChildren
210
+ expect(screen.getByText('platform-component')).toBeInTheDocument();
211
+ // Note: We can't easily test the wrapper class without direct node access,
212
+ // but the functionality is verified by the existing integration tests
213
+ });
80
214
  it('matches snapshot', () => {
81
215
  const { asFragment } = render(
82
216
  <ThemeProvider theme="light">
@@ -16,33 +16,36 @@ export const ThemeProvider = ({
16
16
  screenMode = DEFAULT_SCREEN_MODE,
17
17
  children,
18
18
  className = undefined,
19
- isNotRootProvider = undefined,
19
+ isNotRootProvider = false,
20
20
  }: ThemeProviderProps) => {
21
- const contextExists = useContext(ThemeContext) !== undefined;
22
- const isContextRoot = isNotRootProvider !== undefined ? !isNotRootProvider : !contextExists;
21
+ const isContextRoot = useContext(ThemeContext) === undefined;
23
22
 
24
23
  // useEffect hook used to apply the theme class to the HTML element
25
24
  useEffect(() => {
26
- if (isContextRoot) {
25
+ if (!isNotRootProvider && isContextRoot) {
27
26
  // Remove all the theme classes from the documentElement
28
27
  document.documentElement.className.match(themeClass)?.forEach((item) => {
29
28
  document.documentElement.classList.remove(item);
30
29
  });
31
30
 
32
31
  const themeClasses = getThemeClassName(theme, screenMode).split(' ');
33
- themeClasses.forEach((item) => {
34
- document.documentElement.classList.add(item);
35
- });
36
32
 
37
- // Add np-theme-personal for business and platform themes at root level only
33
+ // Auto-detection: Add np-theme-personal for business and platform themes when this is a root provider (page wrapper)
38
34
  const isBusinessTheme = theme === 'business' || theme?.startsWith('business');
39
35
  const isPlatformTheme = theme === 'platform' || theme?.startsWith('platform');
36
+ const shouldAddPersonalClass = (isBusinessTheme || isPlatformTheme) && !isNotRootProvider;
37
+
38
+ // Apply theme classes
39
+ themeClasses.forEach((item) => {
40
+ document.documentElement.classList.add(item);
41
+ });
40
42
 
41
- if (isBusinessTheme || isPlatformTheme) {
43
+ // Add np-theme-personal for business and platform themes only in root provider (page wrapper)
44
+ if (shouldAddPersonalClass) {
42
45
  document.documentElement.classList.add('np-theme-personal');
43
46
  }
44
47
  }
45
- }, [isContextRoot, theme, screenMode]);
48
+ }, [isNotRootProvider, isContextRoot, theme, screenMode]);
46
49
 
47
50
  const contextValue = useMemo(() => ({ theme, screenMode }), [screenMode, theme]);
48
51