@websline/system-components 1.0.3 → 1.0.5

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 (27) hide show
  1. package/dist/components/atoms/input/Input.svelte +5 -4
  2. package/dist/components/atoms/input/input.variants.d.ts +102 -9
  3. package/dist/components/atoms/input/input.variants.js +44 -5
  4. package/dist/components/atoms/radio/Radio.svelte +3 -2
  5. package/dist/components/atoms/select/Select.svelte +11 -10
  6. package/dist/components/atoms/select/select.variants.d.ts +34 -26
  7. package/dist/components/atoms/select/select.variants.js +12 -22
  8. package/dist/components/atoms/switch/Switch.svelte +3 -2
  9. package/dist/components/atoms/textarea/Textarea.svelte +5 -4
  10. package/dist/components/atoms/textarea/textarea.variants.d.ts +45 -21
  11. package/dist/components/atoms/textarea/textarea.variants.js +5 -7
  12. package/dist/components/atoms/utils/xScroll/XScroll.svelte +87 -0
  13. package/dist/components/atoms/utils/xScroll/XScroll.svelte.d.ts +25 -0
  14. package/dist/components/atoms/utils/xScroll/xScroll.variants.d.ts +39 -0
  15. package/dist/components/atoms/utils/xScroll/xScroll.variants.js +16 -0
  16. package/dist/components/molecules/formField/FormField.svelte +13 -8
  17. package/dist/components/molecules/formField/FormField.svelte.d.ts +14 -6
  18. package/dist/components/molecules/formField/formField.variants.d.ts +42 -6
  19. package/dist/components/molecules/formField/formField.variants.js +14 -2
  20. package/dist/components/molecules/selectorCard/SelectorCard.svelte +2 -2
  21. package/dist/components/molecules/toggleGroup/ToggleGroup.svelte +10 -7
  22. package/dist/components/molecules/toggleGroup/ToggleGroup.svelte.d.ts +1 -1
  23. package/dist/components/molecules/toggleGroup/toggleGroup.variants.d.ts +49 -11
  24. package/dist/components/molecules/toggleGroup/toggleGroup.variants.js +16 -6
  25. package/dist/index.d.ts +1 -0
  26. package/dist/index.js +1 -0
  27. package/package.json +29 -29
@@ -41,8 +41,9 @@
41
41
  }
42
42
 
43
43
  return {
44
- id,
44
+ disabled,
45
45
  error,
46
+ id,
46
47
  required,
47
48
  };
48
49
  });
@@ -51,10 +52,10 @@
51
52
  <input
52
53
  class={inputVariants({
53
54
  class: className,
54
- disabled,
55
+ disabled: localValues.disabled,
55
56
  error: localValues.error,
56
- })}
57
- {disabled}
57
+ }).base()}
58
+ disabled={localValues.disabled}
58
59
  id={localValues.id}
59
60
  {name}
60
61
  {placeholder}
@@ -1,22 +1,115 @@
1
+ /**
2
+ * @property {boolean} [defaultValue] Use this variant if the element doesn't support the placeholder selector
3
+ */
4
+ export const inputBaseVariant: import("tailwind-variants").TVReturnType<{
5
+ disabled: {
6
+ true: {
7
+ base: string;
8
+ };
9
+ };
10
+ error: {
11
+ true: {
12
+ base: string;
13
+ };
14
+ };
15
+ }, {
16
+ base: string[];
17
+ }, undefined, {
18
+ disabled: {
19
+ true: {
20
+ base: string;
21
+ };
22
+ };
23
+ error: {
24
+ true: {
25
+ base: string;
26
+ };
27
+ };
28
+ }, {
29
+ base: string[];
30
+ }, import("tailwind-variants").TVReturnType<{
31
+ disabled: {
32
+ true: {
33
+ base: string;
34
+ };
35
+ };
36
+ error: {
37
+ true: {
38
+ base: string;
39
+ };
40
+ };
41
+ }, {
42
+ base: string[];
43
+ }, undefined, unknown, unknown, undefined>>;
1
44
  export const inputVariants: import("tailwind-variants").TVReturnType<{
45
+ [key: string]: {
46
+ [key: string]: import("tailwind-variants").ClassValue | {
47
+ base?: import("tailwind-variants").ClassValue;
48
+ };
49
+ };
50
+ } | {
51
+ disabled: {
52
+ true: import("tailwind-variants").ClassValue | {
53
+ base?: import("tailwind-variants").ClassValue;
54
+ };
55
+ };
56
+ error: {
57
+ true: import("tailwind-variants").ClassValue | {
58
+ base?: import("tailwind-variants").ClassValue;
59
+ };
60
+ };
61
+ }, {
62
+ base: string;
63
+ }, undefined, {
64
+ disabled: {
65
+ true: {
66
+ base: string;
67
+ };
68
+ };
69
+ error: {
70
+ true: {
71
+ base: string;
72
+ };
73
+ };
74
+ }, {
75
+ base: string[];
76
+ }, import("tailwind-variants").TVReturnType<{
2
77
  disabled: {
3
- true: string;
78
+ true: {
79
+ base: string;
80
+ };
4
81
  };
5
82
  error: {
6
- true: string;
83
+ true: {
84
+ base: string;
85
+ };
7
86
  };
8
- }, undefined, "transition-[border, outline] h-10 w-full rounded border border-neutral-500 bg-transparent px-4 body-default text-neutral-800 placeholder-neutral-500 outline-transparent duration-300 hover:border-neutral-800 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 dark:text-white dark:hover:border-neutral-200 dark:focus:border-white dark:focus:ring-white", {
87
+ }, {
88
+ base: string[];
89
+ }, undefined, {
9
90
  disabled: {
10
- true: string;
91
+ true: {
92
+ base: string;
93
+ };
11
94
  };
12
95
  error: {
13
- true: string;
96
+ true: {
97
+ base: string;
98
+ };
14
99
  };
15
- }, undefined, import("tailwind-variants").TVReturnType<{
100
+ }, {
101
+ base: string[];
102
+ }, import("tailwind-variants").TVReturnType<{
16
103
  disabled: {
17
- true: string;
104
+ true: {
105
+ base: string;
106
+ };
18
107
  };
19
108
  error: {
20
- true: string;
109
+ true: {
110
+ base: string;
111
+ };
21
112
  };
22
- }, undefined, "transition-[border, outline] h-10 w-full rounded border border-neutral-500 bg-transparent px-4 body-default text-neutral-800 placeholder-neutral-500 outline-transparent duration-300 hover:border-neutral-800 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 dark:text-white dark:hover:border-neutral-200 dark:focus:border-white dark:focus:ring-white", unknown, unknown, undefined>>;
113
+ }, {
114
+ base: string[];
115
+ }, undefined, unknown, unknown, undefined>>>;
@@ -1,15 +1,54 @@
1
1
  import { tv } from "tailwind-variants";
