@efolusi/meridian 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.
- package/README.md +12 -0
- package/ai/AgentRun.d.ts +20 -0
- package/ai/AgentRun.js +100 -0
- package/ai/ChatMessage.d.ts +19 -0
- package/ai/ChatMessage.js +81 -0
- package/ai/Citation.d.ts +23 -0
- package/ai/Citation.js +146 -0
- package/ai/Confirmation.d.ts +26 -0
- package/ai/Confirmation.js +84 -0
- package/ai/Conversation.d.ts +15 -0
- package/ai/Conversation.js +81 -0
- package/ai/DocumentCard.d.ts +17 -0
- package/ai/DocumentCard.js +101 -0
- package/ai/FeedbackBar.d.ts +14 -0
- package/ai/FeedbackBar.js +84 -0
- package/ai/GeneratedImage.d.ts +22 -0
- package/ai/GeneratedImage.js +100 -0
- package/ai/ModelSelector.d.ts +21 -0
- package/ai/ModelSelector.js +112 -0
- package/ai/Player.d.ts +18 -0
- package/ai/Player.js +201 -0
- package/ai/PromptComposer.d.ts +28 -0
- package/ai/PromptComposer.js +111 -0
- package/ai/PromptSteps.d.ts +18 -0
- package/ai/PromptSteps.js +167 -0
- package/ai/Reasoning.d.ts +17 -0
- package/ai/Reasoning.js +57 -0
- package/ai/RichComposer.d.ts +25 -0
- package/ai/RichComposer.js +247 -0
- package/ai/Sandbox.d.ts +20 -0
- package/ai/Sandbox.js +96 -0
- package/ai/SelectionQuote.d.ts +15 -0
- package/ai/SelectionQuote.js +123 -0
- package/ai/SourceCard.d.ts +17 -0
- package/ai/SourceCard.js +57 -0
- package/ai/Suggestions.d.ts +10 -0
- package/ai/Suggestions.js +38 -0
- package/ai/Task.d.ts +15 -0
- package/ai/Task.js +49 -0
- package/ai/Todo.d.ts +13 -0
- package/ai/Todo.js +87 -0
- package/ai/ToolCall.d.ts +30 -0
- package/ai/ToolCall.js +147 -0
- package/ai/Transcript.d.ts +27 -0
- package/ai/Transcript.js +96 -0
- package/ai/UsageMeter.d.ts +21 -0
- package/ai/UsageMeter.js +81 -0
- package/ai/WebPreview.d.ts +19 -0
- package/ai/WebPreview.js +179 -0
- package/assets/fonts/BricolageGrotesque-Variable.ttf +0 -0
- package/assets/fonts/Figtree-Italic-Variable.ttf +0 -0
- package/assets/fonts/Figtree-Variable.ttf +0 -0
- package/assets/fonts/JetBrainsMono-Italic-Variable.ttf +0 -0
- package/assets/fonts/JetBrainsMono-Variable.ttf +0 -0
- package/assets/fonts/OFL-BricolageGrotesque.txt +93 -0
- package/assets/fonts/OFL-Figtree.txt +93 -0
- package/assets/fonts/OFL-JetBrainsMono.txt +93 -0
- package/code/CodeBlock.d.ts +17 -0
- package/code/CodeBlock.js +99 -0
- package/code/Console.d.ts +19 -0
- package/code/Console.js +124 -0
- package/code/CopyField.d.ts +10 -0
- package/code/CopyField.js +54 -0
- package/code/Diff.d.ts +26 -0
- package/code/Diff.js +358 -0
- package/code/EnvList.d.ts +14 -0
- package/code/EnvList.js +89 -0
- package/code/Exception.d.ts +25 -0
- package/code/Exception.js +90 -0
- package/code/Terminal.d.ts +20 -0
- package/code/Terminal.js +58 -0
- package/data/BarChart.d.ts +14 -0
- package/data/BarChart.js +44 -0
- package/data/DonutChart.d.ts +17 -0
- package/data/DonutChart.js +114 -0
- package/data/EmptyState.d.ts +13 -0
- package/data/EmptyState.js +39 -0
- package/data/KeyValueList.d.ts +14 -0
- package/data/KeyValueList.js +34 -0
- package/data/LineChart.d.ts +15 -0
- package/data/LineChart.js +85 -0
- package/data/Skeleton.d.ts +11 -0
- package/data/Skeleton.js +49 -0
- package/data/Sparkline.d.ts +14 -0
- package/data/Sparkline.js +42 -0
- package/data/Stat.d.ts +14 -0
- package/data/Stat.js +40 -0
- package/data/StatusDot.d.ts +10 -0
- package/data/StatusDot.js +34 -0
- package/data/Table.d.ts +53 -0
- package/data/Table.js +174 -0
- package/dates/Calendar.d.ts +8 -0
- package/dates/Calendar.js +143 -0
- package/dates/DatePicker.d.ts +12 -0
- package/dates/DatePicker.js +118 -0
- package/display/Accordion.d.ts +15 -0
- package/display/Accordion.js +52 -0
- package/display/AspectRatio.d.ts +8 -0
- package/display/AspectRatio.js +24 -0
- package/display/Avatar.d.ts +17 -0
- package/display/Avatar.js +52 -0
- package/display/Badge.d.ts +10 -0
- package/display/Badge.js +34 -0
- package/display/Card.d.ts +17 -0
- package/display/Card.js +51 -0
- package/display/Carousel.d.ts +16 -0
- package/display/Carousel.js +97 -0
- package/display/Collapsible.d.ts +12 -0
- package/display/Collapsible.js +46 -0
- package/display/Divider.d.ts +9 -0
- package/display/Divider.js +33 -0
- package/display/Kbd.d.ts +7 -0
- package/display/Kbd.js +18 -0
- package/display/Link.d.ts +12 -0
- package/display/Link.js +41 -0
- package/display/ListItem.d.ts +19 -0
- package/display/ListItem.js +61 -0
- package/display/Resizable.d.ts +16 -0
- package/display/Resizable.js +90 -0
- package/display/ScrollArea.d.ts +8 -0
- package/display/ScrollArea.js +28 -0
- package/display/Tag.d.ts +9 -0
- package/display/Tag.js +41 -0
- package/display/Toolbar.d.ts +22 -0
- package/display/Toolbar.js +55 -0
- package/display/TreeList.d.ts +20 -0
- package/display/TreeList.js +101 -0
- package/feedback/Alert.d.ts +14 -0
- package/feedback/Alert.js +56 -0
- package/feedback/Banner.d.ts +15 -0
- package/feedback/Banner.js +49 -0
- package/feedback/ConfirmDialog.d.ts +18 -0
- package/feedback/ConfirmDialog.js +49 -0
- package/feedback/Dialog.d.ts +13 -0
- package/feedback/Dialog.js +107 -0
- package/feedback/Loader.d.ts +12 -0
- package/feedback/Loader.js +41 -0
- package/feedback/Progress.d.ts +15 -0
- package/feedback/Progress.js +48 -0
- package/feedback/Spinner.d.ts +9 -0
- package/feedback/Spinner.js +38 -0
- package/feedback/Toast.d.ts +70 -0
- package/feedback/Toast.js +216 -0
- package/feedback/Tooltip.d.ts +12 -0
- package/feedback/Tooltip.js +86 -0
- package/files/FileDrop.d.ts +15 -0
- package/files/FileDrop.js +75 -0
- package/files/FileTile.d.ts +19 -0
- package/files/FileTile.js +96 -0
- package/files/FileTypeIcon.d.ts +11 -0
- package/files/FileTypeIcon.js +121 -0
- package/finance/PaymentCard.d.ts +17 -0
- package/finance/PaymentCard.js +109 -0
- package/forms/Button.d.ts +15 -0
- package/forms/Button.js +82 -0
- package/forms/ButtonGroup.d.ts +5 -0
- package/forms/ButtonGroup.js +22 -0
- package/forms/ButtonTile.d.ts +21 -0
- package/forms/ButtonTile.js +69 -0
- package/forms/Checkbox.d.ts +6 -0
- package/forms/Checkbox.js +52 -0
- package/forms/Combobox.d.ts +17 -0
- package/forms/Combobox.js +162 -0
- package/forms/DigitEntry.d.ts +15 -0
- package/forms/DigitEntry.js +88 -0
- package/forms/FormField.d.ts +39 -0
- package/forms/FormField.js +127 -0
- package/forms/IconButton.d.ts +11 -0
- package/forms/IconButton.js +41 -0
- package/forms/Input.d.ts +14 -0
- package/forms/Input.js +75 -0
- package/forms/InputGroup.d.ts +15 -0
- package/forms/InputGroup.js +59 -0
- package/forms/Label.d.ts +11 -0
- package/forms/Label.js +29 -0
- package/forms/Radio.d.ts +6 -0
- package/forms/Radio.js +46 -0
- package/forms/Select.d.ts +10 -0
- package/forms/Select.js +68 -0
- package/forms/Slider.d.ts +18 -0
- package/forms/Slider.js +75 -0
- package/forms/Switch.d.ts +6 -0
- package/forms/Switch.js +46 -0
- package/forms/Textarea.d.ts +8 -0
- package/forms/Textarea.js +58 -0
- package/forms/Toggle.d.ts +26 -0
- package/forms/Toggle.js +85 -0
- package/icons/Icon.d.ts +13 -0
- package/icons/Icon.js +54 -0
- package/index.d.ts +106 -0
- package/index.js +106 -0
- package/navigation/Breadcrumbs.d.ts +12 -0
- package/navigation/Breadcrumbs.js +41 -0
- package/navigation/Menubar.d.ts +10 -0
- package/navigation/Menubar.js +173 -0
- package/navigation/PageControl.d.ts +11 -0
- package/navigation/PageControl.js +36 -0
- package/navigation/Pagination.d.ts +9 -0
- package/navigation/Pagination.js +68 -0
- package/navigation/SegmentedControl.d.ts +17 -0
- package/navigation/SegmentedControl.js +42 -0
- package/navigation/SideNav.d.ts +18 -0
- package/navigation/SideNav.js +87 -0
- package/navigation/Steps.d.ts +15 -0
- package/navigation/Steps.js +61 -0
- package/navigation/Tabs.d.ts +17 -0
- package/navigation/Tabs.js +76 -0
- package/navigation/TopNav.d.ts +10 -0
- package/navigation/TopNav.js +26 -0
- package/overlay/CommandPalette.d.ts +21 -0
- package/overlay/CommandPalette.js +164 -0
- package/overlay/ContextMenu.d.ts +11 -0
- package/overlay/ContextMenu.js +140 -0
- package/overlay/Drawer.d.ts +14 -0
- package/overlay/Drawer.js +99 -0
- package/overlay/HoverCard.d.ts +17 -0
- package/overlay/HoverCard.js +74 -0
- package/overlay/Menu.d.ts +24 -0
- package/overlay/Menu.js +153 -0
- package/overlay/Popover.d.ts +16 -0
- package/overlay/Popover.js +96 -0
- package/overlay/Portal.d.ts +10 -0
- package/overlay/Portal.js +127 -0
- package/package.json +41 -0
- package/styles.css +6 -0
- package/tokens/base.css +10 -0
- package/tokens/colors.css +38 -0
- package/tokens/effects.css +22 -0
- package/tokens/fonts.css +5 -0
- package/tokens/spacing.css +12 -0
- package/tokens/typography.css +9 -0
package/forms/Input.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Icon } from "../icons/Icon.js";
|
|
4
|
+
import { injectEfCss } from "./Button.js";
|
|
5
|
+
import { useFieldProps } from "./FormField.js";
|
|
6
|
+
const CSS = `
|
|
7
|
+
.ef-field{display:flex;flex-direction:column;gap:6px}
|
|
8
|
+
.ef-field__label{font-size:var(--text-sm);font-weight:var(--weight-semibold);color:var(--text-primary)}
|
|
9
|
+
.ef-field__hint{font-size:var(--text-xs);color:var(--text-muted)}
|
|
10
|
+
.ef-field__error{font-size:var(--text-xs);color:var(--danger-600);display:flex;align-items:center;gap:4px}
|
|
11
|
+
.ef-input{position:relative;display:flex;align-items:center}
|
|
12
|
+
.ef-input__el{width:100%;border:1px solid var(--border-strong);border-radius:var(--radius-sm);background:var(--surface-card);color:var(--text-primary);font-family:var(--font-sans);transition:border-color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
|
|
13
|
+
.ef-input__el::placeholder{color:var(--text-muted)}
|
|
14
|
+
.ef-input__el:hover:not(:disabled){border-color:var(--sand-400)}
|
|
15
|
+
.ef-input__el:focus{outline:none;border-color:var(--accent);box-shadow:var(--focus-ring)}
|
|
16
|
+
.ef-input__el:disabled{background:var(--surface-sunken);color:var(--text-muted);cursor:not-allowed}
|
|
17
|
+
.ef-input--sm .ef-input__el{height:var(--control-h-sm);padding:0 10px;font-size:var(--text-sm)}
|
|
18
|
+
.ef-input--md .ef-input__el{height:var(--control-h-md);padding:0 12px;font-size:var(--text-md)}
|
|
19
|
+
.ef-input--lg .ef-input__el{height:var(--control-h-lg);padding:0 14px;font-size:var(--text-lg)}
|
|
20
|
+
.ef-input--icon.ef-input--sm .ef-input__el{padding-left:32px}
|
|
21
|
+
.ef-input--icon.ef-input--md .ef-input__el{padding-left:36px}
|
|
22
|
+
.ef-input--icon.ef-input--lg .ef-input__el{padding-left:40px}
|
|
23
|
+
.ef-input__icon{position:absolute;left:11px;color:var(--text-muted);display:inline-flex;pointer-events:none}
|
|
24
|
+
.ef-input--invalid .ef-input__el{border-color:var(--danger-600)}
|
|
25
|
+
.ef-input--invalid .ef-input__el:focus{box-shadow:var(--focus-ring-danger)}
|
|
26
|
+
`;
|
|
27
|
+
export function Input({
|
|
28
|
+
label,
|
|
29
|
+
hint,
|
|
30
|
+
error,
|
|
31
|
+
iconLeft,
|
|
32
|
+
size = 'md',
|
|
33
|
+
invalid,
|
|
34
|
+
style,
|
|
35
|
+
className,
|
|
36
|
+
...rest
|
|
37
|
+
}) {
|
|
38
|
+
injectEfCss('ef-css-input', CSS);
|
|
39
|
+
// Picks up id / aria wiring when nested in a FormField; standalone this is a no-op.
|
|
40
|
+
const field = useFieldProps({
|
|
41
|
+
invalid,
|
|
42
|
+
error,
|
|
43
|
+
id: rest.id,
|
|
44
|
+
'aria-describedby': rest['aria-describedby']
|
|
45
|
+
});
|
|
46
|
+
const bad = field.invalid;
|
|
47
|
+
const control = /*#__PURE__*/React.createElement("span", {
|
|
48
|
+
className: `ef-input ef-input--${size}${iconLeft ? ' ef-input--icon' : ''}${bad ? ' ef-input--invalid' : ''}`
|
|
49
|
+
}, iconLeft ? /*#__PURE__*/React.createElement("span", {
|
|
50
|
+
className: "ef-input__icon"
|
|
51
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
|
52
|
+
name: iconLeft,
|
|
53
|
+
size: size === 'lg' ? 18 : 16
|
|
54
|
+
})) : null, /*#__PURE__*/React.createElement("input", _extends({
|
|
55
|
+
className: "ef-input__el",
|
|
56
|
+
"aria-invalid": bad || undefined
|
|
57
|
+
}, rest, field.controlProps)));
|
|
58
|
+
if (!label && !hint && !error) return /*#__PURE__*/React.cloneElement(control, {
|
|
59
|
+
style,
|
|
60
|
+
className: control.props.className + (className ? ' ' + className : '')
|
|
61
|
+
});
|
|
62
|
+
return /*#__PURE__*/React.createElement("label", {
|
|
63
|
+
className: `ef-field${className ? ' ' + className : ''}`,
|
|
64
|
+
style: style
|
|
65
|
+
}, label ? /*#__PURE__*/React.createElement("span", {
|
|
66
|
+
className: "ef-field__label"
|
|
67
|
+
}, label) : null, control, error ? /*#__PURE__*/React.createElement("span", {
|
|
68
|
+
className: "ef-field__error"
|
|
69
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
|
70
|
+
name: "circle-alert",
|
|
71
|
+
size: 12
|
|
72
|
+
}), error) : hint ? /*#__PURE__*/React.createElement("span", {
|
|
73
|
+
className: "ef-field__hint"
|
|
74
|
+
}, hint) : null);
|
|
75
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface InputGroupProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'> {
|
|
2
|
+
/** Field label rendered above */
|
|
3
|
+
label?: string;
|
|
4
|
+
/** Muted helper text below */
|
|
5
|
+
hint?: string;
|
|
6
|
+
/** Error message below — also sets invalid styling */
|
|
7
|
+
error?: string;
|
|
8
|
+
/** Leading addon: string renders a tinted cell, a node renders bare */
|
|
9
|
+
prefix?: React.ReactNode;
|
|
10
|
+
/** Trailing addon: string renders a tinted cell, a node renders bare */
|
|
11
|
+
suffix?: React.ReactNode;
|
|
12
|
+
/** @default 'md' */
|
|
13
|
+
size?: 'sm' | 'md' | 'lg';
|
|
14
|
+
}
|
|
15
|
+
export declare function InputGroup(props: InputGroupProps): React.JSX.Element;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { injectEfCss } from "./Button.js";
|
|
4
|
+
import { useFieldProps } from "./FormField.js";
|
|
5
|
+
const CSS = `
|
|
6
|
+
.ef-igroup{display:flex;flex-direction:column;gap:6px;width:100%}
|
|
7
|
+
.ef-igroup__label{font-size:var(--text-sm);font-weight:600;color:var(--text-primary)}
|
|
8
|
+
.ef-igroup__row{display:flex;align-items:stretch;width:100%;border:1px solid var(--border-strong);border-radius:var(--radius-sm);background:var(--surface-card);transition:box-shadow var(--dur-fast) var(--ease-out)}
|
|
9
|
+
.ef-igroup__row:focus-within{box-shadow:var(--focus-ring)}
|
|
10
|
+
.ef-igroup--invalid .ef-igroup__row{border-color:var(--danger-600)}
|
|
11
|
+
.ef-igroup__addon{display:flex;align-items:center;gap:6px;padding:0 11px;background:var(--surface-sunken);color:var(--text-muted);font-size:var(--text-sm);white-space:nowrap;flex:none}
|
|
12
|
+
.ef-igroup__addon--lead{border-right:1px solid var(--border-default);border-radius:calc(var(--radius-sm) - 1px) 0 0 calc(var(--radius-sm) - 1px)}
|
|
13
|
+
.ef-igroup__addon--trail{border-left:1px solid var(--border-default);border-radius:0 calc(var(--radius-sm) - 1px) calc(var(--radius-sm) - 1px) 0}
|
|
14
|
+
.ef-igroup__addon--bare{background:none;border:none;padding:0 4px}
|
|
15
|
+
.ef-igroup__input{flex:1;min-width:0;height:34px;padding:0 11px;border:none;background:transparent;font-family:var(--font-sans);font-size:var(--text-md);color:var(--text-primary)}
|
|
16
|
+
.ef-igroup__input:focus{outline:none}
|
|
17
|
+
.ef-igroup__input::placeholder{color:var(--text-muted)}
|
|
18
|
+
.ef-igroup--sm .ef-igroup__input{height:26px;font-size:var(--text-sm)}
|
|
19
|
+
.ef-igroup--lg .ef-igroup__input{height:42px}
|
|
20
|
+
.ef-igroup__note{font-size:12.5px;color:var(--text-muted)}
|
|
21
|
+
.ef-igroup__note--error{color:var(--danger-600)}
|
|
22
|
+
`;
|
|
23
|
+
export function InputGroup({
|
|
24
|
+
label,
|
|
25
|
+
hint,
|
|
26
|
+
error,
|
|
27
|
+
prefix,
|
|
28
|
+
suffix,
|
|
29
|
+
size = 'md',
|
|
30
|
+
style,
|
|
31
|
+
className,
|
|
32
|
+
...rest
|
|
33
|
+
}) {
|
|
34
|
+
injectEfCss('ef-css-igroup', CSS);
|
|
35
|
+
// Picks up id / aria wiring when nested in a FormField; standalone this is a no-op.
|
|
36
|
+
const field = useFieldProps({
|
|
37
|
+
error,
|
|
38
|
+
id: rest.id,
|
|
39
|
+
'aria-describedby': rest['aria-describedby']
|
|
40
|
+
});
|
|
41
|
+
const addon = (node, where) => node == null ? null : /*#__PURE__*/React.createElement("span", {
|
|
42
|
+
className: `ef-igroup__addon ef-igroup__addon--${where}${typeof node !== 'string' ? ' ef-igroup__addon--bare' : ''}`
|
|
43
|
+
}, node);
|
|
44
|
+
return /*#__PURE__*/React.createElement("label", {
|
|
45
|
+
className: `ef-igroup ef-igroup--${size}${error ? ' ef-igroup--invalid' : ''}${className ? ' ' + className : ''}`,
|
|
46
|
+
style: style
|
|
47
|
+
}, label ? /*#__PURE__*/React.createElement("span", {
|
|
48
|
+
className: "ef-igroup__label"
|
|
49
|
+
}, label) : null, /*#__PURE__*/React.createElement("span", {
|
|
50
|
+
className: "ef-igroup__row"
|
|
51
|
+
}, addon(prefix, 'lead'), /*#__PURE__*/React.createElement("input", _extends({
|
|
52
|
+
className: "ef-igroup__input",
|
|
53
|
+
"aria-invalid": field.invalid || undefined
|
|
54
|
+
}, rest, field.controlProps)), addon(suffix, 'trail')), error ? /*#__PURE__*/React.createElement("span", {
|
|
55
|
+
className: "ef-igroup__note ef-igroup__note--error"
|
|
56
|
+
}, error) : hint ? /*#__PURE__*/React.createElement("span", {
|
|
57
|
+
className: "ef-igroup__note"
|
|
58
|
+
}, hint) : null);
|
|
59
|
+
}
|
package/forms/Label.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface LabelProps {
|
|
2
|
+
htmlFor?: string;
|
|
3
|
+
/** Red asterisk */
|
|
4
|
+
required?: boolean;
|
|
5
|
+
/** Muted inline hint after the text */
|
|
6
|
+
hint?: React.ReactNode;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
style?: React.CSSProperties;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function Label(props: LabelProps): React.JSX.Element;
|
package/forms/Label.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { injectEfCss } from "./Button.js";
|
|
4
|
+
const CSS = `
|
|
5
|
+
.ef-label{display:inline-flex;align-items:baseline;gap:5px;font-family:var(--font-sans);font-size:var(--text-sm);font-weight:600;color:var(--text-primary)}
|
|
6
|
+
.ef-label__req{color:var(--danger-600);font-weight:600}
|
|
7
|
+
.ef-label__hint{font-weight:400;color:var(--text-muted);font-size:12.5px}
|
|
8
|
+
`;
|
|
9
|
+
export function Label({
|
|
10
|
+
htmlFor,
|
|
11
|
+
required,
|
|
12
|
+
hint,
|
|
13
|
+
children,
|
|
14
|
+
style,
|
|
15
|
+
className,
|
|
16
|
+
...rest
|
|
17
|
+
}) {
|
|
18
|
+
injectEfCss('ef-css-label', CSS);
|
|
19
|
+
return /*#__PURE__*/React.createElement("label", _extends({}, rest, {
|
|
20
|
+
htmlFor: htmlFor,
|
|
21
|
+
className: `ef-label${className ? ' ' + className : ''}`,
|
|
22
|
+
style: style
|
|
23
|
+
}), children, required ? /*#__PURE__*/React.createElement("span", {
|
|
24
|
+
className: "ef-label__req",
|
|
25
|
+
"aria-hidden": "true"
|
|
26
|
+
}, "*") : null, hint ? /*#__PURE__*/React.createElement("span", {
|
|
27
|
+
className: "ef-label__hint"
|
|
28
|
+
}, hint) : null);
|
|
29
|
+
}
|
package/forms/Radio.d.ts
ADDED
package/forms/Radio.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { injectEfCss } from "./Button.js";
|
|
4
|
+
import { useFieldProps } from "./FormField.js";
|
|
5
|
+
const CSS = `
|
|
6
|
+
.ef-radio{display:inline-flex;align-items:flex-start;gap:10px;cursor:pointer;user-select:none}
|
|
7
|
+
.ef-radio--disabled{opacity:.45;cursor:not-allowed}
|
|
8
|
+
.ef-radio__input{position:absolute;opacity:0;width:0;height:0}
|
|
9
|
+
.ef-radio__dot{display:inline-flex;align-items:center;justify-content:center;flex:none;width:18px;height:18px;margin-top:1px;border:1.5px solid var(--border-strong);border-radius:var(--radius-full);background:var(--surface-card);transition:border-color var(--dur-fast) var(--ease-out),transform var(--dur-med) var(--ease-spring)}
|
|
10
|
+
.ef-radio__dot::after{content:'';width:8px;height:8px;border-radius:var(--radius-full);background:var(--accent);opacity:0;transform:scale(.4);transition:opacity var(--dur-fast) var(--ease-out),transform var(--dur-med) var(--ease-spring)}
|
|
11
|
+
.ef-radio__input:checked+.ef-radio__dot{border-color:var(--accent)}
|
|
12
|
+
.ef-radio__input:checked+.ef-radio__dot::after{opacity:1;transform:scale(1)}
|
|
13
|
+
.ef-radio:active .ef-radio__dot{transform:scale(.95)}
|
|
14
|
+
.ef-radio__input:focus-visible+.ef-radio__dot{box-shadow:var(--focus-ring)}
|
|
15
|
+
.ef-radio__label{font-size:var(--text-md);color:var(--text-primary);line-height:1.4}
|
|
16
|
+
.ef-radio__desc{display:block;font-size:var(--text-sm);color:var(--text-muted)}
|
|
17
|
+
`;
|
|
18
|
+
export function Radio({
|
|
19
|
+
label,
|
|
20
|
+
description,
|
|
21
|
+
disabled,
|
|
22
|
+
style,
|
|
23
|
+
className,
|
|
24
|
+
...rest
|
|
25
|
+
}) {
|
|
26
|
+
injectEfCss('ef-css-radio', CSS);
|
|
27
|
+
// Picks up id / aria wiring when nested in a FormField; standalone this is a no-op.
|
|
28
|
+
const field = useFieldProps({
|
|
29
|
+
id: rest.id,
|
|
30
|
+
'aria-describedby': rest['aria-describedby']
|
|
31
|
+
});
|
|
32
|
+
return /*#__PURE__*/React.createElement("label", {
|
|
33
|
+
className: `ef-radio${disabled ? ' ef-radio--disabled' : ''}${className ? ' ' + className : ''}`,
|
|
34
|
+
style: style
|
|
35
|
+
}, /*#__PURE__*/React.createElement("input", _extends({
|
|
36
|
+
type: "radio",
|
|
37
|
+
className: "ef-radio__input",
|
|
38
|
+
disabled: disabled
|
|
39
|
+
}, rest, field.controlProps)), /*#__PURE__*/React.createElement("span", {
|
|
40
|
+
className: "ef-radio__dot"
|
|
41
|
+
}), label ? /*#__PURE__*/React.createElement("span", {
|
|
42
|
+
className: "ef-radio__label"
|
|
43
|
+
}, label, description ? /*#__PURE__*/React.createElement("span", {
|
|
44
|
+
className: "ef-radio__desc"
|
|
45
|
+
}, description) : null) : null);
|
|
46
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface SelectProps extends Omit<React.SelectHTMLAttributes<HTMLSelectElement>, 'size'> {
|
|
2
|
+
label?: string;
|
|
3
|
+
hint?: string;
|
|
4
|
+
/** Options as strings or {value, label}; alternatively pass <option> children */
|
|
5
|
+
options?: Array<string | { value: string; label: string }>;
|
|
6
|
+
/** @default 'md' */
|
|
7
|
+
size?: 'sm' | 'md' | 'lg';
|
|
8
|
+
invalid?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function Select(props: SelectProps): React.JSX.Element;
|
package/forms/Select.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Icon } from "../icons/Icon.js";
|
|
4
|
+
import { injectEfCss } from "./Button.js";
|
|
5
|
+
import { useFieldProps } from "./FormField.js";
|
|
6
|
+
const CSS = `
|
|
7
|
+
.ef-field{display:flex;flex-direction:column;gap:6px}
|
|
8
|
+
.ef-field__label{font-size:var(--text-sm);font-weight:var(--weight-semibold);color:var(--text-primary)}
|
|
9
|
+
.ef-field__hint{font-size:var(--text-xs);color:var(--text-muted)}
|
|
10
|
+
.ef-select{position:relative;display:flex;align-items:center}
|
|
11
|
+
.ef-select__el{width:100%;appearance:none;border:1px solid var(--border-strong);border-radius:var(--radius-sm);background:var(--surface-card);color:var(--text-primary);font-family:var(--font-sans);cursor:pointer;transition:border-color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
|
|
12
|
+
.ef-select__el:hover:not(:disabled){border-color:var(--sand-400)}
|
|
13
|
+
.ef-select__el:focus{outline:none;border-color:var(--accent);box-shadow:var(--focus-ring)}
|
|
14
|
+
.ef-select__el:disabled{background:var(--surface-sunken);color:var(--text-muted);cursor:not-allowed}
|
|
15
|
+
.ef-select--sm .ef-select__el{height:var(--control-h-sm);padding:0 28px 0 10px;font-size:var(--text-sm)}
|
|
16
|
+
.ef-select--md .ef-select__el{height:var(--control-h-md);padding:0 32px 0 12px;font-size:var(--text-md)}
|
|
17
|
+
.ef-select--lg .ef-select__el{height:var(--control-h-lg);padding:0 36px 0 14px;font-size:var(--text-lg)}
|
|
18
|
+
.ef-select__chevron{position:absolute;right:10px;color:var(--text-muted);pointer-events:none;display:inline-flex}
|
|
19
|
+
.ef-select--invalid .ef-select__el{border-color:var(--danger-600)}
|
|
20
|
+
`;
|
|
21
|
+
export function Select({
|
|
22
|
+
label,
|
|
23
|
+
hint,
|
|
24
|
+
options,
|
|
25
|
+
size = 'md',
|
|
26
|
+
invalid,
|
|
27
|
+
children,
|
|
28
|
+
style,
|
|
29
|
+
className,
|
|
30
|
+
...rest
|
|
31
|
+
}) {
|
|
32
|
+
injectEfCss('ef-css-select', CSS);
|
|
33
|
+
// Picks up id / aria wiring when nested in a FormField; standalone this is a no-op.
|
|
34
|
+
const field = useFieldProps({
|
|
35
|
+
invalid,
|
|
36
|
+
id: rest.id,
|
|
37
|
+
'aria-describedby': rest['aria-describedby']
|
|
38
|
+
});
|
|
39
|
+
const control = /*#__PURE__*/React.createElement("span", {
|
|
40
|
+
className: `ef-select ef-select--${size}${field.invalid ? ' ef-select--invalid' : ''}`
|
|
41
|
+
}, /*#__PURE__*/React.createElement("select", _extends({
|
|
42
|
+
className: "ef-select__el",
|
|
43
|
+
"aria-invalid": field.invalid || undefined
|
|
44
|
+
}, rest, field.controlProps), options ? options.map(o => typeof o === 'string' ? /*#__PURE__*/React.createElement("option", {
|
|
45
|
+
key: o,
|
|
46
|
+
value: o
|
|
47
|
+
}, o) : /*#__PURE__*/React.createElement("option", {
|
|
48
|
+
key: o.value,
|
|
49
|
+
value: o.value
|
|
50
|
+
}, o.label)) : children), /*#__PURE__*/React.createElement("span", {
|
|
51
|
+
className: "ef-select__chevron"
|
|
52
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
|
53
|
+
name: "chevron-down",
|
|
54
|
+
size: 16
|
|
55
|
+
})));
|
|
56
|
+
if (!label && !hint) return /*#__PURE__*/React.cloneElement(control, {
|
|
57
|
+
style,
|
|
58
|
+
className: control.props.className + (className ? ' ' + className : '')
|
|
59
|
+
});
|
|
60
|
+
return /*#__PURE__*/React.createElement("label", {
|
|
61
|
+
className: `ef-field${className ? ' ' + className : ''}`,
|
|
62
|
+
style: style
|
|
63
|
+
}, label ? /*#__PURE__*/React.createElement("span", {
|
|
64
|
+
className: "ef-field__label"
|
|
65
|
+
}, label) : null, control, hint ? /*#__PURE__*/React.createElement("span", {
|
|
66
|
+
className: "ef-field__hint"
|
|
67
|
+
}, hint) : null);
|
|
68
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface SliderProps {
|
|
2
|
+
label?: string;
|
|
3
|
+
/** Show current value right of the label */
|
|
4
|
+
showValue?: boolean;
|
|
5
|
+
/** Format the shown value, e.g. v => v + '%' */
|
|
6
|
+
format?: (v: number) => string;
|
|
7
|
+
/** @default 0 */ min?: number;
|
|
8
|
+
/** @default 100 */ max?: number;
|
|
9
|
+
/** @default 1 */ step?: number;
|
|
10
|
+
/** Controlled value */
|
|
11
|
+
value?: number;
|
|
12
|
+
defaultValue?: number;
|
|
13
|
+
onChange?: (value: number, e: React.ChangeEvent) => void;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
style?: React.CSSProperties;
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function Slider(props: SliderProps): React.JSX.Element;
|
package/forms/Slider.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { injectEfCss } from "./Button.js";
|
|
4
|
+
import { useFieldProps } from "./FormField.js";
|
|
5
|
+
const CSS = `
|
|
6
|
+
.ef-slider{display:flex;flex-direction:column;gap:8px}
|
|
7
|
+
.ef-slider__row{display:flex;align-items:center;gap:12px}
|
|
8
|
+
.ef-slider__label{font-size:var(--text-sm);font-weight:var(--weight-semibold);color:var(--text-primary);display:flex;justify-content:space-between}
|
|
9
|
+
.ef-slider__val{font-family:var(--font-mono);font-size:var(--text-sm);font-weight:400;color:var(--text-muted)}
|
|
10
|
+
.ef-slider__input{-webkit-appearance:none;appearance:none;width:100%;height:16px;background:transparent;cursor:pointer;margin:0}
|
|
11
|
+
.ef-slider__input::-webkit-slider-runnable-track{height:2px;border-radius:2px;background:linear-gradient(to right,var(--accent) var(--ef-fill,50%),var(--border-strong) var(--ef-fill,50%))}
|
|
12
|
+
.ef-slider__input::-webkit-slider-thumb{-webkit-appearance:none;width:14px;height:14px;margin-top:-6px;border-radius:var(--radius-full);background:var(--surface-card);border:1.5px solid var(--accent);transition:transform var(--dur-fast) var(--ease-out)}
|
|
13
|
+
.ef-slider__input:active::-webkit-slider-thumb{transform:scale(1.15)}
|
|
14
|
+
.ef-slider__input:focus-visible{outline:none}
|
|
15
|
+
.ef-slider__input:focus-visible::-webkit-slider-thumb{box-shadow:var(--focus-ring)}
|
|
16
|
+
.ef-slider__input:disabled{opacity:.45;cursor:not-allowed}
|
|
17
|
+
.ef-slider__input::-moz-range-track{height:2px;border-radius:2px;background:var(--border-strong)}
|
|
18
|
+
.ef-slider__input::-moz-range-progress{height:2px;border-radius:2px;background:var(--accent)}
|
|
19
|
+
.ef-slider__input::-moz-range-thumb{width:12px;height:12px;border-radius:var(--radius-full);background:var(--surface-card);border:1.5px solid var(--accent)}
|
|
20
|
+
`;
|
|
21
|
+
export function Slider({
|
|
22
|
+
label,
|
|
23
|
+
showValue,
|
|
24
|
+
format,
|
|
25
|
+
min = 0,
|
|
26
|
+
max = 100,
|
|
27
|
+
step = 1,
|
|
28
|
+
value,
|
|
29
|
+
defaultValue,
|
|
30
|
+
onChange,
|
|
31
|
+
disabled,
|
|
32
|
+
style,
|
|
33
|
+
className,
|
|
34
|
+
...rest
|
|
35
|
+
}) {
|
|
36
|
+
injectEfCss('ef-css-slider', CSS);
|
|
37
|
+
// Picks up id / aria wiring when nested in a FormField; standalone this is a no-op.
|
|
38
|
+
const field = useFieldProps({
|
|
39
|
+
id: rest.id,
|
|
40
|
+
'aria-describedby': rest['aria-describedby']
|
|
41
|
+
});
|
|
42
|
+
const [inner, setInner] = React.useState(defaultValue != null ? defaultValue : (min + max) / 2);
|
|
43
|
+
const v = value != null ? value : inner;
|
|
44
|
+
const pct = (v - min) / (max - min) * 100;
|
|
45
|
+
const handle = e => {
|
|
46
|
+
const n = +e.target.value;
|
|
47
|
+
if (value == null) setInner(n);
|
|
48
|
+
if (onChange) onChange(n, e);
|
|
49
|
+
};
|
|
50
|
+
const input = /*#__PURE__*/React.createElement("input", _extends({
|
|
51
|
+
type: "range",
|
|
52
|
+
className: "ef-slider__input",
|
|
53
|
+
style: {
|
|
54
|
+
'--ef-fill': pct + '%'
|
|
55
|
+
},
|
|
56
|
+
min: min,
|
|
57
|
+
max: max,
|
|
58
|
+
step: step,
|
|
59
|
+
value: v,
|
|
60
|
+
onChange: handle,
|
|
61
|
+
disabled: disabled
|
|
62
|
+
}, rest, field.controlProps));
|
|
63
|
+
if (!label && !showValue) return /*#__PURE__*/React.createElement("span", {
|
|
64
|
+
className: `ef-slider${className ? ' ' + className : ''}`,
|
|
65
|
+
style: style
|
|
66
|
+
}, input);
|
|
67
|
+
return /*#__PURE__*/React.createElement("label", {
|
|
68
|
+
className: `ef-slider${className ? ' ' + className : ''}`,
|
|
69
|
+
style: style
|
|
70
|
+
}, (label || showValue) && /*#__PURE__*/React.createElement("span", {
|
|
71
|
+
className: "ef-slider__label"
|
|
72
|
+
}, label, /*#__PURE__*/React.createElement("span", {
|
|
73
|
+
className: "ef-slider__val"
|
|
74
|
+
}, showValue ? format ? format(v) : v : '')), input);
|
|
75
|
+
}
|
package/forms/Switch.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { injectEfCss } from "./Button.js";
|
|
4
|
+
import { useFieldProps } from "./FormField.js";
|
|
5
|
+
const CSS = `
|
|
6
|
+
.ef-switch{display:inline-flex;align-items:center;gap:10px;cursor:pointer;user-select:none}
|
|
7
|
+
.ef-switch--disabled{opacity:.45;cursor:not-allowed}
|
|
8
|
+
.ef-switch__input{position:absolute;opacity:0;width:0;height:0}
|
|
9
|
+
.ef-switch__track{position:relative;flex:none;width:36px;height:21px;border-radius:var(--radius-full);background:var(--border-strong);transition:background var(--dur-med) var(--ease-out)}
|
|
10
|
+
.ef-switch__track::after{content:'';position:absolute;top:2.5px;left:2.5px;width:16px;height:16px;border-radius:var(--radius-full);background:var(--surface-card);box-shadow:var(--shadow-sm);transition:transform var(--dur-med) var(--ease-spring)}
|
|
11
|
+
.ef-switch__input:checked+.ef-switch__track{background:var(--accent)}
|
|
12
|
+
.ef-switch__input:checked+.ef-switch__track::after{transform:translateX(15px)}
|
|
13
|
+
.ef-switch__input:focus-visible+.ef-switch__track{box-shadow:var(--focus-ring)}
|
|
14
|
+
.ef-switch--sm .ef-switch__track{width:30px;height:18px}
|
|
15
|
+
.ef-switch--sm .ef-switch__track::after{width:13px;height:13px;top:2.5px}
|
|
16
|
+
.ef-switch--sm .ef-switch__input:checked+.ef-switch__track::after{transform:translateX(12px)}
|
|
17
|
+
.ef-switch__label{font-size:var(--text-md);color:var(--text-primary)}
|
|
18
|
+
`;
|
|
19
|
+
export function Switch({
|
|
20
|
+
label,
|
|
21
|
+
size = 'md',
|
|
22
|
+
disabled,
|
|
23
|
+
style,
|
|
24
|
+
className,
|
|
25
|
+
...rest
|
|
26
|
+
}) {
|
|
27
|
+
injectEfCss('ef-css-switch', CSS);
|
|
28
|
+
// Picks up id / aria wiring when nested in a FormField; standalone this is a no-op.
|
|
29
|
+
const field = useFieldProps({
|
|
30
|
+
id: rest.id,
|
|
31
|
+
'aria-describedby': rest['aria-describedby']
|
|
32
|
+
});
|
|
33
|
+
return /*#__PURE__*/React.createElement("label", {
|
|
34
|
+
className: `ef-switch ef-switch--${size}${disabled ? ' ef-switch--disabled' : ''}${className ? ' ' + className : ''}`,
|
|
35
|
+
style: style
|
|
36
|
+
}, /*#__PURE__*/React.createElement("input", _extends({
|
|
37
|
+
type: "checkbox",
|
|
38
|
+
role: "switch",
|
|
39
|
+
className: "ef-switch__input",
|
|
40
|
+
disabled: disabled
|
|
41
|
+
}, rest, field.controlProps)), /*#__PURE__*/React.createElement("span", {
|
|
42
|
+
className: "ef-switch__track"
|
|
43
|
+
}), label ? /*#__PURE__*/React.createElement("span", {
|
|
44
|
+
className: "ef-switch__label"
|
|
45
|
+
}, label) : null);
|
|
46
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
2
|
+
label?: string;
|
|
3
|
+
hint?: string;
|
|
4
|
+
/** Error message below — also sets invalid styling */
|
|
5
|
+
error?: string;
|
|
6
|
+
invalid?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function Textarea(props: TextareaProps): React.JSX.Element;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Icon } from "../icons/Icon.js";
|
|
4
|
+
import { injectEfCss } from "./Button.js";
|
|
5
|
+
import { useFieldProps } from "./FormField.js";
|
|
6
|
+
const CSS = `
|
|
7
|
+
.ef-field{display:flex;flex-direction:column;gap:6px}
|
|
8
|
+
.ef-field__label{font-size:var(--text-sm);font-weight:var(--weight-semibold);color:var(--text-primary)}
|
|
9
|
+
.ef-field__hint{font-size:var(--text-xs);color:var(--text-muted)}
|
|
10
|
+
.ef-field__error{font-size:var(--text-xs);color:var(--danger-600);display:flex;align-items:center;gap:4px}
|
|
11
|
+
.ef-textarea{width:100%;min-height:80px;padding:10px 12px;border:1px solid var(--border-strong);border-radius:var(--radius-sm);background:var(--surface-card);color:var(--text-primary);font-family:var(--font-sans);font-size:var(--text-md);line-height:var(--leading-normal);resize:vertical;transition:border-color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
|
|
12
|
+
.ef-textarea::placeholder{color:var(--text-muted)}
|
|
13
|
+
.ef-textarea:hover:not(:disabled){border-color:var(--sand-400)}
|
|
14
|
+
.ef-textarea:focus{outline:none;border-color:var(--accent);box-shadow:var(--focus-ring)}
|
|
15
|
+
.ef-textarea:disabled{background:var(--surface-sunken);color:var(--text-muted);cursor:not-allowed}
|
|
16
|
+
.ef-textarea--invalid{border-color:var(--danger-600)}
|
|
17
|
+
.ef-textarea--invalid:focus{box-shadow:var(--focus-ring-danger)}
|
|
18
|
+
`;
|
|
19
|
+
export function Textarea({
|
|
20
|
+
label,
|
|
21
|
+
hint,
|
|
22
|
+
error,
|
|
23
|
+
invalid,
|
|
24
|
+
style,
|
|
25
|
+
className,
|
|
26
|
+
...rest
|
|
27
|
+
}) {
|
|
28
|
+
injectEfCss('ef-css-textarea', CSS);
|
|
29
|
+
// Picks up id / aria wiring when nested in a FormField; standalone this is a no-op.
|
|
30
|
+
const field = useFieldProps({
|
|
31
|
+
invalid,
|
|
32
|
+
error,
|
|
33
|
+
id: rest.id,
|
|
34
|
+
'aria-describedby': rest['aria-describedby']
|
|
35
|
+
});
|
|
36
|
+
const bad = field.invalid;
|
|
37
|
+
const el = /*#__PURE__*/React.createElement("textarea", _extends({
|
|
38
|
+
className: `ef-textarea${bad ? ' ef-textarea--invalid' : ''}`,
|
|
39
|
+
"aria-invalid": bad || undefined
|
|
40
|
+
}, rest, field.controlProps));
|
|
41
|
+
if (!label && !hint && !error) return /*#__PURE__*/React.cloneElement(el, {
|
|
42
|
+
style,
|
|
43
|
+
className: el.props.className + (className ? ' ' + className : '')
|
|
44
|
+
});
|
|
45
|
+
return /*#__PURE__*/React.createElement("label", {
|
|
46
|
+
className: `ef-field${className ? ' ' + className : ''}`,
|
|
47
|
+
style: style
|
|
48
|
+
}, label ? /*#__PURE__*/React.createElement("span", {
|
|
49
|
+
className: "ef-field__label"
|
|
50
|
+
}, label) : null, el, error ? /*#__PURE__*/React.createElement("span", {
|
|
51
|
+
className: "ef-field__error"
|
|
52
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
|
53
|
+
name: "circle-alert",
|
|
54
|
+
size: 12
|
|
55
|
+
}), error) : hint ? /*#__PURE__*/React.createElement("span", {
|
|
56
|
+
className: "ef-field__hint"
|
|
57
|
+
}, hint) : null);
|
|
58
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface ToggleProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
2
|
+
/** Controlled pressed state */
|
|
3
|
+
pressed?: boolean;
|
|
4
|
+
defaultPressed?: boolean;
|
|
5
|
+
onPressedChange?: (pressed: boolean) => void;
|
|
6
|
+
/** Identity when used inside a ToggleGroup */
|
|
7
|
+
value?: string;
|
|
8
|
+
/** Lucide icon name */
|
|
9
|
+
icon?: string;
|
|
10
|
+
/** @default 'md' */
|
|
11
|
+
size?: 'sm' | 'md';
|
|
12
|
+
children?: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export interface ToggleGroupProps {
|
|
15
|
+
/** @default 'single' */
|
|
16
|
+
type?: 'single' | 'multiple';
|
|
17
|
+
/** Controlled: string (single) or string[] (multiple) */
|
|
18
|
+
value?: string | string[] | null;
|
|
19
|
+
defaultValue?: string | string[] | null;
|
|
20
|
+
onChange?: (value: string | string[] | null) => void;
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
style?: React.CSSProperties;
|
|
23
|
+
className?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function Toggle(props: ToggleProps): React.JSX.Element;
|
|
26
|
+
export declare function ToggleGroup(props: ToggleGroupProps): React.JSX.Element;
|