@streamscloud/kit 0.76.5 → 0.78.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.
Files changed (34) hide show
  1. package/dist/core/utils/color-helper.d.ts +10 -0
  2. package/dist/core/utils/color-helper.js +25 -1
  3. package/dist/ui/form-field/cmp.form-field-validatable.svelte +3 -3
  4. package/dist/ui/form-field/cmp.form-field-validatable.svelte.d.ts +4 -4
  5. package/dist/ui/table/cmp.table-draggable.svelte +56 -304
  6. package/dist/ui/table/cmp.table-draggable.svelte.d.ts +30 -19
  7. package/dist/ui/table/cmp.table.svelte +23 -264
  8. package/dist/ui/table/cmp.table.svelte.d.ts +32 -18
  9. package/dist/ui/table/table-cells/table-checkbox-cell.svelte +0 -1
  10. package/dist/ui/table/table-cells/table-move-row-cell.svelte +0 -2
  11. package/dist/ui/table/table-cells/table-text-cell.svelte +0 -1
  12. package/dist/ui/table/table-column-models.svelte.d.ts +5 -0
  13. package/dist/ui/table/table-column-models.svelte.js +6 -0
  14. package/dist/ui/table/table-core.svelte +407 -0
  15. package/dist/ui/table/table-core.svelte.d.ts +88 -0
  16. package/dist/ui/table/table-headers/table-header-sortable.svelte +1 -4
  17. package/dist/ui/table/table-headers/table-header.svelte +1 -1
  18. package/dist/ui/table/table-localization.d.ts +1 -0
  19. package/dist/ui/table/table-localization.js +7 -0
  20. package/dist/ui/table/table-model.svelte.js +9 -1
  21. package/dist/ui/table/types.d.ts +22 -1
  22. package/dist/ui/validatable/cmp.validatable.svelte +3 -4
  23. package/dist/ui/validatable/cmp.validatable.svelte.d.ts +6 -6
  24. package/dist/ui/validatable/cmp.validation-error.svelte +4 -4
  25. package/dist/ui/validatable/cmp.validation-error.svelte.d.ts +7 -6
  26. package/dist/ui/validatable/field-frame.svelte +25 -15
  27. package/dist/ui/validatable/field-frame.svelte.d.ts +8 -8
  28. package/dist/ui/validatable/index.d.ts +1 -0
  29. package/dist/ui/validatable/types.d.ts +7 -0
  30. package/dist/ui/validatable/types.js +1 -0
  31. package/package.json +1 -1
  32. package/dist/ui/table/_table-styles.scss +0 -158
  33. package/dist/ui/table/table-view.svelte.d.ts +0 -15
  34. package/dist/ui/table/table-view.svelte.js +0 -47
@@ -10,6 +10,7 @@ export type FieldBinding<V> = {
10
10
  };
11
11
  };
12
12
  import type { FormValidationHandler } from '../../core/validation';
13
+ import type { ErrorPlacement } from './types';
13
14
  import type { Snippet } from 'svelte';
