praxis-kit 0.1.0 → 0.1.1

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.
@@ -810,12 +810,35 @@ type ControlProps<G extends PolymorphicGenerics, TAs extends ElementType> = Owne
810
810
  * Component-defined props always take precedence.
811
811
  */
812
812
  type IntrinsicPropsWithoutOwned<G extends PolymorphicGenerics, TAs extends ElementType> = Omit<IntrinsicJSXProps<TAs>, keyof ControlProps<G, TAs> | 'children'>;
813
+ /**
814
+ * `data-*` attribute passthrough.
815
+ *
816
+ * React's `JSX.IntrinsicElements[tag]` prop types carry no `data-*` index — the JSX checker
817
+ * special-cases `data-*` at the call site instead — so `IntrinsicPropsWithoutOwned` (which is
818
+ * `Omit<JSX.IntrinsicElements[tag], …>`) has no `data-*` key either. A polymorphic component
819
+ * always renders to a host element (or forwards to one via `asChild`) and its runtime prop
820
+ * pipeline forwards `data-*` unchanged, so the extracted prop type must admit them: without this,
821
+ * a wrapper can't destructure a `data-*` the contract sets in `defaults` (`data-slot` is the
822
+ * common case — a styling hook every design system sets and overrides) — `ContractProps<typeof
823
+ * Component>['data-slot']` would be a type error even though `<Component data-slot="…" />` is
824
+ * accepted.
825
+ *
826
+ * The value type is `string | number | boolean | undefined` by deliberate choice — exactly what
827
+ * React serializes onto a `data-*` attribute (`true`/`false` render as the strings `"true"` /
828
+ * `"false"`, not omitted; `undefined` omits) and what survives praxis-kit's prop pipeline
829
+ * unchanged. It is intentionally tighter than the framework-neutral `unknown` the core contract
830
+ * uses, so a wrapper can destructure a `data-*` and forward it without a cast — the whole point.
831
+ */
832
+ type DataAttribute = `data-${string}`;
833
+ type DataAttributes = {
834
+ [key: DataAttribute]: string | number | boolean | undefined;
835
+ };
813
836
  /**
814
837
  * Props shared by every rendering strategy.
815
838
  *
816
839
  * Each render mode contributes only its discriminating props.
817
840
  */
818
- type BaseProps<G extends PolymorphicGenerics, TAs extends ElementType> = IntrinsicPropsWithoutOwned<G, TAs> & ControlProps<G, TAs>;
841
+ type BaseProps<G extends PolymorphicGenerics, TAs extends ElementType> = IntrinsicPropsWithoutOwned<G, TAs> & ControlProps<G, TAs> & DataAttributes;
819
842
  /** Standard rendering (`asChild` absent or false). */
