@juspay/svelte-ui-components 2.10.0 → 2.11.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 +337 -77
- package/dist/Accordion/Accordion.svelte +4 -2
- package/dist/Accordion/Accordion.svelte.d.ts +2 -4
- package/dist/Accordion/properties.d.ts +6 -0
- package/dist/Accordion/properties.js +1 -0
- package/dist/Animations/ModalAnimation.svelte +11 -9
- package/dist/Avatar/Avatar.svelte +122 -0
- package/dist/Avatar/Avatar.svelte.d.ts +4 -0
- package/dist/Avatar/properties.d.ts +15 -0
- package/dist/Avatar/properties.js +1 -0
- package/dist/Badge/Badge.svelte +2 -2
- package/dist/Badge/properties.d.ts +1 -0
- package/dist/Banner/Banner.svelte +132 -48
- package/dist/Banner/Banner.svelte.d.ts +1 -1
- package/dist/Banner/properties.d.ts +8 -3
- package/dist/Book/Book.svelte +281 -0
- package/dist/Book/Book.svelte.d.ts +4 -0
- package/dist/Book/properties.d.ts +24 -0
- package/dist/Book/properties.js +1 -0
- package/dist/BrandLoader/BrandLoader.svelte +3 -3
- package/dist/BrandLoader/properties.d.ts +1 -0
- package/dist/Browser/Browser.svelte +193 -0
- package/dist/Browser/Browser.svelte.d.ts +3 -0
- package/dist/Browser/properties.d.ts +16 -0
- package/dist/Browser/properties.js +1 -0
- package/dist/Button/Button.svelte +20 -7
- package/dist/Button/properties.d.ts +7 -4
- package/dist/Calendar/Calendar.svelte +476 -0
- package/dist/Calendar/Calendar.svelte.d.ts +4 -0
- package/dist/Calendar/properties.d.ts +30 -0
- package/dist/Calendar/properties.js +1 -0
- package/dist/Carousel/Carousel.svelte +19 -16
- package/dist/Carousel/properties.d.ts +1 -0
- package/dist/CheckListItem/CheckListItem.svelte +31 -26
- package/dist/CheckListItem/properties.d.ts +4 -1
- package/dist/Checkbox/Checkbox.svelte +157 -0
- package/dist/Checkbox/Checkbox.svelte.d.ts +4 -0
- package/dist/Checkbox/properties.d.ts +17 -0
- package/dist/Checkbox/properties.js +1 -0
- package/dist/Choicebox/Choicebox.svelte +85 -0
- package/dist/Choicebox/Choicebox.svelte.d.ts +4 -0
- package/dist/Choicebox/properties.d.ts +14 -0
- package/dist/Choicebox/properties.js +1 -0
- package/dist/CommandMenu/CommandMenu.svelte +452 -0
- package/dist/CommandMenu/CommandMenu.svelte.d.ts +4 -0
- package/dist/CommandMenu/properties.d.ts +26 -0
- package/dist/CommandMenu/properties.js +1 -0
- package/dist/ContextMenu/ContextMenu.svelte +308 -0
- package/dist/ContextMenu/ContextMenu.svelte.d.ts +4 -0
- package/dist/ContextMenu/properties.d.ts +26 -0
- package/dist/ContextMenu/properties.js +1 -0
- package/dist/Gauge/Gauge.svelte +70 -0
- package/dist/Gauge/Gauge.svelte.d.ts +4 -0
- package/dist/Gauge/properties.d.ts +9 -0
- package/dist/Gauge/properties.js +1 -0
- package/dist/GridItem/GridItem.svelte +5 -4
- package/dist/GridItem/properties.d.ts +1 -0
- package/dist/Icon/Icon.svelte +3 -3
- package/dist/Icon/properties.d.ts +1 -0
- package/dist/IconStack/IconStack.svelte +3 -3
- package/dist/IconStack/properties.d.ts +1 -0
- package/dist/Img/Img.svelte +5 -3
- package/dist/Img/properties.d.ts +5 -1
- package/dist/Input/Input.svelte +12 -6
- package/dist/Input/properties.d.ts +1 -0
- package/dist/InputButton/InputButton.svelte +4 -3
- package/dist/InputButton/properties.d.ts +5 -6
- package/dist/KeyboardInput/KeyboardInput.svelte +93 -0
- package/dist/KeyboardInput/KeyboardInput.svelte.d.ts +4 -0
- package/dist/KeyboardInput/properties.d.ts +12 -0
- package/dist/KeyboardInput/properties.js +1 -0
- package/dist/ListItem/ListItem.svelte +31 -28
- package/dist/ListItem/properties.d.ts +1 -0
- package/dist/Loader/Loader.svelte +10 -6
- package/dist/Loader/Loader.svelte.d.ts +3 -25
- package/dist/Loader/properties.d.ts +3 -0
- package/dist/Loader/properties.js +1 -0
- package/dist/LoadingDots/LoadingDots.svelte +64 -0
- package/dist/LoadingDots/LoadingDots.svelte.d.ts +3 -0
- package/dist/LoadingDots/properties.d.ts +8 -0
- package/dist/LoadingDots/properties.js +1 -0
- package/dist/Menu/Menu.svelte +349 -0
- package/dist/Menu/Menu.svelte.d.ts +4 -0
- package/dist/Menu/properties.d.ts +24 -0
- package/dist/Menu/properties.js +1 -0
- package/dist/Modal/Modal.svelte +10 -9
- package/dist/Modal/properties.d.ts +1 -0
- package/dist/Pagination/Pagination.svelte +152 -0
- package/dist/Pagination/Pagination.svelte.d.ts +4 -0
- package/dist/Pagination/properties.d.ts +14 -0
- package/dist/Pagination/properties.js +1 -0
- package/dist/Phone/Phone.svelte +234 -0
- package/dist/Phone/Phone.svelte.d.ts +3 -0
- package/dist/Phone/properties.d.ts +11 -0
- package/dist/Phone/properties.js +1 -0
- package/dist/Pill/Pill.svelte +130 -0
- package/dist/Pill/Pill.svelte.d.ts +4 -0
- package/dist/Pill/properties.d.ts +16 -0
- package/dist/Pill/properties.js +1 -0
- package/dist/Progress/Progress.svelte +68 -0
- package/dist/Progress/Progress.svelte.d.ts +4 -0
- package/dist/Progress/properties.d.ts +10 -0
- package/dist/Progress/properties.js +1 -0
- package/dist/Radio/Radio.svelte +128 -0
- package/dist/Radio/Radio.svelte.d.ts +4 -0
- package/dist/Radio/properties.d.ts +15 -0
- package/dist/Radio/properties.js +1 -0
- package/dist/RelativeTime/RelativeTime.svelte +117 -0
- package/dist/RelativeTime/RelativeTime.svelte.d.ts +4 -0
- package/dist/RelativeTime/properties.d.ts +13 -0
- package/dist/RelativeTime/properties.js +1 -0
- package/dist/Scroller/Scroller.svelte +389 -0
- package/dist/Scroller/Scroller.svelte.d.ts +4 -0
- package/dist/Scroller/properties.d.ts +30 -0
- package/dist/Scroller/properties.js +1 -0
- package/dist/Select/Select.svelte +382 -344
- package/dist/Select/Select.svelte.d.ts +1 -1
- package/dist/Select/properties.d.ts +16 -26
- package/dist/Sheet/Sheet.svelte +264 -0
- package/dist/Sheet/Sheet.svelte.d.ts +4 -0
- package/dist/Sheet/properties.d.ts +19 -0
- package/dist/Sheet/properties.js +1 -0
- package/dist/Shimmer/Shimmer.svelte +44 -0
- package/dist/Shimmer/Shimmer.svelte.d.ts +4 -0
- package/dist/Shimmer/properties.d.ts +4 -0
- package/dist/Shimmer/properties.js +1 -0
- package/dist/Slider/Slider.svelte +144 -0
- package/dist/Slider/Slider.svelte.d.ts +4 -0
- package/dist/Slider/properties.d.ts +17 -0
- package/dist/Slider/properties.js +1 -0
- package/dist/Snippet/Snippet.svelte +123 -0
- package/dist/Snippet/Snippet.svelte.d.ts +4 -0
- package/dist/Snippet/properties.d.ts +15 -0
- package/dist/Snippet/properties.js +1 -0
- package/dist/SplitButton/SplitButton.svelte +135 -0
- package/dist/SplitButton/SplitButton.svelte.d.ts +4 -0
- package/dist/SplitButton/properties.d.ts +17 -0
- package/dist/SplitButton/properties.js +1 -0
- package/dist/Status/Status.svelte +5 -3
- package/dist/Status/properties.d.ts +1 -0
- package/dist/Stepper/Step.svelte +3 -3
- package/dist/Stepper/Stepper.svelte +3 -3
- package/dist/Stepper/properties.d.ts +2 -0
- package/dist/Table/Table.svelte +15 -8
- package/dist/Table/properties.d.ts +1 -0
- package/dist/Tabs/Tabs.svelte +240 -0
- package/dist/Tabs/Tabs.svelte.d.ts +4 -0
- package/dist/Tabs/properties.d.ts +16 -0
- package/dist/Tabs/properties.js +1 -0
- package/dist/ThemeSwitcher/ThemeSwitcher.svelte +249 -0
- package/dist/ThemeSwitcher/ThemeSwitcher.svelte.d.ts +4 -0
- package/dist/ThemeSwitcher/properties.d.ts +19 -0
- package/dist/ThemeSwitcher/properties.js +1 -0
- package/dist/Toast/Toast.svelte +25 -30
- package/dist/Toast/properties.d.ts +1 -0
- package/dist/Toggle/Toggle.svelte +2 -2
- package/dist/Toggle/properties.d.ts +1 -0
- package/dist/Toolbar/Toolbar.svelte +8 -7
- package/dist/Toolbar/properties.d.ts +1 -0
- package/dist/Tooltip/Tooltip.svelte +153 -0
- package/dist/Tooltip/Tooltip.svelte.d.ts +4 -0
- package/dist/Tooltip/properties.d.ts +13 -0
- package/dist/Tooltip/properties.js +1 -0
- package/dist/assets/battery.svg +5 -0
- package/dist/assets/checkmark.svg +3 -0
- package/dist/assets/chevron-down-sm.svg +3 -0
- package/dist/assets/chevron-down.svg +3 -0
- package/dist/assets/chevron-left-lg.svg +3 -0
- package/dist/assets/chevron-left.svg +3 -0
- package/dist/assets/chevron-right-lg.svg +3 -0
- package/dist/assets/chevron-right.svg +3 -0
- package/dist/assets/chevron-up.svg +3 -0
- package/dist/assets/close.svg +4 -0
- package/dist/assets/copy.svg +4 -0
- package/dist/assets/error-circle.svg +5 -0
- package/dist/assets/lock.svg +3 -0
- package/dist/assets/minus.svg +3 -0
- package/dist/assets/monitor.svg +5 -0
- package/dist/assets/moon.svg +3 -0
- package/dist/assets/palette.svg +7 -0
- package/dist/assets/search.svg +4 -0
- package/dist/assets/signal.svg +6 -0
- package/dist/assets/sun.svg +11 -0
- package/dist/assets/wifi.svg +3 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +27 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +18 -4
- package/package.json +8 -1
package/README.md
CHANGED
|
@@ -1,114 +1,374 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @juspay/svelte-ui-components
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
This library is publish on npm & can be installed via any npm client.
|
|
8
|
-
Use the following command to install the library.
|
|
3
|
+
A themeable Svelte 5 component library where **every visual property is a CSS custom property**. Build any design system on top — no source changes needed.
|
|
9
4
|
|
|
10
5
|
```bash
|
|
11
6
|
npm install @juspay/svelte-ui-components
|
|
12
7
|
```
|
|
13
8
|
|
|
14
|
-
|
|
9
|
+
Requires `svelte ^5.41.2` and `type-decoder ^2.1.0` as peer dependencies.
|
|
10
|
+
|
|
11
|
+
---
|
|
15
12
|
|
|
16
|
-
|
|
13
|
+
## Why This Library?
|
|
17
14
|
|
|
18
|
-
|
|
15
|
+
Most component libraries ship with a fixed look. Changing it means fighting overrides, patching internals, or forking.
|
|
16
|
+
|
|
17
|
+
This library takes a different approach: **components are unstyled by default** and expose every visual decision — colors, spacing, typography, borders, shadows, radii — as CSS custom properties. You define the design system. The components render it.
|
|
18
|
+
|
|
19
|
+
```svelte
|
|
20
|
+
<!-- A button that looks however you want -->
|
|
21
|
+
<div class="my-theme">
|
|
22
|
+
<Button text="Continue" onclick={handleClick} />
|
|
23
|
+
</div>
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- Select
|
|
34
|
-
- Status Screen
|
|
35
|
-
- Table
|
|
36
|
-
- Toggle
|
|
37
|
-
- Toolbar
|
|
25
|
+
<style>
|
|
26
|
+
.my-theme {
|
|
27
|
+
--button-color: #000;
|
|
28
|
+
--button-text-color: #fff;
|
|
29
|
+
--button-border-radius: 8px;
|
|
30
|
+
--button-padding: 12px 24px;
|
|
31
|
+
--button-font-size: 14px;
|
|
32
|
+
--button-font-weight: 600;
|
|
33
|
+
--button-hover-color: #222;
|
|
34
|
+
--button-border: 1px solid #333;
|
|
35
|
+
}
|
|
36
|
+
</style>
|
|
37
|
+
```
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
---
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
## Quick Start
|
|
42
42
|
|
|
43
43
|
```svelte
|
|
44
44
|
<script lang="ts">
|
|
45
|
-
import { Button,
|
|
45
|
+
import { Button, Input, Toggle, Toast } from '@juspay/svelte-ui-components';
|
|
46
46
|
</script>
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
<!-- Basic button -->
|
|
49
|
+
<Button text="Submit" onclick={() => console.log('clicked')} />
|
|
50
|
+
|
|
51
|
+
<!-- Input with validation -->
|
|
52
|
+
<Input
|
|
53
|
+
value=""
|
|
54
|
+
placeholder="Enter email"
|
|
55
|
+
dataType="email"
|
|
56
|
+
onStateChange={(state) => console.log(state)}
|
|
57
|
+
/>
|
|
58
|
+
|
|
59
|
+
<!-- Toggle switch -->
|
|
60
|
+
<Toggle checked={false} text="Dark mode" onclick={(val) => console.log(val)} />
|
|
49
61
|
```
|
|
50
62
|
|
|
51
|
-
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Components
|
|
66
|
+
|
|
67
|
+
### Inputs & Form Controls
|
|
68
|
+
|
|
69
|
+
| Component | Description | Docs |
|
|
70
|
+
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------------- |
|
|
71
|
+
| **Button** | Action trigger with circular loader, progress bar, icon/children snippets, and aria-expanded support. | [docs](docs/Button.md) |
|
|
72
|
+
| **Input** | Text field with built-in validation for email, phone, password, and custom patterns. Supports text transformers and textarea mode. | [docs](docs/Input.md) |
|
|
73
|
+
| **InputButton** | Input field fused with action buttons — for search bars, OTP entry, coupon codes. | [docs](docs/InputButton.md) |
|
|
74
|
+
| **Select** | Dropdown picker with single-select (with search), multi-select (checkboxes + Select All + Apply), and custom content slots. | [docs](docs/Select.md) |
|
|
75
|
+
| **Toggle** | Labeled on/off switch with sliding ball animation. | [docs](docs/Toggle.md) |
|
|
76
|
+
| **Checkbox** | Styled checkbox input with custom SVG checkmark. | [docs](docs/Checkbox.md) |
|
|
77
|
+
| **Radio** | Styled radio button with custom circular indicator. | [docs](docs/Radio.md) |
|
|
78
|
+
| **Slider** | Range slider with configurable min, max, step, and optional value display. | [docs](docs/Slider.md) |
|
|
79
|
+
| **Choicebox** | Selectable option group with single-select (radio) or multi-select (checkbox) behavior and custom content. | [docs](docs/Choicebox.md) |
|
|
80
|
+
|
|
81
|
+
### Display & Data
|
|
82
|
+
|
|
83
|
+
| Component | Description | Docs |
|
|
84
|
+
| ---------------- | ----------------------------------------------------------------------------------------------- | ---------------------------- |
|
|
85
|
+
| **Avatar** | Circular avatar with image (Img with fallback) or text initial. | [docs](docs/Avatar.md) |
|
|
86
|
+
| **Badge** | Icon with a numeric/text badge overlay in the corner. | [docs](docs/Badge.md) |
|
|
87
|
+
| **GridItem** | Grid cell with icon, label, and loading overlay animation. | [docs](docs/GridItem.md) |
|
|
88
|
+
| **Icon** | Clickable icon with optional text label. | [docs](docs/Icon.md) |
|
|
89
|
+
| **IconStack** | Layered horizontal stack of overlapping circular icons/avatars. | [docs](docs/IconStack.md) |
|
|
90
|
+
| **Img** | Image with automatic fallback on load error. | [docs](docs/Img.md) |
|
|
91
|
+
| **ListItem** | Multi-section list row with images, labels, and accordion expansion. | [docs](docs/ListItem.md) |
|
|
92
|
+
| **Pill** | Compact label/tag for status or categories, optionally clickable with a11y. | [docs](docs/Pill.md) |
|
|
93
|
+
| **Status** | Full-screen status display for success/failure screens. | [docs](docs/Status.md) |
|
|
94
|
+
| **Table** | Sortable data table with sticky headers and per-cell scrolling. | [docs](docs/Table.md) |
|
|
95
|
+
| **RelativeTime** | Auto-updating relative time display ("5 minutes ago") with locale support and optional tooltip. | [docs](docs/RelativeTime.md) |
|
|
96
|
+
|
|
97
|
+
### Feedback & Loading
|
|
98
|
+
|
|
99
|
+
| Component | Description | Docs |
|
|
100
|
+
| --------------- | ----------------------------------------------------------------------------------------------- | --------------------------- |
|
|
101
|
+
| **Banner** | Sticky notification banner with icon snippet, dismiss button, link text, and click interaction. | [docs](docs/Banner.md) |
|
|
102
|
+
| **BrandLoader** | Full-screen branded splash/loading animation. | [docs](docs/BrandLoader.md) |
|
|
103
|
+
| **Loader** | Circular spinner with gradient foreground. | [docs](docs/Loader.md) |
|
|
104
|
+
| **LoadingDots** | Animated inline dot sequence with bounce/pulse animations. | [docs](docs/LoadingDots.md) |
|
|
105
|
+
| **Shimmer** | Loading placeholder with animated shimmer effect. All visuals via CSS variables. | [docs](docs/Shimmer.md) |
|
|
106
|
+
| **Toast** | Animated slide-in notification with type variants and auto-dismiss. | [docs](docs/Toast.md) |
|
|
107
|
+
| **Progress** | Horizontal progress bar with animated fill. | [docs](docs/Progress.md) |
|
|
108
|
+
| **Gauge** | Semicircular gauge/meter with configurable segments and animated value. | [docs](docs/Gauge.md) |
|
|
109
|
+
|
|
110
|
+
### Overlays & Panels
|
|
111
|
+
|
|
112
|
+
| Component | Description | Docs |
|
|
113
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------- | -------------------------------- |
|
|
114
|
+
| **Modal** | Dialog overlay with configurable size, alignment, header, footer, transitions, and back-press support. | [docs](docs/Modal.md) |
|
|
115
|
+
| **ModalAnimation** | Fly/fade transition wrapper for modal content. | [docs](docs/ModalAnimation.md) |
|
|
116
|
+
| **OverlayAnimation** | Fade transition wrapper for overlay backgrounds. | [docs](docs/OverlayAnimation.md) |
|
|
117
|
+
| **Sheet** | Slide-in panel from any edge (left/right/top/bottom) with header, scrollable content, footer, and focus trap. | [docs](docs/Sheet.md) |
|
|
118
|
+
| **CommandMenu** | Command palette (Ctrl+K) with fuzzy search, grouped commands, and keyboard navigation. | [docs](docs/CommandMenu.md) |
|
|
119
|
+
| **ContextMenu** | Right-click context menu with nested submenus, separators, and keyboard navigation. | [docs](docs/ContextMenu.md) |
|
|
120
|
+
| **Menu** | Dropdown action menu with keyboard navigation, typeahead, disabled/danger items, and separators. | [docs](docs/Menu.md) |
|
|
121
|
+
| **Tooltip** | Hover-triggered tooltip with configurable position and delay. | [docs](docs/Tooltip.md) |
|
|
122
|
+
|
|
123
|
+
### Navigation & Structure
|
|
52
124
|
|
|
53
|
-
|
|
54
|
-
|
|
125
|
+
| Component | Description | Docs |
|
|
126
|
+
| ----------------- | ---------------------------------------------------------------------------------------------- | ----------------------------- |
|
|
127
|
+
| **Accordion** | Expandable/collapsible container with CSS grid animation. | [docs](docs/Accordion.md) |
|
|
128
|
+
| **Carousel** | Horizontal content slider with swipe and pagination dots. | [docs](docs/Carousel.md) |
|
|
129
|
+
| **CheckListItem** | Checklist row with checkbox, label, and toggleable checked state. | [docs](docs/CheckListItem.md) |
|
|
130
|
+
| **Pagination** | Page navigation with previous/next buttons and numbered page links. | [docs](docs/Pagination.md) |
|
|
131
|
+
| **Scroller** | Overflowing item list with arrow navigation, gradient edges, drag-to-scroll, and snap support. | [docs](docs/Scroller.md) |
|
|
132
|
+
| **Stepper** | Multi-step progress indicator with completed, active, and pending states. | [docs](docs/Stepper.md) |
|
|
133
|
+
| **Step** | Individual step within a Stepper — renders number, label, and connector. | [docs](docs/Step.md) |
|
|
134
|
+
| **Tabs** | Tabbed interface with animated active indicator. | [docs](docs/Tabs.md) |
|
|
135
|
+
| **Toolbar** | Fixed header bar with back button, title, and customizable content areas. | [docs](docs/Toolbar.md) |
|
|
55
136
|
|
|
56
|
-
|
|
137
|
+
### Actions
|
|
57
138
|
|
|
58
|
-
|
|
59
|
-
|
|
139
|
+
| Component | Description | Docs |
|
|
140
|
+
| ----------------- | ------------------------------------------------------------------------- | ----------------------------- |
|
|
141
|
+
| **Snippet** | Copyable command-line snippet with prompt prefix and copy button. | [docs](docs/Snippet.md) |
|
|
142
|
+
| **SplitButton** | Primary action button with dropdown secondary actions via Menu component. | [docs](docs/SplitButton.md) |
|
|
143
|
+
| **KeyboardInput** | Keyboard shortcut display with styled key caps. | [docs](docs/KeyboardInput.md) |
|
|
144
|
+
| **ThemeSwitcher** | Segmented control for light/dark/system theme switching. | [docs](docs/ThemeSwitcher.md) |
|
|
60
145
|
|
|
61
|
-
|
|
146
|
+
### Decorative
|
|
62
147
|
|
|
63
|
-
|
|
64
|
-
|
|
148
|
+
| Component | Description | Docs |
|
|
149
|
+
| ----------- | ------------------------------------------------ | ----------------------- |
|
|
150
|
+
| **Book** | 3D book display with animated page turning. | [docs](docs/Book.md) |
|
|
151
|
+
| **Browser** | Browser window chrome frame for content display. | [docs](docs/Browser.md) |
|
|
152
|
+
| **Phone** | Smartphone device frame for app previews. | [docs](docs/Phone.md) |
|
|
65
153
|
|
|
66
|
-
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Theming
|
|
157
|
+
|
|
158
|
+
### How It Works
|
|
159
|
+
|
|
160
|
+
Every component reads its visual properties from CSS custom properties with sensible defaults. To create a theme, define the variables on any ancestor element:
|
|
161
|
+
|
|
162
|
+
```css
|
|
163
|
+
/* theme.css */
|
|
164
|
+
.my-design-system {
|
|
165
|
+
/* Button */
|
|
166
|
+
--button-color: #0070f3;
|
|
167
|
+
--button-text-color: #fff;
|
|
168
|
+
--button-border-radius: 6px;
|
|
169
|
+
--button-padding: 10px 20px;
|
|
170
|
+
--button-font-family: 'Inter', sans-serif;
|
|
171
|
+
--button-font-size: 14px;
|
|
172
|
+
--button-hover-color: #0060df;
|
|
173
|
+
|
|
174
|
+
/* Input */
|
|
175
|
+
--input-background: #fafafa;
|
|
176
|
+
--input-border: 1px solid #eaeaea;
|
|
177
|
+
--input-radius: 6px;
|
|
178
|
+
--input-font-family: 'Inter', sans-serif;
|
|
179
|
+
--input-focus-border: 1px solid #0070f3;
|
|
180
|
+
|
|
181
|
+
/* Toast */
|
|
182
|
+
--toast-border-radius: 8px;
|
|
183
|
+
--toast-font-family: 'Inter', sans-serif;
|
|
184
|
+
--toast-success-background-color: #0070f3;
|
|
185
|
+
|
|
186
|
+
/* Modal */
|
|
187
|
+
--modal-border-radius: 12px;
|
|
188
|
+
--modal-content-background-color: #fff;
|
|
189
|
+
--background-color: #00000066;
|
|
190
|
+
}
|
|
191
|
+
```
|
|
67
192
|
|
|
68
193
|
```svelte
|
|
69
|
-
<
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
</script>
|
|
194
|
+
<div class="my-design-system">
|
|
195
|
+
<Button text="Save" onclick={save} />
|
|
196
|
+
<Input value="" placeholder="Search..." />
|
|
197
|
+
</div>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Scoped Theming
|
|
201
|
+
|
|
202
|
+
Because CSS variables cascade, you can scope different themes to different parts of your app:
|
|
203
|
+
|
|
204
|
+
```svelte
|
|
205
|
+
<div class="light-theme">
|
|
206
|
+
<Button text="Light" onclick={handleClick} />
|
|
207
|
+
</div>
|
|
85
208
|
|
|
86
|
-
<div class="
|
|
87
|
-
<Button
|
|
209
|
+
<div class="dark-theme">
|
|
210
|
+
<Button text="Dark" onclick={handleClick} />
|
|
88
211
|
</div>
|
|
89
212
|
|
|
90
213
|
<style>
|
|
91
|
-
.
|
|
92
|
-
--button-color:
|
|
93
|
-
--button-text-color:
|
|
94
|
-
|
|
214
|
+
.light-theme {
|
|
215
|
+
--button-color: #fff;
|
|
216
|
+
--button-text-color: #000;
|
|
217
|
+
--button-border: 1px solid #eaeaea;
|
|
218
|
+
}
|
|
219
|
+
.dark-theme {
|
|
220
|
+
--button-color: #111;
|
|
221
|
+
--button-text-color: #fff;
|
|
222
|
+
--button-border: 1px solid #333;
|
|
95
223
|
}
|
|
96
224
|
</style>
|
|
97
225
|
```
|
|
98
226
|
|
|
99
|
-
###
|
|
227
|
+
### CSS Variable Reference
|
|
228
|
+
|
|
229
|
+
Each component documents its full set of CSS variables in the [docs/](docs/) directory. The variable naming convention follows the pattern:
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
--{component}-{element}-{property}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
For example:
|
|
236
|
+
|
|
237
|
+
- `--button-color` — button background color
|
|
238
|
+
- `--input-error-msg-text-color` — input error message text color
|
|
239
|
+
- `--modal-footer-primary-button-border-radius` — border radius of the primary button inside a modal footer
|
|
240
|
+
- `--toast-success-background-color` — background color for success variant toasts
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Props & Types
|
|
245
|
+
|
|
246
|
+
Components use a typed props pattern split into mandatory, optional, and event properties:
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
// Every component follows this pattern
|
|
250
|
+
type ButtonProperties = OptionalButtonProperties & ButtonEventProperties;
|
|
251
|
+
|
|
252
|
+
type OptionalButtonProperties = {
|
|
253
|
+
text?: string;
|
|
254
|
+
enable?: boolean;
|
|
255
|
+
disabled?: boolean;
|
|
256
|
+
showLoader?: boolean;
|
|
257
|
+
loaderType?: 'Circular' | 'ProgressBar';
|
|
258
|
+
type?: 'submit' | 'reset' | 'button';
|
|
259
|
+
icon?: Snippet;
|
|
260
|
+
children?: Snippet;
|
|
261
|
+
ariaLabel?: string;
|
|
262
|
+
ariaExpanded?: boolean;
|
|
263
|
+
// ...
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
type ButtonEventProperties = {
|
|
267
|
+
onclick?: (event: MouseEvent) => void;
|
|
268
|
+
onkeyup?: (event: KeyboardEvent) => void;
|
|
269
|
+
};
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
All types are exported from the package:
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
import type {
|
|
276
|
+
ButtonProperties,
|
|
277
|
+
InputProperties,
|
|
278
|
+
ModalProperties,
|
|
279
|
+
SelectProperties,
|
|
280
|
+
ToastProperties,
|
|
281
|
+
MenuItem,
|
|
282
|
+
SheetSide
|
|
283
|
+
// ...
|
|
284
|
+
} from '@juspay/svelte-ui-components';
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Svelte 5 Patterns
|
|
290
|
+
|
|
291
|
+
This library is built on Svelte 5 and uses its modern APIs:
|
|
292
|
+
|
|
293
|
+
- **`$props()`** for declaring component properties
|
|
294
|
+
- **`$state()`** and **`$derived()`** for reactive state
|
|
295
|
+
- **`$bindable()`** for two-way bound props (e.g., `Sheet.open`, `Banner.visible`, `Button.showProgressBar`)
|
|
296
|
+
- **`Snippet`** for composable content slots (e.g., `Button.icon`, `Sheet.content`, `Banner.rightContent`)
|
|
297
|
+
|
|
298
|
+
```svelte
|
|
299
|
+
<script lang="ts">
|
|
300
|
+
import { Sheet } from '@juspay/svelte-ui-components';
|
|
301
|
+
|
|
302
|
+
let open = $state(false);
|
|
303
|
+
</script>
|
|
304
|
+
|
|
305
|
+
<button onclick={() => (open = true)}>Open</button>
|
|
306
|
+
|
|
307
|
+
<Sheet bind:open title="Settings" side="right">
|
|
308
|
+
{#snippet content()}
|
|
309
|
+
<p>Sheet body goes here.</p>
|
|
310
|
+
{/snippet}
|
|
311
|
+
{#snippet footer()}
|
|
312
|
+
<button onclick={() => (open = false)}>Done</button>
|
|
313
|
+
{/snippet}
|
|
314
|
+
</Sheet>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## MCP Server
|
|
320
|
+
|
|
321
|
+
An MCP (Model Context Protocol) server ships as a separate package for AI-assisted development:
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
npm install @juspay/svelte-ui-components-mcp
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
It provides full component documentation — props, events, CSS variables, type references — through a standard MCP tool interface. Useful for integrating component knowledge into AI coding assistants.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Development
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
pnpm install # install dependencies
|
|
335
|
+
pnpm dev # start dev server with hot reload
|
|
336
|
+
pnpm build # build the library (vite + svelte-package + publint)
|
|
337
|
+
pnpm test # run integration + unit tests
|
|
338
|
+
pnpm lint # check formatting and lint rules
|
|
339
|
+
pnpm format # auto-format source files
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Project Structure
|
|
343
|
+
|
|
344
|
+
```
|
|
345
|
+
src/lib/
|
|
346
|
+
{Component}/
|
|
347
|
+
{Component}.svelte # component implementation
|
|
348
|
+
properties.ts # prop type definitions
|
|
349
|
+
types.ts # shared types (ValidationState, InputDataType, etc.)
|
|
350
|
+
utils.ts # shared utilities (validateInput, createDebouncer)
|
|
351
|
+
index.ts # public exports
|
|
352
|
+
|
|
353
|
+
docs/ # component documentation (one markdown file per component)
|
|
354
|
+
mcp/ # MCP server package (separate npm package)
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## Release
|
|
360
|
+
|
|
361
|
+
Pushing to the `release` branch triggers an automated CI pipeline:
|
|
362
|
+
|
|
363
|
+
1. Lints the codebase
|
|
364
|
+
2. Determines semver bump from conventional commit message (`feat:` = minor, `fix:` = patch, `!` = major)
|
|
365
|
+
3. Bumps `package.json` version and generates a changelog
|
|
366
|
+
4. Builds the package
|
|
367
|
+
5. Creates a GitHub release with a git tag
|
|
368
|
+
6. Publishes to npm (`--access public`)
|
|
100
369
|
|
|
101
|
-
|
|
102
|
-
- Install dependencies using `pnpm install`
|
|
103
|
-
- Make changes to the components
|
|
104
|
-
- Run tests using `pnpm run test`
|
|
105
|
-
- Commit the changes
|
|
106
|
-
- Push the changes
|
|
107
|
-
- Create a pull request
|
|
370
|
+
---
|
|
108
371
|
|
|
109
|
-
|
|
372
|
+
## License
|
|
110
373
|
|
|
111
|
-
|
|
112
|
-
- [ ] Add documentation for all components
|
|
113
|
-
- [ ] Add more components
|
|
114
|
-
- [ ] Add tests
|
|
374
|
+
MIT
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
2
|
+
import type { AccordionProperties } from './properties';
|
|
3
|
+
|
|
4
|
+
let { expand = false, children, classes }: AccordionProperties = $props();
|
|
3
5
|
</script>
|
|
4
6
|
|
|
5
|
-
<div class="accordion" class:expanded={expand}>
|
|
7
|
+
<div class="accordion {classes ?? ''}" class:expanded={expand}>
|
|
6
8
|
<div class="accordion-content">
|
|
7
9
|
{@render children?.()}
|
|
8
10
|
</div>
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
children: any;
|
|
4
|
-
}, {}, "">;
|
|
1
|
+
import type { AccordionProperties } from './properties';
|
|
2
|
+
declare const Accordion: import("svelte").Component<AccordionProperties, {}, "">;
|
|
5
3
|
type Accordion = ReturnType<typeof Accordion>;
|
|
6
4
|
export default Accordion;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -33,18 +33,20 @@
|
|
|
33
33
|
</script>
|
|
34
34
|
|
|
35
35
|
{#if enable}
|
|
36
|
-
{#if useFlyAnimation}
|
|
37
|
-
<div
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
{#if useFlyAnimation && useOutTransition}
|
|
37
|
+
<div in:fly|global={flyAnimationProperties} out:fly|global={flyAnimationProperties}>
|
|
38
|
+
{@render children?.()}
|
|
39
|
+
</div>
|
|
40
|
+
{:else if useFlyAnimation}
|
|
41
|
+
<div in:fly|global={flyAnimationProperties}>
|
|
42
|
+
{@render children?.()}
|
|
43
|
+
</div>
|
|
44
|
+
{:else if useOutTransition}
|
|
45
|
+
<div in:fade|global={fadeAnimationProperties} out:fade|global={fadeAnimationProperties}>
|
|
41
46
|
{@render children?.()}
|
|
42
47
|
</div>
|
|
43
48
|
{:else}
|
|
44
|
-
<div
|
|
45
|
-
in:fade|global={fadeAnimationProperties}
|
|
46
|
-
out:fade|global={useOutTransition ? fadeAnimationProperties : undefined}
|
|
47
|
-
>
|
|
49
|
+
<div in:fade|global={fadeAnimationProperties}>
|
|
48
50
|
{@render children?.()}
|
|
49
51
|
</div>
|
|
50
52
|
{/if}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { AvatarProperties } from './properties';
|
|
3
|
+
import Img from '../Img/Img.svelte';
|
|
4
|
+
|
|
5
|
+
let { src, alt, name, size = 'medium', testId, onclick, classes }: AvatarProperties = $props();
|
|
6
|
+
|
|
7
|
+
let imageError = $state(false);
|
|
8
|
+
|
|
9
|
+
let showImage = $derived(typeof src === 'string' && src.length > 0 && !imageError);
|
|
10
|
+
|
|
11
|
+
let initials = $derived.by(() => {
|
|
12
|
+
if (typeof name !== 'string' || name.trim().length === 0) {
|
|
13
|
+
return '';
|
|
14
|
+
}
|
|
15
|
+
const words = name.trim().split(/\s+/);
|
|
16
|
+
if (words.length === 0) {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
const firstWord = words.at(0);
|
|
20
|
+
const lastWord = words.at(-1);
|
|
21
|
+
const first = typeof firstWord === 'string' && firstWord.length > 0 ? firstWord.charAt(0) : '';
|
|
22
|
+
const last =
|
|
23
|
+
words.length > 1 && typeof lastWord === 'string' && lastWord.length > 0
|
|
24
|
+
? lastWord.charAt(0)
|
|
25
|
+
: '';
|
|
26
|
+
return (first + last).toUpperCase();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
function handleImageError(): void {
|
|
30
|
+
imageError = true;
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
{#snippet content()}
|
|
35
|
+
{#if showImage && typeof src === 'string'}
|
|
36
|
+
<span class="avatar-img-wrapper">
|
|
37
|
+
<Img {src} {alt} onerror={handleImageError} />
|
|
38
|
+
</span>
|
|
39
|
+
{:else}
|
|
40
|
+
<span class="avatar-initials">{initials}</span>
|
|
41
|
+
{/if}
|
|
42
|
+
{/snippet}
|
|
43
|
+
|
|
44
|
+
{#if typeof onclick === 'function'}
|
|
45
|
+
<button
|
|
46
|
+
class="avatar avatar-{size} {classes ?? ''}"
|
|
47
|
+
type="button"
|
|
48
|
+
aria-label={alt}
|
|
49
|
+
data-pw={testId}
|
|
50
|
+
{onclick}
|
|
51
|
+
>
|
|
52
|
+
{@render content()}
|
|
53
|
+
</button>
|
|
54
|
+
{:else}
|
|
55
|
+
<div class="avatar avatar-{size} {classes ?? ''}" role="img" aria-label={alt} data-pw={testId}>
|
|
56
|
+
{@render content()}
|
|
57
|
+
</div>
|
|
58
|
+
{/if}
|
|
59
|
+
|
|
60
|
+
<style>
|
|
61
|
+
.avatar {
|
|
62
|
+
display: inline-flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
justify-content: center;
|
|
65
|
+
padding: 0;
|
|
66
|
+
border-radius: var(--avatar-border-radius, 50%);
|
|
67
|
+
border: var(--avatar-border, none);
|
|
68
|
+
box-shadow: var(--avatar-box-shadow, none);
|
|
69
|
+
cursor: var(--avatar-cursor, default);
|
|
70
|
+
overflow: hidden;
|
|
71
|
+
background-color: var(--avatar-background, #e0e0e0);
|
|
72
|
+
font-family: inherit;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.avatar:hover {
|
|
76
|
+
opacity: var(--avatar-hover-opacity, 1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.avatar-small {
|
|
80
|
+
width: var(--avatar-small-width, 32px);
|
|
81
|
+
height: var(--avatar-small-height, 32px);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.avatar-medium {
|
|
85
|
+
width: var(--avatar-medium-width, 40px);
|
|
86
|
+
height: var(--avatar-medium-height, 40px);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.avatar-large {
|
|
90
|
+
width: var(--avatar-large-width, 56px);
|
|
91
|
+
height: var(--avatar-large-height, 56px);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.avatar-img-wrapper {
|
|
95
|
+
display: contents;
|
|
96
|
+
--image-width: 100%;
|
|
97
|
+
--image-height: 100%;
|
|
98
|
+
--image-object-fit: var(--avatar-object-fit, cover);
|
|
99
|
+
--image-border-radius: 0px;
|
|
100
|
+
--image-padding: 0px;
|
|
101
|
+
--image-margin: 0px;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.avatar-initials {
|
|
105
|
+
color: var(--avatar-text-color, #555555);
|
|
106
|
+
font-weight: var(--avatar-font-weight, 600);
|
|
107
|
+
font-family: var(--avatar-font-family, inherit);
|
|
108
|
+
user-select: none;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.avatar-small .avatar-initials {
|
|
112
|
+
font-size: var(--avatar-small-font-size, 12px);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.avatar-medium .avatar-initials {
|
|
116
|
+
font-size: var(--avatar-medium-font-size, 14px);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.avatar-large .avatar-initials {
|
|
120
|
+
font-size: var(--avatar-large-font-size, 20px);
|
|
121
|
+
}
|
|
122
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type AvatarSize = 'small' | 'medium' | 'large';
|
|
2
|
+
export type AvatarProperties = MandatoryAvatarProperties & OptionalAvatarProperties & AvatarEventProperties;
|
|
3
|
+
export type MandatoryAvatarProperties = {
|
|
4
|
+
alt: string;
|
|
5
|
+
};
|
|
6
|
+
export type OptionalAvatarProperties = {
|
|
7
|
+
src?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
size?: AvatarSize;
|
|
10
|
+
testId?: string;
|
|
11
|
+
classes?: string;
|
|
12
|
+
};
|
|
13
|
+
export type AvatarEventProperties = {
|
|
14
|
+
onclick?: (event: MouseEvent) => void;
|
|
15
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|