@streamscloud/kit 0.21.1 → 0.21.2
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/ui/date-picker/cmp.date-time-picker.svelte +65 -0
- package/dist/ui/date-picker/cmp.date-time-picker.svelte.d.ts +28 -0
- package/dist/ui/date-picker/cmp.time-picker.svelte +88 -0
- package/dist/ui/date-picker/cmp.time-picker.svelte.d.ts +50 -0
- package/dist/ui/date-picker/index.d.ts +2 -0
- package/dist/ui/date-picker/index.js +2 -0
- package/dist/ui/select/cmp.multiselect.svelte.d.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script lang="ts">import DatePicker from './cmp.date-picker.svelte';
|
|
2
|
+
import TimePicker from './cmp.time-picker.svelte';
|
|
3
|
+
const { value, size = 'md', datePlaceholder = '', min, step = 30, on } = $props();
|
|
4
|
+
const DEFAULT_TIME = '12:00';
|
|
5
|
+
const pad = (n) => n.toString().padStart(2, '0');
|
|
6
|
+
const toTimeValue = (date) => `${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
7
|
+
const currentDate = $derived(value ? new Date(value) : null);
|
|
8
|
+
const timeValue = $derived(currentDate ? toTimeValue(currentDate) : DEFAULT_TIME);
|
|
9
|
+
const onDateChange = (next) => {
|
|
10
|
+
if (!next) {
|
|
11
|
+
on?.change?.(null);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const picked = new Date(next);
|
|
15
|
+
const combined = new Date(currentDate ?? picked);
|
|
16
|
+
if (!currentDate) {
|
|
17
|
+
const [hours, minutes] = DEFAULT_TIME.split(':').map(Number);
|
|
18
|
+
combined.setHours(hours, minutes, 0, 0);
|
|
19
|
+
}
|
|
20
|
+
combined.setFullYear(picked.getFullYear(), picked.getMonth(), picked.getDate());
|
|
21
|
+
on?.change?.(combined.toISOString());
|
|
22
|
+
};
|
|
23
|
+
const onTimeChange = (next) => {
|
|
24
|
+
if (!currentDate) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const [hours, minutes] = next.split(':').map(Number);
|
|
28
|
+
const combined = new Date(currentDate);
|
|
29
|
+
combined.setHours(hours, minutes, 0, 0);
|
|
30
|
+
on?.change?.(combined.toISOString());
|
|
31
|
+
};
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<div class="date-time" class:date-time--date-only={!currentDate}>
|
|
35
|
+
<DatePicker clearable size={size} value={value} placeholder={datePlaceholder} min={min} on={{ change: onDateChange }} />
|
|
36
|
+
{#if currentDate}
|
|
37
|
+
<TimePicker clearable={false} size={size} step={step} value={timeValue} on={{ change: onTimeChange }} />
|
|
38
|
+
{/if}
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<!--
|
|
42
|
+
@component
|
|
43
|
+
DateTimePicker — composes `DatePicker` + `TimePicker` into one ISO date-time field. The time row appears
|
|
44
|
+
only once a date is picked (defaulting to `12:00`); `size` and `step` thread down to both controls.
|
|
45
|
+
Emits an ISO 8601 string — or `null` when the date is cleared — via `on.change`.
|
|
46
|
+
|
|
47
|
+
### CSS Custom Properties
|
|
48
|
+
| Property | Description | Default |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| `--sc-kit--date-time-picker--time-width` | Width of the time column | `6rem` |
|
|
51
|
+
| `--sc-kit--date-time-picker--gap` | Gap between the date and time fields | `var(--sc-kit--space--2)` |
|
|
52
|
+
-->
|
|
53
|
+
|
|
54
|
+
<style>.date-time {
|
|
55
|
+
--_dtp--time-width: var(--sc-kit--date-time-picker--time-width, 6rem);
|
|
56
|
+
--_dtp--gap: var(--sc-kit--date-time-picker--gap, var(--sc-kit--space--2));
|
|
57
|
+
display: grid;
|
|
58
|
+
grid-template-columns: minmax(0, 1fr) var(--_dtp--time-width);
|
|
59
|
+
gap: var(--_dtp--gap);
|
|
60
|
+
width: 100%;
|
|
61
|
+
max-width: 100%;
|
|
62
|
+
}
|
|
63
|
+
.date-time--date-only {
|
|
64
|
+
grid-template-columns: minmax(0, 1fr);
|
|
65
|
+
}</style>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { LikeDate } from './types';
|
|
2
|
+
type Props = {
|
|
3
|
+
value: string | null;
|
|
4
|
+
/** @default 'md' */
|
|
5
|
+
size?: 'sm' | 'md' | 'lg';
|
|
6
|
+
datePlaceholder?: string;
|
|
7
|
+
/** Earliest selectable date (inclusive). */
|
|
8
|
+
min?: LikeDate;
|
|
9
|
+
/** Minute interval for the time list. @default 30 */
|
|
10
|
+
step?: number;
|
|
11
|
+
on?: {
|
|
12
|
+
change?: (value: string | null) => void;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* DateTimePicker — composes `DatePicker` + `TimePicker` into one ISO date-time field. The time row appears
|
|
17
|
+
* only once a date is picked (defaulting to `12:00`); `size` and `step` thread down to both controls.
|
|
18
|
+
* Emits an ISO 8601 string — or `null` when the date is cleared — via `on.change`.
|
|
19
|
+
*
|
|
20
|
+
* ### CSS Custom Properties
|
|
21
|
+
* | Property | Description | Default |
|
|
22
|
+
* |---|---|---|
|
|
23
|
+
* | `--sc-kit--date-time-picker--time-width` | Width of the time column | `6rem` |
|
|
24
|
+
* | `--sc-kit--date-time-picker--gap` | Gap between the date and time fields | `var(--sc-kit--space--2)` |
|
|
25
|
+
*/
|
|
26
|
+
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
27
|
+
type Cmp = ReturnType<typeof Cmp>;
|
|
28
|
+
export default Cmp;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<script lang="ts">import { Singleselect } from '../select';
|
|
2
|
+
const { size = 'md', step = 30, placeholder = '', disabled = false, readonly = false, inert = false, error = false, borderless = false, id, name, 'aria-label': ariaLabel, 'aria-describedby': ariaDescribedby, 'aria-required': ariaRequired, ...mode } = $props();
|
|
3
|
+
const MINUTES_PER_DAY = 24 * 60;
|
|
4
|
+
const pad = (n) => n.toString().padStart(2, '0');
|
|
5
|
+
const stepOptions = $derived.by(() => {
|
|
6
|
+
const count = Math.max(1, Math.floor(MINUTES_PER_DAY / step));
|
|
7
|
+
return Array.from({ length: count }, (_, i) => {
|
|
8
|
+
const total = i * step;
|
|
9
|
+
const label = `${pad(Math.floor(total / 60))}:${pad(total % 60)}`;
|
|
10
|
+
return { label, value: label };
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
const options = $derived.by(() => {
|
|
14
|
+
const current = mode.value;
|
|
15
|
+
if (current && !stepOptions.some((option) => option.value === current)) {
|
|
16
|
+
return [...stepOptions, { label: current, value: current }].sort((a, b) => a.value.localeCompare(b.value));
|
|
17
|
+
}
|
|
18
|
+
return stepOptions;
|
|
19
|
+
});
|
|
20
|
+
const emit = (next) => {
|
|
21
|
+
if (mode.clearable) {
|
|
22
|
+
mode.on?.change?.(next);
|
|
23
|
+
}
|
|
24
|
+
else if (next !== null) {
|
|
25
|
+
mode.on?.change?.(next);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<div class="time-picker">
|
|
31
|
+
{#if mode.clearable}
|
|
32
|
+
<Singleselect
|
|
33
|
+
clearable
|
|
34
|
+
value={mode.value}
|
|
35
|
+
options={options}
|
|
36
|
+
size={size}
|
|
37
|
+
placeholder={placeholder}
|
|
38
|
+
disabled={disabled}
|
|
39
|
+
readonly={readonly}
|
|
40
|
+
inert={inert}
|
|
41
|
+
error={error}
|
|
42
|
+
borderless={borderless}
|
|
43
|
+
id={id}
|
|
44
|
+
name={name}
|
|
45
|
+
aria-label={ariaLabel}
|
|
46
|
+
aria-describedby={ariaDescribedby}
|
|
47
|
+
aria-required={ariaRequired}
|
|
48
|
+
on={{ change: emit }} />
|
|
49
|
+
{:else}
|
|
50
|
+
<Singleselect
|
|
51
|
+
clearable={false}
|
|
52
|
+
value={mode.value}
|
|
53
|
+
options={options}
|
|
54
|
+
size={size}
|
|
55
|
+
placeholder={placeholder}
|
|
56
|
+
disabled={disabled}
|
|
57
|
+
readonly={readonly}
|
|
58
|
+
inert={inert}
|
|
59
|
+
error={error}
|
|
60
|
+
borderless={borderless}
|
|
61
|
+
id={id}
|
|
62
|
+
name={name}
|
|
63
|
+
aria-label={ariaLabel}
|
|
64
|
+
aria-describedby={ariaDescribedby}
|
|
65
|
+
aria-required={ariaRequired}
|
|
66
|
+
on={{ change: emit }} />
|
|
67
|
+
{/if}
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<!--
|
|
71
|
+
@component
|
|
72
|
+
TimePicker — an `'HH:mm'` (24-hour) time field built on `Singleselect` over a time grid generated from
|
|
73
|
+
`step` (minutes). Discriminated by `clearable`: `true` allows clearing to `null` and shows an X button;
|
|
74
|
+
`false` requires a value. An out-of-grid `value` is injected into the list so it always renders. Emits
|
|
75
|
+
the picked `'HH:mm'` string via `on.change`.
|
|
76
|
+
|
|
77
|
+
### CSS Custom Properties
|
|
78
|
+
| Property | Description | Default |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| `--sc-kit--time-picker--width` | Field width | `100%` |
|
|
81
|
+
-->
|
|
82
|
+
|
|
83
|
+
<style>.time-picker {
|
|
84
|
+
--_tp--width: var(--sc-kit--time-picker--width, 100%);
|
|
85
|
+
display: flex;
|
|
86
|
+
width: var(--_tp--width);
|
|
87
|
+
max-width: 100%;
|
|
88
|
+
}</style>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
type BaseProps = {
|
|
2
|
+
/** @default 'md' */
|
|
3
|
+
size?: 'sm' | 'md' | 'lg';
|
|
4
|
+
/** Minute interval between generated options. @default 30 */
|
|
5
|
+
step?: number;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
/** Focusable, value visible, but selection cannot change. */
|
|
9
|
+
readonly?: boolean;
|
|
10
|
+
/** Non-interactive, unstyled view-only mode. */
|
|
11
|
+
inert?: boolean;
|
|
12
|
+
error?: boolean;
|
|
13
|
+
borderless?: boolean;
|
|
14
|
+
id?: string;
|
|
15
|
+
name?: string;
|
|
16
|
+
'aria-label'?: string;
|
|
17
|
+
'aria-describedby'?: string;
|
|
18
|
+
'aria-required'?: boolean;
|
|
19
|
+
};
|
|
20
|
+
type ClearableProps = BaseProps & {
|
|
21
|
+
/** Value can be cleared to `null`; shows a clear (X) button when set. */
|
|
22
|
+
clearable: true;
|
|
23
|
+
value: string | null | undefined;
|
|
24
|
+
on?: {
|
|
25
|
+
change?: (value: string | null) => void;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
type RequiredProps = BaseProps & {
|
|
29
|
+
/** Value is required. No clear button. */
|
|
30
|
+
clearable: false;
|
|
31
|
+
value: string;
|
|
32
|
+
on?: {
|
|
33
|
+
change?: (value: string) => void;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
type Props = ClearableProps | RequiredProps;
|
|
37
|
+
/**
|
|
38
|
+
* TimePicker — an `'HH:mm'` (24-hour) time field built on `Singleselect` over a time grid generated from
|
|
39
|
+
* `step` (minutes). Discriminated by `clearable`: `true` allows clearing to `null` and shows an X button;
|
|
40
|
+
* `false` requires a value. An out-of-grid `value` is injected into the list so it always renders. Emits
|
|
41
|
+
* the picked `'HH:mm'` string via `on.change`.
|
|
42
|
+
*
|
|
43
|
+
* ### CSS Custom Properties
|
|
44
|
+
* | Property | Description | Default |
|
|
45
|
+
* |---|---|---|
|
|
46
|
+
* | `--sc-kit--time-picker--width` | Field width | `100%` |
|
|
47
|
+
*/
|
|
48
|
+
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
49
|
+
type Cmp = ReturnType<typeof Cmp>;
|
|
50
|
+
export default Cmp;
|
|
@@ -5,7 +5,7 @@ export type MultiselectInstance = {
|
|
|
5
5
|
};
|
|
6
6
|
import { type MultiselectBaseProps, type SelectOption } from './types';
|
|
7
7
|
declare function $$render<T>(): {
|
|
8
|
-
props: Omit<MultiselectBaseProps<T>, "value" | "on" | "
|
|
8
|
+
props: Omit<MultiselectBaseProps<T>, "value" | "on" | "loadOptions" | "debounceMs" | "groupHeader" | "selectionMode" | "parentSource"> & {
|
|
9
9
|
/** Flat option list. Fuse filters in-memory on every keystroke — no debounce. */
|
|
10
10
|
options: SelectOption<T>[];
|
|
11
11
|
/** Current selection — array of values. Order is preserved (and editable when `reorderable`). */
|