@progressive-development/pd-contact 0.9.1 → 1.0.0
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 +21 -2
- package/README.md +29 -56
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/pd-contact/PdContact.d.ts +39 -24
- package/dist/pd-contact/PdContact.d.ts.map +1 -1
- package/dist/pd-contact/PdContact.js +521 -74
- package/dist/pd-contact/pd-contact-edit.stories.d.ts +51 -16
- package/dist/pd-contact/pd-contact-edit.stories.d.ts.map +1 -1
- package/dist/pd-contact/pd-contact-view.stories.d.ts +53 -11
- package/dist/pd-contact/pd-contact-view.stories.d.ts.map +1 -1
- package/dist/pd-page/dist/pd-socialmedia/PdSocialmedia.js +426 -0
- package/dist/pd-page/dist/pd-socialmedia/pd-socialmedia-model.js +240 -0
- package/dist/pd-page/dist/pd-socialmedia.js +7 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -6
|
@@ -1,18 +1,53 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/web-components';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/web-components-vite';
|
|
2
|
+
import { PdContactData } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Story arguments interface for pd-contact (edit mode).
|
|
5
|
+
* Maps to the component's public API when used as an editable form.
|
|
6
|
+
*/
|
|
7
|
+
interface PdContactEditArgs {
|
|
8
|
+
/** List of input fields to display (empty = all fields) */
|
|
9
|
+
inputFields: string[];
|
|
10
|
+
/** List of required field keys for validation */
|
|
11
|
+
requiredFields: string[];
|
|
12
|
+
/** Show property date selection field */
|
|
13
|
+
withPropertyDate: boolean;
|
|
14
|
+
/** Pre-populated contact data */
|
|
15
|
+
contact?: PdContactData;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* ## pd-contact (Edit Mode)
|
|
19
|
+
*
|
|
20
|
+
* Contact form component for creating and editing contact information with
|
|
21
|
+
* built-in validation support.
|
|
22
|
+
*
|
|
23
|
+
* ### Features
|
|
24
|
+
* - Private/Business contact type toggle via radio group
|
|
25
|
+
* - Configurable visible fields via `inputFields` array
|
|
26
|
+
* - Required field validation via `requiredFields` array
|
|
27
|
+
* - Optional property/building year selection
|
|
28
|
+
* - Auto-complete hints for browser autofill
|
|
29
|
+
* - Integration with pd-form-container for validation lifecycle
|
|
30
|
+
*
|
|
31
|
+
* ### Form Methods
|
|
32
|
+
* - `triggerValidate()` — triggers validation and returns Promise<boolean>
|
|
33
|
+
* - `getValues()` — returns current form data as PdContactData
|
|
34
|
+
* - `valid` — getter for current validation state
|
|
35
|
+
*/
|
|
36
|
+
declare const meta: Meta<PdContactEditArgs>;
|
|
7
37
|
export default meta;
|
|
8
|
-
type Story = StoryObj
|
|
9
|
-
|
|
10
|
-
export declare const
|
|
11
|
-
|
|
12
|
-
export declare const
|
|
13
|
-
|
|
14
|
-
export declare const
|
|
15
|
-
|
|
16
|
-
export declare const
|
|
17
|
-
|
|
38
|
+
type Story = StoryObj<PdContactEditArgs>;
|
|
39
|
+
/** Default empty contact form with all fields visible. Interactive via Controls panel. */
|
|
40
|
+
export declare const Default: Story;
|
|
41
|
+
/** Contact form pre-filled with private person data (first name, last name, address). */
|
|
42
|
+
export declare const PrepopulatedPrivate: Story;
|
|
43
|
+
/** Contact form pre-filled with company data (company name, VAT number). */
|
|
44
|
+
export declare const PrepopulatedCompany: Story;
|
|
45
|
+
/** Form with all fields marked as required — shows validation indicators. */
|
|
46
|
+
export declare const AllFieldsRequired: Story;
|
|
47
|
+
/** Demonstrates showing only a subset of fields using the inputFields array. */
|
|
48
|
+
export declare const CustomFieldSelection: Story;
|
|
49
|
+
/** Form with the optional property/building year selection field enabled. */
|
|
50
|
+
export declare const WithPropertyDate: Story;
|
|
51
|
+
/** CSS Custom Properties — Branded and Redesigned variants. */
|
|
52
|
+
export declare const CustomStyling: Story;
|
|
18
53
|
//# sourceMappingURL=pd-contact-edit.stories.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pd-contact-edit.stories.d.ts","sourceRoot":"","sources":["../../src/pd-contact/pd-contact-edit.stories.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pd-contact-edit.stories.d.ts","sourceRoot":"","sources":["../../src/pd-contact/pd-contact-edit.stories.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAGrE,OAAO,EAWL,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAErB,OAAO,iBAAiB,CAAC;AACzB,OAAO,6CAA6C,CAAC;AAMrD;;;GAGG;AACH,UAAU,iBAAiB;IACzB,2DAA2D;IAC3D,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,iDAAiD;IACjD,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,yCAAyC;IACzC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iCAAiC;IACjC,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAuED;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,iBAAiB,CAmFjC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAAC;AAMzC,0FAA0F;AAC1F,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAMjC,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,EAAE,KAIjC,CAAC;AAMF,4EAA4E;AAC5E,eAAO,MAAM,mBAAmB,EAAE,KAIjC,CAAC;AAMF,6EAA6E;AAC7E,eAAO,MAAM,iBAAiB,EAAE,KAI/B,CAAC;AAMF,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,EAAE,KAoClC,CAAC;AAMF,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,EAAE,KAQ9B,CAAC;AAMF,+DAA+D;AAC/D,eAAO,MAAM,aAAa,EAAE,KAuE3B,CAAC"}
|
|
@@ -1,13 +1,55 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/web-components';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/web-components-vite';
|
|
2
|
+
import { PdContactData } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Story arguments interface for pd-contact (view mode).
|
|
5
|
+
* Maps to the component's public API when used as a read-only display.
|
|
6
|
+
*/
|
|
7
|
+
interface PdContactViewArgs {
|
|
8
|
+
/** Show summary view (read-only display) */
|
|
9
|
+
summary: boolean;
|
|
10
|
+
/** Render phone and email as clickable links */
|
|
11
|
+
phoneMailLink: boolean;
|
|
12
|
+
/** View type: 'detail' or 'card' (business card) */
|
|
13
|
+
viewType: "detail" | "card";
|
|
14
|
+
/** Card layout mode: 'auto', 'horizontal', or 'vertical' */
|
|
15
|
+
cardLayout: "auto" | "horizontal" | "vertical";
|
|
16
|
+
/** Contact data to display */
|
|
17
|
+
contact: PdContactData;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* ## pd-contact (View Mode)
|
|
21
|
+
*
|
|
22
|
+
* Contact display component for showing contact information in read-only mode.
|
|
23
|
+
* Supports two view types: detail (structured list) and card (business card layout).
|
|
24
|
+
*
|
|
25
|
+
* ### Features
|
|
26
|
+
* - Detail view with structured address, phone, email, and social media display
|
|
27
|
+
* - Business card view with logo, responsive layout, and social media integration
|
|
28
|
+
* - Private and business contact support (company name, VAT number)
|
|
29
|
+
* - Clickable phone/email links with icons
|
|
30
|
+
* - Card view with container-query-based responsive layout (auto/horizontal/vertical)
|
|
31
|
+
* - CSS custom properties for full visual customization
|
|
32
|
+
* - CSS part `card-wrapper` for external card styling
|
|
33
|
+
*
|
|
34
|
+
* ### View Types
|
|
35
|
+
* - `detail` — Traditional structured contact display (default)
|
|
36
|
+
* - `card` — Business card layout with logo and social media
|
|
37
|
+
*/
|
|
38
|
+
declare const meta: Meta<PdContactViewArgs>;
|
|
7
39
|
export default meta;
|
|
8
|
-
type Story = StoryObj
|
|
9
|
-
|
|
10
|
-
export declare const
|
|
11
|
-
|
|
12
|
-
export declare const
|
|
40
|
+
type Story = StoryObj<PdContactViewArgs>;
|
|
41
|
+
/** Default contact view showing a private person. Interactive via Controls panel. */
|
|
42
|
+
export declare const Default: Story;
|
|
43
|
+
/** All detail view variants at a glance: private, company, with title/social media. */
|
|
44
|
+
export declare const AllDetailVariants: Story;
|
|
45
|
+
/** Detail view with titleName as header, website link, and social media integration. */
|
|
46
|
+
export declare const DetailWithTitleAndSocialMedia: Story;
|
|
47
|
+
/** Business card with auto-responsive layout — switches between horizontal (>500px) and vertical (<500px). */
|
|
48
|
+
export declare const CardDefault: Story;
|
|
49
|
+
/** Card view with all three layout modes side by side. */
|
|
50
|
+
export declare const CardLayouts: Story;
|
|
51
|
+
/** Card view with different content configurations: without logo, without social media, minimal. */
|
|
52
|
+
export declare const CardContentVariations: Story;
|
|
53
|
+
/** CSS Custom Properties — Branded and Redesigned card variants. */
|
|
54
|
+
export declare const CustomStyling: Story;
|
|
13
55
|
//# sourceMappingURL=pd-contact-view.stories.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pd-contact-view.stories.d.ts","sourceRoot":"","sources":["../../src/pd-contact/pd-contact-view.stories.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pd-contact-view.stories.d.ts","sourceRoot":"","sources":["../../src/pd-contact/pd-contact-view.stories.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAGrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,iBAAiB,CAAC;AAMzB;;;GAGG;AACH,UAAU,iBAAiB;IACzB,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,gDAAgD;IAChD,aAAa,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC5B,4DAA4D;IAC5D,UAAU,EAAE,MAAM,GAAG,YAAY,GAAG,UAAU,CAAC;IAC/C,8BAA8B;IAC9B,OAAO,EAAE,aAAa,CAAC;CACxB;AAyED;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,iBAAiB,CAgFjC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAAC;AAMzC,qFAAqF;AACrF,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAMjC,uFAAuF;AACvF,eAAO,MAAM,iBAAiB,EAAE,KA0C/B,CAAC;AAMF,wFAAwF;AACxF,eAAO,MAAM,6BAA6B,EAAE,KAY3C,CAAC;AAMF,8GAA8G;AAC9G,eAAO,MAAM,WAAW,EAAE,KAazB,CAAC;AAMF,0DAA0D;AAC1D,eAAO,MAAM,WAAW,EAAE,KAwCzB,CAAC;AAMF,oGAAoG;AACpG,eAAO,MAAM,qBAAqB,EAAE,KA+CnC,CAAC;AAMF,oEAAoE;AACpE,eAAO,MAAM,aAAa,EAAE,KAuF3B,CAAC"}
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import { css, LitElement, html, nothing } from 'lit';
|
|
2
|
+
import { property, state, query } from 'lit/decorators.js';
|
|
3
|
+
import { localized, msg } from '@lit/localize';
|
|
4
|
+
import '@progressive-development/pd-forms/pd-suggestion-box';
|
|
5
|
+
import '@progressive-development/pd-forms/pd-form-row';
|
|
6
|
+
import '@progressive-development/pd-forms/pd-button';
|
|
7
|
+
import '@progressive-development/pd-forms/pd-input';
|
|
8
|
+
import '@progressive-development/pd-icon/pd-icon';
|
|
9
|
+
import { SOCIAL_PROVIDERS } from './pd-socialmedia-model.js';
|
|
10
|
+
import { pdIcons } from '@progressive-development/pd-icon';
|
|
11
|
+
|
|
12
|
+
var __defProp = Object.defineProperty;
|
|
13
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
14
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
15
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
16
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
17
|
+
if (decorator = decorators[i])
|
|
18
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
19
|
+
if (kind && result) __defProp(target, key, result);
|
|
20
|
+
return result;
|
|
21
|
+
};
|
|
22
|
+
let PdSocialmedia = class extends LitElement {
|
|
23
|
+
constructor() {
|
|
24
|
+
super(...arguments);
|
|
25
|
+
this.summary = false;
|
|
26
|
+
this.initItems = [];
|
|
27
|
+
this.providers = SOCIAL_PROVIDERS;
|
|
28
|
+
this.showLabelBelowIcon = false;
|
|
29
|
+
this.openLinksInSameTab = false;
|
|
30
|
+
this._pendingAddProvider = null;
|
|
31
|
+
this._currentInputValue = null;
|
|
32
|
+
this._editItems = [];
|
|
33
|
+
this._openAddSuggestItem = (e) => {
|
|
34
|
+
const metaProvider = e.detail;
|
|
35
|
+
const providerId = metaProvider?.id;
|
|
36
|
+
if (!providerId) return;
|
|
37
|
+
this._pendingAddProvider = metaProvider;
|
|
38
|
+
this._currentInputValue = null;
|
|
39
|
+
};
|
|
40
|
+
this._closeAddSuggestedItem = (_e) => {
|
|
41
|
+
this._pendingAddProvider = null;
|
|
42
|
+
this._currentInputValue = null;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
willUpdate(_changedProperties) {
|
|
46
|
+
if (_changedProperties.has("initItems")) {
|
|
47
|
+
this._editItems = [...this.initItems || []];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// --- Public API helpers ---
|
|
51
|
+
addItem(entry) {
|
|
52
|
+
const next = [...this._editItems, entry];
|
|
53
|
+
this._editItems = next;
|
|
54
|
+
this.emitChange();
|
|
55
|
+
}
|
|
56
|
+
removeIndex(index) {
|
|
57
|
+
const next = this._editItems.slice();
|
|
58
|
+
next.splice(index, 1);
|
|
59
|
+
this._editItems = next;
|
|
60
|
+
this.emitChange();
|
|
61
|
+
}
|
|
62
|
+
get value() {
|
|
63
|
+
return this._editItems;
|
|
64
|
+
}
|
|
65
|
+
// --- Render ---
|
|
66
|
+
render() {
|
|
67
|
+
return this.summary ? this.renderView() : this.renderEdit();
|
|
68
|
+
}
|
|
69
|
+
renderView() {
|
|
70
|
+
const items = this._editItems ?? [];
|
|
71
|
+
const empty = items.length === 0;
|
|
72
|
+
return html`
|
|
73
|
+
<ul
|
|
74
|
+
class="view-list"
|
|
75
|
+
aria-label="${msg("Social-Media-Profile", {
|
|
76
|
+
id: "pd.socialmedia.aria.label"
|
|
77
|
+
})}"
|
|
78
|
+
>
|
|
79
|
+
${empty ? html`<li>
|
|
80
|
+
<span
|
|
81
|
+
>${msg("Keine Einträge", { id: "pd.socialmedia.empty" })}</span
|
|
82
|
+
>
|
|
83
|
+
</li>` : items.map((item) => {
|
|
84
|
+
const provider = this._findProvider(item.providerId);
|
|
85
|
+
const label = provider?.label ?? item.label ?? item.providerId;
|
|
86
|
+
const href = this._toUrl(provider, item.value);
|
|
87
|
+
const title = `${label}: ${href}`;
|
|
88
|
+
const content = html`
|
|
89
|
+
<div class="icon-tile" title=${title}>
|
|
90
|
+
${provider?.icon ?? "link"}
|
|
91
|
+
${this.showLabelBelowIcon ? html`<div class="icon-label">${label}</div>` : nothing}
|
|
92
|
+
</div>
|
|
93
|
+
`;
|
|
94
|
+
return html` <li>
|
|
95
|
+
${href ? html` <a
|
|
96
|
+
href=${href}
|
|
97
|
+
target=${this.openLinksInSameTab ? "_self" : "_blank"}
|
|
98
|
+
rel="noopener noreferrer"
|
|
99
|
+
aria-label=${label}
|
|
100
|
+
>${content}</a
|
|
101
|
+
>` : html`<div class="icon-tile" aria-label=${label}>
|
|
102
|
+
${content}
|
|
103
|
+
</div>`}
|
|
104
|
+
</li>`;
|
|
105
|
+
})}
|
|
106
|
+
</ul>
|
|
107
|
+
`;
|
|
108
|
+
}
|
|
109
|
+
renderEdit() {
|
|
110
|
+
return html`
|
|
111
|
+
<div class="edit">
|
|
112
|
+
<div>
|
|
113
|
+
<pd-form-row>
|
|
114
|
+
<pd-suggestion-box
|
|
115
|
+
id="suggesBoxId"
|
|
116
|
+
span="full"
|
|
117
|
+
label="${msg("Neuer Eintrag", {
|
|
118
|
+
id: "pd.socialmedia.new.entry"
|
|
119
|
+
})}"
|
|
120
|
+
minCharsToSearch="1"
|
|
121
|
+
placeholder="${msg("Socialmedia eingeben...", {
|
|
122
|
+
id: "pd.socialmedia.placeholder"
|
|
123
|
+
})}"
|
|
124
|
+
.callFunction="${this._searchSocialProviders.bind(this)}"
|
|
125
|
+
@element-selected="${this._openAddSuggestItem}"
|
|
126
|
+
@element-unselected="${this._closeAddSuggestedItem}"
|
|
127
|
+
@pd-form-element-change="${(e) => e.stopPropagation()}"
|
|
128
|
+
@pd-form-element-register="${(e) => e.stopPropagation()}"
|
|
129
|
+
@pd-form-element-unregister="${(e) => e.stopPropagation()}"
|
|
130
|
+
></pd-suggestion-box>
|
|
131
|
+
</pd-form-row>
|
|
132
|
+
${this._pendingAddProvider !== null ? this._renderAddRow() : ""}
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
<div class="edit-list">
|
|
136
|
+
${this._editItems?.map((item, i) => {
|
|
137
|
+
const meta = this._findProvider(item.providerId);
|
|
138
|
+
const label = meta?.label ?? item.providerId;
|
|
139
|
+
return html`
|
|
140
|
+
<div class="row">
|
|
141
|
+
<div class="provider">
|
|
142
|
+
${meta?.icon ?? "link"}<span>${label}</span>
|
|
143
|
+
</div>
|
|
144
|
+
<div class="value">${item.value}</div>
|
|
145
|
+
<button
|
|
146
|
+
class="btn-icon danger"
|
|
147
|
+
@click=${() => this.removeIndex(i)}
|
|
148
|
+
aria-label="${msg("Eintrag löschen", {
|
|
149
|
+
id: "pd.socialmedia.delete"
|
|
150
|
+
})}"
|
|
151
|
+
>
|
|
152
|
+
<pd-icon icon="${pdIcons.ICON_DELETE_NEW}"></pd-icon>
|
|
153
|
+
</button>
|
|
154
|
+
</div>
|
|
155
|
+
`;
|
|
156
|
+
})}
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
`;
|
|
160
|
+
}
|
|
161
|
+
_renderAddRow() {
|
|
162
|
+
const provider = this._pendingAddProvider;
|
|
163
|
+
if (!provider) return html`<p>! Missing Provider !</p>`;
|
|
164
|
+
return html`
|
|
165
|
+
<pd-form-row class="no-padding">
|
|
166
|
+
<pd-input
|
|
167
|
+
id="scValueId"
|
|
168
|
+
maxlength="250"
|
|
169
|
+
span="full"
|
|
170
|
+
label="${`${provider.icon} ${provider.label}`}"
|
|
171
|
+
helperTxt="${`Pattern: ${provider.pattern}`}"
|
|
172
|
+
placeholder="${provider.placeholder || `Eingabe ${provider.inputKind}`}"
|
|
173
|
+
valueName="providerValue"
|
|
174
|
+
@pd-form-element-change="${(e) => {
|
|
175
|
+
this._currentInputValue = e.detail.value;
|
|
176
|
+
e.stopPropagation();
|
|
177
|
+
}}"
|
|
178
|
+
@pd-form-element-register="${(e) => e.stopPropagation()}"
|
|
179
|
+
@pd-form-element-unregister="${(e) => e.stopPropagation()}"
|
|
180
|
+
required
|
|
181
|
+
></pd-input>
|
|
182
|
+
</pd-form-row>
|
|
183
|
+
<div class="current-input-url">
|
|
184
|
+
URL:
|
|
185
|
+
<a
|
|
186
|
+
target="_blank"
|
|
187
|
+
href="${this._toUrl(provider, this._currentInputValue || "") || ""}"
|
|
188
|
+
>${this._toUrl(provider, this._currentInputValue || "")}</a
|
|
189
|
+
>
|
|
190
|
+
</div>
|
|
191
|
+
|
|
192
|
+
<div class="add-button-group">
|
|
193
|
+
<pd-button
|
|
194
|
+
icon="${pdIcons.ICON_CLOSE}"
|
|
195
|
+
text="${msg("Abbrechen", { id: "pd.socialmedia.cancel" })}"
|
|
196
|
+
@button-clicked="${() => {
|
|
197
|
+
this._currentInputValue = null;
|
|
198
|
+
this._pendingAddProvider = null;
|
|
199
|
+
this._suggestForm?.reset();
|
|
200
|
+
}}"
|
|
201
|
+
></pd-button>
|
|
202
|
+
<pd-button
|
|
203
|
+
icon="${pdIcons.ICON_SYNC}"
|
|
204
|
+
text="${msg("Speichern", { id: "pd.socialmedia.save" })}"
|
|
205
|
+
@button-clicked="${() => {
|
|
206
|
+
this.addItem({
|
|
207
|
+
providerId: this._pendingAddProvider?.id || "",
|
|
208
|
+
value: this._currentInputValue || ""
|
|
209
|
+
});
|
|
210
|
+
this._currentInputValue = null;
|
|
211
|
+
this._pendingAddProvider = null;
|
|
212
|
+
this._suggestForm?.reset();
|
|
213
|
+
}}"
|
|
214
|
+
></pd-button>
|
|
215
|
+
</div>
|
|
216
|
+
`;
|
|
217
|
+
}
|
|
218
|
+
// --- Suggest Box Helper
|
|
219
|
+
async _searchSocialProviders(input) {
|
|
220
|
+
const includedIds = this._editItems.map((item) => item.providerId);
|
|
221
|
+
return Promise.resolve(
|
|
222
|
+
SOCIAL_PROVIDERS.filter(
|
|
223
|
+
(v) => !includedIds.includes(v.id) && (v.label.toLowerCase().includes(input.toLowerCase()) || v.category.toLowerCase().includes(input.toLowerCase()) || v.aliases?.join()?.toLowerCase().includes(input.toLowerCase()))
|
|
224
|
+
).map((e) => ({
|
|
225
|
+
id: e.id,
|
|
226
|
+
name: `${e.icon || ""} ${e.label || "--"}`,
|
|
227
|
+
subInfo: html`<b><em>${e.category || "--"}:</em></b> ${e.aliases?.join(
|
|
228
|
+
","
|
|
229
|
+
) || e.id}`,
|
|
230
|
+
objectValue: e
|
|
231
|
+
}))
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
// --- Private helpers ---
|
|
235
|
+
_findProvider(id) {
|
|
236
|
+
if (!id) return void 0;
|
|
237
|
+
return this.providers?.find((p) => p.id === id);
|
|
238
|
+
}
|
|
239
|
+
_toUrl(meta, raw) {
|
|
240
|
+
const v = raw?.trim();
|
|
241
|
+
if (!v) return null;
|
|
242
|
+
if (meta?.toUrl) return meta.toUrl(v);
|
|
243
|
+
if (/^https?:\/\//i.test(v)) return v;
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
emitChange() {
|
|
247
|
+
this.dispatchEvent(
|
|
248
|
+
new CustomEvent("items-change", {
|
|
249
|
+
detail: { items: this._editItems },
|
|
250
|
+
bubbles: true,
|
|
251
|
+
composed: true
|
|
252
|
+
})
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
PdSocialmedia.styles = css`
|
|
257
|
+
:host {
|
|
258
|
+
display: block;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/* View: icons row */
|
|
262
|
+
.view-list {
|
|
263
|
+
display: flex;
|
|
264
|
+
flex-wrap: wrap;
|
|
265
|
+
gap: var(--pd-gap, 0.5rem);
|
|
266
|
+
align-items: center;
|
|
267
|
+
list-style: none;
|
|
268
|
+
padding: 0;
|
|
269
|
+
margin: 0;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.view-list li:hover .icon-tile .icon-label {
|
|
273
|
+
color: var(--pd-default-hover-col);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.icon-tile {
|
|
277
|
+
display: inline-flex;
|
|
278
|
+
flex-direction: column;
|
|
279
|
+
align-items: center;
|
|
280
|
+
justify-content: center;
|
|
281
|
+
gap: 0.25rem;
|
|
282
|
+
padding: 0.25rem;
|
|
283
|
+
min-width: 2.25rem;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.icon-tile a,
|
|
287
|
+
.icon-tile button[role="link"] {
|
|
288
|
+
display: inline-flex;
|
|
289
|
+
align-items: center;
|
|
290
|
+
justify-content: center;
|
|
291
|
+
text-decoration: none;
|
|
292
|
+
outline: none;
|
|
293
|
+
border: none;
|
|
294
|
+
background: none;
|
|
295
|
+
cursor: pointer;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.icon-label {
|
|
299
|
+
font-size: 0.75rem;
|
|
300
|
+
line-height: 1;
|
|
301
|
+
color: var(--pd-sc-text-muted, var(--pd-default-disabled-col));
|
|
302
|
+
text-align: center;
|
|
303
|
+
max-width: 6rem;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/* Edit: list */
|
|
307
|
+
.edit {
|
|
308
|
+
display: flex;
|
|
309
|
+
flex-direction: column;
|
|
310
|
+
gap: 1rem;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.edit-list {
|
|
314
|
+
display: flex;
|
|
315
|
+
flex-direction: column;
|
|
316
|
+
gap: 0.1rem;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.row {
|
|
320
|
+
display: grid;
|
|
321
|
+
grid-template-columns: auto 1fr auto;
|
|
322
|
+
align-items: center;
|
|
323
|
+
gap: 0;
|
|
324
|
+
padding: 0 var(--pd-spacing-xs);
|
|
325
|
+
border-radius: var(--pd-radius-md);
|
|
326
|
+
max-width: 500px;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.edit-list > .row:nth-child(odd) {
|
|
330
|
+
background: var(--pd-sc-row-bg-odd-col, var(--pd-default-bg-light-col));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.edit-list > .row:nth-child(even) {
|
|
334
|
+
background: var(--pd-sc-row-bg-even-col, var(--pd-default-bg-dark-col));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.edit-list > .row:hover {
|
|
338
|
+
background: var(--pd-sc-row-bg-col-hover, var(--pd-default-lightest-col));
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.provider {
|
|
342
|
+
font-family: var(--pd-default-font-title-family);
|
|
343
|
+
color: var(--pd-sc-edit-provider-col, var(--pd-default-font-title-col));
|
|
344
|
+
display: inline-flex;
|
|
345
|
+
align-items: center;
|
|
346
|
+
gap: 0.5rem;
|
|
347
|
+
min-width: 10rem;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.value {
|
|
351
|
+
font-family: var(--pd-default-font-input-family);
|
|
352
|
+
font-size: 0.95rem;
|
|
353
|
+
color: var(--pd-sc-edit-value-col, var(--pd-default-font-input-col));
|
|
354
|
+
overflow: hidden;
|
|
355
|
+
text-overflow: ellipsis;
|
|
356
|
+
white-space: nowrap;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.btn-icon {
|
|
360
|
+
display: inline-flex;
|
|
361
|
+
align-items: center;
|
|
362
|
+
justify-content: center;
|
|
363
|
+
width: 2rem;
|
|
364
|
+
height: 2rem;
|
|
365
|
+
border: none;
|
|
366
|
+
background: none;
|
|
367
|
+
border-radius: 0.5rem;
|
|
368
|
+
cursor: pointer;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.btn-icon:hover {
|
|
372
|
+
background: var(--pd-surface-200, rgba(0, 0, 0, 0.05));
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.danger {
|
|
376
|
+
--pd-icon-col: var(--pd-default-error-col, #c0392b);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.btn-icon:focus-visible {
|
|
380
|
+
outline: 2px solid var(--pd-focus-ring-col, var(--pd-default-col));
|
|
381
|
+
outline-offset: 2px;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.current-input-url {
|
|
385
|
+
color: var(--pd-sc-text-muted, var(--pd-default-disabled-col));
|
|
386
|
+
padding-top: 0.2rem;
|
|
387
|
+
font-size: 1rem;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.add-button-group {
|
|
391
|
+
padding-top: 0.5rem;
|
|
392
|
+
--pd-button-font-size: 1rem;
|
|
393
|
+
}
|
|
394
|
+
`;
|
|
395
|
+
__decorateClass([
|
|
396
|
+
property({ type: Boolean, reflect: true })
|
|
397
|
+
], PdSocialmedia.prototype, "summary", 2);
|
|
398
|
+
__decorateClass([
|
|
399
|
+
property({ type: Array })
|
|
400
|
+
], PdSocialmedia.prototype, "initItems", 2);
|
|
401
|
+
__decorateClass([
|
|
402
|
+
property({ type: Array })
|
|
403
|
+
], PdSocialmedia.prototype, "providers", 2);
|
|
404
|
+
__decorateClass([
|
|
405
|
+
property({ type: Boolean })
|
|
406
|
+
], PdSocialmedia.prototype, "showLabelBelowIcon", 2);
|
|
407
|
+
__decorateClass([
|
|
408
|
+
property({ type: Boolean })
|
|
409
|
+
], PdSocialmedia.prototype, "openLinksInSameTab", 2);
|
|
410
|
+
__decorateClass([
|
|
411
|
+
state()
|
|
412
|
+
], PdSocialmedia.prototype, "_pendingAddProvider", 2);
|
|
413
|
+
__decorateClass([
|
|
414
|
+
state()
|
|
415
|
+
], PdSocialmedia.prototype, "_currentInputValue", 2);
|
|
416
|
+
__decorateClass([
|
|
417
|
+
state()
|
|
418
|
+
], PdSocialmedia.prototype, "_editItems", 2);
|
|
419
|
+
__decorateClass([
|
|
420
|
+
query("#suggesBoxId")
|
|
421
|
+
], PdSocialmedia.prototype, "_suggestForm", 2);
|
|
422
|
+
PdSocialmedia = __decorateClass([
|
|
423
|
+
localized()
|
|
424
|
+
], PdSocialmedia);
|
|
425
|
+
|
|
426
|
+
export { PdSocialmedia };
|