@descope/web-components-ui 1.0.367 → 1.0.369

Sign up to get free protection for your applications and to get access to all the features.
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