ui-svelte 0.1.0 → 0.2.1

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 SappsJs
3
+ Copyright (c) 2025 UiSvelte
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **A modern, accessible UI component library built for Svelte 5**
4
4
 
5
- SappsUI is a comprehensive UI component library designed to leverage Svelte 5's latest features. Build beautiful, accessible interfaces with minimal configuration and maximum developer experience.
5
+ Ui Svelte is a comprehensive UI component library designed to leverage Svelte 5's latest features. Build beautiful, accessible interfaces with minimal configuration and maximum developer experience.
6
6
 
7
7
  ---
8
8
 
@@ -62,7 +62,7 @@ Optimized bundle size with tree-shaking support. Only import what you need for b
62
62
 
63
63
  ```bash
64
64
  # or
65
- bun add sappsui
65
+ bun add ui-svelte
66
66
  ```
67
67
 
68
68
  ---
@@ -71,13 +71,13 @@ bun add sappsui
71
71
 
72
72
  ```svelte
73
73
  <script lang="ts">
74
- import { Button, Card, TextField } from 'sappsui';
74
+ import { Button, Card, TextField } from 'ui-svelte';
75
75
 
76
76
  let name = $state('');
77
77
  </script>
78
78
 
79
79
  <Card>
80
- <h2>Welcome to SappsUI</h2>
80
+ <h2>Welcome to Ui Svelte</h2>
81
81
 
82
82
  <TextField name="username" label="Your Name" placeholder="Enter your name..." bind:value={name} />
83
83
 
@@ -109,9 +109,9 @@ SappsUI includes a comprehensive set of components for building modern web appli
109
109
 
110
110
  ## 🌟 Support
111
111
 
112
- If you find SappsUI helpful, please consider giving it a star on GitHub! Your support helps us continue improving the library.
112
+ If you find UiSvelte helpful, please consider giving it a star on GitHub! Your support helps us continue improving the library.
113
113
 
114
- For questions, issues, or feature requests, please visit our [GitHub Issues](https://github.com/sappsdev/sappsui_svelte/issues) page.
114
+ For questions, issues, or feature requests, please visit our [GitHub Issues](https://github.com/sappsdev/ui-svelte/issues) page.
115
115
 
116
116
  ---
117
117
 
@@ -9,7 +9,7 @@
9
9
  variant?:
10
10
  | 'primary'
11
11
  | 'secondary'
12
- | 'soft'
12
+ | 'muted'
13
13
  | 'outlined'
14
14
  | 'ghost'
15
15
  | 'success'
@@ -176,7 +176,7 @@
176
176
  <div class={baseClasses}>
177
177
  <audio bind:this={audio} {src}></audio>
178
178
 
179
- <Button onclick={togglePlay} size="md" variant="ghost">
179
+ <Button onclick={togglePlay} size="md" {variant}>
180
180
  {#if isPlaying}
181
181
  <Icon icon={Pause24RegularIcon} />
182
182
  {:else}
@@ -1,7 +1,7 @@
1
1
  type Props = {
2
2
  class?: string;
3
3
  src: string;
4
- variant?: 'primary' | 'secondary' | 'soft' | 'outlined' | 'ghost' | 'success' | 'info' | 'danger' | 'warning';
4
+ variant?: 'primary' | 'secondary' | 'muted' | 'outlined' | 'ghost' | 'success' | 'info' | 'danger' | 'warning';
5
5
  };
6
6
  declare const Audio: import("svelte").Component<Props, {}, "">;
7
7
  type Audio = ReturnType<typeof Audio>;
@@ -110,7 +110,6 @@
110
110
  visualize();
111
111
  } catch (error) {
112
112
  console.error('Error accessing microphone:', error);
113
- alert('No se pudo acceder al micrófono');
114
113
  }
115
114
  }
116
115
 
@@ -135,11 +134,8 @@
135
134
  if (!response.ok) {
136
135
  throw new Error(`Upload failed: ${response.statusText}`);
137
136
  }
138
-
139
- console.log('Audio uploaded successfully');
140
137
  } catch (error) {
141
138
  console.error('Error uploading audio:', error);
142
- alert('Error al subir el audio');
143
139
  } finally {
144
140
  isUploading = false;
145
141
  }
@@ -354,7 +350,7 @@
354
350
 
355
351
  <div class={baseClasses}>
356
352
  {#if isReviewing}
357
- <Button onclick={togglePlayback} size="md" variant="ghost">
353
+ <Button onclick={togglePlayback} size="md" {variant}>
358
354
  {#if isPlaying}
359
355
  <Icon icon={Pause24RegularIcon} />
360
356
  {:else}
@@ -376,18 +372,18 @@
376
372
  <span class="media-time">{formatTime(recordingTime)}</span>
377
373
 
378
374
  <div class="flex gap-2">
379
- <Button onclick={discardRecording} size="md" variant="ghost">
375
+ <Button onclick={discardRecording} size="md" {variant}>
380
376
  <Icon icon={Delete24RegularIcon} />
381
377
  </Button>
382
- <Button onclick={continueRecording} size="md" variant="ghost">
378
+ <Button onclick={continueRecording} size="md" {variant}>
383
379
  <Icon icon={Record24RegularIcon} />
384
380
  </Button>
385
- <Button onclick={confirmRecording} size="md" variant="ghost">
381
+ <Button onclick={confirmRecording} size="md" {variant}>
386
382
  <Icon icon={Checkmark24RegularIcon} />
387
383
  </Button>
388
384
  </div>
389
385
  {:else if !isRecording}
390
- <Button onclick={startRecording} size="md" variant="ghost">
386
+ <Button onclick={startRecording} size="md" {variant}>
391
387
  <Icon icon={Record24RegularIcon} />
392
388
  </Button>
393
389
 
@@ -401,7 +397,7 @@
401
397
 
402
398
  <span class="media-time">{formatTime(recordingTime)}</span>
403
399
  {:else}
404
- <Button onclick={handleToggleRecording} size="md" variant="ghost">
400
+ <Button onclick={handleToggleRecording} size="md" {variant}>
405
401
  {#if isPaused}
406
402
  <Icon icon={Play24RegularIcon} />
407
403
  {:else}
@@ -423,7 +419,7 @@
423
419
 
424
420
  <span class="media-time">{formatTime(recordingTime)}</span>
425
421
 
426
- <Button onclick={stopRecording} size="md" variant="ghost" isLoading={isUploading}>
422
+ <Button onclick={stopRecording} size="md" {variant} isLoading={isUploading}>
427
423
  <Icon icon={RecordStop24RegularIcon} />
428
424
  </Button>
429
425
  {/if}
package/dist/css/base.css CHANGED
@@ -1,6 +1,6 @@
1
1
  @layer base {
2
2
  body {
3
- @apply h-dvh flex flex-col;
3
+ @apply h-dvh flex flex-col relative;
4
4
  @apply bg-background text-on-background;
5
5
  }
6
6
 
@@ -1,12 +1,14 @@
1
1
  <script lang="ts">
2
- import { Avatar } from '../index.js';
2
+ import { Avatar, Icon } from '../index.js';
3
3
  import { cn } from '../utils/class-names.js';
4
4
  import type { Snippet } from 'svelte';
5
+ import type { IconData } from './Icon.svelte';
5
6
 
6
7
  type Props = {
7
8
  id?: string | number;
8
9
  label?: string;
9
10
  description?: string;
11
+ icon?: IconData;
10
12
  src?: string;
11
13
  variant?: 'ghost' | 'outlined' | 'surface' | 'primary' | 'secondary' | 'muted';
12
14
  size?: 'sm' | 'md' | 'lg';
@@ -29,6 +31,7 @@
29
31
  label,
30
32
  description,
31
33
  src,
34
+ icon,
32
35
  variant = 'ghost',
33
36
  size = 'md',
34
37
  status,
@@ -88,6 +91,9 @@
88
91
  </script>
89
92
 
90
93
  {#snippet itemContent()}
94
+ {#if icon}
95
+ <Icon {icon} />
96
+ {/if}
91
97
  {#if src}
92
98
  <Avatar {src} {status} size={avatarSizes[size]} variant="transparent" />
93
99
  {/if}
@@ -1,8 +1,10 @@
1
1
  import type { Snippet } from 'svelte';
2
+ import type { IconData } from './Icon.svelte';
2
3
  type Props = {
3
4
  id?: string | number;
4
5
  label?: string;
5
6
  description?: string;
7
+ icon?: IconData;
6
8
  src?: string;
7
9
  variant?: 'ghost' | 'outlined' | 'surface' | 'primary' | 'secondary' | 'muted';
8
10
  size?: 'sm' | 'md' | 'lg';
@@ -50,14 +50,22 @@
50
50
  };
51
51
  </script>
52
52
 
53
- <div class={cn('section', variantClasses[variant], isSolid && 'is-solid', className)}>
53
+ <div
54
+ class={cn(
55
+ 'section',
56
+ variantClasses[variant],
57
+ isSolid && 'is-solid',
58
+ isBoxed && 'boxed',
59
+ className
60
+ )}
61
+ >
54
62
  {#if cover}
55
63
  <img src={cover} alt="cover" class={cn('section-cover', coverClass)} />
56
64
  {/if}
57
65
  {#if hasOverlay}
58
66
  <div class={cn('section-overlay', overlayClass)}></div>
59
67
  {/if}
60
- <div class={cn('section-body', isBoxed && 'boxed', bodyClass)}>
68
+ <div class={cn('section-body', bodyClass)}>
61
69
  {@render children()}
62
70
  </div>
63
71
  </div>
@@ -1,7 +1,7 @@
1
1
  @layer components {
2
2
  .card {
3
3
  @apply relative flex flex-col rounded-ui overflow-hidden;
4
- @apply transition-colors duration-300 ease-in-out;
4
+ @apply transition-all duration-300 ease-in-out;
5
5
 
6
6
  &:has(> .card-cover) {
7
7
  @apply bg-transparent! text-white! text-shadow-sm! z-0;
@@ -17,6 +17,10 @@
17
17
  .item.is-sm {
18
18
  @apply p-2 gap-2;
19
19
 
20
+ .icon {
21
+ @apply w-4 h-4;
22
+ }
23
+
20
24
  .item-label {
21
25
  @apply text-sm;
22
26
  }
@@ -29,6 +33,10 @@
29
33
  .item.is-md {
30
34
  @apply p-3 gap-3;
31
35
 
36
+ .icon {
37
+ @apply w-5 h-5;
38
+ }
39
+
32
40
  .item-label {
33
41
  @apply text-base;
34
42
  }
@@ -41,6 +49,10 @@
41
49
  .item.is-lg {
42
50
  @apply p-4 gap-4;
43
51
 
52
+ .icon {
53
+ @apply w-6 h-6;
54
+ }
55
+
44
56
  .item-label {
45
57
  @apply text-lg;
46
58
  }
@@ -1,4 +1,6 @@
1
1
  <script lang="ts">
2
+ import { Icon } from '../index.js';
3
+ import type { IconData } from '../types.js';
2
4
  import { cn } from '../utils/class-names.js';
3
5
  import type { Snippet } from 'svelte';
4
6
  import type { HTMLInputAttributes } from 'svelte/elements';
@@ -11,8 +13,10 @@
11
13
  type?: 'text' | 'password' | 'email' | 'number' | 'tel' | 'url';
12
14
  class?: string;
13
15
  controlClass?: string;
14
- prefix?: Snippet;
15
- suffix?: Snippet;
16
+ startIcon?: IconData;
17
+ endIcon?: IconData;
18
+ startText?: string;
19
+ endText?: string;
16
20
  onchange?: (value: unknown) => void;
17
21
  oninput?: (value: unknown) => void;
18
22
  variant?: 'primary' | 'secondary' | 'muted' | 'outlined' | 'line';
@@ -39,8 +43,10 @@
39
43
  type = 'text',
40
44
  class: className,
41
45
  controlClass,
42
- prefix,
43
- suffix,
46
+ startIcon,
47
+ endIcon,
48
+ startText,
49
+ endText,
44
50
  onchange,
45
51
  oninput,
46
52
  variant = 'outlined',
@@ -119,7 +125,13 @@
119
125
  </span>
120
126
  {/if}
121
127
 
122
- {@render prefix?.()}
128
+ {#if startIcon}
129
+ <Icon icon={startIcon} class={iconClasses} />
130
+ {/if}
131
+
132
+ {#if startText}
133
+ <span class={textClasses}>{startText}</span>
134
+ {/if}
123
135
 
124
136
  <input
125
137
  {type}
@@ -143,7 +155,13 @@
143
155
  onfocusout={() => (isFocused = false)}
144
156
  />
145
157
 
146
- {@render suffix?.()}
158
+ {#if endText}
159
+ <span class={textClasses}>{endText}</span>
160
+ {/if}
161
+
162
+ {#if endIcon}
163
+ <Icon icon={endIcon} class={iconClasses} />
164
+ {/if}
147
165
  </label>
148
166
 
149
167
  {#if errorText || helpText}
@@ -1,4 +1,4 @@
1
- import type { Snippet } from 'svelte';
1
+ import type { IconData } from '../types.js';
2
2
  import type { HTMLInputAttributes } from 'svelte/elements';
3
3
  type Props = {
4
4
  el?: HTMLInputElement;
@@ -8,8 +8,10 @@ type Props = {
8
8
  type?: 'text' | 'password' | 'email' | 'number' | 'tel' | 'url';
9
9
  class?: string;
10
10
  controlClass?: string;
11
- prefix?: Snippet;
12
- suffix?: Snippet;
11
+ startIcon?: IconData;
12
+ endIcon?: IconData;
13
+ startText?: string;
14
+ endText?: string;
13
15
  onchange?: (value: unknown) => void;
14
16
  oninput?: (value: unknown) => void;
15
17
  variant?: 'primary' | 'secondary' | 'muted' | 'outlined' | 'line';
package/dist/index.css CHANGED
@@ -71,8 +71,8 @@
71
71
  --color-primary: var(--primary, oklch(54.6% 0.245 262.881)); /* blue-600 */
72
72
  --color-on-primary: var(--on-primary, oklch(93.2% 0.032 255.585)); /* blue-100 */
73
73
 
74
- --color-secondary: var(--secondary, oklch(60% 0.118 184.704)); /* teal-600 */
75
- --color-on-secondary: var(--on-secondary, oklch(95.3% 0.051 180.801)); /* teal-100 */
74
+ --color-secondary: var(--secondary, oklch(0.592 0.249 0.584)); /* pink-600 */
75
+ --color-on-secondary: var(--on-secondary, oklch(0.948 0.028 342.258)); /* pink-100 */
76
76
 
77
77
  --color-muted: var(--muted, oklch(87.2% 0.01 258.338)); /* gray-300 */
78
78
  --color-on-muted: var(--on-muted, oklch(27.8% 0.033 256.848)); /* gray-700 */
@@ -15,6 +15,8 @@
15
15
  isBlurred?: boolean;
16
16
  isBordered?: boolean;
17
17
  hideOnScroll?: boolean;
18
+ isSticky?: boolean;
19
+ isBoxed?: boolean;
18
20
  };
19
21
 
20
22
  const {
@@ -28,6 +30,8 @@
28
30
  endClass,
29
31
  isBordered,
30
32
  isBlurred,
33
+ isSticky,
34
+ isBoxed,
31
35
  hideOnScroll
32
36
  }: Props = $props();
33
37
 
@@ -48,14 +52,18 @@
48
52
  });
49
53
 
50
54
  $effect(() => {
51
- if (hideOnScroll && scroll.scrollY > headerHeight) {
55
+ if (!hideOnScroll) {
56
+ return;
57
+ }
58
+
59
+ if (scroll.scrollY > headerHeight) {
52
60
  if (scroll.scrollY > lastScrollY) {
53
61
  isHidden = true;
54
62
  } else if (scroll.scrollY < lastScrollY) {
55
63
  isHidden = false;
56
64
  }
57
65
  lastScrollY = scroll.scrollY;
58
- } else if (hideOnScroll) {
66
+ } else {
59
67
  isHidden = false;
60
68
  lastScrollY = scroll.scrollY;
61
69
  }
@@ -71,10 +79,11 @@
71
79
  isBordered && 'is-bordered',
72
80
  shouldBlur && 'is-blurred',
73
81
  isHidden && 'is-hidden',
82
+ isSticky && 'is-sticky',
74
83
  className
75
84
  )}
76
85
  >
77
- <div class={cn('appbar-content', contentClass)}>
86
+ <div class={cn('appbar-content', isBoxed && 'boxed', contentClass)}>
78
87
  {#if start}
79
88
  <div class={cn('appbar-start', startClass)}>
80
89
  {@render start()}
@@ -11,6 +11,8 @@ type Props = {
11
11
  isBlurred?: boolean;
12
12
  isBordered?: boolean;
13
13
  hideOnScroll?: boolean;
14
+ isSticky?: boolean;
15
+ isBoxed?: boolean;
14
16
  };
15
17
  declare const AppBar: import("svelte").Component<Props, {}, "">;
16
18
  type AppBar = ReturnType<typeof AppBar>;
@@ -14,6 +14,7 @@
14
14
  endClass?: string;
15
15
  isBlurred?: boolean;
16
16
  isBordered?: boolean;
17
+ isBoxed?: boolean;
17
18
  hideOnScroll?: boolean;
18
19
  };
19
20
 
@@ -28,6 +29,7 @@
28
29
  endClass,
29
30
  isBordered,
30
31
  isBlurred,
32
+ isBoxed,
31
33
  hideOnScroll
32
34
  }: Props = $props();
33
35
 
@@ -74,7 +76,7 @@
74
76
  className
75
77
  )}
76
78
  >
77
- <div class={cn('footer-content', contentClass)}>
79
+ <div class={cn('footer-content', isBoxed && 'boxed', contentClass)}>
78
80
  {#if start}
79
81
  <div class={cn('footer-start', startClass)}>
80
82
  {@render start()}
@@ -10,6 +10,7 @@ type Props = {
10
10
  endClass?: string;
11
11
  isBlurred?: boolean;
12
12
  isBordered?: boolean;
13
+ isBoxed?: boolean;
13
14
  hideOnScroll?: boolean;
14
15
  };
15
16
  declare const Footer: import("svelte").Component<Props, {}, "">;
@@ -12,6 +12,7 @@
12
12
  mainClass?: string;
13
13
  startClass?: string;
14
14
  endClass?: string;
15
+ isBoxed?: boolean;
15
16
  };
16
17
 
17
18
  const {
@@ -23,15 +24,18 @@
23
24
  bodyClass,
24
25
  mainClass,
25
26
  startClass,
26
- endClass
27
+ endClass,
28
+ isBoxed
27
29
  }: Props = $props();
28
30
  </script>
29
31
 
30
32
  {@render appBar?.()}
31
- <div class={cn('scaffold-body', bodyClass)}>
33
+ <div class={cn('scaffold-body', isBoxed && 'boxed', bodyClass)}>
32
34
  {#if start}
33
35
  <aside class={cn('scaffold-start', startClass)}>
34
- {@render start()}
36
+ <div class={cn('scaffold-content')}>
37
+ {@render start()}
38
+ </div>
35
39
  </aside>
36
40
  {/if}
37
41
  <div class={cn('scaffold-main', mainClass)}>
@@ -39,7 +43,9 @@
39
43
  </div>
40
44
  {#if end}
41
45
  <aside class={cn('scaffold-end', endClass)}>
42
- {@render end()}
46
+ <div class={cn('scaffold-content')}>
47
+ {@render end()}
48
+ </div>
43
49
  </aside>
44
50
  {/if}
45
51
  </div>
@@ -9,6 +9,7 @@ type Props = {
9
9
  mainClass?: string;
10
10
  startClass?: string;
11
11
  endClass?: string;
12
+ isBoxed?: boolean;
12
13
  };
13
14
  declare const Scaffold: import("svelte").Component<Props, {}, "">;
14
15
  type Scaffold = ReturnType<typeof Scaffold>;
@@ -1,10 +1,13 @@
1
1
  @layer components {
2
2
  .appbar {
3
- @apply w-full fixed top-0 z-30 bg-background;
4
- @apply transition-all duration-300 ease-in-out;
3
+ @apply w-full z-30;
4
+
5
+ &.is-sticky {
6
+ @apply fixed top-0;
7
+ }
5
8
 
6
9
  &.is-blurred {
7
- @apply backdrop-blur-lg bg-transparent;
10
+ @apply backdrop-blur-lg;
8
11
  }
9
12
 
10
13
  &.is-bordered {
@@ -20,15 +23,15 @@
20
23
  @apply w-full px-2 h-full min-h-12;
21
24
 
22
25
  .appbar-start {
23
- @apply flex flex-nowrap justify-start items-center p-2 md:p-3 gap-2 md:gap-3 relative;
26
+ @apply flex flex-nowrap justify-start items-center p-3 gap-3 relative;
24
27
  }
25
28
 
26
29
  .appbar-center {
27
- @apply flex flex-1 flex-nowrap justify-center items-center p-2 md:p-3 gap-2 md:gap-3 relative;
30
+ @apply flex flex-1 flex-nowrap justify-center items-center p-3 gap-3 relative;
28
31
  }
29
32
 
30
33
  .appbar-end {
31
- @apply flex flex-nowrap justify-end items-center p-2 md:p-3 gap-2 md:gap-3 relative;
34
+ @apply flex flex-nowrap justify-end items-center p-3 gap-3 relative;
32
35
  }
33
36
  }
34
37
  }
@@ -1,15 +1,21 @@
1
1
  @layer components {
2
2
  .scaffold-body {
3
3
  @apply flex h-full w-full relative;
4
- @apply bg-background text-on-background;
5
4
  .scaffold-main {
6
5
  @apply relative flex-1 flex flex-col min-w-0;
7
6
  }
8
7
  .scaffold-start {
9
- @apply fixed z-10;
8
+ @apply relative;
10
9
  }
11
10
  .scaffold-end {
12
- @apply fixed right-0 z-10;
11
+ @apply relative;
12
+ }
13
+
14
+ .scaffold-start,
15
+ .scaffold-end {
16
+ .scaffold-content {
17
+ @apply fixed w-fit h-full;
18
+ }
13
19
  }
14
20
  }
15
21
  }
@@ -1,17 +1,17 @@
1
1
  @layer components {
2
2
  .sidebar {
3
- @apply flex h-full flex-col bg-background text-on-background;
3
+ @apply flex w-fit h-full flex-col;
4
4
 
5
5
  .sidebar-header {
6
- @apply flex flex-col gap-3 p-3;
6
+ @apply relative flex flex-col gap-3 p-3;
7
7
  }
8
8
 
9
9
  .sidebar-footer {
10
- @apply flex flex-col gap-3 p-3;
10
+ @apply relative flex flex-col gap-3 p-3;
11
11
  }
12
12
 
13
13
  .sidebar-body {
14
- @apply flex min-h-0 flex-1 flex-col gap-3 p-3 overflow-auto;
14
+ @apply relative flex min-h-0 w-full flex-col gap-3 p-3 overflow-hidden hover:overflow-y-auto;
15
15
  }
16
16
  }
17
17
  }
@@ -43,13 +43,15 @@
43
43
  class: className,
44
44
  variant = 'primary',
45
45
  size = 'md',
46
- isWide = false,
47
- isCompact = false,
48
- isCollapsible = false
46
+ isWide,
47
+ isCompact,
48
+ isCollapsible
49
49
  }: Props = $props();
50
50
 
51
- let openSubmenus = $state<Record<number, boolean>>(
52
- items.reduce(
51
+ let openSubmenus = $state<Record<number, boolean>>({});
52
+
53
+ $effect(() => {
54
+ const initialState = items.reduce(
53
55
  (acc, item, index) => {
54
56
  if (item.type === 'submenu' && item.open) {
55
57
  acc[index] = true;
@@ -57,10 +59,15 @@
57
59
  return acc;
58
60
  },
59
61
  {} as Record<number, boolean>
60
- )
61
- );
62
+ );
63
+ openSubmenus = initialState;
64
+ });
65
+
66
+ let isExpanded = $state(true);
62
67
 
63
- let isExpanded = $state(!isCollapsible);
68
+ $effect(() => {
69
+ isExpanded = !isCollapsible;
70
+ });
64
71
 
65
72
  const variantClasses = {
66
73
  primary: 'sidenav-primary',
@@ -184,6 +191,9 @@
184
191
  class="sidenav-header sidenav-submenu-trigger"
185
192
  onclick={() => toggleSubmenu(index)}
186
193
  >
194
+ {#if item.icon}
195
+ <Icon icon={item.icon} />
196
+ {/if}
187
197
  {#if isExpanded || !isCollapsible}
188
198
  <div class="sidenav-header-content">
189
199
  <div class="sidenav-header-label">{item.label}</div>
@@ -79,7 +79,7 @@
79
79
 
80
80
  &.navmenu-primary {
81
81
  .navmenu-item.is-active {
82
- @apply bg-primary/10 text-primary;
82
+ @apply bg-on-primary text-primary;
83
83
 
84
84
  .navmenu-icon {
85
85
  @apply text-primary;
@@ -89,7 +89,7 @@
89
89
 
90
90
  &.navmenu-secondary {
91
91
  .navmenu-item.is-active {
92
- @apply bg-secondary/10 text-secondary;
92
+ @apply bg-on-secondary text-secondary;
93
93
 
94
94
  .navmenu-icon {
95
95
  @apply text-secondary;
@@ -29,7 +29,6 @@
29
29
 
30
30
  &.sidenav-header-link {
31
31
  @apply cursor-pointer rounded-ui outline-none;
32
- @apply transition-all duration-200;
33
32
  @apply hover:bg-muted/50;
34
33
 
35
34
  &.is-active {
@@ -51,7 +50,7 @@
51
50
  }
52
51
 
53
52
  .sidenav-item {
54
- @apply relative flex w-fit items-center gap-2 rounded-ui pl-4 pr-3 py-2;
53
+ @apply relative flex w-fit items-center gap-2 rounded-ui px-3 py-2;
55
54
  @apply cursor-pointer select-none outline-none;
56
55
  @apply hover:bg-muted;
57
56
 
@@ -102,7 +101,7 @@
102
101
 
103
102
  &.is-sm {
104
103
  .sidenav-item {
105
- @apply gap-1.5 pl-3 pr-2 py-1.5 text-xs;
104
+ @apply gap-1.5 px-2 py-1.5 text-xs;
106
105
 
107
106
  .sidenav-icon-wrapper .sidenav-icon {
108
107
  @apply h-4 w-4;
@@ -120,7 +119,7 @@
120
119
 
121
120
  &.is-md {
122
121
  .sidenav-item {
123
- @apply gap-2 pl-4 pr-3 py-2 text-sm;
122
+ @apply gap-2 px-3 py-2 text-sm;
124
123
 
125
124
  .sidenav-icon-wrapper .sidenav-icon {
126
125
  @apply h-5 w-5;
@@ -138,7 +137,7 @@
138
137
 
139
138
  &.is-lg {
140
139
  .sidenav-item {
141
- @apply gap-3 pl-5 pr-4 py-3 text-base;
140
+ @apply gap-3 px-4 py-3 text-base;
142
141
 
143
142
  .sidenav-icon-wrapper .sidenav-icon {
144
143
  @apply h-6 w-6;
@@ -227,16 +226,15 @@
227
226
 
228
227
  .sidenav-submenu-trigger {
229
228
  @apply w-full cursor-pointer rounded-ui outline-none;
230
- @apply transition-all duration-200;
231
229
  @apply hover:bg-muted/50;
232
230
  @apply justify-start;
233
231
  }
234
232
 
235
233
  .sidenav-submenu-content {
236
- @apply ml-6 flex flex-col gap-0.5 border-l border-muted pl-2;
234
+ @apply ml-5 flex flex-col gap-0.5 border-l border-muted pl-2;
237
235
 
238
236
  .sidenav-subitem {
239
- @apply text-sm pl-2;
237
+ @apply text-sm;
240
238
  }
241
239
  }
242
240
  }
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { Item } from '../index.js';
3
+ import type { IconData } from '../types.js';
3
4
  import { onMount, type Snippet } from 'svelte';
4
5
 
5
6
  type Option = {
@@ -7,6 +8,7 @@
7
8
  label: string;
8
9
  description?: string;
9
10
  src?: string;
11
+ icon?: IconData;
10
12
  href?: string;
11
13
  onclick?: (option: Option) => void;
12
14
  };
@@ -125,6 +127,7 @@
125
127
  <Item
126
128
  label={item.label}
127
129
  src={item.src}
130
+ icon={item.icon}
128
131
  description={item.description}
129
132
  id={item.id}
130
133
  href={item.href}
package/dist/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { IconData } from './display/Icon.svelte';
1
2
  export interface DatePosition {
2
3
  top: number;
3
4
  left: number;
@@ -14,62 +15,4 @@ export type BandScale = ((value: string) => number) & {
14
15
  bandwidth: () => number;
15
16
  step: () => number;
16
17
  };
17
- export interface ChartConfig {
18
- [key: string]: {
19
- label: string;
20
- color: string;
21
- icon?: string;
22
- };
23
- }
24
- export interface ChartDataPoint {
25
- [key: string]: string | number;
26
- }
27
- export interface ChartMargin {
28
- top: number;
29
- right: number;
30
- bottom: number;
31
- left: number;
32
- }
33
- export type ChartData = ChartDataPoint[];
34
- export interface ChartProps {
35
- data: ChartData;
36
- config: ChartConfig;
37
- className?: string;
38
- width?: number;
39
- height?: number;
40
- }
41
- export interface BarChartProps extends ChartProps {
42
- xKey: string;
43
- yKeys: string[];
44
- showGrid?: boolean;
45
- showAxis?: boolean;
46
- barSpacing?: number;
47
- }
48
- export interface LineChartProps extends ChartProps {
49
- xKey: string;
50
- yKeys: string[];
51
- showGrid?: boolean;
52
- showAxis?: boolean;
53
- smooth?: boolean;
54
- showDots?: boolean;
55
- }
56
- export interface PieChartProps extends ChartProps {
57
- valueKey: string;
58
- labelKey: string;
59
- showLabels?: boolean;
60
- innerRadius?: number;
61
- }
62
- export interface AreaChartProps extends ChartProps {
63
- xKey: string;
64
- yKeys: string[];
65
- showGrid?: boolean;
66
- showAxis?: boolean;
67
- smooth?: boolean;
68
- stacked?: boolean;
69
- }
70
- export interface DoughnutChartProps extends ChartProps {
71
- valueKey: string;
72
- labelKey: string;
73
- showLabels?: boolean;
74
- innerRadius?: number;
75
- }
18
+ export type { IconData };
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "ui-svelte",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "author": {
5
5
  "name": "SappsDev",
6
6
  "email": "info@sappsdev.com"
7
7
  },
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "https://github.com/sappsdev/sappsui_svelte.git"
10
+ "url": "https://github.com/sappsdev/ui-svelte.git"
11
11
  },
12
12
  "devDependencies": {
13
13
  "@sveltejs/adapter-auto": "^6.1.0",
@@ -43,7 +43,7 @@
43
43
  "!dist/**/*.test.*",
44
44
  "!dist/**/*.spec.*"
45
45
  ],
46
- "homepage": "https://svelte.sappsdev.com",
46
+ "homepage": "https://ui-svelte.sappsdev.com",
47
47
  "keywords": [
48
48
  "svelte"
49
49
  ],