@duskmoon-dev/el-breadcrumbs 0.4.0 → 0.6.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/README.md +141 -0
- package/dist/cjs/index.js +30 -39
- package/dist/cjs/index.js.map +3 -3
- package/dist/cjs/register.js +30 -39
- package/dist/cjs/register.js.map +3 -3
- package/dist/esm/index.js +28 -37
- package/dist/esm/index.js.map +3 -3
- package/dist/esm/register.js +28 -37
- package/dist/esm/register.js.map +3 -3
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/el-dm-breadcrumbs.d.ts +1 -1
- package/dist/types/el-dm-breadcrumbs.d.ts.map +1 -1
- package/package.json +6 -5
package/dist/esm/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// src/el-dm-breadcrumbs.ts
|
|
2
|
-
import { BaseElement, css } from "@duskmoon-dev/el-
|
|
2
|
+
import { BaseElement, css } from "@duskmoon-dev/el-base";
|
|
3
|
+
import { css as navigationCSS } from "@duskmoon-dev/core/components/navigation";
|
|
4
|
+
var coreStyles = navigationCSS.replace(/@layer\s+components\s*\{/, "").replace(/\}\s*$/, "");
|
|
3
5
|
var styles = css`
|
|
4
6
|
:host {
|
|
5
7
|
display: block;
|
|
@@ -9,57 +11,46 @@ var styles = css`
|
|
|
9
11
|
display: none !important;
|
|
10
12
|
}
|
|
11
13
|
|
|
14
|
+
/* Import core navigation styles */
|
|
15
|
+
${coreStyles}
|
|
16
|
+
|
|
12
17
|
.breadcrumbs-nav {
|
|
13
18
|
font-family: inherit;
|
|
14
19
|
}
|
|
15
20
|
|
|
16
|
-
.breadcrumbs
|
|
17
|
-
|
|
18
|
-
flex-wrap: wrap;
|
|
19
|
-
align-items: center;
|
|
20
|
-
gap: 0.5rem;
|
|
21
|
-
list-style: none;
|
|
22
|
-
margin: 0;
|
|
21
|
+
/* Override core .breadcrumbs padding since we manage our own layout */
|
|
22
|
+
.breadcrumbs {
|
|
23
23
|
padding: 0;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
.
|
|
27
|
-
|
|
28
|
-
align-items: center;
|
|
29
|
-
gap: 0.5rem;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
.breadcrumbs-link {
|
|
26
|
+
/* Override core .breadcrumb-link with our custom colors */
|
|
27
|
+
.breadcrumb-link {
|
|
33
28
|
color: var(--color-primary);
|
|
34
|
-
text-decoration: none;
|
|
35
|
-
font-size: 0.875rem;
|
|
36
|
-
line-height: 1.25rem;
|
|
37
|
-
transition: color 150ms ease;
|
|
38
|
-
cursor: pointer;
|
|
39
29
|
}
|
|
40
30
|
|
|
41
|
-
.
|
|
31
|
+
.breadcrumb-link:hover {
|
|
42
32
|
color: var(--color-primary-dark, var(--color-primary));
|
|
43
|
-
text-decoration: underline;
|
|
44
33
|
}
|
|
45
34
|
|
|
46
|
-
.
|
|
35
|
+
.breadcrumb-link:focus {
|
|
47
36
|
outline: 2px solid var(--color-primary);
|
|
48
37
|
outline-offset: 2px;
|
|
49
38
|
border-radius: 2px;
|
|
50
39
|
}
|
|
51
40
|
|
|
52
|
-
.
|
|
41
|
+
.breadcrumb-item-active {
|
|
53
42
|
color: var(--color-on-surface);
|
|
54
43
|
font-size: 0.875rem;
|
|
55
44
|
line-height: 1.25rem;
|
|
56
|
-
font-weight: 500;
|
|
57
45
|
}
|
|
58
46
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
47
|
+
/* Hide core's separator ::before — we render separator text explicitly */
|
|
48
|
+
.breadcrumb-separator::before {
|
|
49
|
+
display: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.breadcrumb-separator {
|
|
53
|
+
opacity: 1;
|
|
63
54
|
}
|
|
64
55
|
|
|
65
56
|
/* Hide slotted separator template */
|
|
@@ -108,9 +99,9 @@ class ElDmBreadcrumbs extends BaseElement {
|
|
|
108
99
|
const escapedLabel = this._escapeHtml(item.label);
|
|
109
100
|
if (isLast) {
|
|
110
101
|
return `
|
|
111
|
-
<li class="
|
|
102
|
+
<li class="breadcrumb-item" part="item">
|
|
112
103
|
<span
|
|
113
|
-
class="
|
|
104
|
+
class="breadcrumb-item-active"
|
|
114
105
|
part="current"
|
|
115
106
|
aria-current="page"
|
|
116
107
|
>${escapedLabel}</span>
|
|
@@ -118,20 +109,20 @@ class ElDmBreadcrumbs extends BaseElement {
|
|
|
118
109
|
`;
|
|
119
110
|
}
|
|
120
111
|
return `
|
|
121
|
-
<li class="
|
|
112
|
+
<li class="breadcrumb-item" part="item">
|
|
122
113
|
<a
|
|
123
|
-
class="
|
|
114
|
+
class="breadcrumb-link"
|
|
124
115
|
part="link"
|
|
125
116
|
href="${item.href || "#"}"
|
|
126
117
|
data-index="${index}"
|
|
127
118
|
>${escapedLabel}</a>
|
|
128
|
-
<span class="
|
|
119
|
+
<span class="breadcrumb-separator" part="separator" aria-hidden="true">${separatorHtml}</span>
|
|
129
120
|
</li>
|
|
130
121
|
`;
|
|
131
122
|
}).join("");
|
|
132
123
|
return `
|
|
133
124
|
<nav class="breadcrumbs-nav" part="nav" aria-label="Breadcrumb">
|
|
134
|
-
<ol class="breadcrumbs
|
|
125
|
+
<ol class="breadcrumbs" part="list">
|
|
135
126
|
${itemsHtml}
|
|
136
127
|
</ol>
|
|
137
128
|
<slot name="separator"></slot>
|
|
@@ -140,7 +131,7 @@ class ElDmBreadcrumbs extends BaseElement {
|
|
|
140
131
|
}
|
|
141
132
|
update() {
|
|
142
133
|
super.update();
|
|
143
|
-
const links = this.shadowRoot?.querySelectorAll(".
|
|
134
|
+
const links = this.shadowRoot?.querySelectorAll(".breadcrumb-link");
|
|
144
135
|
links?.forEach((link) => {
|
|
145
136
|
const index = parseInt(link.getAttribute("data-index") || "0", 10);
|
|
146
137
|
const item = this.items[index];
|
|
@@ -162,5 +153,5 @@ export {
|
|
|
162
153
|
ElDmBreadcrumbs
|
|
163
154
|
};
|
|
164
155
|
|
|
165
|
-
//# debugId=
|
|
156
|
+
//# debugId=9ED3FCA4F8A00B7464756E2164756E21
|
|
166
157
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/el-dm-breadcrumbs.ts", "../../src/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * DuskMoon Breadcrumbs Element\n *\n * A hierarchical navigation breadcrumbs component for displaying the user's\n * current location within a site structure.\n *\n * @element el-dm-breadcrumbs\n *\n * @attr {string} items - JSON array of breadcrumb items [{label, href}]\n * @attr {string} separator - Separator character between items (default '/')\n *\n * @slot separator - Custom separator element to use between items\n *\n * @csspart nav - The navigation container\n * @csspart list - The ordered list element\n * @csspart item - Individual breadcrumb item container\n * @csspart link - Breadcrumb link element\n * @csspart current - Current page text (last item)\n * @csspart separator - Separator element between items\n *\n * @fires navigate - Fired when a breadcrumb link is clicked. Detail: { item, index }\n */\n\nimport { BaseElement, css } from '@duskmoon-dev/el-core';\n\n/**\n * Represents a single breadcrumb item\n */\nexport interface BreadcrumbItem {\n /** Display label for the breadcrumb */\n label: string;\n /** URL for the breadcrumb link (optional for last item) */\n href?: string;\n}\n\n/**\n * Event detail for the navigate event\n */\nexport interface NavigateEventDetail {\n /** The breadcrumb item that was clicked */\n item: BreadcrumbItem;\n /** The index of the clicked item */\n index: number;\n}\n\nconst styles = css`\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n .breadcrumbs-nav {\n font-family: inherit;\n }\n\n .breadcrumbs
|
|
5
|
+
"/**\n * DuskMoon Breadcrumbs Element\n *\n * A hierarchical navigation breadcrumbs component for displaying the user's\n * current location within a site structure.\n *\n * @element el-dm-breadcrumbs\n *\n * @attr {string} items - JSON array of breadcrumb items [{label, href}]\n * @attr {string} separator - Separator character between items (default '/')\n *\n * @slot separator - Custom separator element to use between items\n *\n * @csspart nav - The navigation container\n * @csspart list - The ordered list element\n * @csspart item - Individual breadcrumb item container\n * @csspart link - Breadcrumb link element\n * @csspart current - Current page text (last item)\n * @csspart separator - Separator element between items\n *\n * @fires navigate - Fired when a breadcrumb link is clicked. Detail: { item, index }\n */\n\nimport { BaseElement, css } from '@duskmoon-dev/el-base';\nimport { css as navigationCSS } from '@duskmoon-dev/core/components/navigation';\n\n/**\n * Represents a single breadcrumb item\n */\nexport interface BreadcrumbItem {\n /** Display label for the breadcrumb */\n label: string;\n /** URL for the breadcrumb link (optional for last item) */\n href?: string;\n}\n\n/**\n * Event detail for the navigate event\n */\nexport interface NavigateEventDetail {\n /** The breadcrumb item that was clicked */\n item: BreadcrumbItem;\n /** The index of the clicked item */\n index: number;\n}\n\n// Strip @layer wrapper for Shadow DOM compatibility\nconst coreStyles = navigationCSS.replace(/@layer\\s+components\\s*\\{/, '').replace(/\\}\\s*$/, '');\n\nconst styles = css`\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n /* Import core navigation styles */\n ${coreStyles}\n\n .breadcrumbs-nav {\n font-family: inherit;\n }\n\n /* Override core .breadcrumbs padding since we manage our own layout */\n .breadcrumbs {\n padding: 0;\n }\n\n /* Override core .breadcrumb-link with our custom colors */\n .breadcrumb-link {\n color: var(--color-primary);\n }\n\n .breadcrumb-link:hover {\n color: var(--color-primary-dark, var(--color-primary));\n }\n\n .breadcrumb-link:focus {\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n border-radius: 2px;\n }\n\n .breadcrumb-item-active {\n color: var(--color-on-surface);\n font-size: 0.875rem;\n line-height: 1.25rem;\n }\n\n /* Hide core's separator ::before — we render separator text explicitly */\n .breadcrumb-separator::before {\n display: none;\n }\n\n .breadcrumb-separator {\n opacity: 1;\n }\n\n /* Hide slotted separator template */\n ::slotted([slot='separator']) {\n display: none;\n }\n`;\n\nexport class ElDmBreadcrumbs extends BaseElement {\n static properties = {\n items: { type: Array, reflect: false },\n separator: { type: String, reflect: true, default: '/' },\n };\n\n /** Array of breadcrumb items */\n declare items: BreadcrumbItem[];\n\n /** Separator character between items */\n declare separator: string;\n\n constructor() {\n super();\n this.attachStyles(styles);\n this.items = [];\n }\n\n /**\n * Handle click on a breadcrumb link\n */\n private _handleClick(event: Event, item: BreadcrumbItem, index: number): void {\n event.preventDefault();\n\n // emit returns true if event was not cancelled\n const notCancelled = this.emit<NavigateEventDetail>('navigate', {\n item,\n index,\n });\n\n // If event was not prevented, navigate to the href\n if (notCancelled && item.href) {\n window.location.href = item.href;\n }\n }\n\n /**\n * Get the separator HTML - either from slot or default\n */\n private _getSeparatorHtml(): string {\n const slottedSeparator = this.querySelector('[slot=\"separator\"]');\n if (slottedSeparator) {\n return slottedSeparator.outerHTML.replace('slot=\"separator\"', '');\n }\n return this.separator || '/';\n }\n\n /**\n * Escape HTML special characters to prevent XSS\n */\n private _escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n\n render(): string {\n const itemsArray = Array.isArray(this.items) ? this.items : [];\n const separatorHtml = this._getSeparatorHtml();\n\n const itemsHtml = itemsArray\n .map((item, index) => {\n const isLast = index === itemsArray.length - 1;\n const escapedLabel = this._escapeHtml(item.label);\n\n if (isLast) {\n // Last item is current page - not clickable\n return `\n <li class=\"breadcrumb-item\" part=\"item\">\n <span\n class=\"breadcrumb-item-active\"\n part=\"current\"\n aria-current=\"page\"\n >${escapedLabel}</span>\n </li>\n `;\n }\n\n // Regular breadcrumb link\n return `\n <li class=\"breadcrumb-item\" part=\"item\">\n <a\n class=\"breadcrumb-link\"\n part=\"link\"\n href=\"${item.href || '#'}\"\n data-index=\"${index}\"\n >${escapedLabel}</a>\n <span class=\"breadcrumb-separator\" part=\"separator\" aria-hidden=\"true\">${separatorHtml}</span>\n </li>\n `;\n })\n .join('');\n\n return `\n <nav class=\"breadcrumbs-nav\" part=\"nav\" aria-label=\"Breadcrumb\">\n <ol class=\"breadcrumbs\" part=\"list\">\n ${itemsHtml}\n </ol>\n <slot name=\"separator\"></slot>\n </nav>\n `;\n }\n\n update(): void {\n super.update();\n\n // Attach click handlers to all breadcrumb links\n const links = this.shadowRoot?.querySelectorAll('.breadcrumb-link');\n links?.forEach((link) => {\n const index = parseInt(link.getAttribute('data-index') || '0', 10);\n const item = this.items[index];\n if (item) {\n link.addEventListener('click', (e) => this._handleClick(e, item, index));\n }\n });\n }\n}\n",
|
|
6
6
|
"/**\n * @duskmoon-dev/el-breadcrumbs\n *\n * DuskMoon Breadcrumbs custom element\n */\n\nimport { ElDmBreadcrumbs } from './el-dm-breadcrumbs.js';\n\nexport { ElDmBreadcrumbs };\nexport type { BreadcrumbItem, NavigateEventDetail } from './el-dm-breadcrumbs.js';\n\n/**\n * Register the el-dm-breadcrumbs custom element\n *\n * @example\n * ```ts\n * import { register } from '@duskmoon-dev/el-breadcrumbs';\n * register();\n * ```\n */\nexport function register(): void {\n if (!customElements.get('el-dm-breadcrumbs')) {\n customElements.define('el-dm-breadcrumbs', ElDmBreadcrumbs);\n }\n}\n"
|
|
7
7
|
],
|
|
8
|
-
"mappings": ";AAuBA;
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "9ED3FCA4F8A00B7464756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
package/dist/esm/register.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// src/el-dm-breadcrumbs.ts
|
|
2
|
-
import { BaseElement, css } from "@duskmoon-dev/el-
|
|
2
|
+
import { BaseElement, css } from "@duskmoon-dev/el-base";
|
|
3
|
+
import { css as navigationCSS } from "@duskmoon-dev/core/components/navigation";
|
|
4
|
+
var coreStyles = navigationCSS.replace(/@layer\s+components\s*\{/, "").replace(/\}\s*$/, "");
|
|
3
5
|
var styles = css`
|
|
4
6
|
:host {
|
|
5
7
|
display: block;
|
|
@@ -9,57 +11,46 @@ var styles = css`
|
|
|
9
11
|
display: none !important;
|
|
10
12
|
}
|
|
11
13
|
|
|
14
|
+
/* Import core navigation styles */
|
|
15
|
+
${coreStyles}
|
|
16
|
+
|
|
12
17
|
.breadcrumbs-nav {
|
|
13
18
|
font-family: inherit;
|
|
14
19
|
}
|
|
15
20
|
|
|
16
|
-
.breadcrumbs
|
|
17
|
-
|
|
18
|
-
flex-wrap: wrap;
|
|
19
|
-
align-items: center;
|
|
20
|
-
gap: 0.5rem;
|
|
21
|
-
list-style: none;
|
|
22
|
-
margin: 0;
|
|
21
|
+
/* Override core .breadcrumbs padding since we manage our own layout */
|
|
22
|
+
.breadcrumbs {
|
|
23
23
|
padding: 0;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
.
|
|
27
|
-
|
|
28
|
-
align-items: center;
|
|
29
|
-
gap: 0.5rem;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
.breadcrumbs-link {
|
|
26
|
+
/* Override core .breadcrumb-link with our custom colors */
|
|
27
|
+
.breadcrumb-link {
|
|
33
28
|
color: var(--color-primary);
|
|
34
|
-
text-decoration: none;
|
|
35
|
-
font-size: 0.875rem;
|
|
36
|
-
line-height: 1.25rem;
|
|
37
|
-
transition: color 150ms ease;
|
|
38
|
-
cursor: pointer;
|
|
39
29
|
}
|
|
40
30
|
|
|
41
|
-
.
|
|
31
|
+
.breadcrumb-link:hover {
|
|
42
32
|
color: var(--color-primary-dark, var(--color-primary));
|
|
43
|
-
text-decoration: underline;
|
|
44
33
|
}
|
|
45
34
|
|
|
46
|
-
.
|
|
35
|
+
.breadcrumb-link:focus {
|
|
47
36
|
outline: 2px solid var(--color-primary);
|
|
48
37
|
outline-offset: 2px;
|
|
49
38
|
border-radius: 2px;
|
|
50
39
|
}
|
|
51
40
|
|
|
52
|
-
.
|
|
41
|
+
.breadcrumb-item-active {
|
|
53
42
|
color: var(--color-on-surface);
|
|
54
43
|
font-size: 0.875rem;
|
|
55
44
|
line-height: 1.25rem;
|
|
56
|
-
font-weight: 500;
|
|
57
45
|
}
|
|
58
46
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
47
|
+
/* Hide core's separator ::before — we render separator text explicitly */
|
|
48
|
+
.breadcrumb-separator::before {
|
|
49
|
+
display: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.breadcrumb-separator {
|
|
53
|
+
opacity: 1;
|
|
63
54
|
}
|
|
64
55
|
|
|
65
56
|
/* Hide slotted separator template */
|
|
@@ -108,9 +99,9 @@ class ElDmBreadcrumbs extends BaseElement {
|
|
|
108
99
|
const escapedLabel = this._escapeHtml(item.label);
|
|
109
100
|
if (isLast) {
|
|
110
101
|
return `
|
|
111
|
-
<li class="
|
|
102
|
+
<li class="breadcrumb-item" part="item">
|
|
112
103
|
<span
|
|
113
|
-
class="
|
|
104
|
+
class="breadcrumb-item-active"
|
|
114
105
|
part="current"
|
|
115
106
|
aria-current="page"
|
|
116
107
|
>${escapedLabel}</span>
|
|
@@ -118,20 +109,20 @@ class ElDmBreadcrumbs extends BaseElement {
|
|
|
118
109
|
`;
|
|
119
110
|
}
|
|
120
111
|
return `
|
|
121
|
-
<li class="
|
|
112
|
+
<li class="breadcrumb-item" part="item">
|
|
122
113
|
<a
|
|
123
|
-
class="
|
|
114
|
+
class="breadcrumb-link"
|
|
124
115
|
part="link"
|
|
125
116
|
href="${item.href || "#"}"
|
|
126
117
|
data-index="${index}"
|
|
127
118
|
>${escapedLabel}</a>
|
|
128
|
-
<span class="
|
|
119
|
+
<span class="breadcrumb-separator" part="separator" aria-hidden="true">${separatorHtml}</span>
|
|
129
120
|
</li>
|
|
130
121
|
`;
|
|
131
122
|
}).join("");
|
|
132
123
|
return `
|
|
133
124
|
<nav class="breadcrumbs-nav" part="nav" aria-label="Breadcrumb">
|
|
134
|
-
<ol class="breadcrumbs
|
|
125
|
+
<ol class="breadcrumbs" part="list">
|
|
135
126
|
${itemsHtml}
|
|
136
127
|
</ol>
|
|
137
128
|
<slot name="separator"></slot>
|
|
@@ -140,7 +131,7 @@ class ElDmBreadcrumbs extends BaseElement {
|
|
|
140
131
|
}
|
|
141
132
|
update() {
|
|
142
133
|
super.update();
|
|
143
|
-
const links = this.shadowRoot?.querySelectorAll(".
|
|
134
|
+
const links = this.shadowRoot?.querySelectorAll(".breadcrumb-link");
|
|
144
135
|
links?.forEach((link) => {
|
|
145
136
|
const index = parseInt(link.getAttribute("data-index") || "0", 10);
|
|
146
137
|
const item = this.items[index];
|
|
@@ -161,5 +152,5 @@ function register() {
|
|
|
161
152
|
// src/register.ts
|
|
162
153
|
register();
|
|
163
154
|
|
|
164
|
-
//# debugId=
|
|
155
|
+
//# debugId=75B4D4D7AB43B86264756E2164756E21
|
|
165
156
|
//# sourceMappingURL=register.js.map
|
package/dist/esm/register.js.map
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/el-dm-breadcrumbs.ts", "../../src/index.ts", "../../src/register.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * DuskMoon Breadcrumbs Element\n *\n * A hierarchical navigation breadcrumbs component for displaying the user's\n * current location within a site structure.\n *\n * @element el-dm-breadcrumbs\n *\n * @attr {string} items - JSON array of breadcrumb items [{label, href}]\n * @attr {string} separator - Separator character between items (default '/')\n *\n * @slot separator - Custom separator element to use between items\n *\n * @csspart nav - The navigation container\n * @csspart list - The ordered list element\n * @csspart item - Individual breadcrumb item container\n * @csspart link - Breadcrumb link element\n * @csspart current - Current page text (last item)\n * @csspart separator - Separator element between items\n *\n * @fires navigate - Fired when a breadcrumb link is clicked. Detail: { item, index }\n */\n\nimport { BaseElement, css } from '@duskmoon-dev/el-core';\n\n/**\n * Represents a single breadcrumb item\n */\nexport interface BreadcrumbItem {\n /** Display label for the breadcrumb */\n label: string;\n /** URL for the breadcrumb link (optional for last item) */\n href?: string;\n}\n\n/**\n * Event detail for the navigate event\n */\nexport interface NavigateEventDetail {\n /** The breadcrumb item that was clicked */\n item: BreadcrumbItem;\n /** The index of the clicked item */\n index: number;\n}\n\nconst styles = css`\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n .breadcrumbs-nav {\n font-family: inherit;\n }\n\n .breadcrumbs
|
|
5
|
+
"/**\n * DuskMoon Breadcrumbs Element\n *\n * A hierarchical navigation breadcrumbs component for displaying the user's\n * current location within a site structure.\n *\n * @element el-dm-breadcrumbs\n *\n * @attr {string} items - JSON array of breadcrumb items [{label, href}]\n * @attr {string} separator - Separator character between items (default '/')\n *\n * @slot separator - Custom separator element to use between items\n *\n * @csspart nav - The navigation container\n * @csspart list - The ordered list element\n * @csspart item - Individual breadcrumb item container\n * @csspart link - Breadcrumb link element\n * @csspart current - Current page text (last item)\n * @csspart separator - Separator element between items\n *\n * @fires navigate - Fired when a breadcrumb link is clicked. Detail: { item, index }\n */\n\nimport { BaseElement, css } from '@duskmoon-dev/el-base';\nimport { css as navigationCSS } from '@duskmoon-dev/core/components/navigation';\n\n/**\n * Represents a single breadcrumb item\n */\nexport interface BreadcrumbItem {\n /** Display label for the breadcrumb */\n label: string;\n /** URL for the breadcrumb link (optional for last item) */\n href?: string;\n}\n\n/**\n * Event detail for the navigate event\n */\nexport interface NavigateEventDetail {\n /** The breadcrumb item that was clicked */\n item: BreadcrumbItem;\n /** The index of the clicked item */\n index: number;\n}\n\n// Strip @layer wrapper for Shadow DOM compatibility\nconst coreStyles = navigationCSS.replace(/@layer\\s+components\\s*\\{/, '').replace(/\\}\\s*$/, '');\n\nconst styles = css`\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n /* Import core navigation styles */\n ${coreStyles}\n\n .breadcrumbs-nav {\n font-family: inherit;\n }\n\n /* Override core .breadcrumbs padding since we manage our own layout */\n .breadcrumbs {\n padding: 0;\n }\n\n /* Override core .breadcrumb-link with our custom colors */\n .breadcrumb-link {\n color: var(--color-primary);\n }\n\n .breadcrumb-link:hover {\n color: var(--color-primary-dark, var(--color-primary));\n }\n\n .breadcrumb-link:focus {\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n border-radius: 2px;\n }\n\n .breadcrumb-item-active {\n color: var(--color-on-surface);\n font-size: 0.875rem;\n line-height: 1.25rem;\n }\n\n /* Hide core's separator ::before — we render separator text explicitly */\n .breadcrumb-separator::before {\n display: none;\n }\n\n .breadcrumb-separator {\n opacity: 1;\n }\n\n /* Hide slotted separator template */\n ::slotted([slot='separator']) {\n display: none;\n }\n`;\n\nexport class ElDmBreadcrumbs extends BaseElement {\n static properties = {\n items: { type: Array, reflect: false },\n separator: { type: String, reflect: true, default: '/' },\n };\n\n /** Array of breadcrumb items */\n declare items: BreadcrumbItem[];\n\n /** Separator character between items */\n declare separator: string;\n\n constructor() {\n super();\n this.attachStyles(styles);\n this.items = [];\n }\n\n /**\n * Handle click on a breadcrumb link\n */\n private _handleClick(event: Event, item: BreadcrumbItem, index: number): void {\n event.preventDefault();\n\n // emit returns true if event was not cancelled\n const notCancelled = this.emit<NavigateEventDetail>('navigate', {\n item,\n index,\n });\n\n // If event was not prevented, navigate to the href\n if (notCancelled && item.href) {\n window.location.href = item.href;\n }\n }\n\n /**\n * Get the separator HTML - either from slot or default\n */\n private _getSeparatorHtml(): string {\n const slottedSeparator = this.querySelector('[slot=\"separator\"]');\n if (slottedSeparator) {\n return slottedSeparator.outerHTML.replace('slot=\"separator\"', '');\n }\n return this.separator || '/';\n }\n\n /**\n * Escape HTML special characters to prevent XSS\n */\n private _escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n\n render(): string {\n const itemsArray = Array.isArray(this.items) ? this.items : [];\n const separatorHtml = this._getSeparatorHtml();\n\n const itemsHtml = itemsArray\n .map((item, index) => {\n const isLast = index === itemsArray.length - 1;\n const escapedLabel = this._escapeHtml(item.label);\n\n if (isLast) {\n // Last item is current page - not clickable\n return `\n <li class=\"breadcrumb-item\" part=\"item\">\n <span\n class=\"breadcrumb-item-active\"\n part=\"current\"\n aria-current=\"page\"\n >${escapedLabel}</span>\n </li>\n `;\n }\n\n // Regular breadcrumb link\n return `\n <li class=\"breadcrumb-item\" part=\"item\">\n <a\n class=\"breadcrumb-link\"\n part=\"link\"\n href=\"${item.href || '#'}\"\n data-index=\"${index}\"\n >${escapedLabel}</a>\n <span class=\"breadcrumb-separator\" part=\"separator\" aria-hidden=\"true\">${separatorHtml}</span>\n </li>\n `;\n })\n .join('');\n\n return `\n <nav class=\"breadcrumbs-nav\" part=\"nav\" aria-label=\"Breadcrumb\">\n <ol class=\"breadcrumbs\" part=\"list\">\n ${itemsHtml}\n </ol>\n <slot name=\"separator\"></slot>\n </nav>\n `;\n }\n\n update(): void {\n super.update();\n\n // Attach click handlers to all breadcrumb links\n const links = this.shadowRoot?.querySelectorAll('.breadcrumb-link');\n links?.forEach((link) => {\n const index = parseInt(link.getAttribute('data-index') || '0', 10);\n const item = this.items[index];\n if (item) {\n link.addEventListener('click', (e) => this._handleClick(e, item, index));\n }\n });\n }\n}\n",
|
|
6
6
|
"/**\n * @duskmoon-dev/el-breadcrumbs\n *\n * DuskMoon Breadcrumbs custom element\n */\n\nimport { ElDmBreadcrumbs } from './el-dm-breadcrumbs.js';\n\nexport { ElDmBreadcrumbs };\nexport type { BreadcrumbItem, NavigateEventDetail } from './el-dm-breadcrumbs.js';\n\n/**\n * Register the el-dm-breadcrumbs custom element\n *\n * @example\n * ```ts\n * import { register } from '@duskmoon-dev/el-breadcrumbs';\n * register();\n * ```\n */\nexport function register(): void {\n if (!customElements.get('el-dm-breadcrumbs')) {\n customElements.define('el-dm-breadcrumbs', ElDmBreadcrumbs);\n }\n}\n",
|
|
7
7
|
"/**\n * Auto-register el-dm-breadcrumbs custom element\n *\n * @example\n * ```ts\n * import '@duskmoon-dev/el-breadcrumbs/register';\n *\n * // Now you can use <el-dm-breadcrumbs> in HTML\n * ```\n */\nimport { register } from './index.js';\n\nregister();\n"
|
|
8
8
|
],
|
|
9
|
-
"mappings": ";AAuBA;
|
|
10
|
-
"debugId": "
|
|
9
|
+
"mappings": ";AAuBA;AACA,gBAAS;AAuBT,IAAM,aAAa,cAAc,QAAQ,4BAA4B,EAAE,EAAE,QAAQ,UAAU,EAAE;AAE7F,IAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA+CG,MAAM,wBAAwB,YAAY;AAAA,SACxC,aAAa;AAAA,IAClB,OAAO,EAAE,MAAM,OAAO,SAAS,MAAM;AAAA,IACrC,WAAW,EAAE,MAAM,QAAQ,SAAS,MAAM,SAAS,IAAI;AAAA,EACzD;AAAA,EAQA,WAAW,GAAG;AAAA,IACZ,MAAM;AAAA,IACN,KAAK,aAAa,MAAM;AAAA,IACxB,KAAK,QAAQ,CAAC;AAAA;AAAA,EAMR,YAAY,CAAC,OAAc,MAAsB,OAAqB;AAAA,IAC5E,MAAM,eAAe;AAAA,IAGrB,MAAM,eAAe,KAAK,KAA0B,YAAY;AAAA,MAC9D;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IAGD,IAAI,gBAAgB,KAAK,MAAM;AAAA,MAC7B,OAAO,SAAS,OAAO,KAAK;AAAA,IAC9B;AAAA;AAAA,EAMM,iBAAiB,GAAW;AAAA,IAClC,MAAM,mBAAmB,KAAK,cAAc,oBAAoB;AAAA,IAChE,IAAI,kBAAkB;AAAA,MACpB,OAAO,iBAAiB,UAAU,QAAQ,oBAAoB,EAAE;AAAA,IAClE;AAAA,IACA,OAAO,KAAK,aAAa;AAAA;AAAA,EAMnB,WAAW,CAAC,MAAsB;AAAA,IACxC,MAAM,MAAM,SAAS,cAAc,KAAK;AAAA,IACxC,IAAI,cAAc;AAAA,IAClB,OAAO,IAAI;AAAA;AAAA,EAGb,MAAM,GAAW;AAAA,IACf,MAAM,aAAa,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,QAAQ,CAAC;AAAA,IAC7D,MAAM,gBAAgB,KAAK,kBAAkB;AAAA,IAE7C,MAAM,YAAY,WACf,IAAI,CAAC,MAAM,UAAU;AAAA,MACpB,MAAM,SAAS,UAAU,WAAW,SAAS;AAAA,MAC7C,MAAM,eAAe,KAAK,YAAY,KAAK,KAAK;AAAA,MAEhD,IAAI,QAAQ;AAAA,QAEV,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAMA;AAAA;AAAA;AAAA,MAGT;AAAA,MAGA,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,sBAKO,KAAK,QAAQ;AAAA,4BACP;AAAA,eACb;AAAA,qFACsE;AAAA;AAAA;AAAA,KAG9E,EACA,KAAK,EAAE;AAAA,IAEV,OAAO;AAAA;AAAA;AAAA,YAGC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOV,MAAM,GAAS;AAAA,IACb,MAAM,OAAO;AAAA,IAGb,MAAM,QAAQ,KAAK,YAAY,iBAAiB,kBAAkB;AAAA,IAClE,OAAO,QAAQ,CAAC,SAAS;AAAA,MACvB,MAAM,QAAQ,SAAS,KAAK,aAAa,YAAY,KAAK,KAAK,EAAE;AAAA,MACjE,MAAM,OAAO,KAAK,MAAM;AAAA,MACxB,IAAI,MAAM;AAAA,QACR,KAAK,iBAAiB,SAAS,CAAC,MAAM,KAAK,aAAa,GAAG,MAAM,KAAK,CAAC;AAAA,MACzE;AAAA,KACD;AAAA;AAEL;;;AC1MO,SAAS,QAAQ,GAAS;AAAA,EAC/B,IAAI,CAAC,eAAe,IAAI,mBAAmB,GAAG;AAAA,IAC5C,eAAe,OAAO,qBAAqB,eAAe;AAAA,EAC5D;AAAA;;;ACXF,SAAS;",
|
|
10
|
+
"debugId": "75B4D4D7AB43B86264756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|