@openbunny/react 0.1.1 → 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
@@ -13,12 +13,16 @@ helpers with no site content.
13
13
  | `CommandBlock`, `CommandLine`, `ShellCommand` | Numbered command steps, one command row, token spans |
14
14
  | `CopyButton`, `Button` | Clipboard button, base button |
15
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 |
16
18
 
17
19
  The package renders no site identity. Each component takes its text, artwork
18
20
  and behaviour through props. Where a prop has a default, the default is neutral
19
21
  English. No component imports `next`, an analytics client or a router, and none
20
- renders a link. A caller that needs a link passes its own element as a child or
21
- 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`.
22
26
 
23
27
  ## Install
24
28
 
@@ -70,6 +74,7 @@ that respect.
70
74
  `tailwind.css` from the theme maps each colour to a Tailwind utility. The
71
75
  components use these utilities: `border-line`, `bg-paper`, `bg-paper-inset`,
72
76
  `bg-foreground`, `text-background`, `text-foreground`, `text-ink`, `text-muted`,
77
+ `hover:text-sprout`,
73
78
  `border-foreground`, `ring` and the `font-display`, `font-sc` and `font-mono`
74
79
  families. `styles.css` reads `--ink-deep`, `--ink-mid`, `--sprout` and
75
80
  `--font-weight-bold`. Components assume square corners (`--radius-*` is `0`).
@@ -83,8 +88,8 @@ families. `styles.css` reads `--ink-deep`, `--ink-mid`, `--sprout` and
83
88
  | `.js-only` | `@openbunny/react/styles.css` | `CopyButton` | hidden under `@media (scripting: none)` |
84
89
 
85
90
  `src/styles.test.ts` fails when a component uses a custom class that neither
86
- this table nor the theme defines. The theme defines `.link` and `.chip`; no
87
- 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.
88
93
 
89
94
  ### Document contract
90
95
 
@@ -104,6 +109,10 @@ Every prop is required unless its row shows a default or `?`.
104
109
  | `CommandBlock` | `id`, `number`, `title`, `steps`: `CommandStep[]`, `note?`, `copyAll?` (`false`), `copy?`, `copyLabel?`, `lead?` |
105
110
  | `CommandLine` | `command`, `copy?`, `copyLabel?` |
106
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` |
107
116
  | `PageSection` | `id`, `className?`, `children` |
108
117
  | `PageShell` | `children` |
109
118
  | `PageTitle` | `title`, `lastChangedAt?`, `changedLabel?`, `formatDate?` |
@@ -121,6 +130,15 @@ Types and helpers:
121
130
  - `CopyText`: `caption?`, `copiedCaption?`, `failureHint?`, `onCopy?`.
122
131
  - `shellTokens(command)` returns `ShellToken[]`; it throws on unbalanced quotes.
123
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.
124
142
  - `cn(...classes)` merges class names.
125
143
 
126
144
  `bun run build` also emits declarations in `dist/index.d.ts`.
@@ -136,6 +154,8 @@ Copy, captions and labels are props with neutral English defaults.
136
154
  | `CommandBlock` | `copy`, `copyLabel`, `copyAllCaption`, `copyAllLabel`, `note`, `lead` |
137
155
  | `PageTitle` | `changedLabel`, `formatDate(isoDate)` |
138
156
  | `SkipLink` | `label` |
157
+ | `References` | `sourceLabel`, `backLinkLabel(number, occurrence, occurrences)` |
158
+ | `Screenshot` | `alt` (required), `caption` (required) |
139
159
 
140
160
  `CopyButton` reports a successful copy through `onCopy`. The consumer attaches
141
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"}
@@ -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.1",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Generic React components for OpenBunny sites.",