2
2
 
3
- const inputVariants = tv({
4
- base: "transition-[border, outline] h-10 w-full rounded border border-neutral-500 bg-transparent px-4 body-default text-neutral-800 placeholder-neutral-500 outline-transparent duration-300 hover:border-neutral-800 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 dark:text-white dark:hover:border-neutral-200 dark:focus:border-white dark:focus:ring-white",
3
+ /**
4
+ * @property {boolean} [defaultValue] Use this variant if the element doesn't support the placeholder selector
5
+ */
6
+ const inputBaseVariant = tv({
7
+ slots: {
8
+ base: [
9
+ "w-full rounded bg-transparent px-4 body-default",
10
+ "text-neutral-900 placeholder-neutral-500 dark:text-neutral-200",
11
+ "outline-transparent transition-[border,color,outline] duration-300",
12
+ "border border-neutral-300 dark:border-neutral-700",
13
+ ],
14
+ },
5
15
  variants: {
6
16
  disabled: {
7
- true: "cursor-not-allowed opacity-50",
17
+ true: { base: "cursor-not-allowed opacity-40" },
8
18
  },
9
19
  error: {
10
- true: "border border-red-500 text-red-500 outline outline-red-500 focus:border-red-500 focus:ring-red-500",
20
+ true: {
21
+ base: "border-current text-red-500 ring ring-current dark:border-current dark:text-red-500",
22
+ },
23
+ },
24
+ },
25
+ compoundVariants: [
26
+ {
27
+ disabled: false,
28
+ error: false,
29
+ class: {
30
+ base: [
31
+ "hover:ring-1 focus:ring-1",
32
+ "hover:border-blue-500 hover:ring-blue-500 focus:border-blue-500 focus:ring-blue-500",
33
+ "dark:hover:border-blue-400 dark:hover:ring-blue-400 dark:focus:border-blue-400 dark:focus:ring-blue-400",
34
+ ],
35
+ },
11
36
  },
37
+ {
38
+ defaultValue: true,
39
+ error: false,
40
+ class: {
41
+ base: "text-neutral-500 dark:text-neutral-500",
42
+ },
43
+ },
44
+ ],
45
+ });
46
+
47
+ const inputVariants = tv({
48
+ extend: inputBaseVariant,
49
+ slots: {
50
+ base: "h-10",
12
51
  },
13
52
  });
14
53
 
15
- export { inputVariants };
54
+ export { inputBaseVariant, inputVariants };
@@ -35,6 +35,7 @@
35
35
  }
36
36
 
37
37
  return {
38
+ disabled,
38
39
  id,
39
40
  required,
40
41
  };
@@ -47,9 +48,9 @@
47
48
  class={radioVariants({
48
49
  checked,
49
50
  class: className,
50
- disabled,
51
+ disabled: localValues.disabled,
51
52
  })}
52
- {disabled}
53
+ disabled={localValues.disabled}
53
54
  id={localValues.id}
54
55
  {name}
55
56
  required={localValues.required}
@@ -37,22 +37,24 @@
37
37
  }
38
38
 
39
39
  return {
40
- id,
40
+ disabled,
41
41
  error,
42
+ id,
42
43
  required,
43
44
  };
44
45
  });
45
46
 
46
- let styles = $derived(selectVariants());
47
+ let styles = $derived(
48
+ selectVariants({
49
+ defaultValue: value === "" || value == null,
50
+ error: localValues.error,
51
+ }),
52
+ );
47
53
  </script>
48
54
 
49
55
  <select
50
- class={styles.select({
51
- class: className,
52
- disabled,
53
- error: localValues.error,
54
- })}
55
- {disabled}
56
+ class={styles.base({ class: className, disabled: localValues.disabled })}
57
+ disabled={localValues.disabled}
56
58
  id={localValues.id}
57
59
  required={localValues.required}
58
60
  bind:value
@@ -72,8 +74,7 @@
72
74
 
73
75
  <style>
