scoobie 14.3.7 → 14.4.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 CHANGED
@@ -345,11 +345,12 @@ export const MyFirstInlineCode = () => (
345
345
 
346
346
  Render an internal link with the same opinions as our [MdxProvider](#mdxprovider):
347
347
 
348
- - Internal links pass through the `v` and `v-panel` URL parameters for UI version switching
348
+ - Internal links pass through the `v` or [ScoobieLinkProvider] URL parameters for UI version switching
349
349
 
350
350
  Unlike [SmartTextLink](#smarttextlink), this is not bound to a parent [Text] as it has no underlying [TextLink].
351
351
  It can be used to make complex components navigable rather than just sections of text.
352
352
 
353
+ [scoobielinkprovider]: #scoobielinkprovider
353
354
  [text]: https://seek-oss.github.io/braid-design-system/components/Text/
354
355
  [textlink]: https://seek-oss.github.io/braid-design-system/components/TextLink/
355
356
 
@@ -398,7 +399,7 @@ export const Component = () => (
398
399
 
399
400
  Render all underlying links as follows:
400
401
 
401
- - Internal links pass through the `v` and `v-panel` URL parameters for UI version switching
402
+ - Internal links pass through the `v` or [ScoobieLinkProvider] URL parameters for UI version switching
402
403
  - External links open in a new tab
403
404
  - Links with a [`download` attribute] prompt the user with a file download
404
405
 
@@ -421,6 +422,25 @@ export const Component = () => (
421
422
 
422
423
  [braidprovider]: https://seek-oss.github.io/braid-design-system/components/BraidProvider
423
424
 
425
+ ### ScoobieLinkProvider
426
+
427
+ Propagate a custom set of URL parameters on internal links.
428
+
429
+ ```tsx
430
+ import { BraidProvider, TextLink } from 'braid-design-system';
431
+ import apacTheme from 'braid-design-system/themes/apac';
432
+ import React from 'react';
433
+ import { ScoobieLink } from 'scoobie';
434
+
435
+ export const Component = () => (
436
+ <ScoobieLinkProvider propagateSearchParams={['debug', 'v']}>
437
+ <BraidProvider linkComponent={ScoobieLink} theme={apacTheme}>
438
+ <TextLink href="/root-relative">Internal link</TextLink>
439
+ </BraidProvider>
440
+ </ScoobieLinkProvider>
441
+ );
442
+ ```
443
+
424
444
  ### SmartTextLink
425
445
 
426
446
  Render a text link with the same opinions as our [MdxProvider](#mdxprovider):
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "license": "MIT",
5
5
  "main": "src/index.ts",
6
6
  "sideEffects": false,
7
- "version": "14.3.7",
7
+ "version": "14.4.0",
8
8
  "dependencies": {
9
9
  "@capsizecss/core": "^3.0.0",
10
10
  "@mdx-js/loader": "^1.6.22",
@@ -4,6 +4,8 @@ import { NavLink, useLocation } from 'react-router-dom';
4
4
 
5
5
  import { parseInternalHref } from '../private/url';
6
6
 
7
+ import { useScoobieLink } from './ScoobieLinkProvider';
8
+
7
9
  import * as styles from './InternalLink.css';
8
10
 
9
11
  interface Props
@@ -18,7 +20,12 @@ export const InternalLink = forwardRef<HTMLAnchorElement, Props>(
18
20
  ({ className, href, reset = true, state, ...restProps }, ref) => {
19
21
  const location = useLocation();
20
22
 
21
- const to = { ...parseInternalHref(href, location), state };
23
+ const { propagateSearchParams } = useScoobieLink();
24
+
25
+ const to = {
26
+ ...parseInternalHref(href, location, propagateSearchParams),
27
+ state,
28
+ };
22
29
 
23
30
  return (
24
31
  <NavLink
@@ -0,0 +1,29 @@
1
+ import React, { type ReactNode, createContext, useContext } from 'react';
2
+
3
+ interface ScoobieLinkContext {
4
+ propagateSearchParams: string[];
5
+ }
6
+
7
+ const ctx = createContext<ScoobieLinkContext>({
8
+ propagateSearchParams: ['v'],
9
+ });
10
+
11
+ interface ScoobieLinkProviderProps {
12
+ children: ReactNode;
13
+
14
+ /**
15
+ * The search parameters to propagate on internal links.
16
+ *
17
+ * This defaults to `['v']` in the absence of a `ScoobieLinkProvider`.
18
+ */
19
+ propagateSearchParams: string[];
20
+ }
21
+
22
+ export const ScoobieLinkProvider = ({
23
+ children,
24
+ ...value
25
+ }: ScoobieLinkProviderProps) => {
26
+ <ctx.Provider value={value}>{children}</ctx.Provider>;
27
+ };
28
+
29
+ export const useScoobieLink = () => useContext(ctx);
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ export { InlineCode } from './components/InlineCode';
5
5
  export { InternalLink } from './components/InternalLink';
6
6
  export { MdxProvider } from './components/MdxProvider';
7
7
  export { ScoobieLink } from './components/ScoobieLink';
8
+ export { ScoobieLinkProvider } from './components/ScoobieLinkProvider';
8
9
  export { SmartTextLink } from './components/SmartTextLink';
9
10
  export { Table } from './components/Table';
10
11
  export { TableRow } from './components/TableRow';
@@ -1,14 +1,5 @@
1
1
  const EXAMPLE_BASE_URL = 'https://example.com';
2
2
 
3
- const parseVersionParams = (search: string) => {
4
- const urlSearchParams = new URLSearchParams(search);
5
-
6
- return {
7
- v: urlSearchParams.get('v'),
8
- vPanel: urlSearchParams.get('v-panel'),
9
- };
10
- };
11
-
12
3
  const hrefToUrl = (href: string, pathname: string) => {
13
4
  if (href.startsWith('/')) {
14
5
  return new URL(`${EXAMPLE_BASE_URL}${href}`);
@@ -27,16 +18,18 @@ export const parseInternalHref = (
27
18
  pathname: string;
28
19
  search: string;
29
20
  },
21
+ propagateSearchParams: string[],
30
22
  ) => {
31
23
  const { hash, pathname, searchParams } = hrefToUrl(href, location.pathname);
32
24
 
33
- const { v, vPanel } = parseVersionParams(location.search);
25
+ const priorSearchParams = new URLSearchParams(location.search);
34
26
 
35
- if (v !== null) {
36
- searchParams.set('v', v);
37
- }
38
- if (vPanel !== null) {
39
- searchParams.set('v-panel', vPanel);
27
+ for (const key of propagateSearchParams) {
28
+ const value = priorSearchParams.get(key);
29
+
30
+ if (value !== null) {
31
+ searchParams.set(key, value);
32
+ }
40
33
  }
41
34
 
42
35
  const search = searchParams.toString();