@real-router/solid 0.2.10 → 0.2.11
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/cjs/index.js +128 -9
- package/dist/esm/index.mjs +128 -9
- package/dist/types/components/Link.d.ts.map +1 -1
- package/dist/types/directives/link.d.ts.map +1 -1
- package/dist/types/dom-utils/index.d.ts +4 -0
- package/dist/types/dom-utils/index.d.ts.map +1 -0
- package/dist/types/dom-utils/link-utils.d.ts +6 -0
- package/dist/types/dom-utils/link-utils.d.ts.map +1 -0
- package/dist/types/dom-utils/route-announcer.d.ts +9 -0
- package/dist/types/dom-utils/route-announcer.d.ts.map +1 -0
- package/package.json +2 -3
- package/src/RouterProvider.tsx +1 -1
- package/src/components/Link.tsx +5 -1
- package/src/directives/link.tsx +5 -1
package/dist/cjs/index.js
CHANGED
|
@@ -148,8 +148,6 @@ const RouteView = Object.assign(RouteViewRoot, {
|
|
|
148
148
|
NotFound
|
|
149
149
|
});
|
|
150
150
|
|
|
151
|
-
const e=`data-real-router-announcer`;function t(e,t){let o=`Navigated to `,c=true,l=false,u=false,d=``,f,p=n(),m=setTimeout(()=>{l=true;},100),h=e.subscribe(({route:e})=>{if(c){c=false;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(u)return;let t=i(e,o);t&&t!==d&&l&&(d=t,clearTimeout(f),p.textContent=t,f=setTimeout(()=>{p.textContent=``,d=``;},7e3),a());});});});return {destroy(){u=true,h(),clearTimeout(f),clearTimeout(m),r();}}}function n(){let t=document.querySelector(`[${e}]`);if(t)return t;let n=document.createElement(`div`);return n.setAttribute(`style`,`position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0`),n.setAttribute(`aria-live`,`assertive`),n.setAttribute(`aria-atomic`,`true`),n.setAttribute(e,``),document.body.prepend(n),n}function r(){document.querySelector(`[${e}]`)?.remove();}function i(e,t,n){let r=document.querySelector(`h1`)?.textContent.trim()??``,i=e.name.startsWith(`@@`)?``:e.name;return `${t}${r||document.title||i||globalThis.location.pathname}`}function a(){let e=document.querySelector(`h1`);e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:true}));}function o(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function s(e,t,n){try{let r=e.buildUrl;return r?r(t,n):e.buildPath(t,n)}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function c(e,t,n){return e&&t?n?`${n} ${t}`.trim():t:n??void 0}function l(e){e instanceof HTMLAnchorElement||e instanceof HTMLButtonElement||(e.getAttribute(`role`)||e.setAttribute(`role`,`link`),e.getAttribute(`tabindex`)||e.setAttribute(`tabindex`,`0`));}
|
|
152
|
-
|
|
153
151
|
/**
|
|
154
152
|
* Stable empty object for default params
|
|
155
153
|
*/
|
|
@@ -160,6 +158,127 @@ const EMPTY_PARAMS = Object.freeze({});
|
|
|
160
158
|
*/
|
|
161
159
|
const EMPTY_OPTIONS = Object.freeze({});
|
|
162
160
|
|
|
161
|
+
const CLEAR_DELAY = 7000;
|
|
162
|
+
const SAFARI_READY_DELAY = 100;
|
|
163
|
+
const ANNOUNCER_ATTR = "data-real-router-announcer";
|
|
164
|
+
const INTERNAL_ROUTE_PREFIX = "@@";
|
|
165
|
+
const VISUALLY_HIDDEN = "position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0";
|
|
166
|
+
function createRouteAnnouncer(router, options) {
|
|
167
|
+
const prefix = "Navigated to ";
|
|
168
|
+
let isInitialNavigation = true;
|
|
169
|
+
let isReady = false;
|
|
170
|
+
let isDestroyed = false;
|
|
171
|
+
let lastAnnouncedText = "";
|
|
172
|
+
let clearTimeoutId;
|
|
173
|
+
const announcer = getOrCreateAnnouncer();
|
|
174
|
+
const safariTimeoutId = setTimeout(() => {
|
|
175
|
+
isReady = true;
|
|
176
|
+
}, SAFARI_READY_DELAY);
|
|
177
|
+
const unsubscribe = router.subscribe(({
|
|
178
|
+
route
|
|
179
|
+
}) => {
|
|
180
|
+
if (isInitialNavigation) {
|
|
181
|
+
isInitialNavigation = false;
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
requestAnimationFrame(() => {
|
|
185
|
+
requestAnimationFrame(() => {
|
|
186
|
+
if (isDestroyed) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const text = resolveText(route, prefix);
|
|
190
|
+
if (text && text !== lastAnnouncedText && isReady) {
|
|
191
|
+
lastAnnouncedText = text;
|
|
192
|
+
clearTimeout(clearTimeoutId);
|
|
193
|
+
announcer.textContent = text;
|
|
194
|
+
clearTimeoutId = setTimeout(() => {
|
|
195
|
+
announcer.textContent = "";
|
|
196
|
+
lastAnnouncedText = "";
|
|
197
|
+
}, CLEAR_DELAY);
|
|
198
|
+
manageFocus();
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
return {
|
|
204
|
+
destroy() {
|
|
205
|
+
isDestroyed = true;
|
|
206
|
+
unsubscribe();
|
|
207
|
+
clearTimeout(clearTimeoutId);
|
|
208
|
+
clearTimeout(safariTimeoutId);
|
|
209
|
+
removeAnnouncer();
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function getOrCreateAnnouncer() {
|
|
214
|
+
const existing = document.querySelector(`[${ANNOUNCER_ATTR}]`);
|
|
215
|
+
if (existing) {
|
|
216
|
+
return existing;
|
|
217
|
+
}
|
|
218
|
+
const element = document.createElement("div");
|
|
219
|
+
element.setAttribute("style", VISUALLY_HIDDEN);
|
|
220
|
+
element.setAttribute("aria-live", "assertive");
|
|
221
|
+
element.setAttribute("aria-atomic", "true");
|
|
222
|
+
element.setAttribute(ANNOUNCER_ATTR, "");
|
|
223
|
+
document.body.prepend(element);
|
|
224
|
+
return element;
|
|
225
|
+
}
|
|
226
|
+
function removeAnnouncer() {
|
|
227
|
+
document.querySelector(`[${ANNOUNCER_ATTR}]`)?.remove();
|
|
228
|
+
}
|
|
229
|
+
function resolveText(route, prefix, getCustomText) {
|
|
230
|
+
const h1 = document.querySelector("h1");
|
|
231
|
+
const h1Text = h1?.textContent.trim() ?? "";
|
|
232
|
+
const routeName = route.name.startsWith(INTERNAL_ROUTE_PREFIX) ? "" : route.name;
|
|
233
|
+
const rawText = h1Text || document.title || routeName || globalThis.location.pathname;
|
|
234
|
+
return `${prefix}${rawText}`;
|
|
235
|
+
}
|
|
236
|
+
function manageFocus() {
|
|
237
|
+
const h1 = document.querySelector("h1");
|
|
238
|
+
if (!h1) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (!h1.hasAttribute("tabindex")) {
|
|
242
|
+
h1.setAttribute("tabindex", "-1");
|
|
243
|
+
}
|
|
244
|
+
h1.focus({
|
|
245
|
+
preventScroll: true
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function shouldNavigate(evt) {
|
|
250
|
+
return evt.button === 0 && !evt.metaKey && !evt.altKey && !evt.ctrlKey && !evt.shiftKey;
|
|
251
|
+
}
|
|
252
|
+
function buildHref(router, routeName, routeParams) {
|
|
253
|
+
try {
|
|
254
|
+
const buildUrl = router.buildUrl;
|
|
255
|
+
if (buildUrl) {
|
|
256
|
+
return buildUrl(routeName, routeParams);
|
|
257
|
+
}
|
|
258
|
+
return router.buildPath(routeName, routeParams);
|
|
259
|
+
} catch {
|
|
260
|
+
console.error(`[real-router] Route "${routeName}" is not defined. The element will render without an href attribute.`);
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function buildActiveClassName(isActive, activeClassName, baseClassName) {
|
|
265
|
+
if (isActive && activeClassName) {
|
|
266
|
+
return baseClassName ? `${baseClassName} ${activeClassName}`.trim() : activeClassName;
|
|
267
|
+
}
|
|
268
|
+
return baseClassName ?? undefined;
|
|
269
|
+
}
|
|
270
|
+
function applyLinkA11y(element) {
|
|
271
|
+
if (element instanceof HTMLAnchorElement || element instanceof HTMLButtonElement) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
if (!element.getAttribute("role")) {
|
|
275
|
+
element.setAttribute("role", "link");
|
|
276
|
+
}
|
|
277
|
+
if (!element.getAttribute("tabindex")) {
|
|
278
|
+
element.setAttribute("tabindex", "0");
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
163
282
|
var _tmpl$ = /*#__PURE__*/web.template(`<a>`);
|
|
164
283
|
function Link(props) {
|
|
165
284
|
const merged = solidJs.mergeProps({
|
|
@@ -177,7 +296,7 @@ function Link(props) {
|
|
|
177
296
|
strict: local.activeStrict,
|
|
178
297
|
ignoreQueryParams: local.ignoreQueryParams
|
|
179
298
|
}));
|
|
180
|
-
const href = solidJs.createMemo(() =>
|
|
299
|
+
const href = solidJs.createMemo(() => buildHref(router, local.routeName, local.routeParams));
|
|
181
300
|
const handleClick = evt => {
|
|
182
301
|
if (local.onClick) {
|
|
183
302
|
local.onClick(evt);
|
|
@@ -185,13 +304,13 @@ function Link(props) {
|
|
|
185
304
|
return;
|
|
186
305
|
}
|
|
187
306
|
}
|
|
188
|
-
if (!
|
|
307
|
+
if (!shouldNavigate(evt) || local.target === "_blank") {
|
|
189
308
|
return;
|
|
190
309
|
}
|
|
191
310
|
evt.preventDefault();
|
|
192
311
|
router.navigate(local.routeName, local.routeParams, local.routeOptions).catch(() => {});
|
|
193
312
|
};
|
|
194
|
-
const finalClassName = solidJs.createMemo(() =>
|
|
313
|
+
const finalClassName = solidJs.createMemo(() => buildActiveClassName(isActive(), local.activeClassName, local.class));
|
|
195
314
|
return (() => {
|
|
196
315
|
var _el$ = _tmpl$();
|
|
197
316
|
web.spread(_el$, web.mergeProps(rest, {
|
|
@@ -245,14 +364,14 @@ function link(element, accessor) {
|
|
|
245
364
|
|
|
246
365
|
// Set href on <a> elements
|
|
247
366
|
if (element instanceof HTMLAnchorElement) {
|
|
248
|
-
const href =
|
|
367
|
+
const href = buildHref(router, options.routeName, options.routeParams ?? EMPTY_PARAMS);
|
|
249
368
|
if (href === undefined) {
|
|
250
369
|
element.removeAttribute("href");
|
|
251
370
|
} else {
|
|
252
371
|
element.href = href;
|
|
253
372
|
}
|
|
254
373
|
}
|
|
255
|
-
|
|
374
|
+
applyLinkA11y(element);
|
|
256
375
|
|
|
257
376
|
// Active class tracking (reactive)
|
|
258
377
|
if (options.activeClassName) {
|
|
@@ -269,7 +388,7 @@ function link(element, accessor) {
|
|
|
269
388
|
|
|
270
389
|
// Click handler
|
|
271
390
|
function handleClick(evt) {
|
|
272
|
-
if (!
|
|
391
|
+
if (!shouldNavigate(evt)) {
|
|
273
392
|
return;
|
|
274
393
|
}
|
|
275
394
|
if (element instanceof HTMLAnchorElement) {
|
|
@@ -341,7 +460,7 @@ function RouterProvider(props) {
|
|
|
341
460
|
if (!props.announceNavigation) {
|
|
342
461
|
return;
|
|
343
462
|
}
|
|
344
|
-
const announcer =
|
|
463
|
+
const announcer = createRouteAnnouncer(props.router);
|
|
345
464
|
solidJs.onCleanup(() => {
|
|
346
465
|
announcer.destroy();
|
|
347
466
|
});
|
package/dist/esm/index.mjs
CHANGED
|
@@ -146,8 +146,6 @@ const RouteView = Object.assign(RouteViewRoot, {
|
|
|
146
146
|
NotFound
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
-
const e=`data-real-router-announcer`;function t(e,t){let o=`Navigated to `,c=true,l=false,u=false,d=``,f,p=n(),m=setTimeout(()=>{l=true;},100),h=e.subscribe(({route:e})=>{if(c){c=false;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(u)return;let t=i(e,o);t&&t!==d&&l&&(d=t,clearTimeout(f),p.textContent=t,f=setTimeout(()=>{p.textContent=``,d=``;},7e3),a());});});});return {destroy(){u=true,h(),clearTimeout(f),clearTimeout(m),r();}}}function n(){let t=document.querySelector(`[${e}]`);if(t)return t;let n=document.createElement(`div`);return n.setAttribute(`style`,`position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0`),n.setAttribute(`aria-live`,`assertive`),n.setAttribute(`aria-atomic`,`true`),n.setAttribute(e,``),document.body.prepend(n),n}function r(){document.querySelector(`[${e}]`)?.remove();}function i(e,t,n){let r=document.querySelector(`h1`)?.textContent.trim()??``,i=e.name.startsWith(`@@`)?``:e.name;return `${t}${r||document.title||i||globalThis.location.pathname}`}function a(){let e=document.querySelector(`h1`);e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:true}));}function o(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function s(e,t,n){try{let r=e.buildUrl;return r?r(t,n):e.buildPath(t,n)}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function c(e,t,n){return e&&t?n?`${n} ${t}`.trim():t:n??void 0}function l(e){e instanceof HTMLAnchorElement||e instanceof HTMLButtonElement||(e.getAttribute(`role`)||e.setAttribute(`role`,`link`),e.getAttribute(`tabindex`)||e.setAttribute(`tabindex`,`0`));}
|
|
150
|
-
|
|
151
149
|
/**
|
|
152
150
|
* Stable empty object for default params
|
|
153
151
|
*/
|
|
@@ -158,6 +156,127 @@ const EMPTY_PARAMS = Object.freeze({});
|
|
|
158
156
|
*/
|
|
159
157
|
const EMPTY_OPTIONS = Object.freeze({});
|
|
160
158
|
|
|
159
|
+
const CLEAR_DELAY = 7000;
|
|
160
|
+
const SAFARI_READY_DELAY = 100;
|
|
161
|
+
const ANNOUNCER_ATTR = "data-real-router-announcer";
|
|
162
|
+
const INTERNAL_ROUTE_PREFIX = "@@";
|
|
163
|
+
const VISUALLY_HIDDEN = "position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0";
|
|
164
|
+
function createRouteAnnouncer(router, options) {
|
|
165
|
+
const prefix = "Navigated to ";
|
|
166
|
+
let isInitialNavigation = true;
|
|
167
|
+
let isReady = false;
|
|
168
|
+
let isDestroyed = false;
|
|
169
|
+
let lastAnnouncedText = "";
|
|
170
|
+
let clearTimeoutId;
|
|
171
|
+
const announcer = getOrCreateAnnouncer();
|
|
172
|
+
const safariTimeoutId = setTimeout(() => {
|
|
173
|
+
isReady = true;
|
|
174
|
+
}, SAFARI_READY_DELAY);
|
|
175
|
+
const unsubscribe = router.subscribe(({
|
|
176
|
+
route
|
|
177
|
+
}) => {
|
|
178
|
+
if (isInitialNavigation) {
|
|
179
|
+
isInitialNavigation = false;
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
requestAnimationFrame(() => {
|
|
183
|
+
requestAnimationFrame(() => {
|
|
184
|
+
if (isDestroyed) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const text = resolveText(route, prefix);
|
|
188
|
+
if (text && text !== lastAnnouncedText && isReady) {
|
|
189
|
+
lastAnnouncedText = text;
|
|
190
|
+
clearTimeout(clearTimeoutId);
|
|
191
|
+
announcer.textContent = text;
|
|
192
|
+
clearTimeoutId = setTimeout(() => {
|
|
193
|
+
announcer.textContent = "";
|
|
194
|
+
lastAnnouncedText = "";
|
|
195
|
+
}, CLEAR_DELAY);
|
|
196
|
+
manageFocus();
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
return {
|
|
202
|
+
destroy() {
|
|
203
|
+
isDestroyed = true;
|
|
204
|
+
unsubscribe();
|
|
205
|
+
clearTimeout(clearTimeoutId);
|
|
206
|
+
clearTimeout(safariTimeoutId);
|
|
207
|
+
removeAnnouncer();
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function getOrCreateAnnouncer() {
|
|
212
|
+
const existing = document.querySelector(`[${ANNOUNCER_ATTR}]`);
|
|
213
|
+
if (existing) {
|
|
214
|
+
return existing;
|
|
215
|
+
}
|
|
216
|
+
const element = document.createElement("div");
|
|
217
|
+
element.setAttribute("style", VISUALLY_HIDDEN);
|
|
218
|
+
element.setAttribute("aria-live", "assertive");
|
|
219
|
+
element.setAttribute("aria-atomic", "true");
|
|
220
|
+
element.setAttribute(ANNOUNCER_ATTR, "");
|
|
221
|
+
document.body.prepend(element);
|
|
222
|
+
return element;
|
|
223
|
+
}
|
|
224
|
+
function removeAnnouncer() {
|
|
225
|
+
document.querySelector(`[${ANNOUNCER_ATTR}]`)?.remove();
|
|
226
|
+
}
|
|
227
|
+
function resolveText(route, prefix, getCustomText) {
|
|
228
|
+
const h1 = document.querySelector("h1");
|
|
229
|
+
const h1Text = h1?.textContent.trim() ?? "";
|
|
230
|
+
const routeName = route.name.startsWith(INTERNAL_ROUTE_PREFIX) ? "" : route.name;
|
|
231
|
+
const rawText = h1Text || document.title || routeName || globalThis.location.pathname;
|
|
232
|
+
return `${prefix}${rawText}`;
|
|
233
|
+
}
|
|
234
|
+
function manageFocus() {
|
|
235
|
+
const h1 = document.querySelector("h1");
|
|
236
|
+
if (!h1) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (!h1.hasAttribute("tabindex")) {
|
|
240
|
+
h1.setAttribute("tabindex", "-1");
|
|
241
|
+
}
|
|
242
|
+
h1.focus({
|
|
243
|
+
preventScroll: true
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function shouldNavigate(evt) {
|
|
248
|
+
return evt.button === 0 && !evt.metaKey && !evt.altKey && !evt.ctrlKey && !evt.shiftKey;
|
|
249
|
+
}
|
|
250
|
+
function buildHref(router, routeName, routeParams) {
|
|
251
|
+
try {
|
|
252
|
+
const buildUrl = router.buildUrl;
|
|
253
|
+
if (buildUrl) {
|
|
254
|
+
return buildUrl(routeName, routeParams);
|
|
255
|
+
}
|
|
256
|
+
return router.buildPath(routeName, routeParams);
|
|
257
|
+
} catch {
|
|
258
|
+
console.error(`[real-router] Route "${routeName}" is not defined. The element will render without an href attribute.`);
|
|
259
|
+
return undefined;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function buildActiveClassName(isActive, activeClassName, baseClassName) {
|
|
263
|
+
if (isActive && activeClassName) {
|
|
264
|
+
return baseClassName ? `${baseClassName} ${activeClassName}`.trim() : activeClassName;
|
|
265
|
+
}
|
|
266
|
+
return baseClassName ?? undefined;
|
|
267
|
+
}
|
|
268
|
+
function applyLinkA11y(element) {
|
|
269
|
+
if (element instanceof HTMLAnchorElement || element instanceof HTMLButtonElement) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (!element.getAttribute("role")) {
|
|
273
|
+
element.setAttribute("role", "link");
|
|
274
|
+
}
|
|
275
|
+
if (!element.getAttribute("tabindex")) {
|
|
276
|
+
element.setAttribute("tabindex", "0");
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
161
280
|
var _tmpl$ = /*#__PURE__*/template(`<a>`);
|
|
162
281
|
function Link(props) {
|
|
163
282
|
const merged = mergeProps({
|
|
@@ -175,7 +294,7 @@ function Link(props) {
|
|
|
175
294
|
strict: local.activeStrict,
|
|
176
295
|
ignoreQueryParams: local.ignoreQueryParams
|
|
177
296
|
}));
|
|
178
|
-
const href = createMemo(() =>
|
|
297
|
+
const href = createMemo(() => buildHref(router, local.routeName, local.routeParams));
|
|
179
298
|
const handleClick = evt => {
|
|
180
299
|
if (local.onClick) {
|
|
181
300
|
local.onClick(evt);
|
|
@@ -183,13 +302,13 @@ function Link(props) {
|
|
|
183
302
|
return;
|
|
184
303
|
}
|
|
185
304
|
}
|
|
186
|
-
if (!
|
|
305
|
+
if (!shouldNavigate(evt) || local.target === "_blank") {
|
|
187
306
|
return;
|
|
188
307
|
}
|
|
189
308
|
evt.preventDefault();
|
|
190
309
|
router.navigate(local.routeName, local.routeParams, local.routeOptions).catch(() => {});
|
|
191
310
|
};
|
|
192
|
-
const finalClassName = createMemo(() =>
|
|
311
|
+
const finalClassName = createMemo(() => buildActiveClassName(isActive(), local.activeClassName, local.class));
|
|
193
312
|
return (() => {
|
|
194
313
|
var _el$ = _tmpl$();
|
|
195
314
|
spread(_el$, mergeProps$1(rest, {
|
|
@@ -243,14 +362,14 @@ function link(element, accessor) {
|
|
|
243
362
|
|
|
244
363
|
// Set href on <a> elements
|
|
245
364
|
if (element instanceof HTMLAnchorElement) {
|
|
246
|
-
const href =
|
|
365
|
+
const href = buildHref(router, options.routeName, options.routeParams ?? EMPTY_PARAMS);
|
|
247
366
|
if (href === undefined) {
|
|
248
367
|
element.removeAttribute("href");
|
|
249
368
|
} else {
|
|
250
369
|
element.href = href;
|
|
251
370
|
}
|
|
252
371
|
}
|
|
253
|
-
|
|
372
|
+
applyLinkA11y(element);
|
|
254
373
|
|
|
255
374
|
// Active class tracking (reactive)
|
|
256
375
|
if (options.activeClassName) {
|
|
@@ -267,7 +386,7 @@ function link(element, accessor) {
|
|
|
267
386
|
|
|
268
387
|
// Click handler
|
|
269
388
|
function handleClick(evt) {
|
|
270
|
-
if (!
|
|
389
|
+
if (!shouldNavigate(evt)) {
|
|
271
390
|
return;
|
|
272
391
|
}
|
|
273
392
|
if (element instanceof HTMLAnchorElement) {
|
|
@@ -339,7 +458,7 @@ function RouterProvider(props) {
|
|
|
339
458
|
if (!props.announceNavigation) {
|
|
340
459
|
return;
|
|
341
460
|
}
|
|
342
|
-
const announcer =
|
|
461
|
+
const announcer = createRouteAnnouncer(props.router);
|
|
343
462
|
onCleanup(() => {
|
|
344
463
|
announcer.destroy();
|
|
345
464
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../../src/components/Link.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../../src/components/Link.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAEpC,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC5C,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAC5B,GAAG,CAAC,OAAO,CAgFb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/directives/link.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/directives/link.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,CAAC,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC5C,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,MAAM,oBAAoB,CAAC,CAAC,CAAC,GACtC,IAAI,CA+DN"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dom-utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EACL,cAAc,EACd,SAAS,EACT,oBAAoB,EACpB,aAAa,GACd,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Router, Params } from "@real-router/core";
|
|
2
|
+
export declare function shouldNavigate(evt: MouseEvent): boolean;
|
|
3
|
+
export declare function buildHref(router: Router, routeName: string, routeParams: Params): string | undefined;
|
|
4
|
+
export declare function buildActiveClassName(isActive: boolean, activeClassName: string | undefined, baseClassName: string | undefined): string | undefined;
|
|
5
|
+
export declare function applyLinkA11y(element: HTMLElement): void;
|
|
6
|
+
//# sourceMappingURL=link-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-utils.d.ts","sourceRoot":"","sources":["../../../src/dom-utils/link-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAExD,wBAAgB,cAAc,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAQvD;AAID,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,SAAS,CAgBpB;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,OAAO,EACjB,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,aAAa,EAAE,MAAM,GAAG,SAAS,GAChC,MAAM,GAAG,SAAS,CAQpB;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAaxD"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Router, State } from "@real-router/core";
|
|
2
|
+
export interface RouteAnnouncerOptions {
|
|
3
|
+
prefix?: string;
|
|
4
|
+
getAnnouncementText?: (route: State) => string;
|
|
5
|
+
}
|
|
6
|
+
export declare function createRouteAnnouncer(router: Router, options?: RouteAnnouncerOptions): {
|
|
7
|
+
destroy: () => void;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=route-announcer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-announcer.d.ts","sourceRoot":"","sources":["../../../src/dom-utils/route-announcer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AASvD,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC;CAChD;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,qBAAqB,GAC9B;IAAE,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAuDzB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@real-router/solid",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"description": "Solid.js integration for Real-Router",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -70,8 +70,7 @@
|
|
|
70
70
|
"solid-js": "1.9.12",
|
|
71
71
|
"vite-plugin-solid": "2.11.11",
|
|
72
72
|
"vitest": "4.1.0",
|
|
73
|
-
"
|
|
74
|
-
"@real-router/browser-plugin": "^0.11.7"
|
|
73
|
+
"@real-router/browser-plugin": "^0.11.8"
|
|
75
74
|
},
|
|
76
75
|
"peerDependencies": {
|
|
77
76
|
"solid-js": ">=1.7.0"
|
package/src/RouterProvider.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { getNavigator } from "@real-router/core";
|
|
2
2
|
import { createRouteSource } from "@real-router/sources";
|
|
3
|
-
import { createRouteAnnouncer } from "dom-utils";
|
|
4
3
|
import { createSelector, onCleanup, onMount } from "solid-js";
|
|
5
4
|
|
|
6
5
|
import { RouterContext, RouteContext } from "./context";
|
|
7
6
|
import { createSignalFromSource } from "./createSignalFromSource";
|
|
7
|
+
import { createRouteAnnouncer } from "./dom-utils/index.js";
|
|
8
8
|
|
|
9
9
|
import type { Router } from "@real-router/core";
|
|
10
10
|
import type { ParentProps, JSX } from "solid-js";
|
package/src/components/Link.tsx
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { createActiveRouteSource } from "@real-router/sources";
|
|
2
|
-
import { shouldNavigate, buildHref, buildActiveClassName } from "dom-utils";
|
|
3
2
|
import { createMemo, mergeProps, splitProps, useContext } from "solid-js";
|
|
4
3
|
|
|
5
4
|
import { EMPTY_PARAMS, EMPTY_OPTIONS } from "../constants";
|
|
6
5
|
import { RouterContext } from "../context";
|
|
7
6
|
import { createSignalFromSource } from "../createSignalFromSource";
|
|
7
|
+
import {
|
|
8
|
+
shouldNavigate,
|
|
9
|
+
buildHref,
|
|
10
|
+
buildActiveClassName,
|
|
11
|
+
} from "../dom-utils/index.js";
|
|
8
12
|
import { useRouter } from "../hooks/useRouter";
|
|
9
13
|
|
|
10
14
|
import type { LinkProps } from "../types";
|
package/src/directives/link.tsx
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { createActiveRouteSource } from "@real-router/sources";
|
|
2
|
-
import { shouldNavigate, applyLinkA11y, buildHref } from "dom-utils";
|
|
3
2
|
import { createEffect, onCleanup } from "solid-js";
|
|
4
3
|
|
|
5
4
|
import { EMPTY_PARAMS, EMPTY_OPTIONS } from "../constants";
|
|
6
5
|
import { createSignalFromSource } from "../createSignalFromSource";
|
|
6
|
+
import {
|
|
7
|
+
shouldNavigate,
|
|
8
|
+
applyLinkA11y,
|
|
9
|
+
buildHref,
|
|
10
|
+
} from "../dom-utils/index.js";
|
|
7
11
|
import { useRouter } from "../hooks/useRouter";
|
|
8
12
|
|
|
9
13
|
import type { Params } from "@real-router/core";
|