praxis-kit 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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -0
  3. package/dist/_shared/diagnostics.d.ts +312 -0
  4. package/dist/_shared/diagnostics.js +360 -0
  5. package/dist/build-runtime-CJ_nQEaZ.js +5065 -0
  6. package/dist/codemod/index.d.ts +2 -0
  7. package/dist/codemod/index.js +176520 -0
  8. package/dist/contract/index.d.ts +677 -0
  9. package/dist/contract/index.js +341 -0
  10. package/dist/eslint/index.d.ts +90 -0
  11. package/dist/eslint/index.js +1047 -0
  12. package/dist/guards/index.d.ts +78 -0
  13. package/dist/guards/index.js +118 -0
  14. package/dist/html/index.d.ts +151 -0
  15. package/dist/html/index.js +1244 -0
  16. package/dist/index-BIBd_iPD.d.ts +951 -0
  17. package/dist/lit/index.d.ts +862 -0
  18. package/dist/lit/index.js +4893 -0
  19. package/dist/preact/index.d.ts +796 -0
  20. package/dist/preact/index.js +5043 -0
  21. package/dist/react/index.d.ts +28 -0
  22. package/dist/react/index.js +205 -0
  23. package/dist/react/legacy.d.ts +29 -0
  24. package/dist/react/legacy.js +80 -0
  25. package/dist/solid/index.d.ts +728 -0
  26. package/dist/solid/index.js +4821 -0
  27. package/dist/svelte/Polymorphic.svelte +190 -0
  28. package/dist/svelte/_polymorphic-runtime.d.ts +102 -0
  29. package/dist/svelte/_polymorphic-runtime.js +371 -0
  30. package/dist/svelte/index.d.ts +994 -0
  31. package/dist/svelte/index.js +4482 -0
  32. package/dist/tailwind/index.d.ts +197 -0
  33. package/dist/tailwind/index.js +767 -0
  34. package/dist/tailwind/safelist.css +20 -0
  35. package/dist/ts-plugin/index.cjs +166 -0
  36. package/dist/ts-plugin/index.d.cts +9 -0
  37. package/dist/utils/index.d.ts +19 -0
  38. package/dist/utils/index.js +21 -0
  39. package/dist/vite-plugin/index.d.ts +200 -0
  40. package/dist/vite-plugin/index.js +2106 -0
  41. package/dist/vue/index.d.ts +729 -0
  42. package/dist/vue/index.js +4945 -0
  43. package/dist/web/index.d.ts +832 -0
  44. package/dist/web/index.js +4868 -0
  45. package/package.json +258 -0
