@operato/contact 8.0.0-beta.0 β†’ 8.0.0-beta.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.
@@ -0,0 +1,9 @@
1
+ {
2
+ "recommendations": [
3
+ "esbenp.prettier-vscode",
4
+ "runem.lit-plugin",
5
+ "dbaeumer.vscode-eslint"
6
+ ],
7
+ "unwantedRecommendations": [
8
+ ]
9
+ }
package/CHANGELOG.md CHANGED
@@ -3,6 +3,15 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [8.0.0-beta.1](https://github.com/hatiolab/operato/compare/v8.0.0-beta.0...v8.0.0-beta.1) (2025-01-08)
7
+
8
+
9
+ ### :bug: Bug Fix
10
+
11
+ * missing .npmignore ([be05985](https://github.com/hatiolab/operato/commit/be05985abfae4af53501f718dd52932099f7fbcb))
12
+
13
+
14
+
6
15
  ## [8.0.0-beta.0](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.56...v8.0.0-beta.0) (2025-01-07)
7
16
 
8
17
  **Note:** Version bump only for package @operato/contact
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@operato/contact",
3
3
  "description": "Webcomponent ox-contact following open-wc recommendations",
4
4
  "author": "heartyoh",
5
- "version": "8.0.0-beta.0",
5
+ "version": "8.0.0-beta.1",
6
6
  "main": "dist/src/index.js",
7
7
  "module": "dist/src/index.js",
8
8
  "license": "MIT",
@@ -58,8 +58,8 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "@material/web": "^2.0.0",
61
- "@operato/styles": "^8.0.0-beta.0",
62
- "@operato/utils": "^8.0.0-beta.0",
61
+ "@operato/styles": "^8.0.0-beta.1",
62
+ "@operato/utils": "^8.0.0-beta.1",
63
63
  "lit": "^3.1.2"
64
64
  },
65
65
  "devDependencies": {
@@ -94,5 +94,5 @@
94
94
  "prettier --write"
95
95
  ]
96
96
  },
97
- "gitHead": "c4e9cc245659d050a9ffd66542083a6daad4bcb9"
97
+ "gitHead": "d5b28a2e9deb632c0dc80132f6a7196dd6fe4220"
98
98
  }