820
843
  type NormalRenderMode = {
821
844
  asChild?: false;
@@ -742,16 +742,32 @@ type GenericsOf<T extends HasGenerics<PolymorphicGenerics>> = T extends HasGener
742
742
  * makes that a type-level fact too, so `{ as: 'a' }` written against `ContractProps<T>` is a compile
743
743
  * error, not a silently-ignored no-op a caller could believe was doing something.
744
744
  *
745
+ * `data-*` attributes pass through (`DataAttributes` below). `_buildProps()` in
746
+ * `createContractComponent` scans every attribute set on the custom element into the pipeline, so
747
+ * `<praxis-button data-slot="…">` is real, forwarded input — a `data-*` a contract sets in
748
+ * `defaults` (`data-slot`, the near-universal styling hook) has to be a member of `ContractProps`
749
+ * for a consumer to type it. Other global/host attributes (`id`, `class`, `slot`, `aria-*`,
750
+ * `role`) are equally accepted on the element but are *not* part of this type: they are DOM
751
+ * globals a caller sets on the element directly, not part of a component's declared prop contract.
752
+ * `data-*` is the exception because contracts author it as an overridable prop.
753
+ *
745
754
  * ```ts
746
755
  * const Button = createContractComponent({ tag: 'button', name: 'Button', /* ... *\/ })
747
756
  *
748
757
  * type ButtonProps = ContractProps<typeof Button>
749
758
  * ```
750
759
  */
751
- type ContractProps<T extends HasGenerics<PolymorphicGenerics>> = Simplify<OmitIndexSignature<PropsOf<GenericsOf<T>>> & OmitIndexSignature<VariantProps<VariantsOf<GenericsOf<T>>>> & {
760
+ type ContractProps<T extends HasGenerics<PolymorphicGenerics>> = Simplify<OmitIndexSignature<PropsOf<GenericsOf<T>>> & OmitIndexSignature<VariantProps<VariantsOf<GenericsOf<T>>>> & DataAttributes & {
752
761
  as?: never;
753
762
  recipe?: keyof RecipeOf<GenericsOf<T>>;
754
763
  }>;
764
+ /**
765
+ * `data-*` attribute passthrough. The value type is `string | number | boolean | undefined` —
766
+ * what a `data-*` attribute serializes to (mirrors the React adapter's own `DataAttributes`).
767
+ */
768
+ type DataAttributes = {
769
+ [key: `data-${string}`]: string | number | boolean | undefined;
770
+ };
755
771
  //#endregion
756
772
  //#region ../../adapters/lit/src/create-contract-component.d.ts
757
773
  /**
@@ -1,4 +1,4 @@
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";
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-DiPzmjWW.js";
2
2
  //#region ../../adapters/react/src/current/create-contract-component.d.ts
3
3
  /**
4
4
  * Creates a polymorphic React 19 component with praxis-kit contracts applied.
@@ -1,4 +1,4 @@
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";
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-DiPzmjWW.js";
2
2
  //#region ../../adapters/react/src/legacy/create-contract-component.d.ts
3
3
  /**
4
4
  * Creates a polymorphic React component with praxis-kit contracts applied, for React 18 and
@@ -713,16 +713,32 @@ type GenericsOf<T extends HasGenerics<PolymorphicGenerics>> = T extends HasGener
713
713
  * makes that a type-level fact too, so `{ as: 'a' }` written against `ContractProps<T>` is a compile
714
714
  * error, not a silently-ignored no-op a caller could believe was doing something.
715
715
  *
716
+ * `data-*` attributes pass through (`DataAttributes` below). `_buildProps()` in
717
+ * `createContractComponent` scans every attribute set on the custom element into the pipeline, so
718
+ * `<praxis-button data-slot="…">` is real, forwarded input — a `data-*` a contract sets in
719
+ * `defaults` (`data-slot`, the near-universal styling hook) has to be a member of `ContractProps`
720
+ * for a consumer to type it. Other global/host attributes (`id`, `class`, `slot`, `aria-*`,
721
+ * `role`) are equally accepted on the element but are *not* part of this type: they are DOM
722
+ * globals a caller sets on the element directly, not part of a component's declared prop contract.
723
+ * `data-*` is the exception because contracts author it as an overridable prop.
724
+ *
716
725
  * ```ts
717
726
  * const Button = createContractComponent({ tag: 'button', name: 'Button', /* ... *\/ })
718
727
  *
719
728
  * type ButtonProps = ContractProps<typeof Button>
720
729
  * ```
721
730
  */
722
- type ContractProps<T extends HasGenerics<PolymorphicGenerics>> = Simplify<OmitIndexSignature<PropsOf<GenericsOf<T>>> & OmitIndexSignature<VariantProps<VariantsOf<GenericsOf<T>>>> & {
731
+ type ContractProps<T extends HasGenerics<PolymorphicGenerics>> = Simplify<OmitIndexSignature<PropsOf<GenericsOf<T>>> & OmitIndexSignature<VariantProps<VariantsOf<GenericsOf<T>>>> & DataAttributes & {
723
732
  as?: never;
724
733
  recipe?: keyof RecipeOf<GenericsOf<T>>;
725
734
  }>;
735
+ /**
736
+ * `data-*` attribute passthrough. The value type is `string | number | boolean | undefined` —
737
+ * what a `data-*` attribute serializes to (mirrors the React adapter's own `DataAttributes`).
738
+ */
739
+ type DataAttributes = {
740
+ [key: `data-${string}`]: string | number | boolean | undefined;
741
+ };
726
742
  //#endregion
727
743
  //#region ../../adapters/web/src/create-contract-component.d.ts
728
744
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "praxis-kit",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Praxis Kit — HTML semantics, ARIA requirements, and component composition rules as executable contracts, shared across every framework adapter. The single npm package for all adapters and tooling.",
@@ -208,9 +208,9 @@
208
208
  "unplugin-solid": "^2.0.0",
209
209
  "vite": "^8.2.2",
210
210
  "vue": "^3.5.42",
211
- "@praxis-kit/core": "0.0.0",
212
211
  "@praxis-kit/diagnostics": "0.0.0",
213
- "@praxis-kit/primitive": "0.0.0"
212
+ "@praxis-kit/primitive": "0.0.0",
213
+ "@praxis-kit/core": "0.0.0"
214
214
  },
215
215
  "publishConfig": {
216
216
  "access": "public"