@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.
@@ -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;
@@ -1,2 +1,4 @@
1
1
  export { default as DatePicker } from './cmp.date-picker.svelte';
2
+ export { default as DateTimePicker } from './cmp.date-time-picker.svelte';
3
+ export { default as TimePicker } from './cmp.time-picker.svelte';
2
4
  export type { LikeDate } from './types';
@@ -1 +1,3 @@
1
1
  export { default as DatePicker } from './cmp.date-picker.svelte';
2
+ export { default as DateTimePicker } from './cmp.date-time-picker.svelte';
3
+ export { default as TimePicker } from './cmp.time-picker.svelte';
@@ -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" | "debounceMs" | "loadOptions" | "groupHeader" | "selectionMode" | "parentSource"> & {
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`). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamscloud/kit",
3
- "version": "0.21.1",
3
+ "version": "0.21.2",
4
4
  "author": "StreamsCloud",
5
5
  "repository": {
6
6
  "type": "git",