@juspay/svelte-ui-components 2.10.0 → 2.12.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.
Files changed (190) hide show
  1. package/README.md +337 -77
  2. package/dist/Accordion/Accordion.svelte +4 -2
  3. package/dist/Accordion/Accordion.svelte.d.ts +2 -4
  4. package/dist/Accordion/properties.d.ts +6 -0
  5. package/dist/Accordion/properties.js +1 -0
  6. package/dist/Animations/ModalAnimation.svelte +11 -9
  7. package/dist/Avatar/Avatar.svelte +122 -0
  8. package/dist/Avatar/Avatar.svelte.d.ts +4 -0
  9. package/dist/Avatar/properties.d.ts +15 -0
  10. package/dist/Avatar/properties.js +1 -0
  11. package/dist/Badge/Badge.svelte +2 -2
  12. package/dist/Badge/properties.d.ts +1 -0
  13. package/dist/Banner/Banner.svelte +132 -48
  14. package/dist/Banner/Banner.svelte.d.ts +1 -1
  15. package/dist/Banner/properties.d.ts +8 -3
  16. package/dist/Book/Book.svelte +281 -0
  17. package/dist/Book/Book.svelte.d.ts +4 -0
  18. package/dist/Book/properties.d.ts +24 -0
  19. package/dist/Book/properties.js +1 -0
  20. package/dist/BrandLoader/BrandLoader.svelte +3 -3
  21. package/dist/BrandLoader/properties.d.ts +1 -0
  22. package/dist/Browser/Browser.svelte +193 -0
  23. package/dist/Browser/Browser.svelte.d.ts +3 -0
  24. package/dist/Browser/properties.d.ts +16 -0
  25. package/dist/Browser/properties.js +1 -0
  26. package/dist/Button/Button.svelte +20 -7
  27. package/dist/Button/properties.d.ts +7 -4
  28. package/dist/Calendar/Calendar.svelte +476 -0
  29. package/dist/Calendar/Calendar.svelte.d.ts +4 -0
  30. package/dist/Calendar/properties.d.ts +30 -0
  31. package/dist/Calendar/properties.js +1 -0
  32. package/dist/Carousel/Carousel.svelte +19 -16
  33. package/dist/Carousel/properties.d.ts +1 -0
  34. package/dist/CheckListItem/CheckListItem.svelte +31 -26
  35. package/dist/CheckListItem/properties.d.ts +4 -1
  36. package/dist/Checkbox/Checkbox.svelte +157 -0
  37. package/dist/Checkbox/Checkbox.svelte.d.ts +4 -0
  38. package/dist/Checkbox/properties.d.ts +17 -0
  39. package/dist/Checkbox/properties.js +1 -0
  40. package/dist/Choicebox/Choicebox.svelte +85 -0
  41. package/dist/Choicebox/Choicebox.svelte.d.ts +4 -0
  42. package/dist/Choicebox/properties.d.ts +14 -0
  43. package/dist/Choicebox/properties.js +1 -0
  44. package/dist/CommandMenu/CommandMenu.svelte +452 -0
  45. package/dist/CommandMenu/CommandMenu.svelte.d.ts +4 -0
  46. package/dist/CommandMenu/properties.d.ts +26 -0
  47. package/dist/CommandMenu/properties.js +1 -0
  48. package/dist/ContextMenu/ContextMenu.svelte +308 -0
  49. package/dist/ContextMenu/ContextMenu.svelte.d.ts +4 -0
  50. package/dist/ContextMenu/properties.d.ts +26 -0
  51. package/dist/ContextMenu/properties.js +1 -0
  52. package/dist/Gauge/Gauge.svelte +70 -0
  53. package/dist/Gauge/Gauge.svelte.d.ts +4 -0
  54. package/dist/Gauge/properties.d.ts +9 -0
  55. package/dist/Gauge/properties.js +1 -0
  56. package/dist/GridItem/GridItem.svelte +5 -4
  57. package/dist/GridItem/properties.d.ts +1 -0
  58. package/dist/Icon/Icon.svelte +3 -3
  59. package/dist/Icon/properties.d.ts +1 -0
  60. package/dist/IconStack/IconStack.svelte +3 -3
  61. package/dist/IconStack/properties.d.ts +1 -0
  62. package/dist/Img/Img.svelte +5 -3
  63. package/dist/Img/properties.d.ts +5 -1
  64. package/dist/Input/Input.svelte +12 -6
  65. package/dist/Input/properties.d.ts +1 -0
  66. package/dist/InputButton/InputButton.svelte +4 -3
  67. package/dist/InputButton/properties.d.ts +5 -6
  68. package/dist/KeyboardInput/KeyboardInput.svelte +93 -0
  69. package/dist/KeyboardInput/KeyboardInput.svelte.d.ts +4 -0
  70. package/dist/KeyboardInput/properties.d.ts +12 -0
  71. package/dist/KeyboardInput/properties.js +1 -0
  72. package/dist/ListItem/ListItem.svelte +31 -28
  73. package/dist/ListItem/properties.d.ts +1 -0
  74. package/dist/Loader/Loader.svelte +10 -6
  75. package/dist/Loader/Loader.svelte.d.ts +3 -25
  76. package/dist/Loader/properties.d.ts +3 -0
  77. package/dist/Loader/properties.js +1 -0
  78. package/dist/LoadingDots/LoadingDots.svelte +64 -0
  79. package/dist/LoadingDots/LoadingDots.svelte.d.ts +3 -0
  80. package/dist/LoadingDots/properties.d.ts +8 -0
  81. package/dist/LoadingDots/properties.js +1 -0
  82. package/dist/Menu/Menu.svelte +349 -0
  83. package/dist/Menu/Menu.svelte.d.ts +4 -0
  84. package/dist/Menu/properties.d.ts +24 -0
  85. package/dist/Menu/properties.js +1 -0
  86. package/dist/Modal/Modal.svelte +10 -9
  87. package/dist/Modal/properties.d.ts +1 -0
  88. package/dist/Pagination/Pagination.svelte +152 -0
  89. package/dist/Pagination/Pagination.svelte.d.ts +4 -0
  90. package/dist/Pagination/properties.d.ts +14 -0
  91. package/dist/Pagination/properties.js +1 -0
  92. package/dist/Phone/Phone.svelte +234 -0
  93. package/dist/Phone/Phone.svelte.d.ts +3 -0
  94. package/dist/Phone/properties.d.ts +11 -0
  95. package/dist/Phone/properties.js +1 -0
  96. package/dist/Pill/Pill.svelte +130 -0
  97. package/dist/Pill/Pill.svelte.d.ts +4 -0
  98. package/dist/Pill/properties.d.ts +16 -0
  99. package/dist/Pill/properties.js +1 -0
  100. package/dist/Progress/Progress.svelte +68 -0
  101. package/dist/Progress/Progress.svelte.d.ts +4 -0
  102. package/dist/Progress/properties.d.ts +10 -0
  103. package/dist/Progress/properties.js +1 -0
  104. package/dist/Radio/Radio.svelte +128 -0
  105. package/dist/Radio/Radio.svelte.d.ts +4 -0
  106. package/dist/Radio/properties.d.ts +15 -0
  107. package/dist/Radio/properties.js +1 -0
  108. package/dist/RelativeTime/RelativeTime.svelte +117 -0
  109. package/dist/RelativeTime/RelativeTime.svelte.d.ts +4 -0
  110. package/dist/RelativeTime/properties.d.ts +13 -0
  111. package/dist/RelativeTime/properties.js +1 -0
  112. package/dist/Scroller/Scroller.svelte +389 -0
  113. package/dist/Scroller/Scroller.svelte.d.ts +4 -0
  114. package/dist/Scroller/properties.d.ts +30 -0
  115. package/dist/Scroller/properties.js +1 -0
  116. package/dist/Select/Select.svelte +382 -344
  117. package/dist/Select/Select.svelte.d.ts +1 -1
  118. package/dist/Select/properties.d.ts +16 -26
  119. package/dist/Sheet/Sheet.svelte +264 -0
  120. package/dist/Sheet/Sheet.svelte.d.ts +4 -0
  121. package/dist/Sheet/properties.d.ts +19 -0
  122. package/dist/Sheet/properties.js +1 -0
  123. package/dist/Shimmer/Shimmer.svelte +44 -0
  124. package/dist/Shimmer/Shimmer.svelte.d.ts +4 -0
  125. package/dist/Shimmer/properties.d.ts +4 -0
  126. package/dist/Shimmer/properties.js +1 -0
  127. package/dist/Slider/Slider.svelte +144 -0
  128. package/dist/Slider/Slider.svelte.d.ts +4 -0
  129. package/dist/Slider/properties.d.ts +17 -0
  130. package/dist/Slider/properties.js +1 -0
  131. package/dist/Snippet/Snippet.svelte +123 -0
  132. package/dist/Snippet/Snippet.svelte.d.ts +4 -0
  133. package/dist/Snippet/properties.d.ts +15 -0
  134. package/dist/Snippet/properties.js +1 -0
  135. package/dist/SplitButton/SplitButton.svelte +135 -0
  136. package/dist/SplitButton/SplitButton.svelte.d.ts +4 -0
  137. package/dist/SplitButton/properties.d.ts +17 -0
  138. package/dist/SplitButton/properties.js +1 -0
  139. package/dist/Status/Status.svelte +5 -3
  140. package/dist/Status/properties.d.ts +1 -0
  141. package/dist/Stepper/Step.svelte +3 -3
  142. package/dist/Stepper/Stepper.svelte +3 -3
  143. package/dist/Stepper/properties.d.ts +2 -0
  144. package/dist/Table/Table.svelte +249 -67
  145. package/dist/Table/properties.d.ts +19 -1
  146. package/dist/Tabs/Tabs.svelte +240 -0
  147. package/dist/Tabs/Tabs.svelte.d.ts +4 -0
  148. package/dist/Tabs/properties.d.ts +16 -0
  149. package/dist/Tabs/properties.js +1 -0
  150. package/dist/ThemeSwitcher/ThemeSwitcher.svelte +249 -0
  151. package/dist/ThemeSwitcher/ThemeSwitcher.svelte.d.ts +4 -0
  152. package/dist/ThemeSwitcher/properties.d.ts +19 -0
  153. package/dist/ThemeSwitcher/properties.js +1 -0
  154. package/dist/Toast/Toast.svelte +25 -30
  155. package/dist/Toast/properties.d.ts +1 -0
  156. package/dist/Toggle/Toggle.svelte +2 -2
  157. package/dist/Toggle/properties.d.ts +1 -0
  158. package/dist/Toolbar/Toolbar.svelte +8 -7
  159. package/dist/Toolbar/properties.d.ts +1 -0
  160. package/dist/Tooltip/Tooltip.svelte +153 -0
  161. package/dist/Tooltip/Tooltip.svelte.d.ts +4 -0
  162. package/dist/Tooltip/properties.d.ts +13 -0
  163. package/dist/Tooltip/properties.js +1 -0
  164. package/dist/assets/battery.svg +5 -0
  165. package/dist/assets/checkmark.svg +3 -0
  166. package/dist/assets/chevron-down-sm.svg +3 -0
  167. package/dist/assets/chevron-down.svg +3 -0
  168. package/dist/assets/chevron-left-lg.svg +3 -0
  169. package/dist/assets/chevron-left.svg +3 -0
  170. package/dist/assets/chevron-right-lg.svg +3 -0
  171. package/dist/assets/chevron-right.svg +3 -0
  172. package/dist/assets/chevron-up.svg +3 -0
  173. package/dist/assets/close.svg +4 -0
  174. package/dist/assets/copy.svg +4 -0
  175. package/dist/assets/error-circle.svg +5 -0
  176. package/dist/assets/lock.svg +3 -0
  177. package/dist/assets/minus.svg +3 -0
  178. package/dist/assets/monitor.svg +5 -0
  179. package/dist/assets/moon.svg +3 -0
  180. package/dist/assets/palette.svg +7 -0
  181. package/dist/assets/search.svg +4 -0
  182. package/dist/assets/signal.svg +6 -0
  183. package/dist/assets/sort-default.svg +4 -0
  184. package/dist/assets/sun.svg +11 -0
  185. package/dist/assets/wifi.svg +3 -0
  186. package/dist/index.d.ts +55 -0
  187. package/dist/index.js +27 -0
  188. package/dist/utils.d.ts +2 -0
  189. package/dist/utils.js +18 -4
  190. package/package.json +8 -1