74
76
  select {
75
- appearance: base-select;
76
-
77
+ &,
77
78
  &::picker(select) {
78
79
  appearance: base-select;
79
80
  }
@@ -1,58 +1,66 @@
1
1
  export const selectVariants: import("tailwind-variants").TVReturnType<{
2
2
  disabled: {
3
- true: {
3
+ false: {
4
+ base: string;
4
5
  option: string;
5
- select: string;
6
6
  };
7
- false: {
7
+ true: {
8
8
  option: string;
9
- select: string[];
9
+ };
10
+ };
11
+ }, {
12
+ base: string[];
13
+ option: string[];
14
+ }, undefined, {
15
+ disabled: {
16
+ true: {
17
+ base: string;
10
18
  };
11
19
  };
12
20
  error: {
13
21
  true: {
14
- select: string;
22
+ base: string;
15
23
  };
16
24
  };
17
25
  }, {
18
- select: string[];
19
- option: string[];
20
- }, undefined, {
26
+ base: string[];
27
+ }, import("tailwind-variants").TVReturnType<{
21
28
  disabled: {
22
29
  true: {
23
- option: string;
24
- select: string;
30
+ base: string;
25
31
  };
26
- false: {
27
- option: string;
28
- select: string[];
32
+ };
33
+ error: {
34
+ true: {
35
+ base: string;
36
+ };
37
+ };
38
+ }, {
39
+ base: string[];
40
+ }, undefined, {
41
+ disabled: {
42
+ true: {
43
+ base: string;
29
44
  };
30
45
  };
31
46
  error: {
32
47
  true: {
33
- select: string;
48
+ base: string;
34
49
  };
35
50
  };
36
51
  }, {
37
- select: string[];
38
- option: string[];
52
+ base: string[];
39
53
  }, import("tailwind-variants").TVReturnType<{
40
54
  disabled: {
41
55
  true: {
42
- option: string;
43
- select: string;
44
- };
45
- false: {
46
- option: string;
47
- select: string[];
56
+ base: string;
48
57
  };
49
58
  };
50
59
  error: {
51
60
  true: {
52
- select: string;
61
+ base: string;
53
62
  };
54
63
  };
55
64
  }, {
56
- select: string[];
57
- option: string[];
58
- }, undefined, unknown, unknown, undefined>>;
65
+ base: string[];
66
+ }, undefined, unknown, unknown, undefined>>>;
@@ -1,46 +1,36 @@
1
1
  import { tv } from "tailwind-variants";
2
+ import { inputBaseVariant } from "../input/input.variants.js";
2
3
 
3
4
  const selectVariants = tv({
5
+ extend: inputBaseVariant,
4
6
  slots: {
5
- select: [
6
- "flex min-h-10 w-full items-center rounded bg-transparent px-4 pr-2 body-default",
7
- "text-neutral-900 dark:text-neutral-200",
8
- "transition-[border, outline, color] outline-transparent duration-300",
9
- "border border-neutral-500 bg-none",
7
+ base: [
8
+ "flex min-h-10 items-center bg-none pr-2",
10
9
  "[&::picker(select)]:my-1 [&::picker(select)]:rounded [&::picker(select)]:border-0 [&::picker(select)]:p-1",
11
10
  "[&::picker-icon]:hidden",
12
11
  "[&::picker(select)]:bg-white [&::picker(select)]:shadow-sm dark:[&::picker(select)]:bg-neutral-800",
13
- "[&::after]:bg-current [&::after]:bg-size-[100%] [&::after]:bg-center [&::after]:bg-no-repeat",
14
- "[&::after]:ml-auto [&::after]:size-5 [&::after]:shrink-0 [&::after]:content-['']",
15
- "[&:open::after]:rotate-180",
12
+ "after:bg-current after:bg-size-[100%] after:bg-center after:bg-no-repeat",
13
+ "after:ml-auto after:size-5 after:shrink-0",
14
+ "[&:open]:after:rotate-180",
16
15
  ],
17
16
  option: [
18
17
  "flex rounded p-2 body-small",
18
+ "bg-white dark:bg-neutral-800",
19
+ "bg-linear-to-r to-transparent",
19
20
  "[&::checkmark]:order-1 [&::checkmark]:ml-auto [&::checkmark]:shrink-0",
20
21
  "[&::checkmark]:bg-current [&::checkmark]:bg-size-[100%] [&::checkmark]:bg-center [&::checkmark]:bg-no-repeat",
21
22
  "[&::checkmark]:size-4 [&::checkmark]:content-['']",
22
- "bg-white text-neutral-900 dark:bg-neutral-800 dark:text-neutral-200",
23
- "bg-linear-to-r to-transparent",
24
23
  ],
25
24
  },
26
25
  variants: {
27
26
  disabled: {
28
- true: {
29
- option: "text-neutral-500 dark:text-neutral-500 [&::checkmark]:hidden",
30
- select: "opacity-25",
31
- },
32
27
  false: {
28
+ base: "hover:text-blue-500 dark:hover:text-blue-400",
33
29
  option:
34
- "cursor-pointer hover:from-neutral-1000/30 dark:hover:from-neutral-50/30",
35
- select: [
36
- "hover:border-current hover:ring-current focus:border-current focus:ring-current",
37
- "hover:text-blue-500 hover:ring-1 focus:text-blue-500 focus:ring-1 dark:hover:text-blue-400 dark:focus:text-blue-400",
38
- ],
30
+ "cursor-pointer text-neutral-900 hover:from-black/15 dark:text-neutral-200 dark:hover:from-white/15",
39
31
  },
40
- },
41
- error: {
42
32
  true: {
43
- select: "border-red-500 text-red-500 dark:border-red-500 dark:text-red-500",
33
+ option: "text-neutral-500 dark:text-neutral-500 [&::checkmark]:hidden",
44
34
  },
45
35
  },
46
36
  },
@@ -35,6 +35,7 @@
35
35
  }
36
36
 
37
37
  return {
38
+ disabled,
38
39
  id,
39
40
  required,
40
41
  };
@@ -46,9 +47,9 @@
46
47
  class={switchVariants({
47
48
  checked,
48
49
  class: className,
49
- disabled,
50
+ disabled: localValues.disabled,
50
51
  })}
51
- {disabled}
52
+ disabled={localValues.disabled}
52
53
  id={localValues.id}
53
54
  {name}
54
55
  required={localValues.required}
@@ -41,8 +41,9 @@
41
41
  }
42
42
 
43
43
  return {
44
- id,
44
+ disabled,
45
45
  error,
46
+ id,
46
47
  required,
47
48
  };
48
49
  });
@@ -51,11 +52,11 @@
51
52
  <textarea
52
53
  class={textareaVariants({
53
54
  class: className,
54
- disabled,
55
+ disabled: localValues.disabled,
55
56
  error: localValues.error,
56
57
  size,
57
- })}
58
- {disabled}
58
+ }).base()}
59
+ disabled={localValues.disabled}
59
60
  id={localValues.id}
60
61
  {name}
61
62
  {placeholder}