package/.editorconfig DELETED
@@ -1,29 +0,0 @@
1
- # EditorConfig helps developers define and maintain consistent
2
- # coding styles between different editors and IDEs
3
- # editorconfig.org
4
-
5
- root = true
6
-
7
-
8
- [*]
9
-
10
- # Change these settings to your own preference
11
- indent_style = space
12
- indent_size = 2
13
-
14
- # We recommend you to keep these unchanged
15
- end_of_line = lf
16
- charset = utf-8
17
- trim_trailing_whitespace = true
18
- insert_final_newline = true
19
-
20
- [*.md]
21
- trim_trailing_whitespace = false
22
-
23
- [*.json]
24
- indent_size = 2
25
-
26
- [*.{html,js,md}]
27
- block_comment_start = /**
28
- block_comment = *
29
- block_comment_end = */
@@ -1,3 +0,0 @@
1
- module.exports = {
2
- stories: ['../dist/stories/**/*.stories.{js,md,mdx}'],
3
- };
@@ -1,52 +0,0 @@
1
- import { i18next } from '@operato/i18n'
2
-
3
- export const globalTypes = {
4
- locale: {
5
- name: 'Locale',
6
- description: 'Internationalization locale',
7
- toolbar: {
8
- icon: 'globe',
9
- items: [
10
- { value: 'en', right: 'πŸ‡ΊπŸ‡Έ', title: 'English' },
11
- { value: 'ko', right: 'πŸ‡°πŸ‡·', title: 'ν•œκ΅­μ–΄' },
12
- { value: 'zh', right: 'πŸ‡¨πŸ‡³', title: 'δΈ­ζ–‡' },
13
- { value: 'ja', right: 'πŸ‡―πŸ‡΅', title: 'ζ—₯本θͺž' },
14
- { value: 'ms', right: 'πŸ‡²πŸ‡Ύ', title: 'Bahasa Melayu' }
15
- ],
16
- showName: true
17
- }
18
- },
19
- theme: {
20
- name: 'Theme',
21
- description: 'Global theme for components',
22
- toolbar: {
23
- icon: 'paintbrush',
24
- items: [
25
- { value: 'light', title: 'Light' },
26
- { value: 'dark', title: 'Dark' }
27
- ],
28
- showName: true
29
- }
30
- }
31
- }
32
-
33
- export const decorators = [
34
- (Story, context) => {
35
- const { locale, theme } = context.globals
36
-
37
- if (locale) {
38
- i18next.changeLanguage(locale)
39
- }
40
-
41
- // Set the theme class for the document
42
- if (theme === 'dark') {
43
- document.documentElement.classList.add('dark')
44
- document.documentElement.classList.remove('light')
45
- } else {
46
- document.documentElement.classList.add('light')
47
- document.documentElement.classList.remove('dark')
48
- }
49
-
50
- return Story()
51
- }
52
- ]
@@ -1,8 +0,0 @@
1
- import { storybookPlugin } from '@web/dev-server-storybook';
2
- import baseConfig from '../web-dev-server.config.mjs';
3
-
4
- export default /** @type {import('@web/dev-server').DevServerConfig} */ ({
5
- ...baseConfig,
6
- open: '/',
7
- plugins: [storybookPlugin({ type: 'web-components' }), ...baseConfig.plugins],
8
- });
package/src/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export { OxContact } from './ox-contact.js'
2
- export { OxPfp } from './ox-pfp.js'
3
- export { OxPfpView } from './ox-pfp-view.js'
@@ -1,260 +0,0 @@
1
- import '@material/web/icon/icon.js'
2
- import './ox-pfp.js'
3
-
4
- import { html, css, LitElement, PropertyValues } from 'lit'
5
- import { customElement, property, state, query, queryAll } from 'lit/decorators.js'
6
- import { Contact, ContactField, ContactItem } from './ox-contact'
7
- import { ScrollbarStyles } from '@operato/styles'
8
- import { i18next } from '@operato/i18n'
9
- import { OxPfp } from './ox-pfp.js'
10
-
11
- @customElement('ox-contact-edit')
12
- export class OxContactEdit extends LitElement {
13
- static styles = [
14
- ScrollbarStyles,
15
- css`
16
- :host {
17
- display: block;
18
- padding: 25px;
19
- }
20
-
21
- input,
22
- select,
23
- textarea {
24
- padding: 8px;
25
- border-radius: 4px;
26
- border: 1px solid var(--md-sys-color-outline, #ccc);
27
- background-color: #fff;
28
- color: var(--md-sys-color-on-surface);
29
- font-size: 16px; /* for iPhone */
30
- box-shadow: 0 1px 1px 0px rgba(0, 0, 0, 0.1);
31
- transition:
32
- border-color 0.3s ease,
33
- box-shadow 0.3s ease;
34
- }
35
-
36
- input:focus,
37
- select:focus,
38
- textarea:focus {
39
- border-color: var(--md-sys-color-primary, #6200ea);
40
- box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
41
- outline: none;
42
- }
43
-
44
- :host > div {
45
- padding: 10px 0;
46
- display: block;
47
- border-bottom: 1px solid blue;
48
- }
49
-
50
- :host > div > div {
51
- padding: 4px 0;
52
- box-sizing: border-box;
53
-
54
- display: flex;
55
- flex-direction: row;
56
- gap: 10px;
57
- align-items: center;
58
- }
59
-
60
- :host > div > div:hover {
61
- position: relative;
62
- }
63
-
64
- [data-item='label'] {
65
- width: 100px;
66
- text-align: right;
67
- }
68
-
69
- [data-item='value'] {
70
- flex: 1;
71
- }
72
-
73
- :host > div[name] {
74
- display: flex;
75
- align-items: center;
76
- gap: 10px;
77
- font-weight: bold;
78
- font-size: 1.4em;
79
- }
80
-
81
- :host ox-pfp {
82
- display: inline-block;
83
- width: 100px;
84
- height: 100px;
85
- }
86
-
87
- :host > div[name] > div[name-content] {
88
- flex: 1;
89
-
90
- display: grid;
91
- grid-template-columns: minmax(auto, 160px) 1fr;
92
- gap: var(--spacing-medium);
93
- align-items: center;
94
-
95
- span {
96
- text-align: right;
97
- }
98
- }
99
-
100
- div[field] {
101
- display: flex;
102
- flex-direction: row;
103
- align-items: center;
104
- gap: 10px;
105
- }
106
-
107
- div[field] > span {
108
- width: 100px;
109
- text-align: right;
110
- }
111
-
112
- div[field] > input {
113
- flex: 1;
114
- }
115
-
116
- textarea {
117
- width: 100%;
118
- min-height: 100px;
119
- box-sizing: border-box;
120
- resize: none;
121
- }
122
- `
123
- ]
124
-
125
- @property({ type: Object }) contact: Contact = {}
126
-
127
- @state() private stageContact: Contact = JSON.parse(JSON.stringify(this.contact))
128
-
129
- @query('#name') name!: HTMLTextAreaElement
130
- @query('#company') company!: HTMLTextAreaElement
131
- @query('#note') note!: HTMLTextAreaElement
132
- @query('ox-pfp') pfp!: OxPfp
133
- @queryAll('[item-field]') fields!: NodeListOf<HTMLDivElement>
134
-
135
- render() {
136
- const { profile, items = [], name, company, note } = this.stageContact || {}
137
- var sorted: { [type: string]: ContactItem[] } = {}
138
-
139
- items.forEach(item => {
140
- if (!sorted[item.type as string]) {
141
- sorted[item.type] = [item]
142
- } else {
143
- sorted[item.type as string].push(item)
144
- }
145
- })
146
-
147
- return html`
148
- <div name>
149
- <ox-pfp .profile=${profile} .name=${name}></ox-pfp>
150
-
151
- <div name-content>
152
- <span>${i18next.t('label.name')}</span>
153
- <input type="text" id="name" .value=${name ?? ''} @change=${(e: Event) => this.buildStageContact()} />
154
- <span>${i18next.t('label.company')}</span>
155
- <input type="text" id="company" .value=${company ?? ''} @change=${(e: Event) => this.buildStageContact()} />
156
- </div>
157
- </div>
158
- ${['department', 'email', 'phone', 'address'].map(type => {
159
- var items = [...(sorted[type] || []), { type: type as ContactField, label: 'work', value: '' }]
160
-
161
- return html`
162
- <div data-type=${type}>
163
- ${type}
164
- ${items.map(
165
- item =>
166
- html`<div @change=${(e: Event) => this.onChangeItem(e, item)} .item=${item} item-field>
167
- ${item.value
168
- ? html`<md-icon
169
- @click=${() => {
170
- item.value = ''
171
- this.buildStageContact()
172
- }}
173
- >cancel</md-icon
174
- >`
175
- : html`<md-icon></md-icon>`}
176
- <select .value=${item.label} data-item="label">
177
- ${['home', 'work', 'other', 'mobile'].map(
178
- option => html` <option value=${option} ?selected=${option === item.label}>${option}</option>`
179
- )}
180
- </select>
181
- <input type="text" .value=${item.value} data-item="value" />
182
- </div>`
183
- )}
184
- </div>
185
- `
186
- })}
187
- <div note>
188
- note
189
- <textarea id="note" .value=${note || ''} @change=${() => this.buildStageContact()}></textarea>
190
- </div>
191
- `
192
- }
193
-
194
- updated(changes: PropertyValues<this>) {
195
- if (changes.has('contact')) {
196
- this.stageContact = JSON.parse(JSON.stringify(this.contact))
197
- }
198
- }
199
-
200
- buildItems() {
201
- const items: ContactItem[] = []
202
-
203
- this.fields.forEach(fieldElement => {
204
- const item = (fieldElement as any).item
205
- if (item.value) {
206
- items.push(item)
207
- }
208
- })
209
-
210
- return items
211
- }
212
-
213
- buildStageContact() {
214
- this.stageContact = {
215
- ...this.stageContact,
216
- profile: this.pfp.profile,
217
- name: this.name.value,
218
- company: this.company.value,
219
- note: this.note.value,
220
- items: this.buildItems()
221
- }
222
- }
223
-
224
- onChangeItem(e: Event, item: ContactItem) {
225
- const target = e.currentTarget as HTMLElement
226
- const labelElement = target.querySelector('[data-item="label"]') as HTMLSelectElement
227
- const valueElement = target.querySelector('[data-item="value"]') as HTMLInputElement
228
-
229
- item.label = labelElement.value
230
- item.value = valueElement.value
231
-
232
- if (e.target === valueElement || item.value) {
233
- this.buildStageContact()
234
- }
235
- }
236
-
237
- save() {
238
- this.buildStageContact()
239
-
240
- this.dispatchEvent(
241
- new CustomEvent('edit-done', {
242
- detail: this.stageContact
243
- })
244
- )
245
- }
246
-
247
- cancel() {
248
- this.dispatchEvent(
249
- new CustomEvent('edit-cancel', {
250
- detail: this.stageContact
251
- })
252
- )
253
- }
254
-
255
- reset() {
256
- this.buildStageContact()
257
-
258
- this.stageContact = JSON.parse(JSON.stringify(this.contact))
259
- }
260
- }
@@ -1,189 +0,0 @@
1
- import './ox-pfp-view.js'
2
-
3
- import { html, css, LitElement } from 'lit'
4
- import { customElement, property } from 'lit/decorators.js'
5
- import { Contact, ContactField, ContactItem } from './ox-contact'
6
-
7
- @customElement('ox-contact-view')
8
- export class OxContactView extends LitElement {
9
- static styles = css`
10
- :host {
11
- display: block;
12
- --md-icon-size: 16px;
13
-
14
- color: var(--md-sys-color-on-surface);
15
- background-color: var(--md-sys-color-surface);
16
- }
17
-
18
- :host > div {
19
- padding: var(--spacing-medium, 8px);
20
- display: block;
21
- border-bottom: 1px solid rgba(0, 0, 0, 0.1);
22
- font-size: 0.9em;
23
- text-transform: capitalize;
24
- }
25
-
26
- :host > div > div {
27
- padding: 4px 0;
28
- box-sizing: border-box;
29
-
30
- display: flex;
31
- flex-direction: row;
32
- gap: 10px;
33
- }
34
-
35
- :host > div > div:hover {
36
- position: relative;
37
- }
38
-
39
- :host > div > div:hover::before {
40
- content: '';
41
- display: block;
42
- position: absolute;
43
- text-align: left;
44
- line-height: 24px;
45
- top: 0;
46
- right: 0;
47
- width: 100%;
48
- height: 100%;
49
- opacity: 0.15;
50
- background-image: linear-gradient(var(--md-sys-color-primary, gray), var(--md-sys-color-primary, gray));
51
- }
52
-
53
- [data-item='label'] {
54
- width: 80px;
55
- text-align: right;
56
- color: var(--md-sys-color-primary, #017e7f);
57
- }
58
-
59
- [data-item='value'] {
60
- flex: 1;
61
- text-transform: none;
62
- }
63
-
64
- :host > div[name] {
65
- display: flex;
66
- align-items: center;
67
- gap: 15px;
68
- font-weight: bold;
69
- font-size: 1.4em;
70
- }
71
-
72
- :host ox-pfp-view {
73
- display: inline-block;
74
-
75
- --ox-pfp-size: 75px;
76
- }
77
-
78
- :host > div[name] > div[name-content] {
79
- flex: 1;
80
-
81
- display: flex;
82
- flex-direction: column;
83
- }
84
-
85
- div[data-type='email'] md-icon::before {
86
- content: 'mail_outline';
87
- }
88
-
89
- div[data-type='phone'] md-icon::before {
90
- content: 'phone';
91
- }
92
-
93
- div[data-type='address'] md-icon::before {
94
- content: 'place';
95
- }
96
-
97
- div[data-type='department'] md-icon::before {
98
- content: 'diversity_3';
99
- }
100
-
101
- div[data-type='company'] md-icon::before {
102
- content: 'business';
103
- }
104
-
105
- div[data-type='etc'] md-icon::before {
106
- content: 'feed';
107
- }
108
-
109
- div[note] md-icon::before {
110
- content: 'subject';
111
- }
112
-
113
- :host > div > [name-content] {
114
- gap: 3px;
115
- }
116
-
117
- div md-icon {
118
- position: relative;
119
- top: 3px;
120
- margin-right: 3px;
121
- opacity: 0.5;
122
- color: var(--md-sys-color-on-primary-container, #333);
123
- }
124
-
125
- [name-content] div {
126
- color: var(--md-sys-color-on-primary-container, #333);
127
- font-size: 1.2em;
128
- }
129
-
130
- [name-content] [company] {
131
- color: var(--md-sys-color-on-secondary-container, #666);
132
- font-weight: normal;
133
- font-size: 0.9em;
134
- }
135
- `
136
-
137
- @property({ type: Object }) contact: Contact = {}
138
-
139
- render() {
140
- const { profile, items = [], name, company, note } = this.contact || {}
141
- var sorted: { [type: string]: ContactItem[] } = {}
142
-
143
- items.forEach(item => {
144
- if (!sorted[item.type as string]) {
145
- sorted[item.type] = [item]
146
- } else {
147
- sorted[item.type as string].push(item)
148
- }
149
- })
150
-
151
- return html`
152
- <div name>
153
- <ox-pfp-view .profile=${profile} .name=${name}></ox-pfp-view>
154
-
155
- <div name-content>
156
- <div>
157
- <span data-item="value">${name}</span>
158
- </div>
159
- <div company>
160
- <span data-item="value">${company}</span>
161
- </div>
162
- </div>
163
- </div>
164
-
165
- ${['department', 'email', 'phone', 'address', 'company', 'etc']
166
- .map(type => sorted[type])
167
- .filter(items => items && items.length > 0)
168
- .map(
169
- items =>
170
- html`<div data-type=${items[0].type}>
171
- <md-icon></md-icon>
172
- ${items[0].type}
173
- ${items.map(
174
- item =>
175
- html`<div>
176
- <label data-item="label"> ${item.label}</label>
177
- <span data-item="value">${item.value}</span>
178
- </div>`
179
- )}
180
- </div>`
181
- )}
182
- <div note>
183
- <md-icon></md-icon>
184
- note
185
- <div>${note || ''}</div>
186
- </div>
187
- `
188
- }
189
- }