14
15
  declare function $$render<T extends Record<string, unknown>, K extends keyof T & string>(): {
15
16
  props: {
@@ -31,11 +32,11 @@ declare function $$render<T extends Record<string, unknown>, K extends keyof T &
31
32
  /** Show errors even when the field has not been touched. @default false */
32
33
  disableTouchedTracking?: boolean;
33
34
  /**
34
- * Reserve space below the field for the error message. Turn off when a sibling must align to
35
- * the field's real bottom edge — the message then overlays whatever sits below the field.
36
- * @default false
35
+ * Where the error message sits: `'overlay'` covers whatever is below the field, `'reserved'` keeps a
36
+ * permanent strip so toggling never shifts layout, `'inline'` grows the field only while an error is shown.
37
+ * @default 'overlay'
37
38
  */
38
- reserveErrorSpace?: boolean;
39
+ errorPlacement?: ErrorPlacement;
39
40
  /**
40
41
  * Extra consumer callbacks. Run AFTER the validation wiring; they cannot override it.
41
42
  * The `children` snippet always receives fully-wired `field.on.*`.
@@ -73,8 +74,7 @@ interface $$IsomorphicComponent {
73
74
  /**
74
75
  * Binds a form field to any kit input via a render-prop snippet. The base inputs stay unchanged;
75
76
  * `Validatable` is the only place that knows about `FormValidationHandler`. Wraps children in an
76
- * internal `FieldFrame` that reserves space for the error message so toggling doesn't shift
77
- * layout; `reserveErrorSpace={false}` drops the reserve — the message overlays content below.
77
+ * internal `FieldFrame` that renders the error message below the field, placed per `errorPlacement`.
78
78
  *
79
79
  * ### Usage
80
80
  * ```svelte
@@ -1,9 +1,9 @@
1
1
  <script lang="ts" generics="T extends Record<string, unknown>">import { default as FieldFrame } from './field-frame.svelte';
2
- let { name, validationResult, reserveErrorSpace = false, children } = $props();
2
+ let { name, validationResult, errorPlacement = 'overlay', children } = $props();
3
3
  const errorText = $derived(validationResult?.errors[name] ?? null);
4
4
  </script>
5
5
 
6
- <FieldFrame error={errorText} reserveErrorSpace={reserveErrorSpace}>
6
+ <FieldFrame error={errorText} errorPlacement={errorPlacement}>
7
7
  {@render children()}
8
8
  </FieldFrame>
9
9
 
@@ -11,6 +11,6 @@ const errorText = $derived(validationResult?.errors[name] ?? null);
11
11
  @component
12
12
  Wraps a form field and displays validation errors from a `FormValidateResult` object. Stateless
13
13
  sibling of `Validatable` for cases where the consumer already has the validation result in hand
14
- (e.g. server-validated forms) and does not need a `FormValidationHandler`. Pass
15
- `reserveErrorSpace={false}` to overlay the message instead of reserving layout space.
14
+ (e.g. server-validated forms) and does not need a `FormValidationHandler`. `errorPlacement` picks
15
+ where the message sits — same contract as `Validatable`.
16
16
  -->
@@ -1,4 +1,5 @@
1
1
  import type { FormValidateResult } from '../../core/validation';
2
+ import type { ErrorPlacement } from './types';
2
3
  import type { Snippet } from 'svelte';
3
4
  declare function $$render<T extends Record<string, unknown>>(): {
4
5
  props: {
@@ -7,11 +8,11 @@ declare function $$render<T extends Record<string, unknown>>(): {
7
8
  /** Validation result object containing error messages */
8
9
  validationResult?: FormValidateResult<T>;
9
10
  /**
10
- * Reserve space below the field for the error message. Turn off when a sibling must align to
11
- * the field's real bottom edge — the message then overlays whatever sits below the field.
12
- * @default false
11
+ * Where the error message sits: `'overlay'` covers whatever is below the field, `'reserved'` keeps a
12
+ * permanent strip so toggling never shifts layout, `'inline'` grows the field only while an error is shown.
13
+ * @default 'overlay'
13
14
  */
14
- reserveErrorSpace?: boolean;
15
+ errorPlacement?: ErrorPlacement;
15
16
  children: Snippet;
16
17
  };
17
18
  exports: {};
@@ -36,8 +37,8 @@ interface $$IsomorphicComponent {
36
37
  /**
37
38
  * Wraps a form field and displays validation errors from a `FormValidateResult` object. Stateless
38
39
  * sibling of `Validatable` for cases where the consumer already has the validation result in hand
39
- * (e.g. server-validated forms) and does not need a `FormValidationHandler`. Pass
40
- * `reserveErrorSpace={false}` to overlay the message instead of reserving layout space.
40
+ * (e.g. server-validated forms) and does not need a `FormValidationHandler`. `errorPlacement` picks
41
+ * where the message sits — same contract as `Validatable`.
41
42
  */
42
43
  declare const Cmp: $$IsomorphicComponent;
43
44
  type Cmp<T extends Record<string, unknown>> = InstanceType<typeof Cmp<T>>;
@@ -1,40 +1,50 @@
1
- <script lang="ts">let { error, reserveErrorSpace = false, children } = $props();
1
+ <script lang="ts">let { error, errorPlacement = 'overlay', children } = $props();
2
2
  export {};
3
3
  </script>
4
4
 
5
- <div class="field-frame" class:field-frame--errored={!!error} class:field-frame--no-reserve={!reserveErrorSpace}>
5
+ <div class="field-frame" class:field-frame--reserved={errorPlacement === 'reserved'}>
6
6
  {@render children()}
7
7
  {#if error}
8
- <small class="field-frame__message">{error}</small>
8
+ <small class="field-frame__message field-frame__message--{errorPlacement}">{error}</small>
9
9
  {/if}
10
10
  </div>
11
11
 
12
12
  <!--
13
13
  @component
14
- Internal helper — wraps a form field and renders its error message in an absolutely-positioned slot
15
- below, with reserved space so the layout doesn't shift when the error toggles. With
16
- `reserveErrorSpace={false}` the reserve is dropped — the message stays absolutely positioned and
17
- overlays whatever sits below the field. Used internally by `Validatable` / `ValidationError` (and
18
- any other field-shaped kit consumer that needs the same visual contract).
14
+ Internal helper — wraps a form field and renders its error message below it, placed per `errorPlacement`: overlaying
15
+ the content below, inside a permanently reserved strip, or in normal flow so the field grows only while the error is
16
+ shown. Used internally by `Validatable` / `ValidationError` (and any other field-shaped kit consumer that needs the
17
+ same visual contract).
19
18
 
20
19
  Not exported from `index.ts` — for kit-internal use only.
21
20
  -->
22
21
 
23
22
  <style>.field-frame {
24
23
  position: relative;
25
- margin-bottom: 1.1em;
26
24
  display: block;
27
25
  }
28
- .field-frame--no-reserve {
29
- margin-bottom: 0;
26
+ .field-frame--reserved {
27
+ padding-block-end: 1.1rem;
30
28
  }
31
29
  .field-frame__message {
32
- position: absolute;
33
- top: calc(100% + 0.1em);
34
- left: 0;
35
- right: 0;
36
30
  display: block;
37
31
  color: var(--sc-kit--color--danger);
38
32
  font-size: 0.6875rem;
33
+ line-height: 1.5;
39
34
  font-weight: 400;
35
+ }
36
+ .field-frame__message--overlay {
37
+ position: absolute;
38
+ top: calc(100% + 0.0688rem);
39
+ left: 0;
40
+ right: 0;
41
+ }
42
+ .field-frame__message--reserved {
43
+ position: absolute;
44
+ bottom: 0;
45
+ left: 0;
46
+ right: 0;
47
+ }
48
+ .field-frame__message--inline {
49
+ margin-top: 0.0688rem;
40
50
  }</style>
@@ -1,17 +1,17 @@
1
+ import type { ErrorPlacement } from './types';
1
2
  import type { Snippet } from 'svelte';
2
3
  type Props = {
3
- /** Error message to display below the field. Falsy hides the message and the `--errored` flag. */
4
+ /** Error message to display below the field. Falsy hides the message. */
4
5
  error?: string | null | undefined;
5
- /** Reserve space below the field for the error message. Off drops the reserve — the message overlays content below. @default false */
6
- reserveErrorSpace?: boolean;
6
+ /** Where the error message sits relative to the field. @default 'overlay' */
7
+ errorPlacement?: ErrorPlacement;
7
8
  children: Snippet;
8
9
  };
9
10
  /**
10
- * Internal helper — wraps a form field and renders its error message in an absolutely-positioned slot
11
- * below, with reserved space so the layout doesn't shift when the error toggles. With
12
- * `reserveErrorSpace={false}` the reserve is dropped — the message stays absolutely positioned and
13
- * overlays whatever sits below the field. Used internally by `Validatable` / `ValidationError` (and
14
- * any other field-shaped kit consumer that needs the same visual contract).
11
+ * Internal helper — wraps a form field and renders its error message below it, placed per `errorPlacement`: overlaying
12
+ * the content below, inside a permanently reserved strip, or in normal flow so the field grows only while the error is
13
+ * shown. Used internally by `Validatable` / `ValidationError` (and any other field-shaped kit consumer that needs the
14
+ * same visual contract).
15
15
  *
16
16
  * Not exported from `index.ts` — for kit-internal use only.
17
17
  */
@@ -1,3 +1,4 @@
1
1
  export { default as Validatable } from './cmp.validatable.svelte';
2
2
  export type { FieldBinding, ValidateOnEvent } from './cmp.validatable.svelte';
3
3
  export { default as ValidationError } from './cmp.validation-error.svelte';
4
+ export type { ErrorPlacement } from './types';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Where a field's validation message sits.
3
+ * - `'overlay'` — absolutely positioned below the field; no space reserved, the message covers whatever sits below.
4
+ * - `'reserved'` — absolutely positioned inside a permanently reserved strip, so toggling the error never shifts layout.
5
+ * - `'inline'` — in normal flow, only while an error is shown: the field grows on error and shrinks back when it clears.
6
+ */
7
+ export type ErrorPlacement = 'overlay' | 'reserved' | 'inline';
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamscloud/kit",
3
- "version": "0.76.5",
3
+ "version": "0.78.0",
4
4
  "author": "StreamsCloud",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,158 +0,0 @@
1
- @use 'styles/mixins';
2
- @use 'styles/functions';
3
-
4
- @mixin base {
5
- .alternative-view {
6
- &__placeholder {
7
- width: 100%;
8
- display: flex;
9
- align-items: center;
10
- justify-content: center;
11
- font-size: 80%;
12
- user-select: none;
13
- }
14
- }
15
-
16
- .table-container {
17
- --_table--row--height: var(--sc-kit--table--row--height, var(--_table--size-row-height));
18
- --_table--cell--font-size: var(--sc-kit--table--cell--font-size, var(--_table--size-cell-font-size));
19
- --_table--cell--horizontal-padding: var(--sc-kit--table--cell--horizontal-padding, var(--_table--size-cell-padding));
20
- --_table--head--height: var(--sc-kit--table--head--height, var(--_table--size-head-height, var(--_table--row--height)));
21
-
22
- --_table--head--background-color: var(--sc-kit--table--head--background-color, var(--sc-kit--color--bg--field-alt));
23
- --_table--head--color: var(--sc-kit--table--head--color, var(--sc-kit--color--text--secondary));
24
- --_table--border-color: var(--sc-kit--table--border-color, var(--sc-kit--color--border));
25
- --_table--row--color: var(--sc-kit--table--row--color, transparent);
26
- --_table--row--alternative-color: var(--sc-kit--table--row--alternative-color, var(--sc-kit--color--bg--hover));
27
- --_table--zebra--color: var(--sc-kit--table--zebra--color, light-dark(#fcfcfd, #232323));
28
- --_table--selected--color: var(--sc-kit--table--selected--color, var(--sc-kit--color--accent--softer));
29
- --_table--selected--color-hover: var(--sc-kit--table--selected--color--hover, var(--sc-kit--color--accent--soft));
30
-
31
- --_table--card--background: var(--sc-kit--table--card--background, var(--sc-kit--color--bg--panel));
32
- --_table--card--border-color: var(--sc-kit--table--card--border-color, var(--sc-kit--color--border));
33
- --_table--card--border-radius: var(--sc-kit--table--card--border-radius, var(--sc-kit--radius--lg));
34
- --_table--card--padding-bottom: var(--sc-kit--table--card--padding-bottom, var(--sc-kit--space--4));
35
-
36
- display: flex;
37
- overflow-x: auto;
38
- height: 100%;
39
-
40
- @include mixins.scrollbar();
41
-
42
- &--md {
43
- --_table--size-row-height: #{functions.to-rem(44)};
44
- --_table--size-head-height: #{functions.to-rem(40)};
45
- --_table--size-cell-font-size: var(--sc-kit--font-size--md);
46
- --_table--size-cell-padding: var(--sc-kit--space--4);
47
- }
48
-
49
- &--sm {
50
- --_table--size-row-height: #{functions.to-rem(36)};
51
- --_table--size-head-height: #{functions.to-rem(32)};
52
- --_table--size-cell-font-size: var(--sc-kit--font-size--sm);
53
- --_table--size-cell-padding: var(--sc-kit--space--3);
54
- }
55
-
56
- &--card {
57
- background: var(--_table--card--background);
58
- border: 1px solid var(--_table--card--border-color);
59
- border-radius: var(--_table--card--border-radius);
60
- padding-bottom: var(--_table--card--padding-bottom);
61
- // No overflow here: the radius already clips via the base overflow-x, and `hidden` would kill both scroll axes.
62
- }
63
- }
64
-
65
- .table {
66
- width: 100%;
67
- table-layout: auto;
68
- height: fit-content;
69
- border-collapse: separate;
70
- border-spacing: 0;
71
-
72
- &__head {
73
- height: var(--_table--head--height);
74
- max-height: var(--_table--head--height);
75
- background: var(--_table--head--background-color);
76
- color: var(--_table--head--color);
77
- font-size: var(--sc-kit--table--head--font-size, var(--sc-kit--font-size--sm));
78
- font-weight: var(--sc-kit--font-weight--semibold);
79
- }
80
-
81
- &__th {
82
- padding: 0 var(--_table--cell--horizontal-padding);
83
- text-align: left;
84
- vertical-align: middle;
85
- border-bottom: 1px solid var(--_table--border-color);
86
- @include mixins.no-select;
87
-
88
- &--centered {
89
- text-align: center;
90
- --_table-header--justify-content: center;
91
- }
92
- }
93
-
94
- &__tr {
95
- height: var(--_table--row--height);
96
- max-height: var(--_table--row--height);
97
- background: var(--_table--row--color);
98
-
99
- &--zebra {
100
- background: var(--_table--zebra--color);
101
- }
102
-
103
- &:hover,
104
- &--highlighted {
105
- background: var(--_table--row--alternative-color);
106
- --_table--move-row-cell-opacity: 1;
107
- }
108
-
109
- &--selected {
110
- background: var(--_table--selected--color);
111
- }
112
-
113
- &--selected:hover {
114
- background: var(--_table--selected--color-hover);
115
- }
116
-
117
- &--placeholder {
118
- background: var(--_table--row--color) !important;
119
- }
120
- }
121
-
122
- &__td {
123
- padding: 0 var(--_table--cell--horizontal-padding);
124
- border-bottom: 1px solid var(--_table--border-color);
125
- font-size: var(--_table--cell--font-size);
126
- color: var(--sc-kit--color--text--primary);
127
- vertical-align: middle;
128
-
129
- &--centered {
130
- text-align: center;
131
- }
132
-
133
- &--clickable {
134
- cursor: pointer;
135
- }
136
-
137
- &--flush {
138
- border-bottom: none;
139
- }
140
- }
141
-
142
- &__placeholder {
143
- display: flex;
144
- align-items: center;
145
- justify-content: center;
146
- font-size: 80%;
147
- user-select: none;
148
- }
149
-
150
- &--sticky-header {
151
- thead {
152
- position: sticky;
153
- top: 0;
154
- z-index: 1;
155
- }
156
- }
157
- }
158
- }
@@ -1,15 +0,0 @@
1
- import type { ResolvedColumn } from './table-column-models.svelte';
2
- import type { TableModel } from './table-model.svelte';
3
- import type { WithId } from './types';
4
- type SelectionCallbacks<T> = {
5
- selectionChanged?: (e: T[]) => void;
6
- itemsSelected?: (e: T[]) => void;
7
- itemsDeselected?: (e: T[]) => void;
8
- };
9
- /** Inline width declarations for a column's `th` / `td`: the preferred width plus, when set, the floor the browser must honour. */
10
- export declare const columnWidthStyle: <T extends WithId>(column: ResolvedColumn<T>) => string;
11
- /** Shared presentation wiring for the table views: selection-event subscriptions + the no-items placeholder decision (on/off gate + anti-flicker delay). */
12
- export declare const createTableView: <T extends WithId>(model: () => TableModel<T>, on: () => SelectionCallbacks<T> | undefined, noItemsPlaceholderEnabled?: () => boolean | undefined, noItemsPlaceholderDelay?: () => number | undefined) => {
13
- readonly showNoItemsPlaceholder: boolean;
14
- };
15
- export {};
@@ -1,47 +0,0 @@
1
- import { untrack } from 'svelte';
2
- /** Inline width declarations for a column's `th` / `td`: the preferred width plus, when set, the floor the browser must honour. */
3
- export const columnWidthStyle = (column) => {
4
- const width = column.cssWidth ? `width: ${column.cssWidth};` : 'width: auto;';
5
- return column.minCssWidth ? `${width} min-width: ${column.minCssWidth};` : width;
6
- };
7
- /** Shared presentation wiring for the table views: selection-event subscriptions + the no-items placeholder decision (on/off gate + anti-flicker delay). */
8
- export const createTableView = (model, on, noItemsPlaceholderEnabled = () => undefined, noItemsPlaceholderDelay = () => undefined) => {
9
- let showNoItemsPlaceholder = $state(false);
10
- let timeout = 0;
11
- $effect(() => untrack(() => {
12
- const selection = model().selection;
13
- const subscriptions = [
14
- selection.subscribeOnChange((values) => on()?.selectionChanged?.(values)),
15
- selection.subscribeOnAdd((values) => on()?.itemsSelected?.(values)),
16
- selection.subscribeOnRemove((values) => on()?.itemsDeselected?.(values))
17
- ];
18
- return () => subscriptions.forEach((unsubscribe) => unsubscribe());
19
- }));
20
- $effect(() => {
21
- if (model().items.length) {
22
- clearTimeout(timeout);
23
- showNoItemsPlaceholder = false;
24
- return;
25
- }
26
- if (noItemsPlaceholderEnabled() === false) {
27
- clearTimeout(timeout);
28
- showNoItemsPlaceholder = false;
29
- return;
30
- }
31
- const delay = noItemsPlaceholderDelay() ?? 0;
32
- if (delay <= 0) {
33
- clearTimeout(timeout);
34
- showNoItemsPlaceholder = true;
35
- return;
36
- }
37
- timeout = window.setTimeout(() => {
38
- showNoItemsPlaceholder = !model().items.length;
39
- }, delay);
40
- return () => clearTimeout(timeout);
41
- });
42
- return {
43
- get showNoItemsPlaceholder() {
44
- return showNoItemsPlaceholder;
45
- }
46
- };
47
- };