machinalayout 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +295 -49
- package/dist/chunk-2ZQ2RFFI.js +400 -0
- package/dist/chunk-33CKBEJH.js +186 -0
- package/dist/chunk-BJOQRPPX.js +382 -0
- package/dist/chunk-KYWOCAHK.js +205 -0
- package/dist/chunk-RJYRJ3LD.js +0 -0
- package/dist/chunk-SVWYWI7I.js +59 -0
- package/dist/chunk-VREK57S3.js +13 -0
- package/dist/chunk-ZVDE7PX4.js +222 -0
- package/dist/debugOverlay-pJpj0n5H.d.ts +125 -0
- package/dist/deus/index.d.ts +14 -0
- package/dist/deus/index.js +26 -0
- package/dist/dispatch/index.d.ts +49 -0
- package/dist/dispatch/index.js +217 -0
- package/dist/handoff/index.d.ts +44 -0
- package/dist/handoff/index.js +83 -0
- package/dist/index.d.ts +54 -236
- package/dist/index.js +753 -583
- package/dist/inspect/index.d.ts +8 -0
- package/dist/inspect/index.js +97 -0
- package/dist/react/index.d.ts +41 -0
- package/dist/react/index.js +9 -0
- package/dist/react-native/index.d.ts +30 -0
- package/dist/react-native/index.js +84 -0
- package/dist/screenCatalog-ZjonGiOi.d.ts +46 -0
- package/dist/text/index.d.ts +10 -0
- package/dist/text/index.js +9 -0
- package/dist/text/react/index.d.ts +14 -0
- package/dist/text/react/index.js +7 -0
- package/dist/text/react-native/index.d.ts +16 -0
- package/dist/text/react-native/index.js +155 -0
- package/dist/text/vue/index.d.ts +113 -0
- package/dist/text/vue/index.js +202 -0
- package/dist/types-B90jb3RW.d.ts +184 -0
- package/dist/types-C4poVJpR.d.ts +74 -0
- package/dist/types-DLYAhNXw.d.ts +32 -0
- package/dist/vue/index.d.ts +173 -0
- package/dist/vue/index.js +112 -0
- package/docs/adapter-packaging-a0-plan.md +352 -0
- package/docs/adapters.md +19 -0
- package/docs/api-coherence-m8-audit.md +397 -0
- package/docs/deusmachina.md +108 -0
- package/docs/error-codes.md +95 -0
- package/docs/grid-arrange-m5a-contract.md +480 -0
- package/docs/grid-arrange.md +51 -0
- package/docs/inspection-and-handoff.md +126 -0
- package/docs/layout-interpolation.md +52 -0
- package/docs/machina-dispatch-d0-contract.md +496 -0
- package/docs/machina-dispatch.md +143 -0
- package/docs/named-layers.md +40 -0
- package/docs/react-adapter.md +63 -58
- package/docs/react-native-adapter.md +56 -0
- package/docs/react-native-text-renderer.md +50 -0
- package/docs/reference-alignment-m7a-contract.md +384 -0
- package/docs/reference-alignment.md +44 -0
- package/docs/responsive-variants.md +54 -0
- package/docs/screen-catalog-and-viewports.md +124 -0
- package/docs/stack-geometry-helpers.md +115 -0
- package/docs/vue-adapter.md +55 -0
- package/docs/vue-text-renderer.md +55 -0
- package/package.json +127 -60
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { S as SummarizeMachinaDomOptions, M as MachinaDomSummary } from '../types-DLYAhNXw.js';
|
|
2
|
+
export { a as MachinaDomSummaryNode } from '../types-DLYAhNXw.js';
|
|
3
|
+
import '../types-B90jb3RW.js';
|
|
4
|
+
|
|
5
|
+
type DomRoot = ParentNode | Element | Document;
|
|
6
|
+
declare function summarizeMachinaDom(rootOrOptions?: DomRoot | SummarizeMachinaDomOptions): MachinaDomSummary;
|
|
7
|
+
|
|
8
|
+
export { MachinaDomSummary, SummarizeMachinaDomOptions, summarizeMachinaDom };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// src/inspect/summarizeMachinaDom.ts
|
|
2
|
+
var DEFAULT_SELECTOR = "[data-machina-node-id]";
|
|
3
|
+
var DEFAULT_MAX_TEXT_LENGTH = 120;
|
|
4
|
+
function getGlobalDocument() {
|
|
5
|
+
return typeof document === "undefined" ? void 0 : document;
|
|
6
|
+
}
|
|
7
|
+
function isOptions(value) {
|
|
8
|
+
if (value === void 0 || value === null || typeof value !== "object") return false;
|
|
9
|
+
return "root" in value || "selector" in value || "includeTextExcerpt" in value || "includeA11y" in value || "generatedAt" in value || "maxTextLength" in value || "includeEmptyNodes" in value;
|
|
10
|
+
}
|
|
11
|
+
function readOptionalAttribute(element, name) {
|
|
12
|
+
const value = element.getAttribute(name);
|
|
13
|
+
return value === null || value === "" ? void 0 : value;
|
|
14
|
+
}
|
|
15
|
+
function rectFromElement(element) {
|
|
16
|
+
const rect = element.getBoundingClientRect();
|
|
17
|
+
return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };
|
|
18
|
+
}
|
|
19
|
+
function textExcerpt(element, maxLength) {
|
|
20
|
+
const normalized = (element.textContent ?? "").replace(/\s+/g, " ").trim();
|
|
21
|
+
if (normalized === "") return void 0;
|
|
22
|
+
return normalized.length > maxLength ? normalized.slice(0, maxLength) : normalized;
|
|
23
|
+
}
|
|
24
|
+
function canMatchRoot(root) {
|
|
25
|
+
return typeof root.matches === "function";
|
|
26
|
+
}
|
|
27
|
+
function queryMatchingElements(root, selector) {
|
|
28
|
+
const matches = Array.from(root.querySelectorAll(selector));
|
|
29
|
+
if (canMatchRoot(root) && root.matches(selector)) return [root, ...matches];
|
|
30
|
+
return matches;
|
|
31
|
+
}
|
|
32
|
+
function nearestMatchingAncestor(element, selected, root) {
|
|
33
|
+
let parent = element.parentElement;
|
|
34
|
+
while (parent) {
|
|
35
|
+
if (selected.has(parent)) return parent;
|
|
36
|
+
if (parent === root) return void 0;
|
|
37
|
+
parent = parent.parentElement;
|
|
38
|
+
}
|
|
39
|
+
return void 0;
|
|
40
|
+
}
|
|
41
|
+
function makeSummaryNode(element, options) {
|
|
42
|
+
const node = {
|
|
43
|
+
tagName: element.tagName.toLowerCase(),
|
|
44
|
+
rect: rectFromElement(element),
|
|
45
|
+
children: []
|
|
46
|
+
};
|
|
47
|
+
const nodeId = readOptionalAttribute(element, "data-machina-node-id");
|
|
48
|
+
const view = readOptionalAttribute(element, "data-machina-view");
|
|
49
|
+
const slot = readOptionalAttribute(element, "data-machina-slot");
|
|
50
|
+
const debugLabel = readOptionalAttribute(element, "data-machina-debug-label");
|
|
51
|
+
const layer = readOptionalAttribute(element, "data-machina-layer");
|
|
52
|
+
if (nodeId !== void 0) node.nodeId = nodeId;
|
|
53
|
+
if (view !== void 0) node.view = view;
|
|
54
|
+
if (slot !== void 0) node.slot = slot;
|
|
55
|
+
if (debugLabel !== void 0) node.debugLabel = debugLabel;
|
|
56
|
+
if (layer !== void 0) node.layer = layer;
|
|
57
|
+
if (options.includeA11y) {
|
|
58
|
+
const role = readOptionalAttribute(element, "role");
|
|
59
|
+
const ariaLabel = readOptionalAttribute(element, "aria-label");
|
|
60
|
+
if (role !== void 0) node.role = role;
|
|
61
|
+
if (ariaLabel !== void 0) node.ariaLabel = ariaLabel;
|
|
62
|
+
}
|
|
63
|
+
if (options.includeTextExcerpt) {
|
|
64
|
+
const excerpt = textExcerpt(element, options.maxTextLength);
|
|
65
|
+
if (excerpt !== void 0) node.textExcerpt = excerpt;
|
|
66
|
+
}
|
|
67
|
+
return node;
|
|
68
|
+
}
|
|
69
|
+
function summarizeMachinaDom(rootOrOptions) {
|
|
70
|
+
const options = isOptions(rootOrOptions) ? rootOrOptions : { root: rootOrOptions };
|
|
71
|
+
const selector = options.selector ?? DEFAULT_SELECTOR;
|
|
72
|
+
const root = options.root ?? getGlobalDocument();
|
|
73
|
+
const summary = { schemaVersion: 1, rootSelector: selector, nodes: [] };
|
|
74
|
+
if (options.generatedAt !== void 0) summary.generatedAt = options.generatedAt;
|
|
75
|
+
if (root === void 0 || typeof root.querySelectorAll !== "function") return summary;
|
|
76
|
+
const elements = queryMatchingElements(root, selector);
|
|
77
|
+
const selected = new Set(elements);
|
|
78
|
+
const nodeByElement = /* @__PURE__ */ new Map();
|
|
79
|
+
const nodeOptions = {
|
|
80
|
+
includeTextExcerpt: options.includeTextExcerpt ?? false,
|
|
81
|
+
includeA11y: options.includeA11y ?? false,
|
|
82
|
+
maxTextLength: options.maxTextLength ?? DEFAULT_MAX_TEXT_LENGTH
|
|
83
|
+
};
|
|
84
|
+
for (const element of elements) nodeByElement.set(element, makeSummaryNode(element, nodeOptions));
|
|
85
|
+
for (const element of elements) {
|
|
86
|
+
const node = nodeByElement.get(element);
|
|
87
|
+
if (!node) continue;
|
|
88
|
+
const parent = nearestMatchingAncestor(element, selected, root);
|
|
89
|
+
const parentNode = parent === void 0 ? void 0 : nodeByElement.get(parent);
|
|
90
|
+
if (parentNode) parentNode.children.push(node);
|
|
91
|
+
else summary.nodes.push(node);
|
|
92
|
+
}
|
|
93
|
+
return summary;
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
summarizeMachinaDom
|
|
97
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { o as MachinaDebugOverlayMode } from '../debugOverlay-pJpj0n5H.js';
|
|
3
|
+
import { b as ResolvedLayoutDocument, N as NodeId, R as Rect, a as ResolvedLayoutNode } from '../types-B90jb3RW.js';
|
|
4
|
+
|
|
5
|
+
type MachinaSlotProps<TViewData = unknown, TNodeData = unknown> = {
|
|
6
|
+
id: NodeId;
|
|
7
|
+
rect: Rect;
|
|
8
|
+
debugLabel?: string;
|
|
9
|
+
node: ResolvedLayoutNode;
|
|
10
|
+
viewKey?: string;
|
|
11
|
+
viewData?: TViewData;
|
|
12
|
+
nodeData?: TNodeData;
|
|
13
|
+
};
|
|
14
|
+
type MachinaRenderLayer = {
|
|
15
|
+
z: number;
|
|
16
|
+
};
|
|
17
|
+
type MachinaReactDebugOverlayOptions = {
|
|
18
|
+
mode?: MachinaDebugOverlayMode;
|
|
19
|
+
labels?: boolean;
|
|
20
|
+
borders?: boolean;
|
|
21
|
+
selectedNodeId?: string;
|
|
22
|
+
};
|
|
23
|
+
type MachinaReactViewProps = {
|
|
24
|
+
layout: ResolvedLayoutDocument;
|
|
25
|
+
views?: Record<string, React.ComponentType<MachinaSlotProps>>;
|
|
26
|
+
viewData?: Record<string, unknown>;
|
|
27
|
+
nodeData?: Record<NodeId, unknown>;
|
|
28
|
+
className?: string;
|
|
29
|
+
style?: React.CSSProperties;
|
|
30
|
+
nodeClassName?: string;
|
|
31
|
+
debug?: boolean;
|
|
32
|
+
nodeContainment?: "none" | "layout-paint" | "strict";
|
|
33
|
+
nodeContentVisibility?: "none" | "auto";
|
|
34
|
+
nodeContainIntrinsicSize?: string;
|
|
35
|
+
layers?: Record<string, MachinaRenderLayer>;
|
|
36
|
+
defaultLayer?: string;
|
|
37
|
+
debugOverlay?: MachinaReactDebugOverlayOptions;
|
|
38
|
+
};
|
|
39
|
+
declare function MachinaReactView(props: MachinaReactViewProps): React.JSX.Element;
|
|
40
|
+
|
|
41
|
+
export { type MachinaReactDebugOverlayOptions, MachinaReactView, type MachinaReactViewProps, type MachinaSlotProps };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
3
|
+
import { N as NodeId, R as Rect, a as ResolvedLayoutNode, b as ResolvedLayoutDocument } from '../types-B90jb3RW.js';
|
|
4
|
+
|
|
5
|
+
type MachinaNativeSlotProps<TViewData = unknown, TNodeData = unknown> = {
|
|
6
|
+
id: NodeId;
|
|
7
|
+
rect: Rect;
|
|
8
|
+
debugLabel?: string;
|
|
9
|
+
node: ResolvedLayoutNode;
|
|
10
|
+
viewKey?: string;
|
|
11
|
+
viewData?: TViewData;
|
|
12
|
+
nodeData?: TNodeData;
|
|
13
|
+
};
|
|
14
|
+
type MachinaReactNativeLayer = {
|
|
15
|
+
z: number;
|
|
16
|
+
};
|
|
17
|
+
type MachinaReactNativeViewProps = {
|
|
18
|
+
layout: ResolvedLayoutDocument;
|
|
19
|
+
views?: Record<string, React.ComponentType<MachinaNativeSlotProps>>;
|
|
20
|
+
viewData?: Record<string, unknown>;
|
|
21
|
+
nodeData?: Record<NodeId, unknown>;
|
|
22
|
+
layers?: Record<string, MachinaReactNativeLayer>;
|
|
23
|
+
defaultLayer?: string;
|
|
24
|
+
debug?: boolean;
|
|
25
|
+
style?: StyleProp<ViewStyle>;
|
|
26
|
+
nodeStyle?: StyleProp<ViewStyle>;
|
|
27
|
+
};
|
|
28
|
+
declare function MachinaReactNativeView(props: MachinaReactNativeViewProps): React.ReactElement;
|
|
29
|
+
|
|
30
|
+
export { type MachinaNativeSlotProps, type MachinaReactNativeLayer, MachinaReactNativeView, type MachinaReactNativeViewProps };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import {
|
|
2
|
+
toResolvedTree
|
|
3
|
+
} from "../chunk-SVWYWI7I.js";
|
|
4
|
+
import "../chunk-VREK57S3.js";
|
|
5
|
+
|
|
6
|
+
// src/react-native/MachinaReactNativeView.tsx
|
|
7
|
+
import React from "react";
|
|
8
|
+
import { Text, View } from "react-native";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
function normalizeLayerZ(value) {
|
|
11
|
+
if (value === void 0 || !Number.isFinite(value)) return 0;
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
function getLayerZ(node, layers, defaultLayer) {
|
|
15
|
+
return normalizeLayerZ(layers[node.layer ?? defaultLayer]?.z);
|
|
16
|
+
}
|
|
17
|
+
function renderNode(node, parentRect, props) {
|
|
18
|
+
const left = node.rect.x - parentRect.x;
|
|
19
|
+
const top = node.rect.y - parentRect.y;
|
|
20
|
+
const viewKey = node.view ?? node.slot;
|
|
21
|
+
const ViewComponent = viewKey ? props.views[viewKey] : void 0;
|
|
22
|
+
const layerZ = getLayerZ(node, props.layers, props.defaultLayer);
|
|
23
|
+
const nodeZ = node.z ?? 0;
|
|
24
|
+
return /* @__PURE__ */ jsxs(
|
|
25
|
+
View,
|
|
26
|
+
{
|
|
27
|
+
testID: `machina-node-${node.id}`,
|
|
28
|
+
style: [
|
|
29
|
+
{
|
|
30
|
+
position: "absolute",
|
|
31
|
+
left,
|
|
32
|
+
top,
|
|
33
|
+
width: node.rect.width,
|
|
34
|
+
height: node.rect.height,
|
|
35
|
+
zIndex: layerZ * 100 + nodeZ
|
|
36
|
+
},
|
|
37
|
+
props.debug ? { borderWidth: 1, borderColor: "rgba(59, 130, 246, 0.9)" } : null,
|
|
38
|
+
props.nodeStyle
|
|
39
|
+
],
|
|
40
|
+
children: [
|
|
41
|
+
props.debug ? /* @__PURE__ */ jsx(Text, { children: node.debugLabel ?? node.id }) : null,
|
|
42
|
+
ViewComponent && props.nodes[node.id] && viewKey ? React.createElement(ViewComponent, {
|
|
43
|
+
id: node.id,
|
|
44
|
+
rect: { ...node.rect },
|
|
45
|
+
debugLabel: node.debugLabel,
|
|
46
|
+
node: { ...props.nodes[node.id], rect: { ...props.nodes[node.id].rect } },
|
|
47
|
+
viewKey,
|
|
48
|
+
viewData: props.viewData?.[viewKey],
|
|
49
|
+
nodeData: props.nodeData?.[node.id]
|
|
50
|
+
}) : null,
|
|
51
|
+
[...node.children].map((child, index) => ({ child, index })).sort(
|
|
52
|
+
(a, b) => getLayerZ(a.child, props.layers, props.defaultLayer) - getLayerZ(b.child, props.layers, props.defaultLayer) || (a.child.z ?? 0) - (b.child.z ?? 0) || a.index - b.index
|
|
53
|
+
).map(({ child }) => renderNode(child, node.rect, props))
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
node.id
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
function MachinaReactNativeView(props) {
|
|
60
|
+
const tree = toResolvedTree(props.layout);
|
|
61
|
+
return /* @__PURE__ */ jsx(
|
|
62
|
+
View,
|
|
63
|
+
{
|
|
64
|
+
testID: "machina-root-wrapper",
|
|
65
|
+
style: [
|
|
66
|
+
{ position: "relative", width: tree.rect.width, height: tree.rect.height },
|
|
67
|
+
props.style
|
|
68
|
+
],
|
|
69
|
+
children: renderNode(tree, tree.rect, {
|
|
70
|
+
views: props.views ?? {},
|
|
71
|
+
viewData: props.viewData,
|
|
72
|
+
nodeData: props.nodeData,
|
|
73
|
+
nodes: props.layout.nodes,
|
|
74
|
+
layers: props.layers ?? { base: { z: 0 } },
|
|
75
|
+
defaultLayer: props.defaultLayer ?? "base",
|
|
76
|
+
debug: props.debug,
|
|
77
|
+
nodeStyle: props.nodeStyle
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
export {
|
|
83
|
+
MachinaReactNativeView
|
|
84
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
type MachinaViewport = {
|
|
2
|
+
key: string;
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
deviceScaleFactor?: number;
|
|
6
|
+
label?: string;
|
|
7
|
+
tags?: readonly string[];
|
|
8
|
+
};
|
|
9
|
+
type MachinaViewportMatrix = readonly MachinaViewport[];
|
|
10
|
+
type MachinaScreen = {
|
|
11
|
+
key: string;
|
|
12
|
+
route: string;
|
|
13
|
+
fixture?: string;
|
|
14
|
+
viewports?: readonly string[];
|
|
15
|
+
tags?: readonly string[];
|
|
16
|
+
title?: string;
|
|
17
|
+
metadata?: Record<string, unknown>;
|
|
18
|
+
};
|
|
19
|
+
type MachinaScreenCatalog = {
|
|
20
|
+
screens: Record<string, MachinaScreen>;
|
|
21
|
+
order: string[];
|
|
22
|
+
};
|
|
23
|
+
type MachinaScreenViewportTask = {
|
|
24
|
+
key: string;
|
|
25
|
+
screenKey: string;
|
|
26
|
+
viewportKey: string;
|
|
27
|
+
route: string;
|
|
28
|
+
fixture?: string;
|
|
29
|
+
viewport: MachinaViewport;
|
|
30
|
+
screen: MachinaScreen;
|
|
31
|
+
tags: readonly string[];
|
|
32
|
+
artifactBaseName: string;
|
|
33
|
+
};
|
|
34
|
+
type ExpandOptions = {
|
|
35
|
+
screenKeys?: readonly string[];
|
|
36
|
+
viewportKeys?: readonly string[];
|
|
37
|
+
tags?: readonly string[];
|
|
38
|
+
};
|
|
39
|
+
declare function defineMachinaViewports(viewports: readonly MachinaViewport[]): MachinaViewportMatrix;
|
|
40
|
+
declare function createViewportMatrix(preset?: "standard-responsive" | "desktop-only" | "mobile-first"): MachinaViewportMatrix;
|
|
41
|
+
declare function defineMachinaScreens(screens: readonly MachinaScreen[]): MachinaScreenCatalog;
|
|
42
|
+
declare function slugMachinaArtifactName(input: string): string;
|
|
43
|
+
declare function getMachinaViewport(viewports: MachinaViewportMatrix, key: string): MachinaViewport;
|
|
44
|
+
declare function expandScreenViewportTasks(catalog: MachinaScreenCatalog, viewports: MachinaViewportMatrix, options?: ExpandOptions): MachinaScreenViewportTask[];
|
|
45
|
+
|
|
46
|
+
export { type MachinaViewport as M, type MachinaScreenViewportTask as a, type MachinaScreen as b, type MachinaScreenCatalog as c, type MachinaViewportMatrix as d, createViewportMatrix as e, defineMachinaScreens as f, defineMachinaViewports as g, expandScreenViewportTasks as h, getMachinaViewport as i, slugMachinaArtifactName as s };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { a as MachinaTextSource, P as ParseMachinaTextResult, d as MachinaInline, g as MachinaTextDiagnostic } from '../types-C4poVJpR.js';
|
|
2
|
+
export { c as MachinaBulletItem, e as MachinaTextAlign, f as MachinaTextBlock, h as MachinaTextDiagnosticCode, i as MachinaTextDiagnosticLevel, b as MachinaTextDocument, j as MachinaTextLeading, k as MachinaTextOverflow, M as MachinaTextSpec, l as MachinaTextVariant, m as MachinaTextVerticalAlign, n as MachinaTextWrap } from '../types-C4poVJpR.js';
|
|
3
|
+
|
|
4
|
+
declare function parseMachinaTextInline(text: string): {
|
|
5
|
+
inline: MachinaInline[];
|
|
6
|
+
diagnostics: MachinaTextDiagnostic[];
|
|
7
|
+
};
|
|
8
|
+
declare function parseMachinaText(source: MachinaTextSource | string): ParseMachinaTextResult;
|
|
9
|
+
|
|
10
|
+
export { MachinaInline, MachinaTextDiagnostic, MachinaTextSource, ParseMachinaTextResult, parseMachinaText, parseMachinaTextInline };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { M as MachinaTextSpec, a as MachinaTextSource, b as MachinaTextDocument } from '../../types-C4poVJpR.js';
|
|
3
|
+
|
|
4
|
+
type MachinaTextViewProps = {
|
|
5
|
+
text: MachinaTextSpec | MachinaTextSource | MachinaTextDocument | string;
|
|
6
|
+
className?: string;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
linkTarget?: React.HTMLAttributeAnchorTarget;
|
|
9
|
+
onLinkClick?: (href: string, event: React.MouseEvent<HTMLAnchorElement>) => void;
|
|
10
|
+
showDiagnostics?: boolean;
|
|
11
|
+
};
|
|
12
|
+
declare function MachinaTextView(props: MachinaTextViewProps): React.JSX.Element;
|
|
13
|
+
|
|
14
|
+
export { MachinaTextView, type MachinaTextViewProps };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyleProp, TextStyle, ViewStyle } from 'react-native';
|
|
3
|
+
import { M as MachinaTextSpec, a as MachinaTextSource, b as MachinaTextDocument } from '../../types-C4poVJpR.js';
|
|
4
|
+
|
|
5
|
+
type MachinaNativeTextViewProps = {
|
|
6
|
+
text: MachinaTextSpec | MachinaTextSource | MachinaTextDocument | string;
|
|
7
|
+
style?: StyleProp<TextStyle>;
|
|
8
|
+
contentStyle?: StyleProp<ViewStyle>;
|
|
9
|
+
linkStyle?: StyleProp<TextStyle>;
|
|
10
|
+
codeStyle?: StyleProp<TextStyle>;
|
|
11
|
+
onLinkPress?: (href: string) => void;
|
|
12
|
+
showDiagnostics?: boolean;
|
|
13
|
+
};
|
|
14
|
+
declare function MachinaNativeTextView(props: MachinaNativeTextViewProps): React.ReactElement;
|
|
15
|
+
|
|
16
|
+
export { MachinaNativeTextView, type MachinaNativeTextViewProps };
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parseMachinaText
|
|
3
|
+
} from "../../chunk-BJOQRPPX.js";
|
|
4
|
+
|
|
5
|
+
// src/text/react-native/MachinaNativeTextView.tsx
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { Text, View } from "react-native";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
var DEFAULT_POLICY = {
|
|
10
|
+
variant: "body",
|
|
11
|
+
wrap: "word",
|
|
12
|
+
overflow: "clip",
|
|
13
|
+
align: "start",
|
|
14
|
+
leading: "normal",
|
|
15
|
+
blockGap: 8,
|
|
16
|
+
listGap: 2,
|
|
17
|
+
valign: "top"
|
|
18
|
+
};
|
|
19
|
+
var VARIANT_STYLE = {
|
|
20
|
+
body: { fontSize: 14, fontWeight: "400" },
|
|
21
|
+
label: { fontSize: 12, fontWeight: "500" },
|
|
22
|
+
caption: { fontSize: 11, fontWeight: "400", opacity: 0.8 },
|
|
23
|
+
title: { fontSize: 18, fontWeight: "700" },
|
|
24
|
+
mono: { fontSize: 12, fontFamily: "monospace" }
|
|
25
|
+
};
|
|
26
|
+
var isDoc = (v) => typeof v === "object" && v !== null && "blocks" in v;
|
|
27
|
+
var isSpec = (v) => typeof v === "object" && v !== null && "kind" in v && v.kind === "text";
|
|
28
|
+
var normalizePositive = (v, f) => typeof v === "number" && Number.isFinite(v) && v > 0 ? v : f;
|
|
29
|
+
var normalizeNonNegative = (v, f) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : f;
|
|
30
|
+
function resolveLeadingMultiplier(policy) {
|
|
31
|
+
if (policy.leading === "tight") return 1.15;
|
|
32
|
+
if (policy.leading === "loose") return 1.6;
|
|
33
|
+
if (typeof policy.leading === "number") return policy.leading;
|
|
34
|
+
if (policy.variant === "body") return 1.4;
|
|
35
|
+
if (policy.variant === "label") return 1.3;
|
|
36
|
+
if (policy.variant === "caption") return 1.25;
|
|
37
|
+
if (policy.variant === "title") return 1.25;
|
|
38
|
+
return 1.35;
|
|
39
|
+
}
|
|
40
|
+
function normalizeLeading(value) {
|
|
41
|
+
if (value === void 0) return DEFAULT_POLICY.leading;
|
|
42
|
+
if (value === "tight" || value === "normal" || value === "loose") return value;
|
|
43
|
+
return normalizePositive(value, resolveLeadingMultiplier(DEFAULT_POLICY));
|
|
44
|
+
}
|
|
45
|
+
function normalizeText(text) {
|
|
46
|
+
if (isDoc(text)) return { document: text, diagnostics: [], policy: DEFAULT_POLICY };
|
|
47
|
+
if (isSpec(text)) {
|
|
48
|
+
const result2 = parseMachinaText(text.source);
|
|
49
|
+
return {
|
|
50
|
+
document: result2.document,
|
|
51
|
+
diagnostics: result2.diagnostics,
|
|
52
|
+
policy: {
|
|
53
|
+
variant: text.variant ?? DEFAULT_POLICY.variant,
|
|
54
|
+
wrap: text.wrap ?? DEFAULT_POLICY.wrap,
|
|
55
|
+
overflow: text.overflow ?? DEFAULT_POLICY.overflow,
|
|
56
|
+
align: text.align ?? DEFAULT_POLICY.align,
|
|
57
|
+
leading: normalizeLeading(text.leading),
|
|
58
|
+
blockGap: normalizeNonNegative(text.blockGap, DEFAULT_POLICY.blockGap),
|
|
59
|
+
listGap: normalizeNonNegative(text.listGap, DEFAULT_POLICY.listGap),
|
|
60
|
+
valign: text.valign ?? DEFAULT_POLICY.valign
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const result = parseMachinaText(typeof text === "string" ? { kind: "machina-text", text } : text);
|
|
65
|
+
return { document: result.document, diagnostics: result.diagnostics, policy: DEFAULT_POLICY };
|
|
66
|
+
}
|
|
67
|
+
function textStyle(policy) {
|
|
68
|
+
const base = VARIANT_STYLE[policy.variant];
|
|
69
|
+
const fontSize = base.fontSize ?? 14;
|
|
70
|
+
return {
|
|
71
|
+
...base,
|
|
72
|
+
lineHeight: fontSize * resolveLeadingMultiplier(policy),
|
|
73
|
+
textAlign: policy.align === "center" ? "center" : policy.align === "end" ? "right" : "left"
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
var pProps = (policy) => policy.overflow === "ellipsis" ? { numberOfLines: 1, ellipsizeMode: "tail" } : policy.wrap === "none" ? { numberOfLines: 1 } : {};
|
|
77
|
+
function renderInline(inline, key, props) {
|
|
78
|
+
switch (inline.kind) {
|
|
79
|
+
case "text":
|
|
80
|
+
return /* @__PURE__ */ jsx(React.Fragment, { children: inline.text }, key);
|
|
81
|
+
case "strong":
|
|
82
|
+
return /* @__PURE__ */ jsx(Text, { style: { fontWeight: "700" }, children: inline.children.map((c, i) => renderInline(c, `${key}-s-${i}`, props)) }, key);
|
|
83
|
+
case "emphasis":
|
|
84
|
+
return /* @__PURE__ */ jsx(Text, { style: { fontStyle: "italic" }, children: inline.children.map((c, i) => renderInline(c, `${key}-e-${i}`, props)) }, key);
|
|
85
|
+
case "code":
|
|
86
|
+
return /* @__PURE__ */ jsx(Text, { style: [{ fontFamily: "monospace" }, props.codeStyle], children: inline.text }, key);
|
|
87
|
+
case "link":
|
|
88
|
+
return /* @__PURE__ */ jsx(
|
|
89
|
+
Text,
|
|
90
|
+
{
|
|
91
|
+
style: [{ textDecorationLine: "underline", color: "#2563eb" }, props.linkStyle],
|
|
92
|
+
onPress: () => props.onLinkPress?.(inline.href),
|
|
93
|
+
children: inline.children.map((c, i) => renderInline(c, `${key}-l-${i}`, props))
|
|
94
|
+
},
|
|
95
|
+
key
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function renderBullet(item, path, props, policy, depth) {
|
|
100
|
+
return /* @__PURE__ */ jsxs(View, { style: { marginBottom: policy.listGap, marginLeft: depth * 12 }, children: [
|
|
101
|
+
/* @__PURE__ */ jsxs(View, { style: { flexDirection: "row", alignItems: "flex-start" }, children: [
|
|
102
|
+
/* @__PURE__ */ jsx(Text, { style: textStyle(policy), children: "\u2022 " }),
|
|
103
|
+
/* @__PURE__ */ jsx(Text, { style: [{ flexShrink: 1 }, textStyle(policy)], ...pProps(policy), children: item.inline.map((i, idx) => renderInline(i, `${path}-i-${idx}`, props)) })
|
|
104
|
+
] }),
|
|
105
|
+
item.children?.map(
|
|
106
|
+
(child, idx) => renderBullet(child, `${path}-c-${idx}`, props, policy, depth + 1)
|
|
107
|
+
)
|
|
108
|
+
] }, path);
|
|
109
|
+
}
|
|
110
|
+
function MachinaNativeTextView(props) {
|
|
111
|
+
const normalized = normalizeText(props.text);
|
|
112
|
+
const justifyContent = normalized.policy.valign === "center" ? "center" : normalized.policy.valign === "bottom" ? "flex-end" : "flex-start";
|
|
113
|
+
return /* @__PURE__ */ jsx(View, { style: [{ width: "100%", height: "100%", justifyContent }, props.contentStyle], children: /* @__PURE__ */ jsxs(View, { style: { minWidth: 0 }, children: [
|
|
114
|
+
normalized.document.blocks.map(
|
|
115
|
+
(block, idx) => block.kind === "paragraph" ? /* @__PURE__ */ jsx(
|
|
116
|
+
Text,
|
|
117
|
+
{
|
|
118
|
+
style: [
|
|
119
|
+
textStyle(normalized.policy),
|
|
120
|
+
idx === normalized.document.blocks.length - 1 ? void 0 : { marginBottom: normalized.policy.blockGap },
|
|
121
|
+
props.style
|
|
122
|
+
],
|
|
123
|
+
...pProps(normalized.policy),
|
|
124
|
+
children: block.inline.map((i, iIdx) => renderInline(i, `b-${idx}-${iIdx}`, props))
|
|
125
|
+
},
|
|
126
|
+
`b-${idx}`
|
|
127
|
+
) : /* @__PURE__ */ jsx(
|
|
128
|
+
View,
|
|
129
|
+
{
|
|
130
|
+
style: idx === normalized.document.blocks.length - 1 ? void 0 : { marginBottom: normalized.policy.blockGap },
|
|
131
|
+
children: block.items.map(
|
|
132
|
+
(item, itemIdx) => renderBullet(item, `b-${idx}-item-${itemIdx}`, props, normalized.policy, 0)
|
|
133
|
+
)
|
|
134
|
+
},
|
|
135
|
+
`b-${idx}`
|
|
136
|
+
)
|
|
137
|
+
),
|
|
138
|
+
props.showDiagnostics && normalized.diagnostics.length > 0 ? /* @__PURE__ */ jsx(
|
|
139
|
+
Text,
|
|
140
|
+
{
|
|
141
|
+
style: {
|
|
142
|
+
marginTop: normalized.policy.blockGap,
|
|
143
|
+
padding: 8,
|
|
144
|
+
fontSize: 11,
|
|
145
|
+
fontFamily: "monospace",
|
|
146
|
+
backgroundColor: "rgba(127, 127, 127, 0.12)"
|
|
147
|
+
},
|
|
148
|
+
children: normalized.diagnostics.map((d) => `${d.code} (${d.line}:${d.column}) ${d.message}`).join("\n")
|
|
149
|
+
}
|
|
150
|
+
) : null
|
|
151
|
+
] }) });
|
|
152
|
+
}
|
|
153
|
+
export {
|
|
154
|
+
MachinaNativeTextView
|
|
155
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import * as vue from 'vue';
|
|
2
|
+
import { PropType, StyleValue } from 'vue';
|
|
3
|
+
import { M as MachinaTextSpec, a as MachinaTextSource, b as MachinaTextDocument } from '../../types-C4poVJpR.js';
|
|
4
|
+
|
|
5
|
+
type MachinaVueTextViewProps = {
|
|
6
|
+
text: MachinaTextSpec | MachinaTextSource | MachinaTextDocument | string;
|
|
7
|
+
rootClass?: unknown;
|
|
8
|
+
rootStyle?: StyleValue;
|
|
9
|
+
linkTarget?: string;
|
|
10
|
+
onLinkClick?: (href: string, event: MouseEvent) => void;
|
|
11
|
+
showDiagnostics?: boolean;
|
|
12
|
+
linkClass?: unknown;
|
|
13
|
+
linkStyle?: StyleValue;
|
|
14
|
+
codeClass?: unknown;
|
|
15
|
+
codeStyle?: StyleValue;
|
|
16
|
+
};
|
|
17
|
+
declare const MachinaVueTextView: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
18
|
+
text: {
|
|
19
|
+
type: PropType<MachinaVueTextViewProps["text"]>;
|
|
20
|
+
required: true;
|
|
21
|
+
};
|
|
22
|
+
rootClass: {
|
|
23
|
+
type: PropType<unknown>;
|
|
24
|
+
default: undefined;
|
|
25
|
+
};
|
|
26
|
+
rootStyle: {
|
|
27
|
+
type: PropType<StyleValue>;
|
|
28
|
+
default: undefined;
|
|
29
|
+
};
|
|
30
|
+
linkTarget: {
|
|
31
|
+
type: StringConstructor;
|
|
32
|
+
default: undefined;
|
|
33
|
+
};
|
|
34
|
+
onLinkClick: {
|
|
35
|
+
type: PropType<MachinaVueTextViewProps["onLinkClick"]>;
|
|
36
|
+
default: undefined;
|
|
37
|
+
};
|
|
38
|
+
showDiagnostics: {
|
|
39
|
+
type: BooleanConstructor;
|
|
40
|
+
default: boolean;
|
|
41
|
+
};
|
|
42
|
+
linkClass: {
|
|
43
|
+
type: PropType<unknown>;
|
|
44
|
+
default: undefined;
|
|
45
|
+
};
|
|
46
|
+
linkStyle: {
|
|
47
|
+
type: PropType<StyleValue>;
|
|
48
|
+
default: undefined;
|
|
49
|
+
};
|
|
50
|
+
codeClass: {
|
|
51
|
+
type: PropType<unknown>;
|
|
52
|
+
default: undefined;
|
|
53
|
+
};
|
|
54
|
+
codeStyle: {
|
|
55
|
+
type: PropType<StyleValue>;
|
|
56
|
+
default: undefined;
|
|
57
|
+
};
|
|
58
|
+
}>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
59
|
+
[key: string]: any;
|
|
60
|
+
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
61
|
+
text: {
|
|
62
|
+
type: PropType<MachinaVueTextViewProps["text"]>;
|
|
63
|
+
required: true;
|
|
64
|
+
};
|
|
65
|
+
rootClass: {
|
|
66
|
+
type: PropType<unknown>;
|
|
67
|
+
default: undefined;
|
|
68
|
+
};
|
|
69
|
+
rootStyle: {
|
|
70
|
+
type: PropType<StyleValue>;
|
|
71
|
+
default: undefined;
|
|
72
|
+
};
|
|
73
|
+
linkTarget: {
|
|
74
|
+
type: StringConstructor;
|
|
75
|
+
default: undefined;
|
|
76
|
+
};
|
|
77
|
+
onLinkClick: {
|
|
78
|
+
type: PropType<MachinaVueTextViewProps["onLinkClick"]>;
|
|
79
|
+
default: undefined;
|
|
80
|
+
};
|
|
81
|
+
showDiagnostics: {
|
|
82
|
+
type: BooleanConstructor;
|
|
83
|
+
default: boolean;
|
|
84
|
+
};
|
|
85
|
+
linkClass: {
|
|
86
|
+
type: PropType<unknown>;
|
|
87
|
+
default: undefined;
|
|
88
|
+
};
|
|
89
|
+
linkStyle: {
|
|
90
|
+
type: PropType<StyleValue>;
|
|
91
|
+
default: undefined;
|
|
92
|
+
};
|
|
93
|
+
codeClass: {
|
|
94
|
+
type: PropType<unknown>;
|
|
95
|
+
default: undefined;
|
|
96
|
+
};
|
|
97
|
+
codeStyle: {
|
|
98
|
+
type: PropType<StyleValue>;
|
|
99
|
+
default: undefined;
|
|
100
|
+
};
|
|
101
|
+
}>> & Readonly<{}>, {
|
|
102
|
+
onLinkClick: ((href: string, event: MouseEvent) => void) | undefined;
|
|
103
|
+
rootClass: undefined;
|
|
104
|
+
rootStyle: StyleValue;
|
|
105
|
+
linkTarget: string;
|
|
106
|
+
showDiagnostics: boolean;
|
|
107
|
+
linkClass: undefined;
|
|
108
|
+
linkStyle: StyleValue;
|
|
109
|
+
codeClass: undefined;
|
|
110
|
+
codeStyle: StyleValue;
|
|
111
|
+
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
112
|
+
|
|
113
|
+
export { MachinaVueTextView, type MachinaVueTextViewProps };
|