@aspect-ops/exon-ui 0.0.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 (106) hide show
  1. package/dist/components/Badge/Badge.svelte +60 -0
  2. package/dist/components/Badge/Badge.svelte.d.ts +9 -0
  3. package/dist/components/Badge/index.d.ts +2 -0
  4. package/dist/components/Badge/index.js +1 -0
  5. package/dist/components/BottomNav/BottomNav.svelte +128 -0
  6. package/dist/components/BottomNav/BottomNav.svelte.d.ts +8 -0
  7. package/dist/components/BottomNav/BottomNavItem.svelte +133 -0
  8. package/dist/components/BottomNav/BottomNavItem.svelte.d.ts +8 -0
  9. package/dist/components/Breadcrumbs/BreadcrumbItem.svelte +65 -0
  10. package/dist/components/Breadcrumbs/BreadcrumbItem.svelte.d.ts +7 -0
  11. package/dist/components/Breadcrumbs/BreadcrumbSeparator.svelte +27 -0
  12. package/dist/components/Breadcrumbs/BreadcrumbSeparator.svelte.d.ts +7 -0
  13. package/dist/components/Breadcrumbs/Breadcrumbs.svelte +114 -0
  14. package/dist/components/Breadcrumbs/Breadcrumbs.svelte.d.ts +8 -0
  15. package/dist/components/Button/Button.svelte +209 -0
  16. package/dist/components/Button/Button.svelte.d.ts +14 -0
  17. package/dist/components/Button/index.d.ts +2 -0
  18. package/dist/components/Button/index.js +1 -0
  19. package/dist/components/Checkbox/Checkbox.svelte +166 -0
  20. package/dist/components/Checkbox/Checkbox.svelte.d.ts +16 -0
  21. package/dist/components/Checkbox/CheckboxGroup.svelte +55 -0
  22. package/dist/components/Checkbox/CheckboxGroup.svelte.d.ts +12 -0
  23. package/dist/components/Checkbox/index.d.ts +2 -0
  24. package/dist/components/Checkbox/index.js +2 -0
  25. package/dist/components/FormField/FormField.svelte +101 -0
  26. package/dist/components/FormField/FormField.svelte.d.ts +13 -0
  27. package/dist/components/FormField/index.d.ts +1 -0
  28. package/dist/components/FormField/index.js +1 -0
  29. package/dist/components/Icon/Icon.svelte +47 -0
  30. package/dist/components/Icon/Icon.svelte.d.ts +11 -0
  31. package/dist/components/Icon/index.d.ts +2 -0
  32. package/dist/components/Icon/index.js +1 -0
  33. package/dist/components/Link/Link.svelte +56 -0
  34. package/dist/components/Link/Link.svelte.d.ts +9 -0
  35. package/dist/components/Link/index.d.ts +2 -0
  36. package/dist/components/Link/index.js +1 -0
  37. package/dist/components/Menu/Menu.svelte +14 -0
  38. package/dist/components/Menu/Menu.svelte.d.ts +7 -0
  39. package/dist/components/Menu/MenuContent.svelte +71 -0
  40. package/dist/components/Menu/MenuContent.svelte.d.ts +10 -0
  41. package/dist/components/Menu/MenuItem.svelte +73 -0
  42. package/dist/components/Menu/MenuItem.svelte.d.ts +7 -0
  43. package/dist/components/Menu/MenuSeparator.svelte +19 -0
  44. package/dist/components/Menu/MenuSeparator.svelte.d.ts +6 -0
  45. package/dist/components/Menu/MenuSub.svelte +14 -0
  46. package/dist/components/Menu/MenuSub.svelte.d.ts +7 -0
  47. package/dist/components/Menu/MenuSubContent.svelte +60 -0
  48. package/dist/components/Menu/MenuSubContent.svelte.d.ts +7 -0
  49. package/dist/components/Menu/MenuSubTrigger.svelte +84 -0
  50. package/dist/components/Menu/MenuSubTrigger.svelte.d.ts +7 -0
  51. package/dist/components/Menu/MenuTrigger.svelte +32 -0
  52. package/dist/components/Menu/MenuTrigger.svelte.d.ts +7 -0
  53. package/dist/components/Navbar/NavItem.svelte +99 -0
  54. package/dist/components/Navbar/NavItem.svelte.d.ts +8 -0
  55. package/dist/components/Navbar/Navbar.svelte +243 -0
  56. package/dist/components/Navbar/Navbar.svelte.d.ts +10 -0
  57. package/dist/components/Radio/Radio.svelte +93 -0
  58. package/dist/components/Radio/Radio.svelte.d.ts +10 -0
  59. package/dist/components/Radio/RadioGroup.svelte +72 -0
  60. package/dist/components/Radio/RadioGroup.svelte.d.ts +14 -0
  61. package/dist/components/Radio/index.d.ts +2 -0
  62. package/dist/components/Radio/index.js +2 -0
  63. package/dist/components/Select/Select.svelte +251 -0
  64. package/dist/components/Select/Select.svelte.d.ts +17 -0
  65. package/dist/components/Select/index.d.ts +1 -0
  66. package/dist/components/Select/index.js +1 -0
  67. package/dist/components/Sidebar/Sidebar.svelte +48 -0
  68. package/dist/components/Sidebar/Sidebar.svelte.d.ts +7 -0
  69. package/dist/components/Sidebar/SidebarGroup.svelte +141 -0
  70. package/dist/components/Sidebar/SidebarGroup.svelte.d.ts +7 -0
  71. package/dist/components/Sidebar/SidebarItem.svelte +151 -0
  72. package/dist/components/Sidebar/SidebarItem.svelte.d.ts +8 -0
  73. package/dist/components/Switch/Switch.svelte +120 -0
  74. package/dist/components/Switch/Switch.svelte.d.ts +13 -0
  75. package/dist/components/Switch/index.d.ts +1 -0
  76. package/dist/components/Switch/index.js +1 -0
  77. package/dist/components/Tabs/TabContent.svelte +91 -0
  78. package/dist/components/Tabs/TabContent.svelte.d.ts +7 -0
  79. package/dist/components/Tabs/TabList.svelte +46 -0
  80. package/dist/components/Tabs/TabList.svelte.d.ts +7 -0
  81. package/dist/components/Tabs/TabTrigger.svelte +68 -0
  82. package/dist/components/Tabs/TabTrigger.svelte.d.ts +7 -0
  83. package/dist/components/Tabs/Tabs.svelte +69 -0
  84. package/dist/components/Tabs/Tabs.svelte.d.ts +7 -0
  85. package/dist/components/TextInput/TextInput.svelte +200 -0
  86. package/dist/components/TextInput/TextInput.svelte.d.ts +35 -0
  87. package/dist/components/TextInput/index.d.ts +1 -0
  88. package/dist/components/TextInput/index.js +1 -0
  89. package/dist/components/Textarea/Textarea.svelte +198 -0
  90. package/dist/components/Textarea/Textarea.svelte.d.ts +33 -0
  91. package/dist/components/Textarea/index.d.ts +1 -0
  92. package/dist/components/Textarea/index.js +1 -0
  93. package/dist/components/Typography/Typography.svelte +99 -0
  94. package/dist/components/Typography/Typography.svelte.d.ts +10 -0
  95. package/dist/components/Typography/index.d.ts +2 -0
  96. package/dist/components/Typography/index.js +1 -0
  97. package/dist/index.d.ts +37 -0
  98. package/dist/index.js +41 -0
  99. package/dist/styles/tokens.css +431 -0
  100. package/dist/test-setup.d.ts +1 -0
  101. package/dist/test-setup.js +1 -0
  102. package/dist/types/index.d.ts +129 -0
  103. package/dist/types/index.js +1 -0
  104. package/dist/types/navigation.d.ts +118 -0
  105. package/dist/types/navigation.js +1 -0
  106. package/package.json +130 -0
