@privaty/ui-forms 0.1.5 → 0.3.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 +28 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/inputs/date-picker-input.svelte +134 -0
- package/dist/inputs/date-picker-input.svelte.d.ts +68 -0
- package/dist/inputs/month-picker-input.svelte +107 -0
- package/dist/inputs/month-picker-input.svelte.d.ts +53 -0
- package/dist/inputs/picker-frame.svelte +207 -0
- package/dist/inputs/picker-frame.svelte.d.ts +49 -0
- package/dist/inputs/week-picker-input.svelte +108 -0
- package/dist/inputs/week-picker-input.svelte.d.ts +54 -0
- package/dist/testing/tailwind.css +5 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -43,6 +43,33 @@ component, all string-valued), `SelectInput`, `CheckboxInput`. Plus
|
|
|
43
43
|
`Submit`, `Reset`, `FormError`. Icon-style Submit/Reset: pass children; the
|
|
44
44
|
label stays as the accessible name.
|
|
45
45
|
|
|
46
|
+
## Picker inputs
|
|
47
|
+
|
|
48
|
+
`DatePickerInput`, `MonthPickerInput`, and `WeekPickerInput` pair the
|
|
49
|
+
native input with the core library's cross-browser calendar pickers — the
|
|
50
|
+
custom month/week UIs Firefox never got, and one consistent picker
|
|
51
|
+
everywhere else.
|
|
52
|
+
|
|
53
|
+
- The **native input stays visible as the FormData carrier**: typing works,
|
|
54
|
+
native mobile pickers stay, and Kit reads live form data as ever. Firefox
|
|
55
|
+
renders month/week carriers as plain text inputs — exactly the gap the
|
|
56
|
+
calendar button fills.
|
|
57
|
+
- **Firefox date exception**: Firefox draws an unhideable calendar icon on
|
|
58
|
+
`type="date"` (Bugzilla 1830890), so `DatePickerInput` yields there — the
|
|
59
|
+
native icon opens Firefox's own picker and our trigger hides, keeping one
|
|
60
|
+
icon in every browser. Month/week use our picker everywhere.
|
|
61
|
+
- The overlaid calendar button opens the picker in an anchored `Popover`
|
|
62
|
+
(top layer, light dismiss, zero-lag scroll tracking). A pick **writes the
|
|
63
|
+
input the way typing does** (DOM value + a bubbling `input` event), so
|
|
64
|
+
validation cadence, touch marking, and dirty tracking are identical to
|
|
65
|
+
manual entry — one write path, no programmatic special case.
|
|
66
|
+
- `min`/`max` flow to both the native input and the picker, and `locale`
|
|
67
|
+
is on all three; `DatePickerInput` adds `isDateDisabled`,
|
|
68
|
+
`showWeekNumbers`, and `firstDayOfWeek` (all picker-side — constraints
|
|
69
|
+
still belong in the schema, typing can produce anything).
|
|
70
|
+
- The trigger's accessible name comes from `labels.calendar.open`; while
|
|
71
|
+
the form submits, the input turns readonly and the trigger disables.
|
|
72
|
+
|
|
46
73
|
## The validation model
|
|
47
74
|
|
|
48
75
|
- **With `schema`** (a Standard Schema, e.g. valibot): validation runs
|
|
@@ -99,8 +126,7 @@ availableFrom: v.pipe(v.string(), v.nonEmpty("required"), v.regex(/^\d{4}-\d{2}$
|
|
|
99
126
|
- No-JS submissions are out of scope for v1 (Submit renders its gate state
|
|
100
127
|
into SSR HTML).
|
|
101
128
|
- Browser support: Firefox has no `type="month"`/`"week"` pickers (falls
|
|
102
|
-
back to a text input) —
|
|
103
|
-
planned post-v1.
|
|
129
|
+
back to a text input) — the picker inputs above fill exactly that gap.
|
|
104
130
|
|
|
105
131
|
## Testing
|
|
106
132
|
|
package/dist/index.d.ts
CHANGED
|
@@ -9,10 +9,13 @@ export { default as Submit } from "./components/submit.svelte";
|
|
|
9
9
|
export { default as Form } from "./form.svelte";
|
|
10
10
|
export { default as CheckboxInput } from "./inputs/checkbox-input.svelte";
|
|
11
11
|
export { default as DateInput } from "./inputs/date-input.svelte";
|
|
12
|
+
export { default as DatePickerInput } from "./inputs/date-picker-input.svelte";
|
|
13
|
+
export { default as MonthPickerInput } from "./inputs/month-picker-input.svelte";
|
|
12
14
|
export { default as NumberInput } from "./inputs/number-input.svelte";
|
|
13
15
|
export { default as SelectInput } from "./inputs/select-input.svelte";
|
|
14
16
|
export { default as TextareaInput } from "./inputs/textarea-input.svelte";
|
|
15
17
|
export { default as TextInput } from "./inputs/text-input.svelte";
|
|
18
|
+
export { default as WeekPickerInput } from "./inputs/week-picker-input.svelte";
|
|
16
19
|
export { wireField } from "./inputs/wire-field";
|
|
17
20
|
export type { WiredField, WireFieldOptions } from "./inputs/wire-field";
|
|
18
21
|
export type { CheckboxField, CheckboxFieldAttributes, DateField, DateFieldAttributes, DateFieldType, FieldRegistration, NumberField, NumberFieldAttributes, SelectField, SelectFieldAttributes, TextField, TextFieldAttributes, TextFieldType, } from "./types/field";
|
package/dist/index.js
CHANGED
|
@@ -9,9 +9,12 @@ export { default as Submit } from "./components/submit.svelte";
|
|
|
9
9
|
export { default as Form } from "./form.svelte";
|
|
10
10
|
export { default as CheckboxInput } from "./inputs/checkbox-input.svelte";
|
|
11
11
|
export { default as DateInput } from "./inputs/date-input.svelte";
|
|
12
|
+
export { default as DatePickerInput } from "./inputs/date-picker-input.svelte";
|
|
13
|
+
export { default as MonthPickerInput } from "./inputs/month-picker-input.svelte";
|
|
12
14
|
export { default as NumberInput } from "./inputs/number-input.svelte";
|
|
13
15
|
export { default as SelectInput } from "./inputs/select-input.svelte";
|
|
14
16
|
export { default as TextareaInput } from "./inputs/textarea-input.svelte";
|
|
15
17
|
export { default as TextInput } from "./inputs/text-input.svelte";
|
|
18
|
+
export { default as WeekPickerInput } from "./inputs/week-picker-input.svelte";
|
|
16
19
|
// The extension point for custom inputs.
|
|
17
20
|
export { wireField } from "./inputs/wire-field";
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
Date field with a cross-browser calendar popover, wired to a SvelteKit
|
|
3
|
+
remote form field — must render inside a <Form>. The native date input
|
|
4
|
+
stays visible as the FormData carrier (typeable, native mobile pickers
|
|
5
|
+
intact); the overlaid calendar button opens the library's DatePicker in
|
|
6
|
+
an anchored Popover, and a pick writes the input exactly the way typing
|
|
7
|
+
does — validation, touch, and dirty tracking behave identically. Values
|
|
8
|
+
are the native input's "YYYY-MM-DD" strings.
|
|
9
|
+
|
|
10
|
+
Firefox exception: it draws an unhideable calendar icon on date inputs
|
|
11
|
+
(Bugzilla 1830890), so there the native affordance wins — our trigger
|
|
12
|
+
hides and the icon opens Firefox's own date picker (min/max respected;
|
|
13
|
+
week numbers and isDateDisabled are picker-side visuals only there —
|
|
14
|
+
the schema validates regardless, as always).
|
|
15
|
+
-->
|
|
16
|
+
<script lang="ts">
|
|
17
|
+
import DatePicker from "@privaty/ui/calendar/date-picker.svelte";
|
|
18
|
+
import type { LabelStyle } from "@privaty/ui/components/types.js";
|
|
19
|
+
import type { DateField } from "../types/field";
|
|
20
|
+
import PickerFrame from "./picker-frame.svelte";
|
|
21
|
+
|
|
22
|
+
interface Props {
|
|
23
|
+
/** The SvelteKit remote form field to bind. Structural — anything
|
|
24
|
+
* satisfying the DateField slice works, e.g. a fake from the public
|
|
25
|
+
* testing subpath. */
|
|
26
|
+
field: DateField;
|
|
27
|
+
/** Visible label text for the control. */
|
|
28
|
+
label: string;
|
|
29
|
+
|
|
30
|
+
/** Label placement: "top" (default), "left", or "hidden". No floating:
|
|
31
|
+
* date-family inputs render their format scaffold even when empty, so
|
|
32
|
+
* :placeholder-shown never behaves. */
|
|
33
|
+
labelStyle?: Exclude<LabelStyle, "floating">;
|
|
34
|
+
|
|
35
|
+
/** Marks the field required: feeds the majority-aware required/optional
|
|
36
|
+
* marker. Validation itself comes from the field's schema. */
|
|
37
|
+
required?: boolean;
|
|
38
|
+
/** Disables the control. Disabled controls are excluded from FormData —
|
|
39
|
+
* never disable to lock the form during submit; the input already turns
|
|
40
|
+
* readonly (and the calendar trigger disables) while submitting. */
|
|
41
|
+
disabled?: boolean;
|
|
42
|
+
/** Renders the input readonly and disables the calendar trigger. */
|
|
43
|
+
readonly?: boolean;
|
|
44
|
+
|
|
45
|
+
/** Initial "YYYY-MM-DD" value. */
|
|
46
|
+
initialValue?: string;
|
|
47
|
+
|
|
48
|
+
/** Inclusive ISO bounds, applied to BOTH the native input and the
|
|
49
|
+
* picker (out-of-range days render disabled). */
|
|
50
|
+
min?: string;
|
|
51
|
+
max?: string;
|
|
52
|
+
/** Marks additional days disabled in the picker (booked dates,
|
|
53
|
+
* weekends, …). Typing can still produce them — validate in the
|
|
54
|
+
* schema, as with every constraint. */
|
|
55
|
+
isDateDisabled?: (iso: string) => boolean;
|
|
56
|
+
|
|
57
|
+
/** BCP 47 tag for the picker's names and default week start —
|
|
58
|
+
* overrides `UiConfig.locale`. */
|
|
59
|
+
locale?: string;
|
|
60
|
+
/** ISO weekday the picker grid starts on (Monday = 1 … Sunday = 7). */
|
|
61
|
+
firstDayOfWeek?: number;
|
|
62
|
+
/** Adds the ISO week-number column to the picker. */
|
|
63
|
+
showWeekNumbers?: boolean;
|
|
64
|
+
|
|
65
|
+
/** Extra classes for the outer field wrapper. */
|
|
66
|
+
class?: string;
|
|
67
|
+
/** Extra classes for the <label> element. */
|
|
68
|
+
labelClass?: string;
|
|
69
|
+
/** Extra classes for the <input> element. */
|
|
70
|
+
inputClass?: string;
|
|
71
|
+
/** Extra classes for the required/optional marker. */
|
|
72
|
+
markerClass?: string;
|
|
73
|
+
/** Extra classes for the error <ul>. */
|
|
74
|
+
errorClass?: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const {
|
|
78
|
+
field,
|
|
79
|
+
label,
|
|
80
|
+
|
|
81
|
+
labelStyle,
|
|
82
|
+
|
|
83
|
+
required = false,
|
|
84
|
+
disabled = false,
|
|
85
|
+
readonly = false,
|
|
86
|
+
|
|
87
|
+
initialValue = "",
|
|
88
|
+
|
|
89
|
+
min,
|
|
90
|
+
max,
|
|
91
|
+
isDateDisabled,
|
|
92
|
+
|
|
93
|
+
locale,
|
|
94
|
+
firstDayOfWeek,
|
|
95
|
+
showWeekNumbers = false,
|
|
96
|
+
|
|
97
|
+
class: classes,
|
|
98
|
+
labelClass,
|
|
99
|
+
inputClass,
|
|
100
|
+
markerClass,
|
|
101
|
+
errorClass,
|
|
102
|
+
}: Props = $props();
|
|
103
|
+
</script>
|
|
104
|
+
|
|
105
|
+
<PickerFrame
|
|
106
|
+
{field}
|
|
107
|
+
{label}
|
|
108
|
+
type="date"
|
|
109
|
+
{labelStyle}
|
|
110
|
+
{required}
|
|
111
|
+
{disabled}
|
|
112
|
+
{readonly}
|
|
113
|
+
{initialValue}
|
|
114
|
+
{min}
|
|
115
|
+
{max}
|
|
116
|
+
class={classes}
|
|
117
|
+
{labelClass}
|
|
118
|
+
{inputClass}
|
|
119
|
+
{markerClass}
|
|
120
|
+
{errorClass}
|
|
121
|
+
>
|
|
122
|
+
{#snippet picker({ value, select })}
|
|
123
|
+
<DatePicker
|
|
124
|
+
{value}
|
|
125
|
+
onselect={select}
|
|
126
|
+
{min}
|
|
127
|
+
{max}
|
|
128
|
+
{isDateDisabled}
|
|
129
|
+
{locale}
|
|
130
|
+
{firstDayOfWeek}
|
|
131
|
+
{showWeekNumbers}
|
|
132
|
+
/>
|
|
133
|
+
{/snippet}
|
|
134
|
+
</PickerFrame>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { LabelStyle } from "@privaty/ui/components/types.js";
|
|
2
|
+
import type { DateField } from "../types/field";
|
|
3
|
+
interface Props {
|
|
4
|
+
/** The SvelteKit remote form field to bind. Structural — anything
|
|
5
|
+
* satisfying the DateField slice works, e.g. a fake from the public
|
|
6
|
+
* testing subpath. */
|
|
7
|
+
field: DateField;
|
|
8
|
+
/** Visible label text for the control. */
|
|
9
|
+
label: string;
|
|
10
|
+
/** Label placement: "top" (default), "left", or "hidden". No floating:
|
|
11
|
+
* date-family inputs render their format scaffold even when empty, so
|
|
12
|
+
* :placeholder-shown never behaves. */
|
|
13
|
+
labelStyle?: Exclude<LabelStyle, "floating">;
|
|
14
|
+
/** Marks the field required: feeds the majority-aware required/optional
|
|
15
|
+
* marker. Validation itself comes from the field's schema. */
|
|
16
|
+
required?: boolean;
|
|
17
|
+
/** Disables the control. Disabled controls are excluded from FormData —
|
|
18
|
+
* never disable to lock the form during submit; the input already turns
|
|
19
|
+
* readonly (and the calendar trigger disables) while submitting. */
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
/** Renders the input readonly and disables the calendar trigger. */
|
|
22
|
+
readonly?: boolean;
|
|
23
|
+
/** Initial "YYYY-MM-DD" value. */
|
|
24
|
+
initialValue?: string;
|
|
25
|
+
/** Inclusive ISO bounds, applied to BOTH the native input and the
|
|
26
|
+
* picker (out-of-range days render disabled). */
|
|
27
|
+
min?: string;
|
|
28
|
+
max?: string;
|
|
29
|
+
/** Marks additional days disabled in the picker (booked dates,
|
|
30
|
+
* weekends, …). Typing can still produce them — validate in the
|
|
31
|
+
* schema, as with every constraint. */
|
|
32
|
+
isDateDisabled?: (iso: string) => boolean;
|
|
33
|
+
/** BCP 47 tag for the picker's names and default week start —
|
|
34
|
+
* overrides `UiConfig.locale`. */
|
|
35
|
+
locale?: string;
|
|
36
|
+
/** ISO weekday the picker grid starts on (Monday = 1 … Sunday = 7). */
|
|
37
|
+
firstDayOfWeek?: number;
|
|
38
|
+
/** Adds the ISO week-number column to the picker. */
|
|
39
|
+
showWeekNumbers?: boolean;
|
|
40
|
+
/** Extra classes for the outer field wrapper. */
|
|
41
|
+
class?: string;
|
|
42
|
+
/** Extra classes for the <label> element. */
|
|
43
|
+
labelClass?: string;
|
|
44
|
+
/** Extra classes for the <input> element. */
|
|
45
|
+
inputClass?: string;
|
|
46
|
+
/** Extra classes for the required/optional marker. */
|
|
47
|
+
markerClass?: string;
|
|
48
|
+
/** Extra classes for the error <ul>. */
|
|
49
|
+
errorClass?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Date field with a cross-browser calendar popover, wired to a SvelteKit
|
|
53
|
+
* remote form field — must render inside a <Form>. The native date input
|
|
54
|
+
* stays visible as the FormData carrier (typeable, native mobile pickers
|
|
55
|
+
* intact); the overlaid calendar button opens the library's DatePicker in
|
|
56
|
+
* an anchored Popover, and a pick writes the input exactly the way typing
|
|
57
|
+
* does — validation, touch, and dirty tracking behave identically. Values
|
|
58
|
+
* are the native input's "YYYY-MM-DD" strings.
|
|
59
|
+
*
|
|
60
|
+
* Firefox exception: it draws an unhideable calendar icon on date inputs
|
|
61
|
+
* (Bugzilla 1830890), so there the native affordance wins — our trigger
|
|
62
|
+
* hides and the icon opens Firefox's own date picker (min/max respected;
|
|
63
|
+
* week numbers and isDateDisabled are picker-side visuals only there —
|
|
64
|
+
* the schema validates regardless, as always).
|
|
65
|
+
*/
|
|
66
|
+
declare const DatePickerInput: import("svelte").Component<Props, {}, "">;
|
|
67
|
+
type DatePickerInput = ReturnType<typeof DatePickerInput>;
|
|
68
|
+
export default DatePickerInput;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
Month field with a cross-browser picker popover, wired to a SvelteKit
|
|
3
|
+
remote form field — must render inside a <Form>. The native month input
|
|
4
|
+
stays visible as the FormData carrier (Firefox renders it as a plain
|
|
5
|
+
text input — exactly the gap the picker fills); the overlaid calendar
|
|
6
|
+
button opens the library's MonthPicker in an anchored Popover, and a
|
|
7
|
+
pick writes the input exactly the way typing does. Values are the
|
|
8
|
+
native input's "YYYY-MM" strings.
|
|
9
|
+
-->
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
import MonthPicker from "@privaty/ui/calendar/month-picker.svelte";
|
|
12
|
+
import type { LabelStyle } from "@privaty/ui/components/types.js";
|
|
13
|
+
import type { DateField } from "../types/field";
|
|
14
|
+
import PickerFrame from "./picker-frame.svelte";
|
|
15
|
+
|
|
16
|
+
interface Props {
|
|
17
|
+
/** The SvelteKit remote form field to bind. Structural — anything
|
|
18
|
+
* satisfying the DateField slice works, e.g. a fake from the public
|
|
19
|
+
* testing subpath. */
|
|
20
|
+
field: DateField;
|
|
21
|
+
/** Visible label text for the control. */
|
|
22
|
+
label: string;
|
|
23
|
+
|
|
24
|
+
/** Label placement: "top" (default), "left", or "hidden". No floating
|
|
25
|
+
* (see DateInput). */
|
|
26
|
+
labelStyle?: Exclude<LabelStyle, "floating">;
|
|
27
|
+
|
|
28
|
+
/** Marks the field required: feeds the majority-aware required/optional
|
|
29
|
+
* marker. Validation itself comes from the field's schema. */
|
|
30
|
+
required?: boolean;
|
|
31
|
+
/** Disables the control. Disabled controls are excluded from FormData —
|
|
32
|
+
* never disable to lock the form during submit; the input already turns
|
|
33
|
+
* readonly (and the calendar trigger disables) while submitting. */
|
|
34
|
+
disabled?: boolean;
|
|
35
|
+
/** Renders the input readonly and disables the calendar trigger. */
|
|
36
|
+
readonly?: boolean;
|
|
37
|
+
|
|
38
|
+
/** Initial "YYYY-MM" value. */
|
|
39
|
+
initialValue?: string;
|
|
40
|
+
|
|
41
|
+
/** Inclusive "YYYY-MM" bounds, applied to BOTH the native input and
|
|
42
|
+
* the picker (out-of-range months render disabled). */
|
|
43
|
+
min?: string;
|
|
44
|
+
max?: string;
|
|
45
|
+
|
|
46
|
+
/** BCP 47 tag for the picker's month names — overrides
|
|
47
|
+
* `UiConfig.locale`. */
|
|
48
|
+
locale?: string;
|
|
49
|
+
|
|
50
|
+
/** Extra classes for the outer field wrapper. */
|
|
51
|
+
class?: string;
|
|
52
|
+
/** Extra classes for the <label> element. */
|
|
53
|
+
labelClass?: string;
|
|
54
|
+
/** Extra classes for the <input> element. */
|
|
55
|
+
inputClass?: string;
|
|
56
|
+
/** Extra classes for the required/optional marker. */
|
|
57
|
+
markerClass?: string;
|
|
58
|
+
/** Extra classes for the error <ul>. */
|
|
59
|
+
errorClass?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const {
|
|
63
|
+
field,
|
|
64
|
+
label,
|
|
65
|
+
|
|
66
|
+
labelStyle,
|
|
67
|
+
|
|
68
|
+
required = false,
|
|
69
|
+
disabled = false,
|
|
70
|
+
readonly = false,
|
|
71
|
+
|
|
72
|
+
initialValue = "",
|
|
73
|
+
|
|
74
|
+
min,
|
|
75
|
+
max,
|
|
76
|
+
|
|
77
|
+
locale,
|
|
78
|
+
|
|
79
|
+
class: classes,
|
|
80
|
+
labelClass,
|
|
81
|
+
inputClass,
|
|
82
|
+
markerClass,
|
|
83
|
+
errorClass,
|
|
84
|
+
}: Props = $props();
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<PickerFrame
|
|
88
|
+
{field}
|
|
89
|
+
{label}
|
|
90
|
+
type="month"
|
|
91
|
+
{labelStyle}
|
|
92
|
+
{required}
|
|
93
|
+
{disabled}
|
|
94
|
+
{readonly}
|
|
95
|
+
{initialValue}
|
|
96
|
+
{min}
|
|
97
|
+
{max}
|
|
98
|
+
class={classes}
|
|
99
|
+
{labelClass}
|
|
100
|
+
{inputClass}
|
|
101
|
+
{markerClass}
|
|
102
|
+
{errorClass}
|
|
103
|
+
>
|
|
104
|
+
{#snippet picker({ value, select })}
|
|
105
|
+
<MonthPicker {value} onselect={select} {min} {max} {locale} />
|
|
106
|
+
{/snippet}
|
|
107
|
+
</PickerFrame>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { LabelStyle } from "@privaty/ui/components/types.js";
|
|
2
|
+
import type { DateField } from "../types/field";
|
|
3
|
+
interface Props {
|
|
4
|
+
/** The SvelteKit remote form field to bind. Structural — anything
|
|
5
|
+
* satisfying the DateField slice works, e.g. a fake from the public
|
|
6
|
+
* testing subpath. */
|
|
7
|
+
field: DateField;
|
|
8
|
+
/** Visible label text for the control. */
|
|
9
|
+
label: string;
|
|
10
|
+
/** Label placement: "top" (default), "left", or "hidden". No floating
|
|
11
|
+
* (see DateInput). */
|
|
12
|
+
labelStyle?: Exclude<LabelStyle, "floating">;
|
|
13
|
+
/** Marks the field required: feeds the majority-aware required/optional
|
|
14
|
+
* marker. Validation itself comes from the field's schema. */
|
|
15
|
+
required?: boolean;
|
|
16
|
+
/** Disables the control. Disabled controls are excluded from FormData —
|
|
17
|
+
* never disable to lock the form during submit; the input already turns
|
|
18
|
+
* readonly (and the calendar trigger disables) while submitting. */
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
/** Renders the input readonly and disables the calendar trigger. */
|
|
21
|
+
readonly?: boolean;
|
|
22
|
+
/** Initial "YYYY-MM" value. */
|
|
23
|
+
initialValue?: string;
|
|
24
|
+
/** Inclusive "YYYY-MM" bounds, applied to BOTH the native input and
|
|
25
|
+
* the picker (out-of-range months render disabled). */
|
|
26
|
+
min?: string;
|
|
27
|
+
max?: string;
|
|
28
|
+
/** BCP 47 tag for the picker's month names — overrides
|
|
29
|
+
* `UiConfig.locale`. */
|
|
30
|
+
locale?: string;
|
|
31
|
+
/** Extra classes for the outer field wrapper. */
|
|
32
|
+
class?: string;
|
|
33
|
+
/** Extra classes for the <label> element. */
|
|
34
|
+
labelClass?: string;
|
|
35
|
+
/** Extra classes for the <input> element. */
|
|
36
|
+
inputClass?: string;
|
|
37
|
+
/** Extra classes for the required/optional marker. */
|
|
38
|
+
markerClass?: string;
|
|
39
|
+
/** Extra classes for the error <ul>. */
|
|
40
|
+
errorClass?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Month field with a cross-browser picker popover, wired to a SvelteKit
|
|
44
|
+
* remote form field — must render inside a <Form>. The native month input
|
|
45
|
+
* stays visible as the FormData carrier (Firefox renders it as a plain
|
|
46
|
+
* text input — exactly the gap the picker fills); the overlaid calendar
|
|
47
|
+
* button opens the library's MonthPicker in an anchored Popover, and a
|
|
48
|
+
* pick writes the input exactly the way typing does. Values are the
|
|
49
|
+
* native input's "YYYY-MM" strings.
|
|
50
|
+
*/
|
|
51
|
+
declare const MonthPickerInput: import("svelte").Component<Props, {}, "">;
|
|
52
|
+
type MonthPickerInput = ReturnType<typeof MonthPickerInput>;
|
|
53
|
+
export default MonthPickerInput;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
INTERNAL shared frame for the picker inputs (DatePickerInput,
|
|
3
|
+
MonthPickerInput, WeekPickerInput) — not exported. A real native input
|
|
4
|
+
wired to a SvelteKit remote form field stays the FormData carrier
|
|
5
|
+
(typeable, native mobile pickers intact), with a calendar trigger button
|
|
6
|
+
overlaid on its end that opens the given picker in an anchored Popover.
|
|
7
|
+
|
|
8
|
+
A pick writes the input THE WAY TYPING DOES: DOM value first, then a real
|
|
9
|
+
bubbling `input` event. Kit's form-level listener reads the element's
|
|
10
|
+
value into field state, and the Form validates and marks the field
|
|
11
|
+
touched in exactly the order manual entry would — one write path, no
|
|
12
|
+
special programmatic branch.
|
|
13
|
+
-->
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
import { tick, type Snippet } from "svelte";
|
|
16
|
+
import { CalendarIcon } from "@lucide/svelte";
|
|
17
|
+
import { cn } from "@privaty/ui/cn.js";
|
|
18
|
+
import FieldFrame from "@privaty/ui/components/field-frame.svelte";
|
|
19
|
+
import type { LabelStyle } from "@privaty/ui/components/types.js";
|
|
20
|
+
import { getUiConfig } from "@privaty/ui/config/context.js";
|
|
21
|
+
import { getUiDensity } from "@privaty/ui/config/density.js";
|
|
22
|
+
import Popover from "@privaty/ui/overlays/popover.svelte";
|
|
23
|
+
import { coreTheme } from "@privaty/ui/theme.js";
|
|
24
|
+
import type { DateField, DateFieldType } from "../types/field";
|
|
25
|
+
import { wireField } from "./wire-field";
|
|
26
|
+
|
|
27
|
+
interface Props {
|
|
28
|
+
/** The SvelteKit remote form field to bind (structural slice). */
|
|
29
|
+
field: DateField;
|
|
30
|
+
/** Visible label text for the control. */
|
|
31
|
+
label: string;
|
|
32
|
+
/** The native carrier type — also the value format the picker speaks. */
|
|
33
|
+
type: Extract<DateFieldType, "date" | "month" | "week">;
|
|
34
|
+
|
|
35
|
+
/** Label placement — no floating (see DateInput). */
|
|
36
|
+
labelStyle?: Exclude<LabelStyle, "floating">;
|
|
37
|
+
|
|
38
|
+
required?: boolean;
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
readonly?: boolean;
|
|
41
|
+
|
|
42
|
+
/** ISO-style string in the chosen type's format. */
|
|
43
|
+
initialValue?: string;
|
|
44
|
+
|
|
45
|
+
/** Native bounds, forwarded to the input (the wrappers also forward
|
|
46
|
+
* them to their picker). */
|
|
47
|
+
min?: string;
|
|
48
|
+
max?: string;
|
|
49
|
+
|
|
50
|
+
class?: string;
|
|
51
|
+
labelClass?: string;
|
|
52
|
+
inputClass?: string;
|
|
53
|
+
markerClass?: string;
|
|
54
|
+
errorClass?: string;
|
|
55
|
+
|
|
56
|
+
/** Renders the picker inside the Popover panel. `value` is the field's
|
|
57
|
+
* current string; wire `select` to the picker's `onselect`. */
|
|
58
|
+
picker: Snippet<[{ value: string; select: (iso: string) => void }]>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const {
|
|
62
|
+
field,
|
|
63
|
+
label,
|
|
64
|
+
type,
|
|
65
|
+
|
|
66
|
+
labelStyle,
|
|
67
|
+
|
|
68
|
+
required = false,
|
|
69
|
+
disabled = false,
|
|
70
|
+
readonly = false,
|
|
71
|
+
|
|
72
|
+
initialValue = "",
|
|
73
|
+
|
|
74
|
+
min,
|
|
75
|
+
max,
|
|
76
|
+
|
|
77
|
+
class: classes,
|
|
78
|
+
labelClass,
|
|
79
|
+
inputClass,
|
|
80
|
+
markerClass,
|
|
81
|
+
errorClass,
|
|
82
|
+
|
|
83
|
+
picker,
|
|
84
|
+
}: Props = $props();
|
|
85
|
+
|
|
86
|
+
const config = getUiConfig();
|
|
87
|
+
|
|
88
|
+
const attributes = $derived(field.as(type, initialValue));
|
|
89
|
+
|
|
90
|
+
// The field, type, and initialValue are stable for the component's lifetime,
|
|
91
|
+
// so capturing the initial name and registration is intentional.
|
|
92
|
+
// svelte-ignore state_referenced_locally
|
|
93
|
+
const name = attributes.name;
|
|
94
|
+
|
|
95
|
+
// svelte-ignore state_referenced_locally
|
|
96
|
+
const wired = wireField({
|
|
97
|
+
name,
|
|
98
|
+
initialValue,
|
|
99
|
+
required,
|
|
100
|
+
issues: () => field.issues(),
|
|
101
|
+
getValue: () => field.value(),
|
|
102
|
+
setValue: (value) => field.set(value as string),
|
|
103
|
+
normalize: (value) => (value == null ? "" : String(value)),
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const densityContext = getUiDensity();
|
|
107
|
+
const compact = $derived(densityContext.density === "compact");
|
|
108
|
+
|
|
109
|
+
// What the picker highlights: the field's live value (Kit tracks
|
|
110
|
+
// undefined until the first edit — the seed stands in).
|
|
111
|
+
const currentValue = $derived(String(field.value() ?? initialValue));
|
|
112
|
+
|
|
113
|
+
const uid = $props.id();
|
|
114
|
+
const locked = $derived(disabled || readonly || wired.state.isSubmitting);
|
|
115
|
+
|
|
116
|
+
let inputElement = $state<HTMLInputElement>();
|
|
117
|
+
let triggerElement = $state<HTMLButtonElement>();
|
|
118
|
+
let open = $state(false);
|
|
119
|
+
|
|
120
|
+
function select(iso: string) {
|
|
121
|
+
// The popover can outlive its trigger's enabled state (a submit that
|
|
122
|
+
// starts while it is open) — a locked control accepts no picks.
|
|
123
|
+
if (!inputElement || locked) return;
|
|
124
|
+
inputElement.value = iso;
|
|
125
|
+
// A real bubbling event — Kit's and the Form's listeners sit on the
|
|
126
|
+
// <form>, and Svelte delegates besides.
|
|
127
|
+
inputElement.dispatchEvent(new Event("input", { bubbles: true }));
|
|
128
|
+
open = false;
|
|
129
|
+
// The focused cell just left the top layer with the panel — hand focus
|
|
130
|
+
// back to the trigger, the way light dismiss does.
|
|
131
|
+
void tick().then(() => triggerElement?.focus());
|
|
132
|
+
}
|
|
133
|
+
</script>
|
|
134
|
+
|
|
135
|
+
<FieldFrame
|
|
136
|
+
id={uid}
|
|
137
|
+
{label}
|
|
138
|
+
{labelStyle}
|
|
139
|
+
errors={wired.errors}
|
|
140
|
+
marker={wired.marker}
|
|
141
|
+
class={classes}
|
|
142
|
+
{labelClass}
|
|
143
|
+
markerClass={cn(required && "text-red-700 dark:text-red-500", markerClass)}
|
|
144
|
+
{errorClass}
|
|
145
|
+
>
|
|
146
|
+
{#snippet control({ id, errorsId })}
|
|
147
|
+
<span class="relative block w-full">
|
|
148
|
+
<input
|
|
149
|
+
{...attributes}
|
|
150
|
+
bind:this={inputElement}
|
|
151
|
+
{id}
|
|
152
|
+
class={cn(
|
|
153
|
+
coreTheme.controlBase,
|
|
154
|
+
coreTheme.controlSurface,
|
|
155
|
+
compact
|
|
156
|
+
? coreTheme.controlPadding.compact
|
|
157
|
+
: coreTheme.controlPadding.comfortable,
|
|
158
|
+
// Our trigger replaces Chromium's built-in indicator; pr-8 keeps
|
|
159
|
+
// the text clear of the overlaid button.
|
|
160
|
+
"pr-8 [&::-webkit-calendar-picker-indicator]:hidden",
|
|
161
|
+
// Firefox refuses to hide its own date icon (Bugzilla 1830890) —
|
|
162
|
+
// there the native affordance wins for dates: our trigger steps
|
|
163
|
+
// aside (below) and the padding returns to base. The @supports
|
|
164
|
+
// (-moz-appearance) detect matches Gecko only. Month/week draw
|
|
165
|
+
// no native icon anywhere, so they keep our trigger everywhere.
|
|
166
|
+
type === "date" && "supports-[-moz-appearance:none]:pr-2",
|
|
167
|
+
inputClass,
|
|
168
|
+
)}
|
|
169
|
+
aria-describedby={errorsId}
|
|
170
|
+
aria-invalid={wired.errors.length > 0 ? true : undefined}
|
|
171
|
+
{disabled}
|
|
172
|
+
readonly={readonly || wired.state.isSubmitting}
|
|
173
|
+
{min}
|
|
174
|
+
{max}
|
|
175
|
+
/>
|
|
176
|
+
<Popover bind:open placement="bottom-end">
|
|
177
|
+
{#snippet trigger(props)}
|
|
178
|
+
<button
|
|
179
|
+
type="button"
|
|
180
|
+
bind:this={triggerElement}
|
|
181
|
+
{...props}
|
|
182
|
+
class={cn(
|
|
183
|
+
coreTheme.controlTrigger,
|
|
184
|
+
// See the input's class note: Firefox dates use the native
|
|
185
|
+
// icon and picker instead of a doubled affordance.
|
|
186
|
+
type === "date" && "supports-[-moz-appearance:none]:hidden",
|
|
187
|
+
)}
|
|
188
|
+
disabled={locked}
|
|
189
|
+
title={config.labels.calendar.open}
|
|
190
|
+
>
|
|
191
|
+
<CalendarIcon class="size-4" aria-hidden="true" />
|
|
192
|
+
<span class="sr-only">{config.labels.calendar.open}</span>
|
|
193
|
+
</button>
|
|
194
|
+
{/snippet}
|
|
195
|
+
<!-- The panel renders inside the consumer's <form>, and the
|
|
196
|
+
pickers' unnamed header dropdowns fire bubbling input events —
|
|
197
|
+
which Kit's form-level listener and the Form's validate-on-
|
|
198
|
+
input would otherwise treat as edits (validation round-trips
|
|
199
|
+
from pure calendar navigation). The carrier input's own
|
|
200
|
+
synthetic pick event fires OUTSIDE this wrapper. -->
|
|
201
|
+
<div oninput={(event) => event.stopPropagation()}>
|
|
202
|
+
{@render picker({ value: currentValue, select })}
|
|
203
|
+
</div>
|
|
204
|
+
</Popover>
|
|
205
|
+
</span>
|
|
206
|
+
{/snippet}
|
|
207
|
+
</FieldFrame>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type Snippet } from "svelte";
|
|
2
|
+
import type { LabelStyle } from "@privaty/ui/components/types.js";
|
|
3
|
+
import type { DateField, DateFieldType } from "../types/field";
|
|
4
|
+
interface Props {
|
|
5
|
+
/** The SvelteKit remote form field to bind (structural slice). */
|
|
6
|
+
field: DateField;
|
|
7
|
+
/** Visible label text for the control. */
|
|
8
|
+
label: string;
|
|
9
|
+
/** The native carrier type — also the value format the picker speaks. */
|
|
10
|
+
type: Extract<DateFieldType, "date" | "month" | "week">;
|
|
11
|
+
/** Label placement — no floating (see DateInput). */
|
|
12
|
+
labelStyle?: Exclude<LabelStyle, "floating">;
|
|
13
|
+
required?: boolean;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
readonly?: boolean;
|
|
16
|
+
/** ISO-style string in the chosen type's format. */
|
|
17
|
+
initialValue?: string;
|
|
18
|
+
/** Native bounds, forwarded to the input (the wrappers also forward
|
|
19
|
+
* them to their picker). */
|
|
20
|
+
min?: string;
|
|
21
|
+
max?: string;
|
|
22
|
+
class?: string;
|
|
23
|
+
labelClass?: string;
|
|
24
|
+
inputClass?: string;
|
|
25
|
+
markerClass?: string;
|
|
26
|
+
errorClass?: string;
|
|
27
|
+
/** Renders the picker inside the Popover panel. `value` is the field's
|
|
28
|
+
* current string; wire `select` to the picker's `onselect`. */
|
|
29
|
+
picker: Snippet<[{
|
|
30
|
+
value: string;
|
|
31
|
+
select: (iso: string) => void;
|
|
32
|
+
}]>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* INTERNAL shared frame for the picker inputs (DatePickerInput,
|
|
36
|
+
* MonthPickerInput, WeekPickerInput) — not exported. A real native input
|
|
37
|
+
* wired to a SvelteKit remote form field stays the FormData carrier
|
|
38
|
+
* (typeable, native mobile pickers intact), with a calendar trigger button
|
|
39
|
+
* overlaid on its end that opens the given picker in an anchored Popover.
|
|
40
|
+
*
|
|
41
|
+
* A pick writes the input THE WAY TYPING DOES: DOM value first, then a real
|
|
42
|
+
* bubbling `input` event. Kit's form-level listener reads the element's
|
|
43
|
+
* value into field state, and the Form validates and marks the field
|
|
44
|
+
* touched in exactly the order manual entry would — one write path, no
|
|
45
|
+
* special programmatic branch.
|
|
46
|
+
*/
|
|
47
|
+
declare const PickerFrame: import("svelte").Component<Props, {}, "">;
|
|
48
|
+
type PickerFrame = ReturnType<typeof PickerFrame>;
|
|
49
|
+
export default PickerFrame;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
Week field with a cross-browser picker popover, wired to a SvelteKit
|
|
3
|
+
remote form field — must render inside a <Form>. The native week input
|
|
4
|
+
stays visible as the FormData carrier (Firefox renders it as a plain
|
|
5
|
+
text input — exactly the gap the picker fills); the overlaid calendar
|
|
6
|
+
button opens the library's WeekPicker in an anchored Popover, and a pick
|
|
7
|
+
writes the input exactly the way typing does. Values are the native
|
|
8
|
+
input's "YYYY-Www" strings (ISO-8601 weeks, the Danish convention).
|
|
9
|
+
-->
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
import WeekPicker from "@privaty/ui/calendar/week-picker.svelte";
|
|
12
|
+
import type { LabelStyle } from "@privaty/ui/components/types.js";
|
|
13
|
+
import type { DateField } from "../types/field";
|
|
14
|
+
import PickerFrame from "./picker-frame.svelte";
|
|
15
|
+
|
|
16
|
+
interface Props {
|
|
17
|
+
/** The SvelteKit remote form field to bind. Structural — anything
|
|
18
|
+
* satisfying the DateField slice works, e.g. a fake from the public
|
|
19
|
+
* testing subpath. */
|
|
20
|
+
field: DateField;
|
|
21
|
+
/** Visible label text for the control. */
|
|
22
|
+
label: string;
|
|
23
|
+
|
|
24
|
+
/** Label placement: "top" (default), "left", or "hidden". No floating
|
|
25
|
+
* (see DateInput). */
|
|
26
|
+
labelStyle?: Exclude<LabelStyle, "floating">;
|
|
27
|
+
|
|
28
|
+
/** Marks the field required: feeds the majority-aware required/optional
|
|
29
|
+
* marker. Validation itself comes from the field's schema. */
|
|
30
|
+
required?: boolean;
|
|
31
|
+
/** Disables the control. Disabled controls are excluded from FormData —
|
|
32
|
+
* never disable to lock the form during submit; the input already turns
|
|
33
|
+
* readonly (and the calendar trigger disables) while submitting. */
|
|
34
|
+
disabled?: boolean;
|
|
35
|
+
/** Renders the input readonly and disables the calendar trigger. */
|
|
36
|
+
readonly?: boolean;
|
|
37
|
+
|
|
38
|
+
/** Initial "YYYY-Www" value. */
|
|
39
|
+
initialValue?: string;
|
|
40
|
+
|
|
41
|
+
/** Inclusive "YYYY-Www" bounds, applied to BOTH the native input and
|
|
42
|
+
* the picker (out-of-range weeks render disabled). */
|
|
43
|
+
min?: string;
|
|
44
|
+
max?: string;
|
|
45
|
+
|
|
46
|
+
/** BCP 47 tag for the picker's names — overrides `UiConfig.locale`.
|
|
47
|
+
* The grid itself is always Monday-first (ISO weeks are only
|
|
48
|
+
* well-defined that way). */
|
|
49
|
+
locale?: string;
|
|
50
|
+
|
|
51
|
+
/** Extra classes for the outer field wrapper. */
|
|
52
|
+
class?: string;
|
|
53
|
+
/** Extra classes for the <label> element. */
|
|
54
|
+
labelClass?: string;
|
|
55
|
+
/** Extra classes for the <input> element. */
|
|
56
|
+
inputClass?: string;
|
|
57
|
+
/** Extra classes for the required/optional marker. */
|
|
58
|
+
markerClass?: string;
|
|
59
|
+
/** Extra classes for the error <ul>. */
|
|
60
|
+
errorClass?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const {
|
|
64
|
+
field,
|
|
65
|
+
label,
|
|
66
|
+
|
|
67
|
+
labelStyle,
|
|
68
|
+
|
|
69
|
+
required = false,
|
|
70
|
+
disabled = false,
|
|
71
|
+
readonly = false,
|
|
72
|
+
|
|
73
|
+
initialValue = "",
|
|
74
|
+
|
|
75
|
+
min,
|
|
76
|
+
max,
|
|
77
|
+
|
|
78
|
+
locale,
|
|
79
|
+
|
|
80
|
+
class: classes,
|
|
81
|
+
labelClass,
|
|
82
|
+
inputClass,
|
|
83
|
+
markerClass,
|
|
84
|
+
errorClass,
|
|
85
|
+
}: Props = $props();
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<PickerFrame
|
|
89
|
+
{field}
|
|
90
|
+
{label}
|
|
91
|
+
type="week"
|
|
92
|
+
{labelStyle}
|
|
93
|
+
{required}
|
|
94
|
+
{disabled}
|
|
95
|
+
{readonly}
|
|
96
|
+
{initialValue}
|
|
97
|
+
{min}
|
|
98
|
+
{max}
|
|
99
|
+
class={classes}
|
|
100
|
+
{labelClass}
|
|
101
|
+
{inputClass}
|
|
102
|
+
{markerClass}
|
|
103
|
+
{errorClass}
|
|
104
|
+
>
|
|
105
|
+
{#snippet picker({ value, select })}
|
|
106
|
+
<WeekPicker {value} onselect={select} {min} {max} {locale} />
|
|
107
|
+
{/snippet}
|
|
108
|
+
</PickerFrame>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { LabelStyle } from "@privaty/ui/components/types.js";
|
|
2
|
+
import type { DateField } from "../types/field";
|
|
3
|
+
interface Props {
|
|
4
|
+
/** The SvelteKit remote form field to bind. Structural — anything
|
|
5
|
+
* satisfying the DateField slice works, e.g. a fake from the public
|
|
6
|
+
* testing subpath. */
|
|
7
|
+
field: DateField;
|
|
8
|
+
/** Visible label text for the control. */
|
|
9
|
+
label: string;
|
|
10
|
+
/** Label placement: "top" (default), "left", or "hidden". No floating
|
|
11
|
+
* (see DateInput). */
|
|
12
|
+
labelStyle?: Exclude<LabelStyle, "floating">;
|
|
13
|
+
/** Marks the field required: feeds the majority-aware required/optional
|
|
14
|
+
* marker. Validation itself comes from the field's schema. */
|
|
15
|
+
required?: boolean;
|
|
16
|
+
/** Disables the control. Disabled controls are excluded from FormData —
|
|
17
|
+
* never disable to lock the form during submit; the input already turns
|
|
18
|
+
* readonly (and the calendar trigger disables) while submitting. */
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
/** Renders the input readonly and disables the calendar trigger. */
|
|
21
|
+
readonly?: boolean;
|
|
22
|
+
/** Initial "YYYY-Www" value. */
|
|
23
|
+
initialValue?: string;
|
|
24
|
+
/** Inclusive "YYYY-Www" bounds, applied to BOTH the native input and
|
|
25
|
+
* the picker (out-of-range weeks render disabled). */
|
|
26
|
+
min?: string;
|
|
27
|
+
max?: string;
|
|
28
|
+
/** BCP 47 tag for the picker's names — overrides `UiConfig.locale`.
|
|
29
|
+
* The grid itself is always Monday-first (ISO weeks are only
|
|
30
|
+
* well-defined that way). */
|
|
31
|
+
locale?: string;
|
|
32
|
+
/** Extra classes for the outer field wrapper. */
|
|
33
|
+
class?: string;
|
|
34
|
+
/** Extra classes for the <label> element. */
|
|
35
|
+
labelClass?: string;
|
|
36
|
+
/** Extra classes for the <input> element. */
|
|
37
|
+
inputClass?: string;
|
|
38
|
+
/** Extra classes for the required/optional marker. */
|
|
39
|
+
markerClass?: string;
|
|
40
|
+
/** Extra classes for the error <ul>. */
|
|
41
|
+
errorClass?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Week field with a cross-browser picker popover, wired to a SvelteKit
|
|
45
|
+
* remote form field — must render inside a <Form>. The native week input
|
|
46
|
+
* stays visible as the FormData carrier (Firefox renders it as a plain
|
|
47
|
+
* text input — exactly the gap the picker fills); the overlaid calendar
|
|
48
|
+
* button opens the library's WeekPicker in an anchored Popover, and a pick
|
|
49
|
+
* writes the input exactly the way typing does. Values are the native
|
|
50
|
+
* input's "YYYY-Www" strings (ISO-8601 weeks, the Danish convention).
|
|
51
|
+
*/
|
|
52
|
+
declare const WeekPickerInput: import("svelte").Component<Props, {}, "">;
|
|
53
|
+
type WeekPickerInput = ReturnType<typeof WeekPickerInput>;
|
|
54
|
+
export default WeekPickerInput;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/* Loads Tailwind into browser-mode specs that assert real computed styles —
|
|
2
|
+
component classes are inert without it (e.g. the picker trigger's
|
|
3
|
+
Firefox-only display:none never applies). Same recipe as @privaty/ui's
|
|
4
|
+
testing stylesheet: v4 auto-detects sources from the repo root. */
|
|
5
|
+
@import "tailwindcss";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@privaty/ui-forms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -40,10 +40,11 @@
|
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@sveltejs/kit": "^3.0.0-next.0",
|
|
43
|
-
"svelte": "^5.
|
|
44
|
-
"@privaty/ui": "^0.
|
|
43
|
+
"svelte": "^5.29.0",
|
|
44
|
+
"@privaty/ui": "^0.3.0"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
+
"@lucide/svelte": "^1.34.0",
|
|
47
48
|
"@standard-schema/spec": "^1.1.0"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
@@ -55,7 +56,7 @@
|
|
|
55
56
|
"svelte-check": "^4.7.6",
|
|
56
57
|
"typescript": "^6.0.3",
|
|
57
58
|
"@config/eslint": "0.0.0",
|
|
58
|
-
"@privaty/ui": "0.
|
|
59
|
+
"@privaty/ui": "0.3.0",
|
|
59
60
|
"@config/typescript": "0.0.0"
|
|
60
61
|
},
|
|
61
62
|
"scripts": {
|