@openbunny/react 0.1.0 → 0.2.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
@@ -1,8 +1,5 @@
1
1
  # @openbunny/react
2
2
 
3
- > **Work in progress.** Names, identifiers and interfaces can change without
4
- > notice.
5
-
6
3
  Generic React components for OpenBunny sites. The package ships components and
7
4
  helpers with no site content.
8
5
 
@@ -16,12 +13,16 @@ helpers with no site content.
16
13
  | `CommandBlock`, `CommandLine`, `ShellCommand` | Numbered command steps, one command row, token spans |
17
14
  | `CopyButton`, `Button` | Clipboard button, base button |
18
15
  | `SkipLink`, `ChevronIcon` | Skip-to-content link, chevron icon |
16
+ | `Cite`, `CiteGroup`, `References` | Numbered citation markers and their reference list |
17
+ | `Screenshot` | Bordered image with a caption below |
19
18
 
20
19
  The package renders no site identity. Each component takes its text, artwork
21
20
  and behaviour through props. Where a prop has a default, the default is neutral
22
21
  English. No component imports `next`, an analytics client or a router, and none
23
- renders a link. A caller that needs a link passes its own element as a child or
24
- as a prop of type `ReactNode`.
22
+ renders a link to a route. The citation components render plain `<a>` elements
23
+ to in-page `#cite-` and `#ref-` anchors and to each `Reference`'s `url`. A
24
+ caller that needs a link to a route passes its own element as a child or as a
25
+ prop of type `ReactNode`.
25
26
 
26
27
  ## Install
27
28
 
@@ -73,6 +74,7 @@ that respect.
73
74
  `tailwind.css` from the theme maps each colour to a Tailwind utility. The
74
75
  components use these utilities: `border-line`, `bg-paper`, `bg-paper-inset`,
75
76
  `bg-foreground`, `text-background`, `text-foreground`, `text-ink`, `text-muted`,
77
+ `hover:text-sprout`,
76
78
  `border-foreground`, `ring` and the `font-display`, `font-sc` and `font-mono`
77
79
  families. `styles.css` reads `--ink-deep`, `--ink-mid`, `--sprout` and
78
80
  `--font-weight-bold`. Components assume square corners (`--radius-*` is `0`).
@@ -86,8 +88,8 @@ families. `styles.css` reads `--ink-deep`, `--ink-mid`, `--sprout` and
86
88
  | `.js-only` | `@openbunny/react/styles.css` | `CopyButton` | hidden under `@media (scripting: none)` |
87
89
 
88
90
  `src/styles.test.ts` fails when a component uses a custom class that neither
89
- this table nor the theme defines. The theme defines `.link` and `.chip`; no
90
- component uses them.
91
+ this table nor the theme defines. The theme defines `.link` and `.chip`;
92
+ `References` uses `.link` for its source and back-links.
91
93
 
92
94
  ### Document contract
93
95
 
@@ -107,6 +109,10 @@ Every prop is required unless its row shows a default or `?`.
107
109
  | `CommandBlock` | `id`, `number`, `title`, `steps`: `CommandStep[]`, `note?`, `copyAll?` (`false`), `copy?`, `copyLabel?`, `lead?` |
108
110
  | `CommandLine` | `command`, `copy?`, `copyLabel?` |
109
111
  | `CopyButton` | `text`, `label`, `caption?`, `copiedCaption?`, `failureHint?`, `onCopy?` |
112
+ | `Cite` | `id`, `registry`: `CitationRegistry` |
113
+ | `CiteGroup` | `ids`, `registry`: `CitationRegistry` |
114
+ | `References` | `items`: `Reference[]`, `registry`: `CitationRegistry`, `sourceLabel?`, `backLinkLabel?`: `BackLinkLabel` |
115
+ | `Screenshot` | `src`, `alt`, `width`, `height`, `caption`: `ReactNode` |
110
116
  | `PageSection` | `id`, `className?`, `children` |
111
117
  | `PageShell` | `children` |
