@agora-sdk/social-react-native 0.6.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/LICENSE +202 -0
- package/dist/cjs/components/CommunityWeather.d.ts +24 -0
- package/dist/cjs/components/CommunityWeather.js +128 -0
- package/dist/cjs/components/CommunityWeather.js.map +1 -0
- package/dist/cjs/components/Constellation.d.ts +24 -0
- package/dist/cjs/components/Constellation.js +97 -0
- package/dist/cjs/components/Constellation.js.map +1 -0
- package/dist/cjs/components/Neighborhood.d.ts +24 -0
- package/dist/cjs/components/Neighborhood.js +131 -0
- package/dist/cjs/components/Neighborhood.js.map +1 -0
- package/dist/cjs/components/SocialTransparency.d.ts +21 -0
- package/dist/cjs/components/SocialTransparency.js +43 -0
- package/dist/cjs/components/SocialTransparency.js.map +1 -0
- package/dist/cjs/index.d.ts +11 -0
- package/dist/cjs/index.js +40 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/layout.d.ts +25 -0
- package/dist/cjs/layout.js +54 -0
- package/dist/cjs/layout.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/palette.d.ts +58 -0
- package/dist/cjs/palette.js +65 -0
- package/dist/cjs/palette.js.map +1 -0
- package/dist/esm/components/CommunityWeather.d.ts +24 -0
- package/dist/esm/components/CommunityWeather.js +89 -0
- package/dist/esm/components/CommunityWeather.js.map +1 -0
- package/dist/esm/components/Constellation.d.ts +24 -0
- package/dist/esm/components/Constellation.js +61 -0
- package/dist/esm/components/Constellation.js.map +1 -0
- package/dist/esm/components/Neighborhood.d.ts +24 -0
- package/dist/esm/components/Neighborhood.js +92 -0
- package/dist/esm/components/Neighborhood.js.map +1 -0
- package/dist/esm/components/SocialTransparency.d.ts +21 -0
- package/dist/esm/components/SocialTransparency.js +40 -0
- package/dist/esm/components/SocialTransparency.js.map +1 -0
- package/dist/esm/index.d.ts +11 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/layout.d.ts +25 -0
- package/dist/esm/layout.js +50 -0
- package/dist/esm/layout.js.map +1 -0
- package/dist/esm/palette.d.ts +58 -0
- package/dist/esm/palette.js +60 -0
- package/dist/esm/palette.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// <Neighborhood /> — the caller's own named ties, lit by dyadic brightness (React Native).
|
|
3
|
+
//
|
|
4
|
+
// Native port of the web component. Renders the self-view tie list (brightest-first, as the server
|
|
5
|
+
// sorts it). Brightness drives a glow treatment ONLY — the number is never shown, labeled, or compared
|
|
6
|
+
// between ties (SOCIAL.md §6). Ties at the floor band render as a warm "sprout" (hopeful/new), not a
|
|
7
|
+
// grey absence. An optional RN Switch wires the `includeInteractions` toggle. Returns `null` when the
|
|
8
|
+
// lens is disabled or still loading.
|
|
9
|
+
//
|
|
10
|
+
// Privacy note: the underlying hook keeps ties in component state only and clears them on a user/project
|
|
11
|
+
// switch — this component adds no cache of its own, so the self-view never lingers across sign-outs.
|
|
12
|
+
import React from "react";
|
|
13
|
+
import { View, Text, Image, Switch, ScrollView, StyleSheet } from "react-native";
|
|
14
|
+
import Svg, { Defs, LinearGradient, Stop, Rect } from "react-native-svg";
|
|
15
|
+
import { useSocialNeighborhood } from "@agora-sdk/social-core";
|
|
16
|
+
import { brightnessTreatment } from "../palette.js";
|
|
17
|
+
/** Subtle glyphs for the tie-kind chips. Hints, not labels. */
|
|
18
|
+
const TIE_KIND_GLYPH = {
|
|
19
|
+
follow: "→",
|
|
20
|
+
connection: "↔",
|
|
21
|
+
interaction: "·",
|
|
22
|
+
};
|
|
23
|
+
/** Best available display label for a tie, falling back gracefully when fields are null. */
|
|
24
|
+
function displayName(tie) {
|
|
25
|
+
return tie.name ?? tie.username ?? "Someone";
|
|
26
|
+
}
|
|
27
|
+
/** First glyph for the avatar fallback. */
|
|
28
|
+
function initial(tie) {
|
|
29
|
+
return displayName(tie).charAt(0).toUpperCase();
|
|
30
|
+
}
|
|
31
|
+
/** One tie card — avatar (or initial) + name + tie-kind chips, lit by brightness glow. */
|
|
32
|
+
function TieCard({ tie, gradientId }) {
|
|
33
|
+
const t = brightnessTreatment(tie.brightness);
|
|
34
|
+
// Sprout ties get a warm amber halo (hopeful/new); brighter ties get a golden glow. Never grey.
|
|
35
|
+
// The opacity rides on shadowOpacity, so the color itself is fully opaque.
|
|
36
|
+
const glowColor = t.isSprout ? "#e0a955" : "#f4c64a";
|
|
37
|
+
return (_jsxs(View, { style: styles.card, children: [_jsx(View, { style: [
|
|
38
|
+
styles.avatar,
|
|
39
|
+
{
|
|
40
|
+
transform: [{ scale: t.scale }],
|
|
41
|
+
shadowColor: glowColor,
|
|
42
|
+
shadowRadius: t.shadowRadius,
|
|
43
|
+
shadowOpacity: t.shadowOpacity,
|
|
44
|
+
elevation: t.elevation,
|
|
45
|
+
},
|
|
46
|
+
], children: tie.avatar ? (_jsx(Image, { source: { uri: tie.avatar }, style: styles.avatarImg })) : (_jsxs(_Fragment, { children: [_jsxs(Svg, { width: 40, height: 40, style: StyleSheet.absoluteFill, children: [_jsx(Defs, { children: _jsxs(LinearGradient, { id: gradientId, x1: "0", y1: "0", x2: "1", y2: "1", children: [_jsx(Stop, { offset: "0", stopColor: "#e0a955" }), _jsx(Stop, { offset: "1", stopColor: "#f4c64a" })] }) }), _jsx(Rect, { width: 40, height: 40, rx: 20, fill: `url(#${gradientId})` })] }), _jsx(Text, { style: styles.avatarInitial, children: initial(tie) })] })) }), _jsxs(View, { style: styles.cardText, children: [_jsx(Text, { style: styles.name, children: displayName(tie) }), _jsx(View, { style: styles.kinds, children: tie.tieKinds.map((kind) => (_jsxs(Text, { style: styles.kind, accessibilityLabel: kind, children: [TIE_KIND_GLYPH[kind], " ", kind] }, kind))) })] })] }));
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Render the caller's Neighborhood — their named ties, lit by dyadic brightness.
|
|
50
|
+
*
|
|
51
|
+
* Self-contained: reads {@link useSocialNeighborhood} and gates on the feature config. Ties render in
|
|
52
|
+
* the server's brightest-first order; brightness becomes glow/scale, never a number. Optionally shows
|
|
53
|
+
* the interactions toggle.
|
|
54
|
+
*
|
|
55
|
+
* @param props - {@link NeighborhoodProps}.
|
|
56
|
+
* @returns The tie list, or `null` when the lens is disabled or still loading.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```tsx
|
|
60
|
+
* <Neighborhood showInteractionsToggle />
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export function Neighborhood({ showInteractionsToggle = false, style, }) {
|
|
64
|
+
const { neighborhood, includeInteractions, setIncludeInteractions } = useSocialNeighborhood();
|
|
65
|
+
// Stable per-mount prefix so each tie's fallback gradient id is unique within this component instance.
|
|
66
|
+
const gid = `nb-${React.useId().replace(/:/g, "")}`;
|
|
67
|
+
if (!neighborhood)
|
|
68
|
+
return null;
|
|
69
|
+
return (_jsxs(View, { style: style, children: [showInteractionsToggle && (_jsxs(View, { style: styles.toggleRow, children: [_jsx(Switch, { value: includeInteractions, onValueChange: setIncludeInteractions }), _jsx(Text, { style: styles.toggleLabel, children: "Include people I\u2019ve interacted with" })] })), _jsx(ScrollView, { children: neighborhood.ties.map((tie, i) => (_jsx(TieCard, { tie: tie, gradientId: `${gid}-${i}` }, tie.userId))) })] }));
|
|
70
|
+
}
|
|
71
|
+
const styles = StyleSheet.create({
|
|
72
|
+
toggleRow: { flexDirection: "row", alignItems: "center", gap: 8, marginBottom: 8 },
|
|
73
|
+
toggleLabel: { fontSize: 13 },
|
|
74
|
+
card: { flexDirection: "row", alignItems: "center", gap: 12, paddingVertical: 8, paddingHorizontal: 4 },
|
|
75
|
+
avatar: {
|
|
76
|
+
width: 40,
|
|
77
|
+
height: 40,
|
|
78
|
+
borderRadius: 20,
|
|
79
|
+
overflow: "visible",
|
|
80
|
+
alignItems: "center",
|
|
81
|
+
justifyContent: "center",
|
|
82
|
+
shadowOffset: { width: 0, height: 0 },
|
|
83
|
+
backgroundColor: "#e0a955", // base tint behind the SVG/Image so the glow never reads grey
|
|
84
|
+
},
|
|
85
|
+
avatarImg: { width: 40, height: 40, borderRadius: 20 },
|
|
86
|
+
avatarInitial: { color: "#1b1b24", fontWeight: "700", fontSize: 16 },
|
|
87
|
+
cardText: { flexDirection: "column", gap: 2 },
|
|
88
|
+
name: { fontSize: 14, fontWeight: "600" },
|
|
89
|
+
kinds: { flexDirection: "row", gap: 6 },
|
|
90
|
+
kind: { fontSize: 11, color: "#9ca3af" },
|
|
91
|
+
});
|
|
92
|
+
//# sourceMappingURL=Neighborhood.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Neighborhood.js","sourceRoot":"","sources":["../../../src/components/Neighborhood.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/** Props for {@link SocialTransparency}. */
|
|
3
|
+
export interface SocialTransparencyProps {
|
|
4
|
+
/** Optional style for the root element. */
|
|
5
|
+
style?: object;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Render the social-graph transparency panel.
|
|
9
|
+
*
|
|
10
|
+
* Self-contained: reads {@link useSocialTransparency} from the provider. Lists the enabled lenses and
|
|
11
|
+
* the tuning that shapes them, in member-safe terms.
|
|
12
|
+
*
|
|
13
|
+
* @param props - {@link SocialTransparencyProps}.
|
|
14
|
+
* @returns The disclosure panel, or `null` until the config has resolved.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <SocialTransparency />
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function SocialTransparency({ style, }: SocialTransparencyProps): React.ReactElement | null;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { View, Text, StyleSheet } from "react-native";
|
|
3
|
+
import { useSocialTransparency } from "@agora-sdk/social-core";
|
|
4
|
+
/** One labeled row in the disclosure panel. */
|
|
5
|
+
function Row({ label, value }) {
|
|
6
|
+
return (_jsxs(View, { style: styles.row, children: [_jsx(Text, { style: styles.rowLabel, children: label }), _jsx(Text, { style: styles.rowValue, children: value })] }));
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Render the social-graph transparency panel.
|
|
10
|
+
*
|
|
11
|
+
* Self-contained: reads {@link useSocialTransparency} from the provider. Lists the enabled lenses and
|
|
12
|
+
* the tuning that shapes them, in member-safe terms.
|
|
13
|
+
*
|
|
14
|
+
* @param props - {@link SocialTransparencyProps}.
|
|
15
|
+
* @returns The disclosure panel, or `null` until the config has resolved.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* <SocialTransparency />
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function SocialTransparency({ style, }) {
|
|
23
|
+
const { config } = useSocialTransparency();
|
|
24
|
+
if (!config)
|
|
25
|
+
return null;
|
|
26
|
+
const lenses = [
|
|
27
|
+
config.weatherEnabled && "Weather",
|
|
28
|
+
config.constellationEnabled && "Constellation",
|
|
29
|
+
config.neighborhoodEnabled && "Neighborhood",
|
|
30
|
+
].filter(Boolean);
|
|
31
|
+
return (_jsxs(View, { style: style, accessibilityLabel: "How the social graph works", children: [_jsx(Text, { style: styles.heading, children: "How your community graph works" }), _jsx(Row, { label: "Active lenses", value: lenses.length ? lenses.join(", ") : "None" }), _jsx(Row, { label: "Warmth memory", value: `~${config.warmthHalfLifeDays}-day half-life` }), _jsx(Row, { label: "Friction memory", value: `~${config.frictionHalfLifeDays}-day half-life` }), _jsx(Row, { label: "Smallest visible cluster", value: `${config.constellationKFloor}+ members` }), _jsx(Row, { label: "Neighborhood includes interactions", value: config.neighborhoodIncludeInteractions ? "By default" : "Only if you opt in" }), _jsx(Text, { style: styles.footnote, children: "Warmth fades gently over time, so the graph reflects how things are now \u2014 not a permanent score. Clusters smaller than the floor are never shown. Your Neighborhood is yours alone." })] }));
|
|
32
|
+
}
|
|
33
|
+
const styles = StyleSheet.create({
|
|
34
|
+
heading: { fontSize: 14, fontWeight: "600", marginBottom: 8 },
|
|
35
|
+
row: { flexDirection: "row", justifyContent: "space-between", gap: 16, paddingVertical: 4 },
|
|
36
|
+
rowLabel: { fontSize: 13, color: "#9ca3af" },
|
|
37
|
+
rowValue: { fontSize: 13, fontWeight: "600" },
|
|
38
|
+
footnote: { fontSize: 12, color: "#9ca3af", marginTop: 10, lineHeight: 18 },
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=SocialTransparency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SocialTransparency.js","sourceRoot":"","sources":["../../../src/components/SocialTransparency.tsx"],"names":[],"mappings":";AAQA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAQ/D,+CAA+C;AAC/C,SAAS,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,EAAoC;IAC7D,OAAO,CACL,MAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,GAAG,aACrB,KAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,YAAG,KAAK,GAAQ,EAC5C,KAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,YAAG,KAAK,GAAQ,IACvC,CACR,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CAAC,EACjC,KAAK,GACmB;IACxB,MAAM,EAAE,MAAM,EAAE,GAAG,qBAAqB,EAAE,CAAC;IAC3C,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,MAAM,GAAG;QACb,MAAM,CAAC,cAAc,IAAI,SAAS;QAClC,MAAM,CAAC,oBAAoB,IAAI,eAAe;QAC9C,MAAM,CAAC,mBAAmB,IAAI,cAAc;KAC7C,CAAC,MAAM,CAAC,OAAO,CAAa,CAAC;IAE9B,OAAO,CACL,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAC,4BAA4B,aACjE,KAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,OAAO,+CAAuC,EAClE,KAAC,GAAG,IAAC,KAAK,EAAC,eAAe,EAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,GAAI,EAChF,KAAC,GAAG,IAAC,KAAK,EAAC,eAAe,EAAC,KAAK,EAAE,IAAI,MAAM,CAAC,kBAAkB,gBAAgB,GAAI,EACnF,KAAC,GAAG,IAAC,KAAK,EAAC,iBAAiB,EAAC,KAAK,EAAE,IAAI,MAAM,CAAC,oBAAoB,gBAAgB,GAAI,EACvF,KAAC,GAAG,IAAC,KAAK,EAAC,0BAA0B,EAAC,KAAK,EAAE,GAAG,MAAM,CAAC,mBAAmB,WAAW,GAAI,EACzF,KAAC,GAAG,IACF,KAAK,EAAC,oCAAoC,EAC1C,KAAK,EAAE,MAAM,CAAC,+BAA+B,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,oBAAoB,GACnF,EACF,KAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,yMAGrB,IACF,CACR,CAAC;AACJ,CAAC;AAED,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAC/B,OAAO,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE;IAC7D,GAAG,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,GAAG,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,EAAE;IAC3F,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE;IAC5C,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE;IAC7C,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;CAC5E,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from "@agora-sdk/social-core";
|
|
2
|
+
export { CommunityWeather } from "./components/CommunityWeather.js";
|
|
3
|
+
export type { CommunityWeatherProps } from "./components/CommunityWeather.js";
|
|
4
|
+
export { Constellation } from "./components/Constellation.js";
|
|
5
|
+
export type { ConstellationProps } from "./components/Constellation.js";
|
|
6
|
+
export { Neighborhood } from "./components/Neighborhood.js";
|
|
7
|
+
export type { NeighborhoodProps } from "./components/Neighborhood.js";
|
|
8
|
+
export { SocialTransparency } from "./components/SocialTransparency.js";
|
|
9
|
+
export type { SocialTransparencyProps } from "./components/SocialTransparency.js";
|
|
10
|
+
export { bandPalette, bandColors, brightnessTreatment } from "./palette.js";
|
|
11
|
+
export type { BandColors, BrightnessTreatment } from "./palette.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// @agora-sdk/social-react-native — bare React Native bindings for the Agora social graph.
|
|
2
|
+
//
|
|
3
|
+
// Re-exports the platform-agnostic core (provider + four feature-gated hooks + transport + wire types)
|
|
4
|
+
// and adds the NATIVE visual components for the three lenses plus the transparency disclosure, drawn on
|
|
5
|
+
// React Native primitives + react-native-svg. Use this package (not core directly) in a bare RN app so
|
|
6
|
+
// the components ship. The shared climate palette is exported too, so host apps can match the SDK's
|
|
7
|
+
// warmth vocabulary in their own chrome. The data layer is pure REST — no platform crypto involved.
|
|
8
|
+
export * from "@agora-sdk/social-core";
|
|
9
|
+
// ── components ────────────────────────────────────────────────────────────────
|
|
10
|
+
export { CommunityWeather } from "./components/CommunityWeather.js";
|
|
11
|
+
export { Constellation } from "./components/Constellation.js";
|
|
12
|
+
export { Neighborhood } from "./components/Neighborhood.js";
|
|
13
|
+
export { SocialTransparency } from "./components/SocialTransparency.js";
|
|
14
|
+
// ── shared visual vocabulary (palette + brightness mapping) ───────────────────
|
|
15
|
+
export { bandPalette, bandColors, brightnessTreatment } from "./palette.js";
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,EAAE;AACF,uGAAuG;AACvG,wGAAwG;AACxG,uGAAuG;AACvG,oGAAoG;AACpG,oGAAoG;AAEpG,cAAc,wBAAwB,CAAC;AAEvC,iFAAiF;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEpE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAGxE,iFAAiF;AACjF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type SimulationNodeDatum } from "d3-force";
|
|
2
|
+
import type { BlobSizeBucket, ConstellationBlob, WeatherBand } from "@agora-sdk/social-core";
|
|
3
|
+
/**
|
|
4
|
+
* Fixed bucket → blob radius (px). Deliberately coarse: the bucket IS the privacy protection, so the
|
|
5
|
+
* visual never encodes more precision than the bucket itself (SOCIAL.md §6).
|
|
6
|
+
*/
|
|
7
|
+
export declare const BUCKET_RADIUS: Record<BlobSizeBucket, number>;
|
|
8
|
+
/** A blob with a force-resolved position. d3-force mutates `x`/`y` in place during simulation. */
|
|
9
|
+
export interface BlobNode extends SimulationNodeDatum {
|
|
10
|
+
/** Blob radius in px (from {@link BUCKET_RADIUS}). */
|
|
11
|
+
r: number;
|
|
12
|
+
/** Warmth band that tints the blob. */
|
|
13
|
+
warmth: WeatherBand;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Lay out blobs with fresh random positions resolved by a synchronous force pass. Re-randomization is
|
|
17
|
+
* a privacy requirement, so this runs from scratch each time it is called — never memoized to a stable
|
|
18
|
+
* layout. Uses `Math.random()` only for visual placement (no security relevance).
|
|
19
|
+
*
|
|
20
|
+
* @param blobs - The constellation blobs to place.
|
|
21
|
+
* @param width - Canvas width in px.
|
|
22
|
+
* @param height - Canvas height in px.
|
|
23
|
+
* @returns One {@link BlobNode} per blob, with settled, non-overlapping `x`/`y`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function computePositions(blobs: ConstellationBlob[], width: number, height: number): BlobNode[];
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Constellation layout — the d3-force blob placement, shared verbatim with the web sibling.
|
|
2
|
+
//
|
|
3
|
+
// d3-force is pure JS (no DOM), so the exact same synchronous force pass the web `<Constellation />`
|
|
4
|
+
// uses ports to native untouched. The SOCIAL.md §6 privacy rules are baked in here:
|
|
5
|
+
// • Size by BUCKET, never an exact count — radius comes from a fixed bucket→px map.
|
|
6
|
+
// • No stable layout — positions are seeded with a fresh `Math.random()` every call, so no cluster
|
|
7
|
+
// has a "home" a viewer could track across mounts. `Math.random()` is layout-only (no security
|
|
8
|
+
// relevance); the simulation then resolves overlaps with collision + center gravity.
|
|
9
|
+
//
|
|
10
|
+
// No `react-native` import here on purpose: this stays pure logic so it unit-tests under plain vitest.
|
|
11
|
+
import { forceCenter, forceCollide, forceSimulation, } from "d3-force";
|
|
12
|
+
/**
|
|
13
|
+
* Fixed bucket → blob radius (px). Deliberately coarse: the bucket IS the privacy protection, so the
|
|
14
|
+
* visual never encodes more precision than the bucket itself (SOCIAL.md §6).
|
|
15
|
+
*/
|
|
16
|
+
export const BUCKET_RADIUS = {
|
|
17
|
+
"5–9": 20,
|
|
18
|
+
"10–19": 28,
|
|
19
|
+
"20–49": 38,
|
|
20
|
+
"50–99": 50,
|
|
21
|
+
"100+": 65,
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Lay out blobs with fresh random positions resolved by a synchronous force pass. Re-randomization is
|
|
25
|
+
* a privacy requirement, so this runs from scratch each time it is called — never memoized to a stable
|
|
26
|
+
* layout. Uses `Math.random()` only for visual placement (no security relevance).
|
|
27
|
+
*
|
|
28
|
+
* @param blobs - The constellation blobs to place.
|
|
29
|
+
* @param width - Canvas width in px.
|
|
30
|
+
* @param height - Canvas height in px.
|
|
31
|
+
* @returns One {@link BlobNode} per blob, with settled, non-overlapping `x`/`y`.
|
|
32
|
+
*/
|
|
33
|
+
export function computePositions(blobs, width, height) {
|
|
34
|
+
const nodes = blobs.map((b) => ({
|
|
35
|
+
r: BUCKET_RADIUS[b.size] ?? 28,
|
|
36
|
+
warmth: b.warmth,
|
|
37
|
+
// Random seed placement near the center; the simulation spreads them without overlap.
|
|
38
|
+
x: width / 2 + (Math.random() - 0.5) * width * 0.6,
|
|
39
|
+
y: height / 2 + (Math.random() - 0.5) * height * 0.6,
|
|
40
|
+
}));
|
|
41
|
+
// Build a simulation, immediately stop its internal timer, and tick it synchronously so we get a
|
|
42
|
+
// settled, non-overlapping layout in one render with no animation loop or async state.
|
|
43
|
+
const simulation = forceSimulation(nodes)
|
|
44
|
+
.force("collide", forceCollide((d) => d.r + 8))
|
|
45
|
+
.force("center", forceCenter(width / 2, height / 2))
|
|
46
|
+
.stop();
|
|
47
|
+
simulation.tick(300);
|
|
48
|
+
return nodes;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/layout.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,EAAE;AACF,qGAAqG;AACrG,oFAAoF;AACpF,sFAAsF;AACtF,qGAAqG;AACrG,mGAAmG;AACnG,yFAAyF;AACzF,EAAE;AACF,uGAAuG;AAEvG,OAAO,EACL,WAAW,EACX,YAAY,EACZ,eAAe,GAEhB,MAAM,UAAU,CAAC;AAGlB;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAmC;IAC3D,KAAK,EAAE,EAAE;IACT,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,EAAE;IACX,MAAM,EAAE,EAAE;CACX,CAAC;AAUF;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAA0B,EAC1B,KAAa,EACb,MAAc;IAEd,MAAM,KAAK,GAAe,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1C,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE;QAC9B,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,sFAAsF;QACtF,CAAC,EAAE,KAAK,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,KAAK,GAAG,GAAG;QAClD,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,MAAM,GAAG,GAAG;KACrD,CAAC,CAAC,CAAC;IAEJ,iGAAiG;IACjG,uFAAuF;IACvF,MAAM,UAAU,GAAG,eAAe,CAAC,KAAK,CAAC;SACtC,KAAK,CAAC,SAAS,EAAE,YAAY,CAAW,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;SACxD,KAAK,CAAC,QAAQ,EAAE,WAAW,CAAC,KAAK,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;SACnD,IAAI,EAAE,CAAC;IACV,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAErB,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { WeatherBand } from "@agora-sdk/social-core";
|
|
2
|
+
/** A band's rendering colors: a `core` fill/ink and a softer `glow` for shadows/auras. */
|
|
3
|
+
export interface BandColors {
|
|
4
|
+
/** The primary fill or text color for this band. */
|
|
5
|
+
core: string;
|
|
6
|
+
/** A translucent glow/aura color (for shadows, radial-gradient edges). */
|
|
7
|
+
glow: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Maps each {@link WeatherBand} to its calm climate colors. Kept deliberately in the amber/slate/grey
|
|
11
|
+
* register — **no red anywhere** — so low warmth never reads as an alarm (SOCIAL.md §5). These are the
|
|
12
|
+
* exact same hex/rgba constants as the web palette, so a native and a web client tint warmth identically.
|
|
13
|
+
*
|
|
14
|
+
* - `quiet` — soft grey-blue, "still forming" (the no-data sentinel)
|
|
15
|
+
* - `stormy` — muted slate-blue (low warmth, NOT danger)
|
|
16
|
+
* - `overcast` — cool grey (below average)
|
|
17
|
+
* - `fine` — warm amber-gold (above average)
|
|
18
|
+
* - `sunny` — bright golden-yellow (high warmth)
|
|
19
|
+
*/
|
|
20
|
+
export declare const bandPalette: Record<WeatherBand, BandColors>;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve the climate colors for a band, defaulting to `quiet` for any unexpected value (fail-soft to
|
|
23
|
+
* the neutral "forming" look rather than throwing on malformed server data).
|
|
24
|
+
*
|
|
25
|
+
* @param band - The weather/warmth band to color.
|
|
26
|
+
* @returns The {@link BandColors} for that band.
|
|
27
|
+
*/
|
|
28
|
+
export declare function bandColors(band: WeatherBand): BandColors;
|
|
29
|
+
/**
|
|
30
|
+
* A tie's brightness expressed as React Native visual WEIGHT — shadow glow, elevation, and scale —
|
|
31
|
+
* never as a number. The shadow *color* is chosen by the component (amber for sprouts, golden
|
|
32
|
+
* otherwise); this carries only the magnitude props plus the sprout flag.
|
|
33
|
+
*/
|
|
34
|
+
export interface BrightnessTreatment {
|
|
35
|
+
/** iOS `shadowRadius` in px (higher = warmer, closer). */
|
|
36
|
+
shadowRadius: number;
|
|
37
|
+
/** iOS `shadowOpacity` in `[0, 1]`. */
|
|
38
|
+
shadowOpacity: number;
|
|
39
|
+
/** Android `elevation` (a coarse glow proxy, since Android has no tunable shadow blur). */
|
|
40
|
+
elevation: number;
|
|
41
|
+
/** Node scale multiplier (brighter ties read slightly larger). */
|
|
42
|
+
scale: number;
|
|
43
|
+
/**
|
|
44
|
+
* True for ties at the floor band (`[0.15, 0.24]`): render the warm, hopeful "sprout" treatment, not
|
|
45
|
+
* a grey absence. New ≠ lonely ≠ deficient (SOCIAL.md §6).
|
|
46
|
+
*/
|
|
47
|
+
isSprout: boolean;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Map a dyadic `brightness` in `[0.15, 1.0]` to an RN visual treatment — shadow glow, elevation, scale,
|
|
51
|
+
* and the sprout flag. The brightness number itself is **never** returned for display; it is a rendering
|
|
52
|
+
* input only. The clamp floor and the `isSprout` threshold are identical to the web palette so the
|
|
53
|
+
* privacy semantics never diverge across platforms.
|
|
54
|
+
*
|
|
55
|
+
* @param brightness - Dyadic brightness in `[0.15, 1.0]` (values outside are clamped).
|
|
56
|
+
* @returns The {@link BrightnessTreatment} for that tie.
|
|
57
|
+
*/
|
|
58
|
+
export declare function brightnessTreatment(brightness: number): BrightnessTreatment;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Climate palette + brightness mapping for native — the privacy-critical visual vocabulary.
|
|
2
|
+
//
|
|
3
|
+
// This is the React Native PORT of the web sibling (`@agora-sdk/social-react-js`'s `palette.ts`). It
|
|
4
|
+
// keeps the SAME SOCIAL.md §5 band colors and the SAME §6 brightness thresholds (the `isSprout`
|
|
5
|
+
// floor at 0.24, the `[0.15, 1.0]` clamp) — those are privacy-critical and must not drift between
|
|
6
|
+
// platforms — but `brightnessTreatment` returns RN shadow/elevation props instead of values tuned for
|
|
7
|
+
// a CSS `box-shadow` string. The rule still holds on every surface: a sky/climate register, **never
|
|
8
|
+
// red** for low warmth, and the floor band rendered as a hopeful sprout glow, never a grey absence.
|
|
9
|
+
//
|
|
10
|
+
// No `react-native` import here on purpose: this module is pure logic so it unit-tests under plain
|
|
11
|
+
// vitest (node env) without an RN renderer.
|
|
12
|
+
/**
|
|
13
|
+
* Maps each {@link WeatherBand} to its calm climate colors. Kept deliberately in the amber/slate/grey
|
|
14
|
+
* register — **no red anywhere** — so low warmth never reads as an alarm (SOCIAL.md §5). These are the
|
|
15
|
+
* exact same hex/rgba constants as the web palette, so a native and a web client tint warmth identically.
|
|
16
|
+
*
|
|
17
|
+
* - `quiet` — soft grey-blue, "still forming" (the no-data sentinel)
|
|
18
|
+
* - `stormy` — muted slate-blue (low warmth, NOT danger)
|
|
19
|
+
* - `overcast` — cool grey (below average)
|
|
20
|
+
* - `fine` — warm amber-gold (above average)
|
|
21
|
+
* - `sunny` — bright golden-yellow (high warmth)
|
|
22
|
+
*/
|
|
23
|
+
export const bandPalette = {
|
|
24
|
+
quiet: { core: "#8a94a6", glow: "rgba(138, 148, 166, 0.35)" },
|
|
25
|
+
stormy: { core: "#5b6b86", glow: "rgba(91, 107, 134, 0.40)" },
|
|
26
|
+
overcast: { core: "#8d96a3", glow: "rgba(141, 150, 163, 0.40)" },
|
|
27
|
+
fine: { core: "#e0a955", glow: "rgba(224, 169, 85, 0.55)" },
|
|
28
|
+
sunny: { core: "#f4c64a", glow: "rgba(244, 198, 74, 0.70)" },
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the climate colors for a band, defaulting to `quiet` for any unexpected value (fail-soft to
|
|
32
|
+
* the neutral "forming" look rather than throwing on malformed server data).
|
|
33
|
+
*
|
|
34
|
+
* @param band - The weather/warmth band to color.
|
|
35
|
+
* @returns The {@link BandColors} for that band.
|
|
36
|
+
*/
|
|
37
|
+
export function bandColors(band) {
|
|
38
|
+
return bandPalette[band] ?? bandPalette.quiet;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Map a dyadic `brightness` in `[0.15, 1.0]` to an RN visual treatment — shadow glow, elevation, scale,
|
|
42
|
+
* and the sprout flag. The brightness number itself is **never** returned for display; it is a rendering
|
|
43
|
+
* input only. The clamp floor and the `isSprout` threshold are identical to the web palette so the
|
|
44
|
+
* privacy semantics never diverge across platforms.
|
|
45
|
+
*
|
|
46
|
+
* @param brightness - Dyadic brightness in `[0.15, 1.0]` (values outside are clamped).
|
|
47
|
+
* @returns The {@link BrightnessTreatment} for that tie.
|
|
48
|
+
*/
|
|
49
|
+
export function brightnessTreatment(brightness) {
|
|
50
|
+
const b = Math.min(1, Math.max(0.15, brightness));
|
|
51
|
+
// Same curve as the web sibling: a linear glow within the meaningful range, with the floor band
|
|
52
|
+
// special-cased as the sprout state. Mapped onto RN shadow/elevation props instead of a box-shadow.
|
|
53
|
+
const shadowRadius = 6 + Math.round(b * 22); // ~9px at floor → 28px at full glow
|
|
54
|
+
const shadowOpacity = 0.25 + b * 0.55; // ~0.33 at floor → 0.8 at full glow
|
|
55
|
+
const elevation = 2 + Math.round(b * 10); // Android proxy: ~4 at floor → 12 at full glow
|
|
56
|
+
const scale = 0.94 + b * 0.12; // subtle: brighter ties read slightly larger
|
|
57
|
+
const isSprout = b <= 0.24;
|
|
58
|
+
return { shadowRadius, shadowOpacity, elevation, scale, isSprout };
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=palette.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"palette.js","sourceRoot":"","sources":["../../src/palette.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,EAAE;AACF,qGAAqG;AACrG,gGAAgG;AAChG,kGAAkG;AAClG,sGAAsG;AACtG,oGAAoG;AACpG,oGAAoG;AACpG,EAAE;AACF,mGAAmG;AACnG,4CAA4C;AAY5C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,WAAW,GAAoC;IAC1D,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,2BAA2B,EAAE;IAC7D,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,0BAA0B,EAAE;IAC7D,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,2BAA2B,EAAE;IAChE,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,0BAA0B,EAAE;IAC3D,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,0BAA0B,EAAE;CAC7D,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,IAAiB;IAC1C,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC;AAChD,CAAC;AAuBD;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;IAClD,gGAAgG;IAChG,oGAAoG;IACpG,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,oCAAoC;IACjF,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,oCAAoC;IAC3E,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,+CAA+C;IACzF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,6CAA6C;IAC5E,MAAM,QAAQ,GAAG,CAAC,IAAI,IAAI,CAAC;IAC3B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACrE,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agora-sdk/social-react-native",
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"author": "Agora SDK Plus, maintained by Jenova Marie",
|
|
7
|
+
"description": "Bare React Native components for the Agora social graph: CommunityWeather, Constellation (d3-force + react-native-svg), Neighborhood, SocialTransparency. Re-exports @agora-sdk/social-core.",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"agora",
|
|
10
|
+
"social-graph",
|
|
11
|
+
"community",
|
|
12
|
+
"react-native",
|
|
13
|
+
"typescript"
|
|
14
|
+
],
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/jenova-marie/agora-sdk-plus/issues"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/jenova-marie/agora-sdk-plus",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/jenova-marie/agora-sdk-plus.git",
|
|
22
|
+
"directory": "packages/social/react-native"
|
|
23
|
+
},
|
|
24
|
+
"main": "dist/cjs/index.js",
|
|
25
|
+
"module": "dist/esm/index.js",
|
|
26
|
+
"types": "dist/esm/index.d.ts",
|
|
27
|
+
"type": "module",
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"d3-force": "^3.0.0",
|
|
36
|
+
"@agora-sdk/social-core": "0.6.0"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"@agora-sdk/core": "^1.2.2",
|
|
40
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
41
|
+
"react-native": ">=0.72.0",
|
|
42
|
+
"react-native-svg": ">=13.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/d3-force": "^3.0.10"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build:esm": "tsc -p tsconfig.esm.json",
|
|
49
|
+
"build:cjs": "tsc -p tsconfig.cjs.json && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
|
|
50
|
+
"build": "rimraf dist && pnpm run build:esm && pnpm run build:cjs",
|
|
51
|
+
"prepublish": "pnpm run build"
|
|
52
|
+
}
|
|
53
|
+
}
|