@descope-ui/common 0.1.0 → 0.1.2

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
@@ -2,6 +2,15 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ## [0.1.2](https://github.com/descope/web-components-ui/compare/@descope-ui/common-0.1.1...@descope-ui/common-0.1.2) (2025-09-30)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * st error ([#732](https://github.com/descope/web-components-ui/issues/732)) ([a00ba1b](https://github.com/descope/web-components-ui/commit/a00ba1b28651f846fe8ff337e254d2c87a9a3947))
11
+
12
+ ## [0.1.1](https://github.com/descope/web-components-ui/compare/@descope-ui/common-0.1.0...@descope-ui/common-0.1.1) (2025-09-29)
13
+
5
14
  ## [0.1.0](https://github.com/descope/web-components-ui/compare/@descope-ui/common-0.0.18...@descope-ui/common-0.1.0) (2025-09-02)
6
15
 
7
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@descope-ui/common",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "dependencies": {
5
5
  "element-internals-polyfill": "^1.3.9",
6
6
  "color": "^4.2.3",
@@ -102,5 +102,4 @@ export const createCssVarsList = (componentName, mappings) =>
102
102
 
103
103
  // on some cases we need a selector to be more specific than another
104
104
  // for this we have this fn that generate a class selector multiple times
105
- export const createClassSelectorSpecifier = (className, numOfRepeats) =>
106
- Array(numOfRepeats).fill(`.${className}`).join('');
105
+ export const createClassSelectorSpecifier = (className, numOfRepeats) => `.${className}`.repeat(numOfRepeats);
@@ -100,20 +100,24 @@ export const createStyleMixin =
100
100
 
101
101
  #createOverridesStyle() {
102
102
  if (this.#styleAttributes.length) {
103
- const classSpecifier = createClassSelectorSpecifier(
103
+ let classSpecifier = createClassSelectorSpecifier(
104
104
  componentName,
105
- CSS_SELECTOR_SPECIFIER_MULTIPLY,
105
+ CSS_SELECTOR_SPECIFIER_MULTIPLY
106
106
  );
107
+ const elementId = this.getAttribute('id');
108
+ if (elementId) {
109
+ // basically this is enough to make the selector more specific
110
+ // but just in case there is no id, we will also add the class multiple times
111
+ classSpecifier += `#${elementId}`;
112
+ }
107
113
 
108
- this.#overrideStyleEle = injectStyle(
109
- `:host(${classSpecifier}) {}`,
110
- this.#rootElement,
111
- );
114
+ this.#overrideStyleEle = injectStyle(`:host(${classSpecifier}) {}`, this.#rootElement);
112
115
  }
113
116
  }
114
117
 
118
+
115
119
  #setAttrOverride(attrName, value) {
116
- const style = this.#overrideStyleEle?.cssRules[0].style;
120
+ const style = this.#overrideStyleEle?.cssRules[0]?.style;
117
121
 
118
122
  if (!style) return;
119
123
 
package/src/constants.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export const DESCOPE_PREFIX = 'descope';
2
- export const CSS_SELECTOR_SPECIFIER_MULTIPLY = 3;
2
+ export const CSS_SELECTOR_SPECIFIER_MULTIPLY = 5;
3
3
  export const BASE_THEME_SECTION = 'host';
4
4
  export const PORTAL_THEME_PREFIX = '@';
@@ -71,6 +71,15 @@ export const globalsThemeToStyle = (theme, themeName = '') => {
71
71
  return `*[data-theme="${themeName}"] {${style}}`;
72
72
  };
73
73
 
74
+ function splitAmpersands(str) {
75
+ const match = str.match(/^(&+)?(.*)$/);
76
+ return [match[1] || "", (match[2] || "")];
77
+ }
78
+
79
+ // st attributes are also using selector multiplication
80
+ // so we need to limit the multiplication
81
+ const MAX_SELECTOR_MULTIPLY = 3;
82
+
74
83
  const componentsThemeToStyleObj = (componentsTheme) =>
75
84
  transformTheme(componentsTheme, [], (path, val) => {
76
85
  const [component, ...restPath] = path;
@@ -79,10 +88,7 @@ const componentsThemeToStyleObj = (componentsTheme) =>
79
88
 
80
89
  if (property === 'undefined') {
81
90
  // eslint-disable-next-line no-console
82
- console.warn(
83
- componentName,
84
- `theme value: "${val}" is mapped to an invalid property`,
85
- );
91
+ console.warn(componentName, `theme value: "${val}" is mapped to an invalid property`);
86
92
  }
87
93
 
88
94
  // we need a support for portal components theme (e.g. overlay)
@@ -98,23 +104,26 @@ const componentsThemeToStyleObj = (componentsTheme) =>
98
104
  // do not start with underscore -> key:value, must have 2 no underscore attrs in a row
99
105
  // starts with underscore -> attribute selector
100
106
  const attrsSelector = restPath.reduce((acc, section, idx) => {
101
- if (section.startsWith('_'))
102
- return `${acc}[${kebabCase(section.replace(/^_/, ''))}="true"]`;
107
+ const [ampersands, content] = splitAmpersands(section);
108
+ const selectorMultiplier = Math.min(
109
+ ampersands.length + 1, // if there are no & we need to multiply by 1
110
+ MAX_SELECTOR_MULTIPLY
111
+ );
112
+
113
+ if (content.startsWith('_')) return acc + `[${kebabCase(content.replace(/^_/, ''))}="true"]`.repeat(selectorMultiplier);
103
114
 
104
115
  const nextSection = restPath[idx + 1];
105
116
 
106
- if (typeof nextSection !== 'string' || nextSection.startsWith('_')) {
117
+ if (typeof nextSection !== 'string' || nextSection.startsWith('_') || nextSection.startsWith('&')) {
107
118
  // eslint-disable-next-line no-console
108
119
  console.error(
109
120
  'theme generator',
110
- `your theme structure is invalid, attribute "${section}" is followed by "${nextSection}" which is not allowed`,
121
+ `your theme structure is invalid, attribute "${section}" is followed by "${nextSection}" which is not allowed`
111
122
  );
112
123
  return acc;
113
124
  }
114
125
 
115
- return `${acc}[${kebabCase(section)}="${restPath
116
- .splice(idx + 1, 1)
117
- .join('')}"]`;
126
+ return acc + `[${kebabCase(content)}="${restPath.splice(idx + 1, 1).join('')}"]`.repeat(selectorMultiplier);
118
127
  }, '');
119
128
 
120
129
  const selector = `:host${attrsSelector ? `(${attrsSelector})` : ''}`;