@carbonbits/sixr 1.4.0 → 1.5.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 (56) hide show
  1. package/README.md +139 -60
  2. package/dist/button.cjs +223 -0
  3. package/dist/button.cjs.map +1 -0
  4. package/dist/button.d.cts +34 -0
  5. package/dist/button.d.ts +34 -0
  6. package/dist/button.js +4 -0
  7. package/dist/button.js.map +1 -0
  8. package/dist/chunk-HDTW4FRT.js +111 -0
  9. package/dist/chunk-HDTW4FRT.js.map +1 -0
  10. package/dist/email-input.cjs +213 -170
  11. package/dist/email-input.cjs.map +1 -1
  12. package/dist/email-input.d.cts +4 -6
  13. package/dist/email-input.d.ts +4 -6
  14. package/dist/email-input.js +219 -170
  15. package/dist/email-input.js.map +1 -1
  16. package/dist/field.cjs +206 -0
  17. package/dist/field.cjs.map +1 -0
  18. package/dist/field.d.cts +80 -0
  19. package/dist/field.d.ts +80 -0
  20. package/dist/field.js +186 -0
  21. package/dist/field.js.map +1 -0
  22. package/dist/form.cjs +283 -42
  23. package/dist/form.cjs.map +1 -1
  24. package/dist/form.d.cts +79 -10
  25. package/dist/form.d.ts +79 -10
  26. package/dist/form.js +285 -45
  27. package/dist/form.js.map +1 -1
  28. package/dist/index-CdYkd6zz.d.cts +22 -0
  29. package/dist/index-CdYkd6zz.d.ts +22 -0
  30. package/dist/index.cjs +138 -34
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +116 -55
  33. package/dist/index.d.ts +116 -55
  34. package/dist/index.js +1 -0
  35. package/dist/password-input.cjs +217 -174
  36. package/dist/password-input.cjs.map +1 -1
  37. package/dist/password-input.d.cts +2 -3
  38. package/dist/password-input.d.ts +2 -3
  39. package/dist/password-input.js +222 -173
  40. package/dist/password-input.js.map +1 -1
  41. package/dist/phone-input.cjs +213 -170
  42. package/dist/phone-input.cjs.map +1 -1
  43. package/dist/phone-input.d.cts +5 -5
  44. package/dist/phone-input.d.ts +5 -5
  45. package/dist/phone-input.js +219 -170
  46. package/dist/phone-input.js.map +1 -1
  47. package/dist/styles.css +1 -1
  48. package/dist/text-input.cjs +213 -170
  49. package/dist/text-input.cjs.map +1 -1
  50. package/dist/text-input.d.cts +2 -3
  51. package/dist/text-input.d.ts +2 -3
  52. package/dist/text-input.js +219 -170
  53. package/dist/text-input.js.map +1 -1
  54. package/package.json +26 -2
  55. package/dist/index-DwjxC4l4.d.cts +0 -62
  56. package/dist/index-DwjxC4l4.d.ts +0 -62
package/dist/index.d.ts CHANGED
@@ -1,41 +1,22 @@
1
+ import { ButtonProps } from './button.js';
2
+ export { Button, ButtonSize, ButtonVariant } from './button.js';
1
3
  export { Cart, CartProduct, CartProps } from './cart.js';
2
- import { InputHTMLAttributes, ReactNode } from 'react';
4
+ import { ComponentPropsWithoutRef, ReactNode, FormHTMLAttributes } from 'react';
5
+ import { Label } from '@radix-ui/react-label';
6
+ import { Slot } from '@radix-ui/react-slot';
7
+ import { StandardSchemaV1 } from '@standard-schema/spec';
8
+ import { FieldValues, UseFormReturn, DefaultValues, Mode } from 'react-hook-form';
3
9
  export { Typography, TypographyElement, TypographyProps, TypographyTone, TypographyVariant, TypographyWeight } from './typography.js';
4
10
 
