@captiveorigins/onepedigree-react 0.1.0-alpha.12 → 0.1.0-alpha.15
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/PedigreeExplorer.js +2 -2
- package/dist/PedigreeView.js +2 -2
- package/dist/describe.d.ts +11 -0
- package/dist/describe.js +12 -0
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -1
- package/package.json +5 -5
package/dist/PedigreeExplorer.js
CHANGED
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
3
3
|
import { REORDERABLE_VIEWS } from '@captiveorigins/onepedigree-core';
|
|
4
4
|
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
5
5
|
import { AhnentafelList } from './AhnentafelList.js';
|
|
6
|
-
import { DEFAULT_TERMS, describeStructure, labelOf } from './describe.js';
|
|
6
|
+
import { DEFAULT_TERMS, describeStructure, labelOf, sexWord } from './describe.js';
|
|
7
7
|
import { nearestNode, useOccurrenceHighlighting, usePedigreeSelection } from './hooks.js';
|
|
8
8
|
import { PedigreeView } from './PedigreeView.js';
|
|
9
9
|
import { GeneLegend, GenotypeKey } from './genetics.js';
|
|
@@ -240,5 +240,5 @@ export function PedigreeExplorer(props) {
|
|
|
240
240
|
suppressClick.current = false;
|
|
241
241
|
e.stopPropagation();
|
|
242
242
|
}
|
|
243
|
-
}, "data-reorderable": reorderable ? '' : undefined, children: [_jsxs("div", { className: "op-toolbar", role: "toolbar", "aria-label": labels.controls, children: [_jsx("button", { type: "button", onClick: () => zoom(0.8), "aria-label": labels.zoomIn, "data-tip": labels.zoomIn, children: _jsx(Icon, { name: "zoomIn" }) }), _jsx("button", { type: "button", onClick: () => zoom(1.25), "aria-label": labels.zoomOut, "data-tip": labels.zoomOut, children: _jsx(Icon, { name: "zoomOut" }) }), _jsx("button", { type: "button", onClick: () => setBox(full), "aria-label": labels.fit, "data-tip": labels.fit, children: _jsx(Icon, { name: "fit" }) }), _jsx("button", { type: "button", onClick: download, "aria-label": labels.download, "data-tip": labels.download, children: _jsx(Icon, { name: "download" }) }), _jsx("button", { type: "button", onClick: () => (props.onPrint ? props.onPrint() : printChart(root.current)), "aria-label": labels.print, "data-tip": labels.print, children: _jsx(Icon, { name: "print" }) }), props.themeEditor && (_jsx("button", { type: "button", onClick: () => setEditing((v) => !v), "aria-label": labels.colors, "data-tip": labels.colors, "aria-expanded": editing, children: _jsx(Icon, { name: "palette" }) })), props.toolbar] }), props.themeEditor && editing && (_jsx("div", { className: "op-theme-panel", children: _jsx(ThemeEditor, { value: theme ?? structuredClone(THEME_PRESETS[0]), view: projection.view, onChange: changeTheme }) })), projection.view === 'ahnentafel' ? (_jsx(AhnentafelList, { projection: projection, terminology: props.terminology, parentWords: props.parentWords, getIndividualHref: props.getIndividualHref, selectedIndividualId: selectedId, onSelect: (individualId) => choose(projection.occurrences.find((o) => o.individualId === individualId) ?? null) })) : (_jsx(PedigreeView, { ...props, theme: theme, interactive: true, viewBox: box, selectedIndividualId: selectedId, highlightedOccurrenceIds: highlighted, onNodeClick: (occ) => choose(selectedOccurrence === occ.occurrenceId ? null : occ), onNodeKeyDown: onNodeKeyDown, svgProps: { ...props.svgProps, width: '100%', height: '100%', preserveAspectRatio: 'xMidYMid meet' } })), occurrence && (_jsx("div", { className: "op-quick-view", role: "dialog", "aria-label": labelOf(individual, terms), children: props.renderQuickView ? (props.renderQuickView({ individual, occurrence, href, close })) : (_jsxs(_Fragment, { children: [_jsx("p", { className: "op-quick-view-title", children: labelOf(individual, terms) }), individual?.sex && _jsx("p", { children: individual.sex }), _jsx("p", { children: describeStructure(projection.structures[occurrence.individualId]) }), occurrence.repeated && _jsx("p", { children: terms.repeated }), _jsxs("div", { className: "op-quick-view-actions", children: [href && (_jsxs("a", { href: href, children: [_jsx(Icon, { name: "open" }), labels.open] })), _jsxs("button", { type: "button", onClick: close, children: [_jsx(Icon, { name: "close" }), labels.close] })] })] })) })), (props.geneOverlay || props.genotypes) && (_jsxs("div", { className: "op-gene-legends", children: [props.genotypes && _jsx(GenotypeKey, { display: props.genotypes }), props.geneOverlay && _jsx(GeneLegend, { overlay: props.geneOverlay })] }))] }));
|
|
243
|
+
}, "data-reorderable": reorderable ? '' : undefined, children: [_jsxs("div", { className: "op-toolbar", role: "toolbar", "aria-label": labels.controls, children: [_jsx("button", { type: "button", onClick: () => zoom(0.8), "aria-label": labels.zoomIn, "data-tip": labels.zoomIn, children: _jsx(Icon, { name: "zoomIn" }) }), _jsx("button", { type: "button", onClick: () => zoom(1.25), "aria-label": labels.zoomOut, "data-tip": labels.zoomOut, children: _jsx(Icon, { name: "zoomOut" }) }), _jsx("button", { type: "button", onClick: () => setBox(full), "aria-label": labels.fit, "data-tip": labels.fit, children: _jsx(Icon, { name: "fit" }) }), _jsx("button", { type: "button", onClick: download, "aria-label": labels.download, "data-tip": labels.download, children: _jsx(Icon, { name: "download" }) }), _jsx("button", { type: "button", onClick: () => (props.onPrint ? props.onPrint() : printChart(root.current)), "aria-label": labels.print, "data-tip": labels.print, children: _jsx(Icon, { name: "print" }) }), props.themeEditor && (_jsx("button", { type: "button", onClick: () => setEditing((v) => !v), "aria-label": labels.colors, "data-tip": labels.colors, "aria-expanded": editing, children: _jsx(Icon, { name: "palette" }) })), props.toolbar] }), props.themeEditor && editing && (_jsx("div", { className: "op-theme-panel", children: _jsx(ThemeEditor, { value: theme ?? structuredClone(THEME_PRESETS[0]), view: projection.view, onChange: changeTheme }) })), projection.view === 'ahnentafel' ? (_jsx(AhnentafelList, { projection: projection, terminology: props.terminology, parentWords: props.parentWords, getIndividualHref: props.getIndividualHref, selectedIndividualId: selectedId, onSelect: (individualId) => choose(projection.occurrences.find((o) => o.individualId === individualId) ?? null) })) : (_jsx(PedigreeView, { ...props, theme: theme, interactive: true, viewBox: box, selectedIndividualId: selectedId, highlightedOccurrenceIds: highlighted, onNodeClick: (occ) => choose(selectedOccurrence === occ.occurrenceId ? null : occ), onNodeKeyDown: onNodeKeyDown, svgProps: { ...props.svgProps, width: '100%', height: '100%', preserveAspectRatio: 'xMidYMid meet' } })), occurrence && (_jsx("div", { className: "op-quick-view", role: "dialog", "aria-label": labelOf(individual, terms), children: props.renderQuickView ? (props.renderQuickView({ individual, occurrence, href, close })) : (_jsxs(_Fragment, { children: [_jsx("p", { className: "op-quick-view-title", children: labelOf(individual, terms) }), individual?.sex && _jsx("p", { children: sexWord(individual.sex, terms) }), _jsx("p", { children: describeStructure(projection.structures[occurrence.individualId]) }), occurrence.repeated && _jsx("p", { children: terms.repeated }), _jsxs("div", { className: "op-quick-view-actions", children: [href && (_jsxs("a", { href: href, children: [_jsx(Icon, { name: "open" }), labels.open] })), _jsxs("button", { type: "button", onClick: close, children: [_jsx(Icon, { name: "close" }), labels.close] })] })] })) })), (props.geneOverlay || props.genotypes) && (_jsxs("div", { className: "op-gene-legends", children: [props.genotypes && _jsx(GenotypeKey, { display: props.genotypes }), props.geneOverlay && _jsx(GeneLegend, { overlay: props.geneOverlay })] }))] }));
|
|
244
244
|
}
|
package/dist/PedigreeView.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { estimateNodeWidth, lifeLabel, lifeSpan, nodeSublabel } from '@captiveorigins/onepedigree-core';
|
|
3
|
-
import { arcPath, DEFAULT_TERMS, describeProjection, describeStructure, labelOf, VIEW_LABELS } from './describe.js';
|
|
3
|
+
import { arcPath, DEFAULT_TERMS, describeProjection, describeStructure, labelOf, sexWord, VIEW_LABELS } from './describe.js';
|
|
4
4
|
import { themeStyle } from './themes.js';
|
|
5
5
|
import { GenotypeGlyph, GenotypeStrip, genotypeText, genotypeWord } from './genetics.js';
|
|
6
6
|
const cx = (...c) => c.filter(Boolean).join(' ');
|
|
@@ -120,7 +120,7 @@ export function PedigreeView(props) {
|
|
|
120
120
|
const label = labelOf(individual, terms);
|
|
121
121
|
const aria = [
|
|
122
122
|
label,
|
|
123
|
-
individual?.sex,
|
|
123
|
+
sexWord(individual?.sex, terms),
|
|
124
124
|
lifeLabel(lifeSpan(individual)) || null,
|
|
125
125
|
occurrence.ahnentafel !== undefined ? `Ahnentafel ${occurrence.ahnentafel}` : null,
|
|
126
126
|
occurrence.repeated ? terms.repeated : null,
|
package/dist/describe.d.ts
CHANGED
|
@@ -8,8 +8,19 @@ export type Terminology = {
|
|
|
8
8
|
repeated: string;
|
|
9
9
|
unknown: string;
|
|
10
10
|
privateRecord: string;
|
|
11
|
+
/** Spoken in place of ♂. */
|
|
12
|
+
male: string;
|
|
13
|
+
/** Spoken in place of ♀. */
|
|
14
|
+
female: string;
|
|
15
|
+
/** Spoken when no sex is recorded. */
|
|
16
|
+
sexUnknown: string;
|
|
11
17
|
};
|
|
12
18
|
export declare const DEFAULT_TERMS: Terminology;
|
|
19
|
+
/**
|
|
20
|
+
* The sex in words, for the spoken name: the node shows only ♂ or ♀. Any other
|
|
21
|
+
* host label is spoken as written; a missing one says so instead of staying silent.
|
|
22
|
+
*/
|
|
23
|
+
export declare function sexWord(sex: string | null | undefined, terms?: Terminology): string;
|
|
13
24
|
/** Display name: the label, else the ID; anonymous placeholders (`data.private`) never show their ID. */
|
|
14
25
|
export declare const labelOf: (individual: Individual | undefined, terms?: Terminology) => string;
|
|
15
26
|
/** Words for an individual's origin, so color or shape is never the only signal. */
|
package/dist/describe.js
CHANGED
|
@@ -21,7 +21,19 @@ export const DEFAULT_TERMS = {
|
|
|
21
21
|
repeated: 'appears more than once',
|
|
22
22
|
unknown: 'Unknown',
|
|
23
23
|
privateRecord: 'Private record',
|
|
24
|
+
male: 'male',
|
|
25
|
+
female: 'female',
|
|
26
|
+
sexUnknown: 'sex unknown',
|
|
24
27
|
};
|
|
28
|
+
const SEX_TERM = { male: 'male', m: 'male', female: 'female', f: 'female', '': 'sexUnknown', unknown: 'sexUnknown', u: 'sexUnknown' };
|
|
29
|
+
/**
|
|
30
|
+
* The sex in words, for the spoken name: the node shows only ♂ or ♀. Any other
|
|
31
|
+
* host label is spoken as written; a missing one says so instead of staying silent.
|
|
32
|
+
*/
|
|
33
|
+
export function sexWord(sex, terms = DEFAULT_TERMS) {
|
|
34
|
+
const key = SEX_TERM[(sex ?? '').trim().toLowerCase()];
|
|
35
|
+
return key ? terms[key] : sex.trim();
|
|
36
|
+
}
|
|
25
37
|
/** Display name: the label, else the ID; anonymous placeholders (`data.private`) never show their ID. */
|
|
26
38
|
export const labelOf = (individual, terms = DEFAULT_TERMS) => individual?.data?.private ? terms.privateRecord : individual?.label || individual?.id || terms.unknown;
|
|
27
39
|
const MODE_TEXT = {
|
package/dist/headless.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { usePedigreeLayout, usePedigreeNavigation, usePedigreeProjection, usePedigreeSelection, useOccurrenceHighlighting, nearestNode, type Direction } from './hooks.js';
|
|
2
|
-
export { arcPath, DEFAULT_TERMS, describeProjection, describeStructure, labelOf, VIEW_LABELS, type Terminology } from './describe.js';
|
|
2
|
+
export { arcPath, DEFAULT_TERMS, describeProjection, describeStructure, labelOf, sexWord, VIEW_LABELS, type Terminology } from './describe.js';
|
|
3
3
|
export { contrastRatio, isHexColor, presetTheme, resolveThemeColors, THEME_PRESETS, THEME_TOKENS, themeStyle, TOKEN_LABELS, type PedigreeTheme, type ThemeColors, type ThemeToken, } from './themes.js';
|
package/dist/headless.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { usePedigreeLayout, usePedigreeNavigation, usePedigreeProjection, usePedigreeSelection, useOccurrenceHighlighting, nearestNode } from './hooks.js';
|
|
2
|
-
export { arcPath, DEFAULT_TERMS, describeProjection, describeStructure, labelOf, VIEW_LABELS } from './describe.js';
|
|
2
|
+
export { arcPath, DEFAULT_TERMS, describeProjection, describeStructure, labelOf, sexWord, VIEW_LABELS } from './describe.js';
|
|
3
3
|
export { contrastRatio, isHexColor, presetTheme, resolveThemeColors, THEME_PRESETS, THEME_TOKENS, themeStyle, TOKEN_LABELS, } from './themes.js';
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@captiveorigins/onepedigree-react",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.15",
|
|
4
4
|
"description": "OnePedigree for React: server-renderable SVG pedigree views (all 13), an interactive explorer, headless hooks and CSS-variable styling.",
|
|
5
|
-
"homepage": "https://github.com/
|
|
5
|
+
"homepage": "https://github.com/CaptiveOrigins/onepedigree#readme",
|
|
6
6
|
"bugs": {
|
|
7
|
-
"url": "https://github.com/
|
|
7
|
+
"url": "https://github.com/CaptiveOrigins/onepedigree/issues"
|
|
8
8
|
},
|
|
9
9
|
"keywords": [
|
|
10
10
|
"pedigree",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
18
18
|
"repository": {
|
|
19
19
|
"type": "git",
|
|
20
|
-
"url": "git+https://github.com/
|
|
20
|
+
"url": "git+https://github.com/CaptiveOrigins/onepedigree.git",
|
|
21
21
|
"directory": "packages/react"
|
|
22
22
|
},
|
|
23
23
|
"type": "module",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"node": ">=22"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@captiveorigins/onepedigree-core": "^0.1.0-alpha.
|
|
50
|
+
"@captiveorigins/onepedigree-core": "^0.1.0-alpha.15"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"react": ">=18.2"
|