112
118
  | `PageTitle` | `title`, `lastChangedAt?`, `changedLabel?`, `formatDate?` |
@@ -121,9 +127,18 @@ Types and helpers:
121
127
 
122
128
  - `PlateAsset`: `gifSrc`, `staticSrc` (strings), `width`, `height` (numbers).
123
129
  - `CommandStep`: `command` and `comment` (strings).
124
- - `CopyText`: `caption?`, `copiedCaption?`, `failureHint?`.
130
+ - `CopyText`: `caption?`, `copiedCaption?`, `failureHint?`, `onCopy?`.
125
131
  - `shellTokens(command)` returns `ShellToken[]`; it throws on unbalanced quotes.
126
132
  - `formatLongDate(isoDate)` formats an ISO date for `PageTitle`.
133
+ - `Reference`: `id`, `authors`, `title`, `venue` (strings), `year` (number),
134
+ `url?`.
135
+ - `createCitationRegistry()` returns a `CitationRegistry`. Create one per
136
+ page and pass it to every `Cite`, `CiteGroup` and `References` on that page.
137
+ It numbers sources by first citation, so `References` must render after
138
+ every marker; it lists only cited sources and throws when a cited `id` has
139
+ no `Reference` in `items`.
140
+ - `BackLinkLabel(number, occurrence, occurrences)` returns the screen-reader
141
+ name of one back-link.
127
142
  - `cn(...classes)` merges class names.
128
143
 
129
144
  `bun run build` also emits declarations in `dist/index.d.ts`.
@@ -139,6 +154,8 @@ Copy, captions and labels are props with neutral English defaults.
139
154
  | `CommandBlock` | `copy`, `copyLabel`, `copyAllCaption`, `copyAllLabel`, `note`, `lead` |
140
155
  | `PageTitle` | `changedLabel`, `formatDate(isoDate)` |
141
156
  | `SkipLink` | `label` |
157
+ | `References` | `sourceLabel`, `backLinkLabel(number, occurrence, occurrences)` |
158
+ | `Screenshot` | `alt` (required), `caption` (required) |
142
159
 
143
160
  `CopyButton` reports a successful copy through `onCopy`. The consumer attaches
144
161
  analytics there; the package contains none.
