@design.estate/dees-catalog 7.0.0 → 8.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/dist_bundle/bundle.js +1825 -1148
- package/dist_bundle/bundle.js.map +1 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/00group-button/dees-button/dees-button.d.ts +8 -5
- package/dist_ts_web/elements/00group-button/dees-button/dees-button.js +100 -46
- package/dist_ts_web/elements/00group-form/dees-form-submit/dees-form-submit.js +2 -5
- package/dist_ts_web/elements/00group-utility/dees-icon/dees-icon.js +2 -1
- package/package.json +3 -3
- package/readme.md +6 -3
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/00group-button/dees-button/dees-button.ts +97 -53
- package/ts_web/elements/00group-form/dees-form-submit/dees-form-submit.ts +1 -4
- package/ts_web/elements/00group-utility/dees-icon/dees-icon.ts +1 -0
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
html,
|
|
4
4
|
DeesElement,
|
|
5
5
|
property,
|
|
6
|
+
state,
|
|
6
7
|
type TemplateResult,
|
|
7
8
|
cssManager,
|
|
8
9
|
css,
|
|
@@ -93,18 +94,36 @@ export class DeesButton extends DeesElement {
|
|
|
93
94
|
@property({ type: String, reflect: true })
|
|
94
95
|
accessor iconPosition: 'left' | 'right' = 'left';
|
|
95
96
|
|
|
97
|
+
@state()
|
|
98
|
+
private accessor adoptedText = '';
|
|
99
|
+
|
|
100
|
+
@state()
|
|
101
|
+
private accessor adoptedIcon = '';
|
|
102
|
+
|
|
103
|
+
@state()
|
|
104
|
+
private accessor adoptedIconPosition: 'left' | 'right' = 'left';
|
|
105
|
+
|
|
106
|
+
private lightDomObserver: MutationObserver | undefined = undefined;
|
|
107
|
+
|
|
96
108
|
constructor() {
|
|
97
109
|
super();
|
|
98
110
|
}
|
|
99
111
|
|
|
100
|
-
public async connectedCallback() {
|
|
101
|
-
|
|
112
|
+
public async connectedCallback(): Promise<void> {
|
|
113
|
+
const superConnected = super.connectedCallback();
|
|
114
|
+
this.observeLightDom();
|
|
115
|
+
await superConnected;
|
|
102
116
|
// Auto-detect if inside a form
|
|
103
117
|
if (!this.insideForm && this.closest('dees-form')) {
|
|
104
118
|
this.insideForm = true;
|
|
105
119
|
}
|
|
106
120
|
}
|
|
107
121
|
|
|
122
|
+
public async disconnectedCallback(): Promise<void> {
|
|
123
|
+
this.lightDomObserver?.disconnect();
|
|
124
|
+
await super.disconnectedCallback();
|
|
125
|
+
}
|
|
126
|
+
|
|
108
127
|
public static styles = [
|
|
109
128
|
themeDefaultStyles,
|
|
110
129
|
cssManager.defaultStyles,
|
|
@@ -464,49 +483,76 @@ export class DeesButton extends DeesElement {
|
|
|
464
483
|
`,
|
|
465
484
|
];
|
|
466
485
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
.filter(node => node.nodeType === Node.TEXT_NODE)
|
|
476
|
-
.map(node => node.textContent?.trim())
|
|
477
|
-
.filter(Boolean)
|
|
478
|
-
.join(' ');
|
|
479
|
-
|
|
480
|
-
if (textContent && !this.text) {
|
|
481
|
-
this.text = textContent;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
if (iconElement) {
|
|
485
|
-
const iconValue = iconElement.icon || iconElement.getAttribute('icon') || null;
|
|
486
|
-
|
|
487
|
-
if (iconValue) {
|
|
488
|
-
// Determine position based on DOM order
|
|
489
|
-
const children = Array.from(this.childNodes);
|
|
490
|
-
const iconIndex = children.indexOf(iconElement);
|
|
491
|
-
const textNodes = children.filter(node =>
|
|
492
|
-
node.nodeType === Node.TEXT_NODE && node.textContent?.trim()
|
|
493
|
-
);
|
|
494
|
-
|
|
495
|
-
if (textNodes.length > 0) {
|
|
496
|
-
const firstTextIndex = children.indexOf(textNodes[0]);
|
|
497
|
-
this.iconPosition = iconIndex < firstTextIndex ? 'left' : 'right';
|
|
486
|
+
private observeLightDom(): void {
|
|
487
|
+
this.lightDomObserver ??= new MutationObserver((mutationsArg) => {
|
|
488
|
+
const supportedContentChanged = mutationsArg.some((mutationArg) => {
|
|
489
|
+
if (mutationArg.type === 'childList') {
|
|
490
|
+
return mutationArg.target === this;
|
|
491
|
+
}
|
|
492
|
+
if (mutationArg.type === 'characterData') {
|
|
493
|
+
return mutationArg.target.parentNode === this;
|
|
498
494
|
}
|
|
495
|
+
return mutationArg.target.parentNode === this
|
|
496
|
+
&& (mutationArg.target as Element).localName === 'dees-icon';
|
|
497
|
+
});
|
|
498
|
+
if (supportedContentChanged) {
|
|
499
|
+
this.adoptLightDom();
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
this.lightDomObserver.observe(this, {
|
|
503
|
+
attributes: true,
|
|
504
|
+
attributeFilter: ['icon'],
|
|
505
|
+
characterData: true,
|
|
506
|
+
childList: true,
|
|
507
|
+
subtree: true,
|
|
508
|
+
});
|
|
509
|
+
this.adoptLightDom();
|
|
510
|
+
}
|
|
499
511
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
512
|
+
/** Mirrors supported direct light content without taking ownership of consumer nodes. */
|
|
513
|
+
private adoptLightDom(): void {
|
|
514
|
+
const children = Array.from(this.childNodes);
|
|
515
|
+
const textNodes = children.filter(
|
|
516
|
+
(nodeArg) => nodeArg.nodeType === Node.TEXT_NODE && nodeArg.textContent?.trim(),
|
|
517
|
+
);
|
|
518
|
+
const iconElement = children.find(
|
|
519
|
+
(nodeArg): nodeArg is HTMLElement & { icon?: string } =>
|
|
520
|
+
nodeArg instanceof HTMLElement && nodeArg.localName === 'dees-icon',
|
|
521
|
+
);
|
|
503
522
|
|
|
504
|
-
|
|
505
|
-
|
|
523
|
+
const nextAdoptedText = textNodes
|
|
524
|
+
.map((nodeArg) => nodeArg.textContent!.trim())
|
|
525
|
+
.join(' ');
|
|
526
|
+
const nextAdoptedIcon = iconElement?.icon || iconElement?.getAttribute('icon') || '';
|
|
527
|
+
const nextAdoptedIconPosition =
|
|
528
|
+
iconElement && textNodes.length > 0
|
|
529
|
+
? children.indexOf(iconElement) < children.indexOf(textNodes[0])
|
|
530
|
+
? 'left'
|
|
531
|
+
: 'right'
|
|
532
|
+
: 'left';
|
|
533
|
+
|
|
534
|
+
const textFollowsLightDom = this.text === this.adoptedText;
|
|
535
|
+
const iconFollowsLightDom = (this.icon || '') === this.adoptedIcon;
|
|
536
|
+
const iconPositionFollowsLightDom = this.iconPosition === this.adoptedIconPosition;
|
|
537
|
+
const previousAdoptedIcon = this.adoptedIcon;
|
|
538
|
+
|
|
539
|
+
this.adoptedText = nextAdoptedText;
|
|
540
|
+
this.adoptedIcon = nextAdoptedIcon;
|
|
541
|
+
this.adoptedIconPosition = nextAdoptedIconPosition;
|
|
542
|
+
|
|
543
|
+
if (textFollowsLightDom && this.text !== nextAdoptedText) {
|
|
544
|
+
this.text = nextAdoptedText;
|
|
545
|
+
}
|
|
546
|
+
if (
|
|
547
|
+
iconFollowsLightDom
|
|
548
|
+
&& this.icon !== nextAdoptedIcon
|
|
549
|
+
&& Boolean(nextAdoptedIcon || previousAdoptedIcon)
|
|
550
|
+
) {
|
|
551
|
+
this.icon = nextAdoptedIcon;
|
|
552
|
+
}
|
|
553
|
+
if (iconPositionFollowsLightDom && this.iconPosition !== nextAdoptedIconPosition) {
|
|
554
|
+
this.iconPosition = nextAdoptedIconPosition;
|
|
506
555
|
}
|
|
507
|
-
|
|
508
|
-
// Clear all remaining light DOM
|
|
509
|
-
this.innerHTML = '';
|
|
510
556
|
}
|
|
511
557
|
|
|
512
558
|
public render(): TemplateResult {
|
|
@@ -520,17 +566,20 @@ export class DeesButton extends DeesElement {
|
|
|
520
566
|
|
|
521
567
|
const actualType = typeMap[this.type] || this.type;
|
|
522
568
|
const actualSize = this.type === 'big' ? 'lg' : this.size;
|
|
569
|
+
const effectiveText = this.text;
|
|
570
|
+
const effectiveIcon = this.icon;
|
|
571
|
+
const effectiveIconPosition = this.iconPosition;
|
|
523
572
|
|
|
524
|
-
const leftIcon =
|
|
525
|
-
? html`<dees-icon .icon=${
|
|
573
|
+
const leftIcon = effectiveIconPosition === 'left' && effectiveIcon
|
|
574
|
+
? html`<dees-icon .icon=${effectiveIcon}></dees-icon>`
|
|
526
575
|
: '';
|
|
527
|
-
const rightIcon =
|
|
528
|
-
? html`<dees-icon .icon=${
|
|
576
|
+
const rightIcon = effectiveIconPosition === 'right' && effectiveIcon
|
|
577
|
+
? html`<dees-icon .icon=${effectiveIcon}></dees-icon>`
|
|
529
578
|
: '';
|
|
530
579
|
|
|
531
580
|
// No placeholder label: a button without text renders icon-only.
|
|
532
581
|
// size-icon additionally suppresses text to keep its square geometry.
|
|
533
|
-
const showText = Boolean(
|
|
582
|
+
const showText = Boolean(effectiveText) && !(actualSize === 'icon' && effectiveIcon);
|
|
534
583
|
|
|
535
584
|
return html`
|
|
536
585
|
<div
|
|
@@ -541,7 +590,7 @@ export class DeesButton extends DeesElement {
|
|
|
541
590
|
tabindex=${this.disabled ? -1 : 0}
|
|
542
591
|
aria-disabled=${this.disabled ? 'true' : 'false'}
|
|
543
592
|
aria-busy=${this.status === 'pending' ? 'true' : 'false'}
|
|
544
|
-
.ariaLabel=${showText ? null :
|
|
593
|
+
.ariaLabel=${showText ? null : effectiveText || null}
|
|
545
594
|
@click="${this.dispatchClick}"
|
|
546
595
|
@keydown=${this.handleKeydown}
|
|
547
596
|
@keyup=${this.handleKeyup}
|
|
@@ -554,7 +603,7 @@ export class DeesButton extends DeesElement {
|
|
|
554
603
|
></dees-spinner>
|
|
555
604
|
`}
|
|
556
605
|
${leftIcon}
|
|
557
|
-
${showText ? html`<div class="textbox">${
|
|
606
|
+
${showText ? html`<div class="textbox">${effectiveText}</div>` : ''}
|
|
558
607
|
${rightIcon}
|
|
559
608
|
</div>
|
|
560
609
|
`;
|
|
@@ -644,9 +693,4 @@ export class DeesButton extends DeesElement {
|
|
|
644
693
|
}
|
|
645
694
|
this.faceElement?.click();
|
|
646
695
|
}
|
|
647
|
-
|
|
648
|
-
public async firstUpdated() {
|
|
649
|
-
// Extract light DOM content (icon + text) and set as properties
|
|
650
|
-
this.extractLightDom();
|
|
651
|
-
}
|
|
652
696
|
}
|
|
@@ -91,10 +91,7 @@ export class DeesFormSubmit extends DeesElement {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
public async firstUpdated() {
|
|
94
|
-
// Capture light
|
|
95
|
-
// its own light DOM during extractLightDom(), so we cannot simply forward
|
|
96
|
-
// a <slot> into it — we have to hoist the text onto the .text property
|
|
97
|
-
// ourselves before handing it to dees-button.
|
|
94
|
+
// Capture this wrapper's light-DOM text as the controlled label for its nested button.
|
|
98
95
|
if (!this.text) {
|
|
99
96
|
const slotText = this.textContent?.trim();
|
|
100
97
|
if (slotText) {
|