@@ -0,0 +1,17 @@
1
+ import type { InputSize, SelectOption } from '../../types/index.js';
2
+ interface Props {
3
+ value?: string;
4
+ options: SelectOption[];
5
+ placeholder?: string;
6
+ name?: string;
7
+ id?: string;
8
+ size?: InputSize;
9
+ disabled?: boolean;
10
+ required?: boolean;
11
+ error?: boolean;
12
+ class?: string;
13
+ onchange?: (value: string) => void;
14
+ }
15
+ declare const Select: import("svelte").Component<Props, {}, "value">;
16
+ type Select = ReturnType<typeof Select>;
17
+ export default Select;
@@ -0,0 +1 @@
1
+ export { default as Select } from './Select.svelte';
@@ -0,0 +1 @@
1
+ export { default as Select } from './Select.svelte';
@@ -0,0 +1,48 @@
1
+ <script lang="ts">
2
+ import type { SidebarProps } from '../../types/index.js';
3
+
4
+ interface Props extends SidebarProps {
5
+ children?: import('svelte').Snippet;
6
+ }
7
+
8
+ let { collapsed = $bindable(false), class: className = '', children }: Props = $props();
9
+ </script>
10
+
11
+ <aside
12
+ class="sidebar {className}"
13
+ class:sidebar--collapsed={collapsed}
14
+ aria-label="Sidebar navigation"
15
+ >
16
+ <nav class="sidebar__nav">
17
+ {#if children}
18
+ {@render children()}
19
+ {/if}
20
+ </nav>
21
+ </aside>
22
+
23
+ <style>
24
+ .sidebar {
25
+ display: flex;
26
+ flex-direction: column;
27
+ width: var(--sidebar-width, 16rem);
28
+ min-height: 100%;
29
+ background: var(--color-bg, #ffffff);
30
+ border-right: 1px solid var(--color-border, #e5e7eb);
31
+ font-family: inherit;
32
+ transition: width var(--transition-normal, 200ms ease);
33
+ overflow: hidden;
34
+ }
35
+
36
+ .sidebar--collapsed {
37
+ width: var(--sidebar-collapsed-width, 4rem);
38
+ }
39
+
40
+ .sidebar__nav {
41
+ display: flex;
42
+ flex-direction: column;
43
+ gap: var(--space-xs, 0.25rem);
44
+ padding: var(--space-sm, 0.5rem);
45
+ overflow-y: auto;
46
+ overflow-x: hidden;
47
+ }
48
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { SidebarProps } from '../../types/index.js';
2
+ interface Props extends SidebarProps {
3
+ children?: import('svelte').Snippet;
4
+ }
5
+ declare const Sidebar: import("svelte").Component<Props, {}, "collapsed">;
6
+ type Sidebar = ReturnType<typeof Sidebar>;
7
+ export default Sidebar;
@@ -0,0 +1,141 @@
1
+ <script lang="ts">
2
+ import type { SidebarGroupProps } from '../../types/index.js';
3
+
4
+ interface Props extends SidebarGroupProps {
5
+ children?: import('svelte').Snippet;
6
+ }
7
+
8
+ let {
9
+ label,
10
+ collapsible = false,
11
+ defaultCollapsed = false,
12
+ class: className = '',
13
+ children
14
+ }: Props = $props();
15
+
16
+ let collapsed = $state<boolean>();
17
+ $effect(() => {
18
+ collapsed = defaultCollapsed;
19
+ });
20
+
21
+ function toggleCollapse() {
22
+ if (collapsible) {
23
+ collapsed = !collapsed;
24
+ }
25
+ }
26
+ </script>
27
+
28
+ <div class="sidebar-group {className}">
29
+ {#if label}
30
+ {#if collapsible}
31
+ <button
32
+ type="button"
33
+ class="sidebar-group__header sidebar-group__header--collapsible"
34
+ onclick={toggleCollapse}
35
+ aria-expanded={!collapsed}
36
+ >
37
+ <span class="sidebar-group__label">{label}</span>
38
+ <span class="sidebar-group__chevron" class:sidebar-group__chevron--collapsed={collapsed}>
39
+ <svg
40
+ width="12"
41
+ height="12"
42
+ viewBox="0 0 12 12"
43
+ fill="none"
44
+ stroke="currentColor"
45
+ stroke-width="2"
46
+ stroke-linecap="round"
47
+ >
48
+ <path d="M3 4.5L6 7.5L9 4.5" />
49
+ </svg>
50
+ </span>
51
+ </button>
52
+ {:else}
53
+ <div class="sidebar-group__header">
54
+ <span class="sidebar-group__label">{label}</span>
55
+ </div>
56
+ {/if}
57
+ {/if}
58
+
59
+ <div class="sidebar-group__content" class:sidebar-group__content--collapsed={collapsed}>
60
+ {#if children}
61
+ {@render children()}
62
+ {/if}
63
+ </div>
64
+ </div>
65
+
66
+ <style>
67
+ .sidebar-group {
68
+ display: flex;
69
+ flex-direction: column;
70
+ gap: var(--space-2xs, 0.125rem);
71
+ }
72
+
73
+ :global(.sidebar-group + .sidebar-group) {
74
+ margin-top: var(--space-md, 1rem);
75
+ }
76
+
77
+ .sidebar-group__header {
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: space-between;
81
+ gap: var(--space-xs, 0.25rem);
82
+ padding: var(--space-xs, 0.25rem) var(--space-md, 1rem);
83
+ }
84
+
85
+ .sidebar-group__header--collapsible {
86
+ width: 100%;
87
+ background: transparent;
88
+ border: none;
89
+ cursor: pointer;
90
+ border-radius: var(--radius-sm, 0.25rem);
91
+ transition: background-color var(--transition-fast, 150ms ease);
92
+ }
93
+
94
+ .sidebar-group__header--collapsible:hover {
95
+ background: var(--color-bg-muted, #f3f4f6);
96
+ }
97
+
98
+ .sidebar-group__header--collapsible:focus-visible {
99
+ outline: 2px solid var(--color-primary, #3b82f6);
100
+ outline-offset: -2px;
101
+ }
102
+
103
+ .sidebar-group__label {
104
+ font-size: var(--text-xs, 0.75rem);
105
+ font-weight: 600;
106
+ text-transform: uppercase;
107
+ letter-spacing: 0.05em;
108
+ color: var(--color-text-muted, #6b7280);
109
+ }
110
+
111
+ .sidebar-group__chevron {
112
+ display: inline-flex;
113
+ align-items: center;
114
+ justify-content: center;
115
+ color: var(--color-text-muted, #6b7280);
116
+ transition: transform var(--transition-fast, 150ms ease);
117
+ }
118
+
119
+ .sidebar-group__chevron--collapsed {
120
+ transform: rotate(-90deg);
121
+ }
122
+
123
+ .sidebar-group__content {
124
+ display: flex;
125
+ flex-direction: column;
126
+ gap: var(--space-2xs, 0.125rem);
127
+ overflow: hidden;
128
+ transition: max-height var(--transition-normal, 200ms ease);
129
+ }
130
+
131
+ .sidebar-group__content--collapsed {
132
+ max-height: 0;
133
+ opacity: 0;
134
+ pointer-events: none;
135
+ }
136
+
137
+ /* Hide group labels when sidebar is collapsed */
138
+ :global(.sidebar--collapsed) .sidebar-group__header {
139
+ display: none;
140
+ }
141
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { SidebarGroupProps } from '../../types/index.js';
2
+ interface Props extends SidebarGroupProps {
3
+ children?: import('svelte').Snippet;
4
+ }
5
+ declare const SidebarGroup: import("svelte").Component<Props, {}, "">;
6
+ type SidebarGroup = ReturnType<typeof SidebarGroup>;
7
+ export default SidebarGroup;
@@ -0,0 +1,151 @@
1
+ <script lang="ts">
2
+ import type { SidebarItemProps } from '../../types/index.js';
3
+
4
+ interface Props extends SidebarItemProps {
5
+ onclick?: () => void;
6
+ children?: import('svelte').Snippet;
7
+ }
8
+
9
+ let {
10
+ label,
11
+ href,
12
+ icon,
13
+ active = false,
14
+ badge,
15
+ indentLevel = 0,
16
+ class: className = '',
17
+ onclick,
18
+ children
19
+ }: Props = $props();
20
+
21
+ const paddingLeft = $derived(`calc(var(--space-md, 1rem) + ${indentLevel * 1}rem)`);
22
+ </script>
23
+
24
+ {#if href}
25
+ <a
26
+ {href}
27
+ class="sidebar-item {className}"
28
+ class:sidebar-item--active={active}
29
+ style:padding-left={paddingLeft}
30
+ aria-current={active ? 'page' : undefined}
31
+ >
32
+ {#if icon}
33
+ <span class="sidebar-item__icon">{icon}</span>
34
+ {/if}
35
+ <span class="sidebar-item__label">
36
+ {#if children}
37
+ {@render children()}
38
+ {:else}
39
+ {label}
40
+ {/if}
41
+ </span>
42
+ {#if badge !== undefined && badge > 0}
43
+ <span class="sidebar-item__badge">{badge > 99 ? '99+' : badge}</span>
44
+ {/if}
45
+ </a>
46
+ {:else}
47
+ <button
48
+ type="button"
49
+ class="sidebar-item {className}"
50
+ class:sidebar-item--active={active}
51
+ style:padding-left={paddingLeft}
52
+ aria-current={active ? 'page' : undefined}
53
+ {onclick}
54
+ >
55
+ {#if icon}
56
+ <span class="sidebar-item__icon">{icon}</span>
57
+ {/if}
58
+ <span class="sidebar-item__label">
59
+ {#if children}
60
+ {@render children()}
61
+ {:else}
62
+ {label}
63
+ {/if}
64
+ </span>
65
+ {#if badge !== undefined && badge > 0}
66
+ <span class="sidebar-item__badge">{badge > 99 ? '99+' : badge}</span>
67
+ {/if}
68
+ </button>
69
+ {/if}
70
+
71
+ <style>
72
+ .sidebar-item {
73
+ display: flex;
74
+ align-items: center;
75
+ gap: var(--space-sm, 0.5rem);
76
+ /* Touch target minimum (F20) */
77
+ min-height: var(--touch-target-min, 44px);
78
+ padding: var(--space-sm, 0.5rem) var(--space-md, 1rem);
79
+ background: transparent;
80
+ border: none;
81
+ border-radius: var(--radius-sm, 0.25rem);
82
+ color: var(--color-text-muted, #6b7280);
83
+ font-size: var(--text-sm, 0.875rem);
84
+ text-decoration: none;
85
+ text-align: left;
86
+ cursor: pointer;
87
+ transition: all var(--transition-fast, 150ms ease);
88
+ -webkit-tap-highlight-color: transparent;
89
+ white-space: nowrap;
90
+ overflow: hidden;
91
+ }
92
+
93
+ .sidebar-item:hover {
94
+ color: var(--color-text, #1f2937);
95
+ background: var(--color-bg-muted, #f3f4f6);
96
+ }
97
+
98
+ .sidebar-item:focus-visible {
99
+ outline: 2px solid var(--color-primary, #3b82f6);
100
+ outline-offset: -2px;
101
+ }
102
+
103
+ .sidebar-item--active {
104
+ color: var(--color-primary, #3b82f6);
105
+ background: var(--color-primary-bg, #eff6ff);
106
+ }
107
+
108
+ .sidebar-item--active:hover {
109
+ color: var(--color-primary, #3b82f6);
110
+ background: var(--color-primary-bg, #eff6ff);
111
+ }
112
+
113
+ .sidebar-item__icon {
114
+ display: inline-flex;
115
+ align-items: center;
116
+ justify-content: center;
117
+ flex-shrink: 0;
118
+ width: 1.5rem;
119
+ font-size: 1.25rem;
120
+ }
121
+
122
+ .sidebar-item__label {
123
+ flex: 1;
124
+ min-width: 0;
125
+ overflow: hidden;
126
+ text-overflow: ellipsis;
127
+ }
128
+
129
+ /* Hide label when sidebar is collapsed */
130
+ :global(.sidebar--collapsed) .sidebar-item__label {
131
+ display: none;
132
+ }
133
+
134
+ :global(.sidebar--collapsed) .sidebar-item__badge {
135
+ display: none;
136
+ }
137
+
138
+ .sidebar-item__badge {
139
+ flex-shrink: 0;
140
+ min-width: 1.25rem;
141
+ height: 1.25rem;
142
+ padding: 0 var(--space-2xs, 0.125rem);
143
+ background: var(--color-primary, #3b82f6);
144
+ color: var(--color-text-inverse, #ffffff);
145
+ font-size: var(--text-xs, 0.75rem);
146
+ font-weight: 600;
147
+ line-height: 1.25rem;
148
+ text-align: center;
149
+ border-radius: var(--radius-full, 9999px);
150
+ }
151
+ </style>
@@ -0,0 +1,8 @@
1
+ import type { SidebarItemProps } from '../../types/index.js';
2
+ interface Props extends SidebarItemProps {
3
+ onclick?: () => void;
4
+ children?: import('svelte').Snippet;
5
+ }
6
+ declare const SidebarItem: import("svelte").Component<Props, {}, "">;
7
+ type SidebarItem = ReturnType<typeof SidebarItem>;
8
+ export default SidebarItem;
@@ -0,0 +1,120 @@
1
+ <script lang="ts">
2
+ import { Switch as SwitchPrimitive } from 'bits-ui';
3
+
4
+ interface Props {
5
+ checked?: boolean;
6
+ name?: string;
7
+ id?: string;
8
+ disabled?: boolean;
9
+ required?: boolean;
10
+ class?: string;
11
+ onchange?: (checked: boolean) => void;
12
+ children?: import('svelte').Snippet;
13
+ }
14
+
15
+ let {
16
+ checked = $bindable(false),
17
+ name,
18
+ id,
19
+ disabled = false,
20
+ required = false,
21
+ class: className = '',
22
+ onchange,
23
+ children
24
+ }: Props = $props();
25
+
26
+ function handleCheckedChange(newChecked: boolean) {
27
+ checked = newChecked;
28
+ onchange?.(newChecked);
29
+ }
30
+ </script>
31
+
32
+ <div class="switch-wrapper {className}">
33
+ <SwitchPrimitive.Root
34
+ class="switch {disabled ? 'switch--disabled' : ''}"
35
+ {checked}
36
+ {name}
37
+ {id}
38
+ {disabled}
39
+ {required}
40
+ aria-required={required}
41
+ onCheckedChange={handleCheckedChange}
42
+ >
43
+ <SwitchPrimitive.Thumb class="switch__thumb" />
44
+ </SwitchPrimitive.Root>
45
+
46
+ {#if children}
47
+ <label for={id} class="switch__label" class:switch__label--disabled={disabled}>
48
+ {@render children()}
49
+ </label>
50
+ {/if}
51
+ </div>
52
+
53
+ <style>
54
+ .switch-wrapper {
55
+ display: inline-flex;
56
+ align-items: center;
57
+ gap: var(--space-sm, 0.5rem);
58
+ }
59
+
60
+ :global(.switch) {
61
+ position: relative;
62
+ display: inline-flex;
63
+ align-items: center;
64
+ width: 2.75rem;
65
+ height: 1.5rem;
66
+ min-width: 2.75rem;
67
+ min-height: 1.5rem;
68
+ padding: 2px;
69
+ border: none;
70
+ border-radius: 9999px;
71
+ background: var(--color-bg-muted, #e5e7eb);
72
+ cursor: pointer;
73
+ transition: background var(--transition-fast, 150ms ease);
74
+ -webkit-tap-highlight-color: transparent;
75
+ }
76
+
77
+ :global(.switch:focus-visible) {
78
+ outline: none;
79
+ box-shadow: 0 0 0 3px var(--color-primary-alpha, rgba(59, 130, 246, 0.1));
80
+ }
81
+
82
+ :global(.switch[data-state='checked']) {
83
+ background: var(--color-primary, #3b82f6);
84
+ }
85
+
86
+ :global(.switch--disabled) {
87
+ opacity: 0.5;
88
+ cursor: not-allowed;
89
+ }
90
+
91
+ :global(.switch__thumb) {
92
+ display: block;
93
+ width: 1.25rem;
94
+ height: 1.25rem;
95
+ border-radius: 50%;
96
+ background: var(--color-bg, #ffffff);
97
+ box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.1));
98
+ transition: transform var(--transition-fast, 150ms ease);
99
+ }
100
+
101
+ :global(.switch[data-state='checked'] .switch__thumb) {
102
+ transform: translateX(1.25rem);
103
+ }
104
+
105
+ .switch__label {
106
+ font-family: inherit;
107
+ font-size: var(--text-sm, 0.875rem);
108
+ color: var(--color-text, #1f2937);
109
+ cursor: pointer;
110
+ user-select: none;
111
+ min-height: var(--touch-target-min, 44px);
112
+ display: flex;
113
+ align-items: center;
114
+ }
115
+
116
+ .switch__label--disabled {
117
+ opacity: 0.5;
118
+ cursor: not-allowed;
119
+ }
120
+ </style>
@@ -0,0 +1,13 @@
1
+ interface Props {
2
+ checked?: boolean;
3
+ name?: string;
4
+ id?: string;
5
+ disabled?: boolean;
6
+ required?: boolean;
7
+ class?: string;
8
+ onchange?: (checked: boolean) => void;
9
+ children?: import('svelte').Snippet;
10
+ }
11
+ declare const Switch: import("svelte").Component<Props, {}, "checked">;
12
+ type Switch = ReturnType<typeof Switch>;
13
+ export default Switch;
@@ -0,0 +1 @@
1
+ export { default as Switch } from './Switch.svelte';
@@ -0,0 +1 @@
1
+ export { default as Switch } from './Switch.svelte';
@@ -0,0 +1,91 @@
1
+ <script lang="ts">
2
+ import { Tabs as TabsPrimitive } from 'bits-ui';
3
+ import type { TabContentProps } from '../../types/index.js';
4
+ import type { Action } from 'svelte/action';
5
+
6
+ interface Props extends TabContentProps {
7
+ children?: import('svelte').Snippet;
8
+ }
9
+
10
+ let { value, lazy = false, class: className = '', children }: Props = $props();
11
+
12
+ // Track if this content has ever been rendered (for lazy loading)
13
+ let hasRendered = $state(false);
14
+
15
+ // Action to watch for when content becomes active
16
+ const watchActive: Action<HTMLElement> = (node) => {
17
+ if (!lazy || hasRendered) return;
18
+
19
+ // Find the TabsPrimitive.Content child element
20
+ const contentElement = node.querySelector('[data-state]');
21
+ if (!contentElement) return;
22
+
23
+ // Check initial state
24
+ if (contentElement.getAttribute('data-state') === 'active') {
25
+ hasRendered = true;
26
+ return;
27
+ }
28
+
29
+ // Watch for state changes
30
+ const observer = new MutationObserver((mutations) => {
31
+ for (const mutation of mutations) {
32
+ if (
33
+ mutation.type === 'attributes' &&
34
+ mutation.attributeName === 'data-state' &&
35
+ contentElement.getAttribute('data-state') === 'active'
36
+ ) {
37
+ hasRendered = true;
38
+ observer.disconnect();
39
+ break;
40
+ }
41
+ }
42
+ });
43
+
44
+ observer.observe(contentElement, {
45
+ attributes: true,
46
+ attributeFilter: ['data-state']
47
+ });
48
+
49
+ return {
50
+ destroy() {
51
+ observer.disconnect();
52
+ }
53
+ };
54
+ };
55
+ </script>
56
+
57
+ <div use:watchActive class="tab-content-wrapper">
58
+ <TabsPrimitive.Content {value} class="tab-content {className}">
59
+ {#if !lazy || hasRendered}
60
+ {#if children}
61
+ {@render children()}
62
+ {/if}
63
+ {/if}
64
+ </TabsPrimitive.Content>
65
+ </div>
66
+
67
+ <style>
68
+ .tab-content-wrapper {
69
+ display: contents;
70
+ }
71
+
72
+ :global(.tab-content) {
73
+ font-family: inherit;
74
+ padding: var(--space-md, 1rem);
75
+ animation: fadeIn var(--transition-normal, 200ms ease);
76
+ }
77
+
78
+ :global(.tab-content:focus-visible) {
79
+ outline: 2px solid var(--color-primary, #3b82f6);
80
+ outline-offset: 2px;
81
+ }
82
+
83
+ @keyframes fadeIn {
84
+ from {
85
+ opacity: 0;
86
+ }
87
+ to {
88
+ opacity: 1;
89
+ }
90
+ }
91
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { TabContentProps } from '../../types/index.js';
2
+ interface Props extends TabContentProps {
3
+ children?: import('svelte').Snippet;
4
+ }
5
+ declare const TabContent: import("svelte").Component<Props, {}, "">;
6
+ type TabContent = ReturnType<typeof TabContent>;
7
+ export default TabContent;
@@ -0,0 +1,46 @@
1
+ <script lang="ts">
2
+ import { Tabs as TabsPrimitive } from 'bits-ui';
3
+ import type { TabListProps } from '../../types/index.js';
4
+
5
+ interface Props extends TabListProps {
6
+ children?: import('svelte').Snippet;
7
+ }
8
+
9
+ let { scrollable = false, class: className = '', children }: Props = $props();
10
+
11
+ const scrollableClass = $derived(scrollable ? 'tab-list--scrollable' : '');
12
+ </script>
13
+
14
+ <TabsPrimitive.List class="tab-list {scrollableClass} {className}">
15
+ {#if children}
16
+ {@render children()}
17
+ {/if}
18
+ </TabsPrimitive.List>
19
+
20
+ <style>
21
+ :global(.tab-list) {
22
+ font-family: inherit;
23
+ display: flex;
24
+ gap: var(--space-xs, 0.25rem);
25
+ border-bottom: 1px solid var(--color-border, #e5e7eb);
26
+ }
27
+
28
+ :global(.tab-list[data-orientation='vertical']) {
29
+ flex-direction: column;
30
+ border-bottom: none;
31
+ border-right: 1px solid var(--color-border, #e5e7eb);
32
+ }
33
+
34
+ /* Scrollable styles - only applies to horizontal orientation */
35
+ :global(.tab-list--scrollable[data-orientation='horizontal']) {
36
+ overflow-x: auto;
37
+ overflow-y: hidden;
38
+ -webkit-overflow-scrolling: touch;
39
+ scrollbar-width: none; /* Firefox */
40
+ -ms-overflow-style: none; /* IE/Edge */
41
+ }
42
+
43
+ :global(.tab-list--scrollable[data-orientation='horizontal']::-webkit-scrollbar) {
44
+ display: none; /* Chrome/Safari */
45
+ }
46
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { TabListProps } from '../../types/index.js';
2
+ interface Props extends TabListProps {
3
+ children?: import('svelte').Snippet;
4
+ }
5
+ declare const TabList: import("svelte").Component<Props, {}, "">;
6
+ type TabList = ReturnType<typeof TabList>;
7
+ export default TabList;