@@ -1,37 +1,61 @@
1
1
  export const textareaVariants: import("tailwind-variants").TVReturnType<{
2
- disabled: {
3
- true: string;
4
- };
5
- error: {
6
- true: string;
7
- };
8
2
  size: {
9
3
  small: string;
10
4
  medium: string;
11
5
  large: string;
12
6
  };
13
- }, undefined, "transition-[border, outline] w-full resize-none rounded border border-neutral-500 bg-transparent p-4 body-default text-neutral-800 placeholder-neutral-500 outline-transparent duration-300 hover:border-neutral-800 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 dark:text-white dark:hover:border-neutral-200 dark:focus:border-white dark:focus:ring-white", {
7
+ }, {
8
+ base: string;
9
+ }, undefined, {
14
10
  disabled: {
15
- true: string;
11
+ true: {
12
+ base: string;
13
+ };
16
14
  };
17
15
  error: {
18
- true: string;
16
+ true: {
17
+ base: string;
18
+ };
19
19
  };
20
- size: {
21
- small: string;
22
- medium: string;
23
- large: string;
20
+ }, {
21
+ base: string[];
22
+ }, import("tailwind-variants").TVReturnType<{
23
+ disabled: {
24
+ true: {
25
+ base: string;
26
+ };
24
27
  };
25
- }, undefined, import("tailwind-variants").TVReturnType<{
28
+ error: {
29
+ true: {
30
+ base: string;
31
+ };
32
+ };
33
+ }, {
34
+ base: string[];
35
+ }, undefined, {
26
36
  disabled: {
27
- true: string;
37
+ true: {
38
+ base: string;
39
+ };
28
40
  };
29
41
  error: {
30
- true: string;
42
+ true: {
43
+ base: string;
44
+ };
31
45
  };
32
- size: {
33
- small: string;
34
- medium: string;
35
- large: string;
46
+ }, {
47
+ base: string[];
48
+ }, import("tailwind-variants").TVReturnType<{
49
+ disabled: {
50
+ true: {
51
+ base: string;
52
+ };
53
+ };
54
+ error: {
55
+ true: {
56
+ base: string;
57
+ };
36
58
  };
37
- }, undefined, "transition-[border, outline] w-full resize-none rounded border border-neutral-500 bg-transparent p-4 body-default text-neutral-800 placeholder-neutral-500 outline-transparent duration-300 hover:border-neutral-800 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 dark:text-white dark:hover:border-neutral-200 dark:focus:border-white dark:focus:ring-white", unknown, unknown, undefined>>;
59
+ }, {
60
+ base: string[];
61
+ }, undefined, unknown, unknown, undefined>>>;
@@ -1,14 +1,12 @@
1
1
  import { tv } from "tailwind-variants";
2
+ import { inputBaseVariant } from "../input/input.variants.js";
2
3
 
3
4
  const textareaVariants = tv({
4
- base: "transition-[border, outline] w-full resize-none rounded border border-neutral-500 bg-transparent p-4 body-default text-neutral-800 placeholder-neutral-500 outline-transparent duration-300 hover:border-neutral-800 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 dark:text-white dark:hover:border-neutral-200 dark:focus:border-white dark:focus:ring-white",
5
+ extend: inputBaseVariant,
6
+ slots: {
7
+ base: "resize-none p-4",
8
+ },
5
9
  variants: {
6
- disabled: {
7
- true: "cursor-not-allowed opacity-50",
8
- },
9
- error: {
10
- true: "border border-red-500 text-red-500 outline outline-red-500 focus:border-red-500 focus:ring-red-500",
11
- },
12
10
  size: {
13
11
  small: "h-30",
14
12
  medium: "h-42",
@@ -0,0 +1,87 @@
1
+ <script>
2
+ import { onMount } from "svelte";
3
+ import { xScrollVariants } from "./xScroll.variants.js";
4
+
5
+ /**
6
+ * @typedef {Object} Props
7
+ * @property {import('svelte').Snippet} [children] Children content – can be text, HTML, or other Svelte components
8
+ * @property {string} [class=""] Additional CSS classes to apply to the component
9
+ */
10
+
11
+ /** @type {Props} */
12
+ let { children, class: className = "", ...rest } = $props();
13
+
14
+ let ro;
15
+ let scroller = $state();
16
+ let edgeStart = $state(true);
17
+ let edgeEnd = $state(false);
18
+
19
+ let styles = $derived(xScrollVariants());
20
+
21
+ const updateEdges = ({ clientWidth, scrollLeft, scrollWidth }) => {
22
+ const threshold = 3; // px
23
+ edgeStart = scrollLeft < threshold;
24
+ edgeEnd = scrollLeft + threshold >= scrollWidth - clientWidth;
25
+ };
26
+
27
+ const onwheel = (event) => {
28
+ const scrollContainer = event.currentTarget;
29
+ if (event.deltaY === 0) return;
30
+
31
+ event.preventDefault();
32
+ scrollContainer.scrollLeft += event.deltaY + event.deltaX;
33
+
34
+ updateEdges(scrollContainer);
35
+ };
36
+
37
+ onMount(() => {
38
+ if (scroller) {
39
+ ro = new ResizeObserver(() => {
40
+ updateEdges(scroller);
41
+ });
42
+
43
+ ro.observe(scroller);
44
+ }
45
+
46
+ return () => {
47
+ ro?.disconnect();
48
+ };
49
+ });
50
+ </script>
51
+
52
+ <div class={styles.base({ class: className })} {...rest}>
53
+ {#if !edgeStart}
54
+ <div class={styles.overflowStart()}></div>
55
+ {/if}
56
+ <div
57
+ class={styles.scroller()}
58
+ {onwheel}
59
+ onscrollend={(e) => updateEdges(e.target)}
60
+ bind:this={scroller}>
61
+ <div class={styles.inner()}>{@render children?.()}</div>
62
+ </div>
63
+ {#if !edgeEnd}
64
+ <div class={styles.overflowEnd()}></div>
65
+ {/if}
66
+ </div>
67
+
68
+ <style>
69
+ .overflow-x-auto {
70
+ -ms-overflow-style: none;
71
+ scrollbar-width: none;
72
+ }
73
+
74
+ .overflow-x-auto::-webkit-scrollbar {
75
+ width: 0;
76
+ height: 0;
77
+ }
78
+
79
+ .overflow-x-auto:hover {
80
+ scrollbar-width: thin;
81
+ scrollbar-color: color-mix(in lab, black, currentColor 75%) currentColor;
82
+ }
83
+
84
+ :global(.dark) .overflow-x-auto:hover {
85
+ scrollbar-color: color-mix(in lab, white, currentColor 50%) currentColor;
86
+ }
87
+ </style>
@@ -0,0 +1,25 @@
1
+ export default XScroll;
2
+ type XScroll = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<Props>): void;
5
+ };
6
+ declare const XScroll: import("svelte").Component<{
7
+ /**
8
+ * Children content – can be text, HTML, or other Svelte components
9
+ */
10
+ children?: import("svelte").Snippet;
11
+ /**
12
+ * Additional CSS classes to apply to the component
13
+ */
14
+ class?: string;
15
+ }, {}, "">;
16
+ type Props = {
17
+ /**
18
+ * Children content – can be text, HTML, or other Svelte components
19
+ */
20
+ children?: import("svelte").Snippet;
21
+ /**
22
+ * Additional CSS classes to apply to the component
23
+ */
24
+ class?: string;
25
+ };
@@ -0,0 +1,39 @@
1
+ export const xScrollVariants: import("tailwind-variants").TVReturnType<{
2
+ [key: string]: {
3
+ [key: string]: import("tailwind-variants").ClassValue | {
4
+ base?: import("tailwind-variants").ClassValue;
5
+ scroller?: import("tailwind-variants").ClassValue;
6
+ inner?: import("tailwind-variants").ClassValue;
7
+ overflowStart?: import("tailwind-variants").ClassValue;
8
+ overflowEnd?: import("tailwind-variants").ClassValue;
9
+ };
10
+ };
11
+ } | {
12
+ [x: string]: {
13
+ [x: string]: import("tailwind-variants").ClassValue | {
14
+ base?: import("tailwind-variants").ClassValue;
15
+ scroller?: import("tailwind-variants").ClassValue;
16
+ inner?: import("tailwind-variants").ClassValue;
17
+ overflowStart?: import("tailwind-variants").ClassValue;
18
+ overflowEnd?: import("tailwind-variants").ClassValue;
19
+ };
20
+ };
21
+ }, {
22
+ base: string;
23
+ scroller: string;
24
+ inner: string;
25
+ overflowStart: string[];
26
+ overflowEnd: string[];
27
+ }, undefined, any, {
28
+ base: string;
29
+ scroller: string;
30
+ inner: string;
31
+ overflowStart: string[];
32
+ overflowEnd: string[];
33
+ }, import("tailwind-variants").TVReturnType<any, {
34
+ base: string;
35
+ scroller: string;
36
+ inner: string;
37
+ overflowStart: string[];
38
+ overflowEnd: string[];
39
+ }, undefined, unknown, unknown, undefined>>;
@@ -0,0 +1,16 @@
1
+ import { tv } from "tailwind-variants";
2
+
3
+ const EDGE_BASE =
4
+ "pointer-events-none absolute top-0 z-1000 h-full w-6 from-current to-transparent";
5
+
6
+ const xScrollVariants = tv({
7
+ slots: {
8
+ base: "relative",
9
+ scroller: "overflow-x-auto",
10
+ inner: "inline-block min-w-full",
11
+ overflowStart: [EDGE_BASE, "left-0 bg-linear-to-r"],
12
+ overflowEnd: [EDGE_BASE, "right-0 bg-linear-to-l"],
13
+ },
14
+ });
15
+
16
+ export { xScrollVariants };
@@ -1,29 +1,31 @@
1
1
  <script>
2
2
  import { setContext } from "svelte";
3
3
  import { formFieldVariants } from "./formField.variants.js";
4
- import { HelperText, Label } from "../../../index.js";
4
+ import { HelperText, Label, utils } from "../../../index.js";
5
5
 
6
6
  /**
7
7
  * @typedef {Object} Props
8
8
  * @property {import('svelte').Snippet} [children] Children content – can be text, HTML, or other Svelte components
9
9
  * @property {string} [class=""] Additional CSS classes to apply to the component
10
- * @property {boolean} [error=false] Whether the form field has an error
10
+ * @property {boolean} [disabled=false] Whether the form field is disabled (passed down to the input)
11
+ * @property {boolean} [error=false] Whether the form field has an error (passed down to the input)
11
12
  * @property {string} [errorText=""] The error text for the form field
12
13
  * @property {string} [helperText=""] The helper text for the form field
13
- * @property {string} [id=""] The id attribute for the form field
14
+ * @property {string} [id=""] The id attribute for the form field (passed down to the input)
14
15
  * @property {string} [label=""] The label text for the form field
15
16
  * @property {"stacked" | "inline"} [layout="stacked"] The layout of the input and label
16
- * @property {boolean} [required=false] Whether the form field is required
17
+ * @property {boolean} [required=false] Whether the form field is required (passed down to the input)
17
18
  */
18
19
 
19
20
  /** @type {Props} */
20
21
  let {
21
22
  children,
22
23
  class: className,
24
+ disabled = false,
23
25
  error = false,
24
26
  errorText,
25
27
  helperText,
26
- id,
28
+ id = utils.generateId(),
27
29
  label,
28
30
  layout = "stacked",
29
31
  required = false,
@@ -31,6 +33,7 @@
31
33
 
32
34
  setContext("form-field-store", () => {
33
35
  return {
36
+ disabled,
34
37
  error,
35
38
  id,
36
39
  required,
@@ -44,17 +47,19 @@
44
47
 
45
48
  return helperText;
46
49
  });
50
+
51
+ let styles = $derived(formFieldVariants({ disabled, layout }));
47
52
  </script>
48
53
 
49
- <div class={formFieldVariants({ class: className, layout })}>
54
+ <div class={styles.base({ class: className })}>
50
55
  {#if label}
51
- <Label for={id} {error}>{label}{required ? " *" : ""}</Label>
56
+ <Label class={styles.label()} for={id} {error} {required}>{label}</Label>
52
57
  {/if}
53
58
 
54
59
  {@render children?.()}
55
60
 
56
61
  {#if localHelperText}
57
- <HelperText class={layout === "inline" ? "sm:col-[2]" : ""} {error}>
62
+ <HelperText class={styles.helperText()} {error}>
58
63
  {localHelperText}
59
64
  </HelperText>
60
65
  {/if}
@@ -13,7 +13,11 @@ declare const FormField: import("svelte").Component<{
13
13
  */
14
14
  class?: string;
15
15
  /**
16
- * Whether the form field has an error
16
+ * Whether the form field is disabled (passed down to the input)
17
+ */
18
+ disabled?: boolean;
19
+ /**
20
+ * Whether the form field has an error (passed down to the input)
17
21
  */
18
22
  error?: boolean;
19
23
  /**
@@ -25,7 +29,7 @@ declare const FormField: import("svelte").Component<{
25
29
  */
26
30
  helperText?: string;
27
31
  /**
28
- * The id attribute for the form field
32
+ * The id attribute for the form field (passed down to the input)
29
33
  */
30
34
  id?: string;
31
35
  /**
@@ -37,7 +41,7 @@ declare const FormField: import("svelte").Component<{
37
41
  */
38
42
  layout?: "stacked" | "inline";
39
43
  /**
40
- * Whether the form field is required
44
+ * Whether the form field is required (passed down to the input)
41
45
  */
42
46
  required?: boolean;
43
47
  }, {}, "">;
@@ -51,7 +55,11 @@ type Props = {
51
55
  */
52
56
  class?: string;
53
57
  /**
54
- * Whether the form field has an error
58
+ * Whether the form field is disabled (passed down to the input)
59
+ */
60
+ disabled?: boolean;
61
+ /**
62
+ * Whether the form field has an error (passed down to the input)
55
63
  */
56
64
  error?: boolean;
57
65
  /**
@@ -63,7 +71,7 @@ type Props = {
63
71
  */
64
72
  helperText?: string;
65
73
  /**
66
- * The id attribute for the form field
74
+ * The id attribute for the form field (passed down to the input)
67
75
  */
68
76
  id?: string;
69
77
  /**
@@ -75,7 +83,7 @@ type Props = {
75
83
  */
76
84
  layout?: "stacked" | "inline";
77
85
  /**
78
- * Whether the form field is required
86
+ * Whether the form field is required (passed down to the input)
79
87
  */
80
88
  required?: boolean;
81
89
  };
@@ -1,13 +1,49 @@
1
1
  export const formFieldVariants: import("tailwind-variants").TVReturnType<{
2
+ disabled: {
3
+ true: {
4
+ helperText: string;
5
+ };
6
+ };
2
7
  layout: {
3
- inline: string;
8
+ inline: {
9
+ base: string;
10
+ helperText: string;
11
+ };
12
+ };
13
+ }, {
14
+ base: string;
15
+ label: string;
16
+ helperText: string;
17
+ }, undefined, {
18
+ disabled: {
19
+ true: {
20
+ helperText: string;
21
+ };
4
22
  };
5
- }, undefined, "grid gap-2", {
6
23
  layout: {
7
- inline: string;
24
+ inline: {
25
+ base: string;
26
+ helperText: string;
27
+ };
28
+ };
29
+ }, {
30
+ base: string;
31
+ label: string;
32
+ helperText: string;
33
+ }, import("tailwind-variants").TVReturnType<{
34
+ disabled: {
35
+ true: {
36
+ helperText: string;
37
+ };
8
38
  };
9
- }, undefined, import("tailwind-variants").TVReturnType<{
10
39
  layout: {
11
- inline: string;
40
+ inline: {
41
+ base: string;
42
+ helperText: string;
43
+ };
12
44
  };
13
- }, undefined, "grid gap-2", unknown, unknown, undefined>>;
45
+ }, {
46
+ base: string;
47
+ label: string;
48
+ helperText: string;
49
+ }, undefined, unknown, unknown, undefined>>;
@@ -1,10 +1,22 @@
1
1
  import { tv } from "tailwind-variants";
2
2
 
3
3
  const formFieldVariants = tv({
4
- base: "grid gap-2",
4
+ slots: {
5
+ base: "grid gap-2",
6
+ label: "",
7
+ helperText: "-mt-1 ml-4",
8
+ },
5
9
  variants: {
10
+ disabled: {
11
+ true: {
12
+ helperText: "opacity-40",
13
+ },
14
+ },
6
15
  layout: {
7
- inline: "items-center sm:grid-cols-[minmax(120px,auto)_1fr]",
16
+ inline: {
17
+ base: "items-center sm:grid-cols-[minmax(120px,auto)_1fr]",
18
+ helperText: "sm:col-2",
19
+ },
8
20
  },
9
21
  },
10
22
  });
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import { selectorCardVariants } from "./selectorCard.variants.js";
3
- import { Switch, Radio, Label } from "../../../index.js";
3
+ import { Switch, Radio, Label, utils } from "../../../index.js";
4
4
 
5
5
  /**
6
6
  * @typedef {Object} Props
@@ -26,7 +26,7 @@
26
26
  error = false,
27
27
  errorText = "",
28
28
  helperText = "",
29
- id = "",
29
+ id = utils.generateId(),
30
30
  label = "",
31
31
  name,
32
32
  required = false,
@@ -6,6 +6,7 @@
6
6
  toggleGroupVariants,
7
7
  toggleGroupTabVariants,
8
8
  } from "./toggleGroup.variants.js";
9
+ import { XScroll } from "../../../index.js";
9
10
 
10
11
  /**
11
12
  * @typedef {Object} Props
@@ -28,7 +29,7 @@
28
29
  children,
29
30
  class: className = "",
30
31
  size = "medium",
31
- value,
32
+ value = $bindable(),
32
33
  variant = "default",
33
34
  } = $props();
34
35
 
@@ -48,15 +49,17 @@
48
49
  };
49
50
  });
50
51
 
51
- let stylesByVariant = $derived.by(() => {
52
+ let styles = $derived.by(() => {
52
53
  if (variant === "tabs") {
53
- return toggleGroupTabVariants({ appearance, class: className, size, variant });
54
+ return toggleGroupTabVariants();
54
55
  }
55
56
 
56
- return toggleGroupVariants({ appearance, class: className, size, variant });
57
+ return toggleGroupVariants({ appearance, size, variant });
57
58
  });
58
59
  </script>
59
60
 
60
- <div bind:this={toggleGroupEl} class={stylesByVariant} role="tablist">
61
- {@render children?.()}
62
- </div>
61
+ <XScroll class={styles.base({ class: className })}>
62
+ <div bind:this={toggleGroupEl} class={styles.tabs()} role="tablist">
63
+ {@render children?.()}
64
+ </div>
65
+ </XScroll>
@@ -28,7 +28,7 @@ declare const ToggleGroup: import("svelte").Component<{
28
28
  * The variant of the toggle group
29
29
  */
30
30
  variant?: "default" | "tabs";
31
- }, {}, "">;
31
+ }, {}, "value">;
32
32
  type Props = {
33
33
  /**
34
34
  * The appearance variant of the component
@@ -4,32 +4,70 @@ export const toggleGroupVariants: import("tailwind-variants").TVReturnType<{
4
4
  raised: string;
5
5
  };
6
6
  size: {
7
- small: string;
8
- medium: string;
7
+ small: {
8
+ tabs: string;
9
+ };
10
+ medium: {
11
+ tabs: string;
12
+ };
9
13
  };
10
- }, undefined, "flex gap-1 rounded-sm", {
14
+ }, {
15
+ base: string;
16
+ tabs: string;
17
+ }, undefined, {
11
18
  appearance: {
12
19
  default: string;
13
20
  raised: string;
14
21
  };
15
22
  size: {
16
- small: string;
17
- medium: string;
23
+ small: {
24
+ tabs: string;
25
+ };
26
+ medium: {
27
+ tabs: string;
28
+ };
18
29
  };
19
- }, undefined, import("tailwind-variants").TVReturnType<{
30
+ }, {
31
+ base: string;
32
+ tabs: string;
33
+ }, import("tailwind-variants").TVReturnType<{
20
34
  appearance: {
21
35
  default: string;
22
36
  raised: string;
23
37
  };
24
38
  size: {
25
- small: string;
26
- medium: string;
39
+ small: {
40
+ tabs: string;
41
+ };
42
+ medium: {
43
+ tabs: string;
44
+ };
45
+ };
46
+ }, {
47
+ base: string;
48
+ tabs: string;
49
+ }, undefined, unknown, unknown, undefined>>;
50
+ export const toggleGroupTabVariants: import("tailwind-variants").TVReturnType<{
51
+ [key: string]: {
52
+ [key: string]: import("tailwind-variants").ClassValue | {
53
+ base?: import("tailwind-variants").ClassValue;
54
+ tabs?: import("tailwind-variants").ClassValue;
55
+ };
27
56
  };
28
- }, undefined, "flex gap-1 rounded-sm", unknown, unknown, undefined>>;
29
- export const toggleGroupTabVariants: import("tailwind-variants").TVReturnType<{} | {
57
+ } | {
30
58
  [x: string]: {
31
59
  [x: string]: import("tailwind-variants").ClassValue | {
32
60
  base?: import("tailwind-variants").ClassValue;
61
+ tabs?: import("tailwind-variants").ClassValue;
33
62
  };
34
63
  };
35
- }, undefined, "flex h-10 gap-5 border-b border-b-neutral-500", any, undefined, import("tailwind-variants").TVReturnType<any, undefined, "flex h-10 gap-5 border-b border-b-neutral-500", unknown, unknown, undefined>>;
64
+ }, {
65
+ base: string;
66
+ tabs: string;
67
+ }, undefined, any, {
68
+ base: string;
69
+ tabs: string;
70
+ }, import("tailwind-variants").TVReturnType<any, {
71
+ base: string;
72
+ tabs: string;
73
+ }, undefined, unknown, unknown, undefined>>;
@@ -1,21 +1,31 @@
1
1
  import { tv } from "tailwind-variants";
2
2
 
3
3
  const toggleGroupVariants = tv({
4
- base: "flex gap-1 rounded-sm",
4
+ slots: {
5
+ base: "overflow-hidden rounded-sm bg-current",
6
+ tabs: "flex gap-1",
7
+ },
5
8
  variants: {
6
9
  appearance: {
7
- default: "bg-neutral-100 dark:bg-neutral-900",
8
- raised: "bg-neutral-300 dark:bg-neutral-700",
10
+ default: "text-neutral-100 dark:text-neutral-900",
11
+ raised: "text-neutral-300 dark:text-neutral-700",
9
12
  },
10
13
  size: {
11
- small: "h-6 p-0.5",
12
- medium: "h-10 p-1",
14
+ small: {
15
+ tabs: "h-6 p-0.5",
16
+ },
17
+ medium: {
18
+ tabs: "h-10 p-1",
19
+ },
13
20
  },
14
21
  },
15
22
  });
16
23
 
17
24
  const toggleGroupTabVariants = tv({
18
- base: "flex h-10 gap-5 border-b border-b-neutral-500",
25
+ slots: {
26
+ base: "",
27
+ tabs: "flex h-10 gap-5 border-b border-b-neutral-500",
28
+ },
19
29
  });
20
30
 
21
31
  export { toggleGroupVariants, toggleGroupTabVariants };
package/dist/index.d.ts CHANGED
@@ -16,6 +16,7 @@ export { default as Select } from "./components/atoms/select/Select.svelte";
16
16
  export { default as Spinner } from "./components/atoms/feedback/spinner/Spinner.svelte";
17
17
  export { default as Switch } from "./components/atoms/switch/Switch.svelte";
18
18
  export { default as Textarea } from "./components/atoms/textarea/Textarea.svelte";
19
+ export { default as XScroll } from "./components/atoms/utils/xScroll/XScroll.svelte";
19
20
  export * as ColorSwatch from "./components/molecules/pickers/colorSwatch/index.js";
20
21
  export { default as FormActions } from "./components/molecules/formActions/formActions.svelte";
21
22
  export { default as FormField } from "./components/molecules/formField/FormField.svelte";
package/dist/index.js CHANGED
@@ -21,6 +21,7 @@ export { default as Select } from "./components/atoms/select/Select.svelte";
21
21
  export { default as Spinner } from "./components/atoms/feedback/spinner/Spinner.svelte";
22
22
  export { default as Switch } from "./components/atoms/switch/Switch.svelte";
23
23
  export { default as Textarea } from "./components/atoms/textarea/Textarea.svelte";
24
+ export { default as XScroll } from "./components/atoms/utils/xScroll/XScroll.svelte";
24
25
 
25
26
  /**
26
27
  * Molecules
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@websline/system-components",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -26,17 +26,17 @@
26
26
  }
27
27
  },
28
28
  "dependencies": {
29
- "@tiptap/core": "^3.9.0",
30
- "@tiptap/extension-color": "^3.9.0",
31
- "@tiptap/extension-highlight": "^3.9.0",
32
- "@tiptap/extension-placeholder": "^3.9.0",
33
- "@tiptap/extension-text-align": "^3.9.0",
34
- "@tiptap/extension-text-style": "^3.9.0",
35
- "@tiptap/pm": "^3.9.0",
36
- "@tiptap/starter-kit": "^3.9.0",
37
- "bits-ui": "^2.14.1",
29
+ "@tiptap/core": "^3.10.2",
30
+ "@tiptap/extension-color": "^3.10.2",
31
+ "@tiptap/extension-highlight": "^3.10.2",
32
+ "@tiptap/extension-placeholder": "^3.10.2",
33
+ "@tiptap/extension-text-align": "^3.10.2",
34
+ "@tiptap/extension-text-style": "^3.10.2",
35
+ "@tiptap/pm": "^3.10.2",
36
+ "@tiptap/starter-kit": "^3.10.2",
37
+ "bits-ui": "^2.14.2",
38
38
  "dompurify": "^3.3.0",
39
- "tailwind-merge": "3.3.1",
39
+ "tailwind-merge": "^3.4.0",
40
40
  "tailwind-variants": "^3.1.1",
41
41
  "uuid": "^13.0.0"
42
42
  },
@@ -44,37 +44,37 @@
44
44
  "svelte": "^5.38.7"
45
45
  },
46
46
  "devDependencies": {
47
- "@eslint/compat": "^1.4.0",
48
- "@eslint/js": "^9.38.0",
49
- "@storybook/addon-a11y": "^10.0.0",
50
- "@storybook/addon-docs": "^10.0.0",
47
+ "@eslint/compat": "^2.0.0",
48
+ "@eslint/js": "^9.39.1",
49
+ "@storybook/addon-a11y": "^10.0.5",
50
+ "@storybook/addon-docs": "^10.0.5",
51
51
  "@storybook/addon-svelte-csf": "^5.0.10",
52
- "@storybook/sveltekit": "^10.0.0",
52
+ "@storybook/sveltekit": "^10.0.5",
53
53
  "@sveltejs/adapter-auto": "^7.0.0",
54
- "@sveltejs/kit": "^2.48.2",
54
+ "@sveltejs/kit": "^2.48.4",
55
55
  "@sveltejs/package": "^2.5.4",
56
56
  "@sveltejs/vite-plugin-svelte": "^6.2.1",
57
57
  "@tailwindcss/forms": "^0.5.10",
58
58
  "@tailwindcss/typography": "^0.5.19",
59
- "@tailwindcss/vite": "^4.1.16",
60
- "@types/node": "^24.9.2",
61
- "@vitest/browser": "^4.0.4",
62
- "eslint": "^9.38.0",
59
+ "@tailwindcss/vite": "^4.1.17",
60
+ "@types/node": "^24.10.0",
61
+ "@vitest/browser": "^4.0.7",
62
+ "eslint": "^9.39.1",
63
63
  "eslint-config-prettier": "^10.1.8",
64
- "eslint-plugin-storybook": "^10.0.0",
65
- "eslint-plugin-svelte": "^3.12.5",
66
- "globals": "^16.4.0",
64
+ "eslint-plugin-storybook": "^10.0.5",
65
+ "eslint-plugin-svelte": "^3.13.0",
66
+ "globals": "^16.5.0",
67
67
  "playwright": "^1.56.1",
68
68
  "prettier": "^3.6.2",
69
69
  "prettier-plugin-svelte": "^3.4.0",
70
70
  "prettier-plugin-tailwindcss": "^0.7.1",
71
71
  "publint": "^0.3.15",
72
- "storybook": "^10.0.0",
73
- "svelte": "^5.42.3",
74
- "tailwindcss": "^4.1.16",
72
+ "storybook": "^10.0.5",
73
+ "svelte": "^5.43.4",
74
+ "tailwindcss": "^4.1.17",
75
75
  "typescript": "^5.9.3",
76
- "vite": "^7.1.12",
77
- "vitest": "^4.0.4",
76
+ "vite": "^7.2.2",
77
+ "vitest": "^4.0.7",
78
78
  "vitest-browser-svelte": "^2.0.1"
79
79
  },
80
80
  "keywords": [