@playgenx/components 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/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # `@playgenx/components`
2
+
3
+ Default React 19 implementations for every entry in `DEFAULT_REGISTRY`. Pair with `@playgenx/registry` and the parser/validator pipeline.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ pnpm add @playgenx/components react@^19 react-dom@^19
9
+ ```
10
+
11
+ React 19 is a peer dependency; this package does not bundle it.
12
+
13
+ ## What's in here
14
+
15
+ 11 components, each matching a name in `@playgenx/registry`:
16
+
17
+ - `Button` — primary / secondary / ghost variant, disabled state, click handler.
18
+ - `TextField` — labeled controlled-or-uncontrolled input.
19
+ - `Slider` — clamped range input with optional caption.
20
+ - `Chart` — bar / line / pie, hand-rolled SVG, no chart library.
21
+ - `Container` — vertical flex wrapper with padding + gap.
22
+ - `Code` — inline or `<pre><code>` formatting, language data-attribute.
23
+ - `Heading` — `<h1>`..`<h6>` with size-by-level, clamped.
24
+ - `Text` — `<p>` with weight, size, color.
25
+ - `Stepper` — multi-step reveal with previous/current/future states.
26
+ - `Card` — bordered + shadowed wrapper with elevation prop.
27
+ - `List` — `<ul>` or `<ol>` from an array of arbitrary values.
28
+
29
+ ## Use
30
+
31
+ ```tsx
32
+ import { Button, Container, Heading, Text, componentMap } from '@playgenx/components';
33
+ import { DEFAULT_REGISTRY, findSchema } from '@playgenx/registry';
34
+
35
+ function App() {
36
+ return (
37
+ <Container>
38
+ <Heading level={2}>Hello</Heading>
39
+ <Text>A short description.</Text>
40
+ <Button label="Continue" variant="primary" />
41
+ </Container>
42
+ );
43
+ }
44
+
45
+ // Render-time lookup:
46
+ const HeadingC = componentMap['Heading'];
47
+ return <HeadingC level={2}>title</HeadingC>;
48
+ ```
49
+
50
+ ## Determinism
51
+
52
+ Components are render-only and **never** reference `Math.random`, `Date.now`, or runtime-crypto APIs. Hashing inputs (validation, storage) is fully reproducible — `<Chart kind="bar" data={...} />` renders the same SVG every time given the same data.
53
+
54
+ If you mount these in an environment where a renderer may pass non-deterministic callbacks, run inside a sandboxed iframe that the LLM never controls.
55
+
56
+ ## Versioning
57
+
58
+ This package follows PlayGenX's overall version policy (mirror `playgenx` core). A component's prop signature is part of the public contract; new optional props are non-breaking, removing/renaming is a breaking change.
59
+
60
+ ## License
61
+
62
+ MIT — see [LICENSE](../../LICENSE).
@@ -0,0 +1,198 @@
1
+ import * as React from "react";
2
+ import { ComponentType } from "react";
3
+ //#region src/Button.d.ts
4
+ /**
5
+ * Headless-style wrapper over `<button>` accepting the props defined in
6
+ * `DEFAULT_COMPONENT_SCHEMAS.Button`. Pass `onClick` through; this
7
+ * implementation does NOT execute arbitrary functions (deterministic
8
+ * renderer constraint) so the click handler is rendered inert at mount.
9
+ */
10
+ interface ButtonProps {
11
+ /** Visible text. Required. */
12
+ label: string;
13
+ /** Variant. Defaults to 'primary'. */
14
+ variant?: 'primary' | 'secondary' | 'ghost';
15
+ /** Disabled state. Defaults to false. */
16
+ disabled?: boolean;
17
+ /**
18
+ * Optional click handler. The default impl forwards to onClick if
19
+ * present; in a deterministic renderer pass `noEvents` instead.
20
+ */
21
+ onClick?: React.MouseEventHandler<HTMLButtonElement>;
22
+ }
23
+ declare function Button({ label, variant, disabled, onClick }: ButtonProps): React.JSX.Element;
24
+ //#endregion
25
+ //#region src/TextField.d.ts
26
+ interface TextFieldProps {
27
+ label?: string;
28
+ value?: string;
29
+ placeholder?: string;
30
+ disabled?: boolean;
31
+ /**
32
+ * onChange is reported as `node` in the schema (it must be a
33
+ * function reference, which the validator cannot statically type).
34
+ * We forward to React's controlled input handler.
35
+ */
36
+ onChange?: React.ChangeEventHandler<HTMLInputElement>;
37
+ }
38
+ /**
39
+ * Controlled text input. Without `value`/`onChange`, behaves as
40
+ * uncontrolled (uses its own state via defaultValue). When a stable
41
+ * (deterministic) caller wires both, the input is fully controlled.
42
+ */
43
+ declare function TextField({ label, value, placeholder, disabled, onChange }: TextFieldProps): React.JSX.Element;
44
+ //#endregion
45
+ //#region src/Slider.d.ts
46
+ interface SliderProps {
47
+ /** Lower bound, inclusive. Required. */
48
+ min: number;
49
+ /** Upper bound, inclusive. Required. */
50
+ max: number;
51
+ /** Initial / controlled value. */
52
+ value?: number;
53
+ /** Increment between stops. Defaults to 1. */
54
+ step?: number;
55
+ /** Optional caption rendered above the slider. */
56
+ label?: string;
57
+ }
58
+ /**
59
+ * Range input. State: internal `value` mirrors props.value if present
60
+ * (otherwise uncontrolled); clamps to [min, max].
61
+ */
62
+ declare function Slider({ min, max, value, step, label }: SliderProps): React.JSX.Element;
63
+ //#endregion
64
+ //#region src/Chart.d.ts
65
+ type ChartKind = 'bar' | 'line' | 'pie';
66
+ /**
67
+ * The schema lets `data` be any ReactNode, but in practice callers
68
+ * pass JSON-shaped arrays. We narrow at runtime:
69
+ *
70
+ * - bar: `{ labels: string[], values: number[] }`
71
+ * - line: `{ x: number[], y: number[] }` or `{ series: { label, points: {x,y} }[] }`
72
+ * - pie: `{ labels: string[], values: number[] }`
73
+ *
74
+ * Anything that doesn't fit is rendered as a `<pre>` fallback.
75
+ */
76
+ interface ChartProps {
77
+ kind: ChartKind;
78
+ data: unknown;
79
+ title?: string;
80
+ }
81
+ declare function Chart({ kind, data, title }: ChartProps): React.JSX.Element;
82
+ //#endregion
83
+ //#region src/Container.d.ts
84
+ interface ContainerProps {
85
+ padding?: string;
86
+ gap?: string;
87
+ children?: React.ReactNode;
88
+ }
89
+ /**
90
+ * Layout wrapper. Defaults to a vertical flex container with 16px
91
+ * padding and 12px gap when callers omit props.
92
+ */
93
+ declare function Container({ padding, gap, children }: ContainerProps): React.JSX.Element;
94
+ //#endregion
95
+ //#region src/Code.d.ts
96
+ interface CodeProps {
97
+ language?: string;
98
+ children?: React.ReactNode;
99
+ }
100
+ /**
101
+ * Inline code formatter. Renders children as a `<code>` element inside
102
+ * a styled wrapper. If `children` is a single string, it displays
103
+ * verbatim; for multi-line content we fall back to a `<pre>`-styled
104
+ * block.
105
+ */
106
+ declare function Code({ language, children }: CodeProps): React.JSX.Element;
107
+ //#endregion
108
+ //#region src/Heading.d.ts
109
+ interface HeadingProps {
110
+ /**
111
+ * Heading level (1..6). Out-of-range or undefined falls back to 2.
112
+ * The renderer should never see an `Undefined` value here unless the
113
+ * schema validator said optional props can be omitted.
114
+ */
115
+ level?: number;
116
+ color?: string;
117
+ children?: React.ReactNode;
118
+ }
119
+ declare function Heading({ level, color, children }: HeadingProps): React.JSX.Element;
120
+ //#endregion
121
+ //#region src/Text.d.ts
122
+ interface TextProps {
123
+ weight?: 'normal' | 'bold';
124
+ size?: string;
125
+ color?: string;
126
+ children?: React.ReactNode;
127
+ }
128
+ declare function Text({ weight, size, color, children }: TextProps): React.JSX.Element;
129
+ //#endregion
130
+ //#region src/Stepper.d.ts
131
+ interface Step {
132
+ id: string;
133
+ title: string;
134
+ body?: React.ReactNode;
135
+ }
136
+ interface StepperProps {
137
+ steps: Step[];
138
+ /** 0-indexed initial step. Out-of-range falls back to 0. */
139
+ initial?: number;
140
+ }
141
+ /**
142
+ * Multi-step reveal. State: the active index. Previous steps can be
143
+ * revisited; future steps are disabled until reached.
144
+ */
145
+ declare function Stepper({ steps, initial }: StepperProps): React.JSX.Element;
146
+ //#endregion
147
+ //#region src/Card.d.ts
148
+ interface CardProps {
149
+ title?: string;
150
+ /**
151
+ * Visual elevation. 0 = flat (border only), 1+ = heavier shadow.
152
+ * Defaults to 1.
153
+ */
154
+ elevation?: number;
155
+ children?: React.ReactNode;
156
+ }
157
+ declare function Card({ title, elevation, children }: CardProps): React.JSX.Element;
158
+ //#endregion
159
+ //#region src/List.d.ts
160
+ interface ListProps {
161
+ /**
162
+ * Items to render. Schema marks this as `node`; in practice callers
163
+ * pass arrays of strings/numbers/ReactNodes. Anything else is
164
+ * rendered as a single bullet containing the value.
165
+ */
166
+ items?: unknown;
167
+ /** When true, renders as `<ol>` instead of `<ul>`. */
168
+ ordered?: boolean;
169
+ /** Override the wrapper element for full control. */
170
+ children?: React.ReactNode;
171
+ }
172
+ /**
173
+ * List of items. Renders `items` as a list of strings/numbers (the
174
+ * common artifact prompt output). If `children` are passed they take
175
+ * precedence over `items`.
176
+ */
177
+ declare function List({ items, ordered, children }: ListProps): React.JSX.Element;
178
+ //#endregion
179
+ //#region src/registry.d.ts
180
+ /**
181
+ * Map of PascalCase component name to React component. Use this when
182
+ * you have a renderer that walks an AST and needs to pick an
183
+ * implementation at runtime:
184
+ *
185
+ * const C = componentMap[tagName];
186
+ * if (C) el = <C {...props}>{children}</C>;
187
+ *
188
+ * Keys mirror `DEFAULT_REGISTRY.list()`.
189
+ *
190
+ * Type note: components vary in their props shape, so the map is
191
+ * typed permissively (`Record<string, ComponentType<any>>`). Each
192
+ * individual export above is still strictly typed.
193
+ */
194
+ declare const componentMap: Record<string, ComponentType<any>>;
195
+ type ComponentMapKey = keyof typeof componentMap;
196
+ //#endregion
197
+ export { Button, type ButtonProps, Card, type CardProps, Chart, type ChartKind, type ChartProps, Code, type CodeProps, ComponentMapKey, Container, type ContainerProps, Heading, type HeadingProps, List, type ListProps, Slider, type SliderProps, type Step, Stepper, type StepperProps, Text, TextField, type TextFieldProps, type TextProps, componentMap };
198
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/Button.tsx","../src/TextField.tsx","../src/Slider.tsx","../src/Chart.tsx","../src/Container.tsx","../src/Code.tsx","../src/Heading.tsx","../src/Text.tsx","../src/Stepper.tsx","../src/Card.tsx","../src/List.tsx","../src/registry.ts"],"mappings":";;;;;;;;;UASiB;;EAEf;;EAEA;;EAEA;;;;;EAKA,UAAU,MAAM,kBAAkB;;iBAGpB,SACd,OACA,SACA,UACA,WACC,cAAc,MAAM,IAAI;;;UCzBV;EACf;EACA;EACA;EACA;;;;;;EAMA,WAAW,MAAM,mBAAmB;;;;;;;iBAQtB,YACd,OACA,OACA,aACA,UACA,YACC,iBAAiB,MAAM,IAAI;;;UCxBb;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;;;;;iBAOc,SAAS,KAAK,KAAK,OAAO,MAAU,SAAS,cAAc,MAAM,IAAI;;;KCjBzE;;;;;;;;;;;UAYK;EACf,MAAM;EACN;EACA;;iBAGc,QAAQ,MAAM,MAAM,SAAS,aAAa,MAAM,IAAI;;;UCnBnD;EACf;EACA;EACA,WAAW,MAAM;;;;;;iBAOH,YAAY,SAAS,KAAK,YAAY,iBAAiB,MAAM,IAAI;;;UCThE;EACf;EACA,WAAW,MAAM;;;;;;;;iBASH,OAAO,UAAU,YAAY,YAAY,MAAM,IAAI;;;UCXlD;;;;;;EAMf;EACA;EACA,WAAW,MAAM;;iBAYH,UAAU,OAAO,OAAO,YAAY,eAAe,MAAM,IAAI;;;UCpB5D;EACf;EACA;EACA;EACA,WAAW,MAAM;;iBAGH,OAAO,QAAmB,MAAM,OAAO,YAAY,YAAY,MAAM,IAAI;;;UCPxE;EACf;EACA;EACA,OAAO,MAAM;;UAGE;EACf,OAAO;;EAEP;;;;;;iBAOc,UAAU,OAAO,WAAW,eAAe,MAAM,IAAI;;;UChBpD;EACf;;;;;EAKA;EACA,WAAW,MAAM;;iBAGH,OAAO,OAAO,WAAe,YAAY,YAAY,MAAM,IAAI;;;UCV9D;;;;;;EAMf;;EAEA;;EAEA,WAAW,MAAM;;;;;;;iBAQH,OAAO,OAAO,SAAS,YAAY,YAAY,MAAM,IAAI;;;;;;;;;;;;;;;;;cC6B5D,cAAc,eAAe;KAc9B,+BAA+B"}
package/dist/index.mjs ADDED
@@ -0,0 +1,638 @@
1
+ import * as React from "react";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ //#region src/theme.ts
4
+ /**
5
+ * Shared theme tokens for @playgenx/components.
6
+ *
7
+ * All styling is driven from this file. There is intentionally no
8
+ * "config" theme or runtime theme provider — these are the default
9
+ * implementations of the registry, and a downstream host app can swap
10
+ * them out entirely. Tokens live as constants so they're stable
11
+ * across renders and don't allocate per call.
12
+ */
13
+ const colors = {
14
+ bg: "#ffffff",
15
+ fg: "#0f172a",
16
+ mutedFg: "#475569",
17
+ border: "#e2e8f0",
18
+ primary: "#2563eb",
19
+ primaryFg: "#ffffff",
20
+ secondaryFg: "#0f172a",
21
+ ghostFg: "#1d4ed8",
22
+ cardBg: "#f8fafc",
23
+ cardBorder: "#e2e8f0",
24
+ codeBg: "#f1f5f9",
25
+ codeFg: "#0f172a",
26
+ sliderTrack: "#cbd5e1",
27
+ sliderFill: "#2563eb",
28
+ sliderThumb: "#1d4ed8",
29
+ bar: "#2563eb",
30
+ barLabel: "#0f172a",
31
+ pie: [
32
+ "#2563eb",
33
+ "#16a34a",
34
+ "#f59e0b",
35
+ "#dc2626"
36
+ ],
37
+ line: "#2563eb",
38
+ stepperPast: "#16a34a",
39
+ stepperCurrent: "#2563eb",
40
+ stepperFuture: "#cbd5e1"
41
+ };
42
+ const space = {
43
+ none: "0",
44
+ xs: "4px",
45
+ sm: "8px",
46
+ md: "12px",
47
+ lg: "16px",
48
+ xl: "24px"
49
+ };
50
+ const radius = {
51
+ sm: "4px",
52
+ md: "6px",
53
+ lg: "8px"
54
+ };
55
+ //#endregion
56
+ //#region src/Button.tsx
57
+ function Button({ label, variant = "primary", disabled = false, onClick }) {
58
+ return /* @__PURE__ */ jsx("button", {
59
+ type: "button",
60
+ disabled,
61
+ onClick,
62
+ style: {
63
+ fontFamily: "inherit",
64
+ fontSize: "14px",
65
+ fontWeight: 500,
66
+ padding: "8px 14px",
67
+ borderRadius: radius.md,
68
+ border: "1px solid transparent",
69
+ cursor: disabled ? "not-allowed" : "pointer",
70
+ opacity: disabled ? .5 : 1,
71
+ background: variant === "primary" ? colors.primary : variant === "secondary" ? colors.secondaryFg : "transparent",
72
+ color: variant === "ghost" ? colors.ghostFg : variant === "secondary" ? colors.bg : colors.primaryFg,
73
+ borderColor: variant === "ghost" ? colors.border : "transparent"
74
+ },
75
+ "data-pgx": "Button",
76
+ children: label
77
+ });
78
+ }
79
+ //#endregion
80
+ //#region src/TextField.tsx
81
+ /**
82
+ * Controlled text input. Without `value`/`onChange`, behaves as
83
+ * uncontrolled (uses its own state via defaultValue). When a stable
84
+ * (deterministic) caller wires both, the input is fully controlled.
85
+ */
86
+ function TextField({ label, value, placeholder, disabled = false, onChange }) {
87
+ const wrapperStyle = {
88
+ display: "flex",
89
+ flexDirection: "column",
90
+ gap: "4px",
91
+ fontFamily: "inherit"
92
+ };
93
+ const labelStyle = {
94
+ fontSize: "12px",
95
+ fontWeight: 500,
96
+ color: colors.mutedFg
97
+ };
98
+ const inputStyle = {
99
+ fontFamily: "inherit",
100
+ fontSize: "14px",
101
+ padding: "8px 10px",
102
+ border: `1px solid ${colors.border}`,
103
+ borderRadius: radius.md,
104
+ background: colors.bg,
105
+ color: colors.fg,
106
+ outline: "none"
107
+ };
108
+ const inputProps = {
109
+ placeholder,
110
+ disabled,
111
+ onChange
112
+ };
113
+ if (value !== void 0) inputProps.value = value;
114
+ else inputProps.defaultValue = "";
115
+ return /* @__PURE__ */ jsxs("label", {
116
+ style: wrapperStyle,
117
+ "data-pgx": "TextField",
118
+ children: [label !== void 0 ? /* @__PURE__ */ jsx("span", {
119
+ style: labelStyle,
120
+ children: label
121
+ }) : null, /* @__PURE__ */ jsx("input", {
122
+ ...inputProps,
123
+ style: inputStyle
124
+ })]
125
+ });
126
+ }
127
+ //#endregion
128
+ //#region src/Slider.tsx
129
+ /**
130
+ * Range input. State: internal `value` mirrors props.value if present
131
+ * (otherwise uncontrolled); clamps to [min, max].
132
+ */
133
+ function Slider({ min, max, value, step = 1, label }) {
134
+ const [internal, setInternal] = React.useState(() => clamp(value ?? min, min, max));
135
+ const controlled = value !== void 0;
136
+ const current = controlled ? clamp(value, min, max) : internal;
137
+ const trackStyle = {
138
+ display: "flex",
139
+ flexDirection: "column",
140
+ gap: "6px",
141
+ fontFamily: "inherit",
142
+ width: "100%"
143
+ };
144
+ const labelStyle = {
145
+ fontSize: "12px",
146
+ color: colors.mutedFg
147
+ };
148
+ const wrapStyle = {
149
+ display: "flex",
150
+ alignItems: "center",
151
+ gap: "10px"
152
+ };
153
+ const inputStyle = {
154
+ flex: 1,
155
+ accentColor: colors.sliderFill
156
+ };
157
+ const valueStyle = {
158
+ minWidth: "32px",
159
+ textAlign: "right",
160
+ fontVariantNumeric: "tabular-nums",
161
+ fontSize: "14px",
162
+ color: colors.fg
163
+ };
164
+ return /* @__PURE__ */ jsxs("div", {
165
+ style: trackStyle,
166
+ "data-pgx": "Slider",
167
+ children: [label !== void 0 ? /* @__PURE__ */ jsx("span", {
168
+ style: labelStyle,
169
+ children: label
170
+ }) : null, /* @__PURE__ */ jsxs("div", {
171
+ style: wrapStyle,
172
+ children: [/* @__PURE__ */ jsx("input", {
173
+ type: "range",
174
+ min,
175
+ max,
176
+ step,
177
+ value: current,
178
+ disabled: min === max,
179
+ "aria-label": label,
180
+ onChange: (e) => {
181
+ const next = Number(e.currentTarget.value);
182
+ if (!controlled) setInternal(next);
183
+ },
184
+ style: inputStyle
185
+ }), /* @__PURE__ */ jsx("span", {
186
+ style: valueStyle,
187
+ children: current
188
+ })]
189
+ })]
190
+ });
191
+ }
192
+ function clamp(n, lo, hi) {
193
+ if (Number.isNaN(n)) return lo;
194
+ return Math.min(hi, Math.max(lo, n));
195
+ }
196
+ //#endregion
197
+ //#region src/Chart.tsx
198
+ function Chart({ kind, data, title }) {
199
+ return /* @__PURE__ */ jsxs("div", {
200
+ "data-pgx": "Chart",
201
+ "data-chart-kind": kind,
202
+ style: { fontFamily: "inherit" },
203
+ children: [title !== void 0 ? /* @__PURE__ */ jsx("div", {
204
+ style: {
205
+ fontSize: "14px",
206
+ fontWeight: 600,
207
+ color: colors.fg,
208
+ marginBottom: "6px"
209
+ },
210
+ children: title
211
+ }) : null, renderChart(kind, data)]
212
+ });
213
+ }
214
+ function renderChart(kind, data) {
215
+ if (kind === "bar") return renderBar(data);
216
+ if (kind === "line") return renderLine(data);
217
+ return renderPie(data);
218
+ }
219
+ function renderBar(data) {
220
+ const parsed = parseLabeled(data);
221
+ if (!parsed) return fallback("bar chart", data);
222
+ const { labels, values } = parsed;
223
+ const max = Math.max(1, ...values);
224
+ const width = 320;
225
+ const height = 160;
226
+ const barWidth = width / Math.max(1, labels.length);
227
+ return /* @__PURE__ */ jsx("svg", {
228
+ width,
229
+ height,
230
+ role: "img",
231
+ "aria-label": "Bar chart",
232
+ style: { display: "block" },
233
+ children: values.map((v, i) => {
234
+ const h = Math.max(0, v) / max * (height - 24);
235
+ return /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("rect", {
236
+ x: i * barWidth + 2,
237
+ y: height - 12 - h,
238
+ width: Math.max(1, barWidth - 4),
239
+ height: h,
240
+ fill: colors.bar,
241
+ rx: 2
242
+ }), /* @__PURE__ */ jsx("text", {
243
+ x: i * barWidth + barWidth / 2,
244
+ y: height - 2,
245
+ fontSize: 10,
246
+ textAnchor: "middle",
247
+ fill: colors.barLabel,
248
+ children: (labels[i] ?? "").slice(0, 8)
249
+ })] }, i);
250
+ })
251
+ });
252
+ }
253
+ function renderLine(data) {
254
+ let points = [];
255
+ if (data && typeof data === "object" && "series" in data) {
256
+ const first = data.series?.[0];
257
+ points = Array.isArray(first?.points) ? first.points : [];
258
+ } else if (data && typeof data === "object" && Array.isArray(data.x) && Array.isArray(data.y)) {
259
+ const xArr = data.x;
260
+ const yArr = data.y;
261
+ points = xArr.map((x, i) => ({
262
+ x,
263
+ y: yArr[i] ?? 0
264
+ }));
265
+ }
266
+ if (points.length === 0) return fallback("line chart", data);
267
+ const xs = points.map((p) => p.x);
268
+ const ys = points.map((p) => p.y);
269
+ const xMin = Math.min(...xs);
270
+ const xMax = Math.max(...xs);
271
+ const yMin = Math.min(...ys);
272
+ const yMax = Math.max(...ys);
273
+ const w = 320;
274
+ const h = 160;
275
+ const sx = (x) => xMax === xMin ? w / 2 : (x - xMin) / (xMax - xMin) * (w - 8) + 4;
276
+ const sy = (y) => yMax === yMin ? h / 2 : h - (y - yMin) / (yMax - yMin) * (h - 24) - 12;
277
+ return /* @__PURE__ */ jsxs("svg", {
278
+ width: w,
279
+ height: h,
280
+ role: "img",
281
+ "aria-label": "Line chart",
282
+ style: { display: "block" },
283
+ children: [/* @__PURE__ */ jsx("path", {
284
+ d: points.map((p, i) => `${i === 0 ? "M" : "L"}${sx(p.x).toFixed(2)},${sy(p.y).toFixed(2)}`).join(" "),
285
+ fill: "none",
286
+ stroke: colors.line,
287
+ strokeWidth: 2
288
+ }), points.map((p, i) => /* @__PURE__ */ jsx("circle", {
289
+ cx: sx(p.x),
290
+ cy: sy(p.y),
291
+ r: 2,
292
+ fill: colors.line
293
+ }, i))]
294
+ });
295
+ }
296
+ function renderPie(data) {
297
+ const parsed = parseLabeled(data);
298
+ if (!parsed) return fallback("pie chart", data);
299
+ const total = parsed.values.reduce((a, b) => a + Math.max(0, b), 0) || 1;
300
+ const cx = 80;
301
+ const cy = 80;
302
+ const r = 60;
303
+ let angle = -Math.PI / 2;
304
+ return /* @__PURE__ */ jsx("svg", {
305
+ width: 160,
306
+ height: 160,
307
+ role: "img",
308
+ "aria-label": "Pie chart",
309
+ style: { display: "block" },
310
+ children: parsed.values.map((v, i) => {
311
+ const slice = Math.max(0, v) / total * Math.PI * 2;
312
+ const x1 = cx + r * Math.cos(angle);
313
+ const y1 = cy + r * Math.sin(angle);
314
+ const x2 = cx + r * Math.cos(angle + slice);
315
+ const y2 = cy + r * Math.sin(angle + slice);
316
+ const large = slice > Math.PI ? 1 : 0;
317
+ const path = slice >= Math.PI * 2 - 1e-6 ? `M ${cx - r} ${cy} A ${r} ${r} 0 1 1 140 ${cy} A ${r} ${r} 0 1 1 ${cx - r} ${cy}` : `M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 ${large} 1 ${x2} ${y2} Z`;
318
+ angle += slice;
319
+ return /* @__PURE__ */ jsx("path", {
320
+ d: path,
321
+ fill: colors.pie[i % colors.pie.length] ?? colors.bar
322
+ }, i);
323
+ })
324
+ });
325
+ }
326
+ function parseLabeled(data) {
327
+ if (!data || typeof data !== "object") return null;
328
+ const labels = data.labels;
329
+ const values = data.values;
330
+ if (!Array.isArray(labels) || !Array.isArray(values)) return null;
331
+ if (labels.length !== values.length) return null;
332
+ if (!labels.every((l) => typeof l === "string" || typeof l === "number")) return null;
333
+ if (!values.every((v) => typeof v === "number" || typeof v === "string")) return null;
334
+ return {
335
+ labels: labels.map(String),
336
+ values: values.map((v) => typeof v === "number" ? v : Number(v))
337
+ };
338
+ }
339
+ function fallback(label, data) {
340
+ return /* @__PURE__ */ jsxs("pre", {
341
+ style: {
342
+ margin: 0,
343
+ fontSize: "12px",
344
+ background: colors.codeBg,
345
+ color: colors.codeFg,
346
+ padding: "8px",
347
+ borderRadius: "4px",
348
+ overflow: "auto"
349
+ },
350
+ children: [
351
+ label,
352
+ " data: ",
353
+ JSON.stringify(data, null, 2)
354
+ ]
355
+ });
356
+ }
357
+ //#endregion
358
+ //#region src/Container.tsx
359
+ /**
360
+ * Layout wrapper. Defaults to a vertical flex container with 16px
361
+ * padding and 12px gap when callers omit props.
362
+ */
363
+ function Container({ padding, gap, children }) {
364
+ return /* @__PURE__ */ jsx("div", {
365
+ style: {
366
+ display: "flex",
367
+ flexDirection: "column",
368
+ padding: padding ?? "16px",
369
+ gap: gap ?? "12px",
370
+ fontFamily: "inherit",
371
+ color: "inherit",
372
+ boxSizing: "border-box"
373
+ },
374
+ "data-pgx": "Container",
375
+ children
376
+ });
377
+ }
378
+ //#endregion
379
+ //#region src/Code.tsx
380
+ /**
381
+ * Inline code formatter. Renders children as a `<code>` element inside
382
+ * a styled wrapper. If `children` is a single string, it displays
383
+ * verbatim; for multi-line content we fall back to a `<pre>`-styled
384
+ * block.
385
+ */
386
+ function Code({ language, children }) {
387
+ if (typeof children === "string" && children.includes("\n")) return /* @__PURE__ */ jsx("pre", {
388
+ "data-pgx": "Code",
389
+ "data-language": language ?? "text",
390
+ style: {
391
+ background: colors.codeBg,
392
+ color: colors.codeFg,
393
+ padding: "12px",
394
+ borderRadius: radius.md,
395
+ fontSize: "12px",
396
+ overflow: "auto",
397
+ margin: 0
398
+ },
399
+ children: /* @__PURE__ */ jsx("code", { children })
400
+ });
401
+ return /* @__PURE__ */ jsx("code", {
402
+ "data-pgx": "Code-inline",
403
+ "data-language": language ?? "text",
404
+ style: {
405
+ background: colors.codeBg,
406
+ color: colors.codeFg,
407
+ padding: "2px 6px",
408
+ borderRadius: radius.sm,
409
+ fontSize: "0.9em"
410
+ },
411
+ children
412
+ });
413
+ }
414
+ //#endregion
415
+ //#region src/Heading.tsx
416
+ const sizes = {
417
+ 1: "24px",
418
+ 2: "20px",
419
+ 3: "18px",
420
+ 4: "16px",
421
+ 5: "14px",
422
+ 6: "13px"
423
+ };
424
+ function Heading({ level, color, children }) {
425
+ const safeLevel = clampLevel(level);
426
+ const style = {
427
+ fontFamily: "inherit",
428
+ fontSize: sizes[safeLevel] ?? sizes[2],
429
+ fontWeight: 700,
430
+ color: color ?? colors.fg,
431
+ margin: 0,
432
+ lineHeight: 1.3
433
+ };
434
+ return React.createElement(`h${safeLevel}`, {
435
+ style,
436
+ "data-pgx": `Heading`
437
+ }, children);
438
+ }
439
+ function clampLevel(level) {
440
+ if (typeof level !== "number" || !Number.isFinite(level)) return 2;
441
+ const i = Math.floor(level);
442
+ if (i < 1) return 1;
443
+ if (i > 6) return 6;
444
+ return i;
445
+ }
446
+ //#endregion
447
+ //#region src/Text.tsx
448
+ function Text({ weight = "normal", size, color, children }) {
449
+ return /* @__PURE__ */ jsx("p", {
450
+ style: {
451
+ fontFamily: "inherit",
452
+ fontSize: size ?? "14px",
453
+ fontWeight: weight === "bold" ? 600 : 400,
454
+ color: color ?? colors.fg,
455
+ margin: 0,
456
+ lineHeight: 1.5
457
+ },
458
+ "data-pgx": "Text",
459
+ children
460
+ });
461
+ }
462
+ //#endregion
463
+ //#region src/Stepper.tsx
464
+ /**
465
+ * Multi-step reveal. State: the active index. Previous steps can be
466
+ * revisited; future steps are disabled until reached.
467
+ */
468
+ function Stepper({ steps, initial }) {
469
+ const initialIdx = clampIndex(initial ?? 0, steps.length);
470
+ const [active, setActive] = React.useState(initialIdx);
471
+ const wrapStyle = {
472
+ fontFamily: "inherit",
473
+ display: "flex",
474
+ flexDirection: "column",
475
+ gap: "12px"
476
+ };
477
+ const listStyle = {
478
+ display: "flex",
479
+ gap: "6px",
480
+ listStyle: "none",
481
+ padding: 0,
482
+ margin: 0
483
+ };
484
+ const stepBtnBase = {
485
+ width: "28px",
486
+ height: "28px",
487
+ borderRadius: "50%",
488
+ display: "inline-flex",
489
+ alignItems: "center",
490
+ justifyContent: "center",
491
+ fontFamily: "inherit",
492
+ fontSize: "12px",
493
+ fontWeight: 600,
494
+ border: "1px solid transparent"
495
+ };
496
+ const bodyStyle = {
497
+ border: `1px solid ${colors.border}`,
498
+ borderRadius: "6px",
499
+ padding: "10px",
500
+ background: colors.bg,
501
+ color: colors.fg
502
+ };
503
+ return /* @__PURE__ */ jsxs("div", {
504
+ "data-pgx": "Stepper",
505
+ style: wrapStyle,
506
+ children: [/* @__PURE__ */ jsx("ol", {
507
+ style: listStyle,
508
+ children: steps.map((s, i) => {
509
+ const isPast = i < active;
510
+ const isCurrent = i === active;
511
+ const future = i > active;
512
+ const stepStyle = {
513
+ ...stepBtnBase,
514
+ background: isCurrent ? colors.stepperCurrent : isPast ? colors.stepperPast : colors.stepperFuture,
515
+ color: isCurrent || isPast ? "#fff" : colors.fg,
516
+ opacity: future ? .6 : 1,
517
+ cursor: future ? "not-allowed" : "pointer"
518
+ };
519
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("button", {
520
+ type: "button",
521
+ "aria-label": `Step ${i + 1}: ${s.title}`,
522
+ "aria-current": isCurrent ? "step" : void 0,
523
+ disabled: future,
524
+ onClick: () => setActive(i),
525
+ style: stepStyle,
526
+ children: i + 1
527
+ }) }, s.id);
528
+ })
529
+ }), /* @__PURE__ */ jsxs("div", {
530
+ style: bodyStyle,
531
+ children: [/* @__PURE__ */ jsx("div", {
532
+ style: {
533
+ fontWeight: 600,
534
+ marginBottom: "4px",
535
+ fontSize: "14px"
536
+ },
537
+ children: steps[active]?.title ?? ""
538
+ }), /* @__PURE__ */ jsx("div", {
539
+ style: { fontSize: "13px" },
540
+ children: steps[active]?.body ?? null
541
+ })]
542
+ })]
543
+ });
544
+ }
545
+ function clampIndex(n, len) {
546
+ if (len === 0) return 0;
547
+ if (!Number.isFinite(n)) return 0;
548
+ return Math.min(len - 1, Math.max(0, Math.floor(n)));
549
+ }
550
+ //#endregion
551
+ //#region src/Card.tsx
552
+ function Card({ title, elevation = 1, children }) {
553
+ const shadow = elevation >= 3 ? "0 4px 12px rgba(15, 23, 42, 0.18)" : elevation === 2 ? "0 2px 8px rgba(15, 23, 42, 0.12)" : elevation === 1 ? "0 1px 2px rgba(15, 23, 42, 0.06)" : "none";
554
+ return /* @__PURE__ */ jsxs("section", {
555
+ "data-pgx": "Card",
556
+ style: {
557
+ background: colors.cardBg,
558
+ border: `1px solid ${colors.cardBorder}`,
559
+ borderRadius: radius.md,
560
+ boxShadow: shadow,
561
+ padding: space.md,
562
+ fontFamily: "inherit",
563
+ color: colors.fg,
564
+ display: "flex",
565
+ flexDirection: "column",
566
+ gap: space.sm
567
+ },
568
+ children: [title !== void 0 ? /* @__PURE__ */ jsx("h3", {
569
+ style: {
570
+ fontSize: "14px",
571
+ fontWeight: 600,
572
+ margin: 0
573
+ },
574
+ children: title
575
+ }) : null, children]
576
+ });
577
+ }
578
+ //#endregion
579
+ //#region src/List.tsx
580
+ /**
581
+ * List of items. Renders `items` as a list of strings/numbers (the
582
+ * common artifact prompt output). If `children` are passed they take
583
+ * precedence over `items`.
584
+ */
585
+ function List({ items, ordered, children }) {
586
+ const style = {
587
+ margin: 0,
588
+ paddingLeft: "20px",
589
+ fontFamily: "inherit",
590
+ color: colors.fg,
591
+ fontSize: "14px",
592
+ lineHeight: 1.6
593
+ };
594
+ if (children !== void 0 && children !== null) return React.createElement(ordered ? "ol" : "ul", {
595
+ style,
596
+ "data-pgx": "List"
597
+ }, children);
598
+ const arr = Array.isArray(items) ? items : items === void 0 ? [] : [items];
599
+ return React.createElement(ordered ? "ol" : "ul", {
600
+ style,
601
+ "data-pgx": "List"
602
+ }, arr.map((item, i) => {
603
+ return /* @__PURE__ */ jsx("li", { children: typeof item === "string" || typeof item === "number" ? String(item) : JSON.stringify(item) }, i);
604
+ }));
605
+ }
606
+ //#endregion
607
+ //#region src/registry.ts
608
+ /**
609
+ * Map of PascalCase component name to React component. Use this when
610
+ * you have a renderer that walks an AST and needs to pick an
611
+ * implementation at runtime:
612
+ *
613
+ * const C = componentMap[tagName];
614
+ * if (C) el = <C {...props}>{children}</C>;
615
+ *
616
+ * Keys mirror `DEFAULT_REGISTRY.list()`.
617
+ *
618
+ * Type note: components vary in their props shape, so the map is
619
+ * typed permissively (`Record<string, ComponentType<any>>`). Each
620
+ * individual export above is still strictly typed.
621
+ */
622
+ const componentMap = {
623
+ Button,
624
+ TextField,
625
+ Slider,
626
+ Chart,
627
+ Container,
628
+ Code,
629
+ Heading,
630
+ Text,
631
+ Stepper,
632
+ Card,
633
+ List
634
+ };
635
+ //#endregion
636
+ export { Button, Card, Chart, Code, Container, Heading, List, Slider, Stepper, Text, TextField, componentMap };
637
+
638
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/theme.ts","../src/Button.tsx","../src/TextField.tsx","../src/Slider.tsx","../src/Chart.tsx","../src/Container.tsx","../src/Code.tsx","../src/Heading.tsx","../src/Text.tsx","../src/Stepper.tsx","../src/Card.tsx","../src/List.tsx","../src/registry.ts"],"sourcesContent":["/**\n * Shared theme tokens for @playgenx/components.\n *\n * All styling is driven from this file. There is intentionally no\n * \"config\" theme or runtime theme provider — these are the default\n * implementations of the registry, and a downstream host app can swap\n * them out entirely. Tokens live as constants so they're stable\n * across renders and don't allocate per call.\n */\n\nexport const colors = {\n bg: '#ffffff',\n fg: '#0f172a',\n mutedFg: '#475569',\n border: '#e2e8f0',\n primary: '#2563eb',\n primaryFg: '#ffffff',\n secondaryFg: '#0f172a',\n ghostFg: '#1d4ed8',\n cardBg: '#f8fafc',\n cardBorder: '#e2e8f0',\n codeBg: '#f1f5f9',\n codeFg: '#0f172a',\n sliderTrack: '#cbd5e1',\n sliderFill: '#2563eb',\n sliderThumb: '#1d4ed8',\n bar: '#2563eb',\n barLabel: '#0f172a',\n pie: ['#2563eb', '#16a34a', '#f59e0b', '#dc2626'],\n line: '#2563eb',\n stepperPast: '#16a34a',\n stepperCurrent: '#2563eb',\n stepperFuture: '#cbd5e1',\n} as const;\n\nexport const space = {\n none: '0',\n xs: '4px',\n sm: '8px',\n md: '12px',\n lg: '16px',\n xl: '24px',\n} as const;\n\nexport const radius = {\n sm: '4px',\n md: '6px',\n lg: '8px',\n} as const;\n\n/**\n * Common React-friendly prop accepts for content. Components that\n * accept children of arbitrary shape (Heading, Text, Card, Container,\n * ...) use this so the host can pass strings or JSX interchangeably.\n */\nexport type Children = string | number | React.ReactNode;\n\nimport type * as React from 'react';\n","import * as React from 'react';\nimport { colors, radius } from './theme.js';\n\n/**\n * Headless-style wrapper over `<button>` accepting the props defined in\n * `DEFAULT_COMPONENT_SCHEMAS.Button`. Pass `onClick` through; this\n * implementation does NOT execute arbitrary functions (deterministic\n * renderer constraint) so the click handler is rendered inert at mount.\n */\nexport interface ButtonProps {\n /** Visible text. Required. */\n label: string;\n /** Variant. Defaults to 'primary'. */\n variant?: 'primary' | 'secondary' | 'ghost';\n /** Disabled state. Defaults to false. */\n disabled?: boolean;\n /**\n * Optional click handler. The default impl forwards to onClick if\n * present; in a deterministic renderer pass `noEvents` instead.\n */\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n}\n\nexport function Button({\n label,\n variant = 'primary',\n disabled = false,\n onClick,\n}: ButtonProps): React.JSX.Element {\n const styles: React.CSSProperties = {\n fontFamily: 'inherit',\n fontSize: '14px',\n fontWeight: 500,\n padding: '8px 14px',\n borderRadius: radius.md,\n border: '1px solid transparent',\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n background:\n variant === 'primary'\n ? colors.primary\n : variant === 'secondary'\n ? colors.secondaryFg\n : 'transparent',\n color:\n variant === 'ghost' ? colors.ghostFg : variant === 'secondary' ? colors.bg : colors.primaryFg,\n borderColor: variant === 'ghost' ? colors.border : 'transparent',\n };\n return (\n <button type=\"button\" disabled={disabled} onClick={onClick} style={styles} data-pgx=\"Button\">\n {label}\n </button>\n );\n}\n","import * as React from 'react';\nimport { colors, radius } from './theme.js';\n\nexport interface TextFieldProps {\n label?: string;\n value?: string;\n placeholder?: string;\n disabled?: boolean;\n /**\n * onChange is reported as `node` in the schema (it must be a\n * function reference, which the validator cannot statically type).\n * We forward to React's controlled input handler.\n */\n onChange?: React.ChangeEventHandler<HTMLInputElement>;\n}\n\n/**\n * Controlled text input. Without `value`/`onChange`, behaves as\n * uncontrolled (uses its own state via defaultValue). When a stable\n * (deterministic) caller wires both, the input is fully controlled.\n */\nexport function TextField({\n label,\n value,\n placeholder,\n disabled = false,\n onChange,\n}: TextFieldProps): React.JSX.Element {\n const wrapperStyle: React.CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: '4px',\n fontFamily: 'inherit',\n };\n const labelStyle: React.CSSProperties = {\n fontSize: '12px',\n fontWeight: 500,\n color: colors.mutedFg,\n };\n const inputStyle: React.CSSProperties = {\n fontFamily: 'inherit',\n fontSize: '14px',\n padding: '8px 10px',\n border: `1px solid ${colors.border}`,\n borderRadius: radius.md,\n background: colors.bg,\n color: colors.fg,\n outline: 'none',\n };\n const inputProps: React.InputHTMLAttributes<HTMLInputElement> = {\n placeholder,\n disabled,\n onChange,\n };\n // Use uncontrolled defaultValue when caller omits value. We can't\n // set defaultValue AND value without React warning, so branch.\n if (value !== undefined) inputProps.value = value;\n else inputProps.defaultValue = '';\n return (\n <label style={wrapperStyle} data-pgx=\"TextField\">\n {label !== undefined ? <span style={labelStyle}>{label}</span> : null}\n <input {...inputProps} style={inputStyle} />\n </label>\n );\n}\n","import * as React from 'react';\nimport { colors } from './theme.js';\n\nexport interface SliderProps {\n /** Lower bound, inclusive. Required. */\n min: number;\n /** Upper bound, inclusive. Required. */\n max: number;\n /** Initial / controlled value. */\n value?: number;\n /** Increment between stops. Defaults to 1. */\n step?: number;\n /** Optional caption rendered above the slider. */\n label?: string;\n}\n\n/**\n * Range input. State: internal `value` mirrors props.value if present\n * (otherwise uncontrolled); clamps to [min, max].\n */\nexport function Slider({ min, max, value, step = 1, label }: SliderProps): React.JSX.Element {\n // Controlled vs uncontrolled: React forbids both at once. Branch.\n const [internal, setInternal] = React.useState(() => clamp(value ?? min, min, max));\n const controlled = value !== undefined;\n const current = controlled ? clamp(value, min, max) : internal;\n const trackStyle: React.CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: '6px',\n fontFamily: 'inherit',\n width: '100%',\n };\n const labelStyle: React.CSSProperties = {\n fontSize: '12px',\n color: colors.mutedFg,\n };\n const wrapStyle: React.CSSProperties = { display: 'flex', alignItems: 'center', gap: '10px' };\n const inputStyle: React.CSSProperties = { flex: 1, accentColor: colors.sliderFill };\n const valueStyle: React.CSSProperties = {\n minWidth: '32px',\n textAlign: 'right',\n fontVariantNumeric: 'tabular-nums',\n fontSize: '14px',\n color: colors.fg,\n };\n return (\n <div style={trackStyle} data-pgx=\"Slider\">\n {label !== undefined ? <span style={labelStyle}>{label}</span> : null}\n <div style={wrapStyle}>\n <input\n type=\"range\"\n min={min}\n max={max}\n step={step}\n value={current}\n disabled={min === max}\n aria-label={label}\n onChange={(e) => {\n const next = Number(e.currentTarget.value);\n if (!controlled) setInternal(next);\n }}\n style={inputStyle}\n />\n <span style={valueStyle}>{current}</span>\n </div>\n </div>\n );\n}\n\nfunction clamp(n: number, lo: number, hi: number): number {\n if (Number.isNaN(n)) return lo;\n return Math.min(hi, Math.max(lo, n));\n}\n","import * as React from 'react';\nimport { colors } from './theme.js';\n\nexport type ChartKind = 'bar' | 'line' | 'pie';\n\n/**\n * The schema lets `data` be any ReactNode, but in practice callers\n * pass JSON-shaped arrays. We narrow at runtime:\n *\n * - bar: `{ labels: string[], values: number[] }`\n * - line: `{ x: number[], y: number[] }` or `{ series: { label, points: {x,y} }[] }`\n * - pie: `{ labels: string[], values: number[] }`\n *\n * Anything that doesn't fit is rendered as a `<pre>` fallback.\n */\nexport interface ChartProps {\n kind: ChartKind;\n data: unknown;\n title?: string;\n}\n\nexport function Chart({ kind, data, title }: ChartProps): React.JSX.Element {\n return (\n <div data-pgx=\"Chart\" data-chart-kind={kind} style={{ fontFamily: 'inherit' }}>\n {title !== undefined ? (\n <div style={{ fontSize: '14px', fontWeight: 600, color: colors.fg, marginBottom: '6px' }}>\n {title}\n </div>\n ) : null}\n {renderChart(kind, data)}\n </div>\n );\n}\n\nfunction renderChart(kind: ChartKind, data: unknown): React.JSX.Element {\n if (kind === 'bar') return renderBar(data);\n if (kind === 'line') return renderLine(data);\n return renderPie(data);\n}\n\nfunction renderBar(data: unknown): React.JSX.Element {\n const parsed = parseLabeled(data);\n if (!parsed) return fallback('bar chart', data);\n const { labels, values } = parsed;\n const max = Math.max(1, ...values);\n const width = 320;\n const height = 160;\n const barWidth = width / Math.max(1, labels.length);\n return (\n <svg\n width={width}\n height={height}\n role=\"img\"\n aria-label=\"Bar chart\"\n style={{ display: 'block' }}\n >\n {values.map((v, i) => {\n const h = (Math.max(0, v) / max) * (height - 24);\n return (\n <g key={i}>\n <rect\n x={i * barWidth + 2}\n y={height - 12 - h}\n width={Math.max(1, barWidth - 4)}\n height={h}\n fill={colors.bar}\n rx={2}\n />\n <text\n x={i * barWidth + barWidth / 2}\n y={height - 2}\n fontSize={10}\n textAnchor=\"middle\"\n fill={colors.barLabel}\n >\n {(labels[i] ?? '').slice(0, 8)}\n </text>\n </g>\n );\n })}\n </svg>\n );\n}\n\nfunction renderLine(data: unknown): React.JSX.Element {\n // Two accepted shapes; pick whichever parses cleanly.\n let points: Array<{ x: number; y: number }> = [];\n if (data && typeof data === 'object' && 'series' in (data as Record<string, unknown>)) {\n const series = (data as { series: Array<{ points?: Array<{ x: number; y: number }> }> }).series;\n const first = series?.[0];\n points = Array.isArray(first?.points) ? first.points : [];\n } else if (\n data &&\n typeof data === 'object' &&\n Array.isArray((data as { x?: unknown }).x) &&\n Array.isArray((data as { y?: unknown }).y)\n ) {\n const xArr = (data as { x: number[] }).x;\n const yArr = (data as { y: number[] }).y;\n points = xArr.map((x, i) => ({ x, y: yArr[i] ?? 0 }));\n }\n if (points.length === 0) return fallback('line chart', data);\n const xs = points.map((p) => p.x);\n const ys = points.map((p) => p.y);\n const xMin = Math.min(...xs);\n const xMax = Math.max(...xs);\n const yMin = Math.min(...ys);\n const yMax = Math.max(...ys);\n const w = 320;\n const h = 160;\n const sx = (x: number) => (xMax === xMin ? w / 2 : ((x - xMin) / (xMax - xMin)) * (w - 8) + 4);\n const sy = (y: number) =>\n yMax === yMin ? h / 2 : h - ((y - yMin) / (yMax - yMin)) * (h - 24) - 12;\n const path = points\n .map((p, i) => `${i === 0 ? 'M' : 'L'}${sx(p.x).toFixed(2)},${sy(p.y).toFixed(2)}`)\n .join(' ');\n return (\n <svg width={w} height={h} role=\"img\" aria-label=\"Line chart\" style={{ display: 'block' }}>\n <path d={path} fill=\"none\" stroke={colors.line} strokeWidth={2} />\n {points.map((p, i) => (\n <circle key={i} cx={sx(p.x)} cy={sy(p.y)} r={2} fill={colors.line} />\n ))}\n </svg>\n );\n}\n\nfunction renderPie(data: unknown): React.JSX.Element {\n const parsed = parseLabeled(data);\n if (!parsed) return fallback('pie chart', data);\n const total = parsed.values.reduce((a, b) => a + Math.max(0, b), 0) || 1;\n const cx = 80;\n const cy = 80;\n const r = 60;\n let angle = -Math.PI / 2;\n return (\n <svg width={160} height={160} role=\"img\" aria-label=\"Pie chart\" style={{ display: 'block' }}>\n {parsed.values.map((v, i) => {\n const slice = (Math.max(0, v) / total) * Math.PI * 2;\n const x1 = cx + r * Math.cos(angle);\n const y1 = cy + r * Math.sin(angle);\n const x2 = cx + r * Math.cos(angle + slice);\n const y2 = cy + r * Math.sin(angle + slice);\n const large = slice > Math.PI ? 1 : 0;\n const path =\n slice >= Math.PI * 2 - 1e-6\n ? `M ${cx - r} ${cy} A ${r} ${r} 0 1 1 ${cx + r} ${cy} A ${r} ${r} 0 1 1 ${cx - r} ${cy}`\n : `M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 ${large} 1 ${x2} ${y2} Z`;\n angle += slice;\n const fill = colors.pie[i % colors.pie.length] ?? colors.bar;\n return <path key={i} d={path} fill={fill} />;\n })}\n </svg>\n );\n}\n\nfunction parseLabeled(data: unknown): { labels: string[]; values: number[] } | null {\n if (!data || typeof data !== 'object') return null;\n const labels = (data as { labels?: unknown }).labels;\n const values = (data as { values?: unknown }).values;\n if (!Array.isArray(labels) || !Array.isArray(values)) return null;\n if (labels.length !== values.length) return null;\n if (!labels.every((l) => typeof l === 'string' || typeof l === 'number')) return null;\n if (!values.every((v) => typeof v === 'number' || typeof v === 'string')) return null;\n return {\n labels: labels.map(String),\n values: values.map((v) => (typeof v === 'number' ? v : Number(v))),\n };\n}\n\nfunction fallback(label: string, data: unknown): React.JSX.Element {\n return (\n <pre\n style={{\n margin: 0,\n fontSize: '12px',\n background: colors.codeBg,\n color: colors.codeFg,\n padding: '8px',\n borderRadius: '4px',\n overflow: 'auto',\n }}\n >\n {label} data: {JSON.stringify(data, null, 2)}\n </pre>\n );\n}\n","import * as React from 'react';\n\nexport interface ContainerProps {\n padding?: string;\n gap?: string;\n children?: React.ReactNode;\n}\n\n/**\n * Layout wrapper. Defaults to a vertical flex container with 16px\n * padding and 12px gap when callers omit props.\n */\nexport function Container({ padding, gap, children }: ContainerProps): React.JSX.Element {\n const style: React.CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n padding: padding ?? '16px',\n gap: gap ?? '12px',\n fontFamily: 'inherit',\n color: 'inherit',\n boxSizing: 'border-box',\n };\n return (\n <div style={style} data-pgx=\"Container\">\n {children}\n </div>\n );\n}\n","import * as React from 'react';\nimport { colors, radius } from './theme.js';\n\nexport interface CodeProps {\n language?: string;\n children?: React.ReactNode;\n}\n\n/**\n * Inline code formatter. Renders children as a `<code>` element inside\n * a styled wrapper. If `children` is a single string, it displays\n * verbatim; for multi-line content we fall back to a `<pre>`-styled\n * block.\n */\nexport function Code({ language, children }: CodeProps): React.JSX.Element {\n const isString = typeof children === 'string';\n const isMulti = isString && (children as string).includes('\\n');\n if (isMulti) {\n return (\n <pre\n data-pgx=\"Code\"\n data-language={language ?? 'text'}\n style={{\n background: colors.codeBg,\n color: colors.codeFg,\n padding: '12px',\n borderRadius: radius.md,\n fontSize: '12px',\n overflow: 'auto',\n margin: 0,\n }}\n >\n <code>{children}</code>\n </pre>\n );\n }\n return (\n <code\n data-pgx=\"Code-inline\"\n data-language={language ?? 'text'}\n style={{\n background: colors.codeBg,\n color: colors.codeFg,\n padding: '2px 6px',\n borderRadius: radius.sm,\n fontSize: '0.9em',\n }}\n >\n {children}\n </code>\n );\n}\n","import * as React from 'react';\nimport { colors } from './theme.js';\n\nexport interface HeadingProps {\n /**\n * Heading level (1..6). Out-of-range or undefined falls back to 2.\n * The renderer should never see an `Undefined` value here unless the\n * schema validator said optional props can be omitted.\n */\n level?: number;\n color?: string;\n children?: React.ReactNode;\n}\n\nconst sizes: Record<number, string> = {\n 1: '24px',\n 2: '20px',\n 3: '18px',\n 4: '16px',\n 5: '14px',\n 6: '13px',\n};\n\nexport function Heading({ level, color, children }: HeadingProps): React.JSX.Element {\n const safeLevel = clampLevel(level);\n const size = sizes[safeLevel] ?? sizes[2]!;\n const style: React.CSSProperties = {\n fontFamily: 'inherit',\n fontSize: size,\n fontWeight: 700,\n color: color ?? colors.fg,\n margin: 0,\n lineHeight: 1.3,\n };\n // Render an element corresponding to the level. React enforces\n // TagName = 'h1' | 'h2' ... via JSX, so we switch dynamically via\n // createElement.\n return React.createElement(`h${safeLevel}`, { style, 'data-pgx': `Heading` }, children);\n}\n\nfunction clampLevel(level: number | undefined): 1 | 2 | 3 | 4 | 5 | 6 {\n if (typeof level !== 'number' || !Number.isFinite(level)) return 2;\n const i = Math.floor(level);\n if (i < 1) return 1;\n if (i > 6) return 6;\n return i as 1 | 2 | 3 | 4 | 5 | 6;\n}\n","import * as React from 'react';\nimport { colors } from './theme.js';\n\nexport interface TextProps {\n weight?: 'normal' | 'bold';\n size?: string;\n color?: string;\n children?: React.ReactNode;\n}\n\nexport function Text({ weight = 'normal', size, color, children }: TextProps): React.JSX.Element {\n const style: React.CSSProperties = {\n fontFamily: 'inherit',\n fontSize: size ?? '14px',\n fontWeight: weight === 'bold' ? 600 : 400,\n color: color ?? colors.fg,\n margin: 0,\n lineHeight: 1.5,\n };\n return (\n <p style={style} data-pgx=\"Text\">\n {children}\n </p>\n );\n}\n","import * as React from 'react';\nimport { colors } from './theme.js';\n\nexport interface Step {\n id: string;\n title: string;\n body?: React.ReactNode;\n}\n\nexport interface StepperProps {\n steps: Step[];\n /** 0-indexed initial step. Out-of-range falls back to 0. */\n initial?: number;\n}\n\n/**\n * Multi-step reveal. State: the active index. Previous steps can be\n * revisited; future steps are disabled until reached.\n */\nexport function Stepper({ steps, initial }: StepperProps): React.JSX.Element {\n const initialIdx = clampIndex(initial ?? 0, steps.length);\n const [active, setActive] = React.useState(initialIdx);\n const wrapStyle: React.CSSProperties = {\n fontFamily: 'inherit',\n display: 'flex',\n flexDirection: 'column',\n gap: '12px',\n };\n const listStyle: React.CSSProperties = {\n display: 'flex',\n gap: '6px',\n listStyle: 'none',\n padding: 0,\n margin: 0,\n };\n const stepBtnBase: React.CSSProperties = {\n width: '28px',\n height: '28px',\n borderRadius: '50%',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontFamily: 'inherit',\n fontSize: '12px',\n fontWeight: 600,\n border: '1px solid transparent',\n };\n const bodyStyle: React.CSSProperties = {\n border: `1px solid ${colors.border}`,\n borderRadius: '6px',\n padding: '10px',\n background: colors.bg,\n color: colors.fg,\n };\n return (\n <div data-pgx=\"Stepper\" style={wrapStyle}>\n <ol style={listStyle}>\n {steps.map((s, i) => {\n const isPast = i < active;\n const isCurrent = i === active;\n const future = i > active;\n const stepStyle: React.CSSProperties = {\n ...stepBtnBase,\n background: isCurrent\n ? colors.stepperCurrent\n : isPast\n ? colors.stepperPast\n : colors.stepperFuture,\n color: isCurrent || isPast ? '#fff' : colors.fg,\n opacity: future ? 0.6 : 1,\n cursor: future ? 'not-allowed' : 'pointer',\n };\n return (\n <li key={s.id}>\n <button\n type=\"button\"\n aria-label={`Step ${i + 1}: ${s.title}`}\n aria-current={isCurrent ? 'step' : undefined}\n disabled={future}\n onClick={() => setActive(i)}\n style={stepStyle}\n >\n {i + 1}\n </button>\n </li>\n );\n })}\n </ol>\n <div style={bodyStyle}>\n <div style={{ fontWeight: 600, marginBottom: '4px', fontSize: '14px' }}>\n {steps[active]?.title ?? ''}\n </div>\n <div style={{ fontSize: '13px' }}>{steps[active]?.body ?? null}</div>\n </div>\n </div>\n );\n}\n\nfunction clampIndex(n: number, len: number): number {\n if (len === 0) return 0;\n if (!Number.isFinite(n)) return 0;\n return Math.min(len - 1, Math.max(0, Math.floor(n)));\n}\n","import * as React from 'react';\nimport { colors, radius, space } from './theme.js';\n\nexport interface CardProps {\n title?: string;\n /**\n * Visual elevation. 0 = flat (border only), 1+ = heavier shadow.\n * Defaults to 1.\n */\n elevation?: number;\n children?: React.ReactNode;\n}\n\nexport function Card({ title, elevation = 1, children }: CardProps): React.JSX.Element {\n const shadow =\n elevation >= 3\n ? '0 4px 12px rgba(15, 23, 42, 0.18)'\n : elevation === 2\n ? '0 2px 8px rgba(15, 23, 42, 0.12)'\n : elevation === 1\n ? '0 1px 2px rgba(15, 23, 42, 0.06)'\n : 'none';\n const cardStyle: React.CSSProperties = {\n background: colors.cardBg,\n border: `1px solid ${colors.cardBorder}`,\n borderRadius: radius.md,\n boxShadow: shadow,\n padding: space.md,\n fontFamily: 'inherit',\n color: colors.fg,\n display: 'flex',\n flexDirection: 'column',\n gap: space.sm,\n };\n const titleStyle: React.CSSProperties = {\n fontSize: '14px',\n fontWeight: 600,\n margin: 0,\n };\n return (\n <section data-pgx=\"Card\" style={cardStyle}>\n {title !== undefined ? <h3 style={titleStyle}>{title}</h3> : null}\n {children}\n </section>\n );\n}\n","import * as React from 'react';\nimport { colors } from './theme.js';\n\nexport interface ListProps {\n /**\n * Items to render. Schema marks this as `node`; in practice callers\n * pass arrays of strings/numbers/ReactNodes. Anything else is\n * rendered as a single bullet containing the value.\n */\n items?: unknown;\n /** When true, renders as `<ol>` instead of `<ul>`. */\n ordered?: boolean;\n /** Override the wrapper element for full control. */\n children?: React.ReactNode;\n}\n\n/**\n * List of items. Renders `items` as a list of strings/numbers (the\n * common artifact prompt output). If `children` are passed they take\n * precedence over `items`.\n */\nexport function List({ items, ordered, children }: ListProps): React.JSX.Element {\n const style: React.CSSProperties = {\n margin: 0,\n paddingLeft: '20px',\n fontFamily: 'inherit',\n color: colors.fg,\n fontSize: '14px',\n lineHeight: 1.6,\n };\n if (children !== undefined && children !== null) {\n return React.createElement(ordered ? 'ol' : 'ul', { style, 'data-pgx': 'List' }, children);\n }\n const arr = Array.isArray(items) ? items : items === undefined ? [] : [items];\n return React.createElement(\n ordered ? 'ol' : 'ul',\n { style, 'data-pgx': 'List' },\n arr.map((item, i) => {\n const node: React.ReactNode =\n typeof item === 'string' || typeof item === 'number' ? String(item) : JSON.stringify(item);\n return <li key={i}>{node}</li>;\n }),\n );\n}\n","/**\n * Default @playgenx/components barrel.\n *\n * Re-exports every component named in `DEFAULT_REGISTRY` and a\n * `componentMap` keyed by PascalCase component name, so render-time\n * code can do `ComponentMap[tagName](props)`.\n *\n * @packageDocumentation\n */\n\nexport { Button, type ButtonProps } from './Button.js';\nexport { TextField, type TextFieldProps } from './TextField.js';\nexport { Slider, type SliderProps } from './Slider.js';\nexport { Chart, type ChartProps, type ChartKind } from './Chart.js';\nexport { Container, type ContainerProps } from './Container.js';\nexport { Code, type CodeProps } from './Code.js';\nexport { Heading, type HeadingProps } from './Heading.js';\nexport { Text, type TextProps } from './Text.js';\nexport { Stepper, type StepperProps, type Step } from './Stepper.js';\nexport { Card, type CardProps } from './Card.js';\nexport { List, type ListProps } from './List.js';\n\nimport type { ComponentType } from 'react';\nimport { Button } from './Button.js';\nimport { TextField } from './TextField.js';\nimport { Slider } from './Slider.js';\nimport { Chart } from './Chart.js';\nimport { Container } from './Container.js';\nimport { Code } from './Code.js';\nimport { Heading } from './Heading.js';\nimport { Text } from './Text.js';\nimport { Stepper } from './Stepper.js';\nimport { Card } from './Card.js';\nimport { List } from './List.js';\n\n/**\n * Map of PascalCase component name to React component. Use this when\n * you have a renderer that walks an AST and needs to pick an\n * implementation at runtime:\n *\n * const C = componentMap[tagName];\n * if (C) el = <C {...props}>{children}</C>;\n *\n * Keys mirror `DEFAULT_REGISTRY.list()`.\n *\n * Type note: components vary in their props shape, so the map is\n * typed permissively (`Record<string, ComponentType<any>>`). Each\n * individual export above is still strictly typed.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const componentMap: Record<string, ComponentType<any>> = {\n Button,\n TextField,\n Slider,\n Chart,\n Container,\n Code,\n Heading,\n Text,\n Stepper,\n Card,\n List,\n};\n\nexport type ComponentMapKey = keyof typeof componentMap;\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@playgenx/components",
3
+ "version": "0.1.0",
4
+ "description": "Default React 19 implementations for every entry in DEFAULT_REGISTRY. Pair with @playgenx/registry and the parser/validator pipeline.",
5
+ "type": "module",
6
+ "main": "./dist/index.mjs",
7
+ "types": "./dist/index.d.mts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.mts",
11
+ "import": "./dist/index.mjs"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsdown",
19
+ "lint": "eslint src",
20
+ "test": "vitest --run"
21
+ },
22
+ "keywords": [
23
+ "playgenx",
24
+ "react",
25
+ "components"
26
+ ],
27
+ "author": "xorinf <118471720+xorinf@users.noreply.github.com>",
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/xorinf/playgenx.git",
32
+ "directory": "packages/components"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/xorinf/playgenx/issues"
36
+ },
37
+ "homepage": "https://github.com/xorinf/playgenx/tree/main/packages/components",
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "tsdown": {
42
+ "entry": [
43
+ "src/index.ts"
44
+ ],
45
+ "format": [
46
+ "esm"
47
+ ],
48
+ "dts": true,
49
+ "sourcemap": true,
50
+ "clean": true,
51
+ "deps": {
52
+ "alwaysBundle": [
53
+ "^@playgenx/"
54
+ ]
55
+ }
56
+ },
57
+ "peerDependencies": {
58
+ "react": "^19.2.0",
59
+ "react-dom": "^19.2.0"
60
+ },
61
+ "devDependencies": {
62
+ "@playgenx/registry": "workspace:*",
63
+ "@testing-library/react": "^16.2.0",
64
+ "@types/react": "^19.2.17",
65
+ "@types/react-dom": "^19.2.3",
66
+ "jsdom": "^25.0.1",
67
+ "react": "^19.2.7",
68
+ "react-dom": "^19.2.7",
69
+ "tsdown": "^0.22.4",
70
+ "typescript": "^6.0.3",
71
+ "vitest": "^4.1.10"
72
+ }
73
+ }