5
- /**
6
- * Structural shape of a zod schema — every zod schema satisfies it, and any
7
- * version of zod does. Declaring it this way rather than importing `ZodType`
8
- * keeps zod out of this module's public types, so consumers who only want an
9
- * input do not have to install zod to typecheck it.
10
- */
11
- type FieldSchema = {
12
- safeParse: (value: unknown) => {
13
- success: true;
14
- } | {
15
- success: false;
16
- error: {
17
- issues: readonly {
18
- message: string;
19
- }[];
20
- };
21
- };
22
- };
23
- /** Outcome of a single validation pass, handed to `onValidationChange`. */
24
- type FieldValidation = {
25
- valid: boolean;
26
- /** First issue reported by the schema, or `undefined` when valid. */
27
- error?: string;
28
- };
29
-
30
- /** Props every specialised input shares. `type` is fixed by the wrapper. */
31
- type FieldProps = Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "defaultValue" | "type"> & {
11
+ type InputFieldProps = Omit<ComponentPropsWithoutRef<"input">, "name" | "type"> & {
12
+ /** The form field this input edits — the key in the `Form`'s values. */
13
+ name: string;
32
14
  label?: string;
33
15
  /** Guidance under the field. Replaced by the error message while invalid. */
34
16
  hint?: ReactNode;
35
17
  /**
36
18
  * Error supplied by the caller — a server-side or cross-field failure. Takes
37
- * precedence over the schema, so a form can hold a field invalid regardless
38
- * of what `schema` makes of the value on its own.
19
+ * precedence over what the form's schema reports for this field.
39
20
  */
40
21
  error?: string;
41
22
  /** Renders the design's muted "Optional" marker at the end of the label. */
@@ -44,36 +25,115 @@ type FieldProps = Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "valu
44
25
  action?: ReactNode;
45
26
  /** Trailing in-field slot, for affordances like the design's password peek. */
46
27
  trailing?: ReactNode;
47
- value?: string;
48
- defaultValue?: string;
49
- onChange?: (value: string) => void;
50
- /**
51
- * Any zod schema that accepts a string. Only `safeParse` is used, so a
52
- * refined, transformed or preprocessed schema works as well as a plain one.
53
- */
54
- schema?: FieldSchema;
55
- /**
56
- * When the schema runs. `blur` — the default — avoids scolding someone
57
- * mid-keystroke; once a field has gone invalid it revalidates on every
58
- * keystroke so the message clears as soon as it is fixed.
59
- */
60
- validateOn?: "blur" | "change" | "never";
61
- onValidationChange?: (state: FieldValidation) => void;
62
28
  };
63
29
 
64
30
  /**
65
31
  * An email address. Fixes `type="email"` and the keyboard and autofill hints
66
- * that go with it. Pair it with `emailSchema` from `@carbonbits/sixr/validation`
67
- * to validate inline; the schema stays opt-in so this bundle does not require
68
- * zod.
32
+ * that go with it. Validate it with `emailSchema` from
33
+ * `@carbonbits/sixr/validation` in the enclosing `Form`'s schema.
34
+ */
35
+ type EmailInputProps = InputFieldProps;
36
+
37
+ /**
38
+ * The structure behind every form field, with no styling of its own: an id
39
+ * shared by label and control, the error and description ids the control is
40
+ * described by, the field's validity, and — inside a `Form` — the
41
+ * react-hook-form bindings (`value`, `onChange`, `onBlur`, `ref`) that keep
42
+ * the control registered.
43
+ *
44
+ * Styled components compose these primitives with their own classes
45
+ * (`TextInput` and friends do), and a screen that needs a control the
46
+ * library does not ship — a select, a code entry, a toggle — composes them
47
+ * the same way. Everything here is a plain element or a Radix `Slot`, so the
48
+ * styling decisions stay with whoever renders the field.
49
+ *
50
+ * Outside a `Form` the primitives still wire label, control and messages
51
+ * together; the control just isn't registered anywhere and the error comes
52
+ * from the `error` prop alone.
69
53
  */
70
- type EmailInputProps = FieldProps;
54
+ type FieldBindings = {
55
+ name: string;
56
+ value?: unknown;
57
+ onChange?: (event: unknown) => void;
58
+ onBlur?: () => void;
59
+ ref?: (instance: HTMLElement | null) => void;
60
+ };
61
+ type FieldContextValue = {
62
+ id: string;
63
+ name: string;
64
+ descriptionId: string;
65
+ messageId: string;
66
+ error: string | undefined;
67
+ invalid: boolean;
68
+ required: boolean;
69
+ disabled: boolean;
70
+ hasDescription: boolean;
71
+ setHasDescription: (present: boolean) => void;
72
+ bindings: FieldBindings;
73
+ };
74
+ type FieldRootProps = ComponentPropsWithoutRef<"div"> & {
75
+ /** The form field this wires up — the key in the `Form`'s values. */
76
+ name: string;
77
+ /** A caller-supplied error. Outranks whatever the form's schema reports. */
78
+ error?: string;
79
+ required?: boolean;
80
+ disabled?: boolean;
81
+ /** Render the child element as the root instead of a `div`. */
82
+ asChild?: boolean;
83
+ children: ReactNode;
84
+ };
85
+ type FieldLabelProps = ComponentPropsWithoutRef<typeof Label>;
86
+ type FieldControlProps = ComponentPropsWithoutRef<typeof Slot>;
87
+ type FieldDescriptionProps = ComponentPropsWithoutRef<"p"> & {
88
+ asChild?: boolean;
89
+ };
90
+ type FieldMessageProps = ComponentPropsWithoutRef<"p"> & {
91
+ asChild?: boolean;
92
+ };
93
+
94
+ /**
95
+ * A `<form>` on react-hook-form. The schema — any Standard Schema, which
96
+ * every zod 4 schema is — validates the whole form: on first blur per field,
97
+ * then on every change once a field has gone invalid, and again on submit.
98
+ * Fields register themselves through `FieldRoot` (and so through every
99
+ * input in this library), so a form is the schema, the inputs and a submit.
100
+ *
101
+ * `onSubmit` only runs with values the schema accepted, typed as its output.
102
+ * Throwing from it — or calling `form.setError("root", …)` — surfaces the
103
+ * message through `FormError`. While it is pending the fields are disabled
104
+ * and `SubmitButton` shows its spinner.
105
+ *
106
+ * Pass your own `form` (from `useFormInstance`) when a screen needs to reach
107
+ * the instance itself, for `setError`, `reset` or `watch`.
108
+ */
109
+ type FormSchema = StandardSchemaV1<FieldValues, FieldValues>;
110
+ type FormInput<Schema extends FormSchema> = StandardSchemaV1.InferInput<Schema>;
111
+ type FormOutput<Schema extends FormSchema> = StandardSchemaV1.InferOutput<Schema>;
112
+ type FormInstance<Schema extends FormSchema> = UseFormReturn<FormInput<Schema>, unknown, FormOutput<Schema>>;
113
+ type UseFormInstanceOptions<Schema extends FormSchema> = {
114
+ schema?: Schema;
115
+ defaultValues?: DefaultValues<FormInput<Schema>>;
116
+ /** When a field first validates. `onTouched`: first blur, then every change. */
117
+ mode?: Mode;
118
+ };
119
+ type FormProps<Schema extends FormSchema = FormSchema> = Omit<FormHTMLAttributes<HTMLFormElement>, "onSubmit"> & UseFormInstanceOptions<Schema> & {
120
+ onSubmit: (values: FormOutput<Schema>, form: FormInstance<Schema>) => void | Promise<void>;
121
+ /** An instance from `useFormInstance`, when the screen needs it too. */
122
+ form?: FormInstance<Schema>;
123
+ children: ReactNode;
124
+ };
125
+ type FormErrorProps = {
126
+ /** A message to show in place of the form's own root error. */
127
+ children?: ReactNode;
128
+ className?: string;
129
+ };
130
+ type SubmitButtonProps = Omit<ButtonProps, "type" | "loading" | "asChild">;
71
131
 
72
132
  /**
73
133
  * A password. Fixes `type="password"` and owns the design's in-field peek
74
134
  * affordance, so the trailing slot is not exposed here — the toggle is it.
75
135
  */
76
- type PasswordInputProps = Omit<FieldProps, "trailing"> & {
136
+ type PasswordInputProps = Omit<InputFieldProps, "trailing"> & {
77
137
  /** Show the "Show"/"Hide" toggle. On by default, as the design has it. */
78
138
  revealable?: boolean;
79
139
  /** Labels for the toggle, for localisation. */
@@ -84,10 +144,11 @@ type PasswordInputProps = Omit<FieldProps, "trailing"> & {
84
144
  };
85
145
 
86
146
  /**
87
- * A phone number. Fixes `type="tel"` and the numeric keypad. Pair it with
88
- * `phoneSchema` from `@carbonbits/sixr/validation` to validate inline.
147
+ * A phone number. Fixes `type="tel"` and the numeric keypad. Validate it with
148
+ * `phoneSchema` from `@carbonbits/sixr/validation` in the enclosing `Form`'s
149
+ * schema.
89
150
  */
90
- type PhoneInputProps = FieldProps;
151
+ type PhoneInputProps = InputFieldProps;
91
152
 
92
153
  /**
93
154
  * Plain free text: names, job titles, one-time codes. Anything with a format
@@ -95,9 +156,9 @@ type PhoneInputProps = FieldProps;
95
156
  * component (`EmailInput`, `PhoneInput`, `PasswordInput`), which fixes the
96
157
  * keyboard, autocomplete and input type that format needs.
97
158
  */
98
- type TextInputProps = FieldProps & {
159
+ type TextInputProps = InputFieldProps & {
99
160
  /** Renders the value in the design's monospace face, as the code entry does. */
100
161
  mono?: boolean;
101
162
  };
102
163
 
103
- export type { EmailInputProps, FieldProps, FieldSchema, FieldValidation, PasswordInputProps, PhoneInputProps, TextInputProps };
164
+ export { ButtonProps, type EmailInputProps, type FieldBindings, type FieldContextValue, type FieldControlProps, type FieldDescriptionProps, type FieldLabelProps, type FieldMessageProps, type FieldRootProps, type FormErrorProps, type FormInput, type FormInstance, type FormOutput, type FormProps, type FormSchema, type InputFieldProps, type PasswordInputProps, type PhoneInputProps, type SubmitButtonProps, type TextInputProps, type UseFormInstanceOptions };
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export { Button } from './chunk-HDTW4FRT.js';
1
2
  export { Cart } from './chunk-BHSOSXTU.js';
2
3
  export { Typography } from './chunk-NZHHNVXZ.js';
3
4
  //# sourceMappingURL=index.js.map