@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 +62 -0
- package/dist/index.d.mts +198 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +638 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +73 -0
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).
|
package/dist/index.d.mts
ADDED
|
@@ -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
|
+
}
|