@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,60 @@
1
+ <script lang="ts">
2
+ import type { BadgeVariant } from '../../types/index.js';
3
+
4
+ interface Props {
5
+ variant?: BadgeVariant;
6
+ class?: string;
7
+ children?: import('svelte').Snippet;
8
+ }
9
+
10
+ let { variant = 'default', class: className = '', children }: Props = $props();
11
+ </script>
12
+
13
+ <span class="badge badge--{variant} {className}">
14
+ {#if children}
15
+ {@render children()}
16
+ {/if}
17
+ </span>
18
+
19
+ <style>
20
+ .badge {
21
+ display: inline-flex;
22
+ align-items: center;
23
+ padding: var(--space-xs, 0.25rem) var(--space-sm, 0.5rem);
24
+ border-radius: var(--radius-full, 9999px);
25
+ font-family: inherit;
26
+ font-size: var(--text-xs, 0.75rem);
27
+ font-weight: 500;
28
+ line-height: 1;
29
+ }
30
+
31
+ .badge--default {
32
+ background: var(--color-bg-muted, #f3f4f6);
33
+ color: var(--color-text, #1f2937);
34
+ }
35
+
36
+ .badge--primary {
37
+ background: var(--color-primary, #3b82f6);
38
+ color: var(--color-text-inverse, #ffffff);
39
+ }
40
+
41
+ .badge--secondary {
42
+ background: var(--color-secondary, #6b7280);
43
+ color: var(--color-text-inverse, #ffffff);
44
+ }
45
+
46
+ .badge--success {
47
+ background: var(--color-success, #10b981);
48
+ color: var(--color-text-inverse, #ffffff);
49
+ }
50
+
51
+ .badge--warning {
52
+ background: var(--color-warning, #f59e0b);
53
+ color: var(--color-text, #1f2937);
54
+ }
55
+
56
+ .badge--error {
57
+ background: var(--color-error, #ef4444);
58
+ color: var(--color-text-inverse, #ffffff);
59
+ }
60
+ </style>
@@ -0,0 +1,9 @@
1
+ import type { BadgeVariant } from '../../types/index.js';
2
+ interface Props {
3
+ variant?: BadgeVariant;
4
+ class?: string;
5
+ children?: import('svelte').Snippet;
6
+ }
7
+ declare const Badge: import("svelte").Component<Props, {}, "">;
8
+ type Badge = ReturnType<typeof Badge>;
9
+ export default Badge;
@@ -0,0 +1,2 @@
1
+ export { default as Badge } from './Badge.svelte';
2
+ export type { BadgeProps, BadgeVariant } from '../../types/index.js';
@@ -0,0 +1 @@
1
+ export { default as Badge } from './Badge.svelte';
@@ -0,0 +1,128 @@
1
+ <script lang="ts">
2
+ import type { BottomNavProps, BottomNavItemData } from '../../types/index.js';
3
+
4
+ interface Props extends BottomNavProps {
5
+ onchange?: (index: number, item: BottomNavItemData) => void;
6
+ children?: import('svelte').Snippet;
7
+ }
8
+
9
+ let { items = [], activeIndex = 0, class: className = '', onchange, children }: Props = $props();
10
+
11
+ function handleItemClick(index: number) {
12
+ if (onchange && items[index]) {
13
+ onchange(index, items[index]);
14
+ }
15
+ }
16
+ </script>
17
+
18
+ <nav class="bottom-nav {className}" aria-label="Bottom navigation">
19
+ {#if children}
20
+ {@render children()}
21
+ {:else}
22
+ {#each items as item, index}
23
+ <button
24
+ type="button"
25
+ class="bottom-nav__item"
26
+ class:bottom-nav__item--active={index === activeIndex}
27
+ onclick={() => handleItemClick(index)}
28
+ aria-current={index === activeIndex ? 'page' : undefined}
29
+ >
30
+ <span class="bottom-nav__icon">{item.icon}</span>
31
+ <span class="bottom-nav__label">{item.label}</span>
32
+ {#if item.badge !== undefined && item.badge > 0}
33
+ <span class="bottom-nav__badge" aria-label="{item.badge} notifications">
34
+ {item.badge > 99 ? '99+' : item.badge}
35
+ </span>
36
+ {/if}
37
+ </button>
38
+ {/each}
39
+ {/if}
40
+ </nav>
41
+
42
+ <style>
43
+ .bottom-nav {
44
+ position: fixed;
45
+ bottom: 0;
46
+ left: 0;
47
+ right: 0;
48
+ z-index: 40;
49
+ display: flex;
50
+ justify-content: space-around;
51
+ align-items: stretch;
52
+ background: var(--color-bg, #ffffff);
53
+ border-top: 1px solid var(--color-border, #e5e7eb);
54
+ font-family: inherit;
55
+ /* Safe area padding for iOS notch and Android gesture bar (F21) */
56
+ padding-bottom: env(safe-area-inset-bottom, 0);
57
+ }
58
+
59
+ .bottom-nav__item {
60
+ position: relative;
61
+ flex: 1;
62
+ display: flex;
63
+ flex-direction: column;
64
+ align-items: center;
65
+ justify-content: center;
66
+ gap: var(--space-2xs, 0.125rem);
67
+ /* Touch target minimum (F20) */
68
+ min-height: var(--touch-target-min, 44px);
69
+ padding: var(--space-sm, 0.5rem) var(--space-xs, 0.25rem);
70
+ background: transparent;
71
+ border: none;
72
+ color: var(--color-text-muted, #6b7280);
73
+ cursor: pointer;
74
+ transition: all var(--transition-fast, 150ms ease);
75
+ -webkit-tap-highlight-color: transparent;
76
+ }
77
+
78
+ .bottom-nav__item:hover {
79
+ color: var(--color-text, #1f2937);
80
+ background: var(--color-bg-muted, #f3f4f6);
81
+ }
82
+
83
+ .bottom-nav__item:focus-visible {
84
+ outline: 2px solid var(--color-primary, #3b82f6);
85
+ outline-offset: -2px;
86
+ z-index: 1;
87
+ }
88
+
89
+ .bottom-nav__item--active {
90
+ color: var(--color-primary, #3b82f6);
91
+ }
92
+
93
+ .bottom-nav__item--active:hover {
94
+ color: var(--color-primary, #3b82f6);
95
+ }
96
+
97
+ .bottom-nav__icon {
98
+ display: flex;
99
+ align-items: center;
100
+ justify-content: center;
101
+ font-size: 1.5rem;
102
+ line-height: 1;
103
+ }
104
+
105
+ .bottom-nav__label {
106
+ font-size: var(--text-xs, 0.75rem);
107
+ font-weight: 500;
108
+ line-height: 1;
109
+ white-space: nowrap;
110
+ }
111
+
112
+ .bottom-nav__badge {
113
+ position: absolute;
114
+ top: var(--space-xs, 0.25rem);
115
+ left: 50%;
116
+ transform: translateX(0.5rem);
117
+ min-width: 1rem;
118
+ height: 1rem;
119
+ padding: 0 var(--space-2xs, 0.125rem);
120
+ background: var(--color-destructive, #ef4444);
121
+ color: var(--color-text-inverse, #ffffff);
122
+ font-size: var(--text-2xs, 0.625rem);
123
+ font-weight: 600;
124
+ line-height: 1rem;
125
+ text-align: center;
126
+ border-radius: var(--radius-full, 9999px);
127
+ }
128
+ </style>
@@ -0,0 +1,8 @@
1
+ import type { BottomNavProps, BottomNavItemData } from '../../types/index.js';
2
+ interface Props extends BottomNavProps {
3
+ onchange?: (index: number, item: BottomNavItemData) => void;
4
+ children?: import('svelte').Snippet;
5
+ }
6
+ declare const BottomNav: import("svelte").Component<Props, {}, "">;
7
+ type BottomNav = ReturnType<typeof BottomNav>;
8
+ export default BottomNav;
@@ -0,0 +1,133 @@
1
+ <script lang="ts">
2
+ import type { BottomNavItemProps } from '../../types/index.js';
3
+
4
+ interface Props extends BottomNavItemProps {
5
+ onclick?: () => void;
6
+ children?: import('svelte').Snippet;
7
+ }
8
+
9
+ let {
10
+ label,
11
+ icon,
12
+ href,
13
+ active = false,
14
+ badge,
15
+ class: className = '',
16
+ onclick,
17
+ children
18
+ }: Props = $props();
19
+ </script>
20
+
21
+ {#if href}
22
+ <a
23
+ {href}
24
+ class="bottom-nav-item {className}"
25
+ class:bottom-nav-item--active={active}
26
+ aria-current={active ? 'page' : undefined}
27
+ >
28
+ <span class="bottom-nav-item__icon">{icon}</span>
29
+ {#if children}
30
+ <span class="bottom-nav-item__label">{@render children()}</span>
31
+ {:else}
32
+ <span class="bottom-nav-item__label">{label}</span>
33
+ {/if}
34
+ {#if badge !== undefined && badge > 0}
35
+ <span class="bottom-nav-item__badge" aria-label="{badge} notifications">
36
+ {badge > 99 ? '99+' : badge}
37
+ </span>
38
+ {/if}
39
+ </a>
40
+ {:else}
41
+ <button
42
+ type="button"
43
+ class="bottom-nav-item {className}"
44
+ class:bottom-nav-item--active={active}
45
+ aria-current={active ? 'page' : undefined}
46
+ {onclick}
47
+ >
48
+ <span class="bottom-nav-item__icon">{icon}</span>
49
+ {#if children}
50
+ <span class="bottom-nav-item__label">{@render children()}</span>
51
+ {:else}
52
+ <span class="bottom-nav-item__label">{label}</span>
53
+ {/if}
54
+ {#if badge !== undefined && badge > 0}
55
+ <span class="bottom-nav-item__badge" aria-label="{badge} notifications">
56
+ {badge > 99 ? '99+' : badge}
57
+ </span>
58
+ {/if}
59
+ </button>
60
+ {/if}
61
+
62
+ <style>
63
+ .bottom-nav-item {
64
+ position: relative;
65
+ flex: 1;
66
+ display: flex;
67
+ flex-direction: column;
68
+ align-items: center;
69
+ justify-content: center;
70
+ gap: var(--space-2xs, 0.125rem);
71
+ /* Touch target minimum (F20) */
72
+ min-height: var(--touch-target-min, 44px);
73
+ padding: var(--space-sm, 0.5rem) var(--space-xs, 0.25rem);
74
+ background: transparent;
75
+ border: none;
76
+ color: var(--color-text-muted, #6b7280);
77
+ text-decoration: none;
78
+ cursor: pointer;
79
+ transition: all var(--transition-fast, 150ms ease);
80
+ -webkit-tap-highlight-color: transparent;
81
+ }
82
+
83
+ .bottom-nav-item:hover {
84
+ color: var(--color-text, #1f2937);
85
+ background: var(--color-bg-muted, #f3f4f6);
86
+ }
87
+
88
+ .bottom-nav-item:focus-visible {
89
+ outline: 2px solid var(--color-primary, #3b82f6);
90
+ outline-offset: -2px;
91
+ z-index: 1;
92
+ }
93
+
94
+ .bottom-nav-item--active {
95
+ color: var(--color-primary, #3b82f6);
96
+ }
97
+
98
+ .bottom-nav-item--active:hover {
99
+ color: var(--color-primary, #3b82f6);
100
+ }
101
+
102
+ .bottom-nav-item__icon {
103
+ display: flex;
104
+ align-items: center;
105
+ justify-content: center;
106
+ font-size: 1.5rem;
107
+ line-height: 1;
108
+ }
109
+
110
+ .bottom-nav-item__label {
111
+ font-size: var(--text-xs, 0.75rem);
112
+ font-weight: 500;
113
+ line-height: 1;
114
+ white-space: nowrap;
115
+ }
116
+
117
+ .bottom-nav-item__badge {
118
+ position: absolute;
119
+ top: var(--space-xs, 0.25rem);
120
+ left: 50%;
121
+ transform: translateX(0.5rem);
122
+ min-width: 1rem;
123
+ height: 1rem;
124
+ padding: 0 var(--space-2xs, 0.125rem);
125
+ background: var(--color-destructive, #ef4444);
126
+ color: var(--color-text-inverse, #ffffff);
127
+ font-size: var(--text-2xs, 0.625rem);
128
+ font-weight: 600;
129
+ line-height: 1rem;
130
+ text-align: center;
131
+ border-radius: var(--radius-full, 9999px);
132
+ }
133
+ </style>
@@ -0,0 +1,8 @@
1
+ import type { BottomNavItemProps } from '../../types/index.js';
2
+ interface Props extends BottomNavItemProps {
3
+ onclick?: () => void;
4
+ children?: import('svelte').Snippet;
5
+ }
6
+ declare const BottomNavItem: import("svelte").Component<Props, {}, "">;
7
+ type BottomNavItem = ReturnType<typeof BottomNavItem>;
8
+ export default BottomNavItem;
@@ -0,0 +1,65 @@
1
+ <script lang="ts">
2
+ import type { BreadcrumbItemProps } from '../../types/index.js';
3
+
4
+ interface Props extends BreadcrumbItemProps {
5
+ children?: import('svelte').Snippet;
6
+ }
7
+
8
+ let { href, isLast = false, class: className = '', children }: Props = $props();
9
+ </script>
10
+
11
+ <li class="breadcrumb-item {className}">
12
+ {#if href && !isLast}
13
+ <a {href} class="breadcrumb-item__link">
14
+ {#if children}
15
+ {@render children()}
16
+ {/if}
17
+ </a>
18
+ {:else}
19
+ <span class="breadcrumb-item__current" aria-current={isLast ? 'page' : undefined}>
20
+ {#if children}
21
+ {@render children()}
22
+ {/if}
23
+ </span>
24
+ {/if}
25
+ </li>
26
+
27
+ <style>
28
+ .breadcrumb-item {
29
+ display: inline-flex;
30
+ align-items: center;
31
+ min-height: var(--touch-target-min, 44px);
32
+ }
33
+
34
+ .breadcrumb-item__link {
35
+ display: inline-flex;
36
+ align-items: center;
37
+ gap: var(--space-xs, 0.25rem);
38
+ padding: var(--space-xs, 0.25rem) var(--space-sm, 0.5rem);
39
+ color: var(--color-text-muted, #6b7280);
40
+ text-decoration: none;
41
+ border-radius: var(--radius-sm, 0.25rem);
42
+ font-size: var(--text-sm, 0.875rem);
43
+ transition: all var(--transition-fast, 150ms ease);
44
+ }
45
+
46
+ .breadcrumb-item__link:hover {
47
+ color: var(--color-text, #1f2937);
48
+ background: var(--color-bg-muted, #f3f4f6);
49
+ }
50
+
51
+ .breadcrumb-item__link:focus-visible {
52
+ outline: 2px solid var(--color-primary, #3b82f6);
53
+ outline-offset: 2px;
54
+ }
55
+
56
+ .breadcrumb-item__current {
57
+ display: inline-flex;
58
+ align-items: center;
59
+ gap: var(--space-xs, 0.25rem);
60
+ padding: var(--space-xs, 0.25rem) var(--space-sm, 0.5rem);
61
+ color: var(--color-text, #1f2937);
62
+ font-size: var(--text-sm, 0.875rem);
63
+ font-weight: 500;
64
+ }
65
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { BreadcrumbItemProps } from '../../types/index.js';
2
+ interface Props extends BreadcrumbItemProps {
3
+ children?: import('svelte').Snippet;
4
+ }
5
+ declare const BreadcrumbItem: import("svelte").Component<Props, {}, "">;
6
+ type BreadcrumbItem = ReturnType<typeof BreadcrumbItem>;
7
+ export default BreadcrumbItem;
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ class?: string;
4
+ children?: import('svelte').Snippet;
5
+ }
6
+
7
+ let { class: className = '', children }: Props = $props();
8
+ </script>
9
+
10
+ <li class="breadcrumb-separator {className}" aria-hidden="true">
11
+ {#if children}
12
+ {@render children()}
13
+ {:else}
14
+ /
15
+ {/if}
16
+ </li>
17
+
18
+ <style>
19
+ .breadcrumb-separator {
20
+ display: inline-flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+ color: var(--color-text-muted, #6b7280);
24
+ user-select: none;
25
+ padding: 0 var(--space-xs, 0.25rem);
26
+ }
27
+ </style>
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ class?: string;
3
+ children?: import('svelte').Snippet;
4
+ }
5
+ declare const BreadcrumbSeparator: import("svelte").Component<Props, {}, "">;
6
+ type BreadcrumbSeparator = ReturnType<typeof BreadcrumbSeparator>;
7
+ export default BreadcrumbSeparator;
@@ -0,0 +1,114 @@
1
+ <script lang="ts">
2
+ import type { BreadcrumbsProps } from '../../types/index.js';
3
+
4
+ interface Props extends BreadcrumbsProps {
5
+ separator?: import('svelte').Snippet;
6
+ children?: import('svelte').Snippet;
7
+ }
8
+
9
+ let { items = [], class: className = '', separator, children }: Props = $props();
10
+ </script>
11
+
12
+ <nav aria-label="Breadcrumb" class="breadcrumbs {className}">
13
+ <ol class="breadcrumbs__list">
14
+ {#if children}
15
+ {@render children()}
16
+ {:else}
17
+ {#each items as item, index}
18
+ <li class="breadcrumbs__item">
19
+ {#if index > 0}
20
+ <span class="breadcrumbs__separator" aria-hidden="true">
21
+ {#if separator}
22
+ {@render separator()}
23
+ {:else}
24
+ /
25
+ {/if}
26
+ </span>
27
+ {/if}
28
+ {#if item.href && index < items.length - 1}
29
+ <a href={item.href} class="breadcrumbs__link">
30
+ {#if item.icon}
31
+ <span class="breadcrumbs__icon">{item.icon}</span>
32
+ {/if}
33
+ {item.label}
34
+ </a>
35
+ {:else}
36
+ <span class="breadcrumbs__current" aria-current="page">
37
+ {#if item.icon}
38
+ <span class="breadcrumbs__icon">{item.icon}</span>
39
+ {/if}
40
+ {item.label}
41
+ </span>
42
+ {/if}
43
+ </li>
44
+ {/each}
45
+ {/if}
46
+ </ol>
47
+ </nav>
48
+
49
+ <style>
50
+ .breadcrumbs {
51
+ font-family: inherit;
52
+ }
53
+
54
+ .breadcrumbs__list {
55
+ display: flex;
56
+ flex-wrap: wrap;
57
+ align-items: center;
58
+ gap: var(--space-xs, 0.25rem);
59
+ list-style: none;
60
+ margin: 0;
61
+ padding: 0;
62
+ }
63
+
64
+ .breadcrumbs__item {
65
+ display: inline-flex;
66
+ align-items: center;
67
+ gap: var(--space-xs, 0.25rem);
68
+ min-height: var(--touch-target-min, 44px);
69
+ }
70
+
71
+ .breadcrumbs__separator {
72
+ color: var(--color-text-muted, #6b7280);
73
+ user-select: none;
74
+ }
75
+
76
+ .breadcrumbs__link {
77
+ display: inline-flex;
78
+ align-items: center;
79
+ gap: var(--space-xs, 0.25rem);
80
+ padding: var(--space-xs, 0.25rem) var(--space-sm, 0.5rem);
81
+ color: var(--color-text-muted, #6b7280);
82
+ text-decoration: none;
83
+ border-radius: var(--radius-sm, 0.25rem);
84
+ font-size: var(--text-sm, 0.875rem);
85
+ transition: all var(--transition-fast, 150ms ease);
86
+ }
87
+
88
+ .breadcrumbs__link:hover {
89
+ color: var(--color-text, #1f2937);
90
+ background: var(--color-bg-muted, #f3f4f6);
91
+ }
92
+
93
+ .breadcrumbs__link:focus-visible {
94
+ outline: 2px solid var(--color-primary, #3b82f6);
95
+ outline-offset: 2px;
96
+ }
97
+
98
+ .breadcrumbs__current {
99
+ display: inline-flex;
100
+ align-items: center;
101
+ gap: var(--space-xs, 0.25rem);
102
+ padding: var(--space-xs, 0.25rem) var(--space-sm, 0.5rem);
103
+ color: var(--color-text, #1f2937);
104
+ font-size: var(--text-sm, 0.875rem);
105
+ font-weight: 500;
106
+ }
107
+
108
+ .breadcrumbs__icon {
109
+ display: inline-flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ flex-shrink: 0;
113
+ }
114
+ </style>
@@ -0,0 +1,8 @@
1
+ import type { BreadcrumbsProps } from '../../types/index.js';
2
+ interface Props extends BreadcrumbsProps {
3
+ separator?: import('svelte').Snippet;
4
+ children?: import('svelte').Snippet;
5
+ }
6
+ declare const Breadcrumbs: import("svelte").Component<Props, {}, "">;
7
+ type Breadcrumbs = ReturnType<typeof Breadcrumbs>;
8
+ export default Breadcrumbs;