@apliteni/apliteni-ui 0.60.0 → 0.61.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/package.json +1 -1
- package/react/README.md +17 -1
- package/react/dist/index.css +4 -0
- package/react/dist/index.d.ts +25 -3
- package/react/dist/index.js +17 -5
- package/src/styles/input.css +14 -0
package/package.json
CHANGED
package/react/README.md
CHANGED
|
@@ -433,7 +433,10 @@ Import both the kit CSS and React CSS. The Privileged story shows Undo adding a
|
|
|
433
433
|
|
|
434
434
|
`TextField`, `TextArea`, `SelectField`, and `FileField` pair a label with a native
|
|
435
435
|
control. Each creates its own IDs and links hints or errors automatically. Use
|
|
436
|
-
native control props. `SelectField` accepts option children.
|
|
436
|
+
native control props. `SelectField` accepts option children. `TextField` takes
|
|
437
|
+
text, number, email, password and search, forwards its ref to the input, and
|
|
438
|
+
places a decorative kit glyph with `icon` — the same glyph names `Button` and
|
|
439
|
+
`Dropdown` take. Number fields can combine a glyph with a `unit`.
|
|
437
440
|
|
|
438
441
|
```tsx
|
|
439
442
|
<TextField label="Weight" type="number" unit="kg" required />
|
|
@@ -447,6 +450,19 @@ native control props. `SelectField` accepts option children.
|
|
|
447
450
|
`onFileChange`. Use `accept` and `hint` to describe allowed file types and size.
|
|
448
451
|
Your application must validate files before upload.
|
|
449
452
|
|
|
453
|
+
Use `Field` when an existing labelled control needs the kit frame. Spread its
|
|
454
|
+
render-prop attributes onto one labelable control, and apply the existing control
|
|
455
|
+
class and invalid styling as appropriate:
|
|
456
|
+
|
|
457
|
+
```tsx
|
|
458
|
+
<Field label="Due date" hint="Use the delivery date." required>
|
|
459
|
+
{control => <input {...control} className="ui-input" type="date" />}
|
|
460
|
+
</Field>
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
The frame supplies a stable ID, required state, and linked hint/error messages.
|
|
464
|
+
An optional `id` lets the caller choose the control ID; it must be unique.
|
|
465
|
+
|
|
450
466
|
## Toast
|
|
451
467
|
|
|
452
468
|
Wrap your app in `Toast`, then call `useToast()` inside it to add a notice.
|
package/react/dist/index.css
CHANGED
package/react/dist/index.d.ts
CHANGED
|
@@ -546,11 +546,33 @@ type FieldMessage = {
|
|
|
546
546
|
error?: string;
|
|
547
547
|
};
|
|
548
548
|
type Wiring = 'id' | 'aria-describedby' | 'aria-invalid';
|
|
549
|
+
type FieldControlProps = {
|
|
550
|
+
id: string;
|
|
551
|
+
'aria-describedby'?: string;
|
|
552
|
+
'aria-invalid'?: true;
|
|
553
|
+
required?: boolean;
|
|
554
|
+
};
|
|
555
|
+
type FieldProps = FieldMessage & {
|
|
556
|
+
id?: string;
|
|
557
|
+
required?: boolean;
|
|
558
|
+
children: (control: FieldControlProps) => ReactNode;
|
|
559
|
+
};
|
|
560
|
+
/** Spread the supplied attributes onto one labelable control. */
|
|
561
|
+
declare function Field({ id: suppliedId, label, hint, error, required, children }: FieldProps): react.JSX.Element;
|
|
549
562
|
type TextFieldProps = FieldMessage & Omit<InputHTMLAttributes<HTMLInputElement>, Wiring | 'type'> & {
|
|
550
|
-
type?: 'text' | 'number' | 'email';
|
|
563
|
+
type?: 'text' | 'number' | 'email' | 'password' | 'search';
|
|
551
564
|
unit?: string;
|
|
565
|
+
/** Kit glyph name, as Button, Dropdown and vanilla input() take it. Decorative;
|
|
566
|
+
the label supplies the control's name. */
|
|
567
|
+
icon?: string;
|
|
552
568
|
};
|
|
553
|
-
declare
|
|
569
|
+
declare const TextField: react.ForwardRefExoticComponent<FieldMessage & Omit<InputHTMLAttributes<HTMLInputElement>, "type" | Wiring> & {
|
|
570
|
+
type?: "text" | "number" | "email" | "password" | "search";
|
|
571
|
+
unit?: string;
|
|
572
|
+
/** Kit glyph name, as Button, Dropdown and vanilla input() take it. Decorative;
|
|
573
|
+
the label supplies the control's name. */
|
|
574
|
+
icon?: string;
|
|
575
|
+
} & react.RefAttributes<HTMLInputElement>>;
|
|
554
576
|
type TextAreaProps = FieldMessage & Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, Wiring>;
|
|
555
577
|
declare function TextArea({ label, hint, error, required, className, ...props }: TextAreaProps): react.JSX.Element;
|
|
556
578
|
type SelectFieldProps = FieldMessage & Omit<SelectHTMLAttributes<HTMLSelectElement>, Wiring>;
|
|
@@ -640,4 +662,4 @@ declare function Tooltip({ text, children }: TooltipProps): react.JSX.Element;
|
|
|
640
662
|
declare const PAGE_SIZES: readonly number[];
|
|
641
663
|
declare const DEFAULT_PAGE_SIZE: number;
|
|
642
664
|
|
|
643
|
-
export { AppShell, type AppShellProps, type AppShellSection, BackLink, type BackLinkOwnProps, type BackLinkProps, Badge, BusyRegion, type BusyRegionProps, Button, type ButtonProps, Callout, type CalloutProps, type CalloutVariant, Card, type Column, type CommandGroup, type CommandItem, CommandPalette, type CommandPaletteProps, Confirm, type ConfirmProps, DEFAULT_PAGE_SIZE, DataTable, type DataTableProps, DeltaValue, type DeltaValueProps, Denied, type DeniedProps, Drawer, type DrawerProps, DrawerSection, type DrawerSectionProps, Dropdown, type DropdownBadge, type DropdownEntry, type DropdownItem, type DropdownProps, type DropdownRowProps, type DropdownSearch, type DropdownSection, type DropdownSeparator, EmptyState, type EmptyStateProps, type EmptyStateVariant, FileField, type FileFieldProps, type Filter, FilterBar, type FilterBarProps, Icon, KeyValueList, type KeyValueListProps, type KeyValueRow, Modal, type ModalProps, NumericValue, type NumericValueProps, PAGE_SIZES, Pagination, type PaginationProps, Pill, type PillProps, RowIdentity, type RowIdentityProps, type SegmentOption, Segmented, type SegmentedProps, SelectField, type SelectFieldProps, Skeleton, type SkeletonProps, SkeletonTable, type SkeletonTableProps, Snippet, type SnippetProps, StatBand, type StatBandProps, type StatDelta, type StatFigure, type StatTone, type StatVariant, StatusDot, type StatusDotProps, THEME_INIT_SCRIPT, type TabItem, type TableSort, Tabs, type TabsProps, TextArea, type TextAreaProps, TextField, type TextFieldProps, ThemeToggle, type ThemeToggleProps, Timeline, type TimelineEvent, type TimelineEventKind, type TimelineProps, Toast, type ToastNotice, type ToastProps, Tooltip, type TooltipProps, sortTableRows, useToast };
|
|
665
|
+
export { AppShell, type AppShellProps, type AppShellSection, BackLink, type BackLinkOwnProps, type BackLinkProps, Badge, BusyRegion, type BusyRegionProps, Button, type ButtonProps, Callout, type CalloutProps, type CalloutVariant, Card, type Column, type CommandGroup, type CommandItem, CommandPalette, type CommandPaletteProps, Confirm, type ConfirmProps, DEFAULT_PAGE_SIZE, DataTable, type DataTableProps, DeltaValue, type DeltaValueProps, Denied, type DeniedProps, Drawer, type DrawerProps, DrawerSection, type DrawerSectionProps, Dropdown, type DropdownBadge, type DropdownEntry, type DropdownItem, type DropdownProps, type DropdownRowProps, type DropdownSearch, type DropdownSection, type DropdownSeparator, EmptyState, type EmptyStateProps, type EmptyStateVariant, Field, type FieldControlProps, type FieldProps, FileField, type FileFieldProps, type Filter, FilterBar, type FilterBarProps, Icon, KeyValueList, type KeyValueListProps, type KeyValueRow, Modal, type ModalProps, NumericValue, type NumericValueProps, PAGE_SIZES, Pagination, type PaginationProps, Pill, type PillProps, RowIdentity, type RowIdentityProps, type SegmentOption, Segmented, type SegmentedProps, SelectField, type SelectFieldProps, Skeleton, type SkeletonProps, SkeletonTable, type SkeletonTableProps, Snippet, type SnippetProps, StatBand, type StatBandProps, type StatDelta, type StatFigure, type StatTone, type StatVariant, StatusDot, type StatusDotProps, THEME_INIT_SCRIPT, type TabItem, type TableSort, Tabs, type TabsProps, TextArea, type TextAreaProps, TextField, type TextFieldProps, ThemeToggle, type ThemeToggleProps, Timeline, type TimelineEvent, type TimelineEventKind, type TimelineProps, Toast, type ToastNotice, type ToastProps, Tooltip, type TooltipProps, sortTableRows, useToast };
|
package/react/dist/index.js
CHANGED
|
@@ -2167,7 +2167,7 @@ function Timeline({ events, className, ...rest }) {
|
|
|
2167
2167
|
}
|
|
2168
2168
|
|
|
2169
2169
|
// src/Field.tsx
|
|
2170
|
-
import { useEffect as useEffect10, useId as useId10, useRef as useRef15, useState as useState9 } from "react";
|
|
2170
|
+
import { forwardRef as forwardRef4, useEffect as useEffect10, useId as useId10, useRef as useRef15, useState as useState9 } from "react";
|
|
2171
2171
|
import { esc, icon as icon4 } from "@apliteni/apliteni-ui";
|
|
2172
2172
|
import { jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2173
2173
|
function messages(id, hint, error) {
|
|
@@ -2195,13 +2195,19 @@ function Frame({ id, label, hint, error, required, children }) {
|
|
|
2195
2195
|
function wiring(id, hint, error) {
|
|
2196
2196
|
return { id, "aria-describedby": messages(id, hint, error), "aria-invalid": error ? true : void 0 };
|
|
2197
2197
|
}
|
|
2198
|
-
function
|
|
2198
|
+
function Field({ id: suppliedId, label, hint, error, required, children }) {
|
|
2199
|
+
const generatedId = useId10();
|
|
2200
|
+
const id = suppliedId ?? generatedId;
|
|
2201
|
+
return /* @__PURE__ */ jsx26(Frame, { ...{ id, label, hint, error, required }, children: children({ ...wiring(id, hint, error), required }) });
|
|
2202
|
+
}
|
|
2203
|
+
var TextField = forwardRef4(function TextField2({ label, hint, error, required, type = "text", unit, icon: glyph, className = "", ...props }, ref) {
|
|
2199
2204
|
const id = useId10();
|
|
2200
2205
|
const hasUnit = type === "number" && !!unit;
|
|
2201
2206
|
const describedBy = [messages(id, hint, error), hasUnit ? `${id}-unit` : ""].filter(Boolean).join(" ") || void 0;
|
|
2202
2207
|
const control = /* @__PURE__ */ jsx26(
|
|
2203
2208
|
"input",
|
|
2204
2209
|
{
|
|
2210
|
+
ref,
|
|
2205
2211
|
...props,
|
|
2206
2212
|
...wiring(id, hint, error),
|
|
2207
2213
|
required,
|
|
@@ -2211,11 +2217,16 @@ function TextField({ label, hint, error, required, type = "text", unit, classNam
|
|
|
2211
2217
|
className: `ui-input${error ? " is-invalid" : ""} ${className}`
|
|
2212
2218
|
}
|
|
2213
2219
|
);
|
|
2214
|
-
|
|
2220
|
+
const unitSpan = hasUnit ? /* @__PURE__ */ jsx26("span", { id: `${id}-unit`, className: "ui-field-number__unit", children: unit }) : null;
|
|
2221
|
+
return /* @__PURE__ */ jsx26(Frame, { ...{ id, label, hint, error, required }, children: glyph ? /* @__PURE__ */ jsxs21("div", { className: `ui-input-group${hasUnit ? " ui-field-number" : ""}`, children: [
|
|
2222
|
+
/* @__PURE__ */ jsx26("span", { className: "ui-input-group__icon", dangerouslySetInnerHTML: { __html: icon4(glyph) } }),
|
|
2223
|
+
control,
|
|
2224
|
+
unitSpan
|
|
2225
|
+
] }) : hasUnit ? /* @__PURE__ */ jsxs21("div", { className: "ui-field-number", children: [
|
|
2215
2226
|
control,
|
|
2216
|
-
|
|
2227
|
+
unitSpan
|
|
2217
2228
|
] }) : control });
|
|
2218
|
-
}
|
|
2229
|
+
});
|
|
2219
2230
|
function TextArea({ label, hint, error, required, className = "", ...props }) {
|
|
2220
2231
|
const id = useId10();
|
|
2221
2232
|
return /* @__PURE__ */ jsx26(Frame, { ...{ id, label, hint, error, required }, children: /* @__PURE__ */ jsx26(
|
|
@@ -2714,6 +2725,7 @@ export {
|
|
|
2714
2725
|
DrawerSection,
|
|
2715
2726
|
Dropdown,
|
|
2716
2727
|
EmptyState,
|
|
2728
|
+
Field,
|
|
2717
2729
|
FileField,
|
|
2718
2730
|
FilterBar,
|
|
2719
2731
|
Icon,
|
package/src/styles/input.css
CHANGED
|
@@ -69,6 +69,20 @@
|
|
|
69
69
|
.ui-textarea.is-invalid { border-color: var(--pink); }
|
|
70
70
|
/* Invalid fields keep the shared focus indicator; their border carries the error. */
|
|
71
71
|
|
|
72
|
+
/* A search field with a value gets the browser's own clear button, and the
|
|
73
|
+
browser paints it — near-black on the light field, white on the dark one,
|
|
74
|
+
beside the kit's --muted magnifier. Two glyphs, and only one answers to a
|
|
75
|
+
token. .ui-select refuses UA chrome for the same reason, hand-drawing its
|
|
76
|
+
chevron per theme; and the vanilla search specimen is a text input with a
|
|
77
|
+
`search` glyph and no clear button, so a field without one is what the
|
|
78
|
+
design already says. Measured in Chromium; Firefox draws nothing here and
|
|
79
|
+
Edge is untested.
|
|
80
|
+
why: docs/specification.md#colour-and-contrast */
|
|
81
|
+
.ui-input[type="search"]::-webkit-search-cancel-button {
|
|
82
|
+
appearance: none;
|
|
83
|
+
display: none;
|
|
84
|
+
}
|
|
85
|
+
|
|
72
86
|
/* Input with a leading icon / adornment */
|
|
73
87
|
.ui-input-group { position: relative; display: flex; align-items: center; }
|
|
74
88
|
.ui-input-group .ui-input { padding-left: 42px; }
|