@idp.global/catalog 2.0.0 → 2.1.1
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 +27 -0
- package/dist_bundle/bundle.js +3726 -1337
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/idp-admin-overview.d.ts +28 -0
- package/dist_ts_web/elements/idp-admin-overview.js +460 -0
- package/dist_ts_web/elements/idp-admin-shared.d.ts +18 -0
- package/dist_ts_web/elements/idp-admin-shared.js +404 -0
- package/dist_ts_web/elements/idp-admin-shell.d.ts +96 -11
- package/dist_ts_web/elements/idp-admin-shell.js +442 -816
- package/dist_ts_web/elements/idp-admin-sidebar.d.ts +42 -0
- package/dist_ts_web/elements/idp-admin-sidebar.js +702 -0
- package/dist_ts_web/elements/idp-app-pair.d.ts +19 -0
- package/dist_ts_web/elements/idp-app-pair.js +187 -0
- package/dist_ts_web/elements/idp-auth-card.d.ts +17 -0
- package/dist_ts_web/elements/idp-auth-card.js +180 -0
- package/dist_ts_web/elements/idp-avatar.d.ts +17 -0
- package/dist_ts_web/elements/idp-avatar.js +151 -0
- package/dist_ts_web/elements/idp-badge.d.ts +2 -0
- package/dist_ts_web/elements/idp-badge.js +12 -3
- package/dist_ts_web/elements/idp-brand-mark.d.ts +16 -0
- package/dist_ts_web/elements/idp-brand-mark.js +139 -0
- package/dist_ts_web/elements/idp-button.d.ts +3 -0
- package/dist_ts_web/elements/idp-button.js +47 -3
- package/dist_ts_web/elements/idp-consent-card.d.ts +34 -0
- package/dist_ts_web/elements/idp-consent-card.js +217 -0
- package/dist_ts_web/elements/idp-delegation-section.d.ts +59 -0
- package/dist_ts_web/elements/idp-delegation-section.js +609 -0
- package/dist_ts_web/elements/idp-form-submit.d.ts +2 -1
- package/dist_ts_web/elements/idp-form-submit.js +11 -2
- package/dist_ts_web/elements/idp-form.js +2 -2
- package/dist_ts_web/elements/idp-input.d.ts +4 -0
- package/dist_ts_web/elements/idp-input.js +68 -15
- package/dist_ts_web/elements/idp-option-row.d.ts +25 -0
- package/dist_ts_web/elements/idp-option-row.js +267 -0
- package/dist_ts_web/elements/idp-otp-input.d.ts +32 -0
- package/dist_ts_web/elements/idp-otp-input.js +274 -0
- package/dist_ts_web/elements/idp-progress-bar.d.ts +14 -0
- package/dist_ts_web/elements/idp-progress-bar.js +127 -0
- package/dist_ts_web/elements/idp-signed-in-pill.d.ts +15 -0
- package/dist_ts_web/elements/idp-signed-in-pill.js +113 -0
- package/dist_ts_web/elements/idp-spinner.d.ts +13 -0
- package/dist_ts_web/elements/idp-spinner.js +109 -0
- package/dist_ts_web/elements/idp-status-icon.d.ts +18 -0
- package/dist_ts_web/elements/idp-status-icon.js +136 -0
- package/dist_ts_web/elements/index.d.ts +15 -0
- package/dist_ts_web/elements/index.js +16 -1
- package/package.json +2 -2
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/idp-admin-overview.ts +388 -0
- package/ts_web/elements/idp-admin-shared.ts +419 -0
- package/ts_web/elements/idp-admin-shell.ts +514 -871
- package/ts_web/elements/idp-admin-sidebar.ts +648 -0
- package/ts_web/elements/idp-app-pair.ts +120 -0
- package/ts_web/elements/idp-auth-card.ts +113 -0
- package/ts_web/elements/idp-avatar.ts +84 -0
- package/ts_web/elements/idp-badge.ts +5 -1
- package/ts_web/elements/idp-brand-mark.ts +76 -0
- package/ts_web/elements/idp-button.ts +36 -1
- package/ts_web/elements/idp-consent-card.ts +146 -0
- package/ts_web/elements/idp-delegation-section.ts +576 -0
- package/ts_web/elements/idp-form-submit.ts +5 -1
- package/ts_web/elements/idp-form.ts +1 -1
- package/ts_web/elements/idp-input.ts +58 -13
- package/ts_web/elements/idp-option-row.ts +184 -0
- package/ts_web/elements/idp-otp-input.ts +204 -0
- package/ts_web/elements/idp-progress-bar.ts +69 -0
- package/ts_web/elements/idp-signed-in-pill.ts +55 -0
- package/ts_web/elements/idp-spinner.ts +56 -0
- package/ts_web/elements/idp-status-icon.ts +76 -0
- package/ts_web/elements/index.ts +15 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { DeesElement, html, property, customElement, css, type TemplateResult } from '@design.estate/dees-element';
|
|
2
|
+
import { idpElementStyles } from './tokens.js';
|
|
3
|
+
import './idp-brand-mark.js';
|
|
4
|
+
import './idp-icon.js';
|
|
5
|
+
|
|
6
|
+
declare global {
|
|
7
|
+
interface HTMLElementTagNameMap {
|
|
8
|
+
'idp-app-pair': IdpAppPair;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@customElement('idp-app-pair')
|
|
13
|
+
export class IdpAppPair extends DeesElement {
|
|
14
|
+
public static demo = () => html`
|
|
15
|
+
<div style="display: flex; flex-direction: column; gap: 18px;">
|
|
16
|
+
<idp-app-pair appName="design.estate"></idp-app-pair>
|
|
17
|
+
<idp-app-pair appName="task.vc" appColor="#34C759"></idp-app-pair>
|
|
18
|
+
</div>
|
|
19
|
+
`;
|
|
20
|
+
public static demoGroups = ['idp.global v5 auth'];
|
|
21
|
+
|
|
22
|
+
@property({ type: String })
|
|
23
|
+
public accessor appName = '';
|
|
24
|
+
|
|
25
|
+
@property({ type: String })
|
|
26
|
+
public accessor appLogoUrl = '';
|
|
27
|
+
|
|
28
|
+
@property({ type: String })
|
|
29
|
+
public accessor appColor = '#6D5EFC';
|
|
30
|
+
|
|
31
|
+
@property({ type: Number })
|
|
32
|
+
public accessor size = 44;
|
|
33
|
+
|
|
34
|
+
public static styles = [
|
|
35
|
+
...idpElementStyles,
|
|
36
|
+
css`
|
|
37
|
+
:host {
|
|
38
|
+
display: flex;
|
|
39
|
+
justify-content: center;
|
|
40
|
+
}
|
|
41
|
+
.pair {
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
justify-content: center;
|
|
45
|
+
}
|
|
46
|
+
.app-tile {
|
|
47
|
+
display: flex;
|
|
48
|
+
align-items: center;
|
|
49
|
+
justify-content: center;
|
|
50
|
+
flex-shrink: 0;
|
|
51
|
+
border-radius: 12px;
|
|
52
|
+
color: #fff;
|
|
53
|
+
font-family: var(--idp-font);
|
|
54
|
+
font-weight: 700;
|
|
55
|
+
letter-spacing: -0.5px;
|
|
56
|
+
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.14);
|
|
57
|
+
overflow: hidden;
|
|
58
|
+
}
|
|
59
|
+
.app-tile img {
|
|
60
|
+
width: 100%;
|
|
61
|
+
height: 100%;
|
|
62
|
+
object-fit: cover;
|
|
63
|
+
}
|
|
64
|
+
.connector {
|
|
65
|
+
position: relative;
|
|
66
|
+
width: 48px;
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
justify-content: center;
|
|
70
|
+
}
|
|
71
|
+
.connector::before {
|
|
72
|
+
content: '';
|
|
73
|
+
position: absolute;
|
|
74
|
+
left: 4px;
|
|
75
|
+
right: 4px;
|
|
76
|
+
top: 50%;
|
|
77
|
+
border-top: 1.5px dashed var(--idp-border);
|
|
78
|
+
}
|
|
79
|
+
.swap {
|
|
80
|
+
position: relative;
|
|
81
|
+
display: flex;
|
|
82
|
+
align-items: center;
|
|
83
|
+
justify-content: center;
|
|
84
|
+
width: 26px;
|
|
85
|
+
height: 26px;
|
|
86
|
+
border-radius: 999px;
|
|
87
|
+
background: var(--idp-card);
|
|
88
|
+
border: 1px solid var(--idp-border);
|
|
89
|
+
color: var(--idp-fg-3);
|
|
90
|
+
}
|
|
91
|
+
`,
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
private get appInitials(): string {
|
|
95
|
+
return this.appName
|
|
96
|
+
.split(/[\s.]+/)
|
|
97
|
+
.filter(Boolean)
|
|
98
|
+
.map((wordArg) => wordArg[0])
|
|
99
|
+
.slice(0, 2)
|
|
100
|
+
.join('')
|
|
101
|
+
.toUpperCase();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public render(): TemplateResult {
|
|
105
|
+
return html`
|
|
106
|
+
<span class="pair">
|
|
107
|
+
<span
|
|
108
|
+
class="app-tile"
|
|
109
|
+
style="width: ${this.size}px; height: ${this.size}px; font-size: ${Math.round(this.size * 0.33)}px; background: ${this.appColor};"
|
|
110
|
+
>
|
|
111
|
+
${this.appLogoUrl ? html`<img src=${this.appLogoUrl} alt=${this.appName} />` : this.appInitials}
|
|
112
|
+
</span>
|
|
113
|
+
<span class="connector" style="height: ${this.size}px;">
|
|
114
|
+
<span class="swap"><idp-icon name="lucide:ArrowLeftRight" size="13"></idp-icon></span>
|
|
115
|
+
</span>
|
|
116
|
+
<idp-brand-mark size=${this.size}></idp-brand-mark>
|
|
117
|
+
</span>
|
|
118
|
+
`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { DeesElement, html, property, state, customElement, css, type TemplateResult } from '@design.estate/dees-element';
|
|
2
|
+
import { idpElementStyles } from './tokens.js';
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
interface HTMLElementTagNameMap {
|
|
6
|
+
'idp-auth-card': IdpAuthCard;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@customElement('idp-auth-card')
|
|
11
|
+
export class IdpAuthCard extends DeesElement {
|
|
12
|
+
public static demo = () => html`
|
|
13
|
+
<div style="background: var(--sh-bg, #f5f5f7); padding: 40px; display: flex; justify-content: center;">
|
|
14
|
+
<idp-auth-card heading="Sign in" description="to continue to console.idp.global">
|
|
15
|
+
<idp-brand-mark wordmark slot="top"></idp-brand-mark>
|
|
16
|
+
<div style="display: flex; flex-direction: column; gap: 10px; margin-top: 20px;">
|
|
17
|
+
<idp-input size="lg" icon="mail" placeholder="you@example.com"></idp-input>
|
|
18
|
+
<idp-button variant="accent" shape="rect" block icon="arrow-up">Continue</idp-button>
|
|
19
|
+
</div>
|
|
20
|
+
<span slot="footer">By continuing you agree to the Terms and Privacy Notice.</span>
|
|
21
|
+
</idp-auth-card>
|
|
22
|
+
</div>
|
|
23
|
+
`;
|
|
24
|
+
public static demoGroups = ['idp.global v5 auth'];
|
|
25
|
+
|
|
26
|
+
@property({ type: String })
|
|
27
|
+
public accessor heading = '';
|
|
28
|
+
|
|
29
|
+
@property({ type: String })
|
|
30
|
+
public accessor description = '';
|
|
31
|
+
|
|
32
|
+
@property({ type: Number })
|
|
33
|
+
public accessor width = 360;
|
|
34
|
+
|
|
35
|
+
public static styles = [
|
|
36
|
+
...idpElementStyles,
|
|
37
|
+
css`
|
|
38
|
+
:host {
|
|
39
|
+
display: block;
|
|
40
|
+
}
|
|
41
|
+
.card {
|
|
42
|
+
max-width: calc(100vw - 32px);
|
|
43
|
+
margin: 0 auto;
|
|
44
|
+
background: var(--idp-card);
|
|
45
|
+
border: 1px solid var(--idp-border);
|
|
46
|
+
border-radius: 22px;
|
|
47
|
+
box-shadow: 0 10px 30px -14px rgba(0, 0, 0, 0.14), 0 1px 2px rgba(0, 0, 0, 0.04);
|
|
48
|
+
padding: 30px 26px;
|
|
49
|
+
font-family: var(--idp-font);
|
|
50
|
+
color: var(--idp-fg);
|
|
51
|
+
}
|
|
52
|
+
.top {
|
|
53
|
+
display: flex;
|
|
54
|
+
justify-content: center;
|
|
55
|
+
}
|
|
56
|
+
.top ::slotted(*) {
|
|
57
|
+
margin: 0 auto;
|
|
58
|
+
}
|
|
59
|
+
h2 {
|
|
60
|
+
margin: 18px 0 0;
|
|
61
|
+
font-size: 21px;
|
|
62
|
+
font-weight: 700;
|
|
63
|
+
letter-spacing: -0.5px;
|
|
64
|
+
line-height: 1.2;
|
|
65
|
+
text-align: center;
|
|
66
|
+
text-wrap: balance;
|
|
67
|
+
color: var(--idp-fg);
|
|
68
|
+
}
|
|
69
|
+
.description {
|
|
70
|
+
margin: 7px 0 0;
|
|
71
|
+
font-size: 13.5px;
|
|
72
|
+
line-height: 1.5;
|
|
73
|
+
color: var(--idp-fg-3);
|
|
74
|
+
text-align: center;
|
|
75
|
+
text-wrap: pretty;
|
|
76
|
+
}
|
|
77
|
+
.footer {
|
|
78
|
+
display: block;
|
|
79
|
+
margin-top: 14px;
|
|
80
|
+
font-size: 11px;
|
|
81
|
+
line-height: 1.5;
|
|
82
|
+
color: var(--sh-fg-4);
|
|
83
|
+
text-align: center;
|
|
84
|
+
text-wrap: pretty;
|
|
85
|
+
}
|
|
86
|
+
.footer:not(.has-content) {
|
|
87
|
+
display: none;
|
|
88
|
+
}
|
|
89
|
+
`,
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
@state()
|
|
93
|
+
private accessor hasFooterContent = false;
|
|
94
|
+
|
|
95
|
+
public render(): TemplateResult {
|
|
96
|
+
return html`
|
|
97
|
+
<section class="card" part="card" style="width: ${this.width}px;">
|
|
98
|
+
<div class="top"><slot name="top"></slot></div>
|
|
99
|
+
${this.heading ? html`<h2>${this.heading}</h2>` : html``}
|
|
100
|
+
${this.description ? html`<p class="description">${this.description}</p>` : html``}
|
|
101
|
+
<slot></slot>
|
|
102
|
+
<div class="footer ${this.hasFooterContent ? 'has-content' : ''}">
|
|
103
|
+
<slot name="footer" @slotchange=${this.handleFooterSlotChange}></slot>
|
|
104
|
+
</div>
|
|
105
|
+
</section>
|
|
106
|
+
`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private handleFooterSlotChange(eventArg: Event) {
|
|
110
|
+
const slot = eventArg.target as HTMLSlotElement;
|
|
111
|
+
this.hasFooterContent = slot.assignedNodes({ flatten: true }).length > 0;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { DeesElement, html, property, customElement, css, type TemplateResult } from '@design.estate/dees-element';
|
|
2
|
+
import { idpElementStyles } from './tokens.js';
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
interface HTMLElementTagNameMap {
|
|
6
|
+
'idp-avatar': IdpAvatar;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@customElement('idp-avatar')
|
|
11
|
+
export class IdpAvatar extends DeesElement {
|
|
12
|
+
public static demo = () => html`
|
|
13
|
+
<div style="display: flex; gap: 12px; align-items: center;">
|
|
14
|
+
<idp-avatar name="Alex Mercer"></idp-avatar>
|
|
15
|
+
<idp-avatar name="Jane Doe" size="30"></idp-avatar>
|
|
16
|
+
<idp-avatar initials="SR" size="22"></idp-avatar>
|
|
17
|
+
</div>
|
|
18
|
+
`;
|
|
19
|
+
public static demoGroups = ['idp.global v5 primitives'];
|
|
20
|
+
|
|
21
|
+
@property({ type: String })
|
|
22
|
+
public accessor name = '';
|
|
23
|
+
|
|
24
|
+
@property({ type: String })
|
|
25
|
+
public accessor initials = '';
|
|
26
|
+
|
|
27
|
+
@property({ type: Number })
|
|
28
|
+
public accessor size = 38;
|
|
29
|
+
|
|
30
|
+
@property({ type: String })
|
|
31
|
+
public accessor src = '';
|
|
32
|
+
|
|
33
|
+
public static styles = [
|
|
34
|
+
...idpElementStyles,
|
|
35
|
+
css`
|
|
36
|
+
:host {
|
|
37
|
+
display: inline-flex;
|
|
38
|
+
}
|
|
39
|
+
.avatar {
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
justify-content: center;
|
|
43
|
+
flex-shrink: 0;
|
|
44
|
+
border-radius: 999px;
|
|
45
|
+
overflow: hidden;
|
|
46
|
+
background: var(--sh-accent-soft);
|
|
47
|
+
color: var(--sh-accent-soft-fg);
|
|
48
|
+
font-family: var(--idp-font);
|
|
49
|
+
font-weight: 650;
|
|
50
|
+
letter-spacing: -0.3px;
|
|
51
|
+
user-select: none;
|
|
52
|
+
}
|
|
53
|
+
img {
|
|
54
|
+
width: 100%;
|
|
55
|
+
height: 100%;
|
|
56
|
+
object-fit: cover;
|
|
57
|
+
}
|
|
58
|
+
`,
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
private get resolvedInitials(): string {
|
|
62
|
+
if (this.initials) {
|
|
63
|
+
return this.initials.slice(0, 2).toUpperCase();
|
|
64
|
+
}
|
|
65
|
+
return this.name
|
|
66
|
+
.split(' ')
|
|
67
|
+
.filter(Boolean)
|
|
68
|
+
.map((wordArg) => wordArg[0])
|
|
69
|
+
.slice(0, 2)
|
|
70
|
+
.join('')
|
|
71
|
+
.toUpperCase();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public render(): TemplateResult {
|
|
75
|
+
return html`
|
|
76
|
+
<span
|
|
77
|
+
class="avatar"
|
|
78
|
+
style="width: ${this.size}px; height: ${this.size}px; font-size: ${Math.round(this.size * 0.38)}px;"
|
|
79
|
+
>
|
|
80
|
+
${this.src ? html`<img src=${this.src} alt=${this.name} />` : this.resolvedInitials}
|
|
81
|
+
</span>
|
|
82
|
+
`;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DeesElement, html, property, customElement, css, type TemplateResult } from '@design.estate/dees-element';
|
|
2
2
|
import { idpElementStyles } from './tokens.js';
|
|
3
|
+
import './idp-icon.js';
|
|
3
4
|
|
|
4
5
|
export type TIdpBadgeVariant = 'default' | 'accent' | 'ok' | 'warn' | 'error' | 'outline';
|
|
5
6
|
|
|
@@ -25,6 +26,9 @@ export class IdpBadge extends DeesElement {
|
|
|
25
26
|
@property({ type: String })
|
|
26
27
|
public accessor variant: TIdpBadgeVariant = 'default';
|
|
27
28
|
|
|
29
|
+
@property({ type: String })
|
|
30
|
+
public accessor icon = '';
|
|
31
|
+
|
|
28
32
|
public static styles = [
|
|
29
33
|
...idpElementStyles,
|
|
30
34
|
css`
|
|
@@ -76,6 +80,6 @@ export class IdpBadge extends DeesElement {
|
|
|
76
80
|
];
|
|
77
81
|
|
|
78
82
|
public render(): TemplateResult {
|
|
79
|
-
return html`<span class="badge ${this.variant}"
|
|
83
|
+
return html`<span class="badge ${this.variant}">${this.icon ? html`<idp-icon name=${this.icon as any} size="11"></idp-icon>` : html``}<slot></slot></span>`;
|
|
80
84
|
}
|
|
81
85
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { DeesElement, html, property, customElement, css, type TemplateResult } from '@design.estate/dees-element';
|
|
2
|
+
import { idpElementStyles } from './tokens.js';
|
|
3
|
+
import './idp-icon.js';
|
|
4
|
+
|
|
5
|
+
declare global {
|
|
6
|
+
interface HTMLElementTagNameMap {
|
|
7
|
+
'idp-brand-mark': IdpBrandMark;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@customElement('idp-brand-mark')
|
|
12
|
+
export class IdpBrandMark extends DeesElement {
|
|
13
|
+
public static demo = () => html`
|
|
14
|
+
<div style="display: flex; gap: 18px; align-items: center;">
|
|
15
|
+
<idp-brand-mark></idp-brand-mark>
|
|
16
|
+
<idp-brand-mark wordmark></idp-brand-mark>
|
|
17
|
+
<idp-brand-mark size="44"></idp-brand-mark>
|
|
18
|
+
</div>
|
|
19
|
+
`;
|
|
20
|
+
public static demoGroups = ['idp.global v5 primitives'];
|
|
21
|
+
|
|
22
|
+
@property({ type: Number })
|
|
23
|
+
public accessor size = 30;
|
|
24
|
+
|
|
25
|
+
@property({ type: Boolean })
|
|
26
|
+
public accessor wordmark = false;
|
|
27
|
+
|
|
28
|
+
@property({ type: String })
|
|
29
|
+
public accessor label = 'idp.global';
|
|
30
|
+
|
|
31
|
+
public static styles = [
|
|
32
|
+
...idpElementStyles,
|
|
33
|
+
css`
|
|
34
|
+
:host {
|
|
35
|
+
display: inline-flex;
|
|
36
|
+
}
|
|
37
|
+
.brand {
|
|
38
|
+
display: inline-flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
gap: 8px;
|
|
41
|
+
}
|
|
42
|
+
.tile {
|
|
43
|
+
display: flex;
|
|
44
|
+
align-items: center;
|
|
45
|
+
justify-content: center;
|
|
46
|
+
flex-shrink: 0;
|
|
47
|
+
background: var(--idp-accent);
|
|
48
|
+
color: #fff;
|
|
49
|
+
box-shadow: 0 2px 6px var(--sh-accent-ring);
|
|
50
|
+
}
|
|
51
|
+
.wordmark {
|
|
52
|
+
font-family: var(--idp-font);
|
|
53
|
+
font-size: 16px;
|
|
54
|
+
font-weight: 700;
|
|
55
|
+
letter-spacing: -0.4px;
|
|
56
|
+
color: var(--idp-fg);
|
|
57
|
+
white-space: nowrap;
|
|
58
|
+
}
|
|
59
|
+
`,
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
public render(): TemplateResult {
|
|
63
|
+
const radius = Math.round(this.size * 0.27);
|
|
64
|
+
return html`
|
|
65
|
+
<span class="brand">
|
|
66
|
+
<span
|
|
67
|
+
class="tile"
|
|
68
|
+
style="width: ${this.size}px; height: ${this.size}px; border-radius: ${radius}px;"
|
|
69
|
+
>
|
|
70
|
+
<idp-icon name="shield" size=${Math.round(this.size * 0.55)}></idp-icon>
|
|
71
|
+
</span>
|
|
72
|
+
${this.wordmark ? html`<span class="wordmark">${this.label}</span>` : html``}
|
|
73
|
+
</span>
|
|
74
|
+
`;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -11,6 +11,7 @@ import './idp-icon.js';
|
|
|
11
11
|
|
|
12
12
|
export type TIdpButtonVariant = 'default' | 'secondary' | 'outline' | 'ghost' | 'destructive' | 'accent' | 'tint' | 'link';
|
|
13
13
|
export type TIdpButtonSize = 'sm' | 'md' | 'lg';
|
|
14
|
+
export type TIdpButtonShape = 'pill' | 'rect';
|
|
14
15
|
|
|
15
16
|
declare global {
|
|
16
17
|
interface HTMLElementTagNameMap {
|
|
@@ -38,6 +39,12 @@ export class IdpButton extends DeesElement {
|
|
|
38
39
|
@property({ type: String })
|
|
39
40
|
public accessor size: TIdpButtonSize = 'md';
|
|
40
41
|
|
|
42
|
+
@property({ type: String })
|
|
43
|
+
public accessor shape: TIdpButtonShape = 'pill';
|
|
44
|
+
|
|
45
|
+
@property({ type: Boolean, reflect: true })
|
|
46
|
+
public accessor block = false;
|
|
47
|
+
|
|
41
48
|
@property({ type: String })
|
|
42
49
|
public accessor icon = '';
|
|
43
50
|
|
|
@@ -59,6 +66,12 @@ export class IdpButton extends DeesElement {
|
|
|
59
66
|
:host([disabled]) {
|
|
60
67
|
pointer-events: none;
|
|
61
68
|
}
|
|
69
|
+
:host([block]) {
|
|
70
|
+
display: block;
|
|
71
|
+
}
|
|
72
|
+
:host([block]) button {
|
|
73
|
+
width: 100%;
|
|
74
|
+
}
|
|
62
75
|
button {
|
|
63
76
|
display: inline-flex;
|
|
64
77
|
align-items: center;
|
|
@@ -97,6 +110,28 @@ export class IdpButton extends DeesElement {
|
|
|
97
110
|
padding: 11px 24px;
|
|
98
111
|
font-size: 19px;
|
|
99
112
|
}
|
|
113
|
+
.rect {
|
|
114
|
+
border-radius: 12px;
|
|
115
|
+
height: 44px;
|
|
116
|
+
padding: 0 18px;
|
|
117
|
+
font-size: 15px;
|
|
118
|
+
font-weight: 600;
|
|
119
|
+
}
|
|
120
|
+
.rect.outline {
|
|
121
|
+
background: var(--idp-card);
|
|
122
|
+
border: 1.5px solid var(--idp-border);
|
|
123
|
+
font-weight: 550;
|
|
124
|
+
font-size: 14.5px;
|
|
125
|
+
}
|
|
126
|
+
.rect.outline:hover:not(:disabled) {
|
|
127
|
+
background: var(--sh-hover);
|
|
128
|
+
}
|
|
129
|
+
.rect.link {
|
|
130
|
+
height: auto;
|
|
131
|
+
padding: 0;
|
|
132
|
+
border-radius: 0;
|
|
133
|
+
font-size: 12.5px;
|
|
134
|
+
}
|
|
100
135
|
.default {
|
|
101
136
|
background: var(--idp-primary);
|
|
102
137
|
color: var(--idp-primary-fg);
|
|
@@ -178,7 +213,7 @@ export class IdpButton extends DeesElement {
|
|
|
178
213
|
|
|
179
214
|
public render(): TemplateResult {
|
|
180
215
|
return html`
|
|
181
|
-
<button class="${this.variant} ${this.size}" type=${this.type} ?disabled=${this.disabled || this.loading} part="button">
|
|
216
|
+
<button class="${this.variant} ${this.size} ${this.shape === 'rect' ? 'rect' : ''}" type=${this.type} ?disabled=${this.disabled || this.loading} part="button">
|
|
182
217
|
${this.loading
|
|
183
218
|
? html`<span class="spinner" aria-hidden="true"></span>`
|
|
184
219
|
: this.icon ? html`<idp-icon name=${this.icon as any} size="14"></idp-icon>` : html``}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { DeesElement, html, property, customElement, css, type TemplateResult } from '@design.estate/dees-element';
|
|
2
|
+
import { idpElementStyles } from './tokens.js';
|
|
3
|
+
import './idp-auth-card.js';
|
|
4
|
+
import './idp-app-pair.js';
|
|
5
|
+
import './idp-option-row.js';
|
|
6
|
+
import './idp-badge.js';
|
|
7
|
+
import './idp-button.js';
|
|
8
|
+
import './idp-icon.js';
|
|
9
|
+
|
|
10
|
+
export interface IIdpConsentScope {
|
|
11
|
+
id: string;
|
|
12
|
+
title: string;
|
|
13
|
+
description: string;
|
|
14
|
+
icon?: string;
|
|
15
|
+
granted?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
declare global {
|
|
19
|
+
interface HTMLElementTagNameMap {
|
|
20
|
+
'idp-consent-card': IdpConsentCard;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@customElement('idp-consent-card')
|
|
25
|
+
export class IdpConsentCard extends DeesElement {
|
|
26
|
+
public static demo = () => html`
|
|
27
|
+
<div style="background: var(--sh-bg, #f5f5f7); padding: 40px; display: flex; justify-content: center;">
|
|
28
|
+
<idp-consent-card
|
|
29
|
+
appName="design.estate"
|
|
30
|
+
userName="Alex Mercer"
|
|
31
|
+
.scopes=${[
|
|
32
|
+
{ id: 'profile', title: 'Your name and email', description: 'alex@lossless.com', icon: 'user' },
|
|
33
|
+
{ id: 'openid', title: 'Your verified identity', description: 'Signed identifier for design.estate', icon: 'fingerprint' },
|
|
34
|
+
{ id: 'organizations', title: 'Organisation membership', description: 'Read which orgs you belong to', icon: 'building-2', granted: true },
|
|
35
|
+
] as IIdpConsentScope[]}
|
|
36
|
+
></idp-consent-card>
|
|
37
|
+
</div>
|
|
38
|
+
`;
|
|
39
|
+
public static demoGroups = ['idp.global v5 auth'];
|
|
40
|
+
|
|
41
|
+
@property({ type: String })
|
|
42
|
+
public accessor appName = '';
|
|
43
|
+
|
|
44
|
+
@property({ type: String })
|
|
45
|
+
public accessor appUrl = '';
|
|
46
|
+
|
|
47
|
+
@property({ type: String })
|
|
48
|
+
public accessor appLogoUrl = '';
|
|
49
|
+
|
|
50
|
+
@property({ type: String })
|
|
51
|
+
public accessor appColor = '#6D5EFC';
|
|
52
|
+
|
|
53
|
+
@property({ type: String })
|
|
54
|
+
public accessor userName = '';
|
|
55
|
+
|
|
56
|
+
@property({ type: Boolean })
|
|
57
|
+
public accessor busy = false;
|
|
58
|
+
|
|
59
|
+
@property({ type: Array })
|
|
60
|
+
public accessor scopes: IIdpConsentScope[] = [];
|
|
61
|
+
|
|
62
|
+
public static styles = [
|
|
63
|
+
...idpElementStyles,
|
|
64
|
+
css`
|
|
65
|
+
:host {
|
|
66
|
+
display: block;
|
|
67
|
+
font-family: var(--idp-font);
|
|
68
|
+
}
|
|
69
|
+
.scopes {
|
|
70
|
+
display: flex;
|
|
71
|
+
flex-direction: column;
|
|
72
|
+
gap: 10px;
|
|
73
|
+
margin-top: 16px;
|
|
74
|
+
}
|
|
75
|
+
.lock-note {
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
gap: 8px;
|
|
79
|
+
margin-top: 16px;
|
|
80
|
+
padding: 9px 12px;
|
|
81
|
+
background: var(--idp-bg);
|
|
82
|
+
border: 1px solid var(--idp-border);
|
|
83
|
+
border-radius: 11px;
|
|
84
|
+
font-size: 11.5px;
|
|
85
|
+
color: var(--idp-fg-3);
|
|
86
|
+
}
|
|
87
|
+
.actions {
|
|
88
|
+
display: flex;
|
|
89
|
+
flex-direction: column;
|
|
90
|
+
gap: 10px;
|
|
91
|
+
margin-top: 18px;
|
|
92
|
+
}
|
|
93
|
+
`,
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
public render(): TemplateResult {
|
|
97
|
+
return html`
|
|
98
|
+
<idp-auth-card heading="${this.appName} wants to access your idp.global account" description="This will allow ${this.appName} to:">
|
|
99
|
+
<idp-app-pair
|
|
100
|
+
slot="top"
|
|
101
|
+
appName=${this.appName}
|
|
102
|
+
appLogoUrl=${this.appLogoUrl}
|
|
103
|
+
appColor=${this.appColor}
|
|
104
|
+
></idp-app-pair>
|
|
105
|
+
<div class="scopes">
|
|
106
|
+
${this.scopes.map(
|
|
107
|
+
(scopeArg) => html`
|
|
108
|
+
<idp-option-row
|
|
109
|
+
interactive="false"
|
|
110
|
+
tileTone="accent"
|
|
111
|
+
tileSize="30"
|
|
112
|
+
trailing="check"
|
|
113
|
+
icon=${scopeArg.icon || 'check'}
|
|
114
|
+
label=${scopeArg.title}
|
|
115
|
+
description=${scopeArg.description}
|
|
116
|
+
>
|
|
117
|
+
${scopeArg.granted
|
|
118
|
+
? html`<idp-badge slot="trailing" variant="ok">Previously allowed</idp-badge>`
|
|
119
|
+
: html``}
|
|
120
|
+
</idp-option-row>
|
|
121
|
+
`
|
|
122
|
+
)}
|
|
123
|
+
</div>
|
|
124
|
+
<div class="lock-note">
|
|
125
|
+
<idp-icon name="lock" size="14"></idp-icon>
|
|
126
|
+
<span>${this.appName} can't post or make changes on your behalf.</span>
|
|
127
|
+
</div>
|
|
128
|
+
<div class="actions">
|
|
129
|
+
<idp-button variant="accent" shape="rect" block ?loading=${this.busy} @click=${this.handleAllow}>Allow access</idp-button>
|
|
130
|
+
<idp-button variant="outline" shape="rect" block ?disabled=${this.busy} @click=${this.handleCancel}>Cancel</idp-button>
|
|
131
|
+
</div>
|
|
132
|
+
<span slot="footer">
|
|
133
|
+
${this.userName ? html`Signed in as ${this.userName} · ` : html``}Revoke anytime in Connected Apps.
|
|
134
|
+
</span>
|
|
135
|
+
</idp-auth-card>
|
|
136
|
+
`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private handleAllow() {
|
|
140
|
+
this.dispatchEvent(new CustomEvent('idp-consent-allow', { bubbles: true, composed: true }));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private handleCancel() {
|
|
144
|
+
this.dispatchEvent(new CustomEvent('idp-consent-cancel', { bubbles: true, composed: true }));
|
|
145
|
+
}
|
|
146
|
+
}
|