@groundbrick/svelte-ui 0.1.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.
Files changed (60) hide show
  1. package/README.md +125 -0
  2. package/dist/components/Alert.svelte +335 -0
  3. package/dist/components/Alert.svelte.d.ts +24 -0
  4. package/dist/components/AutocompleteInput.svelte +356 -0
  5. package/dist/components/AutocompleteInput.svelte.d.ts +72 -0
  6. package/dist/components/Badge.svelte +185 -0
  7. package/dist/components/Badge.svelte.d.ts +20 -0
  8. package/dist/components/Button.svelte +415 -0
  9. package/dist/components/Button.svelte.d.ts +34 -0
  10. package/dist/components/Card.svelte +181 -0
  11. package/dist/components/Card.svelte.d.ts +24 -0
  12. package/dist/components/CardBody.svelte +78 -0
  13. package/dist/components/CardBody.svelte.d.ts +12 -0
  14. package/dist/components/CardFooter.svelte +81 -0
  15. package/dist/components/CardFooter.svelte.d.ts +14 -0
  16. package/dist/components/CardHeader.svelte +186 -0
  17. package/dist/components/CardHeader.svelte.d.ts +21 -0
  18. package/dist/components/Col.svelte +172 -0
  19. package/dist/components/Col.svelte.d.ts +26 -0
  20. package/dist/components/Container.svelte +118 -0
  21. package/dist/components/Container.svelte.d.ts +14 -0
  22. package/dist/components/Drawer.svelte +233 -0
  23. package/dist/components/Drawer.svelte.d.ts +13 -0
  24. package/dist/components/Dropdown.svelte +190 -0
  25. package/dist/components/Dropdown.svelte.d.ts +26 -0
  26. package/dist/components/DropdownItem.svelte +103 -0
  27. package/dist/components/DropdownItem.svelte.d.ts +22 -0
  28. package/dist/components/DurationInput.svelte +170 -0
  29. package/dist/components/DurationInput.svelte.d.ts +27 -0
  30. package/dist/components/EditableTable.svelte +647 -0
  31. package/dist/components/EditableTable.svelte.d.ts +74 -0
  32. package/dist/components/EmptyState.svelte +192 -0
  33. package/dist/components/EmptyState.svelte.d.ts +22 -0
  34. package/dist/components/FormField.svelte +260 -0
  35. package/dist/components/FormField.svelte.d.ts +68 -0
  36. package/dist/components/GridView.svelte +1022 -0
  37. package/dist/components/GridView.svelte.d.ts +38 -0
  38. package/dist/components/GridView.types.d.ts +28 -0
  39. package/dist/components/GridView.types.js +1 -0
  40. package/dist/components/LoadingSpinner.svelte +253 -0
  41. package/dist/components/LoadingSpinner.svelte.d.ts +17 -0
  42. package/dist/components/Modal.svelte +473 -0
  43. package/dist/components/Modal.svelte.d.ts +42 -0
  44. package/dist/components/PhoneInput.svelte +406 -0
  45. package/dist/components/PhoneInput.svelte.d.ts +31 -0
  46. package/dist/components/PhotoUpload.svelte +529 -0
  47. package/dist/components/PhotoUpload.svelte.d.ts +46 -0
  48. package/dist/components/Row.svelte +153 -0
  49. package/dist/components/Row.svelte.d.ts +18 -0
  50. package/dist/icons/PawPrintIcon.svelte +41 -0
  51. package/dist/icons/PawPrintIcon.svelte.d.ts +14 -0
  52. package/dist/index.d.ts +41 -0
  53. package/dist/index.js +49 -0
  54. package/dist/styles/forms.css +182 -0
  55. package/dist/styles/tokens.css +243 -0
  56. package/dist/utils/duration.d.ts +20 -0
  57. package/dist/utils/duration.js +40 -0
  58. package/dist/utils/scrollLock.d.ts +7 -0
  59. package/dist/utils/scrollLock.js +26 -0
  60. package/package.json +66 -0
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from "svelte";
2
+ interface ContainerProps {
3
+ /** Tamanho máximo do container */
4
+ size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full' | 'fluid';
5
+ /** Padding vertical */
6
+ py?: 'none' | 'sm' | 'md' | 'lg' | 'xl';
7
+ /** Conteúdo do container */
8
+ children?: Snippet;
9
+ /** Classes CSS adicionais */
10
+ class?: string;
11
+ }
12
+ declare const Container: import("svelte").Component<ContainerProps, {}, "">;
13
+ type Container = ReturnType<typeof Container>;
14
+ export default Container;
@@ -0,0 +1,233 @@
1
+ <script lang="ts">
2
+ import { onDestroy } from "svelte";
3
+ import { lockBodyScroll, unlockBodyScroll } from "../utils/scrollLock.js";
4
+ interface Props {
5
+ open: boolean;
6
+ onClose: () => void;
7
+ title?: string;
8
+ customTitle?: import('svelte').Snippet;
9
+ customHeader?: import('svelte').Snippet;
10
+ showHeader?: boolean;
11
+ size?: "default" | "large" | "xlarge";
12
+ children?: import('svelte').Snippet;
13
+ }
14
+
15
+ let {
16
+ open = false,
17
+ onClose,
18
+ title,
19
+ customTitle,
20
+ customHeader,
21
+ showHeader = true,
22
+ size = "large",
23
+ children,
24
+ }: Props = $props();
25
+
26
+ let hasScrollLock = false;
27
+
28
+ function acquireScrollLock() {
29
+ if (hasScrollLock) return;
30
+ lockBodyScroll();
31
+ hasScrollLock = true;
32
+ }
33
+
34
+ function releaseScrollLock() {
35
+ if (!hasScrollLock) return;
36
+ unlockBodyScroll();
37
+ hasScrollLock = false;
38
+ }
39
+
40
+ // Handle ESC key
41
+ function handleKeyDown(event: KeyboardEvent) {
42
+ if (event.key === "Escape" && open) {
43
+ onClose();
44
+ }
45
+ }
46
+
47
+ // Prevent body scroll when drawer is open
48
+ $effect(() => {
49
+ if (open) {
50
+ acquireScrollLock();
51
+ } else {
52
+ releaseScrollLock();
53
+ }
54
+
55
+ return () => {
56
+ releaseScrollLock();
57
+ };
58
+ });
59
+
60
+ onDestroy(() => {
61
+ releaseScrollLock();
62
+ });
63
+ </script>
64
+
65
+ <svelte:window on:keydown={handleKeyDown} />
66
+
67
+ {#if open}
68
+ <!-- Backdrop -->
69
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
70
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
71
+ <div class="drawer-backdrop" onclick={onClose}></div>
72
+
73
+ <!-- Drawer -->
74
+ <div class="drawer drawer-{size}">
75
+ {#if showHeader}
76
+ {#if customHeader}
77
+ {@render customHeader()}
78
+ {:else}
79
+ <div class="drawer-header">
80
+ {#if customTitle}
81
+ <div class="drawer-title-custom">
82
+ {@render customTitle()}
83
+ </div>
84
+ {:else if title}
85
+ <h2 class="drawer-title">{title}</h2>
86
+ {/if}
87
+ <button class="drawer-close" onclick={onClose} aria-label="Fechar">
88
+ <i class="bi bi-x-lg"></i>
89
+ </button>
90
+ </div>
91
+ {/if}
92
+ {/if}
93
+
94
+ <!-- Content -->
95
+ <div class="drawer-content">
96
+ {@render children?.()}
97
+ </div>
98
+ </div>
99
+ {/if}
100
+
101
+ <style>
102
+ /* Backdrop */
103
+ .drawer-backdrop {
104
+ position: fixed;
105
+ top: 0;
106
+ left: 0;
107
+ right: 0;
108
+ bottom: 0;
109
+ background: rgba(0, 0, 0, 0.5);
110
+ backdrop-filter: blur(4px);
111
+ z-index: 1040;
112
+ animation: fadeIn var(--transition-base);
113
+ }
114
+
115
+ @keyframes fadeIn {
116
+ from {
117
+ opacity: 0;
118
+ }
119
+ to {
120
+ opacity: 1;
121
+ }
122
+ }
123
+
124
+ /* Drawer Container */
125
+ .drawer {
126
+ position: fixed;
127
+ top: 0;
128
+ right: 0;
129
+ bottom: 0;
130
+ background: var(--color-white);
131
+ box-shadow: var(--shadow-2xl);
132
+ z-index: 1050;
133
+ display: flex;
134
+ flex-direction: column;
135
+ animation: slideInRight var(--transition-base);
136
+ }
137
+
138
+ @keyframes slideInRight {
139
+ from {
140
+ transform: translateX(100%);
141
+ }
142
+ to {
143
+ transform: translateX(0);
144
+ }
145
+ }
146
+
147
+ /* Drawer Sizes */
148
+ .drawer-default {
149
+ width: min(500px, 90vw);
150
+ }
151
+
152
+ .drawer-large {
153
+ width: min(700px, 90vw);
154
+ }
155
+
156
+ .drawer-xlarge {
157
+ width: min(900px, 95vw);
158
+ }
159
+
160
+ /* Drawer Header */
161
+ .drawer-header {
162
+ display: flex;
163
+ align-items: center;
164
+ justify-content: space-between;
165
+ padding: var(--spacing-xl) var(--spacing-xl) var(--spacing-lg);
166
+ border-bottom: var(--border-width-thin) solid var(--border-color-light);
167
+ flex-shrink: 0;
168
+ }
169
+
170
+ .drawer-header-custom {
171
+ position: absolute;
172
+ width: 100%;
173
+ }
174
+
175
+ .drawer-title {
176
+ margin: 0;
177
+ font-size: var(--font-size-2xl);
178
+ font-weight: var(--font-weight-bold);
179
+ color: var(--color-gray-900);
180
+ }
181
+
182
+ .drawer-title-custom {
183
+ flex: 1;
184
+ min-width: 0;
185
+ }
186
+
187
+ .drawer-close {
188
+ display: flex;
189
+ align-items: center;
190
+ justify-content: center;
191
+ width: 40px;
192
+ height: 40px;
193
+ border: none;
194
+ background: var(--color-gray-100);
195
+ color: var(--color-gray-600);
196
+ border-radius: var(--radius-full);
197
+ cursor: pointer;
198
+ transition: all var(--transition-fast);
199
+ flex-shrink: 0;
200
+ }
201
+
202
+ .drawer-close:hover {
203
+ background: var(--color-gray-200);
204
+ color: var(--color-gray-900);
205
+ transform: rotate(90deg);
206
+ }
207
+
208
+ .drawer-close i {
209
+ font-size: var(--font-size-lg);
210
+ }
211
+
212
+ /* Drawer Content */
213
+ .drawer-content {
214
+ flex: 1;
215
+ overflow-y: auto;
216
+ overflow-x: hidden;
217
+ }
218
+
219
+ /* Mobile Responsive */
220
+ @media (max-width: 768px) {
221
+ .drawer {
222
+ width: 100vw !important;
223
+ }
224
+
225
+ .drawer-header {
226
+ padding: var(--spacing-lg) var(--spacing-md);
227
+ }
228
+
229
+ .drawer-title {
230
+ font-size: var(--font-size-xl);
231
+ }
232
+ }
233
+ </style>
@@ -0,0 +1,13 @@
1
+ interface Props {
2
+ open: boolean;
3
+ onClose: () => void;
4
+ title?: string;
5
+ customTitle?: import('svelte').Snippet;
6
+ customHeader?: import('svelte').Snippet;
7
+ showHeader?: boolean;
8
+ size?: "default" | "large" | "xlarge";
9
+ children?: import('svelte').Snippet;
10
+ }
11
+ declare const Drawer: import("svelte").Component<Props, {}, "">;
12
+ type Drawer = ReturnType<typeof Drawer>;
13
+ export default Drawer;
@@ -0,0 +1,190 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+
4
+ interface DropdownProps {
5
+ /** Conteúdo do botão trigger */
6
+ trigger?: Snippet;
7
+ /** Conteúdo do menu dropdown */
8
+ children?: Snippet;
9
+ /** Variante do botão trigger */
10
+ variant?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'light' | 'dark' | 'outline-primary' | 'outline-secondary' | 'link' | 'ghost';
11
+ /** Tamanho do botão trigger */
12
+ size?: 'sm' | 'md' | 'lg';
13
+ /** Alinhamento do menu */
14
+ align?: 'start' | 'end';
15
+ /** Direção do dropdown */
16
+ direction?: 'down' | 'up' | 'start' | 'end';
17
+ /** Classes CSS adicionais para o wrapper */
18
+ class?: string;
19
+ /** Classes CSS adicionais para o botão */
20
+ buttonClass?: string;
21
+ /** ARIA label para acessibilidade */
22
+ ariaLabel?: string;
23
+ /** Desabilitar dropdown */
24
+ disabled?: boolean;
25
+ }
26
+
27
+ let {
28
+ trigger,
29
+ children,
30
+ variant = 'link',
31
+ size = 'sm',
32
+ align = 'end',
33
+ direction = 'down',
34
+ class: additionalClasses = '',
35
+ buttonClass = '',
36
+ ariaLabel = 'Menu de ações',
37
+ disabled = false
38
+ }: DropdownProps = $props();
39
+
40
+ // Mapear variantes para classes Bootstrap
41
+ const variantClasses: Record<string, string> = {
42
+ primary: 'btn-primary',
43
+ secondary: 'btn-secondary',
44
+ success: 'btn-success',
45
+ danger: 'btn-danger',
46
+ warning: 'btn-warning',
47
+ info: 'btn-info',
48
+ light: 'btn-light',
49
+ dark: 'btn-dark',
50
+ 'outline-primary': 'btn-outline-primary',
51
+ 'outline-secondary': 'btn-outline-secondary',
52
+ link: 'btn-link',
53
+ ghost: 'btn-ghost'
54
+ };
55
+
56
+ const sizeClasses: Record<string, string> = {
57
+ sm: 'btn-sm',
58
+ md: '',
59
+ lg: 'btn-lg'
60
+ };
61
+
62
+ const directionClasses: Record<string, string> = {
63
+ down: 'dropdown',
64
+ up: 'dropup',
65
+ start: 'dropstart',
66
+ end: 'dropend'
67
+ };
68
+
69
+ // Construir classe do botão
70
+ const btnClass = [
71
+ 'btn',
72
+ variantClasses[variant],
73
+ sizeClasses[size],
74
+ 'dropdown-toggle',
75
+ buttonClass
76
+ ].filter(Boolean).join(' ');
77
+
78
+ // Construir classe do menu
79
+ const menuClass = [
80
+ 'dropdown-menu',
81
+ align === 'end' ? 'dropdown-menu-end' : ''
82
+ ].filter(Boolean).join(' ');
83
+
84
+ // Construir classe do wrapper
85
+ const wrapperClass = [
86
+ directionClasses[direction],
87
+ additionalClasses
88
+ ].filter(Boolean).join(' ');
89
+ </script>
90
+
91
+ <div class={wrapperClass}>
92
+ <button
93
+ class={btnClass}
94
+ type="button"
95
+ data-bs-toggle="dropdown"
96
+ aria-expanded="false"
97
+ aria-label={ariaLabel}
98
+ disabled={disabled}
99
+ >
100
+ {#if trigger}
101
+ {@render trigger()}
102
+ {:else}
103
+ <i class="bi bi-three-dots-vertical"></i>
104
+ {/if}
105
+ </button>
106
+ <ul class={menuClass}>
107
+ {#if children}
108
+ {@render children()}
109
+ {/if}
110
+ </ul>
111
+ </div>
112
+
113
+ <style>
114
+ /* ============================================
115
+ DROPDOWN - AgendaPet Design System
116
+ ============================================ */
117
+
118
+ /* Variante Ghost */
119
+ .btn-ghost {
120
+ background: transparent;
121
+ border: none;
122
+ color: var(--color-text);
123
+ padding: 0.5rem 0.75rem;
124
+ border-radius: var(--radius-md);
125
+ transition: all var(--transition-fast);
126
+ }
127
+
128
+ .btn-ghost:hover:not(:disabled) {
129
+ background: var(--color-bg-surface-2);
130
+ color: var(--color-text);
131
+ }
132
+
133
+ .btn-ghost:active:not(:disabled) {
134
+ background: var(--color-gray-200);
135
+ }
136
+
137
+ /* Remove a seta do dropdown para o botão link */
138
+ .btn-link.dropdown-toggle::after {
139
+ display: none;
140
+ }
141
+
142
+ /* Ghost dropdown toggle */
143
+ .btn-ghost.dropdown-toggle::after {
144
+ display: none;
145
+ }
146
+
147
+ /* Dropdown menu styling */
148
+ :global(.dropdown-menu) {
149
+ border: 1px solid var(--color-border-subtle);
150
+ border-radius: var(--radius-lg);
151
+ box-shadow: var(--shadow-lg);
152
+ padding: 0.375rem;
153
+ min-width: 10rem;
154
+ }
155
+
156
+ :global(.dropdown-item) {
157
+ padding: 0.5rem 0.75rem;
158
+ border-radius: var(--radius-md);
159
+ color: var(--color-text);
160
+ font-size: var(--font-size-sm);
161
+ transition: all var(--transition-fast);
162
+ }
163
+
164
+ :global(.dropdown-item:hover),
165
+ :global(.dropdown-item:focus) {
166
+ background-color: var(--color-bg-surface-2);
167
+ color: var(--color-text);
168
+ }
169
+
170
+ :global(.dropdown-item.active),
171
+ :global(.dropdown-item:active) {
172
+ background-color: var(--color-primary);
173
+ color: white;
174
+ }
175
+
176
+ :global(.dropdown-item.text-danger) {
177
+ color: var(--color-danger);
178
+ }
179
+
180
+ :global(.dropdown-item.text-danger:hover),
181
+ :global(.dropdown-item.text-danger:focus) {
182
+ background-color: var(--color-danger-bg);
183
+ color: var(--color-danger);
184
+ }
185
+
186
+ :global(.dropdown-divider) {
187
+ margin: 0.375rem 0;
188
+ border-color: var(--color-border-subtle);
189
+ }
190
+ </style>
@@ -0,0 +1,26 @@
1
+ import type { Snippet } from "svelte";
2
+ interface DropdownProps {
3
+ /** Conteúdo do botão trigger */
4
+ trigger?: Snippet;
5
+ /** Conteúdo do menu dropdown */
6
+ children?: Snippet;
7
+ /** Variante do botão trigger */
8
+ variant?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'light' | 'dark' | 'outline-primary' | 'outline-secondary' | 'link' | 'ghost';
9
+ /** Tamanho do botão trigger */
10
+ size?: 'sm' | 'md' | 'lg';
11
+ /** Alinhamento do menu */
12
+ align?: 'start' | 'end';
13
+ /** Direção do dropdown */
14
+ direction?: 'down' | 'up' | 'start' | 'end';
15
+ /** Classes CSS adicionais para o wrapper */
16
+ class?: string;
17
+ /** Classes CSS adicionais para o botão */
18
+ buttonClass?: string;
19
+ /** ARIA label para acessibilidade */
20
+ ariaLabel?: string;
21
+ /** Desabilitar dropdown */
22
+ disabled?: boolean;
23
+ }
24
+ declare const Dropdown: import("svelte").Component<DropdownProps, {}, "">;
25
+ type Dropdown = ReturnType<typeof Dropdown>;
26
+ export default Dropdown;
@@ -0,0 +1,103 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+
4
+ interface DropdownItemProps {
5
+ /** Item content */
6
+ children?: Snippet;
7
+ /** Left icon */
8
+ icon?: Snippet;
9
+ /** Navigation URL (renders an anchor) */
10
+ href?: string;
11
+ /** Click callback */
12
+ onclick?: (event: MouseEvent) => void;
13
+ /** Color variant */
14
+ variant?: 'default' | 'danger' | 'success' | 'warning' | 'primary';
15
+ /** Disabled item */
16
+ disabled?: boolean;
17
+ /** Additional CSS classes */
18
+ class?: string;
19
+ /** Item type */
20
+ type?: 'item' | 'divider' | 'header';
21
+ }
22
+
23
+ let {
24
+ children,
25
+ icon,
26
+ href,
27
+ onclick,
28
+ variant = 'default',
29
+ disabled = false,
30
+ class: additionalClasses = '',
31
+ type = 'item'
32
+ }: DropdownItemProps = $props();
33
+
34
+ // Variant classes
35
+ const variantClasses: Record<string, string> = {
36
+ default: '',
37
+ danger: 'text-danger',
38
+ success: 'text-success',
39
+ warning: 'text-warning',
40
+ primary: 'text-primary'
41
+ };
42
+
43
+ const itemClass = [
44
+ 'dropdown-item',
45
+ variantClasses[variant],
46
+ additionalClasses
47
+ ].filter(Boolean).join(' ');
48
+ </script>
49
+
50
+ {#if type === 'divider'}
51
+ <li><hr class="dropdown-divider" /></li>
52
+ {:else if type === 'header'}
53
+ <li><h6 class="dropdown-header">{#if children}{@render children()}{/if}</h6></li>
54
+ {:else if href}
55
+ <li>
56
+ <a
57
+ {href}
58
+ class={itemClass}
59
+ class:disabled={disabled}
60
+ aria-disabled={disabled}
61
+ >
62
+ {#if icon}
63
+ <span class="dropdown-icon">
64
+ {@render icon()}
65
+ </span>
66
+ {/if}
67
+ {#if children}
68
+ {@render children()}
69
+ {/if}
70
+ </a>
71
+ </li>
72
+ {:else}
73
+ <li>
74
+ <button
75
+ type="button"
76
+ class={itemClass}
77
+ onclick={onclick}
78
+ disabled={disabled}
79
+ >
80
+ {#if icon}
81
+ <span class="dropdown-icon">
82
+ {@render icon()}
83
+ </span>
84
+ {/if}
85
+ {#if children}
86
+ {@render children()}
87
+ {/if}
88
+ </button>
89
+ </li>
90
+ {/if}
91
+
92
+ <style>
93
+ .dropdown-icon {
94
+ display: inline-flex;
95
+ align-items: center;
96
+ margin-right: 0.5rem;
97
+ }
98
+
99
+ .dropdown-item.disabled {
100
+ pointer-events: none;
101
+ opacity: 0.5;
102
+ }
103
+ </style>
@@ -0,0 +1,22 @@
1
+ import type { Snippet } from "svelte";
2
+ interface DropdownItemProps {
3
+ /** Item content */
4
+ children?: Snippet;
5
+ /** Left icon */
6
+ icon?: Snippet;
7
+ /** Navigation URL (renders an anchor) */
8
+ href?: string;
9
+ /** Click callback */
10
+ onclick?: (event: MouseEvent) => void;
11
+ /** Color variant */
12
+ variant?: 'default' | 'danger' | 'success' | 'warning' | 'primary';
13
+ /** Disabled item */
14
+ disabled?: boolean;
15
+ /** Additional CSS classes */
16
+ class?: string;
17
+ /** Item type */
18
+ type?: 'item' | 'divider' | 'header';
19
+ }
20
+ declare const DropdownItem: import("svelte").Component<DropdownItemProps, {}, "">;
21
+ type DropdownItem = ReturnType<typeof DropdownItem>;
22
+ export default DropdownItem;