@progressive-development/pd-page 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 +34 -57
- package/dist/generated/locales/be.d.ts +19 -1
- package/dist/generated/locales/be.d.ts.map +1 -1
- package/dist/generated/locales/de.d.ts +19 -1
- package/dist/generated/locales/de.d.ts.map +1 -1
- package/dist/generated/locales/en.d.ts +19 -1
- package/dist/generated/locales/en.d.ts.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/locales/be.js +19 -1
- package/dist/locales/de.js +19 -1
- package/dist/locales/en.js +19 -1
- package/dist/pd-contact-us/PdContactUs.d.ts +15 -5
- package/dist/pd-contact-us/PdContactUs.d.ts.map +1 -1
- package/dist/pd-contact-us/PdContactUs.js +94 -134
- package/dist/pd-contact-us/pd-contact-us.stories.d.ts +36 -5
- package/dist/pd-contact-us/pd-contact-us.stories.d.ts.map +1 -1
- package/dist/pd-content/dist/pd-notice-box/PdNoticeBox.js +224 -0
- package/dist/pd-content/dist/pd-notice-box/pd-notice-box.js +8 -0
- package/dist/pd-footer/PdFooter.d.ts +27 -15
- package/dist/pd-footer/PdFooter.d.ts.map +1 -1
- package/dist/pd-footer/PdFooter.js +122 -74
- package/dist/pd-footer/pd-footer.stories.d.ts +47 -7
- package/dist/pd-footer/pd-footer.stories.d.ts.map +1 -1
- package/dist/pd-login/PdLogin.d.ts +59 -0
- package/dist/pd-login/PdLogin.d.ts.map +1 -0
- package/dist/pd-login/PdLogin.js +292 -0
- package/dist/pd-login/pd-login.d.ts +3 -0
- package/dist/pd-login/pd-login.d.ts.map +1 -0
- package/dist/pd-login/pd-login.stories.d.ts +55 -0
- package/dist/pd-login/pd-login.stories.d.ts.map +1 -0
- package/dist/pd-login.d.ts +2 -0
- package/dist/pd-login.js +8 -0
- package/dist/pd-menu/PdMenu.d.ts +72 -40
- package/dist/pd-menu/PdMenu.d.ts.map +1 -1
- package/dist/pd-menu/PdMenu.js +384 -276
- package/dist/pd-menu/pd-menu.stories.d.ts +59 -17
- package/dist/pd-menu/pd-menu.stories.d.ts.map +1 -1
- package/dist/pd-socialmedia/PdSocialmedia.d.ts +56 -0
- package/dist/pd-socialmedia/PdSocialmedia.d.ts.map +1 -0
- package/dist/pd-socialmedia/PdSocialmedia.js +426 -0
- package/dist/pd-socialmedia/pd-socialmedia-model.d.ts +16 -0
- package/dist/pd-socialmedia/pd-socialmedia-model.d.ts.map +1 -0
- package/dist/pd-socialmedia/pd-socialmedia-model.js +240 -0
- package/dist/pd-socialmedia/pd-socialmedia.d.ts +3 -0
- package/dist/pd-socialmedia/pd-socialmedia.d.ts.map +1 -0
- package/dist/pd-socialmedia/pd-socialmedia.stories.d.ts +53 -0
- package/dist/pd-socialmedia/pd-socialmedia.stories.d.ts.map +1 -0
- package/dist/pd-socialmedia.d.ts +2 -0
- package/dist/pd-socialmedia.js +7 -0
- package/dist/pd-toast/PdToast.d.ts +23 -0
- package/dist/pd-toast/PdToast.d.ts.map +1 -0
- package/dist/pd-toast/PdToast.js +222 -0
- package/dist/pd-toast/pd-toast.d.ts +3 -0
- package/dist/pd-toast/pd-toast.d.ts.map +1 -0
- package/dist/pd-toast/pd-toast.stories.d.ts +47 -0
- package/dist/pd-toast/pd-toast.stories.d.ts.map +1 -0
- package/dist/pd-toast.d.ts +2 -0
- package/dist/pd-toast.js +8 -0
- package/dist/stories/01_index.stories.d.ts +36 -4
- package/dist/stories/01_index.stories.d.ts.map +1 -1
- package/dist/toast-bus/toast-bus.d.ts +61 -0
- package/dist/toast-bus/toast-bus.d.ts.map +1 -0
- package/dist/toast-bus/toast-bus.js +42 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +14 -8
|
@@ -1,20 +1,62 @@
|
|
|
1
1
|
import { TemplateResult } from 'lit';
|
|
2
|
-
import { Meta,
|
|
3
|
-
import {
|
|
2
|
+
import { Meta, StoryObj } from '@storybook/web-components-vite';
|
|
3
|
+
import { PdMenuItem } from '../types.js';
|
|
4
|
+
import { ButtonData } from '@progressive-development/pd-forms';
|
|
5
|
+
/**
|
|
6
|
+
* Story arguments interface for pd-menu component.
|
|
7
|
+
* Maps to the component's public API.
|
|
8
|
+
*/
|
|
9
|
+
interface PdMenuArgs {
|
|
10
|
+
/** Main menu items */
|
|
11
|
+
menuItems: PdMenuItem[];
|
|
12
|
+
/** Top menu items (profile, settings, etc.) */
|
|
13
|
+
topMenuItems: PdMenuItem[];
|
|
14
|
+
/** Available language options (ButtonData with text and value) */
|
|
15
|
+
locales: ButtonData[];
|
|
16
|
+
/** Currently selected language (value from ButtonData) */
|
|
17
|
+
selectedLocale: string;
|
|
18
|
+
/** Disable responsive burger menu */
|
|
19
|
+
noBurgerMenu: boolean;
|
|
20
|
+
/** Custom logo slot content */
|
|
21
|
+
logo?: TemplateResult;
|
|
22
|
+
}
|
|
4
23
|
export declare const ticomiLogo: TemplateResult<1>;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
/**
|
|
25
|
+
* ## pd-menu
|
|
26
|
+
*
|
|
27
|
+
* Responsive application navigation menu with burger menu, language selector, and scroll-to-section support.
|
|
28
|
+
*
|
|
29
|
+
* ### Features
|
|
30
|
+
* - Configurable main menu items with scroll-to-section navigation
|
|
31
|
+
* - Top menu bar for secondary actions (profile, settings)
|
|
32
|
+
* - Responsive burger menu for mobile devices (collapses below 768px)
|
|
33
|
+
* - Built-in language selector via pd-button-select-group
|
|
34
|
+
* - Logo slot with click-to-navigate support
|
|
35
|
+
* - Active section highlighting based on scroll position
|
|
36
|
+
* - Full keyboard accessibility (Tab, Enter, Space, Escape)
|
|
37
|
+
*
|
|
38
|
+
* ### Accessibility
|
|
39
|
+
* - Uses `<nav>` with `aria-label` for navigation landmark
|
|
40
|
+
* - Menu items have `role="menuitem"` and `tabindex="0"`
|
|
41
|
+
* - Burger menu button has `aria-expanded` and `aria-controls`
|
|
42
|
+
* - Escape key closes the burger menu
|
|
43
|
+
* - Focus-visible styling for keyboard users
|
|
44
|
+
*/
|
|
45
|
+
declare const meta: Meta<PdMenuArgs>;
|
|
46
|
+
export default meta;
|
|
47
|
+
type Story = StoryObj<PdMenuArgs>;
|
|
48
|
+
/** Default menu with basic navigation items. Interactive via Controls panel. */
|
|
49
|
+
export declare const Default: Story;
|
|
50
|
+
/** Menu with a custom logo in the slotLogo slot. */
|
|
51
|
+
export declare const WithLogo: Story;
|
|
52
|
+
/** Menu with logo, top items (profile), and language selector. */
|
|
53
|
+
export declare const FullFeatured: Story;
|
|
54
|
+
/** Menu with noBurgerMenu — always shows full desktop layout regardless of screen width. */
|
|
55
|
+
export declare const WithoutBurger: Story;
|
|
56
|
+
/** Compact top-only menu without main navigation — useful for secondary page headers. */
|
|
57
|
+
export declare const CompactTopMenu: Story;
|
|
58
|
+
/** Overview of different menu configurations at a glance. */
|
|
59
|
+
export declare const AllVariants: Story;
|
|
60
|
+
/** CSS Custom Properties -- Branded and Redesigned variants. */
|
|
61
|
+
export declare const CustomStyling: Story;
|
|
20
62
|
//# sourceMappingURL=pd-menu.stories.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pd-menu.stories.d.ts","sourceRoot":"","sources":["../../src/pd-menu/pd-menu.stories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,MAAM,KAAK,CAAC;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"pd-menu.stories.d.ts","sourceRoot":"","sources":["../../src/pd-menu/pd-menu.stories.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,cAAc,EAAE,MAAM,KAAK,CAAC;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAErE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAEpE,OAAO,cAAc,CAAC;AAMtB;;;GAGG;AACH,UAAU,UAAU;IAClB,sBAAsB;IACtB,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,+CAA+C;IAC/C,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,kEAAkE;IAClE,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,0DAA0D;IAC1D,cAAc,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,YAAY,EAAE,OAAO,CAAC;IACtB,+BAA+B;IAC/B,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB;AAMD,eAAO,MAAM,UAAU,mBAiEtB,CAAC;AAiCF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAAU,CA4E1B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;AAMlC,gFAAgF;AAChF,eAAO,MAAM,OAAO,EAAE,KAWrB,CAAC;AAMF,oDAAoD;AACpD,eAAO,MAAM,QAAQ,EAAE,KA6BtB,CAAC;AAMF,kEAAkE;AAClE,eAAO,MAAM,YAAY,EAAE,KA2B1B,CAAC;AAMF,4FAA4F;AAC5F,eAAO,MAAM,aAAa,EAAE,KA+B3B,CAAC;AAMF,yFAAyF;AACzF,eAAO,MAAM,cAAc,EAAE,KA6B5B,CAAC;AAMF,6DAA6D;AAC7D,eAAO,MAAM,WAAW,EAAE,KAmDzB,CAAC;AAMF,gEAAgE;AAChE,eAAO,MAAM,aAAa,EAAE,KA2F3B,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { LitElement, TemplateResult, PropertyValues } from 'lit';
|
|
2
|
+
import { SocialProvider } from './pd-socialmedia-model';
|
|
3
|
+
import { SocialEntry } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Social media profiles display and editor component.
|
|
6
|
+
*
|
|
7
|
+
* @summary Social media display (icons) and editor (add/remove) component.
|
|
8
|
+
*
|
|
9
|
+
* @tagname pd-socialmedia
|
|
10
|
+
*
|
|
11
|
+
* @event items-change - Fired when items are added or removed.
|
|
12
|
+
*
|
|
13
|
+
* @cssprop --pd-gap - Icon spacing. Default: `0.5rem`.
|
|
14
|
+
* @cssprop --pd-sc-text-muted - Muted text color. Default: `var(--pd-default-disabled-col)`.
|
|
15
|
+
* @cssprop --pd-sc-row-bg-odd-col - Odd row background. Default: `var(--pd-default-bg-light-col)`.
|
|
16
|
+
* @cssprop --pd-sc-row-bg-even-col - Even row background. Default: `var(--pd-default-bg-dark-col)`.
|
|
17
|
+
* @cssprop --pd-sc-row-bg-col-hover - Row hover background. Default: `var(--pd-default-lightest-col)`.
|
|
18
|
+
* @cssprop --pd-sc-edit-provider-col - Provider label color. Default: `var(--pd-default-font-title-col)`.
|
|
19
|
+
* @cssprop --pd-sc-edit-value-col - Value text color. Default: `var(--pd-default-font-input-col)`.
|
|
20
|
+
*/
|
|
21
|
+
export declare class PdSocialmedia extends LitElement {
|
|
22
|
+
/** View mode (true) shows icons, edit mode (false) shows add/remove list. */
|
|
23
|
+
summary: boolean;
|
|
24
|
+
/** Initial social media entries. */
|
|
25
|
+
initItems: SocialEntry[];
|
|
26
|
+
/** Provider metadata definitions (injectable from outside). */
|
|
27
|
+
providers: SocialProvider[];
|
|
28
|
+
/** Show provider label below icon in view mode. */
|
|
29
|
+
showLabelBelowIcon: boolean;
|
|
30
|
+
/** Open links in same tab instead of new tab. */
|
|
31
|
+
openLinksInSameTab: boolean;
|
|
32
|
+
/** @ignore */
|
|
33
|
+
private _pendingAddProvider;
|
|
34
|
+
/** @ignore */
|
|
35
|
+
private _currentInputValue;
|
|
36
|
+
/** @ignore */
|
|
37
|
+
_editItems: SocialEntry[];
|
|
38
|
+
/** @ignore */
|
|
39
|
+
private _suggestForm;
|
|
40
|
+
static styles: import('lit').CSSResult;
|
|
41
|
+
protected willUpdate(_changedProperties: PropertyValues): void;
|
|
42
|
+
addItem(entry: SocialEntry): void;
|
|
43
|
+
removeIndex(index: number): void;
|
|
44
|
+
get value(): SocialEntry[];
|
|
45
|
+
protected render(): TemplateResult<1>;
|
|
46
|
+
protected renderView(): TemplateResult<1>;
|
|
47
|
+
protected renderEdit(): TemplateResult<1>;
|
|
48
|
+
private _renderAddRow;
|
|
49
|
+
private _searchSocialProviders;
|
|
50
|
+
private _openAddSuggestItem;
|
|
51
|
+
private _closeAddSuggestedItem;
|
|
52
|
+
private _findProvider;
|
|
53
|
+
private _toUrl;
|
|
54
|
+
private emitChange;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=PdSocialmedia.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PdSocialmedia.d.ts","sourceRoot":"","sources":["../../src/pd-socialmedia/PdSocialmedia.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,UAAU,EAIV,cAAc,EACd,cAAc,EACf,MAAM,KAAK,CAAC;AAIb,OAAO,qDAAqD,CAAC;AAC7D,OAAO,+CAA+C,CAAC;AACvD,OAAO,6CAA6C,CAAC;AACrD,OAAO,4CAA4C,CAAC;AACpD,OAAO,0CAA0C,CAAC;AAElD,OAAO,EAAoB,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG1E,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC;;;;;;;;;;;;;;;;GAgBG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC3C,6EAA6E;IAE7E,OAAO,UAAS;IAEhB,oCAAoC;IAEpC,SAAS,EAAE,WAAW,EAAE,CAAM;IAE9B,+DAA+D;IAE/D,SAAS,EAAE,cAAc,EAAE,CAAoB;IAE/C,mDAAmD;IAEnD,kBAAkB,UAAS;IAE3B,iDAAiD;IAEjD,kBAAkB,UAAS;IAE3B,cAAc;IAEd,OAAO,CAAC,mBAAmB,CAA+B;IAE1D,cAAc;IAEd,OAAO,CAAC,kBAAkB,CAAuB;IAEjD,cAAc;IAEd,UAAU,EAAE,WAAW,EAAE,CAAM;IAE/B,cAAc;IAEd,OAAO,CAAC,YAAY,CAAmC;IAEvD,MAAM,CAAC,MAAM,0BA0IX;IAEF,SAAS,CAAC,UAAU,CAAC,kBAAkB,EAAE,cAAc,GAAG,IAAI;IAOvD,OAAO,CAAC,KAAK,EAAE,WAAW;IAM1B,WAAW,CAAC,KAAK,EAAE,MAAM;IAOhC,IAAI,KAAK,kBAER;IAGD,SAAS,CAAC,MAAM;IAIhB,SAAS,CAAC,UAAU;IA+CpB,SAAS,CAAC,UAAU;IAwDpB,OAAO,CAAC,aAAa;YA+DP,sBAAsB;IAoBpC,OAAO,CAAC,mBAAmB,CASzB;IAEF,OAAO,CAAC,sBAAsB,CAG5B;IAGF,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,MAAM;IASd,OAAO,CAAC,UAAU;CASnB"}
|
|
@@ -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 };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type ProviderInputKind = "username" | "url" | "id";
|
|
2
|
+
export interface SocialProvider {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
aliases?: string[];
|
|
6
|
+
category: "Social" | "Music" | "Streaming" | "DJ/Booking" | "Catalog";
|
|
7
|
+
icon: string;
|
|
8
|
+
brandColor?: string;
|
|
9
|
+
inputKind: ProviderInputKind;
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
pattern?: RegExp;
|
|
12
|
+
toUrl: (input: string) => string;
|
|
13
|
+
normalize?: (raw: string) => string;
|
|
14
|
+
}
|
|
15
|
+
export declare const SOCIAL_PROVIDERS: SocialProvider[];
|
|
16
|
+
//# sourceMappingURL=pd-socialmedia-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pd-socialmedia-model.d.ts","sourceRoot":"","sources":["../../src/pd-socialmedia/pd-socialmedia-model.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,KAAK,GAAG,IAAI,CAAC;AAE1D,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,WAAW,GAAG,YAAY,GAAG,SAAS,CAAC;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAEjC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;CACrC;AAED,eAAO,MAAM,gBAAgB,EAAE,cAAc,EAiP5C,CAAC"}
|