@descope-ui/descope-outbound-apps 0.0.2 → 0.0.4

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.0.4](https://github.com/descope/web-components-ui/compare/@descope-ui/descope-outbound-apps-0.0.3...@descope-ui/descope-outbound-apps-0.0.4) (2025-07-22)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * Add background color to Avatar for apps without logo ([#694](https://github.com/descope/web-components-ui/issues/694)) ([e653476](https://github.com/descope/web-components-ui/commit/e65347699885d789e507e3198c926932f6c7e850))
11
+
12
+ ## [0.0.3](https://github.com/descope/web-components-ui/compare/@descope-ui/descope-outbound-apps-0.0.2...@descope-ui/descope-outbound-apps-0.0.3) (2025-07-21)
13
+
5
14
  ## [0.0.2](https://github.com/descope/web-components-ui/compare/@descope-ui/descope-outbound-apps-0.0.1...@descope-ui/descope-outbound-apps-0.0.2) (2025-07-21)
6
15
 
7
16
  ### Dependency Updates
@@ -5,6 +5,7 @@ const componentAttributes = {
5
5
  direction: ['ltr', 'rtl'],
6
6
  numberOfItems: ['1', '5', '10'],
7
7
  size: ['xs', 'sm', 'md', 'lg'],
8
+ readonly: ['false', 'true'],
8
9
  'connect-button-label': ['', 'My Connect'],
9
10
  'disconnect-button-label': ['', 'My Disconnect']
10
11
  };
@@ -79,4 +80,36 @@ test.describe('logic', () => {
79
80
  expect(eventDetail).toHaveProperty('action', 'disconnect');
80
81
  expect(eventDetail).toHaveProperty('id', 'appId_2');
81
82
  });
83
+
84
+ test('prevent dispatch when readonly', async ({ page }) => {
85
+ await page.goto(getStoryUrl(storyName, { readonly: "true" }), {
86
+ waitUntil: 'networkidle',
87
+ });
88
+
89
+ await page.addInitScript(setupEventListener('connect-clicked'));
90
+
91
+ await page.reload({ waitUntil: 'networkidle' });
92
+
93
+ await page.getByText('Connect').first().click();
94
+ await page.waitForTimeout(500);
95
+
96
+ const eventDetail = await page.evaluate(() => (window as any).eventDetails[0]);
97
+
98
+ expect(eventDetail).not.toBeDefined();
99
+ });
82
100
  });
