@streamscloud/kit 0.21.0 → 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.
@@ -116,6 +116,7 @@ Pass `type="anchor"` to render as `<a>` with `href`, or `type="presentational"`
116
116
  | `--sc-kit--button--width` | Explicit width | `fit-content` |
117
117
  | `--sc-kit--button--min-width` | Minimum width | `0` |
118
118
  | `--sc-kit--button--max-width` | Maximum width | `100%` |
119
+ | `--sc-kit--button--justify-content` | Alignment of the button's content along the inline axis | `center` |
119
120
  -->
120
121
 
121
122
  <style>.btn {
@@ -134,12 +135,13 @@ Pass `type="anchor"` to render as `<a>` with `href`, or `type="presentational"`
134
135
  --_btn--width: var(--sc-kit--button--width, fit-content);
135
136
  --_btn--min-width: var(--sc-kit--button--min-width, 0);
136
137
  --_btn--max-width: var(--sc-kit--button--max-width, 100%);
138
+ --_btn--justify-content: var(--sc-kit--button--justify-content, center);
137
139
  --_btn--border-radius: var(--sc-kit--button--border-radius, var(--_btn--size-border-radius, var(--sc-kit--field--border-radius--md)));
138
140
  --_btn--font-weight: var(--sc-kit--button--font-weight, var(--sc-kit--font-weight--regular));
139
141
  box-sizing: border-box;
140
142
  display: flex;
141
143
  align-items: center;
142
- justify-content: center;
144
+ justify-content: var(--_btn--justify-content);
143
145
  gap: var(--_btn--gap);
144
146
  width: var(--_btn--width);
145
147
  min-width: var(--_btn--min-width);
@@ -73,6 +73,7 @@ type Props = ButtonModeProps | AnchorModeProps | PresentationalModeProps;
73
73
  * | `--sc-kit--button--width` | Explicit width | `fit-content` |
74
74
  * | `--sc-kit--button--min-width` | Minimum width | `0` |
75
75
  * | `--sc-kit--button--max-width` | Maximum width | `100%` |
76
+ * | `--sc-kit--button--justify-content` | Alignment of the button's content along the inline axis | `center` |
76
77
  */
77
78
  declare const Cmp: import("svelte").Component<Props, {}, "">;
78
79
  type Cmp = ReturnType<typeof Cmp>;
@@ -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.0",
3
+ "version": "0.21.2",
4
4
  "author": "StreamsCloud",
5
5
  "repository": {
6
6
  "type": "git",