@stacksjs/components 0.2.113 → 0.2.115
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.
|
@@ -67,6 +67,8 @@ export const activeClasses = themeStyle.item.active
|
|
|
67
67
|
</script>
|
|
68
68
|
|
|
69
69
|
<script client>
|
|
70
|
+
import { findActiveSidebarHref } from './route-selection'
|
|
71
|
+
|
|
70
72
|
const emit = defineEmits()
|
|
71
73
|
const sidebarUidProp = '{{ sidebarUid }}'
|
|
72
74
|
const collapsedProp = {{ collapsed }}
|
|
@@ -100,12 +102,33 @@ function setActiveRow(button) {
|
|
|
100
102
|
const classes = activeClassList()
|
|
101
103
|
pane.querySelectorAll('[data-sidebar-item][data-active="true"]').forEach((el) => {
|
|
102
104
|
el.removeAttribute('data-active')
|
|
105
|
+
el.removeAttribute('aria-current')
|
|
103
106
|
el.classList.remove(...classes)
|
|
104
107
|
})
|
|
105
108
|
button.setAttribute('data-active', 'true')
|
|
109
|
+
button.setAttribute('aria-current', 'page')
|
|
106
110
|
button.classList.add(...classes)
|
|
107
111
|
}
|
|
108
112
|
|
|
113
|
+
function syncRouteSelection(url) {
|
|
114
|
+
const links = [...pane.querySelectorAll('a[data-sidebar-item][href]')]
|
|
115
|
+
let currentPath = window.location.pathname
|
|
116
|
+
if (url) {
|
|
117
|
+
try {
|
|
118
|
+
currentPath = new URL(url, window.location.origin).pathname
|
|
119
|
+
}
|
|
120
|
+
catch {}
|
|
121
|
+
}
|
|
122
|
+
const href = findActiveSidebarHref(currentPath, links.map(link => link.getAttribute('href') || ''))
|
|
123
|
+
const active = href ? links.find(link => link.getAttribute('href') === href) : null
|
|
124
|
+
if (active)
|
|
125
|
+
setActiveRow(active)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function onRouteChange(event) {
|
|
129
|
+
syncRouteSelection(event?.detail?.url)
|
|
130
|
+
}
|
|
131
|
+
|
|
109
132
|
// ---------------------------------------------------------------------------
|
|
110
133
|
// Disclosure — rows know their ancestors (data-parents="a/b"). Collapsing a
|
|
111
134
|
// row (or section) marks every descendant with data-collapsed, which the
|
|
@@ -323,18 +346,22 @@ onMount(() => {
|
|
|
323
346
|
|
|
324
347
|
pane.addEventListener('click', onClick)
|
|
325
348
|
pane.addEventListener('keydown', onKeyDown)
|
|
349
|
+
window.addEventListener('stx:navigate', onRouteChange)
|
|
350
|
+
window.addEventListener('popstate', onRouteChange)
|
|
326
351
|
|
|
327
352
|
const scrollArea = pane.querySelector('[data-sidebar-scroll]')
|
|
328
353
|
const thumb = pane.querySelector('[data-sidebar-scroll-thumb]')
|
|
329
354
|
if (scrollArea && thumb) attachOverlayScrollbar(scrollArea, thumb)
|
|
330
355
|
|
|
331
|
-
//
|
|
356
|
+
// Route-derived selection wins over stale server-declared state on direct
|
|
357
|
+
// loads, nested routes, SPA transitions, and browser history navigation.
|
|
358
|
+
syncRouteSelection()
|
|
332
359
|
const active = pane.querySelector('[data-sidebar-item][data-active="true"]')
|
|
333
360
|
if (active) active.classList.add(...activeClassList())
|
|
334
361
|
syncRowVisibility()
|
|
335
362
|
})
|
|
336
363
|
|
|
337
|
-
defineExpose({ collapsed, toggle: toggleCollapse })
|
|
364
|
+
defineExpose({ collapsed, toggle: toggleCollapse, syncRouteSelection })
|
|
338
365
|
</script>
|
|
339
366
|
|
|
340
367
|
<aside
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
// ../../../../../../../tmp/stx-components-build-
|
|
2
|
+
// ../../../../../../../tmp/stx-components-build-mg2saM/stubs/stub-0.js
|
|
3
3
|
var stub_0_default = { __stx: true, src: "./components/CodeBlock.stx" };
|
|
4
|
-
// ../../../../../../../tmp/stx-components-build-
|
|
4
|
+
// ../../../../../../../tmp/stx-components-build-mg2saM/stubs/stub-1.js
|
|
5
5
|
var stub_1_default = { __stx: true, src: "./components/Footer.stx" };
|
|
6
|
-
// ../../../../../../../tmp/stx-components-build-
|
|
6
|
+
// ../../../../../../../tmp/stx-components-build-mg2saM/stubs/stub-2.js
|
|
7
7
|
var stub_2_default = { __stx: true, src: "./components/Hero.stx" };
|
|
8
|
-
// ../../../../../../../tmp/stx-components-build-
|
|
8
|
+
// ../../../../../../../tmp/stx-components-build-mg2saM/stubs/stub-3.js
|
|
9
9
|
var stub_3_default = { __stx: true, src: "./components/Installation.stx" };
|
|
10
10
|
// src/composables/useCopyCode.ts
|
|
11
11
|
function useCopyCode(options) {
|
|
@@ -1132,7 +1132,7 @@ var RadioGroupOption_default = "./RadioGroupOption-s1d6r221.stx";
|
|
|
1132
1132
|
// src/ui/select/Select.stx
|
|
1133
1133
|
var Select_default = "./Select-1vnd0brz.stx";
|
|
1134
1134
|
// src/ui/sidebar/Sidebar.stx
|
|
1135
|
-
var Sidebar_default = "./Sidebar-
|
|
1135
|
+
var Sidebar_default = "./Sidebar-hjazqxv8.stx";
|
|
1136
1136
|
// src/ui/sidebar/SidebarFooter.stx
|
|
1137
1137
|
var SidebarFooter_default = "./SidebarFooter-0aegr99p.stx";
|
|
1138
1138
|
// src/ui/sidebar/SidebarHeader.stx
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function findActiveSidebarHref(currentPath: string, hrefs: string[]): string | null;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/components",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.115",
|
|
5
5
|
"description": "A modern component library built with STX, featuring headwind utility classes and TypeScript syntax highlighting.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.org>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
65
|
"@cwcss/crosswind": "^0.2.12",
|
|
66
|
-
"@stacksjs/stx": "0.2.
|
|
67
|
-
"bun-plugin-stx": "0.2.
|
|
66
|
+
"@stacksjs/stx": "0.2.115",
|
|
67
|
+
"bun-plugin-stx": "0.2.115",
|
|
68
68
|
"ts-syntax-highlighter": "^0.2.1"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
@@ -67,6 +67,8 @@ export const activeClasses = themeStyle.item.active
|
|
|
67
67
|
</script>
|
|
68
68
|
|
|
69
69
|
<script client>
|
|
70
|
+
import { findActiveSidebarHref } from './route-selection'
|
|
71
|
+
|
|
70
72
|
const emit = defineEmits()
|
|
71
73
|
const sidebarUidProp = '{{ sidebarUid }}'
|
|
72
74
|
const collapsedProp = {{ collapsed }}
|
|
@@ -100,12 +102,33 @@ function setActiveRow(button) {
|
|
|
100
102
|
const classes = activeClassList()
|
|
101
103
|
pane.querySelectorAll('[data-sidebar-item][data-active="true"]').forEach((el) => {
|
|
102
104
|
el.removeAttribute('data-active')
|
|
105
|
+
el.removeAttribute('aria-current')
|
|
103
106
|
el.classList.remove(...classes)
|
|
104
107
|
})
|
|
105
108
|
button.setAttribute('data-active', 'true')
|
|
109
|
+
button.setAttribute('aria-current', 'page')
|
|
106
110
|
button.classList.add(...classes)
|
|
107
111
|
}
|
|
108
112
|
|
|
113
|
+
function syncRouteSelection(url) {
|
|
114
|
+
const links = [...pane.querySelectorAll('a[data-sidebar-item][href]')]
|
|
115
|
+
let currentPath = window.location.pathname
|
|
116
|
+
if (url) {
|
|
117
|
+
try {
|
|
118
|
+
currentPath = new URL(url, window.location.origin).pathname
|
|
119
|
+
}
|
|
120
|
+
catch {}
|
|
121
|
+
}
|
|
122
|
+
const href = findActiveSidebarHref(currentPath, links.map(link => link.getAttribute('href') || ''))
|
|
123
|
+
const active = href ? links.find(link => link.getAttribute('href') === href) : null
|
|
124
|
+
if (active)
|
|
125
|
+
setActiveRow(active)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function onRouteChange(event) {
|
|
129
|
+
syncRouteSelection(event?.detail?.url)
|
|
130
|
+
}
|
|
131
|
+
|
|
109
132
|
// ---------------------------------------------------------------------------
|
|
110
133
|
// Disclosure — rows know their ancestors (data-parents="a/b"). Collapsing a
|
|
111
134
|
// row (or section) marks every descendant with data-collapsed, which the
|
|
@@ -323,18 +346,22 @@ onMount(() => {
|
|
|
323
346
|
|
|
324
347
|
pane.addEventListener('click', onClick)
|
|
325
348
|
pane.addEventListener('keydown', onKeyDown)
|
|
349
|
+
window.addEventListener('stx:navigate', onRouteChange)
|
|
350
|
+
window.addEventListener('popstate', onRouteChange)
|
|
326
351
|
|
|
327
352
|
const scrollArea = pane.querySelector('[data-sidebar-scroll]')
|
|
328
353
|
const thumb = pane.querySelector('[data-sidebar-scroll-thumb]')
|
|
329
354
|
if (scrollArea && thumb) attachOverlayScrollbar(scrollArea, thumb)
|
|
330
355
|
|
|
331
|
-
//
|
|
356
|
+
// Route-derived selection wins over stale server-declared state on direct
|
|
357
|
+
// loads, nested routes, SPA transitions, and browser history navigation.
|
|
358
|
+
syncRouteSelection()
|
|
332
359
|
const active = pane.querySelector('[data-sidebar-item][data-active="true"]')
|
|
333
360
|
if (active) active.classList.add(...activeClassList())
|
|
334
361
|
syncRowVisibility()
|
|
335
362
|
})
|
|
336
363
|
|
|
337
|
-
defineExpose({ collapsed, toggle: toggleCollapse })
|
|
364
|
+
defineExpose({ collapsed, toggle: toggleCollapse, syncRouteSelection })
|
|
338
365
|
</script>
|
|
339
366
|
|
|
340
367
|
<aside
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
function normalizePath(path: string): string {
|
|
2
|
+
const clean = (path || '/').split(/[?#]/, 1)[0] || '/'
|
|
3
|
+
const withSlash = clean.startsWith('/') ? clean : `/${clean}`
|
|
4
|
+
return withSlash.replace(/\/+$/, '') || '/'
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function isLocalHref(href: string): boolean {
|
|
8
|
+
return href.startsWith('/') && !href.startsWith('//')
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function findActiveSidebarHref(currentPath: string, hrefs: string[]): string | null {
|
|
12
|
+
const current = normalizePath(currentPath)
|
|
13
|
+
let best: string | null = null
|
|
14
|
+
let bestLength = -1
|
|
15
|
+
|
|
16
|
+
for (const href of hrefs) {
|
|
17
|
+
if (!isLocalHref(href))
|
|
18
|
+
continue
|
|
19
|
+
|
|
20
|
+
const candidate = normalizePath(href)
|
|
21
|
+
const matches = candidate === '/'
|
|
22
|
+
? current === '/'
|
|
23
|
+
: current === candidate || current.startsWith(`${candidate}/`)
|
|
24
|
+
|
|
25
|
+
if (matches && candidate.length > bestLength) {
|
|
26
|
+
best = href
|
|
27
|
+
bestLength = candidate.length
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return best
|
|
32
|
+
}
|