@digital-realty/ix-account-switcher 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 ix-account-switcher
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # \<ix-account-switcher>
2
+
3
+ This webcomponent follows the [open-wc](https://github.com/open-wc/open-wc) recommendation.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm i ix-account-switcher
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```html
14
+ <script type="module">
15
+ import 'ix-account-switcher/ix-account-switcher.js';
16
+ </script>
17
+
18
+ <ix-account-switcher></ix-account-switcher>
19
+ ```
20
+
21
+ ## Linting and formatting
22
+
23
+ To scan the project for linting and formatting errors, run
24
+
25
+ ```bash
26
+ npm run lint
27
+ ```
28
+
29
+ To automatically fix linting and formatting errors, run
30
+
31
+ ```bash
32
+ npm run format
33
+ ```
34
+
35
+ ## Testing with Web Test Runner
36
+
37
+ To execute a single test run:
38
+
39
+ ```bash
40
+ npm run test
41
+ ```
42
+
43
+ To run the tests in interactive watch mode run:
44
+
45
+ ```bash
46
+ npm run test:watch
47
+ ```
48
+
49
+ ## Demoing with Storybook
50
+
51
+ To run a local instance of Storybook for your component, run
52
+
53
+ ```bash
54
+ npm run storybook
55
+ ```
56
+
57
+ To build a production version of Storybook, run
58
+
59
+ ```bash
60
+ npm run storybook:build
61
+ ```
62
+
63
+
64
+ ## Tooling configs
65
+
66
+ For most of the tools, the configuration is in the `package.json` to reduce the amount of files in your project.
67
+
68
+ If you customize the configuration a lot, you can consider moving them to individual files.
69
+
70
+ ## Local Demo with `web-dev-server`
71
+
72
+ ```bash
73
+ npm start
74
+ ```
75
+
76
+ To run a local development server that serves the basic demo located in `demo/index.html`
@@ -0,0 +1,19 @@
1
+ import '@digital-realty/ix-dialog/ix-dialog.js';
2
+ import '@digital-realty/ix-field/ix-field.js';
3
+ import '@digital-realty/ix-icon-button/ix-icon-button.js';
4
+ import '@digital-realty/ix-label-tag/ix-label-tag.js';
5
+ import '@digital-realty/ix-select/ix-select.js';
6
+ import '@digital-realty/ix-select/ix-select-option.js';
7
+ import '@digital-realty/ix-tree/ix-tree.js';
8
+ import { TemplateResult } from 'lit';
9
+ import { MobxLitElement } from '@adobe/lit-mobx';
10
+ import type { NestedAccounts } from './types.js';
11
+ export declare class IxAccountSwitcher extends MobxLitElement {
12
+ accounts: NestedAccounts[];
13
+ showDialog: boolean;
14
+ private renderDialog;
15
+ getSelectedAccount(): NestedAccounts | null;
16
+ private renderNestedAccountStructureSelect;
17
+ private renderFlatAccountStructureSelect;
18
+ render(): TemplateResult<1>;
19
+ }
@@ -0,0 +1,122 @@
1
+ import { __decorate } from "tslib";
2
+ import '@digital-realty/ix-dialog/ix-dialog.js';
3
+ import '@digital-realty/ix-field/ix-field.js';
4
+ import '@digital-realty/ix-icon-button/ix-icon-button.js';
5
+ import '@digital-realty/ix-label-tag/ix-label-tag.js';
6
+ import '@digital-realty/ix-select/ix-select.js';
7
+ import '@digital-realty/ix-select/ix-select-option.js';
8
+ import '@digital-realty/ix-tree/ix-tree.js';
9
+ import { html, nothing } from 'lit';
10
+ import { property, state } from 'lit/decorators.js';
11
+ import { MobxLitElement } from '@adobe/lit-mobx';
12
+ import { userProfile } from './state/userProfile.js';
13
+ import findAccountById from './utils/find-account-by-id.js';
14
+ import { mapAccountsToTreeNode } from './utils/map-accounts-to-tree.js';
15
+ export class IxAccountSwitcher extends MobxLitElement {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.accounts = [];
19
+ this.showDialog = false;
20
+ }
21
+ renderDialog() {
22
+ const rootNode = mapAccountsToTreeNode(this.accounts);
23
+ return html `<ix-dialog
24
+ id="account-switcher-dialog"
25
+ class="relative z-50"
26
+ ?open=${this.showDialog}
27
+ @blur=${() => {
28
+ this.showDialog = false;
29
+ }}
30
+ >
31
+ <div class="headline" slot="headline">
32
+ <span class="title">Switch Account</span>
33
+ <ix-icon-button
34
+ @click=${() => {
35
+ this.showDialog = false;
36
+ }}
37
+ icon="close"
38
+ >
39
+ </ix-icon-button>
40
+ </div>
41
+ <form
42
+ id="account-switcher-dialog-form"
43
+ class="form"
44
+ method="dialog"
45
+ slot="content"
46
+ >
47
+ <ix-tree
48
+ .rootNode=${rootNode}
49
+ .selectedNodeId=${userProfile.accountNumber}
50
+ @on-tree-node-selected=${(e) => {
51
+ userProfile.setAccountNumber(e.detail.message.id);
52
+ this.showDialog = false;
53
+ this.requestUpdate();
54
+ this.dispatchEvent(new CustomEvent('account-switched', {
55
+ detail: e.detail.message.id,
56
+ bubbles: true,
57
+ composed: true,
58
+ }));
59
+ }}
60
+ ></ix-tree>
61
+ </form>
62
+ </ix-dialog>`;
63
+ }
64
+ getSelectedAccount() {
65
+ return findAccountById(this.accounts, userProfile.accountNumber);
66
+ }
67
+ renderNestedAccountStructureSelect() {
68
+ const selectedAccount = this.getSelectedAccount();
69
+ return html `
70
+ <ix-field
71
+ @click=${() => {
72
+ this.showDialog = true;
73
+ }}
74
+ >
75
+ <div class="subaccount-wrap">
76
+ <span class="subaccount-name"> ${selectedAccount === null || selectedAccount === void 0 ? void 0 : selectedAccount.name} </span>
77
+ <ix-icon class="dd-icon">arrow_drop_down</ix-icon>
78
+ </div>
79
+ </ix-field>
80
+ `;
81
+ }
82
+ renderFlatAccountStructureSelect() {
83
+ const selectedAccount = this.getSelectedAccount();
84
+ const activeLabelTag = html `<ix-label-tag>Active</ix-label-tag>`;
85
+ const options = this.accounts.map(account => {
86
+ const isSelected = account.id === (selectedAccount === null || selectedAccount === void 0 ? void 0 : selectedAccount.id);
87
+ return html `<ix-select-option value=${account.id} .selected=${isSelected}>
88
+ <div slot="headline">${account.name}</div>
89
+ <div slot="end">${isSelected ? activeLabelTag : nothing}</div>
90
+ </ix-select-option>`;
91
+ });
92
+ return html `<div class="account-switcher__select">
93
+ <ix-select
94
+ @request-selection=${(e) => {
95
+ const target = e.target;
96
+ userProfile.setAccountNumber(target.value);
97
+ }}
98
+ >
99
+ ${options}
100
+ </ix-select>
101
+ </div>`;
102
+ }
103
+ render() {
104
+ const hasSubaccounts = this.accounts.some(a => a.subaccounts && a.subaccounts.length > 0);
105
+ return html `
106
+ <div class="account-switcher-container">
107
+ ${hasSubaccounts
108
+ ? this.renderNestedAccountStructureSelect()
109
+ : this.renderFlatAccountStructureSelect()}
110
+ </div>
111
+
112
+ ${hasSubaccounts ? this.renderDialog() : null}
113
+ `;
114
+ }
115
+ }
116
+ __decorate([
117
+ property({ type: Array })
118
+ ], IxAccountSwitcher.prototype, "accounts", void 0);
119
+ __decorate([
120
+ state()
121
+ ], IxAccountSwitcher.prototype, "showDialog", void 0);
122
+ //# sourceMappingURL=IxAccountSwitcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IxAccountSwitcher.js","sourceRoot":"","sources":["../src/IxAccountSwitcher.ts"],"names":[],"mappings":"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","sourcesContent":["import '@digital-realty/ix-dialog/ix-dialog.js';\nimport '@digital-realty/ix-field/ix-field.js';\nimport '@digital-realty/ix-icon-button/ix-icon-button.js';\nimport '@digital-realty/ix-label-tag/ix-label-tag.js';\nimport '@digital-realty/ix-select/ix-select.js';\nimport '@digital-realty/ix-select/ix-select-option.js';\nimport '@digital-realty/ix-tree/ix-tree.js';\nimport type { IIxTreeNode } from '@digital-realty/ix-tree';\nimport { html, nothing, TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { MobxLitElement } from '@adobe/lit-mobx';\nimport { userProfile } from './state/userProfile.js';\nimport findAccountById from './utils/find-account-by-id.js';\nimport { mapAccountsToTreeNode } from './utils/map-accounts-to-tree.js';\nimport type { NestedAccounts } from './types.js';\n\nexport class IxAccountSwitcher extends MobxLitElement {\n @property({ type: Array }) accounts: NestedAccounts[] = [];\n\n @state() showDialog: boolean = false;\n\n private renderDialog(): TemplateResult<1> {\n const rootNode: IIxTreeNode = mapAccountsToTreeNode(this.accounts);\n\n return html`<ix-dialog\n id=\"account-switcher-dialog\"\n class=\"relative z-50\"\n ?open=${this.showDialog}\n @blur=${() => {\n this.showDialog = false;\n }}\n >\n <div class=\"headline\" slot=\"headline\">\n <span class=\"title\">Switch Account</span>\n <ix-icon-button\n @click=${() => {\n this.showDialog = false;\n }}\n icon=\"close\"\n >\n </ix-icon-button>\n </div>\n <form\n id=\"account-switcher-dialog-form\"\n class=\"form\"\n method=\"dialog\"\n slot=\"content\"\n >\n <ix-tree\n .rootNode=${rootNode}\n .selectedNodeId=${userProfile.accountNumber}\n @on-tree-node-selected=${(e: CustomEvent) => {\n userProfile.setAccountNumber(e.detail.message.id);\n this.showDialog = false;\n this.requestUpdate();\n this.dispatchEvent(\n new CustomEvent('account-switched', {\n detail: e.detail.message.id,\n bubbles: true,\n composed: true,\n })\n );\n }}\n ></ix-tree>\n </form>\n </ix-dialog>`;\n }\n\n getSelectedAccount() {\n return findAccountById(this.accounts, userProfile.accountNumber as string);\n }\n\n private renderNestedAccountStructureSelect(): TemplateResult<1> {\n const selectedAccount = this.getSelectedAccount();\n\n return html`\n <ix-field\n @click=${() => {\n this.showDialog = true;\n }}\n >\n <div class=\"subaccount-wrap\">\n <span class=\"subaccount-name\"> ${selectedAccount?.name} </span>\n <ix-icon class=\"dd-icon\">arrow_drop_down</ix-icon>\n </div>\n </ix-field>\n `;\n }\n\n private renderFlatAccountStructureSelect(): TemplateResult<1> {\n const selectedAccount = this.getSelectedAccount();\n const activeLabelTag = html`<ix-label-tag>Active</ix-label-tag>`;\n\n const options = this.accounts.map(account => {\n const isSelected = account.id === selectedAccount?.id;\n\n return html`<ix-select-option value=${account.id} .selected=${isSelected}>\n <div slot=\"headline\">${account.name}</div>\n <div slot=\"end\">${isSelected ? activeLabelTag : nothing}</div>\n </ix-select-option>`;\n });\n\n return html`<div class=\"account-switcher__select\">\n <ix-select\n @request-selection=${(e: Event) => {\n const target = e.target as HTMLSelectElement;\n userProfile.setAccountNumber(target.value);\n }}\n >\n ${options}\n </ix-select>\n </div>`;\n }\n\n render(): TemplateResult<1> {\n const hasSubaccounts = this.accounts.some(\n a => a.subaccounts && a.subaccounts.length > 0\n );\n\n return html`\n <div class=\"account-switcher-container\">\n ${hasSubaccounts\n ? this.renderNestedAccountStructureSelect()\n : this.renderFlatAccountStructureSelect()}\n </div>\n\n ${hasSubaccounts ? this.renderDialog() : null}\n `;\n }\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { Account, IAccount } from './types.js';
2
+ export declare const mapAccountToIAccount: (payload: Account[]) => IAccount[];
@@ -0,0 +1,12 @@
1
+ export const mapAccountToIAccount = (payload) => {
2
+ const response = [];
3
+ payload.forEach(account => {
4
+ response.push({
5
+ accountNumber: account.account_number,
6
+ name: account.name,
7
+ parentAccountNumber: account.parent_account_number,
8
+ });
9
+ });
10
+ return response;
11
+ };
12
+ //# sourceMappingURL=account-mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-mapper.js","sourceRoot":"","sources":["../src/account-mapper.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,OAAkB,EAAc,EAAE;IACrE,MAAM,QAAQ,GAAe,EAAE,CAAC;IAEhC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;QACxB,QAAQ,CAAC,IAAI,CAAC;YACZ,aAAa,EAAE,OAAO,CAAC,cAAc;YACrC,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,mBAAmB,EAAE,OAAO,CAAC,qBAAqB;SACnD,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC","sourcesContent":["import type { Account, IAccount } from './types.js';\n\nexport const mapAccountToIAccount = (payload: Account[]): IAccount[] => {\n const response: IAccount[] = [];\n\n payload.forEach(account => {\n response.push({\n accountNumber: account.account_number,\n name: account.name,\n parentAccountNumber: account.parent_account_number,\n });\n });\n\n return response;\n};\n"]}
@@ -0,0 +1 @@
1
+ export declare const AccountSwitcherStyles: import("lit").CSSResult;
@@ -0,0 +1,33 @@
1
+ import { css } from 'lit';
2
+ export const AccountSwitcherStyles = css `
3
+ .subaccount-wrap {
4
+ display: flex;
5
+ --ix-icon-font-size: 1.6rem;
6
+ }
7
+ .subaccount-name {
8
+ overflow: hidden;
9
+ text-overflow: ellipsis;
10
+ white-space: nowrap;
11
+ width: 0;
12
+ flex: 1;
13
+ }
14
+ .dd-icon {
15
+ margin: -2px -5px -5px 0px;
16
+ }
17
+ .headline {
18
+ display: flex;
19
+ }
20
+ .title {
21
+ flex: 1;
22
+ }
23
+ .form {
24
+ border: 1px solid #e0e0e0;
25
+ border-radius: 0.25rem;
26
+ height: calc(488px - 3rem);
27
+ margin: 1rem 1.5rem 1.5rem 1.5rem;
28
+ padding: 0;
29
+ width: calc(560px - 3rem);
30
+ overflow: auto;
31
+ }
32
+ `;
33
+ //# sourceMappingURL=account-switcher-styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-switcher-styles.js","sourceRoot":"","sources":["../src/account-switcher-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BvC,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport const AccountSwitcherStyles = css`\n .subaccount-wrap {\n display: flex;\n --ix-icon-font-size: 1.6rem;\n }\n .subaccount-name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n width: 0;\n flex: 1;\n }\n .dd-icon {\n margin: -2px -5px -5px 0px;\n }\n .headline {\n display: flex;\n }\n .title {\n flex: 1;\n }\n .form {\n border: 1px solid #e0e0e0;\n border-radius: 0.25rem;\n height: calc(488px - 3rem);\n margin: 1rem 1.5rem 1.5rem 1.5rem;\n padding: 0;\n width: calc(560px - 3rem);\n overflow: auto;\n }\n`;\n"]}
@@ -0,0 +1 @@
1
+ export { IxAccountSwitcher } from './IxAccountSwitcher.js';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { IxAccountSwitcher } from './IxAccountSwitcher.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC","sourcesContent":["export { IxAccountSwitcher } from './IxAccountSwitcher.js';\n"]}
@@ -0,0 +1,4 @@
1
+ import { IxAccountSwitcher } from './IxAccountSwitcher.js';
2
+ export declare class IxAccountSwitcherStyled extends IxAccountSwitcher {
3
+ static styles: import("lit").CSSResult[];
4
+ }
@@ -0,0 +1,17 @@
1
+ import { css } from 'lit';
2
+ import { elementTheme } from '@digital-realty/theme';
3
+ import { IxAccountSwitcher } from './IxAccountSwitcher.js';
4
+ import { AccountSwitcherStyles } from './account-switcher-styles.js';
5
+ export class IxAccountSwitcherStyled extends IxAccountSwitcher {
6
+ }
7
+ IxAccountSwitcherStyled.styles = [
8
+ elementTheme,
9
+ AccountSwitcherStyles,
10
+ css `
11
+ :host {
12
+ --md-theme-primary: var(--ix-sys-primary, blue);
13
+ }
14
+ `,
15
+ ];
16
+ window.customElements.define('ix-account-switcher', IxAccountSwitcherStyled);
17
+ //# sourceMappingURL=ix-account-switcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ix-account-switcher.js","sourceRoot":"","sources":["../src/ix-account-switcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,MAAM,OAAO,uBAAwB,SAAQ,iBAAiB;;AAC5C,8BAAM,GAAG;IACvB,YAAY;IACZ,qBAAqB;IACrB,GAAG,CAAA;;;;KAIF;CACF,CAAC;AAGJ,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,qBAAqB,EAAE,uBAAuB,CAAC,CAAC","sourcesContent":["import { css } from 'lit';\nimport { elementTheme } from '@digital-realty/theme';\nimport { IxAccountSwitcher } from './IxAccountSwitcher.js';\nimport { AccountSwitcherStyles } from './account-switcher-styles.js';\n\nexport class IxAccountSwitcherStyled extends IxAccountSwitcher {\n static override styles = [\n elementTheme,\n AccountSwitcherStyles,\n css`\n :host {\n --md-theme-primary: var(--ix-sys-primary, blue);\n }\n `,\n ];\n}\n\nwindow.customElements.define('ix-account-switcher', IxAccountSwitcherStyled);\n"]}
@@ -0,0 +1 @@
1
+ import{html,nothing,css}from"lit";import{elementTheme}from"@digital-realty/theme";import{__decorate}from"tslib";import"@digital-realty/ix-dialog/ix-dialog.js";import"@digital-realty/ix-field/ix-field.js";import"@digital-realty/ix-icon-button/ix-icon-button.js";import"@digital-realty/ix-label-tag/ix-label-tag.js";import"@digital-realty/ix-select/ix-select.js";import"@digital-realty/ix-select/ix-select-option.js";import"@digital-realty/ix-tree/ix-tree.js";import{property,state}from"lit/decorators.js";import{MobxLitElement}from"@adobe/lit-mobx";import{makeAutoObservable,toJS}from"mobx";import{makePersistable}from"mobx-persist-store";class UserProfileState{constructor(){this.accountNumber=void 0,this.accountPermissions=[],makeAutoObservable(this),makePersistable(this,{name:"user-profile",properties:["accountNumber","accountPermissions","contact"],storage:window.localStorage})}setPermissions(e){this.accountPermissions=e}setAccountNumber(e){this.accountNumber=e}setContact(e){this.contact=e}get account(){var e;return null==(e=this.contact)?void 0:e.accounts.find(e=>e.accountNumber===this.accountNumber)}hasUserManagementExternalUserRead(){return this.hasPermission("User Management - External User","read")}hasUserManagementExternalUserUpdate(){return this.hasPermission("User Management - External User","update")}hasUserManagementInternalUserUpdate(){return this.hasPermission("User Management - Internal User","update")}hasCustomRoleManagementApprove(){return this.hasPermission("Role Management - Custom Role","approve")}hasCustomRoleManagementCreate(){return this.hasPermission("Role Management - Custom Roles","create")}hasCustomRoleManagementUpdate(){return this.hasPermission("Role Management - Custom Roles","update")}hasCustomRoleManagementRead(){return this.hasPermission("Role Management - Custom Roles","read")}hasInternalRoleManagementCreate(){return this.hasPermission("Role Management - Internal Roles","create")}hasInternalRoleManagementUpdate(){return this.hasPermission("Role Management - Internal Roles","update")}hasInternalRoleManagementRead(){return this.hasPermission("Role Management - Internal Roles","read")}hasDefaultSystemRoleManagementCreate(){return this.hasPermission("Role Management - Default System Roles","create")}hasDefaultSystemRoleManagementUpdate(){return this.hasPermission("Role Management - Default System Roles","update")}hasDefaultSystemRoleManagementRead(){return this.hasPermission("Role Management - Default System Roles","read")}hasPrivilegeLevel(t,s){var e=["approve","create","update","read"],o=e.findIndex(e=>e===t.toLowerCase());return e.findIndex(e=>e===s.toLowerCase())<=o}hasPermission(t,s){var e=toJS(this.accountPermissions).find(e=>e.accountNumber===this.accountNumber||null===e.accountNumber);let o=!1;return e&&e.permissions.forEach(e=>{e.permissionName===t&&s&&this.hasPrivilegeLevel(s.toLowerCase(),e.privilege.toLowerCase())&&(o=!0)}),o}}const userProfile=new UserProfileState,findAccountById=(e,t)=>{var s=e.find(e=>e.id===t);if(s)return s;for(const a of e)if(a.subaccounts){var o=findAccountById(a.subaccounts,t);if(o)return o}return null},mapAccountToTreeNode=(e,t)=>{const s={expanded:!1,id:e.id,label:e.name,parentId:t.id};return s.children=null==(t=e.subaccounts)?void 0:t.map(e=>mapAccountToTreeNode(e,s)),s},mapAccountsToTreeNode=e=>{const t={expanded:!1,id:"root",label:"",parentId:void 0};return t.children=e.map(e=>mapAccountToTreeNode(e,t)),t};class IxAccountSwitcher extends MobxLitElement{constructor(){super(...arguments),this.accounts=[],this.showDialog=!1}renderDialog(){var e=mapAccountsToTreeNode(this.accounts);return html`<ix-dialog id="account-switcher-dialog" class="relative z-50" ?open="${this.showDialog}" @blur="${()=>{this.showDialog=!1}}"><div class="headline" slot="headline"><span class="title">Switch Account</span><ix-icon-button @click="${()=>{this.showDialog=!1}}" icon="close"></ix-icon-button></div><form id="account-switcher-dialog-form" class="form" method="dialog" slot="content"><ix-tree .rootNode="${e}" .selectedNodeId="${userProfile.accountNumber}" @on-tree-node-selected="${e=>{userProfile.setAccountNumber(e.detail.message.id),this.showDialog=!1,this.requestUpdate(),this.dispatchEvent(new CustomEvent("account-switched",{detail:e.detail.message.id,bubbles:!0,composed:!0}))}}"></ix-tree></form></ix-dialog>`}getSelectedAccount(){return findAccountById(this.accounts,userProfile.accountNumber)}renderNestedAccountStructureSelect(){var e=this.getSelectedAccount();return html`<ix-field @click="${()=>{this.showDialog=!0}}"><div class="subaccount-wrap"><span class="subaccount-name">${null==e?void 0:e.name}</span><ix-icon class="dd-icon">arrow_drop_down</ix-icon></div></ix-field>`}renderFlatAccountStructureSelect(){const s=this.getSelectedAccount(),o=html`<ix-label-tag>Active</ix-label-tag>`;var e=this.accounts.map(e=>{var t=e.id===(null===s||void 0===s?void 0:s.id);return html`<ix-select-option value="${e.id}" .selected="${t}"><div slot="headline">${e.name}</div><div slot="end">${t?o:nothing}</div></ix-select-option>`});return html`<div class="account-switcher__select"><ix-select @request-selection="${e=>{e=e.target;userProfile.setAccountNumber(e.value)}}">${e}</ix-select></div>`}render(){var e=this.accounts.some(e=>e.subaccounts&&0<e.subaccounts.length);return html`<div class="account-switcher-container">${e?this.renderNestedAccountStructureSelect():this.renderFlatAccountStructureSelect()}</div>${e?this.renderDialog():null}`}}__decorate([property({type:Array})],IxAccountSwitcher.prototype,"accounts",void 0),__decorate([state()],IxAccountSwitcher.prototype,"showDialog",void 0);const AccountSwitcherStyles=css`.subaccount-wrap{display:flex;--ix-icon-font-size:1.6rem}.subaccount-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:0;flex:1}.dd-icon{margin:-2px -5px -5px 0}.headline{display:flex}.title{flex:1}.form{border:1px solid #e0e0e0;border-radius:.25rem;height:calc(488px - 3rem);margin:1rem 1.5rem 1.5rem 1.5rem;padding:0;width:calc(560px - 3rem);overflow:auto}`;class IxAccountSwitcherStyled extends IxAccountSwitcher{}IxAccountSwitcherStyled.styles=[elementTheme,AccountSwitcherStyles,css`:host{--md-theme-primary:var(--ix-sys-primary, blue)}`],window.customElements.define("ix-account-switcher",IxAccountSwitcherStyled);export{IxAccountSwitcherStyled};
@@ -0,0 +1,28 @@
1
+ import type { IContactInputAccountsInner, AccountPermission, IContact } from '../types.js';
2
+ declare class UserProfileState {
3
+ constructor();
4
+ accountNumber?: string;
5
+ accountPermissions: AccountPermission[];
6
+ contact: IContact | undefined;
7
+ setPermissions(permissions: AccountPermission[]): void;
8
+ setAccountNumber(accountNumber: string): void;
9
+ setContact(contact: IContact): void;
10
+ get account(): IContactInputAccountsInner;
11
+ hasUserManagementExternalUserRead(): boolean;
12
+ hasUserManagementExternalUserUpdate(): boolean;
13
+ hasUserManagementInternalUserUpdate(): boolean;
14
+ hasCustomRoleManagementApprove(): boolean;
15
+ hasCustomRoleManagementCreate(): boolean;
16
+ hasCustomRoleManagementUpdate(): boolean;
17
+ hasCustomRoleManagementRead(): boolean;
18
+ hasInternalRoleManagementCreate(): boolean;
19
+ hasInternalRoleManagementUpdate(): boolean;
20
+ hasInternalRoleManagementRead(): boolean;
21
+ hasDefaultSystemRoleManagementCreate(): boolean;
22
+ hasDefaultSystemRoleManagementUpdate(): boolean;
23
+ hasDefaultSystemRoleManagementRead(): boolean;
24
+ private hasPrivilegeLevel;
25
+ private hasPermission;
26
+ }
27
+ export declare const userProfile: UserProfileState;
28
+ export {};
@@ -0,0 +1,91 @@
1
+ import { makeAutoObservable, toJS } from 'mobx';
2
+ import { makePersistable } from 'mobx-persist-store';
3
+ class UserProfileState {
4
+ constructor() {
5
+ this.accountNumber = undefined;
6
+ this.accountPermissions = [];
7
+ makeAutoObservable(this);
8
+ makePersistable(this, {
9
+ name: 'user-profile',
10
+ properties: ['accountNumber', 'accountPermissions', 'contact'],
11
+ storage: window.localStorage,
12
+ });
13
+ }
14
+ setPermissions(permissions) {
15
+ this.accountPermissions = permissions;
16
+ }
17
+ setAccountNumber(accountNumber) {
18
+ this.accountNumber = accountNumber;
19
+ }
20
+ setContact(contact) {
21
+ this.contact = contact;
22
+ }
23
+ get account() {
24
+ var _a;
25
+ return (_a = this.contact) === null || _a === void 0 ? void 0 : _a.accounts.find(x => x.accountNumber === this.accountNumber);
26
+ }
27
+ hasUserManagementExternalUserRead() {
28
+ return this.hasPermission('User Management - External User', 'read');
29
+ }
30
+ hasUserManagementExternalUserUpdate() {
31
+ return this.hasPermission('User Management - External User', 'update');
32
+ }
33
+ hasUserManagementInternalUserUpdate() {
34
+ return this.hasPermission('User Management - Internal User', 'update');
35
+ }
36
+ hasCustomRoleManagementApprove() {
37
+ return this.hasPermission('Role Management - Custom Role', 'approve');
38
+ }
39
+ hasCustomRoleManagementCreate() {
40
+ return this.hasPermission('Role Management - Custom Roles', 'create');
41
+ }
42
+ hasCustomRoleManagementUpdate() {
43
+ return this.hasPermission('Role Management - Custom Roles', 'update');
44
+ }
45
+ hasCustomRoleManagementRead() {
46
+ return this.hasPermission('Role Management - Custom Roles', 'read');
47
+ }
48
+ hasInternalRoleManagementCreate() {
49
+ return this.hasPermission('Role Management - Internal Roles', 'create');
50
+ }
51
+ hasInternalRoleManagementUpdate() {
52
+ return this.hasPermission('Role Management - Internal Roles', 'update');
53
+ }
54
+ hasInternalRoleManagementRead() {
55
+ return this.hasPermission('Role Management - Internal Roles', 'read');
56
+ }
57
+ hasDefaultSystemRoleManagementCreate() {
58
+ return this.hasPermission('Role Management - Default System Roles', 'create');
59
+ }
60
+ hasDefaultSystemRoleManagementUpdate() {
61
+ return this.hasPermission('Role Management - Default System Roles', 'update');
62
+ }
63
+ hasDefaultSystemRoleManagementRead() {
64
+ return this.hasPermission('Role Management - Default System Roles', 'read');
65
+ }
66
+ // eslint-disable-next-line class-methods-use-this
67
+ hasPrivilegeLevel(requiredPrivilege, currentUserPrivilege) {
68
+ const privileges = ['approve', 'create', 'update', 'read'];
69
+ const requiredIndex = privileges.findIndex(x => x === requiredPrivilege.toLowerCase());
70
+ const currentIndex = privileges.findIndex(x => x === currentUserPrivilege.toLowerCase());
71
+ return requiredIndex >= currentIndex;
72
+ }
73
+ hasPermission(permission, privilege) {
74
+ const accountPermissionArray = toJS(this.accountPermissions);
75
+ const accountPermission = accountPermissionArray.find(x => x.accountNumber === this.accountNumber || x.accountNumber === null);
76
+ let hasPermission = false;
77
+ if (accountPermission) {
78
+ accountPermission.permissions.forEach(accPermission => {
79
+ if (accPermission.permissionName === permission) {
80
+ if (privilege &&
81
+ this.hasPrivilegeLevel(privilege.toLowerCase(), accPermission.privilege.toLowerCase())) {
82
+ hasPermission = true;
83
+ }
84
+ }
85
+ });
86
+ }
87
+ return hasPermission;
88
+ }
89
+ }
90
+ export const userProfile = new UserProfileState();
91
+ //# sourceMappingURL=userProfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"userProfile.js","sourceRoot":"","sources":["../../src/state/userProfile.ts"],"names":[],"mappings":"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","sourcesContent":["import { makeAutoObservable, toJS } from 'mobx';\nimport { makePersistable } from 'mobx-persist-store';\nimport type {\n IContactInputAccountsInner,\n AccountPermission,\n IContact,\n} from '../types.js';\n\nclass UserProfileState {\n constructor() {\n makeAutoObservable(this);\n makePersistable(this, {\n name: 'user-profile',\n properties: ['accountNumber', 'accountPermissions', 'contact'],\n storage: window.localStorage,\n });\n }\n\n public accountNumber?: string = undefined;\n\n public accountPermissions: AccountPermission[] = [];\n\n public contact: IContact | undefined;\n\n public setPermissions(permissions: AccountPermission[]) {\n this.accountPermissions = permissions;\n }\n\n public setAccountNumber(accountNumber: string) {\n this.accountNumber = accountNumber;\n }\n\n public setContact(contact: IContact) {\n this.contact = contact;\n }\n\n public get account(): IContactInputAccountsInner {\n return this.contact?.accounts.find(\n x => x.accountNumber === this.accountNumber\n ) as IContactInputAccountsInner;\n }\n\n public hasUserManagementExternalUserRead(): boolean {\n return this.hasPermission('User Management - External User', 'read');\n }\n\n public hasUserManagementExternalUserUpdate(): boolean {\n return this.hasPermission('User Management - External User', 'update');\n }\n\n public hasUserManagementInternalUserUpdate(): boolean {\n return this.hasPermission('User Management - Internal User', 'update');\n }\n\n public hasCustomRoleManagementApprove(): boolean {\n return this.hasPermission('Role Management - Custom Role', 'approve');\n }\n\n public hasCustomRoleManagementCreate(): boolean {\n return this.hasPermission('Role Management - Custom Roles', 'create');\n }\n\n public hasCustomRoleManagementUpdate(): boolean {\n return this.hasPermission('Role Management - Custom Roles', 'update');\n }\n\n public hasCustomRoleManagementRead(): boolean {\n return this.hasPermission('Role Management - Custom Roles', 'read');\n }\n\n public hasInternalRoleManagementCreate(): boolean {\n return this.hasPermission('Role Management - Internal Roles', 'create');\n }\n\n public hasInternalRoleManagementUpdate(): boolean {\n return this.hasPermission('Role Management - Internal Roles', 'update');\n }\n\n public hasInternalRoleManagementRead(): boolean {\n return this.hasPermission('Role Management - Internal Roles', 'read');\n }\n\n public hasDefaultSystemRoleManagementCreate(): boolean {\n return this.hasPermission(\n 'Role Management - Default System Roles',\n 'create'\n );\n }\n\n public hasDefaultSystemRoleManagementUpdate(): boolean {\n return this.hasPermission(\n 'Role Management - Default System Roles',\n 'update'\n );\n }\n\n public hasDefaultSystemRoleManagementRead(): boolean {\n return this.hasPermission('Role Management - Default System Roles', 'read');\n }\n\n // eslint-disable-next-line class-methods-use-this\n private hasPrivilegeLevel(\n requiredPrivilege: string,\n currentUserPrivilege: string\n ): boolean {\n const privileges: string[] = ['approve', 'create', 'update', 'read'];\n const requiredIndex = privileges.findIndex(\n x => x === requiredPrivilege.toLowerCase()\n );\n const currentIndex = privileges.findIndex(\n x => x === currentUserPrivilege.toLowerCase()\n );\n\n return requiredIndex >= currentIndex;\n }\n\n private hasPermission(permission: string, privilege: string): boolean {\n const accountPermissionArray = toJS(this.accountPermissions);\n const accountPermission = accountPermissionArray.find(\n x => x.accountNumber === this.accountNumber || x.accountNumber === null\n ) as AccountPermission;\n let hasPermission: boolean = false;\n\n if (accountPermission) {\n accountPermission.permissions.forEach(accPermission => {\n if (accPermission.permissionName === permission) {\n if (\n privilege &&\n this.hasPrivilegeLevel(\n privilege.toLowerCase(),\n accPermission.privilege.toLowerCase()\n )\n ) {\n hasPermission = true;\n }\n }\n });\n }\n\n return hasPermission;\n }\n}\n\nexport const userProfile = new UserProfileState();\n"]}
@@ -0,0 +1,43 @@
1
+ export interface IAccount {
2
+ accountNumber?: string;
3
+ parentAccountNumber?: string | null;
4
+ name?: string;
5
+ }
6
+ export interface Account {
7
+ account_number?: string;
8
+ parent_account_number?: string | null;
9
+ name?: string;
10
+ }
11
+ export interface NestedAccounts {
12
+ id: string;
13
+ name: string;
14
+ status: string;
15
+ accountNumber: string;
16
+ subaccounts?: NestedAccounts[];
17
+ }
18
+ export interface IContactInputAccountsInner {
19
+ id: string;
20
+ name: string;
21
+ status: string;
22
+ accountNumber?: string;
23
+ statusUpdateAt?: string;
24
+ statusUpdateBy?: string;
25
+ }
26
+ export interface IContact {
27
+ id: string;
28
+ firstName: string;
29
+ lastName: string;
30
+ email: string;
31
+ phone: string;
32
+ evacAssistance: boolean;
33
+ accounts: Array<IContactInputAccountsInner>;
34
+ status?: string;
35
+ }
36
+ export type UserPermission = {
37
+ permissionName: string;
38
+ privilege: string;
39
+ };
40
+ export type AccountPermission = {
41
+ accountNumber: string;
42
+ permissions: UserPermission[];
43
+ };
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface IAccount {\n accountNumber?: string;\n parentAccountNumber?: string | null;\n name?: string;\n}\n\nexport interface Account {\n account_number?: string;\n parent_account_number?: string | null;\n name?: string;\n}\n\nexport interface NestedAccounts {\n id: string;\n name: string;\n status: string;\n accountNumber: string;\n subaccounts?: NestedAccounts[];\n}\n\nexport interface IContactInputAccountsInner {\n id: string;\n name: string;\n status: string;\n accountNumber?: string;\n statusUpdateAt?: string;\n statusUpdateBy?: string;\n}\n\nexport interface IContact {\n id: string;\n firstName: string;\n lastName: string;\n email: string;\n phone: string;\n evacAssistance: boolean;\n accounts: Array<IContactInputAccountsInner>;\n status?: string;\n}\n\nexport type UserPermission = {\n permissionName: string;\n privilege: string;\n};\n\nexport type AccountPermission = {\n accountNumber: string;\n permissions: UserPermission[];\n};\n"]}
@@ -0,0 +1,3 @@
1
+ import type { NestedAccounts } from '../types.js';
2
+ declare const findAccountById: (accounts: NestedAccounts[], id: string) => NestedAccounts | null;
3
+ export default findAccountById;
@@ -0,0 +1,17 @@
1
+ const findAccountById = (accounts, id) => {
2
+ const account = accounts.find(a => a.id === id);
3
+ if (account) {
4
+ return account;
5
+ }
6
+ for (const a of accounts) {
7
+ if (a.subaccounts) {
8
+ const foundAccount = findAccountById(a.subaccounts, id);
9
+ if (foundAccount) {
10
+ return foundAccount;
11
+ }
12
+ }
13
+ }
14
+ return null;
15
+ };
16
+ export default findAccountById;
17
+ //# sourceMappingURL=find-account-by-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-account-by-id.js","sourceRoot":"","sources":["../../src/utils/find-account-by-id.ts"],"names":[],"mappings":"AAEA,MAAM,eAAe,GAAG,CACtB,QAA0B,EAC1B,EAAU,EACa,EAAE;IACzB,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAChD,IAAI,OAAO,EAAE;QACX,OAAO,OAAO,CAAC;KAChB;IAED,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE;QACxB,IAAI,CAAC,CAAC,WAAW,EAAE;YACjB,MAAM,YAAY,GAAG,eAAe,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YACxD,IAAI,YAAY,EAAE;gBAChB,OAAO,YAAY,CAAC;aACrB;SACF;KACF;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,eAAe,eAAe,CAAC","sourcesContent":["import type { NestedAccounts } from '../types.js';\n\nconst findAccountById = (\n accounts: NestedAccounts[],\n id: string\n): NestedAccounts | null => {\n const account = accounts.find(a => a.id === id);\n if (account) {\n return account;\n }\n\n for (const a of accounts) {\n if (a.subaccounts) {\n const foundAccount = findAccountById(a.subaccounts, id);\n if (foundAccount) {\n return foundAccount;\n }\n }\n }\n\n return null;\n};\n\nexport default findAccountById;\n"]}
@@ -0,0 +1,8 @@
1
+ import type { IIxTreeNode } from '@digital-realty/ix-tree';
2
+ export interface IAccount {
3
+ accountNumber?: string;
4
+ parentAccountNumber?: string | null;
5
+ name?: string;
6
+ }
7
+ export declare const mapAccountToTreeNode: (account: any, parentNode: IIxTreeNode) => IIxTreeNode;
8
+ export declare const mapAccountsToTreeNode: (accounts: Array<IAccount>) => IIxTreeNode;
@@ -0,0 +1,23 @@
1
+ // TODO: Should use correctly typed definition rather than any
2
+ export const mapAccountToTreeNode = (account, parentNode) => {
3
+ var _a;
4
+ const treeNode = {
5
+ expanded: false,
6
+ id: account.id,
7
+ label: account.name,
8
+ parentId: parentNode.id,
9
+ };
10
+ treeNode.children = (_a = account.subaccounts) === null || _a === void 0 ? void 0 : _a.map((childAccount) => mapAccountToTreeNode(childAccount, treeNode));
11
+ return treeNode;
12
+ };
13
+ export const mapAccountsToTreeNode = (accounts) => {
14
+ const rootNode = {
15
+ expanded: false,
16
+ id: 'root',
17
+ label: '',
18
+ parentId: undefined,
19
+ };
20
+ rootNode.children = accounts.map(account => mapAccountToTreeNode(account, rootNode));
21
+ return rootNode;
22
+ };
23
+ //# sourceMappingURL=map-accounts-to-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map-accounts-to-tree.js","sourceRoot":"","sources":["../../src/utils/map-accounts-to-tree.ts"],"names":[],"mappings":"AAQA,8DAA8D;AAC9D,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,OAAY,EACZ,UAAuB,EACV,EAAE;;IACf,MAAM,QAAQ,GAAgB;QAC5B,QAAQ,EAAE,KAAK;QACf,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,KAAK,EAAE,OAAO,CAAC,IAAI;QACnB,QAAQ,EAAE,UAAU,CAAC,EAAE;KACxB,CAAC;IAEF,QAAQ,CAAC,QAAQ,GAAG,MAAA,OAAO,CAAC,WAAW,0CAAE,GAAG,CAAC,CAAC,YAAiB,EAAE,EAAE,CACjE,oBAAoB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAC7C,CAAC;IAEF,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,QAAyB,EACZ,EAAE;IACf,MAAM,QAAQ,GAAgB;QAC5B,QAAQ,EAAE,KAAK;QACf,EAAE,EAAE,MAAM;QACV,KAAK,EAAE,EAAE;QACT,QAAQ,EAAE,SAAS;KACpB,CAAC;IAEF,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CACzC,oBAAoB,CAAC,OAAO,EAAE,QAAQ,CAAC,CACxC,CAAC;IAEF,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC","sourcesContent":["import type { IIxTreeNode } from '@digital-realty/ix-tree';\n\nexport interface IAccount {\n accountNumber?: string;\n parentAccountNumber?: string | null;\n name?: string;\n}\n\n// TODO: Should use correctly typed definition rather than any\nexport const mapAccountToTreeNode = (\n account: any,\n parentNode: IIxTreeNode\n): IIxTreeNode => {\n const treeNode: IIxTreeNode = {\n expanded: false,\n id: account.id,\n label: account.name,\n parentId: parentNode.id,\n };\n\n treeNode.children = account.subaccounts?.map((childAccount: any) =>\n mapAccountToTreeNode(childAccount, treeNode)\n );\n\n return treeNode;\n};\n\nexport const mapAccountsToTreeNode = (\n accounts: Array<IAccount>\n): IIxTreeNode => {\n const rootNode: IIxTreeNode = {\n expanded: false,\n id: 'root',\n label: '',\n parentId: undefined,\n };\n\n rootNode.children = accounts.map(account =>\n mapAccountToTreeNode(account, rootNode)\n );\n\n return rootNode;\n};\n"]}
package/package.json ADDED
@@ -0,0 +1,110 @@
1
+ {
2
+ "name": "@digital-realty/ix-account-switcher",
3
+ "description": "Webcomponent ix-account-switcher following open-wc recommendations",
4
+ "license": "MIT",
5
+ "author": "Digital Realty",
6
+ "version": "1.0.1",
7
+ "type": "module",
8
+ "main": "dist/index.js",
9
+ "module": "dist/index.js",
10
+ "exports": {
11
+ ".": "./dist/index.js",
12
+ "./ix-account-switcher.js": "./dist/ix-account-switcher.js",
13
+ "./dist/state/userProfile.js": "./dist/state/userProfile.js"
14
+ },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "scripts": {
19
+ "analyze": "cem analyze --litelement",
20
+ "start": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wds\"",
21
+ "build": "tsc && npm run analyze -- --exclude dist && rollup -c",
22
+ "prepublish": "tsc && npm run analyze -- --exclude dist",
23
+ "lint": "eslint --ext .ts,.html . --ignore-path .gitignore && prettier \"**/*.ts\" --check --ignore-path .gitignore",
24
+ "format": "eslint --ext .ts,.html . --fix --ignore-path .gitignore && prettier \"**/*.ts\" --write --ignore-path .gitignore",
25
+ "test": "tsc && wtr --coverage",
26
+ "test:watch": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wtr --watch\""
27
+ },
28
+ "dependencies": {
29
+ "@adobe/lit-mobx": "^2.2.2",
30
+ "@digital-realty/ix-dialog": "^1.0.24",
31
+ "@digital-realty/ix-field": "^1.0.5",
32
+ "@digital-realty/ix-icon-button": "^1.0.37",
33
+ "@digital-realty/ix-label-tag": "^2.1.8",
34
+ "@digital-realty/ix-select": "^1.0.36",
35
+ "@digital-realty/ix-tree": "^3.0.0",
36
+ "@digital-realty/theme": "^1.0.27",
37
+ "lit": "^2.0.2",
38
+ "mobx": "^6.12.3",
39
+ "mobx-persist-store": "^1.1.5"
40
+ },
41
+ "devDependencies": {
42
+ "@custom-elements-manifest/analyzer": "^0.4.17",
43
+ "@open-wc/eslint-config": "^9.2.1",
44
+ "@open-wc/testing": "^3.1.6",
45
+ "@rollup/plugin-replace": "^5.0.5",
46
+ "@typescript-eslint/eslint-plugin": "^5.48.0",
47
+ "@typescript-eslint/parser": "^5.48.0",
48
+ "@web/dev-server": "^0.1.34",
49
+ "@web/dev-server-rollup": "^0.6.2",
50
+ "@web/test-runner": "^0.14.0",
51
+ "concurrently": "^5.3.0",
52
+ "eslint": "^8.31.0",
53
+ "eslint-config-prettier": "^8.3.0",
54
+ "husky": "^4.3.8",
55
+ "lint-staged": "^10.5.4",
56
+ "prettier": "^2.4.1",
57
+ "rollup-plugin-minify-html-literals": "^1.2.6",
58
+ "rollup-plugin-summary": "^2.0.0",
59
+ "rollup-plugin-uglify": "^6.0.4",
60
+ "tslib": "^2.3.1",
61
+ "typescript": "^4.5.2"
62
+ },
63
+ "customElements": "custom-elements.json",
64
+ "eslintConfig": {
65
+ "parser": "@typescript-eslint/parser",
66
+ "extends": [
67
+ "@open-wc",
68
+ "prettier"
69
+ ],
70
+ "plugins": [
71
+ "@typescript-eslint"
72
+ ],
73
+ "rules": {
74
+ "no-unused-vars": "off",
75
+ "@typescript-eslint/no-unused-vars": [
76
+ "error"
77
+ ],
78
+ "import/no-unresolved": "off",
79
+ "import/extensions": [
80
+ "error",
81
+ "always",
82
+ {
83
+ "ignorePackages": true
84
+ }
85
+ ]
86
+ }
87
+ },
88
+ "prettier": {
89
+ "singleQuote": true,
90
+ "arrowParens": "avoid"
91
+ },
92
+ "husky": {
93
+ "hooks": {
94
+ "pre-commit": "lint-staged"
95
+ }
96
+ },
97
+ "lint-staged": {
98
+ "*.ts": [
99
+ "eslint --fix",
100
+ "prettier --write"
101
+ ]
102
+ },
103
+ "files": [
104
+ "/dist",
105
+ "!/dist/test",
106
+ "package.json",
107
+ "README.md",
108
+ "LICENSE"
109
+ ]
110
+ }