@@ -0,0 +1,28 @@
1
+ import { C as MergeRecords, E as AnyRecord, S as EmptyRecord, T as NoVariants, _ as ExtractPluginProps, a as PolymorphicProps, b as VariantMap, c as RenderCallbackProps, d as SlottableProps, f as mergeRefs, g as AnyClassPluginFactory, h as FactoryOptions, i as PolymorphicComponent, l as UnknownProps, m as AnyFactoryOptions, n as ContractProps, o as PolymorphicWithAsChild, p as defineContractComponent, r as ElementRef, s as PolymorphicWithRender, t as ReactFactoryOptions, u as Slottable, v as PolymorphicGenerics, w as NoPreset, x as ElementType, y as RecipeMap } from "../index-BIBd_iPD.js";
2
+ //#region ../../adapters/react/src/current/create-contract-component.d.ts
3
+ /**
4
+ * Creates a polymorphic React 19 component with praxis-kit contracts applied.
5
+ *
6
+ * ```tsx
7
+ * const Button = createContractComponent({
8
+ * tag: 'button',
9
+ * name: 'Button',
10
+ * styling: {
11
+ * base: 'btn',
12
+ * variants: { intent: { primary: 'btn--primary', ghost: 'btn--ghost' } },
13
+ * defaults: { intent: 'primary' },
14
+ * },
15
+ * })
16
+ *
17
+ * <Button intent="ghost" as="a" href="/home">Home</Button>
18
+ * ```
19
+ *
20
+ * `ref` is accepted as a plain prop (React 19) and forwarded to the rendered host element or,
21
+ * with `asChild`, to the consumer's own element. Pass `subComponents` to attach named
22
+ * sub-components (`Card.Header`) and `onElement` to run setup once the real DOM element exists.
23
+ */
24
+ export declare function createContractComponent<TDefault extends ElementType, Props extends UnknownProps = EmptyRecord, Variants extends Readonly<VariantMap> = NoVariants, TPreset extends RecipeMap<Variants> = NoPreset, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory, TAllowed extends ElementType = ElementType, TSubComponents extends Readonly<AnyRecord> = EmptyRecord>(options: ReactFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin, TAllowed> & {
25
+ readonly subComponents?: TSubComponents;
26
+ }): MergeRecords<PolymorphicComponent<PolymorphicGenerics<TDefault, MergeRecords<Props, ExtractPluginProps<TPlugin>>, Variants, TPreset, TAllowed>>, TSubComponents>;
27
+ //#endregion
28
+ export { type AnyFactoryOptions, type ContractProps, type ElementRef, type ElementType, type EmptyRecord, type FactoryOptions, type PolymorphicComponent, type PolymorphicGenerics, type PolymorphicProps, type PolymorphicWithAsChild, type PolymorphicWithRender, type ReactFactoryOptions, type RenderCallbackProps, Slottable, type SlottableProps, defineContractComponent, mergeRefs };
@@ -0,0 +1,205 @@
1
+ import { _ as invariant, a as getElementRef, c as Slottable, d as finalizeComponent, f as SLOT_NAME, g as defineContractComponent, h as isString, i as makeCloneSlotChild, l as applyDisplayName, m as isObject, n as render, o as getPropsRef, p as isFunction, r as applySlot, s as hasWarningGetter, t as buildRuntime$1, u as mergeRefs } from "../build-runtime-CJ_nQEaZ.js";
2
+ import { isValidElement, useCallback, useRef } from "react";
3
+ //#region ../../lib/adapter-utils/src/runtime/is-factory-options-like.ts
4
+ /**
5
+ * Loosely validates one recognized `FactoryOptions` field's runtime shape.
6
+ * "Loosely" because the field's declared type is itself parameterized by a
7
+ * generic (Props, Variants, TPlugin, ...) that's erased at runtime — these
8
+ * checks confirm the field is the right *kind* of value (object, function,
9
+ * string), not that it satisfies its exact generic instantiation, which no
10
+ * runtime check can ever do.
11
+ *
12
+ * Covers every field `FactoryOptions` itself declares — identical across
13
+ * every adapter, since they all extend the same core type. Adapter-specific
14
+ * additions (React's `slotComponent`/`artifact`, every adapter's own
15
+ * `filterProps`, etc.) are passed in by the caller as extra entries.
16
+ */
17
+ const FACTORY_OPTIONS_FIELD_VALIDATORS = {
18
+ tag: (v) => v === void 0 || isString(v),
19
+ name: (v) => v === void 0 || isString(v),
20
+ defaults: (v) => v === void 0 || isObject(v),
21
+ normalize: (v) => v === void 0 || isFunction(v),
22
+ styling: (v) => v === void 0 || isObject(v),
23
+ enforcement: (v) => v === void 0 || isObject(v),
24
+ diagnostics: (v) => v === void 0 || isObject(v),
25
+ subComponents: (v) => v === void 0 || isObject(v),
26
+ onElement: (v) => v === void 0 || isFunction(v)
27
+ };
28
+ /**
29
+ * Type guard narrowing the generic `FactoryOptions` shape down to an
30
+ * adapter-specific factory options type `T` — the type each adapter's
31
+ * `buildRuntime` is declared against.
32
+ *
33
+ * Walks every own enumerable property on `options` and checks it against
34
+ * `FACTORY_OPTIONS_FIELD_VALIDATORS` plus `extraFieldValidators` (the
35
+ * adapter's own additions on top of `FactoryOptions`): an unrecognized key,
36
+ * or a recognized key holding a value of the wrong kind, fails the guard.
37
+ * This is a genuine structural check, not a relabeled assertion — though it
38
+ * necessarily stops at each field's runtime *kind*, since the field's actual
39
+ * generic instantiation is erased at runtime and no guard can validate it.
40
+ * That part remains the caller's responsibility, same as with any other
41
+ * generic function in TypeScript.
42
+ */
43
+ function isFactoryOptionsLike(options, extraFieldValidators) {
44
+ if (!isObject(options)) return false;
45
+ const validators = {
46
+ ...FACTORY_OPTIONS_FIELD_VALIDATORS,
47
+ ...extraFieldValidators
48
+ };
49
+ for (const [key, value] of Object.entries(options)) {
50
+ const validate = validators[key];
51
+ if (!validate || !validate(value)) return false;
52
+ }
53
+ return true;
54
+ }
55
+ //#endregion
56
+ //#region ../../adapters/react/src/shared/to-react-factory-options.ts
57
+ /** React-specific additions on top of `FactoryOptions`. */
58
+ const REACT_FIELD_VALIDATORS = {
59
+ slotComponent: (v) => v === void 0 || isFunction(v) || isObject(v),
60
+ filterProps: (v) => v === void 0 || isFunction(v),
61
+ artifact: (v) => v === void 0 || isObject(v)
62
+ };
63
+ /**
64
+ * Type guard narrowing the generic `FactoryOptions` shape down to
65
+ * `ReactFactoryOptions` — the type `buildRuntime` is declared against. See
66
+ * `isFactoryOptionsLike` for what this does and doesn't validate.
67
+ */
68
+ function isReactFactoryOptions(options) {
69
+ return isFactoryOptionsLike(options, REACT_FIELD_VALIDATORS);
70
+ }
71
+ //#endregion
72
+ //#region ../../adapters/react/src/shared/is-polymorphic-component.ts
73
+ /**
74
+ * Type guard narrowing a generated component's real (framework-specific)
75
+ * function type down to the public `PolymorphicComponent<G>` interface
76
+ * every adapter factory exposes.
77
+ *
78
+ * `PolymorphicComponent<G>`'s call signatures reference `G`, which is
79
+ * erased at runtime, so no guard can check them — the only thing this
80
+ * interface asserts that's actually observable at runtime is "callable" and
81
+ * an optional `displayName` of the right kind. That's a complete check for
82
+ * everything the type declares outside its (compile-time-only) call
83
+ * signatures.
84
+ */
85
+ function isPolymorphicComponent(value) {
86
+ if (!isFunction(value)) return false;
87
+ if (!("displayName" in value)) return true;
88
+ return value.displayName === void 0 || isString(value.displayName);
89
+ }
90
+ //#endregion
91
+ //#region ../../adapters/react/src/current/slot/composeRefs.ts
92
+ function getChildRef(element) {
93
+ return hasWarningGetter(element.props, "ref") ? getElementRef(element) : getPropsRef(element);
94
+ }
95
+ //#endregion
96
+ //#region ../../adapters/react/src/current/slot/cloneSlotChild.ts
97
+ const cloneSlotChild = makeCloneSlotChild(getChildRef);
98
+ //#endregion
99
+ //#region ../../adapters/react/src/current/slot/Slot.tsx
100
+ function Slot({ ref = null, children, ...slotProps }) {
101
+ return applySlot(children, slotProps, ref, cloneSlotChild);
102
+ }
103
+ Slot.displayName = SLOT_NAME;
104
+ //#endregion
105
+ //#region ../../adapters/react/src/current/normalize-children.ts
106
+ const isNonEmptyTextChild = (child) => typeof child === "number" || typeof child === "string" && child.trim().length > 0;
107
+ function normalizeChildren(children) {
108
+ if (isValidElement(children)) return [children];
109
+ if (isNonEmptyTextChild(children)) return [children];
110
+ if (Array.isArray(children)) return children.filter((child) => isValidElement(child) || isNonEmptyTextChild(child));
111
+ return [];
112
+ }
113
+ //#endregion
114
+ //#region ../../adapters/react/src/current/build-runtime.ts
115
+ function buildRuntime(options) {
116
+ return buildRuntime$1(options, Slot, normalizeChildren);
117
+ }
118
+ //#endregion
119
+ //#region ../../adapters/react/src/current/create-contract-component.ts
120
+ /**
121
+ * Creates a polymorphic React 19 component with praxis-kit contracts applied.
122
+ *
123
+ * ```tsx
124
+ * const Button = createContractComponent({
125
+ * tag: 'button',
126
+ * name: 'Button',
127
+ * styling: {
128
+ * base: 'btn',
129
+ * variants: { intent: { primary: 'btn--primary', ghost: 'btn--ghost' } },
130
+ * defaults: { intent: 'primary' },
131
+ * },
132
+ * })
133
+ *
134
+ * <Button intent="ghost" as="a" href="/home">Home</Button>
135
+ * ```
136
+ *
137
+ * `ref` is accepted as a plain prop (React 19) and forwarded to the rendered host element or,
138
+ * with `asChild`, to the consumer's own element. Pass `subComponents` to attach named
139
+ * sub-components (`Card.Header`) and `onElement` to run setup once the real DOM element exists.
140
+ */
141
+ function createContractComponent(options) {
142
+ invariant(isReactFactoryOptions(options), "options is not a valid ReactFactoryOptions object");
143
+ const bundle = buildRuntime(options);
144
+ /** Captured once from the factory options so the callback ref below can remain stable. */
145
+ const { onElement } = options;
146
+ function Component({ ref, ...props }) {
147
+ /**
148
+ * Keep current on every render so the stable callback ref can always read the latest
149
+ * props via getProps() without re-registering.
150
+ */
151
+ const propsRef = useRef(props);
152
+ propsRef.current = props;
153
+ const cleanupRef = useRef(void 0);
154
+ /**
155
+ * `onElement` originates from the options object closed over by createContractComponent,
156
+ * not from props, so it's static for the component's lifetime — this callback intentionally
157
+ * stays stable across renders. React only re-invokes a stable callback ref when the
158
+ * underlying element instance changes (mount, replacement, or unmount), so onElement is
159
+ * registered once for each mounted element, regardless of how many times Component re-renders.
160
+ */
161
+ const onElementRef = useCallback((el) => {
162
+ if (!onElement) return;
163
+ if (el) {
164
+ /**
165
+ * Defensive: React currently always calls this ref with `null` before a replacement
166
+ * element, but that ordering isn't part of the formal callback-ref contract — clean up
167
+ * any existing registration first so a hypothetical el→el invocation can't leak one.
168
+ * Cleared right after invoking, not left to be overwritten below, so a subsequent
169
+ * `onElement(...)` throw doesn't leave a stale, already-invoked cleanup in place to be
170
+ * run a second time on unmount.
171
+ */
172
+ cleanupRef.current?.();
173
+ cleanupRef.current = void 0;
174
+ /**
175
+ * The real element's actual tag is only known at runtime (`tag` default or a consumer's
176
+ * `as` override); `onElement`'s parameter type narrows that per-component via `TDefault`/
177
+ * `TAllowed`, which the DOM ref API itself can't express — see `FactoryOptions.onElement`.
178
+ */
179
+ cleanupRef.current = onElement(el, () => propsRef.current) ?? void 0;
180
+ } else {
181
+ cleanupRef.current?.();
182
+ cleanupRef.current = void 0;
183
+ }
184
+ }, []);
185
+ const mergedRef = onElement ? mergeRefs(ref, onElementRef) : ref;
186
+ return render({
187
+ ...bundle,
188
+ props,
189
+ ref: mergedRef ?? null
190
+ });
191
+ }
192
+ applyDisplayName(Component, options.name);
193
+ const assembled = finalizeComponent(Component, bundle.runtime.options.defaultTag, options.subComponents);
194
+ invariant(isPolymorphicComponent(assembled), "Generated component failed to satisfy the PolymorphicComponent shape");
195
+ /**
196
+ * MergeRecords is a conditional type. While these generics are still open, TypeScript cannot
197
+ * prove that the assembled value satisfies the same conditional expression used by the
198
+ * declared return type. Once the generics are instantiated at a call site, the conditional
199
+ * simplifies correctly. The invariant above validates the runtime shape; this assertion
200
+ * bridges the gap in the compiler's type reasoning.
201
+ */
202
+ return assembled;
203
+ }
204
+ //#endregion
205
+ export { Slottable, createContractComponent, defineContractComponent, mergeRefs };
@@ -0,0 +1,29 @@
1
+ import { C as MergeRecords, E as AnyRecord, S as EmptyRecord, T as NoVariants, _ as ExtractPluginProps, a as PolymorphicProps, b as VariantMap, c as RenderCallbackProps, d as SlottableProps, f as mergeRefs, g as AnyClassPluginFactory, h as FactoryOptions, i as PolymorphicComponent, l as UnknownProps, m as AnyFactoryOptions, n as ContractProps, o as PolymorphicWithAsChild, p as defineContractComponent, r as ElementRef, s as PolymorphicWithRender, t as ReactFactoryOptions, u as Slottable, v as PolymorphicGenerics, w as NoPreset, x as ElementType, y as RecipeMap } from "../index-BIBd_iPD.js";
2
+ //#region ../../adapters/react/src/legacy/create-contract-component.d.ts
3
+ /**
4
+ * Creates a polymorphic React component with praxis-kit contracts applied, for React 18 and
5
+ * earlier (use `praxis-kit/react` instead on React 19, which accepts `ref` as a plain prop).
6
+ *
7
+ * ```tsx
8
+ * const Button = createContractComponent({
9
+ * tag: 'button',
10
+ * name: 'Button',
11
+ * styling: {
12
+ * base: 'btn',
13
+ * variants: { intent: { primary: 'btn--primary', ghost: 'btn--ghost' } },
14
+ * defaults: { intent: 'primary' },
15
+ * },
16
+ * })
17
+ *
18
+ * <Button intent="ghost" as="a" href="/home">Home</Button>
19
+ * ```
20
+ *
21
+ * Returns a `forwardRef` component — `ref` is forwarded to the rendered host element the same
22
+ * way it works in `praxis-kit/react`. Pass `subComponents` to attach named sub-components
23
+ * (`Card.Header`) and `onElement` to run setup once the real DOM element exists.
24
+ */
25
+ export declare function createContractComponent<TDefault extends ElementType, Props extends UnknownProps = EmptyRecord, Variants extends Readonly<VariantMap> = NoVariants, TPreset extends RecipeMap<Variants> = NoPreset, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory, TAllowed extends ElementType = ElementType, TSubComponents extends Readonly<AnyRecord> = EmptyRecord>(options: ReactFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin, TAllowed> & {
26
+ readonly subComponents?: TSubComponents;
27
+ }): MergeRecords<PolymorphicComponent<PolymorphicGenerics<TDefault, MergeRecords<Props, ExtractPluginProps<TPlugin>>, Variants, TPreset, TAllowed>>, TSubComponents>;
28
+ //#endregion
29
+ export { type AnyFactoryOptions, type ContractProps, type ElementRef, type ElementType, type EmptyRecord, type FactoryOptions, type PolymorphicComponent, type PolymorphicGenerics, type PolymorphicProps, type PolymorphicWithAsChild, type PolymorphicWithRender, type ReactFactoryOptions, type RenderCallbackProps, Slottable, type SlottableProps, defineContractComponent, mergeRefs };
@@ -0,0 +1,80 @@
1
+ import { a as getElementRef, c as Slottable, d as finalizeComponent, f as SLOT_NAME, g as defineContractComponent, i as makeCloneSlotChild, l as applyDisplayName, n as render, o as getPropsRef, r as applySlot, s as hasWarningGetter, t as buildRuntime$1, u as mergeRefs } from "../build-runtime-CJ_nQEaZ.js";
2
+ import { Children, forwardRef, isValidElement, useCallback, useRef } from "react";
3
+ //#region ../../adapters/react/src/legacy/slot/composeRefs.ts
4
+ function getChildRef(element) {
5
+ return hasWarningGetter(element, "ref") ? getPropsRef(element) : getElementRef(element);
6
+ }
7
+ //#endregion
8
+ //#region ../../adapters/react/src/legacy/slot/cloneSlotChild.ts
9
+ const cloneSlotChild = makeCloneSlotChild(getChildRef);
10
+ //#endregion
11
+ //#region ../../adapters/react/src/legacy/slot/Slot.tsx
12
+ const Slot = forwardRef(function Slot({ children, ...slotProps }, ref) {
13
+ return applySlot(children, slotProps, ref, cloneSlotChild);
14
+ });
15
+ Slot.displayName = SLOT_NAME;
16
+ //#endregion
17
+ //#region ../../adapters/react/src/legacy/normalize-children.ts
18
+ const isNonEmptyTextChild = (child) => typeof child === "number" || typeof child === "string" && child.trim().length > 0;
19
+ function normalizeChildren(children) {
20
+ return Children.toArray(children).filter((child) => isValidElement(child) || isNonEmptyTextChild(child));
21
+ }
22
+ //#endregion
23
+ //#region ../../adapters/react/src/legacy/build-runtime.ts
24
+ function buildRuntime(options) {
25
+ return buildRuntime$1(options, Slot, normalizeChildren);
26
+ }
27
+ //#endregion
28
+ //#region ../../adapters/react/src/legacy/create-contract-component.ts
29
+ /**
30
+ * Creates a polymorphic React component with praxis-kit contracts applied, for React 18 and
31
+ * earlier (use `praxis-kit/react` instead on React 19, which accepts `ref` as a plain prop).
32
+ *
33
+ * ```tsx
34
+ * const Button = createContractComponent({
35
+ * tag: 'button',
36
+ * name: 'Button',
37
+ * styling: {
38
+ * base: 'btn',
39
+ * variants: { intent: { primary: 'btn--primary', ghost: 'btn--ghost' } },
40
+ * defaults: { intent: 'primary' },
41
+ * },
42
+ * })
43
+ *
44
+ * <Button intent="ghost" as="a" href="/home">Home</Button>
45
+ * ```
46
+ *
47
+ * Returns a `forwardRef` component — `ref` is forwarded to the rendered host element the same
48
+ * way it works in `praxis-kit/react`. Pass `subComponents` to attach named sub-components
49
+ * (`Card.Header`) and `onElement` to run setup once the real DOM element exists.
50
+ */
51
+ function createContractComponent(options) {
52
+ const bundle = buildRuntime(options);
53
+ const { onElement } = options;
54
+ const Component = forwardRef(function Component(props, ref) {
55
+ const propsRef = useRef(props);
56
+ propsRef.current = props;
57
+ const cleanupRef = useRef(void 0);
58
+ const onElementRef = useCallback((el) => {
59
+ if (!onElement) return;
60
+ if (el) {
61
+ cleanupRef.current?.();
62
+ cleanupRef.current = void 0;
63
+ cleanupRef.current = onElement(el, () => propsRef.current) ?? void 0;
64
+ } else {
65
+ cleanupRef.current?.();
66
+ cleanupRef.current = void 0;
67
+ }
68
+ }, []);
69
+ const mergedRef = onElement ? mergeRefs(ref, onElementRef) : ref;
70
+ return render({
71
+ ...bundle,
72
+ props,
73
+ ref: mergedRef
74
+ });
75
+ });
76
+ applyDisplayName(Component, options.name);
77
+ return finalizeComponent(Component, bundle.runtime.options.defaultTag, options.subComponents);
78
+ }
79
+ //#endregion
80
+ export { Slottable, createContractComponent, defineContractComponent, mergeRefs };