@descope/web-components-ui 1.0.367 → 1.0.369

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/dist/index.esm.js CHANGED
@@ -1401,7 +1401,9 @@ const getFileExtension = (path) => {
1401
1401
  return match ? match[1] : null;
1402
1402
  };
1403
1403
 
1404
- const isSvg = (src) => getFileExtension(src) === 'svg' || src.indexOf('image/svg+xml') > -1;
1404
+ const base64Prefix = 'data:image/svg+xml;base64,';
1405
+
1406
+ const isBase64Svg = (src) => src.startsWith(base64Prefix);
1405
1407
 
1406
1408
  const createImgEle = (src) => {
1407
1409
  const ele = document.createElement('img');
@@ -1418,12 +1420,17 @@ const createSvgEle = (text) => {
1418
1420
  const createIcon = async (src) => {
1419
1421
  try {
1420
1422
  let ele;
1421
-
1422
- if (isSvg(src)) {
1423
+ if (isBase64Svg(src)) {
1424
+ // handle base64 source
1425
+ const svgXml = atob(src.slice(base64Prefix.length));
1426
+ ele = createSvgEle(svgXml);
1427
+ } else if (getFileExtension(src) === 'svg') {
1428
+ // handle urls
1423
1429
  const fetchedSrc = await fetch(src);
1424
1430
  const text = await fetchedSrc.text();
1425
1431
  ele = createSvgEle(text);
1426
1432
  } else {
1433
+ // handle binary
1427
1434
  ele = createImgEle(src);
1428
1435
  }
1429
1436
 
@@ -11877,132 +11884,509 @@ const RadioGroupClass = compose(
11877
11884
  customElements.define(componentName$4, RadioGroupClass);
11878
11885
  customElements.define(componentName$5, RadioButtonClass);
11879
11886
 
11880
- const getVarName = (path) => getCssVarName(DESCOPE_PREFIX, ...path);
11887
+ const activeableMixin = (superclass) =>
11888
+ class ActiveableMixinClass extends superclass {
11889
+ init() {
11890
+ super.init?.();
11881
11891
 
11882
- // lodash.set alternative
11883
- const set = (obj, path, value) => {
11884
- const pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g);
11892
+ this.baseElement.addEventListener('mousedown', (e) => {
11893
+ e.preventDefault();
11894
+ this.setAttribute('active', 'true');
11895
+ window.addEventListener('mouseup', () => this.removeAttribute('active'), {
11896
+ once: true,
11897
+ });
11898
+ });
11899
+ }
11900
+ };
11885
11901
 
11886
- pathArray.reduce((acc, key, i) => {
11887
- if (acc[key] === undefined) acc[key] = {};
11888
- if (i === pathArray.length - 1) acc[key] = value;
11889
- return acc[key];
11890
- }, obj);
11902
+ const componentName$3 = getComponentName('list-item');
11891
11903
 
11892
- return obj;
11893
- };
11904
+ const customMixin$1 = (superclass) =>
11905
+ class ListItemMixinClass extends superclass {
11906
+ constructor() {
11907
+ super();
11894
11908
 
11895
- const transformTheme = (theme, path, getTransformation) => {
11896
- return Object.entries(theme).reduce((acc, [key, val]) => {
11897
- if (val?.constructor !== Object) {
11898
- return merge(acc, getTransformation(path.concat(key), val));
11909
+ this.attachShadow({ mode: 'open' }).innerHTML = `
11910
+ <style>
11911
+ /*css*/
11912
+ slot {
11913
+ width: 100%;
11914
+ display: flex;
11915
+ overflow: hidden;
11916
+ box-sizing: border-box;
11917
+ }
11918
+ :host {
11919
+ display: block;
11920
+ }
11921
+
11922
+ /*!css*/
11923
+ </style>
11924
+ <slot></slot>
11925
+ `;
11899
11926
  }
11900
- return merge(acc, transformTheme(val, [...path, key], getTransformation));
11901
- }, {});
11902
- };
11927
+ };
11903
11928
 
11904
- const stringifyArray = (strArr) =>
11905
- strArr.map((str) => (str.includes(' ') ? `"${str}"` : str)).join(', ');
11929
+ const ListItemClass = compose(
11930
+ createStyleMixin({
11931
+ mappings: {
11932
+ padding: {},
11933
+ backgroundColor: {},
11934
+ borderColor: {},
11935
+ borderStyle: {},
11936
+ borderWidth: {},
11937
+ borderRadius: {},
11938
+ outline: {},
11939
+ cursor: {},
11940
+ gap: {},
11941
+ maxWidth: { selector: () => ':host' },
11942
+ alignItems: {},
11943
+ flexDirection: {},
11944
+ transition: {},
11945
+ },
11946
+ }),
11947
+ draggableMixin,
11948
+ componentNameValidationMixin,
11949
+ customMixin$1,
11950
+ activeableMixin
11951
+ )(createBaseClass({ componentName: componentName$3, baseSelector: 'slot' }));
11906
11952
 
11907
- const getCssVarValue = (val) => {
11908
- switch (true) {
11909
- case Array.isArray(val):
11910
- return stringifyArray(val);
11911
- case isUrl(val):
11912
- return `url(${val})`;
11913
- default:
11914
- return val;
11915
- }
11916
- };
11953
+ const componentName$2 = getComponentName('list');
11917
11954
 
11918
- const themeToCSSVarsObj = (theme) =>
11919
- transformTheme(theme, [], (path, val) => ({
11920
- [getVarName(path)]: getCssVarValue(val),
11921
- }));
11955
+ class RawList extends createBaseClass({ componentName: componentName$2, baseSelector: '.wrapper' }) {
11956
+ static get observedAttributes() {
11957
+ return ['variant'];
11958
+ }
11922
11959
 
11923
- const getThemeRefs = (theme, prefix) =>
11924
- transformTheme(theme, [], (path) =>
11925
- set({}, path, `var(${getVarName(prefix ? [prefix, ...path] : path)})`)
11926
- );
11960
+ constructor() {
11961
+ super();
11927
11962
 
11928
- const getThemeVars = (theme, prefix) =>
11929
- transformTheme(theme, [], (path) => set({}, path, getVarName(prefix ? [prefix, ...path] : path)));
11963
+ this.attachShadow({ mode: 'open' }).innerHTML = `
11964
+ <style>
11965
+ /*css*/
11966
+ .wrapper {
11967
+ overflow: auto;
11968
+ display: grid;
11969
+ max-height: 100%;
11970
+ width: 100%;
11971
+ }
11930
11972
 
11931
- const globalsThemeToStyle = (theme, themeName = '') => {
11932
- const style = Object.entries(themeToCSSVarsObj(theme)).reduce(
11933
- (acc, entry) => `${acc}${entry.join(':')};\n`,
11934
- ''
11935
- );
11973
+ :host {
11974
+ display: inline-flex;
11975
+ width: 100%;
11976
+ }
11977
+ slot[name="empty-state"] {
11978
+ justify-content: center;
11979
+ align-items: center;
11980
+ display: flex;
11981
+ flex-grow: 1;
11982
+ }
11936
11983
 
11937
- if (!themeName) return style;
11984
+ :host slot[name="empty-state"] {
11985
+ display: none;
11986
+ }
11987
+ :host([empty]) slot[name="empty-state"] {
11988
+ display: flex;
11989
+ }
11990
+ ::slotted(:not([slot])) {
11991
+ width: 100%;
11992
+ }
11993
+ /*!css*/
11994
+ </style>
11938
11995
 
11939
- return `*[data-theme="${themeName}"] {${style}}`;
11940
- };
11996
+ <div class="wrapper">
11997
+ <slot></slot>
11998
+ <slot name="empty-state">
11999
+ No item...
12000
+ </slot>
12001
+ </div>
12002
+ `;
12003
+ }
11941
12004
 
11942
- const componentsThemeToStyleObj = (componentsTheme) =>
11943
- transformTheme(componentsTheme, [], (path, val) => {
11944
- const [component, ...restPath] = path;
11945
- const property = restPath.pop();
11946
- const componentName = getComponentName(component);
12005
+ get items() {
12006
+ return this.shadowRoot.querySelector('slot').assignedElements();
12007
+ }
11947
12008
 
11948
- if (property === 'undefined') {
11949
- // eslint-disable-next-line no-console
11950
- console.warn(componentName, `theme value: "${val}" is mapped to an invalid property`);
12009
+ #handleEmptyState() {
12010
+ if (this.items.length === 0) {
12011
+ this.setAttribute('empty', 'true');
12012
+ } else {
12013
+ this.removeAttribute('empty');
11951
12014
  }
12015
+ }
11952
12016
 
11953
- // we need a support for portal components theme (e.g. overlay)
11954
- // this allows us to generate those themes under different sections
11955
- // if the theme has root level attribute that starts with #
11956
- // we are generating a new theme
11957
- let themeName = BASE_THEME_SECTION;
12017
+ get variant() {
12018
+ return this.getAttribute('variant') || 'list';
12019
+ }
11958
12020
 
11959
- if (restPath[0] && restPath[0].startsWith(PORTAL_THEME_PREFIX)) {
11960
- themeName = restPath.shift();
11961
- }
12021
+ #handleItemsVariant() {
12022
+ this.items.forEach((item) => {
12023
+ let listItem = item;
12024
+ if (listItem.localName !== ListItemClass.componentName) {
12025
+ listItem = item.querySelector(ListItemClass.componentName);
12026
+ }
11962
12027
 
11963
- // do not start with underscore -> key:value, must have 2 no underscore attrs in a row
11964
- // starts with underscore -> attribute selector
11965
- const attrsSelector = restPath.reduce((acc, section, idx) => {
11966
- if (section.startsWith('_')) return `${acc}[${kebabCase(section.replace(/^_/, ''))}="true"]`;
12028
+ const listItemVariant = this.variant === 'tiles' ? 'tile' : 'row';
12029
+ listItem.setAttribute('variant', listItemVariant);
12030
+ });
12031
+ }
11967
12032
 
11968
- const nextSection = restPath[idx + 1];
12033
+ init() {
12034
+ super.init?.();
11969
12035
 
11970
- if (typeof nextSection !== 'string' || nextSection.startsWith('_')) {
11971
- // eslint-disable-next-line no-console
11972
- console.error(
11973
- 'theme generator',
11974
- `your theme structure is invalid, attribute "${section}" is followed by "${nextSection}" which is not allowed`
11975
- );
11976
- return acc;
11977
- }
12036
+ // we want new items to get the size
12037
+ observeChildren(this, () => {
12038
+ this.#handleEmptyState();
12039
+ this.#handleItemsVariant();
12040
+ });
12041
+ }
11978
12042
 
11979
- return `${acc}[${kebabCase(section)}="${restPath.splice(idx + 1, 1).join('')}"]`;
11980
- }, '');
12043
+ attributeChangedCallback(name, oldValue, newValue) {
12044
+ super.attributeChangedCallback?.(name, oldValue, newValue);
11981
12045
 
11982
- const selector = `:host${attrsSelector ? `(${attrsSelector})` : ''}`;
12046
+ if (newValue === oldValue) return;
11983
12047
 
11984
- return {
11985
- [componentName]: {
11986
- [themeName]: {
11987
- [selector]: {
11988
- [property]: getCssVarValue(val),
11989
- },
11990
- },
11991
- },
11992
- };
11993
- });
12048
+ if (name === 'variant') {
12049
+ this.#handleItemsVariant();
12050
+ }
12051
+ }
12052
+ }
11994
12053
 
11995
- const componentsThemeToStyle = (componentsTheme) =>
11996
- Object.entries(componentsTheme).reduce(
11997
- (acc, [selector, vars]) =>
11998
- `${acc}${selector} { \n${Object.entries(vars)
11999
- .map(([key, val]) => `${key}: ${val}`)
12000
- .join(';\n')} \n}\n\n`,
12001
- ''
12002
- );
12054
+ const ListClass = compose(
12055
+ createStyleMixin({
12056
+ mappings: {
12057
+ hostWidth: { selector: () => ':host', property: 'width' },
12058
+ maxHeight: { selector: () => ':host' },
12059
+ minHeight: {},
12060
+ verticalPadding: [{ property: 'padding-top' }, { property: 'padding-bottom' }],
12061
+ horizontalPadding: [{ property: 'padding-left' }, { property: 'padding-right' }],
12062
+ hostDirection: { selector: () => ':host', property: 'direction' },
12063
+ fontFamily: {},
12064
+ gap: {},
12003
12065
 
12004
- const createComponentsTheme = (componentsTheme) => {
12005
- const styleObj = componentsThemeToStyleObj(componentsTheme);
12066
+ backgroundColor: {},
12067
+ borderRadius: {},
12068
+ borderColor: {},
12069
+ borderStyle: {},
12070
+ borderWidth: {},
12071
+
12072
+ boxShadow: {},
12073
+ gridTemplateColumns: {},
12074
+ maxItemsWidth: { selector: () => '::slotted(:not([slot]))', property: 'max-width' },
12075
+ minItemsWidth: { selector: () => '::slotted(:not([slot]))', property: 'min-width' },
12076
+ itemsHorizontalAlign: { selector: () => '::slotted(*)', property: 'justify-self' },
12077
+ emptyStateTextColor: { selector: () => 'slot[name="empty-state"]', property: 'color' },
12078
+ emptyStateTextFontFamily: {
12079
+ selector: () => 'slot[name="empty-state"]',
12080
+ property: 'font-family',
12081
+ },
12082
+ },
12083
+ }),
12084
+ draggableMixin,
12085
+ componentNameValidationMixin
12086
+ )(RawList);
12087
+
12088
+ customElements.define(componentName$2, ListClass);
12089
+ customElements.define(componentName$3, ListItemClass);
12090
+
12091
+ const defaultValidateSchema = () => true;
12092
+ const defaultItemRenderer = (item) => `<pre>${JSON.stringify(item, null, 4)}</pre>`;
12093
+
12094
+ const createTemplate = (templateString) => {
12095
+ const template = document.createElement('template');
12096
+ template.innerHTML = templateString;
12097
+
12098
+ return template;
12099
+ };
12100
+
12101
+ const getTemplateContent = (templateOrString) => {
12102
+ if (typeof templateOrString === 'string') {
12103
+ return createTemplate(templateOrString).content;
12104
+ }
12105
+
12106
+ if (templateOrString instanceof HTMLTemplateElement) {
12107
+ return templateOrString.content;
12108
+ }
12109
+
12110
+ // eslint-disable-next-line no-console
12111
+ console.error('Invalid template', templateOrString);
12112
+ return null;
12113
+ };
12114
+
12115
+ const createDynamicDataMixin =
12116
+ ({
12117
+ itemRenderer = defaultItemRenderer,
12118
+ validateSchema = defaultValidateSchema,
12119
+ slotName,
12120
+ rerenderAttrsList = [],
12121
+ }) =>
12122
+ (superclass) =>
12123
+ class DynamicDataMixinClass extends superclass {
12124
+ #data = [];
12125
+
12126
+ // eslint-disable-next-line class-methods-use-this
12127
+ #validateSchema(data) {
12128
+ if (!validateSchema) return true;
12129
+
12130
+ const validation = validateSchema(data);
12131
+ if (validation === true) return true;
12132
+
12133
+ // eslint-disable-next-line no-console
12134
+ console.error('Data schema validation failed', validation || '');
12135
+
12136
+ return false;
12137
+ }
12138
+
12139
+ #removeOldItems() {
12140
+ const selector = slotName ? `*[slot="${slotName}"]` : ':not([slot])';
12141
+ this.baseElement.querySelectorAll(selector).forEach((item) => item.remove());
12142
+ }
12143
+
12144
+ #renderItems() {
12145
+ this.#removeOldItems();
12146
+ this.data.forEach((item, index) => {
12147
+ const content = getTemplateContent(itemRenderer(item, index, this));
12148
+ this.baseElement.appendChild(content?.cloneNode(true));
12149
+ });
12150
+ }
12151
+
12152
+ set data(value) {
12153
+ if (this.#validateSchema(value)) {
12154
+ this.#data = value;
12155
+ this.#renderItems();
12156
+ }
12157
+ }
12158
+
12159
+ get data() {
12160
+ return this.#data;
12161
+ }
12162
+
12163
+ init() {
12164
+ super.init?.();
12165
+
12166
+ if (rerenderAttrsList.length) {
12167
+ observeAttributes(this, () => this.#renderItems(), { includeAttrs: rerenderAttrsList });
12168
+ } else {
12169
+ this.#renderItems();
12170
+ }
12171
+ }
12172
+ };
12173
+
12174
+ const componentName$1 = getComponentName('apps-list');
12175
+
12176
+ const limitAbbreviation = (str, limit = 3) =>
12177
+ str
12178
+ .trim()
12179
+ .split(' ')
12180
+ .splice(0, limit)
12181
+ .map((s) => s[0]?.toUpperCase())
12182
+ .join('');
12183
+
12184
+ const itemRenderer = ({ name, icon, url }, _, ref) => `
12185
+ <a href="${url}" target="_blank" title="${url}">
12186
+ <descope-list-item>
12187
+ <descope-avatar
12188
+ img="${icon}"
12189
+ display-name="${name}"
12190
+ abbr=${limitAbbreviation(name)}
12191
+ size=${ref.size}
12192
+ ></descope-avatar>
12193
+ <descope-text
12194
+ variant="body1"
12195
+ mode="primary"
12196
+ >${name}</descope-text>
12197
+ </descope-list-item>
12198
+ </a>
12199
+ `;
12200
+
12201
+ const customMixin = (superclass) =>
12202
+ class AppsListMixinClass extends superclass {
12203
+ get size() {
12204
+ return this.getAttribute('size') || 'sm';
12205
+ }
12206
+ };
12207
+
12208
+ const AppsListClass = compose(
12209
+ createStyleMixin({
12210
+ mappings: {
12211
+ maxHeight: { selector: () => ':host' },
12212
+ minHeight: { selector: () => ':host' },
12213
+ hostDirection: { selector: () => ':host', property: 'direction' },
12214
+ itemsFontWeight: {
12215
+ selector: TextClass.componentName,
12216
+ property: TextClass.cssVarList.fontWeight,
12217
+ },
12218
+ itemsFontSize: {
12219
+ selector: TextClass.componentName,
12220
+ property: TextClass.cssVarList.fontSize,
12221
+ },
12222
+ itemsTextAlign: {
12223
+ selector: TextClass.componentName,
12224
+ property: TextClass.cssVarList.textAlign,
12225
+ },
12226
+ },
12227
+ }),
12228
+ createDynamicDataMixin({ itemRenderer, rerenderAttrsList: ['size'] }),
12229
+ draggableMixin,
12230
+ componentNameValidationMixin,
12231
+ customMixin
12232
+ )(
12233
+ createProxy({
12234
+ slots: ['empty-state'],
12235
+ wrappedEleName: 'descope-list',
12236
+ excludeAttrsSync: ['tabindex', 'class'],
12237
+ componentName: componentName$1,
12238
+ style: () => `
12239
+ :host {
12240
+ width: 100%;
12241
+ display: inline-flex;
12242
+ }
12243
+
12244
+ descope-text::part(text-wrapper) {
12245
+ display: -webkit-box;
12246
+ -webkit-line-clamp: 2;
12247
+ -webkit-box-orient: vertical;
12248
+ overflow: hidden;
12249
+ }
12250
+
12251
+ a {
12252
+ text-decoration: none;
12253
+ }
12254
+
12255
+ descope-text {
12256
+ ${TextClass.cssVarList.hostDirection}: var(${AppsListClass.cssVarList.hostDirection});
12257
+ }
12258
+ `,
12259
+ })
12260
+ );
12261
+
12262
+ customElements.define(componentName$1, AppsListClass);
12263
+
12264
+ const getVarName = (path) => getCssVarName(DESCOPE_PREFIX, ...path);
12265
+
12266
+ // lodash.set alternative
12267
+ const set = (obj, path, value) => {
12268
+ const pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g);
12269
+
12270
+ pathArray.reduce((acc, key, i) => {
12271
+ if (acc[key] === undefined) acc[key] = {};
12272
+ if (i === pathArray.length - 1) acc[key] = value;
12273
+ return acc[key];
12274
+ }, obj);
12275
+
12276
+ return obj;
12277
+ };
12278
+
12279
+ const transformTheme = (theme, path, getTransformation) => {
12280
+ return Object.entries(theme).reduce((acc, [key, val]) => {
12281
+ if (val?.constructor !== Object) {
12282
+ return merge(acc, getTransformation(path.concat(key), val));
12283
+ }
12284
+ return merge(acc, transformTheme(val, [...path, key], getTransformation));
12285
+ }, {});
12286
+ };
12287
+
12288
+ const stringifyArray = (strArr) =>
12289
+ strArr.map((str) => (str.includes(' ') ? `"${str}"` : str)).join(', ');
12290
+
12291
+ const getCssVarValue = (val) => {
12292
+ switch (true) {
12293
+ case Array.isArray(val):
12294
+ return stringifyArray(val);
12295
+ case isUrl(val):
12296
+ return `url(${val})`;
12297
+ default:
12298
+ return val;
12299
+ }
12300
+ };
12301
+
12302
+ const themeToCSSVarsObj = (theme) =>
12303
+ transformTheme(theme, [], (path, val) => ({
12304
+ [getVarName(path)]: getCssVarValue(val),
12305
+ }));
12306
+
12307
+ const getThemeRefs = (theme, prefix) =>
12308
+ transformTheme(theme, [], (path) =>
12309
+ set({}, path, `var(${getVarName(prefix ? [prefix, ...path] : path)})`)
12310
+ );
12311
+
12312
+ const getThemeVars = (theme, prefix) =>
12313
+ transformTheme(theme, [], (path) => set({}, path, getVarName(prefix ? [prefix, ...path] : path)));
12314
+
12315
+ const globalsThemeToStyle = (theme, themeName = '') => {
12316
+ const style = Object.entries(themeToCSSVarsObj(theme)).reduce(
12317
+ (acc, entry) => `${acc}${entry.join(':')};\n`,
12318
+ ''
12319
+ );
12320
+
12321
+ if (!themeName) return style;
12322
+
12323
+ return `*[data-theme="${themeName}"] {${style}}`;
12324
+ };
12325
+
12326
+ const componentsThemeToStyleObj = (componentsTheme) =>
12327
+ transformTheme(componentsTheme, [], (path, val) => {
12328
+ const [component, ...restPath] = path;
12329
+ const property = restPath.pop();
12330
+ const componentName = getComponentName(component);
12331
+
12332
+ if (property === 'undefined') {
12333
+ // eslint-disable-next-line no-console
12334
+ console.warn(componentName, `theme value: "${val}" is mapped to an invalid property`);
12335
+ }
12336
+
12337
+ // we need a support for portal components theme (e.g. overlay)
12338
+ // this allows us to generate those themes under different sections
12339
+ // if the theme has root level attribute that starts with #
12340
+ // we are generating a new theme
12341
+ let themeName = BASE_THEME_SECTION;
12342
+
12343
+ if (restPath[0] && restPath[0].startsWith(PORTAL_THEME_PREFIX)) {
12344
+ themeName = restPath.shift();
12345
+ }
12346
+
12347
+ // do not start with underscore -> key:value, must have 2 no underscore attrs in a row
12348
+ // starts with underscore -> attribute selector
12349
+ const attrsSelector = restPath.reduce((acc, section, idx) => {
12350
+ if (section.startsWith('_')) return `${acc}[${kebabCase(section.replace(/^_/, ''))}="true"]`;
12351
+
12352
+ const nextSection = restPath[idx + 1];
12353
+
12354
+ if (typeof nextSection !== 'string' || nextSection.startsWith('_')) {
12355
+ // eslint-disable-next-line no-console
12356
+ console.error(
12357
+ 'theme generator',
12358
+ `your theme structure is invalid, attribute "${section}" is followed by "${nextSection}" which is not allowed`
12359
+ );
12360
+ return acc;
12361
+ }
12362
+
12363
+ return `${acc}[${kebabCase(section)}="${restPath.splice(idx + 1, 1).join('')}"]`;
12364
+ }, '');
12365
+
12366
+ const selector = `:host${attrsSelector ? `(${attrsSelector})` : ''}`;
12367
+
12368
+ return {
12369
+ [componentName]: {
12370
+ [themeName]: {
12371
+ [selector]: {
12372
+ [property]: getCssVarValue(val),
12373
+ },
12374
+ },
12375
+ },
12376
+ };
12377
+ });
12378
+
12379
+ const componentsThemeToStyle = (componentsTheme) =>
12380
+ Object.entries(componentsTheme).reduce(
12381
+ (acc, [selector, vars]) =>
12382
+ `${acc}${selector} { \n${Object.entries(vars)
12383
+ .map(([key, val]) => `${key}: ${val}`)
12384
+ .join(';\n')} \n}\n\n`,
12385
+ ''
12386
+ );
12387
+
12388
+ const createComponentsTheme = (componentsTheme) => {
12389
+ const styleObj = componentsThemeToStyleObj(componentsTheme);
12006
12390
 
12007
12391
  return Object.keys(styleObj).reduce((acc, componentName) => {
12008
12392
  const componentThemes = styleObj[componentName];
@@ -12444,7 +12828,7 @@ var button$1 = /*#__PURE__*/Object.freeze({
12444
12828
  vars: vars$L
12445
12829
  });
12446
12830
 
12447
- const componentName$3 = getComponentName('input-wrapper');
12831
+ const componentName = getComponentName('input-wrapper');
12448
12832
  const globalRefs$u = getThemeRefs(globals);
12449
12833
 
12450
12834
  const [theme$1, refs, vars$K] = createHelperVars(
@@ -12553,7 +12937,7 @@ const [theme$1, refs, vars$K] = createHelperVars(
12553
12937
  backgroundColor: globalRefs$u.colors.surface.main,
12554
12938
  },
12555
12939
  },
12556
- componentName$3
12940
+ componentName
12557
12941
  );
12558
12942
 
12559
12943
  var inputWrapper = /*#__PURE__*/Object.freeze({
@@ -14358,262 +14742,61 @@ const radioGroup = {
14358
14742
  [vars$5.buttonsSpacing]: 'space-between',
14359
14743
  },
14360
14744
 
14361
- _disabled: {
14362
- [vars$5.itemsLabelColor]: globalRefs$4.colors.surface.light,
14363
- },
14364
- };
14365
-
14366
- var radioGroup$1 = /*#__PURE__*/Object.freeze({
14367
- __proto__: null,
14368
- default: radioGroup,
14369
- radioGroup: radioGroup,
14370
- vars: vars$5
14371
- });
14372
-
14373
- const vars$4 = RadioButtonClass.cssVarList;
14374
- const globalRefs$3 = getThemeRefs(globals);
14375
-
14376
- const radioButton = {
14377
- [vars$4.fontFamily]: refs.fontFamily,
14378
- [vars$4.radioSize]: 'calc(1em + 6px)',
14379
- [vars$4.radioMargin]: 'auto 4px',
14380
- [vars$4.radioCheckedSize]: `calc(var(${vars$4.radioSize})/5)`,
14381
- [vars$4.radioCheckedColor]: globalRefs$3.colors.surface.light,
14382
- [vars$4.radioBackgroundColor]: globalRefs$3.colors.surface.light,
14383
- [vars$4.radioBorderColor]: 'none',
14384
- [vars$4.radioBorderWidth]: 0,
14385
-
14386
- _checked: {
14387
- [vars$4.radioBackgroundColor]: globalRefs$3.colors.surface.contrast,
14388
- },
14389
-
14390
- _hover: {
14391
- cursor: 'pointer',
14392
- },
14393
-
14394
- size: {
14395
- xs: {
14396
- [vars$4.fontSize]: '12px',
14397
- },
14398
- sm: {
14399
- [vars$4.fontSize]: '14px',
14400
- },
14401
- md: {
14402
- [vars$4.fontSize]: '16px',
14403
- },
14404
- lg: {
14405
- [vars$4.fontSize]: '18px',
14406
- },
14407
- },
14408
- };
14409
-
14410
- var radioButton$1 = /*#__PURE__*/Object.freeze({
14411
- __proto__: null,
14412
- default: radioButton,
14413
- radioButton: radioButton,
14414
- vars: vars$4
14415
- });
14416
-
14417
- const activeableMixin = (superclass) =>
14418
- class ActiveableMixinClass extends superclass {
14419
- init() {
14420
- super.init?.();
14421
-
14422
- this.baseElement.addEventListener('mousedown', (e) => {
14423
- e.preventDefault();
14424
- this.setAttribute('active', 'true');
14425
- window.addEventListener('mouseup', () => this.removeAttribute('active'), {
14426
- once: true,
14427
- });
14428
- });
14429
- }
14430
- };
14431
-
14432
- const componentName$2 = getComponentName('list-item');
14433
-
14434
- const customMixin$1 = (superclass) =>
14435
- class ListItemMixinClass extends superclass {
14436
- constructor() {
14437
- super();
14438
-
14439
- this.attachShadow({ mode: 'open' }).innerHTML = `
14440
- <style>
14441
- /*css*/
14442
- slot {
14443
- width: 100%;
14444
- display: flex;
14445
- overflow: hidden;
14446
- box-sizing: border-box;
14447
- }
14448
- :host {
14449
- display: block;
14450
- }
14451
-
14452
- /*!css*/
14453
- </style>
14454
- <slot></slot>
14455
- `;
14456
- }
14457
- };
14458
-
14459
- const ListItemClass = compose(
14460
- createStyleMixin({
14461
- mappings: {
14462
- padding: {},
14463
- backgroundColor: {},
14464
- borderColor: {},
14465
- borderStyle: {},
14466
- borderWidth: {},
14467
- borderRadius: {},
14468
- outline: {},
14469
- cursor: {},
14470
- gap: {},
14471
- maxWidth: { selector: () => ':host' },
14472
- alignItems: {},
14473
- flexDirection: {},
14474
- transition: {},
14475
- },
14476
- }),
14477
- draggableMixin,
14478
- componentNameValidationMixin,
14479
- customMixin$1,
14480
- activeableMixin
14481
- )(createBaseClass({ componentName: componentName$2, baseSelector: 'slot' }));
14482
-
14483
- const componentName$1 = getComponentName('list');
14484
-
14485
- class RawList extends createBaseClass({ componentName: componentName$1, baseSelector: '.wrapper' }) {
14486
- static get observedAttributes() {
14487
- return ['variant'];
14488
- }
14489
-
14490
- constructor() {
14491
- super();
14492
-
14493
- this.attachShadow({ mode: 'open' }).innerHTML = `
14494
- <style>
14495
- /*css*/
14496
- .wrapper {
14497
- overflow: auto;
14498
- display: grid;
14499
- max-height: 100%;
14500
- width: 100%;
14501
- }
14502
-
14503
- :host {
14504
- display: inline-flex;
14505
- width: 100%;
14506
- }
14507
- slot[name="empty-state"] {
14508
- justify-content: center;
14509
- align-items: center;
14510
- display: flex;
14511
- flex-grow: 1;
14512
- }
14513
-
14514
- :host slot[name="empty-state"] {
14515
- display: none;
14516
- }
14517
- :host([empty]) slot[name="empty-state"] {
14518
- display: flex;
14519
- }
14520
- ::slotted(:not([slot])) {
14521
- width: 100%;
14522
- }
14523
- /*!css*/
14524
- </style>
14525
-
14526
- <div class="wrapper">
14527
- <slot></slot>
14528
- <slot name="empty-state">
14529
- No item...
14530
- </slot>
14531
- </div>
14532
- `;
14533
- }
14534
-
14535
- get items() {
14536
- return this.shadowRoot.querySelector('slot').assignedElements();
14537
- }
14538
-
14539
- #handleEmptyState() {
14540
- if (this.items.length === 0) {
14541
- this.setAttribute('empty', 'true');
14542
- } else {
14543
- this.removeAttribute('empty');
14544
- }
14545
- }
14546
-
14547
- get variant() {
14548
- return this.getAttribute('variant') || 'list';
14549
- }
14550
-
14551
- #handleItemsVariant() {
14552
- this.items.forEach((item) => {
14553
- let listItem = item;
14554
- if (listItem.localName !== ListItemClass.componentName) {
14555
- listItem = item.querySelector(ListItemClass.componentName);
14556
- }
14557
-
14558
- const listItemVariant = this.variant === 'tiles' ? 'tile' : 'row';
14559
- listItem.setAttribute('variant', listItemVariant);
14560
- });
14561
- }
14562
-
14563
- init() {
14564
- super.init?.();
14565
-
14566
- // we want new items to get the size
14567
- observeChildren(this, () => {
14568
- this.#handleEmptyState();
14569
- this.#handleItemsVariant();
14570
- });
14571
- }
14745
+ _disabled: {
14746
+ [vars$5.itemsLabelColor]: globalRefs$4.colors.surface.light,
14747
+ },
14748
+ };
14572
14749
 
14573
- attributeChangedCallback(name, oldValue, newValue) {
14574
- super.attributeChangedCallback?.(name, oldValue, newValue);
14750
+ var radioGroup$1 = /*#__PURE__*/Object.freeze({
14751
+ __proto__: null,
14752
+ default: radioGroup,
14753
+ radioGroup: radioGroup,
14754
+ vars: vars$5
14755
+ });
14575
14756
 
14576
- if (newValue === oldValue) return;
14757
+ const vars$4 = RadioButtonClass.cssVarList;
14758
+ const globalRefs$3 = getThemeRefs(globals);
14577
14759
 
14578
- if (name === 'variant') {
14579
- this.#handleItemsVariant();
14580
- }
14581
- }
14582
- }
14760
+ const radioButton = {
14761
+ [vars$4.fontFamily]: refs.fontFamily,
14762
+ [vars$4.radioSize]: 'calc(1em + 6px)',
14763
+ [vars$4.radioMargin]: 'auto 4px',
14764
+ [vars$4.radioCheckedSize]: `calc(var(${vars$4.radioSize})/5)`,
14765
+ [vars$4.radioCheckedColor]: globalRefs$3.colors.surface.light,
14766
+ [vars$4.radioBackgroundColor]: globalRefs$3.colors.surface.light,
14767
+ [vars$4.radioBorderColor]: 'none',
14768
+ [vars$4.radioBorderWidth]: 0,
14583
14769
 
14584
- const ListClass = compose(
14585
- createStyleMixin({
14586
- mappings: {
14587
- hostWidth: { selector: () => ':host', property: 'width' },
14588
- maxHeight: { selector: () => ':host' },
14589
- minHeight: {},
14590
- verticalPadding: [{ property: 'padding-top' }, { property: 'padding-bottom' }],
14591
- horizontalPadding: [{ property: 'padding-left' }, { property: 'padding-right' }],
14592
- hostDirection: { selector: () => ':host', property: 'direction' },
14593
- fontFamily: {},
14594
- gap: {},
14770
+ _checked: {
14771
+ [vars$4.radioBackgroundColor]: globalRefs$3.colors.surface.contrast,
14772
+ },
14595
14773
 
14596
- backgroundColor: {},
14597
- borderRadius: {},
14598
- borderColor: {},
14599
- borderStyle: {},
14600
- borderWidth: {},
14774
+ _hover: {
14775
+ cursor: 'pointer',
14776
+ },
14601
14777
 
14602
- boxShadow: {},
14603
- gridTemplateColumns: {},
14604
- maxItemsWidth: { selector: () => '::slotted(:not([slot]))', property: 'max-width' },
14605
- minItemsWidth: { selector: () => '::slotted(:not([slot]))', property: 'min-width' },
14606
- itemsHorizontalAlign: { selector: () => '::slotted(*)', property: 'justify-self' },
14607
- emptyStateTextColor: { selector: () => 'slot[name="empty-state"]', property: 'color' },
14608
- emptyStateTextFontFamily: {
14609
- selector: () => 'slot[name="empty-state"]',
14610
- property: 'font-family',
14611
- },
14778
+ size: {
14779
+ xs: {
14780
+ [vars$4.fontSize]: '12px',
14612
14781
  },
14613
- }),
14614
- draggableMixin,
14615
- componentNameValidationMixin
14616
- )(RawList);
14782
+ sm: {
14783
+ [vars$4.fontSize]: '14px',
14784
+ },
14785
+ md: {
14786
+ [vars$4.fontSize]: '16px',
14787
+ },
14788
+ lg: {
14789
+ [vars$4.fontSize]: '18px',
14790
+ },
14791
+ },
14792
+ };
14793
+
14794
+ var radioButton$1 = /*#__PURE__*/Object.freeze({
14795
+ __proto__: null,
14796
+ default: radioButton,
14797
+ radioButton: radioButton,
14798
+ vars: vars$4
14799
+ });
14617
14800
 
14618
14801
  const globalRefs$2 = getThemeRefs(globals);
14619
14802
 
@@ -14621,7 +14804,7 @@ const compVars = ListClass.cssVarList;
14621
14804
 
14622
14805
  const [helperTheme, helperRefs, helperVars] = createHelperVars(
14623
14806
  { shadowColor: '#00000020' },
14624
- componentName$1
14807
+ componentName$2
14625
14808
  );
14626
14809
 
14627
14810
  const { shadowColor } = helperRefs;
@@ -14714,177 +14897,6 @@ var listItem = /*#__PURE__*/Object.freeze({
14714
14897
  vars: vars$2
14715
14898
  });
14716
14899
 
14717
- const defaultValidateSchema = () => true;
14718
- const defaultItemRenderer = (item) => `<pre>${JSON.stringify(item, null, 4)}</pre>`;
14719
-
14720
- const createTemplate = (templateString) => {
14721
- const template = document.createElement('template');
14722
- template.innerHTML = templateString;
14723
-
14724
- return template;
14725
- };
14726
-
14727
- const getTemplateContent = (templateOrString) => {
14728
- if (typeof templateOrString === 'string') {
14729
- return createTemplate(templateOrString).content;
14730
- }
14731
-
14732
- if (templateOrString instanceof HTMLTemplateElement) {
14733
- return templateOrString.content;
14734
- }
14735
-
14736
- // eslint-disable-next-line no-console
14737
- console.error('Invalid template', templateOrString);
14738
- return null;
14739
- };
14740
-
14741
- const createDynamicDataMixin =
14742
- ({
14743
- itemRenderer = defaultItemRenderer,
14744
- validateSchema = defaultValidateSchema,
14745
- slotName,
14746
- rerenderAttrsList = [],
14747
- }) =>
14748
- (superclass) =>
14749
- class DynamicDataMixinClass extends superclass {
14750
- #data = [];
14751
-
14752
- // eslint-disable-next-line class-methods-use-this
14753
- #validateSchema(data) {
14754
- if (!validateSchema) return true;
14755
-
14756
- const validation = validateSchema(data);
14757
- if (validation === true) return true;
14758
-
14759
- // eslint-disable-next-line no-console
14760
- console.error('Data schema validation failed', validation || '');
14761
-
14762
- return false;
14763
- }
14764
-
14765
- #removeOldItems() {
14766
- const selector = slotName ? `*[slot="${slotName}"]` : ':not([slot])';
14767
- this.baseElement.querySelectorAll(selector).forEach((item) => item.remove());
14768
- }
14769
-
14770
- #renderItems() {
14771
- this.#removeOldItems();
14772
- this.data.forEach((item, index) => {
14773
- const content = getTemplateContent(itemRenderer(item, index, this));
14774
- this.baseElement.appendChild(content?.cloneNode(true));
14775
- });
14776
- }
14777
-
14778
- set data(value) {
14779
- if (this.#validateSchema(value)) {
14780
- this.#data = value;
14781
- this.#renderItems();
14782
- }
14783
- }
14784
-
14785
- get data() {
14786
- return this.#data;
14787
- }
14788
-
14789
- init() {
14790
- super.init?.();
14791
-
14792
- if (rerenderAttrsList.length) {
14793
- observeAttributes(this, () => this.#renderItems(), { includeAttrs: rerenderAttrsList });
14794
- } else {
14795
- this.#renderItems();
14796
- }
14797
- }
14798
- };
14799
-
14800
- const componentName = getComponentName('apps-list');
14801
-
14802
- const limitAbbreviation = (str, limit = 3) =>
14803
- str
14804
- .trim()
14805
- .split(' ')
14806
- .splice(0, limit)
14807
- .map((s) => s[0]?.toUpperCase())
14808
- .join('');
14809
-
14810
- const itemRenderer = ({ name, icon, url }, _, ref) => `
14811
- <a href="${url}" target="_blank" title="${url}">
14812
- <descope-list-item>
14813
- <descope-avatar
14814
- img="${icon}"
14815
- display-name="${name}"
14816
- abbr=${limitAbbreviation(name)}
14817
- size=${ref.size}
14818
- ></descope-avatar>
14819
- <descope-text
14820
- variant="body1"
14821
- mode="primary"
14822
- >${name}</descope-text>
14823
- </descope-list-item>
14824
- </a>
14825
- `;
14826
-
14827
- const customMixin = (superclass) =>
14828
- class AppsListMixinClass extends superclass {
14829
- get size() {
14830
- return this.getAttribute('size') || 'sm';
14831
- }
14832
- };
14833
-
14834
- const AppsListClass = compose(
14835
- createStyleMixin({
14836
- mappings: {
14837
- maxHeight: { selector: () => ':host' },
14838
- minHeight: { selector: () => ':host' },
14839
- hostDirection: { selector: () => ':host', property: 'direction' },
14840
- itemsFontWeight: {
14841
- selector: TextClass.componentName,
14842
- property: TextClass.cssVarList.fontWeight,
14843
- },
14844
- itemsFontSize: {
14845
- selector: TextClass.componentName,
14846
- property: TextClass.cssVarList.fontSize,
14847
- },
14848
- itemsTextAlign: {
14849
- selector: TextClass.componentName,
14850
- property: TextClass.cssVarList.textAlign,
14851
- },
14852
- },
14853
- }),
14854
- createDynamicDataMixin({ itemRenderer, rerenderAttrsList: ['size'] }),
14855
- draggableMixin,
14856
- componentNameValidationMixin,
14857
- customMixin
14858
- )(
14859
- createProxy({
14860
- slots: ['empty-state'],
14861
- wrappedEleName: 'descope-list',
14862
- excludeAttrsSync: ['tabindex', 'class'],
14863
- componentName,
14864
- style: () => `
14865
- :host {
14866
- width: 100%;
14867
- display: inline-flex;
14868
- }
14869
-
14870
- descope-text::part(text-wrapper) {
14871
- display: -webkit-box;
14872
- -webkit-line-clamp: 2;
14873
- -webkit-box-orient: vertical;
14874
- overflow: hidden;
14875
- }
14876
-
14877
- a {
14878
- text-decoration: none;
14879
- }
14880
-
14881
- descope-text {
14882
- ${TextClass.cssVarList.hostDirection}: var(${AppsListClass.cssVarList.hostDirection});
14883
- }
14884
- `,
14885
- })
14886
- );
14887
-
14888
14900
  const vars$1 = AppsListClass.cssVarList;
14889
14901
  const globalRefs = getThemeRefs(globals);
14890
14902
 
@@ -15031,5 +15043,5 @@ const darkTheme = merge({}, defaultTheme, {
15031
15043
  },
15032
15044
  });
15033
15045
 
15034
- export { AvatarClass, BadgeClass, ButtonClass, ButtonMultiSelectionGroupClass, ButtonSelectionGroupClass, CheckboxClass, CodeSnippetClass, ComboBoxClass, ContainerClass, DividerClass, EmailFieldClass, EnrichedTextClass, GridClass, IconClass, ImageClass, LinkClass, LoaderLinearClass, LoaderRadialClass, LogoClass, MappingsFieldClass, ModalClass, MultiSelectComboBoxClass, NewPasswordClass, NotificationClass, NotpImageClass, NumberFieldClass, PasscodeClass, PasswordClass, PhoneFieldClass, PhoneFieldInputBoxClass, PolicyValidationClass, RadioGroupClass, RecaptchaClass, SamlGroupMappingsClass, SwitchToggleClass, TextAreaClass, TextClass, TextFieldClass, TotpImageClass, UploadFileClass, UserAttributeClass, UserAuthMethodClass, componentsThemeManager, createComponentsTheme, darkTheme, defaultTheme, genColor, globalsThemeToStyle, themeToStyle, themeVars };
15046
+ export { AppsListClass, AvatarClass, BadgeClass, ButtonClass, ButtonMultiSelectionGroupClass, ButtonSelectionGroupClass, CheckboxClass, CodeSnippetClass, ComboBoxClass, ContainerClass, DividerClass, EmailFieldClass, EnrichedTextClass, GridClass, IconClass, ImageClass, LinkClass, ListClass, LoaderLinearClass, LoaderRadialClass, LogoClass, MappingsFieldClass, ModalClass, MultiSelectComboBoxClass, NewPasswordClass, NotificationClass, NotpImageClass, NumberFieldClass, PasscodeClass, PasswordClass, PhoneFieldClass, PhoneFieldInputBoxClass, PolicyValidationClass, RadioGroupClass, RecaptchaClass, SamlGroupMappingsClass, SwitchToggleClass, TextAreaClass, TextClass, TextFieldClass, TotpImageClass, UploadFileClass, UserAttributeClass, UserAuthMethodClass, componentsThemeManager, createComponentsTheme, darkTheme, defaultTheme, genColor, globalsThemeToStyle, themeToStyle, themeVars };
15035
15047
  //# sourceMappingURL=index.esm.js.map