@aspect-ops/exon-ui 0.0.3 → 0.1.0
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/README.md +793 -43
- package/dist/components/Accordion/Accordion.svelte +79 -0
- package/dist/components/Accordion/Accordion.svelte.d.ts +10 -0
- package/dist/components/Accordion/AccordionItem.svelte +198 -0
- package/dist/components/Accordion/AccordionItem.svelte.d.ts +10 -0
- package/dist/components/Accordion/index.d.ts +2 -0
- package/dist/components/Accordion/index.js +2 -0
- package/dist/components/Carousel/Carousel.svelte +454 -0
- package/dist/components/Carousel/Carousel.svelte.d.ts +14 -0
- package/dist/components/Carousel/CarouselSlide.svelte +22 -0
- package/dist/components/Carousel/CarouselSlide.svelte.d.ts +7 -0
- package/dist/components/Carousel/index.d.ts +2 -0
- package/dist/components/Carousel/index.js +2 -0
- package/dist/components/Chip/Chip.svelte +461 -0
- package/dist/components/Chip/Chip.svelte.d.ts +17 -0
- package/dist/components/Chip/ChipGroup.svelte +76 -0
- package/dist/components/Chip/ChipGroup.svelte.d.ts +9 -0
- package/dist/components/Chip/index.d.ts +2 -0
- package/dist/components/Chip/index.js +2 -0
- package/dist/components/DatePicker/DatePicker.svelte +746 -0
- package/dist/components/DatePicker/DatePicker.svelte.d.ts +19 -0
- package/dist/components/DatePicker/index.d.ts +1 -0
- package/dist/components/DatePicker/index.js +1 -0
- package/dist/components/FileUpload/FileUpload.svelte +484 -0
- package/dist/components/FileUpload/FileUpload.svelte.d.ts +16 -0
- package/dist/components/FileUpload/index.d.ts +1 -0
- package/dist/components/FileUpload/index.js +1 -0
- package/dist/components/Image/Image.svelte +223 -0
- package/dist/components/Image/Image.svelte.d.ts +19 -0
- package/dist/components/Image/index.d.ts +1 -0
- package/dist/components/Image/index.js +1 -0
- package/dist/components/OTPInput/OTPInput.svelte +312 -0
- package/dist/components/OTPInput/OTPInput.svelte.d.ts +57 -0
- package/dist/components/OTPInput/index.d.ts +1 -0
- package/dist/components/OTPInput/index.js +1 -0
- package/dist/components/Rating/Rating.svelte +316 -0
- package/dist/components/Rating/Rating.svelte.d.ts +16 -0
- package/dist/components/Rating/index.d.ts +1 -0
- package/dist/components/Rating/index.js +1 -0
- package/dist/components/SearchInput/SearchInput.svelte +480 -0
- package/dist/components/SearchInput/SearchInput.svelte.d.ts +22 -0
- package/dist/components/SearchInput/index.d.ts +1 -0
- package/dist/components/SearchInput/index.js +1 -0
- package/dist/components/Slider/Slider.svelte +324 -0
- package/dist/components/Slider/Slider.svelte.d.ts +14 -0
- package/dist/components/Slider/index.d.ts +1 -0
- package/dist/components/Slider/index.js +1 -0
- package/dist/components/Stepper/Stepper.svelte +100 -0
- package/dist/components/Stepper/Stepper.svelte.d.ts +11 -0
- package/dist/components/Stepper/StepperStep.svelte +391 -0
- package/dist/components/Stepper/StepperStep.svelte.d.ts +13 -0
- package/dist/components/Stepper/index.d.ts +2 -0
- package/dist/components/Stepper/index.js +2 -0
- package/dist/components/TimePicker/TimePicker.svelte +803 -0
- package/dist/components/TimePicker/TimePicker.svelte.d.ts +17 -0
- package/dist/components/TimePicker/index.d.ts +1 -0
- package/dist/components/TimePicker/index.js +1 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.js +9 -0
- package/dist/types/data-display.d.ts +68 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/input.d.ts +67 -0
- package/dist/types/input.js +2 -0
- package/dist/types/navigation.d.ts +15 -0
- package/package.json +1 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { setContext } from 'svelte';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
value?: string | string[];
|
|
6
|
+
multiple?: boolean;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
class?: string;
|
|
9
|
+
children?: import('svelte').Snippet;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
value = $bindable([]),
|
|
14
|
+
multiple = false,
|
|
15
|
+
disabled = false,
|
|
16
|
+
class: className = '',
|
|
17
|
+
children
|
|
18
|
+
}: Props = $props();
|
|
19
|
+
|
|
20
|
+
// Normalize value to always work with arrays internally
|
|
21
|
+
let expandedItems = $derived.by(() => {
|
|
22
|
+
if (Array.isArray(value)) {
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
return value ? [value] : [];
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Context key
|
|
29
|
+
const ACCORDION_KEY = Symbol('accordion');
|
|
30
|
+
|
|
31
|
+
// Context API
|
|
32
|
+
const accordionContext = {
|
|
33
|
+
isExpanded: (itemValue: string): boolean => {
|
|
34
|
+
return expandedItems.includes(itemValue);
|
|
35
|
+
},
|
|
36
|
+
toggle: (itemValue: string): void => {
|
|
37
|
+
if (disabled) return;
|
|
38
|
+
|
|
39
|
+
const isCurrentlyExpanded = expandedItems.includes(itemValue);
|
|
40
|
+
|
|
41
|
+
if (multiple) {
|
|
42
|
+
// Multiple mode: toggle the item in the array
|
|
43
|
+
if (isCurrentlyExpanded) {
|
|
44
|
+
value = expandedItems.filter((v) => v !== itemValue) as typeof value;
|
|
45
|
+
} else {
|
|
46
|
+
value = [...expandedItems, itemValue] as typeof value;
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
// Single mode: replace with new value or clear
|
|
50
|
+
if (isCurrentlyExpanded) {
|
|
51
|
+
value = (Array.isArray(value) ? [] : '') as typeof value;
|
|
52
|
+
} else {
|
|
53
|
+
value = (Array.isArray(value) ? [itemValue] : itemValue) as typeof value;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
isDisabled: (): boolean => disabled
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
setContext(ACCORDION_KEY, accordionContext);
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<div class="accordion {className}" role="presentation">
|
|
64
|
+
{#if children}
|
|
65
|
+
{@render children()}
|
|
66
|
+
{/if}
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<style>
|
|
70
|
+
.accordion {
|
|
71
|
+
display: flex;
|
|
72
|
+
flex-direction: column;
|
|
73
|
+
width: 100%;
|
|
74
|
+
border: 1px solid var(--color-border, #e5e7eb);
|
|
75
|
+
border-radius: var(--radius-md, 0.375rem);
|
|
76
|
+
background: var(--color-bg-card, #ffffff);
|
|
77
|
+
overflow: hidden;
|
|
78
|
+
}
|
|
79
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
value?: string | string[];
|
|
3
|
+
multiple?: boolean;
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
class?: string;
|
|
6
|
+
children?: import('svelte').Snippet;
|
|
7
|
+
}
|
|
8
|
+
declare const Accordion: import("svelte").Component<Props, {}, "value">;
|
|
9
|
+
type Accordion = ReturnType<typeof Accordion>;
|
|
10
|
+
export default Accordion;
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getContext } from 'svelte';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
value: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
class?: string;
|
|
8
|
+
header?: import('svelte').Snippet;
|
|
9
|
+
children?: import('svelte').Snippet;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { value, disabled = false, class: className = '', header, children }: Props = $props();
|
|
13
|
+
|
|
14
|
+
// Context key (must match parent)
|
|
15
|
+
const ACCORDION_KEY = Symbol('accordion');
|
|
16
|
+
|
|
17
|
+
// Get context from parent Accordion
|
|
18
|
+
const ctx = getContext<{
|
|
19
|
+
isExpanded: (value: string) => boolean;
|
|
20
|
+
toggle: (value: string) => void;
|
|
21
|
+
isDisabled: () => boolean;
|
|
22
|
+
}>(ACCORDION_KEY);
|
|
23
|
+
|
|
24
|
+
// Generate unique IDs for ARIA (using $derived to avoid warnings)
|
|
25
|
+
const headerId = $derived(`accordion-header-${value}`);
|
|
26
|
+
const bodyId = $derived(`accordion-body-${value}`);
|
|
27
|
+
|
|
28
|
+
// Derived states
|
|
29
|
+
const isExpanded = $derived(ctx.isExpanded(value));
|
|
30
|
+
const isDisabled = $derived(disabled || ctx.isDisabled());
|
|
31
|
+
|
|
32
|
+
// Toggle handler
|
|
33
|
+
function handleToggle() {
|
|
34
|
+
if (!isDisabled) {
|
|
35
|
+
ctx.toggle(value);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Keyboard handler
|
|
40
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
41
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
42
|
+
event.preventDefault();
|
|
43
|
+
handleToggle();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Body element reference for height animation
|
|
48
|
+
let bodyElement: HTMLDivElement | undefined = $state();
|
|
49
|
+
|
|
50
|
+
// Height calculation for smooth animation
|
|
51
|
+
const contentHeight = $derived.by(() => {
|
|
52
|
+
if (!bodyElement) return '0px';
|
|
53
|
+
if (!isExpanded) return '0px';
|
|
54
|
+
|
|
55
|
+
// Get the actual scrollHeight when expanded
|
|
56
|
+
const height = bodyElement.scrollHeight;
|
|
57
|
+
return `${height}px`;
|
|
58
|
+
});
|
|
59
|
+
</script>
|
|
60
|
+
|
|
61
|
+
<div class="accordion-item {className}">
|
|
62
|
+
<button
|
|
63
|
+
id={headerId}
|
|
64
|
+
class="accordion-header"
|
|
65
|
+
type="button"
|
|
66
|
+
aria-expanded={isExpanded}
|
|
67
|
+
aria-controls={bodyId}
|
|
68
|
+
disabled={isDisabled}
|
|
69
|
+
onclick={handleToggle}
|
|
70
|
+
onkeydown={handleKeydown}
|
|
71
|
+
>
|
|
72
|
+
<span class="accordion-header__content">
|
|
73
|
+
{#if header}
|
|
74
|
+
{@render header()}
|
|
75
|
+
{/if}
|
|
76
|
+
</span>
|
|
77
|
+
<svg
|
|
78
|
+
class="accordion-header__chevron"
|
|
79
|
+
class:accordion-header__chevron--expanded={isExpanded}
|
|
80
|
+
width="20"
|
|
81
|
+
height="20"
|
|
82
|
+
viewBox="0 0 20 20"
|
|
83
|
+
fill="none"
|
|
84
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
85
|
+
aria-hidden="true"
|
|
86
|
+
>
|
|
87
|
+
<path
|
|
88
|
+
d="M5 7.5L10 12.5L15 7.5"
|
|
89
|
+
stroke="currentColor"
|
|
90
|
+
stroke-width="2"
|
|
91
|
+
stroke-linecap="round"
|
|
92
|
+
stroke-linejoin="round"
|
|
93
|
+
/>
|
|
94
|
+
</svg>
|
|
95
|
+
</button>
|
|
96
|
+
|
|
97
|
+
<div
|
|
98
|
+
bind:this={bodyElement}
|
|
99
|
+
id={bodyId}
|
|
100
|
+
class="accordion-body"
|
|
101
|
+
class:accordion-body--expanded={isExpanded}
|
|
102
|
+
role="region"
|
|
103
|
+
aria-labelledby={headerId}
|
|
104
|
+
style="--content-height: {contentHeight}"
|
|
105
|
+
>
|
|
106
|
+
<div class="accordion-body__content">
|
|
107
|
+
{#if children}
|
|
108
|
+
{@render children()}
|
|
109
|
+
{/if}
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<style>
|
|
115
|
+
.accordion-item {
|
|
116
|
+
border-bottom: 1px solid var(--color-border, #e5e7eb);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.accordion-item:last-child {
|
|
120
|
+
border-bottom: none;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Header */
|
|
124
|
+
.accordion-header {
|
|
125
|
+
display: flex;
|
|
126
|
+
align-items: center;
|
|
127
|
+
justify-content: space-between;
|
|
128
|
+
width: 100%;
|
|
129
|
+
min-height: var(--touch-target-min, 44px);
|
|
130
|
+
padding: var(--space-md, 1rem);
|
|
131
|
+
border: none;
|
|
132
|
+
background: transparent;
|
|
133
|
+
color: var(--color-text, #1f2937);
|
|
134
|
+
font-family: inherit;
|
|
135
|
+
font-size: var(--text-base, 1rem);
|
|
136
|
+
font-weight: var(--font-medium, 500);
|
|
137
|
+
text-align: left;
|
|
138
|
+
cursor: pointer;
|
|
139
|
+
transition: background-color var(--transition-fast, 150ms ease);
|
|
140
|
+
-webkit-tap-highlight-color: transparent;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.accordion-header:hover:not(:disabled) {
|
|
144
|
+
background: var(--color-bg-hover, #f3f4f6);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.accordion-header:focus-visible {
|
|
148
|
+
outline: 2px solid var(--color-primary, #3b82f6);
|
|
149
|
+
outline-offset: -2px;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.accordion-header:disabled {
|
|
153
|
+
opacity: 0.5;
|
|
154
|
+
cursor: not-allowed;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.accordion-header__content {
|
|
158
|
+
flex: 1;
|
|
159
|
+
display: flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.accordion-header__chevron {
|
|
164
|
+
flex-shrink: 0;
|
|
165
|
+
margin-left: var(--space-sm, 0.5rem);
|
|
166
|
+
color: var(--color-text-muted, #6b7280);
|
|
167
|
+
transition: transform var(--transition-base, 200ms ease);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.accordion-header__chevron--expanded {
|
|
171
|
+
transform: rotate(180deg);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* Body */
|
|
175
|
+
.accordion-body {
|
|
176
|
+
max-height: 0;
|
|
177
|
+
overflow: hidden;
|
|
178
|
+
transition: max-height var(--transition-base, 200ms ease);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.accordion-body--expanded {
|
|
182
|
+
max-height: var(--content-height);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.accordion-body__content {
|
|
186
|
+
padding: 0 var(--space-md, 1rem) var(--space-md, 1rem);
|
|
187
|
+
color: var(--color-text-muted, #6b7280);
|
|
188
|
+
font-size: var(--text-sm, 0.875rem);
|
|
189
|
+
line-height: var(--leading-normal, 1.5);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* Mobile optimization - ensure min touch target */
|
|
193
|
+
@media (max-width: 640px) {
|
|
194
|
+
.accordion-header {
|
|
195
|
+
min-height: var(--touch-target-min, 44px);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
value: string;
|
|
3
|
+
disabled?: boolean;
|
|
4
|
+
class?: string;
|
|
5
|
+
header?: import('svelte').Snippet;
|
|
6
|
+
children?: import('svelte').Snippet;
|
|
7
|
+
}
|
|
8
|
+
declare const AccordionItem: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type AccordionItem = ReturnType<typeof AccordionItem>;
|
|
10
|
+
export default AccordionItem;
|