@@ -0,0 +1,6 @@
1
+ import { type ReactElement } from "react";
2
+ import { type CitationRegistry } from "../lib/citation-registry.ts";
3
+ export declare function CiteGroup({ ids, registry, }: {
4
+ readonly ids: readonly string[];
5
+ readonly registry: CitationRegistry;
6
+ }): ReactElement;
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Fragment } from "react";
3
+ import { CitationAnchor } from "../lib/citation-anchor.js";
4
+ import { registerCitation, } from "../lib/citation-registry.js";
5
+ export function CiteGroup({ ids, registry, }) {
6
+ const cited = ids.map((id) => ({ id, ...registerCitation(id, registry) }));
7
+ return (_jsxs("span", { className: "whitespace-nowrap", children: ["[", cited.map(({ id, number, occurrence }, index) => (_jsxs(Fragment, { children: [index > 0 ? ", " : null, _jsx(CitationAnchor, { id: id, occurrence: occurrence, children: String(number) })] }, id))), "]"] }));
8
+ }
9
+ //# sourceMappingURL=cite-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cite-group.js","sourceRoot":"","sources":["../../src/components/cite-group.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAqB,MAAM,OAAO,CAAA;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA4B,CAAA;AAC3D,OAAO,EACL,gBAAgB,GAEjB,MAAM,6BAA6B,CAAA;AAEpC,MAAM,UAAU,SAAS,CAAC,EACxB,GAAG,EACH,QAAQ,GAIT;IACC,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,gBAAgB,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAA;IAE1E,OAAO,CACL,gBAAM,SAAS,EAAC,mBAAmB,aAChC,GAAG,EACH,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAChD,MAAC,QAAQ,eACN,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EACxB,KAAC,cAAc,IAAC,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,UAAU,YAC3C,MAAM,CAAC,MAAM,CAAC,GACA,KAJJ,EAAE,CAKN,CACZ,CAAC,EACD,GAAG,IACC,CACR,CAAA;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { ReactElement } from "react";
2
+ import { type CitationRegistry } from "../lib/citation-registry.ts";
3
+ export declare function Cite({ id, registry, }: {
4
+ readonly id: string;
5
+ readonly registry: CitationRegistry;
6
+ }): ReactElement;
@@ -0,0 +1,8 @@
1
+ import { jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { CitationAnchor } from "../lib/citation-anchor.js";
3
+ import { registerCitation, } from "../lib/citation-registry.js";
4
+ export function Cite({ id, registry, }) {
5
+ const { number, occurrence } = registerCitation(id, registry);
6
+ return (_jsxs(CitationAnchor, { id: id, occurrence: occurrence, children: ["[", number, "]"] }));
7
+ }
8
+ //# sourceMappingURL=cite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cite.js","sourceRoot":"","sources":["../../src/components/cite.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA4B,CAAA;AAC3D,OAAO,EACL,gBAAgB,GAEjB,MAAM,6BAA6B,CAAA;AAEpC,MAAM,UAAU,IAAI,CAAC,EACnB,EAAE,EACF,QAAQ,GAIT;IACC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;IAE7D,OAAO,CACL,MAAC,cAAc,IAAC,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,UAAU,kBAC1C,MAAM,SACO,CAClB,CAAA;AACH,CAAC"}
@@ -3,11 +3,11 @@ export type CopyText = {
3
3
  readonly failureHint?: string;
4
4
  readonly caption?: string;
5
5
  readonly copiedCaption?: string;
6
+ readonly onCopy?: () => void;
6
7
  };
7
8
  type CopyButtonProps = CopyText & {
8
9
  readonly text: string;
9
10
  readonly label: string;
10
- readonly onCopy?: () => void;
11
11
  };
12
12
  export declare function CopyButton({ text, label, failureHint, caption, copiedCaption, onCopy, }: CopyButtonProps): ReactElement;
13
13
  export {};
@@ -0,0 +1,10 @@
1
+ import { type ReactElement } from "react";
2
+ import type { CitationRegistry } from "../lib/citation-registry.ts";
3
+ import type { Reference } from "../lib/reference.ts";
4
+ export type BackLinkLabel = (number: number, occurrence: number, occurrences: number) => string;
5
+ export declare function References({ items, registry, sourceLabel, backLinkLabel, }: {
6
+ readonly items: readonly Reference[];
7
+ readonly registry: CitationRegistry;
8
+ readonly sourceLabel?: string;
9
+ readonly backLinkLabel?: BackLinkLabel;
10
+ }): ReactElement;
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Fragment } from "react";
3
+ const defaultBackLinkLabel = (number, occurrence, occurrences) => occurrences > 1
4
+ ? `Back to citation ${String(number)}, occurrence ${String(occurrence)} of ${String(occurrences)}`
5
+ : `Back to citation ${String(number)}`;
6
+ export function References({ items, registry, sourceLabel = "Source", backLinkLabel = defaultBackLinkLabel, }) {
7
+ return (_jsx("ol", { className: "mt-4 flex flex-col gap-3 font-display text-[0.85rem] leading-[1.6]", children: registry.citedIds().map((id) => {
8
+ const reference = items.find((item) => item.id === id);
9
+ if (reference === undefined) {
10
+ throw new Error(`References has no entry for the cited id "${id}". Add a Reference with that id to items, or remove the citation.`);
11
+ }
12
+ const occurrences = registry.occurrenceCount(id);
13
+ const number = registry.numberOf(id);
14
+ const backLinks = Array.from({ length: Math.max(occurrences, 1) }, (_value, index) => index + 1);
15
+ return (_jsxs("li", { id: `ref-${id}`, children: [reference.authors, " (", reference.year, "). ", reference.title, ".", " ", reference.venue, ".", reference.url === undefined ? null : (_jsxs(_Fragment, { children: [" ", _jsx("a", { href: reference.url, className: "link", children: sourceLabel })] })), backLinks.map((occurrence) => (_jsxs(Fragment, { children: [" ", _jsxs("a", { href: `#cite-${id}-${String(occurrence)}`, className: "link", children: [_jsx("span", { className: "sr-only", children: backLinkLabel(number, occurrence, occurrences) }), _jsx("span", { "aria-hidden": "true", children: occurrences > 1 ? `^${String(occurrence)}` : "^" })] })] }, occurrence)))] }, id));
16
+ }) }));
17
+ }
18
+ //# sourceMappingURL=references.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"references.js","sourceRoot":"","sources":["../../src/components/references.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAqB,MAAM,OAAO,CAAA;AAWnD,MAAM,oBAAoB,GAAkB,CAC1C,MAAM,EACN,UAAU,EACV,WAAW,EACX,EAAE,CACF,WAAW,GAAG,CAAC;IACb,CAAC,CAAC,oBAAoB,MAAM,CAAC,MAAM,CAAC,gBAAgB,MAAM,CAAC,UAAU,CAAC,OAAO,MAAM,CAAC,WAAW,CAAC,EAAE;IAClG,CAAC,CAAC,oBAAoB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAA;AAE1C,MAAM,UAAU,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,WAAW,GAAG,QAAQ,EACtB,aAAa,GAAG,oBAAoB,GAMrC;IACC,OAAO,CACL,aAAI,SAAS,EAAC,oEAAoE,YAC/E,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;YAC9B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;YACtD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CACb,6CAA6C,EAAE,mEAAmE,CACnH,CAAA;YACH,CAAC;YAED,MAAM,WAAW,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,CAAA;YAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;YACpC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAC1B,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EACpC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAC7B,CAAA;YAED,OAAO,CACL,cAAI,EAAE,EAAE,OAAO,EAAE,EAAE,aAChB,SAAS,CAAC,OAAO,QAAI,SAAS,CAAC,IAAI,SAAK,SAAS,CAAC,KAAK,OAAG,GAAG,EAC7D,SAAS,CAAC,KAAK,OACf,SAAS,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACpC,8BACG,GAAG,EACJ,YAAG,IAAI,EAAE,SAAS,CAAC,GAAG,EAAE,SAAS,EAAC,MAAM,YACrC,WAAW,GACV,IACH,CACJ,EACA,SAAS,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAC7B,MAAC,QAAQ,eACN,GAAG,EACJ,aAAG,IAAI,EAAE,SAAS,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAC,MAAM,aAC5D,eAAM,SAAS,EAAC,SAAS,YACtB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,GAC1C,EACP,8BAAkB,MAAM,YACrB,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAC5C,IACL,KATS,UAAU,CAUd,CACZ,CAAC,KAvBsB,EAAE,CAwBvB,CACN,CAAA;QACH,CAAC,CAAC,GACC,CACN,CAAA;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ReactElement, ReactNode } from "react";
2
+ export declare function Screenshot({ src, alt, width, height, caption, }: {
3
+ readonly src: string;
4
+ readonly alt: string;
5
+ readonly width: number;
6
+ readonly height: number;
7
+ readonly caption: ReactNode;
8
+ }): ReactElement;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export function Screenshot({ src, alt, width, height, caption, }) {
3
+ return (_jsxs("figure", { className: "flex flex-col gap-2", children: [_jsx("div", { className: "border border-line bg-paper-inset p-1.5", children: _jsx("img", { src: src, alt: alt, width: width, height: height, loading: "lazy", decoding: "async", className: "block h-auto w-full" }) }), _jsx("figcaption", { className: "text-right font-mono text-[0.75rem] leading-normal text-muted", children: caption })] }));
4
+ }
5
+ //# sourceMappingURL=screenshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/components/screenshot.tsx"],"names":[],"mappings":";AAEA,MAAM,UAAU,UAAU,CAAC,EACzB,GAAG,EACH,GAAG,EACH,KAAK,EACL,MAAM,EACN,OAAO,GAOR;IACC,OAAO,CACL,kBAAQ,SAAS,EAAC,qBAAqB,aACrC,cAAK,SAAS,EAAC,yCAAyC,YACtD,cACE,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAC,MAAM,EACd,QAAQ,EAAC,OAAO,EAChB,SAAS,EAAC,qBAAqB,GAC/B,GACE,EACN,qBAAY,SAAS,EAAC,+DAA+D,YAClF,OAAO,GACG,IACN,CACV,CAAA;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -3,6 +3,8 @@ export { shellTokens, type ShellToken } from "./lib/shell-tokens.ts";
3
3
  export { formatLongDate } from "./lib/iso-date.ts";
