compote-ui 0.72.0 → 0.74.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/date-field/date-field.svelte +2 -0
- package/dist/components/date-field/types.d.ts +6 -0
- package/dist/components/date-range-field/date-range-field.svelte +2 -0
- package/dist/components/date-range-field/types.d.ts +6 -0
- package/dist/components/field/field.svelte +21 -4
- package/dist/components/field/types.d.ts +8 -0
- package/package.json +1 -1
- package/skills/component-usage/references/forms-and-inputs.md +19 -0
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
locale: localeProp,
|
|
26
26
|
granularity,
|
|
27
27
|
hourCycle,
|
|
28
|
+
hideTimeZone = true,
|
|
28
29
|
onValueChange
|
|
29
30
|
}: DateFieldProps = $props();
|
|
30
31
|
|
|
@@ -89,6 +90,7 @@
|
|
|
89
90
|
locale: resolvedLocale,
|
|
90
91
|
granularity: granularity ?? 'day',
|
|
91
92
|
hourCycle,
|
|
93
|
+
hideTimeZone,
|
|
92
94
|
value: datePicker().value,
|
|
93
95
|
min,
|
|
94
96
|
max,
|
|
@@ -18,4 +18,10 @@ export interface DateFieldProps extends Omit<DatePickerRootBaseProps, 'value' |
|
|
|
18
18
|
name?: string;
|
|
19
19
|
granularity?: 'day' | 'hour' | 'minute' | 'second';
|
|
20
20
|
hourCycle?: 12 | 24;
|
|
21
|
+
/**
|
|
22
|
+
* Hide the trailing time-zone segment (e.g. `GMT+2`) that a zoned value shows
|
|
23
|
+
* at time granularity. Defaults to `true`, matching `DateInput`. Not inherited
|
|
24
|
+
* from Ark: `hideTimeZone` is a date-input prop, not a date-picker one.
|
|
25
|
+
*/
|
|
26
|
+
hideTimeZone?: boolean;
|
|
21
27
|
}
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
timeZone,
|
|
29
29
|
granularity,
|
|
30
30
|
hourCycle,
|
|
31
|
+
hideTimeZone = true,
|
|
31
32
|
onValueChange
|
|
32
33
|
}: DateRangeFieldProps = $props();
|
|
33
34
|
|
|
@@ -102,6 +103,7 @@
|
|
|
102
103
|
selectionMode: 'range',
|
|
103
104
|
granularity: granularity ?? 'day',
|
|
104
105
|
hourCycle,
|
|
106
|
+
hideTimeZone,
|
|
105
107
|
value: datePicker().value,
|
|
106
108
|
min,
|
|
107
109
|
max,
|
|
@@ -26,4 +26,10 @@ export interface DateRangeFieldProps extends Omit<DatePickerRootBaseProps, 'valu
|
|
|
26
26
|
endName?: string;
|
|
27
27
|
granularity?: 'day' | 'hour' | 'minute' | 'second';
|
|
28
28
|
hourCycle?: 12 | 24;
|
|
29
|
+
/**
|
|
30
|
+
* Hide the trailing time-zone segment (e.g. `GMT+2`) that a zoned value shows
|
|
31
|
+
* at time granularity. Defaults to `true`, matching `DateInput`. Not inherited
|
|
32
|
+
* from Ark: `hideTimeZone` is a date-input prop, not a date-picker one.
|
|
33
|
+
*/
|
|
34
|
+
hideTimeZone?: boolean;
|
|
29
35
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
form,
|
|
8
8
|
field,
|
|
9
9
|
helperText,
|
|
10
|
+
errorText,
|
|
10
11
|
class: className,
|
|
11
12
|
invalid,
|
|
12
13
|
required,
|
|
@@ -14,9 +15,15 @@
|
|
|
14
15
|
...rest
|
|
15
16
|
}: FieldRootProps = $props();
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
// Declared before isInvalid, which reads it.
|
|
19
|
+
const resolvedError = $derived(
|
|
20
|
+
form && field ? (form.errors[field]?.[0] ?? null) : (errorText ?? null)
|
|
21
|
+
);
|
|
22
|
+
// An error that does not also mark the field invalid renders nothing at all:
|
|
23
|
+
// Ark's Field.ErrorText is gated on the field context's `invalid`. So a bare
|
|
24
|
+
// `errorText` implies it, while an explicit `invalid` still wins.
|
|
25
|
+
const isInvalid = $derived(form && field ? form.invalid(field) : (invalid ?? !!resolvedError));
|
|
18
26
|
const isRequired = $derived(form && field ? form.isRequired(field) : (required ?? false));
|
|
19
|
-
const errorText = $derived(form && field ? (form.errors[field]?.[0] ?? null) : null);
|
|
20
27
|
</script>
|
|
21
28
|
|
|
22
29
|
<Field.Root
|
|
@@ -26,9 +33,19 @@
|
|
|
26
33
|
class={cn('group flex flex-col gap-1.5', className)}
|
|
27
34
|
>
|
|
28
35
|
{@render children?.()}
|
|
29
|
-
{#if
|
|
30
|
-
<Field.ErrorText>{
|
|
36
|
+
{#if resolvedError}
|
|
37
|
+
<Field.ErrorText>{resolvedError}</Field.ErrorText>
|
|
31
38
|
{:else if helperText}
|
|
32
39
|
<Field.HelperText>{helperText}</Field.HelperText>
|
|
40
|
+
{:else}
|
|
41
|
+
<!--
|
|
42
|
+
Holds the message line open so a field does not change height when an
|
|
43
|
+
error appears. `1lh` resolves against this element's own line-height, so
|
|
44
|
+
it tracks the theme's font rather than assuming a pixel height. A plain
|
|
45
|
+
div and not an empty Field.HelperText: Ark gives that one an id which
|
|
46
|
+
aria-describedby points at, which would describe the control as having a
|
|
47
|
+
description that isn't there.
|
|
48
|
+
-->
|
|
49
|
+
<div class="h-lh text-xs" aria-hidden="true"></div>
|
|
33
50
|
{/if}
|
|
34
51
|
</Field.Root>
|
|
@@ -11,6 +11,14 @@ export interface FieldRootProps extends FieldRootBaseProps {
|
|
|
11
11
|
form?: FormAdapter;
|
|
12
12
|
field?: string;
|
|
13
13
|
helperText?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Error to render below the control, for validation that does not go through
|
|
16
|
+
* a {@link FormAdapter} (e.g. a SvelteKit remote form's `field.issues()`).
|
|
17
|
+
* Passing it also marks the field invalid unless `invalid` is set explicitly.
|
|
18
|
+
* Ignored when `form` and `field` are given — the adapter wins, as it does
|
|
19
|
+
* for `invalid` and `required`.
|
|
20
|
+
*/
|
|
21
|
+
errorText?: string | null;
|
|
14
22
|
}
|
|
15
23
|
export interface FieldLabelProps extends FieldLabelBaseProps {
|
|
16
24
|
class?: ClassValue;
|
package/package.json
CHANGED
|
@@ -19,6 +19,25 @@ With a form adapter, `Field.Root` derives invalid/required state and renders the
|
|
|
19
19
|
</Field.Root>
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
`errorText` is the per-field route to that same line, for validation that doesn't fit the adapter's
|
|
23
|
+
`Record<string, string[]>` shape — a SvelteKit remote form's `field.issues()`, say. **Passing it
|
|
24
|
+
marks the field invalid**; an explicit `invalid` still wins, and the adapter wins over both.
|
|
25
|
+
|
|
26
|
+
```svelte
|
|
27
|
+
<Field.Root required errorText={fields.password.issues()?.[0]?.message}>
|
|
28
|
+
<PasswordInput label="Password" name={fields.password.as('password').name} />
|
|
29
|
+
</Field.Root>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
One message, not a list: several errors on one value are usually stages of the same judgement, and a
|
|
33
|
+
stack that grows and shrinks per keystroke is what makes a form jump. Independent requirements (a
|
|
34
|
+
password policy) belong in a persistent checklist shown from the start, not in error text. Where you
|
|
35
|
+
genuinely need several, `<Field.ErrorText>` children still work.
|
|
36
|
+
|
|
37
|
+
The message line is **always held open**, so a field never changes height when an error appears and
|
|
38
|
+
nothing below it moves. Errors and `helperText` share that line — an error replaces the helper
|
|
39
|
+
rather than stacking under it.
|
|
40
|
+
|
|
22
41
|
List controls use `{ value, label }` items:
|
|
23
42
|
|
|
24
43
|
```svelte
|