@ladder-ui/field 0.2.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/dist/field.css +47 -0
- package/dist/field.d.ts +97 -0
- package/dist/field.vars.css +15 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +78 -0
- package/dist/index.mjs +72 -0
- package/package.json +70 -0
package/dist/field.css
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
@layer components {
|
|
2
|
+
.lui-field {
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
gap: var(--lui-field-gap);
|
|
6
|
+
}
|
|
7
|
+
.lui-field--horizontal {
|
|
8
|
+
flex-direction: row;
|
|
9
|
+
align-items: center;
|
|
10
|
+
flex-wrap: wrap;
|
|
11
|
+
gap: var(--lui-field-gap);
|
|
12
|
+
}
|
|
13
|
+
.lui-field[data-disabled=true] .lui-field-label,
|
|
14
|
+
.lui-field[data-disabled=true] .lui-field-description {
|
|
15
|
+
opacity: 0.5;
|
|
16
|
+
}
|
|
17
|
+
.lui-field[data-invalid=true] .lui-field-label {
|
|
18
|
+
color: var(--lui-field-error-color);
|
|
19
|
+
}
|
|
20
|
+
.lui-field-label {
|
|
21
|
+
display: block;
|
|
22
|
+
color: var(--lui-field-label-color);
|
|
23
|
+
font-family: var(--lui-font-family);
|
|
24
|
+
font-size: var(--lui-field-label-size);
|
|
25
|
+
font-weight: 500;
|
|
26
|
+
line-height: 1.4;
|
|
27
|
+
}
|
|
28
|
+
.lui-field-description {
|
|
29
|
+
margin: 0;
|
|
30
|
+
color: var(--lui-field-description-color);
|
|
31
|
+
font-family: var(--lui-font-family);
|
|
32
|
+
font-size: var(--lui-field-description-size);
|
|
33
|
+
line-height: 1.5;
|
|
34
|
+
}
|
|
35
|
+
.lui-field-error {
|
|
36
|
+
margin: 0;
|
|
37
|
+
color: var(--lui-field-error-color);
|
|
38
|
+
font-family: var(--lui-font-family);
|
|
39
|
+
font-size: var(--lui-field-error-size);
|
|
40
|
+
line-height: 1.5;
|
|
41
|
+
}
|
|
42
|
+
.lui-field-group {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-direction: column;
|
|
45
|
+
gap: var(--lui-field-group-gap);
|
|
46
|
+
}
|
|
47
|
+
}
|
package/dist/field.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { HTMLAttributes, Ref } from "react";
|
|
2
|
+
import { type LabelProps } from "@ladder-ui/label";
|
|
3
|
+
export interface FieldProps extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
/** React 19 ref — points to the wrapper `<div>` */
|
|
5
|
+
ref?: Ref<HTMLDivElement>;
|
|
6
|
+
/**
|
|
7
|
+
* Layout orientation.
|
|
8
|
+
* - `"vertical"` (default): label stacked above the control
|
|
9
|
+
* - `"horizontal"`: label and control side by side
|
|
10
|
+
*/
|
|
11
|
+
orientation?: "vertical" | "horizontal";
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Field — semantic wrapper for a single form field.
|
|
15
|
+
*
|
|
16
|
+
* Provides layout (label + control + description + error) and propagates
|
|
17
|
+
* disabled/invalid state to child components via `data-disabled` / `data-invalid`
|
|
18
|
+
* HTML attributes, which are picked up by CSS selectors.
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* ```tsx
|
|
22
|
+
* <Field>
|
|
23
|
+
* <FieldLabel htmlFor="email">Email</FieldLabel>
|
|
24
|
+
* <Input id="email" type="email" />
|
|
25
|
+
* <FieldDescription>We'll never share your email.</FieldDescription>
|
|
26
|
+
* </Field>
|
|
27
|
+
*
|
|
28
|
+
* <Field data-invalid="true">
|
|
29
|
+
* <FieldLabel htmlFor="user">Username</FieldLabel>
|
|
30
|
+
* <Input id="user" status="error" aria-invalid="true" />
|
|
31
|
+
* <FieldError>Username already taken.</FieldError>
|
|
32
|
+
* </Field>
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function Field({ ref, className, orientation, ...props }: FieldProps): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
export declare namespace Field {
|
|
37
|
+
var displayName: string;
|
|
38
|
+
}
|
|
39
|
+
export interface FieldLabelProps extends LabelProps {
|
|
40
|
+
/**
|
|
41
|
+
* React 19 ref — points to the `<label>` element.
|
|
42
|
+
* Inherited from LabelProps.
|
|
43
|
+
*/
|
|
44
|
+
ref?: Ref<HTMLLabelElement>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* FieldLabel — a `Label` scoped to a `Field` compound component.
|
|
48
|
+
*
|
|
49
|
+
* Wraps `@ladder-ui/label`'s `Label` and adds the `lui-field-label` class so
|
|
50
|
+
* the parent `Field` can apply context-aware styles:
|
|
51
|
+
* - Dims when `<Field data-disabled="true">` is set
|
|
52
|
+
* - Turns error-color when `<Field data-invalid="true">` is set
|
|
53
|
+
*
|
|
54
|
+
* For labels **outside a Field** context, use `Label` from `@ladder-ui/label`
|
|
55
|
+
* directly — it provides the same accessible `<label>` element with styling
|
|
56
|
+
* but without the Field-specific context.
|
|
57
|
+
*/
|
|
58
|
+
export declare function FieldLabel({ ref, className, ...props }: FieldLabelProps): import("react/jsx-runtime").JSX.Element;
|
|
59
|
+
export declare namespace FieldLabel {
|
|
60
|
+
var displayName: string;
|
|
61
|
+
}
|
|
62
|
+
export interface FieldDescriptionProps extends HTMLAttributes<HTMLParagraphElement> {
|
|
63
|
+
/** React 19 ref — points to the `<p>` element */
|
|
64
|
+
ref?: Ref<HTMLParagraphElement>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* FieldDescription — muted helper text rendered below the control.
|
|
68
|
+
* Dims automatically when the parent `<Field>` has `data-disabled="true"`.
|
|
69
|
+
*/
|
|
70
|
+
export declare function FieldDescription({ ref, className, ...props }: FieldDescriptionProps): import("react/jsx-runtime").JSX.Element;
|
|
71
|
+
export declare namespace FieldDescription {
|
|
72
|
+
var displayName: string;
|
|
73
|
+
}
|
|
74
|
+
export interface FieldErrorProps extends HTMLAttributes<HTMLParagraphElement> {
|
|
75
|
+
/** React 19 ref — points to the `<p>` element */
|
|
76
|
+
ref?: Ref<HTMLParagraphElement>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* FieldError — error text rendered below the control.
|
|
80
|
+
* Has `role="alert"` for live-region announcements.
|
|
81
|
+
* Only meaningful when the parent `<Field>` has `data-invalid="true"`.
|
|
82
|
+
*/
|
|
83
|
+
export declare function FieldError({ ref, className, ...props }: FieldErrorProps): import("react/jsx-runtime").JSX.Element;
|
|
84
|
+
export declare namespace FieldError {
|
|
85
|
+
var displayName: string;
|
|
86
|
+
}
|
|
87
|
+
export interface FieldGroupProps extends HTMLAttributes<HTMLDivElement> {
|
|
88
|
+
/** React 19 ref — points to the wrapper `<div>` */
|
|
89
|
+
ref?: Ref<HTMLDivElement>;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* FieldGroup — groups multiple `<Field>` elements with a consistent vertical gap.
|
|
93
|
+
*/
|
|
94
|
+
export declare function FieldGroup({ ref, className, ...props }: FieldGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
95
|
+
export declare namespace FieldGroup {
|
|
96
|
+
var displayName: string;
|
|
97
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
:root {
|
|
3
|
+
/* Layout */
|
|
4
|
+
--lui-field-gap: 0.375rem;
|
|
5
|
+
--lui-field-group-gap: 1rem;
|
|
6
|
+
/* Label — field-specific overrides of @ladder-ui/label base tokens */
|
|
7
|
+
--lui-field-label-color: var(--lui-surface-text);
|
|
8
|
+
--lui-field-label-size: var(--lui-font-size-sm);
|
|
9
|
+
/* Description */
|
|
10
|
+
--lui-field-description-color: color-mix(in srgb, var(--lui-surface-text) 60%, transparent);
|
|
11
|
+
--lui-field-description-size: var(--lui-font-size-xs);
|
|
12
|
+
/* Error */
|
|
13
|
+
--lui-field-error-color: var(--lui-error);
|
|
14
|
+
--lui-field-error-size: var(--lui-font-size-xs);
|
|
15
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var concatClassNames = require('@ladder-ui/core/concatClassNames');
|
|
5
|
+
var label = require('@ladder-ui/label');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Field — semantic wrapper for a single form field.
|
|
9
|
+
*
|
|
10
|
+
* Provides layout (label + control + description + error) and propagates
|
|
11
|
+
* disabled/invalid state to child components via `data-disabled` / `data-invalid`
|
|
12
|
+
* HTML attributes, which are picked up by CSS selectors.
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* ```tsx
|
|
16
|
+
* <Field>
|
|
17
|
+
* <FieldLabel htmlFor="email">Email</FieldLabel>
|
|
18
|
+
* <Input id="email" type="email" />
|
|
19
|
+
* <FieldDescription>We'll never share your email.</FieldDescription>
|
|
20
|
+
* </Field>
|
|
21
|
+
*
|
|
22
|
+
* <Field data-invalid="true">
|
|
23
|
+
* <FieldLabel htmlFor="user">Username</FieldLabel>
|
|
24
|
+
* <Input id="user" status="error" aria-invalid="true" />
|
|
25
|
+
* <FieldError>Username already taken.</FieldError>
|
|
26
|
+
* </Field>
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
function Field({ ref, className, orientation = "vertical", ...props }) {
|
|
30
|
+
return (jsxRuntime.jsx("div", { ref: ref, className: concatClassNames("lui-field", orientation === "horizontal" && "lui-field--horizontal", className), ...props }));
|
|
31
|
+
}
|
|
32
|
+
Field.displayName = "Field";
|
|
33
|
+
/**
|
|
34
|
+
* FieldLabel — a `Label` scoped to a `Field` compound component.
|
|
35
|
+
*
|
|
36
|
+
* Wraps `@ladder-ui/label`'s `Label` and adds the `lui-field-label` class so
|
|
37
|
+
* the parent `Field` can apply context-aware styles:
|
|
38
|
+
* - Dims when `<Field data-disabled="true">` is set
|
|
39
|
+
* - Turns error-color when `<Field data-invalid="true">` is set
|
|
40
|
+
*
|
|
41
|
+
* For labels **outside a Field** context, use `Label` from `@ladder-ui/label`
|
|
42
|
+
* directly — it provides the same accessible `<label>` element with styling
|
|
43
|
+
* but without the Field-specific context.
|
|
44
|
+
*/
|
|
45
|
+
function FieldLabel({ ref, className, ...props }) {
|
|
46
|
+
return (jsxRuntime.jsx(label.Label, { ref: ref, className: concatClassNames("lui-field-label", className), ...props }));
|
|
47
|
+
}
|
|
48
|
+
FieldLabel.displayName = "FieldLabel";
|
|
49
|
+
/**
|
|
50
|
+
* FieldDescription — muted helper text rendered below the control.
|
|
51
|
+
* Dims automatically when the parent `<Field>` has `data-disabled="true"`.
|
|
52
|
+
*/
|
|
53
|
+
function FieldDescription({ ref, className, ...props }) {
|
|
54
|
+
return (jsxRuntime.jsx("p", { ref: ref, className: concatClassNames("lui-field-description", className), ...props }));
|
|
55
|
+
}
|
|
56
|
+
FieldDescription.displayName = "FieldDescription";
|
|
57
|
+
/**
|
|
58
|
+
* FieldError — error text rendered below the control.
|
|
59
|
+
* Has `role="alert"` for live-region announcements.
|
|
60
|
+
* Only meaningful when the parent `<Field>` has `data-invalid="true"`.
|
|
61
|
+
*/
|
|
62
|
+
function FieldError({ ref, className, ...props }) {
|
|
63
|
+
return (jsxRuntime.jsx("p", { ref: ref, role: "alert", className: concatClassNames("lui-field-error", className), ...props }));
|
|
64
|
+
}
|
|
65
|
+
FieldError.displayName = "FieldError";
|
|
66
|
+
/**
|
|
67
|
+
* FieldGroup — groups multiple `<Field>` elements with a consistent vertical gap.
|
|
68
|
+
*/
|
|
69
|
+
function FieldGroup({ ref, className, ...props }) {
|
|
70
|
+
return (jsxRuntime.jsx("div", { ref: ref, className: concatClassNames("lui-field-group", className), ...props }));
|
|
71
|
+
}
|
|
72
|
+
FieldGroup.displayName = "FieldGroup";
|
|
73
|
+
|
|
74
|
+
exports.Field = Field;
|
|
75
|
+
exports.FieldDescription = FieldDescription;
|
|
76
|
+
exports.FieldError = FieldError;
|
|
77
|
+
exports.FieldGroup = FieldGroup;
|
|
78
|
+
exports.FieldLabel = FieldLabel;
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import concatClassNames from '@ladder-ui/core/concatClassNames';
|
|
3
|
+
import { Label } from '@ladder-ui/label';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Field — semantic wrapper for a single form field.
|
|
7
|
+
*
|
|
8
|
+
* Provides layout (label + control + description + error) and propagates
|
|
9
|
+
* disabled/invalid state to child components via `data-disabled` / `data-invalid`
|
|
10
|
+
* HTML attributes, which are picked up by CSS selectors.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <Field>
|
|
15
|
+
* <FieldLabel htmlFor="email">Email</FieldLabel>
|
|
16
|
+
* <Input id="email" type="email" />
|
|
17
|
+
* <FieldDescription>We'll never share your email.</FieldDescription>
|
|
18
|
+
* </Field>
|
|
19
|
+
*
|
|
20
|
+
* <Field data-invalid="true">
|
|
21
|
+
* <FieldLabel htmlFor="user">Username</FieldLabel>
|
|
22
|
+
* <Input id="user" status="error" aria-invalid="true" />
|
|
23
|
+
* <FieldError>Username already taken.</FieldError>
|
|
24
|
+
* </Field>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
function Field({ ref, className, orientation = "vertical", ...props }) {
|
|
28
|
+
return (jsx("div", { ref: ref, className: concatClassNames("lui-field", orientation === "horizontal" && "lui-field--horizontal", className), ...props }));
|
|
29
|
+
}
|
|
30
|
+
Field.displayName = "Field";
|
|
31
|
+
/**
|
|
32
|
+
* FieldLabel — a `Label` scoped to a `Field` compound component.
|
|
33
|
+
*
|
|
34
|
+
* Wraps `@ladder-ui/label`'s `Label` and adds the `lui-field-label` class so
|
|
35
|
+
* the parent `Field` can apply context-aware styles:
|
|
36
|
+
* - Dims when `<Field data-disabled="true">` is set
|
|
37
|
+
* - Turns error-color when `<Field data-invalid="true">` is set
|
|
38
|
+
*
|
|
39
|
+
* For labels **outside a Field** context, use `Label` from `@ladder-ui/label`
|
|
40
|
+
* directly — it provides the same accessible `<label>` element with styling
|
|
41
|
+
* but without the Field-specific context.
|
|
42
|
+
*/
|
|
43
|
+
function FieldLabel({ ref, className, ...props }) {
|
|
44
|
+
return (jsx(Label, { ref: ref, className: concatClassNames("lui-field-label", className), ...props }));
|
|
45
|
+
}
|
|
46
|
+
FieldLabel.displayName = "FieldLabel";
|
|
47
|
+
/**
|
|
48
|
+
* FieldDescription — muted helper text rendered below the control.
|
|
49
|
+
* Dims automatically when the parent `<Field>` has `data-disabled="true"`.
|
|
50
|
+
*/
|
|
51
|
+
function FieldDescription({ ref, className, ...props }) {
|
|
52
|
+
return (jsx("p", { ref: ref, className: concatClassNames("lui-field-description", className), ...props }));
|
|
53
|
+
}
|
|
54
|
+
FieldDescription.displayName = "FieldDescription";
|
|
55
|
+
/**
|
|
56
|
+
* FieldError — error text rendered below the control.
|
|
57
|
+
* Has `role="alert"` for live-region announcements.
|
|
58
|
+
* Only meaningful when the parent `<Field>` has `data-invalid="true"`.
|
|
59
|
+
*/
|
|
60
|
+
function FieldError({ ref, className, ...props }) {
|
|
61
|
+
return (jsx("p", { ref: ref, role: "alert", className: concatClassNames("lui-field-error", className), ...props }));
|
|
62
|
+
}
|
|
63
|
+
FieldError.displayName = "FieldError";
|
|
64
|
+
/**
|
|
65
|
+
* FieldGroup — groups multiple `<Field>` elements with a consistent vertical gap.
|
|
66
|
+
*/
|
|
67
|
+
function FieldGroup({ ref, className, ...props }) {
|
|
68
|
+
return (jsx("div", { ref: ref, className: concatClassNames("lui-field-group", className), ...props }));
|
|
69
|
+
}
|
|
70
|
+
FieldGroup.displayName = "FieldGroup";
|
|
71
|
+
|
|
72
|
+
export { Field, FieldDescription, FieldError, FieldGroup, FieldLabel };
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ladder-ui/field",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./*.css": "./dist/*.css",
|
|
15
|
+
"./styles/*.css": "./dist/*.css"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"keywords": [
|
|
21
|
+
"nodejs",
|
|
22
|
+
"react",
|
|
23
|
+
"ui",
|
|
24
|
+
"components",
|
|
25
|
+
"library",
|
|
26
|
+
"field",
|
|
27
|
+
"form",
|
|
28
|
+
"label"
|
|
29
|
+
],
|
|
30
|
+
"author": "Ivan Avila <ivelaval@gmail.com> - https://www.vennet.dev",
|
|
31
|
+
"license": "ISC",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+ssh://git@github.com/ivelaval/ladder-ui.git"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/ivelaval/ladder-ui/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/ivelaval/ladder-ui#readme",
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
45
|
+
"@types/react": "^19.0.0",
|
|
46
|
+
"rollup": "^4.59.0",
|
|
47
|
+
"rollup-plugin-postcss": "^4.0.2",
|
|
48
|
+
"sass": "^1.90.0",
|
|
49
|
+
"tslib": "^2.6.2",
|
|
50
|
+
"typescript": "^5.3.3",
|
|
51
|
+
"@ladder-ui/core": "0.2.0",
|
|
52
|
+
"@ladder-ui/label": "0.2.0"
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"@ladder-ui/core": ">=0.0.0",
|
|
56
|
+
"@ladder-ui/label": ">=0.0.0",
|
|
57
|
+
"react": ">=18.0.0"
|
|
58
|
+
},
|
|
59
|
+
"sideEffects": [
|
|
60
|
+
"**/*.css"
|
|
61
|
+
],
|
|
62
|
+
"scripts": {
|
|
63
|
+
"build": "pnpm clean && rollup -c",
|
|
64
|
+
"dev": "rollup -c -w",
|
|
65
|
+
"test": "vitest run",
|
|
66
|
+
"test:watch": "vitest",
|
|
67
|
+
"type-check": "tsc --noEmit",
|
|
68
|
+
"clean": "rm -rf dist"
|
|
69
|
+
}
|
|
70
|
+
}
|