4
4
  export type { PlateAsset } from "./lib/plate-asset.ts";
5
5
  export type { CommandStep } from "./lib/command-step.ts";
6
+ export type { Reference } from "./lib/reference.ts";
7
+ export { createCitationRegistry, type CitationRegistry, } from "./lib/citation-registry.ts";
6
8
  export { ChevronIcon } from "./components/chevron-icon.tsx";
7
9
  export { PageSection } from "./components/page-section.tsx";
8
10
  export { PageShell } from "./components/page-shell.tsx";
@@ -17,3 +19,7 @@ export { PlateHeader } from "./components/plate-header.tsx";
17
19
  export { StatusPage } from "./components/status-page.tsx";
18
20
  export { Button } from "./components/ui/button.tsx";
19
21
  export { CopyButton, type CopyText } from "./components/copy-button.tsx";
22
+ export { Cite } from "./components/cite.tsx";
23
+ export { CiteGroup } from "./components/cite-group.tsx";
24
+ export { References, type BackLinkLabel } from "./components/references.tsx";
25
+ export { Screenshot } from "./components/screenshot.tsx";
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export { cn } from "./lib/utils.js";
2
2
  export { shellTokens } from "./lib/shell-tokens.js";
3
3
  export { formatLongDate } from "./lib/iso-date.js";