101
+
102
+ test.describe('presets', () => {
103
+ test('empty state', async ({ page }) => {
104
+ await page.goto(getStoryUrl(storyName, {
105
+ numberOfItems: '0',
106
+ 'empty-state': 'Custom empty state'
107
+ }), {
108
+ waitUntil: 'networkidle',
109
+ });
110
+
111
+ const componentParent = page.locator(componentName);
112
+
113
+ expect(await componentParent.screenshot()).toMatchSnapshot();
114
+ });
115
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@descope-ui/descope-outbound-apps",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "exports": {
5
5
  ".": {
6
6
  "import": "./src/component/index.js"
@@ -18,9 +18,9 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "@descope-ui/common": "0.0.18",
21
+ "@descope-ui/theme-globals": "0.0.19",
21
22
  "@descope-ui/descope-list": "0.0.1",
22
23
  "@descope-ui/descope-list-item": "0.0.1",
23
- "@descope-ui/theme-globals": "0.0.19",
24
24
  "@descope-ui/descope-text": "0.0.19",
25
25
  "@descope-ui/descope-avatar": "0.0.19",
26
26
  "@descope-ui/descope-icon": "0.0.17",
@@ -15,8 +15,6 @@ import { ListItemClass } from '@descope-ui/descope-list-item/class';
15
15
 
16
16
  export const componentName = getComponentName('outbound-apps');
17
17
 
18
- export const observedAttributes = ['connect-button-label', 'disconnect-button-label', 'data'];
19
-
20
18
  const itemRenderer = (
21
19
  { name, description, logo, appId, isConnected },
22
20
  _,
@@ -29,24 +27,24 @@ const itemRenderer = (
29
27
  ${logo ? `img="${logo}"` : ''}
30
28
  ${name ? `display-name="${name}" abbr=${limitAbbreviation(name)}` : ''}
31
29
  size=${ref.size}
30
+ ${logo ? 'st-avatar-background-color="none"' : ''}
32
31
  class="app-logo"
33
32
  ></descope-avatar>
34
- <div class="content">
35
- <div class="app-title">
33
+
34
+ <div class="content">
36
35
  <descope-text
36
+ class="app-title"
37
37
  variant="subtitle1"
38
38
  mode="primary"
39
39
  >${name}</descope-text>
40
- </div>
41
40
  ${
42
41
  description
43
42
  ? `
44
- <div class="app-description">
45
43
  <descope-text
44
+ class="app-description"
46
45
  variant="body2"
47
46
  mode="primary"
48
47
  >${description}</descope-text>
49
- </div>
50
48
  `
51
49
  : ''
52
50
  }
@@ -66,15 +64,13 @@ const BaseClass = createBaseClass({
66
64
  });
67
65
 
68
66
  class RawOutboundAppsClass extends BaseClass {
69
- static get observedAttributes() {
70
- return observedAttributes;
71
- }
72
-
73
67
  constructor() {
74
68
  super();
75
69
 
76
70
  this.attachShadow({ mode: 'open' }).innerHTML = `
77
- <descope-list></descope-list>
71
+ <descope-list>
72
+ <slot name="empty-state" slot="empty-state"></slot>
73
+ </descope-list>
78
74
  `;
79
75
 
80
76
  this.appsList = this.shadowRoot.querySelector('descope-list');
@@ -91,6 +87,13 @@ class RawOutboundAppsClass extends BaseClass {
91
87
  }
92
88
  .content {
93
89
  flex-grow: 1;
90
+ display: flex;
91
+ flex-direction: column;
92
+ }
93
+ .app-title,
94
+ .app-description {
95
+ display: flex;
96
+ direction: inherit;
94
97
  }
95
98
  descope-list {
96
99
  display: block;
@@ -108,11 +111,17 @@ class RawOutboundAppsClass extends BaseClass {
108
111
  this.appsList.addEventListener('click', this.onAppsListClick.bind(this));
109
112
  }
110
113
 
114
+ get readonly() {
115
+ return this.getAttribute('readonly') === 'true';
116
+ }
117
+
111
118
  onAppsListClick(e) {
112
- const id = e.srcElement.getAttribute('data-outbound-app-id');
113
- const action = e.srcElement.getAttribute('data-action');
114
- if (id && action) {
115
- this.dispatchEvent(new CustomEvent(`${action}-clicked`, { bubbles: true, detail: { id, action } }));
119
+ if (!this.readonly) {
120
+ const id = e.srcElement.getAttribute('data-outbound-app-id');
121
+ const action = e.srcElement.getAttribute('data-action');
122
+ if (id && action) {
123
+ this.dispatchEvent(new CustomEvent(`${action}-clicked`, { bubbles: true, detail: { id, action } }));
124
+ }
116
125
  }
117
126
  }
118
127
 
@@ -155,14 +164,14 @@ export const OutboundAppsClass = compose(
155
164
  selector: TextClass.componentName,
156
165
  property: TextClass.cssVarList.fontSize,
157
166
  },
158
- appLogoBackgroundColor: {
159
- selector: AvatarClass.componentName,
160
- property: AvatarClass.cssVarList.avatarBackgroundColor,
161
- },
162
167
  appLogoGap: {
163
168
  selector: () => ' .app-logo',
164
169
  property: 'margin-inline-end'
165
170
  },
171
+ contentGap: {
172
+ selector: () => ' .content',
173
+ property: 'gap'
174
+ },
166
175
  itemsTextAlign: {
167
176
  selector: TextClass.componentName,
168
177
  property: TextClass.cssVarList.textAlign,
package/src/theme.js CHANGED
@@ -9,6 +9,7 @@ const outboundApps = {
9
9
 
10
10
  [vars.appLogoBackgroundColor]: 'none',
11
11
  [vars.appLogoGap]: globals.spacing.md,
12
+ [vars.contentGap]: globals.spacing.xs,
12
13
 
13
14
  // list-item overrides
14
15
  [vars.itemCursor]: 'default',
@@ -1,16 +1,24 @@
1
1
  import { componentName } from '../src/component';
2
- import { directionControl, sizeControl } from '@descope-ui/common/sb-controls';
2
+ import { directionControl, sizeControl, readOnlyControl } from '@descope-ui/common/sb-controls';
3
3
  import appIcon from './google.svg';
4
4
 
5
- const Template = ({ direction, size, 'connect-button-label': connectButtonLabel, 'disconnect-button-label': disconnectButtonLabel }) => `
5
+ const Template = ({
6
+ direction,
7
+ size,
8
+ 'connect-button-label': connectButtonLabel,
9
+ 'disconnect-button-label': disconnectButtonLabel,
10
+ readonly,
11
+ emptyState
12
+ }) => `
6
13
  <descope-outbound-apps
7
14
  st-host-direction="${direction || ''}"
8
15
  size=${size || ''}
9
16
  connect-button-label="${connectButtonLabel || ''}"
10
17
  disconnect-button-label="${disconnectButtonLabel || ''}"
18
+ readonly="${readonly || false}"
11
19
  >
20
+ <div slot="empty-state">${emptyState}</div>
12
21
  </descope-outbound-apps>
13
- <div class="test-output"></div>
14
22
  `;
15
23
 
16
24
  export default {
@@ -26,7 +34,7 @@ export default {
26
34
  (_, i) => ({
27
35
  appId: `appId_${i + 1}`,
28
36
  name: `App ${i + 1}`,
29
- logo: appIcon,
37
+ logo: i % 2 ? appIcon : '',
30
38
  description: 'App description',
31
39
  isConnected: !!(i % 2),
32
40
  }),
@@ -47,6 +55,7 @@ export default {
47
55
  argTypes: {
48
56
  ...directionControl,
49
57
  ...sizeControl,
58
+ ...readOnlyControl,
50
59
  'connect-button-label': {
51
60
  control: { type: 'text' },
52
61
  },
@@ -61,5 +70,5 @@ export const Default = Template.bind({});
61
70
  Default.args = {
62
71
  size: 'sm',
63
72
  numberOfItems: '5',
64
- emptyState: 'No items in the list...',
73
+ emptyState: 'No outbound apps found!',
65
74
  };