@adea-ai/ui 0.84.0 → 0.87.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 +90 -1
- package/dist/NOTICE +60 -0
- package/dist/components/composites/action-button/action-button.d.ts.map +1 -1
- package/dist/components/composites/action-button/action-button.js +2 -2
- package/dist/components/composites/action-button/action-button.js.map +1 -1
- package/dist/components/composites/catalog-browser/catalog-browser-group.d.ts +20 -0
- package/dist/components/composites/catalog-browser/catalog-browser-group.d.ts.map +1 -0
- package/dist/components/composites/catalog-browser/catalog-browser-group.js +195 -0
- package/dist/components/composites/catalog-browser/catalog-browser-group.js.map +1 -0
- package/dist/components/composites/catalog-browser/catalog-browser.d.ts +3 -0
- package/dist/components/composites/catalog-browser/catalog-browser.d.ts.map +1 -0
- package/dist/components/composites/catalog-browser/catalog-browser.js +378 -0
- package/dist/components/composites/catalog-browser/catalog-browser.js.map +1 -0
- package/dist/components/composites/catalog-browser/catalog-detail.d.ts +21 -0
- package/dist/components/composites/catalog-browser/catalog-detail.d.ts.map +1 -0
- package/dist/components/composites/catalog-browser/catalog-detail.js +92 -0
- package/dist/components/composites/catalog-browser/catalog-detail.js.map +1 -0
- package/dist/components/composites/catalog-browser/catalog-types.d.ts +78 -0
- package/dist/components/composites/catalog-browser/catalog-types.d.ts.map +1 -0
- package/dist/components/composites/catalog-browser/index.d.ts +4 -0
- package/dist/components/composites/catalog-browser/index.d.ts.map +1 -0
- package/dist/components/composites/catalog-browser/index.js +3 -0
- package/dist/components/composites/list-row/list-row.d.ts +6 -3
- package/dist/components/composites/list-row/list-row.d.ts.map +1 -1
- package/dist/components/composites/list-row/list-row.js +69 -7
- package/dist/components/composites/list-row/list-row.js.map +1 -1
- package/dist/components/composites/settings/settings.d.ts +9 -11
- package/dist/components/composites/settings/settings.d.ts.map +1 -1
- package/dist/components/composites/settings/settings.js +48 -33
- package/dist/components/composites/settings/settings.js.map +1 -1
- package/dist/components/conversation/message-composer.js +1 -1
- package/dist/components/conversation/scroll-follow.d.ts.map +1 -1
- package/dist/components/conversation/scroll-follow.js +95 -15
- package/dist/components/conversation/scroll-follow.js.map +1 -1
- package/dist/components/layout/app-shell/index.d.ts +1 -0
- package/dist/components/layout/app-shell/index.d.ts.map +1 -1
- package/dist/components/layout/app-shell/index.js +2 -1
- package/dist/components/layout/app-shell/skip-link.d.ts +11 -0
- package/dist/components/layout/app-shell/skip-link.d.ts.map +1 -0
- package/dist/components/layout/app-shell/skip-link.js +44 -0
- package/dist/components/layout/app-shell/skip-link.js.map +1 -0
- package/dist/components/layout/floating-preview/floating-preview.d.ts +12 -0
- package/dist/components/layout/floating-preview/floating-preview.d.ts.map +1 -0
- package/dist/components/layout/floating-preview/floating-preview.js +283 -0
- package/dist/components/layout/floating-preview/floating-preview.js.map +1 -0
- package/dist/components/layout/floating-preview/index.d.ts +3 -0
- package/dist/components/layout/floating-preview/index.d.ts.map +1 -0
- package/dist/components/layout/floating-preview/index.js +3 -0
- package/dist/components/layout/floating-preview/model.d.ts +74 -0
- package/dist/components/layout/floating-preview/model.d.ts.map +1 -0
- package/dist/components/layout/floating-preview/model.js +146 -0
- package/dist/components/layout/floating-preview/model.js.map +1 -0
- package/dist/components/theme/index.d.ts +1 -0
- package/dist/components/theme/index.d.ts.map +1 -1
- package/dist/components/theme/index.js +2 -1
- package/dist/components/theme/theme-mode-toggle.d.ts +10 -0
- package/dist/components/theme/theme-mode-toggle.d.ts.map +1 -0
- package/dist/components/theme/theme-mode-toggle.js +82 -0
- package/dist/components/theme/theme-mode-toggle.js.map +1 -0
- package/dist/components/ui/checkbox/checkbox.d.ts +2 -0
- package/dist/components/ui/checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/ui/checkbox/checkbox.js +24 -3
- package/dist/components/ui/checkbox/checkbox.js.map +1 -1
- package/dist/components/ui/combobox/combobox.d.ts.map +1 -1
- package/dist/components/ui/combobox/combobox.js +41 -4
- package/dist/components/ui/combobox/combobox.js.map +1 -1
- package/dist/components/ui/combobox/index.d.ts +1 -0
- package/dist/components/ui/combobox/index.d.ts.map +1 -1
- package/dist/components/ui/combobox/index.js +2 -1
- package/dist/components/ui/combobox/value-combobox.d.ts +19 -0
- package/dist/components/ui/combobox/value-combobox.d.ts.map +1 -0
- package/dist/components/ui/combobox/value-combobox.js +42 -0
- package/dist/components/ui/combobox/value-combobox.js.map +1 -0
- package/dist/components/ui/empty/empty-state.d.ts +15 -0
- package/dist/components/ui/empty/empty-state.d.ts.map +1 -0
- package/dist/components/ui/empty/empty-state.js +96 -0
- package/dist/components/ui/empty/empty-state.js.map +1 -0
- package/dist/components/ui/empty/index.d.ts +1 -0
- package/dist/components/ui/empty/index.d.ts.map +1 -1
- package/dist/components/ui/empty/index.js +2 -1
- package/dist/components/ui/entity-icon/entity-icon.d.ts +4 -1
- package/dist/components/ui/entity-icon/entity-icon.d.ts.map +1 -1
- package/dist/components/ui/entity-icon/entity-icon.js +37 -13
- package/dist/components/ui/entity-icon/entity-icon.js.map +1 -1
- package/dist/components/ui/field/field.d.ts +36 -13
- package/dist/components/ui/field/field.d.ts.map +1 -1
- package/dist/components/ui/field/field.js +146 -24
- package/dist/components/ui/field/field.js.map +1 -1
- package/dist/components/ui/field/index.d.ts +3 -1
- package/dist/components/ui/field/index.d.ts.map +1 -1
- package/dist/components/ui/field/index.js +3 -2
- package/dist/components/ui/field/number-field.d.ts +19 -0
- package/dist/components/ui/field/number-field.d.ts.map +1 -0
- package/dist/components/ui/field/number-field.js +76 -0
- package/dist/components/ui/field/number-field.js.map +1 -0
- package/dist/components/ui/input/index.d.ts +1 -0
- package/dist/components/ui/input/index.d.ts.map +1 -1
- package/dist/components/ui/input/index.js +2 -1
- package/dist/components/ui/input/input-control.d.ts +11 -0
- package/dist/components/ui/input/input-control.d.ts.map +1 -0
- package/dist/components/ui/input/input-control.js +24 -0
- package/dist/components/ui/input/input-control.js.map +1 -0
- package/dist/components/ui/input/input.d.ts.map +1 -1
- package/dist/components/ui/input/input.js +56 -28
- package/dist/components/ui/input/input.js.map +1 -1
- package/dist/components/ui/input-group/index.d.ts +1 -0
- package/dist/components/ui/input-group/index.d.ts.map +1 -1
- package/dist/components/ui/input-group/index.js +2 -1
- package/dist/components/ui/input-group/input-group.d.ts.map +1 -1
- package/dist/components/ui/input-group/input-group.js +42 -5
- package/dist/components/ui/input-group/input-group.js.map +1 -1
- package/dist/components/ui/input-group/secret-input-group.d.ts +11 -0
- package/dist/components/ui/input-group/secret-input-group.d.ts.map +1 -0
- package/dist/components/ui/input-group/secret-input-group.js +67 -0
- package/dist/components/ui/input-group/secret-input-group.js.map +1 -0
- package/dist/components/ui/native-select/native-select.d.ts.map +1 -1
- package/dist/components/ui/native-select/native-select.js +39 -4
- package/dist/components/ui/native-select/native-select.js.map +1 -1
- package/dist/components/ui/progress/progress.d.ts.map +1 -1
- package/dist/components/ui/progress/progress.js +30 -18
- package/dist/components/ui/progress/progress.js.map +1 -1
- package/dist/components/ui/radio-group/radio-group.d.ts.map +1 -1
- package/dist/components/ui/radio-group/radio-group.js +41 -4
- package/dist/components/ui/radio-group/radio-group.js.map +1 -1
- package/dist/components/ui/switch/switch.d.ts +2 -0
- package/dist/components/ui/switch/switch.d.ts.map +1 -1
- package/dist/components/ui/switch/switch.js +24 -3
- package/dist/components/ui/switch/switch.js.map +1 -1
- package/dist/components/ui/tabs/tabs.js +1 -1
- package/dist/components/ui/tabs/tabs.js.map +1 -1
- package/dist/components/ui/text-link/index.d.ts +2 -0
- package/dist/components/ui/text-link/index.d.ts.map +1 -0
- package/dist/components/ui/text-link/index.js +2 -0
- package/dist/components/ui/text-link/text-link.d.ts +9 -0
- package/dist/components/ui/text-link/text-link.d.ts.map +1 -0
- package/dist/components/ui/text-link/text-link.js +30 -0
- package/dist/components/ui/text-link/text-link.js.map +1 -0
- package/dist/components/ui/textarea/textarea.d.ts.map +1 -1
- package/dist/components/ui/textarea/textarea.js +41 -4
- package/dist/components/ui/textarea/textarea.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -8
- package/dist/lib/clipboard.d.ts +3 -0
- package/dist/lib/clipboard.d.ts.map +1 -0
- package/dist/lib/clipboard.js +35 -0
- package/dist/lib/clipboard.js.map +1 -0
- package/dist/lib/download.d.ts +3 -0
- package/dist/lib/download.d.ts.map +1 -0
- package/dist/lib/download.js +31 -0
- package/dist/lib/download.js.map +1 -0
- package/dist/lib/form-field.d.ts +37 -0
- package/dist/lib/form-field.d.ts.map +1 -0
- package/dist/lib/form-field.js +47 -0
- package/dist/lib/form-field.js.map +1 -0
- package/dist/r/app-shell.json +5 -0
- package/dist/r/catalog-browser.json +47 -0
- package/dist/r/combobox.json +5 -0
- package/dist/r/empty.json +10 -1
- package/dist/r/field.json +7 -0
- package/dist/r/floating-preview.json +30 -0
- package/dist/r/input-group.json +6 -0
- package/dist/r/input.json +5 -0
- package/dist/r/lib.json +15 -0
- package/dist/r/list-row.json +1 -0
- package/dist/r/registry.json +159 -1
- package/dist/r/src/components/composites/action-button/action-button.tsx +5 -1
- package/dist/r/src/components/composites/catalog-browser/catalog-browser-group.tsx +148 -0
- package/dist/r/src/components/composites/catalog-browser/catalog-browser.tsx +258 -0
- package/dist/r/src/components/composites/catalog-browser/catalog-detail.tsx +64 -0
- package/dist/r/src/components/composites/catalog-browser/catalog-types.ts +83 -0
- package/dist/r/src/components/composites/catalog-browser/index.ts +10 -0
- package/dist/r/src/components/composites/list-row/list-row.tsx +81 -8
- package/dist/r/src/components/composites/settings/settings.tsx +67 -37
- package/dist/r/src/components/conversation/scroll-follow.ts +109 -15
- package/dist/r/src/components/layout/app-shell/index.ts +1 -0
- package/dist/r/src/components/layout/app-shell/skip-link.tsx +35 -0
- package/dist/r/src/components/layout/floating-preview/floating-preview.tsx +260 -0
- package/dist/r/src/components/layout/floating-preview/index.ts +2 -0
- package/dist/r/src/components/layout/floating-preview/model.ts +285 -0
- package/dist/r/src/components/theme/index.ts +1 -0
- package/dist/r/src/components/theme/theme-mode-toggle.tsx +56 -0
- package/dist/r/src/components/ui/checkbox/checkbox.tsx +20 -3
- package/dist/r/src/components/ui/combobox/combobox.tsx +24 -1
- package/dist/r/src/components/ui/combobox/index.ts +1 -0
- package/dist/r/src/components/ui/combobox/value-combobox.tsx +38 -0
- package/dist/r/src/components/ui/empty/empty-state.tsx +71 -0
- package/dist/r/src/components/ui/empty/index.ts +1 -0
- package/dist/r/src/components/ui/entity-icon/entity-icon.tsx +33 -2
- package/dist/r/src/components/ui/field/field.tsx +102 -5
- package/dist/r/src/components/ui/field/index.ts +5 -0
- package/dist/r/src/components/ui/field/number-field.tsx +71 -0
- package/dist/r/src/components/ui/input/index.ts +1 -0
- package/dist/r/src/components/ui/input/input-control.tsx +38 -0
- package/dist/r/src/components/ui/input/input.tsx +32 -20
- package/dist/r/src/components/ui/input-group/index.ts +1 -0
- package/dist/r/src/components/ui/input-group/input-group.tsx +25 -2
- package/dist/r/src/components/ui/input-group/secret-input-group.tsx +58 -0
- package/dist/r/src/components/ui/native-select/native-select.tsx +27 -1
- package/dist/r/src/components/ui/progress/progress.tsx +12 -8
- package/dist/r/src/components/ui/radio-group/radio-group.tsx +30 -2
- package/dist/r/src/components/ui/switch/switch.tsx +20 -3
- package/dist/r/src/components/ui/tabs/tabs.tsx +1 -1
- package/dist/r/src/components/ui/text-link/index.ts +2 -0
- package/dist/r/src/components/ui/text-link/text-link.tsx +28 -0
- package/dist/r/src/components/ui/textarea/textarea.tsx +24 -1
- package/dist/r/src/lib/clipboard.ts +41 -0
- package/dist/r/src/lib/download.ts +29 -0
- package/dist/r/src/lib/form-field.ts +93 -0
- package/dist/r/text-link.json +22 -0
- package/dist/r/theming.json +6 -0
- package/package.json +1 -1
- package/registry.json +159 -1
- package/src/components/composites/action-button/action-button.tsx +5 -1
- package/src/components/composites/catalog-browser/catalog-browser-group.tsx +148 -0
- package/src/components/composites/catalog-browser/catalog-browser.tsx +258 -0
- package/src/components/composites/catalog-browser/catalog-detail.tsx +64 -0
- package/src/components/composites/catalog-browser/catalog-types.ts +83 -0
- package/src/components/composites/catalog-browser/index.ts +10 -0
- package/src/components/composites/list-row/list-row.tsx +81 -8
- package/src/components/composites/settings/settings.tsx +67 -37
- package/src/components/conversation/scroll-follow.ts +109 -15
- package/src/components/layout/app-shell/index.ts +1 -0
- package/src/components/layout/app-shell/skip-link.tsx +35 -0
- package/src/components/layout/floating-preview/floating-preview.tsx +260 -0
- package/src/components/layout/floating-preview/index.ts +2 -0
- package/src/components/layout/floating-preview/model.ts +285 -0
- package/src/components/theme/index.ts +1 -0
- package/src/components/theme/theme-mode-toggle.tsx +56 -0
- package/src/components/ui/checkbox/checkbox.tsx +20 -3
- package/src/components/ui/combobox/combobox.tsx +24 -1
- package/src/components/ui/combobox/index.ts +1 -0
- package/src/components/ui/combobox/value-combobox.tsx +38 -0
- package/src/components/ui/empty/empty-state.tsx +71 -0
- package/src/components/ui/empty/index.ts +1 -0
- package/src/components/ui/entity-icon/entity-icon.tsx +33 -2
- package/src/components/ui/field/field.tsx +102 -5
- package/src/components/ui/field/index.ts +5 -0
- package/src/components/ui/field/number-field.tsx +71 -0
- package/src/components/ui/input/index.ts +1 -0
- package/src/components/ui/input/input-control.tsx +38 -0
- package/src/components/ui/input/input.tsx +32 -20
- package/src/components/ui/input-group/index.ts +1 -0
- package/src/components/ui/input-group/input-group.tsx +25 -2
- package/src/components/ui/input-group/secret-input-group.tsx +58 -0
- package/src/components/ui/native-select/native-select.tsx +27 -1
- package/src/components/ui/progress/progress.tsx +12 -8
- package/src/components/ui/radio-group/radio-group.tsx +30 -2
- package/src/components/ui/switch/switch.tsx +20 -3
- package/src/components/ui/tabs/tabs.tsx +1 -1
- package/src/components/ui/text-link/index.ts +2 -0
- package/src/components/ui/text-link/text-link.tsx +28 -0
- package/src/components/ui/textarea/textarea.tsx +24 -1
- package/src/index.ts +4 -0
- package/src/lib/clipboard.ts +41 -0
- package/src/lib/download.ts +29 -0
- package/src/lib/form-field.ts +93 -0
|
@@ -1,27 +1,36 @@
|
|
|
1
1
|
import { cn } from "../../../lib/utils.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { FormFieldContext, createFormFieldContext } from "../../../lib/form-field.js";
|
|
3
|
+
import { Label } from "../label/label.js";
|
|
4
|
+
import { createComponent, insert, memo, mergeProps, setAttribute, spread, template } from "solid-js/web";
|
|
5
|
+
import { Show, createUniqueId, splitProps } from "solid-js";
|
|
4
6
|
import { TextField } from "@kobalte/core/text-field";
|
|
5
7
|
//#region src/components/ui/field/field.tsx
|
|
6
|
-
var _tmpl$ = /*#__PURE__*/ template(`<
|
|
7
|
-
var _tmpl$2 = /*#__PURE__*/ template(`<
|
|
8
|
-
var _tmpl$3 = /*#__PURE__*/ template(`<
|
|
9
|
-
var _tmpl$4 = /*#__PURE__*/ template(`<
|
|
8
|
+
var _tmpl$ = /*#__PURE__*/ template(`<p class="text-muted-foreground text-sm">`);
|
|
9
|
+
var _tmpl$2 = /*#__PURE__*/ template(`<p role=alert class="text-foreground text-sm">`);
|
|
10
|
+
var _tmpl$3 = /*#__PURE__*/ template(`<div>`);
|
|
11
|
+
var _tmpl$4 = /*#__PURE__*/ template(`<fieldset>`);
|
|
12
|
+
var _tmpl$5 = /*#__PURE__*/ template(`<div data-slot=field-group>`);
|
|
13
|
+
var _tmpl$6 = /*#__PURE__*/ template(`<legend>`);
|
|
14
|
+
var _tmpl$7 = /*#__PURE__*/ template(`<span class="text-muted-foreground text-2xs tracking-wide uppercase">`);
|
|
15
|
+
var _tmpl$8 = /*#__PURE__*/ template(`<div><span class="bg-border h-px flex-1"></span><span class="bg-border h-px flex-1">`);
|
|
10
16
|
/**
|
|
11
17
|
* Field.
|
|
12
18
|
*
|
|
13
19
|
* The wrapper that makes a form control describable and validatable: a label,
|
|
14
20
|
* a description, an error message, and the ARIA relationships between them.
|
|
15
21
|
*
|
|
22
|
+
* This Kobalte TextField composition is for its own `FieldLabel`, `FieldInput`
|
|
23
|
+
* and `FieldTextArea` parts. Use `FormField` to wire the standalone shared
|
|
24
|
+
* controls, including checkboxes, switches and comboboxes.
|
|
25
|
+
*
|
|
16
26
|
* It is built on Kobalte's TextField specifically so `aria-describedby`,
|
|
17
27
|
* `aria-invalid` and `aria-errormessage` are wired by construction. Those three
|
|
18
28
|
* attributes are the difference between "this field is required and empty" and
|
|
19
29
|
* a red border that only a sighted user can perceive — and they are also the
|
|
20
30
|
* first thing a hand-rolled form drops.
|
|
21
31
|
*
|
|
22
|
-
* `Field` owns the description and the error slot, so
|
|
23
|
-
*
|
|
24
|
-
* Compose it with any control: `Field` wraps, `Label`/`Input`/`Select` fill it.
|
|
32
|
+
* `Field` owns the description and the error slot, so its controls line up and
|
|
33
|
+
* its messages land in the same place regardless of which TextField part is used.
|
|
25
34
|
*/
|
|
26
35
|
function Field(props) {
|
|
27
36
|
const [local, rest] = splitProps(props, ["class"]);
|
|
@@ -29,6 +38,108 @@ function Field(props) {
|
|
|
29
38
|
return cn("flex flex-col gap-1.5", local.class);
|
|
30
39
|
} }, rest));
|
|
31
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* FormField.
|
|
43
|
+
*
|
|
44
|
+
* A shared label, help and validation wrapper for any one shared control. Its
|
|
45
|
+
* context is consumed by Input, Textarea, NativeSelect, Checkbox, Switch,
|
|
46
|
+
* RadioGroup and ComboboxInput, so the actual focusable element receives the
|
|
47
|
+
* generated ID and description relationships. Set `group` when the label names
|
|
48
|
+
* a set of controls; the wrapper then uses fieldset and legend semantics.
|
|
49
|
+
*/
|
|
50
|
+
function FormField(props) {
|
|
51
|
+
const [local, rest] = splitProps(props, [
|
|
52
|
+
"class",
|
|
53
|
+
"label",
|
|
54
|
+
"hint",
|
|
55
|
+
"error",
|
|
56
|
+
"controlId",
|
|
57
|
+
"group",
|
|
58
|
+
"children"
|
|
59
|
+
]);
|
|
60
|
+
const fieldId = createUniqueId();
|
|
61
|
+
const labelId = `${fieldId}-label`;
|
|
62
|
+
const descriptionId = `${fieldId}-description`;
|
|
63
|
+
const errorId = `${fieldId}-error`;
|
|
64
|
+
const field = createFormFieldContext({
|
|
65
|
+
controlId: local.controlId,
|
|
66
|
+
defaultControlId: fieldId,
|
|
67
|
+
labelId,
|
|
68
|
+
descriptionId,
|
|
69
|
+
errorId,
|
|
70
|
+
hint: () => local.hint,
|
|
71
|
+
error: () => local.error,
|
|
72
|
+
group: () => local.group ?? false
|
|
73
|
+
});
|
|
74
|
+
const help = () => [createComponent(Show, {
|
|
75
|
+
get when() {
|
|
76
|
+
return local.hint;
|
|
77
|
+
},
|
|
78
|
+
get children() {
|
|
79
|
+
var _el$ = _tmpl$();
|
|
80
|
+
setAttribute(_el$, "id", descriptionId);
|
|
81
|
+
insert(_el$, () => local.hint);
|
|
82
|
+
return _el$;
|
|
83
|
+
}
|
|
84
|
+
}), createComponent(Show, {
|
|
85
|
+
get when() {
|
|
86
|
+
return local.error;
|
|
87
|
+
},
|
|
88
|
+
get children() {
|
|
89
|
+
var _el$2 = _tmpl$2();
|
|
90
|
+
setAttribute(_el$2, "id", errorId);
|
|
91
|
+
insert(_el$2, () => local.error);
|
|
92
|
+
return _el$2;
|
|
93
|
+
}
|
|
94
|
+
})];
|
|
95
|
+
return createComponent(FormFieldContext.Provider, {
|
|
96
|
+
value: field,
|
|
97
|
+
get children() {
|
|
98
|
+
var _el$3 = _tmpl$3();
|
|
99
|
+
spread(_el$3, mergeProps({ get ["class"]() {
|
|
100
|
+
return cn("flex flex-col gap-1.5", local.class);
|
|
101
|
+
} }, rest), false, true);
|
|
102
|
+
insert(_el$3, (() => {
|
|
103
|
+
var _c$ = memo(() => !!local.group);
|
|
104
|
+
return () => _c$() ? createComponent(FieldSet, {
|
|
105
|
+
"class": "flex flex-col gap-1.5",
|
|
106
|
+
get ["aria-describedby"]() {
|
|
107
|
+
return field.describedBy();
|
|
108
|
+
},
|
|
109
|
+
get ["aria-invalid"]() {
|
|
110
|
+
return field.invalid() || void 0;
|
|
111
|
+
},
|
|
112
|
+
get children() {
|
|
113
|
+
return [
|
|
114
|
+
createComponent(FieldLegend, {
|
|
115
|
+
id: labelId,
|
|
116
|
+
variant: "label",
|
|
117
|
+
get children() {
|
|
118
|
+
return local.label;
|
|
119
|
+
}
|
|
120
|
+
}),
|
|
121
|
+
memo(() => local.children),
|
|
122
|
+
memo(() => help())
|
|
123
|
+
];
|
|
124
|
+
}
|
|
125
|
+
}) : [
|
|
126
|
+
createComponent(Label, {
|
|
127
|
+
id: labelId,
|
|
128
|
+
get ["for"]() {
|
|
129
|
+
return field.controlId();
|
|
130
|
+
},
|
|
131
|
+
get children() {
|
|
132
|
+
return local.label;
|
|
133
|
+
}
|
|
134
|
+
}),
|
|
135
|
+
memo(() => local.children),
|
|
136
|
+
memo(help)
|
|
137
|
+
];
|
|
138
|
+
})());
|
|
139
|
+
return _el$3;
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
32
143
|
function FieldLabel(props) {
|
|
33
144
|
const [local, rest] = splitProps(props, ["class"]);
|
|
34
145
|
return createComponent(TextField.Label, mergeProps({ get ["class"]() {
|
|
@@ -67,45 +178,56 @@ function FieldTextArea(props) {
|
|
|
67
178
|
function FieldSet(props) {
|
|
68
179
|
const [local, rest] = splitProps(props, ["class"]);
|
|
69
180
|
return (() => {
|
|
70
|
-
var _el$ = _tmpl$();
|
|
71
|
-
spread(_el
|
|
181
|
+
var _el$4 = _tmpl$4();
|
|
182
|
+
spread(_el$4, mergeProps({ get ["class"]() {
|
|
183
|
+
return cn("flex flex-col gap-4", local.class);
|
|
184
|
+
} }, rest), false, false);
|
|
185
|
+
return _el$4;
|
|
186
|
+
})();
|
|
187
|
+
}
|
|
188
|
+
/** A visual stack for related controls that does not imply fieldset semantics. */
|
|
189
|
+
function FieldGroup(props) {
|
|
190
|
+
const [local, rest] = splitProps(props, ["class"]);
|
|
191
|
+
return (() => {
|
|
192
|
+
var _el$5 = _tmpl$5();
|
|
193
|
+
spread(_el$5, mergeProps({ get ["class"]() {
|
|
72
194
|
return cn("flex flex-col gap-4", local.class);
|
|
73
195
|
} }, rest), false, false);
|
|
74
|
-
return _el
|
|
196
|
+
return _el$5;
|
|
75
197
|
})();
|
|
76
198
|
}
|
|
77
199
|
function FieldLegend(props) {
|
|
78
200
|
const [local, rest] = splitProps(props, ["class", "variant"]);
|
|
79
201
|
return (() => {
|
|
80
|
-
var _el$
|
|
81
|
-
spread(_el$
|
|
202
|
+
var _el$6 = _tmpl$6();
|
|
203
|
+
spread(_el$6, mergeProps({ get ["class"]() {
|
|
82
204
|
return cn("mb-1", local.variant === "label" ? "text-sm font-medium" : "text-base font-semibold tracking-tight", local.class);
|
|
83
205
|
} }, rest), false, false);
|
|
84
|
-
return _el$
|
|
206
|
+
return _el$6;
|
|
85
207
|
})();
|
|
86
208
|
}
|
|
87
209
|
/** A horizontal rule with a word in it, for "or continue with" separators. */
|
|
88
210
|
function FieldSeparator(props) {
|
|
89
211
|
const [local, rest] = splitProps(props, ["class", "children"]);
|
|
90
212
|
return (() => {
|
|
91
|
-
var _el$
|
|
92
|
-
spread(_el$
|
|
213
|
+
var _el$7 = _tmpl$8(), _el$0 = _el$7.firstChild.nextSibling;
|
|
214
|
+
spread(_el$7, mergeProps({ get ["class"]() {
|
|
93
215
|
return cn("relative flex items-center gap-3 py-1", local.class);
|
|
94
216
|
} }, rest), false, true);
|
|
95
|
-
insert(_el$
|
|
217
|
+
insert(_el$7, createComponent(Show, {
|
|
96
218
|
get when() {
|
|
97
219
|
return local.children;
|
|
98
220
|
},
|
|
99
221
|
get children() {
|
|
100
|
-
var _el$
|
|
101
|
-
insert(_el$
|
|
102
|
-
return _el$
|
|
222
|
+
var _el$9 = _tmpl$7();
|
|
223
|
+
insert(_el$9, () => local.children);
|
|
224
|
+
return _el$9;
|
|
103
225
|
}
|
|
104
|
-
}), _el$
|
|
105
|
-
return _el$
|
|
226
|
+
}), _el$0);
|
|
227
|
+
return _el$7;
|
|
106
228
|
})();
|
|
107
229
|
}
|
|
108
230
|
//#endregion
|
|
109
|
-
export { Field, FieldDescription, FieldError, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea };
|
|
231
|
+
export { Field, FieldDescription, FieldError, FieldGroup, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, FormField };
|
|
110
232
|
|
|
111
233
|
//# sourceMappingURL=field.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field.js","names":["TextField","KobalteTextField","ComponentProps","Show","splitProps","cn","Field","props","local","rest","_$createComponent","_$mergeProps","class","FieldLabel","Label","FieldDescription","Description","FieldError","ErrorMessage","FieldInput","Input","FieldTextArea","TextArea","FieldSet","_el$","_tmpl$","_$spread","FieldLegend","variant","_el$2","_tmpl$2","FieldSeparator","children","_el$3","_tmpl$4","_el$4","firstChild","_el$6","nextSibling","_$insert","when","_el$5","_tmpl$3","_$createComponent","KobalteTextField","_$mergeProps"],"sources":["../../../../src/components/ui/field/field.tsx"],"sourcesContent":["import { TextField as KobalteTextField } from '@kobalte/core/text-field'\nimport type { ComponentProps } from 'solid-js'\nimport { Show, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\n\n/**\n * Field.\n *\n * The wrapper that makes a form control describable and validatable: a label,\n * a description, an error message, and the ARIA relationships between them.\n *\n * It is built on Kobalte's TextField specifically so `aria-describedby`,\n * `aria-invalid` and `aria-errormessage` are wired by construction. Those three\n * attributes are the difference between \"this field is required and empty\" and\n * a red border that only a sighted user can perceive — and they are also the\n * first thing a hand-rolled form drops.\n *\n * `Field` owns the description and the error slot, so a form's controls line up\n * and its messages land in the same place regardless of which control is used.\n * Compose it with any control: `Field` wraps, `Label`/`Input`/`Select` fill it.\n */\nexport function Field(props: ComponentProps<typeof KobalteTextField>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteTextField class={cn('flex flex-col gap-1.5', local.class)} {...rest} />\n}\n\nexport function FieldLabel(props: ComponentProps<typeof KobalteTextField.Label>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteTextField.Label class={cn('text-sm leading-none font-medium', local.class)} {...rest} />\n )\n}\n\nexport function FieldDescription(props: ComponentProps<typeof KobalteTextField.Description>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteTextField.Description\n class={cn('text-muted-foreground text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function FieldError(props: ComponentProps<typeof KobalteTextField.ErrorMessage>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteTextField.ErrorMessage class={cn('text-foreground text-sm', local.class)} {...rest} />\n )\n}\n\nexport function FieldInput(props: ComponentProps<typeof KobalteTextField.Input>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteTextField.Input\n class={cn(\n 'h-control-md w-full min-w-0 rounded-md border border-input bg-transparent px-control-md py-1 text-sm',\n 'transition-[color,box-shadow,border-color] ease-out outline-none',\n 'placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',\n 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function FieldTextArea(props: ComponentProps<typeof KobalteTextField.TextArea>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteTextField.TextArea\n class={cn(\n 'flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-control-md py-2 text-sm',\n 'transition-[color,box-shadow,border-color] ease-out outline-none resize-y',\n 'placeholder:text-muted-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',\n 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/**\n * A labelled group of fields with a single legend, for a real `<fieldset>`.\n * Grouping is what lets a screen reader announce \"Shipping address, group\"\n * before reading the four fields inside it.\n */\nexport function FieldSet(props: ComponentProps<'fieldset'>) {\n const [local, rest] = splitProps(props, ['class'])\n return <fieldset class={cn('flex flex-col gap-4', local.class)} {...rest} />\n}\n\nexport function FieldLegend(props: ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) {\n const [local, rest] = splitProps(props, ['class', 'variant'])\n return (\n <legend\n class={cn(\n 'mb-1',\n local.variant === 'label'\n ? 'text-sm font-medium'\n : 'text-base font-semibold tracking-tight',\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/** A horizontal rule with a word in it, for \"or continue with\" separators. */\nexport function FieldSeparator(props: {\n class?: string\n children?: ComponentProps<'span'>['children']\n}) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <div class={cn('relative flex items-center gap-3 py-1', local.class)} {...rest}>\n <span class=\"bg-border h-px flex-1\" />\n <Show when={local.children}>\n <span class=\"text-muted-foreground text-2xs tracking-wide uppercase\">{local.children}</span>\n </Show>\n <span class=\"bg-border h-px flex-1\" />\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"field.js","names":["TextField","KobalteTextField","ComponentProps","JSX","createUniqueId","Show","splitProps","Label","createFormFieldContext","FormFieldContext","cn","Field","props","local","rest","_$createComponent","_$mergeProps","class","FormFieldProps","Omit","label","hint","error","controlId","group","children","Element","FormField","fieldId","labelId","descriptionId","errorId","field","defaultControlId","help","when","_el$","_tmpl$","_$setAttribute","_$insert","_el$2","_tmpl$2","Provider","value","_el$3","_tmpl$3","_$spread","_c$","_$memo","FieldSet","aria-describedby","describedBy","aria-invalid","invalid","undefined","FieldLegend","id","variant","for","FieldLabel","FieldDescription","Description","FieldError","ErrorMessage","FieldInput","Input","FieldTextArea","TextArea","_el$4","_tmpl$4","FieldGroup","_el$5","_tmpl$5","_el$6","_tmpl$6","FieldSeparator","_el$7","_tmpl$8","_el$8","firstChild","_el$0","nextSibling","_el$9","_tmpl$7","_$createComponent","KobalteTextField","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/field/field.tsx"],"sourcesContent":["import { TextField as KobalteTextField } from '@kobalte/core/text-field'\nimport type { ComponentProps, JSX } from 'solid-js'\nimport { createUniqueId, Show, splitProps } from 'solid-js'\nimport { Label } from '../label/label'\nimport { createFormFieldContext, FormFieldContext } from '#lib/form-field'\nimport { cn } from '#lib/utils'\n\n/**\n * Field.\n *\n * The wrapper that makes a form control describable and validatable: a label,\n * a description, an error message, and the ARIA relationships between them.\n *\n * This Kobalte TextField composition is for its own `FieldLabel`, `FieldInput`\n * and `FieldTextArea` parts. Use `FormField` to wire the standalone shared\n * controls, including checkboxes, switches and comboboxes.\n *\n * It is built on Kobalte's TextField specifically so `aria-describedby`,\n * `aria-invalid` and `aria-errormessage` are wired by construction. Those three\n * attributes are the difference between \"this field is required and empty\" and\n * a red border that only a sighted user can perceive — and they are also the\n * first thing a hand-rolled form drops.\n *\n * `Field` owns the description and the error slot, so its controls line up and\n * its messages land in the same place regardless of which TextField part is used.\n */\nexport function Field(props: ComponentProps<typeof KobalteTextField>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteTextField class={cn('flex flex-col gap-1.5', local.class)} {...rest} />\n}\n\nexport type FormFieldProps = Omit<ComponentProps<'div'>, 'children' | 'ref'> & {\n label: string\n hint?: string\n error?: string\n controlId?: string\n group?: boolean\n children: JSX.Element\n}\n\n/**\n * FormField.\n *\n * A shared label, help and validation wrapper for any one shared control. Its\n * context is consumed by Input, Textarea, NativeSelect, Checkbox, Switch,\n * RadioGroup and ComboboxInput, so the actual focusable element receives the\n * generated ID and description relationships. Set `group` when the label names\n * a set of controls; the wrapper then uses fieldset and legend semantics.\n */\nexport function FormField(props: FormFieldProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'label',\n 'hint',\n 'error',\n 'controlId',\n 'group',\n 'children',\n ])\n const fieldId = createUniqueId()\n const labelId = `${fieldId}-label`\n const descriptionId = `${fieldId}-description`\n const errorId = `${fieldId}-error`\n const field = createFormFieldContext({\n controlId: local.controlId,\n defaultControlId: fieldId,\n labelId,\n descriptionId,\n errorId,\n hint: () => local.hint,\n error: () => local.error,\n group: () => local.group ?? false,\n })\n const help = () => (\n <>\n <Show when={local.hint}>\n <p id={descriptionId} class=\"text-muted-foreground text-sm\">\n {local.hint}\n </p>\n </Show>\n <Show when={local.error}>\n <p id={errorId} role=\"alert\" class=\"text-foreground text-sm\">\n {local.error}\n </p>\n </Show>\n </>\n )\n\n return (\n <FormFieldContext.Provider value={field}>\n <div class={cn('flex flex-col gap-1.5', local.class)} {...rest}>\n {local.group ? (\n <FieldSet\n class=\"flex flex-col gap-1.5\"\n aria-describedby={field.describedBy()}\n aria-invalid={field.invalid() || undefined}\n >\n <FieldLegend id={labelId} variant=\"label\">\n {local.label}\n </FieldLegend>\n {local.children}\n {help()}\n </FieldSet>\n ) : (\n <>\n <Label id={labelId} for={field.controlId()}>\n {local.label}\n </Label>\n {local.children}\n {help()}\n </>\n )}\n </div>\n </FormFieldContext.Provider>\n )\n}\n\nexport function FieldLabel(props: ComponentProps<typeof KobalteTextField.Label>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteTextField.Label class={cn('text-sm leading-none font-medium', local.class)} {...rest} />\n )\n}\n\nexport function FieldDescription(props: ComponentProps<typeof KobalteTextField.Description>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteTextField.Description\n class={cn('text-muted-foreground text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function FieldError(props: ComponentProps<typeof KobalteTextField.ErrorMessage>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteTextField.ErrorMessage class={cn('text-foreground text-sm', local.class)} {...rest} />\n )\n}\n\nexport function FieldInput(props: ComponentProps<typeof KobalteTextField.Input>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteTextField.Input\n class={cn(\n 'h-control-md w-full min-w-0 rounded-md border border-input bg-transparent px-control-md py-1 text-sm',\n 'transition-[color,box-shadow,border-color] ease-out outline-none',\n 'placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',\n 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function FieldTextArea(props: ComponentProps<typeof KobalteTextField.TextArea>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteTextField.TextArea\n class={cn(\n 'flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-control-md py-2 text-sm',\n 'transition-[color,box-shadow,border-color] ease-out outline-none resize-y',\n 'placeholder:text-muted-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',\n 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/**\n * A labelled group of fields with a single legend, for a real `<fieldset>`.\n * Grouping is what lets a screen reader announce \"Shipping address, group\"\n * before reading the four fields inside it.\n */\nexport function FieldSet(props: ComponentProps<'fieldset'>) {\n const [local, rest] = splitProps(props, ['class'])\n return <fieldset class={cn('flex flex-col gap-4', local.class)} {...rest} />\n}\n\n/** A visual stack for related controls that does not imply fieldset semantics. */\nexport function FieldGroup(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return <div data-slot=\"field-group\" class={cn('flex flex-col gap-4', local.class)} {...rest} />\n}\n\nexport function FieldLegend(props: ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) {\n const [local, rest] = splitProps(props, ['class', 'variant'])\n return (\n <legend\n class={cn(\n 'mb-1',\n local.variant === 'label'\n ? 'text-sm font-medium'\n : 'text-base font-semibold tracking-tight',\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/** A horizontal rule with a word in it, for \"or continue with\" separators. */\nexport function FieldSeparator(props: {\n class?: string\n children?: ComponentProps<'span'>['children']\n}) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <div class={cn('relative flex items-center gap-3 py-1', local.class)} {...rest}>\n <span class=\"bg-border h-px flex-1\" />\n <Show when={local.children}>\n <span class=\"text-muted-foreground text-2xs tracking-wide uppercase\">{local.children}</span>\n </Show>\n <span class=\"bg-border h-px flex-1\" />\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
export { Field, FieldDescription, FieldError, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, } from './field';
|
|
1
|
+
export { Field, FormField, FieldDescription, FieldError, FieldGroup, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, type FormFieldProps, } from './field';
|
|
2
|
+
export { NumberField } from './number-field';
|
|
3
|
+
export type { NumberFieldProps } from './number-field';
|
|
2
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/field/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,QAAQ,EACR,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/field/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,QAAQ,EACR,aAAa,EACb,KAAK,cAAc,GACpB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA"}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import { Field, FieldDescription, FieldError, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea } from "./field.js";
|
|
2
|
-
|
|
1
|
+
import { Field, FieldDescription, FieldError, FieldGroup, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, FormField } from "./field.js";
|
|
2
|
+
import { NumberField } from "./number-field.js";
|
|
3
|
+
export { Field, FieldDescription, FieldError, FieldGroup, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, FormField, NumberField };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type JSX } from 'solid-js';
|
|
2
|
+
export type NumberFieldProps = {
|
|
3
|
+
label: string;
|
|
4
|
+
hint?: string;
|
|
5
|
+
value: number;
|
|
6
|
+
min: number;
|
|
7
|
+
max: number;
|
|
8
|
+
integer?: boolean;
|
|
9
|
+
onChange: (value: number) => void;
|
|
10
|
+
class?: string;
|
|
11
|
+
onBlur?: JSX.EventHandler<HTMLInputElement, FocusEvent>;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* A controlled numeric field that keeps an editable draft while validating
|
|
15
|
+
* range and integer constraints. Invalid drafts are announced and restored
|
|
16
|
+
* to the latest controlled value when focus leaves the input.
|
|
17
|
+
*/
|
|
18
|
+
export declare function NumberField(props: NumberFieldProps): JSX.Element;
|
|
19
|
+
//# sourceMappingURL=number-field.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"number-field.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/field/number-field.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA8B,KAAK,GAAG,EAAE,MAAM,UAAU,CAAA;AAI/D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAA;CACxD,CAAA;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,eAiDlD"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { FormField } from "./field.js";
|
|
2
|
+
import { Input } from "../input/input.js";
|
|
3
|
+
import { createComponent } from "solid-js/web";
|
|
4
|
+
import { createEffect, createSignal } from "solid-js";
|
|
5
|
+
//#region src/components/ui/field/number-field.tsx
|
|
6
|
+
/**
|
|
7
|
+
* A controlled numeric field that keeps an editable draft while validating
|
|
8
|
+
* range and integer constraints. Invalid drafts are announced and restored
|
|
9
|
+
* to the latest controlled value when focus leaves the input.
|
|
10
|
+
*/
|
|
11
|
+
function NumberField(props) {
|
|
12
|
+
const [draft, setDraft] = createSignal(String(props.value));
|
|
13
|
+
const [error, setError] = createSignal("");
|
|
14
|
+
const integer = () => props.integer ?? true;
|
|
15
|
+
createEffect(() => {
|
|
16
|
+
setDraft(String(props.value));
|
|
17
|
+
});
|
|
18
|
+
const validate = (raw) => {
|
|
19
|
+
if (!raw) return `${props.label} is required.`;
|
|
20
|
+
const next = Number(raw);
|
|
21
|
+
if (!Number.isFinite(next)) return `${props.label} must be a valid number.`;
|
|
22
|
+
if (integer() && !Number.isInteger(next)) return `${props.label} must be a whole number.`;
|
|
23
|
+
if (next < props.min || next > props.max) return `${props.label} must be between ${props.min} and ${props.max}.`;
|
|
24
|
+
return "";
|
|
25
|
+
};
|
|
26
|
+
return createComponent(FormField, {
|
|
27
|
+
get label() {
|
|
28
|
+
return props.label;
|
|
29
|
+
},
|
|
30
|
+
get hint() {
|
|
31
|
+
return props.hint;
|
|
32
|
+
},
|
|
33
|
+
get error() {
|
|
34
|
+
return error();
|
|
35
|
+
},
|
|
36
|
+
get ["class"]() {
|
|
37
|
+
return props.class;
|
|
38
|
+
},
|
|
39
|
+
get children() {
|
|
40
|
+
return createComponent(Input, {
|
|
41
|
+
type: "number",
|
|
42
|
+
get value() {
|
|
43
|
+
return draft();
|
|
44
|
+
},
|
|
45
|
+
get min() {
|
|
46
|
+
return props.min;
|
|
47
|
+
},
|
|
48
|
+
get max() {
|
|
49
|
+
return props.max;
|
|
50
|
+
},
|
|
51
|
+
get step() {
|
|
52
|
+
return integer() ? 1 : "any";
|
|
53
|
+
},
|
|
54
|
+
required: true,
|
|
55
|
+
onInput: (event) => {
|
|
56
|
+
const raw = event.currentTarget.value;
|
|
57
|
+
setDraft(raw);
|
|
58
|
+
const nextError = validate(raw);
|
|
59
|
+
setError(nextError);
|
|
60
|
+
if (!nextError) props.onChange(Number(raw));
|
|
61
|
+
},
|
|
62
|
+
onBlur: (event) => {
|
|
63
|
+
if (validate(draft())) {
|
|
64
|
+
setDraft(String(props.value));
|
|
65
|
+
setError("");
|
|
66
|
+
}
|
|
67
|
+
props.onBlur?.(event);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { NumberField };
|
|
75
|
+
|
|
76
|
+
//# sourceMappingURL=number-field.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"number-field.js","names":["createEffect","createSignal","JSX","FormField","Input","NumberFieldProps","label","hint","value","min","max","integer","onChange","class","onBlur","EventHandler","HTMLInputElement","FocusEvent","NumberField","props","draft","setDraft","String","error","setError","validate","raw","next","Number","isFinite","isInteger","_$createComponent","children","type","step","required","onInput","event","currentTarget","nextError","_$createComponent"],"sources":["../../../../src/components/ui/field/number-field.tsx"],"sourcesContent":["import { createEffect, createSignal, type JSX } from 'solid-js'\nimport { FormField } from './field'\nimport { Input } from '../input/input'\n\nexport type NumberFieldProps = {\n label: string\n hint?: string\n value: number\n min: number\n max: number\n integer?: boolean\n onChange: (value: number) => void\n class?: string\n onBlur?: JSX.EventHandler<HTMLInputElement, FocusEvent>\n}\n\n/**\n * A controlled numeric field that keeps an editable draft while validating\n * range and integer constraints. Invalid drafts are announced and restored\n * to the latest controlled value when focus leaves the input.\n */\nexport function NumberField(props: NumberFieldProps) {\n const [draft, setDraft] = createSignal(String(props.value))\n const [error, setError] = createSignal('')\n const integer = () => props.integer ?? true\n\n createEffect(() => {\n setDraft(String(props.value))\n })\n\n const validate = (raw: string) => {\n if (!raw) return `${props.label} is required.`\n const next = Number(raw)\n if (!Number.isFinite(next)) return `${props.label} must be a valid number.`\n if (integer() && !Number.isInteger(next)) {\n return `${props.label} must be a whole number.`\n }\n if (next < props.min || next > props.max) {\n return `${props.label} must be between ${props.min} and ${props.max}.`\n }\n return ''\n }\n\n return (\n <FormField label={props.label} hint={props.hint} error={error()} class={props.class}>\n <Input\n type=\"number\"\n value={draft()}\n min={props.min}\n max={props.max}\n step={integer() ? 1 : 'any'}\n required\n onInput={(event) => {\n const raw = event.currentTarget.value\n setDraft(raw)\n const nextError = validate(raw)\n setError(nextError)\n if (!nextError) props.onChange(Number(raw))\n }}\n onBlur={(event) => {\n const nextError = validate(draft())\n if (nextError) {\n setDraft(String(props.value))\n setError('')\n }\n props.onBlur?.(event)\n }}\n />\n </FormField>\n )\n}\n"],"mappings":";;;;;;;;;;AAqBA,SAAgBkB,YAAYC,OAAyB;CACnD,MAAM,CAACC,OAAOC,YAAYpB,aAAaqB,OAAOH,MAAMX,KAAK,CAAC;CAC1D,MAAM,CAACe,OAAOC,YAAYvB,aAAa,EAAE;CACzC,MAAMU,gBAAgBQ,MAAMR,WAAW;CAEvCX,mBAAmB;EACjBqB,SAASC,OAAOH,MAAMX,KAAK,CAAC;CAC9B,CAAC;CAED,MAAMiB,YAAYC,QAAgB;EAChC,IAAI,CAACA,KAAK,OAAO,GAAGP,MAAMb,MAAK;EAC/B,MAAMqB,OAAOC,OAAOF,GAAG;EACvB,IAAI,CAACE,OAAOC,SAASF,IAAI,GAAG,OAAO,GAAGR,MAAMb,MAAK;EACjD,IAAIK,QAAQ,KAAK,CAACiB,OAAOE,UAAUH,IAAI,GACrC,OAAO,GAAGR,MAAMb,MAAK;EAEvB,IAAIqB,OAAOR,MAAMV,OAAOkB,OAAOR,MAAMT,KACnC,OAAO,GAAGS,MAAMb,MAAK,mBAAoBa,MAAMV,IAAG,OAAQU,MAAMT,IAAG;EAErE,OAAO;CACT;CAEA,OAAAqB,gBACG5B,WAAS;EAAA,IAACG,QAAK;GAAA,OAAEa,MAAMb;EAAK;EAAA,IAAEC,OAAI;GAAA,OAAEY,MAAMZ;EAAI;EAAA,IAAEgB,QAAK;GAAA,OAAEA,MAAM;EAAC;EAAA,KAAA,WAAA;GAAA,OAASJ,MAAMN;EAAK;EAAA,IAAAmB,WAAA;GAAA,OAAAD,gBAChF3B,OAAK;IACJ6B,MAAI;IAAA,IACJzB,QAAK;KAAA,OAAEY,MAAM;IAAC;IAAA,IACdX,MAAG;KAAA,OAAEU,MAAMV;IAAG;IAAA,IACdC,MAAG;KAAA,OAAES,MAAMT;IAAG;IAAA,IACdwB,OAAI;KAAA,OAAEvB,QAAQ,IAAI,IAAI;IAAK;IAC3BwB,UAAQ;IACRC,UAAUC,UAAU;KAClB,MAAMX,MAAMW,MAAMC,cAAc9B;KAChCa,SAASK,GAAG;KACZ,MAAMa,YAAYd,SAASC,GAAG;KAC9BF,SAASe,SAAS;KAClB,IAAI,CAACA,WAAWpB,MAAMP,SAASgB,OAAOF,GAAG,CAAC;IAC5C;IACAZ,SAASuB,UAAU;KAEjB,IADkBZ,SAASL,MAAM,CAC7BmB,GAAW;MACblB,SAASC,OAAOH,MAAMX,KAAK,CAAC;MAC5BgB,SAAS,EAAE;KACb;KACAL,MAAML,SAASuB,KAAK;IACtB;GAAC,CAAA;EAAA;CAAA,CAAA;AAIT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/input/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/input/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ComponentProps } from 'solid-js';
|
|
2
|
+
/**
|
|
3
|
+
* InputControl.
|
|
4
|
+
*
|
|
5
|
+
* A styled native input with no optional suggestion-list behavior. Use this
|
|
6
|
+
* when a consumer needs only the control; `Input` adds native datalist
|
|
7
|
+
* suggestions for forms that need them.
|
|
8
|
+
*/
|
|
9
|
+
export type InputControlProps = ComponentProps<'input'>;
|
|
10
|
+
export declare function InputControl(props: InputControlProps): import("solid-js").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=input-control.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-control.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/input/input-control.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAI9C;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,CAAC,CAAA;AAEvD,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,kCAwBpD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { cn } from "../../../lib/utils.js";
|
|
2
|
+
import { mergeProps, spread, template } from "solid-js/web";
|
|
3
|
+
import { splitProps } from "solid-js";
|
|
4
|
+
//#region src/components/ui/input/input-control.tsx
|
|
5
|
+
var _tmpl$ = /*#__PURE__*/ template(`<input data-slot=input>`);
|
|
6
|
+
function InputControl(props) {
|
|
7
|
+
const [local, rest] = splitProps(props, ["class", "type"]);
|
|
8
|
+
return (() => {
|
|
9
|
+
var _el$ = _tmpl$();
|
|
10
|
+
spread(_el$, mergeProps({
|
|
11
|
+
get type() {
|
|
12
|
+
return local.type ?? "text";
|
|
13
|
+
},
|
|
14
|
+
get ["class"]() {
|
|
15
|
+
return cn("h-control-md w-full min-w-0 rounded-md border border-input bg-transparent px-control-md py-1 text-sm", "transition-[color,box-shadow,border-color] ease-out outline-none", "placeholder:text-muted-foreground", "selection:bg-primary selection:text-primary-foreground", "file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground", "focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle", "aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle", "disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50", "read-only:bg-surface-hover", local.class);
|
|
16
|
+
}
|
|
17
|
+
}, rest), false, false);
|
|
18
|
+
return _el$;
|
|
19
|
+
})();
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { InputControl };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=input-control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-control.js","names":["ComponentProps","splitProps","cn","InputControlProps","InputControl","props","local","rest","_el$","_tmpl$","_$spread","_$mergeProps","type","class","_$mergeProps"],"sources":["../../../../src/components/ui/input/input-control.tsx"],"sourcesContent":["import type { ComponentProps } from 'solid-js'\nimport { splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\n\n/**\n * InputControl.\n *\n * A styled native input with no optional suggestion-list behavior. Use this\n * when a consumer needs only the control; `Input` adds native datalist\n * suggestions for forms that need them.\n */\nexport type InputControlProps = ComponentProps<'input'>\n\nexport function InputControl(props: InputControlProps) {\n const [local, rest] = splitProps(props, ['class', 'type'])\n\n return (\n <input\n data-slot=\"input\"\n type={local.type ?? 'text'}\n class={cn(\n 'h-control-md w-full min-w-0 rounded-md border border-input bg-transparent px-control-md py-1 text-sm',\n 'transition-[color,box-shadow,border-color] ease-out outline-none',\n 'placeholder:text-muted-foreground',\n 'selection:bg-primary selection:text-primary-foreground',\n 'file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground',\n /* A pointer click on a text field is a typing affordance, so the ring\n appears where the user agent already matches :focus-visible. */\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',\n 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',\n 'read-only:bg-surface-hover',\n local.class\n )}\n {...rest}\n />\n )\n}\n"],"mappings":";;;;;AAaA,SAAgBI,aAAaC,OAA0B;CACrD,MAAM,CAACC,OAAOC,QAAQN,WAAWI,OAAO,CAAC,SAAS,MAAM,CAAC;CAEzD,cAAA;EAAA,IAAAG,OAAAC,OAAA;EAAAC,OAAAF,MAAAG,WAAA;GAAA,IAGIC,OAAI;IAAA,OAAEN,MAAMM,QAAQ;GAAM;GAAA,KAAA,WAAA;IAAA,OACnBV,GACL,wGACA,oEACA,qCACA,0DACA,kHAGA,oFACA,4FACA,gFACA,8BACAI,MAAMO,KACR;GAAC;EAAA,GACGN,IAAI,GAAA,OAAA,KAAA;EAAA,OAAAC;CAAA,EAAA,CAAA;AAGd"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/input/input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/input/input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAK9C;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG;IACjD,gFAAgF;IAChF,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAChC,CAAA;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,kCA+CtC"}
|
|
@@ -1,51 +1,79 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useFormFieldControl } from "../../../lib/form-field.js";
|
|
2
|
+
import { InputControl } from "./input-control.js";
|
|
3
|
+
import { createComponent, effect, insert, memo, mergeProps, setAttribute, template } from "solid-js/web";
|
|
3
4
|
import { For, Show, createUniqueId, splitProps } from "solid-js";
|
|
4
5
|
//#region src/components/ui/input/input.tsx
|
|
5
|
-
var _tmpl$ = /*#__PURE__*/ template(`<
|
|
6
|
-
var _tmpl$2 = /*#__PURE__*/ template(`<
|
|
7
|
-
var _tmpl$3 = /*#__PURE__*/ template(`<option>`);
|
|
6
|
+
var _tmpl$ = /*#__PURE__*/ template(`<datalist>`);
|
|
7
|
+
var _tmpl$2 = /*#__PURE__*/ template(`<option>`);
|
|
8
8
|
function Input(props) {
|
|
9
9
|
const [local, rest] = splitProps(props, [
|
|
10
10
|
"class",
|
|
11
11
|
"type",
|
|
12
|
+
"id",
|
|
12
13
|
"list",
|
|
13
|
-
"suggestions"
|
|
14
|
+
"suggestions",
|
|
15
|
+
"aria-label",
|
|
16
|
+
"aria-labelledby",
|
|
17
|
+
"aria-describedby",
|
|
18
|
+
"aria-invalid",
|
|
19
|
+
"aria-errormessage"
|
|
14
20
|
]);
|
|
21
|
+
const field = useFormFieldControl("control", {
|
|
22
|
+
id: local.id,
|
|
23
|
+
"aria-label": local["aria-label"],
|
|
24
|
+
"aria-labelledby": local["aria-labelledby"],
|
|
25
|
+
"aria-describedby": local["aria-describedby"],
|
|
26
|
+
"aria-invalid": local["aria-invalid"],
|
|
27
|
+
"aria-errormessage": local["aria-errormessage"]
|
|
28
|
+
});
|
|
15
29
|
const suggestionsId = createUniqueId();
|
|
16
30
|
const listId = () => local.list ?? `input-suggestions-${suggestionsId}`;
|
|
17
|
-
return [((
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
return [createComponent(InputControl, mergeProps(rest, {
|
|
32
|
+
get ["class"]() {
|
|
33
|
+
return local.class;
|
|
34
|
+
},
|
|
35
|
+
get type() {
|
|
36
|
+
return local.type;
|
|
37
|
+
},
|
|
38
|
+
get id() {
|
|
39
|
+
return field?.id ?? local.id;
|
|
40
|
+
},
|
|
41
|
+
get list() {
|
|
42
|
+
return memo(() => !!local.suggestions)() ? listId() : local.list;
|
|
43
|
+
},
|
|
44
|
+
get ["aria-label"]() {
|
|
45
|
+
return local["aria-label"];
|
|
46
|
+
},
|
|
47
|
+
get ["aria-labelledby"]() {
|
|
48
|
+
return field?.["aria-labelledby"] ?? local["aria-labelledby"];
|
|
49
|
+
},
|
|
50
|
+
get ["aria-describedby"]() {
|
|
51
|
+
return field?.["aria-describedby"] ?? local["aria-describedby"];
|
|
52
|
+
},
|
|
53
|
+
get ["aria-invalid"]() {
|
|
54
|
+
return field?.["aria-invalid"] ?? local["aria-invalid"];
|
|
55
|
+
},
|
|
56
|
+
get ["aria-errormessage"]() {
|
|
57
|
+
return field?.["aria-errormessage"] ?? local["aria-errormessage"];
|
|
58
|
+
}
|
|
59
|
+
})), createComponent(Show, {
|
|
32
60
|
get when() {
|
|
33
61
|
return local.suggestions;
|
|
34
62
|
},
|
|
35
63
|
children: (suggestions) => (() => {
|
|
36
|
-
var _el$
|
|
37
|
-
insert(_el
|
|
64
|
+
var _el$ = _tmpl$();
|
|
65
|
+
insert(_el$, createComponent(For, {
|
|
38
66
|
get each() {
|
|
39
67
|
return suggestions();
|
|
40
68
|
},
|
|
41
69
|
children: (value) => (() => {
|
|
42
|
-
var _el$
|
|
43
|
-
_el$
|
|
44
|
-
return _el$
|
|
70
|
+
var _el$2 = _tmpl$2();
|
|
71
|
+
_el$2.value = value;
|
|
72
|
+
return _el$2;
|
|
45
73
|
})()
|
|
46
74
|
}));
|
|
47
|
-
effect(() => setAttribute(_el
|
|
48
|
-
return _el
|
|
75
|
+
effect(() => setAttribute(_el$, "id", listId()));
|
|
76
|
+
return _el$;
|
|
49
77
|
})()
|
|
50
78
|
})];
|
|
51
79
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.js","names":["ComponentProps","createUniqueId","For","Show","splitProps","
|
|
1
|
+
{"version":3,"file":"input.js","names":["ComponentProps","createUniqueId","For","Show","splitProps","useFormFieldControl","InputControl","InputProps","suggestions","Input","props","local","rest","field","id","suggestionsId","listId","list","_$createComponent","_$mergeProps","class","type","_$memo","aria-label","aria-labelledby","aria-describedby","aria-invalid","aria-errormessage","when","children","_el$","_tmpl$","_$insert","each","value","_el$2","_tmpl$2","_$effect","_$setAttribute","_$createComponent","_$mergeProps","_$memo","_$setAttribute"],"sources":["../../../../src/components/ui/input/input.tsx"],"sourcesContent":["import type { ComponentProps } from 'solid-js'\nimport { createUniqueId, For, Show, splitProps } from 'solid-js'\nimport { useFormFieldControl } from '#lib/form-field'\nimport { InputControl } from './input-control'\n\n/**\n * Input.\n *\n * Deliberately a plain `<input>` rather than a Kobalte TextField part. The\n * styling contract is what a consumer needs from an input; validation,\n * description and error wiring come from `Field`, which composes this. Keeping\n * them separate is what lets an input sit inside a custom control without\n * inheriting a form's ARIA graph.\n *\n * Height comes from `h-control-md`; an input cannot be given a new height\n * without a new token, which is what keeps it aligned with Button and Select.\n */\nexport type InputProps = ComponentProps<'input'> & {\n /** Native text suggestions; custom values remain valid and submit unchanged. */\n suggestions?: readonly string[]\n}\n\nexport function Input(props: InputProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'type',\n 'id',\n 'list',\n 'suggestions',\n 'aria-label',\n 'aria-labelledby',\n 'aria-describedby',\n 'aria-invalid',\n 'aria-errormessage',\n ])\n const field = useFormFieldControl('control', {\n id: local.id,\n 'aria-label': local['aria-label'],\n 'aria-labelledby': local['aria-labelledby'],\n 'aria-describedby': local['aria-describedby'],\n 'aria-invalid': local['aria-invalid'],\n 'aria-errormessage': local['aria-errormessage'],\n })\n const suggestionsId = createUniqueId()\n const listId = () => local.list ?? `input-suggestions-${suggestionsId}`\n\n return (\n <>\n <InputControl\n {...rest}\n class={local.class}\n type={local.type}\n id={field?.id ?? local.id}\n list={local.suggestions ? listId() : local.list}\n aria-label={local['aria-label']}\n aria-labelledby={field?.['aria-labelledby'] ?? local['aria-labelledby']}\n aria-describedby={field?.['aria-describedby'] ?? local['aria-describedby']}\n aria-invalid={field?.['aria-invalid'] ?? local['aria-invalid']}\n aria-errormessage={field?.['aria-errormessage'] ?? local['aria-errormessage']}\n />\n <Show when={local.suggestions}>\n {(suggestions) => (\n <datalist id={listId()}>\n <For each={suggestions()}>{(value) => <option value={value} />}</For>\n </datalist>\n )}\n </Show>\n </>\n )\n}\n"],"mappings":";;;;;;;AAsBA,SAAgBS,MAAMC,OAAmB;CACvC,MAAM,CAACC,OAAOC,QAAQR,WAAWM,OAAO;EACtC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CAAmB,CACpB;CACD,MAAMG,QAAQR,oBAAoB,WAAW;EAC3CS,IAAIH,MAAMG;EACV,cAAcH,MAAM;EACpB,mBAAmBA,MAAM;EACzB,oBAAoBA,MAAM;EAC1B,gBAAgBA,MAAM;EACtB,qBAAqBA,MAAM;CAC7B,CAAC;CACD,MAAMI,gBAAgBd,eAAe;CACrC,MAAMe,eAAeL,MAAMM,QAAQ,qBAAqBF;CAExD,OAAA,CAAAG,gBAEKZ,cAAYa,WACPP,MAAI;EAAA,KAAA,WAAA;GAAA,OACDD,MAAMS;EAAK;EAAA,IAClBC,OAAI;GAAA,OAAEV,MAAMU;EAAI;EAAA,IAChBP,KAAE;GAAA,OAAED,OAAOC,MAAMH,MAAMG;EAAE;EAAA,IACzBG,OAAI;GAAA,OAAEK,WAAA,CAAA,CAAAX,MAAMH,WAAW,CAAA,CAAA,IAAGQ,OAAO,IAAIL,MAAMM;EAAI;EAAA,KAAA,gBAAA;GAAA,OACnCN,MAAM;EAAa;EAAA,KAAA,qBAAA;GAAA,OACdE,QAAQ,sBAAsBF,MAAM;EAAkB;EAAA,KAAA,sBAAA;GAAA,OACrDE,QAAQ,uBAAuBF,MAAM;EAAmB;EAAA,KAAA,kBAAA;GAAA,OAC5DE,QAAQ,mBAAmBF,MAAM;EAAe;EAAA,KAAA,uBAAA;GAAA,OAC3CE,QAAQ,wBAAwBF,MAAM;EAAoB;CAAA,CAAA,CAAA,GAAAO,gBAE9Ef,MAAI;EAAA,IAACyB,OAAI;GAAA,OAAEjB,MAAMH;EAAW;EAAAqB,WACzBrB,uBAAW;GAAA,IAAAsB,OAAAC,OAAA;GAAAC,OAAAF,MAAAZ,gBAERhB,KAAG;IAAA,IAAC+B,OAAI;KAAA,OAAEzB,YAAY;IAAC;IAAAqB,WAAIK,iBAAK;KAAA,IAAAC,QAAAC,QAAA;KAAAD,MAAAD,QAAoBA;KAAK,OAAAC;IAAA,EAAA,CAAA;GAAI,CAAA,CAAA;GAAAE,aAAAC,aAAAR,MAAA,MADlDd,OAAO,CAAC,CAAA;GAAA,OAAAc;EAAA,EAAA,CAAA;CAGvB,CAAA,CAAA;AAIT"}
|