package/README.md CHANGED
@@ -1,114 +1,374 @@
1
- # Svelte UI Components
1
+ # @juspay/svelte-ui-components
2
2
 
3
- This library provides a collection of reusable UI components built with [Svelte](https://svelte.dev/).
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
- ## Usage
9
+ Requires `svelte ^5.41.2` and `type-decoder ^2.1.0` as peer dependencies.
10
+
11
+ ---
15
12
 
16
- The library contains a collection of components that can be imported & used in your svelte project.
13
+ ## Why This Library?
17
14
 
18
- ### Available components
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
- - Accordion
21
- - Badge
22
- - Banner
23
- - Brand Loader (aka Splash Screen )
24
- - Button
25
- - Carousel
26
- - Checkbox / Checklist Item
27
- - Icon
28
- - Input
29
- - Input with attached Button
30
- - List Item
31
- - Loader
32
- - Modal
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
- All of the components can be easily imported from the 'svelte-ui-components' package.
39
+ ---
40
40
 
41
- #### Example: Importing component from the package
41
+ ## Quick Start
42
42
 
43
43
  ```svelte
44
44
  <script lang="ts">
45
- import { Button, defaultButtonProperties } from '@juspay/svelte-ui-components';
45
+ import { Button, Input, Toggle, Toast } from '@juspay/svelte-ui-components';
46
46
  </script>
47
47
 
48
- <Button properties={{ ...defaultButtonProperties, text: 'Click' }} />
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
- ### Customizing the components
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
- Each component comes with a set of configuration options that can be used to customize the component.
54
- There are two ways to customize the component.
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
- 1. Using css variables:
137
+ ### Actions
57
138
 
58
- - All the components have exposed css variables for all the properties available.
59
- - The css variables can be used to customize the component.
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
- 2. Using props:
146
+ ### Decorative
62
147
 
63
- - All the components have exposed props for dynamic values/variables.
64
- - The props can be used to customize the component.
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
- #### Example: Customizing the component
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
- <script lang="ts">
70
- import {
71
- Button,
72
- type ButtonProperties,
73
- defaultButtonProperties
74
- } from '@juspay/svelte-ui-components';
75
-
76
- const buttonProperties: ButtonProperties = {
77
- ...defaultButtonProperties,
78
- text: 'Submit'
79
- };
80
-
81
- function handleSubmitClick() {
82
- // handle click
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="form">
87
- <Button properties={buttonProperties} on:click={handleSubmitClick} />
209
+ <div class="dark-theme">
210
+ <Button text="Dark" onclick={handleClick} />
88
211
  </div>
89
212
 
90
213
  <style>
91
- .form {
92
- --button-color: black;
93
- --button-text-color: white;
94
- /* Other styling values */
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
- ### Contributing
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
- - Clone the repository
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
- ### Todo Items
372
+ ## License
110
373
 
111
- - [ ] Add demo support
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
- let { expand = false, children } = $props();
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
- declare const Accordion: import("svelte").Component<{
2
- expand?: boolean;
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,6 @@
1
+ import type { Snippet } from 'svelte';
2
+ export type AccordionProperties = {
3
+ expand?: boolean;
4
+ children?: Snippet;
5
+ classes?: string;
6
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -33,18 +33,20 @@
33
33
  </script>
34
34
 
35
35
  {#if enable}
36
- {#if useFlyAnimation}
37
- <div
38
- in:fly|global={flyAnimationProperties}
39
- out:fly|global={useOutTransition ? flyAnimationProperties : undefined}
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,4 @@
1
+ import type { AvatarProperties } from './properties';
2
+ declare const Avatar: import("svelte").Component<AvatarProperties, {}, "">;
3
+ type Avatar = ReturnType<typeof Avatar>;
4
+ export default Avatar;
@@ -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 {};