4
+ export { createCitationRegistry, } from "./lib/citation-registry.js";
4
5
  export { ChevronIcon } from "./components/chevron-icon.js";
5
6
  export { PageSection } from "./components/page-section.js";
6
7
  export { PageShell } from "./components/page-shell.js";
@@ -15,4 +16,8 @@ export { PlateHeader } from "./components/plate-header.js";
15
16
  export { StatusPage } from "./components/status-page.js";
16
17
  export { Button } from "./components/ui/button.js";
17
18
  export { CopyButton } from "./components/copy-button.js";
19
+ export { Cite } from "./components/cite.js";
20
+ export { CiteGroup } from "./components/cite-group.js";
21
+ export { References } from "./components/references.js";
22
+ export { Screenshot } from "./components/screenshot.js";
18
23
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAA;AACnC,OAAO,EAAE,WAAW,EAAmB,MAAM,uBAAuB,CAAA;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAGlD,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA6B,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA6B,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAkC,CAAA;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAAgC,CAAA;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAAgC,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA4B,CAAA;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAwB,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA8B,CAAA;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA4B,CAAA;AACnD,OAAO,EAAE,UAAU,EAAiB,MAAM,6BAA8B,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAA;AACnC,OAAO,EAAE,WAAW,EAAmB,MAAM,uBAAuB,CAAA;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAIlD,OAAO,EACL,sBAAsB,GAEvB,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA6B,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA6B,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAkC,CAAA;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAAgC,CAAA;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAAgC,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA4B,CAAA;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAwB,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA8B,CAAA;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA4B,CAAA;AACnD,OAAO,EAAE,UAAU,EAAiB,MAAM,6BAA8B,CAAA;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAuB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA6B,CAAA;AACvD,OAAO,EAAE,UAAU,EAAsB,MAAM,4BAA6B,CAAA;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA6B,CAAA"}
@@ -0,0 +1,6 @@
1
+ import type { ReactElement, ReactNode } from "react";
2
+ export declare function CitationAnchor({ id, occurrence, children, }: {
3
+ readonly id: string;
4
+ readonly occurrence: number;
5
+ readonly children: ReactNode;
6
+ }): ReactElement;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export function CitationAnchor({ id, occurrence, children, }) {
3
+ return (_jsx("a", { id: `cite-${id}-${String(occurrence)}`, href: `#ref-${id}`, className: "text-ink hover:text-sprout", children: children }));
4
+ }
5
+ //# sourceMappingURL=citation-anchor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"citation-anchor.js","sourceRoot":"","sources":["../../src/lib/citation-anchor.tsx"],"names":[],"mappings":";AAEA,MAAM,UAAU,cAAc,CAAC,EAC7B,EAAE,EACF,UAAU,EACV,QAAQ,GAKT;IACC,OAAO,CACL,YACE,EAAE,EAAE,QAAQ,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,EAAE,EACtC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAClB,SAAS,EAAC,4BAA4B,YAErC,QAAQ,GACP,CACL,CAAA;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ export type CitationRegistry = {
2
+ readonly numberOf: (id: string) => number;
3
+ readonly recordOccurrence: (id: string) => number;
4
+ readonly citedIds: () => readonly string[];
5
+ readonly occurrenceCount: (id: string) => number;
6
+ };
7
+ export declare function createCitationRegistry(): CitationRegistry;
8
+ export declare function registerCitation(id: string, registry: CitationRegistry): {
9
+ readonly number: number;
10
+ readonly occurrence: number;
11
+ };
@@ -0,0 +1,31 @@
1
+ export function createCitationRegistry() {
2
+ const order = [];
3
+ const occurrences = new Map();
4
+ return {
5
+ numberOf(id) {
6
+ let position = order.indexOf(id);
7
+ if (position === -1) {
8
+ order.push(id);
9
+ position = order.length - 1;
10
+ }
11
+ return position + 1;
12
+ },
13
+ recordOccurrence(id) {
14
+ const next = (occurrences.get(id) ?? 0) + 1;
15
+ occurrences.set(id, next);
16
+ return next;
17
+ },
18
+ citedIds() {
19
+ return order;
20
+ },
21
+ occurrenceCount(id) {
22
+ return occurrences.get(id) ?? 0;
23
+ },
24
+ };
25
+ }
26
+ export function registerCitation(id, registry) {
27
+ const number = registry.numberOf(id);
28
+ const occurrence = registry.recordOccurrence(id);
29
+ return { number, occurrence };
30
+ }
31
+ //# sourceMappingURL=citation-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"citation-registry.js","sourceRoot":"","sources":["../../src/lib/citation-registry.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,sBAAsB;IACpC,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAA;IAE7C,OAAO;QACL,QAAQ,CAAC,EAAE;YACT,IAAI,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;YAChC,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;gBACpB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBACd,QAAQ,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;YAC7B,CAAC;YACD,OAAO,QAAQ,GAAG,CAAC,CAAA;QACrB,CAAC;QACD,gBAAgB,CAAC,EAAE;YACjB,MAAM,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;YAC3C,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;YACzB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,QAAQ;YACN,OAAO,KAAK,CAAA;QACd,CAAC;QACD,eAAe,CAAC,EAAE;YAChB,OAAO,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAA;QACjC,CAAC;KACF,CAAA;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,EAAU,EACV,QAA0B;IAE1B,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IACpC,MAAM,UAAU,GAAG,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;IAEhD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAA;AAC/B,CAAC"}
@@ -0,0 +1,8 @@
1
+ export type Reference = {
2
+ readonly id: string;
3
+ readonly authors: string;
4
+ readonly year: number;
5
+ readonly title: string;
6
+ readonly venue: string;
7
+ readonly url?: string;
8
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=reference.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reference.js","sourceRoot":"","sources":["../../src/lib/reference.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openbunny/react",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Generic React components for OpenBunny sites.",