@eventuras/ratio-ui-native 0.0.0-stage → 0.1.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 +382 -0
- package/README.md +96 -2
- package/dist/Button.d.ts +23 -0
- package/dist/Button.d.ts.map +1 -0
- package/dist/Button.js +98 -0
- package/dist/Button.js.map +1 -0
- package/dist/Card.d.ts +28 -0
- package/dist/Card.d.ts.map +1 -0
- package/dist/Card.js +51 -0
- package/dist/Card.js.map +1 -0
- package/dist/RatioProvider.d.ts +38 -0
- package/dist/RatioProvider.d.ts.map +1 -0
- package/dist/RatioProvider.js +55 -0
- package/dist/RatioProvider.js.map +1 -0
- package/dist/Text.d.ts +37 -0
- package/dist/Text.d.ts.map +1 -0
- package/dist/Text.js +66 -0
- package/dist/Text.js.map +1 -0
- package/dist/chat/ChatLinkPreviewCard.d.ts +13 -0
- package/dist/chat/ChatLinkPreviewCard.d.ts.map +1 -0
- package/dist/chat/ChatLinkPreviewCard.js +78 -0
- package/dist/chat/ChatLinkPreviewCard.js.map +1 -0
- package/dist/chat/ChatLog.d.ts +42 -0
- package/dist/chat/ChatLog.d.ts.map +1 -0
- package/dist/chat/ChatLog.js +198 -0
- package/dist/chat/ChatLog.js.map +1 -0
- package/dist/chat/ChatReactions.d.ts +21 -0
- package/dist/chat/ChatReactions.d.ts.map +1 -0
- package/dist/chat/ChatReactions.js +63 -0
- package/dist/chat/ChatReactions.js.map +1 -0
- package/dist/chat/ChatText.d.ts +15 -0
- package/dist/chat/ChatText.d.ts.map +1 -0
- package/dist/chat/ChatText.js +36 -0
- package/dist/chat/ChatText.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/package.json +61 -3
package/dist/Card.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { useTheme } from "./RatioProvider.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import { Pressable, View } from "react-native";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/Card.tsx
|
|
6
|
+
/**
|
|
7
|
+
* A card on the theme's card surface, with its border, corner and shadow.
|
|
8
|
+
* With `onPress` it is one pressable target and lifts while pressed — the
|
|
9
|
+
* web card's hover lift, where touch has no hover.
|
|
10
|
+
*
|
|
11
|
+
* @beta This component is experimental — prop shape may change before release.
|
|
12
|
+
*/
|
|
13
|
+
var Card = ({ children, elevation = "xs", padding = "m", style, ...rest }) => {
|
|
14
|
+
const theme = useTheme();
|
|
15
|
+
const { card } = theme.components;
|
|
16
|
+
const resting = elevation === "none" ? null : card.shadow[elevation];
|
|
17
|
+
const base = {
|
|
18
|
+
backgroundColor: theme.colors.card,
|
|
19
|
+
borderWidth: 1,
|
|
20
|
+
borderColor: theme.colors.border1,
|
|
21
|
+
borderRadius: theme.radius.xl,
|
|
22
|
+
padding: theme.space[padding]
|
|
23
|
+
};
|
|
24
|
+
if (rest.onPress) return /* @__PURE__ */ jsx(Pressable, {
|
|
25
|
+
role: "button",
|
|
26
|
+
...rest,
|
|
27
|
+
style: ({ pressed }) => [
|
|
28
|
+
base,
|
|
29
|
+
{
|
|
30
|
+
backgroundColor: pressed ? theme.colors.cardHover : theme.colors.card,
|
|
31
|
+
borderColor: pressed ? theme.colors.primary : theme.colors.border1,
|
|
32
|
+
boxShadow: theme.shadow(pressed ? card.hoverShadow : resting)
|
|
33
|
+
},
|
|
34
|
+
style
|
|
35
|
+
],
|
|
36
|
+
children
|
|
37
|
+
});
|
|
38
|
+
return /* @__PURE__ */ jsx(View, {
|
|
39
|
+
...rest,
|
|
40
|
+
style: [
|
|
41
|
+
base,
|
|
42
|
+
{ boxShadow: theme.shadow(resting) },
|
|
43
|
+
style
|
|
44
|
+
],
|
|
45
|
+
children
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
//#endregion
|
|
49
|
+
export { Card };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=Card.js.map
|
package/dist/Card.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Card.js","names":[],"sources":["../src/Card.tsx"],"sourcesContent":["// ratio-ui · design system for knowledge sharing\n// SPDX-FileCopyrightText: 2026 Losol AS\n// SPDX-License-Identifier: MPL-2.0\n\nimport React from 'react';\nimport {\n Pressable,\n View,\n type PressableProps,\n type StyleProp,\n type ViewProps,\n type ViewStyle,\n} from 'react-native';\nimport type { SpaceStep } from '@eventuras/ratio-ui-core';\nimport { useTheme } from './RatioProvider';\n\nexport type CardElevation = 'none' | 'xs' | 'sm' | 'md';\n\ninterface CardOwnProps {\n children?: React.ReactNode;\n /** The resting shadow's tier; `none` is flat. @default 'xs' */\n elevation?: CardElevation;\n /** A step of the space scale. @default 'm' */\n padding?: SpaceStep;\n style?: StyleProp<ViewStyle>;\n}\n\n/** @beta Prop shape may change before release. */\nexport type CardProps = CardOwnProps &\n (\n | ({ onPress?: undefined } & Omit<ViewProps, 'style' | 'children'>)\n | ({ onPress: PressableProps['onPress'] } & Omit<PressableProps, 'style' | 'children'>)\n );\n\n/**\n * A card on the theme's card surface, with its border, corner and shadow.\n * With `onPress` it is one pressable target and lifts while pressed — the\n * web card's hover lift, where touch has no hover.\n *\n * @beta This component is experimental — prop shape may change before release.\n */\nexport const Card: React.FC<CardProps> = ({\n children,\n elevation = 'xs',\n padding = 'm',\n style,\n ...rest\n}) => {\n const theme = useTheme();\n const { card } = theme.components;\n const resting = elevation === 'none' ? null : card.shadow[elevation];\n\n const base: ViewStyle = {\n backgroundColor: theme.colors.card,\n borderWidth: 1,\n borderColor: theme.colors.border1,\n borderRadius: theme.radius.xl,\n padding: theme.space[padding],\n };\n\n if (rest.onPress) {\n return (\n <Pressable\n role=\"button\"\n {...(rest as PressableProps)}\n style={({ pressed }) => [\n base,\n {\n backgroundColor: pressed ? theme.colors.cardHover : theme.colors.card,\n borderColor: pressed ? theme.colors.primary : theme.colors.border1,\n boxShadow: theme.shadow(pressed ? card.hoverShadow : resting),\n },\n style,\n ]}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View {...(rest as ViewProps)} style={[base, { boxShadow: theme.shadow(resting) }, style]}>\n {children}\n </View>\n );\n};\n"],"mappings":";;;;;;;;;;;;AAyCA,IAAa,QAA6B,EACxC,UACA,YAAY,MACZ,UAAU,KACV,OACA,GAAG,WACC;CACJ,MAAM,QAAQ,SAAS;CACvB,MAAM,EAAE,SAAS,MAAM;CACvB,MAAM,UAAU,cAAc,SAAS,OAAO,KAAK,OAAO;CAE1D,MAAM,OAAkB;EACtB,iBAAiB,MAAM,OAAO;EAC9B,aAAa;EACb,aAAa,MAAM,OAAO;EAC1B,cAAc,MAAM,OAAO;EAC3B,SAAS,MAAM,MAAM;CACvB;CAEA,IAAI,KAAK,SACP,OACE,oBAAC,WAAD;EACE,MAAK;EACL,GAAK;EACL,QAAQ,EAAE,cAAc;GACtB;GACA;IACE,iBAAiB,UAAU,MAAM,OAAO,YAAY,MAAM,OAAO;IACjE,aAAa,UAAU,MAAM,OAAO,UAAU,MAAM,OAAO;IAC3D,WAAW,MAAM,OAAO,UAAU,KAAK,cAAc,OAAO;GAC9D;GACA;EACF;EAEC;CACQ,CAAA;CAIf,OACE,oBAAC,MAAD;EAAM,GAAK;EAAoB,OAAO;GAAC;GAAM,EAAE,WAAW,MAAM,OAAO,OAAO,EAAE;GAAG;EAAK;EACrF;CACG,CAAA;AAEV"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { ResolvedMode, ResolvedTheme, ShadowKey, Theme } from '@eventuras/ratio-ui-core';
|
|
3
|
+
export type ColorScheme = 'light' | 'dark';
|
|
4
|
+
/** The theme as a component reads it: one mode's colours, and the rest of the theme. @beta */
|
|
5
|
+
export interface RatioTheme extends Omit<ResolvedTheme, 'light' | 'dark'> {
|
|
6
|
+
scheme: ColorScheme;
|
|
7
|
+
/** The colours of the mode in use. */
|
|
8
|
+
colors: ResolvedMode;
|
|
9
|
+
/**
|
|
10
|
+
* A shadow of the mode in use, as a `boxShadow` value (React Native 0.76
|
|
11
|
+
* and up). `undefined` for `null`, so it can go straight into a style.
|
|
12
|
+
*/
|
|
13
|
+
shadow: (key: ShadowKey | null) => string | undefined;
|
|
14
|
+
}
|
|
15
|
+
/** @beta Prop shape may change before release. */
|
|
16
|
+
export interface RatioProviderProps {
|
|
17
|
+
/** The theme, as `@eventuras/ratio-ui-core` authors it. @default bureau */
|
|
18
|
+
theme?: Theme;
|
|
19
|
+
/** Force light or dark. @default the device's setting */
|
|
20
|
+
colorScheme?: ColorScheme;
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Puts a theme in reach of every Ratio component below it, in the device's
|
|
25
|
+
* light or dark mode unless `colorScheme` says otherwise.
|
|
26
|
+
*
|
|
27
|
+
* @beta This component is experimental — prop shape may change before release.
|
|
28
|
+
*/
|
|
29
|
+
export declare const RatioProvider: React.FC<RatioProviderProps>;
|
|
30
|
+
/**
|
|
31
|
+
* The theme in use. Without a `RatioProvider` above, Bureau in the device's
|
|
32
|
+
* mode — so a component works on its own, and a provider is only needed to
|
|
33
|
+
* choose.
|
|
34
|
+
*
|
|
35
|
+
* @beta The shape of the theme it returns may change before release.
|
|
36
|
+
*/
|
|
37
|
+
export declare function useTheme(): RatioTheme;
|
|
38
|
+
//# sourceMappingURL=RatioProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RatioProvider.d.ts","sourceRoot":"","sources":["../src/RatioProvider.tsx"],"names":[],"mappings":"AAIA,OAAO,KAA6C,MAAM,OAAO,CAAC;AAElE,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,KAAK,EACX,MAAM,0BAA0B,CAAC;AAGlC,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAE3C,8FAA8F;AAC9F,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,aAAa,EAAE,OAAO,GAAG,MAAM,CAAC;IACvE,MAAM,EAAE,WAAW,CAAC;IACpB,sCAAsC;IACtC,MAAM,EAAE,YAAY,CAAC;IACrB;;;OAGG;IACH,MAAM,EAAE,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG,SAAS,CAAC;CACvD;AAsBD,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,yDAAyD;IACzD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAMtD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,QAAQ,IAAI,UAAU,CAQrC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createContext, useContext, useMemo } from "react";
|
|
2
|
+
import { useColorScheme } from "react-native";
|
|
3
|
+
import { resolveTheme } from "@eventuras/ratio-ui-core";
|
|
4
|
+
import { bureau } from "@eventuras/ratio-ui-core/themes/bureau";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
//#region src/RatioProvider.tsx
|
|
7
|
+
var toRatioTheme = (resolved, scheme) => {
|
|
8
|
+
const { light, dark, ...rest } = resolved;
|
|
9
|
+
const colors = scheme === "dark" ? dark : light;
|
|
10
|
+
return {
|
|
11
|
+
...rest,
|
|
12
|
+
scheme,
|
|
13
|
+
colors,
|
|
14
|
+
shadow: (key) => {
|
|
15
|
+
if (!key) return void 0;
|
|
16
|
+
const { x, y, blur, color } = colors[key];
|
|
17
|
+
return `${x}px ${y}px ${blur}px ${color}`;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
var RatioContext = createContext(null);
|
|
22
|
+
var defaultResolved = resolveTheme(bureau);
|
|
23
|
+
/**
|
|
24
|
+
* Puts a theme in reach of every Ratio component below it, in the device's
|
|
25
|
+
* light or dark mode unless `colorScheme` says otherwise.
|
|
26
|
+
*
|
|
27
|
+
* @beta This component is experimental — prop shape may change before release.
|
|
28
|
+
*/
|
|
29
|
+
var RatioProvider = ({ theme, colorScheme, children }) => {
|
|
30
|
+
const system = useColorScheme();
|
|
31
|
+
const scheme = colorScheme ?? (system === "dark" ? "dark" : "light");
|
|
32
|
+
const resolved = useMemo(() => theme ? resolveTheme(theme) : defaultResolved, [theme]);
|
|
33
|
+
const value = useMemo(() => toRatioTheme(resolved, scheme), [resolved, scheme]);
|
|
34
|
+
return /* @__PURE__ */ jsx(RatioContext.Provider, {
|
|
35
|
+
value,
|
|
36
|
+
children
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* The theme in use. Without a `RatioProvider` above, Bureau in the device's
|
|
41
|
+
* mode — so a component works on its own, and a provider is only needed to
|
|
42
|
+
* choose.
|
|
43
|
+
*
|
|
44
|
+
* @beta The shape of the theme it returns may change before release.
|
|
45
|
+
*/
|
|
46
|
+
function useTheme() {
|
|
47
|
+
const fromProvider = useContext(RatioContext);
|
|
48
|
+
const system = useColorScheme();
|
|
49
|
+
const fallback = useMemo(() => toRatioTheme(defaultResolved, system === "dark" ? "dark" : "light"), [system]);
|
|
50
|
+
return fromProvider ?? fallback;
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { RatioProvider, useTheme };
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=RatioProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RatioProvider.js","names":[],"sources":["../src/RatioProvider.tsx"],"sourcesContent":["// ratio-ui · design system for knowledge sharing\n// SPDX-FileCopyrightText: 2026 Losol AS\n// SPDX-License-Identifier: MPL-2.0\n\nimport React, { createContext, useContext, useMemo } from 'react';\nimport { useColorScheme } from 'react-native';\nimport {\n resolveTheme,\n type ResolvedMode,\n type ResolvedTheme,\n type ShadowKey,\n type Theme,\n} from '@eventuras/ratio-ui-core';\nimport { bureau } from '@eventuras/ratio-ui-core/themes/bureau';\n\nexport type ColorScheme = 'light' | 'dark';\n\n/** The theme as a component reads it: one mode's colours, and the rest of the theme. @beta */\nexport interface RatioTheme extends Omit<ResolvedTheme, 'light' | 'dark'> {\n scheme: ColorScheme;\n /** The colours of the mode in use. */\n colors: ResolvedMode;\n /**\n * A shadow of the mode in use, as a `boxShadow` value (React Native 0.76\n * and up). `undefined` for `null`, so it can go straight into a style.\n */\n shadow: (key: ShadowKey | null) => string | undefined;\n}\n\nconst toRatioTheme = (resolved: ResolvedTheme, scheme: ColorScheme): RatioTheme => {\n const { light, dark, ...rest } = resolved;\n const colors = scheme === 'dark' ? dark : light;\n return {\n ...rest,\n scheme,\n colors,\n shadow: key => {\n if (!key) return undefined;\n const { x, y, blur, color } = colors[key];\n return `${x}px ${y}px ${blur}px ${color}`;\n },\n };\n};\n\nconst RatioContext = createContext<RatioTheme | null>(null);\n\n// Bureau is the default theme, resolved once for every app that sets none.\nconst defaultResolved = resolveTheme(bureau);\n\n/** @beta Prop shape may change before release. */\nexport interface RatioProviderProps {\n /** The theme, as `@eventuras/ratio-ui-core` authors it. @default bureau */\n theme?: Theme;\n /** Force light or dark. @default the device's setting */\n colorScheme?: ColorScheme;\n children?: React.ReactNode;\n}\n\n/**\n * Puts a theme in reach of every Ratio component below it, in the device's\n * light or dark mode unless `colorScheme` says otherwise.\n *\n * @beta This component is experimental — prop shape may change before release.\n */\nexport const RatioProvider: React.FC<RatioProviderProps> = ({ theme, colorScheme, children }) => {\n const system = useColorScheme();\n const scheme: ColorScheme = colorScheme ?? (system === 'dark' ? 'dark' : 'light');\n const resolved = useMemo(() => (theme ? resolveTheme(theme) : defaultResolved), [theme]);\n const value = useMemo(() => toRatioTheme(resolved, scheme), [resolved, scheme]);\n return <RatioContext.Provider value={value}>{children}</RatioContext.Provider>;\n};\n\n/**\n * The theme in use. Without a `RatioProvider` above, Bureau in the device's\n * mode — so a component works on its own, and a provider is only needed to\n * choose.\n *\n * @beta The shape of the theme it returns may change before release.\n */\nexport function useTheme(): RatioTheme {\n const fromProvider = useContext(RatioContext);\n const system = useColorScheme();\n const fallback = useMemo(\n () => toRatioTheme(defaultResolved, system === 'dark' ? 'dark' : 'light'),\n [system],\n );\n return fromProvider ?? fallback;\n}\n"],"mappings":";;;;;;AA6BA,IAAM,gBAAgB,UAAyB,WAAoC;CACjF,MAAM,EAAE,OAAO,MAAM,GAAG,SAAS;CACjC,MAAM,SAAS,WAAW,SAAS,OAAO;CAC1C,OAAO;EACL,GAAG;EACH;EACA;EACA,SAAQ,QAAO;GACb,IAAI,CAAC,KAAK,OAAO,KAAA;GACjB,MAAM,EAAE,GAAG,GAAG,MAAM,UAAU,OAAO;GACrC,OAAO,GAAG,EAAE,KAAK,EAAE,KAAK,KAAK,KAAK;EACpC;CACF;AACF;AAEA,IAAM,eAAe,cAAiC,IAAI;AAG1D,IAAM,kBAAkB,aAAa,MAAM;;;;;;;AAiB3C,IAAa,iBAA+C,EAAE,OAAO,aAAa,eAAe;CAC/F,MAAM,SAAS,eAAe;CAC9B,MAAM,SAAsB,gBAAgB,WAAW,SAAS,SAAS;CACzE,MAAM,WAAW,cAAe,QAAQ,aAAa,KAAK,IAAI,iBAAkB,CAAC,KAAK,CAAC;CACvF,MAAM,QAAQ,cAAc,aAAa,UAAU,MAAM,GAAG,CAAC,UAAU,MAAM,CAAC;CAC9E,OAAO,oBAAC,aAAa,UAAd;EAA8B;EAAQ;CAAgC,CAAA;AAC/E;;;;;;;;AASA,SAAgB,WAAuB;CACrC,MAAM,eAAe,WAAW,YAAY;CAC5C,MAAM,SAAS,eAAe;CAC9B,MAAM,WAAW,cACT,aAAa,iBAAiB,WAAW,SAAS,SAAS,OAAO,GACxE,CAAC,MAAM,CACT;CACA,OAAO,gBAAgB;AACzB"}
|
package/dist/Text.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { TextProps as RNTextProps } from 'react-native';
|
|
3
|
+
import { FontSizeStep } from '@eventuras/ratio-ui-core';
|
|
4
|
+
/** How loud the text is: the theme's text, muted or subtle colour. */
|
|
5
|
+
export type TextTone = 'default' | 'muted' | 'subtle';
|
|
6
|
+
/** @beta Prop shape may change before release. */
|
|
7
|
+
export interface TextProps extends RNTextProps {
|
|
8
|
+
/** A step of the type scale. @default 'base' */
|
|
9
|
+
size?: FontSizeStep;
|
|
10
|
+
/** @default 'default' */
|
|
11
|
+
tone?: TextTone;
|
|
12
|
+
/** @default 'regular' */
|
|
13
|
+
weight?: 'regular' | 'medium' | 'semibold' | 'bold';
|
|
14
|
+
/** The theme's font for the role. @default 'body' */
|
|
15
|
+
family?: 'body' | 'display' | 'mono';
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Body text in the theme's font, size and colour.
|
|
19
|
+
*
|
|
20
|
+
* @beta This component is experimental — prop shape may change before release.
|
|
21
|
+
*/
|
|
22
|
+
export declare const Text: React.FC<TextProps>;
|
|
23
|
+
export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
24
|
+
/** @beta Prop shape may change before release. */
|
|
25
|
+
export interface HeadingProps extends Omit<TextProps, 'family' | 'size'> {
|
|
26
|
+
/** The heading's level, for screen readers and the default size. @default 2 */
|
|
27
|
+
level?: HeadingLevel;
|
|
28
|
+
/** Overrides the level's size. */
|
|
29
|
+
size?: FontSizeStep;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A heading in the theme's display font, announced as one with its level.
|
|
33
|
+
*
|
|
34
|
+
* @beta This component is experimental — prop shape may change before release.
|
|
35
|
+
*/
|
|
36
|
+
export declare const Heading: React.FC<HeadingProps>;
|
|
37
|
+
//# sourceMappingURL=Text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Text.d.ts","sourceRoot":"","sources":["../src/Text.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAkB,KAAK,SAAS,IAAI,WAAW,EAAkB,MAAM,cAAc,CAAC;AAC7F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,sEAAsE;AACtE,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEtD,kDAAkD;AAClD,MAAM,WAAW,SAAU,SAAQ,WAAW;IAC5C,gDAAgD;IAChD,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,yBAAyB;IACzB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,yBAAyB;IACzB,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;IACpD,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;CACtC;AAWD;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAyBpC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEjD,kDAAkD;AAClD,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,SAAS,EAAE,QAAQ,GAAG,MAAM,CAAC;IACtE,+EAA+E;IAC/E,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,kCAAkC;IAClC,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAYD;;;;GAIG;AACH,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAa1C,CAAC"}
|
package/dist/Text.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { useTheme } from "./RatioProvider.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import { Text } from "react-native";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/Text.tsx
|
|
6
|
+
var WEIGHT = {
|
|
7
|
+
regular: "400",
|
|
8
|
+
medium: "500",
|
|
9
|
+
semibold: "600",
|
|
10
|
+
bold: "700"
|
|
11
|
+
};
|
|
12
|
+
var TONE = {
|
|
13
|
+
default: "text",
|
|
14
|
+
muted: "textMuted",
|
|
15
|
+
subtle: "textSubtle"
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Body text in the theme's font, size and colour.
|
|
19
|
+
*
|
|
20
|
+
* @beta This component is experimental — prop shape may change before release.
|
|
21
|
+
*/
|
|
22
|
+
var Text$1 = ({ size = "base", tone = "default", weight = "regular", family = "body", style, ...rest }) => {
|
|
23
|
+
const theme = useTheme();
|
|
24
|
+
const fontSize = theme.fontSize[size];
|
|
25
|
+
return /* @__PURE__ */ jsx(Text, {
|
|
26
|
+
...rest,
|
|
27
|
+
style: [{
|
|
28
|
+
fontFamily: theme.font[family],
|
|
29
|
+
fontSize,
|
|
30
|
+
lineHeight: Math.round(fontSize * 1.5),
|
|
31
|
+
fontWeight: WEIGHT[weight],
|
|
32
|
+
color: theme.colors[TONE[tone]]
|
|
33
|
+
}, style]
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
var HEADING_SIZE = {
|
|
37
|
+
1: "4xl",
|
|
38
|
+
2: "3xl",
|
|
39
|
+
3: "2xl",
|
|
40
|
+
4: "xl",
|
|
41
|
+
5: "lg",
|
|
42
|
+
6: "base"
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* A heading in the theme's display font, announced as one with its level.
|
|
46
|
+
*
|
|
47
|
+
* @beta This component is experimental — prop shape may change before release.
|
|
48
|
+
*/
|
|
49
|
+
var Heading = ({ level = 2, size, weight = "bold", style, ...rest }) => {
|
|
50
|
+
const fontSize = useTheme().fontSize[size ?? HEADING_SIZE[level]];
|
|
51
|
+
return /* @__PURE__ */ jsx(Text$1, {
|
|
52
|
+
role: "heading",
|
|
53
|
+
"aria-level": level,
|
|
54
|
+
family: "display",
|
|
55
|
+
weight,
|
|
56
|
+
...rest,
|
|
57
|
+
style: [{
|
|
58
|
+
fontSize,
|
|
59
|
+
lineHeight: Math.round(fontSize * 1.2)
|
|
60
|
+
}, style]
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
//#endregion
|
|
64
|
+
export { Heading, Text$1 as Text };
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=Text.js.map
|
package/dist/Text.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Text.js","names":[],"sources":["../src/Text.tsx"],"sourcesContent":["// ratio-ui · design system for knowledge sharing\n// SPDX-FileCopyrightText: 2026 Losol AS\n// SPDX-License-Identifier: MPL-2.0\n\nimport React from 'react';\nimport { Text as RNText, type TextProps as RNTextProps, type TextStyle } from 'react-native';\nimport type { FontSizeStep } from '@eventuras/ratio-ui-core';\nimport { useTheme } from './RatioProvider';\n\n/** How loud the text is: the theme's text, muted or subtle colour. */\nexport type TextTone = 'default' | 'muted' | 'subtle';\n\n/** @beta Prop shape may change before release. */\nexport interface TextProps extends RNTextProps {\n /** A step of the type scale. @default 'base' */\n size?: FontSizeStep;\n /** @default 'default' */\n tone?: TextTone;\n /** @default 'regular' */\n weight?: 'regular' | 'medium' | 'semibold' | 'bold';\n /** The theme's font for the role. @default 'body' */\n family?: 'body' | 'display' | 'mono';\n}\n\nconst WEIGHT: Record<NonNullable<TextProps['weight']>, TextStyle['fontWeight']> = {\n regular: '400',\n medium: '500',\n semibold: '600',\n bold: '700',\n};\n\nconst TONE = { default: 'text', muted: 'textMuted', subtle: 'textSubtle' } as const;\n\n/**\n * Body text in the theme's font, size and colour.\n *\n * @beta This component is experimental — prop shape may change before release.\n */\nexport const Text: React.FC<TextProps> = ({\n size = 'base',\n tone = 'default',\n weight = 'regular',\n family = 'body',\n style,\n ...rest\n}) => {\n const theme = useTheme();\n const fontSize = theme.fontSize[size];\n return (\n <RNText\n {...rest}\n style={[\n {\n fontFamily: theme.font[family],\n fontSize,\n lineHeight: Math.round(fontSize * 1.5),\n fontWeight: WEIGHT[weight],\n color: theme.colors[TONE[tone]],\n },\n style,\n ]}\n />\n );\n};\n\nexport type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;\n\n/** @beta Prop shape may change before release. */\nexport interface HeadingProps extends Omit<TextProps, 'family' | 'size'> {\n /** The heading's level, for screen readers and the default size. @default 2 */\n level?: HeadingLevel;\n /** Overrides the level's size. */\n size?: FontSizeStep;\n}\n\n// The web's Heading scale, one step per level.\nconst HEADING_SIZE: Record<HeadingLevel, FontSizeStep> = {\n 1: '4xl',\n 2: '3xl',\n 3: '2xl',\n 4: 'xl',\n 5: 'lg',\n 6: 'base',\n};\n\n/**\n * A heading in the theme's display font, announced as one with its level.\n *\n * @beta This component is experimental — prop shape may change before release.\n */\nexport const Heading: React.FC<HeadingProps> = ({ level = 2, size, weight = 'bold', style, ...rest }) => {\n const theme = useTheme();\n const fontSize = theme.fontSize[size ?? HEADING_SIZE[level]];\n return (\n <Text\n role=\"heading\"\n aria-level={level}\n family=\"display\"\n weight={weight}\n {...rest}\n style={[{ fontSize, lineHeight: Math.round(fontSize * 1.2) }, style]}\n />\n );\n};\n"],"mappings":";;;;;AAwBA,IAAM,SAA4E;CAChF,SAAS;CACT,QAAQ;CACR,UAAU;CACV,MAAM;AACR;AAEA,IAAM,OAAO;CAAE,SAAS;CAAQ,OAAO;CAAa,QAAQ;AAAa;;;;;;AAOzE,IAAa,UAA6B,EACxC,OAAO,QACP,OAAO,WACP,SAAS,WACT,SAAS,QACT,OACA,GAAG,WACC;CACJ,MAAM,QAAQ,SAAS;CACvB,MAAM,WAAW,MAAM,SAAS;CAChC,OACE,oBAAC,MAAD;EACE,GAAI;EACJ,OAAO,CACL;GACE,YAAY,MAAM,KAAK;GACvB;GACA,YAAY,KAAK,MAAM,WAAW,GAAG;GACrC,YAAY,OAAO;GACnB,OAAO,MAAM,OAAO,KAAK;EAC3B,GACA,KACF;CACD,CAAA;AAEL;AAaA,IAAM,eAAmD;CACvD,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;AACL;;;;;;AAOA,IAAa,WAAmC,EAAE,QAAQ,GAAG,MAAM,SAAS,QAAQ,OAAO,GAAG,WAAW;CAEvG,MAAM,WADQ,SACG,CAAA,CAAM,SAAS,QAAQ,aAAa;CACrD,OACE,oBAAC,QAAD;EACE,MAAK;EACL,cAAY;EACZ,QAAO;EACC;EACR,GAAI;EACJ,OAAO,CAAC;GAAE;GAAU,YAAY,KAAK,MAAM,WAAW,GAAG;EAAE,GAAG,KAAK;CACpE,CAAA;AAEL"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { ChatLinkPreview } from '@eventuras/ratio-ui-core/chat';
|
|
3
|
+
interface ChatLinkPreviewCardProps {
|
|
4
|
+
preview: ChatLinkPreview;
|
|
5
|
+
onOpenLink: (url: string) => void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The card under a message: site name, title, description and a square
|
|
9
|
+
* thumbnail. One pressable target, named by the title.
|
|
10
|
+
*/
|
|
11
|
+
export declare const ChatLinkPreviewCard: React.FC<ChatLinkPreviewCardProps>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=ChatLinkPreviewCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatLinkPreviewCard.d.ts","sourceRoot":"","sources":["../../src/chat/ChatLinkPreviewCard.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAInF,UAAU,wBAAwB;IAChC,OAAO,EAAE,eAAe,CAAC;IACzB,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAMD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAwDlE,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { useTheme } from "../RatioProvider.js";
|
|
2
|
+
import { Text as Text$1 } from "../Text.js";
|
|
3
|
+
import "react";
|
|
4
|
+
import { Image, Pressable, View } from "react-native";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { previewLabel } from "@eventuras/ratio-ui-core/chat";
|
|
7
|
+
//#region src/chat/ChatLinkPreviewCard.tsx
|
|
8
|
+
var THUMB = 64;
|
|
9
|
+
/**
|
|
10
|
+
* The card under a message: site name, title, description and a square
|
|
11
|
+
* thumbnail. One pressable target, named by the title.
|
|
12
|
+
*/
|
|
13
|
+
var ChatLinkPreviewCard = ({ preview, onOpenLink }) => {
|
|
14
|
+
const theme = useTheme();
|
|
15
|
+
const { colors } = theme;
|
|
16
|
+
const { url, title, description, image } = preview;
|
|
17
|
+
return /* @__PURE__ */ jsxs(Pressable, {
|
|
18
|
+
role: "link",
|
|
19
|
+
"aria-label": title ?? description,
|
|
20
|
+
onPress: () => onOpenLink(url),
|
|
21
|
+
style: ({ pressed }) => ({
|
|
22
|
+
flexDirection: "row",
|
|
23
|
+
gap: 12,
|
|
24
|
+
padding: 10,
|
|
25
|
+
borderWidth: 1,
|
|
26
|
+
borderColor: pressed ? colors.border2 : colors.border1,
|
|
27
|
+
borderRadius: theme.radius.md,
|
|
28
|
+
backgroundColor: pressed ? colors.cardHover : colors.card
|
|
29
|
+
}),
|
|
30
|
+
children: [image && /* @__PURE__ */ jsx(Image, {
|
|
31
|
+
source: { uri: image.src },
|
|
32
|
+
accessibilityIgnoresInvertColors: true,
|
|
33
|
+
style: {
|
|
34
|
+
width: THUMB,
|
|
35
|
+
height: THUMB,
|
|
36
|
+
borderRadius: theme.radius.sm,
|
|
37
|
+
backgroundColor: colors.cardHover
|
|
38
|
+
},
|
|
39
|
+
resizeMode: "cover"
|
|
40
|
+
}), /* @__PURE__ */ jsxs(View, {
|
|
41
|
+
style: {
|
|
42
|
+
flex: 1,
|
|
43
|
+
minWidth: 0,
|
|
44
|
+
gap: 2,
|
|
45
|
+
justifyContent: "center"
|
|
46
|
+
},
|
|
47
|
+
children: [
|
|
48
|
+
/* @__PURE__ */ jsx(Text$1, {
|
|
49
|
+
size: "xs",
|
|
50
|
+
tone: "subtle",
|
|
51
|
+
weight: "semibold",
|
|
52
|
+
numberOfLines: 1,
|
|
53
|
+
style: {
|
|
54
|
+
textTransform: "uppercase",
|
|
55
|
+
letterSpacing: .6
|
|
56
|
+
},
|
|
57
|
+
children: previewLabel(preview)
|
|
58
|
+
}),
|
|
59
|
+
title && /* @__PURE__ */ jsx(Text$1, {
|
|
60
|
+
weight: "semibold",
|
|
61
|
+
numberOfLines: 2,
|
|
62
|
+
style: { lineHeight: theme.fontSize.base * 1.3 },
|
|
63
|
+
children: title
|
|
64
|
+
}),
|
|
65
|
+
description && /* @__PURE__ */ jsx(Text$1, {
|
|
66
|
+
size: "sm",
|
|
67
|
+
tone: "muted",
|
|
68
|
+
numberOfLines: 2,
|
|
69
|
+
children: description
|
|
70
|
+
})
|
|
71
|
+
]
|
|
72
|
+
})]
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
//#endregion
|
|
76
|
+
export { ChatLinkPreviewCard };
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=ChatLinkPreviewCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatLinkPreviewCard.js","names":[],"sources":["../../src/chat/ChatLinkPreviewCard.tsx"],"sourcesContent":["// ratio-ui · design system for knowledge sharing\n// SPDX-FileCopyrightText: 2026 Losol AS\n// SPDX-License-Identifier: MPL-2.0\n\nimport React from 'react';\nimport { Image, Pressable, View } from 'react-native';\nimport { previewLabel, type ChatLinkPreview } from '@eventuras/ratio-ui-core/chat';\nimport { useTheme } from '../RatioProvider';\nimport { Text } from '../Text';\n\ninterface ChatLinkPreviewCardProps {\n preview: ChatLinkPreview;\n onOpenLink: (url: string) => void;\n}\n\n// Fixed, so a row is its final height before the image arrives and a late\n// load never moves the rows below it.\nconst THUMB = 64;\n\n/**\n * The card under a message: site name, title, description and a square\n * thumbnail. One pressable target, named by the title.\n */\nexport const ChatLinkPreviewCard: React.FC<ChatLinkPreviewCardProps> = ({ preview, onOpenLink }) => {\n const theme = useTheme();\n const { colors } = theme;\n const { url, title, description, image } = preview;\n\n return (\n <Pressable\n role=\"link\"\n aria-label={title ?? description}\n onPress={() => onOpenLink(url)}\n style={({ pressed }) => ({\n flexDirection: 'row',\n gap: 12,\n padding: 10,\n borderWidth: 1,\n borderColor: pressed ? colors.border2 : colors.border1,\n borderRadius: theme.radius.md,\n backgroundColor: pressed ? colors.cardHover : colors.card,\n })}\n >\n {image && (\n <Image\n source={{ uri: image.src }}\n accessibilityIgnoresInvertColors\n style={{\n width: THUMB,\n height: THUMB,\n borderRadius: theme.radius.sm,\n backgroundColor: colors.cardHover,\n }}\n resizeMode=\"cover\"\n />\n )}\n <View style={{ flex: 1, minWidth: 0, gap: 2, justifyContent: 'center' }}>\n <Text\n size=\"xs\"\n tone=\"subtle\"\n weight=\"semibold\"\n numberOfLines={1}\n style={{ textTransform: 'uppercase', letterSpacing: 0.6 }}\n >\n {previewLabel(preview)}\n </Text>\n {title && (\n <Text weight=\"semibold\" numberOfLines={2} style={{ lineHeight: theme.fontSize.base * 1.3 }}>\n {title}\n </Text>\n )}\n {description && (\n <Text size=\"sm\" tone=\"muted\" numberOfLines={2}>\n {description}\n </Text>\n )}\n </View>\n </Pressable>\n );\n};\n"],"mappings":";;;;;;;AAiBA,IAAM,QAAQ;;;;;AAMd,IAAa,uBAA2D,EAAE,SAAS,iBAAiB;CAClG,MAAM,QAAQ,SAAS;CACvB,MAAM,EAAE,WAAW;CACnB,MAAM,EAAE,KAAK,OAAO,aAAa,UAAU;CAE3C,OACE,qBAAC,WAAD;EACE,MAAK;EACL,cAAY,SAAS;EACrB,eAAe,WAAW,GAAG;EAC7B,QAAQ,EAAE,eAAe;GACvB,eAAe;GACf,KAAK;GACL,SAAS;GACT,aAAa;GACb,aAAa,UAAU,OAAO,UAAU,OAAO;GAC/C,cAAc,MAAM,OAAO;GAC3B,iBAAiB,UAAU,OAAO,YAAY,OAAO;EACvD;EAZF,UAAA,CAcG,SACC,oBAAC,OAAD;GACE,QAAQ,EAAE,KAAK,MAAM,IAAI;GACzB,kCAAA;GACA,OAAO;IACL,OAAO;IACP,QAAQ;IACR,cAAc,MAAM,OAAO;IAC3B,iBAAiB,OAAO;GAC1B;GACA,YAAW;EACZ,CAAA,GAEH,qBAAC,MAAD;GAAM,OAAO;IAAE,MAAM;IAAG,UAAU;IAAG,KAAK;IAAG,gBAAgB;GAAS;GAAtE,UAAA;IACE,oBAAC,QAAD;KACE,MAAK;KACL,MAAK;KACL,QAAO;KACP,eAAe;KACf,OAAO;MAAE,eAAe;MAAa,eAAe;KAAI;KAEvD,UAAA,aAAa,OAAO;IACjB,CAAA;IACL,SACC,oBAAC,QAAD;KAAM,QAAO;KAAW,eAAe;KAAG,OAAO,EAAE,YAAY,MAAM,SAAS,OAAO,IAAI;KACtF,UAAA;IACG,CAAA;IAEP,eACC,oBAAC,QAAD;KAAM,MAAK;KAAK,MAAK;KAAQ,eAAe;KACzC,UAAA;IACG,CAAA;GAEJ;EACG,CAAA,CAAA;;AAEf"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { FlatList, FlatListProps } from 'react-native';
|
|
3
|
+
import { ChatLogMessage } from '@eventuras/ratio-ui-core/chat';
|
|
4
|
+
/** Built-in text of `ChatLog`. Each entry falls back to English. @beta */
|
|
5
|
+
export interface ChatLogLabels {
|
|
6
|
+
/** Name of each message's reaction row. @default 'Reactions' */
|
|
7
|
+
reactions?: string;
|
|
8
|
+
/** Read after the author and time of a message that mentions you. @default 'mentions you' */
|
|
9
|
+
mentionsYou?: string;
|
|
10
|
+
/** Spoken name of the `@` role. @default 'op' */
|
|
11
|
+
op?: string;
|
|
12
|
+
/** Spoken name of the `+` role. @default 'voice' */
|
|
13
|
+
voice?: string;
|
|
14
|
+
}
|
|
15
|
+
/** @beta Prop shape may change before release. */
|
|
16
|
+
export interface ChatLogProps extends Omit<FlatListProps<ChatLogMessage>, 'data' | 'renderItem' | 'keyExtractor'> {
|
|
17
|
+
/** Oldest first, as the web's `Chat.Log` takes them. */
|
|
18
|
+
messages: ChatLogMessage[];
|
|
19
|
+
/** Your own nick: tinted in the log, and messages that mention it get the band. */
|
|
20
|
+
me?: string;
|
|
21
|
+
/** Called with the message and the emoji when you tap a reaction. Without it reactions are read-only. */
|
|
22
|
+
onToggleReaction?: (messageId: string, emoji: string) => void;
|
|
23
|
+
/** Opens a link or a preview the reader taps. @default Linking.openURL */
|
|
24
|
+
onOpenLink?: (url: string) => void;
|
|
25
|
+
/** Built-in text. Each entry falls back to English. */
|
|
26
|
+
labels?: ChatLogLabels;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* ChatLog — the channel log for React Native: one message per row, the nick
|
|
30
|
+
* and time on a line above the text, as the web's `Chat.Log` lays out a
|
|
31
|
+
* narrow log. Links and mentions are read by `@eventuras/ratio-ui-core/chat`,
|
|
32
|
+
* so the app and the web agree on them. Joins and topic changes are `event`
|
|
33
|
+
* rows, `/me` is an `action`, and a `divider` marks a day or "new messages".
|
|
34
|
+
*
|
|
35
|
+
* A `FlatList` underneath, and like the web's log it does not scroll
|
|
36
|
+
* itself: the ref is the list, so the caller decides when to follow new
|
|
37
|
+
* messages. Other `FlatList` props pass through.
|
|
38
|
+
*
|
|
39
|
+
* @beta This component is experimental — prop shape may change before release.
|
|
40
|
+
*/
|
|
41
|
+
export declare const ChatLog: React.ForwardRefExoticComponent<ChatLogProps & React.RefAttributes<FlatList<ChatLogMessage>>>;
|
|
42
|
+
//# sourceMappingURL=ChatLog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatLog.d.ts","sourceRoot":"","sources":["../../src/chat/ChatLog.tsx"],"names":[],"mappings":"AAIA,OAAO,KAA+B,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAiB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAKL,KAAK,cAAc,EAEpB,MAAM,+BAA+B,CAAC;AAOvC,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,kDAAkD;AAClD,MAAM,WAAW,YACf,SAAQ,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,cAAc,CAAC;IACnF,wDAAwD;IACxD,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,mFAAmF;IACnF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yGAAyG;IACzG,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D,0EAA0E;IAC1E,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,uDAAuD;IACvD,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAQD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,OAAO,+FAwClB,CAAC"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { useTheme } from "../RatioProvider.js";
|
|
2
|
+
import { Text as Text$1 } from "../Text.js";
|
|
3
|
+
import { ChatLinkPreviewCard } from "./ChatLinkPreviewCard.js";
|
|
4
|
+
import { ChatReactions } from "./ChatReactions.js";
|
|
5
|
+
import { ChatText } from "./ChatText.js";
|
|
6
|
+
import React, { useCallback, useMemo } from "react";
|
|
7
|
+
import { FlatList, Linking, View } from "react-native";
|
|
8
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { hasPreviewContent, mentionsNick, sameNick, segmentChatText } from "@eventuras/ratio-ui-core/chat";
|
|
10
|
+
//#region src/chat/ChatLog.tsx
|
|
11
|
+
var ROLE_GLYPH = {
|
|
12
|
+
op: "@",
|
|
13
|
+
voice: "+"
|
|
14
|
+
};
|
|
15
|
+
var openUrl = (url) => {
|
|
16
|
+
Linking.openURL(url);
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* ChatLog — the channel log for React Native: one message per row, the nick
|
|
20
|
+
* and time on a line above the text, as the web's `Chat.Log` lays out a
|
|
21
|
+
* narrow log. Links and mentions are read by `@eventuras/ratio-ui-core/chat`,
|
|
22
|
+
* so the app and the web agree on them. Joins and topic changes are `event`
|
|
23
|
+
* rows, `/me` is an `action`, and a `divider` marks a day or "new messages".
|
|
24
|
+
*
|
|
25
|
+
* A `FlatList` underneath, and like the web's log it does not scroll
|
|
26
|
+
* itself: the ref is the list, so the caller decides when to follow new
|
|
27
|
+
* messages. Other `FlatList` props pass through.
|
|
28
|
+
*
|
|
29
|
+
* @beta This component is experimental — prop shape may change before release.
|
|
30
|
+
*/
|
|
31
|
+
var ChatLog = React.forwardRef(function ChatLog({ messages, me, onToggleReaction, onOpenLink = openUrl, labels, contentContainerStyle, ...listProps }, ref) {
|
|
32
|
+
const theme = useTheme();
|
|
33
|
+
const { reactions, mentionsYou, op, voice } = labels ?? {};
|
|
34
|
+
const rowLabels = useMemo(() => ({
|
|
35
|
+
reactions: reactions ?? "Reactions",
|
|
36
|
+
mentionsYou: mentionsYou ?? "mentions you",
|
|
37
|
+
op: op ?? "op",
|
|
38
|
+
voice: voice ?? "voice"
|
|
39
|
+
}), [
|
|
40
|
+
reactions,
|
|
41
|
+
mentionsYou,
|
|
42
|
+
op,
|
|
43
|
+
voice
|
|
44
|
+
]);
|
|
45
|
+
const renderItem = useCallback(({ item }) => /* @__PURE__ */ jsx(ChatLogRow, {
|
|
46
|
+
message: item,
|
|
47
|
+
me,
|
|
48
|
+
onToggleReaction,
|
|
49
|
+
onOpenLink,
|
|
50
|
+
labels: rowLabels
|
|
51
|
+
}), [
|
|
52
|
+
me,
|
|
53
|
+
onToggleReaction,
|
|
54
|
+
onOpenLink,
|
|
55
|
+
rowLabels
|
|
56
|
+
]);
|
|
57
|
+
return /* @__PURE__ */ jsx(FlatList, {
|
|
58
|
+
ref,
|
|
59
|
+
data: messages,
|
|
60
|
+
keyExtractor: (message) => message.id,
|
|
61
|
+
renderItem,
|
|
62
|
+
contentContainerStyle: [{
|
|
63
|
+
paddingVertical: theme.space.xs,
|
|
64
|
+
gap: 2
|
|
65
|
+
}, contentContainerStyle],
|
|
66
|
+
style: { backgroundColor: theme.colors.surface },
|
|
67
|
+
...listProps
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
ChatLog.displayName = "ChatLog";
|
|
71
|
+
var PX = 16;
|
|
72
|
+
var ChatLogRow = ({ message, me, onToggleReaction, onOpenLink, labels }) => {
|
|
73
|
+
const theme = useTheme();
|
|
74
|
+
const { colors } = theme;
|
|
75
|
+
const { id, type = "msg", time, nick, role, text, preview, reactions } = message;
|
|
76
|
+
if (type === "divider") {
|
|
77
|
+
const rule = {
|
|
78
|
+
flex: 1,
|
|
79
|
+
height: 1,
|
|
80
|
+
backgroundColor: colors.border2,
|
|
81
|
+
opacity: .5
|
|
82
|
+
};
|
|
83
|
+
return /* @__PURE__ */ jsxs(View, {
|
|
84
|
+
style: {
|
|
85
|
+
flexDirection: "row",
|
|
86
|
+
alignItems: "center",
|
|
87
|
+
gap: 12,
|
|
88
|
+
paddingHorizontal: PX,
|
|
89
|
+
marginVertical: 8
|
|
90
|
+
},
|
|
91
|
+
children: [
|
|
92
|
+
/* @__PURE__ */ jsx(View, { style: rule }),
|
|
93
|
+
/* @__PURE__ */ jsx(Text$1, {
|
|
94
|
+
size: "xs",
|
|
95
|
+
tone: "subtle",
|
|
96
|
+
weight: "semibold",
|
|
97
|
+
style: {
|
|
98
|
+
textTransform: "uppercase",
|
|
99
|
+
letterSpacing: 1.2
|
|
100
|
+
},
|
|
101
|
+
children: text
|
|
102
|
+
}),
|
|
103
|
+
/* @__PURE__ */ jsx(View, { style: rule })
|
|
104
|
+
]
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (type === "event" || type === "action") return /* @__PURE__ */ jsxs(View, {
|
|
108
|
+
style: {
|
|
109
|
+
flexDirection: "row",
|
|
110
|
+
gap: 8,
|
|
111
|
+
paddingHorizontal: PX,
|
|
112
|
+
paddingVertical: 2
|
|
113
|
+
},
|
|
114
|
+
children: [/* @__PURE__ */ jsx(Text$1, {
|
|
115
|
+
size: "xs",
|
|
116
|
+
family: "mono",
|
|
117
|
+
tone: "subtle",
|
|
118
|
+
style: { lineHeight: theme.fontSize.sm * 1.5 },
|
|
119
|
+
children: time
|
|
120
|
+
}), /* @__PURE__ */ jsx(Text$1, {
|
|
121
|
+
size: "sm",
|
|
122
|
+
tone: type === "event" ? "subtle" : "muted",
|
|
123
|
+
style: {
|
|
124
|
+
flex: 1,
|
|
125
|
+
fontStyle: "italic"
|
|
126
|
+
},
|
|
127
|
+
children: type === "event" ? `— ${text}` : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
128
|
+
["*", nick].filter(Boolean).join(" "),
|
|
129
|
+
" ",
|
|
130
|
+
/* @__PURE__ */ jsx(ChatText, {
|
|
131
|
+
segments: segmentChatText(text, { mentions: false }),
|
|
132
|
+
onOpenLink
|
|
133
|
+
})
|
|
134
|
+
] })
|
|
135
|
+
})]
|
|
136
|
+
});
|
|
137
|
+
const segments = segmentChatText(text);
|
|
138
|
+
const mentionsMe = mentionsNick(segments, me);
|
|
139
|
+
const nickColor = sameNick(nick, me) ? colors.chatNickVoice : role === "op" ? colors.chatNickOp : role === "voice" ? colors.chatNickVoice : colors.chatNick;
|
|
140
|
+
const spoken = [
|
|
141
|
+
role ? `${nick} (${labels[role]})` : nick,
|
|
142
|
+
time,
|
|
143
|
+
mentionsMe ? labels.mentionsYou : void 0
|
|
144
|
+
].filter(Boolean).join(", ");
|
|
145
|
+
return /* @__PURE__ */ jsxs(View, {
|
|
146
|
+
style: {
|
|
147
|
+
gap: 4,
|
|
148
|
+
paddingVertical: 6,
|
|
149
|
+
paddingRight: PX,
|
|
150
|
+
paddingLeft: 13,
|
|
151
|
+
borderLeftWidth: 3,
|
|
152
|
+
borderLeftColor: mentionsMe ? colors.accent : "transparent",
|
|
153
|
+
backgroundColor: mentionsMe ? colors.chatMentionBg : "transparent"
|
|
154
|
+
},
|
|
155
|
+
children: [
|
|
156
|
+
/* @__PURE__ */ jsxs(View, {
|
|
157
|
+
accessible: true,
|
|
158
|
+
"aria-label": spoken,
|
|
159
|
+
style: {
|
|
160
|
+
flexDirection: "row",
|
|
161
|
+
alignItems: "baseline",
|
|
162
|
+
gap: 8
|
|
163
|
+
},
|
|
164
|
+
children: [/* @__PURE__ */ jsxs(Text$1, {
|
|
165
|
+
weight: "semibold",
|
|
166
|
+
numberOfLines: 1,
|
|
167
|
+
style: {
|
|
168
|
+
color: nickColor,
|
|
169
|
+
flexShrink: 1
|
|
170
|
+
},
|
|
171
|
+
children: [role ? ROLE_GLYPH[role] : "", nick]
|
|
172
|
+
}), /* @__PURE__ */ jsx(Text$1, {
|
|
173
|
+
size: "xs",
|
|
174
|
+
family: "mono",
|
|
175
|
+
tone: "subtle",
|
|
176
|
+
children: time
|
|
177
|
+
})]
|
|
178
|
+
}),
|
|
179
|
+
/* @__PURE__ */ jsx(Text$1, { children: /* @__PURE__ */ jsx(ChatText, {
|
|
180
|
+
segments,
|
|
181
|
+
onOpenLink
|
|
182
|
+
}) }),
|
|
183
|
+
preview && hasPreviewContent(preview) && /* @__PURE__ */ jsx(ChatLinkPreviewCard, {
|
|
184
|
+
preview,
|
|
185
|
+
onOpenLink
|
|
186
|
+
}),
|
|
187
|
+
reactions && reactions.length > 0 && /* @__PURE__ */ jsx(ChatReactions, {
|
|
188
|
+
reactions,
|
|
189
|
+
onToggle: onToggleReaction ? (emoji) => onToggleReaction(id, emoji) : void 0,
|
|
190
|
+
"aria-label": labels.reactions
|
|
191
|
+
})
|
|
192
|
+
]
|
|
193
|
+
});
|
|
194
|
+
};
|
|
195
|
+
//#endregion
|
|
196
|
+
export { ChatLog };
|
|
197
|
+
|
|
198
|
+
//# sourceMappingURL=ChatLog.js.map
|