@carbonbits/sixr 1.3.0 → 1.4.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 +77 -18
- package/dist/chunk-NZHHNVXZ.js +118 -0
- package/dist/chunk-NZHHNVXZ.js.map +1 -0
- package/dist/email-input.cjs +390 -0
- package/dist/email-input.cjs.map +1 -0
- package/dist/email-input.d.cts +14 -0
- package/dist/email-input.d.ts +14 -0
- package/dist/email-input.js +367 -0
- package/dist/email-input.js.map +1 -0
- package/dist/index-DwjxC4l4.d.cts +62 -0
- package/dist/index-DwjxC4l4.d.ts +62 -0
- package/dist/index.cjs +112 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -9
- package/dist/index.d.ts +48 -9
- package/dist/index.js +1 -0
- package/dist/password-input.cjs +406 -0
- package/dist/password-input.cjs.map +1 -0
- package/dist/password-input.d.cts +20 -0
- package/dist/password-input.d.ts +20 -0
- package/dist/password-input.js +385 -0
- package/dist/password-input.js.map +1 -0
- package/dist/phone-input.cjs +386 -0
- package/dist/phone-input.cjs.map +1 -0
- package/dist/phone-input.d.cts +12 -0
- package/dist/phone-input.d.ts +12 -0
- package/dist/phone-input.js +363 -0
- package/dist/phone-input.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/text-input.cjs +228 -59
- package/dist/text-input.cjs.map +1 -1
- package/dist/text-input.d.cts +10 -58
- package/dist/text-input.d.ts +10 -58
- package/dist/text-input.js +226 -60
- package/dist/text-input.js.map +1 -1
- package/dist/typography.cjs +120 -0
- package/dist/typography.cjs.map +1 -0
- package/dist/typography.d.cts +46 -0
- package/dist/typography.d.ts +46 -0
- package/dist/typography.js +3 -0
- package/dist/typography.js.map +1 -0
- package/package.json +45 -1
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var reactSlot = require('@radix-ui/react-slot');
|
|
4
5
|
|
|
5
6
|
// src/components/cart/index.tsx
|
|
6
7
|
function formatPrice(value, currency, locale) {
|
|
@@ -35,7 +36,118 @@ function Cart({
|
|
|
35
36
|
] })
|
|
36
37
|
] });
|
|
37
38
|
}
|
|
39
|
+
var DEFAULT_ELEMENT = {
|
|
40
|
+
display: "h1",
|
|
41
|
+
heading: "h2",
|
|
42
|
+
subheading: "h3",
|
|
43
|
+
body: "p",
|
|
44
|
+
label: "span",
|
|
45
|
+
hint: "p",
|
|
46
|
+
code: "code"
|
|
47
|
+
};
|
|
48
|
+
var DEFAULT_WEIGHT = {
|
|
49
|
+
display: "semibold",
|
|
50
|
+
heading: "semibold",
|
|
51
|
+
subheading: "medium",
|
|
52
|
+
body: "regular",
|
|
53
|
+
label: "semibold",
|
|
54
|
+
hint: "regular",
|
|
55
|
+
code: "regular"
|
|
56
|
+
};
|
|
57
|
+
var VARIANT_CLASSES = {
|
|
58
|
+
display: "text-display leading-tight tracking-tight",
|
|
59
|
+
heading: "text-heading leading-tight tracking-tight",
|
|
60
|
+
subheading: "text-subheading leading-snug",
|
|
61
|
+
body: "text-field leading-normal",
|
|
62
|
+
label: "text-label leading-normal",
|
|
63
|
+
hint: "text-hint leading-normal",
|
|
64
|
+
code: "font-code text-field leading-normal"
|
|
65
|
+
};
|
|
66
|
+
var TONE_CLASSES = {
|
|
67
|
+
default: "text-fg",
|
|
68
|
+
muted: "text-fg-muted",
|
|
69
|
+
subtle: "text-fg-subtle",
|
|
70
|
+
accent: "text-accent",
|
|
71
|
+
"on-accent": "text-on-accent",
|
|
72
|
+
success: "text-success",
|
|
73
|
+
warning: "text-warning",
|
|
74
|
+
info: "text-info",
|
|
75
|
+
danger: "text-danger"
|
|
76
|
+
};
|
|
77
|
+
var WEIGHT_CLASSES = {
|
|
78
|
+
regular: "font-normal",
|
|
79
|
+
medium: "font-medium",
|
|
80
|
+
semibold: "font-semibold",
|
|
81
|
+
bold: "font-bold"
|
|
82
|
+
};
|
|
83
|
+
var ALIGN_CLASSES = {
|
|
84
|
+
start: "text-start",
|
|
85
|
+
center: "text-center",
|
|
86
|
+
end: "text-end"
|
|
87
|
+
};
|
|
88
|
+
var ICON_CLASSES = "inline-flex shrink-0 items-center [&>svg]:h-[1em] [&>svg]:w-[1em]";
|
|
89
|
+
function typographyClassName({
|
|
90
|
+
variant,
|
|
91
|
+
tone,
|
|
92
|
+
weight,
|
|
93
|
+
align,
|
|
94
|
+
truncate,
|
|
95
|
+
hasIcon,
|
|
96
|
+
className
|
|
97
|
+
}) {
|
|
98
|
+
return [
|
|
99
|
+
VARIANT_CLASSES[variant],
|
|
100
|
+
TONE_CLASSES[tone],
|
|
101
|
+
WEIGHT_CLASSES[weight],
|
|
102
|
+
align ? ALIGN_CLASSES[align] : "",
|
|
103
|
+
hasIcon ? "inline-flex items-center gap-1.5" : "",
|
|
104
|
+
// With an icon the root is a flex container, and text-overflow only
|
|
105
|
+
// clips block text, so the text span carries the truncation instead.
|
|
106
|
+
truncate && !hasIcon ? "truncate" : "",
|
|
107
|
+
className ?? ""
|
|
108
|
+
].filter(Boolean).join(" ");
|
|
109
|
+
}
|
|
110
|
+
function Typography({
|
|
111
|
+
variant = "body",
|
|
112
|
+
tone = "default",
|
|
113
|
+
weight,
|
|
114
|
+
align,
|
|
115
|
+
truncate = false,
|
|
116
|
+
icon,
|
|
117
|
+
iconPosition = "leading",
|
|
118
|
+
as,
|
|
119
|
+
asChild = false,
|
|
120
|
+
className,
|
|
121
|
+
children,
|
|
122
|
+
...rest
|
|
123
|
+
}) {
|
|
124
|
+
const hasIcon = icon !== void 0 && icon !== null;
|
|
125
|
+
const Component = asChild ? reactSlot.Slot : as ?? DEFAULT_ELEMENT[variant];
|
|
126
|
+
const iconNode = hasIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: ICON_CLASSES, children: icon }) : null;
|
|
127
|
+
const content = hasIcon ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
128
|
+
iconPosition === "leading" ? iconNode : null,
|
|
129
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: truncate ? "min-w-0 truncate" : void 0, children }),
|
|
130
|
+
iconPosition === "trailing" ? iconNode : null
|
|
131
|
+
] }) : children;
|
|
132
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
133
|
+
Component,
|
|
134
|
+
{
|
|
135
|
+
...rest,
|
|
136
|
+
className: typographyClassName({
|
|
137
|
+
variant,
|
|
138
|
+
tone,
|
|
139
|
+
weight: weight ?? DEFAULT_WEIGHT[variant],
|
|
140
|
+
align,
|
|
141
|
+
truncate,
|
|
142
|
+
hasIcon,
|
|
143
|
+
className
|
|
144
|
+
}),
|
|
145
|
+
children: content
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
}
|
|
38
149
|
|
|
39
150
|
exports.Cart = Cart;
|
|
151
|
+
exports.Typography = Typography;
|
|
40
152
|
//# sourceMappingURL=index.cjs.map
|
|
41
153
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/cart/index.tsx"],"names":["jsxs","jsx","Fragment"],"mappings":";;;;;AAkBA,SAAS,WAAA,CAAY,KAAA,EAAe,QAAA,EAAkB,MAAA,EAAgB;AACpE,EAAA,OAAO,IAAI,KAAK,YAAA,CAAa,MAAA,EAAQ,EAAE,KAAA,EAAO,UAAA,EAAY,QAAA,EAAU,CAAA,CAAE,MAAA;AAAA,IACpE;AAAA,GACF;AACF;AAEO,SAAS,IAAA,CAAK;AAAA,EACnB,WAAW,EAAC;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,MAAA,GAAS;AACX,CAAA,EAAc;AACZ,EAAA,MAAM,KAAA,GAAQ,SAAS,MAAA,CAAO,CAAC,KAAK,OAAA,KAAY,GAAA,GAAM,OAAA,CAAQ,KAAA,EAAO,CAAC,CAAA;AAEtE,EAAA,uBACEA,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yFAAA,EACb,QAAA,EAAA;AAAA,oBAAAC,cAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,qCAAA,EAAsC,QAAA,EAAA,MAAA,EAAI,CAAA;AAAA,IAEvD,QAAA,CAAS,WAAW,CAAA,mBACnBA,cAAA,CAAC,OAAE,SAAA,EAAU,uBAAA,EAAwB,QAAA,EAAA,qBAAA,EAAmB,CAAA,mBAExDD,eAAA,CAAAE,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAAD,cAAA,CAAC,QAAG,SAAA,EAAU,wCAAA,EACX,QAAA,EAAA,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,qBACbD,eAAA;AAAA,QAAC,IAAA;AAAA,QAAA;AAAA,UAEC,SAAA,EAAU,gDAAA;AAAA,UAEV,QAAA,EAAA;AAAA,4BAAAC,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uBAAA,EAAyB,QAAA,EAAA,OAAA,CAAQ,IAAA,EAAK,CAAA;AAAA,4BACtDA,cAAA,CAAC,UAAK,SAAA,EAAU,oCAAA,EACb,sBAAY,OAAA,CAAQ,KAAA,EAAO,QAAA,EAAU,MAAM,CAAA,EAC9C;AAAA;AAAA,SAAA;AAAA,QANK,OAAA,CAAQ,MAAM,OAAA,CAAQ;AAAA,OAQ9B,CAAA,EACH,CAAA;AAAA,sBAEAD,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yEAAA,EACb,QAAA,EAAA;AAAA,wBAAAC,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,mCAAA,EAAoC,QAAA,EAAA,OAAA,EAAK,CAAA;AAAA,wBACzDA,cAAA,CAAC,UAAK,SAAA,EAAU,kDAAA,EACb,sBAAY,KAAA,EAAO,QAAA,EAAU,MAAM,CAAA,EACtC;AAAA,OAAA,EACF;AAAA,KAAA,EACF;AAAA,GAAA,EAEJ,CAAA;AAEJ","file":"index.cjs","sourcesContent":["export type CartProduct = {\n /**\n * Stable identity for this line, used as the React key. Falls back to `name`,\n * so pass an `id` whenever a cart can hold two lines with the same name.\n */\n id?: string;\n name: string;\n price: number;\n};\n\nexport type CartProps = {\n products?: CartProduct[];\n /** ISO 4217 code used to format prices. */\n currency?: string;\n /** BCP 47 locale used to format prices. */\n locale?: string;\n};\n\nfunction formatPrice(value: number, currency: string, locale: string) {\n return new Intl.NumberFormat(locale, { style: \"currency\", currency }).format(\n value,\n );\n}\n\nexport function Cart({\n products = [],\n currency = \"KES\",\n locale = \"en-KE\",\n}: CartProps) {\n const total = products.reduce((sum, product) => sum + product.price, 0);\n\n return (\n <div className=\"cart flex w-full max-w-md flex-col gap-4 rounded-lg border border-gray-200 bg-white p-4\">\n <h1 className=\"text-xl font-semibold text-gray-900\">Cart</h1>\n\n {products.length === 0 ? (\n <p className=\"text-sm text-gray-500\">Your cart is empty.</p>\n ) : (\n <>\n <ul className=\"flex flex-col divide-y divide-gray-100\">\n {products.map((product) => (\n <li\n key={product.id ?? product.name}\n className=\"flex items-baseline justify-between gap-4 py-2\"\n >\n <span className=\"text-sm text-gray-800\">{product.name}</span>\n <span className=\"text-sm tabular-nums text-gray-600\">\n {formatPrice(product.price, currency, locale)}\n </span>\n </li>\n ))}\n </ul>\n\n <div className=\"flex items-baseline justify-between gap-4 border-t border-gray-200 pt-2\">\n <span className=\"text-sm font-medium text-gray-900\">Total</span>\n <span className=\"text-sm font-semibold tabular-nums text-gray-900\">\n {formatPrice(total, currency, locale)}\n </span>\n </div>\n </>\n )}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/cart/index.tsx","../src/components/typography/index.tsx"],"names":["jsxs","jsx","Fragment","Slot"],"mappings":"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","file":"index.cjs","sourcesContent":["export type CartProduct = {\n /**\n * Stable identity for this line, used as the React key. Falls back to `name`,\n * so pass an `id` whenever a cart can hold two lines with the same name.\n */\n id?: string;\n name: string;\n price: number;\n};\n\nexport type CartProps = {\n products?: CartProduct[];\n /** ISO 4217 code used to format prices. */\n currency?: string;\n /** BCP 47 locale used to format prices. */\n locale?: string;\n};\n\nfunction formatPrice(value: number, currency: string, locale: string) {\n return new Intl.NumberFormat(locale, { style: \"currency\", currency }).format(\n value,\n );\n}\n\nexport function Cart({\n products = [],\n currency = \"KES\",\n locale = \"en-KE\",\n}: CartProps) {\n const total = products.reduce((sum, product) => sum + product.price, 0);\n\n return (\n <div className=\"cart flex w-full max-w-md flex-col gap-4 rounded-lg border border-gray-200 bg-white p-4\">\n <h1 className=\"text-xl font-semibold text-gray-900\">Cart</h1>\n\n {products.length === 0 ? (\n <p className=\"text-sm text-gray-500\">Your cart is empty.</p>\n ) : (\n <>\n <ul className=\"flex flex-col divide-y divide-gray-100\">\n {products.map((product) => (\n <li\n key={product.id ?? product.name}\n className=\"flex items-baseline justify-between gap-4 py-2\"\n >\n <span className=\"text-sm text-gray-800\">{product.name}</span>\n <span className=\"text-sm tabular-nums text-gray-600\">\n {formatPrice(product.price, currency, locale)}\n </span>\n </li>\n ))}\n </ul>\n\n <div className=\"flex items-baseline justify-between gap-4 border-t border-gray-200 pt-2\">\n <span className=\"text-sm font-medium text-gray-900\">Total</span>\n <span className=\"text-sm font-semibold tabular-nums text-gray-900\">\n {formatPrice(total, currency, locale)}\n </span>\n </div>\n </>\n )}\n </div>\n );\n}\n","import { Slot } from \"@radix-ui/react-slot\";\nimport type { ElementType, HTMLAttributes, ReactNode, Ref } from \"react\";\n\n/**\n * The library's type scale. Everything that renders text — field labels, hints,\n * form errors, headings — goes through here, so a size or colour lives in one\n * place and the tokens in `src/styles/index.css` stay the single source of\n * truth for what \"hint\" or \"muted\" means.\n *\n * Server-safe: no state, no handlers, no directive. It composes Radix `Slot`\n * for `asChild`, which is how a consumer puts these styles on their own\n * element (a `next/link`, a Radix `Label`) without an extra wrapper.\n */\n\nexport type TypographyVariant =\n | \"display\"\n | \"heading\"\n | \"subheading\"\n | \"body\"\n | \"label\"\n | \"hint\"\n | \"code\";\n\nexport type TypographyTone =\n | \"default\"\n | \"muted\"\n | \"subtle\"\n | \"accent\"\n | \"on-accent\"\n | \"success\"\n | \"warning\"\n | \"info\"\n | \"danger\";\n\nexport type TypographyWeight = \"regular\" | \"medium\" | \"semibold\" | \"bold\";\n\nexport type TypographyElement =\n | \"p\"\n | \"span\"\n | \"div\"\n | \"h1\"\n | \"h2\"\n | \"h3\"\n | \"h4\"\n | \"h5\"\n | \"h6\"\n | \"label\"\n | \"code\"\n | \"strong\"\n | \"em\"\n | \"small\";\n\nexport type TypographyProps = Omit<HTMLAttributes<HTMLElement>, \"color\"> & {\n /** Size and default element. `body` unless told otherwise. */\n variant?: TypographyVariant;\n /** Colour role, from the design tokens. */\n tone?: TypographyTone;\n /** Overrides the variant's default weight. */\n weight?: TypographyWeight;\n align?: \"start\" | \"center\" | \"end\";\n /** Clip to one line with an ellipsis. */\n truncate?: boolean;\n /**\n * An icon rendered beside the text, hidden from assistive tech. Sized to the\n * text with `1em`, so the same SVG fits every variant.\n */\n icon?: ReactNode;\n iconPosition?: \"leading\" | \"trailing\";\n /** The element to render. Defaults per variant (`h2` for a heading, and so on). */\n as?: TypographyElement;\n /**\n * Radix-style composition: render the child element itself, with these\n * styles merged onto it, instead of a wrapper. Takes precedence over `as`.\n */\n asChild?: boolean;\n ref?: Ref<HTMLElement>;\n children?: ReactNode;\n};\n\nconst DEFAULT_ELEMENT: Record<TypographyVariant, TypographyElement> = {\n display: \"h1\",\n heading: \"h2\",\n subheading: \"h3\",\n body: \"p\",\n label: \"span\",\n hint: \"p\",\n code: \"code\",\n};\n\nconst DEFAULT_WEIGHT: Record<TypographyVariant, TypographyWeight> = {\n display: \"semibold\",\n heading: \"semibold\",\n subheading: \"medium\",\n body: \"regular\",\n label: \"semibold\",\n hint: \"regular\",\n code: \"regular\",\n};\n\nconst VARIANT_CLASSES: Record<TypographyVariant, string> = {\n display: \"text-display leading-tight tracking-tight\",\n heading: \"text-heading leading-tight tracking-tight\",\n subheading: \"text-subheading leading-snug\",\n body: \"text-field leading-normal\",\n label: \"text-label leading-normal\",\n hint: \"text-hint leading-normal\",\n code: \"font-code text-field leading-normal\",\n};\n\nconst TONE_CLASSES: Record<TypographyTone, string> = {\n default: \"text-fg\",\n muted: \"text-fg-muted\",\n subtle: \"text-fg-subtle\",\n accent: \"text-accent\",\n \"on-accent\": \"text-on-accent\",\n success: \"text-success\",\n warning: \"text-warning\",\n info: \"text-info\",\n danger: \"text-danger\",\n};\n\nconst WEIGHT_CLASSES: Record<TypographyWeight, string> = {\n regular: \"font-normal\",\n medium: \"font-medium\",\n semibold: \"font-semibold\",\n bold: \"font-bold\",\n};\n\nconst ALIGN_CLASSES = {\n start: \"text-start\",\n center: \"text-center\",\n end: \"text-end\",\n} as const;\n\nconst ICON_CLASSES =\n \"inline-flex shrink-0 items-center [&>svg]:h-[1em] [&>svg]:w-[1em]\";\n\nfunction typographyClassName({\n variant,\n tone,\n weight,\n align,\n truncate,\n hasIcon,\n className,\n}: {\n variant: TypographyVariant;\n tone: TypographyTone;\n weight: TypographyWeight;\n align: \"start\" | \"center\" | \"end\" | undefined;\n truncate: boolean;\n hasIcon: boolean;\n className: string | undefined;\n}): string {\n return [\n VARIANT_CLASSES[variant],\n TONE_CLASSES[tone],\n WEIGHT_CLASSES[weight],\n align ? ALIGN_CLASSES[align] : \"\",\n hasIcon ? \"inline-flex items-center gap-1.5\" : \"\",\n // With an icon the root is a flex container, and text-overflow only\n // clips block text, so the text span carries the truncation instead.\n truncate && !hasIcon ? \"truncate\" : \"\",\n className ?? \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n}\n\nexport function Typography({\n variant = \"body\",\n tone = \"default\",\n weight,\n align,\n truncate = false,\n icon,\n iconPosition = \"leading\",\n as,\n asChild = false,\n className,\n children,\n ...rest\n}: TypographyProps) {\n const hasIcon = icon !== undefined && icon !== null;\n // Widened to `ElementType`: the union of intrinsic tags would otherwise\n // demand a `ref` typed to one specific element.\n const Component: ElementType = asChild\n ? Slot\n : (as ?? DEFAULT_ELEMENT[variant]);\n\n const iconNode = hasIcon ? (\n <span aria-hidden=\"true\" className={ICON_CLASSES}>\n {icon}\n </span>\n ) : null;\n\n const content = hasIcon ? (\n <>\n {iconPosition === \"leading\" ? iconNode : null}\n <span className={truncate ? \"min-w-0 truncate\" : undefined}>\n {children}\n </span>\n {iconPosition === \"trailing\" ? iconNode : null}\n </>\n ) : (\n children\n );\n\n return (\n <Component\n {...rest}\n className={typographyClassName({\n variant,\n tone,\n weight: weight ?? DEFAULT_WEIGHT[variant],\n align,\n truncate,\n hasIcon,\n className,\n })}\n >\n {content}\n </Component>\n );\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { Cart, CartProduct, CartProps } from './cart.cjs';
|
|
2
2
|
import { InputHTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
export { Typography, TypographyElement, TypographyProps, TypographyTone, TypographyVariant, TypographyWeight } from './typography.cjs';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Structural shape of a zod schema — every zod schema satisfies it, and any
|
|
@@ -7,7 +8,7 @@ import { InputHTMLAttributes, ReactNode } from 'react';
|
|
|
7
8
|
* keeps zod out of this module's public types, so consumers who only want an
|
|
8
9
|
* input do not have to install zod to typecheck it.
|
|
9
10
|
*/
|
|
10
|
-
type
|
|
11
|
+
type FieldSchema = {
|
|
11
12
|
safeParse: (value: unknown) => {
|
|
12
13
|
success: true;
|
|
13
14
|
} | {
|
|
@@ -20,12 +21,14 @@ type TextInputSchema = {
|
|
|
20
21
|
};
|
|
21
22
|
};
|
|
22
23
|
/** Outcome of a single validation pass, handed to `onValidationChange`. */
|
|
23
|
-
type
|
|
24
|
+
type FieldValidation = {
|
|
24
25
|
valid: boolean;
|
|
25
26
|
/** First issue reported by the schema, or `undefined` when valid. */
|
|
26
27
|
error?: string;
|
|
27
28
|
};
|
|
28
|
-
|
|
29
|
+
|
|
30
|
+
/** Props every specialised input shares. `type` is fixed by the wrapper. */
|
|
31
|
+
type FieldProps = Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "defaultValue" | "type"> & {
|
|
29
32
|
label?: string;
|
|
30
33
|
/** Guidance under the field. Replaced by the error message while invalid. */
|
|
31
34
|
hint?: ReactNode;
|
|
@@ -41,9 +44,6 @@ type TextInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "
|
|
|
41
44
|
action?: ReactNode;
|
|
42
45
|
/** Trailing in-field slot, for affordances like the design's password peek. */
|
|
43
46
|
trailing?: ReactNode;
|
|
44
|
-
/** Renders the value in the design's monospace face. */
|
|
45
|
-
mono?: boolean;
|
|
46
|
-
type?: "text" | "email" | "password" | "tel" | "url" | "search";
|
|
47
47
|
value?: string;
|
|
48
48
|
defaultValue?: string;
|
|
49
49
|
onChange?: (value: string) => void;
|
|
@@ -51,14 +51,53 @@ type TextInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "
|
|
|
51
51
|
* Any zod schema that accepts a string. Only `safeParse` is used, so a
|
|
52
52
|
* refined, transformed or preprocessed schema works as well as a plain one.
|
|
53
53
|
*/
|
|
54
|
-
schema?:
|
|
54
|
+
schema?: FieldSchema;
|
|
55
55
|
/**
|
|
56
56
|
* When the schema runs. `blur` — the default — avoids scolding someone
|
|
57
57
|
* mid-keystroke; once a field has gone invalid it revalidates on every
|
|
58
58
|
* keystroke so the message clears as soon as it is fixed.
|
|
59
59
|
*/
|
|
60
60
|
validateOn?: "blur" | "change" | "never";
|
|
61
|
-
onValidationChange?: (state:
|
|
61
|
+
onValidationChange?: (state: FieldValidation) => void;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 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.
|
|
69
|
+
*/
|
|
70
|
+
type EmailInputProps = FieldProps;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* A password. Fixes `type="password"` and owns the design's in-field peek
|
|
74
|
+
* affordance, so the trailing slot is not exposed here — the toggle is it.
|
|
75
|
+
*/
|
|
76
|
+
type PasswordInputProps = Omit<FieldProps, "trailing"> & {
|
|
77
|
+
/** Show the "Show"/"Hide" toggle. On by default, as the design has it. */
|
|
78
|
+
revealable?: boolean;
|
|
79
|
+
/** Labels for the toggle, for localisation. */
|
|
80
|
+
revealLabels?: {
|
|
81
|
+
show: string;
|
|
82
|
+
hide: string;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* A phone number. Fixes `type="tel"` and the numeric keypad. Pair it with
|
|
88
|
+
* `phoneSchema` from `@carbonbits/sixr/validation` to validate inline.
|
|
89
|
+
*/
|
|
90
|
+
type PhoneInputProps = FieldProps;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Plain free text: names, job titles, one-time codes. Anything with a format
|
|
94
|
+
* of its own — an email address, a phone number, a password — has its own
|
|
95
|
+
* component (`EmailInput`, `PhoneInput`, `PasswordInput`), which fixes the
|
|
96
|
+
* keyboard, autocomplete and input type that format needs.
|
|
97
|
+
*/
|
|
98
|
+
type TextInputProps = FieldProps & {
|
|
99
|
+
/** Renders the value in the design's monospace face, as the code entry does. */
|
|
100
|
+
mono?: boolean;
|
|
62
101
|
};
|
|
63
102
|
|
|
64
|
-
export type {
|
|
103
|
+
export type { EmailInputProps, FieldProps, FieldSchema, FieldValidation, PasswordInputProps, PhoneInputProps, TextInputProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { Cart, CartProduct, CartProps } from './cart.js';
|
|
2
2
|
import { InputHTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
export { Typography, TypographyElement, TypographyProps, TypographyTone, TypographyVariant, TypographyWeight } from './typography.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Structural shape of a zod schema — every zod schema satisfies it, and any
|
|
@@ -7,7 +8,7 @@ import { InputHTMLAttributes, ReactNode } from 'react';
|
|
|
7
8
|
* keeps zod out of this module's public types, so consumers who only want an
|
|
8
9
|
* input do not have to install zod to typecheck it.
|
|
9
10
|
*/
|
|
10
|
-
type
|
|
11
|
+
type FieldSchema = {
|
|
11
12
|
safeParse: (value: unknown) => {
|
|
12
13
|
success: true;
|
|
13
14
|
} | {
|
|
@@ -20,12 +21,14 @@ type TextInputSchema = {
|
|
|
20
21
|
};
|
|
21
22
|
};
|
|
22
23
|
/** Outcome of a single validation pass, handed to `onValidationChange`. */
|
|
23
|
-
type
|
|
24
|
+
type FieldValidation = {
|
|
24
25
|
valid: boolean;
|
|
25
26
|
/** First issue reported by the schema, or `undefined` when valid. */
|
|
26
27
|
error?: string;
|
|
27
28
|
};
|
|
28
|
-
|
|
29
|
+
|
|
30
|
+
/** Props every specialised input shares. `type` is fixed by the wrapper. */
|
|
31
|
+
type FieldProps = Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "defaultValue" | "type"> & {
|
|
29
32
|
label?: string;
|
|
30
33
|
/** Guidance under the field. Replaced by the error message while invalid. */
|
|
31
34
|
hint?: ReactNode;
|
|
@@ -41,9 +44,6 @@ type TextInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "
|
|
|
41
44
|
action?: ReactNode;
|
|
42
45
|
/** Trailing in-field slot, for affordances like the design's password peek. */
|
|
43
46
|
trailing?: ReactNode;
|
|
44
|
-
/** Renders the value in the design's monospace face. */
|
|
45
|
-
mono?: boolean;
|
|
46
|
-
type?: "text" | "email" | "password" | "tel" | "url" | "search";
|
|
47
47
|
value?: string;
|
|
48
48
|
defaultValue?: string;
|
|
49
49
|
onChange?: (value: string) => void;
|
|
@@ -51,14 +51,53 @@ type TextInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "
|
|
|
51
51
|
* Any zod schema that accepts a string. Only `safeParse` is used, so a
|
|
52
52
|
* refined, transformed or preprocessed schema works as well as a plain one.
|
|
53
53
|
*/
|
|
54
|
-
schema?:
|
|
54
|
+
schema?: FieldSchema;
|
|
55
55
|
/**
|
|
56
56
|
* When the schema runs. `blur` — the default — avoids scolding someone
|
|
57
57
|
* mid-keystroke; once a field has gone invalid it revalidates on every
|
|
58
58
|
* keystroke so the message clears as soon as it is fixed.
|
|
59
59
|
*/
|
|
60
60
|
validateOn?: "blur" | "change" | "never";
|
|
61
|
-
onValidationChange?: (state:
|
|
61
|
+
onValidationChange?: (state: FieldValidation) => void;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 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.
|
|
69
|
+
*/
|
|
70
|
+
type EmailInputProps = FieldProps;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* A password. Fixes `type="password"` and owns the design's in-field peek
|
|
74
|
+
* affordance, so the trailing slot is not exposed here — the toggle is it.
|
|
75
|
+
*/
|
|
76
|
+
type PasswordInputProps = Omit<FieldProps, "trailing"> & {
|
|
77
|
+
/** Show the "Show"/"Hide" toggle. On by default, as the design has it. */
|
|
78
|
+
revealable?: boolean;
|
|
79
|
+
/** Labels for the toggle, for localisation. */
|
|
80
|
+
revealLabels?: {
|
|
81
|
+
show: string;
|
|
82
|
+
hide: string;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* A phone number. Fixes `type="tel"` and the numeric keypad. Pair it with
|
|
88
|
+
* `phoneSchema` from `@carbonbits/sixr/validation` to validate inline.
|
|
89
|
+
*/
|
|
90
|
+
type PhoneInputProps = FieldProps;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Plain free text: names, job titles, one-time codes. Anything with a format
|
|
94
|
+
* of its own — an email address, a phone number, a password — has its own
|
|
95
|
+
* component (`EmailInput`, `PhoneInput`, `PasswordInput`), which fixes the
|
|
96
|
+
* keyboard, autocomplete and input type that format needs.
|
|
97
|
+
*/
|
|
98
|
+
type TextInputProps = FieldProps & {
|
|
99
|
+
/** Renders the value in the design's monospace face, as the code entry does. */
|
|
100
|
+
mono?: boolean;
|
|
62
101
|
};
|
|
63
102
|
|
|
64
|
-
export type {
|
|
103
|
+
export type { EmailInputProps, FieldProps, FieldSchema, FieldValidation, PasswordInputProps, PhoneInputProps, TextInputProps };
|
package/dist/index.js
CHANGED